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