[C++][linux]linux C++获取mac地址

Posted FL1623863129

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++][linux]linux C++获取mac地址相关的知识,希望对你有一定的参考价值。

How to get MAC address of your machine using a C program?

I am working on Ubuntu. How can I get MAC address of my machine or an interface say eth0 using C program.

Share

Follow

edited Jun 18, 2018 at 11:42

Vadim Kotov

7,97488 gold badges4848 silver badges6262 bronze badges

asked Nov 22, 2009 at 19:35

Bruce

33.2k7272 gold badges173173 silver badges262262 bronze badges

Add a comment

12 Answers

Sorted by:

                                              Highest score (default)                                                                   Trending (recent votes count more)                                                                   Date modified (newest first)                                                                   Date created (oldest first)                              

149

Much nicer than all this socket or shell madness is simply using sysfs for this:

the file /sys/class/net/eth0/address carries your mac adress as simple string you can read with fopen()/fscanf()/fclose(). Nothing easier than that.

And if you want to support other network interfaces than eth0 (and you probably want), then simply use opendir()/readdir()/closedir() on /sys/class/net/.

Share

Follow

edited Jul 10, 2017 at 8:54

haccks

103k2525 gold badges170170 silver badges260260 bronze badges

answered Nov 22, 2009 at 23:11

user175104

3,53822 gold badges2323 silver badges2020 bronze badges

  • 5

    Good answer, but not applicable in all situations. e.g. embedded systems (especially older ones, such as old versions of busybox, that don't have sysfs nor can support it because the system itself may be too old) 

    – Alex Marshall

     Apr 15, 2013 at 12:45
  • 3

    The question specifically asked for a C solution 

    – Charles Salvia

     Jun 19, 2014 at 1:48
  • 13

    @CharlesSalvia opening and reading a system file still seems like a C solution... as long as you know what your target system provides! Granted, your program will be tied to that type of system. But just compiling a program ties it to a system's architecture. I think this answer will help in many (but not all) situations. 

    – moodboom

     Dec 29, 2016 at 14:53 
  • (using Debian derived Bunsen on WiFi) See: /sys/class/net/wlp2s0/address 

    – AAAfarmclub

     Sep 12, 2020 at 23:30

You need to iterate over all the available interfaces on your machine, and use ioctl with SIOCGIFHWADDR flag to get the mac address. The mac address will be obtained as a 6-octet binary array. You also want to skip the loopback interface.

#include <sys/ioctl.h>
#include <net/if.h> 
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>

int main()

    struct ifreq ifr;
    struct ifconf ifc;
    char buf[1024];
    int success = 0;

    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock == -1)  /* handle error*/ ;

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    if (ioctl(sock, SIOCGIFCONF, &ifc) == -1)  /* handle error */ 

    struct ifreq* it = ifc.ifc_req;
    const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));

    for (; it != end; ++it) 
        strcpy(ifr.ifr_name, it->ifr_name);
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) 
            if (! (ifr.ifr_flags & IFF_LOOPBACK))  // don't count loopback
                if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) 
                    success = 1;
                    break;
                
            
        
        else  /* handle error */ 
    

    unsigned char mac_address[6];

    if (success) memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);

Share

Follow

edited May 25, 2012 at 0:35

Jamesprite

1577 bronze badges

answered Nov 22, 2009 at 19:48

Charles Salvia

51.7k1212 gold badges128128 silver badges140140 bronze badges

  • 1

    Why does this not need struct in front if ifreq and ifconf? Were typedefs for these structs removed in more recent kernels, that existed in 2009 when this was written? 

    – Karl P

     Jul 20, 2011 at 17:39
  • I think it should be noted that OpenVZ containers do not have a MAC address and therefore, none of these solutions would work. The MAC address is (assumed to be) 00:00:00:00:00:00 

    – SameOldNick

     Feb 22, 2014 at 7:19
  • 2

    It only works if there is link on eth0. It doesn't work if the network cable is unplugged (on Ubuntu). 

    – Florin Petriuc

You want to take a look at the getifaddrs(3) manual page. There is an example in C in the manpage itself that you can use. You want to get the address with the type AF_LINK.

Add a comment

25

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>

int main()

  struct ifreq s;
  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);

  strcpy(s.ifr_name, "eth0");
  if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) 
    int i;
    for (i = 0; i < 6; ++i)
      printf(" %02x", (unsigned char) s.ifr_addr.sa_data[i]);
    puts("\\n");
    return 0;
  
  return 1;

