/********************************************************************** * %FUNCTION: SetupPipes (static) * %ARGUMENTS: * es -- event selector * %RETURNS: * 0 on success; -1 on failure * %DESCRIPTION: * Sets up pipes with an event handler to handle IPC from a signal handler ***********************************************************************/ static int SetupPipes(EventSelector *es) { /* If already done, do nothing */ if (PipeHandler) return 0; /* Initialize the child-process hash table */ hash_init(&child_process_table, offsetof(struct ChildEntry, hash), child_hash, child_compare); /* Open pipe to self */ if (pipe(Pipe) < 0) { return -1; } PipeHandler = Event_AddHandler(es, Pipe[0], EVENT_FLAG_READABLE, DoPipe, NULL); if (!PipeHandler) { int old_errno = errno; close(Pipe[0]); close(Pipe[1]); errno = old_errno; return -1; } return 0; }
static int SetupPipes(EventSelector *es) { if (PipeHandler) return 0; hash_init(&child_process_table, offsetof(struct ChildEntry, hash), child_hash, child_compare); if (pipe(Pipe) < 0) { return -1; } PipeHandler = Event_AddHandler(es, Pipe[0], EVENT_FLAG_READABLE, DoPipe, NULL); if (!PipeHandler) { int old_errno = errno; close(Pipe[0]); close(Pipe[1]); errno = old_errno; return -1; } return 0; }
/********************************************************************** * %FUNCTION: Event_AddHandlerWithTimeout * %ARGUMENTS: * es -- event selector * fd -- file descriptor to watch * flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE * t -- Timeout after which to call handler, even if not readable/writable. * If t.tv_sec < 0, calls normal Event_AddHandler with no timeout. * fn -- callback function to call when event is triggered * data -- extra data to pass to callback function * %RETURNS: * A newly-allocated EventHandler, or NULL. ***********************************************************************/ EventHandler * Event_AddHandlerWithTimeout(EventSelector *es, int fd, unsigned int flags, struct timeval t, EventCallbackFunc fn, void *data) { EventHandler *eh; struct timeval now; /* If timeout is negative, just do normal non-timing-out event */ if (t.tv_sec < 0 || t.tv_usec < 0) { return Event_AddHandler(es, fd, flags, fn, data); } /* Specifically disable timer and deleted flags */ flags &= (~(EVENT_FLAG_TIMER | EVENT_FLAG_DELETED)); flags |= EVENT_FLAG_TIMEOUT; /* Bad file descriptor? */ if (fd < 0) { errno = EBADF; return NULL; } /* Bad timeout? */ if (t.tv_usec >= 1000000) { errno = EINVAL; return NULL; } eh = malloc(sizeof(EventHandler)); if (!eh) return NULL; /* Convert time interval to absolute time */ gettimeofday(&now, NULL); t.tv_sec += now.tv_sec; t.tv_usec += now.tv_usec; if (t.tv_usec >= 1000000) { t.tv_usec -= 1000000; t.tv_sec++; } eh->fd = fd; eh->flags = flags; eh->tmout = t; eh->fn = fn; eh->data = data; /* Add immediately. This is safe even if we are in a handler. */ eh->next = es->handlers; es->handlers = eh; EVENT_DEBUG(("Event_AddHandlerWithTimeout(es=%p, fd=%d, flags=%u, t=%d/%d) -> %p\n", es, fd, flags, t.tv_sec, t.tv_usec, eh)); return eh; }
/********************************************************************** * %FUNCTION: SetupPipes (static) * %ARGUMENTS: * es -- event selector * %RETURNS: * 0 on success; -1 on failure * %DESCRIPTION: * Sets up pipes with an event handler to handle IPC from a signal handler ***********************************************************************/ static int SetupPipes(EventSelector *es) { int flags; int i; /* If already done, do nothing */ if (PipeHandler) return 0; MyPid = getpid(); /* Initialize the child-process hash table */ hash_init(&child_process_table, offsetof(struct ChildEntry, hash), child_hash, child_compare); /* Open pipe to self */ if (pipe(Pipe) < 0) { return -1; } /* Make pipes non-blocking */ for (i=0; i<=1; i++) { flags = fcntl(Pipe[i], F_GETFL, 0); if (flags != -1) { flags = fcntl(Pipe[i], F_SETFL, flags | O_NONBLOCK); } if (flags == -1) { close(Pipe[0]); close(Pipe[1]); return -1; } } PipeHandler = Event_AddHandler(es, Pipe[0], EVENT_FLAG_READABLE, DoPipe, NULL); if (!PipeHandler) { int old_errno = errno; close(Pipe[0]); close(Pipe[1]); errno = old_errno; return -1; } return 0; }
/********************************************************************** * %FUNCTION: network_init * %ARGUMENTS: * es -- an event selector * %RETURNS: * >= 0 if all is OK, <0 if not * %DESCRIPTION: * Initializes network; opens socket on UDP port 1701; sets up * event handler for incoming packets. ***********************************************************************/ int l2tp_network_init(EventSelector *es) { struct sockaddr_in me; int flags; gethostname(Hostname, sizeof(Hostname)); Hostname[sizeof(Hostname)-1] = 0; Event_HandleSignal(es, SIGINT, sigint_handler); if (Sock >= 0) { if (NetworkReadHandler) { Event_DelHandler(es, NetworkReadHandler); NetworkReadHandler = NULL; } close(Sock); Sock = -1; } Sock = socket(PF_INET, SOCK_DGRAM, 0); if (Sock < 0) { l2tp_set_errmsg("network_init: socket: %s", strerror(errno)); return -1; } me.sin_family = AF_INET; me.sin_addr = Settings.listen_addr; me.sin_port = htons((uint16_t) Settings.listen_port); if (bind(Sock, (struct sockaddr *) &me, sizeof(me)) < 0) { l2tp_set_errmsg("network_init: bind: %s", strerror(errno)); close(Sock); Sock = -1; return -1; } /* Set socket non-blocking */ flags = fcntl(Sock, F_GETFL); flags |= O_NONBLOCK; fcntl(Sock, F_SETFL, flags); /* Set up the network read handler */ Event_AddHandler(es, Sock, EVENT_FLAG_READABLE, network_readable, NULL); return Sock; }
/********************************************************************** * %FUNCTION: EventTcp_CreateAcceptor * %ARGUMENTS: * es -- event selector * socket -- listening socket * f -- function to call when a connection is accepted * data -- extra data to pass to f. * %RETURNS: * An event handler on success, NULL on failure. * %DESCRIPTION: * Sets up an accepting socket and calls "f" whenever a new * connection arrives. ***********************************************************************/ EventHandler * EventTcp_CreateAcceptor(EventSelector *es, int socket, EventTcpAcceptFunc f) { int flags; EVENT_DEBUG(("EventTcp_CreateAcceptor(es=%p, socket=%d)\n", es, socket)); /* Make sure socket is non-blocking */ flags = fcntl(socket, F_GETFL, 0); if (flags == -1) { return NULL; } if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) == -1) { return NULL; } return Event_AddHandler(es, socket, EVENT_FLAG_READABLE, handle_accept, (void *) f); }