コード例 #1
0
ファイル: xfrm_test.py プロジェクト: fukehan/kernel
    def _CheckNullEncryptionTunnelMode(self, version):
        family = net_test.GetAddressFamily(version)
        netid = self.RandomNetid()
        local_addr = self.MyAddress(version, netid)
        remote_addr = self.GetRemoteAddress(version)

        # Borrow the address of another netId as the source address of the tunnel
        tun_local = self.MyAddress(version, self.RandomNetid(netid))
        # For generality, pick a tunnel endpoint that's not the address we
        # connect the socket to.
        tun_remote = TUNNEL_ENDPOINTS[version]

        # Output
        self.xfrm.AddSaInfo(tun_local, tun_remote, 0xABCD,
                            xfrm.XFRM_MODE_TUNNEL, 123,
                            xfrm_base._ALGO_CRYPT_NULL,
                            xfrm_base._ALGO_AUTH_NULL, None, None, None, netid)
        # Input
        self.xfrm.AddSaInfo(tun_remote, tun_local, 0x9876,
                            xfrm.XFRM_MODE_TUNNEL, 456,
                            xfrm_base._ALGO_CRYPT_NULL,
                            xfrm_base._ALGO_AUTH_NULL, None, None, None, None)

        sock = net_test.UDPSocket(family)
        self.SelectInterface(sock, netid, "mark")
        sock.bind((local_addr, 0))
        local_port = sock.getsockname()[1]
        remote_port = 5555

        xfrm_base.ApplySocketPolicy(sock, family, xfrm.XFRM_POLICY_OUT, 0xABCD,
                                    123, (tun_local, tun_remote))
        xfrm_base.ApplySocketPolicy(sock, family, xfrm.XFRM_POLICY_IN, 0x9876,
                                    456, (tun_remote, tun_local))

        # Create and receive an ESP packet.
        IpType = {4: scapy.IP, 6: scapy.IPv6}[version]
        input_pkt = (IpType(src=remote_addr, dst=local_addr) /
                     scapy.UDP(sport=remote_port, dport=local_port) /
                     "input hello")
        input_pkt = IpType(str(input_pkt))  # Compute length, checksum.
        input_pkt = xfrm_base.EncryptPacketWithNull(input_pkt, 0x9876, 1,
                                                    (tun_remote, tun_local))

        self.ReceivePacketOn(netid, input_pkt)
        msg, addr = sock.recvfrom(1024)
        self.assertEquals("input hello", msg)
        self.assertEquals((remote_addr, remote_port), addr[:2])

        # Send and capture a packet.
        sock.sendto("output hello", (remote_addr, remote_port))
        packets = self.ReadAllPacketsOn(netid)
        self.assertEquals(1, len(packets))
        output_pkt = packets[0]
        output_pkt, esp_hdr = xfrm_base.DecryptPacketWithNull(output_pkt)
        self.assertEquals(output_pkt[scapy.UDP].len, len("output_hello") + 8)
        self.assertEquals(remote_addr, output_pkt.dst)
        self.assertEquals(remote_port, output_pkt[scapy.UDP].dport)
        # length of the payload plus the UDP header
        self.assertEquals("output hello", str(output_pkt[scapy.UDP].payload))
        self.assertEquals(0xABCD, esp_hdr.spi)
コード例 #2
0
  def CheckPktinfoRouting(self, version):
    for _ in xrange(self.ITERATIONS):
      for netid in self.tuns:
        family = self.GetProtocolFamily(version)
        s = net_test.UDPSocket(family)

        if version == 6:
          # Create a flowlabel so we can use it.
          net_test.SetFlowLabel(s, net_test.IPV6_ADDR, 0xbeef)

          # Specify some arbitrary options.
          cmsgs = [
              (net_test.SOL_IPV6, IPV6_HOPLIMIT, 39),
              (net_test.SOL_IPV6, IPV6_TCLASS, 0x83),
              (net_test.SOL_IPV6, IPV6_FLOWINFO, int(htonl(0xbeef))),
          ]
        else:
          # Support for setting IPv4 TOS and TTL via cmsg only appeared in 3.13.
          cmsgs = []
          s.setsockopt(net_test.SOL_IP, IP_TTL, 39)
          s.setsockopt(net_test.SOL_IP, IP_TOS, 0x83)

        dstaddr = self.GetRemoteAddress(version)
        self.SendOnNetid(version, s, dstaddr, 53, netid, UDP_PAYLOAD, cmsgs)

        sport = s.getsockname()[1]
        srcaddr = self.MyAddress(version, netid)

        desc, expected = packets.UDPWithOptions(version, srcaddr, dstaddr,
                                                sport=sport)

        msg = "IPv%d UDP using pktinfo routing: expected %s on %s" % (
            version, desc, self.GetInterfaceName(netid))
        self.ExpectPacketOn(netid, msg, expected)
