В zebra-0.94-alt1 при попытке использовать RIP v2 на ppp-интерфейсе после нескольких поднятий и обрывов связи ripd перестаёт использовать интерфейс: 2004/03/31 13:31:58 RIP: can't setsockopt IP_ADD_MEMBERSHIP No buffer space available 2004/03/31 13:31:58 RIP: multicast join failed, interface ppp0 not running Это воспроизводится также следующей командой (при этом в конфигурации должен быть включен rip version 2 для интерфейса test): for ((i=0; i < 20; ++i)) do ip tunnel add mode ipip local 192.168.99.0 remote 192.168.99.1 name test; ip addr add 192.168.98.1 peer 192.168.98.2 dev test; ip link set test multicast on up; sleep 2; ip tunnel del name test; done После добавления трассировки вызовов ipv4_multicast_join/ipv4_multicast_leave выявилась следующая картина: 2004/03/31 17:50:51 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180334) for test 2004/03/31 17:50:52 RIP: interface delete test index 180334 flags 4240 metric 1 mtu 1480 2004/03/31 17:50:53 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180335) for test 2004/03/31 17:50:54 RIP: interface delete test index 180335 flags 4240 metric 1 mtu 1480 2004/03/31 17:50:55 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180336) for test 2004/03/31 17:50:56 RIP: interface delete test index 180336 flags 4240 metric 1 mtu 1480 2004/03/31 17:50:57 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180337) for test 2004/03/31 17:50:58 RIP: interface delete test index 180337 flags 4240 metric 1 mtu 1480 2004/03/31 17:50:59 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180338) for test 2004/03/31 17:51:00 RIP: interface delete test index 180338 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:01 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180339) for test 2004/03/31 17:51:02 RIP: interface delete test index 180339 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:03 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180340) for test 2004/03/31 17:51:04 RIP: interface delete test index 180340 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:05 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180341) for test 2004/03/31 17:51:06 RIP: interface delete test index 180341 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:07 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180342) for test 2004/03/31 17:51:08 RIP: interface delete test index 180342 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:09 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180343) for test 2004/03/31 17:51:10 RIP: interface delete test index 180343 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:11 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180344) for test 2004/03/31 17:51:12 RIP: interface delete test index 180344 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:13 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180345) for test 2004/03/31 17:51:14 RIP: interface delete test index 180345 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:15 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180346) for test 2004/03/31 17:51:16 RIP: interface delete test index 180346 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:17 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180347) for test 2004/03/31 17:51:18 RIP: interface delete test index 180347 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:19 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180348) for test 2004/03/31 17:51:20 RIP: interface delete test index 180348 flags 4240 metric 1 mtu 1480 2004/03/31 17:51:21 RIP: ipv4_multicast_join(sock=6, group=0xe0000009, ifa=0xc0a86201, ifindex=180349) for test 2004/03/31 17:51:21 RIP: can't setsockopt IP_ADD_MEMBERSHIP No buffer space available 2004/03/31 17:51:21 RIP: multicast join failed, interface test not running 2004/03/31 17:51:22 RIP: interface delete test index 180349 flags 4240 metric 1 mtu 1480 Т.е., каждый раз при появлении нового интерфейса выполняется join, однако при удалении интерфейса leave не выполняется, а ядро автоматически не вычищает записи при удалении интерфейсов (возможно, оно и не должно этого делать).
Дополнение: rip_multicast_leave() всё-таки вызывается, но при этом не проходит тест if_is_up (ifp), поэтому ничего не делается.
Created attachment 373 [details] fix IP_ADD_MEMBERSHIP leak in ripd (RIP v2) when interfaces are deleted
Не проверял (вообще RIP не использую), но по части zebra вполне может быть. Всё оказывается немного хуже, странность ещё и в реализации IGMP. Ещё раз перечитал RFC1112 и понял, что ситуация с опусканием и поднятием интерфейса там явно не определена даже для однократного вызова ip_mc_join_group(). С одной стороны, приложения не волнуют такие события, они не обязаны отслеживать таблицу интерфейсов, с другой стороны, в этом конкретном случае join производится на конкретный ifindex и он уходит в даун. Мне кажется, разумным решением было бы различное поведение IGMP-кода в ядре при вызове join на любой интерфейс и на какой-то конкретный интерфейс (по аналогии bind() для TCP/UDP). Severity: major подтверждаю. P.S. Исходя из моего скромного опыта программирования для IGMP год назад могу подозревать, что в этой стороне зарыта ещё не одна неожиданность, по крайней мере в мультикастовых заголовочных файлах нужен порядочный аудит. Последний раз их трогал Алан Кокс в непонятно каком году.
Патч приложен к zebra-0.94-alt2
Проблема осталась недофиксенной :( Ещё не до конца разобрался - похоже, интерфейсы иногда удаляются без предварительного down. Это проявляется реже, но всё-таки происходит; возможно, проявляется только с настоящим ppp, а не с использованным для быстрого тестирования патча ipip-туннелем.
Могу только дёрнуть Kunihiro, RIP вообще не использую.
Кстати, в zebra-0.95-pre2 вижу этот патч приложенным.
Нашёл ещё одно безобразие (в последнее время это стало проявляться чаще): 2004/10/06 18:46:49 RIP: connected address 192.168.200.1/32 is deleted 2004/10/06 18:46:49 RIP: interface ppp0 index 347 flags 4240 metric 1 mtu 1500 is down 2004/10/06 18:46:52 RIP: rip_interface_delete: ppp0 is not up 2004/10/06 18:46:52 RIP: rip_multicast_leave: ppp0 is not up 2004/10/06 18:46:52 RIP: interface delete ppp0 index 347 flags 4240 metric 1 mtu 1500 Т.е, сначала через rip_interface_address_delete() удаляются адреса, в результате потом rip_multicast_leave() ничего не делает. :( Похоже, придётся перехватывать ещё и удаление адресов, отслеживая joined_multicast для каждого адреса.
0.95-pre3 пошла в Sisyphus
0.95 пошла
Я не могу это сейчас ни диагностировать, ни чинить.