xref: /netbsd-src/external/mpl/dhcp/dist/doc/api+protocol (revision 6fb29d29285c26a62fae51364e3aa9f51d403424)
1*6fb29d29SchristosThis file documents the protocol that the ISC DHCP server and ISC
2*6fb29d29SchristosObject Management clients (clients that use the ISC Object Management
3*6fb29d29SchristosAPI) speak between one another.
4*6fb29d29Schristos
5*6fb29d29SchristosProtocol:
6*6fb29d29Schristos
7*6fb29d29SchristosAll multi-byte numbers are represented in network byte order.
8*6fb29d29Schristos
9*6fb29d29SchristosOn startup, each side sends a status message indicating what version
10*6fb29d29Schristosof the protocol they are speaking.   The status message looks like
11*6fb29d29Schristosthis:
12*6fb29d29Schristos
13*6fb29d29Schristos+---------+---------+
14*6fb29d29Schristos| version | hlength |
15*6fb29d29Schristos+---------+---------+
16*6fb29d29Schristos
17*6fb29d29Schristosversion - a 32-bit fixed-point number with the decimal point between
18*6fb29d29Schristos	  the third and second decimal digits from the left,
19*6fb29d29Schristos	  representing the version of the protocol.   The current
20*6fb29d29Schristos	  protocol version is 1.00.   If the field were considered as
21*6fb29d29Schristos	  a 32-bit integer, this would correspond to a value of 100
22*6fb29d29Schristos	  decimal, or 0x64.
23*6fb29d29Schristos
24*6fb29d29Schristoshlength - a 32-bit integer representing the length of the fixed-length
25*6fb29d29Schristos	  header in subsequent messages.   This is normally 56, but
26*6fb29d29Schristos	  can be changed to a value larger than 56 by either side
27*6fb29d29Schristos	  without upgrading the revision number.
28*6fb29d29Schristos
29*6fb29d29Schristos
30*6fb29d29SchristosThe startup message is not authenticated.   Either side may reject the
31*6fb29d29Schristosother side's startup message as invalid by simply closing the
32*6fb29d29Schristosconnection.   The only fixed part of the startup message is the
33*6fb29d29Schristosversion number - future versions may delete hlength, or add further
34*6fb29d29Schristosstartup information.
35*6fb29d29Schristos
36*6fb29d29SchristosFollowing the startup message, all messages have the same format.
37*6fb29d29SchristosCurrently, the format includes a fixed-length header (the length in
38*6fb29d29Schristoshlength, above)
39*6fb29d29Schristos
40*6fb29d29Schristos+--------+----+--------+----+-----+---------+------------+------------+-----+
41*6fb29d29Schristos| authid | op | handle | id | rid | authlen | msg values | obj values | sig |
42*6fb29d29Schristos+--------+----+--------+----+-----+---------+------------+------------+-----+
43*6fb29d29Schristos
44*6fb29d29SchristosThe fixed-length header consists of:
45*6fb29d29Schristos
46*6fb29d29Schristosauthid = a 32-bit authenticator handle.
47*6fb29d29Schristos	For an original message (one not in response to some other
48*6fb29d29Schristos	message), this will be chosen by the originator.   For a
49*6fb29d29Schristos	message in response to another message, the authenticator for
50*6fb29d29Schristos	that message is used, except if the response is an error
51*6fb29d29Schristos	message indicating that the authenticator used was unknown,
52*6fb29d29Schristos	in which case the null authenticator is used.   Messages that
53*6fb29d29Schristos	are generated as the result of a notify registration use the
54*6fb29d29Schristos	authenticator used in the original notify registration.
55*6fb29d29Schristos	The authenticator itself is generated by having one side of
56*6fb29d29Schristos	the connection send an object of type "authenticator" to the
57*6fb29d29Schristos	other side with values that indicate what kind of
58*6fb29d29Schristos	authentication mechanism to use and what key to use.   The two
59*6fb29d29Schristos	most likely things here are a Kerberos V principal name or the
60*6fb29d29Schristos	name of a shared secret that can be used to calculate an MD5
61*6fb29d29Schristos	hash.   The mechanism for doing this has yet to be finalized.
62*6fb29d29Schristos	If authid is zero, the message is not authenticated.
63*6fb29d29Schristos
64*6fb29d29Schristosop = 32-bit opcode, one of:
65*6fb29d29Schristos	open = 1
66*6fb29d29Schristos	refresh = 2
67*6fb29d29Schristos	update = 3
68*6fb29d29Schristos	notify = 4
69*6fb29d29Schristos	error = 5
70*6fb29d29Schristos	delete = 6
71*6fb29d29Schristoshandle = 32-bit object handle
72*6fb29d29Schristos	A handle on the object being opened, created, refreshed or
73*6fb29d29Schristos	updated.   If no handle is yet available (e.g., with open and
74*6fb29d29Schristos	new), then the value zero is sent.
75*6fb29d29Schristosid = 32-bit transaction id of the message - a monotonically increasing
76*6fb29d29Schristos     number that starts with some randomly chosen number at the
77*6fb29d29Schristos     beginning of the life of the connection.   The value should never
78*6fb29d29Schristos     be zero.
79*6fb29d29Schristosrid = 32-bit transaction ID of the message to which this message is a
80*6fb29d29Schristos      response, or zero if this message is not in response to a
81*6fb29d29Schristos      message from the other side.
82*6fb29d29Schristos
83*6fb29d29Schristosauthlen = a 32-bit number representing the length of the authenticator
84*6fb29d29Schristos
85*6fb29d29Schristosmsg values = a series of name+value pairs, specific to this message.
86*6fb29d29Schristos	 Each name+value pair starts with a 16-bit name length,
87*6fb29d29Schristos	 followed by that many bytes of name, followed by a 32-bit
88*6fb29d29Schristos	 value length, followed by that many bytes of value.   If the
89*6fb29d29Schristos	 length is zero, this is a value of the blank string.   If the
90*6fb29d29Schristos	 length is all ones (2^32-1), then there is no value - for an
91*6fb29d29Schristos	 update, this means the value for this name and the name
92*6fb29d29Schristos	 itself should be deleted from the object, which may or may
93*6fb29d29Schristos	 not be possible.   The list of name/value pairs ends with a
94*6fb29d29Schristos	 zero-length name, which is not followed by a value
95*6fb29d29Schristos	 length/value pair.
96*6fb29d29Schristos
97*6fb29d29Schristosobj values = a series of name+value pairs, as above, specific to the
98*6fb29d29Schristos	object being created, updated or refreshed.
99*6fb29d29Schristos
100*6fb29d29Schristossignature = authlen bytes of data signing the message.   The signature
101*6fb29d29Schristos	    algorithm is a property of the authenticator handle.
102*6fb29d29Schristos
103*6fb29d29SchristosMessage types:
104*6fb29d29Schristos
105*6fb29d29Schristos1: open
106*6fb29d29Schristos   relevant input values:
107*6fb29d29Schristos	object-type = the name of the type of object
108*6fb29d29Schristos	open:create = boolean - create the object if it doesn't yet exist
109*6fb29d29Schristos	open:exclusive = boolean - don't open the object if it does exist
110*6fb29d29Schristos	open:update = boolean - update the object with included values
111*6fb29d29Schristos		      if it matches.
112*6fb29d29Schristos	the handle should always be the null handle
113*6fb29d29Schristos
114*6fb29d29Schristos   The input value must also contain key information for the type of
115*6fb29d29Schristos   object being searched that uniquely identifies an object, or search
116*6fb29d29Schristos   information that matches only one object.  Each object has a key
117*6fb29d29Schristos   specification (a key is something that uniquely identifies an
118*6fb29d29Schristos   object), so see the key specification for that object to see
119*6fb29d29Schristos   what to send here.   An open message with the create flag set must
120*6fb29d29Schristos   specify a key, and not merely matching criteria.   Some objects may
121*6fb29d29Schristos   allow more than one key, and it may be that the union of those keys
122*6fb29d29Schristos   is required to uniquely identify the object, or it may be that any
123*6fb29d29Schristos   one such key will uniquely identify the object.   The documentation
124*6fb29d29Schristos   for the type of object will specify this.
125*6fb29d29Schristos
126*6fb29d29Schristos   An open message will result in an immediate response message whose
127*6fb29d29Schristos   opcode will either be "error" or "update".   The error message may
128*6fb29d29Schristos   include an error:reason value containing a text string explaining
129*6fb29d29Schristos   the error, and will always include an error:code value which will
130*6fb29d29Schristos   be the numeric error code for what went wrong.   Possible error
131*6fb29d29Schristos   codes are:
132*6fb29d29Schristos
133*6fb29d29Schristos	not found - no such object exists
134*6fb29d29Schristos	already exists - object already exists, and exclusive flag was
135*6fb29d29Schristos			 set.
136*6fb29d29Schristos	not unique - more than one object matching the specification
137*6fb29d29Schristos		     exists.
138*6fb29d29Schristos	permission denied - the authenticator ID specified does not
139*6fb29d29Schristos			    have authorization to access this object,
140*6fb29d29Schristos			    or if the update flag was specified, to
141*6fb29d29Schristos			    update the object.
142*6fb29d29Schristos
143*6fb29d29Schristos   If the response is an update message, the update message will
144*6fb29d29Schristos   include the object handle and all of the name/value pairs
145*6fb29d29Schristos   associated with that object.
146*6fb29d29Schristos
147*6fb29d29Schristos2: refresh
148*6fb29d29Schristos
149*6fb29d29Schristos   no input values except the handle need be specified.   The null
150*6fb29d29Schristos   handle may not be specified.   If the handle is valid, and the
151*6fb29d29Schristos   authenticator ID specified has permission to examine the object,
152*6fb29d29Schristos   then an update message will be sent for that object.   Otherwise,
153*6fb29d29Schristos   one of the following errors will be sent:
154*6fb29d29Schristos
155*6fb29d29Schristos	invalid handle - the handle does not refer to a known object
156*6fb29d29Schristos	permisson denied - the handle refers to an object that the
157*6fb29d29Schristos			   requestor does not have permission to
158*6fb29d29Schristos			   examine.
159*6fb29d29Schristos
160*6fb29d29Schristos3: update
161*6fb29d29Schristos
162*6fb29d29Schristos   Requests that the contents of the specified object be updated with
163*6fb29d29Schristos   the values included.   Values that are not specified are not
164*6fb29d29Schristos   updated.   The response will be either an error message or an
165*6fb29d29Schristos   update-ok message.   If rid is nonzero, no response will be
166*6fb29d29Schristos   generated, even if there was an error.   Possible errors include:
167*6fb29d29Schristos
168*6fb29d29Schristos	invalid handle - no such object was found
169*6fb29d29Schristos	permission denied - the handle refers to an object that the
170*6fb29d29Schristos			    requestor does not have permission to
171*6fb29d29Schristos			    modify.
172*6fb29d29Schristos	not confirmed - the update could not be committed due to some
173*6fb29d29Schristos			kind of resource problem, for example
174*6fb29d29Schristos			insufficient memory or a disk failure.
175*6fb29d29Schristos
176*6fb29d29Schristos4: notify
177*6fb29d29Schristos
178*6fb29d29Schristos   Requests that whenever the object with the specified handle is
179*6fb29d29Schristos   modified, an update be sent.   If there is something wrong with the
180*6fb29d29Schristos   request, an error message will be returned immediately.
181*6fb29d29Schristos   Otherwise, whenever a change is made to the object, an update
182*6fb29d29Schristos   message will be sent containing whatever changes were made (or
183*6fb29d29Schristos   possibly all the values associated with the object, depending on
184*6fb29d29Schristos   the implementation).   Possible errors:
185*6fb29d29Schristos
186*6fb29d29Schristos	invalid handle
187*6fb29d29Schristos	permission denied - the handle refers to an object that the
188*6fb29d29Schristos			    requestor does not have permission to
189*6fb29d29Schristos			    examine.
190*6fb29d29Schristos	not supported - the object implementation does not support
191*6fb29d29Schristos			notifications
192*6fb29d29Schristos
193*6fb29d29Schristos5: status
194*6fb29d29Schristos
195*6fb29d29Schristos   Sends a status code in response to a message.  Always sent in
196*6fb29d29Schristos   response to a message sent by the other side.  There should never
197*6fb29d29Schristos   be a response to this message.
198*6fb29d29Schristos
199*6fb29d29Schristos6: delete
200*6fb29d29Schristos
201*6fb29d29Schristos   Deletes the specified object.   Response will be either request-ok,
202*6fb29d29Schristos   or error.   Possible errors include:
203*6fb29d29Schristos
204*6fb29d29Schristos	invalid handle - no such object was found
205*6fb29d29Schristos	permission denied - the handle refers to an object that the
206*6fb29d29Schristos			    requestor does not have permission to
207*6fb29d29Schristos			    modify.
208*6fb29d29Schristos	not confirmed - the deletion could not be committed due to
209*6fb29d29Schristos			some kind of resource problem, for example
210*6fb29d29Schristos			insufficient memory or a disk failure.
211*6fb29d29Schristos
212*6fb29d29Schristos7: notify-cancel
213*6fb29d29Schristos
214*6fb29d29Schristos   Like notify, but requests that an existing notification be cancelled.
215*6fb29d29Schristos
216*6fb29d29Schristos8: notify-cancelled
217*6fb29d29Schristos
218*6fb29d29Schristos   Indicates that because of a local change, a notification that had
219*6fb29d29Schristos   been registered can no longer be performed.   This could be as a
220*6fb29d29Schristos   result of the permissions on a object changing, or an object being
221*6fb29d29Schristos   deleted.   There should never be a response to this message.
222*6fb29d29Schristos
223*6fb29d29Schristosinternals:
224*6fb29d29Schristos
225*6fb29d29SchristosBoth client and server use same protocol and infrastructure.   There
226*6fb29d29Schristosare many object types, each of which is stored in a registry.
227*6fb29d29SchristosObjects whose type is not recognized can either be handled by the
228*6fb29d29Schristosgeneric object type, which is registered with the type "*".   If no
229*6fb29d29Schristosgeneric object type is registered, then objects with unknown types are
230*6fb29d29Schristossimply not supported.   On the client, there are probably no special
231*6fb29d29Schristosobject handlers (although this is by no means forbidden).   On the
232*6fb29d29Schristosserver, probably everything is a special object.
233*6fb29d29Schristos
234*6fb29d29SchristosEach object type has the following methods:
235*6fb29d29Schristos
236*6fb29d29Schristos
237*6fb29d29Schristos
238*6fb29d29Schristos
239*6fb29d29Schristosdhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
240*6fb29d29Schristos				char *server_name, int port,
241*6fb29d29Schristos				dhcpctl_handle *authinfo)
242*6fb29d29Schristos	synchronous
243*6fb29d29Schristos	returns nonzero status code if it didn't connect, zero otherwise
244*6fb29d29Schristos	stores connection handle through connection, which can be used
245*6fb29d29Schristos	for subsequent access to the specified server.
246*6fb29d29Schristos	server_name is the name of the server, and port is the TCP
247*6fb29d29Schristos	port on which it is listening.
248*6fb29d29Schristos	authinfo is the handle to an object containing authentication
249*6fb29d29Schristos	information.
250*6fb29d29Schristos
251*6fb29d29Schristosdhcpctl_status dhcpctl_open_object (dhcpctl_handle h,
252*6fb29d29Schristos				    dhcpctl_handle connection,
253*6fb29d29Schristos				    int flags)
254*6fb29d29Schristos	asynchronous - just queues the request
255*6fb29d29Schristos	returns nonzero status code if open couldn't be queued
256*6fb29d29Schristos	returns zero if open was queued
257*6fb29d29Schristos	h is a handle to an object created by dhcpctl_new_object
258*6fb29d29Schristos	connection is a connection to a DHCP server
259*6fb29d29Schristos	flags include:
260*6fb29d29Schristos	   DHCPCTL_CREATE - if the object doesn't exist, create it
261*6fb29d29Schristos	   DHCPCTL_UPDATE - update the object on the server using the
262*6fb29d29Schristos			    attached parameters
263*6fb29d29Schristos	   DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE
264*6fb29d29Schristos			  was also specified
265*6fb29d29Schristos
266*6fb29d29Schristosdhcpctl_status dhcpctl_new_object (dhcpctl_handle *h,
267*6fb29d29Schristos				   dhcpctl_handle connection,
268*6fb29d29Schristos				   char *object_type)
269*6fb29d29Schristos	synchronous - creates a local handle for a host entry.
270*6fb29d29Schristos	returns nonzero status code if the local host entry couldn't
271*6fb29d29Schristos	be created
272*6fb29d29Schristos	stores handle to host through h if successful, and returns zero.
273*6fb29d29Schristos	object_type is a pointer to a NUL-terminated string containing
274*6fb29d29Schristos	the ascii name of the type of object being accessed - e.g., "host"
275*6fb29d29Schristos
276*6fb29d29Schristosdhcpctl_status dhcpctl_set_callback (dhcpctl_handle h, void *data,
277*6fb29d29Schristos				     void (*callback) (dhcpctl_handle,
278*6fb29d29Schristos						       dhcpctl_status, void *))
279*6fb29d29Schristos	synchronous, with asynchronous aftereffect
280*6fb29d29Schristos	handle is some object upon which some kind of process has been
281*6fb29d29Schristos	started - e.g., an open, an update or a refresh.
282*6fb29d29Schristos	data is an anonymous pointer containing some information that
283*6fb29d29Schristos	the callback will use to figure out what event completed.
284*6fb29d29Schristos	return value of 0 means callback was successfully set, a nonzero
285*6fb29d29Schristos	status code is returned otherwise.
286*6fb29d29Schristos	Upon completion of whatever task is in process, the callback
287*6fb29d29Schristos	will be passed the handle to the object, a status code
288*6fb29d29Schristos	indicating what happened, and the anonymous pointer passed to
289*6fb29d29Schristos
290*6fb29d29Schristosdhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
291*6fb29d29Schristos					    dhcpctl_status *s)
292*6fb29d29Schristos	synchronous
293*6fb29d29Schristos	returns zero if the callback completes, a nonzero status if
294*6fb29d29Schristos	there was some problem relating to the wait operation.   The
295*6fb29d29Schristos	status of the queued request will be stored through s, and
296*6fb29d29Schristos	will also be either zero for success or nonzero for some kind
297*6fb29d29Schristos	of failure.    Never returns until completion or until the
298*6fb29d29Schristos	connection to the server is lost.   This performs the same
299*6fb29d29Schristos	function as dhcpctl_set_callback and the subsequent callback,
300*6fb29d29Schristos	for programs that want to do inline execution instead of using
301*6fb29d29Schristos	callbacks.
302*6fb29d29Schristos
303*6fb29d29Schristosdhcpctl_status dhcpctl_get_value (data_string *result,
304*6fb29d29Schristos				  dhcpctl_handle h, char *value_name)
305*6fb29d29Schristos	synchronous
306*6fb29d29Schristos	returns zero if the call succeeded, a nonzero status code if
307*6fb29d29Schristos	it didn't.
308*6fb29d29Schristos	result is the address of an empty data string (initialized
309*6fb29d29Schristos	with bzero or cleared with data_string_forget).   On
310*6fb29d29Schristos	successful completion, the addressed data string will contain
311*6fb29d29Schristos	the value that was fetched.
312*6fb29d29Schristos	dhcpctl_handle refers to some dhcpctl item
313*6fb29d29Schristos	value_name refers to some value related to that item - e.g.,
314*6fb29d29Schristos	for a handle associated with a completed host lookup, value
315*6fb29d29Schristos	could be one of "hardware-address", "dhcp-client-identifier",
316*6fb29d29Schristos	"known" or "client-hostname".
317*6fb29d29Schristos
318*6fb29d29Schristosdhcpctl_status dhcpctl_get_boolean (int *result,
319*6fb29d29Schristos				    dhcpctl_handle h, char *value_name)
320*6fb29d29Schristos	like dhcpctl_get_value, but more convenient for boolean
321*6fb29d29Schristos	values, since no data_string needs to be dealt with.
322*6fb29d29Schristos
323*6fb29d29Schristosdhcpctl_status dhcpctl_set_value (dhcpctl_handle h, data_string value,
324*6fb29d29Schristos				  char *value_name)
325*6fb29d29Schristos	Sets a value on an object referred to by a dhcpctl_handle.
326*6fb29d29Schristos	The opposite of dhcpctl_get_value.   Does not update the
327*6fb29d29Schristos	server - just sets the value on the handle.
328*6fb29d29Schristos
329*6fb29d29Schristosdhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, char *value,
330*6fb29d29Schristos					 char *value_name)
331*6fb29d29Schristos	Sets a NUL-terminated ASCII value on an object referred to by
332*6fb29d29Schristos	a dhcpctl_handle.   like dhcpctl_set_value, but saves the
333*6fb29d29Schristos	trouble of creating a data_string for a NUL-terminated string.
334*6fb29d29Schristos	Does not update the server - just sets the value on the handle.
335*6fb29d29Schristos
336*6fb29d29Schristosdhcpctl_status dhcpctl_set_boolean (dhcpctl_handle h, int value,
337*6fb29d29Schristos				    char *value_name)
338*6fb29d29Schristos	Sets a boolean value on an object - like dhcpctl_set_value,
339*6fb29d29Schristos	only more convenient for booleans.
340*6fb29d29Schristos
341*6fb29d29Schristosdhcpctl_status dhcpctl_object_update (dhcpctl_handle h)
342*6fb29d29Schristos	Queues an update on the object referenced by the handle (there
343*6fb29d29Schristos	can't be any other work in progress on the handle).   An
344*6fb29d29Schristos	update means local parameters will be sent to the server.
345*6fb29d29Schristos
346*6fb29d29Schristosdhcpctl_status dhcpctl_object_refresh (dhcpctl_handle h)
347*6fb29d29Schristos	Queues an update on the object referenced by the handle (there
348*6fb29d29Schristos	can't be any other work in progress on the handle).   An
349*6fb29d29Schristos	update means local parameters will be sent to the server.
350*6fb29d29Schristos
351*6fb29d29Schristosdhcpctl_status dhcpctl_object_delete (dhcpctl_handle h)
352*6fb29d29Schristos	Queues a delete of the object referenced by the handle (there
353*6fb29d29Schristos	can't be any other work in progress on the handle).   A
354*6fb29d29Schristos	delete means that the object will be permanently deleted on
355*6fb29d29Schristos	the remote end, assuming the remote end supports object
356*6fb29d29Schristos	persistence.
357*6fb29d29Schristos
358*6fb29d29SchristosSo a sample program that would update a host declaration would look
359*6fb29d29Schristossomething like this:
360*6fb29d29Schristos
361*6fb29d29Schristos	/* Create a local object into which to store authentication
362*6fb29d29Schristos	   information. */
363*6fb29d29Schristos	if ((status = dhcpctl_new_object (&auth, dhcpctl_null_handle,
364*6fb29d29Schristos					  "authentication-information")))
365*6fb29d29Schristos		dhcpctl_error ("Can't create authentication information: %m");
366*6fb29d29Schristos
367*6fb29d29Schristos	/* Set up the authenticator with an algorithm type, user name and
368*6fb29d29Schristos	   password. */
369*6fb29d29Schristos	if ((status = dhcpctl_set_string_value (&auth, "mellon", "username")))
370*6fb29d29Schristos		dhcpctl_error ("Can't set username: %m", status);
371*6fb29d29Schristos	if ((status = dhcpctl_set_string_value (&auth, "three blind mice",
372*6fb29d29Schristos						"password")))
373*6fb29d29Schristos		dhcpctl_error ("Can't set password: %m", status);
374*6fb29d29Schristos	if ((status = dhcpctl_set_string_value (&auth, "md5-hash",
375*6fb29d29Schristos						"algorithm")))
376*6fb29d29Schristos		dhcpctl_error ("Can't set authentication algorithm: %m.",
377*6fb29d29Schristos			       status);
378*6fb29d29Schristos
379*6fb29d29Schristos	/* Connect to the server. */
380*6fb29d29Schristos	if ((status = dhcpctl_connect (&c, "dhcp.server.com", 612, &auth)))
381*6fb29d29Schristos
382*6fb29d29Schristos		dhcpctl_error ("Can't connect to dhcp.server.com: %m",
383*6fb29d29Schristos			       status);
384*6fb29d29Schristos
385*6fb29d29Schristos	/* Create a host object. */
386*6fb29d29Schristos	if ((status = dhcpctl_new_object (&hp, c, "host")))
387*6fb29d29Schristos		dhcpctl_error ("Host create failed: %m", status);
388*6fb29d29Schristos
389*6fb29d29Schristos	/* Create a data_string to contain the host's client
390*6fb29d29Schristos	   identifier, and set it. */
391*6fb29d29Schristos	if ((status =
392*6fb29d29Schristos	     data_string_create_from_hex (&client_id,
393*6fb29d29Schristos					  "1:08:00:2b:34:1a:c3")))
394*6fb29d29Schristos		dhcpctl_error ("Can't create client identifier: %m");
395*6fb29d29Schristos	if ((status = dhcpctl_set_value (hp, client_id,
396*6fb29d29Schristos					 "dhcp-client-identifier")))
397*6fb29d29Schristos		dhcpctl_error ("Host client identifier set failed.");
398*6fb29d29Schristos	/* Set the known flag to 1. */
399*6fb29d29Schristos	if ((status = dhcpctl_set_boolean (hp, 1, "known")))
400*6fb29d29Schristos		dhcpctl_error ("Host known set failed.");
401*6fb29d29Schristos
402*6fb29d29Schristos	/* Open an existing host object that matches the client identifier,
403*6fb29d29Schristos	   and update it from the local context, or if no host entry
404*6fb29d29Schristos	   yet exists matching the identifier, create one and
405*6fb29d29Schristos	   initialize it. */
406*6fb29d29Schristos	if ((status = dhcpctl_open_object (&hp, c,
407*6fb29d29Schristos					   DHCPCTL_CREATE | DHCPCTL_UPDATE)))
408*6fb29d29Schristos		dhcpctl_error ("Can't open host: %m", status);
409*6fb29d29Schristos
410*6fb29d29Schristos	/* Wait for the process to complete, check status. */
411*6fb29d29Schristos	if ((status = dhcpctl_wait_for_completion (hp, &wait_status)))
412*6fb29d29Schristos		dhcpctl_error ("Host create/lookup wait failed: %m", status);
413*6fb29d29Schristos	if (waitstatus)
414*6fb29d29Schristos		dhcpctl_error ("Host create/lookup failed: %m", status);
415*6fb29d29Schristos
416*6fb29d29SchristosThe API is a bit complicated, for a couple of reasons.   I want to
417*6fb29d29Schristosmake it general, so that there aren't a bazillion functions to call,
418*6fb29d29Schristosone for each data type.   I want it to be thread-safe, which is why
419*6fb29d29Schristoseach function returns a status and the error printer requires a status
420*6fb29d29Schristoscode for input.   I want it to be possible to make it asynchronous, so
421*6fb29d29Schristosthat it can work in tandem with, for example, an X toolkit.   If
422*6fb29d29Schristosyou're just writing a simple update cgi program, you probably won't
423*6fb29d29Schristoswant to bother to use the asynchronous callbacks, and indeed the above
424*6fb29d29Schristosexample doesn't.
425*6fb29d29Schristos
426*6fb29d29SchristosI glossed over data strings above - basically, they're objects with a
427*6fb29d29Schristospointer to a reference-counted buffer structure, an offset into that
428*6fb29d29Schristosbuffer, and a length.   These are used within the DHCP server, so you
429*6fb29d29Schristoscan get an idea of how they work - basically, they're a convenient and
430*6fb29d29Schristosefficient way to store a string with a length such that substrings can
431*6fb29d29Schristoseasily be taken and such that more than one user at a time can have a
432*6fb29d29Schristospointer to the string.
433*6fb29d29Schristos
434*6fb29d29SchristosI will also probably add locking primitives, so that you can get the
435*6fb29d29Schristosvalue of something and be sure that some other updator process won't
436*6fb29d29Schristosmodify it while you have the lock.
437