tags:

views:

1339

answers:

6

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

+2  A: 
  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

jldupont
+8  A: 

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.

Juliano
+9  A: 

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()
{
    ifreq ifr;
    ifconf ifc;
    char buf[1024];
    bool success = false;

    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 */ }

    ifreq* it = ifc.ifc_req;
    const ifreq* const end = it + (ifc.ifc_len / sizeof(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 = true;
        break;
       }
      }
     }
     else { /* handle error */ }
    }

    unsigned char mac_address[6];

    if (success) memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);
}
Charles Salvia
A: 

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.

Matt H
It's not very portable at all. It gives nothing on Mac OS X. The output of `ifconfig` does not contain the text `HWaddr`.
dreamlax
It is very portable. It runs on Ubuntu and Kubuntu... ;-)
EricSchaefer
Had to do this earlier in the year on solaris, linux and hpux.
Matt H
Well, the concept is portable. The text may need tweaking for other platforms.
Matt H
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
Also, this isn't going to compile in any C compiler I know of.
BobbyShaftoe
+5  A: 
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <netdb.h>
#include <stdio.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;
}
Employed Russian
+5  A: 

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 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/".

+1 for useful answer
Chris Huang-Leaver