1 /* $OpenBSD: ipsecctl.c,v 1.86 2023/10/09 15:32:14 tobhe 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 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 char * 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 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 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 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", 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 (sbuf != NULL) { 751 if (opts & IPSECCTL_OPT_SHOWALL) 752 ipsecctl_print_title("SAD:"); 753 754 sacount = 0; 755 lim = sbuf + need; 756 for (next = sbuf; next < lim; 757 next += msg->sadb_msg_len * PFKEYV2_CHUNK) { 758 msg = (struct sadb_msg *)next; 759 if (msg->sadb_msg_len == 0) 760 break; 761 sacount++; 762 } 763 if ((sad = calloc(sacount, sizeof(*sad))) == NULL) 764 err(1, "ipsecctl_show: calloc"); 765 i = 0; 766 for (next = sbuf; next < lim; 767 next += msg->sadb_msg_len * PFKEYV2_CHUNK) { 768 msg = (struct sadb_msg *)next; 769 if (msg->sadb_msg_len == 0) 770 break; 771 sad[i].sad_spi = pfkey_get_spi(msg); 772 sad[i].sad_msg = msg; 773 i++; 774 } 775 qsort(sad, sacount, sizeof(*sad), sacompare); 776 for (i = 0; i < sacount; i++) 777 pfkey_print_sa(sad[i].sad_msg, opts); 778 free(sad); 779 free(sbuf); 780 } else if (opts & IPSECCTL_OPT_SHOWALL) { 781 ipsecctl_print_title("SAD:"); 782 printf("No entries\n"); 783 } 784 } 785 786 int 787 ipsecctl_monitor(int opts) 788 { 789 return (pfkey_monitor(opts)); 790 } 791 792 __dead void 793 usage(void) 794 { 795 extern char *__progname; 796 797 fprintf(stderr, "usage: %s [-cdFkmnv] [-D macro=value] [-f file]" 798 " [-i fifo] [-s modifier]\n", __progname); 799 exit(1); 800 } 801 802 const char * 803 ipsecctl_lookup_option(char *cmd, const char **list) 804 { 805 if (cmd != NULL && *cmd) 806 for (; *list; list++) 807 if (!strncmp(cmd, *list, strlen(cmd))) 808 return (*list); 809 return (NULL); 810 } 811 812 int 813 main(int argc, char *argv[]) 814 { 815 int error = 0; 816 int ch; 817 int opts = 0; 818 char *rulesopt = NULL; 819 820 if (argc < 2) 821 usage(); 822 823 while ((ch = getopt(argc, argv, "cD:df:Fi:kmnvs:")) != -1) { 824 switch (ch) { 825 case 'c': 826 opts |= IPSECCTL_OPT_COLLAPSE; 827 break; 828 829 case 'D': 830 if (cmdline_symset(optarg) < 0) 831 warnx("could not parse macro definition %s", 832 optarg); 833 break; 834 835 case 'd': 836 opts |= IPSECCTL_OPT_DELETE; 837 break; 838 839 case 'f': 840 rulesopt = optarg; 841 break; 842 843 case 'F': 844 opts |= IPSECCTL_OPT_FLUSH; 845 break; 846 847 case 'i': 848 isakmpd_fifo = optarg; 849 break; 850 851 case 'k': 852 opts |= IPSECCTL_OPT_SHOWKEY; 853 break; 854 855 case 'm': 856 opts |= IPSECCTL_OPT_MONITOR; 857 break; 858 859 case 'n': 860 opts |= IPSECCTL_OPT_NOACTION; 861 break; 862 863 case 'v': 864 if (opts & IPSECCTL_OPT_VERBOSE) 865 opts |= IPSECCTL_OPT_VERBOSE2; 866 opts |= IPSECCTL_OPT_VERBOSE; 867 break; 868 869 case 's': 870 showopt = ipsecctl_lookup_option(optarg, showopt_list); 871 if (showopt == NULL) { 872 warnx("Unknown show modifier '%s'", optarg); 873 usage(); 874 /* NOTREACHED */ 875 } 876 opts |= IPSECCTL_OPT_SHOW; 877 break; 878 879 default: 880 usage(); 881 /* NOTREACHED */ 882 } 883 } 884 885 if (argc != optind) { 886 warnx("unknown command line argument: %s ...", argv[optind]); 887 usage(); 888 /* NOTREACHED */ 889 } 890 if (opts & IPSECCTL_OPT_FLUSH) 891 if (ipsecctl_flush(opts)) 892 error = 1; 893 894 if (rulesopt != NULL) 895 if (ipsecctl_rules(rulesopt, opts)) 896 error = 1; 897 898 if (showopt != NULL) { 899 switch (*showopt) { 900 case 'f': 901 opts |= IPSECCTL_OPT_SHOWFLOWS; 902 break; 903 case 's': 904 opts |= IPSECCTL_OPT_SHOWSAS; 905 break; 906 case 'a': 907 opts |= IPSECCTL_OPT_SHOWFLOWS; 908 opts |= IPSECCTL_OPT_SHOWSAS; 909 opts |= IPSECCTL_OPT_SHOWALL; 910 break; 911 } 912 ipsecctl_show(opts); 913 } 914 915 if (opts & IPSECCTL_OPT_MONITOR) 916 if (ipsecctl_monitor(opts)) 917 error = 1; 918 919 exit(error); 920 } 921 922 static int 923 unmask(struct ipsec_addr *ipa) 924 { 925 int i = 31, j = 0, b = 0; 926 u_int32_t tmp; 927 928 while (j < 4 && ipa->addr32[j] == 0xffffffff) { 929 b += 32; 930 j++; 931 } 932 if (j < 4) { 933 tmp = ntohl(ipa->addr32[j]); 934 for (i = 31; tmp & (1 << i); --i) 935 b++; 936 } 937 return (b); 938 } 939