Beispiel #1
0
	def HandlePacket( self ):
		rlist, wlist, xlist = select.select(self.dhcp_sockets, [], [])
		s = rlist[0]
		data,sender = s.recvfrom(self.BUFLEN)

		packet = dhcp_packet.DhcpPacket()
		try:
			packet.DecodePacket(data)
		except Exception, e:
			print_exception(e)
			b64_data = base64.b64encode(data)
			print "FAILED TO PARSE: %r: %r" % (e, b64_data)
			dhcp.get_logger().log(dhcp.logging.ERROR,"IGN/UNPARSABLE: %r" % b64_data)

			if raven_client:
				raven_client.captureMessage(
					"Failed to parse invalid DHCP packet",
					tags={
						'server': self.dhcp_socket_info[s]['address'],
					},
					level=level,
					extra={
						'b64_data': b64_data,
						'server_ip_address': self.dhcp_socket_info[s]['address'],
						'server_interface': self.dhcp_socket_info[s],
						't_name': "INVALID",
						'recvd_from': sender,
					},
				)
			return
Beispiel #2
0
		def dhcp_decline(self, packet):
			mac = decode_mac( packet.GetOption('chaddr') )
			requested_ip = '.'.join(map(str,packet.GetOption('request_ip_address')))
			if requested_ip != '0.0.0.0':
				dhcp.get_logger().log(dhcp.logging.ERROR, "%-12s Address in use: %s", 'ERR/DECL:', requested_ip )
				self.__db.mark_abandoned_lease( mac=mac, address=requested_ip )
			else:
				dhcp.get_logger().log(dhcp.logging.ERROR, "%-12s Address in use: %s", 'ERR/DECL2:', mac )
				self.__db.mark_abandoned_lease( mac=mac )
Beispiel #3
0
def log_packet( packet, prefix='', level=dhcp.logging.INFO, raw=False):
	# This should be called for every incoming or outgoing packet.
	pkttype,mac,xid,client,giaddr,recvd_from,req_opts = parse_packet(packet)

	t_name = types[pkttype] if pkttype in types else "INVALID"

	if giaddr != '0.0.0.0':
		client_foo = '%s via %s' % (client, giaddr)
	else:
		client_foo = str(client)

	if packet.IsOption('host_name'):
		host_name=packet.GetOption('host_name')
		client_foo = '%s [option 12: %s]' % (client_foo, ''.join(map(chr,host_name)))

	raw_append = ''
	if raw:
		raw_data = base64.b64encode(packet._raw_data) if packet._raw_data else packet._raw_data
		raw_append = " RAW:%r" % raw_data

	dhcp.get_logger().log(level, "%-12s %-8s %s 0x%08x (%s)%s", prefix, t_name, mac, xid, client_foo, raw_append )

	if raven_client and level >= raven_client_min_level or t_name=='decline':
		if 'IGN' in prefix:
			if 'LIMIT' in prefix:
				message = 'request from %s ignored due to rate limiting' % mac
			elif 'UNAVAIL' in prefix:
				message = 'unable to find appropriate lease: giaddr=%s' % giaddr
			else:
				message = prefix[:-1]
		elif t_name=='decline':
			message = 'dhcpdecline from host %s' % mac
		else:
			message = "%s %s from %s" % (prefix, t_name.upper(), mac,)

		requested_ip = bytes_to_ip(packet, 'request_ip_address')
		
		raven_client.captureMessage(message,
			tags={
				'server': packet.get_recv_interface()['address'],
			},
			level=level,
			extra={
				'server_ip_address': packet.get_recv_interface()['address'],
				'server_interface': packet.get_recv_interface(),
				't_name': t_name,
				'mac': mac,
				'xid': xid,
				'client': client,
				'giaddr': giaddr,
				'requested_ip': requested_ip,
				'recvd_from': recvd_from,
			},
		)
Beispiel #4
0
def log_packet( packet, prefix='', level=dhcp.logging.INFO):
	# This should be called for every incoming or outgoing packet.
	pkttype,mac,xid,client,giaddr,recvd_from,req_opts = parse_packet(packet)

	t_name = types[pkttype]

	if giaddr != '0.0.0.0':
		client_foo = '%s via %s' % (client, giaddr)
	else:
		client_foo = str(client)

	dhcp.get_logger().log(level, "%-12s %-8s %s 0x%08x (%s)", prefix, t_name, mac, xid, client_foo )
