1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 网络ioctl实践3:设置网卡的mac ip 子网掩码 广播地址

网络ioctl实践3:设置网卡的mac ip 子网掩码 广播地址

时间:2022-04-14 19:03:52

相关推荐

网络ioctl实践3:设置网卡的mac ip 子网掩码 广播地址

前言

网络ioctl实践1:获取网卡的MAC和IP

网络ioctl实践2:获取网卡的广播地址和子网掩码

本文使用的命令是:

struct ifreq结构体定义:

#defineIFNAMSIZ16struct ifreq {#define IFHWADDRLEN6union{charifrn_name[IFNAMSIZ];/* if name, e.g. "en0" */} ifr_ifrn;union {structsockaddr ifru_addr;structsockaddr ifru_dstaddr;structsockaddr ifru_broadaddr;structsockaddr ifru_netmask;struct sockaddr ifru_hwaddr;shortifru_flags;intifru_ivalue;intifru_mtu;struct ifmap ifru_map;charifru_slave[IFNAMSIZ];/* Just fits the size */charifru_newname[IFNAMSIZ];void __user *ifru_data;structif_settings ifru_settings;} ifr_ifru;}

一 设置MAC地址:SIOCSIFHWADDR命令

设置mac地址,首先要构造一个struct ifreq类型。例如,初始化网络接口的名字,例如ens33或者eth0,还有设置新的mac地址值。通过ifru_hwaddr成员设置,如下所示:

int i = 0;uint8_t mac[6] = {0x00,0x0c,0x29,0x8c,0x05,0x15};struct ifreq ifr;snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 6;i++){ifr.ifr_ifru.ifru_hwaddr.sa_data[i] = mac[i];}

这里介绍一系列宏:如下所示

#define ifr_nameifr_ifrn.ifrn_name/* interface name */#define ifr_hwaddrifr_ifru.ifru_hwaddr/* MAC address */#defineifr_addrifr_ifru.ifru_addr/* address*/#defineifr_dstaddrifr_ifru.ifru_dstaddr/* other end of p-p lnk*/#defineifr_broadaddrifr_ifru.ifru_broadaddr/* broadcast address*/#defineifr_netmaskifr_ifru.ifru_netmask/* interface net mask*/#defineifr_flagsifr_ifru.ifru_flags/* flags*/#defineifr_metricifr_ifru.ifru_ivalue/* metric*/#defineifr_mtuifr_ifru.ifru_mtu/* mtu*/#define ifr_mapifr_ifru.ifru_map/* device map*/#define ifr_slaveifr_ifru.ifru_slave/* slave device*/#defineifr_dataifr_ifru.ifru_data/* for use by interface*/#define ifr_ifindexifr_ifru.ifru_ivalue/* interface index*/#define ifr_bandwidthifr_ifru.ifru_ivalue /* link bandwidth*/#define ifr_qlenifr_ifru.ifru_ivalue/* Queue length */#define ifr_newnameifr_ifru.ifru_newname/* New name*/#define ifr_settingsifr_ifru.ifru_settings/* Device/proto settings*/

看到这里有没有解决你的一个困惑?我们在书本上看到的是ifr_hwaddr 而不是ifr_ifru.ifru_hwaddr,实际上ifr_hwaddr只是一个宏,厉害吧。

然后就是通过ioctl函数设置该新的MAC地址:

ioctl(fd,SIOCSIFHWADDR,&ifr);

完整实例:ioctl.c

#include <stdio.h>#include <stdint.h>#include <unistd.h>#include <sys/types.h>#include <net/if.h>#include <sys/ioctl.h>#include <stdlib.h>int get_socket(void){int fd = socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}return fd;}int set_mac_by_name(int fd,char *name){struct ifreq ifr;int i = 0;uint8_t mac[6] = {0x00,0x0c,0x29,0x8c,0x05,0x16};snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 6;i++){ifr.ifr_ifru.ifru_hwaddr.sa_data[i] = mac[i];}if(i = ioctl(fd,SIOCSIFHWADDR,&ifr)){perror("ioctl");close(fd);exit(-1);}}int main(int argc,char *argv){int fd = 0;fd = get_socket();set_mac_by_name(fd,"ens33");return 0;}

编译gcc ioctl.c -o app,运行./app,结果如下所示:

root@ubuntu:/home/csdn# ./appioctl: Invalid argumentroot@ubuntu:/home/csdn#

报错了,后上网查询得知,需要设置sa_family成员为ARPHRD_ETHER,并添加宏ARPHRD_ETHER的头文件:

#include<net/if_arp.h>... ...ifr.ifr_ifru.ifru_addr.sa_family = ARPHRD_ETHER;... ...

修改函数set_mac_by_name:

#include<net/if_arp.h>int set_mac_by_name(int fd,char *name){struct ifreq ifr;int i = 0;uint8_t mac[6] = {0x00,0x0c,0x29,0x8c,0x05,0x16};ifr.ifr_ifru.ifru_addr.sa_family = ARPHRD_ETHER;snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 6;i++){ifr.ifr_ifru.ifru_hwaddr.sa_data[i] = mac[i];}if(i = ioctl(fd,SIOCSIFHWADDR,&ifr)){perror("ioctl");close(fd);exit(-1);}}

