Annotation of embedaddon/dhcp/doc/api+protocol, revision 1.1.1.1
1.1 misho 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.
4:
5: Protocol:
6:
7: All multi-byte numbers are represented in network byte order.
8:
9: On startup, each side sends a status message indicating what version
10: of the protocol they are speaking. The status message looks like
11: this:
12:
13: +---------+---------+
14: | version | hlength |
15: +---------+---------+
16:
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
22: decimal, or 0x64.
23:
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.
28:
29:
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
34: startup information.
35:
36: Following the startup message, all messages have the same format.
37: Currently, the format includes a fixed-length header (the length in
38: hlength, above)
39:
40: +--------+----+--------+----+-----+---------+------------+------------+-----+
41: | authid | op | handle | id | rid | authlen | msg values | obj values | sig |
42: +--------+----+--------+----+-----+---------+------------+------------+-----+
43:
44: The fixed-length header consists of:
45:
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.
63:
64: op = 32-bit opcode, one of:
65: open = 1
66: refresh = 2
67: update = 3
68: notify = 4
69: error = 5
70: delete = 6
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
78: be zero.
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.
82:
83: authlen = a 32-bit number representing the length of the authenticator
84:
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
95: length/value pair.
96:
97: obj values = a series of name+value pairs, as above, specific to the
98: object being created, updated or refreshed.
99:
100: signature = authlen bytes of data signing the message. The signature
101: algorithm is a property of the authenticator handle.
102:
103: Message types:
104:
105: 1: open
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
111: if it matches.
112: the handle should always be the null handle
113:
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.
125:
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
131: codes are:
132:
133: not found - no such object exists
134: already exists - object already exists, and exclusive flag was
135: set.
136: not unique - more than one object matching the specification
137: exists.
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
141: update the object.
142:
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.
146:
147: 2: refresh
148:
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:
154:
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
158: examine.
159:
160: 3: update
161:
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:
167:
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
171: modify.
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.
175:
176: 4: notify
177:
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:
185:
186: invalid handle
187: permission denied - the handle refers to an object that the
188: requestor does not have permission to
189: examine.
190: not supported - the object implementation does not support
191: notifications
192:
193: 5: status
194:
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.
198:
199: 6: delete
200:
201: Deletes the specified object. Response will be either request-ok,
202: or error. Possible errors include:
203:
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
207: modify.
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.
211:
212: 7: notify-cancel
213:
214: Like notify, but requests that an existing notification be cancelled.
215:
216: 8: notify-cancelled
217:
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.
222:
223: internals:
224:
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.
233:
234: Each object type has the following methods:
235:
236:
237:
238:
239: dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
240: char *server_name, int port,
241: dhcpctl_handle *authinfo)
242: synchronous
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
249: information.
250:
251: dhcpctl_status dhcpctl_open_object (dhcpctl_handle h,
252: dhcpctl_handle connection,
253: int flags)
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
259: flags include:
260: DHCPCTL_CREATE - if the object doesn't exist, create it
261: DHCPCTL_UPDATE - update the object on the server using the
262: attached parameters
263: DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE
264: was also specified
265:
266: dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h,
267: dhcpctl_handle connection,
268: char *object_type)
269: synchronous - creates a local handle for a host entry.
270: returns nonzero status code if the local host entry couldn't
271: be created
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"
275:
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
289:
290: dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
291: dhcpctl_status *s)
292: synchronous
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
301: callbacks.
302:
303: dhcpctl_status dhcpctl_get_value (data_string *result,
304: dhcpctl_handle h, char *value_name)
305: synchronous
306: returns zero if the call succeeded, a nonzero status code if
307: it didn't.
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".
317:
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.
322:
323: dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, data_string value,
324: char *value_name)
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.
328:
329: dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, char *value,
330: char *value_name)
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.
335:
336: dhcpctl_status dhcpctl_set_boolean (dhcpctl_handle h, int value,
337: char *value_name)
338: Sets a boolean value on an object - like dhcpctl_set_value,
339: only more convenient for booleans.
340:
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.
345:
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.
350:
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
356: persistence.
357:
358: So a sample program that would update a host declaration would look
359: something like this:
360:
361: /* Create a local object into which to store authentication
362: information. */
363: if ((status = dhcpctl_new_object (&auth, dhcpctl_null_handle,
364: "authentication-information")))
365: dhcpctl_error ("Can't create authentication information: %m");
366:
367: /* Set up the authenticator with an algorithm type, user name and
368: password. */
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",
372: "password")))
373: dhcpctl_error ("Can't set password: %m", status);
374: if ((status = dhcpctl_set_string_value (&auth, "md5-hash",
375: "algorithm")))
376: dhcpctl_error ("Can't set authentication algorithm: %m.",
377: status);
378:
379: /* Connect to the server. */
380: if ((status = dhcpctl_connect (&c, "dhcp.server.com", 612, &auth)))
381:
382: dhcpctl_error ("Can't connect to dhcp.server.com: %m",
383: status);
384:
385: /* Create a host object. */
386: if ((status = dhcpctl_new_object (&hp, c, "host")))
387: dhcpctl_error ("Host create failed: %m", status);
388:
389: /* Create a data_string to contain the host's client
390: identifier, and set it. */
391: if ((status =
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.");
401:
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
405: initialize it. */
406: if ((status = dhcpctl_open_object (&hp, c,
407: DHCPCTL_CREATE | DHCPCTL_UPDATE)))
408: dhcpctl_error ("Can't open host: %m", status);
409:
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);
413: if (waitstatus)
414: dhcpctl_error ("Host create/lookup failed: %m", status);
415:
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
424: example doesn't.
425:
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.
433:
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.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>