1 /* $OpenBSD: ipsecctl.c,v 1.84 2018/09/07 12:43:30 kn 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 /* ARGSUSED1 */ 507 void 508 ipsecctl_print_sa(struct ipsec_rule *r, int opts) 509 { 510 printf("%s ", satype[r->satype]); 511 /* tunnel/transport is only meaningful for esp/ah/ipcomp */ 512 if (r->satype != IPSEC_TCPMD5 && r->satype != IPSEC_IPIP) 513 printf("%s ", tmode[r->tmode]); 514 printf("from "); 515 ipsecctl_print_addr(r->src); 516 printf(" to "); 517 ipsecctl_print_addr(r->dst); 518 printf(" spi 0x%08x", r->spi); 519 520 if (r->satype != IPSEC_TCPMD5) { 521 if (r->xfs && r->xfs->authxf) 522 printf(" auth %s", r->xfs->authxf->name); 523 if (r->xfs && r->xfs->encxf) 524 printf(" enc %s", r->xfs->encxf->name); 525 if (r->xfs && r->xfs->compxf) 526 printf(" comp %s", r->xfs->compxf->name); 527 } 528 if (r->authkey && (opts & IPSECCTL_OPT_SHOWKEY)) { 529 if (r->satype == IPSEC_TCPMD5) 530 printf(" "); 531 else 532 printf(" \\\n\t"); 533 printf("authkey 0x"); 534 ipsecctl_print_key(r->authkey); 535 } 536 if (r->enckey && (opts & IPSECCTL_OPT_SHOWKEY)) { 537 if (r->satype == IPSEC_TCPMD5) 538 printf(" "); 539 else 540 printf(" \\\n\t"); 541 printf("enckey 0x"); 542 ipsecctl_print_key(r->enckey); 543 } 544 printf("\n"); 545 } 546 547 void 548 ipsecctl_print_sabundle(struct ipsec_rule *r, int opts) 549 { 550 printf("[bundle %s to ", satype[r->proto]); 551 ipsecctl_print_addr(r->dst); 552 printf(" spi 0x%08x with %s to ", r->spi, satype[r->proto2]); 553 ipsecctl_print_addr(r->dst2); 554 printf(" spi 0x%08x", r->spi2); 555 556 printf("]\n"); 557 } 558 559 void 560 ipsecctl_print_rule(struct ipsec_rule *r, int opts) 561 { 562 struct ipsec_rule *r2; 563 564 if (opts & IPSECCTL_OPT_VERBOSE2) { 565 printf("@%d", r->nr); 566 if (opts & IPSECCTL_OPT_COLLAPSE) { 567 TAILQ_FOREACH(r2, &r->collapsed_rules, bundle_entry) { 568 printf(",%d", r2->nr); 569 } 570 } 571 printf(" "); 572 } 573 574 if (r->type & RULE_FLOW) 575 ipsecctl_print_flow(r, opts); 576 if (r->type & RULE_SA) 577 ipsecctl_print_sa(r, opts); 578 if (r->type & RULE_IKE) 579 ike_print_config(r, opts); 580 if (r->type & RULE_BUNDLE) 581 ipsecctl_print_sabundle(r, opts); 582 } 583 584 int 585 ipsecctl_flush(int opts) 586 { 587 if (opts & IPSECCTL_OPT_NOACTION) 588 return (0); 589 590 if (pfkey_init() == -1) 591 errx(1, "ipsecctl_flush: failed to open PF_KEY socket"); 592 593 if (pfkey_ipsec_flush() == -1) 594 errx(1, "ipsecctl_flush: failed to flush"); 595 596 return (0); 597 } 598 599 void 600 ipsecctl_get_rules(struct ipsecctl *ipsec) 601 { 602 struct sadb_msg *msg; 603 struct ipsec_rule *rule, *last = NULL; 604 int mib[4]; 605 size_t need; 606 char *buf, *lim, *next; 607 608 mib[0] = CTL_NET; 609 mib[1] = PF_KEY; 610 mib[2] = PF_KEY_V2; 611 mib[3] = NET_KEY_SPD_DUMP; 612 613 if (sysctl(mib, 4, NULL, &need, NULL, 0) == -1) 614 err(1, "ipsecctl_get_rules: sysctl"); 615 if (need == 0) 616 return; 617 if ((buf = malloc(need)) == NULL) 618 err(1, "ipsecctl_get_rules: malloc"); 619 if (sysctl(mib, 4, buf, &need, NULL, 0) == -1) 620 err(1, "ipsecctl_get_rules: sysctl"); 621 lim = buf + need; 622 623 for (next = buf; next < lim; next += msg->sadb_msg_len * 624 PFKEYV2_CHUNK) { 625 msg = (struct sadb_msg *)next; 626 if (msg->sadb_msg_len == 0) 627 break; 628 629 rule = calloc(1, sizeof(struct ipsec_rule)); 630 if (rule == NULL) 631 err(1, "ipsecctl_get_rules: calloc"); 632 rule->nr = ipsec->rule_nr++; 633 rule->type |= RULE_FLOW; 634 TAILQ_INIT(&rule->collapsed_rules); 635 636 if (pfkey_parse(msg, rule)) 637 errx(1, "ipsecctl_get_rules: " 638 "failed to parse PF_KEY message"); 639 640 /* 641 * Try to collapse ``rule'' with the last enqueued rule. 642 * 643 * Note that comparing only the last entry works only if 644 * the dump is sorted. 645 */ 646 if ((ipsec->opts & IPSECCTL_OPT_COLLAPSE) && (last != NULL) && 647 (ipsecctl_merge_rules(last, rule) == 0)) 648 continue; 649 650 ipsecctl_add_rule(ipsec, rule); 651 last = rule; 652 } 653 654 free(buf); 655 } 656 657 void 658 ipsecctl_print_title(char *title) 659 { 660 if (!first_title) 661 printf("\n"); 662 first_title = 0; 663 printf("%s\n", title); 664 } 665 666 void 667 ipsecctl_show_flows(int opts) 668 { 669 struct ipsecctl ipsec; 670 struct ipsec_rule *rp; 671 672 bzero(&ipsec, sizeof(ipsec)); 673 ipsec.opts = opts; 674 TAILQ_INIT(&ipsec.rule_queue); 675 676 ipsecctl_get_rules(&ipsec); 677 678 if (opts & IPSECCTL_OPT_SHOWALL) 679 ipsecctl_print_title("FLOWS:"); 680 681 if (TAILQ_FIRST(&ipsec.rule_queue) == 0) { 682 if (opts & IPSECCTL_OPT_SHOWALL) 683 printf("No flows\n"); 684 return; 685 } 686 687 while ((rp = TAILQ_FIRST(&ipsec.rule_queue))) { 688 TAILQ_REMOVE(&ipsec.rule_queue, rp, rule_entry); 689 690 ipsecctl_print_rule(rp, ipsec.opts); 691 692 free(rp->src->name); 693 free(rp->src); 694 free(rp->dst->name); 695 free(rp->dst); 696 if (rp->local) { 697 free(rp->local->name); 698 free(rp->local); 699 } 700 if (rp->peer) { 701 free(rp->peer->name); 702 free(rp->peer); 703 } 704 if (rp->auth) { 705 free(rp->auth->srcid); 706 free(rp->auth->dstid); 707 free(rp->auth); 708 } 709 free(rp); 710 } 711 } 712 713 void 714 ipsecctl_show_sas(int opts) 715 { 716 struct sadb_msg *msg; 717 struct sad *sad; 718 int mib[5], sacount, i; 719 size_t need = 0; 720 char *buf, *lim, *next; 721 722 mib[0] = CTL_NET; 723 mib[1] = PF_KEY; 724 mib[2] = PF_KEY_V2; 725 mib[3] = NET_KEY_SADB_DUMP; 726 mib[4] = SADB_SATYPE_UNSPEC; 727 728 if (opts & IPSECCTL_OPT_SHOWALL) 729 ipsecctl_print_title("SAD:"); 730 731 /* When the SAD is empty we get ENOENT, no need to err(). */ 732 if (sysctl(mib, 5, NULL, &need, NULL, 0) == -1 && errno != ENOENT) 733 err(1, "ipsecctl_show_sas: sysctl"); 734 if (need == 0) { 735 if (opts & IPSECCTL_OPT_SHOWALL) 736 printf("No entries\n"); 737 return; 738 } 739 if ((buf = malloc(need)) == NULL) 740 err(1, "ipsecctl_show_sas: malloc"); 741 if (sysctl(mib, 5, buf, &need, NULL, 0) == -1) 742 err(1, "ipsecctl_show_sas: sysctl"); 743 sacount = 0; 744 lim = buf + need; 745 for (next = buf; next < lim; 746 next += msg->sadb_msg_len * PFKEYV2_CHUNK) { 747 msg = (struct sadb_msg *)next; 748 if (msg->sadb_msg_len == 0) 749 break; 750 sacount++; 751 } 752 if ((sad = calloc(sacount, sizeof(*sad))) == NULL) 753 err(1, "ipsecctl_show_sas: calloc"); 754 i = 0; 755 for (next = buf; next < lim; 756 next += msg->sadb_msg_len * PFKEYV2_CHUNK) { 757 msg = (struct sadb_msg *)next; 758 if (msg->sadb_msg_len == 0) 759 break; 760 sad[i].sad_spi = pfkey_get_spi(msg); 761 sad[i].sad_msg = msg; 762 i++; 763 } 764 qsort(sad, sacount, sizeof(*sad), sacompare); 765 for (i = 0; i < sacount; i++) 766 pfkey_print_sa(sad[i].sad_msg, opts); 767 free(sad); 768 free(buf); 769 } 770 771 int 772 ipsecctl_monitor(int opts) 773 { 774 return (pfkey_monitor(opts)); 775 } 776 777 __dead void 778 usage(void) 779 { 780 extern char *__progname; 781 782 fprintf(stderr, "usage: %s [-cdFkmnv] [-D macro=value] [-f file]" 783 " [-i fifo] [-s modifier]\n", __progname); 784 exit(1); 785 } 786 787 const char * 788 ipsecctl_lookup_option(char *cmd, const char **list) 789 { 790 if (cmd != NULL && *cmd) 791 for (; *list; list++) 792 if (!strncmp(cmd, *list, strlen(cmd))) 793 return (*list); 794 return (NULL); 795 } 796 797 int 798 main(int argc, char *argv[]) 799 { 800 int error = 0; 801 int ch; 802 int opts = 0; 803 char *rulesopt = NULL; 804 805 if (argc < 2) 806 usage(); 807 808 while ((ch = getopt(argc, argv, "cD:df:Fi:kmnvs:")) != -1) { 809 switch (ch) { 810 case 'c': 811 opts |= IPSECCTL_OPT_COLLAPSE; 812 break; 813 814 case 'D': 815 if (cmdline_symset(optarg) < 0) 816 warnx("could not parse macro definition %s", 817 optarg); 818 break; 819 820 case 'd': 821 opts |= IPSECCTL_OPT_DELETE; 822 break; 823 824 case 'f': 825 rulesopt = optarg; 826 break; 827 828 case 'F': 829 opts |= IPSECCTL_OPT_FLUSH; 830 break; 831 832 case 'i': 833 isakmpd_fifo = optarg; 834 break; 835 836 case 'k': 837 opts |= IPSECCTL_OPT_SHOWKEY; 838 break; 839 840 case 'm': 841 opts |= IPSECCTL_OPT_MONITOR; 842 break; 843 844 case 'n': 845 opts |= IPSECCTL_OPT_NOACTION; 846 break; 847 848 case 'v': 849 if (opts & IPSECCTL_OPT_VERBOSE) 850 opts |= IPSECCTL_OPT_VERBOSE2; 851 opts |= IPSECCTL_OPT_VERBOSE; 852 break; 853 854 case 's': 855 showopt = ipsecctl_lookup_option(optarg, showopt_list); 856 if (showopt == NULL) { 857 warnx("Unknown show modifier '%s'", optarg); 858 usage(); 859 /* NOTREACHED */ 860 } 861 opts |= IPSECCTL_OPT_SHOW; 862 break; 863 864 default: 865 usage(); 866 /* NOTREACHED */ 867 } 868 } 869 870 if (argc != optind) { 871 warnx("unknown command line argument: %s ...", argv[optind]); 872 usage(); 873 /* NOTREACHED */ 874 } 875 if (opts & IPSECCTL_OPT_FLUSH) 876 if (ipsecctl_flush(opts)) 877 error = 1; 878 879 if (rulesopt != NULL) 880 if (ipsecctl_rules(rulesopt, opts)) 881 error = 1; 882 883 if (showopt != NULL) { 884 switch (*showopt) { 885 case 'f': 886 ipsecctl_show_flows(opts); 887 break; 888 case 's': 889 ipsecctl_show_sas(opts); 890 break; 891 case 'a': 892 opts |= IPSECCTL_OPT_SHOWALL; 893 ipsecctl_show_flows(opts); 894 ipsecctl_show_sas(opts); 895 } 896 } 897 898 if (opts & IPSECCTL_OPT_MONITOR) 899 if (ipsecctl_monitor(opts)) 900 error = 1; 901 902 exit(error); 903 } 904 905 static int 906 unmask(struct ipsec_addr *ipa) 907 { 908 int i = 31, j = 0, b = 0; 909 u_int32_t tmp; 910 911 while (j < 4 && ipa->addr32[j] == 0xffffffff) { 912 b += 32; 913 j++; 914 } 915 if (j < 4) { 916 tmp = ntohl(ipa->addr32[j]); 917 for (i = 31; tmp & (1 << i); --i) 918 b++; 919 } 920 return (b); 921 } 922