|
Packit |
fcad23 |
/* UNIT: File Descriptor (FD) Event Manager */
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-config.h>
|
|
Packit |
fcad23 |
#ifdef HAVE_SYS_SELECT
|
|
Packit |
fcad23 |
#include <sys/select.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-includes.h>
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-features.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_api.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/fd_event_manager.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_logging.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/large_fd_set.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(fd_event_manager, libnetsnmp)
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER
|
|
Packit |
fcad23 |
int external_readfd[NUM_EXTERNAL_FDS], external_readfdlen = 0;
|
|
Packit |
fcad23 |
int external_writefd[NUM_EXTERNAL_FDS], external_writefdlen = 0;
|
|
Packit |
fcad23 |
int external_exceptfd[NUM_EXTERNAL_FDS], external_exceptfdlen = 0;
|
|
Packit |
fcad23 |
void (*external_readfdfunc[NUM_EXTERNAL_FDS]) (int, void *);
|
|
Packit |
fcad23 |
void (*external_writefdfunc[NUM_EXTERNAL_FDS]) (int, void *);
|
|
Packit |
fcad23 |
void (*external_exceptfdfunc[NUM_EXTERNAL_FDS]) (int, void *);
|
|
Packit |
fcad23 |
void *external_readfd_data[NUM_EXTERNAL_FDS];
|
|
Packit |
fcad23 |
void *external_writefd_data[NUM_EXTERNAL_FDS];
|
|
Packit |
fcad23 |
void *external_exceptfd_data[NUM_EXTERNAL_FDS];
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int external_fd_unregistered;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Register a given fd for read events. Call callback when events
|
|
Packit |
fcad23 |
* are received.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
register_readfd(int fd, void (*func) (int, void *), void *data)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (external_readfdlen < NUM_EXTERNAL_FDS) {
|
|
Packit |
fcad23 |
external_readfd[external_readfdlen] = fd;
|
|
Packit |
fcad23 |
external_readfdfunc[external_readfdlen] = func;
|
|
Packit |
fcad23 |
external_readfd_data[external_readfdlen] = data;
|
|
Packit |
fcad23 |
external_readfdlen++;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:register_readfd", "registered fd %d\n", fd));
|
|
Packit |
fcad23 |
return FD_REGISTERED_OK;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
snmp_log(LOG_CRIT, "register_readfd: too many file descriptors\n");
|
|
Packit |
fcad23 |
return FD_REGISTRATION_FAILED;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Register a given fd for write events. Call callback when events
|
|
Packit |
fcad23 |
* are received.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
register_writefd(int fd, void (*func) (int, void *), void *data)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (external_writefdlen < NUM_EXTERNAL_FDS) {
|
|
Packit |
fcad23 |
external_writefd[external_writefdlen] = fd;
|
|
Packit |
fcad23 |
external_writefdfunc[external_writefdlen] = func;
|
|
Packit |
fcad23 |
external_writefd_data[external_writefdlen] = data;
|
|
Packit |
fcad23 |
external_writefdlen++;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:register_writefd", "registered fd %d\n", fd));
|
|
Packit |
fcad23 |
return FD_REGISTERED_OK;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
snmp_log(LOG_CRIT,
|
|
Packit |
fcad23 |
"register_writefd: too many file descriptors\n");
|
|
Packit |
fcad23 |
return FD_REGISTRATION_FAILED;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Register a given fd for exception events. Call callback when events
|
|
Packit |
fcad23 |
* are received.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
register_exceptfd(int fd, void (*func) (int, void *), void *data)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (external_exceptfdlen < NUM_EXTERNAL_FDS) {
|
|
Packit |
fcad23 |
external_exceptfd[external_exceptfdlen] = fd;
|
|
Packit |
fcad23 |
external_exceptfdfunc[external_exceptfdlen] = func;
|
|
Packit |
fcad23 |
external_exceptfd_data[external_exceptfdlen] = data;
|
|
Packit |
fcad23 |
external_exceptfdlen++;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:register_exceptfd", "registered fd %d\n", fd));
|
|
Packit |
fcad23 |
return FD_REGISTERED_OK;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
snmp_log(LOG_CRIT,
|
|
Packit |
fcad23 |
"register_exceptfd: too many file descriptors\n");
|
|
Packit |
fcad23 |
return FD_REGISTRATION_FAILED;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Unregister a given fd for read events.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
unregister_readfd(int fd)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int i, j;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (i = 0; i < external_readfdlen; i++) {
|
|
Packit |
fcad23 |
if (external_readfd[i] == fd) {
|
|
Packit |
fcad23 |
external_readfdlen--;
|
|
Packit |
fcad23 |
for (j = i; j < external_readfdlen; j++) {
|
|
Packit |
fcad23 |
external_readfd[j] = external_readfd[j + 1];
|
|
Packit |
fcad23 |
external_readfdfunc[j] = external_readfdfunc[j + 1];
|
|
Packit |
fcad23 |
external_readfd_data[j] = external_readfd_data[j + 1];
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:unregister_readfd", "unregistered fd %d\n", fd));
|
|
Packit |
fcad23 |
external_fd_unregistered = 1;
|
|
Packit |
fcad23 |
return FD_UNREGISTERED_OK;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return FD_NO_SUCH_REGISTRATION;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Unregister a given fd for read events.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
unregister_writefd(int fd)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int i, j;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (i = 0; i < external_writefdlen; i++) {
|
|
Packit |
fcad23 |
if (external_writefd[i] == fd) {
|
|
Packit |
fcad23 |
external_writefdlen--;
|
|
Packit |
fcad23 |
for (j = i; j < external_writefdlen; j++) {
|
|
Packit |
fcad23 |
external_writefd[j] = external_writefd[j + 1];
|
|
Packit |
fcad23 |
external_writefdfunc[j] = external_writefdfunc[j + 1];
|
|
Packit |
fcad23 |
external_writefd_data[j] = external_writefd_data[j + 1];
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:unregister_writefd", "unregistered fd %d\n", fd));
|
|
Packit |
fcad23 |
external_fd_unregistered = 1;
|
|
Packit |
fcad23 |
return FD_UNREGISTERED_OK;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return FD_NO_SUCH_REGISTRATION;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Unregister a given fd for exception events.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
unregister_exceptfd(int fd)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int i, j;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (i = 0; i < external_exceptfdlen; i++) {
|
|
Packit |
fcad23 |
if (external_exceptfd[i] == fd) {
|
|
Packit |
fcad23 |
external_exceptfdlen--;
|
|
Packit |
fcad23 |
for (j = i; j < external_exceptfdlen; j++) {
|
|
Packit |
fcad23 |
external_exceptfd[j] = external_exceptfd[j + 1];
|
|
Packit |
fcad23 |
external_exceptfdfunc[j] = external_exceptfdfunc[j + 1];
|
|
Packit |
fcad23 |
external_exceptfd_data[j] = external_exceptfd_data[j + 1];
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:unregister_exceptfd", "unregistered fd %d\n",
|
|
Packit |
fcad23 |
fd));
|
|
Packit |
fcad23 |
external_fd_unregistered = 1;
|
|
Packit |
fcad23 |
return FD_UNREGISTERED_OK;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return FD_NO_SUCH_REGISTRATION;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* NET-SNMP External Event Info
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
void netsnmp_external_event_info(int *numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_large_fd_set lreadfds;
|
|
Packit |
fcad23 |
netsnmp_large_fd_set lwritefds;
|
|
Packit |
fcad23 |
netsnmp_large_fd_set lexceptfds;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds);
|
|
Packit |
fcad23 |
netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds);
|
|
Packit |
fcad23 |
netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_external_event_info2(numfds, &lreadfds, &lwritefds, &lexceptfds);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0
|
|
Packit |
fcad23 |
|| netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0
|
|
Packit |
fcad23 |
|| netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR,
|
|
Packit |
fcad23 |
"Use netsnmp_external_event_info2() for processing"
|
|
Packit |
fcad23 |
" large file descriptors\n");
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_cleanup(&lreadfds);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_cleanup(&lwritefds);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_cleanup(&lexceptfds);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void netsnmp_external_event_info2(int *numfds,
|
|
Packit |
fcad23 |
netsnmp_large_fd_set *readfds,
|
|
Packit |
fcad23 |
netsnmp_large_fd_set *writefds,
|
|
Packit |
fcad23 |
netsnmp_large_fd_set *exceptfds)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int i;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
external_fd_unregistered = 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (i = 0; i < external_readfdlen; i++) {
|
|
Packit |
fcad23 |
NETSNMP_LARGE_FD_SET(external_readfd[i], readfds);
|
|
Packit |
fcad23 |
if (external_readfd[i] >= *numfds)
|
|
Packit |
fcad23 |
*numfds = external_readfd[i] + 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
for (i = 0; i < external_writefdlen; i++) {
|
|
Packit |
fcad23 |
NETSNMP_LARGE_FD_SET(external_writefd[i], writefds);
|
|
Packit |
fcad23 |
if (external_writefd[i] >= *numfds)
|
|
Packit |
fcad23 |
*numfds = external_writefd[i] + 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
for (i = 0; i < external_exceptfdlen; i++) {
|
|
Packit |
fcad23 |
NETSNMP_LARGE_FD_SET(external_exceptfd[i], exceptfds);
|
|
Packit |
fcad23 |
if (external_exceptfd[i] >= *numfds)
|
|
Packit |
fcad23 |
*numfds = external_exceptfd[i] + 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* NET-SNMP Dispatch External Events
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
void netsnmp_dispatch_external_events(int *count, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_large_fd_set lreadfds;
|
|
Packit |
fcad23 |
netsnmp_large_fd_set lwritefds;
|
|
Packit |
fcad23 |
netsnmp_large_fd_set lexceptfds;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds);
|
|
Packit |
fcad23 |
netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds);
|
|
Packit |
fcad23 |
netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_dispatch_external_events2(count, &lreadfds, &lwritefds, &lexceptfds);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0
|
|
Packit |
fcad23 |
|| netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0
|
|
Packit |
fcad23 |
|| netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR,
|
|
Packit |
fcad23 |
"Use netsnmp_dispatch_external_events2() for processing"
|
|
Packit |
fcad23 |
" large file descriptors\n");
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_cleanup(&lreadfds);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_cleanup(&lwritefds);
|
|
Packit |
fcad23 |
netsnmp_large_fd_set_cleanup(&lexceptfds);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void netsnmp_dispatch_external_events2(int *count,
|
|
Packit |
fcad23 |
netsnmp_large_fd_set *readfds,
|
|
Packit |
fcad23 |
netsnmp_large_fd_set *writefds,
|
|
Packit |
fcad23 |
netsnmp_large_fd_set *exceptfds)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int i;
|
|
Packit |
fcad23 |
for (i = 0;
|
|
Packit |
fcad23 |
*count && (i < external_readfdlen) && !external_fd_unregistered; i++) {
|
|
Packit |
fcad23 |
if (NETSNMP_LARGE_FD_ISSET(external_readfd[i], readfds)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events",
|
|
Packit |
fcad23 |
"readfd[%d] = %d\n", i, external_readfd[i]));
|
|
Packit |
fcad23 |
external_readfdfunc[i] (external_readfd[i],
|
|
Packit |
fcad23 |
external_readfd_data[i]);
|
|
Packit |
fcad23 |
NETSNMP_LARGE_FD_CLR(external_readfd[i], readfds);
|
|
Packit |
fcad23 |
(*count)--;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
for (i = 0;
|
|
Packit |
fcad23 |
*count && (i < external_writefdlen) && !external_fd_unregistered; i++) {
|
|
Packit |
fcad23 |
if (NETSNMP_LARGE_FD_ISSET(external_writefd[i], writefds)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events",
|
|
Packit |
fcad23 |
"writefd[%d] = %d\n", i, external_writefd[i]));
|
|
Packit |
fcad23 |
external_writefdfunc[i] (external_writefd[i],
|
|
Packit |
fcad23 |
external_writefd_data[i]);
|
|
Packit |
fcad23 |
NETSNMP_LARGE_FD_CLR(external_writefd[i], writefds);
|
|
Packit |
fcad23 |
(*count)--;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
for (i = 0;
|
|
Packit |
fcad23 |
*count && (i < external_exceptfdlen) && !external_fd_unregistered; i++) {
|
|
Packit |
fcad23 |
if (NETSNMP_LARGE_FD_ISSET(external_exceptfd[i], exceptfds)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events",
|
|
Packit |
fcad23 |
"exceptfd[%d] = %d\n", i, external_exceptfd[i]));
|
|
Packit |
fcad23 |
external_exceptfdfunc[i] (external_exceptfd[i],
|
|
Packit |
fcad23 |
external_exceptfd_data[i]);
|
|
Packit |
fcad23 |
NETSNMP_LARGE_FD_CLR(external_exceptfd[i], exceptfds);
|
|
Packit |
fcad23 |
(*count)--;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#else /* !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */
|
|
Packit |
fcad23 |
netsnmp_feature_unused(fd_event_manager);
|
|
Packit |
fcad23 |
#endif /* !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */
|