linux c ioctl设置获取网关,路由信息
在日常开发中避免不了对本地网络的设置需求,一般情况下我们使用system接口进行临时的IP修改,或者open,rend write,操作/etc/network/interface这样的网络文件实现IP的永久修改,但是这样的修改方式相较来说比较低端。
其实在linux中有一个万能接口:ioctl函数,该函数几乎可以设置linux下的一切状态,接下来我们来了解下ioctl设置网络IP 子网掩码的方式。
我们首先需要了解网络接口结构体: struct ifreq;
#if __UAPI_DEF_IF_IFREQ
struct ifreq {
#define IFHWADDRLEN 6
union
{
char ifrn_name[IFNAMSIZ]; //网卡设备名:eth0,ens33等
} ifr_ifrn;union {
struct sockaddr ifru_addr; //ip地址
struct sockaddr ifru_dstaddr; //目标IP地址
struct sockaddr ifru_broadaddr; //广播地址
struct sockaddr ifru_netmask; //子网掩码
struct sockaddr ifru_hwaddr; //MAC地址
short ifru_flags; //网络接口标记
int ifru_ivalue; //请求不通含义不同
int ifru_mtu; //网卡地址映射
struct ifmap ifru_map; //最大传输单元
char ifru_slave[IFNAMSIZ]; //占位符
char ifru_newname[IFNAMSIZ];//新名称
void __user * ifru_data; //用户数据
struct if_settings ifru_settings; //设备协议设置
} ifr_ifru;
};
#endif /* __UAPI_DEF_IF_IFREQ */
利用ioctl就可以获取或者设置上面的结构体信息,达到网络IP,子网掩码的获取与设置的目的:
当然是用ioctl接口少不了请求码;网络的相关请求码request如下:
类别 | 请求码 | 描述 | 请求数据类型 |
套接口 | SIOCATMARK | 是否位于带外标记 | int |
SIOCGPGRP | 获取套接口的进程id或者进程组id | int | |
SIOCSPGRP | 设置套接口的进程id或者进程组id | int | |
网络接口 | SIOCGIFCONF | 获取所有接口的清单 | struct ifconf |
SIOCSIFADDR | 设置本地IP地址 | stuct ifreq | |
SIOCGIFADDR | 获取本地IP地址 | struct ifreq | |
SIOCSIFNETMASK | 设置本地子网掩码 | struct ifreq | |
SIOCGIFNETMASK | 获取本地子网掩码 | struct ifreq | |
SIOCSIFBRDADDR | 设置广播地址 | struct ifreq | |
SIOCGIFBRDADDR | 获取广播地址 | struct ifreq | |
SIOCSIFDSTADDR | 设置点对点地址 | struct ifreq | |
SIOCGIFDSTADDR | 获取点对点地址 | struct ifreq | |
SIOCGIFMTU | 获取接口MTU | struct ifreq | |
SIOCSIFFLAGS | 设置接口标识 | struct ifreq | |
SIOCGIFFLAGS | 获取接口标识 | struct ifreq | |
文件 | FIONBIN | 设置/清除非阻塞I/O标志 | int |
FIOASYNC | 设置/清除信号驱动异步I/O标志 | int | |
FIONREAD | 获取接收缓存区中的字节数 | int |
具体的获取和设置网络的IP实现如下:
获取本地IP地址:
/********************************************************* 描述:* 获取ethName网卡的IP地址* 参数:* ethName:网卡名称* 返回值:* 获取到的IP地址*********************************************************/std::string NetHelper::GetIPAdderss(std::string ethName)
{int ret;int fd;struct ifreq ifreq;char ip[12] = {0};std::string myip;std::string ERROR = "ERROR";//创建套接字fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);//填充网卡设备名属性,ethName:网卡设备名:eth0 ens33等memset(&ifreq, 0x00, sizeof(struct ifreq));strcpy(ifreq.ifr_name, ethName.c_str());//通过网卡名获取网卡网络数据保存至结构体ret = ioctl(fd, SIOCGIFADDR, &ifreq);if (ret < 0){perror("SIOCGIFADDR: ");close(fd);return ERROR;}if (ifreq.ifr_addr.sa_family != AF_INET){close(fd);return ERROR;}//将获取的ip地址转化为字符串struct sockaddr_in *addr = (struct sockaddr_in *)&(ifreq.ifr_addr);strcpy(ip, inet_ntoa(addr->sin_addr));myip = ip;printf("ip = %sn", ip);close(fd);return myip;
}
设置本地IP:
/********************************************************* 描述:* 设置ethName网卡的IP地址* 参数:* ethName:网卡名称* IP:要设置的IP地址* 返回值:* 设置成功返回:true,失败返回:false*********************************************************/
bool NetHelper::SetIPAdress(std::string ethName, std::string IP)
{int ret = 0;int fd = 0;int first = 0;int second = 0;int third = 0;int four = 0;struct ifreq ifreq;uint8_t ip[4] = {0};fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);if (fd < 0){std::cout << "create socket fd error!" << std::endl;close(fd);return false;}memset(&ifreq, 0, sizeof(ifreq));strcpy(ifreq.ifr_name, ethName.c_str());sscanf(IP.c_str(), "%d.%d.%d.%d", &first, &second, &third, &four);ip[0] = (uint8_t)first;ip[1] = (uint8_t)second;ip[2] = (uint8_t)third;ip[3] = (uint8_t)four;//设置IP属性ifreq.ifr_addr.sa_family = AF_INET;struct sockaddr_in *addr = (struct sockaddr_in *)&(ifreq.ifr_addr);memcpy(&(addr->sin_addr.s_addr), ip, 4);ret = ioctl(fd, SIOCSIFADDR, &ifreq);if (ret < 0){perror("set ip ioctl error:");close(fd);return false;}close(fd);return true;
}
获取子网掩码:
/********************************************************* 描述:* 获取ethName网卡的子网掩码* 参数:* ethName:网卡名称* 返回值:* 获取到的子网掩码*********************************************************/
std::string NetHelper::GetNetmask(std::string ethName)
{int ret;int fd;struct ifreq ifreq;char mask[12] = {0};std::string mymask;std::string ERROR = "ERROR";fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);memset(&ifreq, 0x00, sizeof(struct ifreq));strcpy(ifreq.ifr_name, ethName.c_str());/** 获取子网掩码*/ret = ioctl(fd, SIOCGIFNETMASK, &ifreq);if (ret < 0){perror("SIOCGIFNETMASK: ");close(fd);return ERROR;}if (ifreq.ifr_addr.sa_family != AF_INET){close(fd);return ERROR;}struct sockaddr_in *addr = (struct sockaddr_in *)&(ifreq.ifr_addr);strcpy(mask, inet_ntoa(addr->sin_addr));mymask = mask;printf("mask = %sn", mask);close(fd);return mymask;
}
设置值子网掩码:
/********************************************************* 描述:* 设置ethName网卡的子网掩码* 参数:* ethName:网卡名称* mask:要设置的子网掩码* 返回值:* 设置成功返回:true,失败返回:false*********************************************************/
bool NetHelper::SetNetmask(std::string ethName, std::string mask)
{int ret = 0;int fd = 0;int first = 0;int second = 0;int third = 0;int four = 0;struct ifreq ifreq;uint8_t mymask[4] = {0};fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);if (fd < 0){std::cout << "create socket fd error!" << std::endl;close(fd);return false;}mymask[0] = (uint8_t)first;mymask[1] = (uint8_t)second;mymask[2] = (uint8_t)third;mymask[3] = (uint8_t)four;memset(&ifreq, 0, sizeof(ifreq));strcpy(ifreq.ifr_name, ethName.c_str());ifreq.ifr_addr.sa_family = AF_INET;struct sockaddr_in *addr = (struct sockaddr_in *)&(ifreq.ifr_addr);memcpy(&(addr->sin_addr.s_addr), mymask, 4);ret = ioctl(fd, SIOCSIFNETMASK, &ifreq);if (ret < 0){perror("maks set error : ");close(fd);return false;}printf("set ip : %d.%d.%d.%dn", (int)mymask[0], (int)mymask[1], (int)mymask[2], (int)mymask[3]);close(fd);return true;
}
以上就是通过ioctl获取,设置网络信息的详细步骤,至于网关的设置和获取就涉及到路由相关,请参考我的下篇博文。
本文发布于:2024-02-04 12:03:04,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170706756255389.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |