File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / omapip / protocol.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:30:18 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>