]> git.ipfire.org Git - thirdparty/dhcp.git/blob - omapip/listener.c
- Fix all the OMAPI objects in the DHCP server and client that weren't
[thirdparty/dhcp.git] / omapip / listener.c
1 /* listener.c
2
3 Subroutines that support the generic listener object. */
4
5 /*
6 * Copyright (c) 1999-2000 Internet Software Consortium.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
42 */
43
44 #include <omapip/omapip_p.h>
45
46 OMAPI_OBJECT_ALLOC (omapi_listener,
47 omapi_listener_object_t, omapi_type_listener)
48
49 isc_result_t omapi_listen (omapi_object_t *h,
50 unsigned port,
51 int max)
52 {
53 omapi_addr_t addr;
54 addr.addrtype = AF_INET;
55 addr.addrlen = sizeof (struct in_addr);
56 memset (addr.address, 0, sizeof addr.address); /* INADDR_ANY */
57 addr.port = port;
58
59 return omapi_listen_addr (h, &addr, max);
60 }
61
62 isc_result_t omapi_listen_addr (omapi_object_t *h,
63 omapi_addr_t *addr,
64 int max)
65 {
66 struct hostent *he;
67 int hix;
68 isc_result_t status;
69 omapi_listener_object_t *obj;
70 int i;
71 struct in_addr ia;
72
73 /* Get the handle. */
74 obj = (omapi_listener_object_t *)0;
75 status = omapi_listener_allocate (&obj, MDL);
76 if (status != ISC_R_SUCCESS)
77 return status;
78
79 /* Connect this object to the inner object. */
80 status = omapi_object_reference (&h -> outer,
81 (omapi_object_t *)obj, MDL);
82 if (status != ISC_R_SUCCESS) {
83 omapi_listener_dereference (&obj, MDL);
84 return status;
85 }
86 status = omapi_object_reference (&obj -> inner, h, MDL);
87 if (status != ISC_R_SUCCESS) {
88 omapi_listener_dereference (&obj, MDL);
89 return status;
90 }
91
92 /* Currently only support TCPv4 addresses. */
93 if (addr -> addrtype != AF_INET)
94 return ISC_R_INVALIDARG;
95
96 /* Set up the address on which we will listen... */
97 obj -> address.sin_port = htons (addr -> port);
98 memcpy (&obj -> address.sin_addr,
99 addr -> address, sizeof obj -> address.sin_addr);
100 #if defined (HAVE_SA_LEN)
101 obj -> address.sin_len =
102 sizeof (struct sockaddr_in);
103 #endif
104 obj -> address.sin_family = AF_INET;
105 memset (&(obj -> address.sin_zero), 0,
106 sizeof obj -> address.sin_zero);
107
108 /* Create a socket on which to listen. */
109 obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
110 if (!obj -> socket) {
111 omapi_listener_dereference (&obj, MDL);
112 if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
113 return ISC_R_NORESOURCES;
114 return ISC_R_UNEXPECTED;
115 }
116
117 #if defined (HAVE_SETFD)
118 if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
119 close (obj -> socket);
120 omapi_listener_dereference (&obj, MDL);
121 return ISC_R_UNEXPECTED;
122 }
123 #endif
124
125 /* Try to bind to the wildcard address using the port number
126 we were given. */
127 i = bind (obj -> socket,
128 (struct sockaddr *)&obj -> address, sizeof obj -> address);
129 if (i < 0) {
130 omapi_listener_dereference (&obj, MDL);
131 if (errno == EADDRINUSE)
132 return ISC_R_ADDRNOTAVAIL;
133 if (errno == EPERM)
134 return ISC_R_NOPERM;
135 return ISC_R_UNEXPECTED;
136 }
137
138 /* Now tell the kernel to listen for connections. */
139 if (listen (obj -> socket, max)) {
140 omapi_listener_dereference (&obj, MDL);
141 return ISC_R_UNEXPECTED;
142 }
143
144 if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
145 omapi_listener_dereference (&obj, MDL);
146 return ISC_R_UNEXPECTED;
147 }
148
149 status = omapi_register_io_object ((omapi_object_t *)obj,
150 omapi_listener_readfd, 0,
151 omapi_accept, 0, 0);
152 omapi_listener_dereference (&obj, MDL);
153 return status;
154 }
155
156 /* Return the socket on which the dispatcher should wait for readiness
157 to read, for a listener object. */
158 int omapi_listener_readfd (omapi_object_t *h)
159 {
160 omapi_listener_object_t *l;
161
162 if (h -> type != omapi_type_listener)
163 return -1;
164 l = (omapi_listener_object_t *)h;
165
166 return l -> socket;
167 }
168
169 /* Reader callback for a listener object. Accept an incoming connection. */
170 isc_result_t omapi_accept (omapi_object_t *h)
171 {
172 isc_result_t status;
173 SOCKLEN_T len;
174 omapi_connection_object_t *obj;
175 omapi_listener_object_t *listener;
176 int i;
177
178 if (h -> type != omapi_type_listener)
179 return ISC_R_INVALIDARG;
180 listener = (omapi_listener_object_t *)h;
181
182 /* Get the handle. */
183 obj = (omapi_connection_object_t *)0;
184 status = omapi_connection_allocate (&obj, MDL);
185 if (status != ISC_R_SUCCESS)
186 return status;
187
188 /* Accept the connection. */
189 len = sizeof obj -> remote_addr;
190 obj -> socket =
191 accept (listener -> socket,
192 ((struct sockaddr *)
193 &(obj -> remote_addr)), &len);
194 if (obj -> socket < 0) {
195 omapi_connection_dereference (&obj, MDL);
196 if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
197 return ISC_R_NORESOURCES;
198 return ISC_R_UNEXPECTED;
199 }
200
201 obj -> state = omapi_connection_connected;
202
203 status = omapi_register_io_object ((omapi_object_t *)obj,
204 omapi_connection_readfd,
205 omapi_connection_writefd,
206 omapi_connection_reader,
207 omapi_connection_writer,
208 omapi_connection_reaper);
209 if (status != ISC_R_SUCCESS) {
210 omapi_connection_dereference (&obj, MDL);
211 return status;
212 }
213
214 omapi_listener_reference (&obj -> listener, listener, MDL);
215
216 status = omapi_signal (h, "connect", obj);
217
218 /* Lose our reference to the connection, so it'll be gc'd when it's
219 reaped. */
220 omapi_connection_dereference (&obj, MDL);
221 return status;
222 }
223
224 isc_result_t omapi_listener_set_value (omapi_object_t *h,
225 omapi_object_t *id,
226 omapi_data_string_t *name,
227 omapi_typed_data_t *value)
228 {
229 if (h -> type != omapi_type_listener)
230 return ISC_R_INVALIDARG;
231
232 if (h -> inner && h -> inner -> type -> set_value)
233 return (*(h -> inner -> type -> set_value))
234 (h -> inner, id, name, value);
235 return ISC_R_NOTFOUND;
236 }
237
238 isc_result_t omapi_listener_get_value (omapi_object_t *h,
239 omapi_object_t *id,
240 omapi_data_string_t *name,
241 omapi_value_t **value)
242 {
243 if (h -> type != omapi_type_listener)
244 return ISC_R_INVALIDARG;
245
246 if (h -> inner && h -> inner -> type -> get_value)
247 return (*(h -> inner -> type -> get_value))
248 (h -> inner, id, name, value);
249 return ISC_R_NOTFOUND;
250 }
251
252 isc_result_t omapi_listener_destroy (omapi_object_t *h,
253 const char *file, int line)
254 {
255 omapi_listener_object_t *l;
256
257 if (h -> type != omapi_type_listener)
258 return ISC_R_INVALIDARG;
259 l = (omapi_listener_object_t *)h;
260
261 if (l -> socket != -1) {
262 close (l -> socket);
263 l -> socket = -1;
264 }
265 return ISC_R_SUCCESS;
266 }
267
268 isc_result_t omapi_listener_signal_handler (omapi_object_t *h,
269 const char *name, va_list ap)
270 {
271 if (h -> type != omapi_type_listener)
272 return ISC_R_INVALIDARG;
273
274 if (h -> inner && h -> inner -> type -> signal_handler)
275 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
276 name, ap);
277 return ISC_R_NOTFOUND;
278 }
279
280 /* Write all the published values associated with the object through the
281 specified connection. */
282
283 isc_result_t omapi_listener_stuff_values (omapi_object_t *c,
284 omapi_object_t *id,
285 omapi_object_t *l)
286 {
287 int i;
288
289 if (l -> type != omapi_type_listener)
290 return ISC_R_INVALIDARG;
291
292 if (l -> inner && l -> inner -> type -> stuff_values)
293 return (*(l -> inner -> type -> stuff_values)) (c, id,
294 l -> inner);
295 return ISC_R_SUCCESS;
296 }
297