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