This just made my day.

-----Original Message-----
From: "Ted Unangst" <t...@tedunangst.com>
Sent: ‎11/‎20/‎2014 6:26 PM
To: "tech@openbsd.org" <tech@openbsd.org>
Subject: httpd errata

[on behalf of reyk]

Many people want to test the new httpd in OpenBSD 5.6; so we decided
to provide various improvements from -current for 5.6.
See the description below for more details.


untrusted comment: signature from openbsd 5.6 base private key
RWR0EANmo9nqhn3Gnfk2/2x+xII6do92zreKp/t5zOwfkVgsQAI4ZCPkWAazbbnWNV7Ptkle876f/kb6C2KuvnTqvwUItsyvogA=

OpenBSD 5.6 errata 9, Nov 18, 2014:  httpd was developed very rapidly
in the weeks before 5.6 release, and it has a few flaws.  It would be
nice to get these flaws fully remediated before the next release, and
that requires the community to want to use it.  Therefore here is a
"jumbo" patch that brings in the most important fixes.

Apply patch using:

    signify -Vep /etc/signify/openbsd-56-base.pub -x 009_httpd.patch.sig \
        -m - | (cd /usr/src && patch -p0)

Then build and install httpd:

    cd /usr/src/usr.sbin/httpd
    make obj
    make
    make install

