[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.
Follow
7,97488 gold badges4848 silver badges6262 bronze badges
asked Nov 22, 2009 at 19:35
33.2k7272 gold badges173173 silver badges262262 bronze badges
- Please see also related question: stackoverflow.com/questions/4951257/…
– Keeely
Nov 23, 2018 at 9:55
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/
.
Follow
103k2525 gold badges170170 silver badges260260 bronze badges
answered Nov 22, 2009 at 23:11
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) Apr 15, 2013 at 12:45 -
3
The question specifically asked for a C solution 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 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);
Follow
1577 bronze badges
answered Nov 22, 2009 at 19:48
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
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).
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
.
- in the manpage of getifaddrs linked the type
AF_LINK
is not described. Perhaps this is superseded byAF_PACKET
? Feb 6, 2016 at 15:15 -
3
According to stackoverflow.com/a/26038501/5230867 it seems that AF_LINK is macOS/BSD-specific, while AF_PACKET is the Linux equivalent. Sep 26, 2018 at 23:05
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;
Follow
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;
Follow
answered Feb 6, 2016 at 15:06
11k4343 gold badges5757 silver badges9191 bronze badges
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;
Follow
answered Jun 24, 2014 at 12:45
45655 silver badges1212 bronze badges
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));
9281111 silver badges1919 bronze badges
-
On Linux, use the service of "Network Manager" over the DBus.
-
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
91.9k5656 gold badges199199 silver badges314314 bronze badges
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.
Follow
11k4343 gold badges5757 silver badges9191 bronze badges
answered Nov 22, 2009 at 19:54
35.5k4242 gold badges171171 silver badges280280 bronze badges
-
4
It's not very portable at all. It gives nothing on Mac OS X. The output ofifconfig
does not contain the textHWaddr
.– dreamlax
Nov 22, 2009 at 20:25 - Had to do this earlier in the year on solaris, linux and hpux.
– hookenz
Nov 22, 2009 at 22:04 -
1
Well, the concept is portable. The text may need tweaking for other platforms.– hookenz
Nov 22, 2009 at 22:05 -
2
Using shell scripts, even one as tiny as yours is far from portable. There is a joke that goes that a shell is easier to port than a shell script :p– sigjuice
Nov 23, 2009 at 1:59 -
8
Also, this isn't going to compile in any C compiler I know of. Nov 23, 2009 at 14:10
Expanding on the answer given by @user175104 ...
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
answered Sep 11, 2020 at 5:36
31544 silver badges1111 bronze badges
-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地址的主要内容,如果未能解决你的问题,请参考以下文章