FreeBSD中读取Ethernet Address的一种可行方法

#include <net/if.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
#include <net/ethernet.h>

int main()
{
    struct ifaddrs *list;
    if(getifaddrs(&list) < 0)
    {
        perror("getifaddrs");
        return;
    }
        
    struct ifaddrs *cur;        
    for(cur = list; cur != NULL; cur = cur->ifa_next)
    {
        if(cur->ifa_addr->sa_family != AF_LINK)
            continue;
        char *name = cur->ifa_name;
        printf(name);printf("\n");
        char *addr;
        struct sockaddr_dl *sdl;
        sdl = (struct sockaddr_dl *)cur->ifa_addr;
                addr = ether_ntoa((const struct ether_addr *)LLADDR(sdl));
        printf(addr);printf("\n");
    }
        
    freeifaddrs(list);
    return 0;
}
看了TCP/IP Illustrated Vol 2,再看看源代码,才知道当 sa_family==AF_LINK 时,ifa_addr实际上是 struct sockaddr_dl  格式, 根据书里的写法,LLADDR宏是用来从sockaddr_dl获取ether_addr的位置,而ifa_addr里面的各个数的定义也清楚了……
struct sockaddr_dl {
    u_char    sdl_len;    /* Total length of sockaddr */
    u_char    sdl_family;    /* AF_LINK */ (当前版本AF_LINK=18, socket.h)
    u_short    sdl_index;    /* if != 0, system given index for interface */(我的rl0是1)
    u_char    sdl_type;    /* interface type */ (IFT_ETHER, 0x6, if_types.h)
    u_char    sdl_nlen;    /* interface name length, no trailing 0 reqd. */ (我的为3("rl0"))
    u_char    sdl_alen;    /* link level address length */ (ETHER_ADDR_LEN, 0x6)
    u_char    sdl_slen;    /* link layer selector length */ (0, 难道还是没有用?)
    char    sdl_data[46];    /* minimum work area, can be larger;
                   contains both if name and ll address */ ("rl0"+ether_addr…)
};
而LLADDR宏也就是把sdl_data偏移掉接口的名字,接下来就是接口的地址……
另外,struct ifaddrs和struct ifaddr很象,但是原来的ifa_ifp,也就是回指接口结构的指针没了。安全考虑? 为了区分内核和用户?
所以,坚信Linus的名言,有问题去看源代码!……
Old Blog Link: http://computer.mblogger.cn/henryhu/posts/61230.aspx

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.