def testCrossProtocolCrash(self):
    # Checks that an ICMP error containing a ping packet that matches the ID
    # of a socket of the wrong protocol (which can happen when using 464xlat)
    # doesn't crash the kernel.

    # We can only test this using IPv6 unreachables and IPv4 ping sockets,
    # because IPv4 packets sent by scapy.send() on loopback are not received by
    # the kernel. So we don't actually use this function yet.
    def GetIPv4Unreachable(port):  # pylint: disable=unused-variable
      return (scapy.IP(src="192.0.2.1", dst="127.0.0.1") /
              scapy.ICMP(type=3, code=0) /
              scapy.IP(src="127.0.0.1", dst="127.0.0.1") /
              scapy.ICMP(type=8, id=port, seq=1))

    def GetIPv6Unreachable(port):
      return (scapy.IPv6(src="::1", dst="::1") /
              scapy.ICMPv6DestUnreach() /
              scapy.IPv6(src="::1", dst="::1") /
              scapy.ICMPv6EchoRequest(id=port, seq=1, data="foobarbaz"))

    # An unreachable matching the ID of a socket of the wrong protocol
    # shouldn't crash.
    s = net_test.IPv4PingSocket()
    s.connect(("127.0.0.1", 12345))
    _, port = s.getsockname()
    scapy.send(GetIPv6Unreachable(port))
  def testIPv6Bind(self):
    # Bind to unspecified address.
    s = net_test.IPv6PingSocket()
    s.bind(("::", 769))
    self.assertEquals(("::", 769, 0, 0), s.getsockname())

    # Bind to loopback.
    s = net_test.IPv6PingSocket()
    s.bind(("::1", 99))
    self.assertEquals(("::1", 99, 0, 0), s.getsockname())

    # Binding twice is not allowed.
    self.assertRaisesErrno(errno.EINVAL, s.bind, ("::1", 22))

    # But binding two different sockets to the same ID is allowed.
    s2 = net_test.IPv6PingSocket()
    s2.bind(("::1", 99))
    self.assertEquals(("::1", 99, 0, 0), s2.getsockname())
    s3 = net_test.IPv6PingSocket()
    s3.bind(("::1", 99))
    self.assertEquals(("::1", 99, 0, 0), s3.getsockname())

    # Binding both IPv4 and IPv6 to the same socket works.
    s4 = net_test.IPv4PingSocket()
    s6 = net_test.IPv6PingSocket()
    s4.bind(("0.0.0.0", 444))
    s6.bind(("::", 666, 0, 0))

    # Can't bind after sendto.
    s = net_test.IPv6PingSocket()
    s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 9132))
    self.assertRaisesErrno(errno.EINVAL, s.bind, ("::", 5429))
  def testCrossProtocolCalls(self):
    """Tests that passing in the wrong family returns EAFNOSUPPORT."""

    def CheckEAFNoSupport(function, *args):
      self.assertRaisesErrno(errno.EAFNOSUPPORT, function, *args)

    ipv6sockaddr = csocket.Sockaddr((net_test.IPV6_ADDR, 53))

    # In order to check that IPv6 socket calls return EAFNOSUPPORT when passed
    # IPv4 socket address structures, we need to pass down a socket address
    # length argument that's at least sizeof(sockaddr_in6). Otherwise, the calls
    # will fail immediately with EINVAL because the passed-in socket length is
    # too short. So create a sockaddr_in that's as long as a sockaddr_in6.
    ipv4sockaddr = csocket.Sockaddr((net_test.IPV4_ADDR, 53))
    ipv4sockaddr = csocket.SockaddrIn6(
        ipv4sockaddr.Pack() +
        "\x00" * (len(csocket.SockaddrIn6) - len(csocket.SockaddrIn)))

    s4 = net_test.IPv4PingSocket()
    s6 = net_test.IPv6PingSocket()

    # We can't just call s.connect(), s.bind() etc. with a tuple of the wrong
    # address family, because the Python implementation will just pass garbage
    # down to the kernel. So call the C functions directly.
    CheckEAFNoSupport(csocket.Bind, s4, ipv6sockaddr)
    CheckEAFNoSupport(csocket.Bind, s6, ipv4sockaddr)
    CheckEAFNoSupport(csocket.Connect, s4, ipv6sockaddr)
    CheckEAFNoSupport(csocket.Connect, s6, ipv4sockaddr)
    CheckEAFNoSupport(csocket.Sendmsg,
                      s4, ipv6sockaddr, net_test.IPV4_PING, None, 0)
    CheckEAFNoSupport(csocket.Sendmsg,
                      s6, ipv4sockaddr, net_test.IPV6_PING, None, 0)
 def testIPv4Error(self):
   s = net_test.IPv4PingSocket()
   s.setsockopt(SOL_IP, IP_TTL, 2)
   s.setsockopt(SOL_IP, net_test.IP_RECVERR, 1)
   s.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 55))
   # We can't check the actual error because Python 2.7 doesn't implement
   # recvmsg, but we can at least check that the socket returns an error.
   self.assertRaisesErrno(errno.EHOSTUNREACH, s.recv, 32768)  # No response.
 def testIPv4NoCrash(self):
   # Python 2.x does not provide either read() or recvmsg.
   s = net_test.IPv4PingSocket()
   written = s.sendto(net_test.IPV4_PING, ("127.0.0.1", 55))
   self.assertEquals(len(net_test.IPV4_PING), written)
   fd = s.fileno()
   reply = posix.read(fd, 4096)
   self.assertEquals(written, len(reply))
