xref: /openbsd/usr.sbin/relayd/relay.c (revision 7b36286a)
1 /*	$OpenBSD: relay.c,v 1.104 2008/08/11 08:24:41 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/time.h>
22 #include <sys/stat.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <sys/tree.h>
26 #include <sys/hash.h>
27 #include <sys/resource.h>
28 
29 #include <net/if.h>
30 #include <netinet/in_systm.h>
31 #include <netinet/in.h>
32 #include <netinet/ip.h>
33 #include <netinet/tcp.h>
34 #include <arpa/inet.h>
35 
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <err.h>
43 #include <pwd.h>
44 #include <event.h>
45 #include <fnmatch.h>
46 
47 #include <openssl/ssl.h>
48 
49 #include "relayd.h"
50 
51 void		 relay_sig_handler(int sig, short, void *);
52 void		 relay_statistics(int, short, void *);
53 void		 relay_dispatch_pfe(int, short, void *);
54 void		 relay_dispatch_parent(int, short, void *);
55 void		 relay_shutdown(void);
56 
57 void		 relay_privinit(void);
58 void		 relay_nodedebug(const char *, struct protonode *);
59 void		 relay_protodebug(struct relay *);
60 void		 relay_init(void);
61 void		 relay_launch(void);
62 int		 relay_socket(struct sockaddr_storage *, in_port_t,
63 		    struct protocol *, int);
64 int		 relay_socket_listen(struct sockaddr_storage *, in_port_t,
65 		    struct protocol *);
66 int		 relay_socket_connect(struct sockaddr_storage *, in_port_t,
67 		    struct protocol *, int);
68 
69 void		 relay_accept(int, short, void *);
70 void		 relay_input(struct session *);
71 
72 int		 relay_connect(struct session *);
73 void		 relay_connected(int, short, void *);
74 void		 relay_bindanyreq(struct session *, in_port_t, int);
75 void		 relay_bindany(int, short, void *);
76 
77 u_int32_t	 relay_hash_addr(struct sockaddr_storage *, u_int32_t);
78 
79 void		 relay_write(struct bufferevent *, void *);
80 void		 relay_read(struct bufferevent *, void *);
81 void		 relay_error(struct bufferevent *, short, void *);
82 void		 relay_dump(struct ctl_relay_event *, const void *, size_t);
83 
84 int		 relay_resolve(struct ctl_relay_event *,
85 		    struct protonode *, struct protonode *);
86 int		 relay_handle_http(struct ctl_relay_event *,
87 		    struct protonode *, struct protonode *,
88 		    struct protonode *, int);
89 void		 relay_read_http(struct bufferevent *, void *);
90 static int	_relay_lookup_url(struct ctl_relay_event *, char *, char *,
91 		    char *, enum digest_type);
92 int		 relay_lookup_url(struct ctl_relay_event *,
93 		    const char *, enum digest_type);
94 int		 relay_lookup_query(struct ctl_relay_event *);
95 int		 relay_lookup_cookie(struct ctl_relay_event *, const char *);
96 void		 relay_read_httpcontent(struct bufferevent *, void *);
97 void		 relay_read_httpchunks(struct bufferevent *, void *);
98 char		*relay_expand_http(struct ctl_relay_event *, char *,
99 		    char *, size_t);
100 void		 relay_close_http(struct session *, u_int, const char *,
101 		    u_int16_t);
102 
103 SSL_CTX		*relay_ssl_ctx_create(struct relay *);
104 void		 relay_ssl_transaction(struct session *);
105 void		 relay_ssl_accept(int, short, void *);
106 void		 relay_ssl_connected(struct ctl_relay_event *);
107 void		 relay_ssl_readcb(int, short, void *);
108 void		 relay_ssl_writecb(int, short, void *);
109 
110 int		 relay_bufferevent_add(struct event *, int);
111 #ifdef notyet
112 int		 relay_bufferevent_printf(struct ctl_relay_event *,
113 		    const char *, ...);
114 #endif
115 int		 relay_bufferevent_print(struct ctl_relay_event *, char *);
116 int		 relay_bufferevent_write_buffer(struct ctl_relay_event *,
117 		    struct evbuffer *);
118 int		 relay_bufferevent_write_chunk(struct ctl_relay_event *,
119 		    struct evbuffer *, size_t);
120 int		 relay_bufferevent_write(struct ctl_relay_event *,
121 		    void *, size_t);
122 char		*relay_load_file(const char *, off_t *);
123 static __inline int
124 		 relay_proto_cmp(struct protonode *, struct protonode *);
125 extern void	 bufferevent_read_pressure_cb(struct evbuffer *, size_t,
126 		    size_t, void *);
127 
128 volatile sig_atomic_t relay_sessions;
129 objid_t relay_conid;
130 
131 static struct relayd		*env = NULL;
132 struct imsgbuf			*ibuf_pfe;
133 struct imsgbuf			*ibuf_main;
134 int				 proc_id;
135 
136 void
137 relay_sig_handler(int sig, short event, void *arg)
138 {
139 	switch (sig) {
140 	case SIGTERM:
141 	case SIGINT:
142 		(void)event_loopexit(NULL);
143 	}
144 }
145 
146 pid_t
147 relay(struct relayd *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
148     int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
149     int pipe_pfe2relay[RELAY_MAXPROC][2])
150 {
151 	pid_t		 pid;
152 	struct passwd	*pw;
153 	struct event	 ev_sigint;
154 	struct event	 ev_sigterm;
155 	int		 i;
156 
157 	switch (pid = fork()) {
158 	case -1:
159 		fatal("relay: cannot fork");
160 	case 0:
161 		break;
162 	default:
163 		return (pid);
164 	}
165 
166 	env = x_env;
167 	purge_config(env, PURGE_RDRS);
168 
169 	/* Need root privileges for relay initialization */
170 	relay_privinit();
171 
172 	if ((pw = getpwnam(RELAYD_USER)) == NULL)
173 		fatal("relay: getpwnam");
174 
175 #ifndef DEBUG
176 	if (chroot(pw->pw_dir) == -1)
177 		fatal("relay: chroot");
178 	if (chdir("/") == -1)
179 		fatal("relay: chdir(\"/\")");
180 
181 #else
182 #warning disabling privilege revocation and chroot in DEBUG mode
183 #endif
184 
185 	setproctitle("socket relay engine");
186 	relayd_process = PROC_RELAY;
187 
188 #ifndef DEBUG
189 	if (setgroups(1, &pw->pw_gid) ||
190 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
191 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
192 		fatal("relay: can't drop privileges");
193 #endif
194 
195 	/* Fork child handlers */
196 	for (i = 1; i < env->sc_prefork_relay; i++) {
197 		if (fork() == 0) {
198 			proc_id = i;
199 			break;
200 		}
201 	}
202 
203 	event_init();
204 
205 	/* Per-child initialization */
206 	relay_init();
207 
208 	signal_set(&ev_sigint, SIGINT, relay_sig_handler, NULL);
209 	signal_set(&ev_sigterm, SIGTERM, relay_sig_handler, NULL);
210 	signal_add(&ev_sigint, NULL);
211 	signal_add(&ev_sigterm, NULL);
212 	signal(SIGHUP, SIG_IGN);
213 	signal(SIGPIPE, SIG_IGN);
214 
215 	/* setup pipes */
216 	close(pipe_pfe2hce[0]);
217 	close(pipe_pfe2hce[1]);
218 	close(pipe_parent2hce[0]);
219 	close(pipe_parent2hce[1]);
220 	close(pipe_parent2pfe[0]);
221 	close(pipe_parent2pfe[1]);
222 	for (i = 0; i < env->sc_prefork_relay; i++) {
223 		if (i == proc_id)
224 			continue;
225 		close(pipe_parent2relay[i][0]);
226 		close(pipe_parent2relay[i][1]);
227 		close(pipe_pfe2relay[i][0]);
228 		close(pipe_pfe2relay[i][1]);
229 	}
230 	close(pipe_parent2relay[proc_id][1]);
231 	close(pipe_pfe2relay[proc_id][1]);
232 
233 	if ((ibuf_pfe = calloc(1, sizeof(struct imsgbuf))) == NULL ||
234 	    (ibuf_main = calloc(1, sizeof(struct imsgbuf))) == NULL)
235 		fatal("relay");
236 	imsg_init(ibuf_main, pipe_parent2relay[proc_id][0],
237 	    relay_dispatch_parent);
238 	imsg_init(ibuf_pfe, pipe_pfe2relay[proc_id][0], relay_dispatch_pfe);
239 
240 	ibuf_pfe->events = EV_READ;
241 	event_set(&ibuf_pfe->ev, ibuf_pfe->fd, ibuf_pfe->events,
242 	    ibuf_pfe->handler, ibuf_pfe);
243 	event_add(&ibuf_pfe->ev, NULL);
244 
245 	ibuf_main->events = EV_READ;
246 	event_set(&ibuf_main->ev, ibuf_main->fd, ibuf_main->events,
247 	    ibuf_main->handler, ibuf_main);
248 	event_add(&ibuf_main->ev, NULL);
249 
250 	relay_launch();
251 
252 	event_dispatch();
253 	relay_shutdown();
254 
255 	return (0);
256 }
257 
258 void
259 relay_shutdown(void)
260 {
261 	struct session	*con;
262 
263 	struct relay	*rlay;
264 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
265 		if (rlay->rl_conf.flags & F_DISABLE)
266 			continue;
267 		close(rlay->rl_s);
268 		while ((con = SPLAY_ROOT(&rlay->rl_sessions)) != NULL)
269 			relay_close(con, "shutdown");
270 	}
271 	usleep(200);	/* XXX relay needs to shutdown last */
272 	log_info("socket relay engine exiting");
273 	_exit(0);
274 }
275 
276 void
277 relay_nodedebug(const char *name, struct protonode *pn)
278 {
279 	const char	*s;
280 	int		 digest;
281 
282 	if (pn->action == NODE_ACTION_NONE)
283 		return;
284 
285 	fprintf(stderr, "\t\t");
286 	fprintf(stderr, "%s ", name);
287 
288 	switch (pn->type) {
289 	case NODE_TYPE_HEADER:
290 		break;
291 	case NODE_TYPE_QUERY:
292 		fprintf(stderr, "query ");
293 		break;
294 	case NODE_TYPE_COOKIE:
295 		fprintf(stderr, "cookie ");
296 		break;
297 	case NODE_TYPE_PATH:
298 		fprintf(stderr, "path ");
299 		break;
300 	case NODE_TYPE_URL:
301 		fprintf(stderr, "url ");
302 		break;
303 	}
304 
305 	switch (pn->action) {
306 	case NODE_ACTION_APPEND:
307 		fprintf(stderr, "append \"%s\" to \"%s\"",
308 		    pn->value, pn->key);
309 		break;
310 	case NODE_ACTION_CHANGE:
311 		fprintf(stderr, "change \"%s\" to \"%s\"",
312 		    pn->key, pn->value);
313 		break;
314 	case NODE_ACTION_REMOVE:
315 		fprintf(stderr, "remove \"%s\"",
316 		    pn->key);
317 		break;
318 	case NODE_ACTION_EXPECT:
319 	case NODE_ACTION_FILTER:
320 		s = pn->action == NODE_ACTION_EXPECT ? "expect" : "filter";
321 		digest = pn->flags & PNFLAG_LOOKUP_URL_DIGEST;
322 		if (strcmp(pn->value, "*") == 0)
323 			fprintf(stderr, "%s %s\"%s\"", s,
324 			    digest ? "digest " : "", pn->key);
325 		else
326 			fprintf(stderr, "%s \"%s\" from \"%s\"", s,
327 			    pn->value, pn->key);
328 		break;
329 	case NODE_ACTION_HASH:
330 		fprintf(stderr, "hash \"%s\"", pn->key);
331 		break;
332 	case NODE_ACTION_LOG:
333 		fprintf(stderr, "log \"%s\"", pn->key);
334 		break;
335 	case NODE_ACTION_MARK:
336 		if (strcmp(pn->value, "*") == 0)
337 			fprintf(stderr, "mark \"%s\"", pn->key);
338 		else
339 			fprintf(stderr, "mark \"%s\" from \"%s\"",
340 			    pn->value, pn->key);
341 		break;
342 	case NODE_ACTION_NONE:
343 		break;
344 	}
345 	fprintf(stderr, "\n");
346 }
347 
348 void
349 relay_protodebug(struct relay *rlay)
350 {
351 	struct protocol		*proto = rlay->rl_proto;
352 	struct protonode	*proot, *pn;
353 	struct proto_tree	*tree;
354 	const char		*name;
355 	int			 i;
356 
357 	fprintf(stderr, "protocol %d: name %s\n", proto->id, proto->name);
358 	fprintf(stderr, "\tflags: 0x%04x\n", proto->flags);
359 	if (proto->cache != -1)
360 		fprintf(stderr, "\tssl session cache: %d\n", proto->cache);
361 	fprintf(stderr, "\ttype: ");
362 	switch (proto->type) {
363 	case RELAY_PROTO_TCP:
364 		fprintf(stderr, "tcp\n");
365 		break;
366 	case RELAY_PROTO_HTTP:
367 		fprintf(stderr, "http\n");
368 		break;
369 	case RELAY_PROTO_DNS:
370 		fprintf(stderr, "dns\n");
371 		break;
372 	}
373 
374 	name = "request";
375 	tree = &proto->request_tree;
376  show:
377 	i = 0;
378 	RB_FOREACH(proot, proto_tree, tree) {
379 #if DEBUG > 1
380 		i = 0;
381 #endif
382 		PROTONODE_FOREACH(pn, proot, entry) {
383 #if DEBUG > 1
384 			i = 0;
385 #endif
386 			if (++i > 100)
387 				break;
388 			relay_nodedebug(name, pn);
389 		}
390 		/* Limit the number of displayed lines */
391 		if (++i > 100) {
392 			fprintf(stderr, "\t\t...\n");
393 			break;
394 		}
395 	}
396 	if (tree == &proto->request_tree) {
397 		name = "response";
398 		tree = &proto->response_tree;
399 		goto show;
400 	}
401 }
402 
403 void
404 relay_privinit(void)
405 {
406 	struct relay	*rlay;
407 	extern int	 debug;
408 
409 	if (env->sc_flags & F_SSL)
410 		ssl_init(env);
411 
412 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
413 		log_debug("relay_privinit: adding relay %s", rlay->rl_conf.name);
414 
415 		if (debug)
416 			relay_protodebug(rlay);
417 
418 		switch (rlay->rl_proto->type) {
419 		case RELAY_PROTO_DNS:
420 			relay_udp_privinit(env, rlay);
421 			break;
422 		case RELAY_PROTO_TCP:
423 		case RELAY_PROTO_HTTP:
424 			/* Use defaults */
425 			break;
426 		}
427 
428 		if (rlay->rl_conf.flags & F_UDP)
429 			rlay->rl_s = relay_udp_bind(&rlay->rl_conf.ss,
430 			    rlay->rl_conf.port, rlay->rl_proto);
431 		else
432 			rlay->rl_s = relay_socket_listen(&rlay->rl_conf.ss,
433 			    rlay->rl_conf.port, rlay->rl_proto);
434 		if (rlay->rl_s == -1)
435 			fatal("relay_privinit: failed to listen");
436 	}
437 }
438 
439 void
440 relay_init(void)
441 {
442 	struct relay	*rlay;
443 	struct host	*host;
444 	struct timeval	 tv;
445 	struct rlimit	 rl;
446 
447 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
448 		fatal("relay_init: failed to get resource limit");
449 	log_debug("relay_init: max open files %d", rl.rlim_max);
450 
451 	/*
452 	 * Allow the maximum number of open file descriptors for this
453 	 * login class (which should be the class "daemon" by default).
454 	 */
455 	rl.rlim_cur = rl.rlim_max;
456 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
457 		fatal("relay_init: failed to set resource limit");
458 
459 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
460 		if ((rlay->rl_conf.flags & F_SSL) &&
461 		    (rlay->rl_ssl_ctx = relay_ssl_ctx_create(rlay)) == NULL)
462 			fatal("relay_init: failed to create SSL context");
463 
464 		if (rlay->rl_dsttable != NULL) {
465 			switch (rlay->rl_conf.dstmode) {
466 			case RELAY_DSTMODE_ROUNDROBIN:
467 				rlay->rl_dstkey = 0;
468 				break;
469 			case RELAY_DSTMODE_LOADBALANCE:
470 			case RELAY_DSTMODE_HASH:
471 				rlay->rl_dstkey =
472 				    hash32_str(rlay->rl_conf.name, HASHINIT);
473 				rlay->rl_dstkey =
474 				    hash32_str(rlay->rl_dsttable->conf.name,
475 				    rlay->rl_dstkey);
476 				break;
477 			}
478 			rlay->rl_dstnhosts = 0;
479 			TAILQ_FOREACH(host, &rlay->rl_dsttable->hosts, entry) {
480 				if (rlay->rl_dstnhosts >= RELAY_MAXHOSTS)
481 					fatal("relay_init: "
482 					    "too many hosts in table");
483 				host->idx = rlay->rl_dstnhosts;
484 				rlay->rl_dsthost[rlay->rl_dstnhosts++] = host;
485 			}
486 			log_info("adding %d hosts from table %s%s",
487 			    rlay->rl_dstnhosts, rlay->rl_dsttable->conf.name,
488 			    rlay->rl_dsttable->conf.check ? "" : " (no check)");
489 		}
490 
491 		switch (rlay->rl_proto->type) {
492 		case RELAY_PROTO_DNS:
493 			relay_udp_init(rlay);
494 			break;
495 		case RELAY_PROTO_TCP:
496 		case RELAY_PROTO_HTTP:
497 			/* Use defaults */
498 			break;
499 		}
500 	}
501 
502 	/* Schedule statistics timer */
503 	evtimer_set(&env->sc_statev, relay_statistics, NULL);
504 	bcopy(&env->sc_statinterval, &tv, sizeof(tv));
505 	evtimer_add(&env->sc_statev, &tv);
506 }
507 
508 void
509 relay_statistics(int fd, short events, void *arg)
510 {
511 	struct relay		*rlay;
512 	struct ctl_stats	 crs, *cur;
513 	struct timeval		 tv, tv_now;
514 	int			 resethour = 0, resetday = 0;
515 	struct session		*con, *next_con;
516 
517 	/*
518 	 * This is a hack to calculate some average statistics.
519 	 * It doesn't try to be very accurate, but could be improved...
520 	 */
521 
522 	timerclear(&tv);
523 	if (gettimeofday(&tv_now, NULL) == -1)
524 		fatal("relay_init: gettimeofday");
525 
526 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
527 		bzero(&crs, sizeof(crs));
528 		resethour = resetday = 0;
529 
530 		cur = &rlay->rl_stats[proc_id];
531 		cur->cnt += cur->last;
532 		cur->tick++;
533 		cur->avg = (cur->last + cur->avg) / 2;
534 		cur->last_hour += cur->last;
535 		if ((cur->tick % (3600 / env->sc_statinterval.tv_sec)) == 0) {
536 			cur->avg_hour = (cur->last_hour + cur->avg_hour) / 2;
537 			resethour++;
538 		}
539 		cur->last_day += cur->last;
540 		if ((cur->tick % (86400 / env->sc_statinterval.tv_sec)) == 0) {
541 			cur->avg_day = (cur->last_day + cur->avg_day) / 2;
542 			resethour++;
543 		}
544 		bcopy(cur, &crs, sizeof(crs));
545 
546 		cur->last = 0;
547 		if (resethour)
548 			cur->last_hour = 0;
549 		if (resetday)
550 			cur->last_day = 0;
551 
552 		crs.id = rlay->rl_conf.id;
553 		crs.proc = proc_id;
554 		imsg_compose(ibuf_pfe, IMSG_STATISTICS, 0, 0, -1,
555 		    &crs, sizeof(crs));
556 
557 		for (con = SPLAY_ROOT(&rlay->rl_sessions);
558 		    con != NULL; con = next_con) {
559 			next_con = SPLAY_NEXT(session_tree,
560 			    &rlay->rl_sessions, con);
561 			timersub(&tv_now, &con->se_tv_last, &tv);
562 			if (timercmp(&tv, &rlay->rl_conf.timeout, >=))
563 				relay_close(con, "hard timeout");
564 		}
565 	}
566 
567 	/* Schedule statistics timer */
568 	evtimer_set(&env->sc_statev, relay_statistics, NULL);
569 	bcopy(&env->sc_statinterval, &tv, sizeof(tv));
570 	evtimer_add(&env->sc_statev, &tv);
571 }
572 
573 void
574 relay_launch(void)
575 {
576 	struct relay	*rlay;
577 	void		(*callback)(int, short, void *);
578 
579 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
580 		log_debug("relay_launch: running relay %s", rlay->rl_conf.name);
581 
582 		rlay->rl_up = HOST_UP;
583 
584 		if (rlay->rl_conf.flags & F_UDP)
585 			callback = relay_udp_server;
586 		else
587 			callback = relay_accept;
588 
589 		event_set(&rlay->rl_ev, rlay->rl_s, EV_READ|EV_PERSIST,
590 		    callback, rlay);
591 		event_add(&rlay->rl_ev, NULL);
592 	}
593 }
594 
595 int
596 relay_socket_af(struct sockaddr_storage *ss, in_port_t port)
597 {
598 	switch (ss->ss_family) {
599 	case AF_INET:
600 		((struct sockaddr_in *)ss)->sin_port = port;
601 		((struct sockaddr_in *)ss)->sin_len =
602 		    sizeof(struct sockaddr_in);
603 		break;
604 	case AF_INET6:
605 		((struct sockaddr_in6 *)ss)->sin6_port = port;
606 		((struct sockaddr_in6 *)ss)->sin6_len =
607 		    sizeof(struct sockaddr_in6);
608 		break;
609 	default:
610 		return (-1);
611 	}
612 
613 	return (0);
614 }
615 
616 int
617 relay_socket(struct sockaddr_storage *ss, in_port_t port,
618     struct protocol *proto, int fd)
619 {
620 	int s = -1, val;
621 	struct linger lng;
622 
623 	if (relay_socket_af(ss, port) == -1)
624 		goto bad;
625 
626 	s = fd == -1 ? socket(ss->ss_family, SOCK_STREAM, IPPROTO_TCP) : fd;
627 	if (s == -1)
628 		goto bad;
629 
630 	/*
631 	 * Socket options
632 	 */
633 	bzero(&lng, sizeof(lng));
634 	if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1)
635 		goto bad;
636 	val = 1;
637 	if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1)
638 		goto bad;
639 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
640 		goto bad;
641 	if (proto->tcpflags & TCPFLAG_BUFSIZ) {
642 		val = proto->tcpbufsiz;
643 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
644 		    &val, sizeof(val)) == -1)
645 			goto bad;
646 		val = proto->tcpbufsiz;
647 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
648 		    &val, sizeof(val)) == -1)
649 			goto bad;
650 	}
651 
652 	/*
653 	 * IP options
654 	 */
655 	if (proto->tcpflags & TCPFLAG_IPTTL) {
656 		val = (int)proto->tcpipttl;
657 		if (setsockopt(s, IPPROTO_IP, IP_TTL,
658 		    &val, sizeof(val)) == -1)
659 			goto bad;
660 	}
661 	if (proto->tcpflags & TCPFLAG_IPMINTTL) {
662 		val = (int)proto->tcpipminttl;
663 		if (setsockopt(s, IPPROTO_IP, IP_MINTTL,
664 		    &val, sizeof(val)) == -1)
665 			goto bad;
666 	}
667 
668 	/*
669 	 * TCP options
670 	 */
671 	if (proto->tcpflags & (TCPFLAG_NODELAY|TCPFLAG_NNODELAY)) {
672 		if (proto->tcpflags & TCPFLAG_NNODELAY)
673 			val = 0;
674 		else
675 			val = 1;
676 		if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
677 		    &val, sizeof(val)) == -1)
678 			goto bad;
679 	}
680 	if (proto->tcpflags & (TCPFLAG_SACK|TCPFLAG_NSACK)) {
681 		if (proto->tcpflags & TCPFLAG_NSACK)
682 			val = 0;
683 		else
684 			val = 1;
685 		if (setsockopt(s, IPPROTO_TCP, TCP_SACK_ENABLE,
686 		    &val, sizeof(val)) == -1)
687 			goto bad;
688 	}
689 
690 	return (s);
691 
692  bad:
693 	if (s != -1)
694 		close(s);
695 	return (-1);
696 }
697 
698 int
699 relay_socket_connect(struct sockaddr_storage *ss, in_port_t port,
700     struct protocol *proto, int fd)
701 {
702 	int	s;
703 
704 	if ((s = relay_socket(ss, port, proto, fd)) == -1)
705 		return (-1);
706 
707 	if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) {
708 		if (errno != EINPROGRESS)
709 			goto bad;
710 	}
711 
712 	return (s);
713 
714  bad:
715 	close(s);
716 	return (-1);
717 }
718 
719 int
720 relay_socket_listen(struct sockaddr_storage *ss, in_port_t port,
721     struct protocol *proto)
722 {
723 	int s;
724 
725 	if ((s = relay_socket(ss, port, proto, -1)) == -1)
726 		return (-1);
727 
728 	if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1)
729 		goto bad;
730 	if (listen(s, proto->tcpbacklog) == -1)
731 		goto bad;
732 
733 	return (s);
734 
735  bad:
736 	close(s);
737 	return (-1);
738 }
739 
740 void
741 relay_connected(int fd, short sig, void *arg)
742 {
743 	struct session		*con = (struct session *)arg;
744 	struct relay		*rlay = (struct relay *)con->se_relay;
745 	struct protocol		*proto = rlay->rl_proto;
746 	evbuffercb		 outrd = relay_read;
747 	evbuffercb		 outwr = relay_write;
748 	struct bufferevent	*bev;
749 
750 	if (sig == EV_TIMEOUT) {
751 		relay_close_http(con, 504, "connect timeout", 0);
752 		return;
753 	}
754 
755 	DPRINTF("relay_connected: session %d: %ssuccessful",
756 	    con->se_id, rlay->rl_proto->lateconnect ? "late connect " : "");
757 
758 	switch (rlay->rl_proto->type) {
759 	case RELAY_PROTO_HTTP:
760 		/* Check the servers's HTTP response */
761 		if (!RB_EMPTY(&rlay->rl_proto->response_tree)) {
762 			outrd = relay_read_http;
763 			if ((con->se_out.nodes = calloc(proto->response_nodes,
764 			    sizeof(u_int8_t))) == NULL) {
765 				relay_close_http(con, 500,
766 				    "failed to allocate nodes", 0);
767 				return;
768 			}
769 		}
770 		break;
771 	case RELAY_PROTO_TCP:
772 		/* Use defaults */
773 		break;
774 	default:
775 		fatalx("relay_input: unknown protocol");
776 	}
777 
778 	/*
779 	 * Relay <-> Server
780 	 */
781 	bev = bufferevent_new(fd, outrd, outwr, relay_error, &con->se_out);
782 	if (bev == NULL) {
783 		relay_close_http(con, 500,
784 		    "failed to allocate output buffer event", 0);
785 		return;
786 	}
787 	evbuffer_free(bev->output);
788 	bev->output = con->se_out.output;
789 	if (bev->output == NULL)
790 		fatal("relay_connected: invalid output buffer");
791 
792 	con->se_out.bev = bev;
793 	bufferevent_settimeout(bev,
794 	    rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec);
795 	bufferevent_enable(bev, EV_READ|EV_WRITE);
796 }
797 
798 void
799 relay_input(struct session *con)
800 {
801 	struct relay	*rlay = (struct relay *)con->se_relay;
802 	struct protocol *proto = rlay->rl_proto;
803 	evbuffercb	 inrd = relay_read;
804 	evbuffercb	 inwr = relay_write;
805 
806 	switch (rlay->rl_proto->type) {
807 	case RELAY_PROTO_HTTP:
808 		/* Check the client's HTTP request */
809 		if (!RB_EMPTY(&rlay->rl_proto->request_tree) ||
810 		    proto->lateconnect) {
811 			inrd = relay_read_http;
812 			if ((con->se_in.nodes = calloc(proto->request_nodes,
813 			    sizeof(u_int8_t))) == NULL) {
814 				relay_close(con, "failed to allocate nodes");
815 				return;
816 			}
817 		}
818 		break;
819 	case RELAY_PROTO_TCP:
820 		/* Use defaults */
821 		break;
822 	default:
823 		fatalx("relay_input: unknown protocol");
824 	}
825 
826 	/*
827 	 * Client <-> Relay
828 	 */
829 	con->se_in.bev = bufferevent_new(con->se_in.s, inrd, inwr,
830 	    relay_error, &con->se_in);
831 	if (con->se_in.bev == NULL) {
832 		relay_close(con, "failed to allocate input buffer event");
833 		return;
834 	}
835 
836 	/* Initialize the SSL wrapper */
837 	if ((rlay->rl_conf.flags & F_SSL) && con->se_in.ssl != NULL)
838 		relay_ssl_connected(&con->se_in);
839 
840 	bufferevent_settimeout(con->se_in.bev,
841 	    rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec);
842 	bufferevent_enable(con->se_in.bev, EV_READ|EV_WRITE);
843 }
844 
845 void
846 relay_write(struct bufferevent *bev, void *arg)
847 {
848 	struct ctl_relay_event	*cre = (struct ctl_relay_event *)arg;
849 	struct session		*con = (struct session *)cre->con;
850 	if (gettimeofday(&con->se_tv_last, NULL) == -1)
851 		con->se_done = 1;
852 	if (con->se_done)
853 		relay_close(con, "last write (done)");
854 }
855 
856 void
857 relay_dump(struct ctl_relay_event *cre, const void *buf, size_t len)
858 {
859 	if (!len)
860 		return;
861 
862 	/*
863 	 * This function will dump the specified message directly
864 	 * to the underlying session, without waiting for success
865 	 * of non-blocking events etc. This is useful to print an
866 	 * error message before gracefully closing the session.
867 	 */
868 	if (cre->ssl != NULL)
869 		(void)SSL_write(cre->ssl, buf, len);
870 	else
871 		(void)write(cre->s, buf, len);
872 }
873 
874 void
875 relay_read(struct bufferevent *bev, void *arg)
876 {
877 	struct ctl_relay_event	*cre = (struct ctl_relay_event *)arg;
878 	struct session		*con = (struct session *)cre->con;
879 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
880 
881 	if (gettimeofday(&con->se_tv_last, NULL) == -1)
882 		goto fail;
883 	if (!EVBUFFER_LENGTH(src))
884 		return;
885 	if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
886 		goto fail;
887 	if (con->se_done)
888 		goto done;
889 	bufferevent_enable(con->se_in.bev, EV_READ);
890 	return;
891  done:
892 	relay_close(con, "last read (done)");
893 	return;
894  fail:
895 	relay_close(con, strerror(errno));
896 }
897 
898 int
899 relay_resolve(struct ctl_relay_event *cre,
900     struct protonode *proot, struct protonode *pn)
901 {
902 	struct session		*con = (struct session *)cre->con;
903 	char			 buf[READ_BUF_SIZE], *ptr;
904 	int			 id;
905 
906 	if (pn->mark && (pn->mark != con->se_mark))
907 		return (0);
908 
909 	switch (pn->action) {
910 	case NODE_ACTION_FILTER:
911 		id = cre->nodes[proot->id];
912 		if (SIMPLEQ_NEXT(pn, entry) == NULL)
913 			cre->nodes[proot->id] = 0;
914 		if (id <= 1)
915 			return (0);
916 		break;
917 	case NODE_ACTION_EXPECT:
918 		id = cre->nodes[proot->id];
919 		if (SIMPLEQ_NEXT(pn, entry) == NULL)
920 			cre->nodes[proot->id] = 0;
921 		if (id > 1)
922 			return (0);
923 		break;
924 	default:
925 		if (cre->nodes[pn->id]) {
926 			cre->nodes[pn->id] = 0;
927 			return (0);
928 		}
929 		break;
930 	}
931 	switch (pn->action) {
932 	case NODE_ACTION_APPEND:
933 	case NODE_ACTION_CHANGE:
934 		ptr = pn->value;
935 		if ((pn->flags & PNFLAG_MACRO) &&
936 		    (ptr = relay_expand_http(cre, pn->value,
937 		    buf, sizeof(buf))) == NULL)
938 			break;
939 		if (relay_bufferevent_print(cre->dst, pn->key) == -1 ||
940 		    relay_bufferevent_print(cre->dst, ": ") == -1 ||
941 		    relay_bufferevent_print(cre->dst, ptr) == -1 ||
942 		    relay_bufferevent_print(cre->dst, "\r\n") == -1) {
943 			relay_close_http(con, 500,
944 			    "failed to modify header", 0);
945 			return (-1);
946 		}
947 		DPRINTF("relay_resolve: add '%s: %s'",
948 		    pn->key, ptr);
949 		break;
950 	case NODE_ACTION_EXPECT:
951 		DPRINTF("relay_resolve: missing '%s: %s'",
952 		    pn->key, pn->value);
953 		relay_close_http(con, 403, "incomplete request", pn->label);
954 		return (-1);
955 	case NODE_ACTION_FILTER:
956 		DPRINTF("relay_resolve: filtered '%s: %s'",
957 		    pn->key, pn->value);
958 		relay_close_http(con, 403, "rejecting request", pn->label);
959 		return (-1);
960 	default:
961 		break;
962 	}
963 	return (0);
964 }
965 
966 char *
967 relay_expand_http(struct ctl_relay_event *cre, char *val, char *buf, size_t len)
968 {
969 	struct session	*con = (struct session *)cre->con;
970 	struct relay	*rlay = (struct relay *)con->se_relay;
971 	char		 ibuf[128];
972 
973 	(void)strlcpy(buf, val, len);
974 
975 	if (strstr(val, "$REMOTE_") != NULL) {
976 		if (strstr(val, "$REMOTE_ADDR") != NULL) {
977 			if (print_host(&cre->ss, ibuf, sizeof(ibuf)) == NULL)
978 				return (NULL);
979 			if (expand_string(buf, len,
980 			    "$REMOTE_ADDR", ibuf) != 0)
981 				return (NULL);
982 		}
983 		if (strstr(val, "$REMOTE_PORT") != NULL) {
984 			snprintf(ibuf, sizeof(ibuf), "%u", ntohs(cre->port));
985 			if (expand_string(buf, len,
986 			    "$REMOTE_PORT", ibuf) != 0)
987 				return (NULL);
988 		}
989 	}
990 	if (strstr(val, "$SERVER_") != NULL) {
991 		if (strstr(val, "$SERVER_ADDR") != NULL) {
992 			if (print_host(&rlay->rl_conf.ss,
993 			    ibuf, sizeof(ibuf)) == NULL)
994 				return (NULL);
995 			if (expand_string(buf, len,
996 			    "$SERVER_ADDR", ibuf) != 0)
997 				return (NULL);
998 		}
999 		if (strstr(val, "$SERVER_PORT") != NULL) {
1000 			snprintf(ibuf, sizeof(ibuf), "%u",
1001 			    ntohs(rlay->rl_conf.port));
1002 			if (expand_string(buf, len,
1003 			    "$SERVER_PORT", ibuf) != 0)
1004 				return (NULL);
1005 		}
1006 		if (strstr(val, "$SERVER_NAME") != NULL) {
1007 			if (expand_string(buf, len,
1008 			    "$SERVER_NAME", RELAYD_SERVERNAME) != 0)
1009 				return (NULL);
1010 		}
1011 	}
1012 	if (strstr(val, "$TIMEOUT") != NULL) {
1013 		snprintf(ibuf, sizeof(ibuf), "%lu", rlay->rl_conf.timeout.tv_sec);
1014 		if (expand_string(buf, len, "$TIMEOUT", ibuf) != 0)
1015 			return (NULL);
1016 	}
1017 
1018 	return (buf);
1019 }
1020 
1021 int
1022 relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
1023     struct protonode *pn, struct protonode *pk, int header)
1024 {
1025 	struct session		*con = (struct session *)cre->con;
1026 	char			 buf[READ_BUF_SIZE], *ptr;
1027 	int			 ret = PN_DROP, mark = 0;
1028 	struct protonode	*next;
1029 
1030 	/* Check if this action depends on a marked session */
1031 	if (pn->mark != 0)
1032 		mark = pn->mark == con->se_mark ? 1 : -1;
1033 
1034 	switch (pn->action) {
1035 	case NODE_ACTION_EXPECT:
1036 	case NODE_ACTION_FILTER:
1037 	case NODE_ACTION_MARK:
1038 		break;
1039 	default:
1040 		if (mark == -1)
1041 			return (PN_PASS);
1042 		break;
1043 	}
1044 
1045 	switch (pn->action) {
1046 	case NODE_ACTION_APPEND:
1047 		if (!header)
1048 			return (PN_PASS);
1049 		ptr = pn->value;
1050 		if ((pn->flags & PNFLAG_MACRO) &&
1051 		    (ptr = relay_expand_http(cre, pn->value,
1052 		    buf, sizeof(buf))) == NULL)
1053 			break;
1054 		if (relay_bufferevent_print(cre->dst, pn->key) == -1 ||
1055 		    relay_bufferevent_print(cre->dst, ": ") == -1 ||
1056 		    relay_bufferevent_print(cre->dst, pk->value) == -1 ||
1057 		    relay_bufferevent_print(cre->dst, ", ") == -1 ||
1058 		    relay_bufferevent_print(cre->dst, ptr) == -1 ||
1059 		    relay_bufferevent_print(cre->dst, "\r\n") == -1)
1060 			goto fail;
1061 		cre->nodes[pn->id] = 1;
1062 		DPRINTF("relay_handle_http: append '%s: %s, %s'",
1063 		    pk->key, pk->value, ptr);
1064 		break;
1065 	case NODE_ACTION_CHANGE:
1066 	case NODE_ACTION_REMOVE:
1067 		if (!header)
1068 			return (PN_PASS);
1069 		DPRINTF("relay_handle_http: change/remove '%s: %s'",
1070 		    pk->key, pk->value);
1071 		break;
1072 	case NODE_ACTION_EXPECT:
1073 		/*
1074 		 * A client may specify the header line for multiple times
1075 		 * trying to circumvent the filter.
1076 		 */
1077 		if (cre->nodes[proot->id] > 1) {
1078 			relay_close_http(con, 400, "repeated header line", 0);
1079 			return (PN_FAIL);
1080 		}
1081 		/* FALLTHROUGH */
1082 	case NODE_ACTION_FILTER:
1083 		DPRINTF("relay_handle_http: %s '%s: %s'",
1084 		    (pn->action == NODE_ACTION_EXPECT) ? "expect" : "filter",
1085 		    pn->key, pn->value);
1086 
1087 		/* Do not drop the entity */
1088 		ret = PN_PASS;
1089 
1090 		if (mark != -1 &&
1091 		    fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0) {
1092 			cre->nodes[proot->id] = 1;
1093 
1094 			/* Fail instantly */
1095 			if (pn->action == NODE_ACTION_FILTER) {
1096 				relay_close_http(con, 403,
1097 				    "rejecting request", pn->label);
1098 				return (PN_FAIL);
1099 			}
1100 		}
1101 		next = SIMPLEQ_NEXT(pn, entry);
1102 		if (next == NULL || next->action != pn->action)
1103 			cre->nodes[proot->id]++;
1104 		break;
1105 	case NODE_ACTION_HASH:
1106 		DPRINTF("relay_handle_http: hash '%s: %s'",
1107 		    pn->key, pk->value);
1108 		con->se_hashkey = hash32_str(pk->value, con->se_hashkey);
1109 		ret = PN_PASS;
1110 		break;
1111 	case NODE_ACTION_LOG:
1112 		DPRINTF("relay_handle_http: log '%s: %s'",
1113 		    pn->key, pk->value);
1114 		ret = PN_PASS;
1115 		break;
1116 	case NODE_ACTION_MARK:
1117 		DPRINTF("relay_handle_http: mark '%s: %s'",
1118 		    pn->key, pk->value);
1119 		if (fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0)
1120 			con->se_mark = pn->mark;
1121 		ret = PN_PASS;
1122 		break;
1123 	case NODE_ACTION_NONE:
1124 		return (PN_PASS);
1125 	}
1126 	if (mark != -1 && pn->flags & PNFLAG_LOG) {
1127 		bzero(buf, sizeof(buf));
1128 		if (snprintf(buf, sizeof(buf), " [%s: %s]",
1129 		    pk->key, pk->value) == -1 ||
1130 		    evbuffer_add(con->se_log, buf, strlen(buf)) == -1)
1131 			goto fail;
1132 	}
1133 
1134 	return (ret);
1135  fail:
1136 	relay_close_http(con, 500, strerror(errno), 0);
1137 	return (PN_FAIL);
1138 }
1139 
1140 void
1141 relay_read_httpcontent(struct bufferevent *bev, void *arg)
1142 {
1143 	struct ctl_relay_event	*cre = (struct ctl_relay_event *)arg;
1144 	struct session		*con = (struct session *)cre->con;
1145 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
1146 	size_t			 size;
1147 
1148 	if (gettimeofday(&con->se_tv_last, NULL) == -1)
1149 		goto fail;
1150 	size = EVBUFFER_LENGTH(src);
1151 	DPRINTF("relay_read_httpcontent: size %d, to read %d",
1152 	    size, cre->toread);
1153 	if (!size)
1154 		return;
1155 	if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
1156 		goto fail;
1157 	if (size >= cre->toread)
1158 		bev->readcb = relay_read_http;
1159 	cre->toread -= size;
1160 	DPRINTF("relay_read_httpcontent: done, size %d, to read %d",
1161 	    size, cre->toread);
1162 	if (con->se_done)
1163 		goto done;
1164 	if (bev->readcb != relay_read_httpcontent)
1165 		bev->readcb(bev, arg);
1166 	bufferevent_enable(bev, EV_READ);
1167 	return;
1168  done:
1169 	relay_close(con, "last http content read");
1170 	return;
1171  fail:
1172 	relay_close(con, strerror(errno));
1173 }
1174 
1175 void
1176 relay_read_httpchunks(struct bufferevent *bev, void *arg)
1177 {
1178 	struct ctl_relay_event	*cre = (struct ctl_relay_event *)arg;
1179 	struct session		*con = (struct session *)cre->con;
1180 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
1181 	char			*line;
1182 	long			 lval;
1183 	size_t			 size;
1184 
1185 	if (gettimeofday(&con->se_tv_last, NULL) == -1)
1186 		goto fail;
1187 	size = EVBUFFER_LENGTH(src);
1188 	DPRINTF("relay_read_httpchunks: size %d, to read %d",
1189 	    size, cre->toread);
1190 	if (!size)
1191 		return;
1192 
1193 	if (!cre->toread) {
1194 		line = evbuffer_readline(src);
1195 		if (line == NULL) {
1196 			/* Ignore empty line, continue */
1197 			bufferevent_enable(bev, EV_READ);
1198 			return;
1199 		}
1200 		if (!strlen(line)) {
1201 			free(line);
1202 			goto next;
1203 		}
1204 
1205 		/* Read prepended chunk size in hex, ingore the trailer */
1206 		if (sscanf(line, "%lx", &lval) != 1) {
1207 			free(line);
1208 			relay_close(con, "invalid chunk size");
1209 			return;
1210 		}
1211 
1212 		if (relay_bufferevent_print(cre->dst, line) == -1 ||
1213 		    relay_bufferevent_print(cre->dst, "\r\n") == -1) {
1214 			free(line);
1215 			goto fail;
1216 		}
1217 		free(line);
1218 
1219 		/* Last chunk is 0 bytes followed by an empty newline */
1220 		if ((cre->toread = lval) == 0) {
1221 			DPRINTF("relay_read_httpchunks: last chunk");
1222 
1223 			line = evbuffer_readline(src);
1224 			if (line == NULL) {
1225 				relay_close(con, "invalid last chunk");
1226 				return;
1227 			}
1228 			free(line);
1229 			if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
1230 				goto fail;
1231 
1232 			/* Switch to HTTP header mode */
1233 			bev->readcb = relay_read_http;
1234 		}
1235 	} else {
1236 		/* Read chunk data */
1237 		if (size > cre->toread)
1238 			size = cre->toread;
1239 		if (relay_bufferevent_write_chunk(cre->dst, src, size) == -1)
1240 			goto fail;
1241 		cre->toread -= size;
1242 		DPRINTF("relay_read_httpchunks: done, size %d, to read %d",
1243 		    size, cre->toread);
1244 
1245 		if (cre->toread == 0) {
1246 			/* Chunk is terminated by an empty (empty) newline */
1247 			line = evbuffer_readline(src);
1248 			if (line != NULL)
1249 				free(line);
1250 			if (relay_bufferevent_print(cre->dst, "\r\n\r\n") == -1)
1251 				goto fail;
1252 		}
1253 	}
1254 
1255  next:
1256 	if (con->se_done)
1257 		goto done;
1258 	if (EVBUFFER_LENGTH(src))
1259 		bev->readcb(bev, arg);
1260 	bufferevent_enable(bev, EV_READ);
1261 	return;
1262 
1263  done:
1264 	relay_close(con, "last http chunk read (done)");
1265 	return;
1266  fail:
1267 	relay_close(con, strerror(errno));
1268 }
1269 
1270 void
1271 relay_read_http(struct bufferevent *bev, void *arg)
1272 {
1273 	struct ctl_relay_event	*cre = (struct ctl_relay_event *)arg;
1274 	struct session		*con = (struct session *)cre->con;
1275 	struct relay		*rlay = (struct relay *)con->se_relay;
1276 	struct protocol		*proto = rlay->rl_proto;
1277 	struct evbuffer		*src = EVBUFFER_INPUT(bev);
1278 	struct protonode	*pn, pk, *proot, *pnv = NULL, pkv;
1279 	char			*line;
1280 	int			 header = 0, ret, pass = 0;
1281 	const char		*errstr;
1282 	size_t			 size;
1283 
1284 	if (gettimeofday(&con->se_tv_last, NULL) == -1)
1285 		goto fail;
1286 	size = EVBUFFER_LENGTH(src);
1287 	DPRINTF("relay_read_http: size %d, to read %d", size, cre->toread);
1288 	if (!size) {
1289 		if (cre->dir == RELAY_DIR_RESPONSE)
1290 			return;
1291 		cre->toread = 0;
1292 		goto done;
1293 	}
1294 
1295 	pk.type = NODE_TYPE_HEADER;
1296 
1297 	while (!cre->done && (line = evbuffer_readline(src)) != NULL) {
1298 		/*
1299 		 * An empty line indicates the end of the request.
1300 		 * libevent already stripped the \r\n for us.
1301 		 */
1302 		if (!strlen(line)) {
1303 			cre->done = 1;
1304 			free(line);
1305 			break;
1306 		}
1307 		pk.key = line;
1308 
1309 		/*
1310 		 * The first line is the GET/POST/PUT/... request,
1311 		 * subsequent lines are HTTP headers.
1312 		 */
1313 		if (++cre->line == 1) {
1314 			pk.value = strchr(pk.key, ' ');
1315 		} else
1316 			pk.value = strchr(pk.key, ':');
1317 		if (pk.value == NULL || strlen(pk.value) < 3) {
1318 			if (cre->line == 1) {
1319 				free(line);
1320 				relay_close_http(con, 400, "malformed", 0);
1321 				return;
1322 			}
1323 
1324 			DPRINTF("relay_read_http: request '%s'", line);
1325 			/* Append line to the output buffer */
1326 			if (relay_bufferevent_print(cre->dst, line) == -1 ||
1327 			    relay_bufferevent_print(cre->dst, "\r\n") == -1) {
1328 				free(line);
1329 				goto fail;
1330 			}
1331 			free(line);
1332 			continue;
1333 		}
1334 		if (*pk.value == ':') {
1335 			*pk.value++ = '\0';
1336 			pk.value++;
1337 			header = 1;
1338 		} else {
1339 			*pk.value++ = '\0';
1340 			header = 0;
1341 		}
1342 
1343 		DPRINTF("relay_read_http: header '%s: %s'", pk.key, pk.value);
1344 
1345 		/*
1346 		 * Identify and handle specific HTTP request methods
1347 		 */
1348 		if (cre->line == 1) {
1349 			if (cre->dir == RELAY_DIR_RESPONSE) {
1350 				cre->method = HTTP_METHOD_RESPONSE;
1351 				goto lookup;
1352 			} else if (strcmp("HEAD", pk.key) == 0)
1353 				cre->method = HTTP_METHOD_HEAD;
1354 			else if (strcmp("POST", pk.key) == 0)
1355 				cre->method = HTTP_METHOD_POST;
1356 			else if (strcmp("PUT", pk.key) == 0)
1357 				cre->method = HTTP_METHOD_PUT;
1358 			else if (strcmp("DELETE", pk.key) == 0)
1359 				cre->method = HTTP_METHOD_DELETE;
1360 			else if (strcmp("OPTIONS", pk.key) == 0)
1361 				cre->method = HTTP_METHOD_OPTIONS;
1362 			else if (strcmp("TRACE", pk.key) == 0)
1363 				cre->method = HTTP_METHOD_TRACE;
1364 			else if (strcmp("CONNECT", pk.key) == 0)
1365 				cre->method = HTTP_METHOD_CONNECT;
1366 			else {
1367 				/* Use GET method as the default */
1368 				cre->method = HTTP_METHOD_GET;
1369 			}
1370 
1371 			/*
1372 			 * Decode the path and query
1373 			 */
1374 			cre->path = strdup(pk.value);
1375 			if (cre->path == NULL) {
1376 				free(line);
1377 				goto fail;
1378 			}
1379 			cre->version = strchr(cre->path, ' ');
1380 			if (cre->version != NULL)
1381 				*cre->version++ = '\0';
1382 			cre->args = strchr(cre->path, '?');
1383 			if (cre->args != NULL)
1384 				*cre->args++ = '\0';
1385 #ifdef DEBUG
1386 			char	 buf[BUFSIZ];
1387 			if (snprintf(buf, sizeof(buf), " \"%s\"",
1388 			    cre->path) == -1 ||
1389 			    evbuffer_add(con->se_log, buf, strlen(buf)) == -1) {
1390 				free(line);
1391 				goto fail;
1392 			}
1393 #endif
1394 
1395 			/*
1396 			 * Lookup protocol handlers in the URL path
1397 			 */
1398 			if ((proto->flags & F_LOOKUP_PATH) == 0)
1399 				goto lookup;
1400 
1401 			pkv.key = cre->path;
1402 			pkv.type = NODE_TYPE_PATH;
1403 			pkv.value = cre->args == NULL ? "" : cre->args;
1404 
1405 			DPRINTF("relay_read_http: "
1406 			    "lookup path '%s: %s'", pkv.key, pkv.value);
1407 
1408 			if ((proot = RB_FIND(proto_tree,
1409 			    cre->tree, &pkv)) == NULL)
1410 				goto lookup;
1411 
1412 			PROTONODE_FOREACH(pnv, proot, entry) {
1413 				ret = relay_handle_http(cre, proot,
1414 				    pnv, &pkv, 0);
1415 				if (ret == PN_FAIL)
1416 					goto abort;
1417 			}
1418 		} else if ((cre->method == HTTP_METHOD_POST ||
1419 		    cre->method == HTTP_METHOD_PUT ||
1420 		    cre->method == HTTP_METHOD_RESPONSE) &&
1421 		    strcasecmp("Content-Length", pk.key) == 0) {
1422 			/*
1423 			 * Need to read data from the client after the
1424 			 * HTTP header.
1425 			 * XXX What about non-standard clients not using
1426 			 * the carriage return? And some browsers seem to
1427 			 * include the line length in the content-length.
1428 			 */
1429 			cre->toread = strtonum(pk.value, 0, INT_MAX, &errstr);
1430 			if (errstr) {
1431 				relay_close_http(con, 500, errstr, 0);
1432 				goto abort;
1433 			}
1434 		}
1435  lookup:
1436 		if (strcasecmp("Transfer-Encoding", pk.key) == 0 &&
1437 		    strcasecmp("chunked", pk.value) == 0)
1438 			cre->chunked = 1;
1439 
1440 		/* Match the HTTP header */
1441 		if ((pn = RB_FIND(proto_tree, cre->tree, &pk)) == NULL)
1442 			goto next;
1443 
1444 		if (cre->dir == RELAY_DIR_RESPONSE)
1445 			goto handle;
1446 
1447 		if (pn->flags & PNFLAG_LOOKUP_URL) {
1448 			/*
1449 			 * Lookup the URL of type example.com/path?args.
1450 			 * Either as a plain string or SHA1/MD5 digest.
1451 			 */
1452 			if ((pn->flags & PNFLAG_LOOKUP_DIGEST(0)) &&
1453 			    relay_lookup_url(cre, pk.value,
1454 			    DIGEST_NONE) == PN_FAIL)
1455 				goto abort;
1456 			if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_SHA1)) &&
1457 			    relay_lookup_url(cre, pk.value,
1458 			    DIGEST_SHA1) == PN_FAIL)
1459 				goto abort;
1460 			if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_MD5)) &&
1461 			    relay_lookup_url(cre, pk.value,
1462 			    DIGEST_MD5) == PN_FAIL)
1463 				goto abort;
1464 		} else if (pn->flags & PNFLAG_LOOKUP_QUERY) {
1465 			/* Lookup the HTTP query arguments */
1466 			if (relay_lookup_query(cre) == PN_FAIL)
1467 				goto abort;
1468 		} else if (pn->flags & PNFLAG_LOOKUP_COOKIE) {
1469 			/* Lookup the HTTP cookie */
1470 			if (relay_lookup_cookie(cre, pk.value) == PN_FAIL)
1471 				goto abort;
1472 		}
1473 
1474  handle:
1475 		pass = 0;
1476 		PROTONODE_FOREACH(pnv, pn, entry) {
1477 			ret = relay_handle_http(cre, pn, pnv, &pk, header);
1478 			if (ret == PN_PASS)
1479 				pass = 1;
1480 			else if (ret == PN_FAIL)
1481 				goto abort;
1482 		}
1483 
1484 		if (pass) {
1485  next:
1486 			if (relay_bufferevent_print(cre->dst, pk.key) == -1 ||
1487 			    relay_bufferevent_print(cre->dst,
1488 			    header ? ": " : " ") == -1 ||
1489 			    relay_bufferevent_print(cre->dst, pk.value) == -1 ||
1490 			    relay_bufferevent_print(cre->dst, "\r\n") == -1) {
1491 				free(line);
1492 				goto fail;
1493 			}
1494 		}
1495 		free(line);
1496 	}
1497 	if (cre->done) {
1498 		RB_FOREACH(proot, proto_tree, cre->tree) {
1499 			PROTONODE_FOREACH(pn, proot, entry)
1500 				if (relay_resolve(cre, proot, pn) != 0)
1501 					return;
1502 		}
1503 
1504 		switch (cre->method) {
1505 		case HTTP_METHOD_NONE:
1506 			relay_close_http(con, 406, "no method", 0);
1507 			return;
1508 		case HTTP_METHOD_CONNECT:
1509 			/* Data stream */
1510 			bev->readcb = relay_read;
1511 			break;
1512 		case HTTP_METHOD_POST:
1513 		case HTTP_METHOD_PUT:
1514 		case HTTP_METHOD_RESPONSE:
1515 			/* HTTP request payload */
1516 			if (cre->toread) {
1517 				bev->readcb = relay_read_httpcontent;
1518 				break;
1519 			}
1520 
1521 			/* Single-pass HTTP response */
1522 			bev->readcb = relay_read;
1523 			break;
1524 		default:
1525 			/* HTTP handler */
1526 			bev->readcb = relay_read_http;
1527 			break;
1528 		}
1529 		if (cre->chunked) {
1530 			/* Chunked transfer encoding */
1531 			cre->toread = 0;
1532 			bev->readcb = relay_read_httpchunks;
1533 		}
1534 
1535 		/* Write empty newline and switch to relay mode */
1536 		if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
1537 			goto fail;
1538 
1539 		cre->line = 0;
1540 		cre->method = 0;
1541 		cre->done = 0;
1542 		cre->chunked = 0;
1543 
1544  done:
1545 		if (cre->dir == RELAY_DIR_REQUEST && !cre->toread &&
1546 		    proto->lateconnect && cre->dst->bev == NULL) {
1547 			if (rlay->rl_conf.fwdmode == FWD_TRANS) {
1548 				relay_bindanyreq(con, 0, IPPROTO_TCP);
1549 				return;
1550 			}
1551 			if (relay_connect(con) == -1)
1552 				relay_close_http(con, 502, "session failed", 0);
1553 			return;
1554 		}
1555 	}
1556 	if (con->se_done) {
1557 		relay_close(con, "last http read (done)");
1558 		return;
1559 	}
1560 	if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_http)
1561 		bev->readcb(bev, arg);
1562 	bufferevent_enable(bev, EV_READ);
1563 	return;
1564  fail:
1565 	relay_close_http(con, 500, strerror(errno), 0);
1566 	return;
1567  abort:
1568 	free(line);
1569 }
1570 
1571 static int
1572 _relay_lookup_url(struct ctl_relay_event *cre, char *host, char *path,
1573     char *query, enum digest_type type)
1574 {
1575 	struct session		*con = (struct session *)cre->con;
1576 	struct protonode	*proot, *pnv, pkv;
1577 	char			*val, *md = NULL;
1578 	int			 ret = PN_FAIL;
1579 
1580 	if (asprintf(&val, "%s%s%s%s",
1581 	    host, path,
1582 	    query == NULL ? "" : "?",
1583 	    query == NULL ? "" : query) == -1) {
1584 		relay_close_http(con, 500, "failed to allocate URL", 0);
1585 		return (PN_FAIL);
1586 	}
1587 
1588 	DPRINTF("_relay_lookup_url: %s", val);
1589 
1590 	switch (type) {
1591 	case DIGEST_SHA1:
1592 	case DIGEST_MD5:
1593 		if ((md = digeststr(type, val, strlen(val), NULL)) == NULL) {
1594 			relay_close_http(con, 500,
1595 			    "failed to allocate digest", 0);
1596 			goto fail;
1597 		}
1598 		pkv.key = md;
1599 		break;
1600 	case DIGEST_NONE:
1601 		pkv.key = val;
1602 		break;
1603 	}
1604 	pkv.type = NODE_TYPE_URL;
1605 	pkv.value = "";
1606 
1607 	if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL)
1608 		goto done;
1609 
1610 	PROTONODE_FOREACH(pnv, proot, entry) {
1611 		ret = relay_handle_http(cre, proot, pnv, &pkv, 0);
1612 		if (ret == PN_FAIL)
1613 			goto fail;
1614 	}
1615 
1616  done:
1617 	ret = PN_PASS;
1618  fail:
1619 	if (md != NULL)
1620 		free(md);
1621 	free(val);
1622 	return (ret);
1623 }
1624 
1625 int
1626 relay_lookup_url(struct ctl_relay_event *cre, const char *str,
1627     enum digest_type type)
1628 {
1629 	struct session	*con = (struct session *)cre->con;
1630 	int		 i, j, dots;
1631 	char		*hi[RELAY_MAXLOOKUPLEVELS], *p, *pp, *c, ch;
1632 	char		 ph[MAXHOSTNAMELEN];
1633 	int		 ret;
1634 
1635 	if (cre->path == NULL)
1636 		return (PN_PASS);
1637 
1638 	/*
1639 	 * This is an URL lookup algorithm inspired by
1640 	 * http://code.google.com/apis/safebrowsing/
1641 	 *     developers_guide.html#PerformingLookups
1642 	 */
1643 
1644 	DPRINTF("relay_lookup_url: host: '%s', path: '%s', query: '%s'",
1645 	    str, cre->path, cre->args == NULL ? "" : cre->args);
1646 
1647 	if (canonicalize_host(str, ph, sizeof(ph)) == NULL) {
1648 		relay_close_http(con, 400, "invalid host name", 0);
1649 		return (PN_FAIL);
1650 	}
1651 
1652 	bzero(hi, sizeof(hi));
1653 	for (dots = -1, i = strlen(ph) - 1; i > 0; i--) {
1654 		if (ph[i] == '.' && ++dots)
1655 			hi[dots - 1] = &ph[i + 1];
1656 		if (dots > (RELAY_MAXLOOKUPLEVELS - 2))
1657 			break;
1658 	}
1659 	if (dots == -1)
1660 		dots = 0;
1661 	hi[dots] = ph;
1662 
1663 	if ((pp = strdup(cre->path)) == NULL) {
1664 		relay_close_http(con, 500, "failed to allocate path", 0);
1665 		return (PN_FAIL);
1666 	}
1667 	for (i = (RELAY_MAXLOOKUPLEVELS - 1); i >= 0; i--) {
1668 		if (hi[i] == NULL)
1669 			continue;
1670 
1671 		/* 1. complete path with query */
1672 		if (cre->args != NULL)
1673 			if ((ret = _relay_lookup_url(cre, hi[i],
1674 			    pp, cre->args, type)) != PN_PASS)
1675 				goto done;
1676 
1677 		/* 2. complete path without query */
1678 		if ((ret = _relay_lookup_url(cre, hi[i],
1679 		    pp, NULL, type)) != PN_PASS)
1680 			goto done;
1681 
1682 		/* 3. traverse path */
1683 		for (j = 0, p = strchr(pp, '/');
1684 		    p != NULL; p = strchr(p, '/'), j++) {
1685 			if (j > (RELAY_MAXLOOKUPLEVELS - 2) || ++p == '\0')
1686 				break;
1687 			c = &pp[p - pp];
1688 			ch = *c;
1689 			*c = '\0';
1690 			if ((ret = _relay_lookup_url(cre, hi[i],
1691 			    pp, NULL, type)) != PN_PASS)
1692 				goto done;
1693 			*c = ch;
1694 		}
1695 	}
1696 
1697 	ret = PN_PASS;
1698  done:
1699 	free(pp);
1700 	return (ret);
1701 }
1702 
1703 int
1704 relay_lookup_query(struct ctl_relay_event *cre)
1705 {
1706 	struct session		*con = (struct session *)cre->con;
1707 	struct protonode	*proot, *pnv, pkv;
1708 	char			*val, *ptr;
1709 	int			 ret;
1710 
1711 	if (cre->path == NULL || cre->args == NULL || strlen(cre->args) < 2)
1712 		return (PN_PASS);
1713 	if ((val = strdup(cre->args)) == NULL) {
1714 		relay_close_http(con, 500, "failed to allocate query", 0);
1715 		return (PN_FAIL);
1716 	}
1717 
1718 	ptr = val;
1719 	while (ptr != NULL && strlen(ptr)) {
1720 		pkv.key = ptr;
1721 		pkv.type = NODE_TYPE_QUERY;
1722 		if ((ptr = strchr(ptr, '&')) != NULL)
1723 			*ptr++ = '\0';
1724 		if ((pkv.value =
1725 		    strchr(pkv.key, '=')) == NULL ||
1726 		    strlen(pkv.value) < 1)
1727 			continue;
1728 		*pkv.value++ = '\0';
1729 
1730 		if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL)
1731 			continue;
1732 		PROTONODE_FOREACH(pnv, proot, entry) {
1733 			ret = relay_handle_http(cre, proot,
1734 			    pnv, &pkv, 0);
1735 			if (ret == PN_FAIL)
1736 				goto done;
1737 		}
1738 	}
1739 
1740 	ret = PN_PASS;
1741  done:
1742 	free(val);
1743 	return (ret);
1744 }
1745 
1746 int
1747 relay_lookup_cookie(struct ctl_relay_event *cre, const char *str)
1748 {
1749 	struct session		*con = (struct session *)cre->con;
1750 	struct protonode	*proot, *pnv, pkv;
1751 	char			*val, *ptr;
1752 	int			 ret;
1753 
1754 	if ((val = strdup(str)) == NULL) {
1755 		relay_close_http(con, 500, "failed to allocate cookie", 0);
1756 		return (PN_FAIL);
1757 	}
1758 
1759 	for (ptr = val; ptr != NULL && strlen(ptr);) {
1760 		if (*ptr == ' ')
1761 			*ptr++ = '\0';
1762 		pkv.key = ptr;
1763 		pkv.type = NODE_TYPE_COOKIE;
1764 		if ((ptr = strchr(ptr, ';')) != NULL)
1765 			*ptr++ = '\0';
1766 		/*
1767 		 * XXX We do not handle attributes
1768 		 * ($Path, $Domain, or $Port)
1769 		 */
1770 		if (*pkv.key == '$')
1771 			continue;
1772 
1773 		if ((pkv.value =
1774 		    strchr(pkv.key, '=')) == NULL ||
1775 		    strlen(pkv.value) < 1)
1776 			continue;
1777 		*pkv.value++ = '\0';
1778 		if (*pkv.value == '"')
1779 			*pkv.value++ = '\0';
1780 		if (pkv.value[strlen(pkv.value) - 1] == '"')
1781 			pkv.value[strlen(pkv.value) - 1] = '\0';
1782 		if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL)
1783 			continue;
1784 		PROTONODE_FOREACH(pnv, proot, entry) {
1785 			ret = relay_handle_http(cre, proot, pnv, &pkv, 0);
1786 			if (ret == PN_FAIL)
1787 				goto done;
1788 		}
1789 	}
1790 
1791 	ret = PN_PASS;
1792  done:
1793 	free(val);
1794 	return (ret);
1795 }
1796 
1797 void
1798 relay_close_http(struct session *con, u_int code, const char *msg,
1799     u_int16_t labelid)
1800 {
1801 	struct relay		*rlay = (struct relay *)con->se_relay;
1802 	struct bufferevent	*bev = con->se_in.bev;
1803 	const char		*httperr = print_httperror(code), *text = "";
1804 	char			*httpmsg;
1805 	time_t			 t;
1806 	struct tm		*lt;
1807 	char			 tmbuf[32], hbuf[128];
1808 	const char		*style, *label = NULL;
1809 
1810 	/* In some cases this function may be called from generic places */
1811 	if (rlay->rl_proto->type != RELAY_PROTO_HTTP ||
1812 	    (rlay->rl_proto->flags & F_RETURN) == 0) {
1813 		relay_close(con, msg);
1814 		return;
1815 	}
1816 
1817 	if (bev == NULL)
1818 		goto done;
1819 
1820 	/* Some system information */
1821 	if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL)
1822 		goto done;
1823 
1824 	/* RFC 2616 "tolerates" asctime() */
1825 	time(&t);
1826 	lt = localtime(&t);
1827 	tmbuf[0] = '\0';
1828 	if (asctime_r(lt, tmbuf) != NULL)
1829 		tmbuf[strlen(tmbuf) - 1] = '\0';	/* skip final '\n' */
1830 
1831 	/* Do not send details of the Internal Server Error */
1832 	if (code != 500)
1833 		text = msg;
1834 	if (labelid != 0)
1835 		label = pn_id2name(labelid);
1836 
1837 	/* A CSS stylesheet allows minimal customization by the user */
1838 	if ((style = rlay->rl_proto->style) == NULL)
1839 		style = "body { background-color: #a00000; color: white; }";
1840 
1841 	/* Generate simple HTTP+HTML error document */
1842 	if (asprintf(&httpmsg,
1843 	    "HTTP/1.x %03d %s\r\n"
1844 	    "Date: %s\r\n"
1845 	    "Server: %s\r\n"
1846 	    "Connection: close\r\n"
1847 	    "Content-Type: text/html\r\n"
1848 	    "\r\n"
1849 	    "<!DOCTYPE HTML PUBLIC "
1850 	    "\"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
1851 	    "<html>\n"
1852 	    "<head>\n"
1853 	    "<title>%03d %s</title>\n"
1854 	    "<style type=\"text/css\"><!--\n%s\n--></style>\n"
1855 	    "</head>\n"
1856 	    "<body>\n"
1857 	    "<h1>%s</h1>\n"
1858 	    "<div id='m'>%s</div>\n"
1859 	    "<div id='l'>%s</div>\n"
1860 	    "<hr><address>%s at %s port %d</address>\n"
1861 	    "</body>\n"
1862 	    "</html>\n",
1863 	    code, httperr, tmbuf, RELAYD_SERVERNAME,
1864 	    code, httperr, style, httperr, text,
1865 	    label == NULL ? "" : label,
1866 	    RELAYD_SERVERNAME, hbuf, ntohs(rlay->rl_conf.port)) == -1)
1867 		goto done;
1868 
1869 	/* Dump the message without checking for success */
1870 	relay_dump(&con->se_in, httpmsg, strlen(httpmsg));
1871 	free(httpmsg);
1872 
1873  done:
1874 	if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1)
1875 		relay_close(con, msg);
1876 	else {
1877 		relay_close(con, httpmsg);
1878 		free(httpmsg);
1879 	}
1880 }
1881 
1882 void
1883 relay_error(struct bufferevent *bev, short error, void *arg)
1884 {
1885 	struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
1886 	struct session *con = (struct session *)cre->con;
1887 	struct evbuffer *dst;
1888 
1889 	if (error & EVBUFFER_TIMEOUT) {
1890 		relay_close(con, "buffer event timeout");
1891 		return;
1892 	}
1893 	if (error & (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) {
1894 		bufferevent_disable(bev, EV_READ|EV_WRITE);
1895 
1896 		con->se_done = 1;
1897 		if (cre->dst->bev != NULL) {
1898 			dst = EVBUFFER_OUTPUT(cre->dst->bev);
1899 			if (EVBUFFER_LENGTH(dst))
1900 				return;
1901 		}
1902 
1903 		relay_close(con, "done");
1904 		return;
1905 	}
1906 	relay_close(con, "buffer event error");
1907 }
1908 
1909 void
1910 relay_accept(int fd, short sig, void *arg)
1911 {
1912 	struct relay *rlay = (struct relay *)arg;
1913 	struct protocol *proto = rlay->rl_proto;
1914 	struct session *con = NULL;
1915 	struct ctl_natlook *cnl = NULL;
1916 	socklen_t slen;
1917 	struct timeval tv;
1918 	struct sockaddr_storage ss;
1919 	int s = -1;
1920 
1921 	slen = sizeof(ss);
1922 	if ((s = accept(fd, (struct sockaddr *)&ss, (socklen_t *)&slen)) == -1)
1923 		return;
1924 
1925 	if (relay_sessions >= RELAY_MAX_SESSIONS ||
1926 	    rlay->rl_conf.flags & F_DISABLE)
1927 		goto err;
1928 
1929 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
1930 		goto err;
1931 
1932 	if ((con = (struct session *)
1933 	    calloc(1, sizeof(struct session))) == NULL)
1934 		goto err;
1935 
1936 	con->se_in.s = s;
1937 	con->se_in.ssl = NULL;
1938 	con->se_out.s = -1;
1939 	con->se_out.ssl = NULL;
1940 	con->se_in.dst = &con->se_out;
1941 	con->se_out.dst = &con->se_in;
1942 	con->se_in.con = con;
1943 	con->se_out.con = con;
1944 	con->se_relay = rlay;
1945 	con->se_id = ++relay_conid;
1946 	con->se_relayid = rlay->rl_conf.id;
1947 	con->se_hashkey = rlay->rl_dstkey;
1948 	con->se_in.tree = &proto->request_tree;
1949 	con->se_out.tree = &proto->response_tree;
1950 	con->se_in.dir = RELAY_DIR_REQUEST;
1951 	con->se_out.dir = RELAY_DIR_RESPONSE;
1952 	con->se_retry = rlay->rl_conf.dstretry;
1953 	con->se_bnds = -1;
1954 	if (gettimeofday(&con->se_tv_start, NULL) == -1)
1955 		goto err;
1956 	bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last));
1957 	bcopy(&ss, &con->se_in.ss, sizeof(con->se_in.ss));
1958 	con->se_out.port = rlay->rl_conf.dstport;
1959 	switch (ss.ss_family) {
1960 	case AF_INET:
1961 		con->se_in.port = ((struct sockaddr_in *)&ss)->sin_port;
1962 		break;
1963 	case AF_INET6:
1964 		con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
1965 		break;
1966 	}
1967 
1968 	relay_sessions++;
1969 	SPLAY_INSERT(session_tree, &rlay->rl_sessions, con);
1970 
1971 	/* Increment the per-relay session counter */
1972 	rlay->rl_stats[proc_id].last++;
1973 
1974 	/* Pre-allocate output buffer */
1975 	con->se_out.output = evbuffer_new();
1976 	if (con->se_out.output == NULL) {
1977 		relay_close(con, "failed to allocate output buffer");
1978 		return;
1979 	}
1980 
1981 	/* Pre-allocate log buffer */
1982 	con->se_log = evbuffer_new();
1983 	if (con->se_log == NULL) {
1984 		relay_close(con, "failed to allocate log buffer");
1985 		return;
1986 	}
1987 
1988 	if (rlay->rl_conf.flags & F_NATLOOK) {
1989 		if ((cnl = (struct ctl_natlook *)
1990 		    calloc(1, sizeof(struct ctl_natlook))) == NULL) {
1991 			relay_close(con, "failed to allocate nat lookup");
1992 			return;
1993 		}
1994 	}
1995 
1996 	if (rlay->rl_conf.flags & F_NATLOOK && cnl != NULL) {
1997 		con->se_cnl = cnl;
1998 		bzero(cnl, sizeof(*cnl));
1999 		cnl->in = -1;
2000 		cnl->id = con->se_id;
2001 		cnl->proc = proc_id;
2002 		cnl->proto = IPPROTO_TCP;
2003 
2004 		bcopy(&con->se_in.ss, &cnl->src, sizeof(cnl->src));
2005 		slen = sizeof(cnl->dst);
2006 		if (getsockname(s,
2007 		    (struct sockaddr *)&cnl->dst, &slen) == -1) {
2008 			relay_close(con, "failed to get local address");
2009 			return;
2010 		}
2011 
2012 		imsg_compose(ibuf_pfe, IMSG_NATLOOK, 0, 0, -1, cnl,
2013 		    sizeof(*cnl));
2014 
2015 		/* Schedule timeout */
2016 		evtimer_set(&con->se_ev, relay_natlook, con);
2017 		bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv));
2018 		evtimer_add(&con->se_ev, &tv);
2019 		return;
2020 	}
2021 
2022 	relay_session(con);
2023 	return;
2024  err:
2025 	if (s != -1) {
2026 		close(s);
2027 		if (con != NULL)
2028 			free(con);
2029 	}
2030 }
2031 
2032 u_int32_t
2033 relay_hash_addr(struct sockaddr_storage *ss, u_int32_t p)
2034 {
2035 	struct sockaddr_in	*sin4;
2036 	struct sockaddr_in6	*sin6;
2037 
2038 	if (ss->ss_family == AF_INET) {
2039 		sin4 = (struct sockaddr_in *)ss;
2040 		p = hash32_buf(&sin4->sin_addr,
2041 		    sizeof(struct in_addr), p);
2042 	} else {
2043 		sin6 = (struct sockaddr_in6 *)ss;
2044 		p = hash32_buf(&sin6->sin6_addr,
2045 		    sizeof(struct in6_addr), p);
2046 	}
2047 
2048 	return (p);
2049 }
2050 
2051 int
2052 relay_from_table(struct session *con)
2053 {
2054 	struct relay		*rlay = (struct relay *)con->se_relay;
2055 	struct host		*host;
2056 	struct table		*table = rlay->rl_dsttable;
2057 	u_int32_t		 p = con->se_hashkey;
2058 	int			 idx = 0;
2059 
2060 	if (table->conf.check && !table->up) {
2061 		log_debug("relay_from_table: no active hosts");
2062 		return (-1);
2063 	}
2064 
2065 	switch (rlay->rl_conf.dstmode) {
2066 	case RELAY_DSTMODE_ROUNDROBIN:
2067 		if ((int)rlay->rl_dstkey >= rlay->rl_dstnhosts)
2068 			rlay->rl_dstkey = 0;
2069 		idx = (int)rlay->rl_dstkey;
2070 		break;
2071 	case RELAY_DSTMODE_LOADBALANCE:
2072 		p = relay_hash_addr(&con->se_in.ss, p);
2073 		/* FALLTHROUGH */
2074 	case RELAY_DSTMODE_HASH:
2075 		p = relay_hash_addr(&rlay->rl_conf.ss, p);
2076 		p = hash32_buf(&rlay->rl_conf.port, sizeof(rlay->rl_conf.port), p);
2077 		if ((idx = p % rlay->rl_dstnhosts) >= RELAY_MAXHOSTS)
2078 			return (-1);
2079 	}
2080 	host = rlay->rl_dsthost[idx];
2081 	DPRINTF("relay_from_table: host %s, p 0x%08x, idx %d",
2082 	    host->conf.name, p, idx);
2083 	while (host != NULL) {
2084 		DPRINTF("relay_from_table: host %s", host->conf.name);
2085 		if (!table->conf.check || host->up == HOST_UP)
2086 			goto found;
2087 		host = TAILQ_NEXT(host, entry);
2088 	}
2089 	TAILQ_FOREACH(host, &table->hosts, entry) {
2090 		DPRINTF("relay_from_table: next host %s", host->conf.name);
2091 		if (!table->conf.check || host->up == HOST_UP)
2092 			goto found;
2093 	}
2094 
2095 	/* Should not happen */
2096 	fatalx("relay_from_table: no active hosts, desynchronized");
2097 
2098  found:
2099 	if (rlay->rl_conf.dstmode == RELAY_DSTMODE_ROUNDROBIN)
2100 		rlay->rl_dstkey = host->idx + 1;
2101 	con->se_retry = host->conf.retry;
2102 	con->se_out.port = table->conf.port;
2103 	bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss));
2104 
2105 	return (0);
2106 }
2107 
2108 void
2109 relay_natlook(int fd, short event, void *arg)
2110 {
2111 	struct session		*con = (struct session *)arg;
2112 	struct relay		*rlay = (struct relay *)con->se_relay;
2113 	struct ctl_natlook	*cnl = con->se_cnl;
2114 
2115 	if (cnl == NULL)
2116 		fatalx("invalid NAT lookup");
2117 
2118 	if (con->se_out.ss.ss_family == AF_UNSPEC && cnl->in == -1 &&
2119 	    rlay->rl_conf.dstss.ss_family == AF_UNSPEC && rlay->rl_dsttable == NULL) {
2120 		relay_close(con, "session NAT lookup failed");
2121 		return;
2122 	}
2123 	if (cnl->in != -1) {
2124 		bcopy(&cnl->rdst, &con->se_out.ss, sizeof(con->se_out.ss));
2125 		con->se_out.port = cnl->rdport;
2126 	}
2127 	free(con->se_cnl);
2128 	con->se_cnl = NULL;
2129 
2130 	relay_session(con);
2131 }
2132 
2133 void
2134 relay_session(struct session *con)
2135 {
2136 	struct relay		*rlay = (struct relay *)con->se_relay;
2137 	struct ctl_relay_event	*in = &con->se_in, *out = &con->se_out;
2138 
2139 	if (bcmp(&rlay->rl_conf.ss, &out->ss, sizeof(out->ss)) == 0 &&
2140 	    out->port == rlay->rl_conf.port) {
2141 		log_debug("relay_session: session %d: looping",
2142 		    con->se_id);
2143 		relay_close(con, "session aborted");
2144 		return;
2145 	}
2146 
2147 	if (rlay->rl_conf.flags & F_UDP) {
2148 		/*
2149 		 * Call the UDP protocol-specific handler
2150 		 */
2151 		if (rlay->rl_proto->request == NULL)
2152 			fatalx("invalide UDP session");
2153 		if ((*rlay->rl_proto->request)(con) == -1)
2154 			relay_close(con, "session failed");
2155 		return;
2156 	}
2157 
2158 	if ((rlay->rl_conf.flags & F_SSL) && (in->ssl == NULL)) {
2159 		relay_ssl_transaction(con);
2160 		return;
2161 	}
2162 
2163 	if (!rlay->rl_proto->lateconnect) {
2164 		if (rlay->rl_conf.fwdmode == FWD_TRANS)
2165 			relay_bindanyreq(con, 0, IPPROTO_TCP);
2166 		else if (relay_connect(con) == -1) {
2167 			relay_close(con, "session failed");
2168 			return;
2169 		}
2170 	}
2171 
2172 	relay_input(con);
2173 }
2174 
2175 void
2176 relay_bindanyreq(struct session *con, in_port_t port, int proto)
2177 {
2178 	struct relay		*rlay = (struct relay *)con->se_relay;
2179 	struct ctl_bindany	 bnd;
2180 	struct timeval		 tv;
2181 
2182 	bzero(&bnd, sizeof(bnd));
2183 	bnd.bnd_id = con->se_id;
2184 	bnd.bnd_proc = proc_id;
2185 	bnd.bnd_port = port;
2186 	bnd.bnd_proto = proto;
2187 	bcopy(&con->se_in.ss, &bnd.bnd_ss, sizeof(bnd.bnd_ss));
2188 	imsg_compose(ibuf_main, IMSG_BINDANY, 0, 0, -1, &bnd, sizeof(bnd));
2189 
2190 	/* Schedule timeout */
2191 	evtimer_set(&con->se_ev, relay_bindany, con);
2192 	bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv));
2193 	evtimer_add(&con->se_ev, &tv);
2194 }
2195 
2196 void
2197 relay_bindany(int fd, short event, void *arg)
2198 {
2199 	struct session	*con = (struct session *)arg;
2200 
2201 	if (con->se_bnds == -1) {
2202 		relay_close(con, "bindany failed, invalid socket");
2203 		return;
2204 	}
2205 
2206 	if (relay_connect((struct session *)con) == -1)
2207 		relay_close(con, "session failed");
2208 }
2209 
2210 int
2211 relay_connect(struct session *con)
2212 {
2213 	struct relay	*rlay = (struct relay *)con->se_relay;
2214 	int		 bnds = -1, ret;
2215 
2216 	if (gettimeofday(&con->se_tv_start, NULL) == -1)
2217 		return (-1);
2218 
2219 	if (rlay->rl_dsttable != NULL) {
2220 		if (relay_from_table(con) != 0)
2221 			return (-1);
2222 	} else if (con->se_out.ss.ss_family == AF_UNSPEC) {
2223 		bcopy(&rlay->rl_conf.dstss, &con->se_out.ss,
2224 		    sizeof(con->se_out.ss));
2225 		con->se_out.port = rlay->rl_conf.dstport;
2226 	}
2227 
2228 	if (rlay->rl_conf.fwdmode == FWD_TRANS) {
2229 		if (con->se_bnds == -1) {
2230 			log_debug("relay_connect: could not bind any sock");
2231 			return (-1);
2232 		}
2233 		bnds = con->se_bnds;
2234 	}
2235 
2236 	/* Do the IPv4-to-IPv6 or IPv6-to-IPv4 translation if requested */
2237 	if (rlay->rl_conf.dstaf.ss_family != AF_UNSPEC) {
2238 		if (con->se_out.ss.ss_family == AF_INET &&
2239 		    rlay->rl_conf.dstaf.ss_family == AF_INET6)
2240 			ret = map4to6(&con->se_out.ss, &rlay->rl_conf.dstaf);
2241 		else if (con->se_out.ss.ss_family == AF_INET6 &&
2242 		    rlay->rl_conf.dstaf.ss_family == AF_INET)
2243 			ret = map6to4(&con->se_out.ss);
2244 		else
2245 			ret = 0;
2246 		if (ret != 0) {
2247 			log_debug("relay_connect: mapped to invalid address");
2248 			return (-1);
2249 		}
2250 	}
2251 
2252  retry:
2253 	if ((con->se_out.s = relay_socket_connect(&con->se_out.ss,
2254 	    con->se_out.port, rlay->rl_proto, bnds)) == -1) {
2255 		if (con->se_retry) {
2256 			con->se_retry--;
2257 			log_debug("relay_connect: session %d: "
2258 			    "forward failed: %s, %s",
2259 			    con->se_id, strerror(errno),
2260 			    con->se_retry ? "next retry" : "last retry");
2261 			goto retry;
2262 		}
2263 		log_debug("relay_connect: session %d: forward failed: %s",
2264 		    con->se_id, strerror(errno));
2265 		return (-1);
2266 	}
2267 
2268 	if (errno == EINPROGRESS)
2269 		event_again(&con->se_ev, con->se_out.s, EV_WRITE|EV_TIMEOUT,
2270 		    relay_connected, &con->se_tv_start, &env->sc_timeout, con);
2271 	else
2272 		relay_connected(con->se_out.s, EV_WRITE, con);
2273 
2274 	return (0);
2275 }
2276 
2277 void
2278 relay_close(struct session *con, const char *msg)
2279 {
2280 	struct relay	*rlay = (struct relay *)con->se_relay;
2281 	char		 ibuf[128], obuf[128], *ptr = NULL;
2282 
2283 	SPLAY_REMOVE(session_tree, &rlay->rl_sessions, con);
2284 
2285 	event_del(&con->se_ev);
2286 	if (con->se_in.bev != NULL)
2287 		bufferevent_disable(con->se_in.bev, EV_READ|EV_WRITE);
2288 	if (con->se_out.bev != NULL)
2289 		bufferevent_disable(con->se_out.bev, EV_READ|EV_WRITE);
2290 
2291 	if (env->sc_opts & RELAYD_OPT_LOGUPDATE) {
2292 		bzero(&ibuf, sizeof(ibuf));
2293 		bzero(&obuf, sizeof(obuf));
2294 		(void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf));
2295 		(void)print_host(&con->se_out.ss, obuf, sizeof(obuf));
2296 		if (EVBUFFER_LENGTH(con->se_log) &&
2297 		    evbuffer_add_printf(con->se_log, "\r\n") != -1)
2298 			ptr = evbuffer_readline(con->se_log);
2299 		log_info("relay %s, session %d (%d active), %d, %s -> %s:%d, "
2300 		    "%s%s%s", rlay->rl_conf.name, con->se_id, relay_sessions,
2301 		    con->se_mark, ibuf, obuf, ntohs(con->se_out.port), msg,
2302 		    ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr);
2303 		if (ptr != NULL)
2304 			free(ptr);
2305 	}
2306 
2307 	if (con->se_priv != NULL)
2308 		free(con->se_priv);
2309 	if (con->se_in.bev != NULL)
2310 		bufferevent_free(con->se_in.bev);
2311 	else if (con->se_in.output != NULL)
2312 		evbuffer_free(con->se_in.output);
2313 	if (con->se_in.ssl != NULL) {
2314 		/* XXX handle non-blocking shutdown */
2315 		if (SSL_shutdown(con->se_in.ssl) == 0)
2316 			SSL_shutdown(con->se_in.ssl);
2317 		SSL_free(con->se_in.ssl);
2318 	}
2319 	if (con->se_in.s != -1)
2320 		close(con->se_in.s);
2321 	if (con->se_in.path != NULL)
2322 		free(con->se_in.path);
2323 	if (con->se_in.buf != NULL)
2324 		free(con->se_in.buf);
2325 	if (con->se_in.nodes != NULL)
2326 		free(con->se_in.nodes);
2327 
2328 	if (con->se_out.bev != NULL)
2329 		bufferevent_free(con->se_out.bev);
2330 	else if (con->se_out.output != NULL)
2331 		evbuffer_free(con->se_out.output);
2332 	if (con->se_out.s != -1)
2333 		close(con->se_out.s);
2334 	if (con->se_out.path != NULL)
2335 		free(con->se_out.path);
2336 	if (con->se_out.buf != NULL)
2337 		free(con->se_out.buf);
2338 	if (con->se_out.nodes != NULL)
2339 		free(con->se_out.nodes);
2340 
2341 	if (con->se_log != NULL)
2342 		evbuffer_free(con->se_log);
2343 
2344 	if (con->se_cnl != NULL) {
2345 #if 0
2346 		imsg_compose(ibuf_pfe, IMSG_KILLSTATES, 0, 0, -1,
2347 		    cnl, sizeof(*cnl));
2348 #endif
2349 		free(con->se_cnl);
2350 	}
2351 
2352 	free(con);
2353 	relay_sessions--;
2354 }
2355 
2356 void
2357 relay_dispatch_pfe(int fd, short event, void *ptr)
2358 {
2359 	struct imsgbuf		*ibuf;
2360 	struct imsg		 imsg;
2361 	ssize_t			 n;
2362 	struct relay		*rlay;
2363 	struct session		*con;
2364 	struct ctl_natlook	 cnl;
2365 	struct timeval		 tv;
2366 	struct host		*host;
2367 	struct table		*table;
2368 	struct ctl_status	 st;
2369 	objid_t			 id;
2370 
2371 	ibuf = ptr;
2372 	switch (event) {
2373 	case EV_READ:
2374 		if ((n = imsg_read(ibuf)) == -1)
2375 			fatal("relay_dispatch_pfe: imsg_read_error");
2376 		if (n == 0) {
2377 			/* this pipe is dead, so remove the event handler */
2378 			event_del(&ibuf->ev);
2379 			event_loopexit(NULL);
2380 			return;
2381 		}
2382 		break;
2383 	case EV_WRITE:
2384 		if (msgbuf_write(&ibuf->w) == -1)
2385 			fatal("relay_dispatch_pfe: msgbuf_write");
2386 		imsg_event_add(ibuf);
2387 		return;
2388 	default:
2389 		fatalx("relay_dispatch_pfe: unknown event");
2390 	}
2391 
2392 	for (;;) {
2393 		if ((n = imsg_get(ibuf, &imsg)) == -1)
2394 			fatal("relay_dispatch_pfe: imsg_read error");
2395 		if (n == 0)
2396 			break;
2397 
2398 		switch (imsg.hdr.type) {
2399 		case IMSG_HOST_DISABLE:
2400 			memcpy(&id, imsg.data, sizeof(id));
2401 			if ((host = host_find(env, id)) == NULL)
2402 				fatalx("relay_dispatch_pfe: desynchronized");
2403 			if ((table = table_find(env, host->conf.tableid)) ==
2404 			    NULL)
2405 				fatalx("relay_dispatch_pfe: invalid table id");
2406 			if (host->up == HOST_UP)
2407 				table->up--;
2408 			host->flags |= F_DISABLE;
2409 			host->up = HOST_UNKNOWN;
2410 			break;
2411 		case IMSG_HOST_ENABLE:
2412 			memcpy(&id, imsg.data, sizeof(id));
2413 			if ((host = host_find(env, id)) == NULL)
2414 				fatalx("relay_dispatch_pfe: desynchronized");
2415 			host->flags &= ~(F_DISABLE);
2416 			host->up = HOST_UNKNOWN;
2417 			break;
2418 		case IMSG_HOST_STATUS:
2419 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(st))
2420 				fatalx("relay_dispatch_pfe: invalid request");
2421 			memcpy(&st, imsg.data, sizeof(st));
2422 			if ((host = host_find(env, st.id)) == NULL)
2423 				fatalx("relay_dispatch_pfe: invalid host id");
2424 			if (host->flags & F_DISABLE)
2425 				break;
2426 			if (host->up == st.up) {
2427 				log_debug("relay_dispatch_pfe: host %d => %d",
2428 				    host->conf.id, host->up);
2429 				fatalx("relay_dispatch_pfe: desynchronized");
2430 			}
2431 
2432 			if ((table = table_find(env, host->conf.tableid))
2433 			    == NULL)
2434 				fatalx("relay_dispatch_pfe: invalid table id");
2435 
2436 			DPRINTF("relay_dispatch_pfe: [%d] state %d for "
2437 			    "host %u %s", proc_id, st.up,
2438 			    host->conf.id, host->conf.name);
2439 
2440 			if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) ||
2441 			    (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) {
2442 				host->up = st.up;
2443 				break;
2444 			}
2445 			if (st.up == HOST_UP)
2446 				table->up++;
2447 			else
2448 				table->up--;
2449 			host->up = st.up;
2450 			break;
2451 		case IMSG_NATLOOK:
2452 			bcopy(imsg.data, &cnl, sizeof(cnl));
2453 			if ((con = session_find(env, cnl.id)) == NULL ||
2454 			    con->se_cnl == NULL) {
2455 				log_debug("relay_dispatch_pfe: "
2456 				    "session expired");
2457 				break;
2458 			}
2459 			bcopy(&cnl, con->se_cnl, sizeof(*con->se_cnl));
2460 			evtimer_del(&con->se_ev);
2461 			evtimer_set(&con->se_ev, relay_natlook, con);
2462 			bzero(&tv, sizeof(tv));
2463 			evtimer_add(&con->se_ev, &tv);
2464 			break;
2465 		case IMSG_CTL_SESSION:
2466 			TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
2467 				SPLAY_FOREACH(con, session_tree,
2468 				    &rlay->rl_sessions)
2469 					imsg_compose(ibuf, IMSG_CTL_SESSION,
2470 					    0, 0, -1, con, sizeof(*con));
2471 			imsg_compose(ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
2472 			break;
2473 		default:
2474 			log_debug("relay_dispatch_msg: unexpected imsg %d",
2475 			    imsg.hdr.type);
2476 			break;
2477 		}
2478 		imsg_free(&imsg);
2479 	}
2480 	imsg_event_add(ibuf);
2481 }
2482 
2483 void
2484 relay_dispatch_parent(int fd, short event, void * ptr)
2485 {
2486 	struct session		*con;
2487 	struct imsgbuf		*ibuf;
2488 	struct imsg		 imsg;
2489 	ssize_t			 n;
2490 	struct timeval		 tv;
2491 	objid_t			 id;
2492 
2493 	ibuf = ptr;
2494 	switch (event) {
2495 	case EV_READ:
2496 		if ((n = imsg_read(ibuf)) == -1)
2497 			fatal("relay_dispatch_parent: imsg_read error");
2498 		if (n == 0) {
2499 			/* this pipe is dead, so remove the event handler */
2500 			event_del(&ibuf->ev);
2501 			event_loopexit(NULL);
2502 			return;
2503 		}
2504 		break;
2505 	case EV_WRITE:
2506 		if (msgbuf_write(&ibuf->w) == -1)
2507 			fatal("relay_dispatch_parent: msgbuf_write");
2508 		imsg_event_add(ibuf);
2509 		return;
2510 	default:
2511 		fatalx("relay_dispatch_parent: unknown event");
2512 	}
2513 
2514 	for (;;) {
2515 		if ((n = imsg_get(ibuf, &imsg)) == -1)
2516 			fatal("relay_dispatch_parent: imsg_read error");
2517 		if (n == 0)
2518 			break;
2519 
2520 		switch (imsg.hdr.type) {
2521 		case IMSG_BINDANY:
2522 			bcopy(imsg.data, &id, sizeof(id));
2523 			if ((con = session_find(env, id)) == NULL) {
2524 				log_debug("relay_dispatch_parent: "
2525 				    "session expired");
2526 				break;
2527 			}
2528 
2529 			/* Will validate the result later */
2530 			con->se_bnds = imsg_get_fd(ibuf);
2531 
2532 			evtimer_del(&con->se_ev);
2533 			evtimer_set(&con->se_ev, relay_bindany, con);
2534 			bzero(&tv, sizeof(tv));
2535 			evtimer_add(&con->se_ev, &tv);
2536 			break;
2537 		default:
2538 			log_debug("relay_dispatch_parent: unexpected imsg %d",
2539 			    imsg.hdr.type);
2540 			break;
2541 		}
2542 		imsg_free(&imsg);
2543 	}
2544 	imsg_event_add(ibuf);
2545 }
2546 
2547 SSL_CTX *
2548 relay_ssl_ctx_create(struct relay *rlay)
2549 {
2550 	struct protocol *proto = rlay->rl_proto;
2551 	SSL_CTX *ctx;
2552 
2553 	ctx = SSL_CTX_new(SSLv23_method());
2554 	if (ctx == NULL)
2555 		goto err;
2556 
2557 	/* Modify session timeout and cache size*/
2558 	SSL_CTX_set_timeout(ctx, rlay->rl_conf.timeout.tv_sec);
2559 	if (proto->cache < -1) {
2560 		SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
2561 	} else if (proto->cache >= -1) {
2562 		SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
2563 		if (proto->cache >= 0)
2564 			SSL_CTX_sess_set_cache_size(ctx, proto->cache);
2565 	}
2566 
2567 	/* Enable all workarounds and set SSL options */
2568 	SSL_CTX_set_options(ctx, SSL_OP_ALL);
2569 	SSL_CTX_set_options(ctx,
2570 	    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
2571 
2572 	/* Set the allowed SSL protocols */
2573 	if ((proto->sslflags & SSLFLAG_SSLV2) == 0)
2574 		SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
2575 	if ((proto->sslflags & SSLFLAG_SSLV3) == 0)
2576 		SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
2577 	if ((proto->sslflags & SSLFLAG_TLSV1) == 0)
2578 		SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
2579 
2580 	if (!SSL_CTX_set_cipher_list(ctx, proto->sslciphers))
2581 		goto err;
2582 
2583 	log_debug("relay_ssl_ctx_create: loading certificate");
2584 	if (!ssl_ctx_use_certificate_chain(ctx,
2585 	    rlay->rl_ssl_cert, rlay->rl_ssl_cert_len))
2586 		goto err;
2587 
2588 	log_debug("relay_ssl_ctx_create: loading private key");
2589 	if (!ssl_ctx_use_private_key(ctx, rlay->rl_ssl_key, rlay->rl_ssl_key_len))
2590 		goto err;
2591 	if (!SSL_CTX_check_private_key(ctx))
2592 		goto err;
2593 
2594 	/* Set session context to the local relay name */
2595 	if (!SSL_CTX_set_session_id_context(ctx, rlay->rl_conf.name,
2596 	    strlen(rlay->rl_conf.name)))
2597 		goto err;
2598 
2599 	return (ctx);
2600 
2601  err:
2602 	if (ctx != NULL)
2603 		SSL_CTX_free(ctx);
2604 	ssl_error(rlay->rl_conf.name, "relay_ssl_ctx_create");
2605 	return (NULL);
2606 }
2607 
2608 void
2609 relay_ssl_transaction(struct session *con)
2610 {
2611 	struct relay	*rlay = (struct relay *)con->se_relay;
2612 	SSL		*ssl;
2613 
2614 	ssl = SSL_new(rlay->rl_ssl_ctx);
2615 	if (ssl == NULL)
2616 		goto err;
2617 
2618 	if (!SSL_set_ssl_method(ssl, SSLv23_server_method()))
2619 		goto err;
2620 	if (!SSL_set_fd(ssl, con->se_in.s))
2621 		goto err;
2622 	SSL_set_accept_state(ssl);
2623 
2624 	con->se_in.ssl = ssl;
2625 
2626 	event_again(&con->se_ev, con->se_in.s, EV_TIMEOUT|EV_READ,
2627 	    relay_ssl_accept, &con->se_tv_start, &env->sc_timeout, con);
2628 	return;
2629 
2630  err:
2631 	if (ssl != NULL)
2632 		SSL_free(ssl);
2633 	ssl_error(rlay->rl_conf.name, "relay_ssl_transaction");
2634 }
2635 
2636 void
2637 relay_ssl_accept(int fd, short event, void *arg)
2638 {
2639 	struct session	*con = (struct session *)arg;
2640 	struct relay	*rlay = (struct relay *)con->se_relay;
2641 	int		 ret;
2642 	int		 ssl_err;
2643 	int		 retry_flag;
2644 
2645 	if (event == EV_TIMEOUT) {
2646 		relay_close(con, "SSL accept timeout");
2647 		return;
2648 	}
2649 
2650 	retry_flag = ssl_err = 0;
2651 
2652 	ret = SSL_accept(con->se_in.ssl);
2653 	if (ret <= 0) {
2654 		ssl_err = SSL_get_error(con->se_in.ssl, ret);
2655 
2656 		switch (ssl_err) {
2657 		case SSL_ERROR_WANT_READ:
2658 			retry_flag = EV_READ;
2659 			goto retry;
2660 		case SSL_ERROR_WANT_WRITE:
2661 			retry_flag = EV_WRITE;
2662 			goto retry;
2663 		case SSL_ERROR_ZERO_RETURN:
2664 		case SSL_ERROR_SYSCALL:
2665 			if (ret == 0) {
2666 				relay_close(con, "closed");
2667 				return;
2668 			}
2669 			/* FALLTHROUGH */
2670 		default:
2671 			ssl_error(rlay->rl_conf.name, "relay_ssl_accept");
2672 			relay_close(con, "SSL accept error");
2673 			return;
2674 		}
2675 	}
2676 
2677 
2678 #ifdef DEBUG
2679 	log_info("relay %s, session %d established (%d active)",
2680 	    rlay->rl_conf.name, con->se_id, relay_sessions);
2681 #else
2682 	log_debug("relay %s, session %d established (%d active)",
2683 	    rlay->rl_conf.name, con->se_id, relay_sessions);
2684 #endif
2685 	relay_session(con);
2686 	return;
2687 
2688 retry:
2689 	DPRINTF("relay_ssl_accept: session %d: scheduling on %s", con->se_id,
2690 	    (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE");
2691 	event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_ssl_accept,
2692 	    &con->se_tv_start, &env->sc_timeout, con);
2693 }
2694 
2695 void
2696 relay_ssl_connected(struct ctl_relay_event *cre)
2697 {
2698 	/*
2699 	 * Hack libevent - we overwrite the internal bufferevent I/O
2700 	 * functions to handle the SSL abstraction.
2701 	 */
2702 	event_set(&cre->bev->ev_read, cre->s, EV_READ,
2703 	    relay_ssl_readcb, cre->bev);
2704 	event_set(&cre->bev->ev_write, cre->s, EV_WRITE,
2705 	    relay_ssl_writecb, cre->bev);
2706 }
2707 
2708 void
2709 relay_ssl_readcb(int fd, short event, void *arg)
2710 {
2711 	struct bufferevent *bufev = arg;
2712 	struct ctl_relay_event *cre = (struct ctl_relay_event *)bufev->cbarg;
2713 	struct session *con = (struct session *)cre->con;
2714 	struct relay *rlay = (struct relay *)con->se_relay;
2715 	int ret = 0, ssl_err = 0;
2716 	short what = EVBUFFER_READ;
2717 	size_t len;
2718 	char rbuf[READ_BUF_SIZE];
2719 	int howmuch = READ_BUF_SIZE;
2720 
2721 	if (event == EV_TIMEOUT) {
2722 		what |= EVBUFFER_TIMEOUT;
2723 		goto err;
2724 	}
2725 
2726 	if (bufev->wm_read.high != 0)
2727 		howmuch = MIN(sizeof(rbuf), bufev->wm_read.high);
2728 
2729 	ret = SSL_read(cre->ssl, rbuf, howmuch);
2730 	if (ret <= 0) {
2731 		ssl_err = SSL_get_error(cre->ssl, ret);
2732 
2733 		switch (ssl_err) {
2734 		case SSL_ERROR_WANT_READ:
2735 			DPRINTF("relay_ssl_readcb: session %d: "
2736 			    "want read", con->se_id);
2737 			goto retry;
2738 		case SSL_ERROR_WANT_WRITE:
2739 			DPRINTF("relay_ssl_readcb: session %d: "
2740 			    "want write", con->se_id);
2741 			goto retry;
2742 		default:
2743 			if (ret == 0)
2744 				what |= EVBUFFER_EOF;
2745 			else {
2746 				ssl_error(rlay->rl_conf.name, "relay_ssl_readcb");
2747 				what |= EVBUFFER_ERROR;
2748 			}
2749 			goto err;
2750 		}
2751 	}
2752 
2753 	if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
2754 		what |= EVBUFFER_ERROR;
2755 		goto err;
2756 	}
2757 
2758 	relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
2759 
2760 	len = EVBUFFER_LENGTH(bufev->input);
2761 	if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
2762 		return;
2763 	if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
2764 		struct evbuffer *buf = bufev->input;
2765 		event_del(&bufev->ev_read);
2766 		evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
2767 		return;
2768 	}
2769 
2770 	if (bufev->readcb != NULL)
2771 		(*bufev->readcb)(bufev, bufev->cbarg);
2772 	return;
2773 
2774  retry:
2775 	relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
2776 	return;
2777 
2778  err:
2779 	(*bufev->errorcb)(bufev, what, bufev->cbarg);
2780 }
2781 
2782 void
2783 relay_ssl_writecb(int fd, short event, void *arg)
2784 {
2785 	struct bufferevent *bufev = arg;
2786 	struct ctl_relay_event *cre = (struct ctl_relay_event *)bufev->cbarg;
2787 	struct session *con = (struct session *)cre->con;
2788 	struct relay *rlay = (struct relay *)con->se_relay;
2789 	int ret = 0, ssl_err;
2790 	short what = EVBUFFER_WRITE;
2791 
2792 	if (event == EV_TIMEOUT) {
2793 		what |= EVBUFFER_TIMEOUT;
2794 		goto err;
2795 	}
2796 
2797 	if (EVBUFFER_LENGTH(bufev->output)) {
2798 		if (cre->buf == NULL) {
2799 			cre->buflen = EVBUFFER_LENGTH(bufev->output);
2800 			if ((cre->buf = malloc(cre->buflen)) == NULL) {
2801 				what |= EVBUFFER_ERROR;
2802 				goto err;
2803 			}
2804 			bcopy(EVBUFFER_DATA(bufev->output),
2805 			    cre->buf, cre->buflen);
2806 		}
2807 
2808 		ret = SSL_write(cre->ssl, cre->buf, cre->buflen);
2809 		if (ret <= 0) {
2810 			ssl_err = SSL_get_error(cre->ssl, ret);
2811 
2812 			switch (ssl_err) {
2813 			case SSL_ERROR_WANT_READ:
2814 				DPRINTF("relay_ssl_writecb: session %d: "
2815 				    "want read", con->se_id);
2816 				goto retry;
2817 			case SSL_ERROR_WANT_WRITE:
2818 				DPRINTF("relay_ssl_writecb: session %d: "
2819 				    "want write", con->se_id);
2820 				goto retry;
2821 			default:
2822 				if (ret == 0)
2823 					what |= EVBUFFER_EOF;
2824 				else {
2825 					ssl_error(rlay->rl_conf.name,
2826 					    "relay_ssl_writecb");
2827 					what |= EVBUFFER_ERROR;
2828 				}
2829 				goto err;
2830 			}
2831 		}
2832 		evbuffer_drain(bufev->output, ret);
2833 	}
2834 	if (cre->buf != NULL) {
2835 		free(cre->buf);
2836 		cre->buf = NULL;
2837 		cre->buflen = 0;
2838 	}
2839 
2840 	if (EVBUFFER_LENGTH(bufev->output) != 0)
2841 		relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
2842 
2843 	if (bufev->writecb != NULL &&
2844 	    EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
2845 		(*bufev->writecb)(bufev, bufev->cbarg);
2846 	return;
2847 
2848  retry:
2849 	if (cre->buflen != 0)
2850 		relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
2851 	return;
2852 
2853  err:
2854 	if (cre->buf != NULL) {
2855 		free(cre->buf);
2856 		cre->buf = NULL;
2857 		cre->buflen = 0;
2858 	}
2859 	(*bufev->errorcb)(bufev, what, bufev->cbarg);
2860 }
2861 
2862 int
2863 relay_bufferevent_add(struct event *ev, int timeout)
2864 {
2865 	struct timeval tv, *ptv = NULL;
2866 
2867 	if (timeout) {
2868 		timerclear(&tv);
2869 		tv.tv_sec = timeout;
2870 		ptv = &tv;
2871 	}
2872 
2873 	return (event_add(ev, ptv));
2874 }
2875 
2876 #ifdef notyet
2877 int
2878 relay_bufferevent_printf(struct ctl_relay_event *cre, const char *fmt, ...)
2879 {
2880 	int ret;
2881 	va_list ap;
2882 
2883 	va_start(ap, fmt);
2884 	ret = evbuffer_add_vprintf(cre->output, fmt, ap);
2885 	va_end(ap);
2886 
2887 	if (cre->bev != NULL &&
2888 	    ret != -1 && EVBUFFER_LENGTH(cre->output) > 0 &&
2889 	    (cre->bev->enabled & EV_WRITE))
2890 		bufferevent_enable(cre->bev, EV_WRITE);
2891 
2892 	return (ret);
2893 }
2894 #endif
2895 
2896 int
2897 relay_bufferevent_print(struct ctl_relay_event *cre, char *str)
2898 {
2899 	if (cre->bev == NULL)
2900 		return (evbuffer_add(cre->output, str, strlen(str)));
2901 	return (bufferevent_write(cre->bev, str, strlen(str)));
2902 }
2903 
2904 int
2905 relay_bufferevent_write_buffer(struct ctl_relay_event *cre,
2906     struct evbuffer *buf)
2907 {
2908 	if (cre->bev == NULL)
2909 		return (evbuffer_add_buffer(cre->output, buf));
2910 	return (bufferevent_write_buffer(cre->bev, buf));
2911 }
2912 
2913 int
2914 relay_bufferevent_write_chunk(struct ctl_relay_event *cre,
2915     struct evbuffer *buf, size_t size)
2916 {
2917 	int ret;
2918 	ret = relay_bufferevent_write(cre, buf->buffer, size);
2919 	if (ret != -1)
2920 		evbuffer_drain(buf, size);
2921 	return (ret);
2922 }
2923 
2924 int
2925 relay_bufferevent_write(struct ctl_relay_event *cre, void *data, size_t size)
2926 {
2927 	if (cre->bev == NULL)
2928 		return (evbuffer_add(cre->output, data, size));
2929 	return (bufferevent_write(cre->bev, data, size));
2930 }
2931 
2932 int
2933 relay_cmp_af(struct sockaddr_storage *a, struct sockaddr_storage *b)
2934 {
2935 	int ret = -1;
2936 	struct sockaddr_in ia, ib;
2937 	struct sockaddr_in6 ia6, ib6;
2938 
2939 	switch (a->ss_family) {
2940 	case AF_INET:
2941 		bcopy(a, &ia, sizeof(struct sockaddr_in));
2942 		bcopy(b, &ib, sizeof(struct sockaddr_in));
2943 
2944 		ret = memcmp(&ia.sin_addr, &ib.sin_addr,
2945 		    sizeof(ia.sin_addr));
2946 		if (ret == 0)
2947 			ret = memcmp(&ia.sin_port, &ib.sin_port,
2948 			    sizeof(ia.sin_port));
2949 		break;
2950 	case AF_INET6:
2951 		bcopy(a, &ia6, sizeof(struct sockaddr_in6));
2952 		bcopy(b, &ib6, sizeof(struct sockaddr_in6));
2953 
2954 		ret = memcmp(&ia6.sin6_addr, &ib6.sin6_addr,
2955 		    sizeof(ia6.sin6_addr));
2956 		if (ret == 0)
2957 			ret = memcmp(&ia6.sin6_port, &ib6.sin6_port,
2958 			    sizeof(ia6.sin6_port));
2959 		break;
2960 	default:
2961 		break;
2962 	}
2963 
2964 	return (ret);
2965 }
2966 
2967 char *
2968 relay_load_file(const char *name, off_t *len)
2969 {
2970 	struct stat	 st;
2971 	off_t		 size;
2972 	u_int8_t	*buf = NULL;
2973 	int		 fd;
2974 
2975 	if ((fd = open(name, O_RDONLY)) == -1)
2976 		return (NULL);
2977 	if (fstat(fd, &st) != 0)
2978 		goto fail;
2979 	size = st.st_size;
2980 	if ((buf = (char *)calloc(1, size + 1)) == NULL)
2981 		goto fail;
2982 	if (read(fd, buf, size) != size)
2983 		goto fail;
2984 
2985 	close(fd);
2986 
2987 	*len = size + 1;
2988 	return (buf);
2989 
2990  fail:
2991 	if (buf != NULL)
2992 		free(buf);
2993 	close(fd);
2994 	return (NULL);
2995 }
2996 
2997 int
2998 relay_load_certfiles(struct relay *rlay)
2999 {
3000 	char	 certfile[PATH_MAX];
3001 	char	 hbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
3002 
3003 	if ((rlay->rl_conf.flags & F_SSL) == 0)
3004 		return (0);
3005 
3006 	if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL)
3007 		return (-1);
3008 
3009 	if (snprintf(certfile, sizeof(certfile),
3010 	    "/etc/ssl/%s.crt", hbuf) == -1)
3011 		return (-1);
3012 	if ((rlay->rl_ssl_cert = relay_load_file(certfile,
3013 	    &rlay->rl_ssl_cert_len)) == NULL)
3014 		return (-1);
3015 	log_debug("relay_load_certfile: using certificate %s", certfile);
3016 
3017 	if (snprintf(certfile, sizeof(certfile),
3018 	    "/etc/ssl/private/%s.key", hbuf) == -1)
3019 		return -1;
3020 	if ((rlay->rl_ssl_key = relay_load_file(certfile,
3021 	    &rlay->rl_ssl_key_len)) == NULL)
3022 		return (-1);
3023 	log_debug("relay_load_certfile: using private key %s", certfile);
3024 
3025 	return (0);
3026 }
3027 
3028 static __inline int
3029 relay_proto_cmp(struct protonode *a, struct protonode *b)
3030 {
3031 	int ret;
3032 	ret = strcasecmp(a->key, b->key);
3033 	if (ret == 0)
3034 		ret = (int)a->type - b->type;
3035 	return (ret);
3036 }
3037 
3038 RB_GENERATE(proto_tree, protonode, nodes, relay_proto_cmp);
3039 
3040 int
3041 relay_session_cmp(struct session *a, struct session *b)
3042 {
3043 	struct relay	*rlay = (struct relay *)b->se_relay;
3044 	struct protocol	*proto = rlay->rl_proto;
3045 
3046 	if (proto != NULL && proto->cmp != NULL)
3047 		return ((*proto->cmp)(a, b));
3048 
3049 	return ((int)a->se_id - b->se_id);
3050 }
3051 
3052 SPLAY_GENERATE(session_tree, session, se_nodes, relay_session_cmp);
3053