linux 下C实现获取网卡IP和MAC地址

 本文使用getifaddrs 函数获取网卡的IP和MAC地址。getifaddrs函数有个特点,就是获取地址时以链表方式返回,且每个链表节点要么是IP,要么是MAC,所以如果要将网卡的IP和MAC地址同时返回的话,需要对对返回链表进行查找和重新组合。本文实现目的,在于以网卡名方式返回IP和MAC地址。代码如下:

#ifndef _MYLIB_H
#define _MYLIB_H
#include 
#include 

#define error_report(msg) \
	do { perror(msg); \
		exit (EXIT_FAILURE) \
	}while (0)

//clean the stdin cach
void clean_cach (void);

//get a string from stdin
int getstring (char *str, int num);

/* define a get if info struct */
struct if_ipv4_info {
  char if_name[10];;
  unsigned char ip_addr[20];
  unsigned char hd_addr[20];

  struct if_ipv4_info *next;
};
#endif

函数实现

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "mylib.h"

#define DEBUG 0

struct if_ipv4_info *if_info = NULL;

/*
** add ip to a linklist
*/
static int  add_to_link (struct ifaddrs *ifap, char *buf)
{
  struct if_ipv4_info *p, *q;

  if (if_info == NULL) {  
    if_info = malloc (sizeof (struct if_ipv4_info));
    /* init head */
    if_info->next = NULL;
    if_info->ip_addr[0] = '\0';
    if_info->hd_addr[0] = '\0';

    if (if_info == NULL) {
      fprintf (stderr, "malloc failed\n");
      exit (EXIT_FAILURE);
    }
    strcpy (if_info->if_name, ifap->ifa_name);
    switch (ifap->ifa_addr->sa_family) {
      case AF_INET:
        strcpy (if_info->ip_addr, buf);
     //   printf ("head %s", if_info->ip_addr);
        break;
      case AF_PACKET:
        strcpy (if_info->hd_addr, buf);
      //  printf ("head %s", if_info->hd_addr);
        break;
      default:
        break;
    } //switch
  }else {
    for (p = if_info; p != NULL; p = p->next) {
      q = p;
      if (strcmp (p->if_name, ifap->ifa_name) == 0) {
        break;
      }
    }
    if (p != NULL) {
      switch (ifap->ifa_addr->sa_family) {
        case AF_INET:
          strcpy (p->ip_addr, buf);
       //   printf ("p %s\n", p->ip_addr);
          break;
        case AF_PACKET:
          strcpy (p->hd_addr, buf);
        //  printf ("p %s\n", p->hd_addr);
          break;
        default:
          break;
      } //switch
    } else {
      p = malloc (sizeof (struct if_ipv4_info));
      /* init node */
      p->next = NULL;
      p->ip_addr[0] = '\0';
      p->hd_addr[0] = '\0';

      if (p == NULL) {
        fprintf (stderr, "malloc failled");
        exit (EXIT_FAILURE);
      }
      strcpy (p->if_name, ifap->ifa_name);
      switch (ifap->ifa_addr->sa_family) {
        case AF_INET:
          strcpy (p->ip_addr, buf);
         // printf ( "else p %s\n", p->ip_addr);
          break;
        case AF_PACKET:
          strcpy (p->hd_addr, buf);
          //printf ( "else p %s\n", p->hd_addr);
          break;
        default:
          break;
    } 
      q->next = p;
  }//else
  }
  return 0;
}

int prt_if_info (struct sockaddr *ifa_addr, char *addrbuf, int bufsize)
{
  memset (addrbuf, 0, bufsize);
  struct sockaddr_ll *s;
  int i;
  int len;
  int family = ifa_addr->sa_family;

  int ret = 0;

  switch (family) {
    case AF_INET: 
      inet_ntop (ifa_addr->sa_family, &((struct sockaddr_in *)ifa_addr)->sin_addr,
                  addrbuf, sizeof (struct sockaddr_in));
      break;
    case AF_PACKET:
      s = (struct sockaddr_ll *)ifa_addr;
      for (i=0,len=0; i<6; i++) {
        len += sprintf (addrbuf+len, "%02x%s", s->sll_addr[i], i<5?":":" ");
      }
      break;
    default:
      ret = -1;
      break;
  }
    return ret;
}

int get_if_info (void)
{
  struct ifaddrs *ifa, *ifap;
  int family;  /* protocl family */

  if (getifaddrs (&ifa) == -1) {
    perror (" getifaddrs\n");
    exit (EXIT_FAILURE);
  }
  char buf[20];

  for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
    if (strcmp (ifap->ifa_name, "lo") == 0) {
      continue; /* skip the lookback card */
    }

    if (ifap->ifa_addr == NULL)
      continue; /* if addr is NULL, this must be no ip address */

    if (prt_if_info (ifap->ifa_addr, buf, 20) == 0) {
     // printf ("%s: %s\n", ifap->ifa_name, buf);
      add_to_link (ifap, buf);
    }
  }
  
  
  /* printf all of them */
  struct if_ipv4_info *p = NULL;
  for (p = if_info; p != NULL; p = p->next) {
    printf ("%s: %s\t%s\n", p->if_name, strlen(p->ip_addr)>0?p->ip_addr: "No ip addr", p->hd_addr);
  }

  /* free link list */
  struct if_ipv4_info *q = NULL;
  for (p = if_info; p != NULL; ) {
    q = p;
    p = p->next;
    free (q);
  } 
  freeifaddrs (ifa);
  return 0;
}


/*
** test code
*/

int main (int argc, char **argv)
{
  get_if_info ();
   return 0;
}

在gcc version 4.7.2 20121109 (Red Hat 4.7.2-8) (GCC)编译通过,运行效果如下

linux 下C实现获取网卡IP和MAC地址_第1张图片


你可能感兴趣的:(Linux网络)