コード例 #3
0
 def CheckIPv6Connectivity(expect_connectivity):
   for netid in self.NETIDS:
     s = net_test.UDPSocket(AF_INET6)
     self.SetSocketMark(s, netid)
     if expect_connectivity:
       self.assertTrue(s.sendto(UDP_PAYLOAD, (net_test.IPV6_ADDR, 1234)))
     else:
       self.assertRaisesErrno(errno.ENETUNREACH, s.sendto, UDP_PAYLOAD,
                              (net_test.IPV6_ADDR, 1234))
コード例 #4
0
    def testIPv6StickyPktinfo(self):
        for _ in xrange(self.ITERATIONS):
            for netid in self.tuns:
                s = net_test.UDPSocket(AF_INET6)

                # Set a flowlabel.
                net_test.SetFlowLabel(s, net_test.IPV6_ADDR, 0xdead)
                s.setsockopt(net_test.SOL_IPV6, net_test.IPV6_FLOWINFO_SEND, 1)

                # Set some destination options.
                nonce = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c"
                dstopts = "".join([
                    "\x11\x02",  # Next header=UDP, 24 bytes of options.
                    "\x01\x06",
                    "\x00" * 6,  # PadN, 6 bytes of padding.
                    "\x8b\x0c",  # ILNP nonce, 12 bytes.
                    nonce
                ])
                s.setsockopt(net_test.SOL_IPV6, IPV6_DSTOPTS, dstopts)
                s.setsockopt(net_test.SOL_IPV6, IPV6_UNICAST_HOPS, 255)

                pktinfo = multinetwork_base.MakePktInfo(
                    6, None, self.ifindices[netid])

                # Set the sticky pktinfo option.
                s.setsockopt(net_test.SOL_IPV6, IPV6_PKTINFO, pktinfo)

                # Specify the flowlabel in the destination address.
                s.sendto(UDP_PAYLOAD, (net_test.IPV6_ADDR, 53, 0xdead, 0))

                sport = s.getsockname()[1]
                srcaddr = self.MyAddress(6, netid)
                expected = (scapy.IPv6(
                    src=srcaddr, dst=net_test.IPV6_ADDR, fl=0xdead, hlim=255) /
                            scapy.IPv6ExtHdrDestOpt(options=[
                                scapy.PadN(optdata="\x00\x00\x00\x00\x00\x00"),
                                scapy.HBHOptUnknown(otype=0x8b, optdata=nonce)
                            ]) / scapy.UDP(sport=sport, dport=53) /
                            UDP_PAYLOAD)
                msg = "IPv6 UDP using sticky pktinfo: expected UDP packet on %s" % (
                    self.GetInterfaceName(netid))
                self.ExpectPacketOn(netid, msg, expected)
コード例 #5
0
    def testReadInterrupted(self):
        """Tests that read() is interrupted by SOCK_DESTROY."""
        for version in [4, 5, 6]:
            family = {4: AF_INET, 5: AF_INET6, 6: AF_INET6}[version]
            s = net_test.UDPSocket(family)
            self.SelectInterface(s, random.choice(self.NETIDS), "mark")
            addr = self.GetRemoteAddress(version)

            # Check that reads on connected sockets are interrupted.
            s.connect((addr, 53))
            self.assertEquals(3, s.send("foo"))
            self.CloseDuringBlockingCall(s, lambda sock: sock.recv(4096),
                                         ECONNABORTED)

            # A destroyed socket is no longer connected, but still usable.
            self.assertRaisesErrno(EDESTADDRREQ, s.send, "foo")
            self.assertEquals(3, s.sendto("foo", (addr, 53)))

            # Check that reads on unconnected sockets are also interrupted.
            self.CloseDuringBlockingCall(s, lambda sock: sock.recv(4096),
                                         ECONNABORTED)
