示例#1
0
def main():

    from optparse import OptionParser

    parser = OptionParser()

    parser.add_option("-d", "--devname",
                      dest="devname", default=None,
                      help="The name of the tap device to open.")

    parser.add_option("-i", "--ifname",
                      dest="ifname", default=None,
                      help="The name of the interface to listen on.")

    parser.add_option("-g", "--group",
                      dest="group", default=None,
                      help="The IPv4 group to use for UML-style multicasts.")

    parser.add_option("-p", "--port",
                      dest="port", default=None,
                      help="The IPv4 port to use for UML-style multicasts.")

    parser.add_option("-a", "--ifaddr",
                      dest="ifaddr", default=None,
                      help="The IP address to listen on.")

    parser.add_option("-S", "--ether_source",
                      dest="ether_source", default=None,
                      help="The Ethernet address to listen on.")

    (options, args) = parser.parse_args()


    if options.devname is not None:
        input = TapConnector(options.devname)
        output = input
    elif options.group is not None:
        if options.port is None:
	    print "Non-optional argument missing."
	    return
        # XXX Currently, UmlMcast4Connector has to use the same broken
        # semantics as QEMU does, to see its traffic -- apps SHOULD be
        # joining groups on specific interfaces.
        # Note that we'll also end up seeing our own traffic.
        #input = UmlMcast4Connector(options.group, options.port, options.ifaddr)
        input = UmlMcast4Connector(options.group, options.port, "0.0.0.0")
        output = input
    elif options.ifname is not None:
        input = PcapConnector(options.ifname)
        output = PcapConnector(options.ifname)
        input.setfilter("udp port 67 or udp port 68")

    if options.ifaddr is None or \
       options.ether_source is None:
	print "Non-optional argument missing."
	return

    ifaddr = inet_atol(options.ifaddr)
    ether_source = ether_atob(options.ether_source)

    ip_id = int(random.random() * 32768)

    # XXX Should really have an API for extracting our
    # local ethernet address.

    running = True
    while running is True:
        packet = input.readpkt()
	chain = packet.chain()

	# Must have: ether + ip + udp + dhcp.
	# UDP checksum ignored. Assume pcap filter above did its job.
	if len(chain.packets) < 4 or \
	   not isinstance(chain.packets[3], dhcpv4):
	    continue

	i_ether = chain.packets[0]
	i_ip = chain.packets[1]
	i_udp = chain.packets[2]
	i_dhcp = chain.packets[3]

	# check dhcp htype is ethernet.
	# check if dhcp.cid in map.

	if i_dhcp.op != pcs.packets.dhcpv4.BOOTREQUEST or \
	   i_dhcp.htype != pcs.packets.dhcpv4.HTYPE_ETHER or \
	   i_dhcp.hlen != 6:
	    continue

	#print i_dhcp

	chaddr_s = ether_btoa(i_dhcp.chaddr[:i_dhcp.hlen])
	if not chaddr_s in map:
	    print "%s not in map" % chaddr_s
	    continue

	ciaddr = inet_atol(map[chaddr_s])	# from map

	dhcp = dhcpv4()
	dhcp.op = pcs.packets.dhcpv4.BOOTREPLY
	dhcp.htype = pcs.packets.dhcpv4.HTYPE_ETHER
	dhcp.hlen = 6
	dhcp.hops = 0
	dhcp.xid = i_dhcp.xid
	dhcp.flags = 0

	#dhcp.ciaddr = ciaddr
	dhcp.siaddr = ifaddr

	# XXX should only fill out if i_dhcp.ciaddr was 0.0.0.0
	dhcp.yiaddr = ciaddr

	dhcp.chaddr = i_dhcp.chaddr
	#dhcp.sname = "myhost"
	#dhcp.file = "/vmunix"

	#dhcp.options.append(dhcpv4_options.cookie().field())

	# server ID.
	# XXX Weeiiird!
	#sid = dhcpv4_options.dhcp_server_identifier()
	#sid.value = ifaddr
	#sid.value = inet_atol("0.0.0.0")
	#dhcp.options.append(sid.field())

	# Subnet mask.
	#sm = dhcpv4_options.subnet_mask()
	#sm.value = inet_atol("255.255.255.0")
	#dhcp.options.append(sm.field())

	# Default gateway.
	#dg = dhcpv4_options.routers()
	#dg.value = ifaddr
	#dhcp.options.append(dg.field())

	# Add end marker.
	#end = dhcpv4_options.end()
	#dhcp.options.append(end.field())

	# Pad BOOTP payload to 32-bit width.
	# XXX BOOTP is problematic because the field which contains
	# the options needs to be clamped to 64 bytes in total. This
	# means we need to know the encoded length of each option.
	# For now, guess it... total length of an RFC-951 payload
	# is always 300 bytes.
	# this shuts up wireshark.
	#padlen = 300 - (len(dhcp.bytes) % 4)
	#padlen = 50 - (len(dhcp.bytes) % 4)
	#padlen = 4
	#pad = dhcpv4_options.pad(padlen)
	#dhcp.options.append(pad.field())

	# Encapsulate ethernet.
	ether = ethernet()
	ether.type = 0x0800
	ether.src = ether_source
	ether.dst = i_dhcp.chaddr[:i_dhcp.hlen]

	# Encapsulate IPv4.
	ip = ipv4()
	ip.version = 4
	ip.hlen = 5
	ip.tos = 0
	ip.id = ip_id
	ip.flags = 0x00
	ip.offset = 0
	ip.ttl = 1
	ip.protocol = IPPROTO_UDP
	ip.src = ifaddr
	ip.dst = ciaddr

	ip_id += 1

	# Encapsulate UDPv4.
	udp = udpv4()
	udp.sport = 67
	udp.dport = 68
	udp.length = len(dhcp.bytes)
	udp.checksum = udp.cksum(ip, dhcp.bytes)

	# Compute header checksums.
	ip.length = len(ip.bytes) + len(udp.bytes) + len(dhcp.bytes)
	ip.checksum = ip.cksum()

	# Send the lot.
	packet = Chain([ether, ip, udp, dhcp])
	packet.encode()
	out = output.write(packet.bytes, len(packet.bytes))
	print out