Index: usr.sbin/httpd/config.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/config.c,v
retrieving revision 1.21
diff -u -p -r1.21 config.c
--- usr.sbin/httpd/config.c     6 Aug 2014 18:21:14 -0000       1.21
+++ usr.sbin/httpd/config.c     18 Nov 2014 15:02:54 -0000
@@ -223,7 +223,7 @@ config_getserver_config(struct httpd *en
 #ifdef DEBUG
        struct privsep          *ps = env->sc_ps;
 #endif
-       struct server_config    *srv_conf;
+       struct server_config    *srv_conf, *parent;
        u_int8_t                *p = imsg->data;
        u_int                    f;
 
@@ -233,18 +233,28 @@ config_getserver_config(struct httpd *en
        IMSG_SIZE_CHECK(imsg, srv_conf);
        memcpy(srv_conf, p, sizeof(*srv_conf));
 
+       /* Reset these variables to avoid free'ing invalid pointers */
+       serverconfig_reset(srv_conf);
+
+       TAILQ_FOREACH(parent, &srv->srv_hosts, entry) {
+               if (strcmp(parent->name, srv_conf->name) == 0)
+                       break;
+       }
+       if (parent == NULL)
+               parent = &srv->srv_conf;
+
        if (srv_conf->flags & SRVFLAG_LOCATION) {
                /* Inherit configuration from the parent */
                f = SRVFLAG_INDEX|SRVFLAG_NO_INDEX;
                if ((srv_conf->flags & f) == 0) {
-                       srv_conf->flags |= srv->srv_conf.flags & f;
-                       (void)strlcpy(srv_conf->index, srv->srv_conf.index,
+                       srv_conf->flags |= parent->flags & f;
+                       (void)strlcpy(srv_conf->index, parent->index,
                            sizeof(srv_conf->index));
                }
 
                f = SRVFLAG_AUTO_INDEX|SRVFLAG_NO_AUTO_INDEX;
                if ((srv_conf->flags & f) == 0)
-                       srv_conf->flags |= srv->srv_conf.flags & f;
+                       srv_conf->flags |= parent->flags & f;
 
                f = SRVFLAG_SOCKET|SRVFLAG_FCGI;
                if ((srv_conf->flags & f) == SRVFLAG_FCGI) {
@@ -255,48 +265,48 @@ config_getserver_config(struct httpd *en
 
                f = SRVFLAG_ROOT;
                if ((srv_conf->flags & f) == 0) {
-                       srv_conf->flags |= srv->srv_conf.flags & f;
-                       (void)strlcpy(srv_conf->root, srv->srv_conf.root,
+                       srv_conf->flags |= parent->flags & f;
+                       (void)strlcpy(srv_conf->root, parent->root,
                            sizeof(srv_conf->root));
                }
 
                f = SRVFLAG_FCGI|SRVFLAG_NO_FCGI;
                if ((srv_conf->flags & f) == 0)
-                       srv_conf->flags |= srv->srv_conf.flags & f;
+                       srv_conf->flags |= parent->flags & f;
 
                f = SRVFLAG_LOG|SRVFLAG_NO_LOG;
                if ((srv_conf->flags & f) == 0) {
-                       srv_conf->flags |= srv->srv_conf.flags & f;
-                       srv_conf->logformat = srv->srv_conf.logformat;
+                       srv_conf->flags |= parent->flags & f;
+                       srv_conf->logformat = parent->logformat;
                }
 
                f = SRVFLAG_SYSLOG|SRVFLAG_NO_SYSLOG;
                if ((srv_conf->flags & f) == 0)
-                       srv_conf->flags |= srv->srv_conf.flags & f;
+                       srv_conf->flags |= parent->flags & f;
 
                f = SRVFLAG_SSL;
-               srv_conf->flags |= srv->srv_conf.flags & f;
+               srv_conf->flags |= parent->flags & f;
 
                f = SRVFLAG_ACCESS_LOG;
                if ((srv_conf->flags & f) == 0) {
-                       srv_conf->flags |= srv->srv_conf.flags & f;
+                       srv_conf->flags |= parent->flags & f;
                        (void)strlcpy(srv_conf->accesslog,
-                           srv->srv_conf.accesslog,
+                           parent->accesslog,
                            sizeof(srv_conf->accesslog));
                }
 
                f = SRVFLAG_ERROR_LOG;
                if ((srv_conf->flags & f) == 0) {
-                       srv_conf->flags |= srv->srv_conf.flags & f;
+                       srv_conf->flags |= parent->flags & f;
                        (void)strlcpy(srv_conf->errorlog,
-                           srv->srv_conf.errorlog,
+                           parent->errorlog,
                            sizeof(srv_conf->errorlog));
                }
 
-               memcpy(&srv_conf->timeout, &srv->srv_conf.timeout,
+               memcpy(&srv_conf->timeout, &parent->timeout,
                    sizeof(srv_conf->timeout));
-               srv_conf->maxrequests = srv->srv_conf.maxrequests;
-               srv_conf->maxrequestbody = srv->srv_conf.maxrequestbody;
+               srv_conf->maxrequests = parent->maxrequests;
+               srv_conf->maxrequestbody = parent->maxrequestbody;
 
                DPRINTF("%s: %s %d location \"%s\", "
                    "parent \"%s\", flags: %s",
@@ -330,6 +340,9 @@ config_getserver(struct httpd *env, stru
        IMSG_SIZE_CHECK(imsg, &srv_conf);
        memcpy(&srv_conf, p, sizeof(srv_conf));
        s = sizeof(srv_conf);
+
+       /* Reset these variables to avoid free'ing invalid pointers */
+       serverconfig_reset(&srv_conf);
 
        if ((u_int)(IMSG_DATA_SIZE(imsg) - s) <
            (srv_conf.ssl_cert_len + srv_conf.ssl_key_len)) {
Index: usr.sbin/httpd/http.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/http.h,v
retrieving revision 1.5
diff -u -p -r1.5 http.h
--- usr.sbin/httpd/http.h       3 Aug 2014 21:33:27 -0000       1.5
+++ usr.sbin/httpd/http.h       18 Nov 2014 15:02:54 -0000
@@ -44,6 +44,32 @@ enum httpmethod {
        HTTP_METHOD_LOCK,
        HTTP_METHOD_UNLOCK,
 
+       /* WebDAV Versioning Extension, RFC 3253 */
+       HTTP_METHOD_VERSION_CONTROL,
+       HTTP_METHOD_REPORT,
+       HTTP_METHOD_CHECKOUT,
+       HTTP_METHOD_CHECKIN,
+       HTTP_METHOD_UNCHECKOUT,
+       HTTP_METHOD_MKWORKSPACE,
+       HTTP_METHOD_UPDATE,
+       HTTP_METHOD_LABEL,
+       HTTP_METHOD_MERGE,
+       HTTP_METHOD_BASELINE_CONTROL,
+       HTTP_METHOD_MKACTIVITY,
+
+       /* WebDAV Ordered Collections, RFC 3648 */
+       HTTP_METHOD_ORDERPATCH,
+
+       /* WebDAV Access Control, RFC 3744 */
+       HTTP_METHOD_ACL,
+
+       /* WebDAV Redirect Reference Resources, RFC 4437 */
+       HTTP_METHOD_MKREDIRECTREF,
+       HTTP_METHOD_UPDATEREDIRECTREF,
+
+       /* WebDAV Search, RFC 5323 */
+       HTTP_METHOD_SEARCH,
+
        /* PATCH, RFC 5789 */
        HTTP_METHOD_PATCH,
 
@@ -71,6 +97,22 @@ struct http_method {
        { HTTP_METHOD_MOVE,             "MOVE" },       \
        { HTTP_METHOD_LOCK,             "LOCK" },       \
        { HTTP_METHOD_UNLOCK,           "UNLOCK" },     \
+       { HTTP_METHOD_VERSION_CONTROL,  "VERSION-CONTROL" }, \
+       { HTTP_METHOD_REPORT,           "REPORT" },     \
+       { HTTP_METHOD_CHECKOUT,         "CHECKOUT" },   \
+       { HTTP_METHOD_CHECKIN,          "CHECKIN" },    \
+       { HTTP_METHOD_UNCHECKOUT,       "UNCHECKOUT" }, \
+       { HTTP_METHOD_MKWORKSPACE,      "MKWORKSPACE" }, \
+       { HTTP_METHOD_UPDATE,           "UPDATE" },     \
+       { HTTP_METHOD_LABEL,            "LABEL" },      \
+       { HTTP_METHOD_MERGE,            "MERGE" },      \
+       { HTTP_METHOD_BASELINE_CONTROL, "BASELINE-CONTROL" }, \
+       { HTTP_METHOD_MKACTIVITY,       "MKACTIVITY" }, \
+       { HTTP_METHOD_ORDERPATCH,       "ORDERPATCH" }, \
+       { HTTP_METHOD_ACL,              "ACL" },        \
+       { HTTP_METHOD_MKREDIRECTREF,    "MKREDIRECTREF" }, \
+       { HTTP_METHOD_UPDATEREDIRECTREF, "UPDATEREDIRECTREF" }, \
+       { HTTP_METHOD_SEARCH,           "SEARCH" },     \
        { HTTP_METHOD_PATCH,            "PATCH" },      \
        { HTTP_METHOD_NONE,             NULL }          \
 }
@@ -155,6 +197,9 @@ struct http_descriptor {
        enum httpmethod          http_method;
        int                      http_chunked;
        char                    *http_version;
+
+       /* Rewritten path remains NULL if not used */
+       char                    *http_path_alias;
 
        /* A tree of headers and attached lists for repeated headers. */
        struct kv               *http_lastheader;
Index: usr.sbin/httpd/httpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.c,v
retrieving revision 1.17
diff -u -p -r1.17 httpd.c
--- usr.sbin/httpd/httpd.c      5 Aug 2014 15:36:59 -0000       1.17
+++ usr.sbin/httpd/httpd.c      18 Nov 2014 15:02:54 -0000
@@ -289,10 +289,20 @@ parent_configure(struct httpd *env)
                        fatal("send media");
        }
 
+       /* First send the servers... */
        TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+               if (srv->srv_conf.flags & SRVFLAG_LOCATION)
+                       continue;
                if (config_setserver(env, srv) == -1)
                        fatal("send server");
        }
+       /* ...and now send the locations */
+       TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
+               if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0)
+                       continue;
+               if (config_setserver(env, srv) == -1)
+                       fatal("send location");
+       }
 
        /* The servers need to reload their config. */
        env->sc_reload = env->sc_prefork_server + 1;
@@ -526,6 +536,46 @@ canonicalize_host(const char *host, char
 }
 
 const char *
+url_decode(char *url)
+{
+       char    *p, *q;
+       char     hex[3];
+       u_long   x;
+
+       hex[2] = '\0';
+       p = q = url;
+
+       while (*p != '\0') {
+               switch (*p) {
+               case '%':
+                       /* Encoding character is followed by two hex chars */
+                       if (!(isxdigit(p[1]) && isxdigit(p[2])))
+                               return (NULL);
+
+                       hex[0] = p[1];
+                       hex[1] = p[2];
+
+                       /*
+                        * We don't have to validate "hex" because it is
+                        * guaranteed to include two hex chars followed by nul.
+                        */
+                       x = strtoul(hex, NULL, 16);             
+                       *q = (char)x;
+                       p += 2;
+                       break;
+               default:
+                       *q = *p;
+                       break;
+               }
+               p++;
+               q++;
+       }
+       *q = '\0';
+
+       return(url);
+}
+
+const char *
 canonicalize_path(const char *input, char *path, size_t len)
 {
        const char      *i;
@@ -580,28 +630,33 @@ canonicalize_path(const char *input, cha
        return (path);
 }
 
-ssize_t
-path_info(char *name)
+size_t
+path_info(char *path)
 {
-       char            *p, *start, *end;
-       char             path[MAXPATHLEN];
+       char            *p, *start, *end, ch;
        struct stat      st;
-
-       if (strlcpy(path, name, sizeof(path)) >= sizeof(path))
-               return (-1);
+       int              ret;
 
        start = path;
        end = start + strlen(path);
 
        for (p = end; p > start; p--) {
-               if (*p != '/')
+               /* Scan every path component from the end and at each '/' */
+               if (p < end && *p != '/')
                        continue;
-               if (stat(path, &st) == 0)
-                       break;
+
+               /* Temporarily cut the path component out */
+               ch = *p;
                *p = '\0';
+               ret = stat(path, &st);
+               *p = ch;
+
+               /* Break if the initial path component was found */
+               if (ret == 0)
+                       break;
        }
 
-       return (strlen(path));
+       return (p - start);
 }
 
 void
@@ -623,6 +678,40 @@ socket_rlimit(int maxfd)
                rl.rlim_cur = MAX(rl.rlim_max, (rlim_t)maxfd);
        if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
                fatal("socket_rlimit: failed to set resource limit");
+}
+
+char *
+evbuffer_getline(struct evbuffer *evb)
+{
+       u_int8_t        *ptr = EVBUFFER_DATA(evb);
+       size_t           len = EVBUFFER_LENGTH(evb);
+       char            *str;
+       u_int            i;
+
+       /* Safe version of evbuffer_readline() */
+       if ((str = get_string(ptr, len)) == NULL)
+               return (NULL);
+
+       for (i = 0; str[i] != '\0'; i++) {
+               if (str[i] == '\r' || str[i] == '\n')
+                       break;
+       }
+
+       if (i == len) {
+               free(str);
+               return (NULL);
+       }
+
+       str[i] = '\0';
+
+       if ((i + 1) < len) {
+               if (ptr[i] == '\r' && ptr[i + 1] == '\n')
+                       i++;
+       }
+
+       evbuffer_drain(evb, ++i);
+
+       return (str);
 }
 
 char *
Index: usr.sbin/httpd/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v
retrieving revision 1.51
diff -u -p -r1.51 httpd.h
--- usr.sbin/httpd/httpd.h      6 Aug 2014 18:21:14 -0000       1.51
+++ usr.sbin/httpd/httpd.h      18 Nov 2014 15:02:54 -0000
@@ -276,7 +276,8 @@ struct client {
        size_t                   clt_buflen;
        struct evbuffer         *clt_output;
        struct event             clt_ev;
-       void                    *clt_desc;
+       void                    *clt_descreq;
+       void                    *clt_descresp;
        int                      clt_sndbufsiz;
 
        int                      clt_fd;
@@ -294,6 +295,8 @@ struct client {
        int                      clt_fcgi_toread;
        int                      clt_fcgi_padding_len;
        int                      clt_fcgi_type;
+       int                      clt_fcgi_chunked;
+       int                      clt_fcgi_end;
        struct evbuffer         *clt_srvevb;
 
        struct evbuffer         *clt_log;
@@ -463,6 +466,8 @@ pid_t        server(struct privsep *, struct p
 int     server_ssl_load_keypair(struct server *);
 int     server_privinit(struct server *);
 void    server_purge(struct server *);
+void    serverconfig_free(struct server_config *);
+void    serverconfig_reset(struct server_config *);
 int     server_socket_af(struct sockaddr_storage *, in_port_t);
 in_port_t
         server_socket_getport(struct sockaddr_storage *);
@@ -477,6 +482,8 @@ void         server_sendlog(struct server_confi
 void    server_close(struct client *, const char *);
 void    server_dump(struct client *, const void *, size_t);
 int     server_client_cmp(struct client *, struct client *);
+int     server_bufferevent_printf(struct client *, const char *, ...)
+           __attribute__((__format__ (printf, 2, 3)));
 int     server_bufferevent_print(struct client *, const char *);
 int     server_bufferevent_write_buffer(struct client *,
            struct evbuffer *);
@@ -508,17 +515,20 @@ const char
 void    server_read_httpcontent(struct bufferevent *, void *);
 void    server_read_httpchunks(struct bufferevent *, void *);
 int     server_writeheader_http(struct client *clt, struct kv *, void *);
-int     server_headers(struct client *,
+int     server_headers(struct client *, void *,
            int (*)(struct client *, struct kv *, void *), void *);
 int     server_writeresponse_http(struct client *);
 int     server_response_http(struct client *, u_int, struct media_type *,
-           size_t);
+           size_t, time_t);
 void    server_reset_http(struct client *);
 void    server_close_http(struct client *);
 int     server_response(struct httpd *, struct client *);
+struct server_config *
+        server_getlocation(struct client *, const char *);
 const char *
         server_http_host(struct sockaddr_storage *, char *, size_t);
-void    server_http_date(char *, size_t);
+char   *server_http_parsehost(char *, char *, size_t, int *);
+ssize_t         server_http_time(time_t, char *, size_t);
 int     server_log_http(struct client *, u_int, size_t);
 
 /* server_file.c */
@@ -533,13 +543,15 @@ int        fcgi_add_stdin(struct client *, str
 void            event_again(struct event *, int, short,
                    void (*)(int, short, void *),
                    struct timeval *, struct timeval *, void *);
+const char     *url_decode(char *);
 const char     *canonicalize_host(const char *, char *, size_t);
 const char     *canonicalize_path(const char *, char *, size_t);
-ssize_t                 path_info(char *);
+size_t          path_info(char *);
 void            imsg_event_add(struct imsgev *);
 int             imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
                    pid_t, int, void *, u_int16_t);
 void            socket_rlimit(int);
+char           *evbuffer_getline(struct evbuffer *);
 char           *get_string(u_int8_t *, size_t);
 void           *get_data(u_int8_t *, size_t);
 int             sockaddr_cmp(struct sockaddr *, struct sockaddr *, int);
@@ -575,6 +587,7 @@ void        log_warn(const char *, ...) __attri
 void   log_warnx(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
 void   log_info(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
 void   log_debug(const char *, ...) __attribute__((__format__ (printf, 1, 2)));
+void   logit(int, const char *, ...) __attribute__((__format__ (printf, 2, 
3)));
 void   vlog(int, const char *, va_list) __attribute__((__format__ (printf, 2, 
0)));
 __dead void fatal(const char *);
 __dead void fatalx(const char *);
Index: usr.sbin/httpd/logger.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/logger.c,v
retrieving revision 1.5
diff -u -p -r1.5 logger.c
--- usr.sbin/httpd/logger.c     6 Aug 2014 12:56:58 -0000       1.5
+++ usr.sbin/httpd/logger.c     18 Nov 2014 15:02:55 -0000
@@ -194,6 +194,9 @@ logger_open(struct server *srv, struct s
 {
        struct log_file *log, *logfile = NULL, *errfile = NULL;
 
+       if (srv_conf->flags & SRVFLAG_SYSLOG)
+               return(0);
+
        /* disassociate */
        srv_conf->logaccess = srv_conf->logerror = NULL;
 
Index: usr.sbin/httpd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.34
diff -u -p -r1.34 parse.y
--- usr.sbin/httpd/parse.y      6 Aug 2014 20:29:54 -0000       1.34
+++ usr.sbin/httpd/parse.y      18 Nov 2014 15:02:55 -0000
@@ -180,7 +180,7 @@ main                : PREFORK NUMBER        {
                                break;
                        if ($2 <= 0 || $2 > SERVER_MAXPROC) {
                                yyerror("invalid number of preforked "
-                                   "servers: %d", $2);
+                                   "servers: %lld", $2);
                                YYERROR;
                        }
                        conf->sc_prefork_server = $2;
@@ -198,15 +198,6 @@ server             : SERVER STRING         {
                                YYACCEPT;
                        }
 
-                       TAILQ_FOREACH(s, conf->sc_servers, srv_entry)
-                               if (!strcmp(s->srv_conf.name, $2))
-                                       break;
-                       if (s != NULL) {
-                               yyerror("server %s defined twice", $2);
-                               free($2);
-                               YYERROR;
-                       }
-
                        if ((s = calloc(1, sizeof (*s))) == NULL)
                                fatal("out of memory");
 
@@ -252,18 +243,46 @@ server            : SERVER STRING         {
                        srv_conf = &srv->srv_conf;
 
                        SPLAY_INIT(&srv->srv_clients);
-                       TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
                } '{' optnl serveropts_l '}'    {
+                       struct server   *s = NULL;
+
+                       TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
+                               if ((s->srv_conf.flags &
+                                   SRVFLAG_LOCATION) == 0 &&
+                                   strcmp(s->srv_conf.name,
+                                   srv->srv_conf.name) == 0 &&
+                                   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)
+                                       break;
+                       }
+                       if (s != NULL) {
+                               yyerror("server \"%s\" defined twice",
+                                   srv->srv_conf.name);
+                               serverconfig_free(srv_conf);
+                               free(srv);
+                               YYABORT;
+                       }
+
                        if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
                                yyerror("listen address not specified");
-                               free($2);
+                               serverconfig_free(srv_conf);
+                               free(srv);
                                YYERROR;
                        }
+
                        if (server_ssl_load_keypair(srv) == -1) {
                                yyerror("failed to load public/private keys "
                                    "for server %s", srv->srv_conf.name);
+                               serverconfig_free(srv_conf);
+                               free(srv);
                                YYERROR;
                        }
+
+                       TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
+
                        srv = NULL;
                        srv_conf = NULL;
                }
@@ -367,17 +386,6 @@ serveroptsl        : LISTEN ON STRING optssl po
                                YYACCEPT;
                        }
 
-                       TAILQ_FOREACH(s, conf->sc_servers, srv_entry)
-                               if (strcmp(s->srv_conf.name,
-                                   srv->srv_conf.name) == 0 &&
-                                   strcmp(s->srv_conf.location, $2) == 0)
-                                       break;
-                       if (s != NULL) {
-                               yyerror("location %s defined twice", $2);
-                               free($2);
-                               YYERROR;
-                       }
-
                        if ((s = calloc(1, sizeof (*s))) == NULL)
                                fatal("out of memory");
 
@@ -416,12 +424,31 @@ serveroptsl       : LISTEN ON STRING optssl po
                        srv = s;
                        srv_conf = &srv->srv_conf;
                        SPLAY_INIT(&srv->srv_clients);
-                       TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
                } '{' optnl serveropts_l '}'    {
+                       struct server   *s = NULL;
+
+                       TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
+                               if ((s->srv_conf.flags & SRVFLAG_LOCATION) &&
+                                   s->srv_conf.id == srv_conf->id &&
+                                   strcmp(s->srv_conf.location,
+                                   srv_conf->location) == 0)
+                                       break;
+                       }
+                       if (s != NULL) {
+                               yyerror("location \"%s\" defined twice",
+                                   srv->srv_conf.location);
+                               serverconfig_free(srv_conf);
+                               free(srv);
+                               YYABORT;
+                       }
+
+                       TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
+
                        srv = parentsrv;
                        srv_conf = &parentsrv->srv_conf;
                        parentsrv = NULL;
                }
+               | include
                ;
 
 fastcgi                : NO FCGI               {
@@ -623,7 +650,7 @@ tcpflags    : SACK                  { srv_conf->tcpflags |
                }
                | BACKLOG NUMBER        {
                        if ($2 < 0 || $2 > SERVER_MAX_CLIENTS) {
-                               yyerror("invalid backlog: %d", $2);
+                               yyerror("invalid backlog: %lld", $2);
                                YYERROR;
                        }
                        srv_conf->tcpbacklog = $2;
@@ -631,13 +658,13 @@ tcpflags  : SACK                  { srv_conf->tcpflags |
                | SOCKET BUFFER NUMBER  {
                        srv_conf->tcpflags |= TCPFLAG_BUFSIZ;
                        if ((srv_conf->tcpbufsiz = $3) < 0) {
-                               yyerror("invalid socket buffer size: %d", $3);
+                               yyerror("invalid socket buffer size: %lld", $3);
                                YYERROR;
                        }
                }
                | IP STRING NUMBER      {
                        if ($3 < 0) {
-                               yyerror("invalid ttl: %d", $3);
+                               yyerror("invalid ttl: %lld", $3);
                                free($2);
                                YYERROR;
                        }
@@ -694,6 +721,9 @@ medianamesl : STRING                                {
                        }
                        free($1);
 
+                       if (!loadcfg)
+                               break;
+
                        if (media_add(conf->sc_mediatypes, &media) == NULL) {
                                yyerror("failed to add media type");
                                YYERROR;
@@ -729,7 +759,7 @@ port                : PORT STRING {
                }
                | PORT NUMBER


[The entire original message is not included.]

Reply via email to