diff options
Diffstat (limited to 'src/pluto/server.c')
-rw-r--r-- | src/pluto/server.c | 1434 |
1 files changed, 718 insertions, 716 deletions
diff --git a/src/pluto/server.c b/src/pluto/server.c index b0e158503..21f65f4f8 100644 --- a/src/pluto/server.c +++ b/src/pluto/server.c @@ -11,8 +11,6 @@ * 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. - * - * RCSID $Id: server.c 3252 2007-10-06 21:24:50Z andreas $ */ #include <stdio.h> @@ -27,7 +25,7 @@ #include <sys/socket.h> #include <sys/un.h> #ifdef SOLARIS -# include <sys/sockio.h> /* for Solaris 2.6: defines SIOCGIFCONF */ +# include <sys/sockio.h> /* for Solaris 2.6: defines SIOCGIFCONF */ #endif #include <netinet/in.h> #include <arpa/inet.h> @@ -38,7 +36,7 @@ #include <net/if.h> #include <sys/ioctl.h> #include <resolv.h> -#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */ +#include <arpa/nameser.h> /* missing from <resolv.h> on old systems */ #include <sys/queue.h> #include <freeswan.h> @@ -55,9 +53,9 @@ #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 "adns.h" /* needs <resolv.h> */ +#include "dnskey.h" /* needs keys.h and adns.h */ +#include "whack.h" /* for RC_LOG_SERIOUS */ #include <pfkeyv2.h> #include <pfkey.h> @@ -68,10 +66,10 @@ * Server main loop and socket initialization routines. */ -static const int on = TRUE; /* by-reference parameter; constant, we hope */ +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 */ +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 */ @@ -86,121 +84,121 @@ struct sockaddr_un info_addr= { AF_UNIX, DEFAULT_CTLBASE INFO_SUFFIX }; 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)); + 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); + /* 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? */ +bool listening = FALSE; /* should we pay attention to IKE messages? */ -struct iface *interfaces = NULL; /* public interfaces */ +struct iface *interfaces = NULL; /* public interfaces */ /* Initialize the interface sockets. */ static void mark_ifaces_dead(void) { - struct iface *p; + struct iface *p; - for (p = interfaces; p != NULL; p = p->next) - p->change = IFN_DELETE; + 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; + 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) + for (p = interfaces; p != NULL; p = p->next) { - some_new = TRUE; + 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 (some_dead) { - if (p->change == IFN_DELETE) - { - *pp = p->next; /* advance *pp */ - pfree(p->vname); - pfree(p->rname); - close(p->fd); - pfree(p); - } - else - { - pp = &p->next; /* advance pp */ - } + 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(); + + /* 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(); + 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; + ip_address addr; + char name[IFNAMSIZ + 20]; /* what would be a safe size? */ + struct raw_iface *next; }; /* Called to handle --interface <ifname> @@ -212,15 +210,15 @@ static int pluto_ifn_roof = 0; bool use_interface(const char *rifn) { - if (pluto_ifn_roof >= (int)elemsof(pluto_ifn)) - { - return FALSE; - } - else - { - pluto_ifn[pluto_ifn_roof++] = rifn; - return TRUE; - } + if (pluto_ifn_roof >= (int)countof(pluto_ifn)) + { + return FALSE; + } + else + { + pluto_ifn[pluto_ifn_roof++] = rifn; + return TRUE; + } } #ifndef IPSECDEVPREFIX @@ -230,538 +228,542 @@ use_interface(const char *rifn) 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(PF_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 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(PF_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 */ { - int i; + ip_address any; - 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 */ + 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()")); } - /* 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 */ + /* Get local interfaces. See netdevice(7). */ + ifconf.ifc_len = sizeof(buf); + ifconf.ifc_buf = (void *) buf; + zero(buf); - /* ignore unconfigured interfaces */ - if (rs->sin_addr.s_addr == 0) - continue; + if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) + exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); - happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr) - , AF_INET, &ri.addr)); + /* 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; - DBG(DBG_CONTROL, DBG_log("found %s with address %s" - , ri.name, ip_str(&ri.addr))); - ri.next = rifaces; - rifaces = clone_thing(ri, "struct raw_iface"); - } + /* ignore all but AF_INET interfaces */ + if (rs->sin_family != AF_INET) + continue; /* not interesting */ - close(master_sock); + /* build a NUL-terminated copy of the rname field */ + memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ); + ri.name[IFNAMSIZ] = '\0'; - return rifaces; + /* 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 (;;) + /* 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) { - 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, "struct raw_iface"); - } + 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); } - fclose(proc_sock); - } - return rifaces; + return rifaces; } #if 1 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; + 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; - } + if (fd < 0) + { + log_errno((e, "socket() in process_raw_ifaces()")); + return -1; + } #if 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); + /* 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); + } } - } -#endif - - 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 -#if defined(linux) && defined(KERNEL26_SUPPORT) - if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX) - { - 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) + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { - level = IPPROTO_IPV6; - opt = IPV6_IPSEC_POLICY; + log_errno((e, "fcntl(,, FD_CLOEXEC) in process_raw_ifaces()")); + close(fd); + return -1; } - else + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR + , (const void *)&on, sizeof(on)) < 0) { - level = IPPROTO_IP; - opt = IP_IPSEC_POLICY; + log_errno((e, "setsockopt SO_REUSEADDR in process_raw_ifaces()")); + close(fd); + return -1; } - if (setsockopt(fd, level, opt - , &policy, sizeof(policy)) < 0) + /* 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 IPSEC_POLICY in process_raw_ifaces()")); - close(fd); - return -1; + log_errno((e, "setsockopt IP_RECVERR in process_raw_ifaces()")); + close(fd); + return -1; } +#endif - policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; + /* 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 - if (setsockopt(fd, level, opt - , &policy, sizeof(policy)) < 0) +#if defined(linux) && defined(KERNEL26_SUPPORT) + if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX) { - log_errno((e, "setsockopt IPSEC_POLICY in process_raw_ifaces()")); - close(fd); - return -1; + 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; + } } - } #endif - 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; + 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; } #endif static void process_raw_ifaces(struct raw_iface *rifaces) { - struct raw_iface *ifp; - - /* Find all virtual/real interface pairs. - * For each real interface... - */ - for (ifp = rifaces; ifp != NULL; ifp = ifp->next) - { - struct raw_iface *v = NULL; /* matching ipsecX interface */ - struct raw_iface fake_v; - bool after = FALSE; /* has vfp passed ifp on the list? */ - bool bad = FALSE; - struct raw_iface *vfp; - - /* ignore if virtual (ipsec*) interface */ - if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0) - continue; - - for (vfp = rifaces; vfp != NULL; vfp = vfp->next) + struct raw_iface *ifp; + + /* Find all virtual/real interface pairs. + * For each real interface... + */ + for (ifp = rifaces; ifp != NULL; ifp = ifp->next) { - if (vfp == ifp) - { - after = TRUE; - } - else if (sameaddr(&ifp->addr, &vfp->addr)) - { - /* Different entries with matching IP addresses. - * Many interesting cases. - */ - if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1) == 0) + struct raw_iface *v = NULL; /* matching ipsecX interface */ + struct raw_iface fake_v; + bool after = FALSE; /* has vfp passed ifp on the list? */ + bool bad = FALSE; + struct raw_iface *vfp; + + /* ignore if virtual (ipsec*) interface */ + if (strneq(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1)) { - if (v != NULL && !streq(v->name, vfp->name)) - { - loglog(RC_LOG_SERIOUS - , "ipsec interfaces %s and %s share same address %s" - , v->name, vfp->name, ip_str(&ifp->addr)); - bad = TRUE; - } - else - { - v = vfp; /* current winner */ - } + continue; } - else + + for (vfp = rifaces; vfp != NULL; vfp = vfp->next) { - /* ugh: a second real interface with the same IP address - * "after" allows us to avoid double reporting. - */ -#if defined(linux) && defined(KERNEL26_SUPPORT) - if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX) - { - if (after) + if (vfp == ifp) { - bad = TRUE; - break; + after = TRUE; } - continue; - } + else if (sameaddr(&ifp->addr, &vfp->addr)) + { + /* Different entries with matching IP addresses. + * Many interesting cases. + */ + if (strneq(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX)-1)) + { + if (v != NULL && !streq(v->name, vfp->name)) + { + loglog(RC_LOG_SERIOUS + , "ipsec interfaces %s and %s share same address %s" + , v->name, vfp->name, ip_str(&ifp->addr)); + bad = TRUE; + } + else + { + v = vfp; /* current winner */ + } + } + else + { + /* ugh: a second real interface with the same IP address + * "after" allows us to avoid double reporting. + */ +#if defined(linux) && defined(KERNEL26_SUPPORT) + if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX) + { + if (after) + { + bad = TRUE; + break; + } + continue; + } #endif - if (after) - { - loglog(RC_LOG_SERIOUS - , "IP interfaces %s and %s share address %s!" - , ifp->name, vfp->name, ip_str(&ifp->addr)); - } - bad = TRUE; + if (after) + { + loglog(RC_LOG_SERIOUS + , "IP interfaces %s and %s share address %s!" + , ifp->name, vfp->name, ip_str(&ifp->addr)); + } + bad = TRUE; + } + } } - } - } - if (bad) - continue; + if (bad) + continue; #if defined(linux) && defined(KERNEL26_SUPPORT) - if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX) - { - v = ifp; - goto add_entry; - } + if (!no_klips && kernel_ops->type == KERNEL_TYPE_LINUX) + { + v = ifp; + goto add_entry; + } #endif - /* what if we didn't find a virtual interface? */ - if (v == NULL) - { - if (no_klips) - { - /* kludge for testing: invent a virtual device */ - static const char fvp[] = "virtual"; - fake_v = *ifp; - passert(sizeof(fake_v.name) > sizeof(fvp)); - strcpy(fake_v.name, fvp); - addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1 - , sizeof(fake_v.name) - (sizeof(fvp) - 1)); - v = &fake_v; - } - else - { - DBG(DBG_CONTROL, - DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored" - , ifp->name, ip_str(&ifp->addr))); - continue; - } - } + /* what if we didn't find a virtual interface? */ + if (v == NULL) + { + if (no_klips) + { + /* kludge for testing: invent a virtual device */ + static const char fvp[] = "virtual"; + fake_v = *ifp; + passert(sizeof(fake_v.name) > sizeof(fvp)); + strcpy(fake_v.name, fvp); + addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1 + , sizeof(fake_v.name) - (sizeof(fvp) - 1)); + v = &fake_v; + } + else + { + DBG(DBG_CONTROL, + DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored" + , ifp->name, ip_str(&ifp->addr))); + continue; + } + } - /* We've got all we need; see if this is a new thing: - * search old interfaces list. - */ + /* We've got all we need; see if this is a new thing: + * search old interfaces list. + */ #if defined(linux) && defined(KERNEL26_SUPPORT) add_entry: #endif - { - 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 = alloc_thing(struct iface, "struct iface"); - q->rname = clone_str(ifp->name, "real device name"); - q->vname = clone_str(v->name, "virtual device 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 = alloc_thing(struct iface, "struct iface"); - q->rname = clone_str(ifp->name, "real device name"); - q->vname = clone_str(v->name, "virtual device 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; - } + struct iface **p = &interfaces; - /* 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)) + for (;;) { - q->change = IFN_KEEP; - } - } - break; + 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 (;;) */ } - - /* try again */ - p = &q->next; - } /* for (;;) */ } - } - /* delete the raw interfaces list */ - while (rifaces != NULL) - { - struct raw_iface *t = rifaces; + /* delete the raw interfaces list */ + while (rifaces != NULL) + { + struct raw_iface *t = rifaces; - rifaces = t->next; - pfree(t); - } + rifaces = t->next; + free(t); + } } void find_ifaces(void) { - mark_ifaces_dead(); - process_raw_ifaces(find_raw_ifaces4()); - process_raw_ifaces(find_raw_ifaces6()); + mark_ifaces_dead(); + process_raw_ifaces(find_raw_ifaces4()); + process_raw_ifaces(find_raw_ifaces6()); - free_dead_ifaces(); /* ditch remaining old entries */ + free_dead_ifaces(); /* ditch remaining old entries */ - if (interfaces == NULL) - loglog(RC_LOG_SERIOUS, "no public interfaces found"); + if (interfaces == NULL) + loglog(RC_LOG_SERIOUS, "no public interfaces found"); } void show_ifaces_status(void) { - struct iface *p; + 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))); + 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 %s" - , bitnamesof(debug_bit_names, cur_debugging)); + whack_log(RC_COMMENT, "debug options: %s" + , bitnamesof(debug_bit_names, cur_debugging)); #endif } @@ -770,7 +772,7 @@ static volatile sig_atomic_t sighupflag = FALSE; static void huphandler(int sig UNUSED) { - sighupflag = TRUE; + sighupflag = TRUE; } static volatile sig_atomic_t sigtermflag = FALSE; @@ -778,7 +780,7 @@ static volatile sig_atomic_t sigtermflag = FALSE; static void termhandler(int sig UNUSED) { - sigtermflag = TRUE; + sigtermflag = TRUE; } /* call_server listens for incoming ISAKMP packets and Whack messages, @@ -787,206 +789,206 @@ termhandler(int sig UNUSED) void call_server(void) { - struct iface *ifp; + struct iface *ifp; - /* catch SIGHUP and SIGTERM */ - { - int r; - struct sigaction act; + /* 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); + passert(r == 0); + } - 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); + for (;;) + { + fd_set readfds; + fd_set writefds; + int ndes; - act.sa_handler = &termhandler; - r = sigaction(SIGTERM, &act, NULL); - passert(r == 0); - } + /* wait for next interesting thing */ - for (;;) - { - fd_set readfds; - fd_set writefds; - int ndes; + for (;;) + { + long next_time = next_event(); /* time to any pending timer event */ + int maxfd = ctl_fd; - /* wait for next interesting thing */ + if (sigtermflag) + exit_pluto(0); - 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); - - /* 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); - } + 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); + + /* 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); + } #ifdef KLIPS - if (!no_klips) - { - int fd = *kernel_ops->async_fdp; - - if (kernel_ops->process_queue) - kernel_ops->process_queue(); - if (maxfd < fd) - maxfd = fd; - passert(!FD_ISSET(fd, &readfds)); - FD_SET(fd, &readfds); - } + if (!no_klips) + { + int fd = *kernel_ops->async_fdp; + + if (kernel_ops->process_queue) + kernel_ops->process_queue(); + if (maxfd < fd) + maxfd = fd; + passert(!FD_ISSET(fd, &readfds)); + FD_SET(fd, &readfds); + } #endif - 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 */ + 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); + } + } - struct timeval tm; + if (next_time == -1) + { + /* select without timer */ - tm.tv_sec = next_time; - tm.tv_usec = 0; - ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm); - } + 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 */ - if (ndes != -1) - break; /* success */ + struct timeval tm; - if (errno != EINTR) - exit_log_errno((e, "select() failed in call_server()")); + tm.tv_sec = next_time; + tm.tv_usec = 0; + ndes = select(maxfd + 1, &readfds, &writefds, NULL, &tm); + } - /* retry if terminated by signal */ - } + if (ndes != -1) + break; /* success */ - /* figure out what is interesting */ + if (errno != EINTR) + exit_log_errno((e, "select() failed in call_server()")); - if (ndes == 0) - { - /* timer event */ + /* retry if terminated by signal */ + } - DBG(DBG_CONTROL, - DBG_log(BLANK_FORMAT); - DBG_log("*time to handle event")); + /* figure out what is interesting */ - handle_timer_event(); - passert(GLOBALS_ARE_RESET()); - } - else - { - /* at least one file descriptor is ready */ - - 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--; - } + 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 */ + + 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--; + } #ifdef KLIPS - if (!no_klips && FD_ISSET(*kernel_ops->async_fdp, &readfds)) - { - passert(ndes > 0); - DBG(DBG_CONTROL, - DBG_log(BLANK_FORMAT); - DBG_log("*received kernel message")); - kernel_ops->process_msg(); - passert(GLOBALS_ARE_RESET()); - ndes--; - } + if (!no_klips && FD_ISSET(*kernel_ops->async_fdp, &readfds)) + { + passert(ndes > 0); + DBG(DBG_CONTROL, + DBG_log(BLANK_FORMAT); + DBG_log("*received kernel message")); + kernel_ops->process_msg(); + passert(GLOBALS_ARE_RESET()); + ndes--; + } #endif - 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--; + 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); } - } - - 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); } - } } /* |