Beispiel #5
0
 def dhcp_decline(self, packet):
     mac = decode_mac(packet.GetOption('chaddr'))
     requested_ip = '.'.join(
         map(str, packet.GetOption('request_ip_address')))
     if requested_ip != '0.0.0.0':
         dhcp.get_logger().log(dhcp.logging.ERROR,
                               "%-12s Address in use: %s", 'ERR/DECL:',
                               requested_ip)
         self.__db.mark_abandoned_lease(mac=mac, address=requested_ip)
     else:
         dhcp.get_logger().log(dhcp.logging.ERROR,
                               "%-12s Address in use: %s", 'ERR/DECL2:',
                               mac)
         self.__db.mark_abandoned_lease(mac=mac)
Beispiel #6
0
def bytes_to_ip(packet, opt_name):
	try:
		addr = packet.GetOption(opt_name)
	except:
		addr = None
	
	if not addr:
		return None

	if type(addr) != list:
		raise Exception("Eh?")

	if len(addr) != 4:
		logger = dhcp.get_logger()
		dhcp.get_logger().log(dhcp.logging.ERROR,"INVALID: %r invalid for %s from %s" % (addr, opt_name, decode_mac(packet.GetOption('chaddr'))))

		return None
	return '.'.join(map(str, addr))
Beispiel #7
0
    def HandlePacket(self):
        if not self.sockets_initialized:
            self._open_sockets()
        rlist, wlist, xlist = select.select(self.dhcp_sockets, [], [])
        s = rlist[0]
        data, sender = s.recvfrom(self.BUFLEN)

        packet = dhcp_packet.DhcpPacket()
        try:
            packet.DecodePacket(data)
        except Exception as e:
            print_exception(e)
            b64_data = base64.b64encode(data)
            print("FAILED TO PARSE: %r: %r" % (e, b64_data))
            dhcp.get_logger().log(dhcp.logging.ERROR,
                                  "IGN/UNPARSABLE: %r" % b64_data)

            if raven_client:
                raven_client.captureMessage(
                    "Failed to parse invalid DHCP packet",
                    tags={"server": self.dhcp_socket_info[s]["address"]},
                    level=dhcp.logging.ERROR,
                    extra={
                        "b64_data": b64_data,
                        "server_ip_address":
                        self.dhcp_socket_info[s]["address"],
                        "server_interface": self.dhcp_socket_info[s],
                        "t_name": "INVALID",
                        "recvd_from": sender,
                    },
                )
            return

        packet.set_sender(sender)
        packet.set_recv_interface(self.dhcp_socket_info[s])

        packet_type = get_packet_type(packet)
        if packet_type is False:
            log_packet(packet, prefix="IGN/INVALID TYPE:", raw=True)
        if not packet.IsDhcpPacket():
            log_packet(packet, prefix="IGN/INVALID PKT:", raw=True)
        self.QueuePacket(packet, packet_type)
Beispiel #8
0
        def dhcp_decline(self, packet):
            mac = decode_mac(packet.GetOption("chaddr"))
            requested_ip = bytes_to_ip(packet, "request_ip_address")

            if requested_ip and requested_ip != "0.0.0.0":
                dhcp.get_logger().log(
                    dhcp.logging.ERROR,
                    "%-12s Address in use: %s (from: %s)",
                    "ERR/DECL:",
                    requested_ip,
                    mac,
                )
                self.__db.mark_abandoned_lease(mac=mac, address=requested_ip)
            else:
                dhcp.get_logger().log(
                    dhcp.logging.ERROR,
                    "%-12s Address in use: (from: %s)",
                    "ERR/DECL2:",
                    mac,
                )
Beispiel #9
0
def bytes_to_ip(packet, opt_name):
    try:
        addr = packet.GetOption(opt_name)
    except Exception:
        addr = None

    if not addr:
        return None

    if type(addr) != list:
        raise Exception("Eh?")

    if len(addr) != 4:
        dhcp.get_logger().log(
            dhcp.logging.ERROR,
            "INVALID: %r invalid for %s from %s" %
            (addr, opt_name, decode_mac(packet.GetOption("chaddr"))),
        )

        return None
    return ".".join(map(str, addr))
Beispiel #10
0
        def dhcp_discover(self, packet):
            router = '.'.join(map(str, packet.GetOption('giaddr')))
            mac = decode_mac(packet.GetOption('chaddr'))
            requested_ip = '.'.join(
                map(str, packet.GetOption('request_ip_address')))

            recv_if = packet.get_recv_interface()
            if router == '0.0.0.0':
                if recv_if['broadcast']:
                    # hey, local DHCP traffic!
                    router = recv_if['address']

            if not requested_ip:
                requested_ip = '.'.join(map(str, packet.GetOption('ciaddr')))
                if not requested_ip:
                    raise Exception("This really needs fixed...")

            lease = self.__db.make_dhcp_lease(
                mac,
                router,
                requested_ip,
                discover=True,
                server_address=recv_if['address'])

            print 'Got lease %s from database' % lease

            while self.address_in_use(lease['address']):
                print 'Address %s in use, marking lease %s as abandoned' % (
                    lease['address'], lease)
                dhcp.get_logger().log(dhcp.logging.ERROR,
                                      "%-12s Address in use: %(15)s",
                                      'ERR/IN_USE:', lease['address'])
                self.__db.mark_abandoned_lease(address=lease['address'])
                lease = self.__db.make_dhcp_lease(
                    mac,
                    router,
                    requested_ip,
                    discover=True,
                    server_address=recv_if['address'])
                print 'Got new lease %s from database' % lease

            # create an offer
            print "> creating offer"
            offer = DhcpPacket()
            offer.CreateDhcpOfferPacketFrom(packet)
            hops = packet.GetOption('hops')
            if hops:
                offer.SetOption('hops', hops)

            # fields
            # FIXME: get a free lease from the DB
            # we will need the function to return: the address, the gateway, the network/netmask/broadcast
            # FIXME: what about lease/renewal/rebinding_time, etc?
            # then offer it

            # Options to request from the DB (address/gateway are assumed)
            offer.SetOption("yiaddr", ip_to_list(lease['address']))

            # options from DB
            print "setting lease time to %s seconds" % lease['lease_time']
            offer.SetOption("ip_address_lease_time",
                            int_to_4_bytes(lease['lease_time']))  # TEST
            #offer.SetOption("renewal_time_value",[0,0,0,60]) # TEST
            #offer.SetOption("rebinding_time_value",[0,0,0,105]) # TEST
            offer.SetOption("subnet_mask", ip_to_list(lease['netmask']))
            offer.SetOption("broadcast_address",
                            ip_to_list(lease['broadcast']))  # TEST
            offer.SetOption("router", ip_to_list(lease['router']))

            #offer.SetOption("hops",[1,]) # TEST: number of hops

            # make a list of requested DHCP options
            requested_options = packet.GetOption('parameter_request_list')
            print "requested_options: %s" % requested_options

            if lease['hostname'] and DhcpOptions[
                    'host_name'] in requested_options:
                offer.SetOption("host_name", map(ord, lease['hostname']))

            # get option/value pairs from database
            opt_vals = self.__db.retrieve_dhcp_options(
                mac=mac, address=requested_ip, option_ids=requested_options)
            print "opt_vals: %s" % str(opt_vals)

            self.assign_dhcp_options(options=opt_vals,
                                     requested=requested_options,
                                     packet=offer)

            # send an offer
            print "  > sending offer"
            self.SendPacket(offer)
Beispiel #11
0
def log_packet(packet, prefix='', level=dhcp.logging.INFO):
    # This should be called for every incoming or outgoing packet.
    pkttype, mac, xid, client, giaddr, recvd_from, req_opts = parse_packet(
        packet)

    t_name = types[pkttype]

    if giaddr != '0.0.0.0':
        client_foo = '%s via %s' % (client, giaddr)
    else:
        client_foo = str(client)

    if packet.IsOption('host_name'):
        host_name = packet.GetOption('host_name')
        client_foo = '%s [option 12: %s]' % (client_foo, ''.join(
            map(chr, host_name)))

    dhcp.get_logger().log(level, "%-12s %-8s %s 0x%08x (%s)", prefix, t_name,
                          mac, xid, client_foo)
    if raven_client and level >= raven_client_min_level or t_name == 'decline':
        if 'IGN' in prefix:
            if 'LIMIT' in prefix:
                message = 'request from %s ignored due to rate limiting' % mac
            elif 'UNAVAIL' in prefix:
                message = 'unable to find appropriate lease: giaddr=%s' % giaddr
            else:
                message = prefix[:-1]
        elif t_name == 'decline':
            message = 'dhcpdecline from host %s' % mac
        else:
            message = "%s %s from %s" % (
                prefix,
                t_name.upper(),
                mac,
            )

        try:
            requested_ip = packet.GetOption('request_ip_address')
        except:
            requested_ip = None

        if requested_ip:
            requested_ip = '.'.join(map(str, requested_ip))

        raven_client.captureMessage(
            message,
            tags={
                'server': packet.get_recv_interface()['address'],
            },
            level=level,
            extra={
                'server_interface': packet.get_recv_interface(),
                't_name': t_name,
                'mac': mac,
                'xid': xid,
                'client': client,
                'giaddr': giaddr,
                'requested_ip': requested_ip,
                'recvd_from': recvd_from,
            },
        )
