xref: /openbsd-src/sbin/iked/config.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: config.c,v 1.15 2012/07/02 13:03:24 mikeb Exp $	*/
2 /*	$vantronix: config.c,v 1.30 2010/05/28 15:34:35 reyk Exp $	*/
3 
4 /*
5  * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net>
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/param.h>
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 #include <sys/wait.h>
24 #include <sys/socket.h>
25 #include <sys/uio.h>
26 
27 #include <net/if.h>
28 #include <netinet/in_systm.h>
29 #include <netinet/in.h>
30 #include <netinet/ip.h>
31 #include <netinet/tcp.h>
32 #include <arpa/inet.h>
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <getopt.h>
39 #include <signal.h>
40 #include <errno.h>
41 #include <err.h>
42 #include <pwd.h>
43 #include <event.h>
44 
45 #include "iked.h"
46 #include "ikev2.h"
47 
48 struct iked_sa *
49 config_new_sa(struct iked *env, int initiator)
50 {
51 	struct iked_sa	*sa;
52 
53 	if ((sa = calloc(1, sizeof(*sa))) == NULL)
54 		return (NULL);
55 
56 	TAILQ_INIT(&sa->sa_proposals);
57 	TAILQ_INIT(&sa->sa_childsas);
58 	TAILQ_INIT(&sa->sa_flows);
59 	TAILQ_INIT(&sa->sa_requests);
60 	TAILQ_INIT(&sa->sa_responses);
61 	sa->sa_hdr.sh_initiator = initiator;
62 	sa->sa_type = IKED_SATYPE_LOCAL;
63 
64 	if (initiator)
65 		sa->sa_hdr.sh_ispi = config_getspi();
66 	else
67 		sa->sa_hdr.sh_rspi = config_getspi();
68 
69 	gettimeofday(&sa->sa_timecreated, NULL);
70 	memcpy(&sa->sa_timeused, &sa->sa_timecreated, sizeof(sa->sa_timeused));
71 
72 	return (sa);
73 }
74 
75 u_int64_t
76 config_getspi(void)
77 {
78 	u_int64_t	 spi;
79 
80 	spi = ((u_int64_t)arc4random() << 32) | arc4random();
81 	if (spi == 0)
82 		return (config_getspi());
83 
84 	return (spi);
85 }
86 
87 void
88 config_free_sa(struct iked *env, struct iked_sa *sa)
89 {
90 	(void)RB_REMOVE(iked_sas, &env->sc_sas, sa);
91 
92 	timer_deregister(env, &sa->sa_timer);
93 
94 	config_free_proposals(&sa->sa_proposals, 0);
95 	config_free_childsas(env, &sa->sa_childsas, NULL, NULL);
96 	sa_free_flows(env, &sa->sa_flows);
97 
98 	if (sa->sa_policy) {
99 		(void)RB_REMOVE(iked_sapeers, &sa->sa_policy->pol_sapeers, sa);
100 		policy_unref(env, sa->sa_policy);
101 	}
102 
103 	ikev2_msg_flushqueue(env, &sa->sa_requests);
104 	ikev2_msg_flushqueue(env, &sa->sa_responses);
105 
106 	ibuf_release(sa->sa_inonce);
107 	ibuf_release(sa->sa_rnonce);
108 
109 	if (sa->sa_dhgroup != NULL)
110 		group_free(sa->sa_dhgroup);
111 	ibuf_release(sa->sa_dhiexchange);
112 	ibuf_release(sa->sa_dhrexchange);
113 
114 	hash_free(sa->sa_prf);
115 	hash_free(sa->sa_integr);
116 	cipher_free(sa->sa_encr);
117 
118 	ibuf_release(sa->sa_key_d);
119 	ibuf_release(sa->sa_key_iauth);
120 	ibuf_release(sa->sa_key_rauth);
121 	ibuf_release(sa->sa_key_iencr);
122 	ibuf_release(sa->sa_key_rencr);
123 	ibuf_release(sa->sa_key_iprf);
124 	ibuf_release(sa->sa_key_rprf);
125 
126 	ibuf_release(sa->sa_1stmsg);
127 	ibuf_release(sa->sa_2ndmsg);
128 
129 	ibuf_release(sa->sa_iid.id_buf);
130 	ibuf_release(sa->sa_rid.id_buf);
131 	ibuf_release(sa->sa_icert.id_buf);
132 	ibuf_release(sa->sa_rcert.id_buf);
133 
134 	ibuf_release(sa->sa_eap.id_buf);
135 	if (sa->sa_eapid != NULL)
136 		free(sa->sa_eapid);
137 	ibuf_release(sa->sa_eapmsk);
138 
139 	free(sa);
140 }
141 
142 struct iked_policy *
143 config_new_policy(struct iked *env)
144 {
145 	struct iked_policy	*pol;
146 
147 	if ((pol = calloc(1, sizeof(*pol))) == NULL)
148 		return (NULL);
149 
150 	TAILQ_INIT(&pol->pol_proposals);
151 	RB_INIT(&pol->pol_sapeers);
152 
153 	return (pol);
154 }
155 
156 void
157 config_free_policy(struct iked *env, struct iked_policy *pol)
158 {
159 	struct iked_sa		*sa;
160 
161 	if (pol->pol_flags & IKED_POLICY_REFCNT)
162 		goto remove;
163 
164 	TAILQ_REMOVE(&env->sc_policies, pol, pol_entry);
165 
166 	RB_FOREACH(sa, iked_sapeers, &pol->pol_sapeers) {
167 		/* Remove from the policy tree, but keep for existing SAs */
168 		if (sa->sa_policy == pol)
169 			policy_ref(env, pol);
170 	}
171 
172 	if (pol->pol_refcnt)
173 		return;
174 
175  remove:
176 	config_free_proposals(&pol->pol_proposals, 0);
177 	config_free_flows(env, &pol->pol_flows);
178 	free(pol);
179 }
180 
181 struct iked_proposal *
182 config_add_proposal(struct iked_proposals *head, u_int id, u_int proto)
183 {
184 	struct iked_proposal	*pp;
185 
186 	TAILQ_FOREACH(pp, head, prop_entry) {
187 		if (pp->prop_protoid == proto &&
188 		    pp->prop_id == id)
189 			return (pp);
190 	}
191 
192 	if ((pp = calloc(1, sizeof(*pp))) == NULL)
193 		return (NULL);
194 
195 	pp->prop_protoid = proto;
196 	pp->prop_id = id;
197 
198 	TAILQ_INSERT_TAIL(head, pp, prop_entry);
199 
200 	return (pp);
201 }
202 
203 void
204 config_free_proposals(struct iked_proposals *head, u_int proto)
205 {
206 	struct iked_proposal	*prop, *next;
207 
208 	for (prop = TAILQ_FIRST(head); prop != NULL; prop = next) {
209 		next = TAILQ_NEXT(prop, prop_entry);
210 
211 		/* Free any proposal or only selected SA proto */
212 		if (proto != 0 && prop->prop_protoid != proto)
213 			continue;
214 
215 		log_debug("%s: free %p", __func__, prop);
216 
217 		TAILQ_REMOVE(head, prop, prop_entry);
218 		if (prop->prop_nxforms)
219 			free(prop->prop_xforms);
220 		free(prop);
221 	}
222 }
223 
224 void
225 config_free_flows(struct iked *env, struct iked_flows *head)
226 {
227 	struct iked_flow	*flow, *next;
228 
229 	for (flow = RB_MIN(iked_flows, head); flow != NULL; flow = next) {
230 		next = RB_NEXT(iked_flows, head, flow);
231 		log_debug("%s: free %p", __func__, flow);
232 		RB_REMOVE(iked_flows, head, flow);
233 		flow_free(flow);
234 	}
235 }
236 
237 void
238 config_free_childsas(struct iked *env, struct iked_childsas *head,
239     struct iked_spi *peerspi, struct iked_spi *localspi)
240 {
241 	struct iked_childsa	*csa, *nextcsa;
242 
243 	if (localspi != NULL)
244 		bzero(localspi, sizeof(*localspi));
245 
246 	for (csa = TAILQ_FIRST(head); csa != NULL; csa = nextcsa) {
247 		nextcsa = TAILQ_NEXT(csa, csa_entry);
248 
249 		if (peerspi != NULL) {
250 			/* Only delete matching peer SPIs */
251 			if (peerspi->spi != csa->csa_peerspi)
252 				continue;
253 
254 			/* Store assigned local SPI */
255 			if (localspi != NULL && localspi->spi == 0)
256 				memcpy(localspi, &csa->csa_spi,
257 				    sizeof(*localspi));
258 		}
259 		log_debug("%s: free %p", __func__, csa);
260 
261 		TAILQ_REMOVE(head, csa, csa_entry);
262 		if (csa->csa_loaded) {
263 			RB_REMOVE(iked_activesas, &env->sc_activesas, csa);
264 			(void)pfkey_sa_delete(env->sc_pfkey, csa);
265 		}
266 		childsa_free(csa);
267 	}
268 }
269 
270 struct iked_transform *
271 config_add_transform(struct iked_proposal *prop, u_int type,
272     u_int id, u_int length, u_int keylength)
273 {
274 	struct iked_transform	*xform;
275 	struct iked_constmap	*map = NULL;
276 	int			 score = 1;
277 	u_int			 i;
278 
279 	switch (type) {
280 	case IKEV2_XFORMTYPE_ENCR:
281 		map = ikev2_xformencr_map;
282 		break;
283 	case IKEV2_XFORMTYPE_PRF:
284 		map = ikev2_xformprf_map;
285 		break;
286 	case IKEV2_XFORMTYPE_INTEGR:
287 		map = ikev2_xformauth_map;
288 		break;
289 	case IKEV2_XFORMTYPE_DH:
290 		map = ikev2_xformdh_map;
291 		break;
292 	case IKEV2_XFORMTYPE_ESN:
293 		map = ikev2_xformesn_map;
294 		break;
295 	default:
296 		log_debug("%s: invalid transform type %d", __func__, type);
297 		return (NULL);
298 	}
299 
300 	for (i = 0; i < prop->prop_nxforms; i++) {
301 		xform = prop->prop_xforms + i;
302 		if (xform->xform_type == type &&
303 		    xform->xform_id == id &&
304 		    xform->xform_length == length)
305 			return (xform);
306 	}
307 
308 	for (i = 0; i < prop->prop_nxforms; i++) {
309 		xform = prop->prop_xforms + i;
310 		if (xform->xform_type == type) {
311 			switch (type) {
312 			case IKEV2_XFORMTYPE_ENCR:
313 			case IKEV2_XFORMTYPE_INTEGR:
314 				score += 3;
315 				break;
316 			case IKEV2_XFORMTYPE_DH:
317 				score += 2;
318 				break;
319 			default:
320 				score += 1;
321 				break;
322 			}
323 		}
324 	}
325 
326 	if ((xform = realloc(prop->prop_xforms,
327 	    (prop->prop_nxforms + 1) * sizeof(*xform))) == NULL) {
328 		return (NULL);
329 	}
330 
331 	prop->prop_xforms = xform;
332 	xform = prop->prop_xforms + prop->prop_nxforms++;
333 	bzero(xform, sizeof(*xform));
334 
335 	xform->xform_type = type;
336 	xform->xform_id = id;
337 	xform->xform_length = length;
338 	xform->xform_keylength = keylength;
339 	xform->xform_score = score;
340 	xform->xform_map = map;
341 
342 	return (xform);
343 }
344 
345 struct iked_transform *
346 config_findtransform(struct iked_proposals *props, u_int8_t type)
347 {
348 	struct iked_proposal	*prop;
349 	struct iked_transform	*xform;
350 	u_int			 i;
351 
352 	/* Search of the first transform with the desired type */
353 	TAILQ_FOREACH(prop, props, prop_entry) {
354 		for (i = 0; i < prop->prop_nxforms; i++) {
355 			xform = prop->prop_xforms + i;
356 			if (xform->xform_type == type)
357 				return (xform);
358 		}
359 	}
360 
361 	return (NULL);
362 }
363 
364 struct iked_user *
365 config_new_user(struct iked *env, struct iked_user *new)
366 {
367 	struct iked_user	*usr, *old;
368 
369 	if ((usr = calloc(1, sizeof(*usr))) == NULL)
370 		return (NULL);
371 
372 	memcpy(usr, new, sizeof(*usr));
373 
374 	if ((old = RB_INSERT(iked_users, &env->sc_users, usr)) != NULL) {
375 		/* Update the password of an existing user*/
376 		memcpy(old, new, sizeof(*old));
377 
378 		log_debug("%s: updating user %s", __func__, usr->usr_name);
379 		free(usr);
380 
381 		return (old);
382 	}
383 
384 	log_debug("%s: inserting new user %s", __func__, usr->usr_name);
385 	return (usr);
386 }
387 
388 /*
389  * Inter-process communication of configuration items.
390  */
391 
392 int
393 config_setcoupled(struct iked *env, u_int couple)
394 {
395 	u_int	 type;
396 
397 	type = couple ? IMSG_CTL_COUPLE : IMSG_CTL_DECOUPLE;
398 	proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0);
399 	proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0);
400 
401 	return (0);
402 }
403 
404 int
405 config_getcoupled(struct iked *env, u_int type)
406 {
407 	return (pfkey_couple(env->sc_pfkey, &env->sc_sas,
408 	    type == IMSG_CTL_COUPLE ? 1 : 0));
409 }
410 
411 int
412 config_setmode(struct iked *env, u_int passive)
413 {
414 	u_int	 type;
415 
416 	type = passive ? IMSG_CTL_PASSIVE : IMSG_CTL_ACTIVE;
417 	proc_compose_imsg(env, PROC_IKEV1, type, -1, NULL, 0);
418 	proc_compose_imsg(env, PROC_IKEV2, type, -1, NULL, 0);
419 
420 	return (0);
421 }
422 
423 int
424 config_getmode(struct iked *env, u_int type)
425 {
426 	u_int8_t	 old;
427 	u_char		*mode[] = { "active", "passive" };
428 
429 	old = env->sc_passive ? 1 : 0;
430 	env->sc_passive = type == IMSG_CTL_PASSIVE ? 1 : 0;
431 
432 	if (old == env->sc_passive)
433 		return (0);
434 
435 	log_debug("%s: mode %s -> %s", __func__,
436 	    mode[old], mode[env->sc_passive]);
437 
438 	return (0);
439 }
440 
441 int
442 config_setreset(struct iked *env, u_int mode, enum privsep_procid id)
443 {
444 	proc_compose_imsg(env, id, IMSG_CTL_RESET, -1, &mode, sizeof(mode));
445 	return (0);
446 }
447 
448 int
449 config_getreset(struct iked *env, struct imsg *imsg)
450 {
451 	struct iked_policy	*pol, *nextpol;
452 	struct iked_sa		*sa, *nextsa;
453 	struct iked_user	*usr, *nextusr;
454 	u_int			 mode;
455 
456 	IMSG_SIZE_CHECK(imsg, &mode);
457 	memcpy(&mode, imsg->data, sizeof(mode));
458 
459 	if (mode == RESET_ALL || mode == RESET_POLICY) {
460 		log_debug("%s: flushing policies", __func__);
461 		for (pol = TAILQ_FIRST(&env->sc_policies);
462 		    pol != NULL; pol = nextpol) {
463 			nextpol = TAILQ_NEXT(pol, pol_entry);
464 			config_free_policy(env, pol);
465 		}
466 	}
467 
468 	if (mode == RESET_ALL || mode == RESET_SA) {
469 		log_debug("%s: flushing SAs", __func__);
470 		for (sa = RB_MIN(iked_sas, &env->sc_sas);
471 		    sa != NULL; sa = nextsa) {
472 			nextsa = RB_NEXT(iked_sas, &env->sc_sas, sa);
473 			config_free_sa(env, sa);
474 		}
475 	}
476 
477 	if (mode == RESET_ALL || mode == RESET_USER) {
478 		log_debug("%s: flushing users", __func__);
479 		for (usr = RB_MIN(iked_users, &env->sc_users);
480 		    usr != NULL; usr = nextusr) {
481 			nextusr = RB_NEXT(iked_users, &env->sc_users, usr);
482 			RB_REMOVE(iked_users, &env->sc_users, usr);
483 			free(usr);
484 		}
485 	}
486 
487 	return (0);
488 }
489 
490 int
491 config_setsocket(struct iked *env, struct sockaddr_storage *ss,
492     in_port_t port, enum privsep_procid id)
493 {
494 	int	 s;
495 
496 	if ((s = udp_bind((struct sockaddr *)ss, port)) == -1)
497 		return (-1);
498 	proc_compose_imsg(env, id, IMSG_UDP_SOCKET, s,
499 	    ss, sizeof(*ss));
500 	return (0);
501 }
502 
503 int
504 config_getsocket(struct iked *env, struct imsg *imsg,
505     void (*cb)(int, short, void *))
506 {
507 	struct iked_socket	*sock, **sptr;
508 
509 	log_debug("%s: received socket fd %d", __func__, imsg->fd);
510 
511 	if ((sock = calloc(1, sizeof(*sock))) == NULL)
512 		fatal("config_getsocket: calloc");
513 
514 	IMSG_SIZE_CHECK(imsg, &sock->sock_addr);
515 
516 	memcpy(&sock->sock_addr, imsg->data, sizeof(sock->sock_addr));
517 	sock->sock_fd = imsg->fd;
518 	sock->sock_env = env;
519 
520 	switch (sock->sock_addr.ss_family) {
521 	case AF_INET:
522 		sptr = &env->sc_sock4;
523 		break;
524 	case AF_INET6:
525 		sptr = &env->sc_sock6;
526 		break;
527 	default:
528 		fatal("config_getsocket: socket af");
529 		/* NOTREACHED */
530 	}
531 	if (*sptr == NULL)
532 		*sptr = sock;
533 
534 	event_set(&sock->sock_ev, sock->sock_fd,
535 	    EV_READ|EV_PERSIST, cb, sock);
536 	event_add(&sock->sock_ev, NULL);
537 
538 	return (0);
539 }
540 
541 int
542 config_setpfkey(struct iked *env, enum privsep_procid id)
543 {
544 	int	 s;
545 
546 	if ((s = pfkey_socket()) == -1)
547 		return (-1);
548 	proc_compose_imsg(env, id, IMSG_PFKEY_SOCKET, s, NULL, 0);
549 	return (0);
550 }
551 
552 int
553 config_getpfkey(struct iked *env, struct imsg *imsg)
554 {
555 	log_debug("%s: received pfkey fd %d", __func__, imsg->fd);
556 	pfkey_init(env, imsg->fd);
557 	return (0);
558 }
559 
560 int
561 config_setuser(struct iked *env, struct iked_user *usr, enum privsep_procid id)
562 {
563 	if (env->sc_opts & IKED_OPT_NOACTION) {
564 		print_user(usr);
565 		return (0);
566 	}
567 
568 	proc_compose_imsg(env, id, IMSG_CFG_USER, -1, usr, sizeof(*usr));
569 	return (0);
570 }
571 
572 int
573 config_getuser(struct iked *env, struct imsg *imsg)
574 {
575 	struct iked_user	 usr;
576 
577 	IMSG_SIZE_CHECK(imsg, &usr);
578 	memcpy(&usr, imsg->data, sizeof(usr));
579 
580 	if (config_new_user(env, &usr) == NULL)
581 		return (-1);
582 
583 	print_user(&usr);
584 
585 	return (0);
586 }
587 
588 int
589 config_setpolicy(struct iked *env, struct iked_policy *pol,
590     enum privsep_procid id)
591 {
592 	struct iked_proposal	*prop;
593 	struct iked_flow	*flow;
594 	struct iked_transform	*xform;
595 	size_t			 size, iovcnt, j, c = 0;
596 	struct iovec		 iov[IOV_MAX];
597 
598 	iovcnt = 1;
599 	size = sizeof(*pol);
600 	TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) {
601 		size += (prop->prop_nxforms * sizeof(*xform)) +
602 		    (sizeof(*prop));
603 		iovcnt += prop->prop_nxforms + 1;
604 	}
605 
606 	size += pol->pol_nflows * sizeof(*flow);
607 	iovcnt += pol->pol_nflows;
608 
609 	if (iovcnt > IOV_MAX) {
610 		log_warn("%s: too many proposals/flows", __func__);
611 		return (-1);
612 	}
613 
614 	iov[c].iov_base = pol;
615 	iov[c++].iov_len = sizeof(*pol);
616 
617 	TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry) {
618 		iov[c].iov_base = prop;
619 		iov[c++].iov_len = sizeof(*prop);
620 
621 		for (j = 0; j < prop->prop_nxforms; j++) {
622 			xform = prop->prop_xforms + j;
623 
624 			iov[c].iov_base = xform;
625 			iov[c++].iov_len = sizeof(*xform);
626 		}
627 	}
628 
629 	RB_FOREACH(flow, iked_flows, &pol->pol_flows) {
630 		iov[c].iov_base = flow;
631 		iov[c++].iov_len = sizeof(*flow);
632 	}
633 
634 	if (env->sc_opts & IKED_OPT_NOACTION) {
635 		print_policy(pol);
636 		return (0);
637 	}
638 
639 	if (proc_composev_imsg(env, id, IMSG_CFG_POLICY, -1,
640 	    iov, iovcnt) == -1)
641 		return (-1);
642 
643 	return (0);
644 }
645 
646 int
647 config_getpolicy(struct iked *env, struct imsg *imsg)
648 {
649 	struct iked_policy	*pol;
650 	struct iked_proposal	 pp, *prop;
651 	struct iked_transform	 xf, *xform;
652 	struct iked_flow	*flow;
653 	off_t			 offset = 0;
654 	u_int			 i, j;
655 	u_int8_t		*buf = (u_int8_t *)imsg->data;
656 
657 	IMSG_SIZE_CHECK(imsg, pol);
658 	log_debug("%s: received policy", __func__);
659 
660 	if ((pol = config_new_policy(NULL)) == NULL)
661 		fatal("config_getpolicy: new policy");
662 
663 	memcpy(pol, buf, sizeof(*pol));
664 	offset += sizeof(*pol);
665 
666 	TAILQ_INIT(&pol->pol_proposals);
667 	RB_INIT(&pol->pol_flows);
668 
669 	for (i = 0; i < pol->pol_nproposals; i++) {
670 		memcpy(&pp, buf + offset, sizeof(pp));
671 		offset += sizeof(pp);
672 
673 		if ((prop = config_add_proposal(&pol->pol_proposals,
674 		    pp.prop_id, pp.prop_protoid)) == NULL)
675 			fatal("config_getpolicy: add proposal");
676 
677 		for (j = 0; j < pp.prop_nxforms; j++) {
678 			memcpy(&xf, buf + offset, sizeof(xf));
679 			offset += sizeof(xf);
680 
681 			if ((xform = config_add_transform(prop, xf.xform_type,
682 			    xf.xform_id, xf.xform_length,
683 			    xf.xform_keylength)) == NULL)
684 				fatal("config_getpolicy: add transform");
685 		}
686 	}
687 
688 	for (i = 0; i < pol->pol_nflows; i++) {
689 		if ((flow = calloc(1, sizeof(*flow))) == NULL)
690 			fatal("config_getpolicy: new flow");
691 
692 		memcpy(flow, buf + offset, sizeof(*flow));
693 		offset += sizeof(*flow);
694 
695 		RB_INSERT(iked_flows, &pol->pol_flows, flow);
696 	}
697 
698 	TAILQ_INSERT_TAIL(&env->sc_policies, pol, pol_entry);
699 
700 	if (pol->pol_flags & IKED_POLICY_DEFAULT) {
701 		/* Only one default policy, just free/unref the old one */
702 		if (env->sc_defaultcon != NULL)
703 			config_free_policy(env, env->sc_defaultcon);
704 		env->sc_defaultcon = pol;
705 	}
706 
707 	print_policy(pol);
708 
709 	return (0);
710 }
711 
712 int
713 config_setcompile(struct iked *env, enum privsep_procid id)
714 {
715 	if (env->sc_opts & IKED_OPT_NOACTION)
716 		return (0);
717 
718 	proc_compose_imsg(env, id, IMSG_COMPILE, -1, NULL, 0);
719 	return (0);
720 }
721 
722 int
723 config_getcompile(struct iked *env, struct imsg *imsg)
724 {
725 	/*
726 	 * Do any necessary steps after configuration, for now we
727 	 * only need to compile the skip steps.
728 	 */
729 	policy_calc_skip_steps(&env->sc_policies);
730 
731 	log_debug("%s: compilation done", __func__);
732 	return (0);
733 }
734