Example #1
0
isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *o,
					    const char *name, va_list ap)
{
	dhcpctl_remote_object_t *p;
	omapi_typed_data_t *tv;

	if (o -> type != dhcpctl_remote_type)
		return DHCP_R_INVALIDARG;
	p = (dhcpctl_remote_object_t *)o;

	if (!strcmp (name, "updated")) {
		p -> waitstatus = ISC_R_SUCCESS;
		if (o -> inner -> type == omapi_type_generic)
			omapi_generic_clear_flags (o -> inner);
		return omapi_signal_in (o -> inner, "ready");
	}
	if (!strcmp (name, "status")) {
		p -> waitstatus = va_arg (ap, isc_result_t);
		if (p -> message)
			omapi_typed_data_dereference (&p -> message, MDL);
		tv = va_arg (ap, omapi_typed_data_t *);
		if (tv)
			omapi_typed_data_reference (&p -> message, tv, MDL);
		return omapi_signal_in (o -> inner, "ready");
	}
Example #2
0
isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
				      omapi_object_t *ao,
				      omapi_handle_t handle)
{
	omapi_protocol_object_t *p;
	omapi_remote_auth_t *r;
	isc_result_t status;

	if (ao -> type != omapi_type_auth_key &&
	    (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
		return ISC_R_INVALIDARG;

	if (po -> type != omapi_type_protocol)
		return ISC_R_INVALIDARG;
	p = (omapi_protocol_object_t *)po;

#ifdef DEBUG_PROTOCOL
	log_debug ("omapi_protocol_add_auth(name=%s)",
		   ((omapi_auth_key_t *)ao) -> name);
#endif

	if (p -> verify_auth) {
		status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
		if (status != ISC_R_SUCCESS)
			return status;
	}

	/* If omapi_protocol_connect() was called with a default
	   authenticator, p -> default_auth will already be set,
	   but p -> remote_auth_list will not yet be initialized. */
	if (p -> default_auth && !p -> remote_auth_list) {
		if (p -> default_auth -> a != ao) {
			/* Something just went horribly wrong. */
			omapi_disconnect (p -> outer, 1);
			return ISC_R_UNEXPECTED;
		}

		p -> remote_auth_list = p -> default_auth;
		p -> default_auth -> remote_handle = handle;

		return omapi_signal_in (p -> inner, "ready");
	}

	r = dmalloc (sizeof(*r), MDL);
	if (!r)
		return ISC_R_NOMEMORY;

	status = omapi_object_reference (&r -> a, ao, MDL);
	if (status != ISC_R_SUCCESS) {
		dfree (r, MDL);
		return status;
	}

	r -> remote_handle = handle;
	r -> next = p -> remote_auth_list;
	p -> remote_auth_list = r;

	return ISC_R_SUCCESS;
}
Example #3
0
	/* Find the matching connect object, if there is one. */
	omapi_array_foreach_begin (omapi_connections,
				   omapi_connection_object_t, lp) {
	    for (i = 0; (lp -> connect_list &&
			 i < lp -> connect_list -> count); i++) {
		    if (!memcmp (&remote.sin_addr,
				 &lp -> connect_list -> addresses [i].address,
				 sizeof remote.sin_addr) &&
			(ntohs (remote.sin_port) ==
			 lp -> connect_list -> addresses [i].port))
			lp -> state = omapi_connection_connected;
			lp -> remote_addr = remote;
			lp -> remote_addr.sin_family = AF_INET;
			omapi_addr_list_dereference (&lp -> connect_list, MDL);
			lp -> index = connect_index;
			status = omapi_signal_in ((omapi_object_t *)lp,
						  "connect");
			omapi_connection_dereference (&lp, MDL);
			return;
		}
	} omapi_array_foreach_end (omapi_connections,
Example #4
0
isc_result_t omapi_one_dispatch (omapi_object_t *wo,
				 struct timeval *t)
{
	fd_set r, w, x, rr, ww, xx;
	int max = 0;
	int count;
	int desc;
	struct timeval now, to;
	omapi_io_object_t *io, *prev, *next;
	omapi_waiter_object_t *waiter;
	omapi_object_t *tmp = (omapi_object_t *)0;
	isc_result_t status;

	if (!wo || wo -> type != omapi_type_waiter)
		waiter = (omapi_waiter_object_t *)0;
	else
		waiter = (omapi_waiter_object_t *)wo;

	FD_ZERO (&x);

	/* First, see if the timeout has expired, and if so return. */
	if (t) {
		gettimeofday (&now, (struct timezone *)0);
		cur_tv.tv_sec = now.tv_sec;
		cur_tv.tv_usec = now.tv_usec;
		if (now.tv_sec > t -> tv_sec ||
		    (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
			return ISC_R_TIMEDOUT;
			
		/* We didn't time out, so figure out how long until
		   we do. */
		to.tv_sec = t -> tv_sec - now.tv_sec;
		to.tv_usec = t -> tv_usec - now.tv_usec;
		if (to.tv_usec < 0) {
			to.tv_usec += 1000000;
			to.tv_sec--;
		}

		/* It is possible for the timeout to get set larger than
		   the largest time select() is willing to accept.
		   Restricting the timeout to a maximum of one day should
		   work around this.  -DPN.  (Ref: Bug #416) */
		if (to.tv_sec > (60 * 60 * 24))
			to.tv_sec = 60 * 60 * 24;
	}
	
	/* If the object we're waiting on has reached completion,
	   return now. */
	if (waiter && waiter -> ready)
		return ISC_R_SUCCESS;
	
      again:
	/* If we have no I/O state, we can't proceed. */
	if (!(io = omapi_io_states.next))
		return ISC_R_NOMORE;

	/* Set up the read and write masks. */
	FD_ZERO (&r);
	FD_ZERO (&w);

	for (; io; io = io -> next) {
		/* Check for a read socket.   If we shouldn't be
		   trying to read for this I/O object, either there
		   won't be a readfd function, or it'll return -1. */
		if (io -> readfd && io -> inner &&
		    (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
			FD_SET (desc, &r);
			if (desc > max)
				max = desc;
		}
		
		/* Same deal for write fdets. */
		if (io -> writefd && io -> inner &&
		    (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
			FD_SET (desc, &w);
			if (desc > max)
				max = desc;
		}
	}

	/* poll if all reader are dry */ 
	now.tv_sec = 0;
	now.tv_usec = 0;
	rr=r; 
	ww=w; 
	xx=x;

	/* poll once */
	count = select(max + 1, &r, &w, &x, &now);
	if (!count) {  
		/* We are dry now */ 
		trigger_event(&rw_queue_empty);
		/* Wait for a packet or a timeout... XXX */
		r = rr;
		w = ww;
		x = xx;
		count = select(max + 1, &r, &w, &x, t ? &to : NULL);
	}

	/* Get the current time... */
	gettimeofday (&cur_tv, (struct timezone *)0);

	/* We probably have a bad file descriptor.   Figure out which one.
	   When we find it, call the reaper function on it, which will
	   maybe make it go away, and then try again. */
	if (count < 0) {
		struct timeval t0;
		omapi_io_object_t *prev = (omapi_io_object_t *)0;
		io = (omapi_io_object_t *)0;
		if (omapi_io_states.next)
			omapi_io_reference (&io, omapi_io_states.next, MDL);

		while (io) {
			omapi_object_t *obj;
			FD_ZERO (&r);
			FD_ZERO (&w);
			t0.tv_sec = t0.tv_usec = 0;

			if (io -> readfd && io -> inner &&
			    (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
			    FD_SET (desc, &r);
			    count = select (desc + 1, &r, &w, &x, &t0);
			   bogon:
			    if (count < 0) {
				log_error ("Bad descriptor %d.", desc);
				for (obj = (omapi_object_t *)io;
				     obj -> outer;
				     obj = obj -> outer)
					;
				for (; obj; obj = obj -> inner) {
				    omapi_value_t *ov;
				    int len;
				    const char *s;
				    ov = (omapi_value_t *)0;
				   status = omapi_get_value_str (obj,
							 (omapi_object_t *)0,
							 "name", &ov);
				   if(status!=ISC_R_SUCCESS){
						log_error("omapi_get_value_str failed!\n");
				   }
				    if (ov && ov -> value &&
					(ov -> value -> type ==
					 omapi_datatype_string)) {
					s = (char *)
						ov -> value -> u.buffer.value;
					len = ov -> value -> u.buffer.len;
				    } else {
					s = "";
					len = 0;
				    }
				    log_error ("Object %lx %s%s%.*s",
					       (unsigned long)obj,
					       obj -> type -> name,
					       len ? " " : "",
					       len, s);
				    if (len)
					omapi_value_dereference (&ov, MDL);
				}
				(*(io -> reaper)) (io -> inner);
				if (prev) {
				    omapi_io_dereference (&prev -> next, MDL);
				    if (io -> next)
					omapi_io_reference (&prev -> next,
							    io -> next, MDL);
				} else {
				    omapi_io_dereference
					    (&omapi_io_states.next, MDL);
				    if (io -> next)
					omapi_io_reference
						(&omapi_io_states.next,
						 io -> next, MDL);
				}
				omapi_io_dereference (&io, MDL);
				goto again;
			    }
			}
			
			FD_ZERO (&r);
			FD_ZERO (&w);
			t0.tv_sec = t0.tv_usec = 0;

			/* Same deal for write fdets. */
			if (io -> writefd && io -> inner &&
			    (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
				FD_SET (desc, &w);
				count = select (desc + 1, &r, &w, &x, &t0);
				if (count < 0)
					goto bogon;
			}
			if (prev)
				omapi_io_dereference (&prev, MDL);
			omapi_io_reference (&prev, io, MDL);
			omapi_io_dereference (&io, MDL);
			if (prev -> next)
			    omapi_io_reference (&io, prev -> next, MDL);
		}
		if (prev)
			omapi_io_dereference (&prev, MDL);
		
	}

	for (io = omapi_io_states.next; io; io = io -> next) {
		if (!io -> inner)
			continue;
		omapi_object_reference (&tmp, io -> inner, MDL);
		/* Check for a read descriptor, and if there is one,
		   see if we got input on that socket. */
		if (io -> readfd &&
		    (desc = (*(io -> readfd)) (tmp)) >= 0) {
			if (FD_ISSET (desc, &r))
				((*(io -> reader)) (tmp));
		}
		
		/* Same deal for write descriptors. */
		if (io -> writefd &&
		    (desc = (*(io -> writefd)) (tmp)) >= 0)
		{
			if (FD_ISSET (desc, &w))
				((*(io -> writer)) (tmp));
		}
		omapi_object_dereference (&tmp, MDL);
	}

	/* Now check for I/O handles that are no longer valid,
	   and remove them from the list. */
	prev = NULL;
	io = NULL;
	if (omapi_io_states.next != NULL) {
		omapi_io_reference(&io, omapi_io_states.next, MDL);
	}
	while (io != NULL) {
		if ((io->inner == NULL) || 
		    ((io->reaper != NULL) && 
		     ((io->reaper)(io->inner) != ISC_R_SUCCESS))) 
		{

			omapi_io_object_t *tmp = NULL;
			/* Save a reference to the next
			   pointer, if there is one. */
			if (io->next != NULL) {
				omapi_io_reference(&tmp, io->next, MDL);
				omapi_io_dereference(&io->next, MDL);
			}
			if (prev != NULL) {
				omapi_io_dereference(&prev->next, MDL);
				if (tmp != NULL)
					omapi_io_reference(&prev->next,
							   tmp, MDL);
			} else {
				omapi_io_dereference(&omapi_io_states.next, 
						     MDL);
				if (tmp != NULL)
					omapi_io_reference
					    (&omapi_io_states.next,
					     tmp, MDL);
				else
					omapi_signal_in(
							(omapi_object_t *)
						 	&omapi_io_states,
							"ready");
			}
			if (tmp != NULL)
				omapi_io_dereference(&tmp, MDL);

		} else {

			if (prev != NULL) {
				omapi_io_dereference(&prev, MDL);
			}
			omapi_io_reference(&prev, io, MDL);

		}

		/*
		 * Equivalent to:
		 *   io = io->next
		 * But using our reference counting voodoo.
		 */
		next = NULL;
		if (io->next != NULL) {
			omapi_io_reference(&next, io->next, MDL);
		}
		omapi_io_dereference(&io, MDL);
		if (next != NULL) {
			omapi_io_reference(&io, next, MDL);
			omapi_io_dereference(&next, MDL);
		}
	}
	if (prev != NULL) {
		omapi_io_dereference(&prev, MDL);
	}

	return ISC_R_SUCCESS;
}
Example #5
0
isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
					    const char *name, va_list ap)
{
	isc_result_t status;
	omapi_protocol_object_t *p;
	omapi_object_t *c;
	omapi_message_object_t *m;
	omapi_value_t *signature;
	u_int16_t nlen;
	u_int32_t vlen;
	u_int32_t th;
#if defined (DEBUG_MEMORY_LEAKAGE)
	unsigned long previous_outstanding = 0xDEADBEEF;
	unsigned long connect_outstanding = 0xDEADBEEF;
#endif

	if (h -> type != omapi_type_protocol) {
		/* XXX shouldn't happen.   Put an assert here? */
		return ISC_R_UNEXPECTED;
	}
	p = (omapi_protocol_object_t *)h;

	if (!strcmp (name, "connect")) {
#if defined (DEBUG_MEMORY_LEAKAGE)
		connect_outstanding = dmalloc_outstanding;
#endif
		/* Send the introductory message. */
		status = omapi_protocol_send_intro
			(h, OMAPI_PROTOCOL_VERSION,
			 sizeof (omapi_protocol_header_t));
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect (p -> outer, 1);
			return status;
		}
		return ISC_R_SUCCESS;
	}

	/* Should only receive these when opening the initial authenticator. */
	if (!strcmp (name, "status")) {
		status = va_arg (ap, isc_result_t);
		if (status != ISC_R_SUCCESS) {
			omapi_signal_in (h -> inner, "status", status,
					 (omapi_object_t *)0);
			omapi_disconnect (p -> outer, 1);
			return status;
		} else {
			return omapi_signal_in (h -> inner, "ready");
		}
	}

	/* If we get a disconnect, dump memory usage. */
	if (!strcmp (name, "disconnect")) {
#if defined (DEBUG_MEMORY_LEAKAGE)
	    if (connect_outstanding != 0xDEADBEEF) {
		log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
			  dmalloc_generation,
			  dmalloc_outstanding - previous_outstanding,
			  dmalloc_outstanding, dmalloc_longterm, " long-term");
	    }
#endif
#if defined (DEBUG_MEMORY_LEAKAGE)
	    dmalloc_dump_outstanding ();
#endif
#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
	    dump_rc_history ();
#endif
	    for (m = omapi_registered_messages; m; m = m -> next) {
		if (m -> protocol_object == p) {
		    if (m -> object)
			omapi_signal (m -> object, "disconnect");
		}
	    }
	}

	/* Not a signal we recognize? */
	if (strcmp (name, "ready")) {
		if (p -> inner && p -> inner -> type -> signal_handler)
			return (*(p -> inner -> type -> signal_handler)) (h,
									  name,
									  ap);
		return ISC_R_NOTFOUND;
	}

	if (!p -> outer || p -> outer -> type != omapi_type_connection)
		return ISC_R_INVALIDARG;
	c = p -> outer;

	/* We get here because we requested that we be woken up after
           some number of bytes were read, and that number of bytes
           has in fact been read. */
	switch (p -> state) {
	      case omapi_protocol_intro_wait:
		/* Get protocol version and header size in network
		   byte order. */
		omapi_connection_get_uint32 (c, &p -> protocol_version);
		omapi_connection_get_uint32 (c, &p -> header_size);
	
		/* We currently only support the current protocol version. */
		if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
			omapi_disconnect (c, 1);
			return ISC_R_VERSIONMISMATCH;
		}

		if (p -> header_size < sizeof (omapi_protocol_header_t)) {
			omapi_disconnect (c, 1);
			return ISC_R_PROTOCOLERROR;
		}

		if (p -> default_auth) {
			status = omapi_protocol_send_open
				(h, (omapi_object_t *)0, "authenticator",
				 p -> default_auth -> a,
				 OMAPI_NOTIFY_PROTOCOL);
			if (status != ISC_R_SUCCESS) {
				omapi_disconnect (c, 1);
				return status;
			}
		} else {
			status = omapi_signal_in (h -> inner, "ready");
		}

	      to_header_wait:
		/* The next thing we're expecting is a message header. */
		p -> state = omapi_protocol_header_wait;

		/* Register a need for the number of bytes in a
		   header, and if we already have that many, process
		   them immediately. */
		if ((omapi_connection_require (c, p -> header_size)) !=
		    ISC_R_SUCCESS)
			break;
		/* If we already have the data, fall through. */

	      case omapi_protocol_header_wait:
#if defined (DEBUG_MEMORY_LEAKAGE)
		if (previous_outstanding != 0xDEADBEEF) {
			log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
				  "generation", dmalloc_generation,
				  dmalloc_outstanding - previous_outstanding,
				  dmalloc_outstanding, dmalloc_longterm,
				  " long-term");
#endif
#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
			dmalloc_dump_outstanding ();
#endif
#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
			dump_rc_history ();
#endif
#if defined (DEBUG_MEMORY_LEAKAGE)
		}
		previous_outstanding = dmalloc_outstanding;
#endif
		status = omapi_message_new ((omapi_object_t **)&p -> message,
					    MDL);
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect (c, 1);
			return status;
		}

		p -> verify_result = ISC_R_SUCCESS;

		/* Swap in the header... */
		omapi_connection_get_uint32 (c, &p -> message -> authid);

		/* Bind the authenticator to the message object. */
		if (p -> message -> authid) {
			status = (omapi_protocol_lookup_auth
				  (&p -> message -> id_object, h,
				   p -> message -> authid));
			if (status != ISC_R_SUCCESS)
				p -> verify_result = status;

			/* Activate the authentication key. */
			status = omapi_set_object_value
				(c, (omapi_object_t *)0, "input-authenticator",
				 p -> message -> id_object);
			if (status != ISC_R_SUCCESS) {
				omapi_disconnect (c, 1);
				return status;
			}
		}

		omapi_connection_get_uint32 (c, &p -> message -> authlen);
		omapi_connection_get_uint32 (c, &p -> message -> op);
		omapi_connection_get_uint32 (c, &th);
		p -> message -> h = th;
		omapi_connection_get_uint32 (c, &p -> message -> id);
		omapi_connection_get_uint32 (c, &p -> message -> rid);

		/* If there was any extra header data, skip over it. */
		if (p -> header_size > sizeof (omapi_protocol_header_t)) {
			omapi_connection_copyout
				(0, c, (p -> header_size -
					sizeof (omapi_protocol_header_t)));
		}
						     
		/* XXX must compute partial signature across the
                   XXX preceding bytes.    Also, if authenticator
		   specifies encryption as well as signing, we may
		   have to decrypt the data on the way in. */

		/* First we read in message-specific values, then object
		   values. */
		p -> reading_message_values = 1;

	      need_name_length:
		/* The next thing we're expecting is length of the
		   first name. */
		p -> state = omapi_protocol_name_length_wait;

		/* Wait for a 16-bit length. */
		if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
			break;
		/* If it's already here, fall through. */

	      case omapi_protocol_name_length_wait:
		omapi_connection_get_uint16 (c, &nlen);
		/* A zero-length name means that we're done reading name+value
		   pairs. */
		if (nlen == 0) {
			/* If we've already read in the object, we are
			   done reading the message, but if we've just
			   finished reading in the values associated
			   with the message, we need to read the
			   object. */
			if (p -> reading_message_values) {
				p -> reading_message_values = 0;
				goto need_name_length;
			}

			/* If the authenticator length is zero, there's no
			   signature to read in, so go straight to processing
			   the message. */
			if (p -> message -> authlen == 0)
				goto message_done;

			/* The next thing we're expecting is the
                           message signature. */
			p -> state = omapi_protocol_signature_wait;

			/* Wait for the number of bytes specified for
			   the authenticator.  If we already have it,
			   go read it in. */
			if (omapi_connection_require
			    (c, p -> message -> authlen) == ISC_R_SUCCESS)
				goto signature_wait;
			break;
		}

		/* Allocate a buffer for the name. */
		status = (omapi_data_string_new (&p -> name, nlen, MDL));
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect (c, 1);
			return ISC_R_NOMEMORY;
		}
		p -> state = omapi_protocol_name_wait;
		if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
			break;
		/* If it's already here, fall through. */
					     
	      case omapi_protocol_name_wait:
		omapi_connection_copyout (p -> name -> value, c,
					  p -> name -> len);
		/* Wait for a 32-bit length. */
		p -> state = omapi_protocol_value_length_wait;
		if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
			break;
		/* If it's already here, fall through. */

	      case omapi_protocol_value_length_wait:
		omapi_connection_get_uint32 (c, &vlen);

		/* Zero-length values are allowed - if we get one, we
		   don't have to read any data for the value - just
		   get the next one, if there is a next one. */
		if (!vlen)
			goto insert_new_value;

		status = omapi_typed_data_new (MDL, &p -> value,
					       omapi_datatype_data,
					       vlen);
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect (c, 1);
			return ISC_R_NOMEMORY;
		}

		p -> state = omapi_protocol_value_wait;
		if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
			break;
		/* If it's already here, fall through. */
					     
	      case omapi_protocol_value_wait:
		omapi_connection_copyout (p -> value -> u.buffer.value, c,
					  p -> value -> u.buffer.len);

	      insert_new_value:
		if (p -> reading_message_values) {
			status = (omapi_set_value
				  ((omapi_object_t *)p -> message,
				   p -> message -> id_object,
				   p -> name, p -> value));
		} else {
			if (!p -> message -> object) {
				/* We need a generic object to hang off of the
				   incoming message. */
				status = (omapi_generic_new
					  (&p -> message -> object, MDL));
				if (status != ISC_R_SUCCESS) {
					omapi_disconnect (c, 1);
					return status;
				}
			}
			status = (omapi_set_value
				  ((omapi_object_t *)p -> message -> object,
				   p -> message -> id_object,
				   p -> name, p -> value));
		}
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect (c, 1);
			return status;
		}
		omapi_data_string_dereference (&p -> name, MDL);
		if (p -> value)
			omapi_typed_data_dereference (&p -> value, MDL);
		goto need_name_length;

	      signature_wait:
	      case omapi_protocol_signature_wait:
		if (p -> message -> id_object) {
			/* Compute the signature of the message. */
			signature = (omapi_value_t *)0;
			status = omapi_get_value_str (c, (omapi_object_t *)0,
						      "input-signature",
						      &signature);
			if (status != ISC_R_SUCCESS) {
				omapi_disconnect (c, 1);
				return status;
			}

			/* Disable the authentication key on the connection. */
			status = omapi_set_value_str (c, (omapi_object_t *)0,
						      "input-authenticator",
						      (omapi_typed_data_t *)0);
			if (status != ISC_R_SUCCESS) {
				omapi_value_dereference (&signature, MDL);
				omapi_disconnect (c, 1);
				return status;
			}
		}

		/* Read the authenticator. */
		status = omapi_typed_data_new (MDL,
					       &p -> message -> authenticator,
					       omapi_datatype_data,
					       p -> message -> authlen);
			
		if (status != ISC_R_SUCCESS) {
			omapi_value_dereference (&signature, MDL);
			omapi_disconnect (c, 1);
			return ISC_R_NOMEMORY;
		}
		omapi_connection_copyout
			(p -> message -> authenticator -> u.buffer.value, c,
			 p -> message -> authlen);

		/* Verify the signature. */
		if (p -> message -> id_object &&
		    ((signature -> value -> u.buffer.len !=
		      p -> message -> authlen) ||
		     (memcmp (signature -> value -> u.buffer.value,
			      p -> message -> authenticator -> u.buffer.value,
			      p -> message -> authlen) != 0))) {
			/* Invalid signature. */
			p -> verify_result = ISC_R_INVALIDKEY;
		}

		omapi_value_dereference (&signature, MDL);

		/* Process the message. */
	      message_done:
		if (p -> verify_result != ISC_R_SUCCESS) {
			status = omapi_protocol_send_status
				(h, (omapi_object_t *)0, p -> verify_result,
				 p -> message -> id, (char *)0);
		} else {
			status = omapi_message_process
				((omapi_object_t *)p -> message, h);
		}
		if (status != ISC_R_SUCCESS) {
			omapi_disconnect (c, 1);
			return ISC_R_NOMEMORY;
		}

		omapi_message_dereference (&p -> message, MDL);
#if defined (DEBUG_MEMORY_LEAKAGE)
		log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
			  dmalloc_generation,
			  dmalloc_outstanding - previous_outstanding,
			  dmalloc_outstanding, dmalloc_longterm, " long-term");
#endif
#if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
		dmalloc_dump_outstanding ();
#endif
#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
		dump_rc_history ();
#endif
#if defined (DEBUG_MEMORY_LEAKAGE)
		previous_outstanding = 0xDEADBEEF;
#endif
		/* Now wait for the next message. */
		goto to_header_wait;		

	      default:
		/* XXX should never get here.   Assertion? */
		break;
	}
	return ISC_R_SUCCESS;
}
Example #6
0
static isc_result_t omapi_connection_connect_internal (omapi_object_t *h)
{
	int error;
	omapi_connection_object_t *c;
	socklen_t sl;
	isc_result_t status;

	if (h -> type != omapi_type_connection)
		return DHCP_R_INVALIDARG;
	c = (omapi_connection_object_t *)h;

	if (c -> state == omapi_connection_connecting) {
		sl = sizeof error;
//ScenSim-Port//		if (getsockopt (c -> socket, SOL_SOCKET, SO_ERROR,
//ScenSim-Port//				(char *)&error, &sl) < 0) {
//ScenSim-Port//			omapi_disconnect (h, 1);
//ScenSim-Port//			return ISC_R_SUCCESS;
//ScenSim-Port//		}
		if (!error)
			c -> state = omapi_connection_connected;
	}
	if (c -> state == omapi_connection_connecting ||
	    c -> state == omapi_connection_unconnected) {
		if (c -> cptr >= c -> connect_list -> count) {
			switch (error) {
			      case ECONNREFUSED:
				status = ISC_R_CONNREFUSED;
				break;
			      case ENETUNREACH:
				status = ISC_R_NETUNREACH;
				break;
			      default:
				status = uerr2isc (error);
				break;
			}
			omapi_disconnect (h, 1);
			return status;
		}

		if (c -> connect_list -> addresses [c -> cptr].addrtype !=
		    AF_INET) {
			omapi_disconnect (h, 1);
			return DHCP_R_INVALIDARG;
		}

		memcpy (&c -> remote_addr.sin_addr,
			&c -> connect_list -> addresses [c -> cptr].address,
			sizeof c -> remote_addr.sin_addr);
		c -> remote_addr.sin_family = AF_INET;
		c -> remote_addr.sin_port =
		       htons (c -> connect_list -> addresses [c -> cptr].port);
//ScenSim-Port//#if defined (HAVE_SA_LEN)
//ScenSim-Port//		c -> remote_addr.sin_len = sizeof c -> remote_addr;
//ScenSim-Port//#endif
		memset (&c -> remote_addr.sin_zero, 0,
			sizeof c -> remote_addr.sin_zero);
		++c -> cptr;

//ScenSim-Port//		error = connect (c -> socket,
//ScenSim-Port//				 (struct sockaddr *)&c -> remote_addr,
//ScenSim-Port//				 sizeof c -> remote_addr);
		if (error < 0) {
			error = errno;
			if (error != EINPROGRESS) {
				omapi_disconnect (h, 1);
				switch (error) {
				      case ECONNREFUSED:
					status = ISC_R_CONNREFUSED;
					break;
				      case ENETUNREACH:
					status = ISC_R_NETUNREACH;
					break;
				      default:
					status = uerr2isc (error);
					break;
				}
				return status;
			}
			c -> state = omapi_connection_connecting;
			return DHCP_R_INCOMPLETE;
		}
		c -> state = omapi_connection_connected;
	}
	
	/* I don't know why this would fail, so I'm tempted not to test
	   the return value. */
	sl = sizeof (c -> local_addr);
//ScenSim-Port//	if (getsockname (c -> socket,
//ScenSim-Port//			 (struct sockaddr *)&c -> local_addr, &sl) < 0) {
//ScenSim-Port//	}

	/* Reregister with the I/O object.  If we don't already have an
	   I/O object this turns into a register call, otherwise we simply
	   modify the pointers in the I/O object. */

	status = omapi_reregister_io_object (h,
					     omapi_connection_readfd,
					     omapi_connection_writefd,
					     omapi_connection_reader,
					     omapi_connection_writer,
					     omapi_connection_reaper);

	if (status != ISC_R_SUCCESS) {
		omapi_disconnect (h, 1);
		return status;
	}

	omapi_signal_in (h, "connect");
	omapi_addr_list_dereference (&c -> connect_list, MDL);
	return ISC_R_INPROGRESS;
}