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
– Keeely
Nov 23, 2018 at 9:55Add a comment
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:453
The question specifically asked for a C solution– Charles Salvia
Jun 19, 2014 at 1:4813
@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– AAAfarmclub
Sep 12, 2020 at 23:30You 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
#include
#include
#include
#include
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:3900:00:00:00:00:00
– SameOldNick
Feb 22, 2014 at 7:192
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
.
AF_LINK
is not described. Perhaps this is superseded by AF_PACKET
? – mpromonet
Feb 6, 2016 at 15:153
According to stackoverflow.com/a/26038501/5230867 it seems that AF_LINK is macOS/BSD-specific, while AF_PACKET is the Linux equivalent.– Manfred Urban
Sep 26, 2018 at 23:05Add a comment
25
#include
#include
#include
#include
#include
#include
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
#include
#include
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 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 //printf
#include //strncpy
#include
#include
#include //ifreq
#include //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
#include
#include
#include
using namespace std;
uint64_t getIFMAC(const string &ifname) {
ifstream iface("/sys/class/net/" + ifname + "/address");
string str((istreambuf_iterator(iface)), istreambuf_iterator());
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
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
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
4
It's not very portable at all. It gives nothing on Mac OS X. The output ofifconfig
does not contain the text HWaddr
. – dreamlax
Nov 22, 2009 at 20:25– hookenz
Nov 22, 2009 at 22:041
Well, the concept is portable. The text may need tweaking for other platforms.– hookenz
Nov 22, 2009 at 22:052
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:598
Also, this isn't going to compile in any C compiler I know of.– BobbyShaftoe
Nov 23, 2009 at 14:10Show 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
#include
#include
#include
#include
#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 instead of "
#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.