diff options
author | Reyk Floeter <reyk@esdenera.com> | 2015-01-03 21:06:57 +0100 |
---|---|---|
committer | Reyk Floeter <reyk@esdenera.com> | 2015-01-03 21:06:57 +0100 |
commit | 4f5dd228f08c132afdef71c1a5a124595905d8ae (patch) | |
tree | 653146e322b074f6a796a7b247b8113edcc943df | |
parent | 461ae7b2ed14e4c38ecf78d791138922a6c050f3 (diff) | |
download | httpd-4f5dd228f08c132afdef71c1a5a124595905d8ae.tar.gz httpd-4f5dd228f08c132afdef71c1a5a124595905d8ae.zip |
In the parent, only open a socket once per unique listen statement.
Fixes possible file descriptor exhaustion on configuration load time.
-rw-r--r-- | config.c | 15 | ||||
-rw-r--r-- | parse.y | 8 | ||||
-rw-r--r-- | server.c | 19 |
3 files changed, 34 insertions, 8 deletions
@@ -200,7 +200,9 @@ config_setserver(struct httpd *env, struct server *srv) n = -1; proc_range(ps, id, &n, &m); for (n = 0; n < m; n++) { - if ((fd = dup(srv->srv_s)) == -1) + if (srv->srv_s == -1) + fd = -1; + else if ((fd = dup(srv->srv_s)) == -1) return (-1); proc_composev_imsg(ps, id, n, IMSG_CFG_SERVER, fd, iov, c); @@ -211,9 +213,6 @@ config_setserver(struct httpd *env, struct server *srv) } } - close(srv->srv_s); - srv->srv_s = -1; - return (0); } @@ -356,8 +355,12 @@ config_getserver(struct httpd *env, struct imsg *imsg) if ((srv = server_byaddr((struct sockaddr *) &srv_conf.ss, srv_conf.port)) != NULL) { /* Add "host" to existing listening server */ - if (imsg->fd != -1) - close(imsg->fd); + if (imsg->fd != -1) { + if (srv->srv_s == -1) + srv->srv_s = imsg->fd; + else + close(imsg->fd); + } return (config_getserver_config(env, srv, imsg)); } @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.47 2015/01/03 15:49:18 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.48 2015/01/03 16:20:31 reyk Exp $ */ /* * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org> @@ -226,6 +226,7 @@ server : SERVER STRING { strlcpy(s->srv_conf.errorlog, HTTPD_ERROR_LOG, sizeof(s->srv_conf.errorlog)); s->srv_conf.id = ++last_server_id; + s->srv_s = -1; s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT; s->srv_conf.maxrequests = SERVER_MAXREQUESTS; s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY; @@ -493,6 +494,7 @@ serveroptsl : LISTEN ON STRING opttls port { /* A location entry uses the parent id */ s->srv_conf.id = srv->srv_conf.id; s->srv_conf.flags = SRVFLAG_LOCATION; + s->srv_s = -1; memcpy(&s->srv_conf.ss, &srv->srv_conf.ss, sizeof(s->srv_conf.ss)); s->srv_conf.port = srv->srv_conf.port; @@ -1742,8 +1744,11 @@ server_inherit(struct server *src, const char *name, fatal("out of memory"); dst->srv_conf.id = ++last_server_id; + dst->srv_s = -1; + if (last_server_id == INT_MAX) { yyerror("too many servers defined"); + serverconfig_free(&dst->srv_conf); free(dst); return (NULL); } @@ -1805,6 +1810,7 @@ server_inherit(struct server *src, const char *name, sizeof(dstl->srv_conf.ss)); dstl->srv_conf.port = addr->port; dstl->srv_conf.prefixlen = addr->prefixlen; + dstl->srv_s = -1; DPRINTF("adding location \"%s\" for \"%s[%u]\"", dstl->srv_conf.location, @@ -101,11 +101,27 @@ server_shutdown(void) int server_privinit(struct server *srv) { + struct server *s; + if (srv->srv_conf.flags & SRVFLAG_LOCATION) return (0); log_debug("%s: adding server %s", __func__, srv->srv_conf.name); + /* + * There's no need to open a new socket if a server with the + * same address already exists. + */ + TAILQ_FOREACH(s, env->sc_servers, srv_entry) { + if (s != srv && s->srv_s != -1 && + s->srv_conf.port == srv->srv_conf.port && + sockaddr_cmp((struct sockaddr *)&s->srv_conf.ss, + (struct sockaddr *)&srv->srv_conf.ss, + s->srv_conf.prefixlen) == 0) + return (0); + } + + /* Open listening socket in the privileged process */ if ((srv->srv_s = server_socket_listen(&srv->srv_conf.ss, srv->srv_conf.port, &srv->srv_conf)) == -1) return (-1); @@ -277,7 +293,8 @@ server_purge(struct server *srv) if (evtimer_initialized(&srv->srv_evt)) evtimer_del(&srv->srv_evt); - close(srv->srv_s); + if (srv->srv_s != -1) + close(srv->srv_s); TAILQ_REMOVE(env->sc_servers, srv, srv_entry); /* cleanup sessions */ |