]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* connection.c |
2 | ||
3 | Subroutines for dealing with connections. */ | |
4 | ||
5 | /* | |
edad9be5 | 6 | * Copyright (c) 2009-2014 by Internet Systems Consortium, Inc. ("ISC") |
23d39ae2 | 7 | * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC") |
98311e4b | 8 | * Copyright (c) 1999-2003 by Internet Software Consortium |
61b844bf | 9 | * |
98311e4b DH |
10 | * Permission to use, copy, modify, and distribute this software for any |
11 | * purpose with or without fee is hereby granted, provided that the above | |
12 | * copyright notice and this permission notice appear in all copies. | |
61b844bf | 13 | * |
98311e4b DH |
14 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES |
15 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR | |
17 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
19 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
20 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
61b844bf | 21 | * |
98311e4b DH |
22 | * Internet Systems Consortium, Inc. |
23 | * 950 Charter Street | |
24 | * Redwood City, CA 94063 | |
25 | * <info@isc.org> | |
2c85ac9b | 26 | * https://www.isc.org/ |
49733f31 | 27 | * |
61b844bf TL |
28 | */ |
29 | ||
fe5b0fdd DH |
30 | #include "dhcpd.h" |
31 | ||
6a4c4be8 | 32 | #include <omapip/omapip_p.h> |
d05243c1 | 33 | #include <arpa/inet.h> |
8c3c6552 | 34 | #include <arpa/nameser.h> |
fe5b0fdd | 35 | #include <errno.h> |
61b844bf | 36 | |
ef5cc183 TL |
37 | #if defined (TRACING) |
38 | static void trace_connect_input (trace_type_t *, unsigned, char *); | |
39 | static void trace_connect_stop (trace_type_t *); | |
40 | static void trace_disconnect_input (trace_type_t *, unsigned, char *); | |
41 | static void trace_disconnect_stop (trace_type_t *); | |
42 | trace_type_t *trace_connect; | |
43 | trace_type_t *trace_disconnect; | |
44 | extern omapi_array_t *trace_listeners; | |
45 | #endif | |
aaa98d8c | 46 | static isc_result_t omapi_connection_connect_internal (omapi_object_t *); |
ef5cc183 | 47 | |
20916cae TL |
48 | OMAPI_OBJECT_ALLOC (omapi_connection, |
49 | omapi_connection_object_t, omapi_type_connection) | |
50 | ||
61b844bf | 51 | isc_result_t omapi_connect (omapi_object_t *c, |
b1b7b521 | 52 | const char *server_name, |
d9eefc5d | 53 | unsigned port) |
61b844bf TL |
54 | { |
55 | struct hostent *he; | |
fc24e951 TL |
56 | unsigned i, hix; |
57 | omapi_addr_list_t *addrs = (omapi_addr_list_t *)0; | |
58 | struct in_addr foo; | |
59 | isc_result_t status; | |
60 | ||
e11a162f DN |
61 | #ifdef DEBUG_PROTOCOL |
62 | log_debug ("omapi_connect(%s, port=%d)", server_name, port); | |
63 | #endif | |
64 | ||
fc24e951 TL |
65 | if (!inet_aton (server_name, &foo)) { |
66 | /* If we didn't get a numeric address, try for a domain | |
67 | name. It's okay for this call to block. */ | |
68 | he = gethostbyname (server_name); | |
69 | if (!he) | |
98bf1607 | 70 | return DHCP_R_HOSTUNKNOWN; |
fc24e951 TL |
71 | for (i = 0; he -> h_addr_list [i]; i++) |
72 | ; | |
73 | if (i == 0) | |
98bf1607 | 74 | return DHCP_R_HOSTUNKNOWN; |
fc24e951 TL |
75 | hix = i; |
76 | ||
20916cae TL |
77 | status = omapi_addr_list_new (&addrs, hix, MDL); |
78 | if (status != ISC_R_SUCCESS) | |
79 | return status; | |
fc24e951 TL |
80 | for (i = 0; i < hix; i++) { |
81 | addrs -> addresses [i].addrtype = he -> h_addrtype; | |
82 | addrs -> addresses [i].addrlen = he -> h_length; | |
83 | memcpy (addrs -> addresses [i].address, | |
84 | he -> h_addr_list [i], | |
85 | (unsigned)he -> h_length); | |
86 | addrs -> addresses [i].port = port; | |
87 | } | |
88 | } else { | |
20916cae TL |
89 | status = omapi_addr_list_new (&addrs, 1, MDL); |
90 | if (status != ISC_R_SUCCESS) | |
91 | return status; | |
fc24e951 TL |
92 | addrs -> addresses [0].addrtype = AF_INET; |
93 | addrs -> addresses [0].addrlen = sizeof foo; | |
94 | memcpy (addrs -> addresses [0].address, &foo, sizeof foo); | |
95 | addrs -> addresses [0].port = port; | |
fc24e951 TL |
96 | } |
97 | status = omapi_connect_list (c, addrs, (omapi_addr_t *)0); | |
98 | omapi_addr_list_dereference (&addrs, MDL); | |
99 | return status; | |
100 | } | |
101 | ||
102 | isc_result_t omapi_connect_list (omapi_object_t *c, | |
103 | omapi_addr_list_t *remote_addrs, | |
104 | omapi_addr_t *local_addr) | |
105 | { | |
61b844bf TL |
106 | isc_result_t status; |
107 | omapi_connection_object_t *obj; | |
2f11d5e1 | 108 | int flag; |
fc24e951 | 109 | struct sockaddr_in local_sin; |
61b844bf | 110 | |
20916cae TL |
111 | obj = (omapi_connection_object_t *)0; |
112 | status = omapi_connection_allocate (&obj, MDL); | |
113 | if (status != ISC_R_SUCCESS) | |
114 | return status; | |
61b844bf TL |
115 | |
116 | status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj, | |
4bd8800e | 117 | MDL); |
61b844bf | 118 | if (status != ISC_R_SUCCESS) { |
20916cae | 119 | omapi_connection_dereference (&obj, MDL); |
61b844bf TL |
120 | return status; |
121 | } | |
4bd8800e | 122 | status = omapi_object_reference (&obj -> inner, c, MDL); |
61b844bf | 123 | if (status != ISC_R_SUCCESS) { |
20916cae | 124 | omapi_connection_dereference (&obj, MDL); |
61b844bf TL |
125 | return status; |
126 | } | |
127 | ||
3ce5a420 TL |
128 | /* Store the address list on the object. */ |
129 | omapi_addr_list_reference (&obj -> connect_list, remote_addrs, MDL); | |
130 | obj -> cptr = 0; | |
131 | obj -> state = omapi_connection_unconnected; | |
2f11d5e1 | 132 | |
3ce5a420 TL |
133 | #if defined (TRACING) |
134 | /* If we're playing back, don't actually try to connect - just leave | |
135 | the object available for a subsequent connect or disconnect. */ | |
136 | if (!trace_playback ()) { | |
137 | #endif | |
138 | /* Create a socket on which to communicate. */ | |
139 | obj -> socket = | |
140 | socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
141 | if (obj -> socket < 0) { | |
20916cae | 142 | omapi_connection_dereference (&obj, MDL); |
3ce5a420 TL |
143 | if (errno == EMFILE || errno == ENFILE |
144 | || errno == ENOBUFS) | |
145 | return ISC_R_NORESOURCES; | |
146 | return ISC_R_UNEXPECTED; | |
fc24e951 | 147 | } |
3ce5a420 TL |
148 | |
149 | /* Set up the local address, if any. */ | |
150 | if (local_addr) { | |
151 | /* Only do TCPv4 so far. */ | |
152 | if (local_addr -> addrtype != AF_INET) { | |
153 | omapi_connection_dereference (&obj, MDL); | |
98bf1607 | 154 | return DHCP_R_INVALIDARG; |
3ce5a420 TL |
155 | } |
156 | local_sin.sin_port = htons (local_addr -> port); | |
157 | memcpy (&local_sin.sin_addr, | |
158 | local_addr -> address, | |
159 | local_addr -> addrlen); | |
fc24e951 | 160 | #if defined (HAVE_SA_LEN) |
3ce5a420 | 161 | local_sin.sin_len = sizeof local_addr; |
fc24e951 | 162 | #endif |
3ce5a420 TL |
163 | local_sin.sin_family = AF_INET; |
164 | memset (&local_sin.sin_zero, 0, | |
165 | sizeof local_sin.sin_zero); | |
166 | ||
167 | if (bind (obj -> socket, (struct sockaddr *)&local_sin, | |
168 | sizeof local_sin) < 0) { | |
06eb8bab SK |
169 | omapi_connection_object_t **objp = &obj; |
170 | omapi_object_t **o = (omapi_object_t **)objp; | |
171 | omapi_object_dereference(o, MDL); | |
3ce5a420 TL |
172 | if (errno == EADDRINUSE) |
173 | return ISC_R_ADDRINUSE; | |
174 | if (errno == EADDRNOTAVAIL) | |
175 | return ISC_R_ADDRNOTAVAIL; | |
176 | if (errno == EACCES) | |
177 | return ISC_R_NOPERM; | |
178 | return ISC_R_UNEXPECTED; | |
179 | } | |
d758ad8c | 180 | obj -> local_addr = local_sin; |
fc24e951 | 181 | } |
fc24e951 | 182 | |
fe5b0fdd | 183 | #if defined(F_SETFD) |
3ce5a420 TL |
184 | if (fcntl (obj -> socket, F_SETFD, 1) < 0) { |
185 | close (obj -> socket); | |
186 | omapi_connection_dereference (&obj, MDL); | |
187 | return ISC_R_UNEXPECTED; | |
188 | } | |
892aa61a TL |
189 | #endif |
190 | ||
3ce5a420 TL |
191 | /* Set the SO_REUSEADDR flag (this should not fail). */ |
192 | flag = 1; | |
193 | if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR, | |
194 | (char *)&flag, sizeof flag) < 0) { | |
195 | omapi_connection_dereference (&obj, MDL); | |
196 | return ISC_R_UNEXPECTED; | |
197 | } | |
61b844bf | 198 | |
3ce5a420 TL |
199 | /* Set the file to nonblocking mode. */ |
200 | if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) { | |
201 | omapi_connection_dereference (&obj, MDL); | |
202 | return ISC_R_UNEXPECTED; | |
203 | } | |
61b844bf | 204 | |
3004baba SR |
205 | #ifdef SO_NOSIGPIPE |
206 | /* | |
207 | * If available stop the OS from killing our | |
208 | * program on a SIGPIPE failure | |
209 | */ | |
210 | flag = 1; | |
211 | if (setsockopt(obj->socket, SOL_SOCKET, SO_NOSIGPIPE, | |
212 | (char *)&flag, sizeof(flag)) < 0) { | |
213 | omapi_connection_dereference (&obj, MDL); | |
214 | return ISC_R_UNEXPECTED; | |
215 | } | |
216 | #endif | |
217 | ||
3ce5a420 TL |
218 | status = (omapi_register_io_object |
219 | ((omapi_object_t *)obj, | |
220 | 0, omapi_connection_writefd, | |
221 | 0, omapi_connection_connect, | |
222 | omapi_connection_reaper)); | |
223 | if (status != ISC_R_SUCCESS) | |
224 | goto out; | |
aaa98d8c TL |
225 | status = omapi_connection_connect_internal ((omapi_object_t *) |
226 | obj); | |
199f0b8a SR |
227 | /* |
228 | * inprogress is the same as success but used | |
229 | * to indicate to the dispatch code that we should | |
230 | * mark the socket as requiring more attention. | |
231 | * Routines calling this function should handle | |
232 | * success properly. | |
233 | */ | |
234 | if (status == ISC_R_INPROGRESS) { | |
235 | status = ISC_R_SUCCESS; | |
236 | } | |
3ce5a420 TL |
237 | #if defined (TRACING) |
238 | } | |
239 | omapi_connection_register (obj, MDL); | |
240 | #endif | |
61b844bf | 241 | |
67a291cf | 242 | out: |
20916cae | 243 | omapi_connection_dereference (&obj, MDL); |
fc24e951 | 244 | return status; |
61b844bf TL |
245 | } |
246 | ||
3ce5a420 | 247 | #if defined (TRACING) |
ef5cc183 | 248 | omapi_array_t *omapi_connections; |
3ce5a420 | 249 | |
a7394d15 | 250 | OMAPI_ARRAY_TYPE(omapi_connection, omapi_connection_object_t) |
3ce5a420 | 251 | |
ef5cc183 TL |
252 | void omapi_connection_trace_setup (void) { |
253 | trace_connect = trace_type_register ("connect", (void *)0, | |
254 | trace_connect_input, | |
255 | trace_connect_stop, MDL); | |
256 | trace_disconnect = trace_type_register ("disconnect", (void *)0, | |
257 | trace_disconnect_input, | |
258 | trace_disconnect_stop, MDL); | |
259 | } | |
260 | ||
3ce5a420 TL |
261 | void omapi_connection_register (omapi_connection_object_t *obj, |
262 | const char *file, int line) | |
263 | { | |
264 | isc_result_t status; | |
ef5cc183 TL |
265 | trace_iov_t iov [6]; |
266 | int iov_count = 0; | |
267 | int32_t connect_index, listener_index; | |
268 | static int32_t index; | |
3ce5a420 TL |
269 | |
270 | if (!omapi_connections) { | |
271 | status = omapi_connection_array_allocate (&omapi_connections, | |
272 | file, line); | |
273 | if (status != ISC_R_SUCCESS) | |
274 | return; | |
275 | } | |
276 | ||
ef5cc183 | 277 | status = omapi_connection_array_extend (omapi_connections, obj, |
2844788f | 278 | (int *)0, file, line); |
ef5cc183 TL |
279 | if (status != ISC_R_SUCCESS) { |
280 | obj -> index = -1; | |
281 | return; | |
282 | } | |
283 | ||
31bbee78 | 284 | #if defined (TRACING) |
ef5cc183 TL |
285 | if (trace_record ()) { |
286 | /* Connection registration packet: | |
287 | ||
288 | int32_t index | |
289 | int32_t listener_index [-1 means no listener] | |
290 | u_int16_t remote_port | |
291 | u_int16_t local_port | |
292 | u_int32_t remote_addr | |
293 | u_int32_t local_addr */ | |
294 | ||
295 | connect_index = htonl (index); | |
296 | index++; | |
297 | if (obj -> listener) | |
298 | listener_index = htonl (obj -> listener -> index); | |
299 | else | |
300 | listener_index = htonl (-1); | |
301 | iov [iov_count].buf = (char *)&connect_index; | |
302 | iov [iov_count++].len = sizeof connect_index; | |
303 | iov [iov_count].buf = (char *)&listener_index; | |
304 | iov [iov_count++].len = sizeof listener_index; | |
305 | iov [iov_count].buf = (char *)&obj -> remote_addr.sin_port; | |
306 | iov [iov_count++].len = sizeof obj -> remote_addr.sin_port; | |
307 | iov [iov_count].buf = (char *)&obj -> local_addr.sin_port; | |
308 | iov [iov_count++].len = sizeof obj -> local_addr.sin_port; | |
309 | iov [iov_count].buf = (char *)&obj -> remote_addr.sin_addr; | |
310 | iov [iov_count++].len = sizeof obj -> remote_addr.sin_addr; | |
311 | iov [iov_count].buf = (char *)&obj -> local_addr.sin_addr; | |
312 | iov [iov_count++].len = sizeof obj -> local_addr.sin_addr; | |
313 | ||
314 | status = trace_write_packet_iov (trace_connect, | |
315 | iov_count, iov, file, line); | |
316 | } | |
31bbee78 | 317 | #endif |
3ce5a420 | 318 | } |
ef5cc183 TL |
319 | |
320 | static void trace_connect_input (trace_type_t *ttype, | |
321 | unsigned length, char *buf) | |
322 | { | |
323 | struct sockaddr_in remote, local; | |
324 | int32_t connect_index, listener_index; | |
325 | char *s = buf; | |
326 | omapi_connection_object_t *obj; | |
327 | isc_result_t status; | |
d758ad8c | 328 | int i; |
ef5cc183 TL |
329 | |
330 | if (length != ((sizeof connect_index) + | |
331 | (sizeof remote.sin_port) + | |
332 | (sizeof remote.sin_addr)) * 2) { | |
333 | log_error ("Trace connect: invalid length %d", length); | |
334 | return; | |
335 | } | |
336 | ||
337 | memset (&remote, 0, sizeof remote); | |
338 | memset (&local, 0, sizeof local); | |
d758ad8c | 339 | memcpy (&connect_index, s, sizeof connect_index); |
ef5cc183 | 340 | s += sizeof connect_index; |
d758ad8c | 341 | memcpy (&listener_index, s, sizeof listener_index); |
ef5cc183 TL |
342 | s += sizeof listener_index; |
343 | memcpy (&remote.sin_port, s, sizeof remote.sin_port); | |
344 | s += sizeof remote.sin_port; | |
345 | memcpy (&local.sin_port, s, sizeof local.sin_port); | |
346 | s += sizeof local.sin_port; | |
347 | memcpy (&remote.sin_addr, s, sizeof remote.sin_addr); | |
348 | s += sizeof remote.sin_addr; | |
349 | memcpy (&local.sin_addr, s, sizeof local.sin_addr); | |
350 | s += sizeof local.sin_addr; | |
dc9d7b08 | 351 | POST(s); |
ef5cc183 TL |
352 | |
353 | connect_index = ntohl (connect_index); | |
354 | listener_index = ntohl (listener_index); | |
355 | ||
356 | /* If this was a connect to a listener, then we just slap together | |
357 | a new connection. */ | |
358 | if (listener_index != -1) { | |
359 | omapi_listener_object_t *listener; | |
360 | listener = (omapi_listener_object_t *)0; | |
361 | omapi_array_foreach_begin (trace_listeners, | |
362 | omapi_listener_object_t, lp) { | |
363 | if (lp -> address.sin_port == local.sin_port) { | |
364 | omapi_listener_reference (&listener, lp, MDL); | |
365 | omapi_listener_dereference (&lp, MDL); | |
366 | break; | |
d758ad8c | 367 | } |
ef5cc183 TL |
368 | } omapi_array_foreach_end (trace_listeners, |
369 | omapi_listener_object_t, lp); | |
370 | if (!listener) { | |
5f23e895 | 371 | log_error ("%s%ld, addr %s, port %d", |
ef5cc183 | 372 | "Spurious traced listener connect - index ", |
5f23e895 DN |
373 | (long int)listener_index, |
374 | inet_ntoa (local.sin_addr), | |
ef5cc183 TL |
375 | ntohs (local.sin_port)); |
376 | return; | |
377 | } | |
378 | obj = (omapi_connection_object_t *)0; | |
379 | status = omapi_listener_connect (&obj, listener, -1, &remote); | |
380 | if (status != ISC_R_SUCCESS) { | |
381 | log_error ("traced listener connect: %s", | |
382 | isc_result_totext (status)); | |
383 | } | |
384 | if (obj) | |
385 | omapi_connection_dereference (&obj, MDL); | |
386 | omapi_listener_dereference (&listener, MDL); | |
387 | return; | |
388 | } | |
389 | ||
390 | /* Find the matching connect object, if there is one. */ | |
391 | omapi_array_foreach_begin (omapi_connections, | |
392 | omapi_connection_object_t, lp) { | |
0f750c4f SR |
393 | for (i = 0; (lp->connect_list && |
394 | i < lp->connect_list->count); i++) { | |
d758ad8c | 395 | if (!memcmp (&remote.sin_addr, |
0f750c4f | 396 | &lp->connect_list->addresses[i].address, |
d758ad8c TL |
397 | sizeof remote.sin_addr) && |
398 | (ntohs (remote.sin_port) == | |
0f750c4f SR |
399 | lp->connect_list->addresses[i].port)) { |
400 | lp->state = omapi_connection_connected; | |
401 | lp->remote_addr = remote; | |
402 | lp->remote_addr.sin_family = AF_INET; | |
403 | omapi_addr_list_dereference(&lp->connect_list, MDL); | |
404 | lp->index = connect_index; | |
405 | status = omapi_signal_in((omapi_object_t *)lp, | |
406 | "connect"); | |
407 | omapi_connection_dereference (&lp, MDL); | |
408 | return; | |
409 | } | |
ef5cc183 TL |
410 | } |
411 | } omapi_array_foreach_end (omapi_connections, | |
412 | omapi_connection_object_t, lp); | |
413 | ||
5f23e895 DN |
414 | log_error ("Spurious traced connect - index %ld, addr %s, port %d", |
415 | (long int)connect_index, inet_ntoa (remote.sin_addr), | |
ef5cc183 TL |
416 | ntohs (remote.sin_port)); |
417 | return; | |
418 | } | |
419 | ||
420 | static void trace_connect_stop (trace_type_t *ttype) { } | |
421 | ||
422 | static void trace_disconnect_input (trace_type_t *ttype, | |
423 | unsigned length, char *buf) | |
424 | { | |
425 | int32_t *index; | |
426 | if (length != sizeof *index) { | |
427 | log_error ("trace disconnect: wrong length %d", length); | |
428 | return; | |
429 | } | |
430 | ||
431 | index = (int32_t *)buf; | |
432 | ||
433 | omapi_array_foreach_begin (omapi_connections, | |
434 | omapi_connection_object_t, lp) { | |
435 | if (lp -> index == ntohl (*index)) { | |
436 | omapi_disconnect ((omapi_object_t *)lp, 1); | |
437 | omapi_connection_dereference (&lp, MDL); | |
438 | return; | |
439 | } | |
440 | } omapi_array_foreach_end (omapi_connections, | |
441 | omapi_connection_object_t, lp); | |
442 | ||
5f23e895 DN |
443 | log_error ("trace disconnect: no connection matching index %ld", |
444 | (long int)ntohl (*index)); | |
ef5cc183 TL |
445 | } |
446 | ||
447 | static void trace_disconnect_stop (trace_type_t *ttype) { } | |
3ce5a420 TL |
448 | #endif |
449 | ||
61b844bf TL |
450 | /* Disconnect a connection object from the remote end. If force is nonzero, |
451 | close the connection immediately. Otherwise, shut down the receiving end | |
452 | but allow any unsent data to be sent before actually closing the socket. */ | |
453 | ||
454 | isc_result_t omapi_disconnect (omapi_object_t *h, | |
455 | int force) | |
456 | { | |
457 | omapi_connection_object_t *c; | |
458 | ||
e11a162f DN |
459 | #ifdef DEBUG_PROTOCOL |
460 | log_debug ("omapi_disconnect(%s)", force ? "force" : ""); | |
461 | #endif | |
462 | ||
61b844bf TL |
463 | c = (omapi_connection_object_t *)h; |
464 | if (c -> type != omapi_type_connection) | |
98bf1607 | 465 | return DHCP_R_INVALIDARG; |
61b844bf | 466 | |
ef5cc183 TL |
467 | #if defined (TRACING) |
468 | if (trace_record ()) { | |
66cebfcb | 469 | isc_result_t status; |
ef5cc183 TL |
470 | int32_t index; |
471 | ||
472 | index = htonl (c -> index); | |
473 | status = trace_write_packet (trace_disconnect, | |
474 | sizeof index, (char *)&index, | |
475 | MDL); | |
476 | if (status != ISC_R_SUCCESS) { | |
477 | trace_stop (); | |
478 | log_error ("trace_write_packet: %s", | |
479 | isc_result_totext (status)); | |
480 | } | |
481 | } | |
482 | if (!trace_playback ()) { | |
483 | #endif | |
484 | if (!force) { | |
485 | /* If we're already disconnecting, we don't have to do | |
486 | anything. */ | |
487 | if (c -> state == omapi_connection_disconnecting) | |
61b844bf | 488 | return ISC_R_SUCCESS; |
ef5cc183 TL |
489 | |
490 | /* Try to shut down the socket - this sends a FIN to | |
491 | the remote end, so that it won't send us any more | |
492 | data. If the shutdown succeeds, and we still | |
493 | have bytes left to write, defer closing the socket | |
494 | until that's done. */ | |
495 | if (!shutdown (c -> socket, SHUT_RD)) { | |
496 | if (c -> out_bytes > 0) { | |
497 | c -> state = | |
498 | omapi_connection_disconnecting; | |
499 | return ISC_R_SUCCESS; | |
500 | } | |
61b844bf TL |
501 | } |
502 | } | |
ef5cc183 TL |
503 | close (c -> socket); |
504 | #if defined (TRACING) | |
61b844bf | 505 | } |
ef5cc183 | 506 | #endif |
61b844bf TL |
507 | c -> state = omapi_connection_closed; |
508 | ||
98bf1607 SR |
509 | #if 0 |
510 | /* | |
511 | * Disconnecting from the I/O object seems incorrect as it doesn't | |
512 | * cause the I/O object to be cleaned and released. Previous to | |
513 | * using the isc socket library this wouldn't have caused a problem | |
514 | * with the socket library we would have a reference to a closed | |
515 | * socket. Instead we now do an unregister to properly free the | |
516 | * I/O object. | |
517 | */ | |
518 | ||
61b844bf | 519 | /* Disconnect from I/O object, if any. */ |
ee3aeca6 TL |
520 | if (h -> outer) { |
521 | if (h -> outer -> inner) | |
522 | omapi_object_dereference (&h -> outer -> inner, MDL); | |
4bd8800e | 523 | omapi_object_dereference (&h -> outer, MDL); |
ee3aeca6 | 524 | } |
98bf1607 SR |
525 | #else |
526 | if (h->outer) { | |
527 | omapi_unregister_io_object(h); | |
528 | } | |
529 | #endif | |
61b844bf TL |
530 | |
531 | /* If whatever created us registered a signal handler, send it | |
532 | a disconnect signal. */ | |
533 | omapi_signal (h, "disconnect", h); | |
4619c0a2 DH |
534 | |
535 | /* Disconnect from protocol object, if any. */ | |
536 | if (h->inner != NULL) { | |
537 | if (h->inner->outer != NULL) { | |
538 | omapi_object_dereference(&h->inner->outer, MDL); | |
539 | } | |
540 | omapi_object_dereference(&h->inner, MDL); | |
541 | } | |
542 | ||
543 | /* XXX: the code to free buffers should be in the dereference | |
544 | function, but there is no special-purpose function to | |
545 | dereference connections, so these just get leaked */ | |
546 | /* Free any buffers */ | |
547 | if (c->inbufs != NULL) { | |
548 | omapi_buffer_dereference(&c->inbufs, MDL); | |
549 | } | |
550 | c->in_bytes = 0; | |
551 | if (c->outbufs != NULL) { | |
552 | omapi_buffer_dereference(&c->outbufs, MDL); | |
553 | } | |
554 | c->out_bytes = 0; | |
555 | ||
61b844bf TL |
556 | return ISC_R_SUCCESS; |
557 | } | |
558 | ||
b1b7b521 | 559 | isc_result_t omapi_connection_require (omapi_object_t *h, unsigned bytes) |
61b844bf TL |
560 | { |
561 | omapi_connection_object_t *c; | |
562 | ||
563 | if (h -> type != omapi_type_connection) | |
98bf1607 | 564 | return DHCP_R_INVALIDARG; |
61b844bf TL |
565 | c = (omapi_connection_object_t *)h; |
566 | ||
567 | c -> bytes_needed = bytes; | |
568 | if (c -> bytes_needed <= c -> in_bytes) { | |
569 | return ISC_R_SUCCESS; | |
570 | } | |
98bf1607 | 571 | return DHCP_R_NOTYET; |
61b844bf TL |
572 | } |
573 | ||
574 | /* Return the socket on which the dispatcher should wait for readiness | |
98bf1607 | 575 | to read, for a connection object. */ |
61b844bf TL |
576 | int omapi_connection_readfd (omapi_object_t *h) |
577 | { | |
578 | omapi_connection_object_t *c; | |
579 | if (h -> type != omapi_type_connection) | |
580 | return -1; | |
581 | c = (omapi_connection_object_t *)h; | |
582 | if (c -> state != omapi_connection_connected) | |
583 | return -1; | |
61b844bf TL |
584 | return c -> socket; |
585 | } | |
586 | ||
98bf1607 SR |
587 | /* |
588 | * Return the socket on which the dispatcher should wait for readiness | |
589 | * to write, for a connection object. When bytes are buffered we should | |
590 | * also poke the dispatcher to tell it to start or re-start watching the | |
591 | * socket. | |
592 | */ | |
61b844bf TL |
593 | int omapi_connection_writefd (omapi_object_t *h) |
594 | { | |
595 | omapi_connection_object_t *c; | |
596 | if (h -> type != omapi_type_connection) | |
597 | return -1; | |
2f11d5e1 | 598 | c = (omapi_connection_object_t *)h; |
98bf1607 | 599 | return c->socket; |
61b844bf TL |
600 | } |
601 | ||
fc24e951 | 602 | isc_result_t omapi_connection_connect (omapi_object_t *h) |
aaa98d8c TL |
603 | { |
604 | isc_result_t status; | |
605 | ||
8fa0112d | 606 | /* |
23d39ae2 SR |
607 | * We use the INPROGRESS status to indicate that |
608 | * we want more from the socket. In this case we | |
609 | * have now connected and are trying to write to | |
610 | * the socket for the first time. For the signaling | |
611 | * code this is the same as a SUCCESS so we don't | |
612 | * pass it on as a signal. | |
8fa0112d | 613 | */ |
23d39ae2 | 614 | status = omapi_connection_connect_internal (h); |
8fa0112d SR |
615 | if (status == ISC_R_INPROGRESS) |
616 | return ISC_R_INPROGRESS; | |
617 | ||
23d39ae2 SR |
618 | if (status != ISC_R_SUCCESS) |
619 | omapi_signal (h, "status", status); | |
620 | ||
aaa98d8c TL |
621 | return ISC_R_SUCCESS; |
622 | } | |
623 | ||
624 | static isc_result_t omapi_connection_connect_internal (omapi_object_t *h) | |
fc24e951 | 625 | { |
0f750c4f | 626 | int error = 0; |
fc24e951 | 627 | omapi_connection_object_t *c; |
fe5b0fdd | 628 | socklen_t sl; |
fc24e951 TL |
629 | isc_result_t status; |
630 | ||
631 | if (h -> type != omapi_type_connection) | |
98bf1607 | 632 | return DHCP_R_INVALIDARG; |
fc24e951 TL |
633 | c = (omapi_connection_object_t *)h; |
634 | ||
635 | if (c -> state == omapi_connection_connecting) { | |
636 | sl = sizeof error; | |
637 | if (getsockopt (c -> socket, SOL_SOCKET, SO_ERROR, | |
165bce70 | 638 | (char *)&error, &sl) < 0) { |
fc24e951 TL |
639 | omapi_disconnect (h, 1); |
640 | return ISC_R_SUCCESS; | |
641 | } | |
d86ec998 | 642 | if (!error) |
fc24e951 TL |
643 | c -> state = omapi_connection_connected; |
644 | } | |
645 | if (c -> state == omapi_connection_connecting || | |
646 | c -> state == omapi_connection_unconnected) { | |
647 | if (c -> cptr >= c -> connect_list -> count) { | |
aaa98d8c TL |
648 | switch (error) { |
649 | case ECONNREFUSED: | |
650 | status = ISC_R_CONNREFUSED; | |
651 | break; | |
652 | case ENETUNREACH: | |
653 | status = ISC_R_NETUNREACH; | |
654 | break; | |
655 | default: | |
656 | status = uerr2isc (error); | |
657 | break; | |
658 | } | |
fc24e951 | 659 | omapi_disconnect (h, 1); |
aaa98d8c | 660 | return status; |
fc24e951 TL |
661 | } |
662 | ||
663 | if (c -> connect_list -> addresses [c -> cptr].addrtype != | |
664 | AF_INET) { | |
665 | omapi_disconnect (h, 1); | |
98bf1607 | 666 | return DHCP_R_INVALIDARG; |
fc24e951 TL |
667 | } |
668 | ||
669 | memcpy (&c -> remote_addr.sin_addr, | |
670 | &c -> connect_list -> addresses [c -> cptr].address, | |
671 | sizeof c -> remote_addr.sin_addr); | |
672 | c -> remote_addr.sin_family = AF_INET; | |
673 | c -> remote_addr.sin_port = | |
674 | htons (c -> connect_list -> addresses [c -> cptr].port); | |
675 | #if defined (HAVE_SA_LEN) | |
676 | c -> remote_addr.sin_len = sizeof c -> remote_addr; | |
677 | #endif | |
678 | memset (&c -> remote_addr.sin_zero, 0, | |
679 | sizeof c -> remote_addr.sin_zero); | |
680 | ++c -> cptr; | |
681 | ||
d86ec998 TL |
682 | error = connect (c -> socket, |
683 | (struct sockaddr *)&c -> remote_addr, | |
684 | sizeof c -> remote_addr); | |
685 | if (error < 0) { | |
686 | error = errno; | |
687 | if (error != EINPROGRESS) { | |
fc24e951 | 688 | omapi_disconnect (h, 1); |
67a291cf TL |
689 | switch (error) { |
690 | case ECONNREFUSED: | |
691 | status = ISC_R_CONNREFUSED; | |
692 | break; | |
693 | case ENETUNREACH: | |
694 | status = ISC_R_NETUNREACH; | |
695 | break; | |
696 | default: | |
aaa98d8c | 697 | status = uerr2isc (error); |
67a291cf TL |
698 | break; |
699 | } | |
700 | return status; | |
fc24e951 TL |
701 | } |
702 | c -> state = omapi_connection_connecting; | |
98bf1607 | 703 | return DHCP_R_INCOMPLETE; |
fc24e951 TL |
704 | } |
705 | c -> state = omapi_connection_connected; | |
706 | } | |
707 | ||
708 | /* I don't know why this would fail, so I'm tempted not to test | |
709 | the return value. */ | |
710 | sl = sizeof (c -> local_addr); | |
711 | if (getsockname (c -> socket, | |
712 | (struct sockaddr *)&c -> local_addr, &sl) < 0) { | |
713 | } | |
714 | ||
0493fdca SR |
715 | /* Reregister with the I/O object. If we don't already have an |
716 | I/O object this turns into a register call, otherwise we simply | |
717 | modify the pointers in the I/O object. */ | |
718 | ||
719 | status = omapi_reregister_io_object (h, | |
720 | omapi_connection_readfd, | |
721 | omapi_connection_writefd, | |
722 | omapi_connection_reader, | |
723 | omapi_connection_writer, | |
724 | omapi_connection_reaper); | |
fc24e951 TL |
725 | |
726 | if (status != ISC_R_SUCCESS) { | |
727 | omapi_disconnect (h, 1); | |
728 | return status; | |
729 | } | |
730 | ||
731 | omapi_signal_in (h, "connect"); | |
732 | omapi_addr_list_dereference (&c -> connect_list, MDL); | |
8fa0112d | 733 | return ISC_R_INPROGRESS; |
fc24e951 TL |
734 | } |
735 | ||
61b844bf TL |
736 | /* Reaper function for connection - if the connection is completely closed, |
737 | reap it. If it's in the disconnecting state, there were bytes left | |
738 | to write when the user closed it, so if there are now no bytes left to | |
739 | write, we can close it. */ | |
740 | isc_result_t omapi_connection_reaper (omapi_object_t *h) | |
741 | { | |
742 | omapi_connection_object_t *c; | |
743 | ||
744 | if (h -> type != omapi_type_connection) | |
98bf1607 | 745 | return DHCP_R_INVALIDARG; |
61b844bf TL |
746 | |
747 | c = (omapi_connection_object_t *)h; | |
748 | if (c -> state == omapi_connection_disconnecting && | |
e11a162f DN |
749 | c -> out_bytes == 0) { |
750 | #ifdef DEBUG_PROTOCOL | |
751 | log_debug ("omapi_connection_reaper(): disconnect"); | |
752 | #endif | |
61b844bf | 753 | omapi_disconnect (h, 1); |
e11a162f DN |
754 | } |
755 | if (c -> state == omapi_connection_closed) { | |
756 | #ifdef DEBUG_PROTOCOL | |
757 | log_debug ("omapi_connection_reaper(): closed"); | |
758 | #endif | |
61b844bf | 759 | return ISC_R_NOTCONNECTED; |
e11a162f | 760 | } |
61b844bf TL |
761 | return ISC_R_SUCCESS; |
762 | } | |
763 | ||
98bf1607 | 764 | static isc_result_t make_dst_key (dst_key_t **dst_key, omapi_object_t *a) { |
49146f3c DN |
765 | omapi_value_t *name = (omapi_value_t *)0; |
766 | omapi_value_t *algorithm = (omapi_value_t *)0; | |
767 | omapi_value_t *key = (omapi_value_t *)0; | |
98311e4b | 768 | char *name_str = NULL; |
49146f3c DN |
769 | isc_result_t status = ISC_R_SUCCESS; |
770 | ||
771 | if (status == ISC_R_SUCCESS) | |
772 | status = omapi_get_value_str | |
773 | (a, (omapi_object_t *)0, "name", &name); | |
774 | ||
775 | if (status == ISC_R_SUCCESS) | |
776 | status = omapi_get_value_str | |
777 | (a, (omapi_object_t *)0, "algorithm", &algorithm); | |
778 | ||
779 | if (status == ISC_R_SUCCESS) | |
780 | status = omapi_get_value_str | |
781 | (a, (omapi_object_t *)0, "key", &key); | |
782 | ||
783 | if (status == ISC_R_SUCCESS) { | |
98bf1607 SR |
784 | if ((algorithm->value->type != omapi_datatype_data && |
785 | algorithm->value->type != omapi_datatype_string) || | |
786 | strncasecmp((char *)algorithm->value->u.buffer.value, | |
787 | NS_TSIG_ALG_HMAC_MD5 ".", | |
788 | algorithm->value->u.buffer.len) != 0) { | |
789 | status = DHCP_R_INVALIDARG; | |
49146f3c DN |
790 | } |
791 | } | |
792 | ||
793 | if (status == ISC_R_SUCCESS) { | |
794 | name_str = dmalloc (name -> value -> u.buffer.len + 1, MDL); | |
795 | if (!name_str) | |
796 | status = ISC_R_NOMEMORY; | |
797 | } | |
798 | ||
799 | if (status == ISC_R_SUCCESS) { | |
800 | memcpy (name_str, | |
801 | name -> value -> u.buffer.value, | |
802 | name -> value -> u.buffer.len); | |
803 | name_str [name -> value -> u.buffer.len] = 0; | |
804 | ||
98bf1607 SR |
805 | status = isclib_make_dst_key(name_str, |
806 | DHCP_HMAC_MD5_NAME, | |
807 | key->value->u.buffer.value, | |
808 | key->value->u.buffer.len, | |
809 | dst_key); | |
810 | ||
811 | if (*dst_key == NULL) | |
49146f3c DN |
812 | status = ISC_R_NOMEMORY; |
813 | } | |
814 | ||
815 | if (name_str) | |
816 | dfree (name_str, MDL); | |
817 | if (key) | |
818 | omapi_value_dereference (&key, MDL); | |
819 | if (algorithm) | |
820 | omapi_value_dereference (&algorithm, MDL); | |
821 | if (name) | |
822 | omapi_value_dereference (&name, MDL); | |
823 | ||
824 | return status; | |
825 | } | |
826 | ||
827 | isc_result_t omapi_connection_sign_data (int mode, | |
98bf1607 | 828 | dst_key_t *key, |
49146f3c | 829 | void **context, |
4b63c26e | 830 | const unsigned char *data, |
49146f3c DN |
831 | const unsigned len, |
832 | omapi_typed_data_t **result) | |
833 | { | |
834 | omapi_typed_data_t *td = (omapi_typed_data_t *)0; | |
835 | isc_result_t status; | |
98bf1607 | 836 | dst_context_t **dctx = (dst_context_t **)context; |
49146f3c | 837 | |
98bf1607 SR |
838 | /* Create the context for the dst module */ |
839 | if (mode & SIG_MODE_INIT) { | |
840 | status = dst_context_create(key, dhcp_gbl_ctx.mctx, dctx); | |
841 | if (status != ISC_R_SUCCESS) { | |
842 | return status; | |
843 | } | |
844 | } | |
845 | ||
846 | /* If we have any data add it to the context */ | |
847 | if (len != 0) { | |
848 | isc_region_t region; | |
849 | region.base = (unsigned char *)data; | |
850 | region.length = len; | |
851 | dst_context_adddata(*dctx, ®ion); | |
852 | } | |
853 | ||
854 | /* Finish the signature and clean up the context */ | |
49146f3c | 855 | if (mode & SIG_MODE_FINAL) { |
98bf1607 SR |
856 | unsigned int sigsize; |
857 | isc_buffer_t sigbuf; | |
858 | ||
859 | status = dst_key_sigsize(key, &sigsize); | |
860 | if (status != ISC_R_SUCCESS) { | |
861 | goto cleanup; | |
862 | } | |
863 | ||
49146f3c DN |
864 | status = omapi_typed_data_new (MDL, &td, |
865 | omapi_datatype_data, | |
98bf1607 SR |
866 | sigsize); |
867 | if (status != ISC_R_SUCCESS) { | |
868 | goto cleanup; | |
869 | } | |
49146f3c | 870 | |
98bf1607 SR |
871 | isc_buffer_init(&sigbuf, td->u.buffer.value, td->u.buffer.len); |
872 | status = dst_context_sign(*dctx, &sigbuf); | |
873 | if (status != ISC_R_SUCCESS) { | |
874 | goto cleanup; | |
875 | } | |
49146f3c | 876 | |
98bf1607 SR |
877 | if (result) { |
878 | omapi_typed_data_reference (result, td, MDL); | |
879 | } | |
49146f3c | 880 | |
98bf1607 SR |
881 | cleanup: |
882 | /* We are done with the context and the td. On success | |
883 | * the td is now referenced from result, on failure we | |
884 | * don't need it any more */ | |
885 | if (td) { | |
49146f3c | 886 | omapi_typed_data_dereference (&td, MDL); |
98bf1607 SR |
887 | } |
888 | dst_context_destroy(dctx); | |
889 | return status; | |
49146f3c DN |
890 | } |
891 | ||
49146f3c DN |
892 | return ISC_R_SUCCESS; |
893 | } | |
894 | ||
895 | isc_result_t omapi_connection_output_auth_length (omapi_object_t *h, | |
896 | unsigned *l) | |
897 | { | |
898 | omapi_connection_object_t *c; | |
899 | ||
98bf1607 SR |
900 | if (h->type != omapi_type_connection) |
901 | return DHCP_R_INVALIDARG; | |
49146f3c DN |
902 | c = (omapi_connection_object_t *)h; |
903 | ||
98bf1607 | 904 | if (c->out_key == NULL) |
49146f3c DN |
905 | return ISC_R_NOTFOUND; |
906 | ||
98bf1607 | 907 | return(dst_key_sigsize(c->out_key, l)); |
49146f3c DN |
908 | } |
909 | ||
61b844bf TL |
910 | isc_result_t omapi_connection_set_value (omapi_object_t *h, |
911 | omapi_object_t *id, | |
912 | omapi_data_string_t *name, | |
913 | omapi_typed_data_t *value) | |
914 | { | |
49146f3c DN |
915 | omapi_connection_object_t *c; |
916 | isc_result_t status; | |
917 | ||
61b844bf | 918 | if (h -> type != omapi_type_connection) |
98bf1607 | 919 | return DHCP_R_INVALIDARG; |
49146f3c DN |
920 | c = (omapi_connection_object_t *)h; |
921 | ||
922 | if (omapi_ds_strcmp (name, "input-authenticator") == 0) { | |
923 | if (value && value -> type != omapi_datatype_object) | |
98bf1607 | 924 | return DHCP_R_INVALIDARG; |
49146f3c DN |
925 | |
926 | if (c -> in_context) { | |
927 | omapi_connection_sign_data (SIG_MODE_FINAL, | |
928 | c -> in_key, | |
929 | &c -> in_context, | |
930 | 0, 0, | |
931 | (omapi_typed_data_t **) 0); | |
932 | } | |
933 | ||
98bf1607 SR |
934 | if (c->in_key != NULL) { |
935 | dst_key_free(&c->in_key); | |
49146f3c DN |
936 | } |
937 | ||
938 | if (value) { | |
939 | status = make_dst_key (&c -> in_key, | |
940 | value -> u.object); | |
941 | if (status != ISC_R_SUCCESS) | |
942 | return status; | |
943 | } | |
944 | ||
945 | return ISC_R_SUCCESS; | |
946 | } | |
947 | else if (omapi_ds_strcmp (name, "output-authenticator") == 0) { | |
948 | if (value && value -> type != omapi_datatype_object) | |
98bf1607 | 949 | return DHCP_R_INVALIDARG; |
49146f3c DN |
950 | |
951 | if (c -> out_context) { | |
952 | omapi_connection_sign_data (SIG_MODE_FINAL, | |
953 | c -> out_key, | |
954 | &c -> out_context, | |
955 | 0, 0, | |
956 | (omapi_typed_data_t **) 0); | |
957 | } | |
958 | ||
98bf1607 SR |
959 | if (c->out_key != NULL) { |
960 | dst_key_free(&c->out_key); | |
49146f3c DN |
961 | } |
962 | ||
963 | if (value) { | |
964 | status = make_dst_key (&c -> out_key, | |
965 | value -> u.object); | |
966 | if (status != ISC_R_SUCCESS) | |
967 | return status; | |
968 | } | |
969 | ||
970 | return ISC_R_SUCCESS; | |
971 | } | |
61b844bf TL |
972 | |
973 | if (h -> inner && h -> inner -> type -> set_value) | |
974 | return (*(h -> inner -> type -> set_value)) | |
975 | (h -> inner, id, name, value); | |
976 | return ISC_R_NOTFOUND; | |
977 | } | |
978 | ||
979 | isc_result_t omapi_connection_get_value (omapi_object_t *h, | |
980 | omapi_object_t *id, | |
981 | omapi_data_string_t *name, | |
982 | omapi_value_t **value) | |
983 | { | |
49146f3c DN |
984 | omapi_connection_object_t *c; |
985 | omapi_typed_data_t *td = (omapi_typed_data_t *)0; | |
986 | isc_result_t status; | |
98bf1607 | 987 | unsigned int sigsize; |
49146f3c | 988 | |
61b844bf | 989 | if (h -> type != omapi_type_connection) |
98bf1607 | 990 | return DHCP_R_INVALIDARG; |
49146f3c DN |
991 | c = (omapi_connection_object_t *)h; |
992 | ||
993 | if (omapi_ds_strcmp (name, "input-signature") == 0) { | |
994 | if (!c -> in_key || !c -> in_context) | |
995 | return ISC_R_NOTFOUND; | |
996 | ||
997 | status = omapi_connection_sign_data (SIG_MODE_FINAL, | |
998 | c -> in_key, | |
999 | &c -> in_context, | |
1000 | 0, 0, &td); | |
1001 | if (status != ISC_R_SUCCESS) | |
1002 | return status; | |
1003 | ||
1004 | status = omapi_make_value (value, name, td, MDL); | |
1005 | omapi_typed_data_dereference (&td, MDL); | |
1006 | return status; | |
1007 | ||
1008 | } else if (omapi_ds_strcmp (name, "input-signature-size") == 0) { | |
98bf1607 | 1009 | if (c->in_key == NULL) |
49146f3c DN |
1010 | return ISC_R_NOTFOUND; |
1011 | ||
98bf1607 SR |
1012 | status = dst_key_sigsize(c->in_key, &sigsize); |
1013 | if (status != ISC_R_SUCCESS) { | |
1014 | return(status); | |
1015 | } | |
1016 | ||
1017 | return omapi_make_int_value(value, name, sigsize, MDL); | |
49146f3c DN |
1018 | |
1019 | } else if (omapi_ds_strcmp (name, "output-signature") == 0) { | |
1020 | if (!c -> out_key || !c -> out_context) | |
1021 | return ISC_R_NOTFOUND; | |
1022 | ||
1023 | status = omapi_connection_sign_data (SIG_MODE_FINAL, | |
1024 | c -> out_key, | |
1025 | &c -> out_context, | |
1026 | 0, 0, &td); | |
1027 | if (status != ISC_R_SUCCESS) | |
1028 | return status; | |
1029 | ||
1030 | status = omapi_make_value (value, name, td, MDL); | |
1031 | omapi_typed_data_dereference (&td, MDL); | |
1032 | return status; | |
1033 | ||
1034 | } else if (omapi_ds_strcmp (name, "output-signature-size") == 0) { | |
98bf1607 | 1035 | if (c->out_key == NULL) |
49146f3c DN |
1036 | return ISC_R_NOTFOUND; |
1037 | ||
98bf1607 SR |
1038 | |
1039 | status = dst_key_sigsize(c->out_key, &sigsize); | |
1040 | if (status != ISC_R_SUCCESS) { | |
1041 | return(status); | |
1042 | } | |
1043 | ||
1044 | return omapi_make_int_value(value, name, sigsize, MDL); | |
49146f3c | 1045 | } |
61b844bf TL |
1046 | |
1047 | if (h -> inner && h -> inner -> type -> get_value) | |
1048 | return (*(h -> inner -> type -> get_value)) | |
1049 | (h -> inner, id, name, value); | |
1050 | return ISC_R_NOTFOUND; | |
1051 | } | |
1052 | ||
4bd8800e TL |
1053 | isc_result_t omapi_connection_destroy (omapi_object_t *h, |
1054 | const char *file, int line) | |
61b844bf TL |
1055 | { |
1056 | omapi_connection_object_t *c; | |
1057 | ||
e11a162f DN |
1058 | #ifdef DEBUG_PROTOCOL |
1059 | log_debug ("omapi_connection_destroy()"); | |
1060 | #endif | |
1061 | ||
61b844bf TL |
1062 | if (h -> type != omapi_type_connection) |
1063 | return ISC_R_UNEXPECTED; | |
1064 | c = (omapi_connection_object_t *)(h); | |
1065 | if (c -> state == omapi_connection_connected) | |
1066 | omapi_disconnect (h, 1); | |
1067 | if (c -> listener) | |
20916cae | 1068 | omapi_listener_dereference (&c -> listener, file, line); |
fc24e951 TL |
1069 | if (c -> connect_list) |
1070 | omapi_addr_list_dereference (&c -> connect_list, file, line); | |
61b844bf TL |
1071 | return ISC_R_SUCCESS; |
1072 | } | |
1073 | ||
1074 | isc_result_t omapi_connection_signal_handler (omapi_object_t *h, | |
b1b7b521 | 1075 | const char *name, va_list ap) |
61b844bf TL |
1076 | { |
1077 | if (h -> type != omapi_type_connection) | |
98bf1607 | 1078 | return DHCP_R_INVALIDARG; |
e11a162f DN |
1079 | |
1080 | #ifdef DEBUG_PROTOCOL | |
1081 | log_debug ("omapi_connection_signal_handler(%s)", name); | |
1082 | #endif | |
61b844bf TL |
1083 | |
1084 | if (h -> inner && h -> inner -> type -> signal_handler) | |
1085 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
1086 | name, ap); | |
1087 | return ISC_R_NOTFOUND; | |
1088 | } | |
1089 | ||
1090 | /* Write all the published values associated with the object through the | |
1091 | specified connection. */ | |
1092 | ||
1093 | isc_result_t omapi_connection_stuff_values (omapi_object_t *c, | |
1094 | omapi_object_t *id, | |
1095 | omapi_object_t *m) | |
1096 | { | |
61b844bf | 1097 | if (m -> type != omapi_type_connection) |
98bf1607 | 1098 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1099 | |
1100 | if (m -> inner && m -> inner -> type -> stuff_values) | |
1101 | return (*(m -> inner -> type -> stuff_values)) (c, id, | |
1102 | m -> inner); | |
1103 | return ISC_R_SUCCESS; | |
1104 | } |