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_get_value_str (omapi_object_t *h, omapi_object_t *id, const char *name, omapi_value_t **value) { omapi_object_t *outer; 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)); for (outer = h; outer -> outer; outer = outer -> outer) ; if (outer -> type -> get_value) status = (*(outer -> type -> get_value)) (outer, id, nds, value); else status = ISC_R_NOTFOUND; omapi_data_string_dereference (&nds, MDL); return status; }
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; }
dhcpctl_status dhcpctl_get_value (dhcpctl_data_string *result, dhcpctl_handle h, const char *value_name) { isc_result_t status; omapi_value_t *tv = (omapi_value_t *)0; omapi_data_string_t *value = (omapi_data_string_t *)0; unsigned len; int ip; status = omapi_get_value_str (h, (omapi_object_t *)0, value_name, &tv); if (status != ISC_R_SUCCESS) return status; switch (tv -> value -> type) { case omapi_datatype_int: len = sizeof (int); break; case omapi_datatype_string: case omapi_datatype_data: len = tv -> value -> u.buffer.len; break; case omapi_datatype_object: len = sizeof (omapi_handle_t); break; default: omapi_typed_data_dereference (&tv -> value, MDL); return ISC_R_UNEXPECTED; } status = omapi_data_string_new (result, len, MDL); if (status != ISC_R_SUCCESS) { omapi_typed_data_dereference (&tv -> value, MDL); return status; } switch (tv -> value -> type) { case omapi_datatype_int: ip = htonl (tv -> value -> u.integer); memcpy ((*result) -> value, &ip, sizeof ip); break; case omapi_datatype_string: case omapi_datatype_data: memcpy ((*result) -> value, tv -> value -> u.buffer.value, tv -> value -> u.buffer.len); break; case omapi_datatype_object: ip = htonl (tv -> value -> u.object -> handle); memcpy ((*result) -> value, &ip, sizeof ip); break; } omapi_value_dereference (&tv, MDL); return ISC_R_SUCCESS; }
dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h, const char *name, const char *algorithm, const unsigned char *secret, unsigned secret_len) { struct auth_key *key = (struct auth_key *)0; isc_result_t status; status = omapi_auth_key_new (&key, MDL); if (status != ISC_R_SUCCESS) return status; key -> name = dmalloc (strlen (name) + 1, MDL); if (!key -> name) { omapi_auth_key_dereference (&key, MDL); return ISC_R_NOMEMORY; } strcpy (key -> name, name); /* If the algorithm name isn't an FQDN, tack on the .SIG-ALG.REG.NET. domain. */ if (strchr (algorithm, '.') == 0) { static char add[] = ".SIG-ALG.REG.INT."; key -> algorithm = dmalloc (strlen (algorithm) + sizeof (add), MDL); if (!key -> algorithm) { omapi_auth_key_dereference (&key, MDL); return ISC_R_NOMEMORY; } strcpy (key -> algorithm, algorithm); strcat (key -> algorithm, add); } else { key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL); if (!key -> algorithm) { omapi_auth_key_dereference (&key, MDL); return ISC_R_NOMEMORY; } strcpy (key -> algorithm, algorithm); } status = omapi_data_string_new (&key -> key, secret_len, MDL); if (status != ISC_R_SUCCESS) { omapi_auth_key_dereference (&key, MDL); return status; } memcpy (key -> key -> value, secret, secret_len); key -> key -> len = secret_len; *h = (dhcpctl_handle) key; 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; }
/* valspec is a string of form "var=value" * Return values: 0 - parse error -1 - error setting value 1 - OK */ int setvalue(dhcpctl_handle *p_obj, dhcpctl_data_string *p_val, char *valspec){ char *var, *val; isc_result_t status; dhcpctl_handle object; dhcpctl_data_string value; omprop setproperty; omstate setstate; struct in_addr convaddr; char hwaddr[6]; int i; uint32_t hostint,netint; struct tm timestruct; time_t timeval; object=*p_obj; value=*p_val; var=valspec; val=index(valspec,'='); if (val == NULL) return 0; *val++='\0'; setproperty=stringtoprop(var); switch(setproperty){ case op_ipaddr: if (inet_pton(AF_INET, val, &convaddr)<=0) return 0; omapi_data_string_new(&value, 4, MDL); memcpy(value->value, &convaddr.s_addr,4); break; case op_hwaddr: if (strlen(val) != 17) return 0; for (i=0; i < 17; i+=3){ if (i != 15 && val[i+2] != ':') return 0; val[i+2]='\0'; hwaddr[i/3]=(char)strtol(&val[i], NULL, 16); } omapi_data_string_new(&value, 6, MDL); memcpy(value->value, hwaddr, 6); break; case op_hwtype: hostint=atol(val); netint=htonl(hostint); omapi_data_string_new(&value, sizeof netint, MDL); memcpy(value->value, &netint, sizeof netint); break; case op_state: setstate=stringtostate(val); netint=htonl((unsigned long)setstate); omapi_data_string_new(&value, sizeof netint, MDL); memcpy(value->value, &netint, sizeof netint); break; case op_ends: case op_tstp: case op_tsfp: case op_cltt: strptime(val, "%a %b %d %T %Y", ×truct); timeval=mktime(×truct); netint=htonl((unsigned long)timeval); omapi_data_string_new(&value, 4, MDL); memcpy(value->value, &netint, 4); break; case op_name: case op_client_hostname: case op_statements: case op_group: i=strlen(val); omapi_data_string_new(&value, i, MDL); memcpy(value->value, val, i); break; default: return 0; } /* end of switch */ status=dhcpctl_set_value(object, value, var); if (status != ISC_R_SUCCESS){ dhcpctl_data_string_dereference(&value, MDL); return -1; } return 1; }
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; }