linux C ioctl设置,获取网关,路由信息

您所在的位置:网站首页 ubuntu修改路由表 linux C ioctl设置,获取网关,路由信息

linux C ioctl设置,获取网关,路由信息

2023-04-16 01:27| 来源: 网络整理| 查看: 265

linux c ioctl 设置本地ip 子网掩码网络信息

在日常开发中除了设置网络信息外,路由的设置也是不可避免的,同样仍然使用ioctl万能函数设置,获取设备属性,首先认识下路由属性核心结构:

struct rtentry { unsigned long rt_pad1; struct sockaddr rt_dst; /* 目标地址*/ struct sockaddr rt_gateway; /* 网关*/ struct sockaddr rt_genmask; /* 子网掩码*/ unsigned short rt_flags; short rt_pad2; unsigned long rt_pad3; void *rt_pad4; short rt_metric; /* +1 为了二进制兼容性 */ char __user *rt_dev; /* 强制添加设备 */ unsigned long rt_mtu; /* 路由MTU*/ #ifndef __KERNEL__ #define rt_mss rt_mtu /* 兼容性*/ #endif unsigned long rt_window; unsigned short rt_irtt; /* 最初的RTT*/ };

这个结构由SIOCADDRT和SIOCDELRT调用传递,白话就是这个结构就是在添加路由和删除路由的时候被调用。SIOCADDRT:添加路由,SIOCDELRT:删除路由,就是ioctl调用时使用的请求码。

具体的代码实现如下:

下面代码的参数RouteItem结构如下:

typedef struct { std::string ethName;//网卡名 std::string dest_ip;//目的地址 std::string mask;//子网掩码 std::string nexthop;//下一跳(网关) } RouteItem;

添加路由:

/* 描述: 添加路由项 参数: item:路由项实例 返回值: 成功:true 失败:false */ bool NetHelper::AddRouteItem(RouteItem &item) { int sockfd; struct rtentry rt;//创建结构体变量 //创建套接字 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket creation failed\n"); return false; } //设置网关,又名下一跳:转到下个路由的路由地址 struct sockaddr_in *sockinfo = (struct sockaddr_in *)&rt.rt_gateway; sockinfo->sin_family = AF_INET; sockinfo->sin_addr.s_addr = inet_addr(item.nexthop.c_str()); //设置目的地址 sockinfo = (struct sockaddr_in *)&rt.rt_dst; sockinfo->sin_family = AF_INET; sockinfo->sin_addr.s_addr = inet_addr(item.dest_ip.c_str()); //设置子网掩码 sockinfo = (struct sockaddr_in *)&rt.rt_genmask; sockinfo->sin_family = AF_INET; sockinfo->sin_addr.s_addr = inet_addr(item.mask.c_str()); //设置网卡设备名 rt.rt_flags = RTF_UP | RTF_GATEWAY; rt.rt_dev = (char *)item.ethName.c_str(); //ioctl接口进行路由属性设置 if (ioctl(sockfd, SIOCADDRT, &rt) < 0) { perror("ioctl:"); return false; } return true; }

删除路由代码:

/* 描述: 删除路由项 参数: item:路由对象 返回值: 成功:true 失败:false */ bool NetHelper::DelRouteItem(RouteItem &item) { int fd; struct sockaddr_in _sin; struct sockaddr_in *sin = &_sin; struct rtentry rt; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("create fd of socket error:"); return false; } // 要删除的网关信息,网关信息可以不填充,有ip 子网掩码即可删除路由 memset(&rt, 0, sizeof(struct rtentry)); memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; sin->sin_port = 0; if (inet_aton(item.nexthop.c_str(), &sin->sin_addr) < 0) { perror("gateWay inet_aton error:"); close(fd); return false; } memcpy(&rt.rt_gateway, sin, sizeof(struct sockaddr_in)); //要删除的ip信息 ((struct sockaddr_in *)&rt.rt_dst)->sin_family = AF_INET; if (inet_aton(item.dest_ip.c_str(), &((struct sockaddr_in *)&rt.rt_dst)->sin_addr) < 0) { perror("dest addr inet_aton error:"); close(fd); return false; } //要删除的子网掩码 ((struct sockaddr_in *)&rt.rt_genmask)->sin_family = AF_INET; if (inet_aton(item.mask.c_str(), &((struct sockaddr_in *)&rt.rt_genmask)->sin_addr) < 0) { perror("mask inet_aton error:"); close(fd); return false; } //网卡设备名 rt.rt_dev = (char *)item.ethName.c_str(); rt.rt_flags = RTF_UP | RTF_GATEWAY; if (ioctl(fd, SIOCDELRT, &rt) < 0) { perror("ioctl SIOCADDRT error : "); close(fd); return false; } close(fd); return true; }

路由表用到的指令吗目前只有这两个:

/* Routing table calls. */ #define SIOCADDRT 0x890B /* 添加路由 */ #define SIOCDELRT 0x890C /* 删除路由 */

所以目前还没办法通过ioctl获取路由表信息,一般我们都是通过/proc/net/route文件获取路由表信息,具体路由表的获取方法:

/* 描述: 获得路由表 参数: routeTable:保存路由表的容器 返回值: 成功:true 失败:false */ bool NetHelper::GetRouteTabel(RouteTable &routeTable) { // ubuntu FILE *fp; char devname[64]; unsigned long d, g, m; int r = 0; int flgs, ref, use, metric, mtu, win, ir; uint8_t gate[4] = {0}; uint8_t ip[4] = {0}; uint8_t mask[4] = {0}; std::string gateway; uint8_t ip_str[15] = {0}; uint8_t mask_str[15] = {0}; uint8_t gate_str[15] = {0}; RouteItem item; fp = fopen("/proc/net/route", "r"); /* Skip the first line. */ r = fscanf(fp, "%*[^\n]\n"); if (r < 0) { /* Empty line, read error, or EOF. Yes, if routing table * is completely empty, /proc/net/route has no header. */ fclose(fp); return false; } // ubuntu while (1) { r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", devname, &d, &g, &flgs, &ref, &use, &metric, &m, &mtu, &win, &ir); if (r != 11) { if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */ break; } } // printf("%63s %lx %lx %X %d %d %d %lx %d %d %d\n", devname, d, g, flgs, ref, use, metric, m, mtu, win, ir); // RTF_UP表示该路由可用,RTF_GATEWAY表示该路由为一个网关,组合在一起就是3,表示一个可用的网关 if ((flgs & RTF_GATEWAY) && (flgs & RTF_UP) && g != 0) { memcpy(ip, &d, 4); memcpy(mask, &m, 4); memcpy(gate, &g, 4); sprintf((char *)gate_str, "%d.%d.%d.%d", gate[0], gate[1], gate[2], gate[3]); sprintf((char *)ip_str, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); sprintf((char *)mask_str, "%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]); item.ethName = devname; item.dest_ip = (char *)ip_str; item.mask = (char *)mask_str; item.nexthop = (char *)gate_str; routeTable.push_back(item); } } printf("gate : %d.%d.%d.%d\n", gate[0], gate[1], gate[2], gate[3]); printf("ip : %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); printf("mask : %d.%d.%d.%d\n", mask[0], mask[1], mask[2], mask[3]); std::vector::iterator iter; for (iter = routeTable.begin(); iter != routeTable.end(); iter++) { std::cout ethName


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3