2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-23 18:38:00 +00:00
isc-dhcp/omapip/listener.c

249 lines
6.8 KiB
C
Raw Normal View History

1999-09-02 00:32:56 +00:00
/* listener.c
Subroutines that support the generic listener object. */
/*
* Copyright (c) 1996-1999 Internet Software Consortium.
* Use is subject to license terms which appear in the file named
* ISC-LICENSE that should have accompanied this file when you
* received it. If a file named ISC-LICENSE did not accompany this
* file, or you are not sure the one you have is correct, you may
* obtain an applicable copy of the license at:
*
* http://www.isc.org/isc-license-1.0.html.
*
* This file is part of the ISC DHCP distribution. The documentation
* associated with this file is listed in the file DOCUMENTATION,
* included in the top-level directory of this release.
*
* Support and other services are available for ISC products - see
* http://www.isc.org for more information.
*/
#include <omapip/omapip_p.h>
1999-09-02 00:32:56 +00:00
isc_result_t omapi_listen (omapi_object_t *h,
int port,
int max)
{
struct hostent *he;
int hix;
isc_result_t status;
omapi_listener_object_t *obj;
/* Get the handle. */
obj = (omapi_listener_object_t *)malloc (sizeof *obj);
if (!obj)
return ISC_R_NOMEMORY;
memset (obj, 0, sizeof *obj);
1999-09-02 00:32:56 +00:00
obj -> refcnt = 1;
obj -> type = omapi_type_listener;
/* Connect this object to the inner object. */
status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
"omapi_protocol_listen");
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&obj,
"omapi_protocol_listen");
return status;
}
status = omapi_object_reference (&obj -> inner, h,
"omapi_protocol_listen");
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&obj,
"omapi_protocol_listen");
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,
"omapi_listen");
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
return ISC_R_NORESOURCES;
return ISC_R_UNEXPECTED;
}
/* 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,
"omapi_listen");
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,
"omapi_listen");
return ISC_R_UNEXPECTED;
}
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,
"omapi_listen");
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;
int len;
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 *)malloc (sizeof *obj);
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;
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) {
1999-09-02 00:32:56 +00:00
omapi_object_dereference ((omapi_object_t **)&obj,
"omapi_accept");
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,
"omapi_accept");
return status;
}
omapi_object_reference (&obj -> listener, (omapi_object_t *)listener,
"omapi_accept");
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, "omapi_accept");
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 *name)
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;
}