web-dev-qa-db-fra.com

Comment obtenir l'adresse MAC de votre machine en utilisant un programme C?

Je travaille sur Ubuntu. Comment puis-je obtenir l'adresse MAC de ma machine ou une interface dire eth0 en utilisant le programme C.

61
Bruce

Vous devez parcourir toutes les interfaces disponibles sur votre ordinateur et utiliser ioctl avec SIOCGIFHWADDR pour obtenir l'adresse mac. L'adresse mac sera obtenue sous la forme d'un tableau binaire de 6 octets. Vous souhaitez également ignorer l'interface de bouclage.

#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);
}
51
Charles Salvia

Beaucoup plus agréable que tout ce socket ou folie de Shell utilise simplement sysfs pour cela:

le fichier /sys/class/net/eth0/address porte votre adresse mac sous forme de chaîne simple que vous pouvez lire avec fopen()/fscanf()/fclose(). Rien de plus facile que ça.

Et si vous souhaitez prendre en charge d’autres interfaces réseau que eth0 (et vous le souhaitez probablement), utilisez simplement opendir()/readdir()/closedir() sur /sys/class/net/.

125
user175104

Vous voulez jeter un oeil à la page de manuel getifaddrs (3) . Vous pouvez utiliser un exemple en C dans la page de manuel elle-même. Vous voulez obtenir l'adresse avec le type AF_LINK.

24
Juliano
#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;
}
17
Employed Russian

Je viens d’en écrire un et de le tester sur gentoo dans la 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;
}
8
Akagi201

En utilisant getifaddrs vous pouvez obtenir l’adresse MAC de la famille AF_PACKET

Afin d’afficher l’adresse MAC sur chaque interface, vous pouvez procéder comme suit:

#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;
}
7
mpromonet

En supposant que le code c ++ (c ++ 11) est également correct et que l'interface est connue.

#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=%016lX\n", iface.c_str(), getIFMAC(iface));
}
2
Lincoln
  1. Sous Linux, utilisez le service "Network Manager" sur le DBus.

  2. Il existe également un programme good'ol Shell pouvant être appelé et le résultat saisi (utilisez un exec fonction sous C):

$ /sbin/ifconfig | grep HWaddr

1
jldupont

Une méthode très portable consiste à analyser la sortie de cette commande.

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

Ifconfig peut être exécuté en tant qu'utilisateur actuel (généralement possible) et awk est installé (c'est souvent le cas). Cela vous donnera l'adresse mac de la machine.

0
Matt

Ceci est une ligne Bash qui imprime toutes les adresses Mac disponibles, à l'exception du bouclage:

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

Peut être exécuté à partir d'un programme C.

0
Lacho Tomov