aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2014-07-25 19:28:21 +0200
committerReyk Floeter <reyk@esdenera.com>2014-07-25 19:28:21 +0200
commita357341f2687ab20e50640ee9ba995a8a6ca443b (patch)
tree71fe08208bc2064e39765827e64aa2678ad8ad1d
parent6801bf4ff6b4768d779849eab9b36361e2782d13 (diff)
downloadhttpd-a357341f2687ab20e50640ee9ba995a8a6ca443b.tar.gz
httpd-a357341f2687ab20e50640ee9ba995a8a6ca443b.zip
sync
-rw-r--r--config.c53
-rw-r--r--httpd.c100
-rw-r--r--httpd.conf.514
-rw-r--r--httpd.h23
-rw-r--r--parse.y31
-rw-r--r--server.c56
-rw-r--r--server_file.c8
-rw-r--r--server_http.c28
8 files changed, 271 insertions, 42 deletions
diff --git a/config.c b/config.c
index 8dd395d..eb9e003 100644
--- a/config.c
+++ b/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.3 2014/07/23 13:26:39 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.4 2014/07/25 16:23:19 reyk Exp $ */
/*
* Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -46,6 +46,9 @@
#include "httpd.h"
+int config_getserver_config(struct httpd *, struct server *,
+ struct imsg *);
+
int
config_init(struct httpd *env)
{
@@ -205,27 +208,67 @@ config_setserver(struct httpd *env, struct server *srv)
}
int
+config_getserver_config(struct httpd *env, struct server *srv,
+ struct imsg *imsg)
+{
+#ifdef DEBUG
+ struct privsep *ps = env->sc_ps;
+#endif
+ struct server_config *srv_conf;
+ u_int8_t *p = imsg->data;
+
+ if ((srv_conf = calloc(1, sizeof(*srv_conf))) == NULL)
+ return (-1);
+
+ IMSG_SIZE_CHECK(imsg, srv_conf);
+ memcpy(srv_conf, p, sizeof(*srv_conf));
+
+ TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
+
+ DPRINTF("%s: %s %d received configuration \"%s\", parent \"%s\"",
+ __func__, ps->ps_title[privsep_process], ps->ps_instance,
+ srv_conf->name, srv->srv_conf.name);
+
+ return (0);
+}
+
+int
config_getserver(struct httpd *env, struct imsg *imsg)
{
#ifdef DEBUG
struct privsep *ps = env->sc_ps;
#endif
struct server *srv;
+ struct server_config srv_conf;
u_int8_t *p = imsg->data;
size_t s;
+ IMSG_SIZE_CHECK(imsg, &srv_conf);
+ memcpy(&srv_conf, p, sizeof(srv_conf));
+ s = sizeof(srv_conf);
+
+ /* Check if server with matching listening socket already exists */
+ if ((srv = server_byaddr((struct sockaddr *)
+ &srv_conf.ss)) != NULL) {
+ /* Add "host" to existing listening server */
+ close(imsg->fd);
+ return (config_getserver_config(env,
+ srv, imsg));
+ }
+
+ /* Otherwise create a new server */
if ((srv = calloc(1, sizeof(*srv))) == NULL) {
close(imsg->fd);
return (-1);
}
- IMSG_SIZE_CHECK(imsg, &srv->srv_conf);
- memcpy(&srv->srv_conf, p, sizeof(srv->srv_conf));
- s = sizeof(srv->srv_conf);
-
+ memcpy(&srv->srv_conf, &srv_conf, sizeof(srv->srv_conf));
srv->srv_s = imsg->fd;
SPLAY_INIT(&srv->srv_clients);
+ TAILQ_INIT(&srv->srv_hosts);
+
+ TAILQ_INSERT_TAIL(&srv->srv_hosts, &srv->srv_conf, entry);
TAILQ_INSERT_TAIL(env->sc_servers, srv, srv_entry);
DPRINTF("%s: %s %d received configuration \"%s\"", __func__,
diff --git a/httpd.c b/httpd.c
index c87c2ad..22ae5f9 100644
--- a/httpd.c
+++ b/httpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.c,v 1.6 2014/07/23 23:10:27 reyk Exp $ */
+/* $OpenBSD: httpd.c,v 1.8 2014/07/25 16:23:19 reyk Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -580,6 +580,102 @@ get_data(u_int8_t *ptr, size_t len)
}
int
+sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
+{
+ struct sockaddr_in *a4, *b4;
+ struct sockaddr_in6 *a6, *b6;
+ u_int32_t av[4], bv[4], mv[4];
+
+ if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
+ return (0);
+ else if (a->sa_family > b->sa_family)
+ return (1);
+ else if (a->sa_family < b->sa_family)
+ return (-1);
+
+ if (prefixlen == -1)
+ memset(&mv, 0xff, sizeof(mv));
+
+ switch (a->sa_family) {
+ case AF_INET:
+ a4 = (struct sockaddr_in *)a;
+ b4 = (struct sockaddr_in *)b;
+
+ av[0] = a4->sin_addr.s_addr;
+ bv[0] = b4->sin_addr.s_addr;
+ if (prefixlen != -1)
+ mv[0] = prefixlen2mask(prefixlen);
+
+ if ((av[0] & mv[0]) > (bv[0] & mv[0]))
+ return (1);
+ if ((av[0] & mv[0]) < (bv[0] & mv[0]))
+ return (-1);
+ break;
+ case AF_INET6:
+ a6 = (struct sockaddr_in6 *)a;
+ b6 = (struct sockaddr_in6 *)b;
+
+ memcpy(&av, &a6->sin6_addr.s6_addr, 16);
+ memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
+ if (prefixlen != -1)
+ prefixlen2mask6(prefixlen, mv);
+
+ if ((av[3] & mv[3]) > (bv[3] & mv[3]))
+ return (1);
+ if ((av[3] & mv[3]) < (bv[3] & mv[3]))
+ return (-1);
+ if ((av[2] & mv[2]) > (bv[2] & mv[2]))
+ return (1);
+ if ((av[2] & mv[2]) < (bv[2] & mv[2]))
+ return (-1);
+ if ((av[1] & mv[1]) > (bv[1] & mv[1]))
+ return (1);
+ if ((av[1] & mv[1]) < (bv[1] & mv[1]))
+ return (-1);
+ if ((av[0] & mv[0]) > (bv[0] & mv[0]))
+ return (1);
+ if ((av[0] & mv[0]) < (bv[0] & mv[0]))
+ return (-1);
+ break;
+ }
+
+ return (0);
+}
+
+u_int32_t
+prefixlen2mask(u_int8_t prefixlen)
+{
+ if (prefixlen == 0)
+ return (0);
+
+ if (prefixlen > 32)
+ prefixlen = 32;
+
+ return (htonl(0xffffffff << (32 - prefixlen)));
+}
+
+struct in6_addr *
+prefixlen2mask6(u_int8_t prefixlen, u_int32_t *mask)
+{
+ static struct in6_addr s6;
+ int i;
+
+ if (prefixlen > 128)
+ prefixlen = 128;
+
+ bzero(&s6, sizeof(s6));
+ for (i = 0; i < prefixlen / 8; i++)
+ s6.s6_addr[i] = 0xff;
+ i = prefixlen % 8;
+ if (i)
+ s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
+
+ memcpy(mask, &s6, sizeof(s6));
+
+ return (&s6);
+}
+
+int
accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
int reserve, volatile int *counter)
{
@@ -720,8 +816,6 @@ kv_purge(struct kvtree *keys)
void
kv_free(struct kv *kv)
{
- if (kv->kv_type == KEY_TYPE_NONE)
- return;
if (kv->kv_key != NULL) {
free(kv->kv_key);
}
diff --git a/httpd.conf.5 b/httpd.conf.5
index afef082..cbd1004 100644
--- a/httpd.conf.5
+++ b/httpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.conf.5,v 1.5 2014/07/22 19:03:21 jmc Exp $
+.\" $OpenBSD: httpd.conf.5,v 1.6 2014/07/25 15:47:11 reyk Exp $
.\"
.\" Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 22 2014 $
+.Dd $Mdocdate: July 25 2014 $
.Dt HTTPD.CONF 5
.Os
.Sh NAME
@@ -115,6 +115,16 @@ The following general table options are available:
.Bl -tag -width Ds
.It Ic listen on Ar address Ic port Ar number
Set the listen address and port.
+.It Ic root Ar directory
+Set the document root of the server.
+The
+.Ar directory
+is a pathname within the
+.Xr chroot 2
+root directory of
+.Nm httpd .
+If not specified, it defaults to
+.Pa /htdocs .
.El
.Sh TYPES
Configure the supported media types.
diff --git a/httpd.h b/httpd.h
index ae275bf..cc10bfb 100644
--- a/httpd.h
+++ b/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.7 2014/07/23 19:03:56 reyk Exp $ */
+/* $OpenBSD: httpd.h,v 1.12 2014/07/25 16:23:19 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -123,6 +123,7 @@ struct portrange {
struct address {
struct sockaddr_storage ss;
int ipproto;
+ int prefixlen;
struct portrange port;
char ifname[IFNAMSIZ];
TAILQ_ENTRY(address) entry;
@@ -252,8 +253,9 @@ struct privsep_proc {
struct client {
u_int32_t clt_id;
pid_t clt_pid;
- void *clt_server;
- u_int32_t clt_serverid;
+ void *clt_srv;
+ void *clt_srv_conf;
+ u_int32_t clt_srv_id;
int clt_s;
in_port_t clt_port;
@@ -287,14 +289,20 @@ struct server_config {
u_int32_t id;
u_int32_t flags;
char name[MAXHOSTNAMELEN];
+ char docroot[MAXPATHLEN];
in_port_t port;
struct sockaddr_storage ss;
+ int prefixlen;
struct timeval timeout;
+
+ TAILQ_ENTRY(server_config) entry;
};
+TAILQ_HEAD(serverhosts, server_config);
struct server {
TAILQ_ENTRY(server) srv_entry;
struct server_config srv_conf;
+ struct serverhosts srv_hosts;
u_int8_t srv_tcpflags;
int srv_tcpbufsiz;
@@ -303,10 +311,6 @@ struct server {
u_int8_t srv_tcpipminttl;
int srv_s;
- struct bufferevent *srv_bev;
- int srv_dsts;
- struct bufferevent *srv_dstbev;
-
struct event srv_ev;
struct event srv_evt;
@@ -382,6 +386,8 @@ int server_bufferevent_write_chunk(struct client *,
int server_bufferevent_add(struct event *, int);
int server_bufferevent_write(struct client *, void *, size_t);
void server_inflight_dec(struct client *, const char *);
+struct server *
+ server_byaddr(struct sockaddr *);
SPLAY_PROTOTYPE(client_tree, client, clt_nodes, server_client_cmp);
@@ -422,6 +428,9 @@ int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
void socket_rlimit(int);
char *get_string(u_int8_t *, size_t);
void *get_data(u_int8_t *, size_t);
+int sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
+struct in6_addr *prefixlen2mask6(u_int8_t, u_int32_t *);
+u_int32_t prefixlen2mask(u_int8_t);
int accept_reserve(int, struct sockaddr *, socklen_t *, int,
volatile int *);
struct kv *kv_add(struct kvtree *, char *, char *);
diff --git a/parse.y b/parse.y
index be355af..1105e55 100644
--- a/parse.y
+++ b/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.3 2014/07/23 22:02:02 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.7 2014/07/25 17:04:47 reyk Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -126,7 +126,7 @@ typedef struct {
%}
-%token ALL PORT LISTEN PREFORK SERVER ERROR INCLUDE LOG VERBOSE ON TYPES
+%token ALL PORT LISTEN PREFORK ROOT SERVER ERROR LOG VERBOSE ON TYPES
%token UPDATES INCLUDE
%token <v.string> STRING
%token <v.number> NUMBER
@@ -215,6 +215,8 @@ server : SERVER STRING {
}
free($2);
+ strlcpy(s->srv_conf.docroot, HTTPD_DOCROOT,
+ sizeof(s->srv_conf.docroot));
s->srv_conf.id = ++last_server_id;
s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT;
@@ -262,8 +264,19 @@ serveroptsl : LISTEN ON STRING port {
memcpy(&srv->srv_conf.ss, &h->ss,
sizeof(s->srv_conf.ss));
s->srv_conf.port = h->port.val[0];
+ s->srv_conf.prefixlen = h->prefixlen;
host_free(&al);
}
+ | ROOT STRING {
+ if (strlcpy(srv->srv_conf.docroot, $2,
+ sizeof(srv->srv_conf.docroot)) >=
+ sizeof(srv->srv_conf.docroot)) {
+ yyerror("document root too long");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
;
types : TYPES '{' optnl mediaopts_l '}'
@@ -399,6 +412,7 @@ lookup(char *s)
{ "on", ON },
{ "port", PORT },
{ "prefork", PREFORK },
+ { "root", ROOT },
{ "server", SERVER },
{ "types", TYPES },
{ "updates", UPDATES }
@@ -924,7 +938,10 @@ host_v4(const char *s)
sain->sin_len = sizeof(struct sockaddr_in);
sain->sin_family = AF_INET;
sain->sin_addr.s_addr = ina.s_addr;
-
+ if (sain->sin_addr.s_addr == INADDR_ANY)
+ h->prefixlen = 0; /* 0.0.0.0 address */
+ else
+ h->prefixlen = -1; /* host address */
return (h);
}
@@ -950,7 +967,11 @@ host_v6(const char *s)
sizeof(sa_in6->sin6_addr));
sa_in6->sin6_scope_id =
((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
-
+ if (memcmp(&sa_in6->sin6_addr, &in6addr_any,
+ sizeof(sa_in6->sin6_addr)) == 0)
+ h->prefixlen = 0; /* any address */
+ else
+ h->prefixlen = -1; /* host address */
freeaddrinfo(res);
}
@@ -1003,6 +1024,7 @@ host_dns(const char *s, struct addresslist *al, int max,
if (ipproto != -1)
h->ipproto = ipproto;
h->ss.ss_family = res->ai_family;
+ h->prefixlen = -1; /* host address */
if (res->ai_family == AF_INET) {
sain = (struct sockaddr_in *)&h->ss;
@@ -1065,6 +1087,7 @@ host_if(const char *s, struct addresslist *al, int max,
if (ipproto != -1)
h->ipproto = ipproto;
h->ss.ss_family = af;
+ h->prefixlen = -1; /* host address */
if (af == AF_INET) {
sain = (struct sockaddr_in *)&h->ss;
diff --git a/server.c b/server.c
index 38151ea..21ccff2 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.7 2014/07/23 13:26:39 reyk Exp $ */
+/* $OpenBSD: server.c,v 1.11 2014/07/25 16:23:19 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -151,7 +151,8 @@ server_launch(void)
void
server_purge(struct server *srv)
{
- struct client *clt;
+ struct client *clt;
+ struct server_config *srv_conf;
/* shutdown and remove server */
if (event_initialized(&srv->srv_ev))
@@ -167,9 +168,33 @@ server_purge(struct server *srv)
SPLAY_ROOT(&srv->srv_clients)) != NULL)
server_close(clt, NULL);
+ /* cleanup hosts */
+ while ((srv_conf =
+ TAILQ_FIRST(&srv->srv_hosts)) != NULL) {
+ TAILQ_REMOVE(&srv->srv_hosts, srv_conf, entry);
+
+ /* It might point to our own "default" entry */
+ if (srv_conf != &srv->srv_conf)
+ free(srv_conf);
+ }
+
free(srv);
}
+struct server *
+server_byaddr(struct sockaddr *addr)
+{
+ struct server *srv;
+
+ TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+ if (sockaddr_cmp((struct sockaddr *)&srv->srv_conf.ss,
+ addr, srv->srv_conf.prefixlen) == 0)
+ return (srv);
+ }
+
+ return (NULL);
+}
+
int
server_socket_af(struct sockaddr_storage *ss, in_port_t port)
{
@@ -316,9 +341,9 @@ server_socket_listen(struct sockaddr_storage *ss, in_port_t port,
void
server_input(struct client *clt)
{
- struct server *srv = clt->clt_server;
- evbuffercb inrd = server_read;
- evbuffercb inwr = server_write;
+ struct server_config *srv_conf = clt->clt_srv_conf;
+ evbuffercb inrd = server_read;
+ evbuffercb inwr = server_write;
if (server_httpdesc_init(clt) == -1) {
server_close(clt,
@@ -340,7 +365,7 @@ server_input(struct client *clt)
}
bufferevent_settimeout(clt->clt_bev,
- srv->srv_conf.timeout.tv_sec, srv->srv_conf.timeout.tv_sec);
+ srv_conf->timeout.tv_sec, srv_conf->timeout.tv_sec);
bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE);
}
@@ -472,9 +497,10 @@ server_accept(int fd, short event, void *arg)
clt->clt_s = s;
clt->clt_fd = -1;
clt->clt_toread = TOREAD_UNLIMITED;
- clt->clt_server = srv;
+ clt->clt_srv = srv;
+ clt->clt_srv_conf = &srv->srv_conf;
clt->clt_id = ++server_cltid;
- clt->clt_serverid = srv->srv_conf.id;
+ clt->clt_srv_id = srv->srv_conf.id;
clt->clt_pid = getpid();
clt->clt_inflight = 1;
switch (ss.ss_family) {
@@ -545,11 +571,15 @@ server_inflight_dec(struct client *clt, const char *why)
void
server_close(struct client *clt, const char *msg)
{
- char ibuf[128], obuf[128], *ptr = NULL;
- struct server *srv = clt->clt_server;
+ char ibuf[128], obuf[128], *ptr = NULL;
+ struct server *srv = clt->clt_srv;
+ struct server_config *srv_conf = clt->clt_srv_conf;
SPLAY_REMOVE(client_tree, &srv->srv_clients, clt);
+ /* free the HTTP descriptors incl. headers */
+ server_close_http(clt);
+
event_del(&clt->clt_ev);
if (clt->clt_bev != NULL)
bufferevent_disable(clt->clt_bev, EV_READ|EV_WRITE);
@@ -560,13 +590,13 @@ server_close(struct client *clt, const char *msg)
memset(&ibuf, 0, sizeof(ibuf));
memset(&obuf, 0, sizeof(obuf));
(void)print_host(&clt->clt_ss, ibuf, sizeof(ibuf));
- (void)print_host(&srv->srv_conf.ss, obuf, sizeof(obuf));
+ (void)print_host(&srv_conf->ss, obuf, sizeof(obuf));
if (EVBUFFER_LENGTH(clt->clt_log) &&
evbuffer_add_printf(clt->clt_log, "\r\n") != -1)
ptr = evbuffer_readline(clt->clt_log);
log_info("server %s, "
"client %d (%d active), %s -> %s:%d, "
- "%s%s%s", srv->srv_conf.name, clt->clt_id, server_clients,
+ "%s%s%s", srv_conf->name, clt->clt_id, server_clients,
ibuf, obuf, ntohs(clt->clt_port), msg,
ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr);
if (ptr != NULL)
@@ -575,7 +605,7 @@ server_close(struct client *clt, const char *msg)
if (clt->clt_bev != NULL)
bufferevent_free(clt->clt_bev);
- else if (clt->clt_output != NULL)
+ if (clt->clt_output != NULL)
evbuffer_free(clt->clt_output);
if (clt->clt_file != NULL)
diff --git a/server_file.c b/server_file.c
index 980efa4..c4814a0 100644
--- a/server_file.c
+++ b/server_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_file.c,v 1.10 2014/07/23 22:20:37 reyk Exp $ */
+/* $OpenBSD: server_file.c,v 1.13 2014/07/25 13:10:18 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -119,14 +119,14 @@ int
server_file(struct httpd *env, struct client *clt)
{
struct http_descriptor *desc = clt->clt_desc;
- struct server *srv = clt->clt_server;
+ struct server_config *srv_conf = clt->clt_srv_conf;
struct media_type *media;
const char *errstr = NULL;
int fd = -1, ret;
char path[MAXPATHLEN];
struct stat st;
- if (canonicalize_path(HTTPD_DOCROOT,
+ if (canonicalize_path(srv_conf->docroot,
desc->http_path, path, sizeof(path)) == NULL) {
/* Do not echo the uncanonicalized path */
server_abort_http(clt, 500, "invalid request path");
@@ -171,7 +171,7 @@ server_file(struct httpd *env, struct client *clt)
}
bufferevent_settimeout(clt->clt_file,
- srv->srv_conf.timeout.tv_sec, srv->srv_conf.timeout.tv_sec);
+ srv_conf->timeout.tv_sec, srv_conf->timeout.tv_sec);
bufferevent_enable(clt->clt_file, EV_READ);
bufferevent_disable(clt->clt_bev, EV_READ);
diff --git a/server_http.c b/server_http.c
index 6e15456..98edb96 100644
--- a/server_http.c
+++ b/server_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server_http.c,v 1.10 2014/07/23 21:43:12 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.14 2014/07/25 16:23:19 reyk Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -110,6 +110,7 @@ server_httpdesc_free(struct http_descriptor *desc)
desc->http_version = NULL;
}
kv_purge(&desc->http_headers);
+ desc->http_lastheader = NULL;
}
void
@@ -517,7 +518,7 @@ server_reset_http(struct client *clt)
void
server_abort_http(struct client *clt, u_int code, const char *msg)
{
- struct server *srv = clt->clt_server;
+ struct server_config *srv_conf = clt->clt_srv_conf;
struct bufferevent *bev = clt->clt_bev;
const char *httperr = NULL, *text = "";
char *httpmsg, *extraheader = NULL;
@@ -533,7 +534,7 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
goto done;
/* Some system information */
- if (print_host(&srv->srv_conf.ss, hbuf, sizeof(hbuf)) == NULL)
+ if (print_host(&srv_conf->ss, hbuf, sizeof(hbuf)) == NULL)
goto done;
/* RFC 2616 "tolerates" asctime() */
@@ -595,7 +596,7 @@ server_abort_http(struct client *clt, u_int code, const char *msg)
code, httperr, tmbuf, HTTPD_SERVERNAME,
extraheader == NULL ? "" : extraheader,
code, httperr, style, httperr, text,
- HTTPD_SERVERNAME, hbuf, ntohs(srv->srv_conf.port)) == -1)
+ HTTPD_SERVERNAME, hbuf, ntohs(srv_conf->port)) == -1)
goto done;
/* Dump the message without checking for success */
@@ -627,6 +628,8 @@ int
server_response(struct httpd *httpd, struct client *clt)
{
struct http_descriptor *desc = clt->clt_desc;
+ struct server *srv = clt->clt_srv;
+ struct server_config *srv_conf;
struct kv *kv, key;
int ret;
@@ -656,6 +659,23 @@ server_response(struct httpd *httpd, struct client *clt)
clt->clt_persist = 0;
}
+ /*
+ * Do we have a Host header and matching configuration?
+ * XXX the Host can also appear in the URL path.
+ */
+ key.kv_key = "Host";
+ if ((kv = kv_find(&desc->http_headers, &key)) != NULL) {
+ /* XXX maybe better to turn srv_hosts into a tree */
+ TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) {
+ if (fnmatch(srv_conf->name, kv->kv_value,
+ FNM_CASEFOLD) == 0) {
+ /* Replace host configuration */
+ clt->clt_srv_conf = srv_conf;
+ break;
+ }
+ }
+ }
+
if ((ret = server_file(httpd, clt)) == -1)
return (-1);