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