Share

Follow

edited Oct 18, 2011 at 8:10

Using getifaddrs you can get MAC address from the family AF_PACKET.

In order to display the MAC address to each interface, you can proceed like this:

#include <stdio.h>
#include <ifaddrs.h>
#include <netpacket/packet.h>

int main (int argc, const char * argv[])

    struct ifaddrs *ifaddr=NULL;
    struct ifaddrs *ifa = NULL;
    int i = 0;

    if (getifaddrs(&ifaddr) == -1)
    
         perror("getifaddrs");
    
    else
    
         for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
         
             if ( (ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_PACKET) )
             
                  struct sockaddr_ll *s = (struct sockaddr_ll*)ifa->ifa_addr;
                  printf("%-8s ", ifa->ifa_name);
                  for (i=0; i <s->sll_halen; i++)
                  
                      printf("%02x%c", (s->sll_addr[i]), (i+1!=s->sll_halen)?':':'\\n');
                  
             
         
         freeifaddrs(ifaddr);
    
    return 0;

Ideone

Share

Follow

edited Jun 7, 2019 at 5:56

answered Feb 6, 2016 at 15:06

mpromonet

11k4343 gold badges5757 silver badges9191 bronze badges

Add a comment

12

I have just write one and test it on gentoo in virtualbox.

// get_mac.c
#include <stdio.h>    //printf
#include <string.h>   //strncpy
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>   //ifreq
#include <unistd.h>   //close

