xref: /openbsd-src/usr.sbin/httpd/parse.y (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: parse.y,v 1.82 2016/09/03 14:44:21 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 - 2015 Reyk Floeter <reyk@openbsd.org>
5  * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
6  * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
7  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
8  * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
9  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
10  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
11  * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
12  * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
13  *
14  * Permission to use, copy, modify, and distribute this software for any
15  * purpose with or without fee is hereby granted, provided that the above
16  * copyright notice and this permission notice appear in all copies.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  */
26 
27 %{
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/stat.h>
31 #include <sys/queue.h>
32 #include <sys/tree.h>
33 #include <sys/ioctl.h>
34 #include <sys/sockio.h>
35 #include <sys/time.h>
36 
37 #include <net/if.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 
41 #include <ctype.h>
42 #include <unistd.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <limits.h>
46 #include <stdint.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <netdb.h>
50 #include <string.h>
51 #include <ifaddrs.h>
52 #include <syslog.h>
53 
54 #include "httpd.h"
55 #include "http.h"
56 
57 TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
58 static struct file {
59 	TAILQ_ENTRY(file)	 entry;
60 	FILE			*stream;
61 	char			*name;
62 	int			 lineno;
63 	int			 errors;
64 } *file, *topfile;
65 struct file	*pushfile(const char *, int);
66 int		 popfile(void);
67 int		 check_file_secrecy(int, const char *);
68 int		 yyparse(void);
69 int		 yylex(void);
70 int		 yyerror(const char *, ...)
71     __attribute__((__format__ (printf, 1, 2)))
72     __attribute__((__nonnull__ (1)));
73 int		 kw_cmp(const void *, const void *);
74 int		 lookup(char *);
75 int		 lgetc(int);
76 int		 lungetc(int);
77 int		 findeol(void);
78 
79 TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
80 struct sym {
81 	TAILQ_ENTRY(sym)	 entry;
82 	int			 used;
83 	int			 persist;
84 	char			*nam;
85 	char			*val;
86 };
87 int		 symset(const char *, const char *, int);
88 char		*symget(const char *);
89 
90 struct httpd		*conf = NULL;
91 static int		 errors = 0;
92 static int		 loadcfg = 0;
93 uint32_t		 last_server_id = 0;
94 uint32_t		 last_auth_id = 0;
95 
96 static struct server	*srv = NULL, *parentsrv = NULL;
97 static struct server_config *srv_conf = NULL;
98 struct serverlist	 servers;
99 struct media_type	 media;
100 
101 struct address	*host_v4(const char *);
102 struct address	*host_v6(const char *);
103 int		 host_dns(const char *, struct addresslist *,
104 		    int, struct portrange *, const char *, int);
105 int		 host_if(const char *, struct addresslist *,
106 		    int, struct portrange *, const char *, int);
107 int		 host(const char *, struct addresslist *,
108 		    int, struct portrange *, const char *, int);
109 void		 host_free(struct addresslist *);
110 struct server	*server_inherit(struct server *, struct server_config *,
111 		    struct server_config *);
112 int		 getservice(char *);
113 int		 is_if_in_group(const char *, const char *);
114 
115 typedef struct {
116 	union {
117 		int64_t			 number;
118 		char			*string;
119 		struct timeval		 tv;
120 		struct portrange	 port;
121 		struct auth		 auth;
122 		struct {
123 			struct sockaddr_storage	 ss;
124 			char			 name[HOST_NAME_MAX+1];
125 		}			 addr;
126 	} v;
127 	int lineno;
128 } YYSTYPE;
129 
130 %}
131 
132 %token	ACCESS ALIAS AUTO BACKLOG BODY BUFFER CERTIFICATE CHROOT CIPHERS COMMON
133 %token	COMBINED CONNECTION DHE DIRECTORY ECDHE ERR FCGI INDEX IP KEY LISTEN
134 %token	LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY ON PORT PREFORK PROTOCOLS
135 %token	REQUEST REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TIMEOUT
136 %token	TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD
137 %token	ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS
138 %token	<v.string>	STRING
139 %token  <v.number>	NUMBER
140 %type	<v.port>	port
141 %type	<v.number>	opttls optmatch
142 %type	<v.tv>		timeout
143 %type	<v.string>	numberstring optstring
144 %type	<v.auth>	authopts
145 
146 %%
147 
148 grammar		: /* empty */
149 		| grammar include '\n'
150 		| grammar '\n'
151 		| grammar varset '\n'
152 		| grammar main '\n'
153 		| grammar server '\n'
154 		| grammar types '\n'
155 		| grammar error '\n'		{ file->errors++; }
156 		;
157 
158 include		: INCLUDE STRING		{
159 			struct file	*nfile;
160 
161 			if ((nfile = pushfile($2, 0)) == NULL) {
162 				yyerror("failed to include file %s", $2);
163 				free($2);
164 				YYERROR;
165 			}
166 			free($2);
167 
168 			file = nfile;
169 			lungetc('\n');
170 		}
171 		;
172 
173 varset		: STRING '=' STRING	{
174 			char *s = $1;
175 			while (*s++) {
176 				if (isspace((unsigned char)*s)) {
177 					yyerror("macro name cannot contain "
178 					    "whitespace");
179 					YYERROR;
180 				}
181 			}
182 			if (symset($1, $3, 0) == -1)
183 				fatal("cannot store variable");
184 			free($1);
185 			free($3);
186 		}
187 		;
188 
189 opttls		: /*empty*/	{ $$ = 0; }
190 		| TLS		{ $$ = 1; }
191 		;
192 
193 main		: PREFORK NUMBER	{
194 			if (loadcfg)
195 				break;
196 			if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
197 				yyerror("invalid number of preforked "
198 				    "servers: %lld", $2);
199 				YYERROR;
200 			}
201 			conf->sc_prefork_server = $2;
202 		}
203 		| CHROOT STRING		{
204 			conf->sc_chroot = $2;
205 		}
206 		| LOGDIR STRING		{
207 			conf->sc_logdir = $2;
208 		}
209 		| DEFAULT TYPE mediastring	{
210 			memcpy(&conf->sc_default_type, &media,
211 			    sizeof(struct media_type));
212 		}
213 		;
214 
215 server		: SERVER optmatch STRING	{
216 			struct server	*s;
217 
218 			if (!loadcfg) {
219 				free($3);
220 				YYACCEPT;
221 			}
222 
223 			if ((s = calloc(1, sizeof (*s))) == NULL)
224 				fatal("out of memory");
225 
226 			if (strlcpy(s->srv_conf.name, $3,
227 			    sizeof(s->srv_conf.name)) >=
228 			    sizeof(s->srv_conf.name)) {
229 				yyerror("server name truncated");
230 				free($3);
231 				free(s);
232 				YYERROR;
233 			}
234 			free($3);
235 
236 			strlcpy(s->srv_conf.root, HTTPD_DOCROOT,
237 			    sizeof(s->srv_conf.root));
238 			strlcpy(s->srv_conf.index, HTTPD_INDEX,
239 			    sizeof(s->srv_conf.index));
240 			strlcpy(s->srv_conf.accesslog, HTTPD_ACCESS_LOG,
241 			    sizeof(s->srv_conf.accesslog));
242 			strlcpy(s->srv_conf.errorlog, HTTPD_ERROR_LOG,
243 			    sizeof(s->srv_conf.errorlog));
244 			s->srv_conf.id = ++last_server_id;
245 			s->srv_conf.parent_id = s->srv_conf.id;
246 			s->srv_s = -1;
247 			s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT;
248 			s->srv_conf.maxrequests = SERVER_MAXREQUESTS;
249 			s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY;
250 			s->srv_conf.flags = SRVFLAG_LOG;
251 			if ($2)
252 				s->srv_conf.flags |= SRVFLAG_SERVER_MATCH;
253 			s->srv_conf.logformat = LOG_FORMAT_COMMON;
254 			s->srv_conf.tls_protocols = TLS_PROTOCOLS_DEFAULT;
255 			if ((s->srv_conf.tls_cert_file =
256 			    strdup(HTTPD_TLS_CERT)) == NULL)
257 				fatal("out of memory");
258 			if ((s->srv_conf.tls_key_file =
259 			    strdup(HTTPD_TLS_KEY)) == NULL)
260 				fatal("out of memory");
261 			strlcpy(s->srv_conf.tls_ciphers,
262 			    HTTPD_TLS_CIPHERS,
263 			    sizeof(s->srv_conf.tls_ciphers));
264 			strlcpy(s->srv_conf.tls_dhe_params,
265 			    HTTPD_TLS_DHE_PARAMS,
266 			    sizeof(s->srv_conf.tls_dhe_params));
267 			strlcpy(s->srv_conf.tls_ecdhe_curve,
268 			    HTTPD_TLS_ECDHE_CURVE,
269 			    sizeof(s->srv_conf.tls_ecdhe_curve));
270 
271 			s->srv_conf.hsts_max_age = SERVER_HSTS_DEFAULT_AGE;
272 
273 			if (last_server_id == INT_MAX) {
274 				yyerror("too many servers defined");
275 				free(s);
276 				YYERROR;
277 			}
278 			srv = s;
279 			srv_conf = &srv->srv_conf;
280 
281 			SPLAY_INIT(&srv->srv_clients);
282 			TAILQ_INIT(&srv->srv_hosts);
283 
284 			TAILQ_INSERT_TAIL(&srv->srv_hosts, srv_conf, entry);
285 		} '{' optnl serveropts_l '}'	{
286 			struct server		*s, *sn;
287 			struct server_config	*a, *b;
288 
289 			srv_conf = &srv->srv_conf;
290 
291 			/* Check if the new server already exists. */
292 			if (server_match(srv, 1) != NULL) {
293 				yyerror("server \"%s\" defined twice",
294 				    srv->srv_conf.name);
295 				serverconfig_free(srv_conf);
296 				free(srv);
297 				YYABORT;
298 			}
299 
300 			if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
301 				yyerror("listen address not specified");
302 				serverconfig_free(srv_conf);
303 				free(srv);
304 				YYERROR;
305 			}
306 
307 			if ((s = server_match(srv, 0)) != NULL) {
308 				if ((s->srv_conf.flags & SRVFLAG_TLS) !=
309 				    (srv->srv_conf.flags & SRVFLAG_TLS)) {
310 					yyerror("server \"%s\": tls and "
311 					    "non-tls on same address/port",
312 					    srv->srv_conf.name);
313 					serverconfig_free(srv_conf);
314 					free(srv);
315 					YYERROR;
316 				}
317 				if (server_tls_cmp(s, srv, 0) != 0) {
318 					yyerror("server \"%s\": tls "
319 					    "configuration mismatch on same "
320 					    "address/port",
321 					    srv->srv_conf.name);
322 					serverconfig_free(srv_conf);
323 					free(srv);
324 					YYERROR;
325 				}
326 			}
327 
328 			if ((srv->srv_conf.flags & SRVFLAG_TLS) &&
329 			    srv->srv_conf.tls_protocols == 0) {
330 				yyerror("server \"%s\": no tls protocols",
331 				    srv->srv_conf.name);
332 				serverconfig_free(srv_conf);
333 				free(srv);
334 				YYERROR;
335 			}
336 
337 			if (server_tls_load_keypair(srv) == -1) {
338 				yyerror("server \"%s\": failed to load "
339 				    "public/private keys", srv->srv_conf.name);
340 				serverconfig_free(srv_conf);
341 				free(srv);
342 				YYERROR;
343 			}
344 
345 			DPRINTF("adding server \"%s[%u]\"",
346 			    srv->srv_conf.name, srv->srv_conf.id);
347 
348 			TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
349 
350 			/*
351 			 * Add aliases and additional listen addresses as
352 			 * individual servers.
353 			 */
354 			TAILQ_FOREACH(a, &srv->srv_hosts, entry) {
355 				/* listen address */
356 				if (a->ss.ss_family == AF_UNSPEC)
357 					continue;
358 				TAILQ_FOREACH(b, &srv->srv_hosts, entry) {
359 					/* alias name */
360 					if (*b->name == '\0' ||
361 					    (b == &srv->srv_conf && b == a))
362 						continue;
363 
364 					if ((sn = server_inherit(srv,
365 					    b, a)) == NULL) {
366 						serverconfig_free(srv_conf);
367 						free(srv);
368 						YYABORT;
369 					}
370 
371 					DPRINTF("adding server \"%s[%u]\"",
372 					    sn->srv_conf.name, sn->srv_conf.id);
373 
374 					TAILQ_INSERT_TAIL(conf->sc_servers,
375 					    sn, srv_entry);
376 				}
377 			}
378 
379 			/* Remove temporary aliases */
380 			TAILQ_FOREACH_SAFE(a, &srv->srv_hosts, entry, b) {
381 				TAILQ_REMOVE(&srv->srv_hosts, a, entry);
382 				if (a == &srv->srv_conf)
383 					continue;
384 				serverconfig_free(a);
385 				free(a);
386 			}
387 
388 			srv = NULL;
389 			srv_conf = NULL;
390 		}
391 		;
392 
393 serveropts_l	: serveropts_l serveroptsl nl
394 		| serveroptsl optnl
395 		;
396 
397 serveroptsl	: LISTEN ON STRING opttls port {
398 			struct addresslist	 al;
399 			struct address		*h;
400 			struct server_config	*s_conf, *alias = NULL;
401 
402 			if (parentsrv != NULL) {
403 				yyerror("listen %s inside location", $3);
404 				free($3);
405 				YYERROR;
406 			}
407 
408 			if (srv->srv_conf.ss.ss_family != AF_UNSPEC) {
409 				if ((alias = calloc(1,
410 				    sizeof(*alias))) == NULL)
411 					fatal("out of memory");
412 
413 				/* Add as an IP-based alias. */
414 				s_conf = alias;
415 			} else
416 				s_conf = &srv->srv_conf;
417 
418 			TAILQ_INIT(&al);
419 			if (host($3, &al, 1, &$5, NULL, -1) <= 0) {
420 				yyerror("invalid listen ip: %s", $3);
421 				free($3);
422 				YYERROR;
423 			}
424 			free($3);
425 			h = TAILQ_FIRST(&al);
426 			memcpy(&s_conf->ss, &h->ss, sizeof(s_conf->ss));
427 			s_conf->port = h->port.val[0];
428 			s_conf->prefixlen = h->prefixlen;
429 			host_free(&al);
430 
431 			if ($4)
432 				s_conf->flags |= SRVFLAG_TLS;
433 
434 			if (alias != NULL) {
435 				/* IP-based; use name match flags from parent */
436 				alias->flags &= ~SRVFLAG_SERVER_MATCH;
437 				alias->flags |= srv->srv_conf.flags &
438 				    SRVFLAG_SERVER_MATCH;
439 				TAILQ_INSERT_TAIL(&srv->srv_hosts,
440 				    alias, entry);
441 			}
442 		}
443 		| ALIAS optmatch STRING		{
444 			struct server_config	*alias;
445 
446 			if (parentsrv != NULL) {
447 				yyerror("alias inside location");
448 				free($3);
449 				YYERROR;
450 			}
451 
452 			if ((alias = calloc(1, sizeof(*alias))) == NULL)
453 				fatal("out of memory");
454 
455 			if (strlcpy(alias->name, $3, sizeof(alias->name)) >=
456 			    sizeof(alias->name)) {
457 				yyerror("server alias truncated");
458 				free($3);
459 				free(alias);
460 				YYERROR;
461 			}
462 			free($3);
463 
464 			if ($2)
465 				alias->flags |= SRVFLAG_SERVER_MATCH;
466 
467 			TAILQ_INSERT_TAIL(&srv->srv_hosts, alias, entry);
468 		}
469 		| tcpip			{
470 			if (parentsrv != NULL) {
471 				yyerror("tcp flags inside location");
472 				YYERROR;
473 			}
474 		}
475 		| connection		{
476 			if (parentsrv != NULL) {
477 				yyerror("connection options inside location");
478 				YYERROR;
479 			}
480 		}
481 		| tls			{
482 			struct server_config	*sc;
483 			int			 tls_flag = 0;
484 
485 			if (parentsrv != NULL) {
486 				yyerror("tls configuration inside location");
487 				YYERROR;
488 			}
489 
490 			/* Ensure that at least one server has TLS enabled. */
491 			TAILQ_FOREACH(sc, &srv->srv_hosts, entry) {
492 				tls_flag |= (sc->flags & SRVFLAG_TLS);
493 			}
494 			if (tls_flag == 0) {
495 				yyerror("tls options without tls listener");
496 				YYERROR;
497 			}
498 		}
499 		| root
500 		| directory
501 		| logformat
502 		| fastcgi
503 		| authenticate
504 		| filter
505 		| LOCATION optmatch STRING	{
506 			struct server	*s;
507 
508 			if (srv->srv_conf.ss.ss_family == AF_UNSPEC) {
509 				yyerror("listen address not specified");
510 				free($3);
511 				YYERROR;
512 			}
513 
514 			if (parentsrv != NULL) {
515 				yyerror("location %s inside location", $3);
516 				free($3);
517 				YYERROR;
518 			}
519 
520 			if (!loadcfg) {
521 				free($3);
522 				YYACCEPT;
523 			}
524 
525 			if ((s = calloc(1, sizeof (*s))) == NULL)
526 				fatal("out of memory");
527 
528 			if (strlcpy(s->srv_conf.location, $3,
529 			    sizeof(s->srv_conf.location)) >=
530 			    sizeof(s->srv_conf.location)) {
531 				yyerror("server location truncated");
532 				free($3);
533 				free(s);
534 				YYERROR;
535 			}
536 			free($3);
537 
538 			if (strlcpy(s->srv_conf.name, srv->srv_conf.name,
539 			    sizeof(s->srv_conf.name)) >=
540 			    sizeof(s->srv_conf.name)) {
541 				yyerror("server name truncated");
542 				free(s);
543 				YYERROR;
544 			}
545 
546 			s->srv_conf.id = ++last_server_id;
547 			/* A location entry uses the parent id */
548 			s->srv_conf.parent_id = srv->srv_conf.id;
549 			s->srv_conf.flags = SRVFLAG_LOCATION;
550 			if ($2)
551 				s->srv_conf.flags |= SRVFLAG_LOCATION_MATCH;
552 			s->srv_s = -1;
553 			memcpy(&s->srv_conf.ss, &srv->srv_conf.ss,
554 			    sizeof(s->srv_conf.ss));
555 			s->srv_conf.port = srv->srv_conf.port;
556 			s->srv_conf.prefixlen = srv->srv_conf.prefixlen;
557 
558 			if (last_server_id == INT_MAX) {
559 				yyerror("too many servers/locations defined");
560 				free(s);
561 				YYERROR;
562 			}
563 			parentsrv = srv;
564 			srv = s;
565 			srv_conf = &srv->srv_conf;
566 			SPLAY_INIT(&srv->srv_clients);
567 		} '{' optnl serveropts_l '}'	{
568 			struct server	*s = NULL;
569 
570 			TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
571 				if ((s->srv_conf.flags & SRVFLAG_LOCATION) &&
572 				    s->srv_conf.id == srv_conf->id &&
573 				    strcmp(s->srv_conf.location,
574 				    srv_conf->location) == 0)
575 					break;
576 			}
577 			if (s != NULL) {
578 				yyerror("location \"%s\" defined twice",
579 				    srv->srv_conf.location);
580 				serverconfig_free(srv_conf);
581 				free(srv);
582 				YYABORT;
583 			}
584 
585 			DPRINTF("adding location \"%s\" for \"%s[%u]\"",
586 			    srv->srv_conf.location,
587 			    srv->srv_conf.name, srv->srv_conf.id);
588 
589 			TAILQ_INSERT_TAIL(conf->sc_servers, srv, srv_entry);
590 
591 			srv = parentsrv;
592 			srv_conf = &parentsrv->srv_conf;
593 			parentsrv = NULL;
594 		}
595 		| DEFAULT TYPE mediastring	{
596 			srv_conf->flags |= SRVFLAG_DEFAULT_TYPE;
597 			memcpy(&srv_conf->default_type, &media,
598 			    sizeof(struct media_type));
599 		}
600 		| include
601 		| hsts				{
602 			if (parentsrv != NULL) {
603 				yyerror("hsts inside location");
604 				YYERROR;
605 			}
606 			srv->srv_conf.flags |= SRVFLAG_SERVER_HSTS;
607 		}
608 		;
609 
610 hsts		: HSTS '{' optnl hstsflags_l '}'
611 		| HSTS hstsflags
612 		| HSTS
613 		;
614 
615 hstsflags_l	: hstsflags optcommanl hstsflags_l
616 		| hstsflags optnl
617 		;
618 
619 hstsflags	: MAXAGE NUMBER		{
620 			if ($2 < 0 || $2 > INT_MAX) {
621 				yyerror("invalid number of seconds: %lld", $2);
622 				YYERROR;
623 			}
624 			srv_conf->hsts_max_age = $2;
625 		}
626 		| SUBDOMAINS		{
627 			srv->srv_conf.hsts_flags |= HSTSFLAG_SUBDOMAINS;
628 		}
629 		| PRELOAD		{
630 			srv->srv_conf.hsts_flags |= HSTSFLAG_PRELOAD;
631 		}
632 		;
633 
634 fastcgi		: NO FCGI		{
635 			srv_conf->flags &= ~SRVFLAG_FCGI;
636 			srv_conf->flags |= SRVFLAG_NO_FCGI;
637 		}
638 		| FCGI			{
639 			srv_conf->flags &= ~SRVFLAG_NO_FCGI;
640 			srv_conf->flags |= SRVFLAG_FCGI;
641 		}
642 		| FCGI			{
643 			srv_conf->flags &= ~SRVFLAG_NO_FCGI;
644 			srv_conf->flags |= SRVFLAG_FCGI;
645 		} '{' optnl fcgiflags_l '}'
646 		| FCGI			{
647 			srv_conf->flags &= ~SRVFLAG_NO_FCGI;
648 			srv_conf->flags |= SRVFLAG_FCGI;
649 		} fcgiflags
650 		;
651 
652 fcgiflags_l	: fcgiflags optcommanl fcgiflags_l
653 		| fcgiflags optnl
654 		;
655 
656 fcgiflags	: SOCKET STRING		{
657 			if (strlcpy(srv_conf->socket, $2,
658 			    sizeof(srv_conf->socket)) >=
659 			    sizeof(srv_conf->socket)) {
660 				yyerror("fastcgi socket too long");
661 				free($2);
662 				YYERROR;
663 			}
664 			free($2);
665 			srv_conf->flags |= SRVFLAG_SOCKET;
666 		}
667 		;
668 
669 connection	: CONNECTION '{' optnl conflags_l '}'
670 		| CONNECTION conflags
671 		;
672 
673 conflags_l	: conflags optcommanl conflags_l
674 		| conflags optnl
675 		;
676 
677 conflags	: TIMEOUT timeout		{
678 			memcpy(&srv_conf->timeout, &$2,
679 			    sizeof(struct timeval));
680 		}
681 		| MAXIMUM REQUESTS NUMBER	{
682 			srv_conf->maxrequests = $3;
683 		}
684 		| MAXIMUM REQUEST BODY NUMBER	{
685 			srv_conf->maxrequestbody = $4;
686 		}
687 		;
688 
689 tls		: TLS '{' optnl tlsopts_l '}'
690 		| TLS tlsopts
691 		;
692 
693 tlsopts_l	: tlsopts optcommanl tlsopts_l
694 		| tlsopts optnl
695 		;
696 
697 tlsopts		: CERTIFICATE STRING		{
698 			free(srv_conf->tls_cert_file);
699 			if ((srv_conf->tls_cert_file = strdup($2)) == NULL)
700 				fatal("out of memory");
701 			free($2);
702 		}
703 		| KEY STRING			{
704 			free(srv_conf->tls_key_file);
705 			if ((srv_conf->tls_key_file = strdup($2)) == NULL)
706 				fatal("out of memory");
707 			free($2);
708 		}
709 		| CIPHERS STRING		{
710 			if (strlcpy(srv_conf->tls_ciphers, $2,
711 			    sizeof(srv_conf->tls_ciphers)) >=
712 			    sizeof(srv_conf->tls_ciphers)) {
713 				yyerror("ciphers too long");
714 				free($2);
715 				YYERROR;
716 			}
717 			free($2);
718 		}
719 		| DHE STRING			{
720 			if (strlcpy(srv_conf->tls_dhe_params, $2,
721 			    sizeof(srv_conf->tls_dhe_params)) >=
722 			    sizeof(srv_conf->tls_dhe_params)) {
723 				yyerror("dhe too long");
724 				free($2);
725 				YYERROR;
726 			}
727 			free($2);
728 		}
729 		| ECDHE STRING			{
730 			if (strlcpy(srv_conf->tls_ecdhe_curve, $2,
731 			    sizeof(srv_conf->tls_ecdhe_curve)) >=
732 			    sizeof(srv_conf->tls_ecdhe_curve)) {
733 				yyerror("ecdhe too long");
734 				free($2);
735 				YYERROR;
736 			}
737 			free($2);
738 		}
739 		| PROTOCOLS STRING		{
740 			if (tls_config_parse_protocols(
741 			    &srv_conf->tls_protocols, $2) != 0) {
742 				yyerror("invalid tls protocols");
743 				free($2);
744 				YYERROR;
745 			}
746 			free($2);
747 		}
748 		;
749 
750 root		: ROOT rootflags
751 		| ROOT '{' optnl rootflags_l '}'
752 		;
753 
754 rootflags_l	: rootflags optcommanl rootflags_l
755 		| rootflags optnl
756 		;
757 
758 rootflags	: STRING		{
759 			if (strlcpy(srv->srv_conf.root, $1,
760 			    sizeof(srv->srv_conf.root)) >=
761 			    sizeof(srv->srv_conf.root)) {
762 				yyerror("document root too long");
763 				free($1);
764 				YYERROR;
765 			}
766 			free($1);
767 			srv->srv_conf.flags |= SRVFLAG_ROOT;
768 		}
769 		| STRIP NUMBER		{
770 			if ($2 < 0 || $2 > INT_MAX) {
771 				yyerror("invalid strip number");
772 				YYERROR;
773 			}
774 			srv->srv_conf.strip = $2;
775 		}
776 		;
777 
778 authenticate	: NO AUTHENTICATE		{
779 			srv->srv_conf.flags |= SRVFLAG_NO_AUTH;
780 		}
781 		| AUTHENTICATE authopts		{
782 			struct auth	*auth;
783 
784 			if ((auth = auth_add(conf->sc_auth, &$2)) == NULL) {
785 				yyerror("failed to add auth");
786 				YYERROR;
787 			}
788 
789 			if (auth->auth_id == 0) {
790 				/* New htpasswd, get new Id */
791 				auth->auth_id = ++last_auth_id;
792 				if (last_auth_id == INT_MAX) {
793 					yyerror("too many auth ids defined");
794 					auth_free(conf->sc_auth, auth);
795 					YYERROR;
796 				}
797 			}
798 
799 			srv->srv_conf.auth_id = auth->auth_id;
800 			srv->srv_conf.flags |= SRVFLAG_AUTH;
801 		}
802 		;
803 
804 authopts	: STRING WITH STRING	{
805 			if (strlcpy(srv->srv_conf.auth_realm, $1,
806 			    sizeof(srv->srv_conf.auth_realm)) >=
807 			    sizeof(srv->srv_conf.auth_realm)) {
808 				yyerror("basic auth realm name too long");
809 				free($1);
810 				YYERROR;
811 			}
812 			free($1);
813 			if (strlcpy($$.auth_htpasswd, $3,
814 			    sizeof($$.auth_htpasswd)) >=
815 			    sizeof($$.auth_htpasswd)) {
816 				yyerror("password file name too long");
817 				free($3);
818 				YYERROR;
819 			}
820 			free($3);
821 
822 		}
823 		| WITH STRING		{
824 			if (strlcpy($$.auth_htpasswd, $2,
825 			    sizeof($$.auth_htpasswd)) >=
826 			    sizeof($$.auth_htpasswd)) {
827 				yyerror("password file name too long");
828 				free($2);
829 				YYERROR;
830 			}
831 			free($2);
832 		};
833 
834 directory	: DIRECTORY dirflags
835 		| DIRECTORY '{' optnl dirflags_l '}'
836 		;
837 
838 dirflags_l	: dirflags optcommanl dirflags_l
839 		| dirflags optnl
840 		;
841 
842 dirflags	: INDEX STRING		{
843 			if (strlcpy(srv_conf->index, $2,
844 			    sizeof(srv_conf->index)) >=
845 			    sizeof(srv_conf->index)) {
846 				yyerror("index file too long");
847 				free($2);
848 				YYERROR;
849 			}
850 			srv_conf->flags &= ~SRVFLAG_NO_INDEX;
851 			srv_conf->flags |= SRVFLAG_INDEX;
852 			free($2);
853 		}
854 		| NO INDEX		{
855 			srv_conf->flags &= ~SRVFLAG_INDEX;
856 			srv_conf->flags |= SRVFLAG_NO_INDEX;
857 		}
858 		| AUTO INDEX		{
859 			srv_conf->flags &= ~SRVFLAG_NO_AUTO_INDEX;
860 			srv_conf->flags |= SRVFLAG_AUTO_INDEX;
861 		}
862 		| NO AUTO INDEX		{
863 			srv_conf->flags &= ~SRVFLAG_AUTO_INDEX;
864 			srv_conf->flags |= SRVFLAG_NO_AUTO_INDEX;
865 		}
866 		;
867 
868 
869 logformat	: LOG logflags
870 		| LOG '{' optnl logflags_l '}'
871 		| NO LOG		{
872 			srv_conf->flags &= ~SRVFLAG_LOG;
873 			srv_conf->flags |= SRVFLAG_NO_LOG;
874 		}
875 		;
876 
877 logflags_l	: logflags optcommanl logflags_l
878 		| logflags optnl
879 		;
880 
881 logflags	: STYLE logstyle
882 		| SYSLOG		{
883 			srv_conf->flags &= ~SRVFLAG_NO_SYSLOG;
884 			srv_conf->flags |= SRVFLAG_SYSLOG;
885 		}
886 		| NO SYSLOG		{
887 			srv_conf->flags &= ~SRVFLAG_SYSLOG;
888 			srv_conf->flags |= SRVFLAG_NO_SYSLOG;
889 		}
890 		| ACCESS STRING		{
891 			if (strlcpy(srv_conf->accesslog, $2,
892 			    sizeof(srv_conf->accesslog)) >=
893 			    sizeof(srv_conf->accesslog)) {
894 				yyerror("access log name too long");
895 				free($2);
896 				YYERROR;
897 			}
898 			free($2);
899 			srv_conf->flags |= SRVFLAG_ACCESS_LOG;
900 		}
901 		| ERR STRING		{
902 			if (strlcpy(srv_conf->errorlog, $2,
903 			    sizeof(srv_conf->errorlog)) >=
904 			    sizeof(srv_conf->errorlog)) {
905 				yyerror("error log name too long");
906 				free($2);
907 				YYERROR;
908 			}
909 			free($2);
910 			srv_conf->flags |= SRVFLAG_ERROR_LOG;
911 		}
912 		;
913 
914 logstyle	: COMMON		{
915 			srv_conf->flags &= ~SRVFLAG_NO_LOG;
916 			srv_conf->flags |= SRVFLAG_LOG;
917 			srv_conf->logformat = LOG_FORMAT_COMMON;
918 		}
919 		| COMBINED		{
920 			srv_conf->flags &= ~SRVFLAG_NO_LOG;
921 			srv_conf->flags |= SRVFLAG_LOG;
922 			srv_conf->logformat = LOG_FORMAT_COMBINED;
923 		}
924 		| CONNECTION		{
925 			srv_conf->flags &= ~SRVFLAG_NO_LOG;
926 			srv_conf->flags |= SRVFLAG_LOG;
927 			srv_conf->logformat = LOG_FORMAT_CONNECTION;
928 		}
929 		;
930 
931 filter		: block RETURN NUMBER optstring	{
932 			if ($3 <= 0 || server_httperror_byid($3) == NULL) {
933 				yyerror("invalid return code: %lld", $3);
934 				free($4);
935 				YYERROR;
936 			}
937 			srv_conf->return_code = $3;
938 
939 			if ($4 != NULL) {
940 				/* Only for 3xx redirection headers */
941 				if ($3 < 300 || $3 > 399) {
942 					yyerror("invalid return code for "
943 					    "location URI");
944 					free($4);
945 					YYERROR;
946 				}
947 				srv_conf->return_uri = $4;
948 				srv_conf->return_uri_len = strlen($4) + 1;
949 			}
950 		}
951 		| block DROP			{
952 			/* No return code, silently drop the connection */
953 			srv_conf->return_code = 0;
954 		}
955 		| block				{
956 			/* Forbidden */
957 			srv_conf->return_code = 403;
958 		}
959 		| PASS				{
960 			srv_conf->flags &= ~SRVFLAG_BLOCK;
961 			srv_conf->flags |= SRVFLAG_NO_BLOCK;
962 		}
963 		;
964 
965 block		: BLOCK				{
966 			srv_conf->flags &= ~SRVFLAG_NO_BLOCK;
967 			srv_conf->flags |= SRVFLAG_BLOCK;
968 		}
969 		;
970 
971 optmatch	: /* empty */		{ $$ = 0; }
972 		| MATCH			{ $$ = 1; }
973 		;
974 
975 optstring	: /* empty */		{ $$ = NULL; }
976 		| STRING		{ $$ = $1; }
977 		;
978 
979 tcpip		: TCP '{' optnl tcpflags_l '}'
980 		| TCP tcpflags
981 		;
982 
983 tcpflags_l	: tcpflags optcommanl tcpflags_l
984 		| tcpflags optnl
985 		;
986 
987 tcpflags	: SACK			{ srv_conf->tcpflags |= TCPFLAG_SACK; }
988 		| NO SACK		{ srv_conf->tcpflags |= TCPFLAG_NSACK; }
989 		| NODELAY		{
990 			srv_conf->tcpflags |= TCPFLAG_NODELAY;
991 		}
992 		| NO NODELAY		{
993 			srv_conf->tcpflags |= TCPFLAG_NNODELAY;
994 		}
995 		| BACKLOG NUMBER	{
996 			if ($2 < 0 || $2 > SERVER_MAX_CLIENTS) {
997 				yyerror("invalid backlog: %lld", $2);
998 				YYERROR;
999 			}
1000 			srv_conf->tcpbacklog = $2;
1001 		}
1002 		| SOCKET BUFFER NUMBER	{
1003 			srv_conf->tcpflags |= TCPFLAG_BUFSIZ;
1004 			if ((srv_conf->tcpbufsiz = $3) < 0) {
1005 				yyerror("invalid socket buffer size: %lld", $3);
1006 				YYERROR;
1007 			}
1008 		}
1009 		| IP STRING NUMBER	{
1010 			if ($3 < 0) {
1011 				yyerror("invalid ttl: %lld", $3);
1012 				free($2);
1013 				YYERROR;
1014 			}
1015 			if (strcasecmp("ttl", $2) == 0) {
1016 				srv_conf->tcpflags |= TCPFLAG_IPTTL;
1017 				srv_conf->tcpipttl = $3;
1018 			} else if (strcasecmp("minttl", $2) == 0) {
1019 				srv_conf->tcpflags |= TCPFLAG_IPMINTTL;
1020 				srv_conf->tcpipminttl = $3;
1021 			} else {
1022 				yyerror("invalid TCP/IP flag: %s", $2);
1023 				free($2);
1024 				YYERROR;
1025 			}
1026 			free($2);
1027 		}
1028 		;
1029 
1030 types		: TYPES	'{' optnl mediaopts_l '}'
1031 		;
1032 
1033 mediaopts_l	: mediaopts_l mediaoptsl nl
1034 		| mediaoptsl nl
1035 		;
1036 
1037 mediaoptsl	: mediastring medianames_l optsemicolon
1038 		| include
1039 		;
1040 
1041 mediastring	: STRING '/' STRING	{
1042 			if (strlcpy(media.media_type, $1,
1043 			    sizeof(media.media_type)) >=
1044 			    sizeof(media.media_type) ||
1045 			    strlcpy(media.media_subtype, $3,
1046 			    sizeof(media.media_subtype)) >=
1047 			    sizeof(media.media_subtype)) {
1048 				yyerror("media type too long");
1049 				free($1);
1050 				free($3);
1051 				YYERROR;
1052 			}
1053 			free($1);
1054 			free($3);
1055 		}
1056 		;
1057 
1058 medianames_l	: medianames_l medianamesl
1059 		| medianamesl
1060 		;
1061 
1062 medianamesl	: numberstring				{
1063 			if (strlcpy(media.media_name, $1,
1064 			    sizeof(media.media_name)) >=
1065 			    sizeof(media.media_name)) {
1066 				yyerror("media name too long");
1067 				free($1);
1068 				YYERROR;
1069 			}
1070 			free($1);
1071 
1072 			if (!loadcfg)
1073 				break;
1074 
1075 			if (media_add(conf->sc_mediatypes, &media) == NULL) {
1076 				yyerror("failed to add media type");
1077 				YYERROR;
1078 			}
1079 		}
1080 		;
1081 
1082 port		: PORT NUMBER {
1083 			if ($2 <= 0 || $2 >= (int)USHRT_MAX) {
1084 				yyerror("invalid port: %lld", $2);
1085 				YYERROR;
1086 			}
1087 			$$.val[0] = htons($2);
1088 		}
1089 		| PORT STRING {
1090 			int	 val;
1091 
1092 			if ((val = getservice($2)) == -1) {
1093 				yyerror("invalid port: %s", $2);
1094 				free($2);
1095 				YYERROR;
1096 			}
1097 			free($2);
1098 
1099 			$$.val[0] = val;
1100 		}
1101 		;
1102 
1103 timeout		: NUMBER
1104 		{
1105 			if ($1 < 0) {
1106 				yyerror("invalid timeout: %lld", $1);
1107 				YYERROR;
1108 			}
1109 			$$.tv_sec = $1;
1110 			$$.tv_usec = 0;
1111 		}
1112 		;
1113 
1114 numberstring	: NUMBER		{
1115 			char *s;
1116 			if (asprintf(&s, "%lld", $1) == -1) {
1117 				yyerror("asprintf: number");
1118 				YYERROR;
1119 			}
1120 			$$ = s;
1121 		}
1122 		| STRING
1123 		;
1124 
1125 optsemicolon	: ';'
1126 		|
1127 		;
1128 
1129 optnl		: '\n' optnl
1130 		|
1131 		;
1132 
1133 optcommanl	: ',' optnl
1134 		| nl
1135 		;
1136 
1137 nl		: '\n' optnl
1138 		;
1139 
1140 %%
1141 
1142 struct keywords {
1143 	const char	*k_name;
1144 	int		 k_val;
1145 };
1146 
1147 int
1148 yyerror(const char *fmt, ...)
1149 {
1150 	va_list		 ap;
1151 	char		*msg;
1152 
1153 	file->errors++;
1154 	va_start(ap, fmt);
1155 	if (vasprintf(&msg, fmt, ap) == -1)
1156 		fatalx("yyerror vasprintf");
1157 	va_end(ap);
1158 	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
1159 	free(msg);
1160 	return (0);
1161 }
1162 
1163 int
1164 kw_cmp(const void *k, const void *e)
1165 {
1166 	return (strcmp(k, ((const struct keywords *)e)->k_name));
1167 }
1168 
1169 int
1170 lookup(char *s)
1171 {
1172 	/* this has to be sorted always */
1173 	static const struct keywords keywords[] = {
1174 		{ "access",		ACCESS },
1175 		{ "alias",		ALIAS },
1176 		{ "authenticate",	AUTHENTICATE},
1177 		{ "auto",		AUTO },
1178 		{ "backlog",		BACKLOG },
1179 		{ "block",		BLOCK },
1180 		{ "body",		BODY },
1181 		{ "buffer",		BUFFER },
1182 		{ "certificate",	CERTIFICATE },
1183 		{ "chroot",		CHROOT },
1184 		{ "ciphers",		CIPHERS },
1185 		{ "combined",		COMBINED },
1186 		{ "common",		COMMON },
1187 		{ "connection",		CONNECTION },
1188 		{ "default",		DEFAULT },
1189 		{ "dhe",		DHE },
1190 		{ "directory",		DIRECTORY },
1191 		{ "drop",		DROP },
1192 		{ "ecdhe",		ECDHE },
1193 		{ "error",		ERR },
1194 		{ "fastcgi",		FCGI },
1195 		{ "hsts",		HSTS },
1196 		{ "include",		INCLUDE },
1197 		{ "index",		INDEX },
1198 		{ "ip",			IP },
1199 		{ "key",		KEY },
1200 		{ "listen",		LISTEN },
1201 		{ "location",		LOCATION },
1202 		{ "log",		LOG },
1203 		{ "logdir",		LOGDIR },
1204 		{ "match",		MATCH },
1205 		{ "max",		MAXIMUM },
1206 		{ "max-age",		MAXAGE },
1207 		{ "no",			NO },
1208 		{ "nodelay",		NODELAY },
1209 		{ "on",			ON },
1210 		{ "pass",		PASS },
1211 		{ "port",		PORT },
1212 		{ "prefork",		PREFORK },
1213 		{ "preload",		PRELOAD },
1214 		{ "protocols",		PROTOCOLS },
1215 		{ "request",		REQUEST },
1216 		{ "requests",		REQUESTS },
1217 		{ "return",		RETURN },
1218 		{ "root",		ROOT },
1219 		{ "sack",		SACK },
1220 		{ "server",		SERVER },
1221 		{ "socket",		SOCKET },
1222 		{ "strip",		STRIP },
1223 		{ "style",		STYLE },
1224 		{ "subdomains",		SUBDOMAINS },
1225 		{ "syslog",		SYSLOG },
1226 		{ "tcp",		TCP },
1227 		{ "timeout",		TIMEOUT },
1228 		{ "tls",		TLS },
1229 		{ "type",		TYPE },
1230 		{ "types",		TYPES },
1231 		{ "with",		WITH }
1232 	};
1233 	const struct keywords	*p;
1234 
1235 	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
1236 	    sizeof(keywords[0]), kw_cmp);
1237 
1238 	if (p)
1239 		return (p->k_val);
1240 	else
1241 		return (STRING);
1242 }
1243 
1244 #define MAXPUSHBACK	128
1245 
1246 unsigned char	*parsebuf;
1247 int		 parseindex;
1248 unsigned char	 pushback_buffer[MAXPUSHBACK];
1249 int		 pushback_index = 0;
1250 
1251 int
1252 lgetc(int quotec)
1253 {
1254 	int		c, next;
1255 
1256 	if (parsebuf) {
1257 		/* Read character from the parsebuffer instead of input. */
1258 		if (parseindex >= 0) {
1259 			c = parsebuf[parseindex++];
1260 			if (c != '\0')
1261 				return (c);
1262 			parsebuf = NULL;
1263 		} else
1264 			parseindex++;
1265 	}
1266 
1267 	if (pushback_index)
1268 		return (pushback_buffer[--pushback_index]);
1269 
1270 	if (quotec) {
1271 		if ((c = getc(file->stream)) == EOF) {
1272 			yyerror("reached end of file while parsing "
1273 			    "quoted string");
1274 			if (file == topfile || popfile() == EOF)
1275 				return (EOF);
1276 			return (quotec);
1277 		}
1278 		return (c);
1279 	}
1280 
1281 	while ((c = getc(file->stream)) == '\\') {
1282 		next = getc(file->stream);
1283 		if (next != '\n') {
1284 			c = next;
1285 			break;
1286 		}
1287 		yylval.lineno = file->lineno;
1288 		file->lineno++;
1289 	}
1290 
1291 	while (c == EOF) {
1292 		if (file == topfile || popfile() == EOF)
1293 			return (EOF);
1294 		c = getc(file->stream);
1295 	}
1296 	return (c);
1297 }
1298 
1299 int
1300 lungetc(int c)
1301 {
1302 	if (c == EOF)
1303 		return (EOF);
1304 	if (parsebuf) {
1305 		parseindex--;
1306 		if (parseindex >= 0)
1307 			return (c);
1308 	}
1309 	if (pushback_index < MAXPUSHBACK-1)
1310 		return (pushback_buffer[pushback_index++] = c);
1311 	else
1312 		return (EOF);
1313 }
1314 
1315 int
1316 findeol(void)
1317 {
1318 	int	c;
1319 
1320 	parsebuf = NULL;
1321 
1322 	/* skip to either EOF or the first real EOL */
1323 	while (1) {
1324 		if (pushback_index)
1325 			c = pushback_buffer[--pushback_index];
1326 		else
1327 			c = lgetc(0);
1328 		if (c == '\n') {
1329 			file->lineno++;
1330 			break;
1331 		}
1332 		if (c == EOF)
1333 			break;
1334 	}
1335 	return (ERROR);
1336 }
1337 
1338 int
1339 yylex(void)
1340 {
1341 	unsigned char	 buf[8096];
1342 	unsigned char	*p, *val;
1343 	int		 quotec, next, c;
1344 	int		 token;
1345 
1346 top:
1347 	p = buf;
1348 	while ((c = lgetc(0)) == ' ' || c == '\t')
1349 		; /* nothing */
1350 
1351 	yylval.lineno = file->lineno;
1352 	if (c == '#')
1353 		while ((c = lgetc(0)) != '\n' && c != EOF)
1354 			; /* nothing */
1355 	if (c == '$' && parsebuf == NULL) {
1356 		while (1) {
1357 			if ((c = lgetc(0)) == EOF)
1358 				return (0);
1359 
1360 			if (p + 1 >= buf + sizeof(buf) - 1) {
1361 				yyerror("string too long");
1362 				return (findeol());
1363 			}
1364 			if (isalnum(c) || c == '_') {
1365 				*p++ = c;
1366 				continue;
1367 			}
1368 			*p = '\0';
1369 			lungetc(c);
1370 			break;
1371 		}
1372 		val = symget(buf);
1373 		if (val == NULL) {
1374 			yyerror("macro '%s' not defined", buf);
1375 			return (findeol());
1376 		}
1377 		parsebuf = val;
1378 		parseindex = 0;
1379 		goto top;
1380 	}
1381 
1382 	switch (c) {
1383 	case '\'':
1384 	case '"':
1385 		quotec = c;
1386 		while (1) {
1387 			if ((c = lgetc(quotec)) == EOF)
1388 				return (0);
1389 			if (c == '\n') {
1390 				file->lineno++;
1391 				continue;
1392 			} else if (c == '\\') {
1393 				if ((next = lgetc(quotec)) == EOF)
1394 					return (0);
1395 				if (next == quotec || c == ' ' || c == '\t')
1396 					c = next;
1397 				else if (next == '\n') {
1398 					file->lineno++;
1399 					continue;
1400 				} else
1401 					lungetc(next);
1402 			} else if (c == quotec) {
1403 				*p = '\0';
1404 				break;
1405 			} else if (c == '\0') {
1406 				yyerror("syntax error");
1407 				return (findeol());
1408 			}
1409 			if (p + 1 >= buf + sizeof(buf) - 1) {
1410 				yyerror("string too long");
1411 				return (findeol());
1412 			}
1413 			*p++ = c;
1414 		}
1415 		yylval.v.string = strdup(buf);
1416 		if (yylval.v.string == NULL)
1417 			err(1, "yylex: strdup");
1418 		return (STRING);
1419 	}
1420 
1421 #define allowed_to_end_number(x) \
1422 	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1423 
1424 	if (c == '-' || isdigit(c)) {
1425 		do {
1426 			*p++ = c;
1427 			if ((unsigned)(p-buf) >= sizeof(buf)) {
1428 				yyerror("string too long");
1429 				return (findeol());
1430 			}
1431 		} while ((c = lgetc(0)) != EOF && isdigit(c));
1432 		lungetc(c);
1433 		if (p == buf + 1 && buf[0] == '-')
1434 			goto nodigits;
1435 		if (c == EOF || allowed_to_end_number(c)) {
1436 			const char *errstr = NULL;
1437 
1438 			*p = '\0';
1439 			yylval.v.number = strtonum(buf, LLONG_MIN,
1440 			    LLONG_MAX, &errstr);
1441 			if (errstr) {
1442 				yyerror("\"%s\" invalid number: %s",
1443 				    buf, errstr);
1444 				return (findeol());
1445 			}
1446 			return (NUMBER);
1447 		} else {
1448 nodigits:
1449 			while (p > buf + 1)
1450 				lungetc(*--p);
1451 			c = *--p;
1452 			if (c == '-')
1453 				return (c);
1454 		}
1455 	}
1456 
1457 #define allowed_in_string(x) \
1458 	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1459 	x != '{' && x != '}' && x != '<' && x != '>' && \
1460 	x != '!' && x != '=' && x != '#' && \
1461 	x != ',' && x != ';' && x != '/'))
1462 
1463 	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
1464 		do {
1465 			*p++ = c;
1466 			if ((unsigned)(p-buf) >= sizeof(buf)) {
1467 				yyerror("string too long");
1468 				return (findeol());
1469 			}
1470 		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1471 		lungetc(c);
1472 		*p = '\0';
1473 		if ((token = lookup(buf)) == STRING)
1474 			if ((yylval.v.string = strdup(buf)) == NULL)
1475 				err(1, "yylex: strdup");
1476 		return (token);
1477 	}
1478 	if (c == '\n') {
1479 		yylval.lineno = file->lineno;
1480 		file->lineno++;
1481 	}
1482 	if (c == EOF)
1483 		return (0);
1484 	return (c);
1485 }
1486 
1487 int
1488 check_file_secrecy(int fd, const char *fname)
1489 {
1490 	struct stat	st;
1491 
1492 	if (fstat(fd, &st)) {
1493 		log_warn("cannot stat %s", fname);
1494 		return (-1);
1495 	}
1496 	if (st.st_uid != 0 && st.st_uid != getuid()) {
1497 		log_warnx("%s: owner not root or current user", fname);
1498 		return (-1);
1499 	}
1500 	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
1501 		log_warnx("%s: group writable or world read/writable", fname);
1502 		return (-1);
1503 	}
1504 	return (0);
1505 }
1506 
1507 struct file *
1508 pushfile(const char *name, int secret)
1509 {
1510 	struct file	*nfile;
1511 
1512 	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
1513 		log_warn("%s: malloc", __func__);
1514 		return (NULL);
1515 	}
1516 	if ((nfile->name = strdup(name)) == NULL) {
1517 		log_warn("%s: malloc", __func__);
1518 		free(nfile);
1519 		return (NULL);
1520 	}
1521 	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1522 		log_warn("%s: %s", __func__, nfile->name);
1523 		free(nfile->name);
1524 		free(nfile);
1525 		return (NULL);
1526 	} else if (secret &&
1527 	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1528 		fclose(nfile->stream);
1529 		free(nfile->name);
1530 		free(nfile);
1531 		return (NULL);
1532 	}
1533 	nfile->lineno = 1;
1534 	TAILQ_INSERT_TAIL(&files, nfile, entry);
1535 	return (nfile);
1536 }
1537 
1538 int
1539 popfile(void)
1540 {
1541 	struct file	*prev;
1542 
1543 	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
1544 		prev->errors += file->errors;
1545 
1546 	TAILQ_REMOVE(&files, file, entry);
1547 	fclose(file->stream);
1548 	free(file->name);
1549 	free(file);
1550 	file = prev;
1551 	return (file ? 0 : EOF);
1552 }
1553 
1554 int
1555 parse_config(const char *filename, struct httpd *x_conf)
1556 {
1557 	struct sym		*sym, *next;
1558 	struct media_type	 dflt = HTTPD_DEFAULT_TYPE;
1559 
1560 	conf = x_conf;
1561 	if (config_init(conf) == -1) {
1562 		log_warn("%s: cannot initialize configuration", __func__);
1563 		return (-1);
1564 	}
1565 
1566 	/* Set default media type */
1567 	memcpy(&conf->sc_default_type, &dflt, sizeof(struct media_type));
1568 
1569 	errors = 0;
1570 
1571 	if ((file = pushfile(filename, 0)) == NULL)
1572 		return (-1);
1573 
1574 	topfile = file;
1575 	setservent(1);
1576 
1577 	yyparse();
1578 	errors = file->errors;
1579 	popfile();
1580 
1581 	endservent();
1582 	endprotoent();
1583 
1584 	/* Free macros */
1585 	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
1586 		next = TAILQ_NEXT(sym, entry);
1587 		if (!sym->persist) {
1588 			free(sym->nam);
1589 			free(sym->val);
1590 			TAILQ_REMOVE(&symhead, sym, entry);
1591 			free(sym);
1592 		}
1593 	}
1594 
1595 	return (errors ? -1 : 0);
1596 }
1597 
1598 int
1599 load_config(const char *filename, struct httpd *x_conf)
1600 {
1601 	struct sym		*sym, *next;
1602 	struct http_mediatype	 mediatypes[] = MEDIA_TYPES;
1603 	struct media_type	 m;
1604 	int			 i;
1605 
1606 	conf = x_conf;
1607 	conf->sc_flags = 0;
1608 
1609 	loadcfg = 1;
1610 	errors = 0;
1611 	last_server_id = 0;
1612 	last_auth_id = 0;
1613 
1614 	srv = NULL;
1615 
1616 	if ((file = pushfile(filename, 0)) == NULL)
1617 		return (-1);
1618 
1619 	topfile = file;
1620 	setservent(1);
1621 
1622 	yyparse();
1623 	errors = file->errors;
1624 	popfile();
1625 
1626 	endservent();
1627 	endprotoent();
1628 
1629 	/* Free macros and check which have not been used. */
1630 	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
1631 		next = TAILQ_NEXT(sym, entry);
1632 		if ((conf->sc_opts & HTTPD_OPT_VERBOSE) && !sym->used)
1633 			fprintf(stderr, "warning: macro '%s' not "
1634 			    "used\n", sym->nam);
1635 		if (!sym->persist) {
1636 			free(sym->nam);
1637 			free(sym->val);
1638 			TAILQ_REMOVE(&symhead, sym, entry);
1639 			free(sym);
1640 		}
1641 	}
1642 
1643 	if (TAILQ_EMPTY(conf->sc_servers)) {
1644 		log_warnx("no actions, nothing to do");
1645 		errors++;
1646 	}
1647 
1648 	if (RB_EMPTY(conf->sc_mediatypes)) {
1649 		/* Add default media types */
1650 		for (i = 0; mediatypes[i].media_name != NULL; i++) {
1651 			(void)strlcpy(m.media_name, mediatypes[i].media_name,
1652 			    sizeof(m.media_name));
1653 			(void)strlcpy(m.media_type, mediatypes[i].media_type,
1654 			    sizeof(m.media_type));
1655 			(void)strlcpy(m.media_subtype,
1656 			    mediatypes[i].media_subtype,
1657 			    sizeof(m.media_subtype));
1658 			m.media_encoding = NULL;
1659 
1660 			if (media_add(conf->sc_mediatypes, &m) == NULL) {
1661 				log_warnx("failed to add default media \"%s\"",
1662 				    m.media_name);
1663 				errors++;
1664 			}
1665 		}
1666 	}
1667 
1668 	return (errors ? -1 : 0);
1669 }
1670 
1671 int
1672 symset(const char *nam, const char *val, int persist)
1673 {
1674 	struct sym	*sym;
1675 
1676 	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
1677 	    sym = TAILQ_NEXT(sym, entry))
1678 		;	/* nothing */
1679 
1680 	if (sym != NULL) {
1681 		if (sym->persist == 1)
1682 			return (0);
1683 		else {
1684 			free(sym->nam);
1685 			free(sym->val);
1686 			TAILQ_REMOVE(&symhead, sym, entry);
1687 			free(sym);
1688 		}
1689 	}
1690 	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1691 		return (-1);
1692 
1693 	sym->nam = strdup(nam);
1694 	if (sym->nam == NULL) {
1695 		free(sym);
1696 		return (-1);
1697 	}
1698 	sym->val = strdup(val);
1699 	if (sym->val == NULL) {
1700 		free(sym->nam);
1701 		free(sym);
1702 		return (-1);
1703 	}
1704 	sym->used = 0;
1705 	sym->persist = persist;
1706 	TAILQ_INSERT_TAIL(&symhead, sym, entry);
1707 	return (0);
1708 }
1709 
1710 int
1711 cmdline_symset(char *s)
1712 {
1713 	char	*sym, *val;
1714 	int	ret;
1715 	size_t	len;
1716 
1717 	if ((val = strrchr(s, '=')) == NULL)
1718 		return (-1);
1719 
1720 	len = strlen(s) - strlen(val) + 1;
1721 	if ((sym = malloc(len)) == NULL)
1722 		errx(1, "cmdline_symset: malloc");
1723 
1724 	(void)strlcpy(sym, s, len);
1725 
1726 	ret = symset(sym, val + 1, 1);
1727 	free(sym);
1728 
1729 	return (ret);
1730 }
1731 
1732 char *
1733 symget(const char *nam)
1734 {
1735 	struct sym	*sym;
1736 
1737 	TAILQ_FOREACH(sym, &symhead, entry)
1738 		if (strcmp(nam, sym->nam) == 0) {
1739 			sym->used = 1;
1740 			return (sym->val);
1741 		}
1742 	return (NULL);
1743 }
1744 
1745 struct address *
1746 host_v4(const char *s)
1747 {
1748 	struct in_addr		 ina;
1749 	struct sockaddr_in	*sain;
1750 	struct address		*h;
1751 
1752 	memset(&ina, 0, sizeof(ina));
1753 	if (inet_pton(AF_INET, s, &ina) != 1)
1754 		return (NULL);
1755 
1756 	if ((h = calloc(1, sizeof(*h))) == NULL)
1757 		fatal(__func__);
1758 	sain = (struct sockaddr_in *)&h->ss;
1759 	sain->sin_len = sizeof(struct sockaddr_in);
1760 	sain->sin_family = AF_INET;
1761 	sain->sin_addr.s_addr = ina.s_addr;
1762 	if (sain->sin_addr.s_addr == INADDR_ANY)
1763 		h->prefixlen = 0; /* 0.0.0.0 address */
1764 	else
1765 		h->prefixlen = -1; /* host address */
1766 	return (h);
1767 }
1768 
1769 struct address *
1770 host_v6(const char *s)
1771 {
1772 	struct addrinfo		 hints, *res;
1773 	struct sockaddr_in6	*sa_in6;
1774 	struct address		*h = NULL;
1775 
1776 	memset(&hints, 0, sizeof(hints));
1777 	hints.ai_family = AF_INET6;
1778 	hints.ai_socktype = SOCK_DGRAM; /* dummy */
1779 	hints.ai_flags = AI_NUMERICHOST;
1780 	if (getaddrinfo(s, "0", &hints, &res) == 0) {
1781 		if ((h = calloc(1, sizeof(*h))) == NULL)
1782 			fatal(__func__);
1783 		sa_in6 = (struct sockaddr_in6 *)&h->ss;
1784 		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
1785 		sa_in6->sin6_family = AF_INET6;
1786 		memcpy(&sa_in6->sin6_addr,
1787 		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
1788 		    sizeof(sa_in6->sin6_addr));
1789 		sa_in6->sin6_scope_id =
1790 		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
1791 		if (memcmp(&sa_in6->sin6_addr, &in6addr_any,
1792 		    sizeof(sa_in6->sin6_addr)) == 0)
1793 			h->prefixlen = 0; /* any address */
1794 		else
1795 			h->prefixlen = -1; /* host address */
1796 		freeaddrinfo(res);
1797 	}
1798 
1799 	return (h);
1800 }
1801 
1802 int
1803 host_dns(const char *s, struct addresslist *al, int max,
1804     struct portrange *port, const char *ifname, int ipproto)
1805 {
1806 	struct addrinfo		 hints, *res0, *res;
1807 	int			 error, cnt = 0;
1808 	struct sockaddr_in	*sain;
1809 	struct sockaddr_in6	*sin6;
1810 	struct address		*h;
1811 
1812 	if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0)
1813 		return (cnt);
1814 
1815 	memset(&hints, 0, sizeof(hints));
1816 	hints.ai_family = PF_UNSPEC;
1817 	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
1818 	hints.ai_flags = AI_ADDRCONFIG;
1819 	error = getaddrinfo(s, NULL, &hints, &res0);
1820 	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
1821 		return (0);
1822 	if (error) {
1823 		log_warnx("%s: could not parse \"%s\": %s", __func__, s,
1824 		    gai_strerror(error));
1825 		return (-1);
1826 	}
1827 
1828 	for (res = res0; res && cnt < max; res = res->ai_next) {
1829 		if (res->ai_family != AF_INET &&
1830 		    res->ai_family != AF_INET6)
1831 			continue;
1832 		if ((h = calloc(1, sizeof(*h))) == NULL)
1833 			fatal(__func__);
1834 
1835 		if (port != NULL)
1836 			memcpy(&h->port, port, sizeof(h->port));
1837 		if (ifname != NULL) {
1838 			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1839 			    sizeof(h->ifname))
1840 				log_warnx("%s: interface name truncated",
1841 				    __func__);
1842 			freeaddrinfo(res0);
1843 			free(h);
1844 			return (-1);
1845 		}
1846 		if (ipproto != -1)
1847 			h->ipproto = ipproto;
1848 		h->ss.ss_family = res->ai_family;
1849 		h->prefixlen = -1; /* host address */
1850 
1851 		if (res->ai_family == AF_INET) {
1852 			sain = (struct sockaddr_in *)&h->ss;
1853 			sain->sin_len = sizeof(struct sockaddr_in);
1854 			sain->sin_addr.s_addr = ((struct sockaddr_in *)
1855 			    res->ai_addr)->sin_addr.s_addr;
1856 		} else {
1857 			sin6 = (struct sockaddr_in6 *)&h->ss;
1858 			sin6->sin6_len = sizeof(struct sockaddr_in6);
1859 			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
1860 			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
1861 		}
1862 
1863 		TAILQ_INSERT_HEAD(al, h, entry);
1864 		cnt++;
1865 	}
1866 	if (cnt == max && res) {
1867 		log_warnx("%s: %s resolves to more than %d hosts", __func__,
1868 		    s, max);
1869 	}
1870 	freeaddrinfo(res0);
1871 	return (cnt);
1872 }
1873 
1874 int
1875 host_if(const char *s, struct addresslist *al, int max,
1876     struct portrange *port, const char *ifname, int ipproto)
1877 {
1878 	struct ifaddrs		*ifap, *p;
1879 	struct sockaddr_in	*sain;
1880 	struct sockaddr_in6	*sin6;
1881 	struct address		*h;
1882 	int			 cnt = 0, af;
1883 
1884 	if (getifaddrs(&ifap) == -1)
1885 		fatal("getifaddrs");
1886 
1887 	/* First search for IPv4 addresses */
1888 	af = AF_INET;
1889 
1890  nextaf:
1891 	for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) {
1892 		if (p->ifa_addr->sa_family != af ||
1893 		    (strcmp(s, p->ifa_name) != 0 &&
1894 		    !is_if_in_group(p->ifa_name, s)))
1895 			continue;
1896 		if ((h = calloc(1, sizeof(*h))) == NULL)
1897 			fatal("calloc");
1898 
1899 		if (port != NULL)
1900 			memcpy(&h->port, port, sizeof(h->port));
1901 		if (ifname != NULL) {
1902 			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1903 			    sizeof(h->ifname))
1904 				log_warnx("%s: interface name truncated",
1905 				    __func__);
1906 			freeifaddrs(ifap);
1907 			return (-1);
1908 		}
1909 		if (ipproto != -1)
1910 			h->ipproto = ipproto;
1911 		h->ss.ss_family = af;
1912 		h->prefixlen = -1; /* host address */
1913 
1914 		if (af == AF_INET) {
1915 			sain = (struct sockaddr_in *)&h->ss;
1916 			sain->sin_len = sizeof(struct sockaddr_in);
1917 			sain->sin_addr.s_addr = ((struct sockaddr_in *)
1918 			    p->ifa_addr)->sin_addr.s_addr;
1919 		} else {
1920 			sin6 = (struct sockaddr_in6 *)&h->ss;
1921 			sin6->sin6_len = sizeof(struct sockaddr_in6);
1922 			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
1923 			    p->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
1924 			sin6->sin6_scope_id = ((struct sockaddr_in6 *)
1925 			    p->ifa_addr)->sin6_scope_id;
1926 		}
1927 
1928 		TAILQ_INSERT_HEAD(al, h, entry);
1929 		cnt++;
1930 	}
1931 	if (af == AF_INET) {
1932 		/* Next search for IPv6 addresses */
1933 		af = AF_INET6;
1934 		goto nextaf;
1935 	}
1936 
1937 	if (cnt > max) {
1938 		log_warnx("%s: %s resolves to more than %d hosts", __func__,
1939 		    s, max);
1940 	}
1941 	freeifaddrs(ifap);
1942 	return (cnt);
1943 }
1944 
1945 int
1946 host(const char *s, struct addresslist *al, int max,
1947     struct portrange *port, const char *ifname, int ipproto)
1948 {
1949 	struct address *h;
1950 
1951 	if (strcmp("*", s) == 0)
1952 		s = "0.0.0.0";
1953 
1954 	h = host_v4(s);
1955 
1956 	/* IPv6 address? */
1957 	if (h == NULL)
1958 		h = host_v6(s);
1959 
1960 	if (h != NULL) {
1961 		if (port != NULL)
1962 			memcpy(&h->port, port, sizeof(h->port));
1963 		if (ifname != NULL) {
1964 			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1965 			    sizeof(h->ifname)) {
1966 				log_warnx("%s: interface name truncated",
1967 				    __func__);
1968 				free(h);
1969 				return (-1);
1970 			}
1971 		}
1972 		if (ipproto != -1)
1973 			h->ipproto = ipproto;
1974 
1975 		TAILQ_INSERT_HEAD(al, h, entry);
1976 		return (1);
1977 	}
1978 
1979 	return (host_dns(s, al, max, port, ifname, ipproto));
1980 }
1981 
1982 void
1983 host_free(struct addresslist *al)
1984 {
1985 	struct address	 *h;
1986 
1987 	while ((h = TAILQ_FIRST(al)) != NULL) {
1988 		TAILQ_REMOVE(al, h, entry);
1989 		free(h);
1990 	}
1991 }
1992 
1993 struct server *
1994 server_inherit(struct server *src, struct server_config *alias,
1995     struct server_config *addr)
1996 {
1997 	struct server	*dst, *s, *dstl;
1998 
1999 	if ((dst = calloc(1, sizeof(*dst))) == NULL)
2000 		fatal("out of memory");
2001 
2002 	/* Copy the source server and assign a new Id */
2003 	memcpy(&dst->srv_conf, &src->srv_conf, sizeof(dst->srv_conf));
2004 	if ((dst->srv_conf.tls_cert_file =
2005 	    strdup(src->srv_conf.tls_cert_file)) == NULL)
2006 		fatal("out of memory");
2007 	if ((dst->srv_conf.tls_key_file =
2008 	    strdup(src->srv_conf.tls_key_file)) == NULL)
2009 		fatal("out of memory");
2010 	dst->srv_conf.tls_cert = NULL;
2011 	dst->srv_conf.tls_key = NULL;
2012 	dst->srv_conf.tls_cert_len = 0;
2013 	dst->srv_conf.tls_key_len = 0;
2014 
2015 	if (src->srv_conf.return_uri != NULL &&
2016 	    (dst->srv_conf.return_uri =
2017 	    strdup(src->srv_conf.return_uri)) == NULL)
2018 		fatal("out of memory");
2019 
2020 	dst->srv_conf.id = ++last_server_id;
2021 	dst->srv_conf.parent_id = dst->srv_conf.id;
2022 	dst->srv_s = -1;
2023 
2024 	if (last_server_id == INT_MAX) {
2025 		yyerror("too many servers defined");
2026 		serverconfig_free(&dst->srv_conf);
2027 		free(dst);
2028 		return (NULL);
2029 	}
2030 
2031 	/* Now set alias and listen address */
2032 	strlcpy(dst->srv_conf.name, alias->name, sizeof(dst->srv_conf.name));
2033 	memcpy(&dst->srv_conf.ss, &addr->ss, sizeof(dst->srv_conf.ss));
2034 	dst->srv_conf.port = addr->port;
2035 	dst->srv_conf.prefixlen = addr->prefixlen;
2036 	if (addr->flags & SRVFLAG_TLS)
2037 		dst->srv_conf.flags |= SRVFLAG_TLS;
2038 	else
2039 		dst->srv_conf.flags &= ~SRVFLAG_TLS;
2040 
2041 	/* Don't inherit the "match" option, use it from the alias */
2042 	dst->srv_conf.flags &= ~SRVFLAG_SERVER_MATCH;
2043 	dst->srv_conf.flags |= (alias->flags & SRVFLAG_SERVER_MATCH);
2044 
2045 	if (server_tls_load_keypair(dst) == -1) {
2046 		yyerror("failed to load public/private keys "
2047 		    "for server %s", dst->srv_conf.name);
2048 		serverconfig_free(&dst->srv_conf);
2049 		free(dst);
2050 		return (NULL);
2051 	}
2052 
2053 	/* Check if the new server already exists */
2054 	if (server_match(dst, 1) != NULL) {
2055 		yyerror("server \"%s\" defined twice",
2056 		    dst->srv_conf.name);
2057 		serverconfig_free(&dst->srv_conf);
2058 		free(dst);
2059 		return (NULL);
2060 	}
2061 
2062 	/* Copy all the locations of the source server */
2063 	TAILQ_FOREACH(s, conf->sc_servers, srv_entry) {
2064 		if (!(s->srv_conf.flags & SRVFLAG_LOCATION &&
2065 		    s->srv_conf.parent_id == src->srv_conf.parent_id))
2066 			continue;
2067 
2068 		if ((dstl = calloc(1, sizeof(*dstl))) == NULL)
2069 			fatal("out of memory");
2070 
2071 		memcpy(&dstl->srv_conf, &s->srv_conf, sizeof(dstl->srv_conf));
2072 		strlcpy(dstl->srv_conf.name, alias->name,
2073 		    sizeof(dstl->srv_conf.name));
2074 
2075 		/* Copy the new Id and listen address */
2076 		dstl->srv_conf.id = ++last_server_id;
2077 		dstl->srv_conf.parent_id = dst->srv_conf.id;
2078 		memcpy(&dstl->srv_conf.ss, &addr->ss,
2079 		    sizeof(dstl->srv_conf.ss));
2080 		dstl->srv_conf.port = addr->port;
2081 		dstl->srv_conf.prefixlen = addr->prefixlen;
2082 		dstl->srv_s = -1;
2083 
2084 		DPRINTF("adding location \"%s\" for \"%s[%u]\"",
2085 		    dstl->srv_conf.location,
2086 		    dstl->srv_conf.name, dstl->srv_conf.id);
2087 
2088 		TAILQ_INSERT_TAIL(conf->sc_servers, dstl, srv_entry);
2089 	}
2090 
2091 	return (dst);
2092 }
2093 
2094 int
2095 getservice(char *n)
2096 {
2097 	struct servent	*s;
2098 	const char	*errstr;
2099 	long long	 llval;
2100 
2101 	llval = strtonum(n, 0, UINT16_MAX, &errstr);
2102 	if (errstr) {
2103 		s = getservbyname(n, "tcp");
2104 		if (s == NULL)
2105 			s = getservbyname(n, "udp");
2106 		if (s == NULL) {
2107 			yyerror("unknown port %s", n);
2108 			return (-1);
2109 		}
2110 		return (s->s_port);
2111 	}
2112 
2113 	return (htons((unsigned short)llval));
2114 }
2115 
2116 int
2117 is_if_in_group(const char *ifname, const char *groupname)
2118 {
2119 	unsigned int		 len;
2120 	struct ifgroupreq	 ifgr;
2121 	struct ifg_req		*ifg;
2122 	int			 s;
2123 	int			 ret = 0;
2124 
2125 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
2126 		err(1, "socket");
2127 
2128 	memset(&ifgr, 0, sizeof(ifgr));
2129 	if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ)
2130 		err(1, "IFNAMSIZ");
2131 	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
2132 		if (errno == EINVAL || errno == ENOTTY)
2133 			goto end;
2134 		err(1, "SIOCGIFGROUP");
2135 	}
2136 
2137 	len = ifgr.ifgr_len;
2138 	ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req),
2139 	    sizeof(struct ifg_req));
2140 	if (ifgr.ifgr_groups == NULL)
2141 		err(1, "getifgroups");
2142 	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
2143 		err(1, "SIOCGIFGROUP");
2144 
2145 	ifg = ifgr.ifgr_groups;
2146 	for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
2147 		len -= sizeof(struct ifg_req);
2148 		if (strcmp(ifg->ifgrq_group, groupname) == 0) {
2149 			ret = 1;
2150 			break;
2151 		}
2152 	}
2153 	free(ifgr.ifgr_groups);
2154 
2155 end:
2156 	close(s);
2157 	return (ret);
2158 }
2159