Setting host-identifier from omapi

Christian Kratzer ck-lists at cksoft.de
Mon Oct 22 18:44:42 UTC 2012


Hi,

On Mon, 22 Oct 2012, Matej wrote:
> Hi,
>
> did you have any success with implementing this?

yes we did. Although it turned out to be slightly more than we
initially thought.

I have attached two patches to server/omapi.c and server/db.c and
am cc:ing dhcp-hackers so this gets archived.  I hope the list
accepts the attachments.

The first patch in patch-server__omapi.c.20121015 does following:

- Adds printing of host-identifier options to dhcp_lease_stuff_values()

   This is not related to provisioning host objects but quite handy
   to be able to lookup the agent options on dynamic leases.

- Parses values of type host-identifier in dhcp_host_set_value()
   into a host object.

- Patch dhcp_host_signal_handler() to permit host-identifiers as
   a client identifier.

- Adds printing of host-identifier options to dhcp_host_stuff_values()

The second patch in patch-server__db.c.20121015 does following

- Adds printing of host-identifier options to write_lease()

A couple of things to keep in mind when using this patch:

- When setting values in the host object you supply 'host-identifier' as
   the name of the value and something like

 	option agent.circuit-id "foo"
 	option agent.remote-id "bar"
 	option agent.subscriber-id "baz"

   as the value.  As you see the value includes the quoted option value.

   We set this from python via a patched pypureomapi. Not sure if it's
   possible to get the escaping of the quoted value right from omshell.

- You cannot delete hosts via their host-identifier.  Not sure how much
   work this would be. Might be non trivial.  The workaround is quite
   easy as you can always find, modify and delete hosts via their name.

   So just provision a unique name and use that to delete the host objects.

I would of course be happy to see this in a future ISC dhcp release.

Greetings
Christian Kratzer
CK Software GmbH

>
> Thanks,
> Matej Serc
>
> Dne 24.9.2012 11:23, pi?e Christian Kratzer:
>> Hi,
>> 
>> I am reasearching the possibility of setting up hosts identified by dhcp 
>> option 82 circuit-id or subscriber-id using omapi as follows:
>> 
>> host foo {
>> host-identifier option agent.circuit-id "foo"
>> fixed-address 192.0.2.99;
>> }
>> 
>> I found following thread from January this year:
>> 
>> https://lists.isc.org/pipermail/dhcp-users/2012-January/014807.html
>> 
>>> From looking at the defintion of dhcp_host_set_value in server/omapi.c 
>>> using host-identifier does not seem to be supported currently.
>> 
>>> From further reading it seems that dhcp_host_set_value sets value in a 
>>> struct host_decl instance. I see there is a "struct option 
>>> *host_id_option;" in host_decl.
>> 
>> In order to support host-identifiers over omapi would it be enough to 
>> extend dhcp_host_set_value to parse an option into host_id_option of 
>> host_decl by taking the code from server/confparse.c after if (token == 
>> HOST_IDENTIFIER) at approx line 1893 ?
>> 
>> I am inclined to attempt a path but would like some confirmation that I am 
>> on the right track before opening up a can of worms.
>> 
>> Greetings
>> Christian
>> 
>
>

-- 
Christian Kratzer                      CK Software GmbH
Email:   ck at cksoft.de                  Wildberger Weg 24/2
Phone:   +49 7032 893 997 - 0          D-71126 Gaeufelden
Fax:     +49 7032 893 997 - 9          HRB 245288, Amtsgericht Stuttgart
Web:     http://www.cksoft.de/         Geschaeftsfuehrer: Christian Kratzer
-------------- next part --------------
--- server/omapi.c.orig	2012-08-28 04:13:03.000000000 +0200
+++ server/omapi.c	2012-10-15 09:50:39.000000000 +0200
@@ -38,6 +38,7 @@
    and refine the requirements.  To the extent that this code is
    useful, you have Brian and BCtel to thank.  Any limitations in the
    code are a result of mistakes on my part.  -- Ted Lemon */
+#define DEBUG_OMAPI 	1
 
 #include "dhcpd.h"
 #include <omapip/omapip_p.h>
@@ -627,6 +628,34 @@
 			return status;
 	}
 
