]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/protocol.c
[#148] Replaced hard-coded MD5 algorithm name in OMAPI connection
[thirdparty/dhcp.git] / omapip / protocol.c
CommitLineData
61b844bf
TL
1/* protocol.c
2
3 Functions supporting the object management protocol... */
4
5/*
7512d88b 6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1999-2003 by Internet Software Consortium
61b844bf 8 *
7512d88b
TM
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
61b844bf 12 *
98311e4b
DH
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.
61b844bf 20 *
98311e4b 21 * Internet Systems Consortium, Inc.
429a56d7
TM
22 * PO Box 360
23 * Newmarket, NH 03857 USA
98311e4b 24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
49733f31 26 *
61b844bf
TL
27 */
28
fe5b0fdd
DH
29#include "dhcpd.h"
30
6a4c4be8 31#include <omapip/omapip_p.h>
61b844bf 32
20916cae
TL
33OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
34 omapi_type_protocol)
35OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
36 omapi_type_protocol_listener)
37
61b844bf 38isc_result_t omapi_protocol_connect (omapi_object_t *h,
b1b7b521 39 const char *server_name,
d9eefc5d 40 unsigned port,
49146f3c 41 omapi_object_t *a)
61b844bf 42{
a3239005 43 isc_result_t rstatus, status;
61b844bf
TL
44 omapi_protocol_object_t *obj;
45
e11a162f
DN
46#ifdef DEBUG_PROTOCOL
47 log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
48#endif
49
20916cae
TL
50 obj = (omapi_protocol_object_t *)0;
51 status = omapi_protocol_allocate (&obj, MDL);
52 if (status != ISC_R_SUCCESS)
53 return status;
61b844bf 54
a3239005 55 rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
98bf1607 56 if (rstatus != ISC_R_SUCCESS && rstatus != DHCP_R_INCOMPLETE) {
20916cae 57 omapi_protocol_dereference (&obj, MDL);
a3239005 58 return rstatus;
61b844bf 59 }
4bd8800e
TL
60 status = omapi_object_reference (&h -> outer,
61 (omapi_object_t *)obj, MDL);
61b844bf 62 if (status != ISC_R_SUCCESS) {
20916cae 63 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
64 return status;
65 }
4bd8800e 66 status = omapi_object_reference (&obj -> inner, h, MDL);
61b844bf 67 if (status != ISC_R_SUCCESS) {
20916cae 68 omapi_protocol_dereference (&obj, MDL);
61b844bf
TL
69 return status;
70 }
71
49146f3c
DN
72 /* If we were passed a default authenticator, store it now. We'll
73 open it once we're connected. */
74 if (a) {
75 obj -> default_auth =
76 dmalloc (sizeof(omapi_remote_auth_t), MDL);
77 if (!obj -> default_auth) {
78 omapi_protocol_dereference (&obj, MDL);
79 return ISC_R_NOMEMORY;
80 }
81
82 obj -> default_auth -> next = (omapi_remote_auth_t *)0;
83 status = omapi_object_reference (&obj -> default_auth -> a,
84 a, MDL);
85 if (status != ISC_R_SUCCESS) {
86 dfree (obj -> default_auth, MDL);
87 omapi_protocol_dereference (&obj, MDL);
88 return status;
89 }
90
91 obj -> insecure = 0;
98bf1607 92 rstatus = DHCP_R_INCOMPLETE;
49146f3c
DN
93 } else {
94 obj -> insecure = 1;
a3239005 95#if 0
366556ef 96 status = ISC_R_SUCCESS;
a3239005 97#endif
49146f3c
DN
98 }
99
20916cae 100 omapi_protocol_dereference (&obj, MDL);
a3239005 101 return rstatus;
61b844bf
TL
102}
103
104/* Send the protocol introduction message. */
105isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
b1b7b521
TL
106 unsigned ver,
107 unsigned hsize)
61b844bf
TL
108{
109 isc_result_t status;
110 omapi_protocol_object_t *p;
111
e11a162f
DN
112#ifdef DEBUG_PROTOCOL
113 log_debug ("omapi_protocol_send_intro()");
114#endif
115
61b844bf 116 if (h -> type != omapi_type_protocol)
98bf1607 117 return DHCP_R_INVALIDARG;
61b844bf
TL
118 p = (omapi_protocol_object_t *)h;
119
120 if (!h -> outer || h -> outer -> type != omapi_type_connection)
121 return ISC_R_NOTCONNECTED;
122
123 status = omapi_connection_put_uint32 (h -> outer, ver);
124 if (status != ISC_R_SUCCESS)
125 return status;
126
127 status = omapi_connection_put_uint32 (h -> outer, hsize);
128
129 if (status != ISC_R_SUCCESS)
130 return status;
131
132 /* Require the other end to send an intro - this kicks off the
133 protocol input state machine. */
134 p -> state = omapi_protocol_intro_wait;
135 status = omapi_connection_require (h -> outer, 8);
98bf1607 136 if (status != ISC_R_SUCCESS && status != DHCP_R_NOTYET)
61b844bf
TL
137 return status;
138
139 /* Make up an initial transaction ID for this connection. */
140 p -> next_xid = random ();
141 return ISC_R_SUCCESS;
142}
143
74dc3e0b
EH
144#ifdef DEBUG_PROTOCOL
145extern const char *omapi_message_op_name(int);
146#endif /* DEBUG_PROTOCOL */
147
61b844bf
TL
148isc_result_t omapi_protocol_send_message (omapi_object_t *po,
149 omapi_object_t *id,
150 omapi_object_t *mo,
151 omapi_object_t *omo)
152{
153 omapi_protocol_object_t *p;
154 omapi_object_t *c;
20916cae 155 omapi_message_object_t *m, *om;
49146f3c
DN
156 omapi_remote_auth_t *ra;
157 omapi_value_t *signature;
61b844bf 158 isc_result_t status;
49146f3c 159 unsigned auth_len;
61b844bf
TL
160
161 if (po -> type != omapi_type_protocol ||
162 !po -> outer || po -> outer -> type != omapi_type_connection ||
165bce70 163 mo -> type != omapi_type_message)
98bf1607 164 return DHCP_R_INVALIDARG;
165bce70 165 if (omo && omo -> type != omapi_type_message)
98bf1607 166 return DHCP_R_INVALIDARG;
61b844bf
TL
167 p = (omapi_protocol_object_t *)po;
168 c = (omapi_object_t *)(po -> outer);
169 m = (omapi_message_object_t *)mo;
170 om = (omapi_message_object_t *)omo;
171
e11a162f 172#ifdef DEBUG_PROTOCOL
74dc3e0b
EH
173 log_debug ("omapi_protocol_send_message(): "
174 "op=%s handle=%#lx id=%#lx rid=%#lx",
175 omapi_message_op_name (m->op),
e11a162f
DN
176 (long)(m -> object ? m -> object -> handle : m -> handle),
177 (long)p -> next_xid, (long)m -> rid);
178#endif
179
49146f3c
DN
180 /* Find the authid to use for this message. */
181 if (id) {
182 for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
183 if (ra -> a == id) {
184 break;
185 }
186 }
187
188 if (!ra)
98bf1607 189 return DHCP_R_KEY_UNKNOWN;
49146f3c
DN
190 } else if (p -> remote_auth_list) {
191 ra = p -> default_auth;
192 } else {
193 ra = (omapi_remote_auth_t *)0;
194 }
195
196 if (ra) {
197 m -> authid = ra -> remote_handle;
198 status = omapi_object_reference (&m -> id_object,
199 ra -> a, MDL);
200 if (status != ISC_R_SUCCESS)
201 return status;
202 }
203
204 /* Write the ID of the authentication key we're using. */
205 status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
206 if (status != ISC_R_SUCCESS) {
207 omapi_disconnect (c, 1);
61b844bf 208 return status;
49146f3c
DN
209 }
210
211 /* Activate the authentication key on the connection. */
212 auth_len = 0;
213 if (ra) {
214 status = omapi_set_object_value (c, (omapi_object_t *)0,
215 "output-authenticator",
216 ra -> a);
217 if (status != ISC_R_SUCCESS) {
218 omapi_disconnect (c, 1);
219 return status;
220 }
221
222 status = omapi_connection_output_auth_length (c, &auth_len);
223 if (status != ISC_R_SUCCESS) {
224 omapi_disconnect (c, 1);
225 return status;
226 }
227 }
228
229 /* Write the authenticator length */
230 status = omapi_connection_put_uint32 (c, auth_len);
61b844bf
TL
231 if (status != ISC_R_SUCCESS) {
232 omapi_disconnect (c, 1);
233 return status;
234 }
235
236 /* Write the opcode. */
237 status = omapi_connection_put_uint32 (c, m -> op);
238 if (status != ISC_R_SUCCESS) {
239 omapi_disconnect (c, 1);
240 return status;
241 }
242
243 /* Write the handle. If we've been given an explicit handle, use
244 that. Otherwise, use the handle of the object we're sending.
245 The caller is responsible for arranging for one of these handles
246 to be set (or not). */
247 status = omapi_connection_put_uint32 (c, (m -> h
248 ? m -> h
5a8e13c6
TL
249 : (m -> object
250 ? m -> object -> handle
251 : 0)));
61b844bf
TL
252 if (status != ISC_R_SUCCESS) {
253 omapi_disconnect (c, 1);
254 return status;
255 }
256
257 /* Set and write the transaction ID. */
258 m -> id = p -> next_xid++;
259 status = omapi_connection_put_uint32 (c, m -> id);
260 if (status != ISC_R_SUCCESS) {
261 omapi_disconnect (c, 1);
262 return status;
263 }
264
265 /* Write the transaction ID of the message to which this is a
266 response, if there is such a message. */
5a8e13c6 267 status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
61b844bf
TL
268 if (status != ISC_R_SUCCESS) {
269 omapi_disconnect (c, 1);
270 return status;
271 }
272
581e37e4 273 /* Stuff out the name/value pairs specific to this message. */
5a8e13c6
TL
274 status = omapi_stuff_values (c, id, (omapi_object_t *)m);
275 if (status != ISC_R_SUCCESS) {
276 omapi_disconnect (c, 1);
277 return status;
581e37e4
TL
278 }
279
280 /* Write the zero-length name that terminates the list of name/value
281 pairs specific to the message. */
282 status = omapi_connection_put_uint16 (c, 0);
61b844bf
TL
283 if (status != ISC_R_SUCCESS) {
284 omapi_disconnect (c, 1);
285 return status;
286 }
287
581e37e4
TL
288 /* Stuff out all the published name/value pairs in the object that's
289 being sent in the message, if there is one. */
290 if (m -> object) {
291 status = omapi_stuff_values (c, id, m -> object);
292 if (status != ISC_R_SUCCESS) {
293 omapi_disconnect (c, 1);
294 return status;
295 }
296 }
297
61b844bf 298 /* Write the zero-length name that terminates the list of name/value
581e37e4 299 pairs for the associated object. */
61b844bf
TL
300 status = omapi_connection_put_uint16 (c, 0);
301 if (status != ISC_R_SUCCESS) {
302 omapi_disconnect (c, 1);
303 return status;
304 }
305
49146f3c
DN
306 if (ra) {
307 /* Calculate the message signature. */
308 signature = (omapi_value_t *)0;
309 status = omapi_get_value_str (c, (omapi_object_t *)0,
310 "output-signature", &signature);
311 if (status != ISC_R_SUCCESS) {
312 omapi_disconnect (c, 1);
313 return status;
314 }
315
316 /* Write the authenticator... */
317 status = (omapi_connection_copyin
318 (c, signature -> value -> u.buffer.value,
319 signature -> value -> u.buffer.len));
320 omapi_value_dereference (&signature, MDL);
321 if (status != ISC_R_SUCCESS) {
322 omapi_disconnect (c, 1);
323 return status;
324 }
325
326 /* Dectivate the authentication key on the connection. */
327 status = omapi_set_value_str (c, (omapi_object_t *)0,
328 "output-authenticator",
329 (omapi_typed_data_t *)0);
330 if (status != ISC_R_SUCCESS) {
331 omapi_disconnect (c, 1);
332 return status;
333 }
334 }
61b844bf 335
d758ad8c
TL
336 if (!omo) {
337 omapi_protocol_reference (&m -> protocol_object, p, MDL);
338 }
61b844bf
TL
339 return ISC_R_SUCCESS;
340}
f6b8f48d 341
61b844bf
TL
342
343isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
b1b7b521 344 const char *name, va_list ap)
61b844bf
TL
345{
346 isc_result_t status;
347 omapi_protocol_object_t *p;
348 omapi_object_t *c;
d758ad8c 349 omapi_message_object_t *m;
0f750c4f 350 omapi_value_t *signature = NULL;
61b844bf
TL
351 u_int16_t nlen;
352 u_int32_t vlen;
bbdb72a4 353 u_int32_t th;
31bbee78 354#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b
DH
355 unsigned long previous_outstanding = 0xDEADBEEF;
356 unsigned long connect_outstanding = 0xDEADBEEF;
31bbee78 357#endif
61b844bf
TL
358
359 if (h -> type != omapi_type_protocol) {
360 /* XXX shouldn't happen. Put an assert here? */
361 return ISC_R_UNEXPECTED;
362 }
363 p = (omapi_protocol_object_t *)h;
364
ffc05866 365 if (!strcmp (name, "connect")) {
31bbee78
TL
366#if defined (DEBUG_MEMORY_LEAKAGE)
367 connect_outstanding = dmalloc_outstanding;
368#endif
ffc05866
TL
369 /* Send the introductory message. */
370 status = omapi_protocol_send_intro
7deff076 371 (h, OMAPI_PROTOCOL_VERSION,
ffc05866
TL
372 sizeof (omapi_protocol_header_t));
373 if (status != ISC_R_SUCCESS) {
374 omapi_disconnect (p -> outer, 1);
375 return status;
376 }
377 return ISC_R_SUCCESS;
378 }
379
49146f3c
DN
380 /* Should only receive these when opening the initial authenticator. */
381 if (!strcmp (name, "status")) {
382 status = va_arg (ap, isc_result_t);
383 if (status != ISC_R_SUCCESS) {
384 omapi_signal_in (h -> inner, "status", status,
385 (omapi_object_t *)0);
386 omapi_disconnect (p -> outer, 1);
387 return status;
388 } else {
389 return omapi_signal_in (h -> inner, "ready");
390 }
391 }
392
31bbee78 393 /* If we get a disconnect, dump memory usage. */
a609e69b 394 if (!strcmp (name, "disconnect")) {
31bbee78 395#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b 396 if (connect_outstanding != 0xDEADBEEF) {
31bbee78
TL
397 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
398 dmalloc_generation,
399 dmalloc_outstanding - previous_outstanding,
400 dmalloc_outstanding, dmalloc_longterm, " long-term");
a609e69b 401 }
31bbee78 402#endif
d758ad8c 403#if defined (DEBUG_MEMORY_LEAKAGE)
a609e69b 404 dmalloc_dump_outstanding ();
31bbee78
TL
405#endif
406#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4619c0a2 407 dump_rc_history (h);
31bbee78 408#endif
a609e69b
TL
409 for (m = omapi_registered_messages; m; m = m -> next) {
410 if (m -> protocol_object == p) {
411 if (m -> object)
412 omapi_signal (m -> object, "disconnect");
413 }
414 }
4619c0a2
DH
415
416 /* XXX */
417 return ISC_R_SUCCESS;
31bbee78
TL
418 }
419
61b844bf
TL
420 /* Not a signal we recognize? */
421 if (strcmp (name, "ready")) {
422 if (p -> inner && p -> inner -> type -> signal_handler)
423 return (*(p -> inner -> type -> signal_handler)) (h,
424 name,
425 ap);
426 return ISC_R_NOTFOUND;
427 }
428
429 if (!p -> outer || p -> outer -> type != omapi_type_connection)
98bf1607 430 return DHCP_R_INVALIDARG;
61b844bf
TL
431 c = p -> outer;
432
433 /* We get here because we requested that we be woken up after
434 some number of bytes were read, and that number of bytes
435 has in fact been read. */
436 switch (p -> state) {
437 case omapi_protocol_intro_wait:
438 /* Get protocol version and header size in network
439 byte order. */
d9eefc5d
TL
440 omapi_connection_get_uint32 (c, &p -> protocol_version);
441 omapi_connection_get_uint32 (c, &p -> header_size);
f6b8f48d 442
61b844bf
TL
443 /* We currently only support the current protocol version. */
444 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
445 omapi_disconnect (c, 1);
98bf1607 446 return DHCP_R_VERSIONMISMATCH;
61b844bf
TL
447 }
448
449 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
450 omapi_disconnect (c, 1);
98bf1607 451 return DHCP_R_PROTOCOLERROR;
61b844bf
TL
452 }
453
49146f3c
DN
454 if (p -> default_auth) {
455 status = omapi_protocol_send_open
456 (h, (omapi_object_t *)0, "authenticator",
457 p -> default_auth -> a,
458 OMAPI_NOTIFY_PROTOCOL);
459 if (status != ISC_R_SUCCESS) {
460 omapi_disconnect (c, 1);
461 return status;
462 }
463 } else {
464 status = omapi_signal_in (h -> inner, "ready");
465 }
61b844bf
TL
466
467 to_header_wait:
468 /* The next thing we're expecting is a message header. */
469 p -> state = omapi_protocol_header_wait;
470
471 /* Register a need for the number of bytes in a
472 header, and if we already have that many, process
473 them immediately. */
d9eefc5d
TL
474 if ((omapi_connection_require (c, p -> header_size)) !=
475 ISC_R_SUCCESS)
61b844bf
TL
476 break;
477 /* If we already have the data, fall through. */
478
479 case omapi_protocol_header_wait:
31bbee78 480#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b 481 if (previous_outstanding != 0xDEADBEEF) {
31bbee78
TL
482 log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
483 "generation", dmalloc_generation,
484 dmalloc_outstanding - previous_outstanding,
485 dmalloc_outstanding, dmalloc_longterm,
486 " long-term");
487#endif
488#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
489 dmalloc_dump_outstanding ();
490#endif
491#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4619c0a2 492 dump_rc_history (h);
31bbee78
TL
493#endif
494#if defined (DEBUG_MEMORY_LEAKAGE)
495 }
496 previous_outstanding = dmalloc_outstanding;
497#endif
db4cfe3b
DN
498 status = omapi_message_new ((omapi_object_t **)&p -> message,
499 MDL);
61b844bf
TL
500 if (status != ISC_R_SUCCESS) {
501 omapi_disconnect (c, 1);
502 return status;
503 }
504
49146f3c
DN
505 p -> verify_result = ISC_R_SUCCESS;
506
61b844bf 507 /* Swap in the header... */
d9eefc5d 508 omapi_connection_get_uint32 (c, &p -> message -> authid);
61b844bf 509
49146f3c
DN
510 /* Bind the authenticator to the message object. */
511 if (p -> message -> authid) {
512 status = (omapi_protocol_lookup_auth
513 (&p -> message -> id_object, h,
514 p -> message -> authid));
515 if (status != ISC_R_SUCCESS)
516 p -> verify_result = status;
517
518 /* Activate the authentication key. */
519 status = omapi_set_object_value
520 (c, (omapi_object_t *)0, "input-authenticator",
521 p -> message -> id_object);
522 if (status != ISC_R_SUCCESS) {
523 omapi_disconnect (c, 1);
524 return status;
525 }
526 }
527
d9eefc5d
TL
528 omapi_connection_get_uint32 (c, &p -> message -> authlen);
529 omapi_connection_get_uint32 (c, &p -> message -> op);
bbdb72a4 530 omapi_connection_get_uint32 (c, &th);
3185c188 531 p -> message -> h = th;
d9eefc5d
TL
532 omapi_connection_get_uint32 (c, &p -> message -> id);
533 omapi_connection_get_uint32 (c, &p -> message -> rid);
61b844bf
TL
534
535 /* If there was any extra header data, skip over it. */
536 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
537 omapi_connection_copyout
538 (0, c, (p -> header_size -
539 sizeof (omapi_protocol_header_t)));
540 }
f6b8f48d 541
61b844bf
TL
542 /* XXX must compute partial signature across the
543 XXX preceding bytes. Also, if authenticator
544 specifies encryption as well as signing, we may
545 have to decrypt the data on the way in. */
546
581e37e4
TL
547 /* First we read in message-specific values, then object
548 values. */
549 p -> reading_message_values = 1;
550
61b844bf
TL
551 need_name_length:
552 /* The next thing we're expecting is length of the
553 first name. */
554 p -> state = omapi_protocol_name_length_wait;
555
556 /* Wait for a 16-bit length. */
557 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
558 break;
559 /* If it's already here, fall through. */
560
561 case omapi_protocol_name_length_wait:
562 omapi_connection_get_uint16 (c, &nlen);
563 /* A zero-length name means that we're done reading name+value
564 pairs. */
565 if (nlen == 0) {
581e37e4
TL
566 /* If we've already read in the object, we are
567 done reading the message, but if we've just
568 finished reading in the values associated
569 with the message, we need to read the
570 object. */
571 if (p -> reading_message_values) {
572 p -> reading_message_values = 0;
573 goto need_name_length;
574 }
575
61b844bf
TL
576 /* If the authenticator length is zero, there's no
577 signature to read in, so go straight to processing
578 the message. */
579 if (p -> message -> authlen == 0)
580 goto message_done;
581
582 /* The next thing we're expecting is the
583 message signature. */
584 p -> state = omapi_protocol_signature_wait;
585
586 /* Wait for the number of bytes specified for
587 the authenticator. If we already have it,
588 go read it in. */
589 if (omapi_connection_require
590 (c, p -> message -> authlen) == ISC_R_SUCCESS)
591 goto signature_wait;
592 break;
593 }
594
595 /* Allocate a buffer for the name. */
4bd8800e 596 status = (omapi_data_string_new (&p -> name, nlen, MDL));
61b844bf
TL
597 if (status != ISC_R_SUCCESS) {
598 omapi_disconnect (c, 1);
599 return ISC_R_NOMEMORY;
600 }
581e37e4 601 p -> state = omapi_protocol_name_wait;
61b844bf
TL
602 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
603 break;
604 /* If it's already here, fall through. */
f6b8f48d 605
61b844bf
TL
606 case omapi_protocol_name_wait:
607 omapi_connection_copyout (p -> name -> value, c,
608 p -> name -> len);
609 /* Wait for a 32-bit length. */
581e37e4 610 p -> state = omapi_protocol_value_length_wait;
61b844bf
TL
611 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
612 break;
613 /* If it's already here, fall through. */
614
615 case omapi_protocol_value_length_wait:
616 omapi_connection_get_uint32 (c, &vlen);
617
618 /* Zero-length values are allowed - if we get one, we
619 don't have to read any data for the value - just
620 get the next one, if there is a next one. */
621 if (!vlen)
622 goto insert_new_value;
623
4bd8800e
TL
624 status = omapi_typed_data_new (MDL, &p -> value,
625 omapi_datatype_data,
626 vlen);
61b844bf
TL
627 if (status != ISC_R_SUCCESS) {
628 omapi_disconnect (c, 1);
629 return ISC_R_NOMEMORY;
630 }
631
581e37e4 632 p -> state = omapi_protocol_value_wait;
61b844bf
TL
633 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
634 break;
635 /* If it's already here, fall through. */
f6b8f48d 636
61b844bf
TL
637 case omapi_protocol_value_wait:
638 omapi_connection_copyout (p -> value -> u.buffer.value, c,
639 p -> value -> u.buffer.len);
640
641 insert_new_value:
581e37e4
TL
642 if (p -> reading_message_values) {
643 status = (omapi_set_value
644 ((omapi_object_t *)p -> message,
645 p -> message -> id_object,
646 p -> name, p -> value));
647 } else {
648 if (!p -> message -> object) {
649 /* We need a generic object to hang off of the
650 incoming message. */
651 status = (omapi_generic_new
4bd8800e 652 (&p -> message -> object, MDL));
581e37e4
TL
653 if (status != ISC_R_SUCCESS) {
654 omapi_disconnect (c, 1);
655 return status;
656 }
657 }
658 status = (omapi_set_value
659 ((omapi_object_t *)p -> message -> object,
660 p -> message -> id_object,
661 p -> name, p -> value));
662 }
61b844bf
TL
663 if (status != ISC_R_SUCCESS) {
664 omapi_disconnect (c, 1);
665 return status;
666 }
4bd8800e 667 omapi_data_string_dereference (&p -> name, MDL);
d758ad8c
TL
668 if (p -> value)
669 omapi_typed_data_dereference (&p -> value, MDL);
61b844bf
TL
670 goto need_name_length;
671
672 signature_wait:
673 case omapi_protocol_signature_wait:
49146f3c
DN
674 if (p -> message -> id_object) {
675 /* Compute the signature of the message. */
49146f3c
DN
676 status = omapi_get_value_str (c, (omapi_object_t *)0,
677 "input-signature",
678 &signature);
679 if (status != ISC_R_SUCCESS) {
680 omapi_disconnect (c, 1);
681 return status;
682 }
683
684 /* Disable the authentication key on the connection. */
685 status = omapi_set_value_str (c, (omapi_object_t *)0,
686 "input-authenticator",
687 (omapi_typed_data_t *)0);
688 if (status != ISC_R_SUCCESS) {
689 omapi_value_dereference (&signature, MDL);
690 omapi_disconnect (c, 1);
691 return status;
692 }
693 }
694
695 /* Read the authenticator. */
4bd8800e
TL
696 status = omapi_typed_data_new (MDL,
697 &p -> message -> authenticator,
61b844bf
TL
698 omapi_datatype_data,
699 p -> message -> authlen);
f6b8f48d 700
61b844bf 701 if (status != ISC_R_SUCCESS) {
0f750c4f
SR
702 if (signature != NULL) {
703 omapi_value_dereference (&signature, MDL);
704 }
61b844bf
TL
705 omapi_disconnect (c, 1);
706 return ISC_R_NOMEMORY;
707 }
708 omapi_connection_copyout
709 (p -> message -> authenticator -> u.buffer.value, c,
710 p -> message -> authlen);
49146f3c
DN
711
712 /* Verify the signature. */
713 if (p -> message -> id_object &&
714 ((signature -> value -> u.buffer.len !=
715 p -> message -> authlen) ||
716 (memcmp (signature -> value -> u.buffer.value,
717 p -> message -> authenticator -> u.buffer.value,
718 p -> message -> authlen) != 0))) {
719 /* Invalid signature. */
98bf1607 720 p->verify_result = DHCP_R_INVALIDKEY;
49146f3c
DN
721 }
722
0f750c4f
SR
723 if (signature != NULL) {
724 omapi_value_dereference (&signature, MDL);
725 }
61b844bf 726
581e37e4 727 /* Process the message. */
61b844bf 728 message_done:
49146f3c
DN
729 if (p -> verify_result != ISC_R_SUCCESS) {
730 status = omapi_protocol_send_status
731 (h, (omapi_object_t *)0, p -> verify_result,
732 p -> message -> id, (char *)0);
733 } else {
734 status = omapi_message_process
735 ((omapi_object_t *)p -> message, h);
736 }
581e37e4
TL
737 if (status != ISC_R_SUCCESS) {
738 omapi_disconnect (c, 1);
739 return ISC_R_NOMEMORY;
740 }
741
20916cae 742 omapi_message_dereference (&p -> message, MDL);
31bbee78
TL
743#if defined (DEBUG_MEMORY_LEAKAGE)
744 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
745 dmalloc_generation,
746 dmalloc_outstanding - previous_outstanding,
747 dmalloc_outstanding, dmalloc_longterm, " long-term");
748#endif
749#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
750 dmalloc_dump_outstanding ();
751#endif
752#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4619c0a2 753 dump_rc_history (h);
31bbee78
TL
754#endif
755#if defined (DEBUG_MEMORY_LEAKAGE)
98311e4b 756 previous_outstanding = 0xDEADBEEF;
31bbee78 757#endif
61b844bf 758 /* Now wait for the next message. */
f6b8f48d 759 goto to_header_wait;
61b844bf
TL
760
761 default:
762 /* XXX should never get here. Assertion? */
8a6dfe4c 763 break;
61b844bf
TL
764 }
765 return ISC_R_SUCCESS;
766}
767
49146f3c
DN
768isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
769 omapi_object_t *ao,
770 omapi_handle_t handle)
771{
772 omapi_protocol_object_t *p;
773 omapi_remote_auth_t *r;
774 isc_result_t status;
775
776 if (ao -> type != omapi_type_auth_key &&
777 (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
98bf1607 778 return DHCP_R_INVALIDARG;
49146f3c
DN
779
780 if (po -> type != omapi_type_protocol)
98bf1607 781 return DHCP_R_INVALIDARG;
49146f3c
DN
782 p = (omapi_protocol_object_t *)po;
783
e11a162f
DN
784#ifdef DEBUG_PROTOCOL
785 log_debug ("omapi_protocol_add_auth(name=%s)",
786 ((omapi_auth_key_t *)ao) -> name);
787#endif
788
49146f3c
DN
789 if (p -> verify_auth) {
790 status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
791 if (status != ISC_R_SUCCESS)
792 return status;
793 }
794
795 /* If omapi_protocol_connect() was called with a default
796 authenticator, p -> default_auth will already be set,
797 but p -> remote_auth_list will not yet be initialized. */
798 if (p -> default_auth && !p -> remote_auth_list) {
799 if (p -> default_auth -> a != ao) {
800 /* Something just went horribly wrong. */
801 omapi_disconnect (p -> outer, 1);
802 return ISC_R_UNEXPECTED;
803 }
804
805 p -> remote_auth_list = p -> default_auth;
806 p -> default_auth -> remote_handle = handle;
807
808 return omapi_signal_in (p -> inner, "ready");
809 }
810
811 r = dmalloc (sizeof(*r), MDL);
812 if (!r)
813 return ISC_R_NOMEMORY;
814
815 status = omapi_object_reference (&r -> a, ao, MDL);
816 if (status != ISC_R_SUCCESS) {
817 dfree (r, MDL);
818 return status;
819 }
820
821 r -> remote_handle = handle;
822 r -> next = p -> remote_auth_list;
823 p -> remote_auth_list = r;
824
825 return ISC_R_SUCCESS;
826}
827
828isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
829 omapi_object_t *po,
830 omapi_handle_t handle)
831{
832 omapi_protocol_object_t *p;
833 omapi_remote_auth_t *r;
834
835 if (po -> type != omapi_type_protocol)
98bf1607 836 return DHCP_R_INVALIDARG;
49146f3c
DN
837 p = (omapi_protocol_object_t *)po;
838
839 for (r = p -> remote_auth_list; r; r = r -> next)
840 if (r -> remote_handle == handle)
841 return omapi_object_reference (a, r -> a, MDL);
842
98bf1607 843 return DHCP_R_KEY_UNKNOWN;
49146f3c
DN
844}
845
61b844bf
TL
846isc_result_t omapi_protocol_set_value (omapi_object_t *h,
847 omapi_object_t *id,
848 omapi_data_string_t *name,
849 omapi_typed_data_t *value)
850{
49146f3c
DN
851 omapi_protocol_object_t *p;
852 omapi_remote_auth_t *r;
853
61b844bf 854 if (h -> type != omapi_type_protocol)
98bf1607 855 return DHCP_R_INVALIDARG;
49146f3c
DN
856 p = (omapi_protocol_object_t *)h;
857
858 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
0f750c4f 859 if (!value || value -> type != omapi_datatype_object)
98bf1607 860 return DHCP_R_INVALIDARG;
49146f3c 861
0f750c4f 862 if (!value -> u.object) {
49146f3c
DN
863 p -> default_auth = (omapi_remote_auth_t *)0;
864 } else {
865 for (r = p -> remote_auth_list; r; r = r -> next)
866 if (r -> a == value -> u.object)
867 break;
868
869 if (!r)
98bf1607 870 return DHCP_R_KEY_UNKNOWN;
49146f3c
DN
871
872 p -> default_auth = r;
873 }
874
875 return ISC_R_SUCCESS;
876 }
61b844bf
TL
877
878 if (h -> inner && h -> inner -> type -> set_value)
879 return (*(h -> inner -> type -> set_value))
880 (h -> inner, id, name, value);
881 return ISC_R_NOTFOUND;
882}
883
884isc_result_t omapi_protocol_get_value (omapi_object_t *h,
885 omapi_object_t *id,
886 omapi_data_string_t *name,
887 omapi_value_t **value)
888{
49146f3c
DN
889 omapi_protocol_object_t *p;
890
61b844bf 891 if (h -> type != omapi_type_protocol)
98bf1607 892 return DHCP_R_INVALIDARG;
49146f3c
DN
893 p = (omapi_protocol_object_t *)h;
894
895 if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
896 if (!p -> default_auth)
897 return ISC_R_NOTFOUND;
898
899 return omapi_make_object_value (value, name,
900 p -> default_auth -> a, MDL);
901 }
f6b8f48d 902
61b844bf
TL
903 if (h -> inner && h -> inner -> type -> get_value)
904 return (*(h -> inner -> type -> get_value))
905 (h -> inner, id, name, value);
906 return ISC_R_NOTFOUND;
907}
908
4bd8800e
TL
909isc_result_t omapi_protocol_destroy (omapi_object_t *h,
910 const char *file, int line)
61b844bf
TL
911{
912 omapi_protocol_object_t *p;
913 if (h -> type != omapi_type_protocol)
98bf1607 914 return DHCP_R_INVALIDARG;
61b844bf
TL
915 p = (omapi_protocol_object_t *)h;
916 if (p -> message)
20916cae 917 omapi_message_dereference (&p -> message, file, line);
49146f3c
DN
918
919 /* This will happen if: 1) A default authenticator is supplied to
920 omapi_protocol_connect(), and 2) something goes wrong before
921 the authenticator can be opened. */
922 if (p -> default_auth && !p -> remote_auth_list)
923 dfree (p -> default_auth, file, line);
924
925 while (p -> remote_auth_list) {
bb9189c3
SR
926 omapi_remote_auth_t *r = p -> remote_auth_list;
927 p -> remote_auth_list = p -> remote_auth_list -> next;
928 omapi_object_dereference (&r -> a, file, line);
929 dfree (r, file, line);
49146f3c 930 }
61b844bf
TL
931 return ISC_R_SUCCESS;
932}
933
934/* Write all the published values associated with the object through the
935 specified connection. */
936
937isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
938 omapi_object_t *id,
939 omapi_object_t *p)
940{
61b844bf 941 if (p -> type != omapi_type_protocol)
98bf1607 942 return DHCP_R_INVALIDARG;
61b844bf
TL
943
944 if (p -> inner && p -> inner -> type -> stuff_values)
945 return (*(p -> inner -> type -> stuff_values)) (c, id,
946 p -> inner);
947 return ISC_R_SUCCESS;
948}
949
49146f3c
DN
950/* Returns a boolean indicating whether this protocol requires that
951 messages be authenticated or not. */
952
953isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
954{
955 if (h -> type != omapi_type_protocol)
956 return isc_boolean_false;
957 if (((omapi_protocol_object_t *)h) -> insecure)
958 return isc_boolean_false;
959 else
960 return isc_boolean_true;
961}
962
963/* Sets the address and authenticator verification callbacks. The handle
964 is to a listener object, not a protocol object. */
965
966isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
967 isc_result_t (*verify_addr)
968 (omapi_object_t *,
969 omapi_addr_t *),
970 isc_result_t (*verify_auth)
971 (omapi_object_t *,
972 omapi_auth_key_t *))
973{
974 omapi_protocol_listener_object_t *l;
975
976 if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
977 h = h -> outer;
978
979 if (h -> type != omapi_type_protocol_listener)
98bf1607 980 return DHCP_R_INVALIDARG;
49146f3c
DN
981 l = (omapi_protocol_listener_object_t *)h;
982
983 l -> verify_auth = verify_auth;
984 l -> insecure = 0;
985
0f750c4f
SR
986 if (h -> outer != NULL) {
987 return omapi_listener_configure_security (h -> outer, verify_addr);
988 } else {
989 return DHCP_R_INVALIDARG;
990 }
49146f3c 991}
f6b8f48d 992
49146f3c 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;
f6b8f48d 1095
61b844bf
TL
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;
f6b8f48d 1109
61b844bf
TL
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 }
f6b8f48d
TM
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}