最近研究了通过sysctl方法获取路由表的UNIX源码(FreeBSD
http://www.oschina.net/code/explore/freebsd/sbin/route/route.c),收获不少。
其中找出一段错误如下:
代码1:
L1: if (ifm->ifm_type == RTM_IFINFO) {
L2: get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
L3: printf(" %-15s", sock_ntop(sa, sa->sa_len));
这是用来打印路由对应的Interface ,但是却打印出这个结果:
代码2:
Routing table:
--------------
Destination Gateway Flags Netif Use
default 27.17.172.1 UGSc ppp07.172.1 0
default/0 192.168.1.1 UGSc en1.168.1.1 0
27.17.172.1 27.17.175.111 UH ppp07.175.111 0
本来NetIf部分是由代码1输出的,但现在看起来却像一个结构体被错误的使用带来的后果。
在代码1的L3设置断点,得到sa的数据:
sa_data char [14][14]
0 char
8 '\b'
1 char
0 '\000'
2 char
23 '\027'
3 char
4 '\004'
4 char
0 '\000'
5 char
0 '\000'
6 char
112 'p'
7 char
112 'p'
8 char
112 'p'
9 char
48 '0'
10 char
0 '\000'
11 char
0 '\000'
12 char
0 '\000'
13 char
0 '\000'
可以看到,我们需要的数据是6、7、8、9,也就是对应ppp0,10之后都是'\000' 字符串的结束,说明Interface信息在这里是正常的,经过sock_ntop处理后返回的值出错了。
现在来看,sock_ntop做了一个选择器的工作,就是把socket数据进行识别,就是判断struct sock_addr *的sa_family,然后返回对应family的值。
sa_family对应有 AF_LINK AF_INET 等等。我们这里获取的是接口数据,所以当然是这部分的代码:
代码3:
case AF_LINK: {
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
if (sdl->sdl_len > 0) {
L1: bcopy(&sdl->sdl_data[0], str, sdl->sdl_nlen);
L2: str[sdl->sdl_len] = '\0';
} else
snprintf(str, sizeof(str), "link#%d", sdl->sdl_index);
return (str);
}
我们要观察的是str这块buffer,因为最终我们得到的函数返回是str
断点设在代码3的L1,此时str还保留前一次取ip的数据。bcopy完成了将sdl中长度为 sdl->nlen 的数据拷贝到 str 这个buffer中,然后L2是为这儿buffer加上字符串结束标记。
显然这里出现了问题:我们拷贝了sdl->nlen长度的数据,却在sdl_len处结束字符串,所以这个应该是接口数据多出来的原因。
到文件 net/if_dl.h 中查看 struct sockaddr_dl * :
/*
* Structure of a Link-Level sockaddr:
*/
struct sockaddr_dl {
u_char sdl_len; /* Total length of sockaddr */
u_char sdl_family; /* AF_LINK */
u_short sdl_index; /* if != 0, system given index for interface */
u_char sdl_type; /* interface type */
u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */
u_char sdl_alen; /* link level address length */
u_char sdl_slen; /* link layer selector length */
char sdl_data[12]; /* minimum work area, can be larger;
contains both if name and ll address */
#ifndef __APPLE__
/* For TokenRing */
u_short sdl_rcf; /* source routing control */
u_short sdl_route[16]; /* source routing information */
#endif
};
我们需要的数据长度显然是sdl_nlen , sdl_len 是整块sockaddr的长度,这样标记肯定会继续输出str中未被socket数据覆盖的部分,也就是之前使用过的ip。
回头看看代码2,也就是输出的部分路由表,可以发现每一行Netif的后半段和Gateway的数据是相同的,这也证明了这一点:str使用完之后没有被清空。这是不太好的做法,要么就在正确位置加上字符串结束符‘\0’,要么就每次使用完str就清空一次 —— 呃,以UNIX源码的风格,我想大部分会是前一种 —— 但是我也不知道为何这些程序员都能保持头脑清醒。
===================================
本文来自:http://blog.csdn.net/zh405123507
tags:UNIX Routing Debug Socket
分享到:
相关推荐
修改Windows路由表的程序,实现了对路由表的查询、添加、编辑、删除功能。开发环境VS2010,C++语言
易语言取本机IP路由表源码。@易语言入门教程。
易语言源码易语言取本机IP路由表源码.rar
易语言取本机IP路由表源码.zip
Route命令是在本地 IP 路由表中显示和修改条目网络命令。
一个自动修改路由表的小软件,自用版本,使用时请自己修改配置文件。。。
路由表中的metric,路由表中的metric,路由表中的metric
ROS路由表ROS路由表ROS路由表ROS路由表
易语言取本机IP路由表源码
易语言取本机IP路由表源码,取本机IP路由表,整数IP到文本,GetIpForwardTable
再也不用route add了,GUI操作
路由表 实例 分析 路由表 实例 分析 路由表 实例 分析
四大运营商路由表:电信,联通,教育网,移动。
ROS路由表(电信联通长城路由表大全)
Graphpath从Unix / Linux的路由表中生成一个ASCII网络图
2017年12月最新路由表,对于多连路接入用户做负载分流用,可直接导入routeros
路由表体系结构的设计;Windows操作系统路由表完全解析
移动路由表实现双WAN 路由器 移动的均衡路由
如何读懂路由表,详细整理如何读懂路由表.