3 Subroutines that support the generic listener object. */
6 * Copyright (c) 1999-2000 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
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''.
44 #include <omapip/omapip_p.h>
46 OMAPI_OBJECT_ALLOC (omapi_listener
,
47 omapi_listener_object_t
, omapi_type_listener
)
49 isc_result_t
omapi_listen (omapi_object_t
*h
,
54 addr
.addrtype
= AF_INET
;
55 addr
.addrlen
= sizeof (struct in_addr
);
56 memset (addr
.address
, 0, sizeof addr
.address
); /* INADDR_ANY */
59 return omapi_listen_addr (h
, &addr
, max
);
62 isc_result_t
omapi_listen_addr (omapi_object_t
*h
,
69 omapi_listener_object_t
*obj
;
74 obj
= (omapi_listener_object_t
*)0;
75 status
= omapi_listener_allocate (&obj
, MDL
);
76 if (status
!= ISC_R_SUCCESS
)
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
);
86 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
87 if (status
!= ISC_R_SUCCESS
) {
88 omapi_listener_dereference (&obj
, MDL
);
92 /* Currently only support TCPv4 addresses. */
93 if (addr
-> addrtype
!= AF_INET
)
94 return ISC_R_INVALIDARG
;
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
);
104 obj
-> address
.sin_family
= AF_INET
;
105 memset (&(obj
-> address
.sin_zero
), 0,
106 sizeof obj
-> address
.sin_zero
);
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
;
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
;
125 /* Try to bind to the wildcard address using the port number
127 i
= bind (obj
-> socket
,
128 (struct sockaddr
*)&obj
-> address
, sizeof obj
-> address
);
130 omapi_listener_dereference (&obj
, MDL
);
131 if (errno
== EADDRINUSE
)
132 return ISC_R_ADDRNOTAVAIL
;
135 return ISC_R_UNEXPECTED
;
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
;
144 if (fcntl (obj
-> socket
, F_SETFL
, O_NONBLOCK
) < 0) {
145 omapi_listener_dereference (&obj
, MDL
);
146 return ISC_R_UNEXPECTED
;
149 status
= omapi_register_io_object ((omapi_object_t
*)obj
,
150 omapi_listener_readfd
, 0,
152 omapi_listener_dereference (&obj
, MDL
);
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
)
160 omapi_listener_object_t
*l
;
162 if (h
-> type
!= omapi_type_listener
)
164 l
= (omapi_listener_object_t
*)h
;
169 /* Reader callback for a listener object. Accept an incoming connection. */
170 isc_result_t
omapi_accept (omapi_object_t
*h
)
174 omapi_connection_object_t
*obj
;
175 omapi_listener_object_t
*listener
;
178 if (h
-> type
!= omapi_type_listener
)
179 return ISC_R_INVALIDARG
;
180 listener
= (omapi_listener_object_t
*)h
;
182 /* Get the handle. */
183 obj
= (omapi_connection_object_t
*)0;
184 status
= omapi_connection_allocate (&obj
, MDL
);
185 if (status
!= ISC_R_SUCCESS
)
188 /* Accept the connection. */
189 len
= sizeof obj
-> remote_addr
;
191 accept (listener
-> socket
,
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
;
201 obj
-> state
= omapi_connection_connected
;
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
);
214 omapi_listener_reference (&obj
-> listener
, listener
, MDL
);
216 status
= omapi_signal (h
, "connect", obj
);
218 /* Lose our reference to the connection, so it'll be gc'd when it's
220 omapi_connection_dereference (&obj
, MDL
);
224 isc_result_t
omapi_listener_set_value (omapi_object_t
*h
,
226 omapi_data_string_t
*name
,
227 omapi_typed_data_t
*value
)
229 if (h
-> type
!= omapi_type_listener
)
230 return ISC_R_INVALIDARG
;
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
;
238 isc_result_t
omapi_listener_get_value (omapi_object_t
*h
,
240 omapi_data_string_t
*name
,
241 omapi_value_t
**value
)
243 if (h
-> type
!= omapi_type_listener
)
244 return ISC_R_INVALIDARG
;
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
;
252 isc_result_t
omapi_listener_destroy (omapi_object_t
*h
,
253 const char *file
, int line
)
255 omapi_listener_object_t
*l
;
257 if (h
-> type
!= omapi_type_listener
)
258 return ISC_R_INVALIDARG
;
259 l
= (omapi_listener_object_t
*)h
;
261 if (l
-> socket
!= -1) {
265 return ISC_R_SUCCESS
;
268 isc_result_t
omapi_listener_signal_handler (omapi_object_t
*h
,
269 const char *name
, va_list ap
)
271 if (h
-> type
!= omapi_type_listener
)
272 return ISC_R_INVALIDARG
;
274 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
275 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
277 return ISC_R_NOTFOUND
;
280 /* Write all the published values associated with the object through the
281 specified connection. */
283 isc_result_t
omapi_listener_stuff_values (omapi_object_t
*c
,
289 if (l
-> type
!= omapi_type_listener
)
290 return ISC_R_INVALIDARG
;
292 if (l
-> inner
&& l
-> inner
-> type
-> stuff_values
)
293 return (*(l
-> inner
-> type
-> stuff_values
)) (c
, id
,
295 return ISC_R_SUCCESS
;