def testProcNetIcmp6(self):
    numrows6 = len(self.ReadProcNetSocket("icmp6"))
    s = net_test.IPv6PingSocket()
    s.bind(("::1", 0xace))
    s.connect(("::1", 0xbeef))
    self.CheckSockStatFile("icmp6", "::1", 0xace, "::1", 0xbeef, 1)

    # Check the row goes away when the socket is closed.
    s.close()
    self.assertEquals(numrows6, len(self.ReadProcNetSocket("icmp6")))

    # Try send, bind and connect to check the addresses and the state.
    s = net_test.IPv6PingSocket()
    self.assertEqual(0, len(self.ReadProcNetSocket("icmp6")))
    s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 12345))
    self.assertEqual(1, len(self.ReadProcNetSocket("icmp6")))

    # Can't bind after sendto, apparently.
    s = net_test.IPv6PingSocket()
    self.assertEqual(0, len(self.ReadProcNetSocket("icmp6")))
    s.bind((self.lladdr, 0xd00d, 0, self.ifindex))
    self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "::", 0, 7)

    # Check receive bytes.
    s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_MULTICAST_IF, self.ifindex)
    s.connect(("ff02::1", 0xdead))
    self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "ff02::1", 0xdead, 1)
    s.send(net_test.IPV6_PING)
    time.sleep(0.01)  # Give the other thread time to reply.
    self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "ff02::1", 0xdead, 1,
                           txmem=0, rxmem=0x300)
    self.assertValidPingResponse(s, net_test.IPV6_PING)
    self.CheckSockStatFile("icmp6", self.lladdr, 0xd00d, "ff02::1", 0xdead, 1,
                           txmem=0, rxmem=0)
  def testBindAffectsIdentifier(self):
    s = net_test.IPv6PingSocket()
    s.bind((self.globaladdr, 0xf976))
    s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55))
    self.assertEquals("\xf9\x76", s.recv(32768)[4:6])

    s = net_test.IPv6PingSocket()
    s.bind((self.globaladdr, 0xace))
    s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55))
    self.assertEquals("\x0a\xce", s.recv(32768)[4:6])
  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 testFlowLabel(self):
    s = net_test.IPv6PingSocket()

    # Specifying a flowlabel without having set IPV6_FLOWINFO_SEND succeeds but
    # the flow label in the packet is not set.
    s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 93, 0xdead, 0))
    self.assertValidPingResponse(s, net_test.IPV6_PING)  # Checks flow label==0.

    # If IPV6_FLOWINFO_SEND is set on the socket, attempting to set a flow label
    # that is not registered with the flow manager should return EINVAL...
    s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_FLOWINFO_SEND, 1)
    # ... but this doesn't work yet.
    if False:
      self.assertRaisesErrno(errno.EINVAL, s.sendto, net_test.IPV6_PING,
                             (net_test.IPV6_ADDR, 93, 0xdead, 0))

    # After registering the flow label, it gets sent properly, appears in the
    # output packet, and is returned in the response.
    net_test.SetFlowLabel(s, net_test.IPV6_ADDR, 0xdead)
    self.assertEqual(1, s.getsockopt(net_test.SOL_IPV6,
                                     net_test.IPV6_FLOWINFO_SEND))
    s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 93, 0xdead, 0))
    _, src = s.recvfrom(32768)
    _, _, flowlabel, _ = src
    self.assertEqual(0xdead, flowlabel & 0xfffff)
 def testLinkLocalAddress(self):
   s = net_test.IPv6PingSocket()
   # Sending to a link-local address with no scope fails with EINVAL.
   self.assertRaisesErrno(errno.EINVAL,
                          s.sendto, net_test.IPV6_PING, ("fe80::1", 55))
   # Sending to link-local address with a scope succeeds. Note that Python
   # doesn't understand the "fe80::1%lo" format, even though it returns it.
   s.sendto(net_test.IPV6_PING, ("fe80::1", 55, 0, self.ifindex))
 def testIPv6NoCrash(self):
   # Python 2.x does not provide either read() or recvmsg.
   s = net_test.IPv6PingSocket()
   written = s.sendto(net_test.IPV6_PING, ("::1", 55))
   self.assertEquals(len(net_test.IPV6_PING), written)
   fd = s.fileno()
   reply = posix.read(fd, 4096)
   self.assertEquals(written, len(reply))
 def testMappedAddressFails(self):
   s = net_test.IPv6PingSocket()
   s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55))
   self.assertValidPingResponse(s, net_test.IPV6_PING)
   s.sendto(net_test.IPV6_PING, ("2001:4860:4860::8844", 55))
   self.assertValidPingResponse(s, net_test.IPV6_PING)
   self.assertRaisesErrno(errno.EINVAL, s.sendto, net_test.IPV6_PING,
                          ("::ffff:192.0.2.1", 55))
 def testIPv6Error(self):
   s = net_test.IPv6PingSocket()
   s.setsockopt(net_test.SOL_IPV6, IPV6_UNICAST_HOPS, 2)
   s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_RECVERR, 1)
   s.sendto(net_test.IPV6_PING, (net_test.IPV6_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 testIPv6MulticastPing(self):
   s = net_test.IPv6PingSocket()
   # Send a multicast ping and check we get at least one duplicate.
   # The setsockopt should not be necessary, but ping_v6_sendmsg has a bug.
   s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_MULTICAST_IF, self.ifindex)
   s.sendto(net_test.IPV6_PING, ("ff02::1", 55, 0, self.ifindex))
   self.assertValidPingResponse(s, net_test.IPV6_PING)
   self.assertValidPingResponse(s, net_test.IPV6_PING)
 def testIcmp6SocketsNotInIcmp(self):
   numrows = len(self.ReadProcNetSocket("icmp"))
   numrows6 = len(self.ReadProcNetSocket("icmp6"))
   s = net_test.IPv6PingSocket()
   s.bind(("::1", 0xace))
   s.connect(("::1", 0xbeef))
   self.assertEquals(numrows, len(self.ReadProcNetSocket("icmp")))
   self.assertEquals(numrows6 + 1, len(self.ReadProcNetSocket("icmp6")))
Esempio n. 11
0
    def testLinkLocalOif(self):
        """Checks that ping to link-local addresses works correctly.

    Relevant kernel commits:
      upstream net:
        5e45789 net: ipv6: Fix ping to link-local addresses.
    """
        for mode in ["oif", "ucast_oif", None]:
            s = net_test.IPv6PingSocket()
            for netid in self.NETIDS:
                s2 = net_test.IPv6PingSocket()
                dst = self._RouterAddress(netid, 6)
                self.assertTrue(dst.startswith("fe80:"))

                if mode:
                    self.SelectInterface(s, netid, mode)
                    self.SelectInterface(s2, netid, mode)
                    scopeid = 0
                else:
                    scopeid = self.ifindices[netid]

                if mode == "oif":
                    # If SO_BINDTODEVICE has been set, any attempt to send on another
                    # interface returns EINVAL.
                    othernetid = self.NETIDS[(self.NETIDS.index(netid) + 1) %
                                             len(self.NETIDS)]
                    otherscopeid = self.ifindices[othernetid]
                    self.assertRaisesErrno(errno.EINVAL, s.sendto,
                                           net_test.IPV6_PING,
                                           (dst, 55, 0, otherscopeid))
                    self.assertRaisesErrno(errno.EINVAL, s.connect,
                                           (dst, 55, 0, otherscopeid))

                # Try using both sendto and connect/send.
                # If we get a reply, we sent the packet out on the right interface.
                s.sendto(net_test.IPV6_PING, (dst, 123, 0, scopeid))
                self.assertValidPingResponse(s, net_test.IPV6_PING)

                # IPV6_UNICAST_IF doesn't work on connected sockets.
                if mode != "ucast_oif":
                    s2.connect((dst, 123, 0, scopeid))
                    s2.send(net_test.IPV6_PING)
                    self.assertValidPingResponse(s2, net_test.IPV6_PING)
Esempio n. 12
0
    def testIPv6ScopedBind(self):
        # Can't bind to a link-local address without a scope ID.
        s = net_test.IPv6PingSocket()
        self.assertRaisesErrno(errno.EINVAL, s.bind, (self.lladdr, 1026, 0, 0))

        # Binding to a link-local address with a scope ID works, and the scope ID is
        # returned by a subsequent getsockname. Interestingly, Python's getsockname
        # returns "fe80:1%foo", even though it does not understand it.
        expected = self.lladdr + "%" + self.ifname
        s.bind((self.lladdr, 4646, 0, self.ifindex))
        self.assertEquals((expected, 4646, 0, self.ifindex), s.getsockname())

        # Of course, for the above to work the address actually has to be configured
        # on the machine.
        self.assertRaisesErrno(errno.EADDRNOTAVAIL, s.bind,
                               ("fe80::f00", 1026, 0, 1))

        # Scope IDs on non-link-local addresses are silently ignored.
        s = net_test.IPv6PingSocket()
        s.bind(("::1", 1234, 0, 1))
        self.assertEquals(("::1", 1234, 0, 0), s.getsockname())
  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))
