与getifaddrs的MAC地址

有没有办法通过getifaddrs()获取接口的MAC地址?

我已经有了这个,获取IP地址,但我有点想念MAC 。 我试图在getifaddrs()查找信息,但没有关于MAC地址的信息

 struct ifaddrs *iflist, *iface; if (getifaddrs(&iflist) ifa_next) { int af = iface->ifa_addr->sa_family; const void *addr; const void *mac; switch (af) { case AF_INET: addr = &((struct sockaddr_in *)iface->ifa_addr)->sin_addr; break; //get mac address somehow? default: addr = NULL; } if (addr) { if (inet_ntop(af, addr, addrp, sizeof addrp) == NULL) { perror("inet_ntop"); continue; } if (inet_ntop(af, mac, macp, sizeof macp) == NULL) // this is already for MAC add { perror("inet_ntop"); continue; } if (strcmp(addrp, "127.0.0.1") != 0) { strcat(tableO[i].IPaddr, addrp); strcat(tableO[i].MACaddr, macp); i++; } } 

谢谢

getifaddrs()已经提供了与每个接口关联的MAC地址。 在Linux上,当你碰到一个家庭== AF_PACKET 是MAC地址。 在OSX / BSD上也是如此,但在这种情况下,家庭将是AF_LINK。

在BSD系统上,您可以直接使用getifaddrs来检索MAC。 这是完整的macaddr.c工具的示例:

 #include  #include  #include  #include  #include  int listmacaddrs(void) { struct ifaddrs *ifap, *ifaptr; unsigned char *ptr; if (getifaddrs(&ifap) == 0) { for(ifaptr = ifap; ifaptr != NULL; ifaptr = (ifaptr)->ifa_next) { if (((ifaptr)->ifa_addr)->sa_family == AF_LINK) { ptr = (unsigned char *)LLADDR((struct sockaddr_dl *)(ifaptr)->ifa_addr); printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", (ifaptr)->ifa_name, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)); } } freeifaddrs(ifap); return 1; } else { return 0; } } int macaddr(char *ifname, char *macaddrstr) { struct ifaddrs *ifap, *ifaptr; unsigned char *ptr; if (getifaddrs(&ifap) == 0) { for(ifaptr = ifap; ifaptr != NULL; ifaptr = (ifaptr)->ifa_next) { if (!strcmp((ifaptr)->ifa_name, ifname) && (((ifaptr)->ifa_addr)->sa_family == AF_LINK)) { ptr = (unsigned char *)LLADDR((struct sockaddr_dl *)(ifaptr)->ifa_addr); sprintf(macaddrstr, "%02x:%02x:%02x:%02x:%02x:%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)); break; } } freeifaddrs(ifap); return ifaptr != NULL; } else { return 0; } } extern int main(int argc, char* argv[]) { char macaddrstr[18], *ifname; if (argc == 2) { ifname = argv[1]; if (!strcmp(ifname,"-l")) { return listmacaddrs(); } else { if (macaddr(ifname, macaddrstr)) { printf("%s: %s\n", ifname, macaddrstr); return 0; } else { printf("%s: not found\n", ifname); return 1; } } } else { printf("list all interfaces: %s -l\n", argv[0]); printf("single interface: %s interface_name\n", argv[0]); return 2; } } 

在Linux上,你会做这样的事情

  case AF_PACKET: { struct sockaddr_ll *s = (struct sockaddr_ll*)iface->ifa_addr; int i; int len = 0; for(i = 0; i < 6; i++) len+=sprintf(macp+len,"%02X%s",s->sll_addr[i],i < 5 ? ":":""); } 

但是,您可能需要检查struct sockaddr_ll的更多成员,请参阅此处以获取说明。

如果您使用的是Unix,那么您正在寻找ioctl SIOCGIFHWADDR

SIOCGIFHWADDR,SIOCSIFHWADDR

使用ifr_hwaddr获取或设置设备的硬件地址。 硬件地址在struct sockaddr中指定。 sa_family包含ARPHRD_ *设备类型,sa_data是从字节0开始的L2硬件地址。设置硬件地址是特权操作。

man netdevice

这是获取IP和MAC地址的代码

 #include  #include  #include  #include  #include  #include  #include  int main(void) { char buf[8192] = {0}; struct ifconf ifc = {0}; struct ifreq *ifr = NULL; int sck = 0; int nInterfaces = 0; int i = 0; char ip[INET6_ADDRSTRLEN] = {0}; char macp[19]; struct ifreq *item; struct sockaddr *addr; /* Get a socket handle. */ sck = socket(PF_INET, SOCK_DGRAM, 0); if(sck < 0) { perror("socket"); return 1; } /* Query available interfaces. */ ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(sck, SIOCGIFCONF, &ifc) < 0) { perror("ioctl(SIOCGIFCONF)"); return 1; } /* Iterate through the list of interfaces. */ ifr = ifc.ifc_req; nInterfaces = ifc.ifc_len / sizeof(struct ifreq); for(i = 0; i < nInterfaces; i++) { item = &ifr[i]; addr = &(item->ifr_addr); /* Get the IP address*/ if(ioctl(sck, SIOCGIFADDR, item) < 0) { perror("ioctl(OSIOCGIFADDR)"); } if (inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), ip, sizeof ip) == NULL) //vracia adresu interf { perror("inet_ntop"); continue; } /* Get the MAC address */ if(ioctl(sck, SIOCGIFHWADDR, item) < 0) { perror("ioctl(SIOCGIFHWADDR)"); return 1; } /* display result */ sprintf(macp, " %02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)item->ifr_hwaddr.sa_data[0], (unsigned char)item->ifr_hwaddr.sa_data[1], (unsigned char)item->ifr_hwaddr.sa_data[2], (unsigned char)item->ifr_hwaddr.sa_data[3], (unsigned char)item->ifr_hwaddr.sa_data[4], (unsigned char)item->ifr_hwaddr.sa_data[5]); printf("%s %s ", ip, macp); } return 0; } 

我的实验有不同的列表接口方法

 /* Copyright Yadro (C) 2016 * Author: ed@ngslab.ru * * For those who have pissed off awking output of ip(8)... * * [root@opt-03 ~]# ./lsif * 1: lo : 127.0.0.1 : LOOPBACK - * 2: eno1 : 172.17.32.102 : ETHER 6c:ae:8b:2c:eb:18 * 3: br-ctlplane : 192.0.2.1 : ETHER 6c:ae:8b:2c:eb:19 * 4: br-ctlplane : 192.0.2.3 : ETHER 6c:ae:8b:2c:eb:19 * 5: br-ctlplane : 192.0.2.2 : ETHER 6c:ae:8b:2c:eb:19 * * See netdevice(7) for * - SIOCGIFADDR * - SIOCGIFBRDADDR * - SIOCGIFCONF (here) * - SIOCGIFDSTADDR * - SIOCGIFFLAGS * - SIOCGIFHWADDR (here) * - SIOCGIFINDEX * - SIOCGIFMAP * - SIOCGIFMETRIC * - SIOCGIFMTU * - SIOCGIFNAME * - SIOCGIFNETMASK * - SIOCGIFPFLAGS * - SIOCGIFTXQLEN */ #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  /* the L2 protocols */ #include  #include  /* legacy mode decls */ extern int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt; /* bool type is not a default feature in C */ typedef enum { false = 0, true = 1 } bool; static struct { int mode; bool ifname_set; char ifname[IFNAMSIZ+1]; bool show_ip; bool show_mac; bool flags_set; short flags; bool verbose; } global = {}; int run_ioctl(int opcode, void *arg, const struct sockaddr *sa) { int af = sa ? sa->sa_family : AF_INET; int rc, sock = socket(af, SOCK_DGRAM, 0); if (sock < 0) { if (global.verbose) perror("socket"); return sock; } if (sa) { int sa_len = sizeof(struct sockaddr); switch (af) { case AF_INET: sa_len = sizeof(struct sockaddr_in); break; case AF_INET6: sa_len = sizeof(struct sockaddr_in6); break; case AF_PACKET: sa_len = sizeof(struct sockaddr_ll); break; } if (bind(sock, sa, sa_len)) { // if (global.verbose) perror("bind"); close(sock); return rc; } } rc = ioctl(sock, opcode, arg); if (rc) { // if (global.verbose) perror("ioctl"); close(sock); return rc; } close(sock); return 0; } int query_response_size(void) { struct ifconf ifc = {}; int rc = run_ioctl(SIOCGIFCONF, &ifc, NULL); if (rc) { if (global.verbose) perror("query_response_size"); return rc; } return ifc.ifc_len; } int query_if_hwaddr(struct ifreq *req) { int rc = run_ioctl(SIOCGIFHWADDR, req, NULL); if (rc) { if (global.verbose) perror("query_if_hwaddr:ioctl"); return rc; } return 0; } int query_ip_addr(struct ifreq *req) { int rc; req->ifr_addr.sa_family = AF_INET; rc = run_ioctl(SIOCGIFADDR, req, NULL); if (rc) { if (global.verbose) perror("query_ip_addr:ioctl"); return rc; } return 0; } int query_if_flags(struct ifreq *req) { int rc = run_ioctl(SIOCGIFHWADDR, req, NULL); if (rc) { if (global.verbose) perror("query_if_flags:ioctl"); return rc; } return 0; } double query_if_last_pkt(const struct sockaddr *sa) { struct timeval t; double res; int rc = run_ioctl(SIOCGSTAMP, &t, sa); if (rc) { if (global.verbose) perror("query_if_last_pkt:ioctl"); return -1.0; } res = (double) t.tv_sec; res += ((double) t.tv_usec) / 1000000.0; return res; } enum addr_fmt { ADDR_FMT_LONG, ADDR_FMT_SHORT, }; static const char iff_flag_delimiter[] = ","; #define _STR(x) ""#x #define IFF_FLAG2STR(flag, value, string, descr) \ do { \ if ((value) & (IFF_##flag)) { \ if ((string)[0]) \ strcat((string), iff_flag_delimiter); \ strcat((string), _STR(flag)); \ } \ } while (0) static inline char *if_flags(short flags, enum addr_fmt fmt) { static char sflags[128]; memset(sflags, 0, sizeof(sflags)); /* sprintf(sflags, "0x%0*x", (int)sizeof(flags) * 2, flags); */ IFF_FLAG2STR(UP, flags, sflags, "Interface is up"); IFF_FLAG2STR(BROADCAST, flags, sflags, "Broadcast address valid"); IFF_FLAG2STR(DEBUG, flags, sflags, "Turn on debugging"); IFF_FLAG2STR(LOOPBACK, flags, sflags, "Is a loopback net"); IFF_FLAG2STR(POINTOPOINT, flags, sflags, "Interface is point-to-point link"); IFF_FLAG2STR(NOTRAILERS, flags, sflags, "Avoid use of trailers"); IFF_FLAG2STR(RUNNING, flags, sflags, "Resources allocated"); IFF_FLAG2STR(NOARP, flags, sflags, "No address resolution protocol"); IFF_FLAG2STR(PROMISC, flags, sflags, "Receive all packets"); IFF_FLAG2STR(ALLMULTI, flags, sflags, "Receive all multicast packets"); IFF_FLAG2STR(MASTER, flags, sflags, "Master of a load balancer"); IFF_FLAG2STR(SLAVE, flags, sflags, "Slave of a load balancer"); IFF_FLAG2STR(MULTICAST, flags, sflags, "Supports multicast"); IFF_FLAG2STR(PORTSEL, flags, sflags, "Can set media type"); IFF_FLAG2STR(AUTOMEDIA, flags, sflags, "Auto media select active"); IFF_FLAG2STR(DYNAMIC, flags, sflags, "Dialup device with changing addresses"); return sflags; } static const char *_families[] = { [AF_UNSPEC] = "UNSPEC", [AF_LOCAL] = "LOCAL", /* == [AF_UNIX] == [AF_FILE] */ [AF_INET] = "INET", [AF_AX25] = "AX25", [AF_IPX] = "IPX", [AF_APPLETALK] = "APPLETALK", [AF_NETROM] = "NETROM", [AF_BRIDGE] = "BRIDGE", [AF_ATMPVC] = "ATMPVC", [AF_X25] = "X25", [AF_INET6] = "INET6", [AF_ROSE] = "ROSE", [AF_DECnet] = "DECnet", [AF_NETBEUI] = "NETBEUI", [AF_SECURITY] = "SECURITY", [AF_KEY] = "KEY", [AF_NETLINK] = "NETLINK", [AF_ROUTE] = "ROUTE", [AF_PACKET] = "PACKET", [AF_ASH] = "ASH", [AF_ECONET] = "ECONET", [AF_ATMSVC] = "ATMSVC", [AF_RDS] = "RDS", [AF_SNA] = "SNA", [AF_IRDA] = "IRDA", [AF_PPPOX] = "PPPOX", [AF_WANPIPE] = "WANPIPE", [AF_LLC] = "LLC", [AF_IB] = "IB", [AF_MPLS] = "MPLS", [AF_CAN] = "CAN", [AF_TIPC] = "TIPC", [AF_BLUETOOTH] = "BLUETOOTH", [AF_IUCV] = "IUCV", [AF_RXRPC] = "RXRPC", [AF_ISDN] = "ISDN", [AF_PHONET] = "PHONET", [AF_IEEE802154] = "IEEE802154", [AF_CAIF] = "CAIF", [AF_ALG] = "ALG", [AF_NFC] = "NFC", [AF_VSOCK] = "VSOCK", }; static inline const char *af_name(int af) { if (af >= 0 && af < AF_MAX) return _families[af]; return NULL; } static inline char *add_af_name(char *s, int af, enum addr_fmt fmt) { static int af_name_len_max; if (!af_name_len_max) { int i; for (i = 0; i < AF_MAX; i++) { int l = strlen(af_name(i)); if (l > af_name_len_max) af_name_len_max = l; } af_name_len_max++; /* add a space */ } switch (fmt) { case ADDR_FMT_LONG: sprintf(s, "%-*.*s", af_name_len_max, af_name_len_max, af_name(af)); break; case ADDR_FMT_SHORT: strcpy(s, af_name(af)); strcat(s, " "); break; } s += strlen(s); return s; } #define min(x,y) (((x) > (y)) ? (y) : (x)) #define left_in(space) (sizeof(space) - strlen(space)) static inline void rpad4fmt(char *s, int s_size, int pad_size, enum addr_fmt fmt) { while (fmt == ADDR_FMT_LONG && strlen(s) < min(s_size, pad_size)) strncat(s, " ", s_size); } static inline int fetch_address(const struct sockaddr *sa, char *s, int size) { int inf_size = -1; switch (sa->sa_family) { case AF_INET: inf_size = sizeof(struct sockaddr_in); break; case AF_INET6: inf_size = sizeof(struct sockaddr_in6); break; } return getnameinfo(sa, inf_size, s, size, NULL, 0, NI_NUMERICHOST); } static inline void hex_colon_bytes(char *s, const void *data, int d_sz) { int i; const uint8_t *d = data; char *p; for (i = 0, p = s + strlen(s); i < d_sz; i++) sprintf(p + i * 3, "%02x%s", d[i], (i < d_sz - 1) ? ":" : ""); } static inline void decode_packet(char *s, int size, const struct sockaddr *sa, enum addr_fmt fmt) { const struct sockaddr_ll *ll = (struct sockaddr_ll *)sa; uint8_t *data = (uint8_t *) &ll->sll_addr[0]; const int af = ll->sll_hatype; char *p; switch (af) { case ARPHRD_LOOPBACK: switch (fmt) { case ADDR_FMT_LONG: p = "LOOPBACK -"; break; case ADDR_FMT_SHORT: p = "-"; break; } strncpy(s, p, size); break; case ARPHRD_ETHER: switch (fmt) { case ADDR_FMT_LONG: p = "ETHER %02x:%02x:%02x:%02x:%02x:%02x"; break; case ADDR_FMT_SHORT: p = "%02x:%02x:%02x:%02x:%02x:%02x"; break; } snprintf(s, size, p, data[0], data[1], data[2], data[3], data[4], data[5]); break; default: switch (fmt) { case ADDR_FMT_LONG: snprintf(s, size, "<%d> <", af); break; case ADDR_FMT_SHORT: snprintf(s, size, "<%d/", af); break; } hex_colon_bytes(s, data, ll->sll_halen); strncat(s, ">", size); break; } } static inline char *ip_addr(const struct sockaddr *sa, enum addr_fmt fmt) { const int af = sa->sa_family; static char addr[64]; char *fmx, *p; int i, rc, pad_size; addr[0] = '\0'; p = (fmt == ADDR_FMT_LONG) ? add_af_name(addr, af, fmt) : addr; switch (af) { case AF_INET: pad_size = strlen(addr) + 15; break; case AF_INET6: pad_size = strlen(addr) + 40; break; default: pad_size = 0; break; } switch (af) { case AF_INET: case AF_INET6: rc = fetch_address(sa, p, min(left_in(addr), NI_MAXHOST)); if (rc) { strcat(addr, "", sizeof(addr)); return addr; } rpad4fmt(addr, sizeof(addr), pad_size, fmt); break; case AF_PACKET: /* no real IP here, of course */ decode_packet(p, left_in(addr), sa, fmt); break; default: snprintf(p, left_in(addr), "<%d/", af); hex_colon_bytes(addr, sa->sa_data, sizeof(sa->sa_data)); strncat(addr, ">", left_in(addr)); break; } return addr; } static inline char *hw_addr(const struct sockaddr *sa, enum addr_fmt fmt) { const int af = sa->sa_family; uint8_t *data = (uint8_t *) &sa->sa_data[0]; const size_t data_size = sizeof(sa->sa_data); static char mac[64]; /* ETHER aa:bb:cc:dd:ee:ff */ char *p, *fmx; int i; switch (af) { case ARPHRD_LOOPBACK: switch (fmt) { case ADDR_FMT_LONG: fmx = "LOOPBACK -"; break; case ADDR_FMT_SHORT: fmx = "-"; break; } strcpy(mac, fmx); break; case ARPHRD_ETHER: switch (fmt) { case ADDR_FMT_LONG: fmx = "ETHER %02x:%02x:%02x:%02x:%02x:%02x"; break; case ADDR_FMT_SHORT: fmx = "%02x:%02x:%02x:%02x:%02x:%02x"; break; } sprintf(mac, fmx, data[0], data[1], data[2], data[3], data[4], data[5]); break; default: switch (fmt) { case ADDR_FMT_LONG: sprintf(mac, "<%d> <", af); break; case ADDR_FMT_SHORT: strcpy(mac, "<"); break; } for (i = 0, p = mac + strlen(mac); i < data_size; i++) sprintf(p + i * 3, "%02x%s", data[i], (i < data_size - 1) ? ":" : ">"); break; } return mac; } static inline void add_ip_addr(void *ifx, const char *errmsg, enum addr_fmt fmt) { struct sockaddr *sa; struct ifreq *ifr = ifx; struct ifaddrs *ifa = ifx; switch (global.mode) { case 1: /* already fetched */ sa = &ifr->ifr_addr; break; case 2: sa = query_ip_addr(ifr) ? NULL : &ifr->ifr_addr; break; case 3: /* already fetched */ sa = ifa->ifa_addr; break; } fputs(sa ? ip_addr(sa, fmt) : errmsg, stdout); } static inline void add_hw_addr(struct ifreq *ifr, const char *errmsg, enum addr_fmt fmt) { fputs(query_if_hwaddr(ifr) ? errmsg : hw_addr(&ifr->ifr_addr, fmt), stdout); } static inline void add_flags(void *ifx, const char *errmsg, enum addr_fmt fmt) { struct ifreq *ifr = ifx; struct ifaddrs *ifa = ifx; int flags = -1; switch (global.mode) { case 1: case 2: flags = query_if_flags(ifr) ? -1 : ifr->ifr_flags; break; case 3: /* already fetched */ flags = ifa->ifa_flags; break; } fputs((flags == -1) ? errmsg : if_flags(flags, fmt), stdout); } static inline void add_if_name(void *ifx, enum addr_fmt fmt) { struct ifreq *ifr = ifx; struct ifaddrs *ifa = ifx; char *name; switch (global.mode) { case 1: case 2: name = ifr->ifr_name; break; case 3: name = ifa->ifa_name; break; } switch (fmt) { case ADDR_FMT_LONG: printf("%-*.*s", IFNAMSIZ, IFNAMSIZ, name); break; case ADDR_FMT_SHORT: fputs(name, stdout); break; } } static void print_interface(struct ifreq *ifr) { if (global.ifname_set) { if (strncmp(ifr->ifr_name, global.ifname, IFNAMSIZ)) return; if (global.show_ip || !global.show_mac) { add_ip_addr(ifr, NULL, ADDR_FMT_SHORT); fputs(global.show_ip ? "" : "\t", stdout); } if (global.show_mac || !global.show_ip) add_hw_addr(ifr, "", ADDR_FMT_SHORT); putchar('\n'); return; } add_if_name(ifr, ADDR_FMT_LONG); printf(" : "); add_ip_addr(ifr, " -", ADDR_FMT_LONG); printf(" : "); add_hw_addr(ifr, " ", ADDR_FMT_LONG); if (global.flags_set) { printf(" : "); add_flags(ifr, "", ADDR_FMT_LONG); } putchar('\n'); } static void print_address(struct ifaddrs *ifa) { if (global.ifname_set) { if (strncmp(ifa->ifa_name, global.ifname, IFNAMSIZ)) return; } else { add_if_name(ifa, ADDR_FMT_LONG); printf(" : "); } if (ifa->ifa_addr == NULL) { printf("\n"); return; } add_ip_addr(ifa, " -", ADDR_FMT_LONG); if (global.flags_set) { printf(" : "); add_flags(ifa, "", ADDR_FMT_LONG); } putchar('\n'); return; } static void __dispose_req(struct ifreq **req) { if (req && *req) { free(*req); *req = 0; } } static int __1__query_if_list(void) { struct ifreq *req __attribute__((cleanup(__dispose_req))) = NULL; struct ifconf ifc = {}; int rc, i, j, size = query_response_size(); if (size <= 0) return -1; req = calloc(size, 1); if (!req) { if (global.verbose) perror("query_if_list:cmalloc"); return -1; } ifc.ifc_len = size; ifc.ifc_req = req; rc = run_ioctl(SIOCGIFCONF, &ifc, NULL); if (rc) { if (global.verbose) perror("query_if_list:ioctl"); return rc; } for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++) { struct ifreq *ifr = &ifc.ifc_req[i]; if (global.ifname_set) { if (strncmp(ifr->ifr_name, global.ifname, IFNAMSIZ)) continue; } else printf("%2d: ", i + 1); print_interface(ifr); } return 0; } static void __dispose_if_list_2(struct if_nameindex **if_list) { if (if_list && *if_list) { if_freenameindex(*if_list); *if_list = 0; } } static int __2__query_if_list(void) { struct if_nameindex *i; struct if_nameindex *if_list __attribute__((cleanup(__dispose_if_list_2))) = if_nameindex(); if (!if_list) { if (global.verbose) perror("if_nameindex"); return -1; } for (i = if_list; ! (i->if_index == 0 && i->if_name == NULL); i++) { struct ifreq ifr; // printf("%u: %s\n", i->if_index, i->if_name); strncpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name)); print_interface(&ifr); } return 0; } static void __dispose_if_list_3(struct ifaddrs **if_list) { if (if_list && *if_list) { freeifaddrs(*if_list); *if_list = 0; } } static int __3__query_if_list(void) { struct ifaddrs *ifa; struct ifaddrs *if_list __attribute__((cleanup(__dispose_if_list_3))) = NULL; if (getifaddrs(&if_list) == -1) { if (global.verbose) perror("getifaddrs"); return -1; } for (ifa = if_list; ifa != NULL; ifa = ifa->ifa_next) { // if (!ifa->ifa_addr) // continue; print_address(ifa); } } int query_if_list(void) { switch (global.mode) { case 1: return __1__query_if_list(); case 2: return __2__query_if_list(); case 3: return __3__query_if_list(); } } static char HELP[] = "%s [-f] [-i  [-a | -m]]\n\n" "Options:\n" " -h -- this help\n" " -1, -2, -3 -- use different query schemes:\n" " SIOCGIFCONF, if_nameindex, getifaddrs\n" " -i  -- set  name to query for\n" " -a -- list IP addresses\n" " -m -- list MAC addresses (you may want to use 'sort -u') here\n" " -f -- add flags to the output\n" " -v -- verbose\n" "\n"; static int parse_args(int argc, char * const argv[]) { const static char optspec[] = "hvi:amf123"; global.mode = 1; /* default */ while (true) { int opt = getopt(argc, argv, optspec); if (opt == -1) break; switch (opt) { case 'h': printf(HELP, argv[0]); exit(EXIT_SUCCESS); case '1': global.mode = 1; break; case '2': global.mode = 2; break; case '3': global.mode = 3; break; case '4': global.mode = 4; break; case '5': global.mode = 5; break; case '6': global.mode = 6; break; case '7': global.mode = 7; break; case '8': global.mode = 8; break; case '9': global.mode = 9; break; case 'i': global.ifname_set = true; strncpy(global.ifname, optarg, IFNAMSIZ); continue; case 'a': global.show_ip = true; continue; case 'm': global.show_mac = true; continue; case 'f': global.flags_set = true; continue; case 'v': global.verbose = true; continue; default: return -1; } } /* argv[optind] may be parsed here */ if (optind < argc) { fprintf(stderr, "%s: trailing extra args\n", argv[0]); return -1; } if ((global.show_ip || global.show_mac) && !global.ifname_set) { fprintf(stderr, "%s: -a and -m require -i .\n", argv[0]); return -1; } if (global.show_ip && global.show_mac) { /* just turn'em off */ global.show_ip = false; global.show_mac = false; /* fprintf(stderr, "%s: -a and -m are mutually exclusive.\n", argv[0]); return -1; */ } return 0; } int main(int argc, char * const argv[]) { if (parse_args(argc, argv)) return EXIT_FAILURE; if (query_if_list()) return EXIT_FAILURE; return EXIT_SUCCESS; } 

结合几个答案,这适用于Linux和Mac / iOS / BSD

 #include  #include  #include  #include  #include  #ifdef __linux__ #include  #include  #include  #else #include  #endif int listmacaddrs(void) { struct ifaddrs *ifap, *ifaptr; unsigned char *ptr; if (getifaddrs(&ifap) == 0) { for(ifaptr = ifap; ifaptr != NULL; ifaptr = (ifaptr)->ifa_next) { #ifdef __linux__ char macp[INET6_ADDRSTRLEN]; if (((ifaptr)->ifa_addr)->sa_family == AF_PACKET) { struct sockaddr_ll *s = (struct sockaddr_ll*)(ifaptr->ifa_addr); int i; int len = 0; for (i = 0; i < 6; i++) { len += sprintf(macp+len, "%02X%s", s->sll_addr[i], i < 5 ? ":":""); } printf("%s: %s\n", (ifaptr)->ifa_name, macp); } #else if (((ifaptr)->ifa_addr)->sa_family == AF_LINK) { ptr = (unsigned char *)LLADDR((struct sockaddr_dl *)(ifaptr)->ifa_addr); printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", (ifaptr)->ifa_name, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)); } #endif } freeifaddrs(ifap); return 1; } else { return 0; } } int macaddr(char *ifname, char *macaddrstr) { struct ifaddrs *ifap, *ifaptr; unsigned char *ptr; if (getifaddrs(&ifap) == 0) { for(ifaptr = ifap; ifaptr != NULL; ifaptr = (ifaptr)->ifa_next) { #ifdef __linux__ if (!strcmp((ifaptr)->ifa_name, ifname) && (((ifaptr)->ifa_addr)->sa_family == AF_PACKET)) { struct sockaddr_ll *s = (struct sockaddr_ll*)(ifaptr->ifa_addr); int i; int len = 0; for (i = 0; i < 6; i++) { len += sprintf(macaddrstr+len, "%02X%s", s->sll_addr[i], i < 5 ? ":":""); } break; } #else if (!strcmp((ifaptr)->ifa_name, ifname) && (((ifaptr)->ifa_addr)->sa_family == AF_LINK)) { ptr = (unsigned char *)LLADDR((struct sockaddr_dl *)(ifaptr)->ifa_addr); sprintf(macaddrstr, "%02x:%02x:%02x:%02x:%02x:%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)); break; } #endif } freeifaddrs(ifap); return ifaptr != NULL; } else { return 0; } } extern int main(int argc, char* argv[]) { char macaddrstr[18], *ifname; if (argc == 2) { ifname = argv[1]; if (!strcmp(ifname,"-l")) { return listmacaddrs(); } else { if (macaddr(ifname, macaddrstr)) { printf("%s: %s\n", ifname, macaddrstr); return 0; } else { printf("%s: not found\n", ifname); return 1; } } } else { printf("list all interfaces: %s -l\n", argv[0]); printf("single interface: %s interface_name\n", argv[0]); return 2; } }