xref: /netbsd-src/external/mpl/dhcp/dist/dhcpctl/remote.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
1 /*	$NetBSD: remote.c,v 1.3 2022/04/03 01:10:58 christos Exp $	*/
2 
3 /* remote.c
4 
5    The dhcpctl remote object. */
6 
7 /*
8  * Copyright (C) 2004-2022 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  *   PO Box 360
25  *   Newmarket, NH 03857 USA
26  *   <info@isc.org>
27  *   https://www.isc.org/
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: remote.c,v 1.3 2022/04/03 01:10:58 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 
dhcpctl_new_authenticator(dhcpctl_handle * h,const char * name,const char * algorithm,const unsigned char * secret,unsigned secret_len)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 
dhcpctl_new_object(dhcpctl_handle * h,dhcpctl_handle connection,const char * object_type)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 
dhcpctl_open_object(dhcpctl_handle h,dhcpctl_handle connection,int flags)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 
dhcpctl_remote_set_value(omapi_object_t * h,omapi_object_t * id,omapi_data_string_t * name,omapi_typed_data_t * value)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 
dhcpctl_remote_get_value(omapi_object_t * h,omapi_object_t * id,omapi_data_string_t * name,omapi_value_t ** value)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 
dhcpctl_remote_signal_handler(omapi_object_t * o,const char * name,va_list ap)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 
dhcpctl_remote_destroy(omapi_object_t * h,const char * file,int line)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 
dhcpctl_remote_stuff_values(omapi_object_t * c,omapi_object_t * id,omapi_object_t * p)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