[Toybox] [PATCH 2/3] Refactor display_routes to use rtnetlink
Eric Molitor
emolitor at molitor.org
Sun May 17 03:09:28 PDT 2020
---
toys/pending/route.c | 121 ++++++++++++++++++++++++++++++++-----------
1 file changed, 92 insertions(+), 29 deletions(-)
diff --git a/toys/pending/route.c b/toys/pending/route.c
index 562e5ecd..62fde509 100644
--- a/toys/pending/route.c
+++ b/toys/pending/route.c
@@ -158,45 +158,108 @@ static void get_flag_value(char *str, int flags)
*str = 0;
}
-// extract inet4 route info from /proc/net/route file and display it.
static void display_routes(void)
{
- unsigned long dest, gate, mask;
- int flags, ref, use, metric, mss, win, irtt, items;
- char iface[64] = {0,}, flag_val[10]; //there are 9 flags "UGHRDMDAC" for route.
+ int fd, msg_hdr_len, route_protocol;
+ struct nlmsghdr buf[8192 / sizeof(struct nlmsghdr)];
+ struct nlmsghdr *msg_hdr_ptr;
+ struct rtmsg req;
- FILE *fp = xfopen("/proc/net/route", "r");
+ struct rtmsg *route_entry;
+ struct rtattr *route_attribute;
- xprintf("Kernel IP routing table\n"
- "Destination Gateway Genmask Flags %s Iface\n",
- (toys.optflags & FLAG_e)? " MSS Window irtt" : "Metric Ref Use");
-
- if (fscanf(fp, "%*[^\n]\n") < 0) perror_exit("fscanf"); //skip 1st line
- while ((items = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", iface, &dest,
- &gate, &flags, &ref, &use, &metric, &mask, &mss, &win, &irtt)) == 11)
- {
- char *destip = toybuf, *gateip = toybuf+32, *maskip = toybuf+64; //ip string 16
+ fd = xsocket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (!(flags & RTF_UP)) continue; //skip down interfaces.
-
- if (!dest && !(toys.optflags & FLAG_n)) strcpy( destip, "default");
- else if (!inet_ntop(AF_INET, &dest, destip, 32)) perror_exit("inet");
+ memset(&req, 0, sizeof(req));
+ req.rtm_family = AF_INET;
+ req.rtm_table = RT_TABLE_MAIN;
- if (!gate && !(toys.optflags & FLAG_n)) strcpy( gateip, "*");
- else if (!inet_ntop(AF_INET, &gate, gateip, 32)) perror_exit("inet");
+ send_nlrtmsg(fd, RTM_GETROUTE, NLM_F_REQUEST | NLM_F_DUMP, &req);
- if (!inet_ntop(AF_INET, &mask, maskip, 32)) perror_exit("inet");
+ xprintf("Kernel IP routing table\n"
+ "Destination Gateway Genmask Flags %s Iface\n",
+ (toys.optflags & FLAG_e)? " MSS Window irtt" : "Metric Ref Use");
+
+ msg_hdr_len = xrecv(fd, buf, sizeof(buf));
+ msg_hdr_ptr = (struct nlmsghdr *) buf;
+ while (msg_hdr_ptr->nlmsg_type != NLMSG_DONE) {
+ while (NLMSG_OK(msg_hdr_ptr, msg_hdr_len)) {
+ route_entry = (struct rtmsg *) NLMSG_DATA(msg_hdr_ptr);
+ route_protocol = route_entry->rtm_protocol;
+
+ // Annoyingly NLM_F_MATCH is not yet implemented so even if we pass in
+ // RT_TABLE_MAIN with RTM_GETROUTE it still returns everything so we
+ // have to filter here.
+ if (route_entry->rtm_table == RT_TABLE_MAIN) {
+ struct in_addr netmask_addr;
+ char destip[32] = "0.0.0.0";
+ char gateip[32] = "0.0.0.0";
+ char netmask[32] = "0.0.0.0";
+ char flags[10] = "U";
+ uint32_t priority = 0;
+ char if_name[IF_NAMESIZE] = "-";
+ uint32_t route_netmask;
+
+ if (!(toys.optflags & FLAG_n)) strcpy(destip, "default");
+ if (!(toys.optflags & FLAG_n)) strcpy(gateip, "*");
+
+ route_netmask = route_entry->rtm_dst_len;
+ if (route_netmask == 0) {
+ netmask_addr.s_addr = ~((in_addr_t) -1);
+ } else {
+ netmask_addr.s_addr = htonl(~((1 << (32 - route_netmask)) - 1));
+ }
+ inet_ntop(AF_INET, &netmask_addr, netmask, sizeof(netmask));
+
+ route_attribute = RTM_RTA(route_entry);
+ int route_attribute_len = RTM_PAYLOAD(msg_hdr_ptr);
+ while (RTA_OK(route_attribute, route_attribute_len)) {
+ switch (route_attribute->rta_type) {
+ case RTA_DST:
+ inet_ntop(AF_INET, RTA_DATA(route_attribute), destip, 24);
+ break;
+
+ case RTA_GATEWAY:
+ inet_ntop(AF_INET, RTA_DATA(route_attribute), gateip, 24);
+ strcat(flags, "G");
+ break;
+
+ case RTA_PRIORITY:
+ priority = *(uint32_t *) RTA_DATA(route_attribute);
+ break;
+
+ case RTA_OIF:
+ if_indextoname(*((int *) RTA_DATA(route_attribute)), if_name);
+ break;
+
+ case RTA_METRICS:
+ //todo: Implement mss, win, irtt
+ break;
+ }
+
+ route_attribute = RTA_NEXT(route_attribute, route_attribute_len);
+ }
+
+ // Set/Update flags, rtnetlink.h note RTPROT_REDIRECT is not used
+ if (route_entry->rtm_type == RTN_UNREACHABLE) flags[0] = '!';
+ if (route_netmask == 32) strcat(flags, "H");
+ if (route_protocol == RTPROT_REDIRECT) strcat(flags, "D");
+
+ // Ref is not used by the kernel so hard coding to 0
+ // IPv4 caching is disabled so hard coding Use to 0
+ xprintf("%-15.15s %-15.15s %-16s%-6s", destip, gateip, netmask, flags);
+ if (toys.optflags & FLAG_e) {
+ xprintf("%5d %-5d %6d %s\n", 0, 0, 0, if_name);
+ } else xprintf("%-6d %-2d %7d %s\n", priority, 0, 0, if_name);
+ }
+ msg_hdr_ptr = NLMSG_NEXT(msg_hdr_ptr, msg_hdr_len);
+ }
- //Get flag Values
- get_flag_value(flag_val, flags);
- if (flags & RTF_REJECT) flag_val[0] = '!';
- xprintf("%-15.15s %-15.15s %-16s%-6s", destip, gateip, maskip, flag_val);
- if (toys.optflags & FLAG_e) xprintf("%5d %-5d %6d %s\n", mss, win, irtt, iface);
- else xprintf("%-6d %-2d %7d %s\n", metric, ref, use, iface);
+ msg_hdr_len = xrecv(fd, buf, sizeof(buf));
+ msg_hdr_ptr = (struct nlmsghdr *) buf;
}
- if (items > 0 && feof(fp)) perror_exit("fscanf %d", items);
- fclose(fp);
+ xclose(fd);
}
/*
--
2.25.1
More information about the Toybox
mailing list