Beispiel #1
0
 def test__write(self):
     ts = int(time.time())
     expected_time = datetime.fromtimestamp(ts)
     pkt_sender_mac = '01:02:03:04:05:06'
     pkt_sender_ip = '192.168.0.1'
     pkt_target_ip = '192.168.0.2'
     pkt_target_mac = '00:00:00:00:00:00'
     eth_src = '02:03:04:05:06:07'
     eth_dst = 'ff:ff:ff:ff:ff:ff'
     arp_packet = make_arp_packet(pkt_sender_ip, pkt_sender_mac,
                                  pkt_target_ip, pkt_target_mac)
     arp = ARP(arp_packet,
               time=ts,
               src_mac=hex_str_to_bytes(eth_src),
               dst_mac=hex_str_to_bytes(eth_dst),
               vid=100)
     out = io.StringIO()
     arp.write(out)
     expected_output = dedent("""\
     ARP observed at {expected_time}:
        802.1q VLAN ID (VID): 100 (0x064)
             Ethernet source: {eth_src}
        Ethernet destination: {eth_dst}
               Hardware type: 0x0001
               Protocol type: 0x0800
     Hardware address length: 6
     Protocol address length: 4
                   Operation: 1 (request)
     Sender hardware address: {pkt_sender_mac}
     Sender protocol address: {pkt_sender_ip}
     Target hardware address: {pkt_target_mac}
     Target protocol address: {pkt_target_ip}
     """)
     self.assertThat(out.getvalue().strip(),
                     Equals(expected_output.format(**locals()).strip()))
Beispiel #2
0
class ETHERTYPE:
    """Enumeration to represent ethertypes that MAAS needs to understand."""

    IPV4 = hex_str_to_bytes("0800")
    IPV6 = hex_str_to_bytes("86dd")
    ARP = hex_str_to_bytes("0806")
    VLAN = hex_str_to_bytes("8100")
Beispiel #3
0
def make_ipv6_packet(
    payload_length=None,
    version=None,
    payload=None,
    protocol=0x11,
    truncated=False,
):
    """Construct an IPv6 packet using the specified parameters."""
    if payload is None:
        payload = b""
    if payload_length is None:
        payload_length = len(payload)
    if version is None:
        version = 6
    version__traffic_class__flow_label = (version << 28).to_bytes(4, "big")

    ipv6_packet = (
        # Version, traffic class, flow label
        version__traffic_class__flow_label +
        # Total length in bytes
        payload_length.to_bytes(2, "big") +
        # Next header (default is UDP)
        protocol.to_bytes(1, "big") +
        # Hop limit (TTL)
        hex_str_to_bytes("00") +
        # Source address
        hex_str_to_bytes("00000000000000000000000000000000") +
        # Destination address
        hex_str_to_bytes("00000000000000000000000000000000"))
    assert len(ipv6_packet) == 40, "Length was %d" % len(ipv6_packet)
    if truncated:
        return ipv6_packet[:19]
    ipv6_packet = ipv6_packet + payload
    return ipv6_packet
Beispiel #4
0
def make_udp_packet(
    total_length=None,
    payload=None,
    truncated_header=False,
    truncated_payload=False,
):
    """Construct an IPv4 packet using the specified parameters.

    If the specified `vid` is not None, it is interpreted as an integer VID,
    and the appropriate Ethertype fields are adjusted.
    """
    if payload is None:
        payload = b""
    if total_length is None:
        total_length = 8 + len(payload)

    udp_packet = (
        # Source port
        hex_str_to_bytes("0000") +
        # Destination port
        hex_str_to_bytes("0000") +
        # UDP header length + payload length
        total_length.to_bytes(2, "big") +
        # Checksum
        hex_str_to_bytes("0000"))
    assert len(udp_packet) == 8, "Length was %d" % len(udp_packet)
    if truncated_header:
        return udp_packet[:7]
    udp_packet = udp_packet + payload
    if truncated_payload:
        return udp_packet[:-1]
    return udp_packet
Beispiel #5
0
 def test__parses_non_vlan(self):
     src_mac = factory.make_mac_address()
     dst_mac = factory.make_mac_address()
     ethertype = ETHERTYPE.ARP
     payload = factory.make_bytes(48)
     eth = Ethernet(
         make_ethernet_packet(dst_mac=dst_mac,
                              src_mac=src_mac,
                              ethertype=ethertype,
                              payload=payload))
     self.assertThat(eth.dst_mac, Equals(hex_str_to_bytes(dst_mac)))
     self.assertThat(eth.src_mac, Equals(hex_str_to_bytes(src_mac)))
     self.assertThat(eth.ethertype, Equals(ethertype))
     self.assertThat(eth.payload, Equals(payload))
     self.assertThat(eth.is_valid(), Equals(True))
