Skip to content

Commit

Permalink
Add support for ipv6 addresses to net_adapter.
Browse files Browse the repository at this point in the history
  • Loading branch information
nmoinvaz committed Dec 12, 2023
1 parent 8d75d9c commit cc5b084
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 94 deletions.
17 changes: 16 additions & 1 deletion net_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@
#include <stdbool.h>
#include <stdio.h>

#ifdef _WIN32
# include <ws2tcpip.h>
#else
# include <arpa/inet.h>
#endif

#include "net_adapter.h"

static inline void print_ip(const char *name, uint8_t ip[4]) {
printf(" %s: %d.%d.%d.%d\n", name, ip[0], ip[1], ip[2], ip[3]);
char ip_str[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, ip, ip_str, sizeof(ip_str));
printf(" %s: %s\n", name, ip_str);
}

static inline void print_ipv6(const char *name, uint8_t ipv6[16]) {
char ipv6_str[INET6_ADDRSTRLEN] = {0};
inet_ntop(AF_INET6, ipv6, ipv6_str, sizeof(ipv6_str));
printf(" %s: %s\n", name, ipv6_str);
}

void net_adapter_print(net_adapter_s *adapter) {
Expand All @@ -18,6 +32,7 @@ void net_adapter_print(net_adapter_s *adapter) {
printf("\n");
}
print_ip("ip", adapter->ip);
print_ipv6("ipv6", adapter->ipv6);
print_ip("netmask", adapter->netmask);
print_ip("gateway", adapter->gateway);
print_ip("primary dns", adapter->primary_dns);
Expand Down
1 change: 1 addition & 0 deletions net_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ typedef struct net_adapter_s {
char guid[256];
char description[256];
uint8_t ip[4];
uint8_t ipv6[16];
uint8_t netmask[4];
uint8_t gateway[4];
uint8_t primary_dns[4];
Expand Down
174 changes: 89 additions & 85 deletions net_adapter_linux.c
Original file line number Diff line number Diff line change
@@ -1,85 +1,89 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <net/if.h>
#ifdef HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#else
# define ARPHRD_ETHER 1 // Ethernet hardware format
# define ARPHRD_IEEE802 6 // IEEE 802.2 Ethernet/TR/TB
#endif
#include <sys/ioctl.h>

#include "log.h"
#include "net_adapter.h"
#include "util.h"
#include "util_win.h"

bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
net_adapter_s adapter;
struct ifaddrs *ifp = NULL;
struct ifaddrs *ifa = NULL;

if (getifaddrs(&ifp) == -1)
return false;

for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
// Ignore non-IPv4 adapters
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
continue;
// Ignore non-physical adapters
if (ifa->ifa_flags & IFF_LOOPBACK)
continue;
if ((ifa->ifa_flags & ARPHRD_ETHER) == 0 && (ifa->ifa_flags & ARPHRD_IEEE802) == 0)
continue;

memset(&adapter, 0, sizeof(adapter));

int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (fd) {
struct ifreq ifr = {0};

ifr.ifr_ifindex = if_nametoindex(ifa->ifa_name);

// Copy adapter name
if (ioctl(fd, SIOCGIFNAME, &ifr) == 0)
strncat(adapter.name, ifr.ifr_name, sizeof(adapter.name) - 1);

// Check if the connection is online
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
if (ifr.ifr_flags & IFF_UP)
adapter.is_connected = true;
}

// Copy hardware address
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
adapter.mac_length = IFHWADDRLEN;
if (adapter.mac_length > sizeof(adapter.mac))
adapter.mac_length = sizeof(adapter.mac);
memcpy(adapter.mac, ifr.ifr_hwaddr.sa_data, adapter.mac_length);
}

close(fd);
} else {
strncat(adapter.name, ifa->ifa_name, sizeof(adapter.name) - 1);
}

memcpy(adapter.ip, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, sizeof(adapter.ip));
memcpy(adapter.gateway, &((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr, sizeof(adapter.gateway));
memcpy(adapter.netmask, &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr, sizeof(adapter.netmask));

if (!callback(user_data, &adapter))
break;
}

freeifaddrs(ifp);
return true;
}
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <net/if.h>
#ifdef HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#else
# define ARPHRD_ETHER 1 // Ethernet hardware format
# define ARPHRD_IEEE802 6 // IEEE 802.2 Ethernet/TR/TB
#endif
#include <sys/ioctl.h>

#include "log.h"
#include "net_adapter.h"
#include "util.h"
#include "util_win.h"

bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
net_adapter_s adapter;
struct ifaddrs *ifp = NULL;
struct ifaddrs *ifa = NULL;

if (getifaddrs(&ifp) == -1)
return false;

for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
continue;
// Ignore non-physical adapters
if (ifa->ifa_flags & IFF_LOOPBACK)
continue;
if ((ifa->ifa_flags & ARPHRD_ETHER) == 0 && (ifa->ifa_flags & ARPHRD_IEEE802) == 0)
continue;

