xref: /openbsd-src/sbin/ipsecctl/ipsecctl.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: ipsecctl.c,v 1.80 2015/12/10 17:27:00 mmcc 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 <err.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <netdb.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 
37 #include "ipsecctl.h"
38 #include "pfkey.h"
39 
40 int		 ipsecctl_rules(char *, int);
41 FILE		*ipsecctl_fopen(const char *, const char *);
42 int		 ipsecctl_commit(int, struct ipsecctl *);
43 int		 ipsecctl_add_rule(struct ipsecctl *, struct ipsec_rule *);
44 void		 ipsecctl_free_rule(struct ipsec_rule *);
45 void		 ipsecctl_print_addr(struct ipsec_addr_wrap *);
46 void		 ipsecctl_print_proto(u_int8_t);
47 void		 ipsecctl_print_port(u_int16_t, const char *);
48 void		 ipsecctl_print_key(struct ipsec_key *);
49 void		 ipsecctl_print_flow(struct ipsec_rule *, int);
50 void		 ipsecctl_print_sa(struct ipsec_rule *, int);
51 void		 ipsecctl_print_sagroup(struct ipsec_rule *, int);
52 int		 ipsecctl_flush(int);
53 void		 ipsecctl_get_rules(struct ipsecctl *);
54 void		 ipsecctl_print_title(char *);
55 void		 ipsecctl_show_flows(int);
56 void		 ipsecctl_show_sas(int);
57 int		 ipsecctl_monitor(int);
58 void		 usage(void);
59 const char	*ipsecctl_lookup_option(char *, const char **);
60 static int	 unmask(struct ipsec_addr *, sa_family_t);
61 int		 sacompare(const void *, const void *);
62 
63 const char	*showopt;
64 char		*isakmpd_fifo = "/var/run/isakmpd.fifo";
65 
66 int		 first_title = 1;
67 
68 static const char *showopt_list[] = {
69 	"flow", "sa", "all", NULL
70 };
71 
72 static const char *direction[] = {"?", "in", "out"};
73 static const char *flowtype[] = {"?", "use", "acquire", "require", "deny",
74     "bypass", "dontacq"};
75 static const char *satype[] = {"?", "esp", "ah", "ipcomp", "tcpmd5", "ipip"};
76 static const char *tmode[] = {"?", "transport", "tunnel"};
77 static const char *auth[] = {"?", "psk", "rsa"};
78 
79 struct sad {
80 	struct sadb_msg	*sad_msg;
81 	u_int32_t	 sad_spi;
82 };
83 
84 int
85 sacompare(const void *va, const void *vb)
86 {
87 	const struct sad *a = va, *b = vb;
88 
89 	if (a->sad_spi < b->sad_spi)
90 		return (-1);
91 	if (a->sad_spi > b->sad_spi)
92 		return (1);
93 	return (0);
94 }
95 
96 int
97 ipsecctl_rules(char *filename, int opts)
98 {
99 	struct ipsecctl		 ipsec;
100 	struct ipsec_rule	*rp;
101 	int			 action, error = 0;
102 
103 	bzero(&ipsec, sizeof(ipsec));
104 	ipsec.opts = opts;
105 	TAILQ_INIT(&ipsec.rule_queue);
106 	TAILQ_INIT(&ipsec.group_queue);
107 
108 	if (parse_rules(filename, &ipsec) < 0) {
109 		warnx("Syntax error in config file: ipsec rules not loaded");
110 		error = 1;
111 	} else {
112 		if (opts & IPSECCTL_OPT_DELETE)
113 			action = ACTION_DELETE;
114 		else
115 			action = ACTION_ADD;
116 
117 		if ((opts & IPSECCTL_OPT_NOACTION) == 0)
118 			error = ipsecctl_commit(action, &ipsec);
119 
120 	}
121 
122 	/* This also frees the rules in ipsec.group_queue. */
123 	while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) {
124 		TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry);
125 		ipsecctl_free_rule(rp);
126 	}
127 
128 	return (error);
129 }
130 
131 FILE *
132 ipsecctl_fopen(const char *name, const char *mode)
133 {
134 	struct stat	 st;
135 	FILE		*fp;
136 
137 	fp = fopen(name, mode);
138 	if (fp == NULL)
139 		return (NULL);
140 
141 	if (fstat(fileno(fp), &st)) {
142 		fclose(fp);
143 		return (NULL);
144 	}
145 	if (S_ISDIR(st.st_mode)) {
146 		fclose(fp);
147 		errno = EISDIR;
148 		return (NULL);
149 	}
150 	return (fp);
151 }
152 
153 int
154 ipsecctl_commit(int action, struct ipsecctl *ipsec)
155 {
156 	struct ipsec_rule	*rp;
157 	int			 ret = 0;
158 
159 	if (pfkey_init() == -1)
160 		errx(1, "ipsecctl_commit: failed to open PF_KEY socket");
161 
162 	TAILQ_FOREACH(rp, &ipsec->rule_queue, rule_entry) {
163 		if (rp->type & RULE_IKE) {
164 			if (ike_ipsec_establish(action, rp, isakmpd_fifo) ==
165 			    -1) {
166 				warnx("failed to %s ike rule %d",
167 				    action == ACTION_DELETE ? "delete" : "add",
168 				    rp->nr);
169 				ret = 2;
170 			}
171 		} else {
172 			if (pfkey_ipsec_establish(action, rp) == -1) {
173 				warnx("failed to %s rule %d",
174 				    action == ACTION_DELETE ? "delete" : "add",
175 				    rp->nr);
176 				ret = 2;
177 			}
178 		}
179 	}
180 
181 	return (ret);
182 }
183 
184 int
185 ipsecctl_add_rule(struct ipsecctl *ipsec, struct ipsec_rule *r)
186 {
187 	TAILQ_INSERT_TAIL(&ipsec->rule_queue, r, rule_entry);
188 
189 	if ((ipsec->opts & IPSECCTL_OPT_VERBOSE) && !(ipsec->opts &
190 	    IPSECCTL_OPT_SHOW))
191 		ipsecctl_print_rule(r, ipsec->opts);
192 
193 	return (0);
194 }
195 
196 void
197 ipsecctl_free_rule(struct ipsec_rule *rp)
198 {
199 	if (rp->src) {
200 		free(rp->src->name);
201 		free(rp->src);
202 	}
203 	if (rp->dst) {
204 		free(rp->dst->name);
205 		free(rp->dst);
206 	}
207 	if (rp->dst2) {
208 		free(rp->dst2->name);
209 		free(rp->dst2);
210 	}
211 	if (rp->local) {
212 		free(rp->local->name);
213 		free(rp->local);
214 	}
215 	if (rp->peer) {
216 		free(rp->peer->name);
217 		free(rp->peer);
218 	}
219 	if (rp->auth) {
220 		free(rp->auth->srcid);
221 		free(rp->auth->dstid);
222 		free(rp->auth);
223 	}
224 	if (rp->ikeauth) {
225 		free(rp->ikeauth->string);
226 		free(rp->ikeauth);
227 	}
228 	free(rp->xfs);
229 	free(rp->p1xfs);
230 	free(rp->p2xfs);
231 	free(rp->p1life);
232 	free(rp->p2life);
233 	if (rp->authkey) {
234 		free(rp->authkey->data);
235 		free(rp->authkey);
236 	}
237 	if (rp->enckey) {
238 		free(rp->enckey->data);
239 		free(rp->enckey);
240 	}
241 	free(rp->p1name);
242 	free(rp->p2name);
243 	free(rp->p2lid);
244 	free(rp->p2nid);
245 	free(rp->p2rid);
246 	free(rp);
247 }
248 
249 void
250 ipsecctl_print_addr(struct ipsec_addr_wrap *ipa)
251 {
252 	int		bits;
253 	char		buf[NI_MAXHOST];
254 
255 	if (ipa == NULL) {
256 		printf("?");
257 		return;
258 	}
259 	if (inet_ntop(ipa->af, &ipa->address, buf, sizeof(buf)) == NULL)
260 		printf("?");
261 	else
262 		printf("%s", buf);
263 
264 	bits = unmask(&ipa->mask, ipa->af);
265 	if (bits != (ipa->af == AF_INET ? 32 : 128))
266 		printf("/%d", bits);
267 }
268 
269 void
270 ipsecctl_print_proto(u_int8_t proto)
271 {
272 	struct protoent *p;
273 
274 	if ((p = getprotobynumber(proto)) != NULL)
275 		printf("%s", p->p_name);
276 	else
277 		printf("%u", proto);
278 }
279 
280 void
281 ipsecctl_print_port(u_int16_t port, const char *proto)
282 {
283 	struct servent *s;
284 
285 	if ((s = getservbyport(port, proto)) != NULL)
286 		printf("%s", s->s_name);
287 	else
288 		printf("%u", ntohs(port));
289 }
290 
291 void
292 ipsecctl_print_key(struct ipsec_key *key)
293 {
294 	int	i;
295 
296 	for (i = 0; i < (int)key->len; i++)
297 		printf("%02x", key->data[i]);
298 }
299 
300 void
301 ipsecctl_print_flow(struct ipsec_rule *r, int opts)
302 {
303 	printf("flow %s %s", satype[r->satype], direction[r->direction]);
304 
305 	if (r->proto) {
306 		printf(" proto ");
307 		ipsecctl_print_proto(r->proto);
308 	}
309 	printf(" from ");
310 	ipsecctl_print_addr(r->src);
311 	if (r->sport) {
312 		printf(" port ");
313 		ipsecctl_print_port(r->sport,
314 		    r->proto == IPPROTO_TCP ? "tcp" : "udp");
315 	}
316 	printf(" to ");
317 	ipsecctl_print_addr(r->dst);
318 	if (r->dport) {
319 		printf(" port ");
320 		ipsecctl_print_port(r->dport,
321 		    r->proto == IPPROTO_TCP ? "tcp" : "udp");
322 	}
323 	if (r->local) {
324 		printf(" local ");
325 		ipsecctl_print_addr(r->local);
326 	}
327 	if (r->peer) {
328 		printf(" peer ");
329 		ipsecctl_print_addr(r->peer);
330 	}
331 	if (r->auth) {
332 		if (r->auth->srcid)
333 			printf(" srcid %s", r->auth->srcid);
334 		if (r->auth->dstid)
335 			printf(" dstid %s", r->auth->dstid);
336 		if (r->auth->type > 0)
337 			printf(" %s", auth[r->auth->type]);
338 	}
339 	printf(" type %s", flowtype[r->flowtype]);
340 	printf("\n");
341 }
342 
343 /* ARGSUSED1 */
344 void
345 ipsecctl_print_sa(struct ipsec_rule *r, int opts)
346 {
347 	printf("%s ", satype[r->satype]);
348 	/* tunnel/transport is only meaningful for esp/ah/ipcomp */
349 	if (r->satype != IPSEC_TCPMD5 && r->satype != IPSEC_IPIP)
350 		printf("%s ", tmode[r->tmode]);
351 	printf("from ");
352 	ipsecctl_print_addr(r->src);
353 	printf(" to ");
354 	ipsecctl_print_addr(r->dst);
355 	printf(" spi 0x%08x", r->spi);
356 
357 	if (r->satype != IPSEC_TCPMD5) {
358 		if (r->xfs && r->xfs->authxf)
359 			printf(" auth %s", r->xfs->authxf->name);
360 		if (r->xfs && r->xfs->encxf)
361 			printf(" enc %s", r->xfs->encxf->name);
362 		if (r->xfs && r->xfs->compxf)
363 			printf(" comp %s", r->xfs->compxf->name);
364 	}
365 	if (r->authkey && (opts & IPSECCTL_OPT_SHOWKEY)) {
366 		if (r->satype == IPSEC_TCPMD5)
367 			printf(" ");
368 		else
369 			printf(" \\\n\t");
370 		printf("authkey 0x");
371 		ipsecctl_print_key(r->authkey);
372 	}
373 	if (r->enckey && (opts & IPSECCTL_OPT_SHOWKEY)) {
374 		if (r->satype == IPSEC_TCPMD5)
375 			printf(" ");
376 		else
377 			printf(" \\\n\t");
378 		printf("enckey 0x");
379 		ipsecctl_print_key(r->enckey);
380 	}
381 	printf("\n");
382 }
383 
384 void
385 ipsecctl_print_sagroup(struct ipsec_rule *r, int opts)
386 {
387 	if (!(opts & IPSECCTL_OPT_VERBOSE2))
388 		return;
389 
390 	printf("[group %s to ", satype[r->proto]);
391 	ipsecctl_print_addr(r->dst);
392 	printf(" spi 0x%08x with %s to ", r->spi, satype[r->proto2]);
393 	ipsecctl_print_addr(r->dst2);
394 	printf(" spi 0x%08x", r->spi2);
395 
396 	printf("]\n");
397 }
398 
399 void
400 ipsecctl_print_rule(struct ipsec_rule *r, int opts)
401 {
402 	if (opts & IPSECCTL_OPT_VERBOSE2)
403 		printf("@%d ", r->nr);
404 
405 	if (r->type & RULE_FLOW)
406 		ipsecctl_print_flow(r, opts);
407 	if (r->type & RULE_SA)
408 		ipsecctl_print_sa(r, opts);
409 	if (r->type & RULE_IKE)
410 		ike_print_config(r, opts);
411 	if (r->type & RULE_GROUP)
412 		ipsecctl_print_sagroup(r, opts);
413 }
414 
415 int
416 ipsecctl_flush(int opts)
417 {
418 	if (opts & IPSECCTL_OPT_NOACTION)
419 		return (0);
420 
421 	if (pfkey_init() == -1)
422 		errx(1, "ipsecctl_flush: failed to open PF_KEY socket");
423 
424 	if (pfkey_ipsec_flush() == -1)
425 		errx(1, "ipsecctl_flush: failed to flush");
426 
427 	return (0);
428 }
429 
430 void
431 ipsecctl_get_rules(struct ipsecctl *ipsec)
432 {
433 	struct sadb_msg *msg;
434 	struct ipsec_rule *rule;
435 	int		 mib[4];
436 	size_t		 need;
437 	char		*buf, *lim, *next;
438 
439 	mib[0] = CTL_NET;
440 	mib[1] = PF_KEY;
441 	mib[2] = PF_KEY_V2;
442 	mib[3] = NET_KEY_SPD_DUMP;
443 
444 	if (sysctl(mib, 4, NULL, &need, NULL, 0) == -1)
445 		err(1, "ipsecctl_get_rules: sysctl");
446 	if (need == 0)
447 		return;
448 	if ((buf = malloc(need)) == NULL)
449 		err(1, "ipsecctl_get_rules: malloc");
450 	if (sysctl(mib, 4, buf, &need, NULL, 0) == -1)
451 		err(1, "ipsecctl_get_rules: sysctl");
452 	lim = buf + need;
453 
454 	for (next = buf; next < lim; next += msg->sadb_msg_len *
455 	    PFKEYV2_CHUNK) {
456 		msg = (struct sadb_msg *)next;
457 		if (msg->sadb_msg_len == 0)
458 			break;
459 
460 		rule = calloc(1, sizeof(struct ipsec_rule));
461 		if (rule == NULL)
462 			err(1, "ipsecctl_get_rules: calloc");
463 		rule->nr = ipsec->rule_nr++;
464 		rule->type |= RULE_FLOW;
465 
466 		if (pfkey_parse(msg, rule))
467 			errx(1, "ipsecctl_get_rules: "
468 			    "failed to parse PF_KEY message");
469 
470 		ipsecctl_add_rule(ipsec, rule);
471 	}
472 
473 	free(buf);
474 }
475 
476 void
477 ipsecctl_print_title(char *title)
478 {
479 	if (!first_title)
480 		printf("\n");
481 	first_title = 0;
482 	printf("%s\n", title);
483 }
484 
485 void
486 ipsecctl_show_flows(int opts)
487 {
488 	struct ipsecctl ipsec;
489 	struct ipsec_rule *rp;
490 
491 	bzero(&ipsec, sizeof(ipsec));
492 	ipsec.opts = opts;
493 	TAILQ_INIT(&ipsec.rule_queue);
494 
495 	ipsecctl_get_rules(&ipsec);
496 
497 	if (opts & IPSECCTL_OPT_SHOWALL)
498 		ipsecctl_print_title("FLOWS:");
499 
500 	if (TAILQ_FIRST(&ipsec.rule_queue) == 0) {
501 		if (opts & IPSECCTL_OPT_SHOWALL)
502 			printf("No flows\n");
503 		return;
504 	}
505 
506 	while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) {
507 		TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry);
508 
509 		ipsecctl_print_rule(rp, ipsec.opts);
510 
511 		free(rp->src->name);
512 		free(rp->src);
513 		free(rp->dst->name);
514 		free(rp->dst);
515 		if (rp->local) {
516 			free(rp->local->name);
517 			free(rp->local);
518 		}
519 		if (rp->peer) {
520 			free(rp->peer->name);
521 			free(rp->peer);
522 		}
523 		if (rp->auth) {
524 			free(rp->auth->srcid);
525 			free(rp->auth->dstid);
526 			free(rp->auth);
527 		}
528 		free(rp);
529 	}
530 }
531 
532 void
533 ipsecctl_show_sas(int opts)
534 {
535 	struct sadb_msg *msg;
536 	struct sad	*sad;
537 	int		 mib[5], sacount, i;
538 	size_t		 need = 0;
539 	char		*buf, *lim, *next;
540 
541 	mib[0] = CTL_NET;
542 	mib[1] = PF_KEY;
543 	mib[2] = PF_KEY_V2;
544 	mib[3] = NET_KEY_SADB_DUMP;
545 	mib[4] = SADB_SATYPE_UNSPEC;
546 
547 	if (opts & IPSECCTL_OPT_SHOWALL)
548 		ipsecctl_print_title("SAD:");
549 
550 	/* When the SAD is empty we get ENOENT, no need to err(). */
551 	if (sysctl(mib, 5, NULL, &need, NULL, 0) == -1 && errno != ENOENT)
552 		err(1, "ipsecctl_show_sas: sysctl");
553 	if (need == 0) {
554 		if (opts & IPSECCTL_OPT_SHOWALL)
555 			printf("No entries\n");
556 		return;
557 	}
558 	if ((buf = malloc(need)) == NULL)
559 		err(1, "ipsecctl_show_sas: malloc");
560 	if (sysctl(mib, 5, buf, &need, NULL, 0) == -1)
561 		err(1, "ipsecctl_show_sas: sysctl");
562 	sacount = 0;
563 	lim = buf + need;
564 	for (next = buf; next < lim;
565 	    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
566 		msg = (struct sadb_msg *)next;
567 		if (msg->sadb_msg_len == 0)
568 			break;
569 		sacount++;
570 	}
571 	if ((sad = calloc(sacount, sizeof(*sad))) == NULL)
572 		err(1, "ipsecctl_show_sas: calloc");
573 	i = 0;
574 	for (next = buf; next < lim;
575 	    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
576 		msg = (struct sadb_msg *)next;
577 		if (msg->sadb_msg_len == 0)
578 			break;
579 		sad[i].sad_spi = pfkey_get_spi(msg);
580 		sad[i].sad_msg = msg;
581 		i++;
582 	}
583 	qsort(sad, sacount, sizeof(*sad), sacompare);
584 	for (i = 0; i < sacount; i++)
585 		pfkey_print_sa(sad[i].sad_msg, opts);
586 	free(sad);
587 	free(buf);
588 }
589 
590 int
591 ipsecctl_monitor(int opts)
592 {
593 	return (pfkey_monitor(opts));
594 }
595 
596 __dead void
597 usage(void)
598 {
599 	extern char	*__progname;
600 
601 	fprintf(stderr, "usage: %s [-dFkmnv] [-D macro=value] [-f file]"
602 	    " [-i fifo] [-s modifier]\n", __progname);
603 	exit(1);
604 }
605 
606 const char *
607 ipsecctl_lookup_option(char *cmd, const char **list)
608 {
609 	if (cmd != NULL && *cmd)
610 		for (; *list; list++)
611 			if (!strncmp(cmd, *list, strlen(cmd)))
612 				return (*list);
613 	return (NULL);
614 }
615 
616 int
617 main(int argc, char *argv[])
618 {
619 	int		 error = 0;
620 	int		 ch;
621 	int		 opts = 0;
622 	char		*rulesopt = NULL;
623 
624 	if (argc < 2)
625 		usage();
626 
627 	while ((ch = getopt(argc, argv, "D:df:Fi:kmnvs:")) != -1) {
628 		switch (ch) {
629 		case 'D':
630 			if (cmdline_symset(optarg) < 0)
631 				warnx("could not parse macro definition %s",
632 				    optarg);
633 			break;
634 
635 		case 'd':
636 			opts |= IPSECCTL_OPT_DELETE;
637 			break;
638 
639 		case 'f':
640 			rulesopt = optarg;
641 			break;
642 
643 		case 'F':
644 			opts |= IPSECCTL_OPT_FLUSH;
645 			break;
646 
647 		case 'i':
648 			isakmpd_fifo = optarg;
649 			break;
650 
651 		case 'k':
652 			opts |= IPSECCTL_OPT_SHOWKEY;
653 			break;
654 
655 		case 'm':
656 			opts |= IPSECCTL_OPT_MONITOR;
657 			break;
658 
659 		case 'n':
660 			opts |= IPSECCTL_OPT_NOACTION;
661 			break;
662 
663 		case 'v':
664 			if (opts & IPSECCTL_OPT_VERBOSE)
665 				opts |= IPSECCTL_OPT_VERBOSE2;
666 			opts |= IPSECCTL_OPT_VERBOSE;
667 			break;
668 
669 		case 's':
670 			showopt = ipsecctl_lookup_option(optarg, showopt_list);
671 			if (showopt == NULL) {
672 				warnx("Unknown show modifier '%s'", optarg);
673 				usage();
674 				/* NOTREACHED */
675 			}
676 			opts |= IPSECCTL_OPT_SHOW;
677 			break;
678 
679 		default:
680 			usage();
681 			/* NOTREACHED */
682 		}
683 	}
684 
685 	if (argc != optind) {
686 		warnx("unknown command line argument: %s ...", argv[optind]);
687 		usage();
688 		/* NOTREACHED */
689 	}
690 	if (opts & IPSECCTL_OPT_FLUSH)
691 		if (ipsecctl_flush(opts))
692 			error = 1;
693 
694 	if (rulesopt != NULL)
695 		if (ipsecctl_rules(rulesopt, opts))
696 			error = 1;
697 
698 	if (showopt != NULL) {
699 		switch (*showopt) {
700 		case 'f':
701 			ipsecctl_show_flows(opts);
702 			break;
703 		case 's':
704 			ipsecctl_show_sas(opts);
705 			break;
706 		case 'a':
707 			opts |= IPSECCTL_OPT_SHOWALL;
708 			ipsecctl_show_flows(opts);
709 			ipsecctl_show_sas(opts);
710 		}
711 	}
712 
713 	if (opts & IPSECCTL_OPT_MONITOR)
714 		if (ipsecctl_monitor(opts))
715 			error = 1;
716 
717 	exit(error);
718 }
719 
720 /* ARGSUSED1 */
721 static int
722 unmask(struct ipsec_addr *ipa, sa_family_t af)
723 {
724 	int		i = 31, j = 0, b = 0;
725 	u_int32_t	tmp;
726 
727 	while (j < 4 && ipa->addr32[j] == 0xffffffff) {
728 		b += 32;
729 		j++;
730 	}
731 	if (j < 4) {
732 		tmp = ntohl(ipa->addr32[j]);
733 		for (i = 31; tmp & (1 << i); --i)
734 			b++;
735 	}
736 	return (b);
737 }
738