Python原始IPv6套接字错误

时间:2010-10-19 21:58:20

标签: python ipv6 raw-sockets

我在python中使用原始IPv6套接字时遇到一些问题。我通过以下方式连接:

    if self._socket != None:
        # Close out old socket first
        self._socket.close()
    self._socket = socket.socket(socket.AF_INET6, socket.SOCK_RAW)
    self._socket.bind((self._interface,0))
    self._socket.sendall(data)

其中self._interface是我的本地地址;特别是“fe80 :: fa1e:dfff:fed6:221d”。尝试此操作时,我收到以下错误:

  File "raw.py", line 164, in connect
    self._socket.bind((self._interface,0))
  File "<string>", line 1, in bind
socket.error: [Errno 49] Can't assign requested address

如果我将我的ipv6 localhost地址用于self._interface(“:: 1”)我实际上可以绑定地址,但不能发送任何内容:

    self._socket.sendall(data)
  File "<string>", line 1, in sendall
socket.error: [Errno 39] Destination address required

为什么原始套接字需要目标地址?有没有人在python中使用原始IPv6套接字,可以帮助我理解为什么会发生这种情况?

3 个答案:

答案 0 :(得分:2)

虽然这是一个老问题,但我想添加一个有效的答案并帮助任何后来偶然发现它的人。

关键问题是:

原始套接字未绑定并连接到其他套接字。 sendto 也是正确使用的API。

此外,ipv6数据包需要4个目标地址元组结构,而ipv4需要2个元组结构。

最后,堆栈(至少在Linux模板15上)对ipv6数据包更严格。如果你尝试发送一个空的icmpv4 echo请求,python允许它并在线路上发送一个意义较少的数据包。在ipv6的情况下,当您尝试发送空数据包时,它只会给出“无效参数”错误。因此,在ipv6的情况下也需要有效的请求。以下示例对ipv6执行全部操作并发送有效的ping回应请求以回送地址。

import socket

def main(dest_name):
    addrs = socket.getaddrinfo(dest_name, 0, socket.AF_INET6, 0, socket.SOL_IP)


    print addrs
    dest = addrs[0]

    # A minimal ICMP6-echo message (thanks to abarnert)
    data = '\x80\0\0\0\0\0\0\0'

    icmp = socket.getprotobyname('ipv6-icmp')
    #print icmp

    send_socket = socket.socket(socket.AF_INET6, socket.SOCK_RAW, icmp)
    print "sent to " + str(dest[4])
    send_socket.sendto(data, dest[4])
    send_socket.close()

if __name__ == '__main__':
    main('::1')

答案 1 :(得分:0)

我不理解您bindsendall的组合。据我了解,bind用于服务器套接字,sendall需要连接。您的意思是connect而不是bind吗?

无论如何,根据手册页IN6ADDR_ANY_INIT,相当于INADDR_ANY的IPv6。 Python没有为它定义常量,但这与'::'(全为零)相同。

这对我有用(作为根):

>>> import socket
>>> s = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)
>>> s.bind(('::', 0))

修改 糟糕,我首先没有看到你真的设法将套接字绑定到一个地址。但是,您的第二个问题显而易见:您必须首先连接到某个地址才能发送数据。或者将sendto与地址一起使用。这与IPv4没有什么不同。

答案 2 :(得分:0)

此代码提供具有L2访问权限的原始套接字。不幸的是OSX不支持socket.PF_PACKET ......

soc = socket.socket(socket.PF_PACKET, socket.SOCK_RAW) #create the raw-socket
soc.bind(("lo0", 0))

soc.send(packet)