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