Python: получение сокета IPv6 для приема пакетов, предназначенных для адреса Anycast маршрутизаторов подсети - PullRequest
5 голосов
/ 28 февраля 2009

Как получить сокет для приема пакетов, предназначенных для любого адреса IP-адреса подсети-маршрутизатора?

Я не смог найти никакой информации о том, как это сделать.

В отчаянии я попытался использовать socket.setsockopt, как если бы вы присоединились к многоадресной группе:

# 7 is the interface number 
s = socket(AF_INET6, SOCK_DGRAM)
packed_iface_num = struct.pack("I", 7) 
group = inet_pton(AF_INET6, 'fd36:d00d:d00d:47cb::') + packed_iface_num

# socket.error: (22, 'Invalid argument')
s.setsockopt(IPPROTO_IPV6, IPV6_JOIN_GROUP,  group)

А также с помощью связывания

# socket.error: (99, 'Cannot assign requested address')
s.bind(('fd36:773e:6b4c:47cb::', 9876))

Как и ожидалось, ни один из них не работал. Есть ли способ сделать это?

Ответы [ 2 ]

2 голосов
/ 03 марта 2009

Вместо IPV6_JOIN_GROUP, попробуйте передать IPV6_JOIN_ANYCAST к вашему s.setsockopt() коду. К сожалению, модуль Python socket не определяет его, но вы должны иметь возможность передавать целочисленный эквивалент. В Linux IPV6_JOIN_ANYCAST равно 27, а IPV6_LEAVE_ANYCAST равно 28. (определено в /usr/include/linux/in6.h)

Лучшая документация, которую я смог найти, - это lkml электронное письмо с описанием патча anycast для ядра Linux :

Интерфейс приложения для присоединения и выхода из групп anycast - 2 новые вызовы setsockopt (): IPV6_JOIN_ANYCAST и IPV6_LEAVE_ANYCAST. Аргументы такие же, как соответствующие операции многоадресной рассылки.

Да пребудет с вами танец каме!

0 голосов
/ 28 мая 2009

Опции сокетов IPV6_JOIN_ANYCAST и IPV6_LEAVE_ANYCAST являются нестандартными Linux-измами.

Если вы хотите, чтобы ваш код был portable , то вам, вероятно, следует сделать это стандартным способом, то есть назначить произвольный адрес маршрутизатора подсети соответствующему интерфейсу, а затем привязать сокет к подстановочному адресу и отбросить все, что не отправлено на любой адрес маршрутизатора подсети. Помните, что вы не должны отправлять пакеты с произвольным адресом в поле источника, и вы не можете открыть сокет только для чтения в стандартном API сокетов.

Назначение адреса интерфейса должно быть привилегированной операцией в любой разумной операционной системе, и это та часть, которая не собирается быть стандартной, независимо от того, что вы делаете. Если вы должны сделать это программно, то это будет означать (например, в BSD) использование чего-то вроде SIOCAIFADDR_IN6 кода и системного вызова ioctl(). Обязательно установите флаг IN6_IFF_ANYCAST в поле ifra_flags структуры запроса псевдонима интерфейса.

...