Saturday, August 31, 2013

Obtain MAC Address of Ethernet NIC in Linux

Linux manual page netdevice(7) has good description on ioctl's that one may use to control or query Ethernet NIC.

The following sample program returns the Ethernet adapter's MAC address from its interface name.

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>         /* declares IFNAMSIZ */
#include <net/if_arp.h>     /* declares types of link, such as, APRHRD_ETHER */
#include <net/ethernet.h>   /* declares ETH_ALEN */
#include <netinet/ip.h>     /* declares IPPROTO_IP */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    int sockfd, i, addrlen;
    struct ifreq ifr;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s IFNAME\n", argv[0]);
        exit(1);
    }

    /* many network sockets would do, here are 3 examples. */
    /* sockfd = socket(AF_PACKET, SOCK_RAW, 0); */
    /* sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); */
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sockfd == -1) {
        fprintf(stderr, "Error: calling socket(AF_PACKET, SOCK_DGRAM, 0): %s\n",
            strerror(errno));
        exit(1);
    }

    ifr.ifr_name[IFNAMSIZ-1] = '\0';
    strncpy(ifr.ifr_name, argv[1], IFNAMSIZ-1);

    if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1) {
        fprintf(stderr, "Error: calling ioctl(sockfd, SIOCGIFHWADDR, ...): %s\n",
            strerror(errno));
        exit(1);
    }

    switch(ifr.ifr_hwaddr.sa_family) {
        case ARPHRD_ETHER:
            addrlen = ETH_ALEN;
            break;
        default:
            fprintf(stderr, "Warn: not Ethernet, give up ...\n");
            exit(1);
    }

    for (i=0; i<addrlen-1; i++)
        printf("%02x:", (unsigned char)ifr.ifr_hwaddr.sa_data[i]);
    printf("%02x\n", (unsigned char)ifr.ifr_hwaddr.sa_data[addrlen-1]);

    close(sockfd);
    return 0;
}

No comments:

Post a Comment