示例#2
0
    def test_dhcpv4_encode(self):
        p = dhcpv4()
        assert (p != None)

        p.op = pcs.packets.dhcpv4.BOOTREQUEST
        p.htype = pcs.packets.dhcpv4.HTYPE_ETHER
        p.hlen = 6  # sizeof(struct ether_addr)
        p.hops = 99
        p.xid = 0xABADCAFE
        p.secs = 123
        p.flags = pcs.packets.dhcpv4.BOOTP_BROADCAST

        p.ciaddr = inet_atol("1.2.3.4")
        p.yiaddr = inet_atol("5.6.7.8")
        p.siaddr = inet_atol("9.10.11.12")
        p.giaddr = inet_atol("13.14.15.16")

        p.chaddr = ether_atob("00:01:02:03:04:05")
        p.sname = "fubar"
        p.file = "barfu"

        # Append DHCP options, which MUST include the cookie.

        p.options.append(dhcpv4_options.cookie().field())

        # Maximum DHCP message size.
        msz = dhcpv4_options.dhcp_max_message_size()
        msz.value = 1460
        p.options.append(msz.field())

        # DHCP message type.
        dhcp = dhcpv4_options.dhcp_message_type()
        dhcp.value = DHCPDISCOVER
        p.options.append(dhcp.field())

        # DHCP vendor class.
        vc = dhcpv4_options.dhcp_class_identifier()
        vc.value = "FreeBSD:amd64:7-CURRENT"
        p.options.append(vc.field())

        # BOOTP options end marker.
        end = dhcpv4_options.end()
        p.options.append(end.field())

        # Pad BOOTP payload to 32-bit width.
        padlen = 4 - (len(p.bytes) % 4)
        pad = dhcpv4_options.pad(padlen)
        p.options.append(pad.field())

        p.encode()
        #hd = hexdumper()
        #print p
        #print hd.dump2(p.bytes)
        gotttted = p.bytes
        expected = \
         "\x01\x01\x06\x63\xAB\xAD\xCA\xFE" \
         "\x00\x7B\x80\x00\x01\x02\x03\x04" \
         "\x05\x06\x07\x08\x09\x0A\x0B\x0C" \
         "\x0D\x0E\x0F\x10\x00\x01\x02\x03" \
         "\x04\x05\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x66\x75\x62\x61" \
         "\x72\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x62\x61\x72\x66" \
         "\x75\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x00\x00\x00\x00" \
         "\x00\x00\x00\x00\x63\x82\x53\x63" \
         "\x39\x02\x05\xB4\x35\x01\x01\x3C" \
         "\x17\x46\x72\x65\x65\x42\x53\x44" \
         "\x3A\x61\x6D\x64\x36\x34\x3A\x37" \
         "\x2D\x43\x55\x52\x52\x45\x4E\x54" \
         "\xFF\x00\x00\x00"

        self.assertEqual(expected, gotttted, "test encoding")
