xref: /openbsd/sbin/ipsecctl/ipsecctl.c (revision 4ecd42c0)
1 /*	$OpenBSD: ipsecctl.c,v 1.88 2024/02/06 05:39:28 yasuoka 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 char		*ipsecctl_get_rules(struct ipsecctl *, size_t *);
61 void		 ipsecctl_parse_rules(struct ipsecctl *, char *, size_t);
62 void		 ipsecctl_print_title(char *);
63 void		 ipsecctl_show(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
sacompare(const void * va,const void * vb)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
ipsecctl_rules(char * filename,int opts)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 *
ipsecctl_fopen(const char * name,const char * mode)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
ipsecctl_commit(int action,struct ipsecctl * ipsec)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
ipsecctl_add_rule(struct ipsecctl * ipsec,struct ipsec_rule * r)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
ipsecctl_free_rule(struct ipsec_rule * rp)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
ipsecctl_merge_rules(struct ipsec_rule * to,struct ipsec_rule * from)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
ipsecctl_cmp_ident(struct ipsec_rule * r1,struct ipsec_rule * r2)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
ipsecctl_rule_matchsrc(struct ipsec_rule * r,struct ipsec_addr_wrap * src)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
ipsecctl_rule_matchdst(struct ipsec_rule * r,struct ipsec_addr_wrap * dst)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
ipsecctl_print_addr(struct ipsec_addr_wrap * ipa)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
ipsecctl_print_proto(u_int8_t proto)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
ipsecctl_print_port(u_int16_t port,const char * proto)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
ipsecctl_print_key(struct ipsec_key * key)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
ipsecctl_print_flow(struct ipsec_rule * r,int opts)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
ipsecctl_print_sa(struct ipsec_rule * r,int opts)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
ipsecctl_print_sabundle(struct ipsec_rule * r,int opts)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
ipsecctl_print_rule(struct ipsec_rule * r,int opts)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
ipsecctl_flush(int opts)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 char *
ipsecctl_get_rules(struct ipsecctl * ipsec,size_t * need)599 ipsecctl_get_rules(struct ipsecctl *ipsec, size_t *need)
600 {
601 	int		 mib[4];
602 	char		*buf;
603 
604 	mib[0] = CTL_NET;
605 	mib[1] = PF_KEY;
606 	mib[2] = PF_KEY_V2;
607 	mib[3] = NET_KEY_SPD_DUMP;
608 
609 	if (sysctl(mib, 4, NULL, need, NULL, 0) == -1)
610 		err(1, "ipsecctl_get_rules: sysctl");
611 	if (*need == 0)
612 		return NULL;
613 	if ((buf = malloc(*need)) == NULL)
614 		err(1, "ipsecctl_get_rules: malloc");
615 	if (sysctl(mib, 4, buf, need, NULL, 0) == -1)
616 		err(1, "ipsecctl_get_rules: sysctl");
617 
618 	return buf;
619 }
620 
621 void
ipsecctl_parse_rules(struct ipsecctl * ipsec,char * buf,size_t need)622 ipsecctl_parse_rules(struct ipsecctl *ipsec, char *buf, size_t need)
623 {
624 	struct sadb_msg *msg;
625 	struct ipsec_rule *rule, *last = NULL;
626 	char		*lim, *next;
627 
628 	lim = buf + need;
629 	for (next = buf; next < lim; next += msg->sadb_msg_len *
630 	    PFKEYV2_CHUNK) {
631 		msg = (struct sadb_msg *)next;
632 		if (msg->sadb_msg_len == 0)
633 			break;
634 
635 		rule = calloc(1, sizeof(struct ipsec_rule));
636 		if (rule == NULL)
637 			err(1, "ipsecctl_parse_rules: calloc");
638 		rule->nr = ipsec->rule_nr++;
639 		rule->type |= RULE_FLOW;
640 		TAILQ_INIT(&rule->collapsed_rules);
641 
642 		if (pfkey_parse(msg, rule))
643 			errx(1, "ipsecctl_parse_rules: "
644 			    "failed to parse PF_KEY message");
645 
646 		/*
647 		 * Try to collapse ``rule'' with the last enqueued rule.
648 		 *
649 		 * Note that comparing only the last entry works only if
650 		 * the dump is sorted.
651 		 */
652 		if ((ipsec->opts & IPSECCTL_OPT_COLLAPSE) && (last != NULL) &&
653 		    (ipsecctl_merge_rules(last, rule) == 0))
654 			continue;
655 
656 		ipsecctl_add_rule(ipsec, rule);
657 		last = rule;
658 	}
659 
660 	free(buf);
661 }
662 
663 void
ipsecctl_print_title(char * title)664 ipsecctl_print_title(char *title)
665 {
666 	if (!first_title)
667 		printf("\n");
668 	first_title = 0;
669 	printf("%s\n", title);
670 }
671 
672 void
ipsecctl_show(int opts)673 ipsecctl_show(int opts)
674 {
675 	struct ipsecctl ipsec;
676 	struct ipsec_rule *rp;
677 	struct sadb_msg *msg;
678 	struct sad	*sad;
679 	int		 mib[5], sacount, i;
680 	size_t		 need = 0, rlen;
681 	char		*sbuf = NULL, *rbuf = NULL, *lim, *next;
682 
683 	if (opts & IPSECCTL_OPT_SHOWFLOWS) {
684 		bzero(&ipsec, sizeof(ipsec));
685 		ipsec.opts = opts;
686 		TAILQ_INIT(&ipsec.rule_queue);
687 		rbuf = ipsecctl_get_rules(&ipsec, &rlen);
688 	}
689 
690 	if (opts & IPSECCTL_OPT_SHOWSAS) {
691 		mib[0] = CTL_NET;
692 		mib[1] = PF_KEY;
693 		mib[2] = PF_KEY_V2;
694 		mib[3] = NET_KEY_SADB_DUMP;
695 		mib[4] = SADB_SATYPE_UNSPEC;
696 
697 		/* When the SAD is empty we get ENOENT, no need to err(). */
698 		if (sysctl(mib, 5, NULL, &need, NULL, 0) == -1 &&
699 		    errno != ENOENT)
700 			err(1, "ipsecctl_show: sysctl");
701 		if (need > 0) {
702 			if ((sbuf = malloc(need)) == NULL)
703 				err(1, "ipsecctl_show: malloc");
704 			if (sysctl(mib, 5, sbuf, &need, NULL, 0) == -1)
705 				err(1, "ipsecctl_show: sysctl");
706 		}
707 	}
708 
709 	if (pledge("stdio dns", NULL) == -1)
710 		err(1, "pledge");
711 
712 	if (rbuf != NULL) {
713 		ipsecctl_parse_rules(&ipsec, rbuf, rlen);
714 
715 		if (opts & IPSECCTL_OPT_SHOWALL)
716 			ipsecctl_print_title("FLOWS:");
717 
718 		if (TAILQ_FIRST(&ipsec.rule_queue) != NULL) {
719 			while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) {
720 				TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry);
721 
722 				ipsecctl_print_rule(rp, ipsec.opts);
723 
724 				free(rp->src->name);
725 				free(rp->src);
726 				free(rp->dst->name);
727 				free(rp->dst);
728 				if (rp->local) {
729 					free(rp->local->name);
730 					free(rp->local);
731 				}
732 				if (rp->peer) {
733 					free(rp->peer->name);
734 					free(rp->peer);
735 				}
736 				if (rp->auth) {
737 					free(rp->auth->srcid);
738 					free(rp->auth->dstid);
739 					free(rp->auth);
740 				}
741 				free(rp);
742 			}
743 		}
744 	} else if (opts & IPSECCTL_OPT_SHOWALL) {
745 		ipsecctl_print_title("FLOWS:");
746 		if (opts & IPSECCTL_OPT_SHOWALL)
747 			printf("No flows\n");
748 	}
749 
750 	if (pledge("stdio", NULL) == -1)
751 		err(1, "pledge");
752 
753 	if (sbuf != NULL) {
754 		if (opts & IPSECCTL_OPT_SHOWALL)
755 			ipsecctl_print_title("SAD:");
756 
757 		sacount = 0;
758 		lim = sbuf + need;
759 		for (next = sbuf; next < lim;
760 		    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
761 			msg = (struct sadb_msg *)next;
762 			if (msg->sadb_msg_len == 0)
763 				break;
764 			sacount++;
765 		}
766 		if ((sad = calloc(sacount, sizeof(*sad))) == NULL)
767 			err(1, "ipsecctl_show: calloc");
768 		i = 0;
769 		for (next = sbuf; next < lim;
770 		    next += msg->sadb_msg_len * PFKEYV2_CHUNK) {
771 			msg = (struct sadb_msg *)next;
772 			if (msg->sadb_msg_len == 0)
773 				break;
774 			sad[i].sad_spi = pfkey_get_spi(msg);
775 			sad[i].sad_msg = msg;
776 			i++;
777 		}
778 		qsort(sad, sacount, sizeof(*sad), sacompare);
779 		for (i = 0; i < sacount; i++)
780 			pfkey_print_sa(sad[i].sad_msg, opts);
781 		free(sad);
782 		free(sbuf);
783 	} else if (opts & IPSECCTL_OPT_SHOWALL) {
784 		ipsecctl_print_title("SAD:");
785 		printf("No entries\n");
786 	}
787 }
788 
789 int
ipsecctl_monitor(int opts)790 ipsecctl_monitor(int opts)
791 {
792 	return (pfkey_monitor(opts));
793 }
794 
795 __dead void
usage(void)796 usage(void)
797 {
798 	extern char	*__progname;
799 
800 	fprintf(stderr, "usage: %s [-cdFkmnv] [-D macro=value] [-f file]"
801 	    " [-i fifo] [-s modifier]\n", __progname);
802 	exit(1);
803 }
804 
805 const char *
ipsecctl_lookup_option(char * cmd,const char ** list)806 ipsecctl_lookup_option(char *cmd, const char **list)
807 {
808 	if (cmd != NULL && *cmd)
809 		for (; *list; list++)
810 			if (!strncmp(cmd, *list, strlen(cmd)))
811 				return (*list);
812 	return (NULL);
813 }
814 
815 int
main(int argc,char * argv[])816 main(int argc, char *argv[])
817 {
818 	int		 error = 0;
819 	int		 ch;
820 	int		 opts = 0;
821 	char		*rulesopt = NULL;
822 
823 	if (argc < 2)
824 		usage();
825 
826 	while ((ch = getopt(argc, argv, "cD:df:Fi:kmnvs:")) != -1) {
827 		switch (ch) {
828 		case 'c':
829 			opts |= IPSECCTL_OPT_COLLAPSE;
830 			break;
831 
832 		case 'D':
833 			if (cmdline_symset(optarg) < 0)
834 				warnx("could not parse macro definition %s",
835 				    optarg);
836 			break;
837 
838 		case 'd':
839 			opts |= IPSECCTL_OPT_DELETE;
840 			break;
841 
842 		case 'f':
843 			rulesopt = optarg;
844 			break;
845 
846 		case 'F':
847 			opts |= IPSECCTL_OPT_FLUSH;
848 			break;
849 
850 		case 'i':
851 			isakmpd_fifo = optarg;
852 			break;
853 
854 		case 'k':
855 			opts |= IPSECCTL_OPT_SHOWKEY;
856 			break;
857 
858 		case 'm':
859 			opts |= IPSECCTL_OPT_MONITOR;
860 			break;
861 
862 		case 'n':
863 			opts |= IPSECCTL_OPT_NOACTION;
864 			break;
865 
866 		case 'v':
867 			if (opts & IPSECCTL_OPT_VERBOSE)
868 				opts |= IPSECCTL_OPT_VERBOSE2;
869 			opts |= IPSECCTL_OPT_VERBOSE;
870 			break;
871 
872 		case 's':
873 			showopt = ipsecctl_lookup_option(optarg, showopt_list);
874 			if (showopt == NULL) {
875 				warnx("Unknown show modifier '%s'", optarg);
876 				usage();
877 				/* NOTREACHED */
878 			}
879 			opts |= IPSECCTL_OPT_SHOW;
880 			break;
881 
882 		default:
883 			usage();
884 			/* NOTREACHED */
885 		}
886 	}
887 
888 	if (argc != optind) {
889 		warnx("unknown command line argument: %s ...", argv[optind]);
890 		usage();
891 		/* NOTREACHED */
892 	}
893 	if (opts & IPSECCTL_OPT_FLUSH)
894 		if (ipsecctl_flush(opts))
895 			error = 1;
896 
897 	if (rulesopt != NULL)
898 		if (ipsecctl_rules(rulesopt, opts))
899 			error = 1;
900 
901 	if (showopt != NULL) {
902 		switch (*showopt) {
903 		case 'f':
904 			opts |= IPSECCTL_OPT_SHOWFLOWS;
905 			break;
906 		case 's':
907 			opts |= IPSECCTL_OPT_SHOWSAS;
908 			break;
909 		case 'a':
910 			opts |= IPSECCTL_OPT_SHOWFLOWS;
911 			opts |= IPSECCTL_OPT_SHOWSAS;
912 			opts |= IPSECCTL_OPT_SHOWALL;
913 			break;
914 		}
915 		ipsecctl_show(opts);
916 	}
917 
918 	if (opts & IPSECCTL_OPT_MONITOR)
919 		if (ipsecctl_monitor(opts))
920 			error = 1;
921 
922 	exit(error);
923 }
924 
925 static int
unmask(struct ipsec_addr * ipa)926 unmask(struct ipsec_addr *ipa)
927 {
928 	int		i = 31, j = 0, b = 0;
929 	u_int32_t	tmp;
930 
931 	while (j < 4 && ipa->addr32[j] == 0xffffffff) {
932 		b += 32;
933 		j++;
934 	}
935 	if (j < 4) {
936 		tmp = ntohl(ipa->addr32[j]);
937 		for (i = 31; tmp & (1 << i); --i)
938 			b++;
939 	}
940 	return (b);
941 }
942