Closed tigercosmos closed 2 weeks ago
Hey, I would really like to work on this!
@ADTmux sure, let me know if you encounter any issue.
Hey @tigercosmos, I did experiment with the C API - https://man7.org/linux/man-pages/man3/getifaddrs.3.html , but I found that it does not directly contain the gateway for macOS that I can fetch. Are we thinking about any particular API here? Other methods could include using the routing table or ioctl() system call.
@ADTmux That would be interesting. I tested with getifaddrs
on macOS 14 (arm) and it works fine to me. What is your platform? Could you also post the testing code (a runnable minimum code in a single cpp file) here?
@tigercosmos I used this code snippet (https://file.io/sCmaptmi8x5A) in PcapPlusPlus/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp for testing the C library, and tried to print as much info as I can get, and I can see all network interfaces' details except the Default Gateway The platform I used is macOS 13.4 (Intel)
@ADTmux next time you can just copied the code here if it is not large (more than 200 lines).
The file you provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netdb.h>
int main() {
struct ifaddrs *ifaddr, *ifa;
int family, s;
char host[NI_MAXHOST];
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
printf("Interface: %s\n", ifa->ifa_name);
printf(" Family: ");
switch (family) {
case AF_INET:
printf("AF_INET (IPv4)\n");
break;
case AF_INET6:
printf("AF_INET6 (IPv6)\n");
break;
default:
printf("Unknown\n");
continue;
}
s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf(" Address: %s\n", host);
if (family == AF_INET) {
struct sockaddr_in *netmask = (struct sockaddr_in *)ifa->ifa_netmask;
if (netmask != NULL) {
s = getnameinfo((struct sockaddr *)netmask, sizeof(struct sockaddr_in),
host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
if (s != 0) {
printf("getnameinfo() failed: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
printf(" Netmask: %s\n", host);
}
}
printf(" Flags: %x\n", ifa->ifa_flags);
}
freeifaddrs(ifaddr);
return 0;
}
I will try to run it later.
@ADTmux Just in case if you don't fully understand the requirement. In the code snip at the beginning of the issue, there is a line:
std::string command = "netstat -nr | grep default | grep " + m_Name;
we parse the result (ifaceInfo
) and use the IP to feed to IPv4Address
:
m_DefaultGateway = IPv4Address(ifaceInfo);
your mission is to find out the correct ifaceInfo
(of course you will need to change the name) by the C API.
Hint: the default route has the destination as 0.0.0.0.
Yes I did get the requirement. Basically if I can obtain the Default Gateway as a string I can pass it to IPv4Address()
FYI, not sure if it helps or not, but you may want to refer to the source code of route
, which provides the default route by calling route -n get default
https://opensource.apple.com/source/network_cmds/network_cmds-396.6/route.tproj/route.c.auto.html
regarding your code, obviously using getnameinfo()
is not enough, you may need to play around with C structs and C APIs more.
@ADTmux please let me know if you encounter any issue
Hi I'd like to work on this issue. Can you re reassign this issue to me @tigercosmos ?
@zhengfeihe sure, please go ahead.
currently, we use a shell command to get the gateway in macOS: https://github.com/seladb/PcapPlusPlus/blob/e48be80c8671ca2018db24947c7d71df9c41b1fd/Pcap%2B%2B/src/PcapLiveDevice.cpp#L1013-L1032
We don't need to use shell script here, we can use normal C API instead.