Commit ed38f1ff authored by Robert David Graham's avatar Robert David Graham
Browse files

Mac OS X fixes

parent 7c40c99c
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@
#include <io.h>
#include <fcntl.h>
#define access _access
#elif defined(__linux__)
#else
#include <unistd.h>
#endif

+129 −2
Original line number Diff line number Diff line
@@ -9,11 +9,138 @@

#include "ranges.h" /*for parsing IPv4 addresses */

#if defined(__APPLE__)
int rawsock_get_default_interface(char *ifname, size_t sizeof_ifname)
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <unistd.h>
#include <sys/socket.h>
#include <net/route.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#include <ctype.h>

#define ROUNDUP(a)							\
((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))

static struct sockaddr *
get_rt_address(struct rt_msghdr *rtm, int desired)
{
    int i;
    int bitmask = rtm->rtm_addrs;
    struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
    
    for (i = 0; i < RTAX_MAX; i++) {
        if (bitmask & (1 << i)) {
            if ((1<<i) == desired)
                return sa;
            sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
        } else
            ;
    }
    return NULL;
    
}

int
rawsock_get_default_interface(char *ifname, size_t sizeof_ifname)
{
    int fd;
    int seq = time(0);
    int err;
    struct rt_msghdr *rtm;
    size_t sizeof_buffer;
    
    
    /*
     * Requests/responses from the kernel are done with an "rt_msghdr"
     * structure followed by an array of "sockaddr" structures.
     */
    sizeof_buffer = sizeof(*rtm) + sizeof(struct sockaddr_in)*16;
    rtm = (struct rt_msghdr *)malloc(sizeof_buffer);
    
    
    /*
     * Create a socket for querying the kernel
     */
    fd = socket(PF_ROUTE, SOCK_RAW, 0);
    if (fd <= 0) {
        perror("socket(PF_ROUTE)");
        free(rtm);
        return errno;
    }
    
    
    /*
     * Format and send request to kernel
     */
    memset(rtm, 0, sizeof_buffer);
    rtm->rtm_msglen = sizeof_buffer;
    rtm->rtm_type = RTM_GET;
    rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
    rtm->rtm_version = RTM_VERSION;
    rtm->rtm_seq = seq;
    rtm->rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY | RTA_IFP;
    
    err = write(fd, (char *)rtm, sizeof_buffer);
    if (err < 0 || err != sizeof_buffer) {
        perror("write(RTM_GET)");
        printf("----%u %u\n", err, sizeof_buffer);
        close(fd);
        free(rtm);
        return -1;
    }
    
    /*
     * Read responses until we find one that belongs to us
     */
    for (;;) {
        err = read(fd, (char *)rtm, sizeof_buffer);
        if (err <= 0)
            break;
        if (rtm->rtm_seq != seq) {
            printf("seq: %u %u\n", rtm->rtm_seq, seq);
            continue;
        }
        if (rtm->rtm_pid != getpid()) {
            printf("pid: %u %u\n", rtm->rtm_pid, getpid());
            continue;
        }
        break;
    }
    close(fd);
    
    //hexdump(rtm+1, err-sizeof(*rtm));
    //dump_rt_addresses(rtm);
    
    /*
     * Parse our data
     */
    {
        //struct sockaddr_in *sin;
        struct sockaddr_dl *sdl;
        
        sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP);
        if (sdl) {
            size_t len = sdl->sdl_nlen;
            if (len > sizeof_ifname-1)
                len = sizeof_ifname-1;
            memcpy(ifname, sdl->sdl_data, len);
            ifname[len] = 0;
            return 0;
        }

        /*sin = (struct sockaddr_in *)get_rt_address(rtm, RTA_GATEWAY);
        if (sin) {
            *ipv4 = ntohl(sin->sin_addr.s_addr);
            free(rtm);
            return 0;
        }*/
        
    }
    
    free(rtm);
    return -1;
}


#elif defined(__linux__)
#include <netinet/in.h>
#include <net/if.h>
+72 −14
Original line number Diff line number Diff line
@@ -2,19 +2,22 @@
    retrieve IPv4 address of the named network interface/adapter
    like "eth0"

    This works on both Linux and Windows.
 
    This works on:
        - Windows
        - Linux
        - Apple
        - FreeBSD
 
 I think it'll work the same on any BSD system.
*/
#include "rawsock.h"
#include "string_s.h"
#include "ranges.h" /*for parsing IPv4 addresses */

#if defined(__APPLE__)
unsigned
rawsock_get_adapter_ip(const char *ifname)
{
    return 0;
}
#elif defined(__linux__)
/*****************************************************************************
 *****************************************************************************/
#if defined(__linux__)
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -49,17 +52,16 @@ rawsock_get_adapter_ip(const char *ifname)
    sin = (struct sockaddr_in *)sa;
    return ntohl(sin->sin_addr.s_addr);
}
#endif

#if defined(WIN32)
/*****************************************************************************
 *****************************************************************************/
#elif defined(WIN32)
#include <winsock2.h>
#include <iphlpapi.h>
#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif



