]> git.ipfire.org Git - thirdparty/dhcp.git/blob - dhcpctl/dhcpctl.c
Code cleanup to remove warnings from "gcc -Wall".
[thirdparty/dhcp.git] / dhcpctl / dhcpctl.c
1 /* dhcpctl.c
2
3 Subroutines providing general support for objects. */
4
5 /*
6 * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
33 */
34
35 #include "dhcpd.h"
36 #include <omapip/omapip_p.h>
37 #include "dhcpctl.h"
38
39 omapi_object_type_t *dhcpctl_callback_type;
40 omapi_object_type_t *dhcpctl_remote_type;
41
42 /* dhcpctl_initialize ()
43
44 Must be called before any other dhcpctl function. */
45
46 dhcpctl_status dhcpctl_initialize ()
47 {
48 isc_result_t status;
49
50 status = omapi_init();
51 if (status != ISC_R_SUCCESS)
52 return status;
53
54 status = omapi_object_type_register (&dhcpctl_callback_type,
55 "dhcpctl-callback",
56 dhcpctl_callback_set_value,
57 dhcpctl_callback_get_value,
58 dhcpctl_callback_destroy,
59 dhcpctl_callback_signal_handler,
60 dhcpctl_callback_stuff_values,
61 0, 0, 0, 0, 0, 0,
62 sizeof
63 (dhcpctl_callback_object_t), 0,
64 RC_MISC);
65 if (status != ISC_R_SUCCESS)
66 return status;
67
68 status = omapi_object_type_register (&dhcpctl_remote_type,
69 "dhcpctl-remote",
70 dhcpctl_remote_set_value,
71 dhcpctl_remote_get_value,
72 dhcpctl_remote_destroy,
73 dhcpctl_remote_signal_handler,
74 dhcpctl_remote_stuff_values,
75 0, 0, 0, 0, 0, 0,
76 sizeof (dhcpctl_remote_object_t),
77 0, RC_MISC);
78 if (status != ISC_R_SUCCESS)
79 return status;
80
81 return ISC_R_SUCCESS;
82 }
83
84 /* dhcpctl_connect
85
86 synchronous
87 returns nonzero status code if it didn't connect, zero otherwise
88 stores connection handle through connection, which can be used
89 for subsequent access to the specified server.
90 server_name is the name of the server, and port is the TCP
91 port on which it is listening.
92 authinfo is the handle to an object containing authentication
93 information. */
94
95 dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
96 const char *server_name, int port,
97 dhcpctl_handle authinfo)
98 {
99 isc_result_t status;
100
101 status = omapi_generic_new (connection, MDL);
102 if (status != ISC_R_SUCCESS) {
103 return status;
104 }
105
106 status = omapi_protocol_connect (*connection, server_name,
107 (unsigned)port, authinfo);
108 if (status == ISC_R_SUCCESS)
109 return status;
110 if (status != ISC_R_INCOMPLETE) {
111 omapi_object_dereference (connection, MDL);
112 return status;
113 }
114
115 status = omapi_wait_for_completion (*connection, 0);
116 if (status != ISC_R_SUCCESS) {
117 omapi_object_dereference (connection, MDL);
118 return status;
119 }
120
121 return status;
122 }
123
124 /* dhcpctl_wait_for_completion
125
126 synchronous
127 returns zero if the callback completes, a nonzero status if
128 there was some problem relating to the wait operation. The
129 status of the queued request will be stored through s, and
130 will also be either zero for success or nonzero for some kind
131 of failure. Never returns until completion or until the
132 connection to the server is lost. This performs the same
133 function as dhcpctl_set_callback and the subsequent callback,
134 for programs that want to do inline execution instead of using
135 callbacks. */
136
137 dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
138 dhcpctl_status *s)
139 {
140 isc_result_t status;
141 status = omapi_wait_for_completion (h, 0);
142 if (status != ISC_R_SUCCESS)
143 return status;
144 if (h -> type == dhcpctl_remote_type)
145 *s = ((dhcpctl_remote_object_t *)h) -> waitstatus;
146 return ISC_R_SUCCESS;
147 }
148
149 /* dhcpctl_get_value
150
151 synchronous
152 returns zero if the call succeeded, a nonzero status code if
153 it didn't.
154 result is the address of an empty data string (initialized
155 with bzero or cleared with data_string_forget). On
156 successful completion, the addressed data string will contain
157 the value that was fetched.
158 dhcpctl_handle refers to some dhcpctl item
159 value_name refers to some value related to that item - e.g.,
160 for a handle associated with a completed host lookup, value
161 could be one of "hardware-address", "dhcp-client-identifier",
162 "known" or "client-hostname". */
163
164 dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result,
165 dhcpctl_handle h, const char *value_name)
166 {
167 isc_result_t status;
168 omapi_value_t *tv = (omapi_value_t *)0;
169 unsigned len;
170 int ip;
171
172 status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv);
173 if (status != ISC_R_SUCCESS)
174 return status;
175
176 switch (tv -> value -> type) {
177 case omapi_datatype_int:
178 len = sizeof (int);
179 break;
180
181 case omapi_datatype_string:
182 case omapi_datatype_data:
183 len = tv -> value -> u.buffer.len;
184 break;
185
186 case omapi_datatype_object:
187 len = sizeof (omapi_handle_t);
188 break;
189
190 default:
191 omapi_typed_data_dereference (&tv -> value, MDL);
192 return ISC_R_UNEXPECTED;
193 }
194
195 status = omapi_data_string_new (result, len, MDL);
196 if (status != ISC_R_SUCCESS) {
197 omapi_typed_data_dereference (&tv -> value, MDL);
198 return status;
199 }
200
201 switch (tv -> value -> type) {
202 case omapi_datatype_int:
203 ip = htonl (tv -> value -> u.integer);
204 memcpy ((*result) -> value, &ip, sizeof ip);
205 break;
206
207 case omapi_datatype_string:
208 case omapi_datatype_data:
209 memcpy ((*result) -> value,
210 tv -> value -> u.buffer.value,
211 tv -> value -> u.buffer.len);
212 break;
213
214 case omapi_datatype_object:
215 ip = htonl (tv -> value -> u.object -> handle);
216 memcpy ((*result) -> value, &ip, sizeof ip);
217 break;
218 }
219
220 omapi_value_dereference (&tv, MDL);
221 return ISC_R_SUCCESS;
222 }
223
224 /* dhcpctl_get_boolean
225
226 like dhcpctl_get_value, but more convenient for boolean
227 values, since no data_string needs to be dealt with. */
228
229 dhcpctl_status dhcpctl_get_boolean (int *result,
230 dhcpctl_handle h, const char *value_name)
231 {
232 isc_result_t status;
233 dhcpctl_data_string data = (dhcpctl_data_string)0;
234 int rv;
235
236 status = dhcpctl_get_value (&data, h, value_name);
237 if (status != ISC_R_SUCCESS)
238 return status;
239 if (data -> len != sizeof rv) {
240 omapi_data_string_dereference (&data, MDL);
241 return ISC_R_UNEXPECTED;
242 }
243 memcpy (&rv, data -> value, sizeof rv);
244 *result = ntohl (rv);
245 return ISC_R_SUCCESS;
246 }
247
248 /* dhcpctl_set_value
249
250 Sets a value on an object referred to by a dhcpctl_handle.
251 The opposite of dhcpctl_get_value. Does not update the
252 server - just sets the value on the handle. */
253
254 dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, dhcpctl_data_string value,
255 const char *value_name)
256 {
257 isc_result_t status;
258 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
259 omapi_data_string_t *name = (omapi_data_string_t *)0;
260
261 status = omapi_data_string_new (&name, strlen (value_name), MDL);
262 if (status != ISC_R_SUCCESS)
263 return status;
264 memcpy (name -> value, value_name, strlen (value_name));
265
266 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data,
267 value -> len);
268 if (status != ISC_R_SUCCESS) {
269 omapi_data_string_dereference (&name, MDL);
270 return status;
271 }
272 memcpy (tv -> u.buffer.value, value -> value, value -> len);
273
274 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
275 omapi_data_string_dereference (&name, MDL);
276 omapi_typed_data_dereference (&tv, MDL);
277 return status;
278 }
279
280 /* dhcpctl_set_string_value
281
282 Sets a NUL-terminated ASCII value on an object referred to by
283 a dhcpctl_handle. like dhcpctl_set_value, but saves the
284 trouble of creating a data_string for a NUL-terminated string.
285 Does not update the server - just sets the value on the handle. */
286
287 dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, const char *value,
288 const char *value_name)
289 {
290 isc_result_t status;
291 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
292 omapi_data_string_t *name = (omapi_data_string_t *)0;
293
294 status = omapi_data_string_new (&name, strlen (value_name), MDL);
295 if (status != ISC_R_SUCCESS)
296 return status;
297 memcpy (name -> value, value_name, strlen (value_name));
298
299 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value);
300 if (status != ISC_R_SUCCESS) {
301 omapi_data_string_dereference (&name, MDL);
302 return status;
303 }
304
305 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
306 omapi_data_string_dereference (&name, MDL);
307 omapi_typed_data_dereference (&tv, MDL);
308 return status;
309 }
310
311 /* dhcpctl_set_buffer_value
312
313 Sets a value on an object referred to by a dhcpctl_handle. like
314 dhcpctl_set_value, but saves the trouble of creating a data_string
315 for string for which we have a buffer and length. Does not update
316 the server - just sets the value on the handle. */
317
318 dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h,
319 const char *value, unsigned len,
320 const char *value_name)
321 {
322 isc_result_t status;
323 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
324 omapi_data_string_t *name = (omapi_data_string_t *)0;
325 unsigned ll;
326
327 ll = strlen (value_name);
328 status = omapi_data_string_new (&name, ll, MDL);
329 if (status != ISC_R_SUCCESS)
330 return status;
331 memcpy (name -> value, value_name, ll);
332
333 status = omapi_typed_data_new (MDL, &tv,
334 omapi_datatype_data, len, value);
335 if (status != ISC_R_SUCCESS) {
336 omapi_data_string_dereference (&name, MDL);
337 return status;
338 }
339 memcpy (tv -> u.buffer.value, value, len);
340
341 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
342 omapi_data_string_dereference (&name, MDL);
343 omapi_typed_data_dereference (&tv, MDL);
344 return status;
345 }
346
347 /* dhcpctl_set_null_value
348
349 Sets a null value on an object referred to by a dhcpctl_handle. */
350
351 dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h,
352 const char *value_name)
353 {
354 isc_result_t status;
355 omapi_data_string_t *name = (omapi_data_string_t *)0;
356 unsigned ll;
357
358 ll = strlen (value_name);
359 status = omapi_data_string_new (&name, ll, MDL);
360 if (status != ISC_R_SUCCESS)
361 return status;
362 memcpy (name -> value, value_name, ll);
363
364 status = omapi_set_value (h, (omapi_object_t *)0, name,
365 (omapi_typed_data_t *)0);
366 omapi_data_string_dereference (&name, MDL);
367 return status;
368 }
369
370 /* dhcpctl_set_boolean_value
371
372 Sets a boolean value on an object - like dhcpctl_set_value,
373 only more convenient for booleans. */
374
375 dhcpctl_status dhcpctl_set_boolean_value (dhcpctl_handle h, int value,
376 const char *value_name)
377 {
378 isc_result_t status;
379 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
380 omapi_data_string_t *name = (omapi_data_string_t *)0;
381
382 status = omapi_data_string_new (&name, strlen (value_name), MDL);
383 if (status != ISC_R_SUCCESS)
384 return status;
385 memcpy (name -> value, value_name, strlen (value_name));
386
387 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
388 if (status != ISC_R_SUCCESS) {
389 omapi_data_string_dereference (&name, MDL);
390 return status;
391 }
392
393 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
394 omapi_data_string_dereference (&name, MDL);
395 omapi_typed_data_dereference (&tv, MDL);
396 return status;
397 }
398
399 /* dhcpctl_set_int_value
400
401 Sets a boolean value on an object - like dhcpctl_set_value,
402 only more convenient for booleans. */
403
404 dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value,
405 const char *value_name)
406 {
407 isc_result_t status;
408 omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
409 omapi_data_string_t *name = (omapi_data_string_t *)0;
410
411 status = omapi_data_string_new (&name, strlen (value_name), MDL);
412 if (status != ISC_R_SUCCESS)
413 return status;
414 memcpy (name -> value, value_name, strlen (value_name));
415
416 status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value);
417 if (status != ISC_R_SUCCESS) {
418 omapi_data_string_dereference (&name, MDL);
419 return status;
420 }
421
422 status = omapi_set_value (h, (omapi_object_t *)0, name, tv);
423 omapi_data_string_dereference (&name, MDL);
424 omapi_typed_data_dereference (&tv, MDL);
425 return status;
426 }
427
428 /* dhcpctl_object_update
429
430 Queues an update on the object referenced by the handle (there
431 can't be any other work in progress on the handle). An
432 update means local parameters will be sent to the server. */
433
434 dhcpctl_status dhcpctl_object_update (dhcpctl_handle connection,
435 dhcpctl_handle h)
436 {
437 isc_result_t status;
438 omapi_object_t *message = (omapi_object_t *)0;
439 dhcpctl_remote_object_t *ro;
440
441 if (h -> type != dhcpctl_remote_type)
442 return ISC_R_INVALIDARG;
443 ro = (dhcpctl_remote_object_t *)h;
444
445 status = omapi_message_new (&message, MDL);
446 if (status != ISC_R_SUCCESS) {
447 omapi_object_dereference (&message, MDL);
448 return status;
449 }
450 status = omapi_set_int_value (message, (omapi_object_t *)0,
451 "op", OMAPI_OP_UPDATE);
452 if (status != ISC_R_SUCCESS) {
453 omapi_object_dereference (&message, MDL);
454 return status;
455 }
456
457 status = omapi_set_object_value (message, (omapi_object_t *)0,
458 "object", h);
459 if (status != ISC_R_SUCCESS) {
460 omapi_object_dereference (&message, MDL);
461 return status;
462 }
463
464 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
465 (int)(ro -> remote_handle));
466 if (status != ISC_R_SUCCESS) {
467 omapi_object_dereference (&message, MDL);
468 return status;
469 }
470
471 omapi_message_register (message);
472 status = omapi_protocol_send_message (connection -> outer,
473 (omapi_object_t *)0,
474 message, (omapi_object_t *)0);
475 omapi_object_dereference (&message, MDL);
476 return status;
477 }
478
479 /* Requests a refresh on the object referenced by the handle (there
480 can't be any other work in progress on the handle). A
481 refresh means local parameters are updated from the server. */
482
483 dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle connection,
484 dhcpctl_handle h)
485 {
486 isc_result_t status;
487 omapi_object_t *message = (omapi_object_t *)0;
488 dhcpctl_remote_object_t *ro;
489
490 if (h -> type != dhcpctl_remote_type)
491 return ISC_R_INVALIDARG;
492 ro = (dhcpctl_remote_object_t *)h;
493
494 status = omapi_message_new (&message, MDL);
495 if (status != ISC_R_SUCCESS) {
496 omapi_object_dereference (&message, MDL);
497 return status;
498 }
499 status = omapi_set_int_value (message, (omapi_object_t *)0,
500 "op", OMAPI_OP_REFRESH);
501 if (status != ISC_R_SUCCESS) {
502 omapi_object_dereference (&message, MDL);
503 return status;
504 }
505 status = omapi_set_int_value (message, (omapi_object_t *)0,
506 "handle", (int)(ro -> remote_handle));
507 if (status != ISC_R_SUCCESS) {
508 omapi_object_dereference (&message, MDL);
509 return status;
510 }
511
512 omapi_message_register (message);
513 status = omapi_protocol_send_message (connection -> outer,
514 (omapi_object_t *)0,
515 message, (omapi_object_t *)0);
516
517 /* We don't want to send the contents of the object down the
518 wire, but we do need to reference it so that we know what
519 to do with the update. */
520 status = omapi_set_object_value (message, (omapi_object_t *)0,
521 "object", h);
522 if (status != ISC_R_SUCCESS) {
523 omapi_object_dereference (&message, MDL);
524 return status;
525 }
526
527 omapi_object_dereference (&message, MDL);
528 return status;
529 }
530
531 /* Requests the removal of the object referenced by the handle (there
532 can't be any other work in progress on the handle). A
533 removal means that all searchable references to the object on the
534 server are deleted. */
535
536 dhcpctl_status dhcpctl_object_remove (dhcpctl_handle connection,
537 dhcpctl_handle h)
538 {
539 isc_result_t status;
540 omapi_object_t *message = (omapi_object_t *)0;
541 dhcpctl_remote_object_t *ro;
542
543 if (h -> type != dhcpctl_remote_type)
544 return ISC_R_INVALIDARG;
545 ro = (dhcpctl_remote_object_t *)h;
546
547 status = omapi_message_new (&message, MDL);
548 if (status != ISC_R_SUCCESS) {
549 omapi_object_dereference (&message, MDL);
550 return status;
551 }
552 status = omapi_set_int_value (message, (omapi_object_t *)0,
553 "op", OMAPI_OP_DELETE);
554 if (status != ISC_R_SUCCESS) {
555 omapi_object_dereference (&message, MDL);
556 return status;
557 }
558
559 status = omapi_set_int_value (message, (omapi_object_t *)0, "handle",
560 (int)(ro -> remote_handle));
561 if (status != ISC_R_SUCCESS) {
562 omapi_object_dereference (&message, MDL);
563 return status;
564 }
565
566 status = omapi_set_object_value (message, (omapi_object_t *)0,
567 "notify-object", h);
568 if (status != ISC_R_SUCCESS) {
569 omapi_object_dereference (&message, MDL);
570 return status;
571 }
572
573 omapi_message_register (message);
574 status = omapi_protocol_send_message (connection -> outer,
575 (omapi_object_t *)0,
576 message, (omapi_object_t *)0);
577 omapi_object_dereference (&message, MDL);
578 return status;
579 }
580
581 isc_result_t dhcpctl_data_string_dereference (dhcpctl_data_string *vp,
582 const char *file, int line)
583 {
584 return omapi_data_string_dereference (vp, file, line);
585 }