コード例 #6
0
    def CheckRemarking(self, version, use_connect):
        # Remarking or resetting UNICAST_IF on connected sockets does not work.
        if use_connect:
            modes = ["oif"]
        else:
            modes = ["mark", "oif"]
            if HAVE_UNICAST_IF:
                modes += ["ucast_oif"]

        for mode in modes:
            s = net_test.UDPSocket(self.GetProtocolFamily(version))

            # Figure out what packets to expect.
            unspec = {4: "0.0.0.0", 6: "::"}[version]
            sport = Packets.RandomPort()
            s.bind((unspec, sport))
            dstaddr = {4: self.IPV4_ADDR, 6: self.IPV6_ADDR}[version]
            desc, expected = Packets.UDP(version, unspec, dstaddr, sport)

            # If we're testing connected sockets, connect the socket on the first
            # netid now.
            if use_connect:
                netid = self.tuns.keys()[0]
                self.SelectInterface(s, netid, mode)
                s.connect((dstaddr, 53))
                expected.src = self.MyAddress(version, netid)

            # For each netid, select that network without closing the socket, and
            # check that the packets sent on that socket go out on the right network.
            for netid in self.tuns:
                self.SelectInterface(s, netid, mode)
                if not use_connect:
                    expected.src = self.MyAddress(version, netid)
                s.sendto(UDP_PAYLOAD, (dstaddr, 53))
                connected_str = "Connected" if use_connect else "Unconnected"
                msg = "%s UDPv%d socket remarked using %s: expecting %s on %s" % (
                    connected_str, version, mode, desc,
                    self.GetInterfaceName(netid))
                self.ExpectPacketOn(netid, msg, expected)
                self.SelectInterface(s, None, mode)
コード例 #7
0
    def testOnlinkCommunication(self):
        """Checks that on-link communication goes direct and not through routers."""
        for netid in self.tuns:
            # Send a UDP packet to a random on-link destination.
            s = net_test.UDPSocket(AF_INET6)
            iface = self.GetInterfaceName(netid)
            self.BindToDevice(s, iface)
            # dstaddr can never be our address because GetRandomDestination only fills
            # in the lower 32 bits, but our address has 0xff in the byte before that
            # (since it's constructed from the EUI-64 and so has ff:fe in the middle).
            dstaddr = self.GetRandomDestination(self.IPv6Prefix(netid))
            s.sendto(UDP_PAYLOAD, (dstaddr, 53))

            # Expect an NS for that destination on the interface.
            myaddr = self.MyAddress(6, netid)
            mymac = self.MyMacAddress(netid)
            desc, expected = Packets.NS(myaddr, dstaddr, mymac)
            msg = "Sending UDP packet to on-link destination: expecting %s" % desc
            time.sleep(
                0.0001)  # Required to make the test work on kernel 3.1(!)
            self.ExpectPacketOn(netid, msg, expected)

            # Send an NA.
            tgtmac = "02:00:00:00:%02x:99" % netid
            _, reply = Packets.NA(dstaddr, myaddr, tgtmac)
            # Don't use ReceivePacketOn, since that uses the router's MAC address as
            # the source. Instead, construct our own Ethernet header with source
            # MAC of tgtmac.
            reply = scapy.Ether(src=tgtmac, dst=mymac) / reply
            self.ReceiveEtherPacketOn(netid, reply)

            # Expect the kernel to send the original UDP packet now that the ND cache
            # entry has been populated.
            sport = s.getsockname()[1]
            desc, expected = Packets.UDP(6, myaddr, dstaddr, sport=sport)
            msg = "After NA response, expecting %s" % desc
            self.ExpectPacketOn(netid, msg, expected)