unsigned
rawsock_get_adapter_ip(const char *ifname)
{
@@ -75,7 +77,7 @@ rawsock_get_adapter_ip(const char *ifname)
     */
    pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof (IP_ADAPTER_INFO));
    if (pAdapterInfo == NULL) {
        fprintf(stderr, "Error allocating memory needed to call GetAdaptersinfo\n");
        fprintf(stderr, "error:malloc(): for GetAdaptersinfo\n");
        return 0;
    }

@@ -89,7 +91,7 @@ again:
        free(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
        if (pAdapterInfo == NULL) {
            fprintf(stderr, "Error allocating memory needed to call GetAdaptersinfo\n");
            fprintf(stderr, "error:malloc(): for GetAdaptersinfo\n");
            return 0;
        }
        goto again;
@@ -129,5 +131,61 @@ again:

    return 0;
}
/*****************************************************************************
 *****************************************************************************/
#elif defined(__APPLE__) || defined(__FreeBSD__) || 1
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <arpa/inet.h>

#ifdef AF_LINK
#   include <net/if_dl.h>
#endif
#ifdef AF_PACKET
#   include <netpacket/packet.h>
#endif

unsigned
rawsock_get_adapter_ip(const char *ifname)
{
    int err;
    struct ifaddrs *ifap;
    struct ifaddrs *p;
    unsigned ip;
    
    
    /* Get the list of all network adapters */
    err = getifaddrs(&ifap);
    if (err != 0) {
        perror("getifaddrs");
        return 0;
    }
    
    /* Look through the list until we get our adapter */
    for (p = ifap; p; p = p->ifa_next) {
        if (strcmp(ifname, p->ifa_name) == 0
            && p->ifa_addr
            && p->ifa_addr->sa_family == AF_INET)
            break;
    }
    if (p == NULL)
        goto error; /* not found */
    
    /* Return the address */
    {
        struct sockaddr_in *sin = (struct sockaddr_in *)p->ifa_addr;
        
        ip = ntohl(sin->sin_addr.s_addr);
    }

    freeifaddrs(ifap);
    return ip;
error:
    freeifaddrs(ifap);
    return 0;
}

#endif
+80 −10
Original line number Diff line number Diff line
/*
    get MAC address of named network interface/adapter like "eth0"

    This works on both Windows and linux
    This works on:
        - Windows
        - Linux
        - Apple
        - FreeBSD
 
    I think it'll work the same on any BSD system.
*/
#include "rawsock.h"
#include "string_s.h"

#if defined(__APPLE__)
int
rawsock_get_adapter_mac(const char *ifname, unsigned char *mac)
{
    return -1;
}
#elif defined(__linux__)
/*****************************************************************************
 *****************************************************************************/
#if defined(__linux__)
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -47,9 +49,10 @@ end:
    close(fd);
    return 0;
}
#endif

#if defined(WIN32)
/*****************************************************************************
 *****************************************************************************/
#elif defined(WIN32)
#include <winsock2.h>
#include <iphlpapi.h>
#ifdef _MSC_VER
@@ -118,5 +121,72 @@ again:

    return 0;
}

/*****************************************************************************
 *****************************************************************************/
#elif defined(__APPLE__) || defined(__FreeBSD__) || 1
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <arpa/inet.h>

#ifdef AF_LINK
#   include <net/if_dl.h>
#endif
#ifdef AF_PACKET
#   include <netpacket/packet.h>
#endif

int
rawsock_get_adapter_mac(const char *ifname, unsigned char *mac)
{
    int err;
    struct ifaddrs *ifap;
    struct ifaddrs *p;
    
    
    /* Get the list of all network adapters */
    err = getifaddrs(&ifap);
    if (err != 0) {
        perror("getifaddrs");
        return 1;
    }
    
    /* Look through the list until we get our adapter */
    for (p = ifap; p; p = p->ifa_next) {
        if (strcmp(ifname, p->ifa_name) == 0
            && p->ifa_addr
            && p->ifa_addr->sa_family == AF_LINK)
            break;
    }
    if (p == NULL)
        goto error; /* not found */
    
    
    /* Return the address */
    {
        size_t len = 6;        
        struct sockaddr_dl *link;
        
        link = (struct sockaddr_dl *)p->ifa_addr;
        if (len > link->sdl_alen) {
            memset(mac, 0, 6);
            len = link->sdl_alen;
        }
        
        memcpy(     mac,
               link->sdl_data + link->sdl_nlen,
               len);
        
    }
    
    freeifaddrs(ifap);
    return 0;
error:
    freeifaddrs(ifap);
    return -1;
}

#endif
+110 −21
Original line number Diff line number Diff line
@@ -10,11 +10,87 @@
#include "ranges.h" /*for parsing IPv4 addresses */


#if defined(__APPLE__)
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <unistd.h>
#include <sys/socket.h>
#include <net/route.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#include <ctype.h>

#define ROUNDUP(a)							\
((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))

