xref: /openbsd/sbin/ipsecctl/ipsecctl.c (revision 73471bf0)
1 /*	$OpenBSD: ipsecctl.c,v 1.84 2018/09/07 12:43:30 kn Exp $	*/
2 /*
3  * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/socket.h>
19 #include <sys/sysctl.h>
20 #include <sys/queue.h>
21 #include <sys/stat.h>
22 #include <net/pfkeyv2.h>
23 #include <net/route.h>
24 #include <netinet/in.h>
25 #include <netinet/ip_ipsp.h>
26 #include <arpa/inet.h>
27 
28 #include <assert.h>
29 #include <err.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <netdb.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 #include "ipsecctl.h"
39 #include "pfkey.h"
40 
41 int		 ipsecctl_rules(char *, int);
42 FILE		*ipsecctl_fopen(const char *, const char *);
43 int		 ipsecctl_commit(int, struct ipsecctl *);
44 int		 ipsecctl_add_rule(struct ipsecctl *, struct ipsec_rule *);
45 void		 ipsecctl_free_rule(struct ipsec_rule *);
46 int		 ipsecctl_merge_rules(struct ipsec_rule *, struct ipsec_rule *);
47 int		 ipsecctl_cmp_ident(struct ipsec_rule *, struct ipsec_rule *);
48 int		 ipsecctl_rule_matchsrc(struct ipsec_rule *,
49 		     struct ipsec_addr_wrap *);
50 int		 ipsecctl_rule_matchdst(struct ipsec_rule *,
51 		     struct ipsec_addr_wrap *);
52 void		 ipsecctl_print_addr(struct ipsec_addr_wrap *);
53 void		 ipsecctl_print_proto(u_int8_t);
54 void		 ipsecctl_print_port(u_int16_t, const char *);
55 void		 ipsecctl_print_key(struct ipsec_key *);
56 void		 ipsecctl_print_flow(struct ipsec_rule *, int);
57 void		 ipsecctl_print_sa(struct ipsec_rule *, int);
58 void		 ipsecctl_print_sabundle(struct ipsec_rule *, int);
59 int		 ipsecctl_flush(int);
60 void		 ipsecctl_get_rules(struct ipsecctl *);
61 void		 ipsecctl_print_title(char *);
62 void		 ipsecctl_show_flows(int);
63 void		 ipsecctl_show_sas(int);
64 int		 ipsecctl_monitor(int);
65 void		 usage(void);
66 const char	*ipsecctl_lookup_option(char *, const char **);
67 static int	 unmask(struct ipsec_addr *);
68 int		 sacompare(const void *, const void *);
69 
70 const char	*showopt;
71 char		*isakmpd_fifo = "/var/run/isakmpd.fifo";
72 
73 int		 first_title = 1;
74 
75 static const char *showopt_list[] = {
76 	"flow", "sa", "all", NULL
77 };
78 
79 static const char *direction[] = {"?", "in", "out"};
80 static const char *flowtype[] = {"?", "use", "acquire", "require", "deny",
81     "bypass", "dontacq"};
82 static const char *satype[] = {"?", "esp", "ah", "ipcomp", "tcpmd5", "ipip"};
83 static const char *tmode[] = {"?", "transport", "tunnel"};
84 static const char *auth[] = {"?", "psk", "rsa"};
85 
86 struct sad {
87 	struct sadb_msg	*sad_msg;
88 	u_int32_t	 sad_spi;
89 };
90 
91 int
92 sacompare(const void *va, const void *vb)
93 {
94 	const struct sad *a = va, *b = vb;
95 
96 	if (a->sad_spi < b->sad_spi)
97 		return (-1);
98 	if (a->sad_spi > b->sad_spi)
99 		return (1);
100 	return (0);
101 }
102 
103 int
104 ipsecctl_rules(char *filename, int opts)
105 {
106 	struct ipsecctl		 ipsec;
107 	struct ipsec_rule	*rp;
108 	int			 action, error = 0;
109 
110 	bzero(&ipsec, sizeof(ipsec));
111 	ipsec.opts = opts;
112 	TAILQ_INIT(&ipsec.rule_queue);
113 	TAILQ_INIT(&ipsec.bundle_queue);
114 
115 	if (parse_rules(filename, &ipsec) < 0) {
116 		warnx("Syntax error in config file: ipsec rules not loaded");
117 		error = 1;
118 	} else {
119 		if (opts & IPSECCTL_OPT_DELETE)
120 			action = ACTION_DELETE;
121 		else
122 			action = ACTION_ADD;
123 
124 		if ((opts & IPSECCTL_OPT_NOACTION) == 0)
125 			error = ipsecctl_commit(action, &ipsec);
126 
127 	}
128 
129 	/* This also frees the rules in ipsec.bundle_queue. */
130 	while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) {
131 		TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry);
132 		ipsecctl_free_rule(rp);
133 	}
134 
135 	return (error);
136 }
137 
138 FILE *
139 ipsecctl_fopen(const char *name, const char *mode)
140 {
141 	struct stat	 st;
142 	FILE		*fp;
143 
144 	fp = fopen(name, mode);
145 	if (fp == NULL)
146 		return (NULL);
147 
148 	if (fstat(fileno(fp), &st)) {
149 		fclose(fp);
150 		return (NULL);
151 	}
152 	if (S_ISDIR(st.st_mode)) {
153 		fclose(fp);
154 		errno = EISDIR;
155 		return (NULL);
156 	}
157 	return (fp);
158 }
159 
160 int
161 ipsecctl_commit(int action, struct ipsecctl *ipsec)
162 {
163 	struct ipsec_rule	*rp;
164 	int			 ret = 0;
165 
166 	if (pfkey_init() == -1)
167 		errx(1, "ipsecctl_commit: failed to open PF_KEY socket");
168 
169 	TAILQ_FOREACH(rp, &ipsec->rule_queue, rule_entry) {
170 		if (rp->type & RULE_IKE) {
171 			if (ike_ipsec_establish(action, rp, isakmpd_fifo) ==
172 			    -1) {
173 				warnx("failed to %s ike rule %d",
174 				    action == ACTION_DELETE ? "delete" : "add",
175 				    rp->nr);
176 				ret = 2;
177 			}
178 		} else {
179 			if (pfkey_ipsec_establish(action, rp) == -1) {
180 				warnx("failed to %s rule %d",
181 				    action == ACTION_DELETE ? "delete" : "add",
182 				    rp->nr);
183 				ret = 2;
184 			}
185 		}
186 	}
187 
188 	return (ret);
189 }
190 
191 int
192 ipsecctl_add_rule(struct ipsecctl *ipsec, struct ipsec_rule *r)
193 {
194 	TAILQ_INSERT_TAIL(&ipsec->rule_queue, r, rule_entry);
195 
196 	if ((ipsec->opts & IPSECCTL_OPT_VERBOSE) && !(ipsec->opts &
197 	    IPSECCTL_OPT_SHOW))
198 		ipsecctl_print_rule(r, ipsec->opts);
199 
200 	return (0);
201 }
202 
203 void
204 ipsecctl_free_rule(struct ipsec_rule *rp)
205 {
206 	if (rp->src) {
207 		free(rp->src->name);
208 		free(rp->src);
209 	}
210 	if (rp->dst) {
211 		free(rp->dst->name);
212 		free(rp->dst);
213 	}
214 	if (rp->dst2) {
215 		free(rp->dst2->name);
216 		free(rp->dst2);
217 	}
218 	if (rp->local) {
219 		free(rp->local->name);
220 		free(rp->local);
221 	}
222 	if (rp->peer) {
223 		free(rp->peer->name);
224 		free(rp->peer);
225 	}
226 	if (rp->auth) {
227 		free(rp->auth->srcid);
228 		free(rp->auth->dstid);
229 		free(rp->auth);
230 	}
231 	if (rp->ikeauth) {
232 		free(rp->ikeauth->string);
233 		free(rp->ikeauth);
234 	}
235 	free(rp->xfs);
236 	free(rp->p1xfs);
237 	free(rp->p2xfs);
238 	free(rp->p1life);
239 	free(rp->p2life);
240 	if (rp->authkey) {
241 		free(rp->authkey->data);
242 		free(rp->authkey);
243 	}
244 	if (rp->enckey) {
245 		free(rp->enckey->data);
246 		free(rp->enckey);
247 	}
248 	free(rp->p1name);
249 	free(rp->p2name);
250 	free(rp->p2lid);
251 	free(rp->p2nid);
252 	free(rp->p2rid);
253 	free(rp);
254 }
255 
256 /*
257  * Merge two flow rules if they match.
258  *
259  * Return 0 if ``from'' has been merged into ``to'', -1 otherwise.
260  */
261 int
262 ipsecctl_merge_rules(struct ipsec_rule *to, struct ipsec_rule *from)
263 {
264 	int match = 0;
265 
266 	assert((to->type & RULE_FLOW) && (from->type & RULE_FLOW));
267 
268 	if ((to->satype != from->satype) ||
269 	    (to->direction != from->direction) ||
270 	    (to->sport != from->sport) ||
271 	    (to->dport != from->dport) ||
272 	    (to->proto != from->proto))
273 		return (-1);
274 
275 	if (to->local != NULL || from->local != NULL) {
276 		if ((to->local == NULL) || (from->local == NULL) ||
277 		    memcmp(to->local, from->local, sizeof(*to->local)))
278 			return (-1);
279 	}
280 
281 	if (to->peer != NULL || from->peer != NULL) {
282 		if ((to->peer == NULL) || (from->peer == NULL) ||
283 		    memcmp(to->peer, from->peer, sizeof(*to->peer)))
284 			return (-1);
285 	}
286 
287 	if (ipsecctl_cmp_ident(to, from))
288 		return (-1);
289 
290 	if (ipsecctl_rule_matchsrc(to, from->src)) {
291 		free(from->src->name);
292 		free(from->src);
293 		from->src = NULL;
294 		match = 1;
295 	}
296 	if (ipsecctl_rule_matchdst(to, from->dst)) {
297 		free(from->dst->name);
298 		free(from->dst);
299 		from->dst = NULL;
300 		match = 1;
301 	}
302 
303 	if (!match)
304 		return (-1);
305 
306 	TAILQ_INSERT_TAIL(&to->collapsed_rules, from, bundle_entry);
307 
308 	return (0);
309 }
310 
311 /*
312  * Return 0 if ``r1'' and ``r2'' IDENTITY match, -1 otherwise.
313  */
314 int
315 ipsecctl_cmp_ident(struct ipsec_rule *r1, struct ipsec_rule *r2)
316 {
317 	if ((r1->auth == NULL) && (r2->auth == NULL))
318 		return (0) ;
319 
320 	if ((r1->auth == NULL) || (r2->auth == NULL))
321 		return (-1);
322 
323 	if (r1->auth->type != r2->auth->type)
324 		return (-1);
325 
326 	if (r1->auth->srcid != NULL) {
327 		if (r2->auth->srcid == NULL)
328 			return (-1);
329 
330 		if (strcmp(r1->auth->srcid, r2->auth->srcid))
331 			return (-1);
332 	}
333 
334 	if (r1->auth->dstid) {
335 		if (r2->auth->dstid == NULL)
336 			return (-1);
337 
338 		if (strcmp(r1->auth->dstid, r2->auth->dstid))
339 			return (-1);
340 	}
341 
342 	return (0);
343 }
344 
345 
346 /*
347  * Return 0 if ``r'' or its merged entries contain ``src'', -1 otherwise.
348  */
349 int
350 ipsecctl_rule_matchsrc(struct ipsec_rule *r, struct ipsec_addr_wrap *src)
351 {
352 	struct ipsec_rule *r2;
353 
354 	if (memcmp(r->src, src, sizeof(*r->src)) == 0)
355 		return (-1);
356 
357 	TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) {
358 		if (r2->src == NULL)
359 			continue;
360 		if (memcmp(r2->src, src, sizeof(*r->src)) == 0)
361 			return (-1);
362 	}
363 
364 	return (0);
365 }
366 
367 /*
368  * Return 0 if ``r'' or its merged entries contain ``dst'', -1 otherwise.
369  */
370 int
371 ipsecctl_rule_matchdst(struct ipsec_rule *r, struct ipsec_addr_wrap *dst)
372 {
373 	struct ipsec_rule *r2;
374 
375 	if (memcmp(r->dst, dst, sizeof(*r->dst)) == 0)
376 		return (-1);
377 
378 	TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) {
379 		if (r2->dst == NULL)
380 			continue;
381 		if (memcmp(r2->dst, dst, sizeof(*r->dst)) == 0)
382 			return (-1);
383 	}
384 
385 	return (0);
386 }
387 
388 void
389 ipsecctl_print_addr(struct ipsec_addr_wrap *ipa)
390 {
391 	int		bits;
392 	char		buf[NI_MAXHOST];
393 
394 	if (ipa == NULL) {
395 		printf("?");
396 		return;
397 	}
398 	if (inet_ntop(ipa->af, &ipa->address, buf, sizeof(buf)) == NULL)
399 		printf("?");
400 	else
401 		printf("%s", buf);
402 
403 	bits = unmask(&ipa->mask);
404 	if (bits != (ipa->af == AF_INET ? 32 : 128))
405 		printf("/%d", bits);
406 }
407 
408 void
409 ipsecctl_print_proto(u_int8_t proto)
410 {
411 	struct protoent *p;
412 
413 	if ((p = getprotobynumber(proto)) != NULL)
414 		printf("%s", p->p_name);
415 	else
416 		printf("%u", proto);
417 }
418 
419 void
420 ipsecctl_print_port(u_int16_t port, const char *proto)
421 {
422 	struct servent *s;
423 
424 	if ((s = getservbyport(port, proto)) != NULL)
425 		printf("%s", s->s_name);
426 	else
427 		printf("%u", ntohs(port));
428 }
429 
430 void
431 ipsecctl_print_key(struct ipsec_key *key)
432 {
433 	int	i;
434 
435 	for (i = 0; i < (int)key->len; i++)
436 		printf("%02x", key->data[i]);
437 }
438 
439 void
440 ipsecctl_print_flow(struct ipsec_rule *r, int opts)
441 {
442 	struct ipsec_rule *r2;
443 
444 	printf("flow %s %s", satype[r->satype], direction[r->direction]);
445 
446 	if (r->proto) {
447 		printf(" proto ");
448 		ipsecctl_print_proto(r->proto);
449 	}
450 	printf(" from ");
451 	if (opts & IPSECCTL_OPT_COLLAPSE) {
452 		printf("{ ");
453 		ipsecctl_print_addr(r->src);
454 		TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) {
455 			if (r2->src == NULL)
456 				continue;
457 			printf(", ");
458 			ipsecctl_print_addr(r2->src);
459 		}
460 		printf(" }");
461 	} else
462 		ipsecctl_print_addr(r->src);
463 	if (r->sport) {
464 		printf(" port ");
465 		ipsecctl_print_port(r->sport,
466 		    r->proto == IPPROTO_TCP ? "tcp" : "udp");
467 	}
468 	printf(" to ");
469 	if (opts & IPSECCTL_OPT_COLLAPSE) {
470 		printf("{ ");
471 		ipsecctl_print_addr(r->dst);
472 		TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) {
473 			if (r2->dst == NULL)
474 				continue;
475 			printf(", ");
476 			ipsecctl_print_addr(r2->dst);
477 		}
478 		printf(" }");
479 	} else
480 		ipsecctl_print_addr(r->dst);
481 	if (r->dport) {
482 		printf(" port ");
483 		ipsecctl_print_port(r->dport,
484 		    r->proto == IPPROTO_TCP ? "tcp" : "udp");
485 	}
486 	if (r->local) {
487 		printf(" local ");
488 		ipsecctl_print_addr(r->local);
489 	}
490 	if (r->peer) {
491 		printf(" peer ");
492 		ipsecctl_print_addr(r->peer);
493 	}
494 	if (r->auth) {
495 		if (r->auth->srcid)
496 			printf(" srcid %s", r->auth->srcid);
497 		if (r->auth->dstid)
498 			printf(" dstid %s", r->auth->dstid);
499 		if (r->auth->type > 0)
500 			printf(" %s", auth[r->auth->type]);
501 	}
502 	printf(" type %s", flowtype[r->flowtype]);
503 	printf("\n");
504 }
505 
506 /* ARGSUSED1 */
507 void
508 ipsecctl_print_sa(struct ipsec_rule *r, int opts)
509 {
510 	printf("%s ", satype[r->satype]);
511 	/* tunnel/transport is only meaningful for esp/ah/ipcomp */
512 	if (r->satype != IPSEC_TCPMD5 && r->satype != IPSEC_IPIP)
513 		printf("%s ", tmode[r->tmode]);
514 	printf("from ");
515 	ipsecctl_print_addr(r->src);
516 	printf(" to ");
517 	ipsecctl_print_addr(r->dst);
518 	printf(" spi 0x%08x", r->spi);
519 
520 	if (r->satype != IPSEC_TCPMD5) {
521 		if (r->xfs && r->xfs->authxf)
522 			printf(" auth %s", r->xfs->authxf->name);
523 		if (r->xfs && r->xfs->encxf)
524 			printf(" enc %s", r->xfs->encxf->name);
525 		if (r->xfs && r->xfs->compxf)
526 			printf(" comp %s", r->xfs->compxf->name);
527 	}
528 	if (r->authkey && (opts & IPSECCTL_OPT_SHOWKEY)) {
529 		if (r->satype == IPSEC_TCPMD5)
530 			printf(" ");
531 		else
532 			printf(" \\\n\t");
533 		printf("authkey 0x");
534 		ipsecctl_print_key(r->authkey);
535 	}
536 	if (r->enckey && (opts & IPSECCTL_OPT_SHOWKEY)) {
537 		if (r->satype == IPSEC_TCPMD5)
538 			printf(" ");
539 		else
540 			printf(" \\\n\t");
541 		printf("enckey 0x");
542 		ipsecctl_print_key(r->enckey);
543 	}
544 	printf("\n");
545 }
546 
547 void
548 ipsecctl_print_sabundle(struct ipsec_rule *r, int opts)
549 {
550 	printf("[bundle %s to ", satype[r->proto]);
551 	ipsecctl_print_addr(r->dst);
552 	printf(" spi 0x%08x with %s to ", r->spi, satype[r->proto2]);
553 	ipsecctl_print_addr(r->dst2);
554 	printf(" spi 0x%08x", r->spi2);
555 
556 	printf("]\n");
557 }
558 
559 void
560 ipsecctl_print_rule(struct ipsec_rule *r, int opts)
561 {
562 	struct ipsec_rule *r2;
563 
564 	if (opts & IPSECCTL_OPT_VERBOSE2) {
565 		printf("@%d", r->nr);
566 		if (opts & IPSECCTL_OPT_COLLAPSE) {
567 			TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) {
568 				printf(",%d", r2->nr);
569 			}
570 		}
571 		printf(" ");
572 	}
573 
574 	if (r->type & RULE_FLOW)
575 		ipsecctl_print_flow(r, opts);
576 	if (r->type & RULE_SA)
577 		ipsecctl_print_sa(r, opts);
578 	if (r->type & RULE_IKE)
579 		ike_print_config(r, opts);
580 	if (r->type & RULE_BUNDLE)
581 		ipsecctl_print_sabundle(r, opts);
582 }
583 
584 int
585 ipsecctl_flush(int opts)
586 {
587 	if (opts & IPSECCTL_OPT_NOACTION)
588 		return (0);
589 
590 	if (pfkey_init() == -1)
591 		errx(1, "ipsecctl_flush: failed to open PF_KEY socket");
592 
593 	if (pfkey_ipsec_flush() == -1)
594 		errx(1, "ipsecctl_flush: failed to flush");
595 
596 	return (0);
597 }
598 
599 void
600 ipsecctl_get_rules(struct ipsecctl *ipsec)
601 {
602 	struct sadb_msg *msg;
603 	struct ipsec_rule *rule, *last = NULL;
604 	int		 mib[4];
605 	size_t		 need;
606 	char		*buf, *lim, *next;
607 
608 	mib[0] = CTL_NET;
609 	mib[1] = PF_KEY;
610 	mib[2] = PF_KEY_V2;
611 	mib[3] = NET_KEY_SPD_DUMP;
612 
613 	if (sysctl(mib, 4, NULL, &need, NULL, 0) == -1)
614 		err(1, "ipsecctl_get_rules: sysctl");
615 	if (need == 0)
616 		return;
617 	if ((buf = malloc(need)) == NULL)
618 		err(1, "ipsecctl_get_rules: malloc");
619 	if (sysctl(mib, 4, buf, &need, NULL, 0) == -1)
620 		err(1, "ipsecctl_get_rules: sysctl");
621 	lim = buf + need;
622 
623 	for (next = buf; next < lim; next += msg->sadb_msg_len *
624 	    PFKEYV2_CHUNK) {
625 		msg = (struct sadb_msg *)next;
626 		if (msg->sadb_msg_len == 0)
627 			break;
628 
629 		rule = calloc(1, sizeof(struct ipsec_rule));
630 		if (rule == NULL)
631 			err(1, "ipsecctl_get_rules: calloc");
632 		rule->nr = ipsec->rule_nr++;
633 		rule->type |= RULE_FLOW;
634 		TAILQ_INIT(&rule->collapsed_rules);
635 
636 		if (pfkey_parse(msg, rule))
637 			errx(1, "ipsecctl_get_rules: "
638 			    "failed to parse PF_KEY message");
639 
640 		/*
641 		 * Try to collapse ``rule'' with the last enqueued rule.
642 		 *
643 		 * Note that comparing only the last entry works only if
644 		 * the dump is sorted.
645 		 */
646 		if ((ipsec->opts & IPSECCTL_OPT_COLLAPSE) && (last != NULL) &&
647 		    (ipsecctl_merge_rules(last, rule) == 0))
648 			continue;
649 
650 		ipsecctl_add_rule(ipsec, rule);
651 		last = rule;
652 	}
653 
654 	free(buf);
655 }
656 
657 void
658 ipsecctl_print_title(char *title)
659 {
660 	if (!first_title)
661 		printf("\n");
662 	first_title = 0;
663 	printf("%s\n", title);
664 }
665 
666 void
667 ipsecctl_show_flows(int opts)
668 {
669 	struct ipsecctl ipsec;
670 	struct ipsec_rule *rp;
671 
672 	bzero(&ipsec, sizeof(ipsec));
673 	ipsec.opts = opts;
674 	TAILQ_INIT(&ipsec.rule_queue);
675 
676 	ipsecctl_get_rules(&ipsec);
677 
678 	if (opts & IPSECCTL_OPT_SHOWALL)
679 		ipsecctl_print_title("FLOWS:");
680 
681 	if (TAILQ_FIRST(&ipsec.rule_queue) == 0) {
682 		if (opts & IPSECCTL_OPT_SHOWALL)
683 			printf("No flows\n");
684 		return;
685 	}
686 
687 	while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) {
688 		TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry);
689 
690 		ipsecctl_print_rule(rp, ipsec.opts);
691 
692 		free(rp->src->name);
693 		free(rp->src);
694 		free(rp->dst->name);
695 		free(rp->dst);
696 		if (rp->local) {
697 			free(rp->local->name);
698 			free(rp->local);
699 		}
700 		if (rp->peer) {
701 			free(rp->peer->name);
702 			free(rp->peer);
703 		}
704 		if (rp->auth) {
705 			free(rp->auth->srcid);
706 			free(rp->auth->dstid);
707 			free(rp->auth);
708 		}
709 		free(rp);
710 	}
711 }
712 
713 void
714 ipsecctl_show_sas(int opts)
715 {
716 	struct sadb_msg *msg;
717 	struct sad	*sad;
718 	int		 mib[5], sacount, i;
719 	size_t		 need = 0;
720 	char		*buf, *lim, *next;
721 
722 	mib[0] = CTL_NET;
723 	mib[1] = PF_KEY;
724 	mib[2] = PF_KEY_V2;
725 	mib[3] = NET_KEY_SADB_DUMP;
726 	mib[4] = SADB_SATYPE_UNSPEC;
727 
728 	if (opts & IPSECCTL_OPT_SHOWALL)
729 		ipsecctl_print_title("SAD:");
730 
731 	/* When the SAD is empty we get ENOENT, no need to err(). */
732 	if (sysctl(mib, 5, NULL, &need, NULL, 0) == -1 && errno != ENOENT)
733 		err(1, "ipsecctl_show_sas: sysctl");
734 	if (need == 0) {
735 		if (opts & IPSECCTL_OPT_SHOWALL)
736 			printf("No entries\n");
737 		return;
738 	}
739 	if ((buf = malloc(need)) == NULL)
740 		err(1, "ipsecctl_show_sas: malloc");
741 	if (sysctl(mib, 5, buf, &need, NULL, 0) == -1)
742 		err(1, "ipsecctl_show_sas: sysctl");
743 	sacount = 0;
744 	lim = buf + need;
745 	for (next = buf; next < lim;
746 	    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
747 		msg = (struct sadb_msg *)next;
748 		if (msg->sadb_msg_len == 0)
749 			break;
750 		sacount++;
751 	}
752 	if ((sad = calloc(sacount, sizeof(*sad))) == NULL)
753 		err(1, "ipsecctl_show_sas: calloc");
754 	i = 0;
755 	for (next = buf; next < lim;
756 	    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
757 		msg = (struct sadb_msg *)next;
758 		if (msg->sadb_msg_len == 0)
759 			break;
760 		sad[i].sad_spi = pfkey_get_spi(msg);
761 		sad[i].sad_msg = msg;
762 		i++;
763 	}
764 	qsort(sad, sacount, sizeof(*sad), sacompare);
765 	for (i = 0; i < sacount; i++)
766 		pfkey_print_sa(sad[i].sad_msg, opts);
767 	free(sad);
768 	free(buf);
769 }
770 
771 int
772 ipsecctl_monitor(int opts)
773 {
774 	return (pfkey_monitor(opts));
775 }
776 
777 __dead void
778 usage(void)
779 {
780 	extern char	*__progname;
781 
782 	fprintf(stderr, "usage: %s [-cdFkmnv] [-D macro=value] [-f file]"
783 	    " [-i fifo] [-s modifier]\n", __progname);
784 	exit(1);
785 }
786 
787 const char *
788 ipsecctl_lookup_option(char *cmd, const char **list)
789 {
790 	if (cmd != NULL && *cmd)
791 		for (; *list; list++)
792 			if (!strncmp(cmd, *list, strlen(cmd)))
793 				return (*list);
794 	return (NULL);
795 }
796 
797 int
798 main(int argc, char *argv[])
799 {
800 	int		 error = 0;
801 	int		 ch;
802 	int		 opts = 0;
803 	char		*rulesopt = NULL;
804 
805 	if (argc < 2)
806 		usage();
807 
808 	while ((ch = getopt(argc, argv, "cD:df:Fi:kmnvs:")) != -1) {
809 		switch (ch) {
810 		case 'c':
811 			opts |= IPSECCTL_OPT_COLLAPSE;
812 			break;
813 
814 		case 'D':
815 			if (cmdline_symset(optarg) < 0)
816 				warnx("could not parse macro definition %s",
817 				    optarg);
818 			break;
819 
820 		case 'd':
821 			opts |= IPSECCTL_OPT_DELETE;
822 			break;
823 
824 		case 'f':
825 			rulesopt = optarg;
826 			break;
827 
828 		case 'F':
829 			opts |= IPSECCTL_OPT_FLUSH;
830 			break;
831 
832 		case 'i':
833 			isakmpd_fifo = optarg;
834 			break;
835 
836 		case 'k':
837 			opts |= IPSECCTL_OPT_SHOWKEY;
838 			break;
839 
840 		case 'm':
841 			opts |= IPSECCTL_OPT_MONITOR;
842 			break;
843 
844 		case 'n':
845 			opts |= IPSECCTL_OPT_NOACTION;
846 			break;
847 
848 		case 'v':
849 			if (opts & IPSECCTL_OPT_VERBOSE)
850 				opts |= IPSECCTL_OPT_VERBOSE2;
851 			opts |= IPSECCTL_OPT_VERBOSE;
852 			break;
853 
854 		case 's':
855 			showopt = ipsecctl_lookup_option(optarg, showopt_list);
856 			if (showopt == NULL) {
857 				warnx("Unknown show modifier '%s'", optarg);
858 				usage();
859 				/* NOTREACHED */
860 			}
861 			opts |= IPSECCTL_OPT_SHOW;
862 			break;
863 
864 		default:
865 			usage();
866 			/* NOTREACHED */
867 		}
868 	}
869 
870 	if (argc != optind) {
871 		warnx("unknown command line argument: %s ...", argv[optind]);
872 		usage();
873 		/* NOTREACHED */
874 	}
875 	if (opts & IPSECCTL_OPT_FLUSH)
876 		if (ipsecctl_flush(opts))
877 			error = 1;
878 
879 	if (rulesopt != NULL)
880 		if (ipsecctl_rules(rulesopt, opts))
881 			error = 1;
882 
883 	if (showopt != NULL) {
884 		switch (*showopt) {
885 		case 'f':
886 			ipsecctl_show_flows(opts);
887 			break;
888 		case 's':
889 			ipsecctl_show_sas(opts);
890 			break;
891 		case 'a':
892 			opts |= IPSECCTL_OPT_SHOWALL;
893 			ipsecctl_show_flows(opts);
894 			ipsecctl_show_sas(opts);
895 		}
896 	}
897 
898 	if (opts & IPSECCTL_OPT_MONITOR)
899 		if (ipsecctl_monitor(opts))
900 			error = 1;
901 
902 	exit(error);
903 }
904 
905 static int
906 unmask(struct ipsec_addr *ipa)
907 {
908 	int		i = 31, j = 0, b = 0;
909 	u_int32_t	tmp;
910 
911 	while (j < 4 && ipa->addr32[j] == 0xffffffff) {
912 		b += 32;
913 		j++;
914 	}
915 	if (j < 4) {
916 		tmp = ntohl(ipa->addr32[j]);
917 		for (i = 31; tmp & (1 << i); --i)
918 			b++;
919 	}
920 	return (b);
921 }
922