Hello! 欢迎来到小浪云!


Linux下C语言操作网卡的几个代码实例!特别实用


avatar
小浪云 2025-01-03 18

下面是对原文的重新表述,重点在于如何用c语言直接操作网络接口,例如读写ip地址和mac地址。

如何使用c语言直接操作网络接口

在这篇文章中,我们将讨论如何在C语言中直接操作网络接口。这包括读取和修改IP地址、MAC地址等信息。

1. 基本原理

我们可以通过使用系统提供的socket()和ioctl()函数来实现这些操作。这些函数允许我们与网络接口进行直接的交互,从而获取和设置与网络有关的各种参数。

你可以通过使用这些C语言函数来控制和管理当前系统上的网络接口。通过这两种系统调用,我们可以轻松实现网络接口的操作和管理。

int socket(int domain, int type, int protocol); 功能:     创建套接字 参数:  domain:    Name                Purpose                          Man page   AF_UNIX, AF_LOCAL   Local communication              unix(7)   AF_INET             IPv4 Internet protocols          ip(7)   type:   SOCK_STREAM     Provides sequenced, reliable, two-way, connection-based                       byte  streams.  An out-of-band data transmission mecha‐                       nism may be supported.       SOCK_DGRAM      Supports datagrams (connectionless, unreliable messages                       of a fixed maximum length).  protocol:   通常为0 返回值:  成功:新的套接字的文件描述符  失败:错误码,负值 int ioctl(int fd, unsigned long request, ...); 参数:    fd :文件描述符    request:命令    ... :参数 

其中网络用到的request定义头文件位于:

立即学习C语言免费学习笔记(深入)”;

/usr/include/Linux/sockios.h /* Linux-specific socket ioctls */ #define SIOCINQ  FIONREAD #define SIOCOUTQ TIOCOUTQ        /* output queue size (not sent + not acked) */  /* Routing table calls. */ #define SIOCADDRT 0x890B  /* add routing table entry */ #define SIOCDELRT 0x890C  /* delete routing table entry */ #define SIOCRTMSG 0x890D  /* call to routing system */  /* Socket configuration controls. */ #define SIOCGIFNAME 0x8910  /* get iface name  */ #define SIOCSIFLINK 0x8911  /* set iface channel  */ #define SIOCGIFCONF 0x8912  /* get iface list  */ #define SIOCGIFFLAGS 0x8913  /* get flags   */ #define SIOCSIFFLAGS 0x8914  /* set flags   */ #define SIOCGIFADDR 0x8915  /* get PA address  */ #define SIOCSIFADDR 0x8916  /* set PA address  */ #define SIOCGIFDSTADDR 0x8917  /* get remote PA address */ #define SIOCSIFDSTADDR 0x8918  /* set remote PA address */ #define SIOCGIFBRDADDR 0x8919  /* get broadcast PA address */ #define SIOCSIFBRDADDR 0x891a  /* set broadcast PA address */ #define SIOCGIFNETMASK 0x891b  /* get network PA mask  */ #define SIOCSIFNETMASK 0x891c  /* set network PA mask  */ #define SIOCGIFMETRIC 0x891d  /* get metric   */ #define SIOCSIFMETRIC 0x891e  /* set metric   */ #define SIOCGIFMEM 0x891f  /* get memory address (BSD) */ #define SIOCSIFMEM 0x8920  /* set memory address (BSD) */ #define SIOCGIFMTU 0x8921  /* get MTU size   */ #define SIOCSIFMTU 0x8922  /* set MTU size   */ #define SIOCSIFNAME 0x8923  /* set interface name */ #define SIOCSIFHWADDR 0x8924  /* set hardware address  */ #define SIOCGIFENCAP 0x8925  /* get/set encapsulations       */ #define SIOCSIFENCAP 0x8926   #define SIOCGIFHWADDR 0x8927  /* Get hardware address  */ #define SIOCGIFSLAVE 0x8929  /* Driver slaving support */ #define SIOCSIFSLAVE 0x8930 #define SIOCADDMULTI 0x8931  /* Multicast address lists */ #define SIOCDELMULTI 0x8932 #define SIOCGIFINDEX 0x8933  /* name -> if_index mapping */ #define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */ #define SIOCSIFPFLAGS 0x8934  /* set/get extended flags set */ #define SIOCGIFPFLAGS 0x8935 #define SIOCDIFADDR 0x8936  /* delete PA address  */ #define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */ #define SIOCGIFCOUNT 0x8938  /* get number of devices */ …… 