示例#3
0
    def test_dhcpv4_encode(self):
        p = dhcpv4()
        assert (p != None)

	p.op = pcs.packets.dhcpv4.BOOTREQUEST
	p.htype = pcs.packets.dhcpv4.HTYPE_ETHER
	p.hlen = 6	# sizeof(struct ether_addr)
	p.hops = 99
	p.xid = 0xABADCAFE
	p.secs = 123
	p.flags = pcs.packets.dhcpv4.BOOTP_BROADCAST

	p.ciaddr = inet_atol("1.2.3.4")
	p.yiaddr = inet_atol("5.6.7.8")
	p.siaddr = inet_atol("9.10.11.12")
	p.giaddr = inet_atol("13.14.15.16")

	p.chaddr = ether_atob("00:01:02:03:04:05")
	p.sname = "fubar"
	p.file  = "barfu"

	# Append DHCP options, which MUST include the cookie.

	p.options.append(dhcpv4_options.cookie().field())

	# Maximum DHCP message size.
	msz = dhcpv4_options.dhcp_max_message_size()
	msz.value = 1460
	p.options.append(msz.field())

	# DHCP message type.
	dhcp = dhcpv4_options.dhcp_message_type()
	dhcp.value = DHCPDISCOVER
	p.options.append(dhcp.field())

	# DHCP vendor class.
	vc = dhcpv4_options.dhcp_class_identifier()
	vc.value = "FreeBSD:amd64:7-CURRENT"
	p.options.append(vc.field())

	# BOOTP options end marker.
	end = dhcpv4_options.end()
	p.options.append(end.field())

	# Pad BOOTP payload to 32-bit width.
	padlen = 4 - (len(p.bytes) % 4)
	pad = dhcpv4_options.pad(padlen)
	p.options.append(pad.field())

        p.encode()
	#hd = hexdumper()
	#print p
	#print hd.dump2(p.bytes)
	gotttted = p.bytes
	expected = \
		"\x01\x01\x06\x63\xAB\xAD\xCA\xFE" \
		"\x00\x7B\x80\x00\x01\x02\x03\x04" \
		"\x05\x06\x07\x08\x09\x0A\x0B\x0C" \
		"\x0D\x0E\x0F\x10\x00\x01\x02\x03" \
		"\x04\x05\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x66\x75\x62\x61" \
		"\x72\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x62\x61\x72\x66" \
		"\x75\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x00\x00\x00\x00" \
		"\x00\x00\x00\x00\x63\x82\x53\x63" \
		"\x39\x02\x05\xB4\x35\x01\x01\x3C" \
		"\x17\x46\x72\x65\x65\x42\x53\x44" \
		"\x3A\x61\x6D\x64\x36\x34\x3A\x37" \
		"\x2D\x43\x55\x52\x52\x45\x4E\x54" \
		"\xFF\x00\x00\x00"

	self.assertEqual(expected, gotttted, "test encoding")
示例#4
0
def main():

    from optparse import OptionParser

    parser = OptionParser()

    parser.add_option("-d",
                      "--devname",
                      dest="devname",
                      default=None,
                      help="The name of the tap device to open.")

    parser.add_option("-i",
                      "--ifname",
                      dest="ifname",
                      default=None,
                      help="The name of the interface to listen on.")

    parser.add_option("-g",
                      "--group",
                      dest="group",
                      default=None,
                      help="The IPv4 group to use for UML-style multicasts.")

    parser.add_option("-p",
                      "--port",
                      dest="port",
                      default=None,
                      help="The IPv4 port to use for UML-style multicasts.")

    parser.add_option("-a",
                      "--ifaddr",
                      dest="ifaddr",
                      default=None,
                      help="The IP address to listen on.")

    parser.add_option("-S",
                      "--ether_source",
                      dest="ether_source",
                      default=None,
                      help="The Ethernet address to listen on.")

    (options, args) = parser.parse_args()

    if options.devname is not None:
        input = TapConnector(options.devname)
        output = input
    elif options.group is not None:
        if options.port is None:
            print "Non-optional argument missing."
            return
        # XXX Currently, UmlMcast4Connector has to use the same broken
        # semantics as QEMU does, to see its traffic -- apps SHOULD be
        # joining groups on specific interfaces.
        # Note that we'll also end up seeing our own traffic.
        #input = UmlMcast4Connector(options.group, options.port, options.ifaddr)
        input = UmlMcast4Connector(options.group, options.port, "0.0.0.0")
        output = input
    elif options.ifname is not None:
        input = PcapConnector(options.ifname)
        output = PcapConnector(options.ifname)
        input.setfilter("udp port 67 or udp port 68")

    if options.ifaddr is None or \
       options.ether_source is None:
        print "Non-optional argument missing."
        return

    ifaddr = inet_atol(options.ifaddr)
    ether_source = ether_atob(options.ether_source)

    ip_id = int(random.random() * 32768)

    # XXX Should really have an API for extracting our
    # local ethernet address.

    running = True
    while running is True:
        packet = input.readpkt()
        chain = packet.chain()

        # Must have: ether + ip + udp + dhcp.
        # UDP checksum ignored. Assume pcap filter above did its job.
        if len(chain.packets) < 4 or \
           not isinstance(chain.packets[3], dhcpv4):
            continue

        i_ether = chain.packets[0]
        i_ip = chain.packets[1]
        i_udp = chain.packets[2]
        i_dhcp = chain.packets[3]

        # check dhcp htype is ethernet.
        # check if dhcp.cid in map.

        if i_dhcp.op != pcs.packets.dhcpv4.BOOTREQUEST or \
           i_dhcp.htype != pcs.packets.dhcpv4.HTYPE_ETHER or \
           i_dhcp.hlen != 6:
            continue