+	/* ck at cksoft.de 2012-10-07 BEGIN OMAPI PATCH PART 1/5 */
+	/* Stuff agent_options 
+	 * Adapted from write_lease() in server/db.c
+	 */
+	if (lease -> agent_options) {
+	    struct option_cache *oc;
+	    struct data_string ds;
+	    pair p;
+
+	    memset (&ds, 0, sizeof ds);
+	    for (p = lease -> agent_options -> first; p; p = p -> cdr) {
+	        oc = (struct option_cache *)p -> car;
+	        if (oc -> data.len) {
+			omapi_connection_put_name (c, oc -> option -> name );
+			if (status != ISC_R_SUCCESS)
+				return status;
+
+			omapi_connection_put_string (c, 
+		    		 pretty_print_option (oc -> option, 
+					 oc -> data.data, oc -> data.len, 1, 1));
+
+			if (status != ISC_R_SUCCESS)
+				return status;
+	        }
+	    }
+	}
+	/* ck at cksoft.de 2012-10-07 END OMAPI PATCH PART 1/5 */
+
 	/* TIME values may be 64-bit, depending on system architecture.
 	 * OMAPI must be system independent, both in terms of transmitting
 	 * bytes on the wire in network byte order, and in terms of being
@@ -1047,6 +1076,84 @@
 		return ISC_R_SUCCESS;
 	}
 
+	/* ck at cksoft.de 2012-10-07 BEGIN OMAPI PATCH PART 2/5 */
+	/* Parse host-identifier
+	 * Adapted from parse_host_declaration() in server/confpars.c 
+	 */
+	if (!omapi_ds_strcmp (name, "host-identifier")) {
+		/* only one host-identifier allowed per host */
+		if (host->host_id_option != NULL) {
+			log_info ("only one host-identifier allowed per host");
+			return DHCP_R_INVALIDARG;
+		}
+
+		if (value && (value -> type == omapi_datatype_data ||
+			      value -> type == omapi_datatype_string)) {
+			struct parse *parse;
+			parse = (struct parse *)0;
+			const char *val;
+			enum dhcp_token token;
+			int known;
+			struct option *option;
+			struct expression *expr = NULL;
+
+			status = new_parse(&parse, -1,
+					    (char *) value->u.buffer.value,
+					    value->u.buffer.len,
+					    "network client", 0);
+			if (status != ISC_R_SUCCESS || parse == NULL) {
+				log_info ("status %d from new_parse()",status);
+				return DHCP_R_INVALIDARG;
+			}
+
+			token = next_token(&val, NULL, parse);
+			if (token != OPTION) {
+				/* host-identifier must be an option */
+				log_info ("host-identifier must be an option");
+				end_parse (&parse);
+				return DHCP_R_INVALIDARG;
+			}
+
+			known = 0;
+			option = NULL;
+			status = parse_option_name(parse, 1, &known, &option);
+
+			if ((status != ISC_R_SUCCESS) || (option == NULL)) {
+				log_info ("status %d from parse_option_name()",status);
+				end_parse (&parse);
+				return DHCP_R_INVALIDARG;
+			}
+
+			if (!known) {
+				/* unknown option */
+				end_parse (&parse);
+				log_info ("unknown option");
+				return DHCP_R_INVALIDARG;
+			}
+
+			if (! parse_option_data(&expr, parse, 1, option)) {
+				log_info ("error from parse_option_data()");
+				option_dereference(&option, MDL);
+				end_parse (&parse);
+				return DHCP_R_INVALIDARG;
+			}
+		
+			option_reference(&host->host_id_option, option, MDL);
+			option_dereference(&option, MDL);
+			data_string_copy(&host->host_id, 
+					 &expr->data.const_data, MDL);
+			expression_dereference(&expr, MDL);
+
+			end_parse (&parse);
+		} else {
+			log_info ("value type not one of omapi_datatype_data or omapi_datatype_string");
+			return DHCP_R_INVALIDARG;
+		}
+
+		return ISC_R_SUCCESS;
+	}
+	/* ck at cksoft.de 2012-10-07 END OMAPI PATCH PART 2/5 */
+
 	if (!omapi_ds_strcmp (name, "statements")) {
 		if (!host -> group) {
 			if (!clone_group (&host -> group, root_group, MDL))
@@ -1218,6 +1325,7 @@
 	if (!strcmp (name, "updated")) {
 		/* There must be a client identifier of some sort. */
 		if (host -> interface.hlen == 0 &&
+		    !host -> host_id_option && 	/* ck at cksoft.de 20121014 OMAPI PATCH PART 3/5, host_id_option qualifies as a client identifier */
 		    !host -> client_identifier.len)
 			return DHCP_R_INVALIDARG;
 
@@ -1339,6 +1447,26 @@
 			return status;
 	}
 
+	/* ck at cksoft.de 2012-10-07 BEGIN OMAPI PATCH PART 4/5 */
+	/* Stuff agent_options. Adapted from write_lease() in server/db.c
+	 * There is a single host identifier option in the host object in host_decl->host_id_option.
+	 * As there is no option_cache the data is in the datastring host_decl->host_id
+	 */
+	if (host -> host_id_option && host -> host_id.len) {
+		status = omapi_connection_put_name (c, host -> host_id_option -> name );
+		if (status != ISC_R_SUCCESS)
+			return status;
+
+		status = omapi_connection_put_string (c,
+			pretty_print_option ( host -> host_id_option,
+				host -> host_id.data, host -> host_id.len, 1, 1));
+
+		if (status != ISC_R_SUCCESS)
+			return status;
+	}
+
+	/* ck at cksoft.de 2012-10-07 END OMAPI PATCH PART 4/5 */
+
 	/* Write out the inner object, if any. */
 	if (h -> inner && h -> inner -> type -> stuff_values) {
 		status = ((*(h -> inner -> type -> stuff_values))
-------------- next part --------------
--- server/db.c.orig	2012-10-14 23:06:47.000000000 +0200
+++ server/db.c	2012-10-15 08:54:51.000000000 +0200
@@ -379,6 +379,18 @@
 					++errors;
 			}
 		}
+		/* ck at cksoft.de 2012-10-14 BEGIN OMAPI PATCH PART 5/5 */
+		if (host -> host_id_option && host -> host_id.len) {
+			errno = 0;
+			fprintf (db_file, "\n  host-identifier option agent.%s %s;",
+				host -> host_id_option -> name,
+				pretty_print_option ( host -> host_id_option,
+					host -> host_id.data, host -> host_id.len, 1, 1));
+
+			if (errno)
+				++errors;
+		}
+		/* ck at cksoft.de 2012-10-14 END OMAPI PATCH PART 5/5 */
 		
 		memset (&ip_addrs, 0, sizeof ip_addrs);
 		if (host -> fixed_addr &&


More information about the dhcp-hackers mailing list