其中ioctl的参数需要借助结构体struct ifreq, 定义头文件:

/usr/include/linux/if.h #if __UAPI_DEF_IF_IFREQ Struct ifreq { #define IFHWADDRLEN 6  union  {   char ifrn_name[IFNAMSIZ];  /* if name, e.g. "en0" */  } ifr_ifrn;    union {   struct sockaddr ifru_addr;   struct sockaddr ifru_dstaddr;   struct sockaddr ifru_broadaddr;   struct sockaddr ifru_netmask;   struct  sockaddr ifru_hwaddr;   short ifru_flags;   int ifru_ivalue;   int ifru_mtu;   struct  ifmap ifru_map;   char ifru_slave[IFNAMSIZ]; /* Just fits the size */   char ifru_newname[IFNAMSIZ];   void * ifru_data;   struct if_settings ifru_settings;  } ifr_ifru; }; #endif /* __UAPI_DEF_IF_IFREQ */  #define ifr_name ifr_ifrn.ifrn_name /* interface name  */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address   */ #define ifr_addr ifr_ifru.ifru_addr /* address  */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ #define ifr_flags ifr_ifru.ifru_flags /* flags  */ #define ifr_metric ifr_ifru.ifru_ivalue /* metric  */ #define ifr_mtu  ifr_ifru.ifru_mtu /* mtu   */ #define ifr_map  ifr_ifru.ifru_map /* device map  */ #define ifr_slave ifr_ifru.ifru_slave /* slave device  */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ #define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ #define ifr_bandwidth ifr_ifru.ifru_ivalue    /* link bandwidth */ #define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length  */ #define ifr_newname ifr_ifru.ifru_newname /* New name  */ #define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/ 

二、函数实现

下面将实现不同功能的函数一一列举。

1. 获取本机网卡IP

int getLocalIp(const char *eth, char *ip) {     struct ifreq ifr;     struct sockaddr_in sin;     int fd;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);     if (ioctl(fd, SIOCGIFADDR, &ifr) return -1;     }     memcpy(&sin, &ifr.ifr_addr, sizeof(sin));     snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));     close(fd);     return 0; } 

2. 设置本网卡IP地址

int setIpAddrManual(const char *eth, char *ipstr) {     int fd;     struct sockaddr_in sin;     struct ifreq ifr;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);   sin.sin_addr.s_addr = inet_addr(ipstr);    sin.sin_family = AF_INET;     memcpy(&ifr.ifr_addr, &sin, sizeof(sin));       if (ioctl(fd, SIOCSIFADDR, &ifr) "");         close(fd);         return -1;     }     close(fd);     return 0; }  

3. 获取本机网卡Mac地址

int getLocalMac(const char *eth, char *mac) {       int fd;     struct ifreq ifr;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);     if (ioctl(fd, SIOCGIFHWADDR, &ifr) return -1;     }    snprintf(mac,18, "%02x:%02x:%02x:%02x:%02x:%02x",          (unsigned char) ifr.ifr_hwaddr.sa_data[0],          (unsigned char) ifr.ifr_hwaddr.sa_data[1],          (unsigned char) ifr.ifr_hwaddr.sa_data[2],          (unsigned char) ifr.ifr_hwaddr.sa_data[3],          (unsigned char) ifr.ifr_hwaddr.sa_data[4],          (unsigned char) ifr.ifr_hwaddr.sa_data[5]);     close(fd);     return 0;  }  

4. 设置网卡mac地址

