This is cache of http://othermark.livejournal.com/3005.html. Cache is the snapshot of article that we took when we index feed.
To see original page click here.
We are not affiliated with the authors of this article and not responsible for its content.
amazingly difficult to find 'getting a MAC address from a interface?' answer.
2006-08-15 21:46:46 by Editor in othermark
 
I was trying to convert a piece of network software to FreeBSD. Unfortunately, even though the author quotes "should compile on any POSIX like OS," it doesn't (POSIX != LINUX). It should be obvious, when they drop things like:
  if (ioctl (sock, SIOCGIFADDR, &ifr) < 0)
throughout the code. So the above is from a section of code trying to obtain the MAC address on a interface. Doing this task on FreeBSD can be done through ioctl(), but is discouraged by the developers. They encourage you to use getifaddrs(). This strange and wonderful function grabs all sorts of information from the interface list, however, a couple of things are not obvious about it's use. If you really want to play arround with IF_LINK type addresses on the interfaces returned you need to be using sockaddr_dl not just sockaddr. Overloading sockaddr with magic casting is the new pink these days and thats what's required. It confused me at first since the manpage has:
         struct ifaddrs   *ifa_next;         /* Pointer to next struct */
         char             *ifa_name;         /* Interface name */
         u_int             ifa_flags;        /* Interface flags */
         struct sockaddr  *ifa_addr;         /* Interface address */
         struct sockaddr  *ifa_netmask;      /* Interface netmask */
         struct sockaddr  *ifa_broadaddr;    /* Interface broadcast address */
         struct sockaddr  *ifa_dstaddr;      /* P2P interface destination */
         void             *ifa_data;         /* Address specific data */
for the structure.. same with /usr/include/ifaddrs.h. It turns out copying sa_data of sa_len from your friendly struct sockaddr does not give your the ethernet address from ifa_addr. :( :( :( :(. Too make a long story short:
/* getmac.c -- retrieve the mac address from a interface name */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <ifaddrs.h>

int main(int argc, char ** argv)
{
    struct ifaddrs   *ifaphead;
    unsigned char *   if_mac;
    int               found = 0;
    struct ifaddrs   *ifap;
    struct sockaddr_dl *sdl = NULL;

    if (argc < 2)
    {
        fprintf(stderr,"usage:
");
        fprintf(stderr,"	 %s <interface name>
",argv[0]);
        exit(1);
    }

    if (getifaddrs(&ifaphead) != 0)
    {
        perror("get_if_name: getifaddrs() failed");
        exit(1);
    }

    for (ifap = ifaphead; ifap && !found; ifap = ifap->ifa_next)
    {
        if ((ifap->ifa_addr->sa_family == AF_LINK))
        {
            if (strlen(ifap->ifa_name) == strlen(argv[1]))
                if (strcmp(ifap->ifa_name,argv[1]) == 0)
                {
                    found = 1;
                    sdl = (struct sockaddr_dl *)ifap->ifa_addr;
                    if (sdl)
                    {
                        /* I was returning this from a function before converting
                         * this snippet, which is why I make a copy here on the heap */
                        if_mac = malloc(sdl->sdl_alen);
                        memcpy(if_mac, LLADDR(sdl), sdl->sdl_alen);
                    }
                }
        }
    }
    if (!found)
    {
        fprintf (stderr,"Can't find interface %s.
",argv[1]);
        if(ifaphead)
            freeifaddrs(ifaphead);
        exit(1);
    }

    fprintf (stdout, "%02X%02X%02X%02X%02X%02X
",
        if_mac[0] , if_mac[1] , if_mac[2] ,
        if_mac[3] , if_mac[4] , if_mac[5] );

    if(ifaphead)
        freeifaddrs(ifaphead);
        
    exit(0);
}
 
 
 
 
 
 


SPONSORED LINKS


BROWSE CATEGORIES Expand / MinimizeClose Widget