Beispiel #12
0
		def dhcp_discover(self, packet):
			router = '.'.join(map(str,packet.GetOption('giaddr')))
			mac = decode_mac( packet.GetOption('chaddr') )
			requested_ip = '.'.join(map(str,packet.GetOption('request_ip_address')))
			
			recv_if = packet.get_recv_interface()
			if router == '0.0.0.0':
				if recv_if['broadcast']:
					# hey, local DHCP traffic!
					router = recv_if['address']

			if not requested_ip:
				requested_ip = '.'.join(map(str,packet.GetOption('ciaddr')))
				if not requested_ip:
					raise Exception("This really needs fixed...")

			lease = self.__db.make_dhcp_lease(mac, router, requested_ip, discover=True, server_address = recv_if['address'])
			
			print 'Got lease %s from database' % lease

			while self.address_in_use( lease['address'] ):
				print 'Address %s in use, marking lease %s as abandoned' % ( lease['address'], lease )
				dhcp.get_logger().log(dhcp.logging.ERROR, "%-12s Address in use: %(15)s", 'ERR/IN_USE:', lease['address'] )
				self.__db.mark_abandoned_lease( address=lease['address'] )
				lease = self.__db.make_dhcp_lease(mac, router, requested_ip, discover=True, server_address = recv_if['address'])
				print 'Got new lease %s from database' % lease

			# create an offer
			print "> creating offer"
			offer = DhcpPacket()
			offer.CreateDhcpOfferPacketFrom(packet)
			hops = packet.GetOption('hops')
			if hops:
				offer.SetOption('hops',hops)

			# fields
			# FIXME: get a free lease from the DB
			# we will need the function to return: the address, the gateway, the network/netmask/broadcast
			# FIXME: what about lease/renewal/rebinding_time, etc?
			# then offer it

			# Options to request from the DB (address/gateway are assumed)
			offer.SetOption("yiaddr",ip_to_list(lease['address']))

			# options from DB
			print "setting lease time to %s seconds" % lease['lease_time']
			offer.SetOption("ip_address_lease_time",int_to_4_bytes(lease['lease_time'])) # TEST
			#offer.SetOption("renewal_time_value",[0,0,0,60]) # TEST
			#offer.SetOption("rebinding_time_value",[0,0,0,105]) # TEST
			offer.SetOption("subnet_mask",ip_to_list(lease['netmask']))
			offer.SetOption("broadcast_address",ip_to_list(lease['broadcast'])) # TEST
			offer.SetOption("router",ip_to_list(lease['router']))

			#offer.SetOption("hops",[1,]) # TEST: number of hops

			# make a list of requested DHCP options
			requested_options = packet.GetOption('parameter_request_list')
			print "requested_options: %s" % requested_options

			if lease['hostname'] and DhcpOptions['host_name'] in requested_options:
				offer.SetOption("host_name", map(ord,lease['hostname']))

			# get option/value pairs from database
			opt_vals = self.__db.retrieve_dhcp_options( mac=mac, address=requested_ip, option_ids = requested_options )
			print "opt_vals: %s" % str(opt_vals)

			self.assign_dhcp_options( options=opt_vals, requested=requested_options, packet=offer )

			# send an offer
			print "  > sending offer"
			self.SendPacket(offer)
