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