]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/protocol.c
Fix up some issues found by static analysis
[thirdparty/dhcp.git] / omapip / protocol.c
CommitLineData
61b844bf
TL
1/* protocol.c
2
3 Functions supporting the object management protocol... */
4
5/*
bb9189c3
SR
6 * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 8 * Copyright (c) 1999-2003 by Internet Software Consortium
61b844bf 9 *
98311e4b
DH
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
61b844bf 13 *
98311e4b
DH
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
61b844bf 21 *
98311e4b
DH
22 * Internet Systems Consortium, Inc.
23 * 950 Charter Street
24 * Redwood City, CA 94063
25 * <info@isc.org>
2c85ac9b 26 * https://www.isc.org/
49733f31 27 *
98311e4b 28 * This software has been written for Internet Systems Consortium
49733f31 29 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
98311e4b 30 * To learn more about Internet Systems Consortium, see
2c85ac9b 31 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
49733f31
TL
32 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
33 * ``http://www.nominum.com''.
61b844bf
TL
34 */
35
fe5b0fdd
DH
36#include "dhcpd.h"
37
6a4c4be8 38#include <omapip/omapip_p.h>
61b844bf 39
20916cae
TL
40OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
41 omapi_type_protocol)
42OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
43 omapi_type_protocol_listener)
44
61b844bf 45isc_result_t omapi_protocol_connect (omapi_object_t *h,
b1b7b521 46 const char *server_name,
d9eefc5d 47 unsigned port,
49146f3c 48 omapi_object_t *a)
61b844bf 49{
a3239005 50 isc_result_t rstatus, status;
61b844bf
TL
51 omapi_protocol_object_t *obj;
52
e11a162f
DN
53#ifdef DEBUG_PROTOCOL
54 log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
55#endif
56
20916cae
TL
57 obj = (omapi_protocol_object_t *)0;
58 status = omapi_protocol_allocate (&obj, MDL);
59 if (status != ISC_R_SUCCESS)
60 return status;
61b844bf 61
a3239005 62 rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
98bf1607 63 if (rstatus != ISC_R_SUCCESS && rstatus != DHCP_R_INCOMPLETE) {
20916cae 64 omapi_protocol_dereference (&obj, MDL);
a3239005 65 return rstatus;
61b844bf 66 }
4bd8800e
TL
67 status = omapi_object_reference (&h -> outer,
68 (omapi_object_t *)obj, MDL);
61b844bf 69 if (status != ISC_R_SUCCESS) {
20916cae 70 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
71 return status;
72 }
4bd8800e 73 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 74 if (status != ISC_R_SUCCESS) {
20916cae 75 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
76 return status;
77 }
78
49146f3c
DN
79 /* If we were passed a default authenticator, store it now. We'll
80 open it once we're connected. */
81 if (a) {
82 obj -> default_auth =
83 dmalloc (sizeof(omapi_remote_auth_t), MDL);
84 if (!obj -> default_auth) {
85 omapi_protocol_dereference (&obj, MDL);
86 return ISC_R_NOMEMORY;
87 }
88
89 obj -> default_auth -> next = (omapi_remote_auth_t *)0;
90 status = omapi_object_reference (&obj -> default_auth -> a,
91 a, MDL);
92 if (status != ISC_R_SUCCESS) {
93 dfree (obj -> default_auth, MDL);
94 omapi_protocol_dereference (&obj, MDL);
95 return status;
96 }
97
98 obj -> insecure = 0;
98bf1607 99 rstatus = DHCP_R_INCOMPLETE;
49146f3c
DN
100 } else {
101 obj -> insecure = 1;
a3239005 102#if 0
366556ef 103 status = ISC_R_SUCCESS;
a3239005 104#endif
49146f3c
DN
105 }
106
20916cae 107 omapi_protocol_dereference (&obj, MDL);
a3239005 108 return rstatus;
61b844bf
TL
109}
110
111/* Send the protocol introduction message. */
112isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
b1b7b521
TL
113 unsigned ver,
114 unsigned hsize)
61b844bf
TL
115{
116 isc_result_t status;
117 omapi_protocol_object_t *p;
118
e11a162f
DN
119#ifdef DEBUG_PROTOCOL
120 log_debug ("omapi_protocol_send_intro()");
121#endif
122
61b844bf 123 if (h -> type != omapi_type_protocol)
98bf1607 124 return DHCP_R_INVALIDARG;
61b844bf
TL
125 p = (omapi_protocol_object_t *)h;
126
127 if (!h -> outer || h -> outer -> type != omapi_type_connection)
128 return ISC_R_NOTCONNECTED;
129
130 status = omapi_connection_put_uint32 (h -> outer, ver);
131 if (status != ISC_R_SUCCESS)
132 return status;
133
134 status = omapi_connection_put_uint32 (h -> outer, hsize);
135
136 if (status != ISC_R_SUCCESS)
137 return status;
138
139 /* Require the other end to send an intro - this kicks off the
140 protocol input state machine. */
141 p -> state = omapi_protocol_intro_wait;
142 status = omapi_connection_require (h -> outer, 8);
98bf1607 143 if (status != ISC_R_SUCCESS && status != DHCP_R_NOTYET)
61b844bf
TL
144 return status;
145
146 /* Make up an initial transaction ID for this connection. */
147 p -> next_xid = random ();
148 return ISC_R_SUCCESS;
149}
150
74dc3e0b
EH
151#ifdef DEBUG_PROTOCOL
152extern const char *omapi_message_op_name(int);
153#endif /* DEBUG_PROTOCOL */
154
61b844bf
TL
155isc_result_t omapi_protocol_send_message (omapi_object_t *po,
156 omapi_object_t *id,
157 omapi_object_t *mo,
158 omapi_object_t *omo)
159{
160 omapi_protocol_object_t *p;
161 omapi_object_t *c;
20916cae 162 omapi_message_object_t *m, *om;
49146f3c
DN
163 omapi_remote_auth_t *ra;
164 omapi_value_t *signature;
61b844bf 165 isc_result_t status;
49146f3c 166 unsigned auth_len;
61b844bf
TL
167
168 if (po -> type != omapi_type_protocol ||
169 !po -> outer || po -> outer -> type != omapi_type_connection ||
165bce70 170 mo -> type != omapi_type_message)
98bf1607 171 return DHCP_R_INVALIDARG;
165bce70 172 if (omo && omo -> type != omapi_type_message)
98bf1607 173 return DHCP_R_INVALIDARG;
61b844bf
TL
174 p = (omapi_protocol_object_t *)po;
175 c = (omapi_object_t *)(po -> outer);
176 m = (omapi_message_object_t *)mo;
177 om = (omapi_message_object_t *)omo;
178
e11a162f 179#ifdef DEBUG_PROTOCOL
74dc3e0b
EH
180 log_debug ("omapi_protocol_send_message(): "
181 "op=%s handle=%#lx id=%#lx rid=%#lx",
182 omapi_message_op_name (m->op),
e11a162f
DN
183 (long)(m -> object ? m -> object -> handle : m -> handle),
184 (long)p -> next_xid, (long)m -> rid);
185#endif
186
49146f3c
DN
187 /* Find the authid to use for this message. */
188 if (id) {
189 for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
190 if (ra -> a == id) {
191 break;
192 }
193 }
194
195 if (!ra)
98bf1607 196 return DHCP_R_KEY_UNKNOWN;
49146f3c
DN
197 } else if (p -> remote_auth_list) {
198 ra = p -> default_auth;
199 } else {
200 ra = (omapi_remote_auth_t *)0;
201 }
202
203 if (ra) {
204 m -> authid = ra -> remote_handle;
205 status = omapi_object_reference (&m -> id_object,
206 ra -> a, MDL);
207 if (status != ISC_R_SUCCESS)
208 return status;
209 }
210
211 /* Write the ID of the authentication key we're using. */
212 status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
213 if (status != ISC_R_SUCCESS) {
214 omapi_disconnect (c, 1);
61b844bf 215 return status;
49146f3c
DN
216 }
217
218 /* Activate the authentication key on the connection. */
219 auth_len = 0;
220 if (ra) {
221 status = omapi_set_object_value (c, (omapi_object_t *)0,
222 "output-authenticator",
223 ra -> a);
224 if (status != ISC_R_SUCCESS) {
225 omapi_disconnect (c, 1);
226 return status;
227 }
228
229 status = omapi_connection_output_auth_length (c, &auth_len);
230 if (status != ISC_R_SUCCESS) {
231 omapi_disconnect (c, 1);
232 return status;
233 }
234 }
235
236 /* Write the authenticator length */
237 status = omapi_connection_put_uint32 (c, auth_len);
61b844bf
TL
238 if (status != ISC_R_SUCCESS) {
239 omapi_disconnect (c, 1);
240 return status;
241 }
242
243 /* Write the opcode. */
244 status = omapi_connection_put_uint32 (c, m -> op);
245 if (status != ISC_R_SUCCESS) {
246 omapi_disconnect (c, 1);
247 return status;
248 }
249
250 /* Write the handle. If we've been given an explicit handle, use
251 that. Otherwise, use the handle of the object we're sending.
252 The caller is responsible for arranging for one of these handles
253 to be set (or not). */
254 status = omapi_connection_put_uint32 (c, (m -> h
255 ? m -> h
5a8e13c6
TL
256 : (m -> object
257 ? m -> object -> handle
258 : 0)));
61b844bf
TL
259 if (status != ISC_R_SUCCESS) {
260 omapi_disconnect (c, 1);
261 return status;
262 }
263
264 /* Set and write the transaction ID. */
265 m -> id = p -> next_xid++;
266 status = omapi_connection_put_uint32 (c, m -> id);
267 if (status != ISC_R_SUCCESS) {
268 omapi_disconnect (c, 1);
269 return status;
270 }
271
272 /* Write the transaction ID of the message to which this is a
273 response, if there is such a message. */
5a8e13c6 274 status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
61b844bf
TL
275 if (status != ISC_R_SUCCESS) {
276 omapi_disconnect (c, 1);
277 return status;
278 }
279
581e37e4 280 /* Stuff out the name/value pairs specific to this message. */
5a8e13c6
TL
281 status = omapi_stuff_values (c, id, (omapi_object_t *)m);
282 if (status != ISC_R_SUCCESS) {
283 omapi_disconnect (c, 1);
284 return status;
581e37e4
TL
285 }
286
287 /* Write the zero-length name that terminates the list of name/value
288 pairs specific to the message. */
289 status = omapi_connection_put_uint16 (c, 0);
61b844bf
TL
290 if (status != ISC_R_SUCCESS) {
291 omapi_disconnect (c, 1);
292 return status;
293 }
294
581e37e4
TL
295 /* Stuff out all the published name/value pairs in the object that's
296 being sent in the message, if there is one. */
297 if (m -> object) {
298 status = omapi_stuff_values (c, id, m -> object);
299 if (status != ISC_R_SUCCESS) {
300 omapi_disconnect (c, 1);
301 return status;
302 }
303 }
304
61b844bf 305 /* Write the zero-length name that terminates the list of name/value
581e37e4 306 pairs for the associated object. */
61b844bf
TL
307 status = omapi_connection_put_uint16 (c, 0);
308 if (status != ISC_R_SUCCESS) {
309 omapi_disconnect (c, 1);
310 return status;
311 }
312
49146f3c
DN
313 if (ra) {
314 /* Calculate the message signature. */
315 signature = (omapi_value_t *)0;
316 status = omapi_get_value_str (c, (omapi_object_t *)0,
317 "output-signature", &signature);
318 if (status != ISC_R_SUCCESS) {
319 omapi_disconnect (c, 1);
320 return status;
321 }
322
323 /* Write the authenticator... */
324 status = (omapi_connection_copyin
325 (c, signature -> value -> u.buffer.value,
326 signature -> value -> u.buffer.len));
327 omapi_value_dereference (&signature, MDL);
328 if (status != ISC_R_SUCCESS) {
329 omapi_disconnect (c, 1);
330 return status;
331 }
332
333 /* Dectivate the authentication key on the connection. */
334 status = omapi_set_value_str (c, (omapi_object_t *)0,
335 "output-authenticator",
336 (omapi_typed_data_t *)0);
337 if (status != ISC_R_SUCCESS) {
338 omapi_disconnect (c, 1);
339 return status;
340 }
341 }
61b844bf 342
d758ad8c
TL
343 if (!omo) {
344 omapi_protocol_reference (&m -> protocol_object, p, MDL);
345 }
61b844bf
TL
346 return ISC_R_SUCCESS;
347}
348
349
350isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
b1b7b521 351 const char *name, va_list ap)
61b844bf
TL
352{
353 isc_result_t status;
354 omapi_protocol_object_t *p;
355 omapi_object_t *c;
d758ad8c 356 omapi_message_object_t *m;
49146f3c 357 omapi_value_t *signature;
61b844bf
TL
358 u_int16_t nlen;
359 u_int32_t vlen;
bbdb72a4 360 u_int32_t th;
31bbee78 361#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b
DH
362 unsigned long previous_outstanding = 0xDEADBEEF;
363 unsigned long connect_outstanding = 0xDEADBEEF;
31bbee78 364#endif
61b844bf
TL
365
366 if (h -> type != omapi_type_protocol) {
367 /* XXX shouldn't happen. Put an assert here? */
368 return ISC_R_UNEXPECTED;
369 }
370 p = (omapi_protocol_object_t *)h;
371
ffc05866 372 if (!strcmp (name, "connect")) {
31bbee78
TL
373#if defined (DEBUG_MEMORY_LEAKAGE)
374 connect_outstanding = dmalloc_outstanding;
375#endif
ffc05866
TL
376 /* Send the introductory message. */
377 status = omapi_protocol_send_intro
7deff076 378 (h, OMAPI_PROTOCOL_VERSION,
ffc05866
TL
379 sizeof (omapi_protocol_header_t));
380 if (status != ISC_R_SUCCESS) {
381 omapi_disconnect (p -> outer, 1);
382 return status;
383 }
384 return ISC_R_SUCCESS;
385 }
386
49146f3c
DN
387 /* Should only receive these when opening the initial authenticator. */
388 if (!strcmp (name, "status")) {
389 status = va_arg (ap, isc_result_t);
390 if (status != ISC_R_SUCCESS) {
391 omapi_signal_in (h -> inner, "status", status,
392 (omapi_object_t *)0);
393 omapi_disconnect (p -> outer, 1);
394 return status;
395 } else {
396 return omapi_signal_in (h -> inner, "ready");
397 }
398 }
399
31bbee78 400 /* If we get a disconnect, dump memory usage. */
a609e69b 401 if (!strcmp (name, "disconnect")) {
31bbee78 402#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b 403 if (connect_outstanding != 0xDEADBEEF) {
31bbee78
TL
404 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
405 dmalloc_generation,
406 dmalloc_outstanding - previous_outstanding,
407 dmalloc_outstanding, dmalloc_longterm, " long-term");
a609e69b 408 }
31bbee78 409#endif
d758ad8c 410#if defined (DEBUG_MEMORY_LEAKAGE)
a609e69b 411 dmalloc_dump_outstanding ();
31bbee78
TL
412#endif
413#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4619c0a2 414 dump_rc_history (h);
31bbee78 415#endif
a609e69b
TL
416 for (m = omapi_registered_messages; m; m = m -> next) {
417 if (m -> protocol_object == p) {
418 if (m -> object)
419 omapi_signal (m -> object, "disconnect");
420 }
421 }
4619c0a2
DH
422
423 /* XXX */
424 return ISC_R_SUCCESS;
31bbee78
TL
425 }
426
61b844bf
TL
427 /* Not a signal we recognize? */
428 if (strcmp (name, "ready")) {
429 if (p -> inner && p -> inner -> type -> signal_handler)
430 return (*(p -> inner -> type -> signal_handler)) (h,
431 name,
432 ap);
433 return ISC_R_NOTFOUND;
434 }
435
436 if (!p -> outer || p -> outer -> type != omapi_type_connection)
98bf1607 437 return DHCP_R_INVALIDARG;
61b844bf
TL
438 c = p -> outer;
439
440 /* We get here because we requested that we be woken up after
441 some number of bytes were read, and that number of bytes
442 has in fact been read. */
443 switch (p -> state) {
444 case omapi_protocol_intro_wait:
445 /* Get protocol version and header size in network
446 byte order. */
d9eefc5d
TL
447 omapi_connection_get_uint32 (c, &p -> protocol_version);
448 omapi_connection_get_uint32 (c, &p -> header_size);
61b844bf
TL
449
450 /* We currently only support the current protocol version. */
451 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
452 omapi_disconnect (c, 1);
98bf1607 453 return DHCP_R_VERSIONMISMATCH;
61b844bf
TL
454 }
455
456 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
457 omapi_disconnect (c, 1);
98bf1607 458 return DHCP_R_PROTOCOLERROR;
61b844bf
TL
459 }
460
49146f3c
DN
461 if (p -> default_auth) {
462 status = omapi_protocol_send_open
463 (h, (omapi_object_t *)0, "authenticator",
464 p -> default_auth -> a,
465 OMAPI_NOTIFY_PROTOCOL);
466 if (status != ISC_R_SUCCESS) {
467 omapi_disconnect (c, 1);
468 return status;
469 }
470 } else {
471 status = omapi_signal_in (h -> inner, "ready");
472 }
61b844bf
TL
473
474 to_header_wait:
475 /* The next thing we're expecting is a message header. */
476 p -> state = omapi_protocol_header_wait;
477
478 /* Register a need for the number of bytes in a
479 header, and if we already have that many, process
480 them immediately. */
d9eefc5d
TL
481 if ((omapi_connection_require (c, p -> header_size)) !=
482 ISC_R_SUCCESS)
61b844bf
TL
483 break;
484 /* If we already have the data, fall through. */
485
486 case omapi_protocol_header_wait:
31bbee78 487#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b 488 if (previous_outstanding != 0xDEADBEEF) {
31bbee78
TL
489 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
490 "generation", dmalloc_generation,
491 dmalloc_outstanding - previous_outstanding,
492 dmalloc_outstanding, dmalloc_longterm,
493 " long-term");
494#endif
495#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
496 dmalloc_dump_outstanding ();
497#endif
498#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4619c0a2 499 dump_rc_history (h);
31bbee78
TL
500#endif
501#if defined (DEBUG_MEMORY_LEAKAGE)
502 }
503 previous_outstanding = dmalloc_outstanding;
504#endif
db4cfe3b
DN
505 status = omapi_message_new ((omapi_object_t **)&p -> message,
506 MDL);
61b844bf
TL
507 if (status != ISC_R_SUCCESS) {
508 omapi_disconnect (c, 1);
509 return status;
510 }
511
49146f3c
DN
512 p -> verify_result = ISC_R_SUCCESS;
513
61b844bf 514 /* Swap in the header... */
d9eefc5d 515 omapi_connection_get_uint32 (c, &p -> message -> authid);
61b844bf 516
49146f3c
DN
517 /* Bind the authenticator to the message object. */
518 if (p -> message -> authid) {
519 status = (omapi_protocol_lookup_auth
520 (&p -> message -> id_object, h,
521 p -> message -> authid));
522 if (status != ISC_R_SUCCESS)
523 p -> verify_result = status;
524
525 /* Activate the authentication key. */
526 status = omapi_set_object_value
527 (c, (omapi_object_t *)0, "input-authenticator",
528 p -> message -> id_object);
529 if (status != ISC_R_SUCCESS) {
530 omapi_disconnect (c, 1);
531 return status;
532 }
533 }
534
d9eefc5d
TL
535 omapi_connection_get_uint32 (c, &p -> message -> authlen);
536 omapi_connection_get_uint32 (c, &p -> message -> op);
bbdb72a4 537 omapi_connection_get_uint32 (c, &th);
3185c188 538 p -> message -> h = th;
d9eefc5d
TL
539 omapi_connection_get_uint32 (c, &p -> message -> id);
540 omapi_connection_get_uint32 (c, &p -> message -> rid);
61b844bf
TL
541
542 /* If there was any extra header data, skip over it. */
543 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
544 omapi_connection_copyout
545 (0, c, (p -> header_size -
546 sizeof (omapi_protocol_header_t)));
547 }
548
549 /* XXX must compute partial signature across the
550 XXX preceding bytes. Also, if authenticator
551 specifies encryption as well as signing, we may
552 have to decrypt the data on the way in. */
553
581e37e4
TL
554 /* First we read in message-specific values, then object
555 values. */
556 p -> reading_message_values = 1;
557
61b844bf
TL
558 need_name_length:
559 /* The next thing we're expecting is length of the
560 first name. */
561 p -> state = omapi_protocol_name_length_wait;
562
563 /* Wait for a 16-bit length. */
564 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
565 break;
566 /* If it's already here, fall through. */
567
568 case omapi_protocol_name_length_wait:
569 omapi_connection_get_uint16 (c, &nlen);
570 /* A zero-length name means that we're done reading name+value
571 pairs. */
572 if (nlen == 0) {
581e37e4
TL
573 /* If we've already read in the object, we are
574 done reading the message, but if we've just
575 finished reading in the values associated
576 with the message, we need to read the
577 object. */
578 if (p -> reading_message_values) {
579 p -> reading_message_values = 0;
580 goto need_name_length;
581 }
582
61b844bf
TL
583 /* If the authenticator length is zero, there's no
584 signature to read in, so go straight to processing
585 the message. */
586 if (p -> message -> authlen == 0)
587 goto message_done;
588
589 /* The next thing we're expecting is the
590 message signature. */
591 p -> state = omapi_protocol_signature_wait;
592
593 /* Wait for the number of bytes specified for
594 the authenticator. If we already have it,
595 go read it in. */
596 if (omapi_connection_require
597 (c, p -> message -> authlen) == ISC_R_SUCCESS)
598 goto signature_wait;
599 break;
600 }
601
602 /* Allocate a buffer for the name. */
4bd8800e 603 status = (omapi_data_string_new (&p -> name, nlen, MDL));
61b844bf
TL
604 if (status != ISC_R_SUCCESS) {
605 omapi_disconnect (c, 1);
606 return ISC_R_NOMEMORY;
607 }
581e37e4 608 p -> state = omapi_protocol_name_wait;
61b844bf
TL
609 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
610 break;
611 /* If it's already here, fall through. */
612
613 case omapi_protocol_name_wait:
614 omapi_connection_copyout (p -> name -> value, c,
615 p -> name -> len);
616 /* Wait for a 32-bit length. */
581e37e4 617 p -> state = omapi_protocol_value_length_wait;
61b844bf
TL
618 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
619 break;
620 /* If it's already here, fall through. */
621
622 case omapi_protocol_value_length_wait:
623 omapi_connection_get_uint32 (c, &vlen);
624
625 /* Zero-length values are allowed - if we get one, we
626 don't have to read any data for the value - just
627 get the next one, if there is a next one. */
628 if (!vlen)
629 goto insert_new_value;
630
4bd8800e
TL
631 status = omapi_typed_data_new (MDL, &p -> value,
632 omapi_datatype_data,
633 vlen);
61b844bf
TL
634 if (status != ISC_R_SUCCESS) {
635 omapi_disconnect (c, 1);
636 return ISC_R_NOMEMORY;
637 }
638
581e37e4 639 p -> state = omapi_protocol_value_wait;
61b844bf
TL
640 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
641 break;
642 /* If it's already here, fall through. */
643
644 case omapi_protocol_value_wait:
645 omapi_connection_copyout (p -> value -> u.buffer.value, c,
646 p -> value -> u.buffer.len);
647
648 insert_new_value:
581e37e4
TL
649 if (p -> reading_message_values) {
650 status = (omapi_set_value
651 ((omapi_object_t *)p -> message,
652 p -> message -> id_object,
653 p -> name, p -> value));
654 } else {
655 if (!p -> message -> object) {
656 /* We need a generic object to hang off of the
657 incoming message. */
658 status = (omapi_generic_new
4bd8800e 659 (&p -> message -> object, MDL));
581e37e4
TL
660 if (status != ISC_R_SUCCESS) {
661 omapi_disconnect (c, 1);
662 return status;
663 }
664 }
665 status = (omapi_set_value
666 ((omapi_object_t *)p -> message -> object,
667 p -> message -> id_object,
668 p -> name, p -> value));
669 }
61b844bf
TL
670 if (status != ISC_R_SUCCESS) {
671 omapi_disconnect (c, 1);
672 return status;
673 }
4bd8800e 674 omapi_data_string_dereference (&p -> name, MDL);
d758ad8c
TL
675 if (p -> value)
676 omapi_typed_data_dereference (&p -> value, MDL);
61b844bf
TL
677 goto need_name_length;
678
679 signature_wait:
680 case omapi_protocol_signature_wait:
49146f3c
DN
681 if (p -> message -> id_object) {
682 /* Compute the signature of the message. */
683 signature = (omapi_value_t *)0;
684 status = omapi_get_value_str (c, (omapi_object_t *)0,
685 "input-signature",
686 &signature);
687 if (status != ISC_R_SUCCESS) {
688 omapi_disconnect (c, 1);
689 return status;
690 }
691
692 /* Disable the authentication key on the connection. */
693 status = omapi_set_value_str (c, (omapi_object_t *)0,
694 "input-authenticator",
695 (omapi_typed_data_t *)0);
696 if (status != ISC_R_SUCCESS) {
697 omapi_value_dereference (&signature, MDL);
698 omapi_disconnect (c, 1);
699 return status;
700 }
701 }
702
703 /* Read the authenticator. */
4bd8800e
TL
704 status = omapi_typed_data_new (MDL,
705 &p -> message -> authenticator,
61b844bf
TL
706 omapi_datatype_data,
707 p -> message -> authlen);
708
709 if (status != ISC_R_SUCCESS) {
49146f3c 710 omapi_value_dereference (&signature, MDL);
61b844bf
TL
711 omapi_disconnect (c, 1);
712 return ISC_R_NOMEMORY;
713 }
714 omapi_connection_copyout
715 (p -> message -> authenticator -> u.buffer.value, c,
716 p -> message -> authlen);
49146f3c
DN
717
718 /* Verify the signature. */
719 if (p -> message -> id_object &&
720 ((signature -> value -> u.buffer.len !=
721 p -> message -> authlen) ||
722 (memcmp (signature -> value -> u.buffer.value,
723 p -> message -> authenticator -> u.buffer.value,
724 p -> message -> authlen) != 0))) {
725 /* Invalid signature. */
98bf1607 726 p->verify_result = DHCP_R_INVALIDKEY;
49146f3c
DN
727 }
728
729 omapi_value_dereference (&signature, MDL);
61b844bf 730
581e37e4 731 /* Process the message. */
61b844bf 732 message_done:
49146f3c
DN
733 if (p -> verify_result != ISC_R_SUCCESS) {
734 status = omapi_protocol_send_status
735 (h, (omapi_object_t *)0, p -> verify_result,
736 p -> message -> id, (char *)0);
737 } else {
738 status = omapi_message_process
739 ((omapi_object_t *)p -> message, h);
740 }
581e37e4
TL
741 if (status != ISC_R_SUCCESS) {
742 omapi_disconnect (c, 1);
743 return ISC_R_NOMEMORY;
744 }
745
20916cae 746 omapi_message_dereference (&p -> message, MDL);
31bbee78
TL
747#if defined (DEBUG_MEMORY_LEAKAGE)
748 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
749 dmalloc_generation,
750 dmalloc_outstanding - previous_outstanding,
751 dmalloc_outstanding, dmalloc_longterm, " long-term");
752#endif
753#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
754 dmalloc_dump_outstanding ();
755#endif
756#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4619c0a2 757 dump_rc_history (h);
31bbee78
TL
758#endif
759#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b 760 previous_outstanding = 0xDEADBEEF;
31bbee78 761#endif
61b844bf
TL
762 /* Now wait for the next message. */
763 goto to_header_wait;
764
765 default:
766 /* XXX should never get here. Assertion? */
8a6dfe4c 767 break;
61b844bf
TL
768 }
769 return ISC_R_SUCCESS;
770}
771
49146f3c
DN
772isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
773 omapi_object_t *ao,
774 omapi_handle_t handle)
775{
776 omapi_protocol_object_t *p;
777 omapi_remote_auth_t *r;
778 isc_result_t status;
779
780 if (ao -> type != omapi_type_auth_key &&
781 (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
98bf1607 782 return DHCP_R_INVALIDARG;
49146f3c
DN
783
784 if (po -> type != omapi_type_protocol)
98bf1607 785 return DHCP_R_INVALIDARG;
49146f3c
DN
786 p = (omapi_protocol_object_t *)po;
787
e11a162f
DN
788#ifdef DEBUG_PROTOCOL
789 log_debug ("omapi_protocol_add_auth(name=%s)",
790 ((omapi_auth_key_t *)ao) -> name);
791#endif
792
49146f3c
DN
793 if (p -> verify_auth) {
794 status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
795 if (status != ISC_R_SUCCESS)
796 return status;
797 }
798
799 /* If omapi_protocol_connect() was called with a default
800 authenticator, p -> default_auth will already be set,
801 but p -> remote_auth_list will not yet be initialized. */
802 if (p -> default_auth && !p -> remote_auth_list) {
803 if (p -> default_auth -> a != ao) {
804 /* Something just went horribly wrong. */
805 omapi_disconnect (p -> outer, 1);
806 return ISC_R_UNEXPECTED;
807 }
808
809 p -> remote_auth_list = p -> default_auth;
810 p -> default_auth -> remote_handle = handle;
811
812 return omapi_signal_in (p -> inner, "ready");
813 }
814
815 r = dmalloc (sizeof(*r), MDL);
816 if (!r)
817 return ISC_R_NOMEMORY;
818
819 status = omapi_object_reference (&r -> a, ao, MDL);
820 if (status != ISC_R_SUCCESS) {
821 dfree (r, MDL);
822 return status;
823 }
824
825 r -> remote_handle = handle;
826 r -> next = p -> remote_auth_list;
827 p -> remote_auth_list = r;
828
829 return ISC_R_SUCCESS;
830}
831
832isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
833 omapi_object_t *po,
834 omapi_handle_t handle)
835{
836 omapi_protocol_object_t *p;
837 omapi_remote_auth_t *r;
838
839 if (po -> type != omapi_type_protocol)
98bf1607 840 return DHCP_R_INVALIDARG;
49146f3c
DN
841 p = (omapi_protocol_object_t *)po;
842
843 for (r = p -> remote_auth_list; r; r = r -> next)
844 if (r -> remote_handle == handle)
845 return omapi_object_reference (a, r -> a, MDL);
846
98bf1607 847 return DHCP_R_KEY_UNKNOWN;
49146f3c
DN
848}
849
61b844bf
TL
850isc_result_t omapi_protocol_set_value (omapi_object_t *h,
851 omapi_object_t *id,
852 omapi_data_string_t *name,
853 omapi_typed_data_t *value)
854{
49146f3c
DN
855 omapi_protocol_object_t *p;
856 omapi_remote_auth_t *r;
857
61b844bf 858 if (h -> type != omapi_type_protocol)
98bf1607 859 return DHCP_R_INVALIDARG;
49146f3c
DN
860 p = (omapi_protocol_object_t *)h;
861
862 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
863 if (value -> type != omapi_datatype_object)
98bf1607 864 return DHCP_R_INVALIDARG;
49146f3c
DN
865
866 if (!value || !value -> u.object) {
867 p -> default_auth = (omapi_remote_auth_t *)0;
868 } else {
869 for (r = p -> remote_auth_list; r; r = r -> next)
870 if (r -> a == value -> u.object)
871 break;
872
873 if (!r)
98bf1607 874 return DHCP_R_KEY_UNKNOWN;
49146f3c
DN
875
876 p -> default_auth = r;
877 }
878
879 return ISC_R_SUCCESS;
880 }
61b844bf
TL
881
882 if (h -> inner && h -> inner -> type -> set_value)
883 return (*(h -> inner -> type -> set_value))
884 (h -> inner, id, name, value);
885 return ISC_R_NOTFOUND;
886}
887
888isc_result_t omapi_protocol_get_value (omapi_object_t *h,
889 omapi_object_t *id,
890 omapi_data_string_t *name,
891 omapi_value_t **value)
892{
49146f3c
DN
893 omapi_protocol_object_t *p;
894
61b844bf 895 if (h -> type != omapi_type_protocol)
98bf1607 896 return DHCP_R_INVALIDARG;
49146f3c
DN
897 p = (omapi_protocol_object_t *)h;
898
899 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
900 if (!p -> default_auth)
901 return ISC_R_NOTFOUND;
902
903 return omapi_make_object_value (value, name,
904 p -> default_auth -> a, MDL);
905 }
61b844bf
TL
906
907 if (h -> inner && h -> inner -> type -> get_value)
908 return (*(h -> inner -> type -> get_value))
909 (h -> inner, id, name, value);
910 return ISC_R_NOTFOUND;
911}
912
4bd8800e
TL
913isc_result_t omapi_protocol_destroy (omapi_object_t *h,
914 const char *file, int line)
61b844bf
TL
915{
916 omapi_protocol_object_t *p;
917 if (h -> type != omapi_type_protocol)
98bf1607 918 return DHCP_R_INVALIDARG;
61b844bf
TL
919 p = (omapi_protocol_object_t *)h;
920 if (p -> message)
20916cae 921 omapi_message_dereference (&p -> message, file, line);
49146f3c
DN
922
923 /* This will happen if: 1) A default authenticator is supplied to
924 omapi_protocol_connect(), and 2) something goes wrong before
925 the authenticator can be opened. */
926 if (p -> default_auth && !p -> remote_auth_list)
927 dfree (p -> default_auth, file, line);
928
929 while (p -> remote_auth_list) {
bb9189c3
SR
930 omapi_remote_auth_t *r = p -> remote_auth_list;
931 p -> remote_auth_list = p -> remote_auth_list -> next;
932 omapi_object_dereference (&r -> a, file, line);
933 dfree (r, file, line);
49146f3c 934 }
61b844bf
TL
935 return ISC_R_SUCCESS;
936}
937
938/* Write all the published values associated with the object through the
939 specified connection. */
940
941isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
942 omapi_object_t *id,
943 omapi_object_t *p)
944{
61b844bf 945 if (p -> type != omapi_type_protocol)
98bf1607 946 return DHCP_R_INVALIDARG;
61b844bf
TL
947
948 if (p -> inner && p -> inner -> type -> stuff_values)
949 return (*(p -> inner -> type -> stuff_values)) (c, id,
950 p -> inner);
951 return ISC_R_SUCCESS;
952}
953
49146f3c
DN
954/* Returns a boolean indicating whether this protocol requires that
955 messages be authenticated or not. */
956
957isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
958{
959 if (h -> type != omapi_type_protocol)
960 return isc_boolean_false;
961 if (((omapi_protocol_object_t *)h) -> insecure)
962 return isc_boolean_false;
963 else
964 return isc_boolean_true;
965}
966
967/* Sets the address and authenticator verification callbacks. The handle
968 is to a listener object, not a protocol object. */
969
970isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
971 isc_result_t (*verify_addr)
972 (omapi_object_t *,
973 omapi_addr_t *),
974 isc_result_t (*verify_auth)
975 (omapi_object_t *,
976 omapi_auth_key_t *))
977{
978 omapi_protocol_listener_object_t *l;
979
980 if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
981 h = h -> outer;
982
983 if (h -> type != omapi_type_protocol_listener)
98bf1607 984 return DHCP_R_INVALIDARG;
49146f3c
DN
985 l = (omapi_protocol_listener_object_t *)h;
986
987 l -> verify_auth = verify_auth;
988 l -> insecure = 0;
989
990 return omapi_listener_configure_security (h -> outer, verify_addr);
991}
992
993
61b844bf
TL
994/* Set up a listener for the omapi protocol. The handle stored points to
995 a listener object, not a protocol object. */
996
997isc_result_t omapi_protocol_listen (omapi_object_t *h,
d9eefc5d 998 unsigned port,
61b844bf
TL
999 int max)
1000{
1001 isc_result_t status;
1002 omapi_protocol_listener_object_t *obj;
1003
20916cae
TL
1004 obj = (omapi_protocol_listener_object_t *)0;
1005 status = omapi_protocol_listener_allocate (&obj, MDL);
1006 if (status != ISC_R_SUCCESS)
1007 return status;
61b844bf 1008
4bd8800e
TL
1009 status = omapi_object_reference (&h -> outer,
1010 (omapi_object_t *)obj, MDL);
61b844bf 1011 if (status != ISC_R_SUCCESS) {
20916cae 1012 omapi_protocol_listener_dereference (&obj, MDL);
61b844bf
TL
1013 return status;
1014 }
4bd8800e 1015 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 1016 if (status != ISC_R_SUCCESS) {
20916cae 1017 omapi_protocol_listener_dereference (&obj, MDL);
61b844bf
TL
1018 return status;
1019 }
1020
49146f3c
DN
1021 /* What a terrible default. */
1022 obj -> insecure = 1;
1023
61b844bf 1024 status = omapi_listen ((omapi_object_t *)obj, port, max);
20916cae 1025 omapi_protocol_listener_dereference (&obj, MDL);
61b844bf
TL
1026 return status;
1027}
1028
1029/* Signal handler for protocol listener - if we get a connect signal,
1030 create a new protocol connection, otherwise pass the signal down. */
1031
1032isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
b1b7b521 1033 const char *name, va_list ap)
61b844bf
TL
1034{
1035 isc_result_t status;
1036 omapi_object_t *c;
1037 omapi_protocol_object_t *obj;
1038 omapi_protocol_listener_object_t *p;
1039
1040 if (!o || o -> type != omapi_type_protocol_listener)
98bf1607 1041 return DHCP_R_INVALIDARG;
61b844bf
TL
1042 p = (omapi_protocol_listener_object_t *)o;
1043
1044 /* Not a signal we recognize? */
1045 if (strcmp (name, "connect")) {
1046 if (p -> inner && p -> inner -> type -> signal_handler)
1047 return (*(p -> inner -> type -> signal_handler))
1048 (p -> inner, name, ap);
1049 return ISC_R_NOTFOUND;
1050 }
1051
1052 c = va_arg (ap, omapi_object_t *);
1053 if (!c || c -> type != omapi_type_connection)
98bf1607 1054 return DHCP_R_INVALIDARG;
61b844bf 1055
20916cae
TL
1056 obj = (omapi_protocol_object_t *)0;
1057 status = omapi_protocol_allocate (&obj, MDL);
1058 if (status != ISC_R_SUCCESS)
1059 return status;
61b844bf 1060
49146f3c
DN
1061 obj -> verify_auth = p -> verify_auth;
1062 obj -> insecure = p -> insecure;
1063
4bd8800e 1064 status = omapi_object_reference (&obj -> outer, c, MDL);
61b844bf
TL
1065 if (status != ISC_R_SUCCESS) {
1066 lose:
20916cae 1067 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
1068 omapi_disconnect (c, 1);
1069 return status;
1070 }
1071
4bd8800e
TL
1072 status = omapi_object_reference (&c -> inner,
1073 (omapi_object_t *)obj, MDL);
61b844bf
TL
1074 if (status != ISC_R_SUCCESS)
1075 goto lose;
1076
1077 /* Send the introductory message. */
1078 status = omapi_protocol_send_intro ((omapi_object_t *)obj,
1079 OMAPI_PROTOCOL_VERSION,
1080 sizeof (omapi_protocol_header_t));
1081 if (status != ISC_R_SUCCESS)
1082 goto lose;
1083
20916cae 1084 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
1085 return status;
1086}
1087
1088isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
1089 omapi_object_t *id,
1090 omapi_data_string_t *name,
1091 omapi_typed_data_t *value)
1092{
1093 if (h -> type != omapi_type_protocol_listener)
98bf1607 1094 return DHCP_R_INVALIDARG;
61b844bf
TL
1095
1096 if (h -> inner && h -> inner -> type -> set_value)
1097 return (*(h -> inner -> type -> set_value))
1098 (h -> inner, id, name, value);
1099 return ISC_R_NOTFOUND;
1100}
1101
1102isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
1103 omapi_object_t *id,
1104 omapi_data_string_t *name,
1105 omapi_value_t **value)
1106{
1107 if (h -> type != omapi_type_protocol_listener)
98bf1607 1108 return DHCP_R_INVALIDARG;
61b844bf
TL
1109
1110 if (h -> inner && h -> inner -> type -> get_value)
1111 return (*(h -> inner -> type -> get_value))
1112 (h -> inner, id, name, value);
1113 return ISC_R_NOTFOUND;
1114}
1115
b1b7b521 1116isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
4bd8800e 1117 const char *file, int line)
61b844bf
TL
1118{
1119 if (h -> type != omapi_type_protocol_listener)
98bf1607 1120 return DHCP_R_INVALIDARG;
61b844bf
TL
1121 return ISC_R_SUCCESS;
1122}
1123
1124/* Write all the published values associated with the object through the
1125 specified connection. */
1126
1127isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
1128 omapi_object_t *id,
1129 omapi_object_t *p)
1130{
61b844bf 1131 if (p -> type != omapi_type_protocol_listener)
98bf1607 1132 return DHCP_R_INVALIDARG;
61b844bf
TL
1133
1134 if (p -> inner && p -> inner -> type -> stuff_values)
1135 return (*(p -> inner -> type -> stuff_values)) (c, id,
1136 p -> inner);
1137 return ISC_R_SUCCESS;
1138}
1139
5a8e13c6
TL
1140isc_result_t omapi_protocol_send_status (omapi_object_t *po,
1141 omapi_object_t *id,
1142 isc_result_t waitstatus,
b1b7b521 1143 unsigned rid, const char *msg)
5a8e13c6
TL
1144{
1145 isc_result_t status;
20916cae
TL
1146 omapi_message_object_t *message = (omapi_message_object_t *)0;
1147 omapi_object_t *mo;
5a8e13c6
TL
1148
1149 if (po -> type != omapi_type_protocol)
98bf1607 1150 return DHCP_R_INVALIDARG;
5a8e13c6 1151
db4cfe3b 1152 status = omapi_message_new ((omapi_object_t **)&message, MDL);
5a8e13c6
TL
1153 if (status != ISC_R_SUCCESS)
1154 return status;
20916cae 1155 mo = (omapi_object_t *)message;
5a8e13c6 1156
20916cae 1157 status = omapi_set_int_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
1158 "op", OMAPI_OP_STATUS);
1159 if (status != ISC_R_SUCCESS) {
20916cae 1160 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1161 return status;
1162 }
1163
20916cae 1164 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 1165 "rid", (int)rid);
5a8e13c6 1166 if (status != ISC_R_SUCCESS) {
20916cae 1167 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1168 return status;
1169 }
1170
20916cae 1171 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 1172 "result", (int)waitstatus);
5a8e13c6 1173 if (status != ISC_R_SUCCESS) {
20916cae 1174 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1175 return status;
1176 }
1177
1178 /* If a message has been provided, send it. */
1179 if (msg) {
20916cae 1180 status = omapi_set_string_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
1181 "message", msg);
1182 if (status != ISC_R_SUCCESS) {
20916cae 1183 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1184 return status;
1185 }
1186 }
1187
20916cae
TL
1188 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1189 omapi_message_dereference (&message, MDL);
1190 return status;
5a8e13c6
TL
1191}
1192
49146f3c
DN
1193/* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1194 message to be set to the protocol object. This is used when opening
1195 the default authenticator. */
1196
1197isc_result_t omapi_protocol_send_open (omapi_object_t *po,
1198 omapi_object_t *id,
1199 const char *type,
1200 omapi_object_t *object,
1201 unsigned flags)
1202{
1203 isc_result_t status;
1204 omapi_message_object_t *message = (omapi_message_object_t *)0;
1205 omapi_object_t *mo;
1206
1207 if (po -> type != omapi_type_protocol)
98bf1607 1208 return DHCP_R_INVALIDARG;
49146f3c
DN
1209
1210 status = omapi_message_new ((omapi_object_t **)&message, MDL);
1211 mo = (omapi_object_t *)message;
1212
1213 if (status == ISC_R_SUCCESS)
1214 status = omapi_set_int_value (mo, (omapi_object_t *)0,
1215 "op", OMAPI_OP_OPEN);
1216
1217 if (status == ISC_R_SUCCESS)
1218 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1219 "object", object);
1220
1221 if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
1222 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1223 "create", 1);
1224
1225 if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
1226 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1227 "update", 1);
1228
1229 if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
1230 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1231 "exclusive", 1);
1232
1233 if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
1234 status = omapi_set_object_value (mo, (omapi_object_t *)0,
1235 "notify-object", po);
1236
1237 if (type && (status == ISC_R_SUCCESS))
1238 status = omapi_set_string_value (mo, (omapi_object_t *)0,
1239 "type", type);
1240
1241 if (status == ISC_R_SUCCESS)
1242 status = omapi_message_register (mo);
1243
1244 if (status == ISC_R_SUCCESS) {
1245 status = omapi_protocol_send_message (po, id, mo,
1246 (omapi_object_t *)0);
1247 if (status != ISC_R_SUCCESS)
1248 omapi_message_unregister (mo);
1249 }
1250
1251 if (message)
1252 omapi_message_dereference (&message, MDL);
1253
1254 return status;
1255}
1256
5a8e13c6
TL
1257isc_result_t omapi_protocol_send_update (omapi_object_t *po,
1258 omapi_object_t *id,
b1b7b521 1259 unsigned rid,
5a8e13c6
TL
1260 omapi_object_t *object)
1261{
1262 isc_result_t status;
20916cae
TL
1263 omapi_message_object_t *message = (omapi_message_object_t *)0;
1264 omapi_object_t *mo;
5a8e13c6
TL
1265
1266 if (po -> type != omapi_type_protocol)
98bf1607 1267 return DHCP_R_INVALIDARG;
5a8e13c6 1268
db4cfe3b 1269 status = omapi_message_new ((omapi_object_t **)&message, MDL);
5a8e13c6
TL
1270 if (status != ISC_R_SUCCESS)
1271 return status;
20916cae 1272 mo = (omapi_object_t *)message;
5a8e13c6 1273
20916cae 1274 status = omapi_set_int_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
1275 "op", OMAPI_OP_UPDATE);
1276 if (status != ISC_R_SUCCESS) {
20916cae 1277 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1278 return status;
1279 }
1280
1281 if (rid) {
e5bbe4da 1282 omapi_handle_t handle;
20916cae 1283 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 1284 "rid", (int)rid);
5a8e13c6 1285 if (status != ISC_R_SUCCESS) {
20916cae 1286 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1287 return status;
1288 }
e5bbe4da 1289
5a8e13c6
TL
1290 status = omapi_object_handle (&handle, object);
1291 if (status != ISC_R_SUCCESS) {
20916cae 1292 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1293 return status;
1294 }
20916cae 1295 status = omapi_set_int_value (mo, (omapi_object_t *)0,
b1b7b521 1296 "handle", (int)handle);
5a8e13c6 1297 if (status != ISC_R_SUCCESS) {
20916cae 1298 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1299 return status;
1300 }
1301 }
1302
20916cae 1303 status = omapi_set_object_value (mo, (omapi_object_t *)0,
5a8e13c6
TL
1304 "object", object);
1305 if (status != ISC_R_SUCCESS) {
20916cae 1306 omapi_message_dereference (&message, MDL);
5a8e13c6
TL
1307 return status;
1308 }
1309
20916cae
TL
1310 status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1311 omapi_message_dereference (&message, MDL);
1312 return status;
5a8e13c6 1313}