Esempio n. 14
0
    def testIPv6MTU(self):
        """Tests IPV6_RECVERR and path MTU discovery on ping sockets.

    Relevant kernel commits:
      upstream net-next:
        dcb94b8 ipv6: fix endianness error in icmpv6_err
    """
        s = net_test.IPv6PingSocket()
        s.setsockopt(net_test.SOL_IPV6, csocket.IPV6_DONTFRAG, 1)
        s.setsockopt(net_test.SOL_IPV6, csocket.IPV6_MTU_DISCOVER, 2)
        s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_RECVERR, 1)
        s.connect((net_test.IPV6_ADDR, 55))
        pkt = net_test.IPV6_PING + (PingReplyThread.LINK_MTU + 100) * "a"
        s.send(pkt)
        self.assertRaisesErrno(errno.EMSGSIZE, s.recv, 32768)
        data, addr, cmsg = csocket.Recvmsg(s, 4096, 1024, csocket.MSG_ERRQUEUE)

        # Compare the offending packet with the one we sent. To do this we need to
        # calculate the ident of the packet we sent and blank out the checksum of
        # the one we received.
        ident = struct.pack("!H", s.getsockname()[1])
        pkt = pkt[:4] + ident + pkt[6:]
        data = data[:2] + "\x00\x00" + pkt[4:]
        self.assertEquals(pkt, data)

        # Check the address that the packet was sent to.
        # ... except in 4.1, where it just returns an AF_UNSPEC, like this:
        # recvmsg(9, {msg_name(0)={sa_family=AF_UNSPEC,
        #     sa_data="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
        #     msg_iov(1)=[{"\x80\x00\x04\x6b\x00\xc4\x00\x03\x61\x61\x61\x61\x61\x61"..., 4096}],
        #     msg_controllen=64, {cmsg_len=60, cmsg_level=SOL_IPV6, cmsg_type=, ...},
        #     msg_flags=MSG_ERRQUEUE}, MSG_ERRQUEUE) = 1232
        if net_test.LINUX_VERSION != (4, 1, 0):
            self.assertEquals(csocket.Sockaddr(("2001:4860:4860::8888", 0)),
                              addr)

        # Check the cmsg data, including the link MTU.
        mtu = PingReplyThread.LINK_MTU
        src = self.reply_threads[self.netid].INTERMEDIATE_IPV6
        msglist = [(net_test.SOL_IPV6, net_test.IPV6_RECVERR,
                    (csocket.SockExtendedErr(
                        (errno.EMSGSIZE, csocket.SO_ORIGIN_ICMP6,
                         ICMPV6_PKT_TOOBIG, 0, mtu, 0)),
                     csocket.Sockaddr((src, 0))))]

        # IP[V6]_RECVERR in 3.10 appears to return incorrect data for the port.
        # The fix might have been in 676d236, but we don't have that in 3.10 and it
        # touches code all over the tree. Instead, just don't check the port.
        if net_test.LINUX_VERSION <= (3, 14, 0):
            msglist[0][2][1].port = cmsg[0][2][1].port

        self.assertEquals(msglist, cmsg)