Beispiel #6
0
 def test__properties(self):
     pkt_sender_mac = '01:02:03:04:05:06'
     pkt_sender_ip = '192.168.0.1'
     pkt_target_ip = '192.168.0.2'
     pkt_target_mac = '00:00:00:00:00:00'
     eth_src = '02:03:04:05:06:07'
     eth_dst = 'ff:ff:ff:ff:ff:ff'
     arp_packet = make_arp_packet(pkt_sender_ip, pkt_sender_mac,
                                  pkt_target_ip, pkt_target_mac)
     arp = ARP(arp_packet,
               src_mac=hex_str_to_bytes(eth_src),
               dst_mac=hex_str_to_bytes(eth_dst))
     self.assertThat(arp.source_eui, Equals(EUI(pkt_sender_mac)))
     self.assertThat(arp.target_eui, Equals(EUI(pkt_target_mac)))
     self.assertThat(arp.source_ip, Equals(IPAddress(pkt_sender_ip)))
     self.assertThat(arp.target_ip, Equals(IPAddress(pkt_target_ip)))
Beispiel #7
0
 def test__properties(self):
     pkt_sender_mac = "01:02:03:04:05:06"
     pkt_sender_ip = "192.168.0.1"
     pkt_target_ip = "192.168.0.2"
     pkt_target_mac = "00:00:00:00:00:00"
     eth_src = "02:03:04:05:06:07"
     eth_dst = "ff:ff:ff:ff:ff:ff"
     arp_packet = make_arp_packet(pkt_sender_ip, pkt_sender_mac,
                                  pkt_target_ip, pkt_target_mac)
     arp = ARP(
         arp_packet,
         src_mac=hex_str_to_bytes(eth_src),
         dst_mac=hex_str_to_bytes(eth_dst),
     )
     self.assertThat(arp.source_eui, Equals(EUI(pkt_sender_mac)))
     self.assertThat(arp.target_eui, Equals(EUI(pkt_target_mac)))
     self.assertThat(arp.source_ip, Equals(IPAddress(pkt_sender_ip)))
     self.assertThat(arp.target_ip, Equals(IPAddress(pkt_target_ip)))
Beispiel #8
0
def make_ipv4_packet(
    total_length=None, version=None, ihl=None, payload=None, truncated=False
):
    """Construct an IPv4 packet using the specified parameters."""
    if payload is None:
        payload = b""
    if total_length is None:
        total_length = 20 + len(payload)
    if version is None:
        version = 4
    if ihl is None:
        ihl = 5
    version__ihl = ((version << 4) | ihl).to_bytes(1, "big")

    ipv4_packet = (
        # Version, IHL
        version__ihl
        +
        # TOS
        hex_str_to_bytes("00")
        +
        # Total length in bytes
        total_length.to_bytes(2, "big")
        +
        # Identification
        hex_str_to_bytes("0000")
        +
        # Flags, fragment offset
        hex_str_to_bytes("0000")
        +
        # TTL
        hex_str_to_bytes("00")
        +
        # Protocol (just make it UDP for now)
        hex_str_to_bytes("11")
        +
        # Header checksum
        hex_str_to_bytes("0000")
        +
        # Source address
        hex_str_to_bytes("00000000")
        +
        # Destination address
        hex_str_to_bytes("00000000")
        # No options.
    )
    assert len(ipv4_packet) == 20, "Length was %d" % len(ipv4_packet)
    if truncated:
        return ipv4_packet[:19]
    ipv4_packet = ipv4_packet + payload
    return ipv4_packet
Beispiel #9
0
def make_ethernet_packet(dst_mac='ff:ff:ff:ff:ff:ff',
                         src_mac='01:02:03:04:05:06',
                         ethertype=ETHERTYPE.ARP,
                         vid=None,
                         payload=b''):
    """Construct an Ethernet packet using the specified values.

    If the specified `vid` is not None, it is interpreted as an integer VID,
    and the appropriate Ethertype fields are adjusted.
    """
    # Basic Ethernet header is (destination, source, ethertype)
    ethernet_packet = (
        hex_str_to_bytes(dst_mac) + hex_str_to_bytes(src_mac) +
        # If a VID is defined, use the 802.1q Ethertype instead...
        (hex_str_to_bytes('8100') if vid is not None else ethertype))
    if vid is not None:
        ethernet_packet = (
            ethernet_packet + bytes.fromhex("%04x" % vid) +
            # ... and place the payload Ethertype in the 802.1q header.
            ethertype)
    ethernet_packet = ethernet_packet + payload
    return ethernet_packet
Beispiel #10
0
def make_arp_packet(sender_ip,
                    sender_mac,
                    target_ip,
                    target_mac='00:00:00:00:00:00',
                    op=ARP_OPERATION.REQUEST,
                    hardware_type='0x0001',
                    protocol='0x0800',
                    hardware_length='0x06',
                    protocol_length='0x04'):
    # Concatenate a byte string with the specified values.
    # For ARP format, see: https://tools.ietf.org/html/rfc826
    arp_packet = (hex_str_to_bytes(hardware_type) +
                  hex_str_to_bytes(protocol) +
                  hex_str_to_bytes(hardware_length) +
                  hex_str_to_bytes(protocol_length) + ARP_OPERATION(op) +
                  hex_str_to_bytes(sender_mac) + ipv4_to_bytes(sender_ip) +
                  hex_str_to_bytes(target_mac) + ipv4_to_bytes(target_ip))
    return arp_packet
Beispiel #11
0
class ETHERTYPE:
    """Enumeration to represent ethertypes that MAAS needs to understand."""
    IPV4 = hex_str_to_bytes('0800')
    IPV6 = hex_str_to_bytes('86dd')
    ARP = hex_str_to_bytes('0806')
    VLAN = hex_str_to_bytes('8100')