📄 route.c
字号:
/* * Copyright (c) 1983, 1989 The Regents of the University of California. * All rights reserved. * * %sccs.include.redist.c% */#ifndef lintchar copyright[] ="%Z% Copyright (c) 1983 The Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "%W% (Berkeley) %G%";#endif /* not lint */#include <sys/param.h>#include <sys/file.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/mbuf.h>#include <sys/kinfo.h>#include <net/route.h>#include <net/if_dl.h>#include <netinet/in.h>#include <netns/ns.h>#include <netiso/iso.h>#include <netccitt/x25.h>#include <arpa/inet.h>#include <netdb.h>#include <errno.h>#include <unistd.h>#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <paths.h>struct keytab { char *kt_cp; int kt_i;} keywords[] = {#include "keywords.h"{0, 0}};struct ortentry route;union sockunion { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_ns sns; struct sockaddr_iso siso; struct sockaddr_dl sdl; struct sockaddr_x25 sx25;} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;union sockunion *so_addrs[] = { &so_dst, &so_gate, &so_mask, &so_genmask, &so_ifp, &so_ifa, 0}; typedef union sockunion *sup;int pid, rtm_addrs, uid;int s;int forcehost, forcenet, doflush, nflag, af, qflag, tflag, Cflag, keyword();int iflag, verbose, aflen = sizeof (struct sockaddr_in);int locking, lockrest, debugonly;struct sockaddr_in sin = { sizeof(sin), AF_INET };struct rt_metrics rt_metrics;u_long rtm_inits;struct in_addr inet_makeaddr();char *routename(), *netname();void flushroutes(), newroute(), monitor();void print_getmsg(), print_rtmsg(), pmsg_common(), sodump(), bprintf();int getaddr(), rtmsg();extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa();voidusage(cp) char *cp;{ if (cp) (void) fprintf(stderr, "route: botched keyword: %s\n", cp); (void) fprintf(stderr, "usage: route [ -Cnqv ] cmd [[ -<qualifers> ] args ]\n"); exit(1); /* NOTREACHED */}voidquit(s) char *s;{ int sverrno = errno; (void) fprintf(stderr, "route: "); if (s) (void) fprintf(stderr, "%s: ", s); (void) fprintf(stderr, "%s\n", strerror(sverrno)); exit(1); /* NOTREACHED */}#define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))main(argc, argv) int argc; char **argv;{ extern int optind; int ch; char *argvp; if (argc < 2) usage((char *)NULL); while ((ch = getopt(argc, argv, "Cnqtv")) != EOF) switch(ch) { case 'C': Cflag = 1; /* Use old ioctls. */ break; case 'n': nflag = 1; break; case 'q': qflag = 1; break; case 'v': verbose = 1; break; case 't': tflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; pid = getpid(); uid = getuid(); if (tflag) s = open("/dev/null", O_WRONLY, 0); else if (Cflag) s = socket(AF_INET, SOCK_RAW, 0); else s = socket(PF_ROUTE, SOCK_RAW, 0); if (s < 0) quit("socket"); if (*argv) switch (keyword(*argv)) { case K_GET: uid = 0; /* FALLTHROUGH */ case K_CHANGE: if (Cflag) usage("change or get with -C"); /* FALLTHROUGH */ case K_ADD: case K_DELETE: newroute(argc, argv); exit(0); /* NOTREACHED */ case K_MONITOR: monitor(); /* NOTREACHED */ case K_FLUSH: flushroutes(argc, argv); exit(0); /* NOTREACHED */ } usage(*argv); /* NOTREACHED */}/* * Purge all entries in the routing tables not * associated with network interfaces. */voidflushroutes(argc, argv) int argc; char *argv[];{ int needed, seqno, rlen; char *buf, *next, *lim; register struct rt_msghdr *rtm; if (uid) quit("must be root to alter routing table"); shutdown(s, 0); /* Don't want to read back our messages */ if (argc > 1) { argv++; if (argc == 2 && **argv == '-') switch (keyword(*argv + 1)) { case K_INET: af = AF_INET; break; case K_XNS: af = AF_NS; break; case K_LINK: af = AF_LINK; break; case K_ISO: case K_OSI: af = AF_ISO; break; case K_X25: af = AF_CCITT; default: goto bad; } elsebad: usage(*argv); } if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0) quit("route-getkerninfo-estimate"); if ((buf = malloc(needed)) == NULL) quit("malloc"); if ((rlen = getkerninfo(KINFO_RT_DUMP, buf, &needed, 0)) < 0) quit("actual retrieval of routing table"); lim = buf + rlen; seqno = 0; /* ??? */ for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; if ((rtm->rtm_flags & RTF_GATEWAY) == 0) continue; if (af) { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); if (sa->sa_family != af) continue; } rtm->rtm_type = RTM_DELETE; rtm->rtm_seq = seqno; rlen = write(s, next, rtm->rtm_msglen); if (rlen < (int)rtm->rtm_msglen) { (void) fprintf(stderr, "route: write to routing socket: %s\n", strerror(errno)); (void) printf("got only %d for rlen\n", rlen); break; } seqno++; if (qflag) continue; if (verbose) print_rtmsg(rtm, rlen); else { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ? routename(sa) : netname(sa)); sa = (struct sockaddr *)(sa->sa_len + (char *)sa); (void) printf("%-20.20s ", routename(sa)); (void) printf("done\n"); } }} char *routename(sa) struct sockaddr *sa;{ register char *cp; static char line[50]; struct hostent *hp; static char domain[MAXHOSTNAMELEN + 1]; static int first = 1; char *ns_print(); if (first) { first = 0; if (gethostname(domain, MAXHOSTNAMELEN) == 0 && (cp = index(domain, '.'))) (void) strcpy(domain, cp + 1); else domain[0] = 0; } switch (sa->sa_family) { case AF_INET: { struct in_addr in; in = ((struct sockaddr_in *)sa)->sin_addr; cp = 0; if (in.s_addr == INADDR_ANY) cp = "default"; if (cp == 0 && !nflag) { hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), AF_INET); if (hp) { if ((cp = index(hp->h_name, '.')) && !strcmp(cp + 1, domain)) *cp = 0; cp = hp->h_name; } } if (cp) strcpy(line, cp); else {#define C(x) ((x) & 0xff) in.s_addr = ntohl(in.s_addr); (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); } break; } case AF_NS: return (ns_print((struct sockaddr_ns *)sa)); case AF_LINK: return (link_ntoa((struct sockaddr_dl *)sa)); case AF_ISO: (void) sprintf(line, "iso %s", iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); break; default: { u_short *s = (u_short *)sa->sa_data; u_short *slim = s + ((sa->sa_len + 1) >> 1); char *cp = line + sprintf(line, "(%d)", sa->sa_family); while (s < slim) cp += sprintf(cp, " %x", *s++); break; } } return (line);}/* * Return the name of the network whose address is given. * The address is assumed to be that of a net or subnet, not a host. */char *netname(sa) struct sockaddr *sa;{ char *cp = 0; static char line[50]; struct netent *np = 0; u_long net, mask; register u_long i; int subnetshift; char *ns_print(); switch (sa->sa_family) { case AF_INET: { struct in_addr in; in = ((struct sockaddr_in *)sa)->sin_addr; i = in.s_addr = ntohl(in.s_addr); if (in.s_addr == 0) cp = "default"; else if (!nflag) { if (IN_CLASSA(i)) { mask = IN_CLASSA_NET; subnetshift = 8; } else if (IN_CLASSB(i)) { mask = IN_CLASSB_NET; subnetshift = 8; } else { mask = IN_CLASSC_NET; subnetshift = 4; } /* * If there are more bits than the standard mask * would suggest, subnets must be in use. * Guess at the subnet mask, assuming reasonable * width subnet fields. */ while (in.s_addr &~ mask) mask = (long)mask >> subnetshift; net = in.s_addr & mask; while ((mask & 1) == 0) mask >>= 1, net >>= 1; np = getnetbyaddr(net, AF_INET); if (np) cp = np->n_name; } if (cp) strcpy(line, cp); else if ((in.s_addr & 0xffffff) == 0) (void) sprintf(line, "%u", C(in.s_addr >> 24)); else if ((in.s_addr & 0xffff) == 0) (void) sprintf(line, "%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16)); else if ((in.s_addr & 0xff) == 0) (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16), C(in.s_addr >> 8)); else (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); break; } case AF_NS: return (ns_print((struct sockaddr_ns *)sa)); break; case AF_LINK: return (link_ntoa((struct sockaddr_dl *)sa)); case AF_ISO: (void) sprintf(line, "iso %s", iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); break; default: { u_short *s = (u_short *)sa->sa_data; u_short *slim = s + ((sa->sa_len + 1)>>1); char *cp = line + sprintf(line, "af %d:", sa->sa_family); while (s < slim) cp += sprintf(cp, " %x", *s++); break; } } return (line);}voidset_metric(value, key) char *value; int key;{ int flag = 0; u_long noval, *valp = &noval; switch (key) {#define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break caseof(K_MTU, RTV_MTU, rmx_mtu); caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); caseof(K_RTT, RTV_RTT, rmx_rtt); caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); } rtm_inits |= flag; if (lockrest || locking) rt_metrics.rmx_locks |= flag; if (locking) locking = 0; *valp = atoi(value);}voidnewroute(argc, argv) int argc; register char **argv;{ char *cmd, *dest = "", *gateway = "", *err; int ishost = 0, ret, attempts, oerrno, flags = 0; int key; struct hostent *hp = 0; if (uid) quit("must be root to alter routing table"); cmd = argv[0]; if (*cmd != 'g') shutdown(s, 0); /* Don't want to read back our messages */ while (--argc > 0) { if (**(++argv)== '-') { switch (key = keyword(1 + *argv)) { case K_LINK: af = AF_LINK; aflen = sizeof(struct sockaddr_dl); break; case K_OSI: case K_ISO: af = AF_ISO; aflen = sizeof(struct sockaddr_iso); break; case K_INET: af = AF_INET; aflen = sizeof(struct sockaddr_in); break; case K_X25: af = AF_CCITT; aflen = sizeof(struct sockaddr_x25); break; case K_SA: af = 0; aflen = sizeof(union sockunion); break; case K_XNS: af = AF_NS; aflen = sizeof(struct sockaddr_ns); break; case K_IFACE: case K_INTERFACE: iflag++; break; case K_LOCK: locking = 1; break; case K_LOCKREST: lockrest = 1; break; case K_HOST: forcehost++; break; case K_REJECT: flags |= RTF_REJECT; break; case K_PROTO1: flags |= RTF_PROTO1; break; case K_PROTO2: flags |= RTF_PROTO2; break; case K_CLONING: flags |= RTF_CLONING; break; case K_XRESOLVE: flags |= RTF_XRESOLVE; break; case K_IFA: argc--; (void) getaddr(RTA_IFA, *++argv, 0); break; case K_IFP: argc--; (void) getaddr(RTA_IFP, *++argv, 0); break; case K_GENMASK: argc--; (void) getaddr(RTA_GENMASK, *++argv, 0); break; case K_GATEWAY: argc--; (void) getaddr(RTA_GATEWAY, *++argv, 0); break; case K_DST: argc--; ishost = getaddr(RTA_DST, *++argv, &hp); dest = *argv; break; case K_NETMASK: argc--; (void) getaddr(RTA_NETMASK, *++argv, 0); /* FALLTHROUGH */ case K_NET: forcenet++; break; case K_MTU: case K_HOPCOUNT: case K_EXPIRE: case K_RECVPIPE: case K_SENDPIPE: case K_SSTHRESH: case K_RTT: case K_RTTVAR: argc--; set_metric(*++argv, key); break; default: usage(1+*argv); } } else { if ((rtm_addrs & RTA_DST) == 0) { dest = *argv; ishost = getaddr(RTA_DST, *argv, &hp); } else if ((rtm_addrs & RTA_GATEWAY) == 0) { gateway = *argv; (void) getaddr(RTA_GATEWAY, *argv, &hp); } else { int ret = atoi(*argv); if (ret == 0) { printf("%s,%s", "old usage of trailing 0", "assuming route to if\n"); iflag = 1; continue; } else if (ret > 0 && ret < 10) { printf("old usage of trailing digit, "); printf("assuming route via gateway\n"); iflag = 0; continue; } (void) getaddr(RTA_NETMASK, *argv, 0); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -