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