带有 getifaddrs 的 MAC 地址
Posted
技术标签:
【中文标题】带有 getifaddrs 的 MAC 地址【英文标题】:MAC address with getifaddrs 【发布时间】:2011-10-09 10:01:54 【问题描述】:有没有办法通过getifaddrs()
获取接口的MAC地址?
我已经有了这个来获取 IP 地址,但我有点错过了MAC
。我试图在getifaddrs()
中查找信息,但没有关于MAC
地址的信息
struct ifaddrs *iflist, *iface;
if (getifaddrs(&iflist) < 0)
perror("getifaddrs");
char addrp[INET6_ADDRSTRLEN];
char macp[INET6_ADDRSTRLEN];
int i=0;
for (iface = iflist; iface; iface = iface->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++;
谢谢
【问题讨论】:
【参考方案1】:结合几个答案,这适用于 Linux 和 Mac/ios/BSD
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#ifdef __linux__
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#else
#include <net/if_dl.h>
#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;
【讨论】:
【参考方案2】:my experiments 有不同的方法来列出接口
/* 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 <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <linux/if_link.h>
#include <linux/types.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/ethernet.h> /* the L2 protocols */
#include <arpa/inet.h>
#include <netpacket/packet.h>
/* 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, "<error:");
strncat(addr, gai_strerror(rc), sizeof(addr));
strncat(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, "<no-hw-addr>", ADDR_FMT_SHORT);
putchar('\n');
return;
add_if_name(ifr, ADDR_FMT_LONG);
printf(" : ");
add_ip_addr(ifr, "<error> -", ADDR_FMT_LONG);
printf(" : ");
add_hw_addr(ifr, "<error> <no-hw-addr>", ADDR_FMT_LONG);
if (global.flags_set)
printf(" : ");
add_flags(ifr, "<error-no-flags>", 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("<no-address>\n");
return;
add_ip_addr(ifa, "<error> -", ADDR_FMT_LONG);
if (global.flags_set)
printf(" : ");
add_flags(ifa, "<error-no-flags>", 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 <interface> [-a | -m]]\n\n"
"Options:\n"
" -h -- this help\n"
" -1, -2, -3 -- use different query schemes:\n"
" SIOCGIFCONF, if_nameindex, getifaddrs\n"
" -i <interface> -- set <interface> 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 <interface>.\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;
【讨论】:
【参考方案3】:getifaddrs() 已经提供了与每个接口关联的 MAC 地址。在 Linux 上,当你遇到一个家庭时 == AF_PACKET 就是 MAC 地址。在 OSX / BSD 上也是如此,但在这种情况下,家庭将是 AF_LINK。
【讨论】:
【参考方案4】:在 BSD 系统上,您可以直接使用 getifaddrs 来检索 MAC。 以下是完整的 macaddr.c 工具示例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <ifaddrs.h>
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;
【讨论】:
此解决方案已在 FreeBSD、OS X 和 iOS 上进行了测试。【参考方案5】:这是获取IP和MAC地址的代码
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
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;
【讨论】:
与此问题无关。他在问如何使用 getifaddrs 获取 MAC 地址,而不是其他方式。【参考方案6】:在 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 成员,请参阅 here 了解说明。
【讨论】:
嘿,看起来不错,但我在s->sll_addr[i]
上找到了dereferencing pointer to incomplete type
,不知道为什么。你能帮忙吗?
您添加了所有必要的包含吗?按照包含的链接。
已修复。谢谢!但是我总是得到相同的 MAC 地址,虽然在接口上,它是不一样的。你知道为什么吗?
@shaggy 好吧,你在循环之外有 macp 缓冲区,所以我不知道你是如何查看 MAC 地址的。当您增加 i 时,您还将 addr 与 127.0.0.1 进行比较,这似乎没有什么意义。完整示例请参见pastebin.com/C71fA6UG
为了让这段代码更健壮,你真的应该测试一下sll_hatype==ARPHRD_ETHER
。 (#include <net/if_arp.h>
获取该定义,否则其值仅为 1)。这是因为,至少在理论上,您可能有一个使用非以太网物理地址的非以太网/非 WiFi(严格来说,非 IEEE 802)网络设备,在这种情况下,该地址可能不是 MAC 地址,但其他内容,其长度可能多于或少于 6 个字节,并且可能具有不同的标准打印格式。【参考方案7】:
如果您使用的是 Unix,您正在寻找 ioctl
SIOCGIFHWADDR
:
SIOCGIFHWADDR、SIOCGIFHWADDR
使用 ifr_hwaddr 获取或设置设备的硬件地址。这 硬件地址在 struct sockaddr 中指定。 sa_family 包含 ARPHRD_* 设备类型,sa_data L2 硬件地址起始 从字节 0 开始。设置硬件地址是一项特权操作。
见man netdevice
。
【讨论】:
谢谢,但问题是,如果有什么方法可以通过 getifaddrs() 得到这个以上是关于带有 getifaddrs 的 MAC 地址的主要内容,如果未能解决你的问题,请参考以下文章