1 /* $KAME: setkey.c,v 1.28 2003/06/27 07:15:45 itojun Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/linker.h> 37 #include <sys/module.h> 38 #include <sys/socket.h> 39 #include <sys/time.h> 40 #include <err.h> 41 #include <net/route.h> 42 #include <netinet/in.h> 43 #include <net/pfkeyv2.h> 44 #include <netipsec/keydb.h> 45 #include <netipsec/key_debug.h> 46 #include <netipsec/ipsec.h> 47 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <limits.h> 51 #include <string.h> 52 #include <ctype.h> 53 #include <unistd.h> 54 #include <errno.h> 55 #include <netdb.h> 56 57 #include "libpfkey.h" 58 59 void usage(void); 60 int main(int, char **); 61 int get_supported(void); 62 void sendkeyshort(u_int, uint8_t); 63 void promisc(void); 64 int sendkeymsg(char *, size_t); 65 int postproc(struct sadb_msg *); 66 const char *numstr(int); 67 void shortdump_hdr(void); 68 void shortdump(struct sadb_msg *); 69 static void printdate(void); 70 static int32_t gmt2local(time_t); 71 static int modload(const char *name); 72 73 #define MODE_SCRIPT 1 74 #define MODE_CMDDUMP 2 75 #define MODE_CMDFLUSH 3 76 #define MODE_PROMISC 4 77 78 static int so; 79 80 static int f_forever = 0; 81 static int f_all = 0; 82 static int f_verbose = 0; 83 static int f_mode = 0; 84 static int f_cmddump = 0; 85 static int f_policy = 0; 86 static int f_hexdump = 0; 87 static int f_tflag = 0; 88 static int f_scope = 0; 89 static int f_notimeout = 0; 90 static time_t thiszone; 91 92 extern int lineno; 93 94 extern int parse(FILE **); 95 96 void 97 usage(void) 98 { 99 100 printf("usage: setkey [-v] -c\n"); 101 printf(" setkey [-v] -f filename\n"); 102 printf(" setkey [-v] -e \"<script>\"\n"); 103 printf(" setkey [-Pagltv] -D\n"); 104 printf(" setkey [-Pv] -F\n"); 105 printf(" setkey [-h] -x\n"); 106 exit(1); 107 } 108 109 static int 110 modload(const char *name) 111 { 112 if (modfind(name) < 0) 113 if (kldload(name) < 0 || modfind(name) < 0) { 114 warn("%s: module not found", name); 115 return 0; 116 } 117 return 1; 118 } 119 120 int 121 main(int ac, char **av) 122 { 123 FILE *fp = stdin; 124 int c; 125 126 if (ac == 1) { 127 usage(); 128 /* NOTREACHED */ 129 } 130 131 thiszone = gmt2local(0); 132 133 while ((c = getopt(ac, av, "abcde:f:ghltvxDFPZ")) != -1) { 134 switch (c) { 135 case 'c': 136 f_mode = MODE_SCRIPT; 137 fp = stdin; 138 break; 139 case 'e': 140 if (fp != stdin) { 141 err(-1, "only one -f/-e option is accepted"); 142 } 143 f_mode = MODE_SCRIPT; 144 fp = fmemopen(optarg, strlen(optarg), "r"); 145 if (fp == NULL) { 146 err(-1, "fmemopen"); 147 /*NOTREACHED*/ 148 } 149 break; 150 case 'f': 151 if (fp != stdin) { 152 err(-1, "only one -f/-e option is accepted"); 153 } 154 f_mode = MODE_SCRIPT; 155 if ((fp = fopen(optarg, "r")) == NULL) { 156 err(-1, "fopen"); 157 /*NOTREACHED*/ 158 } 159 break; 160 case 'D': 161 f_mode = MODE_CMDDUMP; 162 break; 163 case 'F': 164 f_mode = MODE_CMDFLUSH; 165 break; 166 case 'a': 167 f_all = 1; 168 break; 169 case 'l': 170 f_forever = 1; 171 break; 172 case 'h': 173 f_hexdump = 1; 174 break; 175 case 'x': 176 f_mode = MODE_PROMISC; 177 f_tflag++; 178 break; 179 case 'P': 180 f_policy = 1; 181 break; 182 case 'g': /* global */ 183 f_scope |= IPSEC_POLICYSCOPE_GLOBAL; 184 break; 185 case 't': /* tunnel */ 186 f_scope |= IPSEC_POLICYSCOPE_IFNET; 187 break; 188 case 'v': 189 f_verbose = 1; 190 break; 191 case 'Z': 192 f_notimeout = 1; 193 break; 194 default: 195 usage(); 196 /*NOTREACHED*/ 197 } 198 } 199 200 modload("ipsec"); 201 so = pfkey_open(); 202 if (so < 0) { 203 perror("pfkey_open"); 204 exit(1); 205 } 206 207 switch (f_mode) { 208 case MODE_CMDDUMP: 209 sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP, 210 f_policy ? f_scope: SADB_SATYPE_UNSPEC); 211 break; 212 case MODE_CMDFLUSH: 213 sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH, 214 SADB_SATYPE_UNSPEC); 215 break; 216 case MODE_SCRIPT: 217 if (get_supported() < 0) { 218 errx(-1, "%s", ipsec_strerror()); 219 /*NOTREACHED*/ 220 } 221 if (parse(&fp)) 222 exit (1); 223 break; 224 case MODE_PROMISC: 225 promisc(); 226 /*NOTREACHED*/ 227 default: 228 usage(); 229 /*NOTREACHED*/ 230 } 231 232 exit(0); 233 } 234 235 int 236 get_supported(void) 237 { 238 239 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) 240 return -1; 241 242 if (pfkey_recv_register(so) < 0) 243 return -1; 244 245 return 0; 246 } 247 248 void 249 sendkeyshort(u_int type, uint8_t satype) 250 { 251 struct sadb_msg msg; 252 253 msg.sadb_msg_version = PF_KEY_V2; 254 msg.sadb_msg_type = type; 255 msg.sadb_msg_errno = 0; 256 msg.sadb_msg_satype = satype; 257 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 258 msg.sadb_msg_reserved = 0; 259 msg.sadb_msg_seq = 0; 260 msg.sadb_msg_pid = getpid(); 261 262 sendkeymsg((char *)&msg, sizeof(msg)); 263 264 return; 265 } 266 267 void 268 promisc(void) 269 { 270 struct sadb_msg msg; 271 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 272 ssize_t l; 273 274 msg.sadb_msg_version = PF_KEY_V2; 275 msg.sadb_msg_type = SADB_X_PROMISC; 276 msg.sadb_msg_errno = 0; 277 msg.sadb_msg_satype = 1; 278 msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 279 msg.sadb_msg_reserved = 0; 280 msg.sadb_msg_seq = 0; 281 msg.sadb_msg_pid = getpid(); 282 283 if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 284 err(1, "send"); 285 /*NOTREACHED*/ 286 } 287 288 while (1) { 289 struct sadb_msg *base; 290 291 if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 292 err(1, "recv"); 293 /*NOTREACHED*/ 294 } 295 296 if (l != sizeof(*base)) 297 continue; 298 299 base = (struct sadb_msg *)rbuf; 300 if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 301 0)) < 0) { 302 err(1, "recv"); 303 /*NOTREACHED*/ 304 } 305 printdate(); 306 if (f_hexdump) { 307 int i; 308 for (i = 0; i < l; i++) { 309 if (i % 16 == 0) 310 printf("%08x: ", i); 311 printf("%02x ", rbuf[i] & 0xff); 312 if (i % 16 == 15) 313 printf("\n"); 314 } 315 if (l % 16) 316 printf("\n"); 317 } 318 /* adjust base pointer for promisc mode */ 319 if (base->sadb_msg_type == SADB_X_PROMISC) { 320 if ((ssize_t)sizeof(*base) < l) 321 base++; 322 else 323 base = NULL; 324 } 325 if (base) { 326 kdebug_sadb(base); 327 printf("\n"); 328 fflush(stdout); 329 } 330 } 331 } 332 333 int 334 sendkeymsg(char *buf, size_t len) 335 { 336 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 337 ssize_t l; 338 struct sadb_msg *msg; 339 struct timeval tv; 340 341 342 if (!f_notimeout) { 343 tv.tv_sec = 1; 344 tv.tv_usec = 0; 345 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, 346 sizeof(tv)) < 0) { 347 perror("setsockopt"); 348 goto end; 349 } 350 } 351 352 if (f_forever) 353 shortdump_hdr(); 354 again: 355 if (f_verbose) { 356 kdebug_sadb((struct sadb_msg *)buf); 357 printf("\n"); 358 } 359 if (f_hexdump) { 360 size_t i; 361 for (i = 0; i < len; i++) { 362 if (i % 16 == 0) 363 printf("%08x: ", (u_int)i); 364 printf("%02x ", buf[i] & 0xff); 365 if (i % 16 == 15) 366 printf("\n"); 367 } 368 if (len % 16) 369 printf("\n"); 370 } 371 372 if ((l = send(so, buf, len, 0)) < 0) { 373 perror("send"); 374 goto end; 375 } 376 377 msg = (struct sadb_msg *)rbuf; 378 do { 379 if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 380 perror("recv"); 381 goto end; 382 } 383 384 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 385 warnx("invalid keymsg length"); 386 break; 387 } 388 389 if (f_verbose) { 390 kdebug_sadb((struct sadb_msg *)rbuf); 391 printf("\n"); 392 } 393 if (postproc(msg) < 0) 394 break; 395 } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 396 397 if (f_forever) { 398 fflush(stdout); 399 sleep(1); 400 goto again; 401 } 402 403 end: 404 return(0); 405 } 406 407 int 408 postproc(struct sadb_msg *msg) 409 { 410 411 if (msg->sadb_msg_errno != 0) { 412 char inf[80]; 413 const char *errmsg = NULL; 414 415 if (f_mode == MODE_SCRIPT) 416 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 417 else 418 inf[0] = '\0'; 419 420 switch (msg->sadb_msg_errno) { 421 case ENOENT: 422 switch (msg->sadb_msg_type) { 423 case SADB_DELETE: 424 case SADB_GET: 425 case SADB_X_SPDDELETE: 426 errmsg = "No entry"; 427 break; 428 case SADB_DUMP: 429 errmsg = "No SAD entries"; 430 break; 431 case SADB_X_SPDDUMP: 432 errmsg = "No SPD entries"; 433 break; 434 } 435 break; 436 default: 437 errmsg = strerror(msg->sadb_msg_errno); 438 } 439 printf("%s%s.\n", inf, errmsg); 440 return(-1); 441 } 442 443 switch (msg->sadb_msg_type) { 444 case SADB_GET: 445 pfkey_sadump(msg); 446 break; 447 448 case SADB_DUMP: 449 /* filter out DEAD SAs */ 450 if (!f_all) { 451 caddr_t mhp[SADB_EXT_MAX + 1]; 452 struct sadb_sa *sa; 453 pfkey_align(msg, mhp); 454 pfkey_check(mhp); 455 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 456 if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 457 break; 458 } 459 } 460 if (f_forever) 461 shortdump(msg); 462 else 463 pfkey_sadump(msg); 464 msg = (struct sadb_msg *)((caddr_t)msg + 465 PFKEY_UNUNIT64(msg->sadb_msg_len)); 466 if (f_verbose) { 467 kdebug_sadb((struct sadb_msg *)msg); 468 printf("\n"); 469 } 470 break; 471 472 case SADB_X_SPDDUMP: 473 pfkey_spdump(msg); 474 if (msg->sadb_msg_seq == 0) break; 475 msg = (struct sadb_msg *)((caddr_t)msg + 476 PFKEY_UNUNIT64(msg->sadb_msg_len)); 477 if (f_verbose) { 478 kdebug_sadb((struct sadb_msg *)msg); 479 printf("\n"); 480 } 481 break; 482 } 483 484 return(0); 485 } 486 487 /*------------------------------------------------------------*/ 488 static const char *satype[] = { 489 NULL, NULL, "ah", "esp" 490 }; 491 static const char *sastate[] = { 492 "L", "M", "D", "d" 493 }; 494 static const char *ipproto[] = { 495 /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 496 NULL, "tcp", NULL, "egp", NULL, 497 /*10*/ NULL, NULL, NULL, NULL, NULL, 498 NULL, NULL, "udp", NULL, NULL, 499 /*20*/ NULL, NULL, "idp", NULL, NULL, 500 NULL, NULL, NULL, NULL, "tp", 501 /*30*/ NULL, NULL, NULL, NULL, NULL, 502 NULL, NULL, NULL, NULL, NULL, 503 /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 504 NULL, "rsvp", "gre", NULL, NULL, 505 /*50*/ "esp", "ah", NULL, NULL, NULL, 506 NULL, NULL, NULL, "icmp6", "none", 507 /*60*/ "dst6", 508 }; 509 510 #define STR_OR_ID(x, tab) \ 511 (((x) < nitems(tab) && tab[(x)]) ? tab[(x)] : numstr(x)) 512 513 const char * 514 numstr(int x) 515 { 516 static char buf[20]; 517 snprintf(buf, sizeof(buf), "#%d", x); 518 return buf; 519 } 520 521 void 522 shortdump_hdr(void) 523 { 524 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 525 "time", "p", "s", "spi", "ltime", "src", "dst"); 526 } 527 528 void 529 shortdump(struct sadb_msg *msg) 530 { 531 caddr_t mhp[SADB_EXT_MAX + 1]; 532 char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 533 struct sadb_sa *sa; 534 struct sadb_address *saddr; 535 struct sadb_lifetime *lts, *lth, *ltc; 536 struct sockaddr *s; 537 u_int t; 538 time_t cur = time(0); 539 540 pfkey_align(msg, mhp); 541 pfkey_check(mhp); 542 543 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 544 545 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 546 547 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 548 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 549 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 550 } else 551 printf("%-1s %-8s", "?", "?"); 552 553 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 554 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 555 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 556 if (lts && lth && ltc) { 557 if (ltc->sadb_lifetime_addtime == 0) 558 t = (u_long)0; 559 else 560 t = (u_long)(cur - ltc->sadb_lifetime_addtime); 561 if (t >= 1000) 562 strlcpy(buf, " big/", sizeof(buf)); 563 else 564 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 565 printf("%s", buf); 566 567 t = (u_long)lth->sadb_lifetime_addtime; 568 if (t >= 1000) 569 strlcpy(buf, "big", sizeof(buf)); 570 else 571 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 572 printf("%s", buf); 573 } else 574 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 575 576 printf(" "); 577 578 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 579 if (saddr->sadb_address_proto) 580 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 581 s = (struct sockaddr *)(saddr + 1); 582 getnameinfo(s, s->sa_len, buf, sizeof(buf), 583 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 584 if (strcmp(pbuf, "0") != 0) 585 printf("%s[%s]", buf, pbuf); 586 else 587 printf("%s", buf); 588 } else 589 printf("?"); 590 591 printf(" -> "); 592 593 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 594 if (saddr->sadb_address_proto) 595 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 596 597 s = (struct sockaddr *)(saddr + 1); 598 getnameinfo(s, s->sa_len, buf, sizeof(buf), 599 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 600 if (strcmp(pbuf, "0") != 0) 601 printf("%s[%s]", buf, pbuf); 602 else 603 printf("%s", buf); 604 } else 605 printf("?"); 606 607 printf("\n"); 608 } 609 610 /* From: tcpdump(1):gmt2local.c and util.c */ 611 /* 612 * Print the timestamp 613 */ 614 static void 615 printdate(void) 616 { 617 struct timeval tp; 618 int s; 619 620 if (gettimeofday(&tp, NULL) == -1) { 621 perror("gettimeofday"); 622 return; 623 } 624 625 if (f_tflag == 1) { 626 /* Default */ 627 s = (tp.tv_sec + thiszone ) % 86400; 628 (void)printf("%02d:%02d:%02d.%06u ", 629 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 630 } else if (f_tflag > 1) { 631 /* Unix timeval style */ 632 (void)printf("%u.%06u ", 633 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 634 } 635 636 printf("\n"); 637 } 638 639 /* 640 * Returns the difference between gmt and local time in seconds. 641 * Use gmtime() and localtime() to keep things simple. 642 */ 643 int32_t 644 gmt2local(time_t t) 645 { 646 register int dt, dir; 647 register struct tm *gmt, *loc; 648 struct tm sgmt; 649 650 if (t == 0) 651 t = time(NULL); 652 gmt = &sgmt; 653 *gmt = *gmtime(&t); 654 loc = localtime(&t); 655 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 656 (loc->tm_min - gmt->tm_min) * 60; 657 658 /* 659 * If the year or julian day is different, we span 00:00 GMT 660 * and must add or subtract a day. Check the year first to 661 * avoid problems when the julian day wraps. 662 */ 663 dir = loc->tm_year - gmt->tm_year; 664 if (dir == 0) 665 dir = loc->tm_yday - gmt->tm_yday; 666 dt += dir * 24 * 60 * 60; 667 668 return (dt); 669 } 670