int kernel_routes(struct kernel_route *routes, int maxroutes) { int mib[6]; char *buf, *p; size_t len; struct rt_msghdr *rtm; int rc, i; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_UNSPEC; /* Address family */ mib[4] = NET_RT_DUMP; /* Dump the kernel routing table */ mib[5] = 0; /* No flags */ rc = sysctl(mib, 6, NULL, &len, NULL, 0); if (rc < 0) { perror("kernel_routes(len)"); return -1; } buf = malloc(len); if(!buf) { perror("kernel_routes(malloc)"); return -1; } rc = sysctl(mib, 6, buf, &len, NULL, 0); if (rc < 0) { perror("kernel_routes(dump)"); goto fail; } i = 0; p = buf; while(p < buf + len && i < maxroutes) { rtm = (struct rt_msghdr*)p; rc = parse_kernel_route(rtm, &routes[i]); if(rc) goto cont; if(debug > 2) print_kernel_route(1,&routes[i]); i++; cont: p += rtm->rtm_msglen; } free(buf); return i; fail: free(buf); return -1; }
static int socket_read(int sock) { int rc; struct { struct rt_msghdr rtm; struct sockaddr_storage addr[RTAX_MAX]; } buf; rc = read(sock, &buf, sizeof(buf)); if(rc <= 0) { perror("kernel_callback(read)"); return 0; } if(buf.rtm.rtm_msglen != rc) { kdebugf("kernel_callback(length)\n"); return -1; } if(buf.rtm.rtm_type == RTM_ADD || buf.rtm.rtm_type == RTM_DELETE || buf.rtm.rtm_type == RTM_CHANGE) { struct kernel_route route; if(buf.rtm.rtm_errno) return 0; rc = parse_kernel_route(&buf.rtm, &route); if(rc < 0) return 0; if(debug > 2) print_kernel_route(1,&route); return 1; } return 0; }
static int filter_kernel_routes(struct nlmsghdr *nh, void *data) { int rc; struct kernel_route *current_route; struct kernel_route route; int maxroutes = 0; struct kernel_route *routes = NULL; int *found = NULL; int len; struct rtmsg *rtm; if(data) { void **args = (void**)data; maxroutes = *(int*)args[0]; routes = (struct kernel_route *)args[1]; found = (int*)args[2]; } len = nh->nlmsg_len; if(data && *found >= maxroutes) return 0; if(nh->nlmsg_type != RTM_NEWROUTE && (data || nh->nlmsg_type != RTM_DELROUTE)) return 0; rtm = (struct rtmsg*)NLMSG_DATA(nh); len -= NLMSG_LENGTH(0); if(rtm->rtm_protocol == RTPROT_BABEL) return 0; if(rtm->rtm_src_len != 0) return 0; if(data) current_route = &routes[*found]; else current_route = &route; rc = parse_kernel_route_rta(rtm, len, current_route); if(rc < 0) return 0; if(martian_prefix(current_route->prefix, current_route->plen)) return 0; /* Ignore default unreachable routes; no idea where they come from. */ if(current_route->plen == 0 && current_route->metric >= KERNEL_INFINITY) return 0; if(debug >= 2) { if(rc >= 0) { print_kernel_route(nh->nlmsg_type, rtm->rtm_protocol, rtm->rtm_type, current_route); } } if (data) *found = (*found)+1; return 1; }