与getifaddrs的MAC地址

sha*_*ggy 8 c ip mac-address interface

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

我已经有了这个,获取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++;
    }
      }
Run Code Online (Sandbox Code Playgroud)

谢谢

Gia*_*olà 13

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


roy*_*ltm 12

在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;
    }
}
Run Code Online (Sandbox Code Playgroud)


nos*_*nos 11

在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 ? ":":"");

        }
Run Code Online (Sandbox Code Playgroud)

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

  • 为了使此代码更加健壮,您确实应该测试“sll_hatype==ARPHRD_ETHER”。(`#include &lt;net/if_arp.h&gt;` 来获取该定义,否则其值仅为 1)。这是因为,至少在理论上,您可能拥有一个使用某些非以太网物理地址的非以太网/非 WiFi(严格来说,非 IEEE 802)网络设备,在这种情况下,该地址可能不是 MAC 地址,但还有其他东西,其长度可能大于或小于 6 个字节,并且可能具有不同的标准打印格式。 (2认同)

小智 6

结合几个答案,这适用于 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;
    }
}
Run Code Online (Sandbox Code Playgroud)


sha*_*ggy 4

这是获取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;
}
Run Code Online (Sandbox Code Playgroud)