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)
Example #2
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)
Example #3
0
    def CheckRecvmsg(self, family, addr):
        s = self._BuildSocket(family, addr)

        if family == AF_INET:
            s.setsockopt(SOL_IP, csocket.IP_PKTINFO, 1)
            s.setsockopt(SOL_IP, csocket.IP_RECVTTL, 1)
            pktinfo_addr = inet_pton(AF_INET, addr)
            pktinfo = (SOL_IP, csocket.IP_PKTINFO,
                       csocket.InPktinfo(
                           (LOOPBACK_IFINDEX, pktinfo_addr, pktinfo_addr)))
            ttl = (SOL_IP, csocket.IP_TTL, 64)
        elif family == AF_INET6:
            s.setsockopt(SOL_IPV6, csocket.IPV6_RECVPKTINFO, 1)
            s.setsockopt(SOL_IPV6, csocket.IPV6_RECVHOPLIMIT, 1)
            pktinfo_addr = inet_pton(AF_INET6, addr)
            pktinfo = (SOL_IPV6, csocket.IPV6_PKTINFO,
                       csocket.In6Pktinfo((pktinfo_addr, LOOPBACK_IFINDEX)))
            ttl = (SOL_IPV6, csocket.IPV6_HOPLIMIT, 64)

        addr = s.getsockname()
        sockaddr = csocket.Sockaddr(addr)
        s.sendto("foo", addr)
        data, addr, cmsg = csocket.Recvmsg(s, 4096, 1024, 0)
        self.assertEqual("foo", data)
        self.assertEqual(sockaddr, addr)
        self.assertEqual([pktinfo, ttl], cmsg)

        s.close()
  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)
Example #5
0
    def CheckRecvfrom(self, family, addr):
        s = self._BuildSocket(family, addr)
        addr = s.getsockname()
        sockaddr = csocket.Sockaddr(addr)
        s.sendto("foo", addr)
        data, addr = csocket.Recvfrom(s, 4096, 0)
        self.assertEqual("foo", data)
        self.assertEqual(sockaddr, addr)

        s.close()
Example #6
0
 def testPacketCount(self):
     self.map_fd = CreateMap(BPF_MAP_TYPE_HASH, 4, 4, 10)
     key = 0xf0f0
     bpf_prog = BpfMov64Reg(BPF_REG_6, BPF_REG_1)
     bpf_prog += BpfLoadMapFd(self.map_fd, BPF_REG_1)
     bpf_prog += BpfMov64Imm(BPF_REG_7, key)
     bpf_prog += BpfStxMem(BPF_W, BPF_REG_10, BPF_REG_7, -4)
     bpf_prog += BpfMov64Reg(BPF_REG_8, BPF_REG_10)
     bpf_prog += BpfAlu64Imm(BPF_ADD, BPF_REG_8, -4)
     bpf_prog += BpfMov64Reg(BPF_REG_2, BPF_REG_8)
     bpf_prog += BpfFuncLookupMap()
     bpf_prog += BpfJumpImm(BPF_AND, BPF_REG_0, 0, 10)
     bpf_prog += BpfLoadMapFd(self.map_fd, BPF_REG_1)
     bpf_prog += BpfMov64Reg(BPF_REG_2, BPF_REG_8)
     bpf_prog += BpfStMem(BPF_W, BPF_REG_10, -8, 1)
     bpf_prog += BpfMov64Reg(BPF_REG_3, BPF_REG_10)
     bpf_prog += BpfAlu64Imm(BPF_ADD, BPF_REG_3, -8)
     bpf_prog += BpfMov64Imm(BPF_REG_4, 0)
     bpf_prog += BpfFuncUpdateMap()
     bpf_prog += BpfLdxMem(BPF_W, BPF_REG_0, BPF_REG_6, 0)
     bpf_prog += BpfExitInsn()
     bpf_prog += BpfMov64Reg(BPF_REG_2, BPF_REG_0)
     bpf_prog += BpfMov64Imm(BPF_REG_1, 1)
     bpf_prog += BpfRawInsn(BPF_STX | BPF_XADD | BPF_W, BPF_REG_2,
                            BPF_REG_1, 0, 0)
     bpf_prog += BpfLdxMem(BPF_W, BPF_REG_0, BPF_REG_6, 0)
     bpf_prog += BpfExitInsn()
     insn_buff = ctypes.create_string_buffer(bpf_prog)
     # this program loaded is used to counting the packet transmitted through
     # a target socket. It will store the packet count into the eBPF map and we
     # will verify if the counting result is correct.
     self.prog_fd = BpfProgLoad(BPF_PROG_TYPE_SOCKET_FILTER,
                                ctypes.addressof(insn_buff), len(insn_buff),
                                BpfInsn._length)
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
     sock.settimeout(1)
     BpfProgAttachSocket(sock.fileno(), self.prog_fd)
     addr = "127.0.0.1"
     sock.bind((addr, 0))
     addr = sock.getsockname()
     sockaddr = csocket.Sockaddr(addr)
     packet_count = 100
     for i in xrange(packet_count):
         sock.sendto("foo", addr)
         data, retaddr = csocket.Recvfrom(sock, 4096, 0)
         self.assertEqual("foo", data)
         self.assertEqual(sockaddr, retaddr)
     self.assertEquals(LookupMap(self.map_fd, key).value, packet_count)
