首页 > 代码库 > Fedora-20上ping本机IP地址时的问题

Fedora-20上ping本机IP地址时的问题

在Fedora 20上写了一个简单的ping程序,创建原始套接字后没有设置任何选项,ping其他主机(NetBSD-1.0)的时候运行正常:

[root@sea network]# ./ping 192.168.1.114PING 192.168.1.114:send packet(icmp):08 00 cc 95 0d 4c 00 00 a5 a5     .....L....a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5                       ....recv packet(ip):45 00 00 54 35 04 40 00 ff 01     E..T5.@...c2 7c c0 a8 01 72 c0 a8 01 65     .|...r...e00 00 d4 95 0d 4c 00 00 a5 a5     .....L....a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5                       ....64 bytes from 192.168.1.114: seq=0, ttl=255[root@sea network]# 

 

但是ping本机的IP地址的时候却有问题了:

[root@sea network]# ./ping 192.168.1.101PING 192.168.1.101:send packet(icmp):08 00 11 95 c8 4c 00 00 a5 a5     .....L....a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5                       ....recv packet(ip):45 00 00 54 a8 c8 40 00 40 01     E..T..@.@.0d c6 c0 a8 01 65 c0 a8 01 65     .....e...e08 00 11 95 c8 4c 00 00 a5 a5     .....L....a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5                       ....error, the type of reply packet is not icmp echoreply![root@sea network]# 

返回的ICMP报文和发送出去的是一样的!!

tcpdump 命令查看网卡接口的数据包,发现没有任何数据输出。觉得这不太可能,忽然想到本机的IP地址是不是发送到环回接口上啦?验证发现果然如此:

[root@sea network]# tcpdump -i lo -X icmptcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes12:06:30.336304 IP sea > sea: ICMP echo request, id 16974, seq 0, length 64    0x0000:  4500 0054 a8d0 4000 4001 0dbe c0a8 0165  E..T..@.@......e    0x0010:  c0a8 0165 0800 9793 424e 0000 a5a5 a5a5  ...e....BN......    0x0020:  a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5  ................    0x0030:  a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5  ................    0x0040:  a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5  ................    0x0050:  a5a5 a5a5                                ....12:06:30.336327 IP sea > sea: ICMP echo reply, id 16974, seq 0, length 64    0x0000:  4500 0054 a8d1 0000 4001 4dbd c0a8 0165  E..T....@.M....e    0x0010:  c0a8 0165 0000 9f93 424e 0000 a5a5 a5a5  ...e....BN......    0x0020:  a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5  ................    0x0030:  a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5  ................    0x0040:  a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5 a5a5  ................    0x0050:  a5a5 a5a5                                ....

tcpdump 的输出来看,lo接口的返回并没有什么问题,但是为什么程序中的 recvfrom 函数会收到和 sendto 一样的数据呢?

Fedora 20自带的 ping 程序又是没有这个问题的,于是下载了 ping 的源码,看看自带的程序是不是做了什么特殊的处理。经过一番调试,最后确认是下面的代码起了作用:

    if (1) {        struct icmp_filter filt;        filt.data = ~((1<<ICMP_SOURCE_QUENCH)|                  (1<<ICMP_DEST_UNREACH)|                  (1<<ICMP_TIME_EXCEEDED)|                  (1<<ICMP_PARAMETERPROB)|                  (1<<ICMP_REDIRECT)|                  (1<<ICMP_ECHOREPLY));        if (setsockopt(icmp_sock, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1)            perror("WARNING: setsockopt(ICMP_FILTER)");    }

过滤掉了 ICMP_ECHO 类型的报文?在我自己的程序中加上类似的代码:

    filt.data = http://www.mamicode.com/~((1<<ICMP_ECHOREPLY));    if (setsockopt(sockfd, SOL_RAW, ICMP_FILTER, (char*)&filt, sizeof(filt)) == -1) {        perror("WARNING: setsockopt(ICMP_FILTER)");    }

重新编译后,运行就正确了:

[root@sea network]# ./ping 192.168.1.101PING 192.168.1.101:send packet(icmp):08 00 37 92 a2 4f 00 00 a5 a5     ..7..O....a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5                       ....recv packet(ip):45 00 00 54 a8 d3 00 00 40 01     E..T....@.4d bb c0 a8 01 65 c0 a8 01 65     M....e...e00 00 3f 92 a2 4f 00 00 a5 a5     ..?..O....a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5 a5 a5 a5 a5 a5 a5     ..........a5 a5 a5 a5                       ....64 bytes from 192.168.1.101: seq=0, ttl=64[root@sea network]# 

 

在NetBSD-1.0上,不设置任何的套接字选项,直接ping本机的IP地址是没有这个问题的。

在Slackware-14.1上测试,也有Fedora-20的问题,看来Linux系统的实现都是这样的。是bug?还是实现特性?