From 68f71c542120fcfa0ddefd52828208fd74d0c683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 17 Jul 2023 15:02:32 +0800 Subject: [PATCH] LocalIP (macOS): detect default route --- src/detection/localip/localip_linux.c | 96 ++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 17fa2651b..ce2bd1e59 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -11,11 +11,14 @@ #if defined(__FreeBSD__) || defined(__APPLE__) #include +#include +#include #else #include #endif -static bool getDefaultRoute(char iface[16 /*IF_NAMESIZE*/ + 1]) +#ifdef __linux__ +static bool getDefaultRoute(char iface[IF_NAMESIZE + 1]) { FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); // skip first line @@ -24,6 +27,7 @@ static bool getDefaultRoute(char iface[16 /*IF_NAMESIZE*/ + 1]) funlockfile(netRoute); unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, + static_assert(IF_NAMESIZE >= 16, "IF_NAMESIZE is too small"); while (fscanf(netRoute, "%16s%llx%*[^\n]", iface, &destination) == 2) { if (destination == 0) @@ -31,6 +35,96 @@ static bool getDefaultRoute(char iface[16 /*IF_NAMESIZE*/ + 1]) } return false; } +#elif defined(__FreeBSD__) || defined(__APPLE__) + +#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) + +#if defined(__APPLE__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__NetBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) +#elif defined(__FreeBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__OpenBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#else +# error unknown platform +#endif + +static struct sockaddr * +get_rt_address(struct rt_msghdr *rtm, int desired) +{ + struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + + for (int i = 0; i < RTAX_MAX; i++) + { + if (rtm->rtm_addrs & (1 << i)) + { + if ((1 <sa_len) + (char *)sa); + } + } + return NULL; +} + +static bool getDefaultRoute(char iface[IF_NAMESIZE + 1]) +{ + //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 + + FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); + if (pfRoute < 0) + return false; + + { + struct timeval timeout = {1, 0}; + setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); + setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); + } + + int pid = getpid(); + + struct { + struct rt_msghdr hdr; + struct sockaddr_in dst; + uint8_t data[512]; + } rtmsg = { + .hdr = { + .rtm_type = RTM_GET, + .rtm_flags = RTF_UP | RTF_GATEWAY, + .rtm_version = RTM_VERSION, + .rtm_addrs = RTA_DST | RTA_IFP, + .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), + .rtm_pid = pid, + .rtm_seq = 1, + }, + .dst = { + .sin_family = AF_INET, + .sin_len = sizeof(rtmsg.dst), + }, + }; + + if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen) + return false; + + while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0) + { + if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid) + { + struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); + if (sdl) + { + assert(sdl->sdl_nlen <= IF_NAMESIZE); + memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); + iface[sdl->sdl_nlen] = 0; + return true; + } + return false; + } + } + return false; +} +#endif static void addNewIp(FFlist* list, const char* name, const char* addr, int type) {