带有 IPv6 的 Pysnmp openServerMode
Pysnmp openServerMode with IPv6
我尝试使用 pysnmp 启动 SNMP 代理。
对于 IPv4 和 IPv6 绑定,它与 localhost ('127.0.0.1' and '::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 专家帮助我吗?
谢谢。
UPDATE: I try to bind it with given suggestion, but is still doesn't work.
the bind command was run from a new installed CentOS. but it still failed:
[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 ~]#
One more update:
I suppose the bind is failed due to my environment has some issue with IPv6 configuration. As I'm only able to get one IPv4 address by using "socket.getaddrinfo()" method.
Br,
-焦大鹏
如果尝试多次绑定同一个套接字,您可能会收到此错误。但是我看不出你的代码是这样的。
那个 .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)
我希望像这样的测试可以帮助您找出问题...
当您使用 IPv6 link-本地地址时,you must always use the scope along with it。 link-本地地址在没有其范围的情况下无效,因此您将收到 Invalid argument
错误。
例如,您必须使用 fe80::a00:27ff:fe9e:9c16%enp0s8
.
而不是使用 fe80::a00:27ff:fe9e:9c16
我尝试使用 pysnmp 启动 SNMP 代理。 对于 IPv4 和 IPv6 绑定,它与 localhost ('127.0.0.1' and '::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 专家帮助我吗?
谢谢。
UPDATE: I try to bind it with given suggestion, but is still doesn't work. the bind command was run from a new installed CentOS. but it still failed: [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 ~]#
One more update: I suppose the bind is failed due to my environment has some issue with IPv6 configuration. As I'm only able to get one IPv4 address by using "socket.getaddrinfo()" method.
Br, -焦大鹏
如果尝试多次绑定同一个套接字,您可能会收到此错误。但是我看不出你的代码是这样的。
那个 .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)
我希望像这样的测试可以帮助您找出问题...
当您使用 IPv6 link-本地地址时,you must always use the scope along with it。 link-本地地址在没有其范围的情况下无效,因此您将收到 Invalid argument
错误。
例如,您必须使用 fe80::a00:27ff:fe9e:9c16%enp0s8
.
fe80::a00:27ff:fe9e:9c16