xref: /openbsd/usr.sbin/relayd/relayd.c (revision 404b540a)
1 /*	$OpenBSD: relayd.c,v 1.92 2009/08/13 13:51:21 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
5  * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/socket.h>
23 #include <sys/wait.h>
24 
25 #include <net/if.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <getopt.h>
33 #include <err.h>
34 #include <errno.h>
35 #include <event.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #include <pwd.h>
40 #include <sha1.h>
41 #include <md5.h>
42 
43 #include <openssl/ssl.h>
44 
45 #include "relayd.h"
46 
47 __dead void	 usage(void);
48 
49 void		 main_sig_handler(int, short, void *);
50 void		 main_shutdown(struct relayd *);
51 void		 main_dispatch_pfe(int, short, void *);
52 void		 main_dispatch_hce(int, short, void *);
53 void		 main_dispatch_relay(int, short, void *);
54 int		 check_child(pid_t, const char *);
55 int		 send_all(struct relayd *, enum imsg_type,
56 		    void *, u_int16_t);
57 void		 reconfigure(void);
58 void		 purge_tree(struct proto_tree *);
59 int		 bindany(struct ctl_bindany *);
60 
61 int		 pipe_parent2pfe[2];
62 int		 pipe_parent2hce[2];
63 int		 pipe_pfe2hce[2];
64 int		 pipe_parent2relay[RELAY_MAXPROC][2];
65 int		 pipe_pfe2relay[RELAY_MAXPROC][2];
66 
67 struct relayd	*relayd_env;
68 
69 struct imsgev	*iev_pfe;
70 struct imsgev	*iev_hce;
71 struct imsgev	*iev_relay;
72 
73 pid_t		 pfe_pid = 0;
74 pid_t		 hce_pid = 0;
75 pid_t		 relay_pid = 0;
76 
77 void
78 main_sig_handler(int sig, short event, void *arg)
79 {
80 	struct relayd		*env = arg;
81 	int			 die = 0;
82 
83 	switch (sig) {
84 	case SIGTERM:
85 	case SIGINT:
86 		die = 1;
87 		/* FALLTHROUGH */
88 	case SIGCHLD:
89 		if (check_child(pfe_pid, "pf update engine")) {
90 			pfe_pid = 0;
91 			die  = 1;
92 		}
93 		if (check_child(hce_pid, "host check engine")) {
94 			hce_pid = 0;
95 			die  = 1;
96 		}
97 		if (check_child(relay_pid, "socket relay engine")) {
98 			relay_pid = 0;
99 			die  = 1;
100 		}
101 		if (die)
102 			main_shutdown(env);
103 		break;
104 	case SIGHUP:
105 		reconfigure();
106 		break;
107 	default:
108 		fatalx("unexpected signal");
109 	}
110 }
111 
112 /* __dead is for lint */
113 __dead void
114 usage(void)
115 {
116 	extern char	*__progname;
117 
118 	fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
119 	    __progname);
120 	exit(1);
121 }
122 
123 int
124 main(int argc, char *argv[])
125 {
126 	int			 c;
127 	int			 debug;
128 	u_int32_t		 opts;
129 	struct relayd		*env;
130 	const char		*conffile;
131 	struct event		 ev_sigint;
132 	struct event		 ev_sigterm;
133 	struct event		 ev_sigchld;
134 	struct event		 ev_sighup;
135 	struct imsgev		*iev;
136 
137 	opts = 0;
138 	debug = 0;
139 	conffile = CONF_FILE;
140 
141 	log_init(1);	/* log to stderr until daemonized */
142 
143 	while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
144 		switch (c) {
145 		case 'd':
146 			debug = 2;
147 			break;
148 		case 'D':
149 			if (cmdline_symset(optarg) < 0)
150 				log_warnx("could not parse macro definition %s",
151 				    optarg);
152 			break;
153 		case 'n':
154 			debug = 2;
155 			opts |= RELAYD_OPT_NOACTION;
156 			break;
157 		case 'f':
158 			conffile = optarg;
159 			break;
160 		case 'v':
161 			opts |= RELAYD_OPT_VERBOSE;
162 			break;
163 		default:
164 			usage();
165 		}
166 	}
167 
168 	argc -= optind;
169 	argv += optind;
170 	if (argc > 0)
171 		usage();
172 
173 	if ((env = parse_config(conffile, opts)) == NULL)
174 		exit(1);
175 	relayd_env = env;
176 
177 	if (env->sc_opts & RELAYD_OPT_NOACTION) {
178 		fprintf(stderr, "configuration OK\n");
179 		exit(0);
180 	}
181 	if (debug)
182 		env->sc_opts |= RELAYD_OPT_LOGUPDATE;
183 
184 	if (geteuid())
185 		errx(1, "need root privileges");
186 
187 	if (getpwnam(RELAYD_USER) == NULL)
188 		errx(1, "unknown user %s", RELAYD_USER);
189 
190 	log_init(debug);
191 
192 	if (!debug) {
193 		if (daemon(1, 0) == -1)
194 			err(1, "failed to daemonize");
195 	}
196 
197 	log_info("startup");
198 
199 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
200 	    pipe_parent2pfe) == -1)
201 		fatal("socketpair");
202 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
203 	    pipe_parent2hce) == -1)
204 		fatal("socketpair");
205 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
206 	    pipe_pfe2hce) == -1)
207 		fatal("socketpair");
208 	for (c = 0; c < env->sc_prefork_relay; c++) {
209 		if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
210 		    pipe_parent2relay[c]) == -1)
211 			fatal("socketpair");
212 		if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
213 		    pipe_pfe2relay[c]) == -1)
214 			fatal("socketpair");
215 		session_socket_blockmode(pipe_pfe2relay[c][0], BM_NONBLOCK);
216 		session_socket_blockmode(pipe_pfe2relay[c][1], BM_NONBLOCK);
217 		session_socket_blockmode(pipe_parent2relay[c][0], BM_NONBLOCK);
218 		session_socket_blockmode(pipe_parent2relay[c][1], BM_NONBLOCK);
219 	}
220 
221 	session_socket_blockmode(pipe_parent2pfe[0], BM_NONBLOCK);
222 	session_socket_blockmode(pipe_parent2pfe[1], BM_NONBLOCK);
223 	session_socket_blockmode(pipe_parent2hce[0], BM_NONBLOCK);
224 	session_socket_blockmode(pipe_parent2hce[1], BM_NONBLOCK);
225 	session_socket_blockmode(pipe_pfe2hce[0], BM_NONBLOCK);
226 	session_socket_blockmode(pipe_pfe2hce[1], BM_NONBLOCK);
227 
228 	pfe_pid = pfe(env, pipe_parent2pfe, pipe_parent2hce,
229 	    pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
230 	hce_pid = hce(env, pipe_parent2pfe, pipe_parent2hce,
231 	    pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
232 	if (env->sc_prefork_relay > 0)
233 		relay_pid = relay(env, pipe_parent2pfe, pipe_parent2hce,
234 		    pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
235 
236 	setproctitle("parent");
237 
238 	event_init();
239 
240 	signal_set(&ev_sigint, SIGINT, main_sig_handler, env);
241 	signal_set(&ev_sigterm, SIGTERM, main_sig_handler, env);
242 	signal_set(&ev_sigchld, SIGCHLD, main_sig_handler, env);
243 	signal_set(&ev_sighup, SIGHUP, main_sig_handler, env);
244 	signal_add(&ev_sigint, NULL);
245 	signal_add(&ev_sigterm, NULL);
246 	signal_add(&ev_sigchld, NULL);
247 	signal_add(&ev_sighup, NULL);
248 	signal(SIGPIPE, SIG_IGN);
249 
250 	close(pipe_parent2pfe[1]);
251 	close(pipe_parent2hce[1]);
252 	close(pipe_pfe2hce[0]);
253 	close(pipe_pfe2hce[1]);
254 	for (c = 0; c < env->sc_prefork_relay; c++) {
255 		close(pipe_pfe2relay[c][0]);
256 		close(pipe_pfe2relay[c][1]);
257 		close(pipe_parent2relay[c][0]);
258 	}
259 
260 	if ((iev_pfe = calloc(1, sizeof(struct imsgev))) == NULL ||
261 	    (iev_hce = calloc(1, sizeof(struct imsgev))) == NULL)
262 		fatal(NULL);
263 
264 	if (env->sc_prefork_relay > 0) {
265 		if ((iev_relay = calloc(env->sc_prefork_relay,
266 		    sizeof(struct imsgev))) == NULL)
267 			fatal(NULL);
268 	}
269 
270 	imsg_init(&iev_pfe->ibuf, pipe_parent2pfe[0]);
271 	imsg_init(&iev_hce->ibuf, pipe_parent2hce[0]);
272 	iev_pfe->handler = main_dispatch_pfe;
273 	iev_pfe->data = env;
274 	iev_hce->handler = main_dispatch_hce;
275 	iev_hce->data = env;
276 
277 	for (c = 0; c < env->sc_prefork_relay; c++) {
278 		iev = &iev_relay[c];
279 		imsg_init(&iev->ibuf, pipe_parent2relay[c][1]);
280 		iev->handler = main_dispatch_relay;
281 		iev->events = EV_READ;
282 		event_set(&iev->ev, iev->ibuf.fd, iev->events,
283 		    iev->handler, iev);
284 		event_add(&iev->ev, NULL);
285 	}
286 
287 	iev_pfe->events = EV_READ;
288 	event_set(&iev_pfe->ev, iev_pfe->ibuf.fd, iev_pfe->events,
289 	    iev_pfe->handler, iev_pfe);
290 	event_add(&iev_pfe->ev, NULL);
291 
292 	iev_hce->events = EV_READ;
293 	event_set(&iev_hce->ev, iev_hce->ibuf.fd, iev_hce->events,
294 	    iev_hce->handler, iev_hce);
295 	event_add(&iev_hce->ev, NULL);
296 
297 	if (env->sc_flags & F_DEMOTE)
298 		carp_demote_reset(env->sc_demote_group, 0);
299 
300 	init_routes(env);
301 
302 	event_dispatch();
303 
304 	return (0);
305 }
306 
307 void
308 main_shutdown(struct relayd *env)
309 {
310 	pid_t	pid;
311 
312 	if (pfe_pid)
313 		kill(pfe_pid, SIGTERM);
314 	if (hce_pid)
315 		kill(hce_pid, SIGTERM);
316 	if (relay_pid)
317 		kill(relay_pid, SIGTERM);
318 
319 	do {
320 		if ((pid = wait(NULL)) == -1 &&
321 		    errno != EINTR && errno != ECHILD)
322 			fatal("wait");
323 	} while (pid != -1 || (pid == -1 && errno == EINTR));
324 
325 	control_cleanup();
326 	carp_demote_shutdown();
327 	if (env->sc_flags & F_DEMOTE)
328 		carp_demote_reset(env->sc_demote_group, 128);
329 	log_info("terminating");
330 	exit(0);
331 }
332 
333 int
334 check_child(pid_t pid, const char *pname)
335 {
336 	int	status;
337 
338 	if (waitpid(pid, &status, WNOHANG) > 0) {
339 		if (WIFEXITED(status)) {
340 			log_warnx("check_child: lost child: %s exited", pname);
341 			return (1);
342 		}
343 		if (WIFSIGNALED(status)) {
344 			log_warnx("check_child: lost child: %s terminated; "
345 			    "signal %d", pname, WTERMSIG(status));
346 			return (1);
347 		}
348 	}
349 
350 	return (0);
351 }
352 
353 int
354 send_all(struct relayd *env, enum imsg_type type, void *buf, u_int16_t len)
355 {
356 	int		 i;
357 
358 	if (imsg_compose_event(iev_pfe, type, 0, 0, -1, buf, len) == -1)
359 		return (-1);
360 	if (imsg_compose_event(iev_hce, type, 0, 0, -1, buf, len) == -1)
361 		return (-1);
362 	for (i = 0; i < env->sc_prefork_relay; i++) {
363 		if (imsg_compose_event(&iev_relay[i], type, 0, 0, -1, buf, len)
364 		    == -1)
365 			return (-1);
366 	}
367 	return (0);
368 }
369 
370 void
371 merge_config(struct relayd *env, struct relayd *new_env)
372 {
373 	env->sc_opts = new_env->sc_opts;
374 	env->sc_flags = new_env->sc_flags;
375 	env->sc_confpath = new_env->sc_confpath;
376 	env->sc_tablecount = new_env->sc_tablecount;
377 	env->sc_rdrcount = new_env->sc_rdrcount;
378 	env->sc_protocount = new_env->sc_protocount;
379 	env->sc_relaycount = new_env->sc_relaycount;
380 
381 	memcpy(&env->sc_interval, &new_env->sc_interval,
382 	    sizeof(env->sc_interval));
383 	memcpy(&env->sc_timeout, &new_env->sc_timeout,
384 	    sizeof(env->sc_timeout));
385 	memcpy(&env->sc_empty_table, &new_env->sc_empty_table,
386 	    sizeof(env->sc_empty_table));
387 	memcpy(&env->sc_proto_default, &new_env->sc_proto_default,
388 	    sizeof(env->sc_proto_default));
389 	env->sc_prefork_relay = new_env->sc_prefork_relay;
390 	(void)strlcpy(env->sc_demote_group, new_env->sc_demote_group,
391 	    sizeof(env->sc_demote_group));
392 
393 	env->sc_tables = new_env->sc_tables;
394 	env->sc_rdrs = new_env->sc_rdrs;
395 	env->sc_relays = new_env->sc_relays;
396 	env->sc_protos = new_env->sc_protos;
397 }
398 
399 
400 void
401 reconfigure(void)
402 {
403 	struct relayd		*env = relayd_env;
404 	struct relayd		*new_env = NULL;
405 	struct rdr		*rdr;
406 	struct address		*virt;
407 	struct table            *table;
408 	struct host             *host;
409 
410 	log_info("reloading configuration");
411 	if ((new_env = parse_config(env->sc_confpath, env->sc_opts)) == NULL) {
412 		log_warnx("configuration reloading FAILED");
413 		return;
414 	}
415 
416 	if (!(env->sc_flags & F_NEEDPF) && (new_env->sc_flags & F_NEEDPF)) {
417 		log_warnx("new configuration requires pf while it "
418 		    "was previously disabled."
419 		    "configuration will not be reloaded");
420 		purge_config(new_env, PURGE_EVERYTHING);
421 		free(new_env);
422 		return;
423 	}
424 
425 	purge_config(env, PURGE_EVERYTHING);
426 	merge_config(env, new_env);
427 	free(new_env);
428 	log_info("configuration merge done");
429 
430 	/*
431 	 * first reconfigure pfe
432 	 */
433 	imsg_compose_event(iev_pfe, IMSG_RECONF, 0, 0, -1, env, sizeof(*env));
434 	TAILQ_FOREACH(table, env->sc_tables, entry) {
435 		imsg_compose_event(iev_pfe, IMSG_RECONF_TABLE, 0, 0, -1,
436 		    &table->conf, sizeof(table->conf));
437 		TAILQ_FOREACH(host, &table->hosts, entry) {
438 			imsg_compose_event(iev_pfe, IMSG_RECONF_HOST, 0, 0, -1,
439 			    &host->conf, sizeof(host->conf));
440 		}
441 	}
442 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
443 		imsg_compose_event(iev_pfe, IMSG_RECONF_RDR, 0, 0, -1,
444 		    &rdr->conf, sizeof(rdr->conf));
445 		TAILQ_FOREACH(virt, &rdr->virts, entry)
446 			imsg_compose_event(iev_pfe, IMSG_RECONF_VIRT, 0, 0, -1,
447 				virt, sizeof(*virt));
448 	}
449 	imsg_compose_event(iev_pfe, IMSG_RECONF_END, 0, 0, -1, NULL, 0);
450 
451 	/*
452 	 * then reconfigure hce
453 	 */
454 	imsg_compose_event(iev_hce, IMSG_RECONF, 0, 0, -1, env, sizeof(*env));
455 	TAILQ_FOREACH(table, env->sc_tables, entry) {
456 		imsg_compose_event(iev_hce, IMSG_RECONF_TABLE, 0, 0, -1,
457 		    &table->conf, sizeof(table->conf));
458 		if (table->sendbuf != NULL)
459 			imsg_compose_event(iev_hce, IMSG_RECONF_SENDBUF,
460 			    0, 0, -1, table->sendbuf,
461 			    strlen(table->sendbuf) + 1);
462 		TAILQ_FOREACH(host, &table->hosts, entry) {
463 			imsg_compose_event(iev_hce, IMSG_RECONF_HOST, 0, 0, -1,
464 			    &host->conf, sizeof(host->conf));
465 		}
466 	}
467 	imsg_compose_event(iev_hce, IMSG_RECONF_END, 0, 0, -1, NULL, 0);
468 }
469 
470 void
471 purge_config(struct relayd *env, u_int8_t what)
472 {
473 	struct table		*table;
474 	struct rdr		*rdr;
475 	struct address		*virt;
476 	struct protocol		*proto;
477 	struct relay		*rlay;
478 	struct rsession		*sess;
479 
480 	if (what & PURGE_TABLES && env->sc_tables != NULL) {
481 		while ((table = TAILQ_FIRST(env->sc_tables)) != NULL)
482 			purge_table(env->sc_tables, table);
483 		free(env->sc_tables);
484 		env->sc_tables = NULL;
485 	}
486 
487 	if (what & PURGE_RDRS && env->sc_rdrs != NULL) {
488 		while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) {
489 			TAILQ_REMOVE(env->sc_rdrs, rdr, entry);
490 			while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) {
491 				TAILQ_REMOVE(&rdr->virts, virt, entry);
492 				free(virt);
493 			}
494 			free(rdr);
495 		}
496 		free(env->sc_rdrs);
497 		env->sc_rdrs = NULL;
498 	}
499 
500 	if (what & PURGE_RELAYS && env->sc_relays != NULL) {
501 		while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL) {
502 			TAILQ_REMOVE(env->sc_relays, rlay, rl_entry);
503 			while ((sess =
504 			    SPLAY_ROOT(&rlay->rl_sessions)) != NULL) {
505 				SPLAY_REMOVE(session_tree,
506 				    &rlay->rl_sessions, sess);
507 				free(sess);
508 			}
509 			if (rlay->rl_bev != NULL)
510 				bufferevent_free(rlay->rl_bev);
511 			if (rlay->rl_dstbev != NULL)
512 				bufferevent_free(rlay->rl_dstbev);
513 			if (rlay->rl_ssl_ctx != NULL)
514 				SSL_CTX_free(rlay->rl_ssl_ctx);
515 			free(rlay);
516 		}
517 		free(env->sc_relays);
518 		env->sc_relays = NULL;
519 	}
520 
521 	if (what & PURGE_PROTOS && env->sc_protos != NULL) {
522 		while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) {
523 			TAILQ_REMOVE(env->sc_protos, proto, entry);
524 			purge_tree(&proto->request_tree);
525 			purge_tree(&proto->response_tree);
526 			if (proto->style != NULL)
527 				free(proto->style);
528 			free(proto);
529 		}
530 		free(env->sc_protos);
531 		env->sc_protos = NULL;
532 	}
533 }
534 
535 void
536 purge_tree(struct proto_tree *tree)
537 {
538 	struct protonode	*proot, *pn;
539 
540 	while ((proot = RB_ROOT(tree)) != NULL) {
541 		RB_REMOVE(proto_tree, tree, proot);
542 		if (proot->key != NULL)
543 			free(proot->key);
544 		if (proot->value != NULL)
545 			free(proot->value);
546 		while ((pn = SIMPLEQ_FIRST(&proot->head)) != NULL) {
547 			SIMPLEQ_REMOVE_HEAD(&proot->head, entry);
548 			if (pn->key != NULL)
549 				free(pn->key);
550 			if (pn->value != NULL)
551 				free(pn->value);
552 			if (pn->label != 0)
553 				pn_unref(pn->label);
554 			free(pn);
555 		}
556 		free(proot);
557 	}
558 }
559 
560 void
561 purge_table(struct tablelist *head, struct table *table)
562 {
563 	struct host		*host;
564 
565 	while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
566 		TAILQ_REMOVE(&table->hosts, host, entry);
567 		if (host->cte.ssl != NULL)
568 			SSL_free(host->cte.ssl);
569 		free(host);
570 	}
571 	if (table->sendbuf != NULL)
572 		free(table->sendbuf);
573 	if (table->conf.flags & F_SSL)
574 		SSL_CTX_free(table->ssl_ctx);
575 
576 	if (head != NULL)
577 		TAILQ_REMOVE(head, table, entry);
578 	free(table);
579 }
580 
581 void
582 imsg_event_add(struct imsgev *iev)
583 {
584 	if (iev->handler == NULL) {
585 		imsg_flush(&iev->ibuf);
586 		return;
587 	}
588 
589 	iev->events = EV_READ;
590 	if (iev->ibuf.w.queued)
591 		iev->events |= EV_WRITE;
592 
593 	event_del(&iev->ev);
594 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
595 	event_add(&iev->ev, NULL);
596 }
597 
598 int
599 imsg_compose_event(struct imsgev *iev, u_int16_t type,
600     u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen)
601 {
602 	int	ret;
603 
604 	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
605 	    pid, fd, data, datalen)) != -1)
606 		imsg_event_add(iev);
607 	return (ret);
608 }
609 
610 void
611 main_dispatch_pfe(int fd, short event, void *ptr)
612 {
613 	struct imsgev		*iev;
614 	struct imsgbuf		*ibuf;
615 	struct imsg		 imsg;
616 	ssize_t			 n;
617 	struct ctl_demote	 demote;
618 	struct ctl_netroute	 crt;
619 	struct relayd		*env;
620 
621 	iev = ptr;
622 	ibuf = &iev->ibuf;
623 	env = (struct relayd *)iev->data;
624 
625 	if (event & EV_READ) {
626 		if ((n = imsg_read(ibuf)) == -1)
627 			fatal("imsg_read_error");
628 		if (n == 0) {
629 			/* this pipe is dead, so remove the event handler */
630 			event_del(&iev->ev);
631 			event_loopexit(NULL);
632 			return;
633 		}
634 	}
635 
636 	if (event & EV_WRITE) {
637 		if (msgbuf_write(&ibuf->w) == -1)
638 			fatal("msgbuf_write");
639 	}
640 
641 	for (;;) {
642 		if ((n = imsg_get(ibuf, &imsg)) == -1)
643 			fatal("main_dispatch_pfe: imsg_read error");
644 		if (n == 0)
645 			break;
646 
647 		switch (imsg.hdr.type) {
648 		case IMSG_DEMOTE:
649 			if (imsg.hdr.len - IMSG_HEADER_SIZE !=
650 			    sizeof(demote))
651 				fatalx("main_dispatch_pfe: "
652 				    "invalid size of demote request");
653 			memcpy(&demote, imsg.data, sizeof(demote));
654 			carp_demote_set(demote.group, demote.level);
655 			break;
656 		case IMSG_RTMSG:
657 			if (imsg.hdr.len - IMSG_HEADER_SIZE !=
658 			    sizeof(crt))
659 				fatalx("main_dispatch_pfe: "
660 				    "invalid size of rtmsg request");
661 			memcpy(&crt, imsg.data, sizeof(crt));
662 			pfe_route(env, &crt);
663 			break;
664 		case IMSG_CTL_RELOAD:
665 			/*
666 			 * so far we only get here if no L7 (relay) is done.
667 			 */
668 			reconfigure();
669 			break;
670 		default:
671 			log_debug("main_dispatch_pfe: unexpected imsg %d",
672 			    imsg.hdr.type);
673 			break;
674 		}
675 		imsg_free(&imsg);
676 	}
677 	imsg_event_add(iev);
678 }
679 
680 void
681 main_dispatch_hce(int fd, short event, void * ptr)
682 {
683 	struct imsgev		*iev;
684 	struct imsgbuf		*ibuf;
685 	struct imsg		 imsg;
686 	ssize_t			 n;
687 	struct ctl_script	 scr;
688 	struct relayd		*env;
689 
690 	env = relayd_env;
691 	iev = ptr;
692 	ibuf = &iev->ibuf;
693 
694 	if (event & EV_READ) {
695 		if ((n = imsg_read(ibuf)) == -1)
696 			fatal("imsg_read error");
697 		if (n == 0) {
698 			/* this pipe is dead, so remove the event handler */
699 			event_del(&iev->ev);
700 			event_loopexit(NULL);
701 			return;
702 		}
703 	}
704 
705 	if (event & EV_WRITE) {
706 		if (msgbuf_write(&ibuf->w) == -1)
707 			fatal("msgbuf_write");
708 	}
709 
710 	for (;;) {
711 		if ((n = imsg_get(ibuf, &imsg)) == -1)
712 			fatal("main_dispatch_hce: imsg_read error");
713 		if (n == 0)
714 			break;
715 
716 		switch (imsg.hdr.type) {
717 		case IMSG_SCRIPT:
718 			if (imsg.hdr.len - IMSG_HEADER_SIZE !=
719 			    sizeof(scr))
720 				fatalx("main_dispatch_hce: "
721 				    "invalid size of script request");
722 			bcopy(imsg.data, &scr, sizeof(scr));
723 			scr.retval = script_exec(env, &scr);
724 			imsg_compose_event(iev_hce, IMSG_SCRIPT,
725 			    0, 0, -1, &scr, sizeof(scr));
726 			break;
727 		case IMSG_SNMPSOCK:
728 			(void)snmp_sendsock(iev);
729 			break;
730 		default:
731 			log_debug("main_dispatch_hce: unexpected imsg %d",
732 			    imsg.hdr.type);
733 			break;
734 		}
735 		imsg_free(&imsg);
736 	}
737 	imsg_event_add(iev);
738 }
739 
740 void
741 main_dispatch_relay(int fd, short event, void * ptr)
742 {
743 	struct relayd		*env = relayd_env;
744 	struct imsgev		*iev;
745 	struct imsgbuf		*ibuf;
746 	struct imsg		 imsg;
747 	ssize_t			 n;
748 	struct ctl_bindany	 bnd;
749 	int			 s;
750 
751 	iev = ptr;
752 	ibuf = &iev->ibuf;
753 
754 	if (event & EV_READ) {
755 		if ((n = imsg_read(ibuf)) == -1)
756 			fatal("imsg_read error");
757 		if (n == 0) {
758 			/* this pipe is dead, so remove the event handler */
759 			event_del(&iev->ev);
760 			event_loopexit(NULL);
761 			return;
762 		}
763 	}
764 
765 	if (event & EV_WRITE) {
766 		if (msgbuf_write(&ibuf->w) == -1)
767 			fatal("msgbuf_write");
768 	}
769 
770 	for (;;) {
771 		if ((n = imsg_get(ibuf, &imsg)) == -1)
772 			fatal("main_dispatch_relay: imsg_read error");
773 		if (n == 0)
774 			break;
775 
776 		switch (imsg.hdr.type) {
777 		case IMSG_BINDANY:
778 			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(bnd))
779 				fatalx("invalid imsg header len");
780 			bcopy(imsg.data, &bnd, sizeof(bnd));
781 			if (bnd.bnd_proc > env->sc_prefork_relay)
782 				fatalx("pfe_dispatch_relay: "
783 				    "invalid relay proc");
784 			switch (bnd.bnd_proto) {
785 			case IPPROTO_TCP:
786 			case IPPROTO_UDP:
787 				break;
788 			default:
789 				fatalx("pfe_dispatch_relay: requested socket "
790 				    "for invalid protocol");
791 				/* NOTREACHED */
792 			}
793 			s = bindany(&bnd);
794 			imsg_compose_event(&iev_relay[bnd.bnd_proc],
795 			    IMSG_BINDANY,
796 			    0, 0, s, &bnd.bnd_id, sizeof(bnd.bnd_id));
797 			break;
798 		default:
799 			log_debug("main_dispatch_relay: unexpected imsg %d",
800 			    imsg.hdr.type);
801 			break;
802 		}
803 		imsg_free(&imsg);
804 	}
805 	imsg_event_add(iev);
806 }
807 
808 struct host *
809 host_find(struct relayd *env, objid_t id)
810 {
811 	struct table	*table;
812 	struct host	*host;
813 
814 	TAILQ_FOREACH(table, env->sc_tables, entry)
815 		TAILQ_FOREACH(host, &table->hosts, entry)
816 			if (host->conf.id == id)
817 				return (host);
818 	return (NULL);
819 }
820 
821 struct table *
822 table_find(struct relayd *env, objid_t id)
823 {
824 	struct table	*table;
825 
826 	TAILQ_FOREACH(table, env->sc_tables, entry)
827 		if (table->conf.id == id)
828 			return (table);
829 	return (NULL);
830 }
831 
832 struct rdr *
833 rdr_find(struct relayd *env, objid_t id)
834 {
835 	struct rdr	*rdr;
836 
837 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry)
838 		if (rdr->conf.id == id)
839 			return (rdr);
840 	return (NULL);
841 }
842 
843 struct relay *
844 relay_find(struct relayd *env, objid_t id)
845 {
846 	struct relay	*rlay;
847 
848 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
849 		if (rlay->rl_conf.id == id)
850 			return (rlay);
851 	return (NULL);
852 }
853 
854 struct rsession *
855 session_find(struct relayd *env, objid_t id)
856 {
857 	struct relay		*rlay;
858 	struct rsession		*con;
859 
860 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
861 		SPLAY_FOREACH(con, session_tree, &rlay->rl_sessions)
862 			if (con->se_id == id)
863 				return (con);
864 	return (NULL);
865 }
866 
867 struct netroute *
868 route_find(struct relayd *env, objid_t id)
869 {
870 	struct netroute	*nr;
871 
872 	TAILQ_FOREACH(nr, env->sc_routes, nr_route)
873 		if (nr->nr_conf.id == id)
874 			return (nr);
875 	return (NULL);
876 }
877 
878 struct host *
879 host_findbyname(struct relayd *env, const char *name)
880 {
881 	struct table	*table;
882 	struct host	*host;
883 
884 	TAILQ_FOREACH(table, env->sc_tables, entry)
885 		TAILQ_FOREACH(host, &table->hosts, entry)
886 			if (strcmp(host->conf.name, name) == 0)
887 				return (host);
888 	return (NULL);
889 }
890 
891 struct table *
892 table_findbyname(struct relayd *env, const char *name)
893 {
894 	struct table	*table;
895 
896 	TAILQ_FOREACH(table, env->sc_tables, entry)
897 		if (strcmp(table->conf.name, name) == 0)
898 			return (table);
899 	return (NULL);
900 }
901 
902 struct table *
903 table_findbyconf(struct relayd *env, struct table *tb)
904 {
905 	struct table		*table;
906 	struct table_config	 a, b;
907 
908 	bcopy(&tb->conf, &a, sizeof(a));
909 	a.id = a.rdrid = 0;
910 	a.flags &= ~(F_USED|F_BACKUP);
911 
912 	TAILQ_FOREACH(table, env->sc_tables, entry) {
913 		bcopy(&table->conf, &b, sizeof(b));
914 		b.id = b.rdrid = 0;
915 		b.flags &= ~(F_USED|F_BACKUP);
916 
917 		/*
918 		 * Compare two tables and return the existing table if
919 		 * the configuration seems to be the same.
920 		 */
921 		if (bcmp(&a, &b, sizeof(b)) == 0 &&
922 		    ((tb->sendbuf == NULL && table->sendbuf == NULL) ||
923 		    (tb->sendbuf != NULL && table->sendbuf != NULL &&
924 		    strcmp(tb->sendbuf, table->sendbuf) == 0)))
925 			return (table);
926 	}
927 	return (NULL);
928 }
929 
930 struct rdr *
931 rdr_findbyname(struct relayd *env, const char *name)
932 {
933 	struct rdr	*rdr;
934 
935 	TAILQ_FOREACH(rdr, env->sc_rdrs, entry)
936 		if (strcmp(rdr->conf.name, name) == 0)
937 			return (rdr);
938 	return (NULL);
939 }
940 
941 struct relay *
942 relay_findbyname(struct relayd *env, const char *name)
943 {
944 	struct relay	*rlay;
945 
946 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
947 		if (strcmp(rlay->rl_conf.name, name) == 0)
948 			return (rlay);
949 	return (NULL);
950 }
951 
952 struct relay *
953 relay_findbyaddr(struct relayd *env, struct relay_config *rc)
954 {
955 	struct relay	*rlay;
956 
957 	TAILQ_FOREACH(rlay, env->sc_relays, rl_entry)
958 		if (bcmp(&rlay->rl_conf.ss, &rc->ss, sizeof(rc->ss)) == 0 &&
959 		    rlay->rl_conf.port == rc->port)
960 			return (rlay);
961 	return (NULL);
962 }
963 
964 void
965 event_again(struct event *ev, int fd, short event,
966     void (*fn)(int, short, void *),
967     struct timeval *start, struct timeval *end, void *arg)
968 {
969 	struct timeval tv_next, tv_now, tv;
970 
971 	if (gettimeofday(&tv_now, NULL) == -1)
972 		fatal("event_again: gettimeofday");
973 
974 	bcopy(end, &tv_next, sizeof(tv_next));
975 	timersub(&tv_now, start, &tv_now);
976 	timersub(&tv_next, &tv_now, &tv_next);
977 
978 	bzero(&tv, sizeof(tv));
979 	if (timercmp(&tv_next, &tv, >))
980 		bcopy(&tv_next, &tv, sizeof(tv));
981 
982 	event_set(ev, fd, event, fn, arg);
983 	event_add(ev, &tv);
984 }
985 
986 int
987 expand_string(char *label, size_t len, const char *srch, const char *repl)
988 {
989 	char *tmp;
990 	char *p, *q;
991 
992 	if ((tmp = calloc(1, len)) == NULL) {
993 		log_debug("expand_string: calloc");
994 		return (-1);
995 	}
996 	p = q = label;
997 	while ((q = strstr(p, srch)) != NULL) {
998 		*q = '\0';
999 		if ((strlcat(tmp, p, len) >= len) ||
1000 		    (strlcat(tmp, repl, len) >= len)) {
1001 			log_debug("expand_string: string too long");
1002 			return (-1);
1003 		}
1004 		q += strlen(srch);
1005 		p = q;
1006 	}
1007 	if (strlcat(tmp, p, len) >= len) {
1008 		log_debug("expand_string: string too long");
1009 		return (-1);
1010 	}
1011 	(void)strlcpy(label, tmp, len);	/* always fits */
1012 	free(tmp);
1013 
1014 	return (0);
1015 }
1016 
1017 void
1018 translate_string(char *str)
1019 {
1020 	char	*reader;
1021 	char	*writer;
1022 
1023 	reader = writer = str;
1024 
1025 	while (*reader) {
1026 		if (*reader == '\\') {
1027 			reader++;
1028 			switch (*reader) {
1029 			case 'n':
1030 				*writer++ = '\n';
1031 				break;
1032 			case 'r':
1033 				*writer++ = '\r';
1034 				break;
1035 			default:
1036 				*writer++ = *reader;
1037 			}
1038 		} else
1039 			*writer++ = *reader;
1040 		reader++;
1041 	}
1042 	*writer = '\0';
1043 }
1044 
1045 char *
1046 digeststr(enum digest_type type, const u_int8_t *data, size_t len, char *buf)
1047 {
1048 	switch (type) {
1049 	case DIGEST_SHA1:
1050 		return (SHA1Data(data, len, buf));
1051 		break;
1052 	case DIGEST_MD5:
1053 		return (MD5Data(data, len, buf));
1054 		break;
1055 	default:
1056 		break;
1057 	}
1058 	return (NULL);
1059 }
1060 
1061 const char *
1062 canonicalize_host(const char *host, char *name, size_t len)
1063 {
1064 	struct sockaddr_in	 sin4;
1065 	struct sockaddr_in6	 sin6;
1066 	u_int			 i, j;
1067 	size_t			 plen;
1068 	char			 c;
1069 
1070 	if (len < 2)
1071 		goto fail;
1072 
1073 	/*
1074 	 * Canonicalize an IPv4/6 address
1075 	 */
1076 	if (inet_pton(AF_INET, host, &sin4) == 1)
1077 		return (inet_ntop(AF_INET, &sin4, name, len));
1078 	if (inet_pton(AF_INET6, host, &sin6) == 1)
1079 		return (inet_ntop(AF_INET6, &sin6, name, len));
1080 
1081 	/*
1082 	 * Canonicalize a hostname
1083 	 */
1084 
1085 	/* 1. remove repeated dots and convert upper case to lower case */
1086 	plen = strlen(host);
1087 	bzero(name, len);
1088 	for (i = j = 0; i < plen; i++) {
1089 		if (j >= (len - 1))
1090 			goto fail;
1091 		c = tolower(host[i]);
1092 		if ((c == '.') && (j == 0 || name[j - 1] == '.'))
1093 			continue;
1094 		name[j++] = c;
1095 	}
1096 
1097 	/* 2. remove trailing dots */
1098 	for (i = j; i > 0; i--) {
1099 		if (name[i - 1] != '.')
1100 			break;
1101 		name[i - 1] = '\0';
1102 		j--;
1103 	}
1104 	if (j <= 0)
1105 		goto fail;
1106 
1107 	return (name);
1108 
1109  fail:
1110 	errno = EINVAL;
1111 	return (NULL);
1112 }
1113 
1114 struct protonode *
1115 protonode_header(enum direction dir, struct protocol *proto,
1116     struct protonode *pk)
1117 {
1118 	struct protonode	*pn;
1119 	struct proto_tree	*tree;
1120 
1121 	if (dir == RELAY_DIR_RESPONSE)
1122 		tree = &proto->response_tree;
1123 	else
1124 		tree = &proto->request_tree;
1125 
1126 	pn = RB_FIND(proto_tree, tree, pk);
1127 	if (pn != NULL)
1128 		return (pn);
1129 	if ((pn = (struct protonode *)calloc(1, sizeof(*pn))) == NULL) {
1130 		log_warn("out of memory");
1131 		return (NULL);
1132 	}
1133 	pn->key = strdup(pk->key);
1134 	if (pn->key == NULL) {
1135 		log_warn("out of memory");
1136 		return (NULL);
1137 	}
1138 	pn->value = NULL;
1139 	pn->action = NODE_ACTION_NONE;
1140 	pn->type = pk->type;
1141 	SIMPLEQ_INIT(&pn->head);
1142 	if (dir == RELAY_DIR_RESPONSE)
1143 		pn->id =
1144 		    proto->response_nodes++;
1145 	else
1146 		pn->id = proto->request_nodes++;
1147 	if (pn->id == INT_MAX) {
1148 		log_warnx("too many protocol "
1149 		    "nodes defined");
1150 		return (NULL);
1151 	}
1152 	RB_INSERT(proto_tree, tree, pn);
1153 	return (pn);
1154 }
1155 
1156 int
1157 protonode_add(enum direction dir, struct protocol *proto,
1158     struct protonode *node)
1159 {
1160 	struct protonode	*pn, *proot, pk;
1161 	struct proto_tree	*tree;
1162 
1163 	if (dir == RELAY_DIR_RESPONSE)
1164 		tree = &proto->response_tree;
1165 	else
1166 		tree = &proto->request_tree;
1167 
1168 	if ((pn = calloc(1, sizeof (*pn))) == NULL) {
1169 		log_warn("out of memory");
1170 		return (-1);
1171 	}
1172 	bcopy(node, pn, sizeof(*pn));
1173 	pn->key = node->key;
1174 	pn->value = node->value;
1175 	SIMPLEQ_INIT(&pn->head);
1176 	if (dir == RELAY_DIR_RESPONSE)
1177 		pn->id = proto->response_nodes++;
1178 	else
1179 		pn->id = proto->request_nodes++;
1180 	if (pn->id == INT_MAX) {
1181 		log_warnx("too many protocol nodes defined");
1182 		free(pn);
1183 		return (-1);
1184 	}
1185 	if ((proot =
1186 	    RB_INSERT(proto_tree, tree, pn)) != NULL) {
1187 		/*
1188 		 * A protocol node with the same key already
1189 		 * exists, append it to a queue behind the
1190 		 * existing node->
1191 		 */
1192 		if (SIMPLEQ_EMPTY(&proot->head))
1193 			SIMPLEQ_NEXT(proot, entry) = pn;
1194 		SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry);
1195 	}
1196 
1197 	if (node->type == NODE_TYPE_COOKIE)
1198 		pk.key = "Cookie";
1199 	else if (node->type == NODE_TYPE_URL)
1200 		pk.key = "Host";
1201 	else
1202 		pk.key = "GET";
1203 	if (node->type != NODE_TYPE_HEADER) {
1204 		pk.type = NODE_TYPE_HEADER;
1205 		pn = protonode_header(dir, proto, &pk);
1206 		if (pn == NULL)
1207 			return (-1);
1208 		switch (node->type) {
1209 		case NODE_TYPE_QUERY:
1210 			pn->flags |= PNFLAG_LOOKUP_QUERY;
1211 			break;
1212 		case NODE_TYPE_COOKIE:
1213 			pn->flags |= PNFLAG_LOOKUP_COOKIE;
1214 			break;
1215 		case NODE_TYPE_URL:
1216 			if (node->flags &
1217 			    PNFLAG_LOOKUP_URL_DIGEST)
1218 				pn->flags |= node->flags &
1219 				    PNFLAG_LOOKUP_URL_DIGEST;
1220 			else
1221 				pn->flags |=
1222 				    PNFLAG_LOOKUP_DIGEST(0);
1223 			break;
1224 		default:
1225 			break;
1226 		}
1227 	}
1228 
1229 	return (0);
1230 }
1231 
1232 int
1233 protonode_load(enum direction dir, struct protocol *proto,
1234     struct protonode *node, const char *name)
1235 {
1236 	FILE			*fp;
1237 	char			 buf[BUFSIZ];
1238 	int			 ret = -1;
1239 	struct protonode	 pn;
1240 
1241 	bcopy(node, &pn, sizeof(pn));
1242 	pn.key = pn.value = NULL;
1243 
1244 	if ((fp = fopen(name, "r")) == NULL)
1245 		return (-1);
1246 
1247 	while (fgets(buf, sizeof(buf), fp) != NULL) {
1248 		/* strip whitespace and newline characters */
1249 		buf[strcspn(buf, "\r\n\t ")] = '\0';
1250 		if (!strlen(buf) || buf[0] == '#')
1251 			continue;
1252 		pn.key = strdup(buf);
1253 		if (node->value != NULL)
1254 			pn.value = strdup(node->value);
1255 		if (pn.key == NULL ||
1256 		    (node->value != NULL && pn.value == NULL))
1257 			goto fail;
1258 		if (protonode_add(dir, proto, &pn) == -1)
1259 			goto fail;
1260 		pn.key = pn.value = NULL;
1261 	}
1262 
1263 	ret = 0;
1264  fail:
1265 	if (pn.key != NULL)
1266 		free(pn.key);
1267 	if (pn.value != NULL)
1268 		free(pn.value);
1269 	fclose(fp);
1270 	return (ret);
1271 }
1272 
1273 int
1274 bindany(struct ctl_bindany *bnd)
1275 {
1276 	int	s, v;
1277 
1278 	s = -1;
1279 	v = 1;
1280 
1281 	if (relay_socket_af(&bnd->bnd_ss, bnd->bnd_port) == -1)
1282 		goto fail;
1283 	if ((s = socket(bnd->bnd_ss.ss_family,
1284 	    bnd->bnd_proto == IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM,
1285 	    bnd->bnd_proto)) == -1)
1286 		goto fail;
1287 	if (setsockopt(s, SOL_SOCKET, SO_BINDANY,
1288 	    &v, sizeof(v)) == -1)
1289 		goto fail;
1290 	if (bind(s, (struct sockaddr *)&bnd->bnd_ss,
1291 	    bnd->bnd_ss.ss_len) == -1)
1292 		goto fail;
1293 
1294 	return (s);
1295 
1296  fail:
1297 	if (s != -1)
1298 		close(s);
1299 	return (-1);
1300 }
1301 
1302 int
1303 map6to4(struct sockaddr_storage *in6)
1304 {
1305 	struct sockaddr_storage	 out4;
1306 	struct sockaddr_in	*sin4 = (struct sockaddr_in *)&out4;
1307 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)in6;
1308 
1309 	bzero(sin4, sizeof(*sin4));
1310 	sin4->sin_len = sizeof(*sin4);
1311 	sin4->sin_family = AF_INET;
1312 	sin4->sin_port = sin6->sin6_port;
1313 
1314 	bcopy(&sin6->sin6_addr.s6_addr[12], &sin4->sin_addr.s_addr,
1315 	    sizeof(sin4->sin_addr));
1316 
1317 	if (sin4->sin_addr.s_addr == INADDR_ANY ||
1318 	    sin4->sin_addr.s_addr == INADDR_BROADCAST ||
1319 	    IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)))
1320 		return (-1);
1321 
1322 	bcopy(&out4, in6, sizeof(*in6));
1323 
1324 	return (0);
1325 }
1326 
1327 int
1328 map4to6(struct sockaddr_storage *in4, struct sockaddr_storage *map)
1329 {
1330 	struct sockaddr_storage	 out6;
1331 	struct sockaddr_in	*sin4 = (struct sockaddr_in *)in4;
1332 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)&out6;
1333 	struct sockaddr_in6	*map6 = (struct sockaddr_in6 *)map;
1334 
1335 	if (sin4->sin_addr.s_addr == INADDR_ANY ||
1336 	    sin4->sin_addr.s_addr == INADDR_BROADCAST ||
1337 	    IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)))
1338 		return (-1);
1339 
1340 	bcopy(map6, sin6, sizeof(*sin6));
1341 	sin6->sin6_len = sizeof(*sin6);
1342 	sin6->sin6_family = AF_INET6;
1343 	sin6->sin6_port = sin4->sin_port;
1344 
1345 	bcopy(&sin4->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12],
1346 	    sizeof(sin4->sin_addr));
1347 
1348 	bcopy(&out6, in4, sizeof(*in4));
1349 
1350 	return (0);
1351 }
1352