【问题标题】:Python raw IPv6 socket errorsPython 原始 IPv6 套接字错误
【发布时间】:2010-10-19 21:58:19
【问题描述】:

我在 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 本地主机地址作为 self._interface ("::1") 我实际上可以绑定地址,但不能发送任何东西:

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

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

【问题讨论】:

    标签: python ipv6 raw-sockets


    【解决方案1】:

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

    关键问题是:

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

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

    最后,堆栈(至少在 Linux mint 15 上)对 ipv6 数据包更加严格。如果您尝试发送一个空的 icmpv4 回显请求,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')
    

    【讨论】:

      【解决方案2】:

      我不明白你对bindsendall 的组合。据我了解,bind 用于服务器套接字,sendall 需要连接。您是说connect 而不是bind

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

      这对我有用(作为 root):

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

      编辑: 糟糕,我第一次没有看到您实际上设法将套接字绑定到一个地址。但是,您的第二个问题很明显:您必须先连接到某个地址,然后才能发送数据。或者使用带有地址的sendto。这与 IPv4 没有什么不同。

      【讨论】:

      【解决方案3】:

      此代码提供了一个具有 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)
      

      【讨论】:

        猜你喜欢
        • 2014-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        • 1970-01-01
        • 2012-01-19
        相关资源
        最近更新 更多