Esempio n. 15
0
    def testIPv6InvalidBind(self):
        s = net_test.IPv6PingSocket()
        self.assertRaisesErrno(errno.EINVAL, s.bind, ("ff02::2", 1026))

        # Binding to an address we don't have only works with IPV6_TRANSPARENT.
        self.assertRaisesErrno(errno.EADDRNOTAVAIL, s.bind,
                               (net_test.IPV6_ADDR, 651))
        try:
            s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_TRANSPARENT, 1)
            s.bind((net_test.IPV6_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 testIPv6LargePacket(self):
   s = net_test.IPv6PingSocket()
   s.bind(("::", 0xace))
   data = net_test.IPV6_PING + "\x01" + 19994 * "\x00" + "aaaaa"
   s.sendto(data, ("::1", 953))
 def testIPv6SendWithNoConnection(self):
   s = net_test.IPv6PingSocket()
   self.assertRaisesErrno(errno.EDESTADDRREQ, s.send, net_test.IPV6_PING)
 def testIPv6LoopbackPingWithConnect(self):
   s = net_test.IPv6PingSocket()
   s.connect(("::1", 55))
   s.send(net_test.IPV6_PING)
   self.assertValidPingResponse(s, net_test.IPV6_PING)
 def testIPv6PingUsingSendto(self):
   s = net_test.IPv6PingSocket()
   written = s.sendto(net_test.IPV6_PING, (net_test.IPV6_ADDR, 55))
   self.assertEquals(len(net_test.IPV6_PING), written)
   self.assertValidPingResponse(s, net_test.IPV6_PING)