/* * Copyright 1996 - 2005 Michiel Boland. * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ diff -ur mathopd-1.6b9/doc/syntax.txt mathopd/doc/syntax.txt --- mathopd-1.6b9/doc/syntax.txt 2006-11-05 04:58:33.000000000 +0900 +++ mathopd/doc/syntax.txt 2009-12-09 12:42:08.868791000 +0900 @@ -143,5 +143,4 @@ socket-option-item: "rcvbuf" integer "sndbuf" integer - "v6only" flag "nodelay" flag diff -ur mathopd-1.6b9/src/config.c mathopd/src/config.c --- mathopd-1.6b9/src/config.c 2007-07-08 01:04:12.000000000 +0900 +++ mathopd/src/config.c 2009-12-09 12:42:08.868791000 +0900 @@ -69,7 +69,7 @@ int line; }; -static int num_servers; +static int num_server_sockets; static struct control *controls; static struct virtual *virtuals; @@ -753,13 +753,6 @@ what = SO_INT; } else #endif -#ifdef IPV6_V6ONLY - if (!strcasecmp(p->tokbuf, "v6only")) { - l = IPPROTO_IPV6; - n = IPV6_V6ONLY; - what = SO_FLAG; - } else -#endif #ifdef TCP_NODELAY if (!strcasecmp(p->tokbuf, "nodelay")) { l = IPPROTO_TCP; @@ -802,11 +795,31 @@ return 0; } +static const char *configsub_server_socket(struct addrinfo *res, struct server_socket **ss) +{ + struct server_socket *s; + + if ((s = malloc(sizeof *s)) == 0) + return e_memory; + s->server_addr = malloc(res->ai_addrlen); + if (s->server_addr == 0) + return e_memory; + s->family = res->ai_family; + s->socktype = res->ai_socktype; + s->protocol = res->ai_protocol; + memcpy(s->server_addr, res->ai_addr, res->ai_addrlen); + s->server_addrlen = res->ai_addrlen; + num_server_sockets++; + s->next = *ss; + *ss = s; + return 0; +} + static const char *config_server(struct configuration *p, struct server **ss) { struct server *s; const char *t; - struct addrinfo hints, *res; + struct addrinfo hints, *res0, *res; int rv, fam; if ((s = malloc(sizeof *s)) == 0) @@ -820,6 +833,7 @@ if (s->port == 0) return e_memory; s->options = 0; + s->sockets = 0; fam = AF_UNSPEC; if ((t = gettoken(p)) != t_open) return t; @@ -850,23 +864,19 @@ hints.ai_family = fam; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; - rv = getaddrinfo(s->addr, s->port, &hints, &res); + rv = getaddrinfo(s->addr, s->port, &hints, &res0); if (rv) { fprintf(stderr, "address %s port %s: %s\n", s->addr ? s->addr : "[any]", s->port, gai_strerror(rv)); return e_illegalport; } - s->server_addr = malloc(res->ai_addrlen); - if (s->server_addr == 0) { - freeaddrinfo(res); - return e_memory; + for (res = res0; res; res = res->ai_next) { + t = configsub_server_socket(res, &s->sockets); + if (t) { + freeaddrinfo(res0); + return t; + } } - s->family = res->ai_family; - s->socktype = res->ai_socktype; - s->protocol = res->ai_protocol; - memcpy(s->server_addr, res->ai_addr, res->ai_addrlen); - s->server_addrlen = res->ai_addrlen; - freeaddrinfo(res); - num_servers++; + freeaddrinfo(res0); s->next = *ss; *ss = s; return 0; @@ -1044,7 +1054,7 @@ int init_buffers(void) { - if (init_pollfds(2 * tuning.num_connections + num_servers) == -1) + if (init_pollfds(2 * tuning.num_connections + num_server_sockets) == -1) return -1; if (init_connections(tuning.num_connections) == -1) return -1; diff -ur mathopd-1.6b9/src/core.c mathopd/src/core.c --- mathopd-1.6b9/src/core.c 2007-07-08 01:04:12.000000000 +0900 +++ mathopd/src/core.c 2009-12-09 12:42:08.868791000 +0900 @@ -199,14 +199,15 @@ static void close_servers(void) { struct server *s; + struct server_socket *ss; - s = servers; - while (s) { - if (s->fd != -1) { - close(s->fd); - s->fd = -1; + for (s = servers; s; s = s->next) { + for (ss = s->sockets; ss; ss = ss->next) { + if (ss->fd != -1) { + close(ss->fd); + ss->fd = -1; + } } - s = s->next; } } @@ -261,7 +262,7 @@ p->ceiling = p->floor + n; } -static int accept_connection(struct server *s) +static int accept_connection(struct server *s, int listenfd) { struct sockaddr_storage sa_remote, sa_local; socklen_t l; @@ -273,7 +274,7 @@ if (cn == 0) return 0; l = sizeof sa_remote; - fd = accept(s->fd, (struct sockaddr *) &sa_remote, &l); + fd = accept(listenfd, (struct sockaddr *) &sa_remote, &l); if (fd == -1) switch (errno) { case EAGAIN: @@ -656,16 +657,17 @@ static int setup_server_pollfds(int n) { struct server *s; + struct server_socket *ss; - s = servers; - while (s) { - if (s->fd != -1) { - pollfds[n].events = POLLIN; - pollfds[n].fd = s->fd; - s->pollno = n++; - } else - s->pollno = -1; - s = s->next; + for (s = servers; s; s = s->next) { + for (ss = s->sockets; ss; ss = ss->next) { + if (ss->fd != -1) { + pollfds[n].events = POLLIN; + pollfds[n].fd = ss->fd; + ss->pollno = n++; + } else + ss->pollno = -1; + } } return n; } @@ -701,14 +703,15 @@ static int run_servers(void) { struct server *s; + struct server_socket *ss; - s = servers; - while (s) { - if (s->pollno != -1) - if (pollfds[s->pollno].revents & POLLIN) - if (accept_connection(s) == -1) - return -1; - s = s->next; + for (s = servers; s; s = s->next) { + for (ss = s->sockets; ss; ss = ss->next) { + if (ss->pollno != -1) + if (pollfds[ss->pollno].revents & POLLIN) + if (accept_connection(s, ss->fd) == -1) + return -1; + } } return 0; } diff -ur mathopd-1.6b9/src/main.c mathopd/src/main.c --- mathopd-1.6b9/src/main.c 2007-07-21 20:38:23.000000000 +0900 +++ mathopd/src/main.c 2009-12-09 12:42:08.868791000 +0900 @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -99,31 +100,48 @@ exit(1); } -static void startup_server(struct server *s) +static void startup_server_socket(struct server *s, struct server_socket *ss) { int onoff; struct server_sockopts *o; - s->fd = socket(s->family, s->socktype, s->protocol); - if (s->fd == -1) + ss->fd = socket(ss->family, ss->socktype, ss->protocol); + if (ss->fd == -1) die("socket", 0); onoff = 1; - if (setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, &onoff, sizeof onoff) == -1) + if (setsockopt(ss->fd, SOL_SOCKET, SO_REUSEADDR, &onoff, sizeof onoff) == -1) die("setsockopt", "cannot set re-use flag"); + if (ss->family == AF_INET6) { +#ifdef IPV6_V6ONLY + onoff = 1; + if (setsockopt(ss->fd, IPPROTO_IPV6, IPV6_V6ONLY, &onoff, sizeof onoff) == -1) + die("setsockopt", "cannot set v6only flag"); +#else + die(0, "IPV6_V6ONLY is needed for IPv6 servers but not defined"); +#endif + } o = s->options; while (o) { - if (setsockopt(s->fd, o->ss_level, o->ss_optname, o->ss_optval, o->ss_optlen) == -1) + if (setsockopt(ss->fd, o->ss_level, o->ss_optname, o->ss_optval, o->ss_optlen) == -1) die("setsockopt", 0); o = o->next; } - fcntl(s->fd, F_SETFD, FD_CLOEXEC); - fcntl(s->fd, F_SETFL, O_NONBLOCK); - if (bind(s->fd, s->server_addr, s->server_addrlen) == -1) + fcntl(ss->fd, F_SETFD, FD_CLOEXEC); + fcntl(ss->fd, F_SETFL, O_NONBLOCK); + if (bind(ss->fd, ss->server_addr, ss->server_addrlen) == -1) die("bind", "cannot start up server at %s port %s", s->addr ? s->addr : "[any]", s->port); - if (listen(s->fd, s->backlog) == -1) + if (listen(ss->fd, s->backlog) == -1) die("listen", 0); } +static void startup_server(struct server *s) +{ + struct server_socket *ss; + + for (ss = s->sockets; ss; ss = ss->next) + startup_server_socket(s, ss); +} + static void sighandler(int sig) { /* diff -ur mathopd-1.6b9/src/mathopd.h mathopd/src/mathopd.h --- mathopd-1.6b9/src/mathopd.h 2007-07-08 01:04:12.000000000 +0900 +++ mathopd/src/mathopd.h 2009-12-09 12:42:08.868791000 +0900 @@ -199,22 +199,27 @@ struct server_sockopts *next; }; -struct server { +struct server_socket { int fd; size_t server_addrlen; struct sockaddr *server_addr; + int pollno; + int family; + int socktype; + int protocol; + struct server_socket *next; +}; + +struct server { struct virtual *children; struct control *controls; struct server *next; - int pollno; struct vserver *vservers; unsigned long backlog; char *addr; char *port; - int family; - int socktype; - int protocol; struct server_sockopts *options; + struct server_socket *sockets; }; struct request_header {