/* support format [00:11:22:33:44:55] */ #define MAC_ARRAY(mac_array)  (unsigned int *)&mac_array[0],(unsigned int *)&mac_array[1],(unsigned int *)&mac_array[2],(unsigned int *)&mac_array[3],(unsigned int *)&mac_array[4],(unsigned int *)&mac_array[5]  int setLocalMac(const char *eth, char *mac) {     int fd;     struct ifreq ifr;  unsigned char mac_array[6] = {0};       bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);  ifr.ifr_hwaddr.sa_family = AF_LOCAL;    sscanf(mac,"%02x:%02x:%02x:%02x:%02x:%02x",   MAC_ARRAY(mac_array));   memcpy(ifr.ifr_hwaddr.sa_data,mac_array,6);      if (ioctl(fd, SIOCSIFHWADDR, &ifr) "SIOCSIFHWADDR:");         close(fd);         return -1;     }      close(fd);     return 0; }  

注意:

  • 网卡地址的第一字节必须是偶数
  • sa_family 值必须为:AF_LOCAL

5. 获取网卡mtu

int getMtu(const char *eth, char *mtu) {     int fd;     struct ifreq ifr;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);     if (ioctl(fd, SIOCGIFMTU, &ifr) return -1;     }      snprintf(mtu,64, "%d", (unsigned char) ifr.ifr_mtu);     close(fd);     return 0; }  

6. 获取广播地址

int getBroadAddr(const char *eth, char *ip) {     int fd;     struct sockaddr_in sin;     struct ifreq ifr;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);     if (ioctl(fd, SIOCGIFBRDADDR, &ifr) "");         close(fd);         return -1;     }     memcpy(&sin, &ifr.ifr_broadaddr, sizeof(sin));     snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));      close(fd);     return 0; }  

7. 获取掩码

int getNetMask(const char *eth, char *mask) {     int fd;     struct sockaddr_in sin;     struct ifreq ifr;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);     if (ioctl(fd, SIOCGIFNETMASK, &ifr) "");         close(fd);         return -1;     }     memcpy(&sin, &ifr.ifr_netmask, sizeof(sin));     snprintf(mask, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));      close(fd);     return 0; } 

8. 获取网卡flag

int getFlags(const char *eth, char *fg) {     int fd;     struct sockaddr_in sin;     struct ifreq ifr;     bzero(&ifr, sizeof(ifr));     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) return -1;     }     strcpy(ifr.ifr_name, eth);     if (ioctl(fd, SIOCGIFFLAGS, &ifr) "");         close(fd);         return -1;     }  snprintf(fg, IP_SIZE, "%x", ifr.ifr_flags);      close(fd);     return 0; }  

三、测试

1. 测试程序

int main(int argc, char **argv) {  int fg=0;  char mac[32]={};  char ip[IP_SIZE]={0};  char buf[64];    getBroadAddr(ethname,ip);  printf("broad ip:	%s ",ip);   getNetMask(ethname,ip);  printf("mask:	%s ",ip);    setIpAddrManual(ethname, "1.1.1.1");  getLocalIp(ethname,ip);  printf("ip:	%s ",ip);    setLocalMac(ethname,"00:11:22:33:44:55");  getLocalMac(ethname,mac);  printf("mac:	%s ",mac);   getMtu(ethname,buf);  printf("mtu:	%s ",buf);    return 1; } 

2. 执行结果

Linux下C语言操作网卡的几个代码实例!特别实用

执行后结果:

peng@ubuntu:~/work/test/ip$ ifconfig  eth0      Link encap:Ethernet  HWaddr 00:11:22:33:44:55             inet addr:1.1.1.1  Bcast:1.255.255.255  Mask:255.0.0.0           inet6 addr: fe80::d9d4:d42b:a04a:9d40/64 Scope:Link           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1           RX packets:188577 errors:0 dropped:0 overruns:0 frame:0           TX packets:208116 errors:0 dropped:0 overruns:0 carrier:0           collisions:0 txqueuelen:1000            RX bytes:53762370 (53.7 MB)  TX bytes:172094089 (172.0 MB) 

完整代码,后天回复:eth

相关阅读