memset(&adapter, 0, sizeof(adapter));

int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (fd) {
struct ifreq ifr = {0};

ifr.ifr_ifindex = if_nametoindex(ifa->ifa_name);

// Copy adapter name
if (ioctl(fd, SIOCGIFNAME, &ifr) == 0)
strncat(adapter.name, ifr.ifr_name, sizeof(adapter.name) - 1);

// Check if the connection is online
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
if (ifr.ifr_flags & IFF_UP)
adapter.is_connected = true;
}

// Copy hardware address
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
adapter.mac_length = IFHWADDRLEN;
if (adapter.mac_length > sizeof(adapter.mac))
adapter.mac_length = sizeof(adapter.mac);
memcpy(adapter.mac, ifr.ifr_hwaddr.sa_data, adapter.mac_length);
}

close(fd);
} else {
strncat(adapter.name, ifa->ifa_name, sizeof(adapter.name) - 1);
}

if (ifa->ifa_addr->sa_family == AF_INET) {
memcpy(adapter.ip, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, sizeof(adapter.ip));
} else if (ifa->ifa_addr->sa_family == AF_INET6) {
memcpy(adapter.ipv6, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, sizeof(adapter.ipv6));
}

memcpy(adapter.gateway, &((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr, sizeof(adapter.gateway));
memcpy(adapter.netmask, &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr, sizeof(adapter.netmask));

if (!callback(user_data, &adapter))
break;
}

freeifaddrs(ifp);
return true;
}
12 changes: 8 additions & 4 deletions net_adapter_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
return false;

for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
// Ignore non-IPv4 adapters
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
if (!ifa->ifa_addr)
continue;

memset(&adapter, 0, sizeof(adapter));
Expand Down Expand Up @@ -72,10 +71,15 @@ bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
adapter.is_connected = true;

strncat(adapter.name, ifa->ifa_name, sizeof(adapter.name) - 1);

adapter.mac_length = 6;
memcpy(adapter.mac, LLADDR((struct sockaddr_dl *)(ifm + 1)), adapter.mac_length);
memcpy(adapter.ip, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, sizeof(adapter.ip));

if (ifa->ifa_addr->sa_family == AF_INET) {
memcpy(adapter.ip, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, sizeof(adapter.ip));
} else if (ifa->ifa_addr->sa_family == AF_INET6) {
memcpy(adapter.ipv6, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, sizeof(adapter.ipv6));
}

memcpy(adapter.gateway, &((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr, sizeof(adapter.gateway));
memcpy(adapter.netmask, &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr, sizeof(adapter.netmask));

Expand Down
14 changes: 10 additions & 4 deletions net_adapter_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <inttypes.h>

#include <winsock2.h>
#include <ws2ipdef.h>
#include <windows.h>
#include <iptypes.h>
#include <iphlpapi.h>
Expand All @@ -29,7 +30,7 @@ bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
if (!callback)
return false;

error = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS, 0, NULL, &buffer_size);
error = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS, 0, NULL, &buffer_size);
if (error != ERROR_SUCCESS && error != ERROR_BUFFER_OVERFLOW) {
LOG_ERROR("Unable to allocate memory for %s (%lu)\n", "adapter info", error);
return false;
Expand All @@ -39,7 +40,7 @@ bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
buffer = calloc(buffer_size, sizeof(uint8_t));
required_size = buffer_size;

error = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS, 0,
error = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS, 0,
(IP_ADAPTER_ADDRESSES *)buffer, &required_size);
if (error != ERROR_SUCCESS) {
LOG_ERROR("Unable to get adapter info (%lu / %lu:%lu)\n", error, buffer_size, required_size);
Expand Down Expand Up @@ -91,8 +92,13 @@ bool net_adapter_enum(void *user_data, net_adapter_cb callback) {
// Populate adapter ip address
unicast_address = adapter_addresses->FirstUnicastAddress;
while (unicast_address) {
memcpy(adapter.ip, &unicast_address->Address.lpSockaddr->sa_data[2], sizeof(adapter.ip));
break;
if (unicast_address->Address.lpSockaddr->sa_family == AF_INET) {
memcpy(adapter.ip, &unicast_address->Address.lpSockaddr->sa_data[2], sizeof(adapter.ip));
} else if (unicast_address->Address.lpSockaddr->sa_family == AF_INET6) {
struct sockaddr_in6 *sockaddr_ipv6 = (struct sockaddr_in6 *)unicast_address->Address.lpSockaddr;
memcpy(adapter.ipv6, &sockaddr_ipv6->sin6_addr, sizeof(adapter.ipv6));
}
unicast_address = unicast_address->Next;
}

// Populate adapter netmask
Expand Down

0 comments on commit cc5b084

Please sign in to comment.