Pysnmp openServerMode с IPv6

Я пытаюсь запустить агент SNMP с помощью pysnmp. для привязки IPv4 и IPv6 он отлично работает с локальным хостом ('127.0.0.1' и '::1')

но когда я пытаюсь использовать другой IPv6 IP-адрес, который я получил из интерфейса, это не удается из-за

[vagrant@test SOURCES]$ sudo python snmp_agent.py enp0s8
Traceback (most recent call last):
  File "snmp_agent.py", line 172, in <module>
    master_agent_startup(ifname=sys.argv[1])
  File "snmp_agent.py", line 101, in master_agent_startup
    (get_ipv6_address(interface_name), SNMP_AGENT_PORT))
  File "/usr/lib/python2.7/site-packages/pysnmp/carrier/asyncore/dgram/base.py", line 50, in openServerMode
    raise error.CarrierError('bind() for %s failed: %s' % (iface, sys.exc_info()[1],))
pysnmp.carrier.error.CarrierError: bind() for ('fe80::a00:27ff:fe9e:9c16', 8001) failed: [Errno 22] Invalid argument

Это вывод интерфейса enp0s8:

[vagrant@test SOURCES]$ ifconfig enp0s8
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.20.20.26  netmask 255.255.255.0  broadcast 172.20.20.255
        inet6 fe80::a00:27ff:fe9e:9c16  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:9e:9c:16  txqueuelen 1000  (Ethernet)
        RX packets 874053  bytes 115842841 (110.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 862314  bytes 114652475 (109.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Это фрагмент кода, который я использовал для привязки IPv6:

def get_ipv6_address(ifname):
    return netifaces.ifaddresses(ifname)[netifaces.AF_INET6][0]['addr'].split('%')[0]

config.addSocketTransport(snmpEngine, udp.domainName,
                          udp.UdpTransport().openServerMode(
                              (get_ipv4_address(interface_name), SNMP_AGENT_PORT))
                          )
config.addSocketTransport(snmpEngine, udp6.domainName,
                          udp6.Udp6SocketTransport().openServerMode(
                              (get_ipv6_address(interface_name), SNMP_AGENT_PORT))
                          )

Из примера pysnmp кажется, что параметр внутри «openServerMode ()» — это просто кортеж IP и порта. И из ошибки вывода я полагаю, что для данного IP и порта ошибки нет. так почему это не удалось из-за неверного аргумента? Не могли бы вы @Ilya Etingof или какой-нибудь другой эксперт по pysnmp помочь мне с этим?

Спасибо.

ОБНОВЛЕНИЕ: я пытаюсь связать его с данным предложением, но все равно не работает. команда bind была запущена из новой установленной CentOS. но все равно не получилось: [root@test ~]# ifconfig

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.10.20.4  netmask 255.255.255.0  broadcast 10.10.20.255
        inet6 fe80::f816:3eff:fee1:5475  prefixlen 64  scopeid 0x20<link>
        ether fa:16:3e:e1:54:75  txqueuelen 1000  (Ethernet)
        RX packets 12242  bytes 962552 (939.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12196  bytes 957826 (935.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@test ~]# python
Python 2.7.5 (default, Oct 11 2015, 17:47:16)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, 0)
>>> addr_and_port = ('fe80::f816:3eff:fedb:ba4f', 8001)
>>> s.bind(addr_and_port)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 22] Invalid argument
>>>
[1]+  Stopped                 python
[root@test ~]# netstat -anp | grep 8001
[root@test ~]#

Еще одно обновление: я полагаю, что привязка не удалась из-за того, что в моей среде есть проблемы с конфигурацией IPv6. Поскольку я могу получить только один адрес IPv4, используя метод «socket.getaddrinfo()».

Бр, - Дапэн Цзяо


person dapeng1011    schedule 19.07.2016    source источник


Ответы (2)


Вы можете получить эту ошибку, если попытаетесь связать один и тот же сокет более одного раза. Но я не вижу, что это так в вашем коде.

Этот метод .openServerMode() не творит чудес — он просто вызывает .bind() для объекта сокета. Для вдохновения, работает ли это в вашей подсказке Python?

from pysnmp.carrier.asyncore.dgram import udp6

addr_and_port = ('fe80::a00:27ff:fe9e:9c16', 8001)
udp6.Udp6SocketTransport().openServerMode(addr_and_port)

или даже:

import socket

s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, 0)
addr_and_port = ('fe80::a00:27ff:fe9e:9c16', 8001)
s.bind(addr_and_port)

Я надеюсь, что подобные тесты помогут вам разобраться в проблеме...

person Ilya Etingof    schedule 19.07.2016
comment
Спасибо за быстрый ответ. Обе эти попытки дают одну и ту же ошибку. Не знаю, как вставить сюда все ошибки. Так что просто дайте несколько строк: «Traceback (последний последний вызов): Файл ‹stdin›, строка 1, в ‹module› Файл /usr/lib/python2.7/site-packages/pysnmp/carrier/asyncore/dgram/base .py, строка 50, в openServerMode возникает ошибка. CarrierError('bind() for %s failed: %s' % (iface, sys.exc_info()[1],)) ' - person dapeng1011; 19.07.2016
comment
'››› s.bind(addr_and_port) Трассировка (последний последний вызов): Файл ‹stdin›, строка 1, в ‹module› Файл /usr/lib64/python2.7/socket.py, строка 224, возврат в meth getattr(self._sock,name)(*args) socket.error: [Errno 22] Неверный аргумент' - person dapeng1011; 19.07.2016

Когда вы используете локальный адрес IPv6, вы всегда должны использовать вместе с ним область действия. Локальный адрес ссылки недействителен без его области действия, поэтому вы получите ошибку Invalid argument.

Например, вместо fe80::a00:27ff:fe9e:9c16 вы должны использовать fe80::a00:27ff:fe9e:9c16%enp0s8.

person Michael Hampton    schedule 21.07.2016