dhcpctl_status dhcpctl_set_data_value (dhcpctl_handle h, const char *value, unsigned len, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; unsigned ll; ll = strlen (value_name); status = omapi_data_string_new (&name, ll, MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, ll); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_data, len, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } memcpy (tv -> u.buffer.value, value, len); status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; }
isc_result_t omapi_object_update (omapi_object_t *obj, omapi_object_t *id, omapi_object_t *src, omapi_handle_t handle) { omapi_generic_object_t *gsrc; isc_result_t status=ISC_R_INVALIDARG; int i; if (!src) return ISC_R_INVALIDARG; if (src -> type != omapi_type_generic) return ISC_R_NOTIMPLEMENTED; gsrc = (omapi_generic_object_t *)src; for (i = 0; i < gsrc -> nvalues; i++) { status = omapi_set_value (obj, id, gsrc -> values [i] -> name, gsrc -> values [i] -> value); if (status != ISC_R_SUCCESS && status != ISC_R_UNCHANGED) return status; } if (handle) status=omapi_set_int_value (obj, id, "remote-handle", (int)handle); if(status!=ISC_R_SUCCESS){ log_error("omapi_set_int_value failed!\n"); } status = omapi_signal (obj, "updated"); if (status != ISC_R_NOTFOUND) return status; return ISC_R_SUCCESS; }
isc_result_t omapi_set_string_value (omapi_object_t *h, omapi_object_t *id, const char *name, const char *value) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *n = (omapi_data_string_t *)0; int len; int ip; status = omapi_data_string_new (&n, strlen (name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (n -> value, name, strlen (name)); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_string, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&n, MDL); return status; } status = omapi_set_value (h, id, n, tv); omapi_data_string_dereference (&n, MDL); omapi_typed_data_dereference (&tv, MDL); return status; }
isc_result_t omapi_object_update (omapi_object_t *obj, omapi_object_t *id, omapi_object_t *src, omapi_handle_t handle) { omapi_generic_object_t *gsrc; isc_result_t status; int i; if (!src) return DHCP_R_INVALIDARG; if (src -> type != omapi_type_generic) return ISC_R_NOTIMPLEMENTED; gsrc = (omapi_generic_object_t *)src; for (i = 0; i < gsrc -> nvalues; i++) { status = omapi_set_value (obj, id, gsrc -> values [i] -> name, gsrc -> values [i] -> value); if (status != ISC_R_SUCCESS && status != DHCP_R_UNCHANGED) return status; } /* * For now ignore the return value. I'm not sure if we want to * generate an error if we can't set the handle value. If we * do add a check we probably should allow unchanged and notfound */ if (handle) (void) omapi_set_int_value (obj, id, "remote-handle", (int)handle); status = omapi_signal (obj, "updated"); if (status != ISC_R_NOTFOUND) return status; return ISC_R_SUCCESS; }
dhcpctl_status dhcpctl_set_null_value (dhcpctl_handle h, const char *value_name) { isc_result_t status; omapi_data_string_t *name = (omapi_data_string_t *)0; unsigned ll; ll = strlen (value_name); status = omapi_data_string_new (&name, ll, MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, ll); status = omapi_set_value (h, (omapi_object_t *)0, name, (omapi_typed_data_t *)0); omapi_data_string_dereference (&name, MDL); return status; }
isc_result_t omapi_set_value_str (omapi_object_t *h, omapi_object_t *id, const char *name, omapi_typed_data_t *value) { omapi_data_string_t *nds; isc_result_t status; nds = (omapi_data_string_t *)0; status = omapi_data_string_new (&nds, strlen (name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (nds -> value, name, strlen (name)); status = omapi_set_value (h, id, nds, value); omapi_data_string_dereference (&nds, MDL); return status; }
dhcpctl_status dhcpctl_set_int_value (dhcpctl_handle h, int value, const char *value_name) { isc_result_t status; omapi_typed_data_t *tv = (omapi_typed_data_t *)0; omapi_data_string_t *name = (omapi_data_string_t *)0; status = omapi_data_string_new (&name, strlen (value_name), MDL); if (status != ISC_R_SUCCESS) return status; memcpy (name -> value, value_name, strlen (value_name)); status = omapi_typed_data_new (MDL, &tv, omapi_datatype_int, value); if (status != ISC_R_SUCCESS) { omapi_data_string_dereference (&name, MDL); return status; } status = omapi_set_value (h, (omapi_object_t *)0, name, tv); omapi_data_string_dereference (&name, MDL); omapi_typed_data_dereference (&tv, MDL); return status; }
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; }