Linux Network Programming

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. */

Leave a Reply

Your email address will not be published. Required fields are marked *