/* * Print routing tables. */ void routepr(u_long rtree, u_long mtree, u_long af2idx, u_long rtbl_id_max, u_int tableid) { struct radix_node_head *rnh, head; int i, idxmax = 0; u_int rtidxmax; printf("Routing tables\n"); if (rtree == 0 || af2idx == 0) { printf("rt_tables: symbol not in namelist\n"); return; } kread((u_long)rtree, &rt_head, sizeof(rt_head)); kread((u_long)rtbl_id_max, &rtidxmax, sizeof(rtidxmax)); kread((long)af2idx, &af2rtafidx, sizeof(af2rtafidx)); for (i = 0; i <= AF_MAX; i++) { if (af2rtafidx[i] > idxmax) idxmax = af2rtafidx[i]; } if ((rnt = calloc(rtidxmax + 1, sizeof(struct radix_node_head **))) == NULL) err(1, NULL); kread((u_long)rt_head, rnt, (rtidxmax + 1) * sizeof(struct radix_node_head **)); if (tableid > rtidxmax || rnt[tableid] == NULL) { printf("Bad table %u\n", tableid); return; } kread((u_long)rnt[tableid], rt_tables, (idxmax + 1) * sizeof(rnh)); for (i = 0; i <= AF_MAX; i++) { if (i == AF_UNSPEC) { if (Aflag && (af == AF_UNSPEC || af == 0xff)) { kread(mtree, &rnh, sizeof(rnh)); kread((u_long)rnh, &head, sizeof(head)); printf("Netmasks:\n"); p_tree(head.rnh_treetop); } continue; } if (af2rtafidx[i] == 0) /* no table for this AF */ continue; if ((rnh = rt_tables[af2rtafidx[i]]) == NULL) continue; kread((u_long)rnh, &head, sizeof(head)); if (af == AF_UNSPEC || af == i) { pr_family(i); do_rtent = 1; pr_rthdr(i, Aflag); p_tree(head.rnh_treetop); } } }
/* * Print a routing table entry. */ static void p_rtentry(struct rt_msghdr *rtm) { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); #ifdef notdef static int masks_done, banner_printed; #endif static int old_af; int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; int width; #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 (old_af != af) { old_af = af; pr_family(af); pr_rthdr(); } /* * Print the information. If wflag is set p_sockaddr() can return * a wider width then specified and we try to fit the second * address in any remaining space so the flags still lines up. */ if (rtm->rtm_addrs == RTA_DST) { p_sockaddr(sa, 0, WID_DST + WID_GW + 2); } else { width = p_sockaddr(sa, rtm->rtm_flags, WID_DST); sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa); p_sockaddr(sa, 0, WID_GW + WID_DST - width); } p_flags(rtm->rtm_flags & interesting, "%-6.6s "); putchar('\n'); }
/* * Print routing tables. */ void show_route_statistic() { struct radix_node_head *rnh, *head; int i; printf("Routing tables\n"); if (Aflag == 0 && NewTree) ntreestuff(); else { //kget(rtree, rt_tables); for (i = 0; i <= AF_MAX; i++) { if ((rnh = rt_tables[i]) == 0) continue; //kget(rnh, head); head = rnh; if (i == AF_UNSPEC) { if (Aflag && af == 0) { printf("Netmasks:\n"); p_tree(head->rnh_treetop); } } else if (af == AF_UNSPEC || af == i) { size_cols(i, head->rnh_treetop); pr_family(i); do_rtent = 1; pr_rthdr(i); p_tree(head->rnh_treetop); } } } }
/* * Print routing tables. */ void routepr(u_long rtree) { struct radix_node_head *rnh, head; int i; printf("Routing tables\n"); if (Aflag == 0 && NewTree) ntreestuff(); else { if (rtree == 0) { printf("rt_tables: symbol not in namelist\n"); return; } kget(rtree, rt_tables); for (i = 0; i <= AF_MAX; i++) { if ((rnh = rt_tables[i]) == 0) continue; kget(rnh, head); if (i == AF_UNSPEC) { if (Aflag && af == 0) { printf("Netmasks:\n"); p_tree(head.rnh_treetop); } } else if (af == AF_UNSPEC || af == i) { size_cols(i, head.rnh_treetop); pr_family(i); do_rtent = 1; pr_rthdr(i); p_tree(head.rnh_treetop); } } } }
/* * Print routing tables. */ void routepr(u_long rtree) { struct radix_node_head **rnhp, *rnh, head; size_t intsize; int fam, fibnum, numfibs; intsize = sizeof(int); if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) fibnum = 0; if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) numfibs = 1; rt_tables = calloc(numfibs * (AF_MAX+1), sizeof(struct radix_node_head *)); if (rt_tables == NULL) err(EX_OSERR, "memory allocation failed"); /* * Since kernel & userland use different timebase * (time_uptime vs time_second) and we are reading kernel memory * directly we should do rt_rmx.rmx_expire --> expire_time conversion. */ if (clock_gettime(CLOCK_UPTIME, &uptime) < 0) err(EX_OSERR, "clock_gettime() failed"); printf("Routing tables\n"); if (Aflag == 0 && NewTree) ntreestuff(); else { if (rtree == 0) { printf("rt_tables: symbol not in namelist\n"); return; } if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs * (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0) return; for (fam = 0; fam <= AF_MAX; fam++) { int tmpfib; switch (fam) { case AF_INET6: case AF_INET: tmpfib = fibnum; break; default: tmpfib = 0; } rnhp = (struct radix_node_head **)*rt_tables; /* Calculate the in-kernel address. */ rnhp += tmpfib * (AF_MAX+1) + fam; /* Read the in kernel rhn pointer. */ if (kget(rnhp, rnh) != 0) continue; if (rnh == NULL) continue; /* Read the rnh data. */ if (kget(rnh, head) != 0) continue; if (fam == AF_UNSPEC) { if (Aflag && af == 0) { printf("Netmasks:\n"); p_tree(head.rnh_treetop); } } else if (af == AF_UNSPEC || af == fam) { size_cols(fam, head.rnh_treetop); pr_family(fam); do_rtent = 1; pr_rthdr(fam); p_tree(head.rnh_treetop); } } } }
static void ntreestuff(int fibnum, int af) { size_t needed; int mib[7]; char *buf, *next, *lim; struct rt_msghdr *rtm; struct sockaddr *sa; int fam = 0, ifindex = 0, size; struct ifaddrs *ifap, *ifa; struct sockaddr_dl *sdl; /* * Retrieve interface list at first * since we need #ifindex -> if_xname match */ if (getifaddrs(&ifap) != 0) err(EX_OSERR, "getifaddrs"); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; sdl = (struct sockaddr_dl *)ifa->ifa_addr; ifindex = sdl->sdl_index; if (ifindex >= ifmap_size) { size = roundup(ifindex + 1, 32) * sizeof(struct ifmap_entry); if ((ifmap = realloc(ifmap, size)) == NULL) errx(2, "realloc(%d) failed", size); memset(&ifmap[ifmap_size], 0, size - ifmap_size * sizeof(struct ifmap_entry)); ifmap_size = roundup(ifindex + 1, 32); } if (*ifmap[ifindex].ifname != '\0') continue; strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ); } freeifaddrs(ifap); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = af; mib[4] = NET_RT_DUMP; mib[5] = 0; mib[6] = fibnum; if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) { err(1, "sysctl: net.route.0.0.dump estimate"); } if ((buf = malloc(needed)) == 0) { errx(2, "malloc(%lu)", (unsigned long)needed); } if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { err(1, "sysctl: net.route.0.0.dump"); } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; /* * Peek inside header to determine AF */ sa = (struct sockaddr *)(rtm + 1); if (fam != sa->sa_family) { fam = sa->sa_family; size_cols(fam, NULL); pr_family(fam); pr_rthdr(fam); } np_rtentry(rtm); } }
static void p_rtable_sysctl(int fibnum, int af) { size_t needed; int mib[7]; char *buf, *next, *lim; struct rt_msghdr *rtm; struct sockaddr *sa; int fam = AF_UNSPEC, ifindex = 0, size; int need_table_close = false; struct ifaddrs *ifap, *ifa; struct sockaddr_dl *sdl; /* * Retrieve interface list at first * since we need #ifindex -> if_xname match */ if (getifaddrs(&ifap) != 0) err(EX_OSERR, "getifaddrs"); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; sdl = (struct sockaddr_dl *)ifa->ifa_addr; ifindex = sdl->sdl_index; if (ifindex >= ifmap_size) { size = roundup(ifindex + 1, 32) * sizeof(struct ifmap_entry); if ((ifmap = realloc(ifmap, size)) == NULL) errx(2, "realloc(%d) failed", size); memset(&ifmap[ifmap_size], 0, size - ifmap_size * sizeof(struct ifmap_entry)); ifmap_size = roundup(ifindex + 1, 32); } if (*ifmap[ifindex].ifname != '\0') continue; strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ); } freeifaddrs(ifap); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = af; mib[4] = NET_RT_DUMP; mib[5] = 0; mib[6] = fibnum; if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d estimate", af, fibnum); if ((buf = malloc(needed)) == NULL) errx(2, "malloc(%lu)", (unsigned long)needed); if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum); lim = buf + needed; xo_open_container("route-table"); xo_open_list("rt-family"); for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; if (rtm->rtm_version != RTM_VERSION) continue; /* * Peek inside header to determine AF */ sa = (struct sockaddr *)(rtm + 1); /* Only print family first time. */ if (fam != sa->sa_family) { if (need_table_close) { xo_close_list("rt-entry"); xo_close_instance("rt-family"); } need_table_close = true; fam = sa->sa_family; wid_dst = WID_DST_DEFAULT(fam); wid_gw = WID_GW_DEFAULT(fam); wid_flags = 6; wid_pksent = 8; wid_mtu = 6; wid_if = WID_IF_DEFAULT(fam); wid_expire = 6; xo_open_instance("rt-family"); pr_family(fam); xo_open_list("rt-entry"); pr_rthdr(fam); } p_rtentry_sysctl("rt-entry", rtm); } if (need_table_close) { xo_close_list("rt-entry"); xo_close_instance("rt-family"); } xo_close_list("rt-family"); xo_close_container("route-table"); free(buf); }