コード例 #8
0
    def CheckForwardingUdp(self, netid, iface1, iface2):
        # TODO: Make a test for IPv4
        # 1. Make version as an argument. Pick address to bind from array based
        #    on version.
        # 2. The prefix length of the address is hardcoded to /64. Use the subnet
        #    mask there instead.
        # 3. We recreate the address with SendRA, which obviously only works for
        #    IPv6. Use AddAddress for IPv4.

        # Create a UDP socket and bind to it
        version = 6
        s = net_test.UDPSocket(AF_INET6)
        self.SetSocketMark(s, netid)
        s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        s.bind(("::", 53))

        remoteaddr = self.GetRemoteAddress(version)
        myaddr = self.MyAddress(version, netid)

        try:
            # Delete address and check if packet is forwarded
            # (and not dropped because an incorrect socket match happened)
            self.iproute.DelAddress(myaddr, 64, self.ifindices[netid])
            hoplimit = 39
            desc, udp_pkt = packets.UDPWithOptions(version, myaddr, remoteaddr,
                                                   53)
            # Decrements the hoplimit of a packet to simulate forwarding.
            desc_fwded, udp_fwd = packets.UDPWithOptions(
                version, myaddr, remoteaddr, 53, hoplimit - 1)
            msg = "Sent %s, expected %s" % (desc, desc_fwded)
            self.ReceivePacketOn(iface1, udp_pkt)
            self.ExpectPacketOn(iface2, msg, udp_fwd)
        finally:
            # Recreate the address.
            self.SendRA(netid)
            s.close()
コード例 #9
0
 def BindToAddress(self, address):
     s = net_test.UDPSocket(AF_INET6)
     s.bind((address, 0, 0, 0))
コード例 #10
0
  def CheckRemarking(self, version, use_connect):
    modes = ["mark", "oif", "uid"]
    # Setting UNICAST_IF on connected sockets does not work.
    if not use_connect and HAVE_UNICAST_IF:
      modes += ["ucast_oif"]

    for mode in modes:
      s = net_test.UDPSocket(self.GetProtocolFamily(version))

      # Figure out what packets to expect.
      sport = net_test.BindRandomPort(version, s)
      dstaddr = {4: self.IPV4_ADDR, 6: self.IPV6_ADDR}[version]
      unspec = {4: "0.0.0.0", 6: "::"}[version]  # Placeholder.
      desc, expected = packets.UDP(version, unspec, dstaddr, sport)

      # If we're testing connected sockets, connect the socket on the first
      # netid now.
      if use_connect:
        netid = self.tuns.keys()[0]
        self.SelectInterface(s, netid, mode)
        s.connect((dstaddr, 53))
        expected.src = self.MyAddress(version, netid)

      # For each netid, select that network without closing the socket, and
      # check that the packets sent on that socket go out on the right network.
      #
      # For connected sockets, routing is cached in the socket's destination
      # cache entry. In this case, we check that just re-selecting the netid
      # (except via SO_BINDTODEVICE) does not change routing, but that
      # subsequently invalidating the destination cache entry does. Arguably
      # this is a bug in the kernel because re-selecting the netid should cause
      # routing to change. But it is a convenient way to check that
      # InvalidateDstCache actually works.
      prevnetid = None
      for netid in self.tuns:
        self.SelectInterface(s, netid, mode)
        if not use_connect:
          expected.src = self.MyAddress(version, netid)

        def ExpectSendUsesNetid(netid):
          connected_str = "Connected" if use_connect else "Unconnected"
          msg = "%s UDPv%d socket remarked using %s: expecting %s on %s" % (
              connected_str, version, mode, desc, self.GetInterfaceName(netid))
          if use_connect:
            s.send(UDP_PAYLOAD)
          else:
            s.sendto(UDP_PAYLOAD, (dstaddr, 53))
          self.ExpectPacketOn(netid, msg, expected)

        if use_connect and mode in ["mark", "uid", "ucast_oif"]:
          # If we have a destination cache entry, packets are not rerouted...
          if prevnetid:
            ExpectSendUsesNetid(prevnetid)
            # ... until we invalidate it.
            self.InvalidateDstCache(version, dstaddr, prevnetid)
          ExpectSendUsesNetid(netid)
        else:
          ExpectSendUsesNetid(netid)

        self.SelectInterface(s, None, mode)
        prevnetid = netid