2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-24 02:47:42 +00:00
isc-dhcp/omapip/listener.c

277 lines
8.2 KiB
C
Raw Normal View History

1999-09-02 00:32:56 +00:00
/* listener.c
Subroutines that support the generic listener object. */
/*
2000-03-17 04:00:32 +00:00
* Copyright (c) 1999-2000 Internet Software Consortium.
* All rights reserved.
1999-09-02 00:32:56 +00:00
*
2000-03-17 04:00:32 +00:00
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
1999-09-02 00:32:56 +00:00
*
2000-03-17 04:00:32 +00:00
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of The Internet Software Consortium nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
1999-09-02 00:32:56 +00:00
*
2000-03-17 04:00:32 +00:00
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This software has been written for the Internet Software Consortium
* by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
* To learn more about the Internet Software Consortium, see
* ``http://www.isc.org/''. To learn more about Vixie Enterprises,
* see ``http://www.vix.com''. To learn more about Nominum, Inc., see
* ``http://www.nominum.com''.
1999-09-02 00:32:56 +00:00
*/
#include <omapip/omapip_p.h>
1999-09-02 00:32:56 +00:00
isc_result_t omapi_listen (omapi_object_t *h,
1999-11-20 18:36:32 +00:00
unsigned port,
1999-09-02 00:32:56 +00:00
int max)
{
struct hostent *he;
int hix;
isc_result_t status;
omapi_listener_object_t *obj;
/* Get the handle. */
obj = (omapi_listener_object_t *)dmalloc (sizeof *obj, MDL);
1999-09-02 00:32:56 +00:00
if (!obj)
return ISC_R_NOMEMORY;
memset (obj, 0, sizeof *obj);
1999-09-02 00:32:56 +00:00
obj -> refcnt = 1;
rc_register_mdl (&obj, obj, obj -> refcnt);
1999-09-02 00:32:56 +00:00
obj -> type = omapi_type_listener;
/* Connect this object to the inner object. */
status = omapi_object_reference (&h -> outer,
(omapi_object_t *)obj, MDL);
1999-09-02 00:32:56 +00:00
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
return status;
}
status = omapi_object_reference (&obj -> inner, h, MDL);
1999-09-02 00:32:56 +00:00
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
return status;
}
/* Set up the address on which we will listen... */
obj -> address.sin_port = htons (port);
obj -> address.sin_addr.s_addr = htonl (INADDR_ANY);
/* Create a socket on which to listen. */
obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!obj -> socket) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
2000-01-05 18:10:59 +00:00
#if defined (HAVE_SETFD)
if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
close (obj -> socket);
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
2000-01-05 18:10:59 +00:00
return ISC_R_UNEXPECTED;
}
#endif
1999-09-02 00:32:56 +00:00
/* Try to bind to the wildcard address using the port number
we were given. */
if (bind (obj -> socket,
(struct sockaddr *)&obj -> address, sizeof obj -> address)) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
if (errno == EADDRINUSE)
return ISC_R_ADDRNOTAVAIL;
if (errno == EPERM)
return ISC_R_NOPERM;
return ISC_R_UNEXPECTED;
}
/* Now tell the kernel to listen for connections. */
if (listen (obj -> socket, max)) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
return ISC_R_UNEXPECTED;
}
if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
return ISC_R_UNEXPECTED;
}
1999-09-02 00:32:56 +00:00
status = omapi_register_io_object ((omapi_object_t *)obj,
omapi_listener_readfd, 0,
omapi_accept, 0, 0);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
return status;
}
return ISC_R_SUCCESS;
}
/* Return the socket on which the dispatcher should wait for readiness
to read, for a listener object. */
int omapi_listener_readfd (omapi_object_t *h)
{
omapi_listener_object_t *l;
if (h -> type != omapi_type_listener)
return -1;
l = (omapi_listener_object_t *)h;
return l -> socket;
}
/* Reader callback for a listener object. Accept an incoming connection. */
isc_result_t omapi_accept (omapi_object_t *h)
{
isc_result_t status;
2000-02-03 03:43:51 +00:00
SOCKLEN_T len;
1999-09-02 00:32:56 +00:00
omapi_connection_object_t *obj;
omapi_listener_object_t *listener;
if (h -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
1999-09-02 00:32:56 +00:00
listener = (omapi_listener_object_t *)h;
/* Get the handle. */
obj = (omapi_connection_object_t *)dmalloc (sizeof *obj, MDL);
1999-09-02 00:32:56 +00:00
if (!obj)
return ISC_R_NOMEMORY;
1999-09-15 19:47:38 +00:00
memset (obj, 0, sizeof *obj);
1999-09-02 00:32:56 +00:00
obj -> refcnt = 1;
rc_register_mdl (&obj, obj, obj -> refcnt);
1999-09-02 00:32:56 +00:00
obj -> type = omapi_type_connection;
/* Accept the connection. */
len = sizeof obj -> remote_addr;
obj -> socket =
accept (listener -> socket,
((struct sockaddr *)
&(obj -> remote_addr)), &len);
if (obj -> socket < 0) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
obj -> state = omapi_connection_connected;
status = omapi_register_io_object ((omapi_object_t *)obj,
omapi_connection_readfd,
omapi_connection_writefd,
omapi_connection_reader,
omapi_connection_writer,
omapi_connection_reaper);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
return status;
}
omapi_object_reference (&obj -> listener,
(omapi_object_t *)listener, MDL);
1999-09-02 00:32:56 +00:00
status = omapi_signal (h, "connect", obj);
/* Lose our reference to the connection, so it'll be gc'd when it's
reaped. */
omapi_object_dereference ((omapi_object_t **)&obj, MDL);
1999-09-02 00:32:56 +00:00
return status;
}
isc_result_t omapi_listener_set_value (omapi_object_t *h,
omapi_object_t *id,
omapi_data_string_t *name,
omapi_typed_data_t *value)
{
if (h -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
if (h -> inner && h -> inner -> type -> set_value)
return (*(h -> inner -> type -> set_value))
(h -> inner, id, name, value);
return ISC_R_NOTFOUND;
}
isc_result_t omapi_listener_get_value (omapi_object_t *h,
omapi_object_t *id,
omapi_data_string_t *name,
omapi_value_t **value)
{
if (h -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
if (h -> inner && h -> inner -> type -> get_value)
return (*(h -> inner -> type -> get_value))
(h -> inner, id, name, value);
return ISC_R_NOTFOUND;
}
isc_result_t omapi_listener_destroy (omapi_object_t *h,
const char *file, int line)
1999-09-02 00:32:56 +00:00
{
omapi_listener_object_t *l;
if (h -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
l = (omapi_listener_object_t *)(h);
if (l -> socket != -1) {
close (l -> socket);
l -> socket = -1;
}
return ISC_R_SUCCESS;
}
isc_result_t omapi_listener_signal_handler (omapi_object_t *h,
const char *name, va_list ap)
1999-09-02 00:32:56 +00:00
{
if (h -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
if (h -> inner && h -> inner -> type -> signal_handler)
return (*(h -> inner -> type -> signal_handler)) (h -> inner,
name, ap);
return ISC_R_NOTFOUND;
}
/* Write all the published values associated with the object through the
specified connection. */
isc_result_t omapi_listener_stuff_values (omapi_object_t *c,
omapi_object_t *id,
omapi_object_t *l)
{
int i;
if (l -> type != omapi_type_listener)
return ISC_R_INVALIDARG;
if (l -> inner && l -> inner -> type -> stuff_values)
return (*(l -> inner -> type -> stuff_values)) (c, id,
l -> inner);
return ISC_R_SUCCESS;
}