LocalIP (macOS): detect default route

This commit is contained in:
李通洲
2023-07-17 15:02:32 +08:00
committed by 李通洲
parent 44faa3aa84
commit 68f71c5421
+95 -1
View File
@@ -11,11 +11,14 @@
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <net/if_dl.h>
#include <net/route.h>
#include <sys/socket.h>
#else
#include <netpacket/packet.h>
#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 <<i ) == desired)
return sa;
sa = (struct sockaddr *)(ROUNDUP(sa->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)
{