diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-01-02 14:18:20 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-01-02 14:18:20 +0100 |
commit | c1343b3278cdf99533b7902744d15969f9d6fdc1 (patch) | |
tree | d5ed3dc5677a59260ec41cd39bb284d3e94c91b3 /src/pluto/server.c | |
parent | b34738ed08c2227300d554b139e2495ca5da97d6 (diff) | |
download | vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.tar.gz vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.zip |
Imported Upstream version 5.0.1
Diffstat (limited to 'src/pluto/server.c')
-rw-r--r-- | src/pluto/server.c | 910 |
1 files changed, 0 insertions, 910 deletions
diff --git a/src/pluto/server.c b/src/pluto/server.c deleted file mode 100644 index 167b1d4c7..000000000 --- a/src/pluto/server.c +++ /dev/null @@ -1,910 +0,0 @@ -/* get-next-event loop - * Copyright (C) 1997 Angelos D. Keromytis. - * Copyright (C) 1998-2002 D. Hugh Redelmeier. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <errno.h> -#include <signal.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#ifdef SOLARIS -# include <sys/sockio.h> /* for Solaris 2.6: defines SIOCGIFCONF */ -#endif -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/time.h> -#include <netdb.h> -#include <unistd.h> -#include <fcntl.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <resolv.h> -#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */ -#include <sys/queue.h> - -#include <freeswan.h> - -#include "constants.h" -#include "defs.h" -#include "state.h" -#include "connections.h" -#include "kernel.h" -#include "log.h" -#include "server.h" -#include "timer.h" -#include "packet.h" -#include "demux.h" /* needs packet.h */ -#include "rcv_whack.h" -#include "keys.h" -#include "adns.h" /* needs <resolv.h> */ -#include "dnskey.h" /* needs keys.h and adns.h */ -#include "whack.h" /* for RC_LOG_SERIOUS */ -#include "pluto.h" - -#include <pfkeyv2.h> -#include <pfkey.h> -#include "kameipsec.h" -#include "nat_traversal.h" - -/* - * Server main loop and socket initialization routines. - */ - -static const int on = TRUE; /* by-reference parameter; constant, we hope */ - -/* control (whack) socket */ -int ctl_fd = NULL_FD; /* file descriptor of control (whack) socket */ -struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX }; - -/* info (showpolicy) socket */ -int policy_fd = NULL_FD; -struct sockaddr_un info_addr= { AF_UNIX, DEFAULT_CTLBASE INFO_SUFFIX }; - -/* Initialize the control socket. - * Note: this is called very early, so little infrastructure is available. - * It is important that the socket is created before the original - * Pluto process returns. - */ -err_t -init_ctl_socket(void) -{ - err_t failed = NULL; - - delete_ctl_socket(); /* preventative medicine */ - ctl_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (ctl_fd == -1) - failed = "create"; - else if (fcntl(ctl_fd, F_SETFD, FD_CLOEXEC) == -1) - failed = "fcntl FD+CLOEXEC"; - else if (setsockopt(ctl_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) - failed = "setsockopt"; - else - { - /* to keep control socket secure, use umask */ - mode_t ou = umask(~S_IRWXU); - - if (bind(ctl_fd, (struct sockaddr *)&ctl_addr - , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0) - failed = "bind"; - umask(ou); - } - - /* 5 is a haphazardly chosen limit for the backlog. - * Rumour has it that this is the max on BSD systems. - */ - if (failed == NULL && listen(ctl_fd, 5) < 0) - failed = "listen() on"; - - return failed == NULL? NULL : builddiag("could not %s control socket: %d %s" - , failed, errno, strerror(errno)); -} - -void -delete_ctl_socket(void) -{ - /* Is noting failure useful? Not when used as preventative medicine. */ - unlink(ctl_addr.sun_path); -} - -bool listening = FALSE; /* should we pay attention to IKE messages? */ - -struct iface *interfaces = NULL; /* public interfaces */ - -/* Initialize the interface sockets. */ - -static void -mark_ifaces_dead(void) -{ - struct iface *p; - - for (p = interfaces; p != NULL; p = p->next) - p->change = IFN_DELETE; -} - -static void -free_dead_ifaces(void) -{ - struct iface *p; - bool some_dead = FALSE - , some_new = FALSE; - - for (p = interfaces; p != NULL; p = p->next) - { - if (p->change == IFN_DELETE) - { - plog("shutting down interface %s/%s %s" - , p->vname, p->rname, ip_str(&p->addr)); - some_dead = TRUE; - } - else if (p->change == IFN_ADD) - { - some_new = TRUE; - } - } - - if (some_dead) - { - struct iface **pp; - - release_dead_interfaces(); - for (pp = &interfaces; (p = *pp) != NULL; ) - { - if (p->change == IFN_DELETE) - { - *pp = p->next; /* advance *pp */ - free(p->vname); - free(p->rname); - close(p->fd); - free(p); - } - else - { - pp = &p->next; /* advance pp */ - } - } - } - - /* this must be done after the release_dead_interfaces - * in case some to the newly unoriented connections can - * become oriented here. - */ - if (some_dead || some_new) - check_orientations(); -} - -void -free_ifaces(void) -{ - mark_ifaces_dead(); - free_dead_ifaces(); -} - -struct raw_iface { - ip_address addr; - char name[IFNAMSIZ + 20]; /* what would be a safe size? */ - struct raw_iface *next; -}; - -/* Called to handle --interface <ifname> - * Semantics: if specified, only these (real) interfaces are considered. - */ -static const char *pluto_ifn[10]; -static int pluto_ifn_roof = 0; - -bool -use_interface(const char *rifn) -{ - if (pluto_ifn_roof >= (int)countof(pluto_ifn)) - { - return FALSE; - } - else - { - pluto_ifn[pluto_ifn_roof++] = rifn; - return TRUE; - } -} - -static struct raw_iface * -find_raw_ifaces4(void) -{ - int j; /* index into buf */ - struct ifconf ifconf; - struct ifreq buf[300]; /* for list of interfaces -- arbitrary limit */ - struct raw_iface *rifaces = NULL; - int master_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ - - /* get list of interfaces with assigned IPv4 addresses from system */ - - if (master_sock == -1) - exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); - - if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR - , (const void *)&on, sizeof(on)) < 0) - exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); - - /* bind the socket */ - { - ip_address any; - - happy(anyaddr(AF_INET, &any)); - setportof(htons(pluto_port), &any); - if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) - exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); - } - - /* Get local interfaces. See netdevice(7). */ - ifconf.ifc_len = sizeof(buf); - ifconf.ifc_buf = (void *) buf; - zero(buf); - - if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) - exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); - - /* Add an entry to rifaces for each interesting interface. */ - for (j = 0; (j+1) * sizeof(*buf) <= (size_t)ifconf.ifc_len; j++) - { - struct raw_iface ri; - const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr; - struct ifreq auxinfo; - - /* ignore all but AF_INET interfaces */ - if (rs->sin_family != AF_INET) - continue; /* not interesting */ - - /* build a NUL-terminated copy of the rname field */ - memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ); - ri.name[IFNAMSIZ] = '\0'; - - /* ignore if our interface names were specified, and this isn't one */ - if (pluto_ifn_roof != 0) - { - int i; - - for (i = 0; i != pluto_ifn_roof; i++) - if (streq(ri.name, pluto_ifn[i])) - break; - if (i == pluto_ifn_roof) - continue; /* not found -- skip */ - } - - /* Find out stuff about this interface. See netdevice(7). */ - zero(&auxinfo); /* paranoia */ - memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ); - if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) - exit_log_errno((e - , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()" - , ri.name)); - if (!(auxinfo.ifr_flags & IFF_UP)) - continue; /* ignore an interface that isn't UP */ - - /* ignore unconfigured interfaces */ - if (rs->sin_addr.s_addr == 0) - continue; - - happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr) - , AF_INET, &ri.addr)); - - DBG(DBG_CONTROL, DBG_log("found %s with address %s" - , ri.name, ip_str(&ri.addr))); - ri.next = rifaces; - rifaces = clone_thing(ri); - } - - close(master_sock); - - return rifaces; -} - -static struct raw_iface * -find_raw_ifaces6(void) -{ - - /* Get list of interfaces with IPv6 addresses from system from /proc/net/if_inet6). - * - * Documentation of format? - * RTFS: linux-2.2.16/net/ipv6/addrconf.c:iface_proc_info() - * linux-2.4.9-13/net/ipv6/addrconf.c:iface_proc_info() - * - * Sample from Gerhard's laptop: - * 00000000000000000000000000000001 01 80 10 80 lo - * 30490009000000000000000000010002 02 40 00 80 ipsec0 - * 30490009000000000000000000010002 07 40 00 80 eth0 - * fe80000000000000025004fffefd5484 02 0a 20 80 ipsec0 - * fe80000000000000025004fffefd5484 07 0a 20 80 eth0 - * - * Each line contains: - * - IPv6 address: 16 bytes, in hex, no punctuation - * - ifindex: 1 byte, in hex - * - prefix_len: 1 byte, in hex - * - scope (e.g. global, link local): 1 byte, in hex - * - flags: 1 byte, in hex - * - device name: string, followed by '\n' - */ - struct raw_iface *rifaces = NULL; - static const char proc_name[] = "/proc/net/if_inet6"; - FILE *proc_sock = fopen(proc_name, "r"); - - if (proc_sock == NULL) - { - DBG(DBG_CONTROL, DBG_log("could not open %s", proc_name)); - } - else - { - for (;;) - { - struct raw_iface ri; - unsigned short xb[8]; /* IPv6 address as 8 16-bit chunks */ - char sb[8*5]; /* IPv6 address as string-with-colons */ - unsigned int if_idx; /* proc field, not used */ - unsigned int plen; /* proc field, not used */ - unsigned int scope; /* proc field, used to exclude link-local */ - unsigned int dad_status; /* proc field, not used */ - /* ??? I hate and distrust scanf -- DHR */ - int r = fscanf(proc_sock - , "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx" - " %02x %02x %02x %02x %20s\n" - , xb+0, xb+1, xb+2, xb+3, xb+4, xb+5, xb+6, xb+7 - , &if_idx, &plen, &scope, &dad_status, ri.name); - - /* ??? we should diagnose any problems */ - if (r != 13) - break; - - /* ignore addresses with link local scope. - * From linux-2.4.9-13/include/net/ipv6.h: - * IPV6_ADDR_LINKLOCAL 0x0020U - * IPV6_ADDR_SCOPE_MASK 0x00f0U - */ - if ((scope & 0x00f0U) == 0x0020U) - continue; - - snprintf(sb, sizeof(sb) - , "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" - , xb[0], xb[1], xb[2], xb[3], xb[4], xb[5], xb[6], xb[7]); - - happy(ttoaddr(sb, 0, AF_INET6, &ri.addr)); - - if (!isunspecaddr(&ri.addr)) - { - DBG(DBG_CONTROL - , DBG_log("found %s with address %s" - , ri.name, sb)); - ri.next = rifaces; - rifaces = clone_thing(ri); - } - } - fclose(proc_sock); - } - - return rifaces; -} - -static int -create_socket(struct raw_iface *ifp, const char *v_name, int port) -{ - int fd = socket(addrtypeof(&ifp->addr), SOCK_DGRAM, IPPROTO_UDP); - int fcntl_flags; - - if (fd < 0) - { - log_errno((e, "socket() in process_raw_ifaces()")); - return -1; - } - - /* Set socket Nonblocking */ - if ((fcntl_flags=fcntl(fd, F_GETFL)) >= 0) { - if (!(fcntl_flags & O_NONBLOCK)) { - fcntl_flags |= O_NONBLOCK; - fcntl(fd, F_SETFL, fcntl_flags); - } - } - - if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - { - log_errno((e, "fcntl(,, FD_CLOEXEC) in process_raw_ifaces()")); - close(fd); - return -1; - } - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR - , (const void *)&on, sizeof(on)) < 0) - { - log_errno((e, "setsockopt SO_REUSEADDR in process_raw_ifaces()")); - close(fd); - return -1; - } - - /* To improve error reporting. See ip(7). */ -#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE) - if (setsockopt(fd, SOL_IP, IP_RECVERR - , (const void *)&on, sizeof(on)) < 0) - { - log_errno((e, "setsockopt IP_RECVERR in process_raw_ifaces()")); - close(fd); - return -1; - } -#endif - - /* With IPv6, there is no fragmentation after - * it leaves our interface. PMTU discovery - * is mandatory but doesn't work well with IKE (why?). - * So we must set the IPV6_USE_MIN_MTU option. - * See draft-ietf-ipngwg-rfc2292bis-01.txt 11.1 - */ -#ifdef IPV6_USE_MIN_MTU /* YUCK: not always defined */ - if (addrtypeof(&ifp->addr) == AF_INET6 - && setsockopt(fd, SOL_SOCKET, IPV6_USE_MIN_MTU - , (const void *)&on, sizeof(on)) < 0) - { - log_errno((e, "setsockopt IPV6_USE_MIN_MTU in process_raw_ifaces()")); - close(fd); - return -1; - } -#endif - - { - struct sadb_x_policy policy; - int level, opt; - - policy.sadb_x_policy_len = sizeof(policy) / IPSEC_PFKEYv2_ALIGN; - policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; - policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS; - policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND; - policy.sadb_x_policy_reserved = 0; - policy.sadb_x_policy_id = 0; - policy.sadb_x_policy_reserved2 = 0; - - if (addrtypeof(&ifp->addr) == AF_INET6) - { - level = IPPROTO_IPV6; - opt = IPV6_IPSEC_POLICY; - } - else - { - level = IPPROTO_IP; - opt = IP_IPSEC_POLICY; - } - - if (setsockopt(fd, level, opt - , &policy, sizeof(policy)) < 0) - { - log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()")); - close(fd); - return -1; - } - - policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; - - if (setsockopt(fd, level, opt - , &policy, sizeof(policy)) < 0) - { - log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()")); - close(fd); - return -1; - } - } - - setportof(htons(port), &ifp->addr); - if (bind(fd, sockaddrof(&ifp->addr), sockaddrlenof(&ifp->addr)) < 0) - { - log_errno((e, "bind() for %s/%s %s:%u in process_raw_ifaces()" - , ifp->name, v_name - , ip_str(&ifp->addr), (unsigned) port)); - close(fd); - return -1; - } - setportof(htons(pluto_port), &ifp->addr); - return fd; -} - -static void -process_raw_ifaces(struct raw_iface *rifaces) -{ - struct raw_iface *ifp; - - /* For each real interface... - */ - for (ifp = rifaces; ifp != NULL; ifp = ifp->next) - { - struct raw_iface *v = NULL; - bool after = FALSE; /* has vfp passed ifp on the list? */ - bool bad = FALSE; - struct raw_iface *vfp; - - for (vfp = rifaces; vfp != NULL; vfp = vfp->next) - { - if (vfp == ifp) - { - after = TRUE; - } - else if (sameaddr(&ifp->addr, &vfp->addr)) - { - /* ugh: a second interface with the same IP address - * "after" allows us to avoid double reporting. - */ - if (after) - { - bad = TRUE; - break; - } - continue; - } - } - - if (bad) - continue; - - v = ifp; - - /* We've got all we need; see if this is a new thing: - * search old interfaces list. - */ - { - struct iface **p = &interfaces; - - for (;;) - { - struct iface *q = *p; - - /* search is over if at end of list */ - if (q == NULL) - { - /* matches nothing -- create a new entry */ - int fd = create_socket(ifp, v->name, pluto_port); - - if (fd < 0) - break; - - if (nat_traversal_support_non_ike - && addrtypeof(&ifp->addr) == AF_INET) - { - nat_traversal_espinudp_socket(fd, ESPINUDP_WITH_NON_IKE); - } - - q = malloc_thing(struct iface); - zero(q); - q->rname = clone_str(ifp->name); - q->vname = clone_str(v->name); - q->addr = ifp->addr; - q->fd = fd; - q->next = interfaces; - q->change = IFN_ADD; - interfaces = q; - plog("adding interface %s/%s %s:%d" - , q->vname, q->rname, ip_str(&q->addr), pluto_port); - - if (nat_traversal_support_port_floating - && addrtypeof(&ifp->addr) == AF_INET) - { - fd = create_socket(ifp, v->name, NAT_T_IKE_FLOAT_PORT); - if (fd < 0) - break; - nat_traversal_espinudp_socket(fd, - ESPINUDP_WITH_NON_ESP); - q = malloc_thing(struct iface); - zero(q); - q->rname = clone_str(ifp->name); - q->vname = clone_str(v->name); - q->addr = ifp->addr; - setportof(htons(NAT_T_IKE_FLOAT_PORT), &q->addr); - q->fd = fd; - q->next = interfaces; - q->change = IFN_ADD; - q->ike_float = TRUE; - interfaces = q; - plog("adding interface %s/%s %s:%d", - q->vname, q->rname, ip_str(&q->addr), NAT_T_IKE_FLOAT_PORT); - } - break; - } - - /* search over if matching old entry found */ - if (streq(q->rname, ifp->name) - && streq(q->vname, v->name) - && sameaddr(&q->addr, &ifp->addr)) - { - /* matches -- rejuvinate old entry */ - q->change = IFN_KEEP; - - /* look for other interfaces to keep (due to NAT-T) */ - for (q = q->next ; q ; q = q->next) - { - if (streq(q->rname, ifp->name) - && streq(q->vname, v->name) - && sameaddr(&q->addr, &ifp->addr)) - { - q->change = IFN_KEEP; - } - } - break; - } - - /* try again */ - p = &q->next; - } /* for (;;) */ - } - } - - /* delete the raw interfaces list */ - while (rifaces != NULL) - { - struct raw_iface *t = rifaces; - - rifaces = t->next; - free(t); - } -} - -void -find_ifaces(void) -{ - mark_ifaces_dead(); - process_raw_ifaces(find_raw_ifaces4()); - process_raw_ifaces(find_raw_ifaces6()); - - free_dead_ifaces(); /* ditch remaining old entries */ - - if (interfaces == NULL) - loglog(RC_LOG_SERIOUS, "no public interfaces found"); -} - -void -show_ifaces_status(void) -{ - struct iface *p; - - for (p = interfaces; p != NULL; p = p->next) - whack_log(RC_COMMENT, "interface %s/%s %s:%d" - , p->vname, p->rname, ip_str(&p->addr), ntohs(portof(&p->addr))); -} - -void -show_debug_status(void) -{ -#ifdef DEBUG - whack_log(RC_COMMENT, "debug options: %s" - , bitnamesof(debug_bit_names, cur_debugging)); -#endif -} - -static volatile sig_atomic_t sighupflag = FALSE; - -static void -huphandler(int sig UNUSED) -{ - sighupflag = TRUE; -} - -static volatile sig_atomic_t sigtermflag = FALSE; - -static void -termhandler(int sig UNUSED) -{ - sigtermflag = TRUE; -} - -/* call_server listens for incoming ISAKMP packets and Whack messages, - * and handles timer events. - */ -void -call_server(void) -{ - struct iface *ifp; - - /* catch SIGHUP and SIGTERM */ - { - int r; - struct sigaction act; - - act.sa_handler = &huphandler; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; /* no SA_ONESHOT, no SA_RESTART, no nothing */ - r = sigaction(SIGHUP, &act, NULL); - passert(r == 0); - - act.sa_handler = &termhandler; - r = sigaction(SIGTERM, &act, NULL); - r = sigaction(SIGINT, &act, NULL); - passert(r == 0); - } - - for (;;) - { - fd_set readfds; - fd_set writefds; - int ndes, events_fd; - - /* wait for next interesting thing */ - - for (;;) - { - long next_time = next_event(); /* time to any pending timer event */ - int maxfd = ctl_fd; - - if (sigtermflag) - exit_pluto(0); - - if (sighupflag) - { - /* Ignorant folks think poking any daemon with SIGHUP - * is polite. We catch it and tell them otherwise. - * There is one use: unsticking a hung recvfrom. - * This sticking happens sometimes -- kernel bug? - */ - sighupflag = FALSE; - plog("Pluto ignores SIGHUP -- perhaps you want \"whack --listen\""); - } - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_SET(ctl_fd, &readfds); - -#ifdef ADNS - /* the only write file-descriptor of interest */ - if (adns_qfd != NULL_FD && unsent_ADNS_queries) - { - if (maxfd < adns_qfd) - maxfd = adns_qfd; - FD_SET(adns_qfd, &writefds); - } - - if (adns_afd != NULL_FD) - { - if (maxfd < adns_afd) - maxfd = adns_afd; - FD_SET(adns_afd, &readfds); - } -#endif /* ADNS */ - - events_fd = pluto->events->get_event_fd(pluto->events); - if (maxfd < events_fd) - maxfd = events_fd; - FD_SET(events_fd, &readfds); - - if (listening) - { - for (ifp = interfaces; ifp != NULL; ifp = ifp->next) - { - if (maxfd < ifp->fd) - maxfd = ifp->fd; - passert(!FD_ISSET(ifp->fd, &readfds)); - FD_SET(ifp->fd, &readfds); - } - } - - if (next_time == -1) - { - /* select without timer */ - - ndes = select(maxfd + 1, &readfds, &writefds, NULL, NULL); - } - else if (next_time == 0) - { - /* timer without select: there is a timer event pending, - * and it should fire now so don't bother to do the select. - */ - ndes = 0; /* signify timer expiration */ - } - else - { - /* select with timer */ - - struct timeval tm; - - tm.tv_sec = next_time; - tm.tv_usec = 0; - ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm); - } - - if (ndes != -1) - break; /* success */ - - if (errno != EINTR) - exit_log_errno((e, "select() failed in call_server()")); - - /* retry if terminated by signal */ - } - - /* figure out what is interesting */ - - if (ndes == 0) - { - /* timer event */ - - DBG(DBG_CONTROL, - DBG_log(BLANK_FORMAT); - DBG_log("*time to handle event")); - - handle_timer_event(); - passert(GLOBALS_ARE_RESET()); - } - else - { - /* at least one file descriptor is ready */ - -#ifdef ADNS - if (adns_qfd != NULL_FD && FD_ISSET(adns_qfd, &writefds)) - { - passert(ndes > 0); - send_unsent_ADNS_queries(); - passert(GLOBALS_ARE_RESET()); - ndes--; - } - - if (adns_afd != NULL_FD && FD_ISSET(adns_afd, &readfds)) - { - passert(ndes > 0); - DBG(DBG_CONTROL, - DBG_log(BLANK_FORMAT); - DBG_log("*received adns message")); - handle_adns_answer(); - passert(GLOBALS_ARE_RESET()); - ndes--; - } -#endif /* ADNS*/ - - if (FD_ISSET(events_fd, &readfds)) - { - passert(ndes > 0); - DBG(DBG_CONTROL, - DBG_log(BLANK_FORMAT); - DBG_log("*handling asynchronous events")); - pluto->events->handle(pluto->events); - passert(GLOBALS_ARE_RESET()); - ndes--; - } - - for (ifp = interfaces; ifp != NULL; ifp = ifp->next) - { - if (FD_ISSET(ifp->fd, &readfds)) - { - /* comm_handle will print DBG_CONTROL intro, - * with more info than we have here. - */ - - passert(ndes > 0); - comm_handle(ifp); - passert(GLOBALS_ARE_RESET()); - ndes--; - } - } - - if (FD_ISSET(ctl_fd, &readfds)) - { - passert(ndes > 0); - DBG(DBG_CONTROL, - DBG_log(BLANK_FORMAT); - DBG_log("*received whack message")); - whack_handle(ctl_fd); - passert(GLOBALS_ARE_RESET()); - ndes--; - } - - passert(ndes == 0); - } - } -} - -/* - * Local Variables: - * c-basic-offset: 4 - * End Variables: - */ |