Remove osx dependency on system() call to get arp information

This commit is contained in:
Pablo S. Torralba 2014-10-30 03:11:27 -07:00 committed by Teddy Reed
parent c7fc2cee22
commit 778951d6a4
3 changed files with 103 additions and 23 deletions

View File

@ -1,43 +1,117 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#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;

View File

@ -0,0 +1,6 @@
table_name("arp")
schema([
Column(name="ip", type="std::string"),
Column(name="mac", type="std::string"),
])
implementation("arp@genArp")