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

时间:2024-03-09 21:09:52

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

#ifndef _MYLIB_H
#define _MYLIB_H
#include <stdlib.h>
#include <errno.h>
 
#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 <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <ifaddrs.h>
#include <net/ethernet.h>
#include <stdio.h>
#include <stdlib.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
 
#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;
}