Ermitteln der Mac-Adresse

Post Reply
Message
Author
bifi

Ermitteln der Mac-Adresse

#1 Post by bifi »

Moin,

ich muss in meinem Programm die MAC-Adressen aller Netzwerkkarten ermitteln. Dabei möchte ich eine saubere Lösung, die nicht über Kommandozeilen-Tools geht und mittels grep/awk/... die MAC raussucht. Wichtig ist dabei, dass keine Loop-Devices berücksichtigt werden.

Könnte mir jemand einen kleinen Denkanstoß geben?


MfG
bfeater

arp

#2 Post by arp »

arp -a

bifi

#3 Post by bifi »

Hi!

Genau so eine Lösung wollte ich nicht. Wie das Forum schon aussagt, möchte ich das in C programmieren. Und ich möchte nicht Kommandozeilentools aufrufen und dann in der Ausgabe rum-grepen/-awken/...!

MfG
bfeater

google

#4 Post by google »


klopskuchen
prolinux-forum-admin
Posts: 1444
Joined: 26. Jun 2004 21:18
Contact:

#5 Post by klopskuchen »

In irgend einer Kernelheaderdatei wird wohl eine Struktur herumschwirren. Da du *alle* Adressen haben möchtest, ist es am einfachsten den Descriptor des Kernels zu benutzen der auf eine Liste *aller* Adressen zeigt:

Code: Select all

FILE *fp;
char *dat = "/proc/net/arp";

if ( (fp = fopen( dat, "r" )) != NULL ){
	hier dein code;
	fclose(fp);
}

MfG, Klopskuchen
When all else fails, read the instructions .

demon
Pro-Linux
Posts: 389
Joined: 24. Nov 1999 0:05
Location: Wörth am Rhein
Contact:

#6 Post by demon »

Hallo,

Da ich nichts besseres während meiner Mittagspause zu tun hatte, hier ein Beispiel für das erste Interface. Loopback wird uebersprungen und die Were im char addr gespeichert:

Code: Select all

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>

int main&#40; int argc, char **argv&#41;
&#123;
    struct ifreq ifr;
    struct ifreq *IFR;
    struct ifconf ifc;
    char buf&#91;1024&#93;;
    u_char addr&#91;6&#93;;
    int sk, i;

    /* getit */
    sk = socket&#40;AF_INET, SOCK_DGRAM, 0&#41;;
    ifc.ifc_len = sizeof&#40;buf&#41;;
    ifc.ifc_buf = buf;
    ioctl&#40;sk, SIOCGIFCONF, &ifc&#41;;

    IFR = ifc.ifc_req;
    for &#40;i = ifc.ifc_len / sizeof&#40;struct ifreq&#41;; i-- >= 0; IFR++&#41; &#123;
        strcpy&#40;ifr.ifr_name, IFR->ifr_name&#41;;
        if &#40;ioctl&#40;sk, SIOCGIFFLAGS, &ifr&#41; == 0&#41; &#123;
            if &#40;! &#40;ifr.ifr_flags & IFF_LOOPBACK&#41;&#41; &#123;
                if &#40;ioctl&#40;sk, SIOCGIFHWADDR, &ifr&#41; == 0&#41; &#123;
		    /* OK. Addr complete */
                    break;
                &#125;
            &#125;
        &#125;
    &#125;
    close&#40;sk&#41;;
    bcopy&#40; ifr.ifr_hwaddr.sa_data, addr, 6&#41;;

    /* Output */
    printf&#40; "Out address&#58; "&#41;;
    for &#40;i=0; i<6; i++&#41; &#123;
        printf&#40;"%2.2x", addr&#91;i&#93;&#41;;
    &#125;
    printf&#40; "\n"&#41;;
    return 0;
&#125;
Bitte beachte, dass das Beispiel keine Ueberpruefung der Returnwerte enthaelt. Also auf jeden Fall noch die Values ueberpruefen. Auch sollte bcopy nur gemacht werden, wenn "break" erreicht wurde. Compilieren mit "gcc name.c". Funktioniert auch nur unter Linux.

Gruss,
demon

bifi

#7 Post by bifi »

Danke, aber ich habe schon eine passende Lösung gefunden. Die Funktion testet, ob die übergebene MAC beim aktuellen Rechner vorhanden ist:

Code: Select all

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>

int
test_mac &#40;unsigned char macaddr&#91;6&#93;&#41;
&#123;
  struct ifreq ifRequest;             // request to the interface
  struct if_nameindex* ifTmp  = NULL; // tmp pointer
  struct if_nameindex* ifList = NULL; // list of interfaces
  int fh     = -1;                    // handle for the socket
  int status = 0;
  int result = -1;

  // open socket
  if &#40;status == 0&#41; &#123;
    fh = socket &#40;PF_INET, SOCK_STREAM, 0&#41;;

    if &#40;fh < 0&#41; &#123;
      printf &#40;"File %s, line %d&#58; socket &#40;&#41; failed\n", __FILE__, __LINE__&#41;;
      status = -1;
    &#125;
  &#125;

  // now get a list of all interfaces
  if &#40;status == 0&#41; &#123;
    ifList = if_nameindex &#40;&#41;;
    
    if &#40;!ifList&#41; &#123;
      printf &#40;"File %s, line %d&#58; if_nameindex &#40;&#41; failed\n", __FILE__, __LINE__&#41;;
      status = -1;
    &#125;
  &#125;

  // get mac address of all devices
  if &#40;status == 0&#41; &#123;
    for &#40;ifTmp = ifList; *&#40;char*&#41;ifTmp != 0; ifTmp++&#41; &#123;
      // set request for ioctl and get mac
      strncpy &#40;ifRequest.ifr_name, ifTmp->if_name, IF_NAMESIZE&#41;;
      if &#40;ioctl &#40;fh, SIOCGIFHWADDR, &ifRequest&#41; == -1&#41;
	// error, skip this device
	continue;

      if &#40;&#40;ifRequest.ifr_addr.sa_family != ARPHRD_ETHER&#41; &&
	  &#40;ifRequest.ifr_addr.sa_family != ARPHRD_EETHER&#41;&#41;
	// skip, no ethernet device
	continue;

      // test for valid mac
      if &#40;&#40;ifRequest.ifr_ifru.ifru_hwaddr.sa_data&#91;0&#93; == macaddr&#91;0&#93;&#41; &&
	  &#40;ifRequest.ifr_ifru.ifru_hwaddr.sa_data&#91;1&#93; == macaddr&#91;1&#93;&#41; &&
	  &#40;ifRequest.ifr_ifru.ifru_hwaddr.sa_data&#91;2&#93; == macaddr&#91;2&#93;&#41; &&
	  &#40;ifRequest.ifr_ifru.ifru_hwaddr.sa_data&#91;3&#93; == macaddr&#91;3&#93;&#41; &&
	  &#40;ifRequest.ifr_ifru.ifru_hwaddr.sa_data&#91;4&#93; == macaddr&#91;4&#93;&#41; &&
	  &#40;ifRequest.ifr_ifru.ifru_hwaddr.sa_data&#91;5&#93; == macaddr&#91;5&#93;&#41;&#41; &#123;
	// found
	result = 0;
	break;
      &#125;
    &#125;
  &#125;

  // clean up
  if &#40;fh >= 0&#41;
    close &#40;fh&#41;;
  if &#40;ifList&#41;
    if_freenameindex &#40;ifList&#41;;

  return result;
&#125;

int
main ...

Post Reply