centos 5(6も?) arping バグ
ちょっと前に調べたので。rstに慣れる意味で書いてみた。
今となっては使っている人はいないかもしれないけど centos 5 の arping はバグってるというお話。 ちなみに、 centos 6 はちゃんと調査してませんが、同じパッチがあたってるようなのでダメかもしれません。 というか centos 6 でも、後述する -c 偶数指定で指定した半分しかarpを出さない問題は残ってました。
実際に見た方が早いと思うので。
-bash-3.2$ date; sudo ./arping -I eth1 -b -c 3 2.2.2.2; echo $?
2012年 9月 1日 土曜日 20:34:21 JST
ARPING 2.2.2.2 from 10.1.1.220 eth1
Sent 3 probes (3 broadcast(s))
Received 0 response(s)
1
-bash-3.2$ date; sudo ./arping -I eth1 -b -c 3 2.2.2.2; echo $?
2012年 9月 1日 土曜日 20:34:26 JST
ARPING 2.2.2.2 from 10.1.1.220 eth1
0
-bash-3.2$ date; sudo ./arping -I eth1 -b -c 3 2.2.2.2; echo $?
2012年 9月 1日 土曜日 20:34:30 JST
ARPING 2.2.2.2 from 10.1.1.220 eth1
Sent 3 probes (3 broadcast(s))
Received 0 response(s)
1
-bash-3.2$ date; sudo ./arping -I eth1 -b -c 3 2.2.2.2; echo $?
2012年 9月 1日 土曜日 20:34:35 JST
ARPING 2.2.2.2 from 10.1.1.220 eth1
0
2.2.2.2 はありもしないアドレスなので、成功するはずが無いはずなのに、正常終了しています。 ちなみに、この現象は割とホストがたくさんぶら下がっていて arp がとびかってる環境で発生します。
なにはともあれ、src.rpmを展開してソースを見てみると、
$ mkdir ipuitls
$ wget ftp://ftp.pbone.net/mirror/vault.centos.org/5.8/os/SRPMS/iputils-20020927-46.el5.src.rpm
$ rpm2cpio iputils-20020927-46.el5.src.rpm | cpio -id
$ mkdir SOURCES
$ cp * SOURCES
$ rpmbuild -bp --define "_topdir `pwd`" iputils.spec
$ cd BUILD/iputils
$ make arping
$ less arping.c
.
. snip
.
184 if ((timeout && MS_TDIFF(tv,start) > timeout*1000 + 500) ||
185 ((count == 0) && (!timeout)))
186 finish();
187
188 if (last.tv_sec==0 || MS_TDIFF(tv,last) > 500) {
189 count--;
190 send_pack(s, src, dst, &me[0], &he[0]);
191 if (count == 0 && unsolicited)
192 finish();
193 }
194 alarm(1);
.
. snip
.
597 if ((cc = recvfrom(s, packet, sizeof(packet), 0,
598 (struct sockaddr *)&from[0], (socklen_t*)&alen)) < 0) {
599 perror("arping: recvfrom");
600 continue;
601 }
602 sigemptyset(&sset);
603 sigaddset(&sset, SIGALRM);
604 sigaddset(&sset, SIGINT);
605 sigprocmask(SIG_BLOCK, &sset, &osset);
606 recv_pack(packet, cc, &from[0]);
607 if(received == count)
608 exit(0);
.
. snip
.
この辺りがすべてを物語っていて、パケットを送信するとcountがデクリメントされて、 なにかしら arp っぽいものを受信していれば count の値と比較して同じなら正常終了する。 ちなみに、 received はちゃんとした reply の arp を受け取ればインクリメントされるので、 この場合、ありもしないホストからちゃんとした reply が帰ってくる事は無いので、常に0。 count が 0 になったときに arp っぽいなにかを受信すれば、正常終了となるバグ。 じゃー、なぜちゃんと失敗する場合があるのかというと、 count が 0 になった状態で SIGALRM をうければ finish() が呼ばれてちゃんと失敗と見なされる。 つまり、最後の最後に、 SIGALRM を受けるのが先か arp っぽいパケットを受けるのが先かで結果が変わる。
補足ですが、しれっと arp っぽいとか書いてますが、これはrecvfromで拾えたパケットという事です。 sokcet自体はPF_PACKETを指定しているので、その対象になる生パケットならなんでもよいという事です。
もう、勘のいい人は気づいたと思いますが。
-bash-3.2$ date; sudo ./arping -I eth1 -b -c 5 10.1.1.1
2012年 9月 1日 土曜日 21:20:23 JST
ARPING 10.1.1.1 from 10.1.1.220 eth1
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.605ms
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.631ms
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.619ms
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.648ms
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.685ms
Sent 5 probes (5 broadcast(s))
Received 5 response(s)
-bash-3.2$ date; sudo ./arping -I eth1 -b -c 6 10.1.1.1
2012年 9月 1日 土曜日 21:20:30 JST
ARPING 10.1.1.1 from 10.1.1.220 eth1
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.655ms
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.639ms
Unicast reply from 10.1.1.1 [00:1B:FC:BD:CF:AA] 0.682ms
存在するホストに対して、 -c のカウントを偶数回にすると半分しか arp を送りません。 で、この問題を引き起こしているパッチは iputils-20020927-12-arping.patch のようです。
解決策ですが、ひとまず、以下のパッチをあてると count = 0 で正常終了する問題は回避できました。
--- arping.c.orig 2012-09-01 21:28:07.443016686 +0900
+++ arping.c 2012-09-01 21:29:22.710022302 +0900
@@ -373,6 +373,7 @@
{
int socket_errno;
int ch;
+ int lcount;
uid_t uid = getuid();
s = socket(PF_PACKET, SOCK_DGRAM, 0);
@@ -400,7 +401,7 @@
quiet++;
break;
case 'c':
- count = atoi(optarg);
+ count = lcount = atoi(optarg);
break;
case 'w':
timeout = atoi(optarg);
@@ -604,7 +605,7 @@
sigaddset(&sset, SIGINT);
sigprocmask(SIG_BLOCK, &sset, &osset);
recv_pack(packet, cc, &from[0]);
- if(received == count)
+ if(received == lcount)
exit(0);
sigprocmask(SIG_SETMASK, &osset, NULL);
}
ちなみに、
if(received == lcount)
exit(0);
このexit(0)はfinish()が正解なんじゃないかと思うのだけれど、、、今回はそのままにしておきました。
centos 6 はというと
[root@hoge iputils]# cat /etc/issue
CentOS release 6.2 (Final)
Kernel \r on an \m
[root@hoge iputils]# arping -b -c 5 49.212.138.1 ; echo $?
ARPING 49.212.138.1 from 49.212.138.173 eth0
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 2.760ms
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 6.674ms
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 5.571ms
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 7.492ms
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 2.950ms
Sent 5 probes (5 broadcast(s))
Received 5 response(s)
0
[root@hoge iputils]# arping -b -c 4 49.212.138.1 ; echo $?
ARPING 49.212.138.1 from 49.212.138.173 eth0
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 2.727ms
Unicast reply from 49.212.138.1 [00:00:5E:00:01:6B] 2.550ms
0
えーっと、、、、、
どうやら、同じパッチがあたっているようです。
どなたに言えばいいんでしょう?
こういうの。
name: | |
email: | |
comment: | |