int main()

    int fd;
    struct ifreq ifr;
    char *iface = "enp0s3";
    unsigned char *mac = NULL;

    memset(&ifr, 0, sizeof(ifr));

    fd = socket(AF_INET, SOCK_DGRAM, 0);

    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name , iface , IFNAMSIZ-1);

    if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) 
        mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;

        //display mac address
        printf("Mac : %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\\n" , mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    

    close(fd);

    return 0;

Share

Follow

answered Jun 24, 2014 at 12:45

Akagi201

45655 silver badges1212 bronze badges

Add a comment

6

Assuming that c++ code (c++11) is okay as well and the interface is known.

#include <cstdint>
#include <fstream>
#include <streambuf>
#include <regex>

using namespace std;

uint64_t getIFMAC(const string &ifname) 
  ifstream iface("/sys/class/net/" + ifname + "/address");
  string str((istreambuf_iterator<char>(iface)), istreambuf_iterator<char>());
  if (str.length() > 0) 
    string hex = regex_replace(str, std::regex(":"), "");
    return stoull(hex, 0, 16);
   else 
    return 0;
  
 
int main()

  string iface = "eth0";
  printf("%s: mac=%016llX\\n", iface.c_str(), getIFMAC(iface));

Share

Lincoln

9281111 silver badges1919 bronze badges

Add a comment

  1. On Linux, use the service of "Network Manager" over the DBus.

  2. There is also good'ol shell program which can be invoke and the result grabbed (use an exec function under C):

$ /sbin/ifconfig | grep HWaddr

Share

91.9k5656 gold badges199199 silver badges314314 bronze badges

Add a comment

0

A very portable way is to parse the output of this command.

ifconfig | awk '$0 ~ /HWaddr/  print $5 '

Provided ifconfig can be run as the current user (usually can) and awk is installed (it often is). This will give you the mac address of the machine.

Share

Follow

edited Jan 25, 2016 at 14:03

mpromonet

11k4343 gold badges5757 silver badges9191 bronze badges

answered Nov 22, 2009 at 19:54

hookenz

35.5k4242 gold badges171171 silver badges280280 bronze badges

Show 1 more comment

Expanding on the answer given by @user175104 ...

Share

0

netlink socket is possible

man netlink(7) netlink(3) rtnetlink(7) rtnetlink(3)

#include <assert.h>
#include <stdio.h>
#include <linux/if.h>
#include <linux/rtnetlink.h>
#include <unistd.h>

#define SZ 8192

int main()

  // Send
  typedef struct 
    struct nlmsghdr nh;
    struct ifinfomsg ifi;
   Req_getlink;
  assert(NLMSG_LENGTH(sizeof(struct ifinfomsg))==sizeof(Req_getlink));
  int fd=-1;
  fd=socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
  assert(0==bind(fd,(struct sockaddr*)(&(struct sockaddr_nl)
    .nl_family=AF_NETLINK,
    .nl_pad=0,
    .nl_pid=getpid(),
    .nl_groups=0
  ),sizeof(struct sockaddr_nl)));
  assert(sizeof(Req_getlink)==send(fd,&(Req_getlink)
    .nh=
      .nlmsg_len=NLMSG_LENGTH(sizeof(struct ifinfomsg)),
      .nlmsg_type=RTM_GETLINK,
      .nlmsg_flags=NLM_F_REQUEST|NLM_F_ROOT,
      .nlmsg_seq=0,
      .nlmsg_pid=0
    ,
    .ifi=
      .ifi_family=AF_UNSPEC,
      // .ifi_family=AF_INET,
      .ifi_type=0,
      .ifi_index=0,
      .ifi_flags=0,
      .ifi_change=0,
    
  ,sizeof(Req_getlink),0));

  // Receive
  char recvbuf[SZ]=;
  int len=0;
  for(char *p=recvbuf;;)
    const int seglen=recv(fd,p,sizeof(recvbuf)-len,0);
    assert(seglen>=1);
    len += seglen;
    if(((struct nlmsghdr*)p)->nlmsg_type==NLMSG_DONE||((struct nlmsghdr*)p)->nlmsg_type==NLMSG_ERROR)
      break;
    p += seglen;
  

  struct nlmsghdr *nh=(struct nlmsghdr*)recvbuf;
  for(;NLMSG_OK(nh,len);nh=NLMSG_NEXT(nh,len))
    if(nh->nlmsg_type==NLMSG_DONE)
      break;

    struct ifinfomsg *ifm=(struct ifinfomsg*)NLMSG_DATA(nh);

    printf("#%d ",ifm->ifi_index);
    #ifdef _NET_IF_H
    #pragma GCC error "include <linux/if.h> instead of <net/if.h>"
    #endif

    // Part 3 rtattr
    struct rtattr *rta=IFLA_RTA(ifm); // /usr/include/linux/if_link.h
    int rtl=RTM_PAYLOAD(nh);

    for(;RTA_OK(rta,rtl);rta=RTA_NEXT(rta,rtl))switch(rta->rta_type)
    case IFLA_IFNAME:printf("%s ",(const char*)RTA_DATA(rta));break;
    case IFLA_ADDRESS:
      printf("hwaddr ");
      for(int i=0;i<5;++i)
        printf("%02X:",*((unsigned char*)RTA_DATA(rta)+i));
      printf("%02X ",*((unsigned char*)RTA_DATA(rta)+5));
      break;
    case IFLA_BROADCAST:
      printf("bcast ");
      for(int i=0;i<5;++i)
        printf("%02X:",*((unsigned char*)RTA_DATA(rta)+i));
      printf("%02X ",*((unsigned char*)RTA_DATA(rta)+5));
      break;
    case IFLA_PERM_ADDRESS:
      printf("perm ");
      for(int i=0;i<5;++i)
        printf("%02X:",*((unsigned char*)RTA_DATA(rta)+i));
      printf("%02X ",*((unsigned char*)RTA_DATA(rta)+5));
      break;
    

    printf("\\n");

  

  close(fd);
  fd=-1;
  return 0;



Example

#1 lo hwaddr 00:00:00:00:00:00 bcast 00:00:00:00:00:00
#2 eth0 hwaddr 57:da:52:45:5b:1a bcast ff:ff:ff:ff:ff:ff perm 57:da:52:45:5b:1a
#3 wlan0 hwaddr 3c:7f:46:47:58:c2 bcast ff:ff:ff:ff:ff:ff perm 3c:7f:46:47:58:c2

Share

answered Sep 11, 2020 at 5:36

Darren Ng

31544 silver badges1111 bronze badges

Add a comment

-1

This is a Bash line that prints all available mac addresses, except the loopback:

for x in `ls /sys/class/net |grep -v lo`; do cat /sys/class/net/$x/address; done

Can be executed from a C program.

以上是关于[C++][linux]linux C++获取mac地址的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ 在 Linux 中获取硬件信息

如何在 C++ 中获取 linux 命令输出字符串和输出状态

Linux:获取孙子的 pid C++

如何从 C++ 程序获取 Linux 上的主板 ID

使用 C++ 在 Windows 中获取时区

使用 C++ 获取 Linux 中进程的 RAM 和 CPU 使用率