int net_rt_list(net_rt_h *rth, void *arg) { /* net.route.0.inet.flags.gateway */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_FLAGS, RTF_GATEWAY}; char ifname[IFNAMSIZ], *buf, *p; struct rt_msghdr *rt; struct sockaddr *sa, *sa_tab[RTAX_MAX]; struct sa dst, gw; size_t l; int i, err = 0; if (sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) return errno; if (!l) return ENOENT; buf = mem_alloc(l, NULL); if (!buf) return ENOMEM; if (sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { err = errno; goto out; } for (p = buf; p<buf+l; p += rt->rtm_msglen) { rt = (void *)p; /* buffer is aligned */ sa = (struct sockaddr *)(rt + 1); if (rt->rtm_type != RTM_GET) continue; if (!(rt->rtm_flags & RTF_UP)) continue; for (i=0; i<RTAX_MAX; i++) { if (rt->rtm_addrs & (1 << i)) { sa_tab[i] = sa; sa = (struct sockaddr *) ((char *)sa + ROUNDUP(sa->sa_len)); } else { sa_tab[i] = NULL; } } if ((rt->rtm_addrs & RTA_DST) == RTA_DST) { err = sa_set_sa(&dst, sa_tab[RTAX_DST]); if (err) continue; } if ((rt->rtm_addrs & RTA_GATEWAY) == RTA_GATEWAY) { err = sa_set_sa(&gw, sa_tab[RTAX_GATEWAY]); if (err) continue; } if_indextoname(rt->rtm_index, ifname); if (rth(ifname, &dst, 0, &gw, arg)) break; } out: mem_deref(buf); return err; }
/** * List all entries in the routing table * * @param rth Route entry handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int net_rt_list(net_rt_h *rth, void *arg) { union { uint8_t buf[BUFSIZE]; struct nlmsghdr msg[1]; } u; struct nlmsghdr *nlmsg; int sock, len, seq = 0, err = 0; if (!rth) return EINVAL; /* Create Socket */ if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { DEBUG_WARNING("list: socket(): (%s)\n", strerror(errno)); return errno; } /* Initialize the buffer */ memset(u.buf, 0, sizeof(u.buf)); /* point the header and the msg structure pointers into the buffer */ nlmsg = u.msg; /* Fill in the nlmsg header*/ nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); nlmsg->nlmsg_type = RTM_GETROUTE; nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nlmsg->nlmsg_seq = seq++; nlmsg->nlmsg_pid = getpid(); /* Send the request */ if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) { err = errno; DEBUG_WARNING("list: write to socket failed (%s)\n", strerror(err)); goto out; } /* Read the response */ if ((len = read_sock(sock, u.buf, sizeof(u.buf), seq, getpid())) < 0) { err = errno; DEBUG_WARNING("list: read from socket failed (%s)\n", strerror(err)); goto out; } /* Parse and print the response */ for (;NLMSG_OK(nlmsg,(uint32_t)len);nlmsg = NLMSG_NEXT(nlmsg,len)) { struct net_rt rt; memset(&rt, 0, sizeof(struct net_rt)); if (0 != rt_parse(nlmsg, &rt)) continue; #ifdef HAVE_INET6 if (AF_INET6 == sa_af(&rt.dst) && IN6_IS_ADDR_UNSPECIFIED(&rt.dst.u.in6.sin6_addr)) continue; #endif if (rth(rt.ifname, &rt.dst, rt.dstlen, &rt.gw, arg)) break; } out: (void)close(sock); return err; }