Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve macOS get default gateway IP #1355

Open
tigercosmos opened this issue Apr 5, 2024 · 13 comments
Open

improve macOS get default gateway IP #1355

tigercosmos opened this issue Apr 5, 2024 · 13 comments

Comments

@tigercosmos
Copy link
Collaborator

currently, we use a shell command to get the gateway in macOS:

#elif defined(__APPLE__) || defined(__FreeBSD__)
std::string command = "netstat -nr | grep default | grep " + m_Name;
std::string ifaceInfo = executeShellCommand(command);
if (ifaceInfo == "")
{
PCPP_LOG_DEBUG("Error retrieving default gateway address: couldn't get netstat output");
return;
}
// remove the word "default"
ifaceInfo.erase(0, 7);
// remove spaces
while (ifaceInfo.at(0) == ' ')
ifaceInfo.erase(0,1);
// erase string after gateway IP address
ifaceInfo.resize(ifaceInfo.find(' ', 0));
m_DefaultGateway = IPv4Address(ifaceInfo);

We don't need to use shell script here, we can use normal C API instead.

@ADTmux
Copy link

ADTmux commented Apr 5, 2024

Hey, I would really like to work on this!

@tigercosmos
Copy link
Collaborator Author

@ADTmux sure, let me know if you encounter any issue.

@ADTmux
Copy link

ADTmux commented Apr 8, 2024

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.

@tigercosmos
Copy link
Collaborator Author

@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?

@ADTmux
Copy link

ADTmux commented Apr 8, 2024

@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)

@tigercosmos
Copy link
Collaborator Author

@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.

@tigercosmos
Copy link
Collaborator Author

tigercosmos commented Apr 8, 2024

@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.

@ADTmux
Copy link

ADTmux commented Apr 8, 2024

Yes I did get the requirement. Basically if I can obtain the Default Gateway as a string I can pass it to IPv4Address()

@tigercosmos
Copy link
Collaborator Author

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

@tigercosmos
Copy link
Collaborator Author

regarding your code, obviously using getnameinfo() is not enough, you may need to play around with C structs and C APIs more.

@tigercosmos
Copy link
Collaborator Author

@ADTmux please let me know if you encounter any issue

@zhengfeihe
Copy link

zhengfeihe commented Apr 24, 2024

Hi I'd like to work on this issue. Can you re reassign this issue to me @tigercosmos ?

@tigercosmos
Copy link
Collaborator Author

@zhengfeihe sure, please go ahead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants