wiki:ネットワークのハードウエアアドレスを取得する

Version 1 (modified by admin, 7 years ago) ( diff )

--

ネットワークのハードウエアアドレスを取得する

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#if defined(SIOCGARP)
# include <net/if_arp.h>
#endif

#if defined __linux__
# define HAVE_INET_NTOP 1
#elif defined __CYGWIN__
# define HAVE_INET_NTOP 1
#else
# define HAVE_INET_NTOP 1
# define HAVE_SOCKADDR_SA_LEN 1
#endif


static
const char *
my_sockaddr_in_ntop(const struct sockaddr_in *sin)
{
#if HAVE_INET_NTOP
  static char buf[INET6_ADDRSTRLEN];
  return inet_ntop(sin->sin_family, &(sin->sin_addr), buf, sizeof(buf));
#else
  return inet_ntoa(sin->sin_addr);
#endif
}

static
const char *
#if defined(SIOCGIFHWADDR)
my_inet_ntop_mac(const struct ifreq *ifr)  /* linux & cygwin */
{
  const unsigned char *p = (const unsigned char *)ifr->ifr_hwaddr.sa_data;
#elif defined(SIOCGARP)
my_inet_ntop_mac(const struct arpreq *arp)
{
  const unsigned char *p = (const unsigned char *)arp->arp_ha.sa_data;
#else
# error not supported...
#endif
  static char buf[65];
  
  sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
                p[0],p[1],p[2],p[3],p[4],p[5]
         );
  return buf;
}


int
main(void)
{
  char  buf[16384];
  struct ifconf ifc;
  int i, numnic, fd;
  int rc;
  
  fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd == -1) {
    fprintf(stderr, "socket err\n");
    exit(1);
  }
  memset(buf, 0, sizeof(buf));
  memset(&ifc, 0, sizeof(ifc));
  ifc.ifc_req = (struct ifreq *)buf;
  ifc.ifc_len = sizeof(buf);
  errno = 0;
  rc = ioctl(fd, SIOCGIFCONF, &ifc);
  if (rc == -1 || errno == EINVAL) {
    fprintf(stderr, "ioctl SIOCGIFCONF err\n");
    exit(1);
  }
  
  for(i=0, numnic=0; i<ifc.ifc_len; ) {
    struct ifreq  *ifr;
#if defined(SIOCGIFHWADDR)
    struct ifreq req;
#elif defined(SIOCGARP)
    struct arpreq req;
#endif
    
    ifr = (struct ifreq *)(buf + i);
    switch (ifr->ifr_addr.sa_family) {
      case AF_INET:
        printf("%3d \"%s\" ", numnic, ifr->ifr_name);
        printf("AF_INET %s", my_sockaddr_in_ntop((struct sockaddr_in *)&ifr->ifr_addr));
#if defined(SIOCGIFHWADDR)
        memcpy(&req, ifr, sizeof(req));
        rc = ioctl(fd, SIOCGIFHWADDR, &req);  /* linux */
#elif defined(SIOCGARP)
        memset(&req, 0, sizeof(req));
        memcpy(&req.arp_pa, &ifr->ifr_addr, sizeof(struct sockaddr_in));
        rc = ioctl(fd, SIOCGARP, &req);
#else
# error not supported...
#endif
        if (rc >= 0) {
          printf("  %s", my_inet_ntop_mac(&req));
        }
        printf("\n");
        break;
    default:
        printf("%3d \"%s\" family=%d\n", numnic, ifr->ifr_name, ifr->ifr_addr.sa_family);
      break;
    }
    ++numnic;
#if HAVE_SOCKADDR_SA_LEN
    i += ifr->ifr_addr.sa_len <= sizeof(struct sockaddr) ?
      sizeof(struct ifreq) :
      sizeof(struct ifreq) - sizeof(struct sockaddr) + ifr->ifr_addr.sa_len;
#else
    i += sizeof(struct ifreq);
#endif
  }
  
  return 0;
}

Note: See TracWiki for help on using the wiki.