Under Construction

MAC-Adresse für ein Netzwerk-Interface abfragen (SIOCGIFHWADDR)

Für die Abfrage der unterliegenden Hardware-Adresse (meistens Ethernet MAC-Adresse) kann unter AIX der Request Code SIOCGIFHWADDR verwendet werden. Die Information wird über die Struktur ifhwaddr_req aus /usr/include/net/if.h zurückgeliefert:

#define MAX_HWADDR_LEN 64
/* ifreq structure for SIOCGIFHWADDR */
struct ifhwaddr_req {
        char    ifr_name[IFNAMSIZ];               /* if name, e.g. "en0" or "ib0" */
        char    ifr_hwaddr[MAX_HWADDR_LEN];          /* device hardware address */
        int     addr_len;
};

Die Struktur ifhwaddr_req unterstützt Adressen mit einer Länge von bis zu 64 Bytes. Im Feld addr_len wird die Länge der Hardware-Adresse zurückgeliefert, für Ethernet Adressen sind das 6 Bytes. Die Hardware-Adresse selbst wird im Array ifr_hwaddr abgelegt. Vor dem Aufruf des ioctl(2) muss der Name des Netzwerk-Interfaces in ifr_name abgelegt werden.

Das folgende Beispiel-Programm zeigt die Verwendung von SIOCGIFHWADDR mit der Struktur ifhwaddr_req:

$ cat get_mac.c
/*
* Copyright (c) 2022 by PowerCampus 01 GmbH
*/
#include <sys/ioctl.h>     // SIOCGIFADDR
#include <sys/socket.h>    // socket()
#include <net/if.h>        // ifhwaddr_req
#include <arpa/inet.h>     // ether_ntoa()
#include <errno.h>         // errno, perror()
#include <unistd.h>        // ioctl(), close()
#include <stdio.h>         // fprintf()
#include <stdlib.h>        // exit()
#include <string.h>        // strncpy()

int main( int argc , char** argv )
{
        int sd;
        int ret;
        struct ether_addr* addr;

        // 1. Provide buffer for the request.
        struct ifhwaddr_req req;

        // 2. Store interface name in ifr_name.
        strncpy(req.ifr_name,argv[1],IFNAMSIZ);

        // 3. Create datagram socket for address family Inet.
        sd = socket(AF_INET,SOCK_DGRAM,0);
        if ( sd == -1 )
        {
                perror("get_mac");
                exit(errno);
        }

        // 4. Call ioctl with command SIOCGIFHWADDR.
        ret = ioctl(sd,SIOCGIFHWADDR,&req);
        if ( ret == -1 )
        {
                perror("get_mac");
                exit(errno);
        }

        // 5. Print MAC-Address.
        addr = (struct ether_addr*)&(req.ifr_hwaddr);
        printf("MAC: %s\n",ether_ntoa(addr));

        // 6. Close socket descriptor
        close(sd);

        return 0;
}
$

Das Programm erwartet als Argument beim Aufruf den Namen eines Netzwerk-Interfaces und gibt dann für dieses Interface die MAC-Adresse aus.

Das Programm kann z.B. mit dem GNU C-Compiler übersetzt werden:

$ gcc -o get_mac get_mac.c
$

Ein kleiner Test für das Netzwerk-Interface en0 zeigt wie gewünscht die MAC-Adresse des Interfaces:

$ get_mac en0
MAC: 32:7e:ba:40:74:5
$

Allerdings unterstützt nicht jedes Netzwerk-Interface den ioctl(2) mit Request-Code SIOGIFHWADDR. Das Loopback-Interface lo0 beispielsweise, besitzt keine Hardware-Adresse und unterstützt die Abfrage entsprechend auch nicht:

$ get_mac lo0
get_mac: Invalid argument
$

Der ioctl(2) liefert in diesem Fall den Fehler EINVAL (Fehler 22: invalid argument) zurück