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