1 /* $NetBSD: remote.c,v 1.2 2018/04/07 22:37:29 christos Exp $ */ 2 3 /* remote.c 4 5 The dhcpctl remote object. */ 6 7 /* 8 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC") 9 * Copyright (c) 1999-2003 by Internet Software Consortium 10 * 11 * This Source Code Form is subject to the terms of the Mozilla Public 12 * License, v. 2.0. If a copy of the MPL was not distributed with this 13 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 * Internet Systems Consortium, Inc. 24 * 950 Charter Street 25 * Redwood City, CA 94063 26 * <info@isc.org> 27 * https://www.isc.org/ 28 * 29 */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: remote.c,v 1.2 2018/04/07 22:37:29 christos Exp $"); 33 34 #include "dhcpd.h" 35 #include <omapip/omapip_p.h> 36 #include "dhcpctl.h" 37 38 /* dhcpctl_new_authenticator 39 40 synchronous - creates an authenticator object. 41 returns nonzero status code if the object couldn't be created 42 stores handle to authenticator through h if successful, and returns zero. 43 name is the authenticator name (NUL-terminated string). 44 algorithm is the NUL-terminated string name of the algorithm to use 45 (currently, only "hmac-md5" is supported). 46 secret and secret_len is the key secret. */ 47 48 dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h, 49 const char *name, 50 const char *algorithm, 51 const unsigned char *secret, 52 unsigned secret_len) 53 { 54 struct auth_key *key = (struct auth_key *)0; 55 isc_result_t status; 56 57 status = omapi_auth_key_new (&key, MDL); 58 if (status != ISC_R_SUCCESS) 59 return status; 60 61 key -> name = dmalloc (strlen (name) + 1, MDL); 62 if (!key -> name) { 63 omapi_auth_key_dereference (&key, MDL); 64 return ISC_R_NOMEMORY; 65 } 66 strcpy (key -> name, name); 67 68 /* If the algorithm name isn't an FQDN, tack on the 69 .SIG-ALG.REG.NET. domain. */ 70 if (strchr (algorithm, '.') == 0) { 71 static char add[] = ".SIG-ALG.REG.INT."; 72 key -> algorithm = dmalloc (strlen (algorithm) + 73 sizeof (add), MDL); 74 if (!key -> algorithm) { 75 omapi_auth_key_dereference (&key, MDL); 76 return ISC_R_NOMEMORY; 77 } 78 strcpy (key -> algorithm, algorithm); 79 strcat (key -> algorithm, add); 80 } else { 81 key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL); 82 if (!key -> algorithm) { 83 omapi_auth_key_dereference (&key, MDL); 84 return ISC_R_NOMEMORY; 85 } 86 strcpy (key -> algorithm, algorithm); 87 } 88 89 status = omapi_data_string_new (&key -> key, secret_len, MDL); 90 if (status != ISC_R_SUCCESS) { 91 omapi_auth_key_dereference (&key, MDL); 92 return status; 93 } 94 memcpy (key -> key -> value, secret, secret_len); 95 key -> key -> len = secret_len; 96 97 *h = (dhcpctl_handle) key; 98 return ISC_R_SUCCESS; 99 } 100 101 102 /* dhcpctl_new_object 103 104 synchronous - creates a local handle for a host entry. 105 returns nonzero status code if the local host entry couldn't 106 be created 107 stores handle to host through h if successful, and returns zero. 108 object_type is a pointer to a NUL-terminated string containing 109 the ascii name of the type of object being accessed - e.g., "host" */ 110 111 dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h, 112 dhcpctl_handle connection, 113 const char *object_type) 114 { 115 dhcpctl_remote_object_t *m; 116 omapi_object_t *g; 117 isc_result_t status; 118 119 m = (dhcpctl_remote_object_t *)0; 120 status = omapi_object_allocate((omapi_object_t **)&m, 121 dhcpctl_remote_type, 0, MDL); 122 if (status != ISC_R_SUCCESS) 123 return status; 124 125 g = (omapi_object_t *)0; 126 status = omapi_generic_new (&g, MDL); 127 if (status != ISC_R_SUCCESS) { 128 dfree (m, MDL); 129 return status; 130 } 131 status = omapi_object_reference (&m -> inner, g, MDL); 132 if (status != ISC_R_SUCCESS) { 133 omapi_object_dereference ((omapi_object_t **)&m, MDL); 134 omapi_object_dereference (&g, MDL); 135 return status; 136 } 137 status = omapi_object_reference (&g -> outer, 138 (omapi_object_t *)m, MDL); 139 140 if (status != ISC_R_SUCCESS) { 141 omapi_object_dereference ((omapi_object_t **)&m, MDL); 142 omapi_object_dereference (&g, MDL); 143 return status; 144 } 145 146 status = omapi_typed_data_new (MDL, &m -> rtype, 147 omapi_datatype_string, 148 object_type); 149 if (status != ISC_R_SUCCESS) { 150 omapi_object_dereference ((omapi_object_t **)&m, MDL); 151 omapi_object_dereference (&g, MDL); 152 return status; 153 } 154 155 status = omapi_object_reference (h, (omapi_object_t *)m, MDL); 156 omapi_object_dereference ((omapi_object_t **)&m, MDL); 157 omapi_object_dereference (&g, MDL); 158 if (status != ISC_R_SUCCESS) 159 return status; 160 161 return status; 162 } 163 164 /* asynchronous - just queues the request 165 returns nonzero status code if open couldn't be queued 166 returns zero if open was queued 167 h is a handle to an object created by dhcpctl_new_object 168 connection is a connection to a DHCP server 169 flags include: 170 DHCPCTL_CREATE - if the object doesn't exist, create it 171 DHCPCTL_UPDATE - update the object on the server using the 172 attached parameters 173 DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE 174 was also specified */ 175 176 dhcpctl_status dhcpctl_open_object (dhcpctl_handle h, 177 dhcpctl_handle connection, 178 int flags) 179 { 180 isc_result_t status; 181 omapi_object_t *message = (omapi_object_t *)0; 182 dhcpctl_remote_object_t *remote; 183 184 if (h -> type != dhcpctl_remote_type) 185 return DHCP_R_INVALIDARG; 186 remote = (dhcpctl_remote_object_t *)h; 187 188 status = omapi_message_new (&message, MDL); 189 if (status != ISC_R_SUCCESS) 190 return status; 191 status = omapi_set_int_value (message, (omapi_object_t *)0, 192 "op", OMAPI_OP_OPEN); 193 if (status != ISC_R_SUCCESS) { 194 omapi_object_dereference (&message, MDL); 195 return status; 196 } 197 status = omapi_set_object_value (message, (omapi_object_t *)0, 198 "object", h); 199 if (status != ISC_R_SUCCESS) { 200 omapi_object_dereference (&message, MDL); 201 return status; 202 } 203 if (flags & DHCPCTL_CREATE) { 204 status = omapi_set_boolean_value (message, (omapi_object_t *)0, 205 "create", 1); 206 if (status != ISC_R_SUCCESS) { 207 omapi_object_dereference (&message, MDL); 208 return status; 209 } 210 } 211 if (flags & DHCPCTL_UPDATE) { 212 status = omapi_set_boolean_value (message, (omapi_object_t *)0, 213 "update", 1); 214 if (status != ISC_R_SUCCESS) { 215 omapi_object_dereference (&message, MDL); 216 return status; 217 } 218 } 219 if (flags & DHCPCTL_EXCL) { 220 status = omapi_set_boolean_value (message, (omapi_object_t *)0, 221 "exclusive", 1); 222 if (status != ISC_R_SUCCESS) { 223 omapi_object_dereference (&message, MDL); 224 return status; 225 } 226 } 227 228 if (remote -> rtype) { 229 status = omapi_set_value_str (message, (omapi_object_t *)0, 230 "type", remote -> rtype); 231 if (status != ISC_R_SUCCESS) { 232 omapi_object_dereference (&message, MDL); 233 return status; 234 } 235 } 236 237 status = omapi_message_register (message); 238 if (status != ISC_R_SUCCESS) { 239 omapi_object_dereference (&message, MDL); 240 return status; 241 } 242 243 status = omapi_protocol_send_message (connection -> outer, 244 (omapi_object_t *)0, 245 message, (omapi_object_t *)0); 246 247 if (status != ISC_R_SUCCESS) 248 omapi_message_unregister (message); 249 250 omapi_object_dereference (&message, MDL); 251 return status; 252 } 253 254 /* Callback methods (not meant to be called directly) */ 255 256 isc_result_t dhcpctl_remote_set_value (omapi_object_t *h, 257 omapi_object_t *id, 258 omapi_data_string_t *name, 259 omapi_typed_data_t *value) 260 { 261 dhcpctl_remote_object_t *ro; 262 unsigned long rh; 263 isc_result_t status; 264 265 if (h -> type != dhcpctl_remote_type) 266 return DHCP_R_INVALIDARG; 267 ro = (dhcpctl_remote_object_t *)h; 268 269 if (!omapi_ds_strcmp (name, "remote-handle")) { 270 status = omapi_get_int_value (&rh, value); 271 if (status == ISC_R_SUCCESS) 272 ro -> remote_handle = rh; 273 return status; 274 } 275 276 if (h -> inner && h -> inner -> type -> set_value) 277 return (*(h -> inner -> type -> set_value)) 278 (h -> inner, id, name, value); 279 return ISC_R_NOTFOUND; 280 } 281 282 isc_result_t dhcpctl_remote_get_value (omapi_object_t *h, 283 omapi_object_t *id, 284 omapi_data_string_t *name, 285 omapi_value_t **value) 286 { 287 if (h -> type != dhcpctl_remote_type) 288 return DHCP_R_INVALIDARG; 289 290 if (h -> inner && h -> inner -> type -> get_value) 291 return (*(h -> inner -> type -> get_value)) 292 (h -> inner, id, name, value); 293 return ISC_R_NOTFOUND; 294 } 295 296 isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *o, 297 const char *name, va_list ap) 298 { 299 dhcpctl_remote_object_t *p; 300 omapi_typed_data_t *tv; 301 302 if (o -> type != dhcpctl_remote_type) 303 return DHCP_R_INVALIDARG; 304 p = (dhcpctl_remote_object_t *)o; 305 306 if (!strcmp (name, "updated")) { 307 p -> waitstatus = ISC_R_SUCCESS; 308 if (o -> inner -> type == omapi_type_generic) 309 omapi_generic_clear_flags (o -> inner); 310 return omapi_signal_in (o -> inner, "ready"); 311 } 312 if (!strcmp (name, "status")) { 313 p -> waitstatus = va_arg (ap, isc_result_t); 314 if (p -> message) 315 omapi_typed_data_dereference (&p -> message, MDL); 316 tv = va_arg (ap, omapi_typed_data_t *); 317 if (tv) 318 omapi_typed_data_reference (&p -> message, tv, MDL); 319 return omapi_signal_in (o -> inner, "ready"); 320 } 321 322 if (p -> inner && p -> inner -> type -> signal_handler) 323 return (*(p -> inner -> type -> signal_handler)) 324 (p -> inner, name, ap); 325 326 return ISC_R_SUCCESS; 327 } 328 329 isc_result_t dhcpctl_remote_destroy (omapi_object_t *h, 330 const char *file, int line) 331 { 332 dhcpctl_remote_object_t *p; 333 if (h -> type != dhcpctl_remote_type) 334 return DHCP_R_INVALIDARG; 335 p = (dhcpctl_remote_object_t *)h; 336 if (p -> handle) 337 omapi_object_dereference ((omapi_object_t **)&p -> handle, 338 file, line); 339 if (p -> rtype) 340 omapi_typed_data_dereference ((omapi_typed_data_t **)&p->rtype, 341 file, line); 342 return ISC_R_SUCCESS; 343 } 344 345 /* Write all the published values associated with the object through the 346 specified connection. */ 347 348 isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *c, 349 omapi_object_t *id, 350 omapi_object_t *p) 351 { 352 if (p -> type != dhcpctl_remote_type) 353 return DHCP_R_INVALIDARG; 354 355 if (p -> inner && p -> inner -> type -> stuff_values) 356 return (*(p -> inner -> type -> stuff_values)) (c, id, 357 p -> inner); 358 return ISC_R_SUCCESS; 359 } 360 361