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