Ich arbeite an Ubuntu. Wie kann ich mit dem C-Programm die MAC-Adresse meines Computers oder eine Schnittstelle wie eth0 ermitteln?
c
linux
mac-address
Bruce
quelle
quelle
Antworten:
Sie müssen alle verfügbaren Schnittstellen auf Ihrem Computer durchlaufen und
ioctl
mitSIOCGIFHWADDR
Flag verwenden, um die Mac-Adresse abzurufen. Die Mac-Adresse wird als 6-Oktett-Binärarray erhalten. Sie möchten auch die Loopback-Schnittstelle überspringen.#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); }
quelle
00:00:00:00:00:00
Viel schöner als all dieser Socket- oder Shell-Wahnsinn ist es, einfach sysfs dafür zu verwenden:
Die Datei enthält
/sys/class/net/eth0/address
Ihre Mac-Adresse als einfache Zeichenfolge, die Sie mitfopen()
/fscanf()
/ lesen könnenfclose()
. Nichts einfacher als das.Und wenn Sie andere Netzwerkschnittstellen als eth0 unterstützen möchten (und dies wahrscheinlich möchten), verwenden Sie einfach
opendir()
/readdir()
/closedir()
on/sys/class/net/
.quelle
Sie möchten einen Blick auf die Handbuchseite von getifaddrs (3) werfen . Es gibt ein Beispiel in C in der Manpage selbst, das Sie verwenden können. Sie möchten die Adresse mit dem Typ erhalten
AF_LINK
.quelle
AF_LINK
nicht beschrieben. Vielleicht wird dies durch ersetztAF_PACKET
?#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; }
quelle
Mit getifaddrs können Sie die MAC-Adresse von der Familie erhalten
AF_PACKET
.Um die MAC-Adresse für jede Schnittstelle anzuzeigen, können Sie wie folgt vorgehen:
#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; }
Ideone
quelle
Ich habe gerade eine geschrieben und teste sie auf 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; }
quelle
Angenommen, C ++ - Code (c ++ 11) ist ebenfalls in Ordnung und die Schnittstelle ist bekannt.
#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)); }
quelle
Verwenden Sie unter Linux den Dienst "Network Manager" über den DBus.
Es gibt auch ein Good'ol- Shell-Programm, das aufgerufen und das Ergebnis erfasst werden kann (verwenden Sie eine Exec- Funktion unter C):
$ /sbin/ifconfig | grep HWaddr
quelle
Eine sehr tragbare Methode besteht darin, die Ausgabe dieses Befehls zu analysieren.
ifconfig | awk '$0 ~ /HWaddr/ { print $5 }'
Vorausgesetzt, ifconfig kann als aktueller Benutzer ausgeführt werden (normalerweise) und awk ist installiert (häufig). Dadurch erhalten Sie die Mac-Adresse des Geräts.
quelle
ifconfig
enthält keinen TextHWaddr
.Erweiterung der Antwort von @ user175104 ...
std::vector<std::string> GetAllFiles(const std::string& folder, bool recursive = false) { // uses opendir, readdir, and struct dirent. // left as an exercise to the reader, as it isn't the point of this OP and answer. } bool ReadFileContents(const std::string& folder, const std::string& fname, std::string& contents) { // uses ifstream to read entire contents // left as an exercise to the reader, as it isn't the point of this OP and answer. } std::vector<std::string> GetAllMacAddresses() { std::vector<std::string> macs; std::string address; // from: /programming/9034575/c-c-linux-mac-address-of-all-interfaces // ... just read /sys/class/net/eth0/address // NOTE: there may be more than one: /sys/class/net/*/address // (1) so walk /sys/class/net/* to find the names to read the address of. std::vector<std::string> nets = GetAllFiles("/sys/class/net/", false); for (auto it = nets.begin(); it != nets.end(); ++it) { // we don't care about the local loopback interface if (0 == strcmp((*it).substr(-3).c_str(), "/lo")) continue; address.clear(); if (ReadFileContents(*it, "address", address)) { if (!address.empty()) { macs.push_back(address); } } } return macs; }
quelle
Netlink Socket ist möglich
Mann
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; }
Beispiel
#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
quelle
Dies ist eine Bash-Zeile, die alle verfügbaren Mac-Adressen mit Ausnahme des Loopbacks druckt:
for x in `ls /sys/class/net |grep -v lo`; do cat /sys/class/net/$x/address; done
Kann von einem C-Programm ausgeführt werden.
quelle