1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * NOTE:I'm trying to use "struct sadb_foo" instead of "sadb_foo_t" 28 * as a maximal PF_KEY portability test. 29 * 30 * Also, this is a deliberately single-threaded app, also for portability 31 * to systems without POSIX threads. 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" 35 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <sys/socket.h> 39 #include <sys/sysmacros.h> 40 #include <sys/fcntl.h> 41 #include <net/pfkeyv2.h> 42 #include <arpa/inet.h> 43 #include <netinet/in.h> 44 #include <sys/uio.h> 45 46 #include <syslog.h> 47 #include <signal.h> 48 #include <unistd.h> 49 #include <limits.h> 50 #include <stdlib.h> 51 #include <stdio.h> 52 #include <stdarg.h> 53 #include <netdb.h> 54 #include <pwd.h> 55 #include <errno.h> 56 #include <libintl.h> 57 #include <locale.h> 58 #include <fcntl.h> 59 #include <strings.h> 60 #include <ctype.h> 61 62 #include <ipsec_util.h> 63 64 static int keysock; 65 static uint32_t seq; 66 static pid_t mypid; 67 static boolean_t vflag = B_FALSE; /* Verbose? */ 68 static boolean_t cflag = B_FALSE; /* Check Only */ 69 70 char *my_fmri = NULL; 71 FILE *debugfile = stdout; 72 73 #define MAX_GET_SIZE 1024 74 /* 75 * WARN() and ERROR() do the same thing really, with ERROR() the function 76 * that prints the error buffer needs to be called at the end of a code block 77 * This will print out all accumulated errors before bailing. The WARN() 78 * macro calls handle_errors() in such a way that it prints the message 79 * then continues. 80 * If the FATAL() macro used call handle_errors() immediately. 81 */ 82 #define ERROR(x, y, z) x = record_error(x, y, z) 83 #define ERROR1(w, x, y, z) w = record_error(w, x, y, z) 84 #define ERROR2(v, w, x, y, z) v = record_error(v, w, x, y, z) 85 #define WARN(x, y, z) ERROR(x, y, z);\ 86 handle_errors(x, NULL, B_FALSE, B_FALSE); x = NULL 87 #define WARN1(w, x, y, z) ERROR1(w, x, y, z);\ 88 handle_errors(w, NULL, B_FALSE, B_FALSE); w = NULL 89 #define WARN2(v, w, x, y, z) ERROR2(v, w, x, y, z);\ 90 handle_errors(v, NULL, B_FALSE, B_FALSE); v = NULL 91 #define FATAL(x, y, z) ERROR(x, y, z);\ 92 handle_errors(x, y, B_TRUE, B_TRUE) 93 #define FATAL1(w, x, y, z) ERROR1(w, x, y, z);\ 94 handle_errors(w, x, B_TRUE, B_TRUE) 95 96 /* Defined as a uint64_t array for alignment purposes. */ 97 static uint64_t get_buffer[MAX_GET_SIZE]; 98 99 /* 100 * Create/Grow a buffer large enough to hold error messages. If *ebuf 101 * is not NULL then it will contain a copy of the command line that 102 * triggered the error/warning, copy this into a new buffer or 103 * append new messages to the existing buffer. 104 */ 105 /*PRINTFLIKE1*/ 106 char * 107 record_error(char *ep, char *ebuf, char *fmt, ...) 108 { 109 char *err_ptr; 110 char tmp_buff[1024]; 111 va_list ap; 112 int length = 0; 113 err_ptr = ep; 114 115 va_start(ap, fmt); 116 length = vsnprintf(tmp_buff, sizeof (tmp_buff), fmt, ap); 117 va_end(ap); 118 119 /* There is a new line character */ 120 length++; 121 122 if (ep == NULL) { 123 if (ebuf != NULL) 124 length += strlen(ebuf); 125 } else { 126 length += strlen(ep); 127 } 128 129 if (err_ptr == NULL) 130 err_ptr = calloc(length, sizeof (char)); 131 else 132 err_ptr = realloc(err_ptr, length); 133 134 if (err_ptr == NULL) 135 Bail("realloc() failure"); 136 137 /* 138 * If (ep == NULL) then this is the first error to record, 139 * copy in the command line that triggered this error/warning. 140 */ 141 if (ep == NULL && ebuf != NULL) 142 (void) strlcpy(err_ptr, ebuf, length); 143 144 /* 145 * Now the actual error. 146 */ 147 (void) strlcat(err_ptr, tmp_buff, length); 148 return (err_ptr); 149 } 150 151 /* 152 * Print usage message. 153 */ 154 static void 155 usage(void) 156 { 157 if (!interactive) { 158 (void) fprintf(stderr, gettext("Usage:\t" 159 "ipseckey [ -nvp ] | cmd [sa_type] [extfield value]*\n")); 160 (void) fprintf(stderr, 161 gettext("\tipseckey [ -nvp ] -f infile\n")); 162 (void) fprintf(stderr, 163 gettext("\tipseckey [ -nvp ] -s outfile\n")); 164 } 165 EXIT_FATAL(NULL); 166 } 167 168 169 /* 170 * Print out any errors, tidy up as required. 171 * error pointer ep will be free()'d 172 */ 173 void 174 handle_errors(char *ep, char *ebuf, boolean_t fatal, boolean_t done) 175 { 176 if (ep != NULL) { 177 if (my_fmri == NULL) { 178 /* 179 * For now suppress the errors when run from smf(5) 180 * because potentially sensitive information could 181 * end up in a publicly readable logfile. 182 */ 183 (void) fprintf(stdout, "%s\n", ep); 184 (void) fflush(stdout); 185 } 186 free(ep); 187 if (fatal) { 188 if (ebuf != NULL) { 189 free(ebuf); 190 } 191 /* reset command buffer */ 192 if (interactive) 193 longjmp(env, 1); 194 } else { 195 return; 196 } 197 } else { 198 /* 199 * No errors, if this is the last time that this function 200 * is called, free(ebuf) and reset command buffer. 201 */ 202 if (done) { 203 if (ebuf != NULL) { 204 free(ebuf); 205 } 206 /* reset command buffer */ 207 if (interactive) 208 longjmp(env, 1); 209 } 210 return; 211 } 212 EXIT_FATAL(NULL); 213 } 214 215 /* 216 * Initialize a PF_KEY base message. 217 */ 218 static void 219 msg_init(struct sadb_msg *msg, uint8_t type, uint8_t satype) 220 { 221 msg->sadb_msg_version = PF_KEY_V2; 222 msg->sadb_msg_type = type; 223 msg->sadb_msg_errno = 0; 224 msg->sadb_msg_satype = satype; 225 /* For starters... */ 226 msg->sadb_msg_len = SADB_8TO64(sizeof (*msg)); 227 msg->sadb_msg_reserved = 0; 228 msg->sadb_msg_seq = ++seq; 229 msg->sadb_msg_pid = mypid; 230 } 231 232 /* 233 * parseXXX and rparseXXX commands parse input and convert them to PF_KEY 234 * field values, or do the reverse for the purposes of saving the SA tables. 235 * (See the save_XXX functions.) 236 */ 237 238 #define CMD_NONE 0 239 #define CMD_UPDATE 2 240 #define CMD_ADD 3 241 #define CMD_DELETE 4 242 #define CMD_GET 5 243 #define CMD_FLUSH 9 244 #define CMD_DUMP 10 245 #define CMD_MONITOR 11 246 #define CMD_PMONITOR 12 247 #define CMD_QUIT 13 248 #define CMD_SAVE 14 249 #define CMD_HELP 15 250 251 /* 252 * Parse the command. 253 */ 254 static int 255 parsecmd(char *cmdstr) 256 { 257 static struct cmdtable { 258 char *cmd; 259 int token; 260 } table[] = { 261 /* 262 * Q: Do we want to do GETSPI? 263 * A: No, it's for automated key mgmt. only. Either that, 264 * or it isn't relevant until we support non IPsec SA types. 265 */ 266 {"update", CMD_UPDATE}, 267 {"add", CMD_ADD}, 268 {"delete", CMD_DELETE}, 269 {"get", CMD_GET}, 270 /* 271 * Q: And ACQUIRE and REGISTER and EXPIRE? 272 * A: not until we support non IPsec SA types. 273 */ 274 {"flush", CMD_FLUSH}, 275 {"dump", CMD_DUMP}, 276 {"monitor", CMD_MONITOR}, 277 {"passive_monitor", CMD_PMONITOR}, 278 {"pmonitor", CMD_PMONITOR}, 279 {"quit", CMD_QUIT}, 280 {"exit", CMD_QUIT}, 281 {"save", CMD_SAVE}, 282 {"help", CMD_HELP}, 283 {"?", CMD_HELP}, 284 {NULL, CMD_NONE} 285 }; 286 struct cmdtable *ct = table; 287 288 while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0) 289 ct++; 290 return (ct->token); 291 } 292 293 /* 294 * Convert a number from a command line. I picked "u_longlong_t" for the 295 * number because we need the largest number available. Also, the strto<num> 296 * calls don't deal in units of uintNN_t. 297 */ 298 static u_longlong_t 299 parsenum(char *num, boolean_t bail, char *ebuf) 300 { 301 u_longlong_t rc = 0; 302 char *end = NULL; 303 char *ep = NULL; 304 305 if (num == NULL) { 306 FATAL(ep, ebuf, gettext("Unexpected end of command line," 307 " was expecting a number.\n")); 308 /* NOTREACHED */ 309 } 310 311 errno = 0; 312 rc = strtoull(num, &end, 0); 313 if (errno != 0 || end == num || *end != '\0') { 314 if (bail) { 315 ERROR1(ep, ebuf, gettext( 316 "Expecting a number, not \"%s\"!\n"), num); 317 } else { 318 /* 319 * -1, while not optimal, is sufficiently out of range 320 * for most of this function's applications when 321 * we don't just bail. 322 */ 323 return ((u_longlong_t)-1); 324 } 325 } 326 handle_errors(ep, NULL, B_FALSE, B_FALSE); 327 return (rc); 328 } 329 330 /* 331 * Parse and reverse parse a specific SA type (AH, ESP, etc.). 332 */ 333 static struct typetable { 334 char *type; 335 int token; 336 } type_table[] = { 337 {"all", SADB_SATYPE_UNSPEC}, 338 {"ah", SADB_SATYPE_AH}, 339 {"esp", SADB_SATYPE_ESP}, 340 /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */ 341 {NULL, 0} /* Token value is irrelevant for this entry. */ 342 }; 343 344 345 static int 346 parsesatype(char *type, char *ebuf) 347 { 348 struct typetable *tt = type_table; 349 char *ep = NULL; 350 351 if (type == NULL) 352 return (SADB_SATYPE_UNSPEC); 353 354 while (tt->type != NULL && strcasecmp(tt->type, type) != 0) 355 tt++; 356 357 /* 358 * New SA types (including ones keysock maintains for user-land 359 * protocols) may be added, so parse a numeric value if possible. 360 */ 361 if (tt->type == NULL) { 362 tt->token = (int)parsenum(type, B_FALSE, ebuf); 363 if (tt->token == -1) { 364 ERROR1(ep, ebuf, gettext( 365 "Unknown SA type (%s).\n"), type); 366 tt->token = SADB_SATYPE_UNSPEC; 367 } 368 } 369 handle_errors(ep, NULL, B_FALSE, B_FALSE); 370 return (tt->token); 371 } 372 373 #define NEXTEOF 0 374 #define NEXTNONE 1 375 #define NEXTNUM 2 376 #define NEXTSTR 3 377 #define NEXTNUMSTR 4 378 #define NEXTADDR 5 379 #define NEXTHEX 6 380 #define NEXTIDENT 7 381 #define NEXTADDR4 8 382 #define NEXTADDR6 9 383 384 #define TOK_EOF 0 385 #define TOK_UNKNOWN 1 386 #define TOK_SPI 2 387 #define TOK_REPLAY 3 388 #define TOK_STATE 4 389 #define TOK_AUTHALG 5 390 #define TOK_ENCRALG 6 391 #define TOK_FLAGS 7 392 #define TOK_SOFT_ALLOC 8 393 #define TOK_SOFT_BYTES 9 394 #define TOK_SOFT_ADDTIME 10 395 #define TOK_SOFT_USETIME 11 396 #define TOK_HARD_ALLOC 12 397 #define TOK_HARD_BYTES 13 398 #define TOK_HARD_ADDTIME 14 399 #define TOK_HARD_USETIME 15 400 #define TOK_CURRENT_ALLOC 16 401 #define TOK_CURRENT_BYTES 17 402 #define TOK_CURRENT_ADDTIME 18 403 #define TOK_CURRENT_USETIME 19 404 #define TOK_SRCADDR 20 405 #define TOK_DSTADDR 21 406 #define TOK_PROXYADDR 22 407 #define TOK_AUTHKEY 23 408 #define TOK_ENCRKEY 24 409 #define TOK_SRCIDTYPE 25 410 #define TOK_DSTIDTYPE 26 411 #define TOK_DPD 27 412 #define TOK_SENS_LEVEL 28 413 #define TOK_SENS_MAP 29 414 #define TOK_INTEG_LEVEL 30 415 #define TOK_INTEG_MAP 31 416 #define TOK_SRCADDR6 32 417 #define TOK_DSTADDR6 33 418 #define TOK_PROXYADDR6 34 419 #define TOK_SRCPORT 35 420 #define TOK_DSTPORT 36 421 #define TOK_PROTO 37 422 #define TOK_ENCAP 38 423 #define TOK_NATLOC 39 424 #define TOK_NATREM 40 425 #define TOK_NATLPORT 41 426 #define TOK_NATRPORT 42 427 #define TOK_IPROTO 43 428 #define TOK_IDSTADDR 44 429 #define TOK_IDSTADDR6 45 430 #define TOK_ISRCPORT 46 431 #define TOK_IDSTPORT 47 432 433 static struct toktable { 434 char *string; 435 int token; 436 int next; 437 } tokens[] = { 438 /* "String", token value, next arg is */ 439 {"spi", TOK_SPI, NEXTNUM}, 440 {"replay", TOK_REPLAY, NEXTNUM}, 441 {"state", TOK_STATE, NEXTNUMSTR}, 442 {"auth_alg", TOK_AUTHALG, NEXTNUMSTR}, 443 {"authalg", TOK_AUTHALG, NEXTNUMSTR}, 444 {"encr_alg", TOK_ENCRALG, NEXTNUMSTR}, 445 {"encralg", TOK_ENCRALG, NEXTNUMSTR}, 446 {"flags", TOK_FLAGS, NEXTNUM}, 447 {"soft_alloc", TOK_SOFT_ALLOC, NEXTNUM}, 448 {"soft_bytes", TOK_SOFT_BYTES, NEXTNUM}, 449 {"soft_addtime", TOK_SOFT_ADDTIME, NEXTNUM}, 450 {"soft_usetime", TOK_SOFT_USETIME, NEXTNUM}, 451 {"hard_alloc", TOK_HARD_ALLOC, NEXTNUM}, 452 {"hard_bytes", TOK_HARD_BYTES, NEXTNUM}, 453 {"hard_addtime", TOK_HARD_ADDTIME, NEXTNUM}, 454 {"hard_usetime", TOK_HARD_USETIME, NEXTNUM}, 455 {"current_alloc", TOK_CURRENT_ALLOC, NEXTNUM}, 456 {"current_bytes", TOK_CURRENT_BYTES, NEXTNUM}, 457 {"current_addtime", TOK_CURRENT_ADDTIME, NEXTNUM}, 458 {"current_usetime", TOK_CURRENT_USETIME, NEXTNUM}, 459 460 {"saddr", TOK_SRCADDR, NEXTADDR}, 461 {"srcaddr", TOK_SRCADDR, NEXTADDR}, 462 {"src", TOK_SRCADDR, NEXTADDR}, 463 {"daddr", TOK_DSTADDR, NEXTADDR}, 464 {"dstaddr", TOK_DSTADDR, NEXTADDR}, 465 {"dst", TOK_DSTADDR, NEXTADDR}, 466 {"proxyaddr", TOK_PROXYADDR, NEXTADDR}, 467 {"proxy", TOK_PROXYADDR, NEXTADDR}, 468 {"innersrc", TOK_PROXYADDR, NEXTADDR}, 469 {"isrc", TOK_PROXYADDR, NEXTADDR}, 470 {"innerdst", TOK_IDSTADDR, NEXTADDR}, 471 {"idst", TOK_IDSTADDR, NEXTADDR}, 472 473 {"sport", TOK_SRCPORT, NEXTNUM}, 474 {"dport", TOK_DSTPORT, NEXTNUM}, 475 {"innersport", TOK_ISRCPORT, NEXTNUM}, 476 {"isport", TOK_ISRCPORT, NEXTNUM}, 477 {"innerdport", TOK_IDSTPORT, NEXTNUM}, 478 {"idport", TOK_IDSTPORT, NEXTNUM}, 479 {"proto", TOK_PROTO, NEXTNUM}, 480 {"ulp", TOK_PROTO, NEXTNUM}, 481 {"iproto", TOK_IPROTO, NEXTNUM}, 482 {"iulp", TOK_IPROTO, NEXTNUM}, 483 484 {"saddr6", TOK_SRCADDR6, NEXTADDR}, 485 {"srcaddr6", TOK_SRCADDR6, NEXTADDR}, 486 {"src6", TOK_SRCADDR6, NEXTADDR}, 487 {"daddr6", TOK_DSTADDR6, NEXTADDR}, 488 {"dstaddr6", TOK_DSTADDR6, NEXTADDR}, 489 {"dst6", TOK_DSTADDR6, NEXTADDR}, 490 {"proxyaddr6", TOK_PROXYADDR6, NEXTADDR}, 491 {"proxy6", TOK_PROXYADDR6, NEXTADDR}, 492 {"innersrc6", TOK_PROXYADDR6, NEXTADDR}, 493 {"isrc6", TOK_PROXYADDR6, NEXTADDR}, 494 {"innerdst6", TOK_IDSTADDR6, NEXTADDR}, 495 {"idst6", TOK_IDSTADDR6, NEXTADDR}, 496 497 {"authkey", TOK_AUTHKEY, NEXTHEX}, 498 {"encrkey", TOK_ENCRKEY, NEXTHEX}, 499 {"srcidtype", TOK_SRCIDTYPE, NEXTIDENT}, 500 {"dstidtype", TOK_DSTIDTYPE, NEXTIDENT}, 501 {"dpd", TOK_DPD, NEXTNUM}, 502 {"sens_level", TOK_SENS_LEVEL, NEXTNUM}, 503 {"sens_map", TOK_SENS_MAP, NEXTHEX}, 504 {"integ_level", TOK_INTEG_LEVEL, NEXTNUM}, 505 {"integ_map", TOK_INTEG_MAP, NEXTHEX}, 506 {"nat_loc", TOK_NATLOC, NEXTADDR}, 507 {"nat_rem", TOK_NATREM, NEXTADDR}, 508 {"nat_lport", TOK_NATLPORT, NEXTNUM}, 509 {"nat_rport", TOK_NATRPORT, NEXTNUM}, 510 {"encap", TOK_ENCAP, NEXTNUMSTR}, 511 {NULL, TOK_UNKNOWN, NEXTEOF} 512 }; 513 514 /* 515 * Q: Do I need stuff for proposals, combinations, supported algorithms, 516 * or SPI ranges? 517 * 518 * A: Probably not, but you never know. 519 * 520 * Parse out extension header type values. 521 */ 522 static int 523 parseextval(char *value, int *next) 524 { 525 struct toktable *tp; 526 527 if (value == NULL) 528 return (TOK_EOF); 529 530 for (tp = tokens; tp->string != NULL; tp++) 531 if (strcmp(value, tp->string) == 0) 532 break; 533 534 /* 535 * Since the OS controls what extensions are available, we don't have 536 * to parse numeric values here. 537 */ 538 539 *next = tp->next; 540 return (tp->token); 541 } 542 543 /* 544 * Parse possible state values. 545 */ 546 static uint8_t 547 parsestate(char *state, char *ebuf) 548 { 549 struct states { 550 char *state; 551 uint8_t retval; 552 } states[] = { 553 {"larval", SADB_SASTATE_LARVAL}, 554 {"mature", SADB_SASTATE_MATURE}, 555 {"dying", SADB_SASTATE_DYING}, 556 {"dead", SADB_SASTATE_DEAD}, 557 {NULL, 0} 558 }; 559 struct states *sp; 560 char *ep = NULL; 561 562 if (state == NULL) { 563 FATAL(ep, ebuf, "Unexpected end of command line " 564 "was expecting a state.\n"); 565 } 566 567 for (sp = states; sp->state != NULL; sp++) { 568 if (strcmp(sp->state, state) == 0) 569 return (sp->retval); 570 } 571 ERROR1(ep, ebuf, gettext("Unknown state type \"%s\"\n"), state); 572 handle_errors(ep, NULL, B_FALSE, B_FALSE); 573 return (0); 574 } 575 576 /* 577 * Return the numerical algorithm identifier corresponding to the specified 578 * algorithm name. 579 */ 580 static uint8_t 581 parsealg(char *alg, int proto_num, char *ebuf) 582 { 583 u_longlong_t invalue; 584 struct ipsecalgent *algent; 585 char *ep = NULL; 586 587 if (alg == NULL) { 588 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 589 "was expecting an algorithm name.\n")); 590 } 591 592 algent = getipsecalgbyname(alg, proto_num, NULL); 593 if (algent != NULL) { 594 uint8_t alg_num; 595 596 alg_num = algent->a_alg_num; 597 freeipsecalgent(algent); 598 599 return (alg_num); 600 } 601 602 /* 603 * Since algorithms can be loaded during kernel run-time, check for 604 * numeric algorithm values too. PF_KEY can catch bad ones with EINVAL. 605 */ 606 invalue = parsenum(alg, B_FALSE, ebuf); 607 if (invalue != (u_longlong_t)-1 && 608 (u_longlong_t)(invalue & (u_longlong_t)0xff) == invalue) 609 return ((uint8_t)invalue); 610 611 if (proto_num == IPSEC_PROTO_ESP) { 612 ERROR1(ep, ebuf, gettext( 613 "Unknown encryption algorithm type \"%s\"\n"), alg); 614 } else { 615 ERROR1(ep, ebuf, gettext( 616 "Unknown authentication algorithm type \"%s\"\n"), alg); 617 } 618 handle_errors(ep, NULL, B_FALSE, B_FALSE); 619 return (0); 620 } 621 622 /* 623 * Parse and reverse parse out a source/destination ID type. 624 */ 625 static struct idtypes { 626 char *idtype; 627 uint8_t retval; 628 } idtypes[] = { 629 {"prefix", SADB_IDENTTYPE_PREFIX}, 630 {"fqdn", SADB_IDENTTYPE_FQDN}, 631 {"domain", SADB_IDENTTYPE_FQDN}, 632 {"domainname", SADB_IDENTTYPE_FQDN}, 633 {"user_fqdn", SADB_IDENTTYPE_USER_FQDN}, 634 {"mailbox", SADB_IDENTTYPE_USER_FQDN}, 635 {"der_dn", SADB_X_IDENTTYPE_DN}, 636 {"der_gn", SADB_X_IDENTTYPE_GN}, 637 {NULL, 0} 638 }; 639 640 static uint16_t 641 parseidtype(char *type, char *ebuf) 642 { 643 struct idtypes *idp; 644 u_longlong_t invalue; 645 char *ep = NULL; 646 647 if (type == NULL) { 648 /* Shouldn't reach here, see callers for why. */ 649 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 650 "was expecting a type.\n")); 651 } 652 653 for (idp = idtypes; idp->idtype != NULL; idp++) { 654 if (strcasecmp(idp->idtype, type) == 0) 655 return (idp->retval); 656 } 657 /* 658 * Since identity types are almost arbitrary, check for numeric 659 * algorithm values too. PF_KEY can catch bad ones with EINVAL. 660 */ 661 invalue = parsenum(type, B_FALSE, ebuf); 662 if (invalue != (u_longlong_t)-1 && 663 (u_longlong_t)(invalue & (u_longlong_t)0xffff) == invalue) 664 return ((uint16_t)invalue); 665 666 667 ERROR1(ep, ebuf, gettext("Unknown identity type \"%s\"\n"), type); 668 669 handle_errors(ep, NULL, B_FALSE, B_FALSE); 670 return (0); 671 } 672 673 /* 674 * Parse an address off the command line. Return length of sockaddr, 675 * and either return a hostent pointer (caller frees). The new 676 * getipnodebyname() call does the Right Thing (TM), even with 677 * raw addresses (colon-separated IPv6 or dotted decimal IPv4). 678 */ 679 680 static struct { 681 struct hostent he; 682 char *addtl[2]; 683 } dummy; 684 static union { 685 struct in6_addr ipv6; 686 struct in_addr ipv4; 687 uint64_t aligner; 688 } addr1; 689 690 static int 691 parseaddr(char *addr, struct hostent **hpp, boolean_t v6only, char *ebuf) 692 { 693 int hp_errno; 694 struct hostent *hp = NULL; 695 char *ep = NULL; 696 697 if (addr == NULL) { 698 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 699 "was expecting an address.\n")); 700 } 701 702 if (!nflag) { 703 /* 704 * Try name->address first. Assume AF_INET6, and 705 * get IPv4's, plus IPv6's if and only if IPv6 is configured. 706 * This means to add IPv6 SAs, you must have IPv6 707 * up-and-running. (AI_DEFAULT works here.) 708 */ 709 hp = getipnodebyname(addr, AF_INET6, 710 (v6only ? AI_ADDRCONFIG : (AI_DEFAULT | AI_ALL)), 711 &hp_errno); 712 } else { 713 /* 714 * Try a normal address conversion only. Use "dummy" 715 * to construct a fake hostent. Caller will know not 716 * to free this one. 717 */ 718 if (inet_pton(AF_INET6, addr, &addr1) == 1) { 719 dummy.he.h_addr_list = dummy.addtl; 720 dummy.addtl[0] = (char *)&addr1; 721 dummy.addtl[1] = NULL; 722 hp = &dummy.he; 723 dummy.he.h_addrtype = AF_INET6; 724 dummy.he.h_length = sizeof (struct in6_addr); 725 } else if (inet_pton(AF_INET, addr, &addr1) == 1) { 726 /* 727 * Remap to AF_INET6 anyway. 728 */ 729 dummy.he.h_addr_list = dummy.addtl; 730 dummy.addtl[0] = (char *)&addr1; 731 dummy.addtl[1] = NULL; 732 hp = &dummy.he; 733 dummy.he.h_addrtype = AF_INET6; 734 dummy.he.h_length = sizeof (struct in6_addr); 735 /* 736 * NOTE: If macro changes to disallow in-place 737 * conversion, rewhack this. 738 */ 739 IN6_INADDR_TO_V4MAPPED(&addr1.ipv4, &addr1.ipv6); 740 } else { 741 hp = NULL; 742 } 743 } 744 745 if (hp == NULL) 746 WARN1(ep, ebuf, gettext("Unknown address %s."), addr); 747 748 *hpp = hp; 749 /* Always return sockaddr_in6 for now. */ 750 handle_errors(ep, NULL, B_FALSE, B_FALSE); 751 return (sizeof (struct sockaddr_in6)); 752 } 753 754 /* 755 * Parse a hex character for a key. A string will take the form: 756 * xxxxxxxxx/nn 757 * where 758 * xxxxxxxxx == a string of hex characters ([0-9][a-f][A-F]) 759 * nn == an optional decimal "mask". If it is not present, it 760 * is assumed that the hex string will be rounded to the nearest 761 * byte, where odd nibbles, like 123 will become 0x0123. 762 * 763 * NOTE:Unlike the expression of IP addresses, I will not allow an 764 * excessive "mask". For example 2112/50 is very illegal. 765 * NOTE2: This key should be in canonical order. Consult your man 766 * pages per algorithm about said order. 767 */ 768 769 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \ 770 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10))) 771 772 static struct sadb_key * 773 parsekey(char *input, char *ebuf) 774 { 775 struct sadb_key *retval; 776 uint_t i, hexlen = 0, bits, alloclen; 777 uint8_t *key; 778 char *ep = NULL; 779 780 if (input == NULL) { 781 FATAL(ep, ebuf, gettext("Unexpected end of command line, " 782 "was expecting a key.\n")); 783 } 784 /* Allow hex values prepended with 0x convention */ 785 if ((strnlen(input, sizeof (hexlen)) > 2) && 786 (strncasecmp(input, "0x", 2) == 0)) 787 input += 2; 788 789 for (i = 0; input[i] != '\0' && input[i] != '/'; i++) 790 hexlen++; 791 792 if (input[i] == '\0') { 793 bits = 0; 794 } else { 795 /* Have /nn. */ 796 input[i] = '\0'; 797 if (sscanf((input + i + 1), "%u", &bits) != 1) { 798 FATAL1(ep, ebuf, gettext( 799 "\"%s\" is not a bit specifier.\n"), 800 (input + i + 1)); 801 } 802 /* hexlen in nibbles */ 803 if (((bits + 3) >> 2) > hexlen) { 804 ERROR2(ep, ebuf, gettext( 805 "bit length %d is too big for %s.\n"), bits, input); 806 } 807 /* 808 * Adjust hexlen down if user gave us too small of a bit 809 * count. 810 */ 811 if ((hexlen << 2) > bits + 3) { 812 WARN2(ep, ebuf, gettext( 813 "WARNING: Lower bits will be truncated " 814 "for:\n\t%s/%d.\n"), input, bits); 815 hexlen = (bits + 3) >> 2; 816 input[hexlen] = '\0'; 817 } 818 } 819 820 /* 821 * Allocate. Remember, hexlen is in nibbles. 822 */ 823 824 alloclen = sizeof (*retval) + roundup((hexlen/2 + (hexlen & 0x1)), 8); 825 retval = malloc(alloclen); 826 827 if (retval == NULL) 828 Bail("malloc(parsekey)"); 829 retval->sadb_key_len = SADB_8TO64(alloclen); 830 retval->sadb_key_reserved = 0; 831 if (bits == 0) 832 retval->sadb_key_bits = (hexlen + (hexlen & 0x1)) << 2; 833 else 834 retval->sadb_key_bits = bits; 835 836 /* 837 * Read in nibbles. Read in odd-numbered as shifted high. 838 * (e.g. 123 becomes 0x1230). 839 */ 840 841 key = (uint8_t *)(retval + 1); 842 for (i = 0; input[i] != '\0'; i += 2) { 843 boolean_t second = (input[i + 1] != '\0'); 844 845 if (!isxdigit(input[i]) || 846 (!isxdigit(input[i + 1]) && second)) { 847 ERROR1(ep, ebuf, gettext( 848 "string '%s' not a hex value.\n"), input); 849 free(retval); 850 retval = NULL; 851 break; 852 } 853 *key = (hd2num(input[i]) << 4); 854 if (second) 855 *key |= hd2num(input[i + 1]); 856 else 857 break; /* out of for loop. */ 858 key++; 859 } 860 861 /* bzero the remaining bits if we're a non-octet amount. */ 862 if (bits & 0x7) 863 *((input[i] == '\0') ? key - 1 : key) &= 864 0xff << (8 - (bits & 0x7)); 865 866 handle_errors(ep, NULL, B_FALSE, B_FALSE); 867 return (retval); 868 } 869 870 /* 871 * Write a message to the PF_KEY socket. If verbose, print the message 872 * heading into the kernel. 873 */ 874 static int 875 key_write(int fd, void *msg, size_t len) 876 { 877 if (vflag) { 878 (void) printf( 879 gettext("VERBOSE ON: Message to kernel looks like:\n")); 880 (void) printf("==========================================\n"); 881 print_samsg(stdout, msg, B_FALSE, vflag, nflag); 882 (void) printf("==========================================\n"); 883 } 884 885 return (write(fd, msg, len)); 886 } 887 888 /* 889 * SIGALRM handler for time_critical_enter. 890 */ 891 static void 892 time_critical_catch(int signal) 893 { 894 if (signal == SIGALRM) { 895 errx(1, gettext("Reply message from PF_KEY timed out.")); 896 } else { 897 errx(1, gettext("Caught signal %d while trying to receive" 898 "PF_KEY reply message"), signal); 899 } 900 /* errx() calls exit. */ 901 } 902 903 #define TIME_CRITICAL_TIME 10 /* In seconds */ 904 905 /* 906 * Enter a "time critical" section where key is waiting for a return message. 907 */ 908 static void 909 time_critical_enter(void) 910 { 911 (void) signal(SIGALRM, time_critical_catch); 912 (void) alarm(TIME_CRITICAL_TIME); 913 } 914 915 /* 916 * Exit the "time critical" section after getting an appropriate return 917 * message. 918 */ 919 static void 920 time_critical_exit(void) 921 { 922 (void) alarm(0); 923 (void) signal(SIGALRM, SIG_DFL); 924 } 925 926 /* 927 * Construct a PF_KEY FLUSH message for the SA type specified. 928 */ 929 static void 930 doflush(int satype) 931 { 932 struct sadb_msg msg; 933 int rc; 934 935 msg_init(&msg, SADB_FLUSH, (uint8_t)satype); 936 rc = key_write(keysock, &msg, sizeof (msg)); 937 if (rc == -1) 938 Bail("write() to PF_KEY socket failed (in doflush)"); 939 940 time_critical_enter(); 941 do { 942 rc = read(keysock, &msg, sizeof (msg)); 943 if (rc == -1) 944 Bail("read (in doflush)"); 945 } while (msg.sadb_msg_seq != seq || msg.sadb_msg_pid != mypid); 946 time_critical_exit(); 947 948 /* 949 * I should _never_ hit the following unless: 950 * 951 * 1. There is a kernel bug. 952 * 2. There is another process filling in its pid with mine, and 953 * issuing a different message that would cause a different result. 954 */ 955 if (msg.sadb_msg_type != SADB_FLUSH || 956 msg.sadb_msg_satype != (uint8_t)satype) { 957 syslog((LOG_NOTICE|LOG_AUTH), 958 gettext("doflush: Return message not of type SADB_FLUSH!")); 959 Bail("doflush: Return message not of type SADB_FLUSH!"); 960 } 961 962 if (msg.sadb_msg_errno != 0) { 963 errno = msg.sadb_msg_errno; 964 if (errno == EINVAL) { 965 print_diagnostic(stderr, msg.sadb_x_msg_diagnostic); 966 warnx(gettext("Cannot flush SA type %d."), satype); 967 } 968 Bail("return message (in doflush)"); 969 } 970 } 971 972 /* 973 * save_XXX functions are used when "saving" the SA tables to either a 974 * file or standard output. They use the dump_XXX functions where needed, 975 * but mostly they use the rparseXXX functions. 976 */ 977 978 /* 979 * Because "save" and "dump" both use the SADB_DUMP message, fold both 980 * into the same function. 981 */ 982 static void 983 dodump(int satype, FILE *ofile) 984 { 985 struct sadb_msg *msg = (struct sadb_msg *)get_buffer; 986 int rc; 987 988 if (ofile != NULL) { 989 (void) fprintf(ofile, 990 gettext("# This key file was generated by the")); 991 (void) fprintf(ofile, 992 gettext(" ipseckey(1m) command's 'save' feature.\n\n")); 993 } 994 msg_init(msg, SADB_DUMP, (uint8_t)satype); 995 rc = key_write(keysock, msg, sizeof (*msg)); 996 if (rc == -1) 997 Bail("write to PF_KEY socket failed (in dodump)"); 998 999 do { 1000 /* 1001 * For DUMP, do only the read as a time critical section. 1002 */ 1003 time_critical_enter(); 1004 rc = read(keysock, get_buffer, sizeof (get_buffer)); 1005 time_critical_exit(); 1006 if (rc == -1) 1007 Bail("read (in dodump)"); 1008 if (msg->sadb_msg_pid == mypid && 1009 msg->sadb_msg_type == SADB_DUMP && 1010 msg->sadb_msg_seq != 0 && 1011 msg->sadb_msg_errno == 0) { 1012 if (ofile == NULL) { 1013 print_samsg(stdout, get_buffer, B_FALSE, vflag, 1014 nflag); 1015 (void) putchar('\n'); 1016 } else { 1017 save_assoc(get_buffer, ofile); 1018 } 1019 } 1020 } while (msg->sadb_msg_pid != mypid || 1021 (msg->sadb_msg_errno == 0 && msg->sadb_msg_seq != 0)); 1022 1023 if (ofile != NULL && ofile != stdout) 1024 (void) fclose(ofile); 1025 1026 if (msg->sadb_msg_errno == 0) { 1027 if (ofile == NULL) 1028 (void) printf( 1029 gettext("Dump succeeded for SA type %d.\n"), 1030 satype); 1031 } else { 1032 print_diagnostic(stderr, msg->sadb_x_msg_diagnostic); 1033 errno = msg->sadb_msg_errno; 1034 Bail("Dump failed"); 1035 } 1036 } 1037 1038 #define SCOPE_UNSPEC 0 1039 #define SCOPE_LINKLOCAL 1 1040 #define SCOPE_SITELOCAL 2 1041 #define SCOPE_GLOBAL 3 1042 #define SCOPE_V4COMPAT 4 1043 #define SCOPE_LOOPBACK 5 /* Pedantic, yes, but necessary. */ 1044 1045 static int 1046 ipv6_addr_scope(struct in6_addr *addr) 1047 { 1048 /* Don't return anything regarding multicast for now... */ 1049 1050 if (IN6_IS_ADDR_UNSPECIFIED(addr)) 1051 return (SCOPE_UNSPEC); 1052 1053 if (IN6_IS_ADDR_LINKLOCAL(addr)) 1054 return (SCOPE_LINKLOCAL); 1055 1056 if (IN6_IS_ADDR_SITELOCAL(addr)) 1057 return (SCOPE_SITELOCAL); 1058 1059 if (IN6_IS_ADDR_V4COMPAT(addr)) 1060 return (SCOPE_V4COMPAT); 1061 1062 if (IN6_IS_ADDR_LOOPBACK(addr)) 1063 return (SCOPE_LOOPBACK); 1064 1065 /* For now, return global by default. */ 1066 return (SCOPE_GLOBAL); 1067 } 1068 1069 /* 1070 * doaddresses(): 1071 * 1072 * Used by doaddup() and dodelget() to create new SA's based on the 1073 * provided source and destination addresses hostent. 1074 * 1075 * sadb_msg_type: expected PF_KEY reply message type 1076 * sadb_msg_satype: expected PF_KEY reply satype 1077 * cmd: user command 1078 * srchp: hostent for the source address(es) 1079 * dsthp: hostent for the destination address(es) 1080 * src: points to the SADB source address extension 1081 * dst: points to the SADB destination address extension 1082 * unspec_src: indicates an unspecified source address. 1083 * buffer: pointer to the SADB buffer to use with PF_KEY 1084 * buffer_size: size of buffer 1085 * spi: spi for this message (set by caller) 1086 * srcport: source port if specified 1087 * dstport: destination port if specified 1088 * proto: IP protocol number if specified 1089 * iproto: Inner (tunnel mode) IP protocol number if specified 1090 * NATT note: we are going to assume a semi-sane world where NAT 1091 * boxen don't explode to multiple addresses. 1092 */ 1093 static void 1094 doaddresses(uint8_t sadb_msg_type, uint8_t sadb_msg_satype, int cmd, 1095 struct hostent *srchp, struct hostent *dsthp, 1096 struct sadb_address *src, struct sadb_address *dst, 1097 boolean_t unspec_src, uint64_t *buffer, int buffer_size, uint32_t spi, 1098 char *ebuf) 1099 { 1100 boolean_t single_dst; 1101 struct sockaddr_in6 *sin6; 1102 struct sadb_msg *msgp; 1103 int i, rc; 1104 char **walker; /* For the SRC and PROXY walking functions. */ 1105 char *first_match; 1106 uint64_t savebuf[MAX_GET_SIZE]; 1107 uint16_t srcport = 0, dstport = 0; 1108 char *ep = NULL; 1109 1110 /* 1111 * Okay, now we have "src", "dst", and maybe "proxy" reassigned 1112 * to point into the buffer to be written to PF_KEY, we can do 1113 * potentially several writes based on destination address. 1114 * 1115 * First, obtain port numbers from passed-in extensions. 1116 */ 1117 1118 if (src != NULL) { 1119 sin6 = (struct sockaddr_in6 *)(src + 1); 1120 srcport = ntohs(sin6->sin6_port); 1121 } 1122 if (dst != NULL) { 1123 sin6 = (struct sockaddr_in6 *)(dst + 1); 1124 dstport = ntohs(sin6->sin6_port); 1125 } 1126 1127 /* 1128 * The rules for ADD, GET, and UPDATE: (NOTE: This assumes IPsec. 1129 * If other consumers of PF_KEY happen, this will have to be 1130 * rewhacked.): 1131 * 1132 * Do a message for every possible DST address. 1133 * 1134 * If a source or proxy address explodes, keep unspecified 1135 * (and mention unspecified). 1136 * 1137 * If dsthp is == dummy.he, then go through the loop once. 1138 * If any other hp is == dummy.he, then you don't have to apply any 1139 * silly rules. 1140 * 1141 * DELETE is different, because you can leave either "src" or "dst" 1142 * blank! You need to explode if one of them is full, and not assume 1143 * that the other is set. 1144 */ 1145 1146 if (dsthp == NULL) { 1147 /* 1148 * No destination address specified. 1149 * With extended diagnostics, we don't have to bail the 1150 * non-DELETE cases here. The EINVAL diagnostics will be 1151 * enough to inform the user(s) what happened. 1152 */ 1153 i = 0; 1154 do { 1155 if (srchp == &dummy.he) { 1156 /* Just to be sure... */ 1157 srchp->h_addr_list[1] = NULL; 1158 } else if (srchp != NULL) { 1159 /* Degenerate case, h_addr_list[0] == NULL. */ 1160 if (srchp->h_addr_list[i] == NULL) 1161 Bail("Empty source address list"); 1162 1163 /* 1164 * Fill in the src sockaddr. 1165 */ 1166 sin6 = (struct sockaddr_in6 *)(src + 1); 1167 bzero(sin6, sizeof (*sin6)); 1168 bcopy(srchp->h_addr_list[i], &sin6->sin6_addr, 1169 sizeof (struct in6_addr)); 1170 sin6->sin6_family = AF_INET6; 1171 sin6->sin6_port = htons(srcport); 1172 } 1173 1174 /* Save off a copy for later writing... */ 1175 msgp = (struct sadb_msg *)buffer; 1176 bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len)); 1177 1178 rc = key_write(keysock, buffer, 1179 SADB_64TO8(msgp->sadb_msg_len)); 1180 if (rc == -1) 1181 Bail("write() to PF_KEY socket " 1182 "(in doaddresses)"); 1183 1184 time_critical_enter(); 1185 do { 1186 rc = read(keysock, buffer, buffer_size); 1187 if (rc == -1) 1188 Bail("read (in doaddresses)"); 1189 } while (msgp->sadb_msg_seq != seq || 1190 msgp->sadb_msg_pid != mypid); 1191 time_critical_exit(); 1192 1193 if (msgp->sadb_msg_type != sadb_msg_type || 1194 msgp->sadb_msg_satype != sadb_msg_satype) { 1195 syslog((LOG_NOTICE|LOG_AUTH), gettext( 1196 "doaddresses: Unexpected returned message " 1197 "(%d exp %d)\n"), msgp->sadb_msg_type, 1198 sadb_msg_type); 1199 Bail("doaddresses: Unexpected returned " 1200 "message"); 1201 } 1202 1203 errno = msgp->sadb_msg_errno; 1204 if (errno != 0) { 1205 if (errno == EINVAL) { 1206 WARN(ep, ebuf, gettext( 1207 "One of the entered " 1208 "values is incorrect.")); 1209 print_diagnostic(stderr, 1210 msgp->sadb_x_msg_diagnostic); 1211 } else { 1212 Bail("return message (in doaddresses)"); 1213 } 1214 } 1215 1216 /* ...and then restore the saved buffer. */ 1217 msgp = (struct sadb_msg *)savebuf; 1218 bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len)); 1219 } while (srchp != NULL && srchp->h_addr_list[++i] != NULL); 1220 return; 1221 } 1222 1223 single_dst = (dsthp == &dummy.he || dsthp->h_addr_list[1] == NULL); 1224 1225 for (i = 0; dsthp->h_addr_list[i] != NULL; i++) { 1226 if (dsthp == &dummy.he) { 1227 /* Just to be sure... */ 1228 dsthp->h_addr_list[1] = NULL; 1229 } else { 1230 /* 1231 * Fill in the dst sockaddr. 1232 */ 1233 sin6 = (struct sockaddr_in6 *)(dst + 1); 1234 bzero(sin6, sizeof (*sin6)); 1235 bcopy(dsthp->h_addr_list[i], &sin6->sin6_addr, 1236 sizeof (struct in6_addr)); 1237 sin6->sin6_family = AF_INET6; 1238 sin6->sin6_port = htons(dstport); 1239 } 1240 1241 /* 1242 * Try and assign src, if there's any ambiguity. 1243 */ 1244 if (!unspec_src && srchp != &dummy.he) { 1245 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1246 /* 1247 * IPv4 address. Find an IPv4 address, then 1248 * keep looking for a second one. If a second 1249 * exists, print a message, and fill in the 1250 * unspecified address. 1251 */ 1252 first_match = NULL; 1253 1254 for (walker = srchp->h_addr_list; 1255 *walker != NULL; walker++) { 1256 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1257 if (IN6_IS_ADDR_V4MAPPED( 1258 (struct in6_addr *)*walker)) { 1259 if (first_match != NULL) 1260 break; 1261 else 1262 first_match = *walker; 1263 } 1264 } 1265 sin6 = (struct sockaddr_in6 *)(src + 1); 1266 bzero(sin6, sizeof (*sin6)); 1267 1268 if (first_match == NULL) { 1269 /* 1270 * No IPv4 hits. Is this a single 1271 * dest? 1272 */ 1273 WARN1(ep, ebuf, gettext( 1274 "No IPv4 source address " 1275 "for name %s.\n"), srchp->h_name); 1276 if (single_dst) { 1277 ERROR(ep, ebuf, gettext( 1278 "Only single destination " 1279 "IP address.\n")); 1280 } else { 1281 /* Continue, but do I print? */ 1282 continue; /* for loop */ 1283 } 1284 1285 /* I should never reach here. */ 1286 } 1287 1288 sin6->sin6_family = AF_INET6; 1289 sin6->sin6_port = htons(srcport); 1290 if (*walker != NULL) { 1291 /* 1292 * Early loop exit. It must've been 1293 * multiple hits... 1294 * 1295 * Issue a null-source warning? 1296 */ 1297 WARN1(ep, ebuf, gettext( 1298 "Multiple IPv4 source addresses " 1299 "for %s, using unspecified source " 1300 "instead."), srchp->h_name); 1301 } else { 1302 /* 1303 * If I reach here w/o hitting the 1304 * previous if statements, I have a 1305 * single source address for this 1306 * destination. 1307 */ 1308 bcopy(first_match, &sin6->sin6_addr, 1309 sizeof (struct in6_addr)); 1310 } 1311 } else { 1312 /* 1313 * IPv6 address. Find an IPv6 address. 1314 * Unlike IPv4 addresses, things can get a 1315 * little more sticky with scopes, etc. 1316 */ 1317 int dst_scope, src_scope; 1318 1319 dst_scope = ipv6_addr_scope(&sin6->sin6_addr); 1320 1321 first_match = NULL; 1322 for (walker = srchp->h_addr_list; 1323 *walker != NULL; walker++) { 1324 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1325 if (!IN6_IS_ADDR_V4MAPPED( 1326 (struct in6_addr *)*walker)) { 1327 /* 1328 * Set first-match, etc. 1329 * Take into account scopes, 1330 * and other IPv6 thingies. 1331 */ 1332 src_scope = ipv6_addr_scope( 1333 /* LINTED E_BAD_PTR_CAST */ 1334 (struct in6_addr *)*walker); 1335 if (src_scope == SCOPE_UNSPEC || 1336 src_scope == dst_scope) { 1337 if (first_match != 1338 NULL) 1339 break; 1340 else 1341 first_match = 1342 *walker; 1343 } 1344 } 1345 } 1346 1347 sin6 = (struct sockaddr_in6 *)(src + 1); 1348 bzero(sin6, sizeof (*sin6)); 1349 sin6->sin6_port = htons(srcport); 1350 if (first_match == NULL) { 1351 /* 1352 * No IPv6 hits. Is this a single 1353 * dest? 1354 */ 1355 WARN1(ep, ebuf, gettext( 1356 "No IPv6 source address of " 1357 "matching scope for name %s.\n"), 1358 srchp->h_name); 1359 if (single_dst) { 1360 ERROR(ep, ebuf, gettext( 1361 "Only a single IPV6 " 1362 "destination " 1363 "address.\n")); 1364 } else { 1365 /* Continue, but do I print? */ 1366 continue; /* for loop */ 1367 } 1368 1369 /* I should never reach here. */ 1370 } 1371 sin6->sin6_family = AF_INET6; 1372 if (*walker != NULL) { 1373 /* 1374 * Early loop exit. Issue a 1375 * null-source warning? 1376 */ 1377 WARN1(ep, ebuf, gettext( 1378 "Multiple IPv6 source addresses " 1379 "for %s of the same scope, using " 1380 "unspecified source instead.\n"), 1381 srchp->h_name); 1382 } else { 1383 /* 1384 * If I reach here w/o hitting the 1385 * previous if statements, I have a 1386 * single source address for this 1387 * destination. 1388 */ 1389 bcopy(first_match, &sin6->sin6_addr, 1390 sizeof (struct in6_addr)); 1391 } 1392 } 1393 } 1394 1395 /* 1396 * If there are errors at this point there is no 1397 * point sending anything to PF_KEY. 1398 */ 1399 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 1400 1401 /* Save off a copy for later writing... */ 1402 msgp = (struct sadb_msg *)buffer; 1403 bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len)); 1404 1405 rc = key_write(keysock, buffer, SADB_64TO8(msgp->sadb_msg_len)); 1406 if (rc == -1) 1407 Bail("write() to PF_KEY socket (in doaddresses)"); 1408 1409 /* Blank the key for paranoia's sake. */ 1410 bzero(buffer, buffer_size); 1411 time_critical_enter(); 1412 do { 1413 rc = read(keysock, buffer, buffer_size); 1414 if (rc == -1) 1415 Bail("read (in doaddresses)"); 1416 } while (msgp->sadb_msg_seq != seq || 1417 msgp->sadb_msg_pid != mypid); 1418 time_critical_exit(); 1419 1420 /* 1421 * I should _never_ hit the following unless: 1422 * 1423 * 1. There is a kernel bug. 1424 * 2. Another process is mistakenly using my pid in a PF_KEY 1425 * message. 1426 */ 1427 if (msgp->sadb_msg_type != sadb_msg_type || 1428 msgp->sadb_msg_satype != sadb_msg_satype) { 1429 syslog((LOG_NOTICE|LOG_AUTH), gettext( 1430 "doaddresses: Unexpected returned message " 1431 "(%d exp %d)\n"), msgp->sadb_msg_type, 1432 sadb_msg_type); 1433 Bail("doaddresses: Unexpected returned message"); 1434 } 1435 1436 if (msgp->sadb_msg_errno != 0) { 1437 char addrprint[INET6_ADDRSTRLEN]; 1438 int on_errno = 0; 1439 char *on_errno_msg; 1440 1441 /* 1442 * Print different error messages depending 1443 * on the SADB message type being processed. 1444 * If we get a ESRCH error for a GET/DELETE 1445 * messages, we report that the SA does not 1446 * exist. If we get a EEXIST error for a 1447 * ADD/UPDATE message, we report that the 1448 * SA already exists. 1449 */ 1450 if (sadb_msg_type == SADB_GET || 1451 sadb_msg_type == SADB_DELETE) { 1452 on_errno = ESRCH; 1453 on_errno_msg = "does not exist"; 1454 } else if (sadb_msg_type == SADB_ADD || 1455 sadb_msg_type == SADB_UPDATE) { 1456 on_errno = EEXIST; 1457 on_errno_msg = "already exists"; 1458 } 1459 1460 errno = msgp->sadb_msg_errno; 1461 if (errno == on_errno) { 1462 ERROR2(ep, ebuf, gettext( 1463 "Association (type = %s) " 1464 "with spi 0x%x and addr\n"), 1465 rparsesatype(msgp->sadb_msg_satype), 1466 ntohl(spi)); 1467 ERROR2(ep, ebuf, "%s %s.\n", 1468 do_inet_ntop(dsthp->h_addr_list[i], 1469 addrprint, sizeof (addrprint)), 1470 on_errno_msg); 1471 msgp = (struct sadb_msg *)savebuf; 1472 bcopy(savebuf, buffer, 1473 SADB_64TO8(msgp->sadb_msg_len)); 1474 continue; 1475 } else { 1476 if (errno == EINVAL) { 1477 ERROR2(ep, ebuf, gettext( 1478 "PF_KEY Diagnostic code %u: %s.\n"), 1479 msgp->sadb_x_msg_diagnostic, 1480 keysock_diag( 1481 msgp->sadb_x_msg_diagnostic)); 1482 } else { 1483 Bail("return message (in doaddresses)"); 1484 } 1485 } 1486 } 1487 1488 if (cmd == CMD_GET) { 1489 if (msgp->sadb_msg_len > MAX_GET_SIZE) { 1490 WARN1(ep, ebuf, gettext("WARNING: " 1491 "SA information bigger than %d bytes.\n"), 1492 SADB_64TO8(MAX_GET_SIZE)); 1493 } 1494 print_samsg(stdout, buffer, B_FALSE, vflag, nflag); 1495 } 1496 1497 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 1498 1499 /* ...and then restore the saved buffer. */ 1500 msgp = (struct sadb_msg *)savebuf; 1501 bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len)); 1502 lines_added++; 1503 } 1504 1505 /* Degenerate case, h_addr_list[0] == NULL. */ 1506 if (i == 0) 1507 Bail("Empty destination address list"); 1508 1509 /* 1510 * free(ebuf) even if there are no errors. 1511 * handle_errors() won't return here. 1512 */ 1513 handle_errors(ep, ebuf, B_TRUE, B_TRUE); 1514 } 1515 1516 /* 1517 * Perform an add or an update. ADD and UPDATE are similar in the extensions 1518 * they need. 1519 */ 1520 static void 1521 doaddup(int cmd, int satype, char *argv[], char *ebuf) 1522 { 1523 uint64_t *buffer, *nexthdr; 1524 struct sadb_msg msg; 1525 struct sadb_sa *assoc = NULL; 1526 struct sadb_address *src = NULL, *dst = NULL; 1527 struct sadb_address *isrc = NULL, *idst = NULL; 1528 struct sadb_address *natt_local = NULL, *natt_remote = NULL; 1529 struct sadb_key *encrypt = NULL, *auth = NULL; 1530 struct sadb_ident *srcid = NULL, *dstid = NULL; 1531 struct sadb_lifetime *hard = NULL, *soft = NULL; /* Current? */ 1532 struct sockaddr_in6 *sin6; 1533 /* MLS TODO: Need sensitivity eventually. */ 1534 int next, token, sa_len, alloclen, totallen = sizeof (msg), prefix; 1535 uint32_t spi = 0; 1536 char *thiscmd, *pstr; 1537 boolean_t readstate = B_FALSE, unspec_src = B_FALSE; 1538 boolean_t alloc_inner = B_FALSE, use_natt = B_FALSE; 1539 struct hostent *srchp = NULL, *dsthp = NULL, *isrchp = NULL, 1540 *idsthp = NULL; 1541 struct hostent *natt_lhp = NULL, *natt_rhp = NULL; 1542 uint16_t srcport = 0, dstport = 0, natt_lport = 0, natt_rport = 0, 1543 isrcport = 0, idstport = 0; 1544 uint8_t proto = 0, iproto = 0; 1545 char *ep = NULL; 1546 1547 thiscmd = (cmd == CMD_ADD) ? "add" : "update"; 1548 1549 msg_init(&msg, ((cmd == CMD_ADD) ? SADB_ADD : SADB_UPDATE), 1550 (uint8_t)satype); 1551 1552 /* Assume last element in argv is set to NULL. */ 1553 do { 1554 token = parseextval(*argv, &next); 1555 argv++; 1556 switch (token) { 1557 case TOK_EOF: 1558 /* Do nothing, I'm done. */ 1559 break; 1560 case TOK_UNKNOWN: 1561 ERROR1(ep, ebuf, gettext( 1562 "Unknown extension field \"%s\" \n"), *(argv - 1)); 1563 break; 1564 case TOK_SPI: 1565 case TOK_REPLAY: 1566 case TOK_STATE: 1567 case TOK_AUTHALG: 1568 case TOK_ENCRALG: 1569 case TOK_ENCAP: 1570 /* 1571 * May want to place this chunk of code in a function. 1572 * 1573 * This code checks for duplicate entries on a command 1574 * line. 1575 */ 1576 1577 /* Allocate the SADB_EXT_SA extension. */ 1578 if (assoc == NULL) { 1579 assoc = malloc(sizeof (*assoc)); 1580 if (assoc == NULL) 1581 Bail("malloc(assoc)"); 1582 bzero(assoc, sizeof (*assoc)); 1583 assoc->sadb_sa_exttype = SADB_EXT_SA; 1584 assoc->sadb_sa_len = 1585 SADB_8TO64(sizeof (*assoc)); 1586 totallen += sizeof (*assoc); 1587 } 1588 switch (token) { 1589 case TOK_SPI: 1590 /* 1591 * If some cretin types in "spi 0" then he/she 1592 * can type in another SPI. 1593 */ 1594 if (assoc->sadb_sa_spi != 0) { 1595 ERROR(ep, ebuf, gettext( 1596 "Can only specify " 1597 "single SPI value.\n")); 1598 break; 1599 } 1600 /* Must convert SPI to network order! */ 1601 assoc->sadb_sa_spi = 1602 htonl((uint32_t)parsenum(*argv, B_TRUE, 1603 ebuf)); 1604 if (assoc->sadb_sa_spi == 0) { 1605 ERROR(ep, ebuf, gettext( 1606 "Invalid SPI value \"0\" .\n")); 1607 } 1608 break; 1609 case TOK_REPLAY: 1610 /* 1611 * That same cretin can do the same with 1612 * replay. 1613 */ 1614 if (assoc->sadb_sa_replay != 0) { 1615 ERROR(ep, ebuf, gettext( 1616 "Can only specify " 1617 "single replay window size.\n")); 1618 break; 1619 } 1620 assoc->sadb_sa_replay = 1621 (uint8_t)parsenum(*argv, B_TRUE, ebuf); 1622 if (assoc->sadb_sa_replay != 0) { 1623 WARN(ep, ebuf, gettext( 1624 "WARNING: Replay with manual" 1625 " keying considered harmful.\n")); 1626 } 1627 break; 1628 case TOK_STATE: 1629 /* 1630 * 0 is an actual state value, LARVAL. This 1631 * means that one can type in the larval state 1632 * and then type in another state on the same 1633 * command line. 1634 */ 1635 if (assoc->sadb_sa_state != 0) { 1636 ERROR(ep, ebuf, gettext( 1637 "Can only specify " 1638 "single SA state.\n")); 1639 break; 1640 } 1641 assoc->sadb_sa_state = parsestate(*argv, 1642 ebuf); 1643 readstate = B_TRUE; 1644 break; 1645 case TOK_AUTHALG: 1646 if (assoc->sadb_sa_auth != 0) { 1647 ERROR(ep, ebuf, gettext( 1648 "Can only specify " 1649 "single auth algorithm.\n")); 1650 break; 1651 } 1652 assoc->sadb_sa_auth = parsealg(*argv, 1653 IPSEC_PROTO_AH, ebuf); 1654 break; 1655 case TOK_ENCRALG: 1656 if (satype == SADB_SATYPE_AH) { 1657 ERROR(ep, ebuf, gettext("Cannot specify" 1658 " encryption with SA type ah.\n")); 1659 break; 1660 } 1661 if (assoc->sadb_sa_encrypt != 0) { 1662 ERROR(ep, ebuf, gettext( 1663 "Can only specify " 1664 "single encryption algorithm.\n")); 1665 break; 1666 } 1667 assoc->sadb_sa_encrypt = parsealg(*argv, 1668 IPSEC_PROTO_ESP, ebuf); 1669 break; 1670 case TOK_ENCAP: 1671 if (use_natt) { 1672 ERROR(ep, ebuf, gettext( 1673 "Can only specify single" 1674 " encapsulation.\n")); 1675 break; 1676 } 1677 if (strncmp(*argv, "udp", 3)) { 1678 ERROR(ep, ebuf, gettext( 1679 "Can only specify udp" 1680 " encapsulation.\n")); 1681 break; 1682 } 1683 use_natt = B_TRUE; 1684 /* set assoc flags later */ 1685 break; 1686 } 1687 argv++; 1688 break; 1689 case TOK_SRCPORT: 1690 if (srcport != 0) { 1691 ERROR(ep, ebuf, gettext("Can only specify " 1692 "single source port.\n")); 1693 break; 1694 } 1695 srcport = parsenum(*argv, B_TRUE, ebuf); 1696 argv++; 1697 break; 1698 case TOK_DSTPORT: 1699 if (dstport != 0) { 1700 ERROR(ep, ebuf, gettext("Can only specify " 1701 "single destination port.\n")); 1702 break; 1703 } 1704 dstport = parsenum(*argv, B_TRUE, ebuf); 1705 argv++; 1706 break; 1707 case TOK_ISRCPORT: 1708 alloc_inner = B_TRUE; 1709 if (isrcport != 0) { 1710 ERROR(ep, ebuf, gettext( 1711 "Can only specify " 1712 "single inner-source port.\n")); 1713 break; 1714 } 1715 isrcport = parsenum(*argv, B_TRUE, ebuf); 1716 argv++; 1717 break; 1718 case TOK_IDSTPORT: 1719 alloc_inner = B_TRUE; 1720 if (idstport != 0) { 1721 ERROR(ep, ebuf, gettext( 1722 "Can only specify " 1723 "single inner-destination port.\n")); 1724 break; 1725 } 1726 idstport = parsenum(*argv, B_TRUE, ebuf); 1727 argv++; 1728 break; 1729 case TOK_NATLPORT: 1730 if (natt_lport != 0) { 1731 ERROR(ep, ebuf, gettext( 1732 "Can only specify " 1733 "single NAT-T local port.\n")); 1734 break; 1735 } 1736 natt_lport = parsenum(*argv, B_TRUE, ebuf); 1737 argv++; 1738 break; 1739 case TOK_NATRPORT: 1740 if (natt_rport != 0) { 1741 ERROR(ep, ebuf, gettext( 1742 "Can only specify " 1743 "single NAT-T remote port.\n")); 1744 break; 1745 } 1746 natt_rport = parsenum(*argv, B_TRUE, ebuf); 1747 argv++; 1748 break; 1749 1750 case TOK_PROTO: 1751 if (proto != 0) { 1752 ERROR(ep, ebuf, gettext( 1753 "Can only specify " 1754 "single protocol.\n")); 1755 break; 1756 } 1757 proto = parsenum(*argv, B_TRUE, ebuf); 1758 argv++; 1759 break; 1760 case TOK_IPROTO: 1761 alloc_inner = B_TRUE; 1762 if (iproto != 0) { 1763 ERROR(ep, ebuf, gettext( 1764 "Can only specify " 1765 "single inner protocol.\n")); 1766 break; 1767 } 1768 iproto = parsenum(*argv, B_TRUE, ebuf); 1769 argv++; 1770 break; 1771 case TOK_SRCADDR: 1772 case TOK_SRCADDR6: 1773 if (src != NULL) { 1774 ERROR(ep, ebuf, gettext( 1775 "Can only specify " 1776 "single source address.\n")); 1777 break; 1778 } 1779 sa_len = parseaddr(*argv, &srchp, 1780 (token == TOK_SRCADDR6), ebuf); 1781 if (srchp == NULL) { 1782 ERROR1(ep, ebuf, gettext( 1783 "Unknown src address \"%s\"\n"), *argv); 1784 break; 1785 } 1786 argv++; 1787 /* 1788 * Round of the sockaddr length to an 8 byte 1789 * boundary to make PF_KEY happy. 1790 */ 1791 alloclen = sizeof (*src) + roundup(sa_len, 8); 1792 src = malloc(alloclen); 1793 if (src == NULL) 1794 Bail("malloc(src)"); 1795 totallen += alloclen; 1796 src->sadb_address_len = SADB_8TO64(alloclen); 1797 src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 1798 src->sadb_address_reserved = 0; 1799 src->sadb_address_prefixlen = 0; 1800 src->sadb_address_proto = 0; 1801 if (srchp == &dummy.he) { 1802 /* 1803 * Single address with -n flag. 1804 */ 1805 sin6 = (struct sockaddr_in6 *)(src + 1); 1806 bzero(sin6, sizeof (*sin6)); 1807 sin6->sin6_family = AF_INET6; 1808 bcopy(srchp->h_addr_list[0], &sin6->sin6_addr, 1809 sizeof (struct in6_addr)); 1810 } 1811 break; 1812 case TOK_DSTADDR: 1813 case TOK_DSTADDR6: 1814 if (dst != NULL) { 1815 ERROR(ep, ebuf, gettext( 1816 "Can only specify single " 1817 "destination address.\n")); 1818 break; 1819 } 1820 sa_len = parseaddr(*argv, &dsthp, 1821 (token == TOK_DSTADDR6), ebuf); 1822 if (dsthp == NULL) { 1823 ERROR1(ep, ebuf, gettext( 1824 "Unknown dst address \"%s\"\n"), *argv); 1825 break; 1826 } 1827 argv++; 1828 alloclen = sizeof (*dst) + roundup(sa_len, 8); 1829 dst = malloc(alloclen); 1830 if (dst == NULL) 1831 Bail("malloc(dst)"); 1832 totallen += alloclen; 1833 dst->sadb_address_len = SADB_8TO64(alloclen); 1834 dst->sadb_address_exttype = SADB_EXT_ADDRESS_DST; 1835 dst->sadb_address_reserved = 0; 1836 dst->sadb_address_prefixlen = 0; 1837 dst->sadb_address_proto = 0; 1838 if (dsthp == &dummy.he) { 1839 /* 1840 * Single address with -n flag. 1841 */ 1842 sin6 = (struct sockaddr_in6 *)(dst + 1); 1843 bzero(sin6, sizeof (*sin6)); 1844 sin6->sin6_family = AF_INET6; 1845 bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr, 1846 sizeof (struct in6_addr)); 1847 } 1848 break; 1849 case TOK_PROXYADDR: 1850 case TOK_PROXYADDR6: 1851 if (isrc != NULL) { 1852 ERROR(ep, ebuf, gettext( 1853 "Can only specify single " 1854 "proxy/inner-source address.\n")); 1855 break; 1856 } 1857 if ((pstr = strchr(*argv, '/')) != NULL) { 1858 /* Parse out the prefix. */ 1859 errno = 0; 1860 prefix = strtol(pstr + 1, NULL, 10); 1861 if (errno != 0) { 1862 ERROR1(ep, ebuf, gettext( 1863 "Invalid prefix %s."), pstr); 1864 break; 1865 } 1866 /* Recycle pstr */ 1867 alloclen = (int)(pstr - *argv); 1868 pstr = malloc(alloclen + 1); 1869 if (pstr == NULL) { 1870 Bail("malloc(pstr)"); 1871 } 1872 (void) strlcpy(pstr, *argv, alloclen + 1); 1873 } else { 1874 pstr = *argv; 1875 /* 1876 * Assume mapping to AF_INET6, and we're a host. 1877 * XXX some miscreants may still make classful 1878 * assumptions. If this is a problem, fix it 1879 * here. 1880 */ 1881 prefix = 128; 1882 } 1883 sa_len = parseaddr(pstr, &isrchp, 1884 (token == TOK_PROXYADDR6), ebuf); 1885 if (isrchp == NULL) { 1886 ERROR1(ep, ebuf, gettext( 1887 "Unknown proxy/inner-source address " 1888 "\"%s\"\n"), *argv); 1889 break; 1890 } 1891 if (pstr != *argv) 1892 free(pstr); 1893 argv++; 1894 alloclen = sizeof (*isrc) + roundup(sa_len, 8); 1895 isrc = malloc(alloclen); 1896 if (isrc == NULL) 1897 Bail("malloc(isrc)"); 1898 totallen += alloclen; 1899 isrc->sadb_address_len = SADB_8TO64(alloclen); 1900 isrc->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; 1901 isrc->sadb_address_reserved = 0; 1902 isrc->sadb_address_prefixlen = prefix; 1903 isrc->sadb_address_proto = 0; 1904 if (isrchp == &dummy.he || 1905 isrchp->h_addr_list[1] == NULL) { 1906 /* 1907 * Single address with -n flag or single name. 1908 */ 1909 sin6 = (struct sockaddr_in6 *)(isrc + 1); 1910 bzero(sin6, sizeof (*sin6)); 1911 sin6->sin6_family = AF_INET6; 1912 bcopy(isrchp->h_addr_list[0], &sin6->sin6_addr, 1913 sizeof (struct in6_addr)); 1914 /* 1915 * normalize prefixlen for IPv4-mapped 1916 * addresses. 1917 */ 1918 if (prefix <= 32 && 1919 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 1920 isrc->sadb_address_prefixlen += 96; 1921 alloc_inner = B_TRUE; 1922 } else { 1923 /* 1924 * If the proxy/isrc address is vague, don't 1925 * bother. 1926 */ 1927 totallen -= alloclen; 1928 free(isrc); 1929 isrc = NULL; 1930 WARN1(ep, ebuf, gettext( 1931 "Proxy/inner-source address %s " 1932 "is vague, not using.\n"), isrchp->h_name); 1933 freehostent(isrchp); 1934 isrchp = NULL; 1935 break; 1936 } 1937 break; 1938 case TOK_IDSTADDR: 1939 case TOK_IDSTADDR6: 1940 if (idst != NULL) { 1941 ERROR(ep, ebuf, gettext( 1942 "Can only specify single " 1943 "inner-destination address.\n")); 1944 break; 1945 } 1946 if ((pstr = strchr(*argv, '/')) != NULL) { 1947 /* Parse out the prefix. */ 1948 errno = 0; 1949 prefix = strtol(pstr + 1, NULL, 10); 1950 if (errno != 0) { 1951 ERROR1(ep, ebuf, gettext( 1952 "Invalid prefix %s.\n"), pstr); 1953 break; 1954 } 1955 /* Recycle pstr */ 1956 alloclen = (int)(pstr - *argv); 1957 pstr = malloc(alloclen + 1); 1958 if (pstr == NULL) { 1959 Bail("malloc(pstr)"); 1960 } 1961 (void) strlcpy(pstr, *argv, alloclen + 1); 1962 } else { 1963 pstr = *argv; 1964 /* 1965 * Assume mapping to AF_INET6, and we're a host. 1966 * XXX some miscreants may still make classful 1967 * assumptions. If this is a problem, fix it 1968 * here. 1969 */ 1970 prefix = 128; 1971 } 1972 sa_len = parseaddr(pstr, &idsthp, 1973 (token == TOK_IDSTADDR6), ebuf); 1974 if (idsthp == NULL) { 1975 ERROR1(ep, ebuf, gettext( 1976 "Unknown Inner Src address " 1977 " \"%s\"\n"), *argv); 1978 break; 1979 } 1980 if (pstr != *argv) 1981 free(pstr); 1982 argv++; 1983 alloclen = sizeof (*idst) + roundup(sa_len, 8); 1984 idst = malloc(alloclen); 1985 if (idst == NULL) 1986 Bail("malloc(idst)"); 1987 totallen += alloclen; 1988 idst->sadb_address_len = SADB_8TO64(alloclen); 1989 idst->sadb_address_exttype = 1990 SADB_X_EXT_ADDRESS_INNER_DST; 1991 idst->sadb_address_reserved = 0; 1992 idst->sadb_address_prefixlen = prefix; 1993 idst->sadb_address_proto = 0; 1994 if (idsthp == &dummy.he || 1995 idsthp->h_addr_list[1] == NULL) { 1996 /* 1997 * Single address with -n flag or single name. 1998 */ 1999 sin6 = (struct sockaddr_in6 *)(idst + 1); 2000 bzero(sin6, sizeof (*sin6)); 2001 sin6->sin6_family = AF_INET6; 2002 bcopy(idsthp->h_addr_list[0], &sin6->sin6_addr, 2003 sizeof (struct in6_addr)); 2004 /* 2005 * normalize prefixlen for IPv4-mapped 2006 * addresses. 2007 */ 2008 if (prefix <= 32 && 2009 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 2010 idst->sadb_address_prefixlen += 96; 2011 alloc_inner = B_TRUE; 2012 } else { 2013 /* 2014 * If the idst address is vague, don't bother. 2015 */ 2016 totallen -= alloclen; 2017 free(idst); 2018 idst = NULL; 2019 WARN1(ep, ebuf, gettext( 2020 "Inner destination address %s " 2021 "is vague, not using.\n"), idsthp->h_name); 2022 freehostent(idsthp); 2023 idsthp = NULL; 2024 break; 2025 } 2026 break; 2027 case TOK_NATLOC: 2028 if (natt_local != NULL) { 2029 ERROR(ep, ebuf, gettext( 2030 "Can only specify " 2031 "single NAT-T local address.\n")); 2032 break; 2033 } 2034 sa_len = parseaddr(*argv, &natt_lhp, 0, ebuf); 2035 if (natt_lhp == NULL) { 2036 ERROR1(ep, ebuf, gettext( 2037 "Unknown NAT-T local address \"%s\"\n"), 2038 *argv); 2039 break; 2040 } 2041 argv++; 2042 /* 2043 * Round of the sockaddr length to an 8 byte 2044 * boundary to make PF_KEY happy. 2045 */ 2046 alloclen = sizeof (*natt_local) + roundup(sa_len, 8); 2047 natt_local = malloc(alloclen); 2048 if (natt_local == NULL) 2049 Bail("malloc(natt_local)"); 2050 totallen += alloclen; 2051 natt_local->sadb_address_len = SADB_8TO64(alloclen); 2052 natt_local->sadb_address_exttype = 2053 SADB_X_EXT_ADDRESS_NATT_LOC; 2054 natt_local->sadb_address_reserved = 0; 2055 natt_local->sadb_address_prefixlen = 0; 2056 natt_local->sadb_address_proto = 0; 2057 if (natt_lhp == &dummy.he || 2058 natt_lhp->h_addr_list[1] == NULL) { 2059 /* 2060 * Single address with -n flag or single name. 2061 */ 2062 sin6 = (struct sockaddr_in6 *)(natt_local + 1); 2063 bzero(sin6, sizeof (*sin6)); 2064 sin6->sin6_family = AF_INET6; 2065 bcopy(natt_lhp->h_addr_list[0], 2066 &sin6->sin6_addr, sizeof (struct in6_addr)); 2067 } else { 2068 /* 2069 * If the nat-local address is vague, don't 2070 * bother. 2071 */ 2072 totallen -= alloclen; 2073 free(natt_local); 2074 natt_local = NULL; 2075 WARN1(ep, ebuf, gettext( 2076 "NAT-T local address %s " 2077 "is vague, not using.\n"), 2078 natt_lhp->h_name); 2079 freehostent(natt_lhp); 2080 natt_lhp = NULL; 2081 break; 2082 } 2083 break; 2084 case TOK_NATREM: 2085 if (natt_remote != NULL) { 2086 ERROR(ep, ebuf, gettext( 2087 "Can only specify " 2088 "single NAT-T remote address.\n")); 2089 break; 2090 } 2091 sa_len = parseaddr(*argv, &natt_rhp, 0, ebuf); 2092 if (natt_rhp == NULL) { 2093 ERROR1(ep, ebuf, gettext( 2094 "Unknown NAT-T remote address \"%s\"\n"), 2095 *argv); 2096 break; 2097 } 2098 argv++; 2099 /* 2100 * Round of the sockaddr length to an 8 byte 2101 * boundary to make PF_KEY happy. 2102 */ 2103 alloclen = sizeof (*natt_remote) + roundup(sa_len, 8); 2104 natt_remote = malloc(alloclen); 2105 if (natt_remote == NULL) 2106 Bail("malloc(natt_remote)"); 2107 totallen += alloclen; 2108 natt_remote->sadb_address_len = SADB_8TO64(alloclen); 2109 natt_remote->sadb_address_exttype = 2110 SADB_X_EXT_ADDRESS_NATT_REM; 2111 natt_remote->sadb_address_reserved = 0; 2112 natt_remote->sadb_address_prefixlen = 0; 2113 natt_remote->sadb_address_proto = 0; 2114 if (natt_rhp == &dummy.he || 2115 natt_rhp->h_addr_list[1] == NULL) { 2116 /* 2117 * Single address with -n flag or single name. 2118 */ 2119 sin6 = (struct sockaddr_in6 *)(natt_remote + 1); 2120 bzero(sin6, sizeof (*sin6)); 2121 sin6->sin6_family = AF_INET6; 2122 bcopy(natt_rhp->h_addr_list[0], 2123 &sin6->sin6_addr, sizeof (struct in6_addr)); 2124 } else { 2125 /* 2126 * If the nat-renote address is vague, don't 2127 * bother. 2128 */ 2129 totallen -= alloclen; 2130 free(natt_remote); 2131 natt_remote = NULL; 2132 WARN1(ep, ebuf, gettext( 2133 "NAT-T remote address %s " 2134 "is vague, not using.\n"), 2135 natt_rhp->h_name); 2136 freehostent(natt_rhp); 2137 natt_rhp = NULL; 2138 break; 2139 } 2140 break; 2141 case TOK_ENCRKEY: 2142 if (encrypt != NULL) { 2143 ERROR(ep, ebuf, gettext( 2144 "Can only specify " 2145 "single encryption key.\n")); 2146 break; 2147 } 2148 if (assoc != NULL && 2149 assoc->sadb_sa_encrypt == SADB_EALG_NULL) { 2150 FATAL(ep, ebuf, gettext( 2151 "Cannot specify a key with NULL " 2152 "encryption algorithm.\n")); 2153 break; 2154 } 2155 encrypt = parsekey(*argv, ebuf); 2156 argv++; 2157 if (encrypt == NULL) { 2158 ERROR(ep, ebuf, gettext( 2159 "Invalid encryption key.\n")); 2160 break; 2161 } 2162 totallen += SADB_64TO8(encrypt->sadb_key_len); 2163 encrypt->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; 2164 break; 2165 case TOK_AUTHKEY: 2166 if (auth != NULL) { 2167 ERROR(ep, ebuf, gettext( 2168 "Can only specify single" 2169 " authentication key.\n")); 2170 break; 2171 } 2172 auth = parsekey(*argv, ebuf); 2173 argv++; 2174 if (auth == NULL) { 2175 ERROR(ep, ebuf, gettext( 2176 "Invalid authentication key.\n")); 2177 break; 2178 } 2179 totallen += SADB_64TO8(auth->sadb_key_len); 2180 auth->sadb_key_exttype = SADB_EXT_KEY_AUTH; 2181 break; 2182 case TOK_SRCIDTYPE: 2183 if (*argv == NULL || *(argv + 1) == NULL) { 2184 FATAL(ep, ebuf, gettext( 2185 "Unexpected end of command " 2186 "line - Expecting Src Type.\n")); 2187 /* NOTREACHED */ 2188 break; 2189 } 2190 if (srcid != NULL) { 2191 ERROR(ep, ebuf, gettext( 2192 "Can only specify single" 2193 " source certificate identity.\n")); 2194 break; 2195 } 2196 alloclen = sizeof (*srcid) + 2197 roundup(strlen(*(argv + 1)) + 1, 8); 2198 srcid = malloc(alloclen); 2199 if (srcid == NULL) 2200 Bail("malloc(srcid)"); 2201 totallen += alloclen; 2202 srcid->sadb_ident_type = parseidtype(*argv, ebuf); 2203 argv++; 2204 srcid->sadb_ident_len = SADB_8TO64(alloclen); 2205 srcid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC; 2206 srcid->sadb_ident_reserved = 0; 2207 srcid->sadb_ident_id = 0; /* Not useful here. */ 2208 (void) strlcpy((char *)(srcid + 1), *argv, alloclen); 2209 argv++; 2210 break; 2211 case TOK_DSTIDTYPE: 2212 if (*argv == NULL || *(argv + 1) == NULL) { 2213 ERROR(ep, ebuf, gettext( 2214 "Unexpected end of command" 2215 " line - expecting dst type.\n")); 2216 break; 2217 } 2218 if (dstid != NULL) { 2219 ERROR(ep, ebuf, gettext( 2220 "Can only specify single destination " 2221 "certificate identity.\n")); 2222 break; 2223 } 2224 alloclen = sizeof (*dstid) + 2225 roundup(strlen(*(argv + 1)) + 1, 8); 2226 dstid = malloc(alloclen); 2227 if (dstid == NULL) 2228 Bail("malloc(dstid)"); 2229 totallen += alloclen; 2230 dstid->sadb_ident_type = parseidtype(*argv, ebuf); 2231 argv++; 2232 dstid->sadb_ident_len = SADB_8TO64(alloclen); 2233 dstid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST; 2234 dstid->sadb_ident_reserved = 0; 2235 dstid->sadb_ident_id = 0; /* Not useful here. */ 2236 (void) strlcpy((char *)(dstid + 1), *argv, alloclen); 2237 argv++; 2238 break; 2239 case TOK_HARD_ALLOC: 2240 case TOK_HARD_BYTES: 2241 case TOK_HARD_ADDTIME: 2242 case TOK_HARD_USETIME: 2243 if (hard == NULL) { 2244 hard = malloc(sizeof (*hard)); 2245 if (hard == NULL) 2246 Bail("malloc(hard_lifetime)"); 2247 bzero(hard, sizeof (*hard)); 2248 hard->sadb_lifetime_exttype = 2249 SADB_EXT_LIFETIME_HARD; 2250 hard->sadb_lifetime_len = 2251 SADB_8TO64(sizeof (*hard)); 2252 totallen += sizeof (*hard); 2253 } 2254 switch (token) { 2255 case TOK_HARD_ALLOC: 2256 if (hard->sadb_lifetime_allocations != 0) { 2257 ERROR(ep, ebuf, gettext( 2258 "Can only specify single" 2259 " hard allocation limit.\n")); 2260 break; 2261 } 2262 hard->sadb_lifetime_allocations = 2263 (uint32_t)parsenum(*argv, B_TRUE, ebuf); 2264 break; 2265 case TOK_HARD_BYTES: 2266 if (hard->sadb_lifetime_bytes != 0) { 2267 ERROR(ep, ebuf, gettext( 2268 "Can only specify " 2269 "single hard byte limit.\n")); 2270 break; 2271 } 2272 hard->sadb_lifetime_bytes = parsenum(*argv, 2273 B_TRUE, ebuf); 2274 break; 2275 case TOK_HARD_ADDTIME: 2276 if (hard->sadb_lifetime_addtime != 0) { 2277 ERROR(ep, ebuf, gettext( 2278 "Can only specify " 2279 "single past-add lifetime.\n")); 2280 break; 2281 } 2282 hard->sadb_lifetime_addtime = parsenum(*argv, 2283 B_TRUE, ebuf); 2284 break; 2285 case TOK_HARD_USETIME: 2286 if (hard->sadb_lifetime_usetime != 0) { 2287 ERROR(ep, ebuf, gettext( 2288 "Can only specify " 2289 "single past-use lifetime.\n")); 2290 break; 2291 } 2292 hard->sadb_lifetime_usetime = parsenum(*argv, 2293 B_TRUE, ebuf); 2294 break; 2295 } 2296 argv++; 2297 break; 2298 case TOK_SOFT_ALLOC: 2299 case TOK_SOFT_BYTES: 2300 case TOK_SOFT_ADDTIME: 2301 case TOK_SOFT_USETIME: 2302 if (soft == NULL) { 2303 soft = malloc(sizeof (*soft)); 2304 if (soft == NULL) 2305 Bail("malloc(soft_lifetime)"); 2306 bzero(soft, sizeof (*soft)); 2307 soft->sadb_lifetime_exttype = 2308 SADB_EXT_LIFETIME_SOFT; 2309 soft->sadb_lifetime_len = 2310 SADB_8TO64(sizeof (*soft)); 2311 totallen += sizeof (*soft); 2312 } 2313 switch (token) { 2314 case TOK_SOFT_ALLOC: 2315 if (soft->sadb_lifetime_allocations != 0) { 2316 ERROR(ep, ebuf, gettext( 2317 "Can only specify single" 2318 " soft allocation limit.\n")); 2319 break; 2320 } 2321 soft->sadb_lifetime_allocations = 2322 (uint32_t)parsenum(*argv, B_TRUE, ebuf); 2323 break; 2324 case TOK_SOFT_BYTES: 2325 if (soft->sadb_lifetime_bytes != 0) { 2326 ERROR(ep, ebuf, gettext( 2327 "Can only specify single" 2328 " soft byte limit.\n")); 2329 break; 2330 } 2331 soft->sadb_lifetime_bytes = parsenum(*argv, 2332 B_TRUE, ebuf); 2333 break; 2334 case TOK_SOFT_ADDTIME: 2335 if (soft->sadb_lifetime_addtime != 0) { 2336 ERROR(ep, ebuf, gettext( 2337 "Can only specify single" 2338 " past-add lifetime.\n")); 2339 break; 2340 } 2341 soft->sadb_lifetime_addtime = parsenum(*argv, 2342 B_TRUE, ebuf); 2343 break; 2344 case TOK_SOFT_USETIME: 2345 if (soft->sadb_lifetime_usetime != 0) { 2346 ERROR(ep, ebuf, gettext( 2347 "Can only specify single" 2348 " past-use lifetime.\n")); 2349 break; 2350 } 2351 soft->sadb_lifetime_usetime = parsenum(*argv, 2352 B_TRUE, ebuf); 2353 break; 2354 } 2355 argv++; 2356 break; 2357 default: 2358 ERROR1(ep, ebuf, gettext( 2359 "Don't use extension %s for add/update.\n"), 2360 *(argv - 1)); 2361 break; 2362 } 2363 } while (token != TOK_EOF); 2364 2365 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 2366 2367 #define PORT_ONLY_ALLOCATE(af, socktype, exttype, extvar, port) { \ 2368 alloclen = sizeof (sadb_address_t) + roundup(sizeof (socktype), 8); \ 2369 (extvar) = calloc(1, alloclen); \ 2370 if ((extvar) == NULL) { \ 2371 Bail("malloc(implicit port)"); \ 2372 } \ 2373 totallen += alloclen; \ 2374 (extvar)->sadb_address_len = SADB_8TO64(alloclen); \ 2375 (extvar)->sadb_address_exttype = (exttype); \ 2376 /* sin/sin6 has equivalent offsets for ports! */ \ 2377 sin6 = (struct sockaddr_in6 *)((extvar) + 1); \ 2378 sin6->sin6_family = (af); \ 2379 sin6->sin6_port = (port); \ 2380 } 2381 2382 /* 2383 * If we specify inner ports or NAT ports w/o addresses, we still need 2384 * to allocate. Also, if we have one inner address, we need the 2385 * other, even if we don't specify anything. 2386 */ 2387 if (use_natt) { 2388 if (natt_lport != 0 && natt_local == NULL) { 2389 PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in, 2390 SADB_X_EXT_ADDRESS_NATT_LOC, natt_local, 2391 natt_lport); 2392 } 2393 2394 if (natt_rport != 0 && natt_remote == NULL) { 2395 PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in, 2396 SADB_X_EXT_ADDRESS_NATT_REM, natt_remote, 2397 natt_rport); 2398 } 2399 } else { 2400 if (natt_lport != 0 || natt_rport != 0) { 2401 ERROR(ep, ebuf, gettext("Must specify 'encap udp' " 2402 "with any NAT-T port.\n")); 2403 } else if (natt_local != NULL || natt_remote != NULL) { 2404 ERROR(ep, ebuf, gettext("Must specify 'encap udp' " 2405 "with any NAT-T address.\n")); 2406 } 2407 } 2408 2409 if (alloc_inner && idst == NULL) { 2410 PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6, 2411 SADB_X_EXT_ADDRESS_INNER_DST, idst, 0); 2412 } 2413 2414 if (alloc_inner && isrc == NULL) { 2415 PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6, 2416 SADB_X_EXT_ADDRESS_INNER_SRC, isrc, 0); 2417 } 2418 #undef PORT_ONLY_ALLOCATE 2419 2420 /* 2421 * Okay, so now I have all of the potential extensions! 2422 * Allocate a single contiguous buffer. Keep in mind that it'll 2423 * be enough because the key itself will be yanked. 2424 */ 2425 2426 if (src == NULL && dst != NULL) { 2427 /* 2428 * Set explicit unspecified source address. 2429 */ 2430 size_t lenbytes = SADB_64TO8(dst->sadb_address_len); 2431 2432 unspec_src = B_TRUE; 2433 totallen += lenbytes; 2434 src = malloc(lenbytes); 2435 if (src == NULL) 2436 Bail("malloc(implicit src)"); 2437 /* Confusing, but we're copying from DST to SRC. :) */ 2438 bcopy(dst, src, lenbytes); 2439 src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 2440 sin6 = (struct sockaddr_in6 *)(src + 1); 2441 bzero(sin6, sizeof (*sin6)); 2442 sin6->sin6_family = AF_INET6; 2443 } 2444 2445 msg.sadb_msg_len = SADB_8TO64(totallen); 2446 2447 buffer = malloc(totallen); 2448 nexthdr = buffer; 2449 bcopy(&msg, nexthdr, sizeof (msg)); 2450 nexthdr += SADB_8TO64(sizeof (msg)); 2451 if (assoc != NULL) { 2452 if (assoc->sadb_sa_spi == 0) { 2453 ERROR1(ep, ebuf, gettext( 2454 "The SPI value is missing for " 2455 "the association you wish to %s.\n"), thiscmd); 2456 } 2457 if (assoc->sadb_sa_auth == 0 && assoc->sadb_sa_encrypt == 0 && 2458 cmd == CMD_ADD) { 2459 free(assoc); 2460 FATAL(ep, ebuf, gettext( 2461 "Select at least one algorithm " 2462 "for this add.\n")); 2463 } 2464 2465 /* Hack to let user specify NULL ESP implicitly. */ 2466 if (msg.sadb_msg_satype == SADB_SATYPE_ESP && 2467 assoc->sadb_sa_encrypt == 0) 2468 assoc->sadb_sa_encrypt = SADB_EALG_NULL; 2469 2470 /* 0 is an actual value. Print a warning if it was entered. */ 2471 if (assoc->sadb_sa_state == 0) { 2472 if (readstate) { 2473 ERROR(ep, ebuf, gettext( 2474 "WARNING: Cannot set LARVAL SA state.\n")); 2475 } 2476 assoc->sadb_sa_state = SADB_SASTATE_MATURE; 2477 } 2478 2479 if (use_natt) { 2480 if (natt_remote != NULL) 2481 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_REM; 2482 if (natt_local != NULL) 2483 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_LOC; 2484 } 2485 2486 if (alloc_inner) { 2487 /* 2488 * For now, assume RFC 3884's dream of transport-mode 2489 * SAs with inner IP address selectors will not 2490 * happen. 2491 */ 2492 assoc->sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL; 2493 if (proto != 0 && proto != IPPROTO_ENCAP && 2494 proto != IPPROTO_IPV6) { 2495 ERROR1(ep, ebuf, gettext( 2496 "WARNING: Protocol type %d not " 2497 "for use with Tunnel-Mode SA.\n"), proto); 2498 /* Continue and let PF_KEY scream... */ 2499 } 2500 } 2501 2502 bcopy(assoc, nexthdr, SADB_64TO8(assoc->sadb_sa_len)); 2503 nexthdr += assoc->sadb_sa_len; 2504 /* Save the SPI for the case of an error. */ 2505 spi = assoc->sadb_sa_spi; 2506 free(assoc); 2507 } else { 2508 if (spi == 0) 2509 ERROR1(ep, ebuf, gettext( 2510 "Need to define SPI for %s.\n"), thiscmd); 2511 ERROR1(ep, ebuf, gettext( 2512 "Need SA parameters for %s.\n"), thiscmd); 2513 } 2514 2515 if (hard != NULL) { 2516 bcopy(hard, nexthdr, SADB_64TO8(hard->sadb_lifetime_len)); 2517 nexthdr += hard->sadb_lifetime_len; 2518 free(hard); 2519 } 2520 2521 if (soft != NULL) { 2522 bcopy(soft, nexthdr, SADB_64TO8(soft->sadb_lifetime_len)); 2523 nexthdr += soft->sadb_lifetime_len; 2524 free(soft); 2525 } 2526 2527 if (encrypt == NULL && auth == NULL && cmd == CMD_ADD) { 2528 ERROR(ep, ebuf, gettext( 2529 "Must have at least one key for an add.\n")); 2530 } 2531 2532 if (encrypt != NULL) { 2533 bcopy(encrypt, nexthdr, SADB_64TO8(encrypt->sadb_key_len)); 2534 nexthdr += encrypt->sadb_key_len; 2535 bzero(encrypt, SADB_64TO8(encrypt->sadb_key_len)); 2536 free(encrypt); 2537 } 2538 2539 if (auth != NULL) { 2540 bcopy(auth, nexthdr, SADB_64TO8(auth->sadb_key_len)); 2541 nexthdr += auth->sadb_key_len; 2542 bzero(auth, SADB_64TO8(auth->sadb_key_len)); 2543 free(auth); 2544 } 2545 2546 if (srcid != NULL) { 2547 bcopy(srcid, nexthdr, SADB_64TO8(srcid->sadb_ident_len)); 2548 nexthdr += srcid->sadb_ident_len; 2549 free(srcid); 2550 } 2551 2552 if (dstid != NULL) { 2553 bcopy(dstid, nexthdr, SADB_64TO8(dstid->sadb_ident_len)); 2554 nexthdr += dstid->sadb_ident_len; 2555 free(dstid); 2556 } 2557 2558 if (dst != NULL) { 2559 bcopy(dst, nexthdr, SADB_64TO8(dst->sadb_address_len)); 2560 free(dst); 2561 dst = (struct sadb_address *)nexthdr; 2562 dst->sadb_address_proto = proto; 2563 ((struct sockaddr_in6 *)(dst + 1))->sin6_port = htons(dstport); 2564 nexthdr += dst->sadb_address_len; 2565 } else { 2566 FATAL1(ep, ebuf, gettext( 2567 "Need destination address for %s.\n"), thiscmd); 2568 } 2569 2570 if (use_natt) { 2571 if (natt_remote == NULL && natt_local == NULL) { 2572 ERROR(ep, ebuf, gettext( 2573 "Must specify NAT-T remote or local address " 2574 "for UDP encapsulation.\n")); 2575 } 2576 2577 if (natt_remote != NULL) { 2578 bcopy(natt_remote, nexthdr, 2579 SADB_64TO8(natt_remote->sadb_address_len)); 2580 free(natt_remote); 2581 natt_remote = (struct sadb_address *)nexthdr; 2582 nexthdr += natt_remote->sadb_address_len; 2583 ((struct sockaddr_in6 *)(natt_remote + 1))->sin6_port = 2584 htons(natt_rport); 2585 } 2586 2587 if (natt_local != NULL) { 2588 bcopy(natt_local, nexthdr, 2589 SADB_64TO8(natt_local->sadb_address_len)); 2590 free(natt_local); 2591 natt_local = (struct sadb_address *)nexthdr; 2592 nexthdr += natt_local->sadb_address_len; 2593 ((struct sockaddr_in6 *)(natt_local + 1))->sin6_port = 2594 htons(natt_lport); 2595 } 2596 } 2597 2598 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 2599 2600 /* 2601 * PF_KEY requires a source address extension, even if the source 2602 * address itself is unspecified. (See "Set explicit unspecified..." 2603 * code fragment above. Destination reality check was above.) 2604 */ 2605 bcopy(src, nexthdr, SADB_64TO8(src->sadb_address_len)); 2606 free(src); 2607 src = (struct sadb_address *)nexthdr; 2608 src->sadb_address_proto = proto; 2609 ((struct sockaddr_in6 *)(src + 1))->sin6_port = htons(srcport); 2610 nexthdr += src->sadb_address_len; 2611 2612 if (isrc != NULL) { 2613 bcopy(isrc, nexthdr, SADB_64TO8(isrc->sadb_address_len)); 2614 free(isrc); 2615 isrc = (struct sadb_address *)nexthdr; 2616 isrc->sadb_address_proto = iproto; 2617 ((struct sockaddr_in6 *)(isrc + 1))->sin6_port = 2618 htons(isrcport); 2619 nexthdr += isrc->sadb_address_len; 2620 } 2621 2622 if (idst != NULL) { 2623 bcopy(idst, nexthdr, SADB_64TO8(idst->sadb_address_len)); 2624 free(idst); 2625 idst = (struct sadb_address *)nexthdr; 2626 idst->sadb_address_proto = iproto; 2627 ((struct sockaddr_in6 *)(idst + 1))->sin6_port = 2628 htons(idstport); 2629 nexthdr += idst->sadb_address_len; 2630 } 2631 2632 if (cflag) { 2633 /* 2634 * Assume the checked cmd would have worked if it was actually 2635 * used. doaddresses() will increment lines_added if it 2636 * succeeds. 2637 */ 2638 lines_added++; 2639 } else { 2640 doaddresses((cmd == CMD_ADD) ? SADB_ADD : SADB_UPDATE, satype, 2641 cmd, srchp, dsthp, src, dst, unspec_src, buffer, totallen, 2642 spi, ebuf); 2643 } 2644 2645 if (isrchp != NULL && isrchp != &dummy.he) 2646 freehostent(isrchp); 2647 if (idsthp != NULL && idsthp != &dummy.he) 2648 freehostent(idsthp); 2649 if (srchp != NULL && srchp != &dummy.he) 2650 freehostent(srchp); 2651 if (dsthp != NULL && dsthp != &dummy.he) 2652 freehostent(dsthp); 2653 if (natt_lhp != NULL && natt_lhp != &dummy.he) 2654 freehostent(natt_lhp); 2655 if (natt_rhp != NULL && natt_rhp != &dummy.he) 2656 freehostent(natt_rhp); 2657 2658 free(ebuf); 2659 free(buffer); 2660 } 2661 2662 /* 2663 * DELETE and GET are similar, in that they only need the extensions 2664 * required to _find_ an SA, and then either delete it or obtain its 2665 * information. 2666 */ 2667 static void 2668 dodelget(int cmd, int satype, char *argv[], char *ebuf) 2669 { 2670 struct sadb_msg *msg = (struct sadb_msg *)get_buffer; 2671 uint64_t *nextext; 2672 struct sadb_sa *assoc = NULL; 2673 struct sadb_address *src = NULL, *dst = NULL; 2674 int next, token, sa_len; 2675 char *thiscmd; 2676 uint32_t spi; 2677 struct hostent *srchp = NULL, *dsthp = NULL; 2678 struct sockaddr_in6 *sin6; 2679 boolean_t unspec_src = B_TRUE; 2680 uint16_t srcport = 0, dstport = 0; 2681 uint8_t proto = 0; 2682 char *ep = NULL; 2683 2684 msg_init(msg, ((cmd == CMD_GET) ? SADB_GET : SADB_DELETE), 2685 (uint8_t)satype); 2686 /* Set the first extension header to right past the base message. */ 2687 nextext = (uint64_t *)(msg + 1); 2688 bzero(nextext, sizeof (get_buffer) - sizeof (*msg)); 2689 2690 thiscmd = (cmd == CMD_GET) ? "get" : "delete"; 2691 2692 #define ALLOC_ADDR_EXT(ext, exttype) \ 2693 (ext) = (struct sadb_address *)nextext; \ 2694 nextext = (uint64_t *)((ext) + 1); \ 2695 nextext += SADB_8TO64(roundup(sa_len, 8)); \ 2696 (ext)->sadb_address_exttype = exttype; \ 2697 (ext)->sadb_address_len = nextext - ((uint64_t *)ext); 2698 2699 /* Assume last element in argv is set to NULL. */ 2700 do { 2701 token = parseextval(*argv, &next); 2702 argv++; 2703 switch (token) { 2704 case TOK_EOF: 2705 /* Do nothing, I'm done. */ 2706 break; 2707 case TOK_UNKNOWN: 2708 ERROR1(ep, ebuf, gettext( 2709 "Unknown extension field \"%s\"\n"), *(argv - 1)); 2710 break; 2711 case TOK_SPI: 2712 if (assoc != NULL) { 2713 ERROR(ep, ebuf, gettext( 2714 "Can only specify single SPI value.\n")); 2715 break; 2716 } 2717 assoc = (struct sadb_sa *)nextext; 2718 nextext = (uint64_t *)(assoc + 1); 2719 assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc)); 2720 assoc->sadb_sa_exttype = SADB_EXT_SA; 2721 assoc->sadb_sa_spi = htonl((uint32_t)parsenum(*argv, 2722 B_TRUE, ebuf)); 2723 spi = assoc->sadb_sa_spi; 2724 argv++; 2725 break; 2726 case TOK_SRCPORT: 2727 if (srcport != 0) { 2728 ERROR(ep, ebuf, gettext( 2729 "Can only specify single source port.\n")); 2730 break; 2731 } 2732 srcport = parsenum(*argv, B_TRUE, ebuf); 2733 argv++; 2734 break; 2735 case TOK_DSTPORT: 2736 if (dstport != 0) { 2737 ERROR(ep, ebuf, gettext( 2738 "Can only " 2739 "specify single destination port.\n")); 2740 break; 2741 } 2742 dstport = parsenum(*argv, B_TRUE, ebuf); 2743 argv++; 2744 break; 2745 case TOK_PROTO: 2746 if (proto != 0) { 2747 ERROR(ep, ebuf, gettext( 2748 "Can only specify single protocol.\n")); 2749 break; 2750 } 2751 proto = parsenum(*argv, B_TRUE, ebuf); 2752 argv++; 2753 break; 2754 case TOK_SRCADDR: 2755 case TOK_SRCADDR6: 2756 if (src != NULL) { 2757 ERROR(ep, ebuf, gettext( 2758 "Can only specify single source addr.\n")); 2759 break; 2760 } 2761 sa_len = parseaddr(*argv, &srchp, 2762 (token == TOK_SRCADDR6), ebuf); 2763 if (srchp == NULL) { 2764 ERROR1(ep, ebuf, gettext( 2765 "Unknown source address \"%s\"\n"), *argv); 2766 break; 2767 } 2768 argv++; 2769 2770 unspec_src = B_FALSE; 2771 2772 ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC); 2773 2774 if (srchp == &dummy.he) { 2775 /* 2776 * Single address with -n flag. 2777 */ 2778 sin6 = (struct sockaddr_in6 *)(src + 1); 2779 bzero(sin6, sizeof (*sin6)); 2780 sin6->sin6_family = AF_INET6; 2781 bcopy(srchp->h_addr_list[0], &sin6->sin6_addr, 2782 sizeof (struct in6_addr)); 2783 } 2784 /* The rest is pre-bzeroed for us. */ 2785 break; 2786 case TOK_DSTADDR: 2787 case TOK_DSTADDR6: 2788 if (dst != NULL) { 2789 ERROR(ep, ebuf, gettext( 2790 "Can only specify single destination " 2791 "address.\n")); 2792 break; 2793 } 2794 sa_len = parseaddr(*argv, &dsthp, 2795 (token == TOK_SRCADDR6), ebuf); 2796 if (dsthp == NULL) { 2797 ERROR1(ep, ebuf, gettext( 2798 "Unknown destination address \"%s\"\n"), 2799 *argv); 2800 break; 2801 } 2802 argv++; 2803 2804 ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST); 2805 2806 if (dsthp == &dummy.he) { 2807 /* 2808 * Single address with -n flag. 2809 */ 2810 sin6 = (struct sockaddr_in6 *)(dst + 1); 2811 bzero(sin6, sizeof (*sin6)); 2812 sin6->sin6_family = AF_INET6; 2813 bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr, 2814 sizeof (struct in6_addr)); 2815 } 2816 /* The rest is pre-bzeroed for us. */ 2817 break; 2818 default: 2819 ERROR2(ep, ebuf, gettext( 2820 "Don't use extension %s for '%s' command.\n"), 2821 *(argv - 1), thiscmd); 2822 break; 2823 } 2824 } while (token != TOK_EOF); 2825 2826 handle_errors(ep, ebuf, B_TRUE, B_FALSE); 2827 2828 if ((srcport != 0) && (src == NULL)) { 2829 ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC); 2830 sin6 = (struct sockaddr_in6 *)(src + 1); 2831 src->sadb_address_proto = proto; 2832 bzero(sin6, sizeof (*sin6)); 2833 sin6->sin6_family = AF_INET6; 2834 sin6->sin6_port = htons(srcport); 2835 } 2836 2837 if ((dstport != 0) && (dst == NULL)) { 2838 ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST); 2839 sin6 = (struct sockaddr_in6 *)(dst + 1); 2840 src->sadb_address_proto = proto; 2841 bzero(sin6, sizeof (*sin6)); 2842 sin6->sin6_family = AF_INET6; 2843 sin6->sin6_port = htons(dstport); 2844 } 2845 2846 /* So I have enough of the message to send it down! */ 2847 msg->sadb_msg_len = nextext - get_buffer; 2848 2849 if (assoc == NULL) { 2850 FATAL1(ep, ebuf, gettext( 2851 "Need SA parameters for %s.\n"), thiscmd); 2852 } 2853 2854 if (cflag) { 2855 /* 2856 * Assume the checked cmd would have worked if it was actually 2857 * used. doaddresses() will increment lines_added if it 2858 * succeeds. 2859 */ 2860 lines_added++; 2861 } else { 2862 doaddresses((cmd == CMD_GET) ? SADB_GET : SADB_DELETE, satype, 2863 cmd, srchp, dsthp, src, dst, unspec_src, get_buffer, 2864 sizeof (get_buffer), spi, NULL); 2865 } 2866 2867 if (srchp != NULL && srchp != &dummy.he) 2868 freehostent(srchp); 2869 if (dsthp != NULL && dsthp != &dummy.he) 2870 freehostent(dsthp); 2871 } 2872 2873 /* 2874 * "ipseckey monitor" should exit very gracefully if ^C is tapped. 2875 */ 2876 static void 2877 monitor_catch(int signal) 2878 { 2879 errx(signal, gettext("Bailing on signal %d."), signal); 2880 } 2881 2882 /* 2883 * Loop forever, listening on PF_KEY messages. 2884 */ 2885 static void 2886 domonitor(boolean_t passive) 2887 { 2888 struct sadb_msg *samsg; 2889 int rc; 2890 2891 /* Catch ^C. */ 2892 (void) signal(SIGINT, monitor_catch); 2893 2894 samsg = (struct sadb_msg *)get_buffer; 2895 if (!passive) { 2896 (void) printf(gettext("Actively")); 2897 msg_init(samsg, SADB_X_PROMISC, 1); /* Turn ON promisc. */ 2898 rc = key_write(keysock, samsg, sizeof (*samsg)); 2899 if (rc == -1) 2900 Bail("write (SADB_X_PROMISC)"); 2901 } else { 2902 (void) printf(gettext("Passively")); 2903 } 2904 (void) printf(gettext(" monitoring the PF_KEY socket.\n")); 2905 2906 for (; ; ) { 2907 /* 2908 * I assume that read() is non-blocking, and will never 2909 * return 0. 2910 */ 2911 rc = read(keysock, samsg, sizeof (get_buffer)); 2912 if (rc == -1) 2913 Bail("read (in domonitor)"); 2914 (void) printf(gettext("Read %d bytes.\n"), rc); 2915 /* 2916 * Q: Should I use the same method of printing as GET does? 2917 * A: For now, yes. 2918 */ 2919 print_samsg(stdout, get_buffer, B_TRUE, vflag, nflag); 2920 (void) putchar('\n'); 2921 } 2922 } 2923 2924 /* 2925 * Either mask or unmask all relevant signals. 2926 */ 2927 static void 2928 mask_signals(boolean_t unmask) 2929 { 2930 sigset_t set; 2931 static sigset_t oset; 2932 2933 if (unmask) { 2934 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 2935 } else { 2936 (void) sigfillset(&set); 2937 (void) sigprocmask(SIG_SETMASK, &set, &oset); 2938 } 2939 } 2940 2941 /* 2942 * Assorted functions to print help text. 2943 */ 2944 #define puts_tr(s) (void) puts(gettext(s)) 2945 2946 static void 2947 doattrhelp() 2948 { 2949 int i; 2950 2951 puts_tr("\nSA attributes:"); 2952 2953 for (i = 0; tokens[i].string != NULL; i++) { 2954 if (i%3 == 0) 2955 (void) printf("\n"); 2956 (void) printf(" %-15.15s", tokens[i].string); 2957 } 2958 (void) printf("\n"); 2959 } 2960 2961 static void 2962 dohelpcmd(char *cmds) 2963 { 2964 int cmd; 2965 2966 if (strcmp(cmds, "attr") == 0) { 2967 doattrhelp(); 2968 return; 2969 } 2970 2971 cmd = parsecmd(cmds); 2972 switch (cmd) { 2973 case CMD_UPDATE: 2974 puts_tr("update - Update an existing SA"); 2975 break; 2976 case CMD_ADD: 2977 puts_tr("add - Add a new security association (SA)"); 2978 break; 2979 case CMD_DELETE: 2980 puts_tr("delete - Delete an SA"); 2981 break; 2982 case CMD_GET: 2983 puts_tr("get - Display an SA"); 2984 break; 2985 case CMD_FLUSH: 2986 puts_tr("flush - Delete all SAs"); 2987 break; 2988 case CMD_DUMP: 2989 puts_tr("dump - Display all SAs"); 2990 break; 2991 case CMD_MONITOR: 2992 puts_tr("monitor - Monitor all PF_KEY reply messages."); 2993 break; 2994 case CMD_PMONITOR: 2995 puts_tr( 2996 "pmonitor, passive_monitor - Monitor PF_KEY messages that"); 2997 puts_tr( 2998 " reply to all PF_KEY sockets."); 2999 break; 3000 3001 case CMD_QUIT: 3002 puts_tr("quit, exit - Exit the program"); 3003 break; 3004 case CMD_SAVE: 3005 puts_tr("save - Saves all SAs to a file"); 3006 break; 3007 case CMD_HELP: 3008 puts_tr("help - Display list of commands"); 3009 puts_tr("help <cmd> - Display help for command"); 3010 puts_tr("help attr - Display possible SA attributes"); 3011 break; 3012 default: 3013 (void) printf(gettext("%s: Unknown command\n"), cmds); 3014 break; 3015 } 3016 } 3017 3018 3019 static void 3020 dohelp(char *cmds) 3021 { 3022 if (cmds != NULL) { 3023 dohelpcmd(cmds); 3024 return; 3025 } 3026 puts_tr("Commands"); 3027 puts_tr("--------"); 3028 puts_tr("?, help - Display this list"); 3029 puts_tr("help <cmd> - Display help for command"); 3030 puts_tr("help attr - Display possible SA attributes"); 3031 puts_tr("quit, exit - Exit the program"); 3032 puts_tr("monitor - Monitor all PF_KEY reply messages."); 3033 puts_tr("pmonitor, passive_monitor - Monitor PF_KEY messages that"); 3034 puts_tr(" reply to all PF_KEY sockets."); 3035 puts_tr(""); 3036 puts_tr("The following commands are of the form:"); 3037 puts_tr(" <command> {SA type} {attribute value}*"); 3038 puts_tr(""); 3039 puts_tr("add (interactive only) - Add a new security association (SA)"); 3040 puts_tr("update (interactive only) - Update an existing SA"); 3041 puts_tr("delete - Delete an SA"); 3042 puts_tr("get - Display an SA"); 3043 puts_tr("flush - Delete all SAs"); 3044 puts_tr("dump - Display all SAs"); 3045 puts_tr("save - Saves all SAs to a file"); 3046 } 3047 3048 /* 3049 * "Parse" a command line from argv. 3050 */ 3051 static void 3052 parseit(int argc, char *argv[], char *ebuf, boolean_t read_cmdfile) 3053 { 3054 int cmd, satype; 3055 char *ep = NULL; 3056 3057 if (argc == 0) 3058 return; 3059 cmd = parsecmd(*argv++); 3060 3061 /* 3062 * Some commands loop forever and should only be run from the command 3063 * line, they should never be run from a command file as this may 3064 * be used at boot time. 3065 */ 3066 switch (cmd) { 3067 case CMD_HELP: 3068 if (read_cmdfile) 3069 ERROR(ep, ebuf, gettext("Help not appropriate in " 3070 "config file.")); 3071 else 3072 dohelp(*argv); 3073 return; 3074 case CMD_MONITOR: 3075 if (read_cmdfile) 3076 ERROR(ep, ebuf, gettext("Monitor not appropriate in " 3077 "config file.")); 3078 else 3079 domonitor(B_FALSE); 3080 break; 3081 case CMD_PMONITOR: 3082 if (read_cmdfile) 3083 ERROR(ep, ebuf, gettext("Monitor not appropriate in " 3084 "config file.")); 3085 else 3086 domonitor(B_TRUE); 3087 break; 3088 case CMD_QUIT: 3089 EXIT_OK(NULL); 3090 } 3091 3092 handle_errors(ep, ebuf, B_FALSE, B_FALSE); 3093 3094 satype = parsesatype(*argv, ebuf); 3095 3096 if (satype != SADB_SATYPE_UNSPEC) { 3097 argv++; 3098 } else { 3099 /* 3100 * You must specify either "all" or a specific SA type 3101 * for the "save" command. 3102 */ 3103 if (cmd == CMD_SAVE) 3104 if (*argv == NULL) { 3105 FATAL(ep, ebuf, gettext( 3106 "Must specify a specific " 3107 "SA type for save.\n")); 3108 } else { 3109 argv++; 3110 } 3111 } 3112 3113 switch (cmd) { 3114 case CMD_FLUSH: 3115 if (!cflag) 3116 doflush(satype); 3117 /* 3118 * If this was called because of an entry in a cmd file 3119 * then this action needs to be counted to prevent 3120 * do_interactive() treating this as an error. 3121 */ 3122 lines_added++; 3123 break; 3124 case CMD_ADD: 3125 case CMD_UPDATE: 3126 /* 3127 * NOTE: Shouldn't allow ADDs or UPDATEs with keying material 3128 * from the command line. 3129 */ 3130 if (!interactive) { 3131 errx(1, gettext( 3132 "can't do ADD or UPDATE from the command line.\n")); 3133 } 3134 if (satype == SADB_SATYPE_UNSPEC) { 3135 FATAL(ep, ebuf, gettext( 3136 "Must specify a specific SA type.")); 3137 /* NOTREACHED */ 3138 } 3139 /* Parse for extensions, including keying material. */ 3140 doaddup(cmd, satype, argv, ebuf); 3141 break; 3142 case CMD_DELETE: 3143 case CMD_GET: 3144 if (satype == SADB_SATYPE_UNSPEC) { 3145 FATAL(ep, ebuf, gettext( 3146 "Must specify a single SA type.")); 3147 /* NOTREACHED */ 3148 } 3149 /* Parse for bare minimum to locate an SA. */ 3150 dodelget(cmd, satype, argv, ebuf); 3151 break; 3152 case CMD_DUMP: 3153 if (read_cmdfile) 3154 ERROR(ep, ebuf, gettext("Dump not appropriate in " 3155 "config file.")); 3156 else 3157 dodump(satype, NULL); 3158 break; 3159 case CMD_SAVE: 3160 if (read_cmdfile) { 3161 ERROR(ep, ebuf, gettext("Save not appropriate in " 3162 "config file.")); 3163 } else { 3164 mask_signals(B_FALSE); /* Mask signals */ 3165 dodump(satype, opensavefile(argv[0])); 3166 mask_signals(B_TRUE); /* Unmask signals */ 3167 } 3168 break; 3169 default: 3170 warnx(gettext("Unknown command (%s).\n"), 3171 *(argv - ((satype == SADB_SATYPE_UNSPEC) ? 1 : 2))); 3172 usage(); 3173 } 3174 handle_errors(ep, ebuf, B_FALSE, B_FALSE); 3175 } 3176 3177 int 3178 main(int argc, char *argv[]) 3179 { 3180 int ch; 3181 FILE *infile = stdin, *savefile; 3182 boolean_t dosave = B_FALSE, readfile = B_FALSE; 3183 char *configfile = NULL; 3184 struct stat sbuf; 3185 3186 (void) setlocale(LC_ALL, ""); 3187 #if !defined(TEXT_DOMAIN) 3188 #define TEXT_DOMAIN "SYS_TEST" 3189 #endif 3190 (void) textdomain(TEXT_DOMAIN); 3191 3192 /* 3193 * Check to see if the command is being run from smf(5). 3194 */ 3195 my_fmri = getenv("SMF_FMRI"); 3196 3197 openlog("ipseckey", LOG_CONS, LOG_AUTH); 3198 if (getuid() != 0) { 3199 errx(1, "Insufficient privileges to run ipseckey."); 3200 } 3201 3202 /* umask me to paranoid, I only want to create files read-only */ 3203 (void) umask((mode_t)00377); 3204 3205 while ((ch = getopt(argc, argv, "pnvf:s:c:")) != EOF) 3206 switch (ch) { 3207 case 'p': 3208 pflag = B_TRUE; 3209 break; 3210 case 'n': 3211 nflag = B_TRUE; 3212 break; 3213 case 'v': 3214 vflag = B_TRUE; 3215 break; 3216 case 'c': 3217 cflag = B_TRUE; 3218 /* FALLTHRU */ 3219 case 'f': 3220 if (dosave) 3221 usage(); 3222 infile = fopen(optarg, "r"); 3223 if (infile == NULL) { 3224 EXIT_BADCONFIG2("Unable to open configuration " 3225 "file: %s\n", optarg); 3226 } 3227 /* 3228 * Check file permissions/ownership and warn or 3229 * fail depending on state of SMF control. 3230 */ 3231 if (fstat(fileno(infile), &sbuf) == -1) { 3232 (void) fclose(infile); 3233 EXIT_BADCONFIG2("Unable to stat configuration " 3234 "file: %s\n", optarg); 3235 } 3236 if (INSECURE_PERMS(sbuf)) { 3237 if (my_fmri != NULL) { 3238 (void) fclose(infile); 3239 EXIT_BADCONFIG2("Config file " 3240 "%s has insecure permissions.", 3241 optarg); 3242 } else { 3243 (void) fprintf(stderr, "%s %s\n", 3244 optarg, gettext( 3245 "has insecure permissions, will be " 3246 "rejected in permanent config.")); 3247 } 3248 } 3249 configfile = strdup(optarg); 3250 readfile = B_TRUE; 3251 break; 3252 case 's': 3253 if (readfile) 3254 usage(); 3255 dosave = B_TRUE; 3256 savefile = opensavefile(optarg); 3257 break; 3258 default: 3259 usage(); 3260 } 3261 3262 argc -= optind; 3263 argv += optind; 3264 3265 mypid = getpid(); 3266 3267 keysock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 3268 3269 if (keysock == -1) { 3270 if (errno == EPERM) { 3271 EXIT_BADPERM("Insufficient privileges to open " 3272 "PF_KEY socket.\n"); 3273 } else { 3274 /* some other reason */ 3275 EXIT_FATAL("Opening PF_KEY socket"); 3276 } 3277 } 3278 3279 if (dosave) { 3280 mask_signals(B_FALSE); /* Mask signals */ 3281 dodump(SADB_SATYPE_UNSPEC, savefile); 3282 mask_signals(B_TRUE); /* Unmask signals */ 3283 EXIT_OK(NULL); 3284 } 3285 3286 /* 3287 * When run from smf(5) flush any existing SA's first 3288 * otherwise you will end up in maintenance mode. 3289 */ 3290 if ((my_fmri != NULL) && readfile) { 3291 (void) fprintf(stdout, gettext( 3292 "Flushing existing SA's before adding new SA's\n")); 3293 (void) fflush(stdout); 3294 doflush(SADB_SATYPE_UNSPEC); 3295 } 3296 if (infile != stdin || *argv == NULL) { 3297 /* Go into interactive mode here. */ 3298 do_interactive(infile, configfile, "ipseckey> ", my_fmri, 3299 parseit); 3300 } 3301 parseit(argc, argv, NULL, B_FALSE); 3302 3303 return (0); 3304 } 3305