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