File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / omapip / protocol.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    1: /* protocol.c
    2: 
    3:    Functions supporting the object management protocol... */
    4: 
    5: /*
    6:  * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
    7:  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
    8:  * Copyright (c) 1999-2003 by Internet Software Consortium
    9:  *
   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.
   13:  *
   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.
   21:  *
   22:  *   Internet Systems Consortium, Inc.
   23:  *   950 Charter Street
   24:  *   Redwood City, CA 94063
   25:  *   <info@isc.org>
   26:  *   https://www.isc.org/
   27:  *
   28:  * This software has been written for Internet Systems Consortium
   29:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
   30:  * To learn more about Internet Systems Consortium, see
   31:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
   32:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
   33:  * ``http://www.nominum.com''.
   34:  */
   35: 
   36: #include "dhcpd.h"
   37: 
   38: #include <omapip/omapip_p.h>
   39: 
   40: OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
   41: 		    omapi_type_protocol)
   42: OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
   43: 		    omapi_type_protocol_listener)
   44: 
   45: isc_result_t omapi_protocol_connect (omapi_object_t *h,
   46: 				     const char *server_name,
   47: 				     unsigned port,
   48: 				     omapi_object_t *a)
   49: {
   50: 	isc_result_t rstatus, status;
   51: 	omapi_protocol_object_t *obj;
   52: 
   53: #ifdef DEBUG_PROTOCOL
   54: 	log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
   55: #endif
   56: 
   57: 	obj = (omapi_protocol_object_t *)0;
   58: 	status = omapi_protocol_allocate (&obj, MDL);
   59: 	if (status != ISC_R_SUCCESS)
   60: 		return status;
   61: 
   62: 	rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
   63: 	if (rstatus != ISC_R_SUCCESS && rstatus != ISC_R_INCOMPLETE) {
   64: 		omapi_protocol_dereference (&obj, MDL);
   65: 		return rstatus;
   66: 	}
   67: 	status = omapi_object_reference (&h -> outer,
   68: 					 (omapi_object_t *)obj, MDL);
   69: 	if (status != ISC_R_SUCCESS) {
   70: 		omapi_protocol_dereference (&obj, MDL);
   71: 		return status;
   72: 	}
   73: 	status = omapi_object_reference (&obj -> inner, h, MDL);
   74: 	if (status != ISC_R_SUCCESS) {
   75: 		omapi_protocol_dereference (&obj, MDL);
   76: 		return status;
   77: 	}
   78: 
   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;
   99: 		rstatus = ISC_R_INCOMPLETE;
  100: 	} else {
  101: 		obj -> insecure = 1;
  102: #if 0
  103: 		status = ISC_R_SUCCESS;
  104: #endif
  105: 	}
  106: 
  107: 	omapi_protocol_dereference (&obj, MDL);
  108: 	return rstatus;
  109: }
  110: 
  111: /* Send the protocol introduction message. */
  112: isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
  113: 					unsigned ver,
  114: 					unsigned hsize)
  115: {
  116: 	isc_result_t status;
  117: 	omapi_protocol_object_t *p;
  118: 
  119: #ifdef DEBUG_PROTOCOL
  120: 	log_debug ("omapi_protocol_send_intro()");
  121: #endif
  122: 
  123: 	if (h -> type != omapi_type_protocol)
  124: 		return ISC_R_INVALIDARG;
  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);
  143: 	if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
  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: 
  151: #ifdef DEBUG_PROTOCOL
  152: extern const char *omapi_message_op_name(int);
  153: #endif /* DEBUG_PROTOCOL */
  154: 
  155: isc_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;
  162: 	omapi_message_object_t *m, *om;
  163: 	omapi_remote_auth_t *ra;
  164: 	omapi_value_t *signature;
  165: 	isc_result_t status;
  166: 	unsigned auth_len;
  167: 
  168: 	if (po -> type != omapi_type_protocol ||
  169: 	    !po -> outer || po -> outer -> type != omapi_type_connection ||
  170: 	    mo -> type != omapi_type_message)
  171: 		return ISC_R_INVALIDARG;
  172: 	if (omo && omo -> type != omapi_type_message)
  173: 		return ISC_R_INVALIDARG;
  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: 
  179: #ifdef DEBUG_PROTOCOL
  180: 	log_debug ("omapi_protocol_send_message(): "
  181: 		   "op=%s  handle=%#lx  id=%#lx  rid=%#lx",
  182: 		   omapi_message_op_name (m->op),
  183: 		   (long)(m -> object ? m -> object -> handle : m -> handle),
  184: 		   (long)p -> next_xid, (long)m -> rid);
  185: #endif
  186: 
  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)
  196: 			return ISC_R_KEY_UNKNOWN;
  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);
  215: 		return status;
  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);
  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
  256: 						  : (m -> object
  257: 						     ? m -> object -> handle
  258: 						     : 0)));
  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. */
  274: 	status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
  275: 	if (status != ISC_R_SUCCESS) {
  276: 		omapi_disconnect (c, 1);
  277: 		return status;
  278: 	}
  279: 
  280: 	/* Stuff out the name/value pairs specific to this message. */
  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;
  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);
  290: 	if (status != ISC_R_SUCCESS) {
  291: 		omapi_disconnect (c, 1);
  292: 		return status;
  293: 	}
  294: 
  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: 
  305: 	/* Write the zero-length name that terminates the list of name/value
  306: 	   pairs for the associated object. */
  307: 	status = omapi_connection_put_uint16 (c, 0);
  308: 	if (status != ISC_R_SUCCESS) {
  309: 		omapi_disconnect (c, 1);
  310: 		return status;
  311: 	}
  312: 
  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: 	}
  342: 
  343: 	if (!omo) {
  344: 		omapi_protocol_reference (&m -> protocol_object, p, MDL);
  345: 	}
  346: 	return ISC_R_SUCCESS;
  347: }
  348: 					  
  349: 
  350: isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
  351: 					    const char *name, va_list ap)
  352: {
  353: 	isc_result_t status;
  354: 	omapi_protocol_object_t *p;
  355: 	omapi_object_t *c;
  356: 	omapi_message_object_t *m;
  357: 	omapi_value_t *signature;
  358: 	u_int16_t nlen;
  359: 	u_int32_t vlen;
  360: 	u_int32_t th;
  361: #if defined (DEBUG_MEMORY_LEAKAGE)
  362: 	unsigned long previous_outstanding = 0xDEADBEEF;
  363: 	unsigned long connect_outstanding = 0xDEADBEEF;
  364: #endif
  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: 
  372: 	if (!strcmp (name, "connect")) {
  373: #if defined (DEBUG_MEMORY_LEAKAGE)
  374: 		connect_outstanding = dmalloc_outstanding;
  375: #endif
  376: 		/* Send the introductory message. */
  377: 		status = omapi_protocol_send_intro
  378: 			(h, OMAPI_PROTOCOL_VERSION,
  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: 
  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: 
  400: 	/* If we get a disconnect, dump memory usage. */
  401: 	if (!strcmp (name, "disconnect")) {
  402: #if defined (DEBUG_MEMORY_LEAKAGE)
  403: 	    if (connect_outstanding != 0xDEADBEEF) {
  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");
  408: 	    }
  409: #endif
  410: #if defined (DEBUG_MEMORY_LEAKAGE)
  411: 	    dmalloc_dump_outstanding ();
  412: #endif
  413: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
  414: 	    dump_rc_history (h);
  415: #endif
  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: 	    }
  422: 
  423: 	    /* XXX */
  424: 	    return ISC_R_SUCCESS;
  425: 	}
  426: 
  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)
  437: 		return ISC_R_INVALIDARG;
  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. */
  447: 		omapi_connection_get_uint32 (c, &p -> protocol_version);
  448: 		omapi_connection_get_uint32 (c, &p -> header_size);
  449: 	
  450: 		/* We currently only support the current protocol version. */
  451: 		if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
  452: 			omapi_disconnect (c, 1);
  453: 			return ISC_R_VERSIONMISMATCH;
  454: 		}
  455: 
  456: 		if (p -> header_size < sizeof (omapi_protocol_header_t)) {
  457: 			omapi_disconnect (c, 1);
  458: 			return ISC_R_PROTOCOLERROR;
  459: 		}
  460: 
  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: 		}
  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. */
  481: 		if ((omapi_connection_require (c, p -> header_size)) !=
  482: 		    ISC_R_SUCCESS)
  483: 			break;
  484: 		/* If we already have the data, fall through. */
  485: 
  486: 	      case omapi_protocol_header_wait:
  487: #if defined (DEBUG_MEMORY_LEAKAGE)
  488: 		if (previous_outstanding != 0xDEADBEEF) {
  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)
  499: 			dump_rc_history (h);
  500: #endif
  501: #if defined (DEBUG_MEMORY_LEAKAGE)
  502: 		}
  503: 		previous_outstanding = dmalloc_outstanding;
  504: #endif
  505: 		status = omapi_message_new ((omapi_object_t **)&p -> message,
  506: 					    MDL);
  507: 		if (status != ISC_R_SUCCESS) {
  508: 			omapi_disconnect (c, 1);
  509: 			return status;
  510: 		}
  511: 
  512: 		p -> verify_result = ISC_R_SUCCESS;
  513: 
  514: 		/* Swap in the header... */
  515: 		omapi_connection_get_uint32 (c, &p -> message -> authid);
  516: 
  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: 
  535: 		omapi_connection_get_uint32 (c, &p -> message -> authlen);
  536: 		omapi_connection_get_uint32 (c, &p -> message -> op);
  537: 		omapi_connection_get_uint32 (c, &th);
  538: 		p -> message -> h = th;
  539: 		omapi_connection_get_uint32 (c, &p -> message -> id);
  540: 		omapi_connection_get_uint32 (c, &p -> message -> rid);
  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: 
  554: 		/* First we read in message-specific values, then object
  555: 		   values. */
  556: 		p -> reading_message_values = 1;
  557: 
  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) {
  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: 
  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. */
  603: 		status = (omapi_data_string_new (&p -> name, nlen, MDL));
  604: 		if (status != ISC_R_SUCCESS) {
  605: 			omapi_disconnect (c, 1);
  606: 			return ISC_R_NOMEMORY;
  607: 		}
  608: 		p -> state = omapi_protocol_name_wait;
  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. */
  617: 		p -> state = omapi_protocol_value_length_wait;
  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: 
  631: 		status = omapi_typed_data_new (MDL, &p -> value,
  632: 					       omapi_datatype_data,
  633: 					       vlen);
  634: 		if (status != ISC_R_SUCCESS) {
  635: 			omapi_disconnect (c, 1);
  636: 			return ISC_R_NOMEMORY;
  637: 		}
  638: 
  639: 		p -> state = omapi_protocol_value_wait;
  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:
  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
  659: 					  (&p -> message -> object, MDL));
  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: 		}
  670: 		if (status != ISC_R_SUCCESS) {
  671: 			omapi_disconnect (c, 1);
  672: 			return status;
  673: 		}
  674: 		omapi_data_string_dereference (&p -> name, MDL);
  675: 		if (p -> value)
  676: 			omapi_typed_data_dereference (&p -> value, MDL);
  677: 		goto need_name_length;
  678: 
  679: 	      signature_wait:
  680: 	      case omapi_protocol_signature_wait:
  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. */
  704: 		status = omapi_typed_data_new (MDL,
  705: 					       &p -> message -> authenticator,
  706: 					       omapi_datatype_data,
  707: 					       p -> message -> authlen);
  708: 			
  709: 		if (status != ISC_R_SUCCESS) {
  710: 			omapi_value_dereference (&signature, MDL);
  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);
  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. */
  726: 			p -> verify_result = ISC_R_INVALIDKEY;
  727: 		}
  728: 
  729: 		omapi_value_dereference (&signature, MDL);
  730: 
  731: 		/* Process the message. */
  732: 	      message_done:
  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: 		}
  741: 		if (status != ISC_R_SUCCESS) {
  742: 			omapi_disconnect (c, 1);
  743: 			return ISC_R_NOMEMORY;
  744: 		}
  745: 
  746: 		omapi_message_dereference (&p -> message, MDL);
  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)
  757: 		dump_rc_history (h);
  758: #endif
  759: #if defined (DEBUG_MEMORY_LEAKAGE)
  760: 		previous_outstanding = 0xDEADBEEF;
  761: #endif
  762: 		/* Now wait for the next message. */
  763: 		goto to_header_wait;		
  764: 
  765: 	      default:
  766: 		/* XXX should never get here.   Assertion? */
  767: 		break;
  768: 	}
  769: 	return ISC_R_SUCCESS;
  770: }
  771: 
  772: isc_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))
  782: 		return ISC_R_INVALIDARG;
  783: 
  784: 	if (po -> type != omapi_type_protocol)
  785: 		return ISC_R_INVALIDARG;
  786: 	p = (omapi_protocol_object_t *)po;
  787: 
  788: #ifdef DEBUG_PROTOCOL
  789: 	log_debug ("omapi_protocol_add_auth(name=%s)",
  790: 		   ((omapi_auth_key_t *)ao) -> name);
  791: #endif
  792: 
  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: 
  832: isc_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)
  840: 		return ISC_R_INVALIDARG;
  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: 
  847: 	return ISC_R_KEY_UNKNOWN;
  848: }
  849: 
  850: isc_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: {
  855: 	omapi_protocol_object_t *p;
  856: 	omapi_remote_auth_t *r;
  857: 
  858: 	if (h -> type != omapi_type_protocol)
  859: 		return ISC_R_INVALIDARG;
  860: 	p = (omapi_protocol_object_t *)h;
  861: 
  862: 	if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
  863: 		if (value -> type != omapi_datatype_object)
  864: 			return ISC_R_INVALIDARG;
  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)
  874: 				return ISC_R_KEY_UNKNOWN;
  875: 
  876: 			p -> default_auth = r;
  877: 		}
  878: 
  879: 		return ISC_R_SUCCESS;
  880: 	}
  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: 
  888: isc_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: {
  893: 	omapi_protocol_object_t *p;
  894: 
  895: 	if (h -> type != omapi_type_protocol)
  896: 		return ISC_R_INVALIDARG;
  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: 	}
  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: 
  913: isc_result_t omapi_protocol_destroy (omapi_object_t *h,
  914: 				     const char *file, int line)
  915: {
  916: 	omapi_protocol_object_t *p;
  917: 	if (h -> type != omapi_type_protocol)
  918: 		return ISC_R_INVALIDARG;
  919: 	p = (omapi_protocol_object_t *)h;
  920: 	if (p -> message)
  921: 		omapi_message_dereference (&p -> message, file, line);
  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) {
  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);
  934: 	}
  935: 	return ISC_R_SUCCESS;
  936: }
  937: 
  938: /* Write all the published values associated with the object through the
  939:    specified connection. */
  940: 
  941: isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
  942: 					  omapi_object_t *id,
  943: 					  omapi_object_t *p)
  944: {
  945: 	if (p -> type != omapi_type_protocol)
  946: 		return ISC_R_INVALIDARG;
  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: 
  954: /* Returns a boolean indicating whether this protocol requires that
  955:    messages be authenticated or not. */
  956: 
  957: isc_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: 
  970: isc_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)
  984: 		return ISC_R_INVALIDARG;
  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: 
  994: /* Set up a listener for the omapi protocol.    The handle stored points to
  995:    a listener object, not a protocol object. */
  996: 
  997: isc_result_t omapi_protocol_listen (omapi_object_t *h,
  998: 				    unsigned port,
  999: 				    int max)
 1000: {
 1001: 	isc_result_t status;
 1002: 	omapi_protocol_listener_object_t *obj;
 1003: 
 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;
 1008: 
 1009: 	status = omapi_object_reference (&h -> outer,
 1010: 					 (omapi_object_t *)obj, MDL);
 1011: 	if (status != ISC_R_SUCCESS) {
 1012: 		omapi_protocol_listener_dereference (&obj, MDL);
 1013: 		return status;
 1014: 	}
 1015: 	status = omapi_object_reference (&obj -> inner, h, MDL);
 1016: 	if (status != ISC_R_SUCCESS) {
 1017: 		omapi_protocol_listener_dereference (&obj, MDL);
 1018: 		return status;
 1019: 	}
 1020: 
 1021: 	/* What a terrible default. */
 1022: 	obj -> insecure = 1;
 1023: 
 1024: 	status = omapi_listen ((omapi_object_t *)obj, port, max);
 1025: 	omapi_protocol_listener_dereference (&obj, MDL);
 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: 
 1032: isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
 1033: 					     const char *name, va_list ap)
 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)
 1041: 		return ISC_R_INVALIDARG;
 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)
 1054: 		return ISC_R_INVALIDARG;
 1055: 
 1056: 	obj = (omapi_protocol_object_t *)0;
 1057: 	status = omapi_protocol_allocate (&obj, MDL);
 1058: 	if (status != ISC_R_SUCCESS)
 1059: 		return status;
 1060: 
 1061: 	obj -> verify_auth = p -> verify_auth;
 1062: 	obj -> insecure = p -> insecure;
 1063: 
 1064: 	status = omapi_object_reference (&obj -> outer, c, MDL);
 1065: 	if (status != ISC_R_SUCCESS) {
 1066: 	      lose:
 1067: 		omapi_protocol_dereference (&obj, MDL);
 1068: 		omapi_disconnect (c, 1);
 1069: 		return status;
 1070: 	}
 1071: 
 1072: 	status = omapi_object_reference (&c -> inner,
 1073: 					 (omapi_object_t *)obj, MDL);
 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: 
 1084: 	omapi_protocol_dereference (&obj, MDL);
 1085: 	return status;
 1086: }
 1087: 
 1088: isc_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)
 1094: 		return ISC_R_INVALIDARG;
 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: 
 1102: isc_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)
 1108: 		return ISC_R_INVALIDARG;
 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: 
 1116: isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
 1117: 					      const char *file, int line)
 1118: {
 1119: 	if (h -> type != omapi_type_protocol_listener)
 1120: 		return ISC_R_INVALIDARG;
 1121: 	return ISC_R_SUCCESS;
 1122: }
 1123: 
 1124: /* Write all the published values associated with the object through the
 1125:    specified connection. */
 1126: 
 1127: isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
 1128: 					    omapi_object_t *id,
 1129: 					    omapi_object_t *p)
 1130: {
 1131: 	if (p -> type != omapi_type_protocol_listener)
 1132: 		return ISC_R_INVALIDARG;
 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: 
 1140: isc_result_t omapi_protocol_send_status (omapi_object_t *po,
 1141: 					 omapi_object_t *id,
 1142: 					 isc_result_t waitstatus,
 1143: 					 unsigned rid, const char *msg)
 1144: {
 1145: 	isc_result_t status;
 1146: 	omapi_message_object_t *message = (omapi_message_object_t *)0;
 1147: 	omapi_object_t *mo;
 1148: 
 1149: 	if (po -> type != omapi_type_protocol)
 1150: 		return ISC_R_INVALIDARG;
 1151: 
 1152: 	status = omapi_message_new ((omapi_object_t **)&message, MDL);
 1153: 	if (status != ISC_R_SUCCESS)
 1154: 		return status;
 1155: 	mo = (omapi_object_t *)message;
 1156: 
 1157: 	status = omapi_set_int_value (mo, (omapi_object_t *)0,
 1158: 				      "op", OMAPI_OP_STATUS);
 1159: 	if (status != ISC_R_SUCCESS) {
 1160: 		omapi_message_dereference (&message, MDL);
 1161: 		return status;
 1162: 	}
 1163: 
 1164: 	status = omapi_set_int_value (mo, (omapi_object_t *)0,
 1165: 				      "rid", (int)rid);
 1166: 	if (status != ISC_R_SUCCESS) {
 1167: 		omapi_message_dereference (&message, MDL);
 1168: 		return status;
 1169: 	}
 1170: 
 1171: 	status = omapi_set_int_value (mo, (omapi_object_t *)0,
 1172: 				      "result", (int)waitstatus);
 1173: 	if (status != ISC_R_SUCCESS) {
 1174: 		omapi_message_dereference (&message, MDL);
 1175: 		return status;
 1176: 	}
 1177: 
 1178: 	/* If a message has been provided, send it. */
 1179: 	if (msg) {
 1180: 		status = omapi_set_string_value (mo, (omapi_object_t *)0,
 1181: 						 "message", msg);
 1182: 		if (status != ISC_R_SUCCESS) {
 1183: 			omapi_message_dereference (&message, MDL);
 1184: 			return status;
 1185: 		}
 1186: 	}
 1187: 
 1188: 	status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
 1189: 	omapi_message_dereference (&message, MDL);
 1190: 	return status;
 1191: }
 1192: 
 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: 
 1197: isc_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)
 1208: 		return ISC_R_INVALIDARG;
 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: 
 1257: isc_result_t omapi_protocol_send_update (omapi_object_t *po,
 1258: 					 omapi_object_t *id,
 1259: 					 unsigned rid,
 1260: 					 omapi_object_t *object)
 1261: {
 1262: 	isc_result_t status;
 1263: 	omapi_message_object_t *message = (omapi_message_object_t *)0;
 1264: 	omapi_object_t *mo;
 1265: 
 1266: 	if (po -> type != omapi_type_protocol)
 1267: 		return ISC_R_INVALIDARG;
 1268: 
 1269: 	status = omapi_message_new ((omapi_object_t **)&message, MDL);
 1270: 	if (status != ISC_R_SUCCESS)
 1271: 		return status;
 1272: 	mo = (omapi_object_t *)message;
 1273: 
 1274: 	status = omapi_set_int_value (mo, (omapi_object_t *)0,
 1275: 				      "op", OMAPI_OP_UPDATE);
 1276: 	if (status != ISC_R_SUCCESS) {
 1277: 		omapi_message_dereference (&message, MDL);
 1278: 		return status;
 1279: 	}
 1280: 
 1281: 	if (rid) {
 1282: 		omapi_handle_t handle;
 1283: 		status = omapi_set_int_value (mo, (omapi_object_t *)0,
 1284: 					      "rid", (int)rid);
 1285: 		if (status != ISC_R_SUCCESS) {
 1286: 			omapi_message_dereference (&message, MDL);
 1287: 			return status;
 1288: 		}
 1289: 
 1290: 		status = omapi_object_handle (&handle, object);
 1291: 		if (status != ISC_R_SUCCESS) {
 1292: 			omapi_message_dereference (&message, MDL);
 1293: 			return status;
 1294: 		}
 1295: 		status = omapi_set_int_value (mo, (omapi_object_t *)0,
 1296: 					      "handle", (int)handle);
 1297: 		if (status != ISC_R_SUCCESS) {
 1298: 			omapi_message_dereference (&message, MDL);
 1299: 			return status;
 1300: 		}
 1301: 	}		
 1302: 		
 1303: 	status = omapi_set_object_value (mo, (omapi_object_t *)0,
 1304: 					 "object", object);
 1305: 	if (status != ISC_R_SUCCESS) {
 1306: 		omapi_message_dereference (&message, MDL);
 1307: 		return status;
 1308: 	}
 1309: 
 1310: 	status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
 1311: 	omapi_message_dereference (&message, MDL);
 1312: 	return status;
 1313: }

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