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