在CentOS 6.4(内核2.6.32)上,为什么下面的第二个Arping调用会创建一个新的ARP表条目,但是第一个却没有?网络行为是相同的,我的困惑是,在我看来,系统调用实际上是等效的。我在这里缺少什么系统行为?
#:- arping -s 10.0.2.15 -f 10.0.2.4
ARPING 10.0.2.4 from 10.0.2.15 eth0
Unicast reply from 10.0.2.4 [52:54:00:01:02:03] 0.681ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)
#:- ip neigh show | grep -c '^10\.0\.2\.4 '
0 # <--- no new ARP entry
#:- arping -f 10.0.2.4
ARPING 10.0.2.4 from 10.0.2.15 eth0
Unicast reply from 10.0.2.4 [52:54:00:01:02:03] 0.681ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)
#:- ip neigh show | grep -c '^10\.0\.2\.4 '
1 # <--- new ARP entry
上面的eth0的地址是10.0.2.15。如果您尝试自己重现此内容,请注意您的目标根本不在ARP表中-例如,它不能处于STALE状态,它必须完全不存在。
现在,如果我跟踪每个调用(并忽略内存位置的差异),则相关的差异是这样的:
$:- diff -uN /tmp/arp-no.trace /tmp/arp-yes.trace
--- /tmp/arp-no.trace 2014-04-23 20:17:46.301575314 -0500
+++ /tmp/arp-yes.trace 2014-04-23 20:17:48.790575314 -0500
@@ -1,4 +1,4 @@
-execve("/sbin/arping", ["arping", "-s", "10.0.2.15", "-f", "10.0.2.4"], [/* 19 vars */]) = 0
+execve("/sbin/arping", ["arping", "-f", "10.0.2.4"], [/* 19 vars */]) = 0
brk(0) = 0xMEMLOCATION
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xMEMLOCATION
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
@@ -37,7 +37,9 @@
ioctl(3, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_BINDTODEVICE, "eth0\0", 5) = 0
-bind(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("10.0.2.15")}, 16) = 0
+setsockopt(4, SOL_SOCKET, SO_DONTROUTE, [1], 4) = 0
+connect(4, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("10.0.2.4")}, 16) = 0
+getsockname(4, {sa_family=AF_INET, sin_port=htons(38207), sin_addr=inet_addr("10.0.2.15")}, [16]) = 0
close(4) = 0
bind(3, {sa_family=AF_PACKET, proto=0x806, if2, pkttype=PACKET_HOST, addr(0)={0, }, 40) = 0
getsockname(3, {sa_family=AF_PACKET, proto=0x806, if2, pkttype=PACKET_HOST, addr(6)={1, 080027538173}, [18]) = 0
... and then the sendto/recvfrom happen ...
在我指定源IP且未创建ARP条目的情况下,将使用短暂的IPPROTO_IP套接字(已创建,绑定(bind)且关闭)来验证源IP地址。在第二种情况下,arping会使用创建的短暂IPPROTO_IP套接字,connect()ed,getsockname()d和封闭的方式猜测源IP地址。
之后,程序行为(和网络 Activity )是相同的。但是,系统的 react 不是,我看到的唯一实质性区别是每个程序对现在关闭的套接字的使用不同但无害。
最佳答案
很好奇,不是吗? :-)
我很确定这与我在另一个Arping实现(我的)中研究的内核错误/功能相同:
https://blog.habets.se/2012/10/Interesting-Arping-bug-report
简短的解释没有任何意义,但总而言之:如果您查找路由然后发送原始ARP数据包,则内核出于某种原因将嗅探ARP应答并填充ARP表。
我不知道为什么,或者甚至是预期的行为。但这是内核完成的。