📄 route.c
字号:
/* * * Copyright (c) 1983, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1989, 1991, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94";#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/sysctl.h>#include <net/if.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;typedef union sockunion *sup;int pid, rtm_addrs, uid;int s;int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword();int iflag, verbose, aflen = sizeof (struct sockaddr_in);int locking, lockrest, debugonly;struct rt_metrics rt_metrics;u_long rtm_inits;struct in_addr inet_makeaddr();char *routename(), *netname();void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();int getaddr(), rtmsg(), x25_makemask();extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa();__dead voidusage(cp) char *cp;{ if (cp) (void) fprintf(stderr, "route: botched keyword: %s\n", cp); (void) fprintf(stderr, "usage: route [ -nqv ] 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))intmain(argc, argv) int argc; char **argv;{ extern int optind; int ch; if (argc < 2) usage((char *)NULL); while ((ch = getopt(argc, argv, "nqdtv")) != EOF) switch(ch) { case 'n': nflag = 1; break; case 'q': qflag = 1; break; case 'v': verbose = 1; break; case 't': tflag = 1; break; case 'd': debugonly = 1; break; case '?': default: usage((char *)NULL); } argc -= optind; argv += optind; pid = getpid(); uid = getuid(); if (tflag) s = open("/dev/null", O_WRONLY, 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: 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[];{ size_t needed; int mib[6], rlen, seqno; char *buf, *next, *lim; register struct rt_msghdr *rtm; if (uid) { errno = EACCES; 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); } mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ mib[3] = 0; /* wildcard address family */ mib[4] = NET_RT_DUMP; mib[5] = 0; /* no flags */ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) quit("route-sysctl-estimate"); if ((buf = malloc(needed)) == NULL) quit("malloc"); if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) quit("actual retrieval of routing table"); lim = buf + needed; if (verbose) (void) printf("Examining routing table from sysctl\n"); seqno = 0; /* ??? */ for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; if (verbose) print_rtmsg(rtm, rtm->rtm_msglen); if ((rtm->rtm_flags & RTF_GATEWAY) == 0) continue; if (af) { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); if (sa->sa_family != af) continue; } if (debugonly) 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; } if (sa->sa_len == 0) strcpy(line, "default"); else 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 || sa->sa_len < 4) 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; u_short *slim = s + ((sa->sa_len + 1) >> 1); char *cp = line + sprintf(line, "(%d)", sa->sa_family); while (++s < slim) /* start with sa->sa_data */ 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -