From 778951d6a44fcebfce7b230857758bce854d8ccb Mon Sep 17 00:00:00 2001 From: "Pablo S. Torralba" Date: Thu, 30 Oct 2014 03:11:27 -0700 Subject: [PATCH] Remove osx dependency on system() call to get arp information --- osquery/tables/networking/darwin/arp.cpp | 120 ++++++++++++++++---- osquery/tables/specs/darwin/arp.table | 6 + osquery/tables/specs/{x => linux}/arp.table | 0 3 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 osquery/tables/specs/darwin/arp.table rename osquery/tables/specs/{x => linux}/arp.table (100%) diff --git a/osquery/tables/networking/darwin/arp.cpp b/osquery/tables/networking/darwin/arp.cpp index bfde6a2f..17a88a25 100644 --- a/osquery/tables/networking/darwin/arp.cpp +++ b/osquery/tables/networking/darwin/arp.cpp @@ -1,43 +1,117 @@ // Copyright 2004-present Facebook. All Rights Reserved. +#include + +#include +#include +#include +#include + +#include +#include + +#include + #include #include #include "osquery/database.h" +typedef struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} route_msg; + namespace osquery { namespace tables { -QueryData genArp() { - Row r; - QueryData results; - FILE *arp_cmd_output; - char *line = NULL; - size_t length; - int ret; +// Transform the ethernet address in a string +char * ether_print(u_char *cp) +{ + char buf[128]; + char *copy; - char ip[32]; - char mac[64]; - char iface[32]; + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); - // We are already calling 'popen', let's give it some more work with sed to clean. - arp_cmd_output = popen("arp -an | sed 's,^[^(]*(\\([^)]*\\)) at \\([^ ]*\\).*on \\([^ ]*\\).*$,\\1 \\2 \\3,'", "r"); - if (arp_cmd_output == NULL) { - return results; + copy = (char *) malloc(sizeof(char) * (strlen(buf) + 1)); + + if (copy != NULL) { + strcpy(copy, buf); + + return copy; + + } else { + return NULL; } - ret = getline(&line, &length, arp_cmd_output); - while (ret > 0) { - sscanf(line, "%s %s %s", ip, mac, iface); +} - r["ip"] = ip; - r["mac"] = mac; - r["iface"] = iface; +void add_address(struct rt_msghdr *rtm, QueryData *results) +{ + Row r; + char *ip_addr; + std::string mac_addr; + struct hostent *hp; + struct sockaddr_inarp *sin; + struct sockaddr_dl *sdl; - results.push_back(r); + sin = (struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)(sin + 1); - line = NULL; - ret = getline(&line, &length, arp_cmd_output); + ip_addr = inet_ntoa(sin->sin_addr); + + if (sdl->sdl_alen != 0) { + mac_addr = ether_print((u_char *)LLADDR(sdl)); + } else { + mac_addr = "incomplete"; + } + if (rtm->rtm_rmx.rmx_expire == 0) { + mac_addr = "permanent"; + } + if (rtm->rtm_addrs & RTA_NETMASK) { + sin = (struct sockaddr_inarp *) (sdl->sdl_len + (char *)sdl); + + if (sin->sin_addr.s_addr == 0xffffffff) + mac_addr = "published"; + + if (sin->sin_len != 8) + mac_addr = "weird"; + } + + r["ip"] = ip_addr; + r["mac"] = mac_addr; + + results->push_back(r); +} + +QueryData genArp() { + QueryData results; + + int mib[6]; + size_t needed; + char *lim, *buf, *next; + struct rt_msghdr *rtm; + int found_entry = 0; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_FLAGS; + mib[5] = RTF_LLINFO; + + sysctl(mib, 6, NULL, &needed, NULL, 0) ; + buf = (char *) malloc(needed); + + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + } + + lim = buf + needed; + for (next = buf; next < lim; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)(void *)next; + add_address(rtm, &results); } return results; diff --git a/osquery/tables/specs/darwin/arp.table b/osquery/tables/specs/darwin/arp.table new file mode 100644 index 00000000..2c217a04 --- /dev/null +++ b/osquery/tables/specs/darwin/arp.table @@ -0,0 +1,6 @@ +table_name("arp") +schema([ + Column(name="ip", type="std::string"), + Column(name="mac", type="std::string"), +]) +implementation("arp@genArp") diff --git a/osquery/tables/specs/x/arp.table b/osquery/tables/specs/linux/arp.table similarity index 100% rename from osquery/tables/specs/x/arp.table rename to osquery/tables/specs/linux/arp.table