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