Beispiel #13
0
        def dhcp_discover(self, packet):
            router = ".".join(map(str, packet.GetOption("giaddr")))
            mac = decode_mac(packet.GetOption("chaddr"))
            requested_ip = bytes_to_ip(packet, "request_ip_address")

            recv_if = packet.get_recv_interface()
            if router == "0.0.0.0":
                if recv_if["broadcast"]:
                    # hey, local DHCP traffic!
                    router = recv_if["address"]

            if not requested_ip:
                requested_ip = "0.0.0.0"

            lease = self.__db.make_dhcp_lease(
                mac,
                router,
                requested_ip,
                discover=True,
                server_address=recv_if["address"],
            )

            print("Got lease %s from database" % lease)

            while self.address_in_use(lease["address"]):
                print("Address %s in use, marking lease %s as abandoned" %
                      (lease["address"], lease))
                dhcp.get_logger().log(
                    dhcp.logging.ERROR,
                    "%-12s Address in use: %(15)s (client: %s)",
                    "ERR/IN_USE:",
                    lease["address"],
                    mac,
                )
                self.__db.mark_abandoned_lease(address=lease["address"])
                lease = self.__db.make_dhcp_lease(
                    mac,
                    router,
                    requested_ip,
                    discover=True,
                    server_address=recv_if["address"],
                )
                print("Got new lease %s from database" % lease)

                # create an offer
            print("> creating offer")
            offer = dhcp_packet.DhcpPacket()
            offer.CreateDhcpOfferPacketFrom(packet)
            hops = packet.GetOption("hops")
            if hops:
                offer.SetOption("hops", hops)

                # fields
                # FIXME: get a free lease from the DB
                # we will need the function to return: the address, the gateway,
                # the network/netmask/broadcast
                # FIXME: what about lease/renewal/rebinding_time, etc?
                # then offer it

                # Options to request from the DB (address/gateway are assumed)
            offer.SetOption("yiaddr", ip_to_list(lease["address"]))

            # options from DB
            print("setting lease time to %s seconds" % lease["lease_time"])
            offer.SetOption("ip_address_lease_time",
                            int_to_4_bytes(lease["lease_time"]))  # TEST
            # offer.SetOption("renewal_time_value",[0,0,0,60]) # TEST
            # offer.SetOption("rebinding_time_value",[0,0,0,105]) # TEST
            offer.SetOption("subnet_mask", ip_to_list(lease["netmask"]))
            offer.SetOption("broadcast_address",
                            ip_to_list(lease["broadcast"]))  # TEST
            offer.SetOption("router", ip_to_list(lease["router"]))

            # offer.SetOption("hops",[1,]) # TEST: number of hops

            # make a list of requested DHCP options
            requested_options = packet.GetOption("parameter_request_list")
            print("requested_options: %s" % requested_options)

            if lease["hostname"] and DhcpOptions[
                    "host_name"] in requested_options:
                offer.SetOption("host_name", list(map(ord, lease["hostname"])))

                # get option/value pairs from database
            opt_vals = self.__db.retrieve_dhcp_options(
                mac=mac, address=requested_ip, option_ids=requested_options)
            print("opt_vals: %s" % str(opt_vals))

            self.assign_dhcp_options(options=opt_vals,
                                     requested=requested_options,
                                     packet=offer)

            # send an offer
            print("  > sending offer")
            self.SendPacket(offer)
Beispiel #14
0
def log_packet(packet, prefix="", level=dhcp.logging.INFO, raw=False):
    # This should be called for every incoming or outgoing packet.
    pkttype, mac, xid, client, giaddr, recvd_from, req_opts = parse_packet(
        packet)

    t_name = types[pkttype] if pkttype in types else "INVALID"

    if giaddr != "0.0.0.0":
        client_foo = "%s via %s" % (client, giaddr)
    else:
        client_foo = str(client)

    if packet.IsOption("host_name"):
        host_name = packet.GetOption("host_name")
        client_foo = "%s [option 12: %s]" % (client_foo, "".join(
            map(chr, host_name)))

    raw_append = ""
    if raw:
        raw_data = (base64.b64encode(packet._raw_data)
                    if packet._raw_data else packet._raw_data)
        raw_append = " RAW:%r" % raw_data

    dhcp.get_logger().log(
        level,
        "%-12s %-8s %s 0x%08x (%s)%s",
        prefix,
        t_name,
        mac,
        xid,
        client_foo,
        raw_append,
    )

    if raven_client and level >= raven_client_min_level or t_name == "decline":
        if "IGN" in prefix:
            if "LIMIT" in prefix:
                message = "request from %s ignored due to rate limiting" % mac
            elif "UNAVAIL" in prefix:
                message = "unable to find appropriate lease: giaddr=%s" % giaddr
            else:
                message = prefix[:-1]
        elif t_name == "decline":
            message = "dhcpdecline from host %s" % mac
        else:
            message = "%s %s from %s" % (prefix, t_name.upper(), mac)

        requested_ip = bytes_to_ip(packet, "request_ip_address")

        raven_client.captureMessage(
            message,
            tags={"server": packet.get_recv_interface()["address"]},
            level=level,
            extra={
                "server_ip_address": packet.get_recv_interface()["address"],
                "server_interface": packet.get_recv_interface(),
                "t_name": t_name,
                "mac": mac,
                "xid": xid,
                "client": client,
                "giaddr": giaddr,
                "requested_ip": requested_ip,
                "recvd_from": recvd_from,
            },
        )