1This file documents the protocol that the ISC DHCP server and ISC 2Object Management clients (clients that use the ISC Object Management 3API) speak between one another. 4 5Protocol: 6 7All multi-byte numbers are represented in network byte order. 8 9On startup, each side sends a status message indicating what version 10of the protocol they are speaking. The status message looks like 11this: 12 13+---------+---------+ 14| version | hlength | 15+---------+---------+ 16 17version - 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 24hlength - 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 30The startup message is not authenticated. Either side may reject the 31other side's startup message as invalid by simply closing the 32connection. The only fixed part of the startup message is the 33version number - future versions may delete hlength, or add further 34startup information. 35 36Following the startup message, all messages have the same format. 37Currently, the format includes a fixed-length header (the length in 38hlength, above) 39 40+--------+----+--------+----+-----+---------+------------+------------+-----+ 41| authid | op | handle | id | rid | authlen | msg values | obj values | sig | 42+--------+----+--------+----+-----+---------+------------+------------+-----+ 43 44The fixed-length header consists of: 45 46authid = 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 64op = 32-bit opcode, one of: 65 open = 1 66 refresh = 2 67 update = 3 68 notify = 4 69 error = 5 70 delete = 6 71handle = 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. 75id = 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. 79rid = 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 83authlen = a 32-bit number representing the length of the authenticator 84 85msg 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 97obj values = a series of name+value pairs, as above, specific to the 98 object being created, updated or refreshed. 99 100signature = authlen bytes of data signing the message. The signature 101 algorithm is a property of the authenticator handle. 102 103Message types: 104 1051: 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 1472: 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 1603: 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 1764: 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 1935: 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 1996: 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 2127: notify-cancel 213 214 Like notify, but requests that an existing notification be cancelled. 215 2168: 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 223internals: 224 225Both client and server use same protocol and infrastructure. There 226are many object types, each of which is stored in a registry. 227Objects whose type is not recognized can either be handled by the 228generic object type, which is registered with the type "*". If no 229generic object type is registered, then objects with unknown types are 230simply not supported. On the client, there are probably no special 231object handlers (although this is by no means forbidden). On the 232server, probably everything is a special object. 233 234Each object type has the following methods: 235 236 237 238 239dhcpctl_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 251dhcpctl_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 266dhcpctl_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 276dhcpctl_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 290dhcpctl_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 303dhcpctl_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 318dhcpctl_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 323dhcpctl_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 329dhcpctl_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 336dhcpctl_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 341dhcpctl_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 346dhcpctl_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 351dhcpctl_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 358So a sample program that would update a host declaration would look 359something 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 416The API is a bit complicated, for a couple of reasons. I want to 417make it general, so that there aren't a bazillion functions to call, 418one for each data type. I want it to be thread-safe, which is why 419each function returns a status and the error printer requires a status 420code for input. I want it to be possible to make it asynchronous, so 421that it can work in tandem with, for example, an X toolkit. If 422you're just writing a simple update cgi program, you probably won't 423want to bother to use the asynchronous callbacks, and indeed the above 424example doesn't. 425 426I glossed over data strings above - basically, they're objects with a 427pointer to a reference-counted buffer structure, an offset into that 428buffer, and a length. These are used within the DHCP server, so you 429can get an idea of how they work - basically, they're a convenient and 430efficient way to store a string with a length such that substrings can 431easily be taken and such that more than one user at a time can have a 432pointer to the string. 433 434I will also probably add locking primitives, so that you can get the 435value of something and be sure that some other updator process won't 436modify it while you have the lock. 437