#print i_dhcp

        chaddr_s = ether_btoa(i_dhcp.chaddr[:i_dhcp.hlen])
        if not chaddr_s in map:
            print "%s not in map" % chaddr_s
            continue

        ciaddr = inet_atol(map[chaddr_s])  # from map

        dhcp = dhcpv4()
        dhcp.op = pcs.packets.dhcpv4.BOOTREPLY
        dhcp.htype = pcs.packets.dhcpv4.HTYPE_ETHER
        dhcp.hlen = 6
        dhcp.hops = 0
        dhcp.xid = i_dhcp.xid
        dhcp.flags = 0

        #dhcp.ciaddr = ciaddr
        dhcp.siaddr = ifaddr

        # XXX should only fill out if i_dhcp.ciaddr was 0.0.0.0
        dhcp.yiaddr = ciaddr

        dhcp.chaddr = i_dhcp.chaddr
        #dhcp.sname = "myhost"
        #dhcp.file = "/vmunix"

        #dhcp.options.append(dhcpv4_options.cookie().field())

        # server ID.
        # XXX Weeiiird!
        #sid = dhcpv4_options.dhcp_server_identifier()
        #sid.value = ifaddr
        #sid.value = inet_atol("0.0.0.0")
        #dhcp.options.append(sid.field())

        # Subnet mask.
        #sm = dhcpv4_options.subnet_mask()
        #sm.value = inet_atol("255.255.255.0")
        #dhcp.options.append(sm.field())

        # Default gateway.
        #dg = dhcpv4_options.routers()
        #dg.value = ifaddr
        #dhcp.options.append(dg.field())

        # Add end marker.
        #end = dhcpv4_options.end()
        #dhcp.options.append(end.field())

        # Pad BOOTP payload to 32-bit width.
        # XXX BOOTP is problematic because the field which contains
        # the options needs to be clamped to 64 bytes in total. This
        # means we need to know the encoded length of each option.
        # For now, guess it... total length of an RFC-951 payload
        # is always 300 bytes.
        # this shuts up wireshark.
        #padlen = 300 - (len(dhcp.bytes) % 4)
        #padlen = 50 - (len(dhcp.bytes) % 4)
        #padlen = 4
        #pad = dhcpv4_options.pad(padlen)
        #dhcp.options.append(pad.field())

        # Encapsulate ethernet.
        ether = ethernet()
        ether.type = 0x0800
        ether.src = ether_source
        ether.dst = i_dhcp.chaddr[:i_dhcp.hlen]

        # Encapsulate IPv4.
        ip = ipv4()
        ip.version = 4
        ip.hlen = 5
        ip.tos = 0
        ip.id = ip_id
        ip.flags = 0x00
        ip.offset = 0
        ip.ttl = 1
        ip.protocol = IPPROTO_UDP
        ip.src = ifaddr
        ip.dst = ciaddr

        ip_id += 1

        # Encapsulate UDPv4.
        udp = udpv4()
        udp.sport = 67
        udp.dport = 68
        udp.length = len(dhcp.bytes)
        udp.checksum = udp.cksum(ip, dhcp.bytes)

        # Compute header checksums.
        ip.length = len(ip.bytes) + len(udp.bytes) + len(dhcp.bytes)
        ip.checksum = ip.cksum()

        # Send the lot.
        packet = Chain([ether, ip, udp, dhcp])
        packet.encode()
        out = output.write(packet.bytes, len(packet.bytes))
        print out