Parsing options

Kelly Yancey kelly at nttmcl.com
Thu Jun 16 18:17:11 UTC 2005


On Thu, 16 Jun 2005, [ISO-8859-1] Erik Alapää wrote:

> Hello! I am using the ISC relay code as a basis for developing a
> special-purpose DHCP relay that, in addition to normal relay
> functionality also will sniff some info from the DHCP packets and pass
> that info to an LDAP server. Now my question: Can anyone offer me some
> advice on how to get the lease time, circuit and remote id:s from the
> options part of a packet? I have looked at the functions used by the
> ISC DHCP client and server, but these seem to be EXTREMELY complicated
> for some reason, and they require strange input parameters that the
> relay does not have access to. They use client states, dhcp universe
> structs, option caches and whatnot :| What I need is a routine that
> simply takes a raw dhcp_packet or a dhcp packet struct as defined in
> includes/dhcpd.h and gets me lease time, circuit and remote id. Looks
> like I will have to build one from scratch :(
>
> Regards,
>
> --
> Erik Alapää
> Software Engineer M. Sc., Lic. Ind. Math.
>

   I did something similar a couple of years back to record lease 
information into a database.  Attached is a code snippet with the 
important bits of parsing the options and extracting the lease times.
Good luck,

   Kelly

-- 
Kelly Yancey  -  kbyanc@{posi.net,FreeBSD.org}  -  kelly at nttmcl.com
-- Attached file included as plaintext by Ecartis --
-- File: dhcrelay-example.c

void
nttmcl_sqllog_dhcp(const struct dhcp_packet *packet, int length)
{
	struct option_state *options = NULL;
	struct option_cache *op;
	char *serverid_str = NULL;
	u_int32_t lease_time = 0;
	u_int32_t renewal_time = 0;
	u_int32_t rebind_time = 0;
	u_int8_t message_type = 0;

	PGresult *result;
	int status;

	/* Sanity check to make sure we have a database connection. */
	if (sql_conn == NULL)
		return;

	/* Sanity check the options cookie to ensure this is a DHCP packet. */
	if (memcmp(packet->options, DHCP_OPTIONS_COOKIE,
	    sizeof(DHCP_OPTIONS_COOKIE) - 1) != 0)
		return;		/* XXX Log bootp data??? */

	if (!option_state_allocate(&options, MDL))
		return;

	if (!parse_option_buffer(options,
	    packet->options + sizeof(DHCP_OPTIONS_COOKIE) - 1,
	    length - DHCP_FIXED_NON_UDP - sizeof(DHCP_OPTIONS_COOKIE) + 1,
	    &dhcp_universe)) {
		option_state_dereference(&options, MDL);
		return;		/* XXX Error should already be logged. */
	}

	if ((op = lookup_option(&dhcp_universe, options,
				DHO_DHCP_MESSAGE_TYPE)) != NULL) {
		message_type = *op->data.data;
	}

	if (message_type != DHCPACK) {
		/* Only interested in ACKs. */
		option_state_dereference(&options, MDL);
		return;
	}

	if ((op = lookup_option(&dhcp_universe, options,
				DHO_DHCP_LEASE_TIME)) != NULL) {
		assert(op->data.len == 4 && sizeof(lease_time) == 4);
		memcpy(&lease_time, op->data.data, op->data.len);
		/* XXX Should be ntoh32. */
		lease_time = ntohl(lease_time);
	}
	if ((op = lookup_option(&dhcp_universe, options,
				DHO_DHCP_RENEWAL_TIME)) != NULL) {
		assert(op->data.len == 4 && sizeof(renewal_time) == 4);
		memcpy(&renewal_time, op->data.data, op->data.len);
		renewal_time = ntohl(renewal_time);
	}
	if ((op = lookup_option(&dhcp_universe, options,
				DHO_DHCP_REBINDING_TIME)) != NULL) {
		assert(op->data.len == 4 && sizeof(rebind_time) == 4);
		memcpy(&rebind_time, op->data.data, op->data.len);
		rebind_time = ntohl(rebind_time);
	}
	if ((op = lookup_option(&dhcp_universe, options,
				DHO_DHCP_SERVER_IDENTIFIER)) != NULL) {
		struct in_addr ip;
		assert(op->data.len == 4 && sizeof(ip) == 4);
		memcpy(&ip, op->data.data, sizeof(ip));
		serverid_str = nttmcl_sql_strquote(inet_ntoa(&ip), NULL);
	}

	if (lease_time == 0)
		lease_time = default_lease_time;
	if (renewal_time == 0)
		renewal_time = lease_time / 2;
	if (rebind_time == 0)
		rebind_time = lease_time * 7 / 8;

	... do stuff with the option values ...

	option_state_dereference(&options, MDL);

	free(serverid_str);
}



More information about the dhcp-hackers mailing list