def SocketUDPLoopBack(packet_count, version, prog_fd):
    family = {4: socket.AF_INET, 6: socket.AF_INET6}[version]
    sock = socket.socket(family, socket.SOCK_DGRAM, 0)
    if prog_fd is not None:
        BpfProgAttachSocket(sock.fileno(), prog_fd)
    net_test.SetNonBlocking(sock)
    addr = {4: "127.0.0.1", 6: "::1"}[version]
    sock.bind((addr, 0))
    addr = sock.getsockname()
    sockaddr = csocket.Sockaddr(addr)
    for i in xrange(packet_count):
        sock.sendto("foo", addr)
        data, retaddr = csocket.Recvfrom(sock, 4096, 0)
        assert "foo" == data
        assert sockaddr == retaddr
    return sock
Example #8
0
 def testProgLoad(self):
     bpf_prog = BpfMov64Reg(BPF_REG_6, BPF_REG_1)
     bpf_prog += BpfLdxMem(BPF_W, BPF_REG_0, BPF_REG_6, 0)
     bpf_prog += BpfExitInsn()
     insn_buff = ctypes.create_string_buffer(bpf_prog)
     # Load a program that does nothing except pass every packet it receives
     # It should not block the packet transmission otherwise the test fails.
     self.prog_fd = BpfProgLoad(BPF_PROG_TYPE_SOCKET_FILTER,
                                ctypes.addressof(insn_buff), len(insn_buff),
                                BpfInsn._length)
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
     sock.settimeout(1)
     BpfProgAttachSocket(sock.fileno(), self.prog_fd)
     addr = "127.0.0.1"
     sock.bind((addr, 0))
     addr = sock.getsockname()
     sockaddr = csocket.Sockaddr(addr)
     sock.sendto("foo", addr)
     data, addr = csocket.Recvfrom(sock, 4096, 0)
     self.assertEqual("foo", data)
     self.assertEqual(sockaddr, addr)
    def testAddDelSa(self):
        src4 = csocket.Sockaddr(("192.0.2.1", 0))
        dst4 = csocket.Sockaddr(("192.0.2.2", 1))
        self.pf_key.AddSa(src4, dst4, 0xdeadbeef, pf_key.SADB_TYPE_ESP,
                          pf_key.IPSEC_MODE_TRANSPORT, 54321,
                          pf_key.SADB_X_EALG_AESCBC, ENCRYPTION_KEY,
                          pf_key.SADB_X_AALG_SHA2_256HMAC, ENCRYPTION_KEY)

        src6 = csocket.Sockaddr(("2001:db8::1", 0))
        dst6 = csocket.Sockaddr(("2001:db8::2", 0))
        self.pf_key.AddSa(src6, dst6, 0xbeefdead, pf_key.SADB_TYPE_ESP,
                          pf_key.IPSEC_MODE_TRANSPORT, 12345,
                          pf_key.SADB_X_EALG_AESCBC, ENCRYPTION_KEY,
                          pf_key.SADB_X_AALG_SHA2_256HMAC, ENCRYPTION_KEY)

        sainfos = self.xfrm.DumpSaInfo()
        self.assertEquals(2, len(sainfos))
        state4, attrs4 = [(s, a) for s, a in sainfos if s.family == AF_INET][0]
        state6, attrs6 = [(s, a) for s, a in sainfos
                          if s.family == AF_INET6][0]

        pfkey_sainfos = self.pf_key.DumpSaInfo()
        self.assertEquals(2, len(pfkey_sainfos))
        self.assertTrue(
            all(msg.satype == pf_key.SDB_TYPE_ESP) for msg, _ in pfkey_sainfos)

        self.assertEquals(xfrm.IPPROTO_ESP, state4.id.proto)
        self.assertEquals(xfrm.IPPROTO_ESP, state6.id.proto)
        self.assertEquals(54321, state4.reqid)
        self.assertEquals(12345, state6.reqid)
        self.assertEquals(0xdeadbeef, state4.id.spi)
        self.assertEquals(0xbeefdead, state6.id.spi)

        self.assertEquals(xfrm.PaddedAddress("192.0.2.1"), state4.saddr)
        self.assertEquals(xfrm.PaddedAddress("192.0.2.2"), state4.id.daddr)
        self.assertEquals(xfrm.PaddedAddress("2001:db8::1"), state6.saddr)
        self.assertEquals(xfrm.PaddedAddress("2001:db8::2"), state6.id.daddr)

        # The algorithm names are null-terminated, but after that contain garbage.
        # Kernel bug?
        aes_name = "cbc(aes)\x00"
        sha256_name = "hmac(sha256)\x00"
        self.assertTrue(attrs4["XFRMA_ALG_CRYPT"].name.startswith(aes_name))
        self.assertTrue(attrs6["XFRMA_ALG_CRYPT"].name.startswith(aes_name))
        self.assertTrue(attrs4["XFRMA_ALG_AUTH"].name.startswith(sha256_name))
        self.assertTrue(attrs6["XFRMA_ALG_AUTH"].name.startswith(sha256_name))

        self.assertEquals(256, attrs4["XFRMA_ALG_CRYPT"].key_len)
        self.assertEquals(256, attrs4["XFRMA_ALG_CRYPT"].key_len)
        self.assertEquals(256, attrs6["XFRMA_ALG_AUTH"].key_len)
        self.assertEquals(256, attrs6["XFRMA_ALG_AUTH"].key_len)
        self.assertEquals(256, attrs6["XFRMA_ALG_AUTH_TRUNC"].key_len)
        self.assertEquals(256, attrs6["XFRMA_ALG_AUTH_TRUNC"].key_len)

        self.assertEquals(128, attrs4["XFRMA_ALG_AUTH_TRUNC"].trunc_len)
        self.assertEquals(128, attrs4["XFRMA_ALG_AUTH_TRUNC"].trunc_len)

        self.pf_key.DelSa(src4, dst4, 0xdeadbeef, pf_key.SADB_TYPE_ESP)
        self.assertEquals(1, len(self.xfrm.DumpSaInfo()))
        self.pf_key.DelSa(src6, dst6, 0xbeefdead, pf_key.SADB_TYPE_ESP)
        self.assertEquals(0, len(self.xfrm.DumpSaInfo()))