xref: /openbsd-src/sbin/ipsecctl/ipsecctl.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
1 /*	$OpenBSD: ipsecctl.c,v 1.85 2023/03/07 17:43:59 guenther 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 void
507 ipsecctl_print_sa(struct ipsec_rule *r, int opts)
508 {
509 	printf("%s ", satype[r->satype]);
510 	/* tunnel/transport is only meaningful for esp/ah/ipcomp */
511 	if (r->satype != IPSEC_TCPMD5 && r->satype != IPSEC_IPIP)
512 		printf("%s ", tmode[r->tmode]);
513 	printf("from ");
514 	ipsecctl_print_addr(r->src);
515 	printf(" to ");
516 	ipsecctl_print_addr(r->dst);
517 	printf(" spi 0x%08x", r->spi);
518 
519 	if (r->satype != IPSEC_TCPMD5) {
520 		if (r->xfs && r->xfs->authxf)
521 			printf(" auth %s", r->xfs->authxf->name);
522 		if (r->xfs && r->xfs->encxf)
523 			printf(" enc %s", r->xfs->encxf->name);
524 		if (r->xfs && r->xfs->compxf)
525 			printf(" comp %s", r->xfs->compxf->name);
526 	}
527 	if (r->authkey && (opts & IPSECCTL_OPT_SHOWKEY)) {
528 		if (r->satype == IPSEC_TCPMD5)
529 			printf(" ");
530 		else
531 			printf(" \\\n\t");
532 		printf("authkey 0x");
533 		ipsecctl_print_key(r->authkey);
534 	}
535 	if (r->enckey && (opts & IPSECCTL_OPT_SHOWKEY)) {
536 		if (r->satype == IPSEC_TCPMD5)
537 			printf(" ");
538 		else
539 			printf(" \\\n\t");
540 		printf("enckey 0x");
541 		ipsecctl_print_key(r->enckey);
542 	}
543 	printf("\n");
544 }
545 
546 void
547 ipsecctl_print_sabundle(struct ipsec_rule *r, int opts)
548 {
549 	printf("[bundle %s to ", satype[r->proto]);
550 	ipsecctl_print_addr(r->dst);
551 	printf(" spi 0x%08x with %s to ", r->spi, satype[r->proto2]);
552 	ipsecctl_print_addr(r->dst2);
553 	printf(" spi 0x%08x", r->spi2);
554 
555 	printf("]\n");
556 }
557 
558 void
559 ipsecctl_print_rule(struct ipsec_rule *r, int opts)
560 {
561 	struct ipsec_rule *r2;
562 
563 	if (opts & IPSECCTL_OPT_VERBOSE2) {
564 		printf("@%d", r->nr);
565 		if (opts & IPSECCTL_OPT_COLLAPSE) {
566 			TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) {
567 				printf(",%d", r2->nr);
568 			}
569 		}
570 		printf(" ");
571 	}
572 
573 	if (r->type & RULE_FLOW)
574 		ipsecctl_print_flow(r, opts);
575 	if (r->type & RULE_SA)
576 		ipsecctl_print_sa(r, opts);
577 	if (r->type & RULE_IKE)
578 		ike_print_config(r, opts);
579 	if (r->type & RULE_BUNDLE)
580 		ipsecctl_print_sabundle(r, opts);
581 }
582 
583 int
584 ipsecctl_flush(int opts)
585 {
586 	if (opts & IPSECCTL_OPT_NOACTION)
587 		return (0);
588 
589 	if (pfkey_init() == -1)
590 		errx(1, "ipsecctl_flush: failed to open PF_KEY socket");
591 
592 	if (pfkey_ipsec_flush() == -1)
593 		errx(1, "ipsecctl_flush: failed to flush");
594 
595 	return (0);
596 }
597 
598 void
599 ipsecctl_get_rules(struct ipsecctl *ipsec)
600 {
601 	struct sadb_msg *msg;
602 	struct ipsec_rule *rule, *last = NULL;
603 	int		 mib[4];
604 	size_t		 need;
605 	char		*buf, *lim, *next;
606 
607 	mib[0] = CTL_NET;
608 	mib[1] = PF_KEY;
609 	mib[2] = PF_KEY_V2;
610 	mib[3] = NET_KEY_SPD_DUMP;
611 
612 	if (sysctl(mib, 4, NULL, &need, NULL, 0) == -1)
613 		err(1, "ipsecctl_get_rules: sysctl");
614 	if (need == 0)
615 		return;
616 	if ((buf = malloc(need)) == NULL)
617 		err(1, "ipsecctl_get_rules: malloc");
618 	if (sysctl(mib, 4, buf, &need, NULL, 0) == -1)
619 		err(1, "ipsecctl_get_rules: sysctl");
620 	lim = buf + need;
621 
622 	for (next = buf; next < lim; next += msg->sadb_msg_len *
623 	    PFKEYV2_CHUNK) {
624 		msg = (struct sadb_msg *)next;
625 		if (msg->sadb_msg_len == 0)
626 			break;
627 
628 		rule = calloc(1, sizeof(struct ipsec_rule));
629 		if (rule == NULL)
630 			err(1, "ipsecctl_get_rules: calloc");
631 		rule->nr = ipsec->rule_nr++;
632 		rule->type |= RULE_FLOW;
633 		TAILQ_INIT(&rule->collapsed_rules);
634 
635 		if (pfkey_parse(msg, rule))
636 			errx(1, "ipsecctl_get_rules: "
637 			    "failed to parse PF_KEY message");
638 
639 		/*
640 		 * Try to collapse ``rule'' with the last enqueued rule.
641 		 *
642 		 * Note that comparing only the last entry works only if
643 		 * the dump is sorted.
644 		 */
645 		if ((ipsec->opts & IPSECCTL_OPT_COLLAPSE) && (last != NULL) &&
646 		    (ipsecctl_merge_rules(last, rule) == 0))
647 			continue;
648 
649 		ipsecctl_add_rule(ipsec, rule);
650 		last = rule;
651 	}
652 
653 	free(buf);
654 }
655 
656 void
657 ipsecctl_print_title(char *title)
658 {
659 	if (!first_title)
660 		printf("\n");
661 	first_title = 0;
662 	printf("%s\n", title);
663 }
664 
665 void
666 ipsecctl_show_flows(int opts)
667 {
668 	struct ipsecctl ipsec;
669 	struct ipsec_rule *rp;
670 
671 	bzero(&ipsec, sizeof(ipsec));
672 	ipsec.opts = opts;
673 	TAILQ_INIT(&ipsec.rule_queue);
674 
675 	ipsecctl_get_rules(&ipsec);
676 
677 	if (opts & IPSECCTL_OPT_SHOWALL)
678 		ipsecctl_print_title("FLOWS:");
679 
680 	if (TAILQ_FIRST(&ipsec.rule_queue) == 0) {
681 		if (opts & IPSECCTL_OPT_SHOWALL)
682 			printf("No flows\n");
683 		return;
684 	}
685 
686 	while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) {
687 		TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry);
688 
689 		ipsecctl_print_rule(rp, ipsec.opts);
690 
691 		free(rp->src->name);
692 		free(rp->src);
693 		free(rp->dst->name);
694 		free(rp->dst);
695 		if (rp->local) {
696 			free(rp->local->name);
697 			free(rp->local);
698 		}
699 		if (rp->peer) {
700 			free(rp->peer->name);
701 			free(rp->peer);
702 		}
703 		if (rp->auth) {
704 			free(rp->auth->srcid);
705 			free(rp->auth->dstid);
706 			free(rp->auth);
707 		}
708 		free(rp);
709 	}
710 }
711 
712 void
713 ipsecctl_show_sas(int opts)
714 {
715 	struct sadb_msg *msg;
716 	struct sad	*sad;
717 	int		 mib[5], sacount, i;
718 	size_t		 need = 0;
719 	char		*buf, *lim, *next;
720 
721 	mib[0] = CTL_NET;
722 	mib[1] = PF_KEY;
723 	mib[2] = PF_KEY_V2;
724 	mib[3] = NET_KEY_SADB_DUMP;
725 	mib[4] = SADB_SATYPE_UNSPEC;
726 
727 	if (opts & IPSECCTL_OPT_SHOWALL)
728 		ipsecctl_print_title("SAD:");
729 
730 	/* When the SAD is empty we get ENOENT, no need to err(). */
731 	if (sysctl(mib, 5, NULL, &need, NULL, 0) == -1 && errno != ENOENT)
732 		err(1, "ipsecctl_show_sas: sysctl");
733 	if (need == 0) {
734 		if (opts & IPSECCTL_OPT_SHOWALL)
735 			printf("No entries\n");
736 		return;
737 	}
738 	if ((buf = malloc(need)) == NULL)
739 		err(1, "ipsecctl_show_sas: malloc");
740 	if (sysctl(mib, 5, buf, &need, NULL, 0) == -1)
741 		err(1, "ipsecctl_show_sas: sysctl");
742 	sacount = 0;
743 	lim = buf + need;
744 	for (next = buf; next < lim;
745 	    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
746 		msg = (struct sadb_msg *)next;
747 		if (msg->sadb_msg_len == 0)
748 			break;
749 		sacount++;
750 	}
751 	if ((sad = calloc(sacount, sizeof(*sad))) == NULL)
752 		err(1, "ipsecctl_show_sas: calloc");
753 	i = 0;
754 	for (next = buf; next < lim;
755 	    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
756 		msg = (struct sadb_msg *)next;
757 		if (msg->sadb_msg_len == 0)
758 			break;
759 		sad[i].sad_spi = pfkey_get_spi(msg);
760 		sad[i].sad_msg = msg;
761 		i++;
762 	}
763 	qsort(sad, sacount, sizeof(*sad), sacompare);
764 	for (i = 0; i < sacount; i++)
765 		pfkey_print_sa(sad[i].sad_msg, opts);
766 	free(sad);
767 	free(buf);
768 }
769 
770 int
771 ipsecctl_monitor(int opts)
772 {
773 	return (pfkey_monitor(opts));
774 }
775 
776 __dead void
777 usage(void)
778 {
779 	extern char	*__progname;
780 
781 	fprintf(stderr, "usage: %s [-cdFkmnv] [-D macro=value] [-f file]"
782 	    " [-i fifo] [-s modifier]\n", __progname);
783 	exit(1);
784 }
785 
786 const char *
787 ipsecctl_lookup_option(char *cmd, const char **list)
788 {
789 	if (cmd != NULL && *cmd)
790 		for (; *list; list++)
791 			if (!strncmp(cmd, *list, strlen(cmd)))
792 				return (*list);
793 	return (NULL);
794 }
795 
796 int
797 main(int argc, char *argv[])
798 {
799 	int		 error = 0;
800 	int		 ch;
801 	int		 opts = 0;
802 	char		*rulesopt = NULL;
803 
804 	if (argc < 2)
805 		usage();
806 
807 	while ((ch = getopt(argc, argv, "cD:df:Fi:kmnvs:")) != -1) {
808 		switch (ch) {
809 		case 'c':
810 			opts |= IPSECCTL_OPT_COLLAPSE;
811 			break;
812 
813 		case 'D':
814 			if (cmdline_symset(optarg) < 0)
815 				warnx("could not parse macro definition %s",
816 				    optarg);
817 			break;
818 
819 		case 'd':
820 			opts |= IPSECCTL_OPT_DELETE;
821 			break;
822 
823 		case 'f':
824 			rulesopt = optarg;
825 			break;
826 
827 		case 'F':
828 			opts |= IPSECCTL_OPT_FLUSH;
829 			break;
830 
831 		case 'i':
832 			isakmpd_fifo = optarg;
833 			break;
834 
835 		case 'k':
836 			opts |= IPSECCTL_OPT_SHOWKEY;
837 			break;
838 
839 		case 'm':
840 			opts |= IPSECCTL_OPT_MONITOR;
841 			break;
842 
843 		case 'n':
844 			opts |= IPSECCTL_OPT_NOACTION;
845 			break;
846 
847 		case 'v':
848 			if (opts & IPSECCTL_OPT_VERBOSE)
849 				opts |= IPSECCTL_OPT_VERBOSE2;
850 			opts |= IPSECCTL_OPT_VERBOSE;
851 			break;
852 
853 		case 's':
854 			showopt = ipsecctl_lookup_option(optarg, showopt_list);
855 			if (showopt == NULL) {
856 				warnx("Unknown show modifier '%s'", optarg);
857 				usage();
858 				/* NOTREACHED */
859 			}
860 			opts |= IPSECCTL_OPT_SHOW;
861 			break;
862 
863 		default:
864 			usage();
865 			/* NOTREACHED */
866 		}
867 	}
868 
869 	if (argc != optind) {
870 		warnx("unknown command line argument: %s ...", argv[optind]);
871 		usage();
872 		/* NOTREACHED */
873 	}
874 	if (opts & IPSECCTL_OPT_FLUSH)
875 		if (ipsecctl_flush(opts))
876 			error = 1;
877 
878 	if (rulesopt != NULL)
879 		if (ipsecctl_rules(rulesopt, opts))
880 			error = 1;
881 
882 	if (showopt != NULL) {
883 		switch (*showopt) {
884 		case 'f':
885 			ipsecctl_show_flows(opts);
886 			break;
887 		case 's':
888 			ipsecctl_show_sas(opts);
889 			break;
890 		case 'a':
891 			opts |= IPSECCTL_OPT_SHOWALL;
892 			ipsecctl_show_flows(opts);
893 			ipsecctl_show_sas(opts);
894 		}
895 	}
896 
897 	if (opts & IPSECCTL_OPT_MONITOR)
898 		if (ipsecctl_monitor(opts))
899 			error = 1;
900 
901 	exit(error);
902 }
903 
904 static int
905 unmask(struct ipsec_addr *ipa)
906 {
907 	int		i = 31, j = 0, b = 0;
908 	u_int32_t	tmp;
909 
910 	while (j < 4 && ipa->addr32[j] == 0xffffffff) {
911 		b += 32;
912 		j++;
913 	}
914 	if (j < 4) {
915 		tmp = ntohl(ipa->addr32[j]);
916 		for (i = 31; tmp & (1 << i); --i)
917 			b++;
918 	}
919 	return (b);
920 }
921