Manual Pages
getifaddrs, freeifaddrs – get interface addresses
packet – packet interface on device level
NETLINK
Generic NETLINK HowTo
Netlink Sockets in C using the 3.X linux kernel
Tutorials & Blogs
Code Snippet: getifaddrs
Get the IP address of the machine
How to get MAC address of your machine using a C program?
How to get local IP and MAC address C [duplicate]
MAC address with getifaddrs (wrong answer!!)
Code Stippet
lldpd/src/daemon/interfaces-linux.c
Get network interface’s MAC address and IP address
#include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/param.h> #include <netinet/in.h> #include <net/ethernet.h> #include <net/if.h> #include <linux/if_link.h> #include <linux/if_vlan.h> #include <linux/sockios.h> #include <ifaddrs.h> bool netif_init(netif_t *netif, const char *name) { bool result = true; int sockfd; struct ifaddrs *ifas; struct ifaddrs *ifa; struct ifreq ifr; struct rtnl_link_stats *stats; struct vlan_ioctl_args ifv; /* string copy name */ strncpy(netif->name, name, NETIF_NAME_SIZE); /* create socket (required for ioctl) */ if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { LOG_ERRNO(LOG_NETWORK_INTERFACE, LOG_ERROR, errno, ("socket failed")); return false; } /* get interface addresses */ if (getifaddrs(&ifas) != 0) { return false; } for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) { if ((ifa->ifa_addr) == NULL) continue; if ((ifa->ifa_flags & IFF_UP) == 0) continue; /* network interface name matches */ if (strcmp(name, ifa->ifa_name) == 0) { switch (ifa->ifa_addr->sa_family) { case AF_INET: netif_add_ipv4_address(netif, IPV4_ADDRESS(&(INADDR(ifa->ifa_addr)->sin_addr)), IPV4_ADDRESS(&(INADDR(ifa->ifa_netmask)->sin_addr)), IPV4_ADDRESS(&(INADDR(ifa->ifa_broadaddr)->sin_addr)), NULL); break; case AF_INET6: netif_add_ipv6_address(netif, IPV6_ADDRESS(&(INADDR6(ifa->ifa_addr)->sin6_addr)), IPV6_ADDRESS(&(INADDR6(ifa->ifa_netmask)->sin6_addr)), IPV6_STATE_VALID); break; case AF_PACKET: stats = ifa->ifa_data; LOG_PRINTLN(LOG_NETWORK_INTERFACE, LOG_DEBUG, ("tx packet: %" PRIu32 " rx packet: %" PRIu32 " tx bytes: %" PRIu32 " rx bytes: %" PRIu32, stats->tx_packets, stats->rx_packets, stats->tx_bytes, stats->rx_bytes)); bzero((char *) &ifr, sizeof(ifr)); strncpy(ifr.ifr_name, netif->name, NETIF_NAME_SIZE); if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) != -1) { netif_add_mac_address(netif, MAC_ADDRESS(LLADDR(LADDR(ifr.ifr_hwaddr.sa_data)))); bzero((char *) &ifv, sizeof(ifv)); ifv.cmd = GET_VLAN_VID_CMD; strncpy(ifv.device1, netif->name, sizeof(ifv.device1)); if (ioctl(sockfd, SIOCGIFVLAN, &ifv) != -1) { netif_add_vid(netif, ifv.u.VID); } } else { LOG_PRINTLN(LOG_NETWORK_INTERFACE, LOG_ERROR, ("couldn't get MAC address")); result = false; goto netif_init_exit; } break; default: continue; } } } netif_init_exit: freeifaddrs(ifas); return result; }
$ grep -r vlan_ioctl /usr/include /usr/include/linux/if_vlan.h:/* Passed in vlan_ioctl_args structure to determine behaviour. */ /usr/include/linux/if_vlan.h:enum vlan_ioctl_cmds { /usr/include/linux/if_vlan.h:struct vlan_ioctl_args { /usr/include/linux/if_vlan.h: int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */