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

本文使用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;
}

时间: 2024-10-08 04:51:15

linux 下C实现获取网卡IP和MAC地址的相关文章

linux 直接通过命令获取到IP,mac等

//通过命令获取mac地址 ifconfig eth0 |grep HWaddr | awk'{print $5}' //获取IP地址 ifconfig eth0 | grep Bcast | awk '{print $2}' | awk -F ':' '{print $2}'

C#获取局域网IP、MAC地址和端口的初学

首先非常感谢Melou的http://www.cnblogs.com/luoht/archive/2009/12/18/1627431.html的随笔,对于初学C#的我,参考你的随笔对我的学习真是有莫大帮助. C#遍历局域网的几种方法: 1.微软社区上介绍了使用Active Directory 来遍历局域网 首先我们来了解DirectoryEntry类是一个什么类. 命名空间:  System.DirectoryServices程序集:  System.DirectoryServices(在 S

java 获取访问者ip和mac地址

获取访问者ip,代码: <% String sip=""; try{ sip = (String)request.getRemoteAddr(); }catch(Exception e){ } %> 获取访问者mac地址,法是用UDP协议来发送查询mac指令然后返回值中解析mac.代码 <% String smac = ""; String sip = request.getHeader("x-forwarded-for");

LINUX下QT与C语言通过网卡名获取网卡IP与MAC

1.QT下 QString RuntimeConfig::ipAddress(QString network) { QList<QNetworkAddressEntry> list; QString localIPaddress; QNetworkInterface interface = QNetworkInterface::interfaceFromName(network); list = interface.addressEntries(); if (!list.isEmpty())

(转)LINUX下Live555不能获取ip地址解决方法

linux下运行live55 显 示如图 :没有获取ip:  ip是0.0.0.0 live555在不知道本地IP地址与网络接口的情况下,通过一个在本地某端口建立一个UDP连接,然后把这个UDP连接加入 到一个组播组 ,当然要对这个组播组进行相应的设置,比如TTL,回环等等:然后通过UDP连接发送一个数据:最后通过这个UDP连接接收这个数据,并且解析相应的发送地址:大概流程就是这样了. 具体的代码片段live555:groupsock/GroupsockHelper.cpp里:因此我们设置固定的

windows和linux下如何远程获取操作系统版本和主机名

远程获取windows和linux操作系统版本和主机名需要具备以下条件: 假设 主机A(windows 7),ip:192.168.12.2 主机B(centos 6.3),ip:192.168.12.3 主机C(windows 2008)-为远程要获取信息的主机,ip:192.168.12.4 主机D(centos 6.3)-为远程要获取信息的主机,ip:192.168.12.5 windows: 1.主机A可以ping通主机C: 2.主机B可以ping通主机C: 3.主机B可以通过161端口

linux下设置电信网通双线路IP地址

工作上遇到需要在linux下设置电信网通双线路IP地址,操作系统为Suse Linux Enterprise Linux 11 SP2,简要记录下步骤: 编辑/etc/sysconfig/network/ifcfg-eth0, /etc/sysconfig/network/ifcfg-eth1, 设置两个网卡的IP地址,eth0为电信的,eth1为网通的 BOOTPROTO='static' BROADCAST='' ETHTOOL_OPTIONS='' IPADDR='${telecomip}

Linux下用C获取当前时间

Linux下用C获取当前时间,具体如下: 代码(可以把clock_gettime换成time(NULL)) ? 1 2 3 4 5 6 7 8 9 10 void getNowTime() {  timespec time;  clock_gettime(CLOCK_REALTIME, &time); //获取相对于1970到现在的秒数  tm nowTime;  localtime_r(&time.tv_sec, &nowtime);  char current[1024];  

win/linux 下使用 psutil 获取进程 CPU / memory / IO 占用信息

psutil - A cross-platform process and system utilities module for Python 1. 安装 pip 安装即可. windows 下需要安装 vs2008,否则报错: Unable to find vcvarsall.bat 如果已经安装 vs2010 / vs2012 则需要设置环境变量,VS90COMNTOOLS 指向已有的 vs 变量. vs2010 设置如下: VS90COMNTOOLS = %VS100COMNTOOLS%