X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/b7080c8e96625177072137d504eb8e9c9d748e49..d5fe66bd4c9ef1a4f8b498bf03dee22c15508571:/netstat.tproj/route.c diff --git a/netstat.tproj/route.c b/netstat.tproj/route.c index 84b945a..06fc5a9 100644 --- a/netstat.tproj/route.c +++ b/netstat.tproj/route.c @@ -59,7 +59,7 @@ static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95"; #endif static const char rcsid[] = - "$Id: route.c,v 1.1.1.2 2000/01/11 01:48:53 wsanchez Exp $"; + "$Id: route.c,v 1.4 2003/07/08 23:03:54 lindak Exp $"; #endif /* not lint */ #include @@ -74,10 +74,10 @@ static const char rcsid[] = #include #include - -#ifdef IPX +#ifndef __APPLE__ #include #include +#include #endif #ifdef NS @@ -86,6 +86,10 @@ static const char rcsid[] = #include +#include +#ifndef __APPLE__ +#include +#endif #include #include #include @@ -97,6 +101,12 @@ static const char rcsid[] = #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) + +/* alignment constraint for routing socket */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + /* * Definitions for showing gateway flags. */ @@ -156,8 +166,7 @@ static void domask __P((char *, u_long, u_long)); * Print routing tables. */ void -routepr(rtree) - u_long rtree; +routepr(u_long rtree) { struct radix_node_head *rnh, head; int i; @@ -185,7 +194,7 @@ routepr(rtree) } else if (af == AF_UNSPEC || af == i) { pr_family(i); do_rtent = 1; - pr_rthdr(); + pr_rthdr(i); p_tree(head.rnh_treetop); } } @@ -196,8 +205,7 @@ routepr(rtree) * Print address family header before a section of the routing table. */ void -pr_family(af) - int af; +pr_family(int af) { char *afname; @@ -205,18 +213,20 @@ pr_family(af) case AF_INET: afname = "Internet"; break; - -#ifdef IPX +#ifdef INET6 + case AF_INET6: + afname = "Internet6"; + break; +#endif /*INET6*/ case AF_IPX: afname = "IPX"; break; -#endif - #ifdef NS case AF_NS: afname = "XNS"; break; #endif +#ifndef __APPLE__ case AF_ISO: afname = "ISO"; break; @@ -226,6 +236,10 @@ pr_family(af) case AF_CCITT: afname = "X.25"; break; + case AF_NETGRAPH: + afname = "Netgraph"; + break; +#endif default: afname = NULL; break; @@ -237,26 +251,49 @@ pr_family(af) } /* column widths; each followed by one space */ -#define WID_DST 18 /* width of destination column */ -#define WID_GW 18 /* width of gateway column */ +#ifndef INET6 +#define WID_DST(af) 18 /* width of destination column */ +#define WID_GW(af) 18 /* width of gateway column */ +#define WID_IF(af) 6 /* width of netif column */ +#else +#define WID_DST(af) \ + ((af) == AF_INET6 ? (lflag ? 39 : (nflag ? 33: 18)) : 18) +#define WID_GW(af) \ + ((af) == AF_INET6 ? (lflag ? 31 : (nflag ? 29 : 18)) : 18) +#define WID_IF(af) ((af) == AF_INET6 ? 8 : 6) +#endif /*INET6*/ /* * Print header for routing table columns. */ void -pr_rthdr() +pr_rthdr(int af) { + if (Aflag) printf("%-8.8s ","Address"); - printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %8.8s %6s\n", - WID_DST, WID_DST, "Destination", - WID_GW, WID_GW, "Gateway", - "Flags", "Refs", "Use", "Netif", "Expire"); + if (af == AF_INET || lflag) + if (lflag) + printf("%-*.*s %-*.*s %-6.6s %6.6s %8.8s %6.6s %*.*s %6s\n", + WID_DST(af), WID_DST(af), "Destination", + WID_GW(af), WID_GW(af), "Gateway", + "Flags", "Refs", "Use", "Mtu", + WID_IF(af), WID_IF(af), "Netif", "Expire"); + else + printf("%-*.*s %-*.*s %-6.6s %6.6s %8.8s %*.*s %6s\n", + WID_DST(af), WID_DST(af), "Destination", + WID_GW(af), WID_GW(af), "Gateway", + "Flags", "Refs", "Use", + WID_IF(af), WID_IF(af), "Netif", "Expire"); + else + printf("%-*.*s %-*.*s %-6.6s %8.8s %6s\n", + WID_DST(af), WID_DST(af), "Destination", + WID_GW(af), WID_GW(af), "Gateway", + "Flags", "Netif", "Expire"); } static struct sockaddr * -kgetsa(dst) - register struct sockaddr *dst; +kgetsa(struct sockaddr *dst) { kget(dst, pt_u.u_sa); @@ -266,13 +303,12 @@ kgetsa(dst) } static void -p_tree(rn) - struct radix_node *rn; +p_tree(struct radix_node *rn) { again: kget(rn, rnode); - if (rnode.rn_b < 0) { + if (rnode.rn_bit < 0) { if (Aflag) printf("%-8.8lx ", (u_long)rn); if (rnode.rn_flags & RNF_ROOT) { @@ -296,8 +332,8 @@ again: printf("%-8.8lx ", (u_long)rn); p_rtnode(); } - rn = rnode.rn_r; - p_tree(rnode.rn_l); + rn = rnode.rn_right; + p_tree(rnode.rn_left); p_tree(rn); } } @@ -305,11 +341,11 @@ again: char nbuf[20]; static void -p_rtnode() +p_rtnode(void) { struct radix_mask *rm = rnode.rn_mklist; - if (rnode.rn_b < 0) { + if (rnode.rn_bit < 0) { if (rnode.rn_mask) { printf("\t mask "); p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), @@ -317,14 +353,14 @@ p_rtnode() } else if (rm == 0) return; } else { - sprintf(nbuf, "(%d)", rnode.rn_b); - printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_l, (u_long)rnode.rn_r); + sprintf(nbuf, "(%d)", rnode.rn_bit); + printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right); } while (rm) { kget(rm, rmask); sprintf(nbuf, " %d refs, ", rmask.rm_refs); printf(" mk = %8.8lx {(%d),%s", - (u_long)rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " "); + (u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " "); if (rmask.rm_flags & RNF_NORMAL) { struct radix_node rnode_aux; printf(" , "); @@ -342,7 +378,7 @@ p_rtnode() } static void -ntreestuff() +ntreestuff(void) { size_t needed; int mib[6]; @@ -373,8 +409,7 @@ ntreestuff() } static void -np_rtentry(rtm) - register struct rt_msghdr *rtm; +np_rtentry(struct rt_msghdr *rtm) { register struct sockaddr *sa = (struct sockaddr *)(rtm + 1); #ifdef notdef @@ -405,9 +440,7 @@ np_rtentry(rtm) p_sockaddr(sa, NULL, 0, 36); else { 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); + sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa); p_sockaddr(sa, NULL, 0, 18); } p_flags(rtm->rtm_flags & interesting, "%-6.6s "); @@ -415,9 +448,7 @@ np_rtentry(rtm) } static void -p_sockaddr(sa, mask, flags, width) - struct sockaddr *sa, *mask; - int flags, width; +p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) { char workbuf[128], *cplim; register char *cp = workbuf; @@ -427,8 +458,11 @@ p_sockaddr(sa, mask, flags, width) { register struct sockaddr_in *sin = (struct sockaddr_in *)sa; - if (sin->sin_addr.s_addr == INADDR_ANY) - cp = "default"; + if ((sin->sin_addr.s_addr == INADDR_ANY) && + mask && + ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) + ==0L) + cp = "default" ; else if (flags & RTF_HOST) cp = routename(sin->sin_addr.s_addr); else if (mask) @@ -439,7 +473,36 @@ p_sockaddr(sa, mask, flags, width) cp = netname(sin->sin_addr.s_addr, 0L); break; } -#ifdef IPX + +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; + struct in6_addr *in6 = &sa6->sin6_addr; + + /* + * XXX: This is a special workaround for KAME kernels. + * sin6_scope_id field of SA should be set in the future. + */ + if (IN6_IS_ADDR_LINKLOCAL(in6) || + IN6_IS_ADDR_MC_LINKLOCAL(in6)) { + /* XXX: override is ok? */ + sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]); + *(u_short *)&in6->s6_addr[2] = 0; + } + + if (flags & RTF_HOST) + cp = routename6(sa6); + else if (mask) + cp = netname6(sa6, + &((struct sockaddr_in6 *)mask)->sin6_addr); + else { + cp = netname6(sa6, NULL); + } + break; + } +#endif /*INET6*/ +#ifndef __APPLE__ case AF_IPX: { struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; @@ -449,9 +512,6 @@ p_sockaddr(sa, mask, flags, width) cp = ipx_print(sa); break; } -#endif - -#if 0 case AF_APPLETALK: { if (!(flags & RTF_HOST) && mask) @@ -460,8 +520,12 @@ p_sockaddr(sa, mask, flags, width) cp = atalk_print(sa,11); break; } + case AF_NETGRAPH: + { + printf("%s", ((struct sockaddr_ng *)sa)->sg_data); + break; + } #endif - #ifdef NS case AF_NS: cp = ns_print(sa); @@ -526,9 +590,7 @@ p_sockaddr(sa, mask, flags, width) } static void -p_flags(f, format) - register int f; - char *format; +p_flags(int f, char *format) { char name[33], *flags; register struct bits *p = bits; @@ -541,10 +603,10 @@ p_flags(f, format) } static void -p_rtentry(rt) - register struct rtentry *rt; +p_rtentry(struct rtentry *rt) { static struct ifnet ifnet, *lastif; + struct rtentry parent; static char name[16]; static char prettyname[9]; struct sockaddr *sa; @@ -553,8 +615,11 @@ p_rtentry(rt) /* * Don't print protocol-cloned routes unless -a. */ - if (rt->rt_parent && !aflag) - return; + if (rt->rt_flags & RTF_WASCLONED && !aflag) { + kget(rt->rt_parent, parent); + if (parent.rt_flags & RTF_PRCLONING) + return; + } bzero(&addr, sizeof(addr)); if ((sa = kgetsa(rt_key(rt)))) @@ -562,40 +627,48 @@ p_rtentry(rt) bzero(&mask, sizeof(mask)); if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) bcopy(sa, &mask, sa->sa_len); - p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, WID_DST); - p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW); + p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, + WID_DST(addr.u_sa.sa_family)); + p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, + WID_GW(addr.u_sa.sa_family)); p_flags(rt->rt_flags, "%-6.6s "); - printf("%6d %8ld ", rt->rt_refcnt, rt->rt_use); + if (addr.u_sa.sa_family == AF_INET || lflag) { + printf("%6ld %8ld ", rt->rt_refcnt, rt->rt_use); + if (lflag) { + if (rt->rt_rmx.rmx_mtu != 0) + printf("%6lu ", rt->rt_rmx.rmx_mtu); + else + printf("%6s ", ""); + } + } if (rt->rt_ifp) { if (rt->rt_ifp != lastif) { kget(rt->rt_ifp, ifnet); kread((u_long)ifnet.if_name, name, 16); lastif = rt->rt_ifp; snprintf(prettyname, sizeof prettyname, - "%.6s%d", name, ifnet.if_unit); + "%s%d", name, ifnet.if_unit); } - printf("%8.8s", prettyname); + printf("%*.*s", WID_IF(addr.u_sa.sa_family), + WID_IF(addr.u_sa.sa_family), prettyname); if (rt->rt_rmx.rmx_expire) { time_t expire_time; if ((expire_time = rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0) - printf(" %6d%s", (int)expire_time, - rt->rt_nodes[0].rn_dupedkey ? " =>" : ""); - } else if (rt->rt_nodes[0].rn_dupedkey) { - printf(" =>"); + printf(" %6d", (int)expire_time); } - + if (rt->rt_nodes[0].rn_dupedkey) + printf(" =>"); } putchar('\n'); } char * -routename(in) - u_long in; +routename(u_long in) { register char *cp; - static char line[MAXHOSTNAMELEN + 1]; + static char line[MAXHOSTNAMELEN]; struct hostent *hp; cp = 0; @@ -604,7 +677,7 @@ routename(in) AF_INET); if (hp) { cp = hp->h_name; - trimdomain(cp); + //### trimdomain(cp, strlen(cp)); } } if (cp) { @@ -620,8 +693,7 @@ routename(in) } static u_long -forgemask(a) - u_long a; +forgemask(u_long a) { u_long m; @@ -635,9 +707,7 @@ forgemask(a) } static void -domask(dst, addr, mask) - char *dst; - u_long addr, mask; +domask(char *dst, u_long addr, u_long mask) { register int b, i; @@ -669,74 +739,182 @@ domask(dst, addr, mask) * The address is assumed to be that of a net or subnet, not a host. */ char * -netname(in, mask) - u_long in, mask; +netname(u_long in, u_long mask) { char *cp = 0; - static char line[MAXHOSTNAMELEN + 1]; + static char line[MAXHOSTNAMELEN]; struct netent *np = 0; u_long net, omask, dmask; register u_long i; i = ntohl(in); + dmask = forgemask(i); omask = mask; if (!nflag && i) { - dmask = forgemask(i); net = i & dmask; if (!(np = getnetbyaddr(i, AF_INET)) && net != i) np = getnetbyaddr(net, AF_INET); if (np) { cp = np->n_name; - trimdomain(cp); + //### trimdomain(cp, strlen(cp)); } } if (cp) strncpy(line, cp, sizeof(line) - 1); - else if ((i & 0xffffff) == 0) - sprintf(line, "%lu", C(i >> 24)); - else if ((i & 0xffff) == 0) - sprintf(line, "%lu.%lu", C(i >> 24) , C(i >> 16)); - else if ((i & 0xff) == 0) - sprintf(line, "%lu.%lu.%lu", C(i >> 24), C(i >> 16), C(i >> 8)); - else - sprintf(line, "%lu.%lu.%lu.%lu", C(i >> 24), - C(i >> 16), C(i >> 8), C(i)); + else { + switch (dmask) { + case IN_CLASSA_NET: + if ((i & IN_CLASSA_HOST) == 0) { + sprintf(line, "%lu", C(i >> 24)); + break; + } + /* FALLTHROUGH */ + case IN_CLASSB_NET: + if ((i & IN_CLASSB_HOST) == 0) { + sprintf(line, "%lu.%lu", + C(i >> 24), C(i >> 16)); + break; + } + /* FALLTHROUGH */ + case IN_CLASSC_NET: + if ((i & IN_CLASSC_HOST) == 0) { + sprintf(line, "%lu.%lu.%lu", + C(i >> 24), C(i >> 16), C(i >> 8)); + break; + } + /* FALLTHROUGH */ + default: + sprintf(line, "%lu.%lu.%lu.%lu", + C(i >> 24), C(i >> 16), C(i >> 8), C(i)); + break; + } + } domask(line+strlen(line), i, omask); return (line); } +#ifdef INET6 +char * +netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask) +{ + static char line[MAXHOSTNAMELEN]; + u_char *p = (u_char *)mask; + u_char *lim; + int masklen, illegal = 0, flag = NI_WITHSCOPEID; + + if (mask) { + for (masklen = 0, lim = p + 16; p < lim; p++) { + switch (*p) { + case 0xff: + masklen += 8; + break; + case 0xfe: + masklen += 7; + break; + case 0xfc: + masklen += 6; + break; + case 0xf8: + masklen += 5; + break; + case 0xf0: + masklen += 4; + break; + case 0xe0: + masklen += 3; + break; + case 0xc0: + masklen += 2; + break; + case 0x80: + masklen += 1; + break; + case 0x00: + break; + default: + illegal ++; + break; + } + } + if (illegal) + fprintf(stderr, "illegal prefixlen\n"); + } + else + masklen = 128; + + if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) + return("default"); + + if (nflag) + flag |= NI_NUMERICHOST; + getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line), + NULL, 0, flag); + + if (nflag) + sprintf(&line[strlen(line)], "/%d", masklen); + + return line; +} + +char * +routename6(struct sockaddr_in6 *sa6) +{ + static char line[MAXHOSTNAMELEN]; + int flag = NI_WITHSCOPEID; + /* use local variable for safety */ + struct sockaddr_in6 sa6_local = {sizeof(sa6_local), AF_INET6, }; + + sa6_local.sin6_addr = sa6->sin6_addr; + sa6_local.sin6_scope_id = sa6->sin6_scope_id; + + if (nflag) + flag |= NI_NUMERICHOST; + + getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len, + line, sizeof(line), NULL, 0, flag); + + return line; +} +#endif /*INET6*/ + /* * Print routing statistics */ void -rt_stats(off) - u_long off; +rt_stats(u_long rtsaddr, u_long rttaddr) { struct rtstat rtstat; + int rttrash; - if (off == 0) { + if (rtsaddr == 0) { printf("rtstat: symbol not in namelist\n"); return; } - kread(off, (char *)&rtstat, sizeof (rtstat)); + if (rttaddr == 0) { + printf("rttrash: symbol not in namelist\n"); + return; + } + kread(rtsaddr, (char *)&rtstat, sizeof (rtstat)); + kread(rttaddr, (char *)&rttrash, sizeof (rttrash)); printf("routing:\n"); - printf("\t%u bad routing redirect%s\n", - rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); - printf("\t%u dynamically created route%s\n", - rtstat.rts_dynamic, plural(rtstat.rts_dynamic)); - printf("\t%u new gateway%s due to redirects\n", - rtstat.rts_newgateway, plural(rtstat.rts_newgateway)); - printf("\t%u destination%s found unreachable\n", - rtstat.rts_unreach, plural(rtstat.rts_unreach)); - printf("\t%u use%s of a wildcard route\n", - rtstat.rts_wildcard, plural(rtstat.rts_wildcard)); -} -#ifdef IPX +#define p(f, m) if (rtstat.f || sflag <= 1) \ + printf(m, rtstat.f, plural(rtstat.f)) + + p(rts_badredirect, "\t%u bad routing redirect%s\n"); + p(rts_dynamic, "\t%u dynamically created route%s\n"); + p(rts_newgateway, "\t%u new gateway%s due to redirects\n"); + p(rts_unreach, "\t%u destination%s found unreachable\n"); + p(rts_wildcard, "\t%u use%s of a wildcard route\n"); +#undef p + if (rttrash || sflag <= 1) + printf("\t%u route%s not in table but not freed\n", + rttrash, plural(rttrash)); +} +#ifndef __APPLE__ char * -ipx_print(sa) - register struct sockaddr *sa; +ipx_print(struct sockaddr *sa) { u_short port; struct servent *sp = 0; @@ -805,8 +983,7 @@ ipx_print(sa) } char * -ipx_phost(sa) - struct sockaddr *sa; +ipx_phost(struct sockaddr *sa) { register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa; struct sockaddr_ipx work; @@ -825,14 +1002,12 @@ ipx_phost(sa) return(p); } #endif - #ifdef NS short ns_nullh[] = {0,0,0}; short ns_bh[] = {-1,-1,-1}; char * -ns_print(sa) - register struct sockaddr *sa; +ns_print(struct sockaddr *sa) { register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa; struct ns_addr work; @@ -878,8 +1053,7 @@ ns_print(sa) } char * -ns_phost(sa) - struct sockaddr *sa; +ns_phost(struct sockaddr *sa) { register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa; struct sockaddr_ns work; @@ -898,8 +1072,7 @@ ns_phost(sa) #endif void -upHex(p0) - char *p0; +upHex(char *p0) { register char *p = p0;