X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/4e64fa9b5a65c0d8a9dd6757a18ad66b1a5a85be..fd88f5c5678c80ff5e338adc372d28a52ad20530:/usr/src/usr.bin/netstat/route.c diff --git a/usr/src/usr.bin/netstat/route.c b/usr/src/usr.bin/netstat/route.c index 3279491b5a..ee98f0714a 100644 --- a/usr/src/usr.bin/netstat/route.c +++ b/usr/src/usr.bin/netstat/route.c @@ -1,15 +1,42 @@ /* - * Copyright (c) 1983, 1988 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. * - * %sccs.include.redist.c% + * 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 lint -static char sccsid[] = "@(#)route.c 5.22 (Berkeley) %G%"; +static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95"; #endif /* not lint */ #include +#include #include #include @@ -23,17 +50,16 @@ static char sccsid[] = "@(#)route.c 5.22 (Berkeley) %G%"; #include -#include -#include +#include +#include #include +#include #include +#include +#include "netstat.h" -extern int nflag, aflag, Aflag, af; -extern char *routename(), *netname(), *ns_print(), *plural(); -extern char *malloc(); -#define kget(p, d) \ - (kvm_read((off_t)(p), (char *)&(d), sizeof (d))) +#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) /* * Definitions for showing gateway flags. @@ -45,13 +71,17 @@ struct bits { { RTF_UP, 'U' }, { RTF_GATEWAY, 'G' }, { RTF_HOST, 'H' }, + { RTF_REJECT, 'R' }, { RTF_DYNAMIC, 'D' }, { RTF_MODIFIED, 'M' }, + { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ + { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ { RTF_CLONING, 'C' }, { RTF_XRESOLVE, 'X' }, { RTF_LLINFO, 'L' }, - { RTF_REJECT, 'R' }, { RTF_STATIC, 'S' }, + { RTF_PROTO1, '1' }, + { RTF_PROTO2, '2' }, { 0 } }; @@ -67,11 +97,21 @@ struct radix_mask rmask; int NewTree = 0; +static struct sockaddr *kgetsa __P((struct sockaddr *)); +static void p_tree __P((struct radix_node *)); +static void p_rtnode __P(()); +static void ntreestuff __P(()); +static void np_rtentry __P((struct rt_msghdr *)); +static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int)); +static void p_flags __P((int, char *)); +static void p_rtentry __P((struct rtentry *)); + /* * Print routing tables. */ +void routepr(rtree) - off_t rtree; + u_long rtree; { struct radix_node_head *rnh, head; int i; @@ -92,7 +132,7 @@ routepr(rtree) continue; kget(rnh, head); if (i == AF_UNSPEC) { - if (Aflag && af == 0) { + if (Aflag && af == 0) { printf("Netmasks:\n"); p_tree(head.rnh_treetop); } @@ -109,6 +149,7 @@ routepr(rtree) /* * Print address family header before a section of the routing table. */ +void pr_family(af) int af; { @@ -144,6 +185,7 @@ pr_family(af) /* * Print header for routing table columns. */ +void pr_rthdr() { @@ -155,17 +197,18 @@ pr_rthdr() "Flags", "Refs", "Use", "Interface"); } -struct sockaddr * +static struct sockaddr * kgetsa(dst) register struct sockaddr *dst; { kget(dst, pt_u.u_sa); if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) - kvm_read((off_t)dst, pt_u.u_data, pt_u.u_sa.sa_len); + kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len); return (&pt_u.u_sa); } +static void p_tree(rn) struct radix_node *rn; { @@ -186,7 +229,7 @@ again: p_rtnode(); } else { p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), - 0, 44); + NULL, 0, 44); putchar('\n'); } if (rn = rnode.rn_dupedkey) @@ -204,6 +247,7 @@ again: char nbuf[20]; +static void p_rtnode() { struct radix_mask *rm = rnode.rn_mklist; @@ -212,7 +256,7 @@ p_rtnode() if (rnode.rn_mask) { printf("\t mask "); p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), - 0, -1); + NULL, 0, -1); } else if (rm == 0) return; } else { @@ -224,7 +268,15 @@ p_rtnode() sprintf(nbuf, " %d refs, ", rmask.rm_refs); printf(" mk = %8.8x {(%d),%s", rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " "); - p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), 0, -1); + if (rmask.rm_flags & RNF_NORMAL) { + struct radix_node rnode_aux; + printf(" , "); + kget(rmask.rm_leaf, rnode_aux); + p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask), + NULL, 0, -1); + } else + p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), + NULL, 0, -1); putchar('}'); if (rm = rmask.rm_mklist) printf(" ->"); @@ -232,18 +284,26 @@ p_rtnode() putchar('\n'); } +static void ntreestuff() { - int needed; + size_t needed; + int mib[6]; char *buf, *next, *lim; register struct rt_msghdr *rtm; - if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0) - { perror("route-getkerninfo-estimate"); exit(1);} + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_DUMP; + mib[5] = 0; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + { perror("route-sysctl-estimate"); exit(1);} if ((buf = malloc(needed)) == 0) { printf("out of space\n"); exit(1);} - if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0) - { perror("getkerninfo of routing table"); exit(1);} + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + { perror("sysctl of routing table"); exit(1);} lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; @@ -251,11 +311,15 @@ ntreestuff() } } +static void np_rtentry(rtm) register struct rt_msghdr *rtm; { register struct sockaddr *sa = (struct sockaddr *)(rtm + 1); - static int masks_done, old_af, banner_printed; +#ifdef notdef + static int masks_done, banner_printed; +#endif + static int old_af; int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; #ifdef notdef @@ -277,23 +341,24 @@ np_rtentry(rtm) old_af = af; } if (rtm->rtm_addrs == RTA_DST) - p_sockaddr(sa, 0, 36); + p_sockaddr(sa, NULL, 0, 36); else { - p_sockaddr(sa, rtm->rtm_flags, 16); + p_sockaddr(sa, NULL, rtm->rtm_flags, 16); if (sa->sa_len == 0) sa->sa_len = sizeof(long); sa = (struct sockaddr *)(sa->sa_len + (char *)sa); - p_sockaddr(sa, 0, 18); + p_sockaddr(sa, NULL, 0, 18); } p_flags(rtm->rtm_flags & interesting, "%-6.6s "); putchar('\n'); } -p_sockaddr(sa, flags, width) - struct sockaddr *sa; +static void +p_sockaddr(sa, mask, flags, width) + struct sockaddr *sa, *mask; int flags, width; { - char format[20], workbuf[128], *cplim; + char workbuf[128], *cplim; register char *cp = workbuf; switch(sa->sa_family) { @@ -301,20 +366,26 @@ p_sockaddr(sa, flags, width) { register struct sockaddr_in *sin = (struct sockaddr_in *)sa; - cp = (sin->sin_addr.s_addr == 0) ? "default" : - ((flags & RTF_HOST) ? - routename(sin->sin_addr) : netname(sin->sin_addr, 0L)); + if (sin->sin_addr.s_addr == INADDR_ANY) + cp = "default"; + else if (flags & RTF_HOST) + cp = routename(sin->sin_addr.s_addr); + else if (mask) + cp = netname(sin->sin_addr.s_addr, + ntohl(((struct sockaddr_in *)mask) + ->sin_addr.s_addr)); + else + cp = netname(sin->sin_addr.s_addr, 0L); break; } case AF_NS: - cp = ns_print((struct sockaddr_ns *)sa); + cp = ns_print(sa); break; case AF_LINK: { register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; - extern char *link_ntoa(); if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) @@ -343,14 +414,16 @@ p_sockaddr(sa, flags, width) default: { - register u_short *s = ((u_short *)sa->sa_data), *slim; + register u_char *s = (u_char *)sa->sa_data, *slim; - slim = (u_short *) sa + ((sa->sa_len + sizeof(u_short) - 1) / - sizeof(u_short)); + slim = sa->sa_len + (u_char *) sa; cplim = cp + sizeof(workbuf) - 6; cp += sprintf(cp, "(%d)", sa->sa_family); - while (s < slim && cp < cplim) - cp += sprintf(cp, " %x", *s++); + while (s < slim && cp < cplim) { + cp += sprintf(cp, " %02x", *s++); + if (s < slim) + cp += sprintf(cp, "%02x", *s++); + } cp = workbuf; } } @@ -364,6 +437,7 @@ p_sockaddr(sa, flags, width) } } +static void p_flags(f, format) register int f; char *format; @@ -378,21 +452,31 @@ p_flags(f, format) printf(format, name); } +static void p_rtentry(rt) -register struct rtentry *rt; + register struct rtentry *rt; { - register struct sockaddr *sa; static struct ifnet ifnet, *lastif; static char name[16]; + register struct sockaddr *sa; + struct sockaddr addr, mask; - p_sockaddr(kgetsa(rt_key(rt)), rt->rt_flags, WID_DST); - p_sockaddr(kgetsa(rt->rt_gateway), 0, WID_GW); + if (!(sa = kgetsa(rt_key(rt)))) + bzero(&addr, sizeof addr); + else + addr = *sa; + if (!rt_mask(rt) || !(sa = kgetsa(rt_mask(rt)))) + bzero(&mask, sizeof mask); + else + mask = *sa; + p_sockaddr(&addr, &mask, rt->rt_flags, WID_DST); + p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW); p_flags(rt->rt_flags, "%-6.6s "); printf("%6d %8d ", rt->rt_refcnt, rt->rt_use); if (rt->rt_ifp) { if (rt->rt_ifp != lastif) { kget(rt->rt_ifp, ifnet); - kvm_read((off_t)ifnet.if_name, name, 16); + kread((u_long)ifnet.if_name, name, 16); lastif = rt->rt_ifp; } printf(" %.15s%d%s", name, ifnet.if_unit, @@ -403,14 +487,13 @@ register struct rtentry *rt; char * routename(in) - struct in_addr in; + u_long in; { register char *cp; static char line[MAXHOSTNAMELEN + 1]; struct hostent *hp; static char domain[MAXHOSTNAMELEN + 1]; static int first = 1; - char *index(); if (first) { first = 0; @@ -435,41 +518,89 @@ routename(in) strncpy(line, cp, sizeof(line) - 1); else { #define C(x) ((x) & 0xff) - in.s_addr = ntohl(in.s_addr); - 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)); + in = ntohl(in); + sprintf(line, "%u.%u.%u.%u", + C(in >> 24), C(in >> 16), C(in >> 8), C(in)); } return (line); } +static u_long +forgemask(a) + u_long a; +{ + u_long m; + + if (IN_CLASSA(a)) + m = IN_CLASSA_NET; + else if (IN_CLASSB(a)) + m = IN_CLASSB_NET; + else + m = IN_CLASSC_NET; + return (m); +} + +static void +domask(dst, addr, mask) + char *dst; + u_long addr, mask; +{ + register int b, i; + + if (!mask || (forgemask(addr) == mask)) { + *dst = '\0'; + return; + } + i = 0; + for (b = 0; b < 32; b++) + if (mask & (1 << b)) { + register int bb; + + i = b; + for (bb = b+1; bb < 32; bb++) + if (!(mask & (1 << bb))) { + i = -1; /* noncontig */ + break; + } + break; + } + if (i == -1) + sprintf(dst, "&0x%lx", mask); + else + sprintf(dst, "/%d", 32-i); +} + /* * 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(in, mask) - struct in_addr in; - u_long mask; + u_long in, mask; { char *cp = 0; static char line[MAXHOSTNAMELEN + 1]; struct netent *np = 0; - u_long net; - register i; + u_long net, omask; + register u_long i; int subnetshift; - i = ntohl(in.s_addr); + i = ntohl(in); + omask = mask; if (!nflag && i) { if (mask == 0) { - if (IN_CLASSA(i)) { - mask = IN_CLASSA_NET; + switch (mask = forgemask(i)) { + case IN_CLASSA_NET: subnetshift = 8; - } else if (IN_CLASSB(i)) { - mask = IN_CLASSB_NET; + break; + case IN_CLASSB_NET: subnetshift = 8; - } else { - mask = IN_CLASSC_NET; + break; + case IN_CLASSC_NET: subnetshift = 4; + break; + default: + abort(); } /* * If there are more bits than the standard mask @@ -486,7 +617,7 @@ netname(in, mask) np = getnetbyaddr(net, AF_INET); if (np) cp = np->n_name; - } + } if (cp) strncpy(line, cp, sizeof(line) - 1); else if ((i & 0xffffff) == 0) @@ -498,14 +629,16 @@ netname(in, mask) else sprintf(line, "%u.%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8), C(i)); + domask(line+strlen(line), i, omask); return (line); } /* * Print routing statistics */ +void rt_stats(off) - off_t off; + u_long off; { struct rtstat rtstat; @@ -513,7 +646,7 @@ rt_stats(off) printf("rtstat: symbol not in namelist\n"); return; } - kvm_read(off, (char *)&rtstat, sizeof (rtstat)); + kread(off, (char *)&rtstat, sizeof (rtstat)); printf("routing:\n"); printf("\t%u bad routing redirect%s\n", rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); @@ -530,9 +663,10 @@ short ns_nullh[] = {0,0,0}; short ns_bh[] = {-1,-1,-1}; char * -ns_print(sns) -struct sockaddr_ns *sns; +ns_print(sa) + register struct sockaddr *sa; { + register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa; struct ns_addr work; union { union ns_net net_e; u_long long_e; } net; u_short port; @@ -561,7 +695,8 @@ struct sockaddr_ns *sns; q = work.x_host.c_host; sprintf(chost, "%02x%02x%02x%02x%02x%02xH", q[0], q[1], q[2], q[3], q[4], q[5]); - for (p = chost; *p == '0' && p < chost + 12; p++); + for (p = chost; *p == '0' && p < chost + 12; p++) + continue; host = p; } if (port) @@ -575,23 +710,26 @@ struct sockaddr_ns *sns; } char * -ns_phost(sns) -struct sockaddr_ns *sns; +ns_phost(sa) + struct sockaddr *sa; { + register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa; struct sockaddr_ns work; static union ns_net ns_zeronet; char *p; - + work = *sns; work.sns_addr.x_port = 0; work.sns_addr.x_net = ns_zeronet; - p = ns_print(&work); + p = ns_print((struct sockaddr *)&work); if (strncmp("0H.", p, 3) == 0) p += 3; return(p); } + +void upHex(p0) -char *p0; + char *p0; { register char *p = p0; for (; *p; p++) switch (*p) {