struct sockaddr *
get_rt_address(struct rt_msghdr *rtm, int desired)
{
    int i;
    int bitmask = rtm->rtm_addrs;
    struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
    
    for (i = 0; i < RTAX_MAX; i++) {
        if (bitmask & (1 << i)) {
            if ((1<<i) == desired)
                return sa;
            sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
        } else
            ;
    }
    return NULL;

}

static void
hexdump(const void *v, size_t len)
{
    const unsigned char *p = (const unsigned char *)v;
    size_t i;
    
    
    for (i=0; i<len; i += 16) {
        size_t j;
        
        for (j=i; j<i+16 && j<len; j++)
            printf("%02x ", p[j]);
        for (;j<i+16; j++)
            printf("   ");
        printf("  ");
        for (j=i; j<i+16 && j<len; j++)
            if (isprint(p[j]) && !isspace(p[j]))
                printf("%c", p[j]);
            else
                printf(".");
        printf("\n");
    }
}

#if 0
#define RTA_DST         0x1     /* destination sockaddr present */
#define RTA_GATEWAY     0x2     /* gateway sockaddr present */
#define RTA_NETMASK     0x4     /* netmask sockaddr present */
#define RTA_GENMASK     0x8     /* cloning mask sockaddr present */
#define RTA_IFP         0x10    /* interface name sockaddr present */
#define RTA_IFA         0x20    /* interface addr sockaddr present */
#define RTA_AUTHOR      0x40    /* sockaddr for author of redirect */
#define RTA_BRD         0x80    /* for NEWADDR, broadcast or p-p dest addr */
#endif

void
dump_rt_addresses(struct rt_msghdr *rtm)
{
    int i;
    int bitmask = rtm->rtm_addrs;
    struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
    
    for (i = 0; i < RTAX_MAX; i++) {
        if (bitmask & (1 << i)) {
            printf("b=%u fam=%u len=%u\n", (1<<i), sa->sa_family, sa->sa_len);
            hexdump(sa, sa->sa_len + sizeof(sa->sa_family));
            sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
        } else
            ;
    }
}

int rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
{
@@ -29,7 +105,7 @@ int rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
     * Requests/responses from the kernel are done with an "rt_msghdr"
     * structure followed by an array of "sockaddr" structures.
     */
    sizeof_buffer = sizeof(*rtm) + sizeof(struct sockaddr_in) * sizeof(int)*8;
    sizeof_buffer = sizeof(*rtm) + sizeof(struct sockaddr_in)*16;
    rtm = (struct rt_msghdr *)malloc(sizeof_buffer);


@@ -53,11 +129,12 @@ int rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
    rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
    rtm->rtm_version = RTM_VERSION;
    rtm->rtm_seq = seq;
    rtm->rtm_addrs = RTA_DST | RTA_NETMASK;
    rtm->rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY | RTA_IFP;

    err = write(fd, (char *)rtm, sizeof_buffer);
    if (err) {
    if (err < 0 || err != sizeof_buffer) {
        perror("write(RTM_GET)");
        printf("----%u %u\n", err, sizeof_buffer);
        close(fd);
        free(rtm);
        return -1;
@@ -70,34 +147,46 @@ int rawsock_get_default_gateway(const char *ifname, unsigned *ipv4)
        err = read(fd, (char *)rtm, sizeof_buffer);
        if (err <= 0)
            break;
        if (rtm->rtm_seq != seq)
        if (rtm->rtm_seq != seq) {
            printf("seq: %u %u\n", rtm->rtm_seq, seq);
            continue;
        if (rtm->rtm_pid != getpid())
        }
        if (rtm->rtm_pid != getpid()) {
            printf("pid: %u %u\n", rtm->rtm_pid, getpid());
            continue;

        }
        break;
    }
    close(fd);

    //hexdump(rtm+1, err-sizeof(*rtm));
    //dump_rt_addresses(rtm);
    
    /*
     * Parse our data
     */
    {
        int i;
        struct sockaddr *sa;

        /* Addresses start right in buffer after RTM structure */
        sa = (struct sockaddr *)(rtm + 1);
        struct sockaddr_in *sin;
        struct sockaddr_dl *sdl;
        
        sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP);
        if (sdl) {
            //hexdump(sdl, sdl->sdl_len);
            //printf("%.*s\n", sdl->sdl_nlen, sdl->sdl_data);
            if (memcmp(ifname, sdl->sdl_data, sdl->sdl_nlen) != 0) {
                fprintf(stderr, "ERROR: ROUTE DOESN'T MATCH INTERFACE\n");
                fprintf(stderr, "YOU'LL HAVE TO SET --router-mac MANUALLY\n");
                exit(1);
            }
        }
        
        for (i=1; i; i *= 2) {
            if (i == RTA_GATEWAY) {
                /* FOUND IT!! copy the address and return */
                struct sockaddr_in *sin = (struct sockaddr_in *)sa;
        sin = (struct sockaddr_in *)get_rt_address(rtm, RTA_GATEWAY);
        if (sin) {
            *ipv4 = ntohl(sin->sin_addr.s_addr);
            free(rtm);
            return 0;
        }
            sa++;
        }
        
    }

    free(rtm);
Loading