int arp_loop(arp_t *r, arp_handler callback, void *arg) { struct ifnet *ifp, ifnet; struct ifnet_arp_cache_head ifarp; struct radix_node_head *head; struct nlist nl[2]; int fd, ret = 0; memset(nl, 0, sizeof(nl)); nl[0].n_name = "ifnet"; if (knlist(nl) < 0 || nl[0].n_type == 0 || (fd = open("/dev/kmem", O_RDONLY, 0)) < 0) return (-1); for (ifp = (struct ifnet *)nl[0].n_value; ifp != NULL; ifp = ifnet.if_next) { _kread(fd, ifp, &ifnet, sizeof(ifnet)); if (ifnet.if_arp_cache_head != NULL) { _kread(fd, ifnet.if_arp_cache_head, &ifarp, sizeof(ifarp)); /* XXX - only ever one rnh, only ever AF_INET. */ if ((ret = _radix_walk(fd, ifarp.arp_cache_head.rnh_treetop, callback, arg)) != 0) break; } } close(fd); return (ret); }
int route_loop(route_t *r, route_handler callback, void *arg) { struct radix_node_head *rnh, head; struct nlist nl[2]; int fd, ret = 0; memset(nl, 0, sizeof(nl)); nl[0].n_name = "radix_node_head"; if (knlist(nl) < 0 || nl[0].n_type == 0 || (fd = open("/dev/kmem", O_RDONLY, 0)) < 0) return (-1); for (_kread(fd, (void *)nl[0].n_value, &rnh, sizeof(rnh)); rnh != NULL; rnh = head.rnh_next) { _kread(fd, rnh, &head, sizeof(head)); /* XXX - only IPv4 for now... */ if (head.rnh_af == AF_INET) { if ((ret = _radix_walk(fd, head.rnh_treetop, callback, arg)) != 0) break; } } close(fd); return (ret); }
static int _radix_walk(int fd, struct radix_node *rn, arp_handler callback, void *arg) { struct radix_node rnode; struct rtentry rt; struct sockaddr_in sin; struct arptab at; struct arp_entry entry; int ret = 0; again: _kread(fd, rn, &rnode, sizeof(rnode)); if (rnode.rn_b < 0) { if (!(rnode.rn_flags & RNF_ROOT)) { _kread(fd, rn, &rt, sizeof(rt)); _kread(fd, rt_key(&rt), &sin, sizeof(sin)); addr_ston((struct sockaddr *)&sin, &entry.arp_pa); _kread(fd, rt.rt_llinfo, &at, sizeof(at)); if (at.at_flags & ATF_COM) { addr_pack(&entry.arp_ha, ADDR_TYPE_ETH, ETH_ADDR_BITS, at.at_hwaddr, ETH_ADDR_LEN); if ((ret = callback(&entry, arg)) != 0) return (ret); } } if ((rn = rnode.rn_dupedkey)) goto again; } else { rn = rnode.rn_r; if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0) return (ret); if ((ret = _radix_walk(fd, rn, callback, arg)) != 0) return (ret); } return (ret); }
static int _radix_walk(int fd, struct radix_node *rn, route_handler callback, void *arg) { struct radix_node rnode; struct rtentry rt; struct sockaddr_in sin; struct route_entry entry; int ret = 0; again: _kread(fd, rn, &rnode, sizeof(rnode)); if (rnode.rn_b < 0) { if (!(rnode.rn_flags & RNF_ROOT)) { entry.intf_name[0] = '\0'; _kread(fd, rn, &rt, sizeof(rt)); _kread(fd, rt_key(&rt), &sin, sizeof(sin)); addr_ston((struct sockaddr *)&sin, &entry.route_dst); if (!(rt.rt_flags & RTF_HOST)) { _kread(fd, rt_mask(&rt), &sin, sizeof(sin)); addr_stob((struct sockaddr *)&sin, &entry.route_dst.addr_bits); } _kread(fd, rt.rt_gateway, &sin, sizeof(sin)); addr_ston((struct sockaddr *)&sin, &entry.route_gw); entry.metric = 0; if ((ret = callback(&entry, arg)) != 0) return (ret); } if ((rn = rnode.rn_dupedkey)) goto again; } else { rn = rnode.rn_r; if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0) return (ret); if ((ret = _radix_walk(fd, rn, callback, arg)) != 0) return (ret); } return (ret); }