+ return;
+}
+
+static union {
+ struct sockaddr u_sa;
+ u_short u_data[128];
+} pt_u;
+int do_rtent = 0;
+struct rtentry rtentry;
+struct radix_node rnode;
+struct radix_mask rmask;
+
+int NewTree = 0;
+treestuff(rtree)
+off_t rtree;
+{
+ struct radix_node_head *rnh, head;
+
+ if (Aflag == 0 && NewTree)
+ return(ntreestuff());
+ for (kget(rtree, rnh); rnh; rnh = head.rnh_next) {
+ kget(rnh, head);
+ if (head.rnh_af == 0) {
+ if (Aflag || af == AF_UNSPEC) {
+ printf("Netmasks:\n");
+ p_tree(head.rnh_treetop);
+ }
+ } else if (af == AF_UNSPEC || af == head.rnh_af) {
+ printf("\nRoute Tree for Protocol Family %d:\n",
+ head.rnh_af);
+ do_rtent = 1;
+ p_tree(head.rnh_treetop);
+ }
+ }
+}
+
+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);
+ }
+ return (&pt_u.u_sa);
+}
+
+p_tree(rn)
+struct radix_node *rn;
+{
+
+again:
+ kget(rn, rnode);
+ if (rnode.rn_b < 0) {
+ if (Aflag)
+ printf("%-8.8x ", rn);
+ if (rnode.rn_flags & RNF_ROOT)
+ printf("(root node)%s",
+ rnode.rn_dupedkey ? " =>\n" : "\n");
+ else if (do_rtent) {
+ kget(rn, rtentry);
+ p_rtentry(&rtentry);
+ if (Aflag)
+ p_rtnode();
+ } else {
+ p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
+ 0, 44);
+ putchar('\n');
+ }
+ if (rn = rnode.rn_dupedkey)
+ goto again;
+ } else {
+ if (Aflag && do_rtent) {
+ printf("%-8.8x ", rn);
+ p_rtnode();
+ }
+ rn = rnode.rn_r;
+ p_tree(rnode.rn_l);
+ p_tree(rn);
+ }
+}
+char nbuf[20];
+
+p_rtnode()
+{
+
+ struct radix_mask *rm = rnode.rn_mklist;
+ if (rnode.rn_b < 0) {
+ if (rnode.rn_mask) {
+ printf("\t mask ");
+ p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
+ 0, -1);
+ } else if (rm == 0)
+ return;
+ } else {
+ sprintf(nbuf, "(%d)", rnode.rn_b);
+ printf("%6.6s %8.8x : %8.8x", nbuf, rnode.rn_l, rnode.rn_r);
+ }
+ while (rm) {
+ kget(rm, rmask);
+ 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);
+ putchar('}');
+ if (rm = rmask.rm_mklist)
+ printf(" ->");
+ }
+ putchar('\n');
+}
+
+ntreestuff()
+{
+ int needed;
+ 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);}
+ if ((buf = malloc(needed)) == 0)
+ { printf("out of space\n"); exit(1);}
+ if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0)
+ { perror("actual retrieval of routing table"); exit(1);}
+ lim = buf + needed;
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ np_rtentry(rtm);
+ }
+}
+
+np_rtentry(rtm)
+register struct rt_msghdr *rtm;
+{
+ register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+ static int masks_done, old_af, banner_printed;
+ int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
+
+#ifdef notdef
+ /* for the moment, netmasks are skipped over */
+ if (!banner_printed) {
+ printf("Netmasks:\n");
+ banner_printed = 1;
+ }
+ if (masks_done == 0) {
+ if (rtm->rtm_addrs != RTA_DST ) {
+ masks_done = 1;
+ af = sa->sa_family;
+ }
+ } else
+#endif
+ af = sa->sa_family;
+ if (af != old_af) {
+ printf("\nRoute Tree for Protocol Family %d:\n", af);
+ old_af = af;
+ }
+ if (rtm->rtm_addrs == RTA_DST)
+ p_sockaddr(sa, 0, 36);
+ else {
+ p_sockaddr(sa, 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_flags(rtm->rtm_flags & interesting, "%-6.6s ");
+ putchar('\n');
+}
+
+p_sockaddr(sa, flags, width)
+struct sockaddr *sa;
+int flags, width;
+{
+ char format[20], workbuf[128], *cp, *cplim;
+ register char *cpout;
+
+ switch(sa->sa_family) {
+ case AF_INET:
+ {
+ 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));
+ }
+ break;
+
+ case AF_NS:
+ cp = ns_print((struct sockaddr_ns *)sa);
+ break;
+
+ default:
+ {
+ register u_short *s = ((u_short *)sa->sa_data), *slim;
+
+ slim = (u_short *) sa + ((sa->sa_len + sizeof(u_short) - 1) /
+ sizeof(u_short));
+ cp = workbuf;
+ cplim = cp + sizeof(workbuf) - 6;
+ cp += sprintf(cp, "(%d)", sa->sa_family);
+ while (s < slim && cp < cplim)
+ cp += sprintf(cp, " %x", *s++);
+ cp = workbuf;
+ }
+ }
+ if (width < 0 )
+ printf("%s ", cp);
+ else {
+ if (nflag)
+ printf("%-*s ", width, cp);
+ else
+ printf("%-*.*s ", width, width, cp);
+ }
+}
+
+p_flags(f, format)
+register int f;
+char *format;
+{
+ char name[33], *flags;
+ register struct bits *p = bits;
+ for (flags = name; p->b_mask; p++)
+ if (p->b_mask & f)
+ *flags++ = p->b_val;
+ *flags = '\0';
+ printf(format, name);
+}
+
+p_rtentry(rt)
+register struct rtentry *rt;
+{
+ char name[16];
+ register struct sockaddr *sa;
+ struct ifnet ifnet;
+
+ p_sockaddr(kgetsa(rt_key(rt)), rt->rt_flags, 16);
+ p_sockaddr(kgetsa(rt->rt_gateway), 0, 18);
+ p_flags(rt->rt_flags, "%-6.6s ");
+ printf("%6d %8d ", rt->rt_refcnt, rt->rt_use);
+ if (rt->rt_ifp == 0) {
+ putchar('\n');
+ return;
+ }
+ kget(rt->rt_ifp, ifnet);
+ kvm_read((off_t)ifnet.if_name, name, 16);
+ printf(" %.15s%d%s", name, ifnet.if_unit,
+ rt->rt_nodes[0].rn_dupedkey ? " =>\n" : "\n");
+}
+
+p_ortentry(rt)
+register struct ortentry *rt;
+{
+ char name[16], *flags;
+ register struct bits *p;
+ register struct sockaddr_in *sin;
+ struct ifnet ifnet;
+
+ p_sockaddr(&rt->rt_dst, rt->rt_flags, 16);
+ p_sockaddr(&rt->rt_gateway, 0, 18);
+ p_flags(rt->rt_flags, "%-6.6s ");
+ printf("%6d %8d ", rt->rt_refcnt, rt->rt_use);
+ if (rt->rt_ifp == 0) {
+ putchar('\n');
+ return;
+ }
+ kget(rt->rt_ifp, ifnet);
+ kvm_read((off_t)ifnet.if_name, name, 16);
+ printf(" %.15s%d\n", name, ifnet.if_unit);