1: /* dhcpctl.c
2:
3: Subroutines providing general support for objects. */
4:
5: /*
6: * Copyright (c) 2004,2007,2009 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: * https://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: * ``https://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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>