Exemplo n.º 6
0
 def testIPv4InvalidBind(self):
     s = net_test.IPv4PingSocket()
     self.assertRaisesErrno(errno.EADDRNOTAVAIL, s.bind,
                            ("255.255.255.255", 1026))
     self.assertRaisesErrno(errno.EADDRNOTAVAIL, s.bind, ("224.0.0.1", 651))
     # Binding to an address we don't have only works with IP_TRANSPARENT.
     self.assertRaisesErrno(errno.EADDRNOTAVAIL, s.bind,
                            (net_test.IPV4_ADDR, 651))
     try:
         s.setsockopt(SOL_IP, net_test.IP_TRANSPARENT, 1)
         s.bind((net_test.IPV4_ADDR, 651))
     except IOError, e:
         if e.errno == errno.EACCES:
             pass  # We're not root. let it go for now.
  def testAfUnspecBind(self):
    # Binding to AF_UNSPEC is treated as IPv4 if the address is 0.0.0.0.
    s4 = net_test.IPv4PingSocket()
    sockaddr = csocket.Sockaddr(("0.0.0.0", 12996))
    sockaddr.family = AF_UNSPEC
    csocket.Bind(s4, sockaddr)
    self.assertEquals(("0.0.0.0", 12996), s4.getsockname())

    # But not if the address is anything else.
    sockaddr = csocket.Sockaddr(("127.0.0.1", 58234))
    sockaddr.family = AF_UNSPEC
    self.assertRaisesErrno(errno.EAFNOSUPPORT, csocket.Bind, s4, sockaddr)

    # This doesn't work for IPv6.
    s6 = net_test.IPv6PingSocket()
    sockaddr = csocket.Sockaddr(("::1", 58997))
    sockaddr.family = AF_UNSPEC
    self.assertRaisesErrno(errno.EAFNOSUPPORT, csocket.Bind, s6, sockaddr)
  def testIPv4Bind(self):
    # Bind to unspecified address.
    s = net_test.IPv4PingSocket()
    s.bind(("0.0.0.0", 544))
    self.assertEquals(("0.0.0.0", 544), s.getsockname())

    # Bind to loopback.
    s = net_test.IPv4PingSocket()
    s.bind(("127.0.0.1", 99))
    self.assertEquals(("127.0.0.1", 99), s.getsockname())

    # Binding twice is not allowed.
    self.assertRaisesErrno(errno.EINVAL, s.bind, ("127.0.0.1", 22))

    # But binding two different sockets to the same ID is allowed.
    s2 = net_test.IPv4PingSocket()
    s2.bind(("127.0.0.1", 99))
    self.assertEquals(("127.0.0.1", 99), s2.getsockname())
    s3 = net_test.IPv4PingSocket()
    s3.bind(("127.0.0.1", 99))
    self.assertEquals(("127.0.0.1", 99), s3.getsockname())

    # If two sockets bind to the same port, the first one to call read() gets
    # the response.
    s4 = net_test.IPv4PingSocket()
    s5 = net_test.IPv4PingSocket()
    s4.bind(("0.0.0.0", 167))
    s5.bind(("0.0.0.0", 167))
    s4.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 44))
    self.assertValidPingResponse(s5, net_test.IPV4_PING)
    net_test.SetSocketTimeout(s4, 100)
    self.assertRaisesErrno(errno.EAGAIN, s4.recv, 32768)

    # If SO_REUSEADDR is turned off, then we get EADDRINUSE.
    s6 = net_test.IPv4PingSocket()
    s4.setsockopt(SOL_SOCKET, SO_REUSEADDR, 0)
    self.assertRaisesErrno(errno.EADDRINUSE, s6.bind, ("0.0.0.0", 167))

    # Can't bind after sendto.
    s = net_test.IPv4PingSocket()
    s.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 9132))
    self.assertRaisesErrno(errno.EINVAL, s.bind, ("0.0.0.0", 5429))
 def testIPv4LargePacket(self):
   s = net_test.IPv4PingSocket()
   data = net_test.IPV4_PING + 20000 * "a"
   s.sendto(data, ("127.0.0.1", 987))
   self.assertValidPingResponse(s, data)
 def testIPv4PingUsingSendto(self):
   s = net_test.IPv4PingSocket()
   written = s.sendto(net_test.IPV4_PING, (net_test.IPV4_ADDR, 55))
   self.assertEquals(len(net_test.IPV4_PING), written)
   self.assertValidPingResponse(s, net_test.IPV4_PING)
 def testIPv4LoopbackPingWithConnect(self):
   s = net_test.IPv4PingSocket()
   s.connect(("127.0.0.1", 55))
   data = net_test.IPV4_PING + "foobarbaz"
   s.send(data)
   self.assertValidPingResponse(s, data)
 def testIPv4SendWithNoConnection(self):
   s = net_test.IPv4PingSocket()
   self.assertRaisesErrno(errno.EDESTADDRREQ, s.send, net_test.IPV4_PING)