it-swarm.dev

Jak získat MAC adresu vašeho počítače pomocí programu C?

Pracuji na Ubuntu. Jak mohu získat MAC adresu svého počítače nebo rozhraní say eth0 pomocí programu C.

61
Bruce

Musíte iterovat přes všechna dostupná rozhraní na vašem počítači a použít ioctl s SIOCGIFHWADDR příznakem, abyste získali MAC adresu. Adresa MAC bude získána jako 6-oktetové binární pole. Také chcete přeskočit rozhraní loopback.

#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

Mnohem hezčí než všechno toto pouzdro nebo šílenství Shell jednoduše používá sysfs:

soubor /sys/class/net/eth0/address nese vaši MAC adresu jako jednoduchý řetězec, který můžete číst pomocí fopen()/fscanf()/fclose(). Nic jednoduššího.

A pokud chcete podporovat jiná síťová rozhraní než eth0 (a pravděpodobně budete chtít), pak jednoduše použijte opendir()/readdir()/closedir() na /sys/class/net/.

125
user175104

Chcete se podívat na stránku getifaddrs (3) manual. Existuje příklad v C v samotném manuálu, který můžete použít. Chcete získat adresu s typem 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

Jednu jsem napsal a otestoval na gentoo ve virtualboxu.

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

Pomocí getifaddrs můžete získat MAC adresu z rodiny AF_PACKET

Chcete-li zobrazit adresu MAC pro každé rozhraní, můžete postupovat takto:

#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

Za předpokladu, že kód c ++ (c ++ 11) je také v pořádku a rozhraní je známo.

#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. V Linuxu použijte službu "Network Manager" přes DBus.

  2. Tam je také good'ol Shell program, který může být vyvolán a výsledek popadl (použijte exec funkce pod C):

$ /sbin/ifconfig | grep HWaddr

1
jldupont

Velmi přenosný způsob je analyzovat výstup tohoto příkazu.

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

Pokud je instalováno ifconfig jako aktuální uživatel (obvykle může) a awk je nainstalován (často je). To vám poskytne adresu MAC stroje.

0
Matt

Toto je řádek Bash, který vytiskne všechny dostupné adresy MAC, s výjimkou zpětné smyčky:

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

Lze provést z programu C.

0
Lacho Tomov