- 论坛徽章:
- 0
|
以下代码改自net-tools相关代码:
#include <asm/types.h>;
#include <sys/param.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <arpa/inet.h>;
#include <arpa/nameser.h>;
#include <net/route.h>; /* realy broken */
#include <sys/ioctl.h>;
#include <ctype.h>;
#include <errno.h>;
#include <netdb.h>;
#include <resolv.h>;
#include <unistd.h>;
#include <stdlib.h>;
#include <string.h>;
#include <stdio.h>;
/************************************************************/
#define RTACTION_ADD 1
#define RTACTION_DEL 2
#define RTACTION_HELP 3
#define E_OPTERR 3
#define E_USAGE 4
#define E_SOCK 5
#define E_LOOKUP 6
/* Keep this in sync with /usr/src/linux/include/linux/route.h */
#define RTF_UP 0x0001 /* route usable */
#define RTF_GATEWAY 0x0002 /* destination is a gateway */
#define RTF_HOST 0x0004 /* host entry (net otherwise) */
#define mask_in_addr(x) (((struct sockaddr_in *)&((x).rt_genmask))->;sin_addr.s_addr)
#define full_mask(x) (x)
/*
#define mask_in_addr(x) ((x).rt_genmask)
#define full_mask(x) (((struct sockaddr_in *)&(x))->;sin_addr.s_addr)
*/
int usage(void)
{
fprintf(stderr, "Usage: inet_route [-vF] del {-host|-net} Target[/prefix] [gw Gw] [metric M] [[dev] If]\n" ;
fprintf(stderr, " inet_route [-vF] add {-host|-net} Target[/prefix] [gw Gw] [metric M]\n" ;
fprintf(stderr, " [netmask N] [mss Mss] [window W] [irtt I]\n" ;
fprintf(stderr, " [mod] [dyn] [reinstate] [[dev] If]\n" ;
fprintf(stderr, " inet_route [-vF] add {-host|-net} Target[/prefix] [metric M] reject\n" ;
fprintf(stderr, " inet_route [-FC] flush NOT supported\n" ;
return (E_USAGE);
}
/* Like strncpy but make sure the resulting string is always 0 terminated. */
char * safe_strncpy(char *dst, const char *src, size_t size)
{
dst[size-1] = '\0';
return strncpy(dst, src, size-1);
}
int INET_getsock(char *bufp, struct sockaddr *sap)
{
char *sp = bufp, *bp;
unsigned int i;
unsigned val;
struct sockaddr_in *sin;
sin = (struct sockaddr_in *) sap;
sin->;sin_family = AF_INET;
sin->;sin_port = 0;
val = 0;
bp = (char *) &
for (i = 0; i < sizeof(sin->;sin_addr.s_addr); i++) {
*sp = toupper(*sp);
if ((*sp >;= 'A') && (*sp <= 'F'))
bp |= (int) (*sp - 'A') + 10;
else if ((*sp >;= '0') && (*sp <= '9'))
bp |= (int) (*sp - '0');
else
return (-1);
bp <<= 4;
sp++;
*sp = toupper(*sp);
if ((*sp >;= 'A') && (*sp <= 'F'))
bp |= (int) (*sp - 'A') + 10;
else if ((*sp >;= '0') && (*sp <= '9'))
bp |= (int) (*sp - '0');
else
return (-1);
sp++;
}
sin->;sin_addr.s_addr = htonl(val);
return (sp - bufp);
}
int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst)
{
struct hostent *hp;
struct netent *np;
/* Grmpf. -FvK */
sin->;sin_family = AF_INET;
sin->;sin_port = 0;
/* Default is special, meaning 0.0.0.0. */
if (!strcmp(name, "default" ) {
sin->;sin_addr.s_addr = INADDR_ANY;
return (1);
}
/* Look to see if it's a dotted quad. */
if (inet_aton(name, &sin->;sin_addr)) {
return 0;
}
/* If we expect this to be a hostname, try hostname database first */
if (hostfirst &&
(hp = gethostbyname(name)) != (struct hostent *) NULL) {
memcpy((char *) &sin->;sin_addr, (char *) hp->;h_addr_list[0],
sizeof(struct in_addr));
return 0;
}
/* Try the NETWORKS database to see if this is a known network. */
if ((np = getnetbyname(name)) != (struct netent *) NULL) {
sin->;sin_addr.s_addr = htonl(np->;n_net);
return 1;
}
if (hostfirst) {
/* Don't try again */
errno = h_errno;
return -1;
}
if ((hp = gethostbyname(name)) == (struct hostent *) NULL) {
errno = h_errno;
return -1;
}
memcpy((char *) &sin->;sin_addr, (char *) hp->;h_addr_list[0],
sizeof(struct in_addr));
return 0;
}
int INET_input(int type, char *bufp, struct sockaddr *sap)
{
switch (type) {
case 1:
return (INET_getsock(bufp, sap));
case 256:
return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
default:
return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
}
}
int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
{
struct sockaddr_in *mask = (struct sockaddr_in *) m;
char *slash, *end;
int prefix;
if ((slash = strchr(adr, '/')) == NULL)
return 0;
*slash++ = '\0';
prefix = strtoul(slash, &end, 0);
if (*end != '\0')
return -1;
if (name) {
sprintf(name, "/%d", prefix);
}
mask->;sin_family = AF_INET;
mask->;sin_addr.s_addr = htonl(~(0xffffffffU >;>; prefix));
return 1;
}
int INET_setroute(int action, int options, char **args)
{
struct rtentry rt;
char target[128], gateway[128] = "NONE", netmask[128] = "default";
int xflag, isnet,skfd;
xflag = 0;
if (!strcmp(*args, "-net" ) {
xflag = 1;
args++;
} else if (!strcmp(*args, "-host" ) {
xflag = 2;
args++;
}
if (*args == NULL)
return (usage());
safe_strncpy(target, *args++, (sizeof target));
/* Clean out the RTREQ structure. */
memset((char *) &rt, 0, sizeof(struct rtentry));
/* Special hack for /prefix syntax */
{
union {
struct sockaddr_in m;
struct sockaddr d;
} mask;
int n;
n = INET_getnetmask(target, &mask.d, netmask);
if (n < 0)
return usage();
else if (n)
rt.rt_genmask = full_mask(mask.d);
}
/* Prefer hostname lookup is -host flag was given */
if ((isnet = INET_input((xflag!=2? 0: 256), target, &rt.rt_dst)) < 0) {
return (1);
}
switch (xflag) {
case 1:
isnet = 1; break;
case 2:
isnet = 0; break;
default:
break;
}
/* Fill in the other fields. */
rt.rt_flags = (RTF_UP | RTF_HOST);
if (isnet)
rt.rt_flags &= ~RTF_HOST;
while (*args) {
if (!strcmp(*args, "netmask" ) {
struct sockaddr mask;
args++;
if (!*args || mask_in_addr(rt))
return (usage());
safe_strncpy(netmask, *args, (sizeof netmask));
if ((isnet = INET_input(0, netmask, &mask)) < 0) {
return (E_LOOKUP);
}
rt.rt_genmask = full_mask(mask);
args++;
continue;
}
if (!strcmp(*args, "gw") || !strcmp(*args, "gateway")) {
args++;
if (!*args)
return (usage());
if (rt.rt_flags & RTF_GATEWAY)
return (usage());
safe_strncpy(gateway, *args, (sizeof gateway));
if ((isnet = INET_input(256, gateway, &rt.rt_gateway)) < 0) {
return (E_LOOKUP);
}
if (isnet) {
fprintf(stderr, "route: %s: cannot use a NETWORK as gateway!\n",gateway);
return (E_OPTERR);
}
rt.rt_flags |= RTF_GATEWAY;
args++;
continue;
}
}
/* sanity checks.. */
if (mask_in_addr(rt)) {
__u32 mask = ~ntohl(mask_in_addr(rt));
if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
fprintf(stderr, "route: netmask %.8x doesn't make sense with host route\n", mask);
return (E_OPTERR);
}
if (mask & (mask + 1)) {
fprintf(stderr, "route: bogus netmask %s\n", netmask);
return (E_OPTERR);
}
mask = ((struct sockaddr_in *) &rt.rt_dst)->;sin_addr.s_addr;
if (mask & ~mask_in_addr(rt)) {
fprintf(stderr, "route: netmask doesn't match route address\n");
return (E_OPTERR);
}
}
/* Fill out netmask if still unset */
if ((action == RTACTION_ADD) && rt.rt_flags & RTF_HOST)
mask_in_addr(rt) = 0xffffffff;
/* Create a socket to the INET kernel. */
if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
return (E_SOCK);
}
/* Tell the kernel to accept this route. */
if (action == RTACTION_DEL) {
if (ioctl(skfd, SIOCDELRT, &rt) < 0) {
perror("SIOCDELRT");
close(skfd);
return (E_SOCK);
}
} else {
if (ioctl(skfd, SIOCADDRT, &rt) < 0) {
perror("SIOCADDRT");
close(skfd);
return (E_SOCK);
}
}
/* Close the socket. */
(void) close(skfd);
return (0);
}
int route_edit(int action, int options, char **argv)
{
return (INET_setroute(action, options, argv));
}
int main(int argc,char **argv)
{
int what,options,i;
what=0;
if(argc<3)
{
printf("argc<3\n");
return 0;
}
argc--;
argv++;
if (!strcmp(*argv, "add"))
what = RTACTION_ADD;
else if (!strcmp(*argv, "del") || !strcmp(*argv, "delete"))
what = RTACTION_DEL;
i = route_edit(what, options, ++argv);
if (i == E_OPTERR)
usage();
return (i);
} |
|