Copyright 1996, 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.6b12.orig/doc/syntax.txt mathopd-1.6b12/doc/syntax.txt --- mathopd-1.6b12.orig/doc/syntax.txt 2006-11-05 04:58:33.000000000 +0900 +++ mathopd-1.6b12/doc/syntax.txt 2012-02-17 22:22:13.000000000 +0900 @@ -143,5 +143,4 @@ socket-option-item: "rcvbuf" integer "sndbuf" integer - "v6only" flag "nodelay" flag diff -ur mathopd-1.6b12.orig/src/config.c mathopd-1.6b12/src/config.c --- mathopd-1.6b12.orig/src/config.c 2011-12-03 10:49:58.000000000 +0900 +++ mathopd-1.6b12/src/config.c 2012-02-17 22:23:06.000000000 +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) @@ -818,6 +831,7 @@ s->addr = 0; s->options = 0; s->port = 0; + s->sockets = 0; fam = AF_UNSPEC; if ((t = gettoken(p)) != t_open) return t; @@ -853,23 +867,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; @@ -1047,7 +1057,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.6b12.orig/src/core.c mathopd-1.6b12/src/core.c --- mathopd-1.6b12.orig/src/core.c 2011-12-16 06:39:08.000000000 +0900 +++ mathopd-1.6b12/src/core.c 2012-02-17 22:22:13.000000000 +0900 @@ -201,14 +201,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; } } @@ -263,7 +264,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; @@ -275,7 +276,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: @@ -662,16 +663,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; } @@ -707,14 +709,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.6b12.orig/src/main.c mathopd-1.6b12/src/main.c --- mathopd-1.6b12.orig/src/main.c 2012-02-03 21:43:24.000000000 +0900 +++ mathopd-1.6b12/src/main.c 2012-02-17 22:22:13.000000000 +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.6b12.orig/src/mathopd.h mathopd-1.6b12/src/mathopd.h --- mathopd-1.6b12.orig/src/mathopd.h 2007-08-24 02:54:29.000000000 +0900 +++ mathopd-1.6b12/src/mathopd.h 2012-02-17 22:22:13.000000000 +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 {