编译gcc ioctl.c -o app,运行./app,结果如下所示:设置之前,mac地址最后一个数是16,设置完毕后,最后一个数变成了15。

root@ubuntu:/home/csdn# ifconfig | sed -n '/ens33/p'ens33Link encap:以太网 硬件地址 00:0c:29:8c:05:16root@ubuntu:/home/csdn# ./approot@ubuntu:/home/csdn# ifconfig | sed -n '/ens33/p'ens33Link encap:以太网 硬件地址 00:0c:29:8c:05:15root@ubuntu:/home/csdn#

二设置IP地址:SIOCSIFADDR命令

根据设置mac地址的经验,首先设置名字ens33,然后ifru_addr.sa_data[2-5]四个值,设置新的IP地址是192.168.0.234.还要设置ifru_addr.sa_family = AF_INET,否则设置会失败。

int i = 0;uint8_t ip[6] = {192,168,0,234};struct ifreq ifr;ifr.ifr_ifru.ifru_addr.sa_family = AF_INET;snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 4;i++){ifr.ifr_ifru.ifru_addr.sa_data[2 + i] = ip[i];}

实例代码:ioctl.c

#include <stdio.h>#include <stdint.h>#include <unistd.h>#include <sys/types.h>#include <net/if.h>#include <sys/ioctl.h>#include <stdlib.h>int get_socket(void){int fd = socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}return fd;}int set_ip_by_name(int fd,char *name){struct ifreq ifr;int i = 0;uint8_t ip[6] = {192,168,0,234};ifr.ifr_ifru.ifru_addr.sa_family = AF_INET;snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 4;i++){ifr.ifr_ifru.ifru_addr.sa_data[2 + i] = ip[i];}if(i = ioctl(fd,SIOCSIFADDR,&ifr)){perror("ioctl");close(fd);exit(-1);}}int main(int argc,char *argv){int fd = 0;fd = get_socket();set_ip_by_name(fd,"ens33");return 0;}

编译gcc ioctl.c -o app,运行./app,结果如下图所示:设置之前,ip地址是192.168.0.11,设置完毕后,IP地址变成了192.168.0.234。

三 设置子网掩码和广播地址

原理和设置ip地址一样,不同的是命令改为SIOCSIFNETMASK和SIOCSIFBRDADDR ,成员赋值改为ifru_netmask和ifru_broadaddr。

测试代码:

#include <stdio.h>#include <stdint.h>#include <unistd.h>#include <sys/types.h>#include <net/if.h>#include <sys/ioctl.h>#include <stdlib.h>#include <net/if_arp.h>int get_socket(void){int fd = socket(AF_INET,SOCK_DGRAM,0);if(fd < 0){perror("socket");exit(-1);}return fd;}int set_netmask_by_name(int fd,char *name){struct ifreq ifr;int i = 0;uint8_t ip[6] = {255,255,255,0};ifr.ifr_ifru.ifru_addr.sa_family = AF_INET;snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 4;i++){ifr.ifr_ifru.ifru_netmask.sa_data[2 + i] = ip[i];}if(i = ioctl(fd,SIOCSIFNETMASK,&ifr)){perror("ioctl");close(fd);exit(-1);}return 0;}int set_broadcast_by_name(int fd,char *name){struct ifreq ifr;int i = 0;uint8_t ip[6] = {192,168,0,255};ifr.ifr_ifru.ifru_addr.sa_family = AF_INET;snprintf(ifr.ifr_ifrn.ifrn_name,sizeof(ifr.ifr_ifrn.ifrn_name),"%s",name);for(i = 0;i < 4;i++){ifr.ifr_ifru.ifru_broadaddr.sa_data[2 + i] = ip[i];}if(i = ioctl(fd,SIOCSIFBRDADDR,&ifr)){perror("ioctl");close(fd);exit(-1);}return 0;}int main(int argc,char *argv){int fd = 0;fd = get_socket();set_netmask_by_name(fd,"ens33");set_broadcast_by_name(fd,"ens33");return 0;}

编译gcc ioctl.c -o app,运行./app,结果如下图所示:设置之前,广播地址是255.255.255.255,设置完毕后,广播地址变成了192.168.0.255。子网掩码设置前后分别是255.255.0.0和255.255.255.0。测试很成功

root@ubuntu:/home/csdn# gcc ioctl.c -o approot@ubuntu:/home/csdn# ifconfig | sed -n '/ens33/,+1p'ens33Link encap:以太网 硬件地址 00:0c:29:8c:05:15inet 地址:192.168.0.11 广播:255.255.255.255 掩码:255.255.0.0root@ubuntu:/home/csdn# ./approot@ubuntu:/home/csdn# ifconfig | sed -n '/ens33/,+1p'ens33Link encap:以太网 硬件地址 00:0c:29:8c:05:15inet 地址:192.168.0.11 广播:192.168.0.255 掩码:255.255.255.0root@ubuntu:/home/csdn#

小结

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。