1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <unistd.h> 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <stdarg.h> 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/stat.h> 35*0Sstevel@tonic-gate #include <fcntl.h> 36*0Sstevel@tonic-gate #include <sys/sysconf.h> 37*0Sstevel@tonic-gate #include <strings.h> 38*0Sstevel@tonic-gate #include <ctype.h> 39*0Sstevel@tonic-gate #include <errno.h> 40*0Sstevel@tonic-gate #include <sys/socket.h> 41*0Sstevel@tonic-gate #include <netdb.h> 42*0Sstevel@tonic-gate #include <netinet/in.h> 43*0Sstevel@tonic-gate #include <arpa/inet.h> 44*0Sstevel@tonic-gate #include <net/pfkeyv2.h> 45*0Sstevel@tonic-gate #include <net/pfpolicy.h> 46*0Sstevel@tonic-gate #include <libintl.h> 47*0Sstevel@tonic-gate #include <setjmp.h> 48*0Sstevel@tonic-gate #include <libgen.h> 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate #include "ipsec_util.h" 51*0Sstevel@tonic-gate #include "ikedoor.h" 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate /* 54*0Sstevel@tonic-gate * This file contains support functions that are shared by the ipsec 55*0Sstevel@tonic-gate * utilities including ipseckey(1m) and ikeadm(1m). 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* Set standard default/initial values for globals... */ 59*0Sstevel@tonic-gate boolean_t pflag = B_FALSE; /* paranoid w.r.t. printing keying material */ 60*0Sstevel@tonic-gate boolean_t nflag = B_FALSE; /* avoid nameservice? */ 61*0Sstevel@tonic-gate boolean_t interactive = B_FALSE; /* util not running on cmdline */ 62*0Sstevel@tonic-gate boolean_t readfile = B_FALSE; /* cmds are being read from a file */ 63*0Sstevel@tonic-gate uint_t lineno = 0; /* track location if reading cmds from file */ 64*0Sstevel@tonic-gate jmp_buf env; /* for error recovery in interactive/readfile modes */ 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate /* 67*0Sstevel@tonic-gate * Print errno and exit if cmdline or readfile, reset state if interactive 68*0Sstevel@tonic-gate */ 69*0Sstevel@tonic-gate void 70*0Sstevel@tonic-gate bail(char *what) 71*0Sstevel@tonic-gate { 72*0Sstevel@tonic-gate if (errno != 0) 73*0Sstevel@tonic-gate warn(what); 74*0Sstevel@tonic-gate else 75*0Sstevel@tonic-gate warnx(gettext("Error: %s"), what); 76*0Sstevel@tonic-gate if (readfile) { 77*0Sstevel@tonic-gate warnx(gettext("System error on line %u."), lineno); 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate if (interactive && !readfile) 80*0Sstevel@tonic-gate longjmp(env, 2); 81*0Sstevel@tonic-gate exit(1); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate /* 85*0Sstevel@tonic-gate * Print caller-supplied variable-arg error msg, then exit if cmdline or 86*0Sstevel@tonic-gate * readfile, or reset state if interactive. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate /*PRINTFLIKE1*/ 89*0Sstevel@tonic-gate void 90*0Sstevel@tonic-gate bail_msg(char *fmt, ...) 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate va_list ap; 93*0Sstevel@tonic-gate char msgbuf[BUFSIZ]; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate va_start(ap, fmt); 96*0Sstevel@tonic-gate (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap); 97*0Sstevel@tonic-gate va_end(ap); 98*0Sstevel@tonic-gate if (readfile) 99*0Sstevel@tonic-gate warnx(gettext("ERROR on line %u:\n%s\n"), lineno, msgbuf); 100*0Sstevel@tonic-gate else 101*0Sstevel@tonic-gate warnx(gettext("ERROR: %s\n"), msgbuf); 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate if (interactive && !readfile) 104*0Sstevel@tonic-gate longjmp(env, 1); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate exit(1); 107*0Sstevel@tonic-gate } 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* 111*0Sstevel@tonic-gate * dump_XXX functions produce ASCII output from various structures. 112*0Sstevel@tonic-gate * 113*0Sstevel@tonic-gate * Because certain errors need to do this to stderr, dump_XXX functions 114*0Sstevel@tonic-gate * take a FILE pointer. 115*0Sstevel@tonic-gate * 116*0Sstevel@tonic-gate * If an error occured while writing to the specified file, these 117*0Sstevel@tonic-gate * functions return -1, zero otherwise. 118*0Sstevel@tonic-gate */ 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate int 121*0Sstevel@tonic-gate dump_sockaddr(struct sockaddr *sa, boolean_t addr_only, FILE *where) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate struct sockaddr_in *sin; 124*0Sstevel@tonic-gate struct sockaddr_in6 *sin6; 125*0Sstevel@tonic-gate char *printable_addr, *protocol; 126*0Sstevel@tonic-gate uint8_t *addrptr; 127*0Sstevel@tonic-gate char storage[INET6_ADDRSTRLEN]; 128*0Sstevel@tonic-gate uint16_t port; 129*0Sstevel@tonic-gate boolean_t unspec; 130*0Sstevel@tonic-gate struct hostent *hp; 131*0Sstevel@tonic-gate int getipnode_errno, addrlen; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate switch (sa->sa_family) { 134*0Sstevel@tonic-gate case AF_INET: 135*0Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 136*0Sstevel@tonic-gate sin = (struct sockaddr_in *)sa; 137*0Sstevel@tonic-gate addrptr = (uint8_t *)&sin->sin_addr; 138*0Sstevel@tonic-gate port = sin->sin_port; 139*0Sstevel@tonic-gate protocol = "AF_INET"; 140*0Sstevel@tonic-gate unspec = (sin->sin_addr.s_addr == 0); 141*0Sstevel@tonic-gate addrlen = sizeof (sin->sin_addr); 142*0Sstevel@tonic-gate break; 143*0Sstevel@tonic-gate case AF_INET6: 144*0Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 145*0Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)sa; 146*0Sstevel@tonic-gate addrptr = (uint8_t *)&sin6->sin6_addr; 147*0Sstevel@tonic-gate port = sin6->sin6_port; 148*0Sstevel@tonic-gate protocol = "AF_INET6"; 149*0Sstevel@tonic-gate unspec = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr); 150*0Sstevel@tonic-gate addrlen = sizeof (sin6->sin6_addr); 151*0Sstevel@tonic-gate break; 152*0Sstevel@tonic-gate default: 153*0Sstevel@tonic-gate return (0); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate if (inet_ntop(sa->sa_family, addrptr, storage, INET6_ADDRSTRLEN) == 157*0Sstevel@tonic-gate NULL) { 158*0Sstevel@tonic-gate printable_addr = gettext("<inet_ntop() failed>"); 159*0Sstevel@tonic-gate } else { 160*0Sstevel@tonic-gate printable_addr = storage; 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate if (addr_only) { 163*0Sstevel@tonic-gate if (fprintf(where, "%s", printable_addr) < 0) 164*0Sstevel@tonic-gate return (-1); 165*0Sstevel@tonic-gate } else { 166*0Sstevel@tonic-gate if (fprintf(where, gettext("%s: port %d, %s"), protocol, 167*0Sstevel@tonic-gate ntohs(port), printable_addr) < 0) 168*0Sstevel@tonic-gate return (-1); 169*0Sstevel@tonic-gate if (!nflag) { 170*0Sstevel@tonic-gate /* 171*0Sstevel@tonic-gate * Do AF_independent reverse hostname lookup here. 172*0Sstevel@tonic-gate */ 173*0Sstevel@tonic-gate if (unspec) { 174*0Sstevel@tonic-gate if (fprintf(where, 175*0Sstevel@tonic-gate gettext(" <unspecified>")) < 0) 176*0Sstevel@tonic-gate return (-1); 177*0Sstevel@tonic-gate } else { 178*0Sstevel@tonic-gate hp = getipnodebyaddr((char *)addrptr, addrlen, 179*0Sstevel@tonic-gate sa->sa_family, &getipnode_errno); 180*0Sstevel@tonic-gate if (hp != NULL) { 181*0Sstevel@tonic-gate if (fprintf(where, 182*0Sstevel@tonic-gate " (%s)", hp->h_name) < 0) 183*0Sstevel@tonic-gate return (-1); 184*0Sstevel@tonic-gate freehostent(hp); 185*0Sstevel@tonic-gate } else { 186*0Sstevel@tonic-gate if (fprintf(where, 187*0Sstevel@tonic-gate gettext(" <unknown>")) < 0) 188*0Sstevel@tonic-gate return (-1); 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate if (fputs(".\n", where) == EOF) 193*0Sstevel@tonic-gate return (-1); 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate return (0); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * Dump a key and bitlen 200*0Sstevel@tonic-gate */ 201*0Sstevel@tonic-gate int 202*0Sstevel@tonic-gate dump_key(uint8_t *keyp, uint_t bitlen, FILE *where) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate int numbytes; 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate numbytes = SADB_1TO8(bitlen); 207*0Sstevel@tonic-gate /* The & 0x7 is to check for leftover bits. */ 208*0Sstevel@tonic-gate if ((bitlen & 0x7) != 0) 209*0Sstevel@tonic-gate numbytes++; 210*0Sstevel@tonic-gate while (numbytes-- != 0) { 211*0Sstevel@tonic-gate if (pflag) { 212*0Sstevel@tonic-gate /* Print no keys if paranoid */ 213*0Sstevel@tonic-gate if (fprintf(where, "XX") < 0) 214*0Sstevel@tonic-gate return (-1); 215*0Sstevel@tonic-gate } else { 216*0Sstevel@tonic-gate if (fprintf(where, "%02x", *keyp++) < 0) 217*0Sstevel@tonic-gate return (-1); 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate if (fprintf(where, "/%u", bitlen) < 0) 221*0Sstevel@tonic-gate return (-1); 222*0Sstevel@tonic-gate return (0); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* 226*0Sstevel@tonic-gate * Print an authentication or encryption algorithm 227*0Sstevel@tonic-gate */ 228*0Sstevel@tonic-gate static int 229*0Sstevel@tonic-gate dump_generic_alg(uint8_t alg_num, int proto_num, FILE *where) 230*0Sstevel@tonic-gate { 231*0Sstevel@tonic-gate struct ipsecalgent *alg; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate alg = getipsecalgbynum(alg_num, proto_num, NULL); 234*0Sstevel@tonic-gate if (alg == NULL) { 235*0Sstevel@tonic-gate if (fprintf(where, gettext("<unknown %u>"), alg_num) < 0) 236*0Sstevel@tonic-gate return (-1); 237*0Sstevel@tonic-gate return (0); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate /* 241*0Sstevel@tonic-gate * Special-case <none> for backward output compat. 242*0Sstevel@tonic-gate * Assume that SADB_AALG_NONE == SADB_EALG_NONE. 243*0Sstevel@tonic-gate */ 244*0Sstevel@tonic-gate if (alg_num == SADB_AALG_NONE) { 245*0Sstevel@tonic-gate if (fputs(gettext("<none>"), where) == EOF) 246*0Sstevel@tonic-gate return (-1); 247*0Sstevel@tonic-gate } else { 248*0Sstevel@tonic-gate if (fputs(alg->a_names[0], where) == EOF) 249*0Sstevel@tonic-gate return (-1); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate freeipsecalgent(alg); 253*0Sstevel@tonic-gate return (0); 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate int 257*0Sstevel@tonic-gate dump_aalg(uint8_t aalg, FILE *where) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate return (dump_generic_alg(aalg, IPSEC_PROTO_AH, where)); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate int 263*0Sstevel@tonic-gate dump_ealg(uint8_t ealg, FILE *where) 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate return (dump_generic_alg(ealg, IPSEC_PROTO_ESP, where)); 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* 269*0Sstevel@tonic-gate * Print an SADB_IDENTTYPE string 270*0Sstevel@tonic-gate * 271*0Sstevel@tonic-gate * Also return TRUE if the actual ident may be printed, FALSE if not. 272*0Sstevel@tonic-gate * 273*0Sstevel@tonic-gate * If rc is not NULL, set its value to -1 if an error occured while writing 274*0Sstevel@tonic-gate * to the specified file, zero otherwise. 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate boolean_t 277*0Sstevel@tonic-gate dump_sadb_idtype(uint8_t idtype, FILE *where, int *rc) 278*0Sstevel@tonic-gate { 279*0Sstevel@tonic-gate boolean_t canprint = B_TRUE; 280*0Sstevel@tonic-gate int rc_val = 0; 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate switch (idtype) { 283*0Sstevel@tonic-gate case SADB_IDENTTYPE_PREFIX: 284*0Sstevel@tonic-gate if (fputs(gettext("prefix"), where) == EOF) 285*0Sstevel@tonic-gate rc_val = -1; 286*0Sstevel@tonic-gate break; 287*0Sstevel@tonic-gate case SADB_IDENTTYPE_FQDN: 288*0Sstevel@tonic-gate if (fputs(gettext("FQDN"), where) == EOF) 289*0Sstevel@tonic-gate rc_val = -1; 290*0Sstevel@tonic-gate break; 291*0Sstevel@tonic-gate case SADB_IDENTTYPE_USER_FQDN: 292*0Sstevel@tonic-gate if (fputs(gettext("user-FQDN (mbox)"), where) == EOF) 293*0Sstevel@tonic-gate rc_val = -1; 294*0Sstevel@tonic-gate break; 295*0Sstevel@tonic-gate case SADB_X_IDENTTYPE_DN: 296*0Sstevel@tonic-gate if (fputs(gettext("ASN.1 DER Distinguished Name"), 297*0Sstevel@tonic-gate where) == EOF) 298*0Sstevel@tonic-gate rc_val = -1; 299*0Sstevel@tonic-gate canprint = B_FALSE; 300*0Sstevel@tonic-gate break; 301*0Sstevel@tonic-gate case SADB_X_IDENTTYPE_GN: 302*0Sstevel@tonic-gate if (fputs(gettext("ASN.1 DER Generic Name"), where) == EOF) 303*0Sstevel@tonic-gate rc_val = -1; 304*0Sstevel@tonic-gate canprint = B_FALSE; 305*0Sstevel@tonic-gate break; 306*0Sstevel@tonic-gate case SADB_X_IDENTTYPE_KEY_ID: 307*0Sstevel@tonic-gate if (fputs(gettext("Generic key id"), where) == EOF) 308*0Sstevel@tonic-gate rc_val = -1; 309*0Sstevel@tonic-gate break; 310*0Sstevel@tonic-gate case SADB_X_IDENTTYPE_ADDR_RANGE: 311*0Sstevel@tonic-gate if (fputs(gettext("Address range"), where) == EOF) 312*0Sstevel@tonic-gate rc_val = -1; 313*0Sstevel@tonic-gate break; 314*0Sstevel@tonic-gate default: 315*0Sstevel@tonic-gate if (fprintf(where, gettext("<unknown %u>"), idtype) < 0) 316*0Sstevel@tonic-gate rc_val = -1; 317*0Sstevel@tonic-gate break; 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate if (rc != NULL) 321*0Sstevel@tonic-gate *rc = rc_val; 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate return (canprint); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * Slice an argv/argc vector from an interactive line or a read-file line. 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate static int 330*0Sstevel@tonic-gate create_argv(char *ibuf, int *newargc, char ***thisargv) 331*0Sstevel@tonic-gate { 332*0Sstevel@tonic-gate unsigned int argvlen = START_ARG; 333*0Sstevel@tonic-gate char **current; 334*0Sstevel@tonic-gate boolean_t firstchar = B_TRUE; 335*0Sstevel@tonic-gate boolean_t inquotes = B_FALSE; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate *thisargv = malloc(sizeof (char *) * argvlen); 338*0Sstevel@tonic-gate if ((*thisargv) == NULL) 339*0Sstevel@tonic-gate return (MEMORY_ALLOCATION); 340*0Sstevel@tonic-gate current = *thisargv; 341*0Sstevel@tonic-gate *current = NULL; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate for (; *ibuf != '\0'; ibuf++) { 344*0Sstevel@tonic-gate if (isspace(*ibuf)) { 345*0Sstevel@tonic-gate if (inquotes) { 346*0Sstevel@tonic-gate continue; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate if (*current != NULL) { 349*0Sstevel@tonic-gate *ibuf = '\0'; 350*0Sstevel@tonic-gate current++; 351*0Sstevel@tonic-gate if (*thisargv + argvlen == current) { 352*0Sstevel@tonic-gate /* Regrow ***thisargv. */ 353*0Sstevel@tonic-gate if (argvlen == TOO_MANY_ARGS) { 354*0Sstevel@tonic-gate free(*thisargv); 355*0Sstevel@tonic-gate return (TOO_MANY_TOKENS); 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate /* Double the allocation. */ 358*0Sstevel@tonic-gate current = realloc(*thisargv, 359*0Sstevel@tonic-gate sizeof (char *) * (argvlen << 1)); 360*0Sstevel@tonic-gate if (current == NULL) { 361*0Sstevel@tonic-gate free(*thisargv); 362*0Sstevel@tonic-gate return (MEMORY_ALLOCATION); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate *thisargv = current; 365*0Sstevel@tonic-gate current += argvlen; 366*0Sstevel@tonic-gate argvlen <<= 1; /* Double the size. */ 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate *current = NULL; 369*0Sstevel@tonic-gate } 370*0Sstevel@tonic-gate } else { 371*0Sstevel@tonic-gate if (firstchar) { 372*0Sstevel@tonic-gate firstchar = B_FALSE; 373*0Sstevel@tonic-gate if (*ibuf == COMMENT_CHAR) { 374*0Sstevel@tonic-gate free(*thisargv); 375*0Sstevel@tonic-gate return (COMMENT_LINE); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate if (*ibuf == QUOTE_CHAR) { 379*0Sstevel@tonic-gate if (inquotes) { 380*0Sstevel@tonic-gate inquotes = B_FALSE; 381*0Sstevel@tonic-gate *ibuf = '\0'; 382*0Sstevel@tonic-gate } else { 383*0Sstevel@tonic-gate inquotes = B_TRUE; 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate continue; 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate if (*current == NULL) { 388*0Sstevel@tonic-gate *current = ibuf; 389*0Sstevel@tonic-gate (*newargc)++; 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* 395*0Sstevel@tonic-gate * Tricky corner case... 396*0Sstevel@tonic-gate * I've parsed _exactly_ the amount of args as I have space. It 397*0Sstevel@tonic-gate * won't return NULL-terminated, and bad things will happen to 398*0Sstevel@tonic-gate * the caller. 399*0Sstevel@tonic-gate */ 400*0Sstevel@tonic-gate if (argvlen == *newargc) { 401*0Sstevel@tonic-gate current = realloc(*thisargv, sizeof (char *) * (argvlen + 1)); 402*0Sstevel@tonic-gate if (current == NULL) { 403*0Sstevel@tonic-gate free(*thisargv); 404*0Sstevel@tonic-gate return (MEMORY_ALLOCATION); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate *thisargv = current; 407*0Sstevel@tonic-gate current[argvlen] = NULL; 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate return (SUCCESS); 411*0Sstevel@tonic-gate } 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate /* 414*0Sstevel@tonic-gate * Enter a mode where commands are read from a file. Treat stdin special. 415*0Sstevel@tonic-gate */ 416*0Sstevel@tonic-gate void 417*0Sstevel@tonic-gate do_interactive(FILE *infile, char *promptstring, parse_cmdln_fn parseit) 418*0Sstevel@tonic-gate { 419*0Sstevel@tonic-gate char ibuf[IBUF_SIZE], holder[IBUF_SIZE]; 420*0Sstevel@tonic-gate char *hptr, **thisargv; 421*0Sstevel@tonic-gate int thisargc; 422*0Sstevel@tonic-gate boolean_t continue_in_progress = B_FALSE; 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate (void) setjmp(env); 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate interactive = B_TRUE; 427*0Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate if (infile == stdin) { 430*0Sstevel@tonic-gate (void) printf("%s", promptstring); 431*0Sstevel@tonic-gate (void) fflush(stdout); 432*0Sstevel@tonic-gate } else { 433*0Sstevel@tonic-gate readfile = B_TRUE; 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate while (fgets(ibuf, IBUF_SIZE, infile) != NULL) { 437*0Sstevel@tonic-gate if (readfile) 438*0Sstevel@tonic-gate lineno++; 439*0Sstevel@tonic-gate thisargc = 0; 440*0Sstevel@tonic-gate thisargv = NULL; 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate /* 443*0Sstevel@tonic-gate * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will 444*0Sstevel@tonic-gate * be null-terminated because of fgets(). 445*0Sstevel@tonic-gate */ 446*0Sstevel@tonic-gate if (ibuf[IBUF_SIZE - 2] != '\0') { 447*0Sstevel@tonic-gate (void) fprintf(stderr, 448*0Sstevel@tonic-gate gettext("Line %d too big.\n"), lineno); 449*0Sstevel@tonic-gate exit(1); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate if (!continue_in_progress) { 453*0Sstevel@tonic-gate /* Use -2 because of \n from fgets. */ 454*0Sstevel@tonic-gate if (ibuf[strlen(ibuf) - 2] == CONT_CHAR) { 455*0Sstevel@tonic-gate /* 456*0Sstevel@tonic-gate * Can use strcpy here, I've checked the 457*0Sstevel@tonic-gate * length already. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate (void) strcpy(holder, ibuf); 460*0Sstevel@tonic-gate hptr = &(holder[strlen(holder)]); 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* Remove the CONT_CHAR from the string. */ 463*0Sstevel@tonic-gate hptr[-2] = ' '; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate continue_in_progress = B_TRUE; 466*0Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 467*0Sstevel@tonic-gate continue; 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate } else { 470*0Sstevel@tonic-gate /* Handle continuations... */ 471*0Sstevel@tonic-gate (void) strncpy(hptr, ibuf, 472*0Sstevel@tonic-gate (size_t)(&(holder[IBUF_SIZE]) - hptr)); 473*0Sstevel@tonic-gate if (holder[IBUF_SIZE - 1] != '\0') { 474*0Sstevel@tonic-gate (void) fprintf(stderr, 475*0Sstevel@tonic-gate gettext("Command buffer overrun.\n")); 476*0Sstevel@tonic-gate exit(1); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate /* Use - 2 because of \n from fgets. */ 479*0Sstevel@tonic-gate if (hptr[strlen(hptr) - 2] == CONT_CHAR) { 480*0Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 481*0Sstevel@tonic-gate hptr += strlen(hptr); 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate /* Remove the CONT_CHAR from the string. */ 484*0Sstevel@tonic-gate hptr[-2] = ' '; 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate continue; 487*0Sstevel@tonic-gate } else { 488*0Sstevel@tonic-gate continue_in_progress = B_FALSE; 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * I've already checked the length... 491*0Sstevel@tonic-gate */ 492*0Sstevel@tonic-gate (void) strcpy(ibuf, holder); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate switch (create_argv(ibuf, &thisargc, &thisargv)) { 497*0Sstevel@tonic-gate case TOO_MANY_TOKENS: 498*0Sstevel@tonic-gate (void) fprintf(stderr, 499*0Sstevel@tonic-gate gettext("Too many input tokens.\n")); 500*0Sstevel@tonic-gate exit(1); 501*0Sstevel@tonic-gate break; 502*0Sstevel@tonic-gate case MEMORY_ALLOCATION: 503*0Sstevel@tonic-gate (void) fprintf(stderr, 504*0Sstevel@tonic-gate gettext("Memory allocation error.\n")); 505*0Sstevel@tonic-gate exit(1); 506*0Sstevel@tonic-gate break; 507*0Sstevel@tonic-gate case COMMENT_LINE: 508*0Sstevel@tonic-gate /* Comment line. */ 509*0Sstevel@tonic-gate break; 510*0Sstevel@tonic-gate default: 511*0Sstevel@tonic-gate parseit(thisargc, thisargv); 512*0Sstevel@tonic-gate free(thisargv); 513*0Sstevel@tonic-gate if (infile == stdin) { 514*0Sstevel@tonic-gate (void) printf("%s", promptstring); 515*0Sstevel@tonic-gate (void) fflush(stdout); 516*0Sstevel@tonic-gate } 517*0Sstevel@tonic-gate break; 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate if (!readfile) { 522*0Sstevel@tonic-gate (void) putchar('\n'); 523*0Sstevel@tonic-gate (void) fflush(stdout); 524*0Sstevel@tonic-gate } 525*0Sstevel@tonic-gate exit(0); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate /* 529*0Sstevel@tonic-gate * Functions to parse strings that represent a debug or privilege level. 530*0Sstevel@tonic-gate * These functions are copied from main.c and door.c in usr.lib/in.iked/common. 531*0Sstevel@tonic-gate * If this file evolves into a common library that may be used by in.iked 532*0Sstevel@tonic-gate * as well as the usr.sbin utilities, those duplicate functions should be 533*0Sstevel@tonic-gate * deleted. 534*0Sstevel@tonic-gate * 535*0Sstevel@tonic-gate * A privilege level may be represented by a simple keyword, corresponding 536*0Sstevel@tonic-gate * to one of the possible levels. A debug level may be represented by a 537*0Sstevel@tonic-gate * series of keywords, separated by '+' or '-', indicating categories to 538*0Sstevel@tonic-gate * be added or removed from the set of categories in the debug level. 539*0Sstevel@tonic-gate * For example, +all-op corresponds to level 0xfffffffb (all flags except 540*0Sstevel@tonic-gate * for D_OP set); while p1+p2+pfkey corresponds to level 0x38. Note that 541*0Sstevel@tonic-gate * the leading '+' is implicit; the first keyword in the list must be for 542*0Sstevel@tonic-gate * a category that is to be added. 543*0Sstevel@tonic-gate * 544*0Sstevel@tonic-gate * These parsing functions make use of a local version of strtok, strtok_d, 545*0Sstevel@tonic-gate * which includes an additional parameter, char *delim. This param is filled 546*0Sstevel@tonic-gate * in with the character which ends the returned token. In other words, 547*0Sstevel@tonic-gate * this version of strtok, in addition to returning the token, also returns 548*0Sstevel@tonic-gate * the single character delimiter from the original string which marked the 549*0Sstevel@tonic-gate * end of the token. 550*0Sstevel@tonic-gate */ 551*0Sstevel@tonic-gate static char * 552*0Sstevel@tonic-gate strtok_d(char *string, const char *sepset, char *delim) 553*0Sstevel@tonic-gate { 554*0Sstevel@tonic-gate static char *lasts; 555*0Sstevel@tonic-gate char *q, *r; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate /* first or subsequent call */ 558*0Sstevel@tonic-gate if (string == NULL) 559*0Sstevel@tonic-gate string = lasts; 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if (string == 0) /* return if no tokens remaining */ 562*0Sstevel@tonic-gate return (NULL); 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate q = string + strspn(string, sepset); /* skip leading separators */ 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate if (*q == '\0') /* return if no tokens remaining */ 567*0Sstevel@tonic-gate return (NULL); 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL) { /* move past token */ 570*0Sstevel@tonic-gate lasts = 0; /* indicate that this is last token */ 571*0Sstevel@tonic-gate } else { 572*0Sstevel@tonic-gate *delim = *r; /* save delimitor */ 573*0Sstevel@tonic-gate *r = '\0'; 574*0Sstevel@tonic-gate lasts = r + 1; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate return (q); 577*0Sstevel@tonic-gate } 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate static keywdtab_t privtab[] = { 580*0Sstevel@tonic-gate { IKE_PRIV_MINIMUM, "base" }, 581*0Sstevel@tonic-gate { IKE_PRIV_MODKEYS, "modkeys" }, 582*0Sstevel@tonic-gate { IKE_PRIV_KEYMAT, "keymat" }, 583*0Sstevel@tonic-gate { IKE_PRIV_MINIMUM, "0" }, 584*0Sstevel@tonic-gate }; 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate int 587*0Sstevel@tonic-gate privstr2num(char *str) 588*0Sstevel@tonic-gate { 589*0Sstevel@tonic-gate keywdtab_t *pp; 590*0Sstevel@tonic-gate char *endp; 591*0Sstevel@tonic-gate int priv; 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate for (pp = privtab; pp < A_END(privtab); pp++) { 594*0Sstevel@tonic-gate if (strcasecmp(str, pp->kw_str) == 0) 595*0Sstevel@tonic-gate return (pp->kw_tag); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate priv = strtol(str, &endp, 0); 599*0Sstevel@tonic-gate if (*endp == '\0') 600*0Sstevel@tonic-gate return (priv); 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate return (-1); 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate static keywdtab_t dbgtab[] = { 606*0Sstevel@tonic-gate { D_CERT, "cert" }, 607*0Sstevel@tonic-gate { D_KEY, "key" }, 608*0Sstevel@tonic-gate { D_OP, "op" }, 609*0Sstevel@tonic-gate { D_P1, "p1" }, 610*0Sstevel@tonic-gate { D_P1, "phase1" }, 611*0Sstevel@tonic-gate { D_P2, "p2" }, 612*0Sstevel@tonic-gate { D_P2, "phase2" }, 613*0Sstevel@tonic-gate { D_PFKEY, "pfkey" }, 614*0Sstevel@tonic-gate { D_POL, "pol" }, 615*0Sstevel@tonic-gate { D_POL, "policy" }, 616*0Sstevel@tonic-gate { D_PROP, "prop" }, 617*0Sstevel@tonic-gate { D_DOOR, "door" }, 618*0Sstevel@tonic-gate { D_CONFIG, "config" }, 619*0Sstevel@tonic-gate { D_ALL, "all" }, 620*0Sstevel@tonic-gate { 0, "0" }, 621*0Sstevel@tonic-gate }; 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate int 624*0Sstevel@tonic-gate dbgstr2num(char *str) 625*0Sstevel@tonic-gate { 626*0Sstevel@tonic-gate keywdtab_t *dp; 627*0Sstevel@tonic-gate 628*0Sstevel@tonic-gate for (dp = dbgtab; dp < A_END(dbgtab); dp++) { 629*0Sstevel@tonic-gate if (strcasecmp(str, dp->kw_str) == 0) 630*0Sstevel@tonic-gate return (dp->kw_tag); 631*0Sstevel@tonic-gate } 632*0Sstevel@tonic-gate return (D_INVALID); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate int 636*0Sstevel@tonic-gate parsedbgopts(char *optarg) 637*0Sstevel@tonic-gate { 638*0Sstevel@tonic-gate char *argp, *endp, op, nextop; 639*0Sstevel@tonic-gate int mask = 0, new; 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate mask = strtol(optarg, &endp, 0); 642*0Sstevel@tonic-gate if (*endp == '\0') 643*0Sstevel@tonic-gate return (mask); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate op = optarg[0]; 646*0Sstevel@tonic-gate if (op != '-') 647*0Sstevel@tonic-gate op = '+'; 648*0Sstevel@tonic-gate argp = strtok_d(optarg, "+-", &nextop); 649*0Sstevel@tonic-gate do { 650*0Sstevel@tonic-gate new = dbgstr2num(argp); 651*0Sstevel@tonic-gate if (new == D_INVALID) { 652*0Sstevel@tonic-gate /* we encountered an invalid keywd */ 653*0Sstevel@tonic-gate return (new); 654*0Sstevel@tonic-gate } 655*0Sstevel@tonic-gate if (op == '+') { 656*0Sstevel@tonic-gate mask |= new; 657*0Sstevel@tonic-gate } else { 658*0Sstevel@tonic-gate mask &= ~new; 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate op = nextop; 661*0Sstevel@tonic-gate } while ((argp = strtok_d(NULL, "+-", &nextop)) != NULL); 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate return (mask); 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* 668*0Sstevel@tonic-gate * functions to manipulate the kmcookie-label mapping file 669*0Sstevel@tonic-gate */ 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate /* 672*0Sstevel@tonic-gate * Open, lockf, fdopen the given file, returning a FILE * on success, 673*0Sstevel@tonic-gate * or NULL on failure. 674*0Sstevel@tonic-gate */ 675*0Sstevel@tonic-gate FILE * 676*0Sstevel@tonic-gate kmc_open_and_lock(char *name) 677*0Sstevel@tonic-gate { 678*0Sstevel@tonic-gate int fd, rtnerr; 679*0Sstevel@tonic-gate FILE *fp; 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate if ((fd = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { 682*0Sstevel@tonic-gate return (NULL); 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate if (lockf(fd, F_LOCK, 0) < 0) { 685*0Sstevel@tonic-gate return (NULL); 686*0Sstevel@tonic-gate } 687*0Sstevel@tonic-gate if ((fp = fdopen(fd, "a+")) == NULL) { 688*0Sstevel@tonic-gate return (NULL); 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate if (fseek(fp, 0, SEEK_SET) < 0) { 691*0Sstevel@tonic-gate /* save errno in case fclose changes it */ 692*0Sstevel@tonic-gate rtnerr = errno; 693*0Sstevel@tonic-gate (void) fclose(fp); 694*0Sstevel@tonic-gate errno = rtnerr; 695*0Sstevel@tonic-gate return (NULL); 696*0Sstevel@tonic-gate } 697*0Sstevel@tonic-gate return (fp); 698*0Sstevel@tonic-gate } 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate /* 701*0Sstevel@tonic-gate * Extract an integer cookie and string label from a line from the 702*0Sstevel@tonic-gate * kmcookie-label file. Return -1 on failure, 0 on success. 703*0Sstevel@tonic-gate */ 704*0Sstevel@tonic-gate int 705*0Sstevel@tonic-gate kmc_parse_line(char *line, int *cookie, char **label) 706*0Sstevel@tonic-gate { 707*0Sstevel@tonic-gate char *cookiestr; 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate *cookie = 0; 710*0Sstevel@tonic-gate *label = NULL; 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate cookiestr = strtok(line, " \t\n"); 713*0Sstevel@tonic-gate if (cookiestr == NULL) { 714*0Sstevel@tonic-gate return (-1); 715*0Sstevel@tonic-gate } 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate /* Everything that follows, up to the newline, is the label. */ 718*0Sstevel@tonic-gate *label = strtok(NULL, "\n"); 719*0Sstevel@tonic-gate if (*label == NULL) { 720*0Sstevel@tonic-gate return (-1); 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate *cookie = atoi(cookiestr); 724*0Sstevel@tonic-gate return (0); 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate /* 728*0Sstevel@tonic-gate * Insert a mapping into the file (if it's not already there), given the 729*0Sstevel@tonic-gate * new label. Return the assigned cookie, or -1 on error. 730*0Sstevel@tonic-gate */ 731*0Sstevel@tonic-gate int 732*0Sstevel@tonic-gate kmc_insert_mapping(char *label) 733*0Sstevel@tonic-gate { 734*0Sstevel@tonic-gate FILE *map; 735*0Sstevel@tonic-gate char linebuf[MAXLINESIZE]; 736*0Sstevel@tonic-gate char *cur_label; 737*0Sstevel@tonic-gate int max_cookie = 0, cur_cookie, rtn_cookie; 738*0Sstevel@tonic-gate int rtnerr = 0; 739*0Sstevel@tonic-gate boolean_t found = B_FALSE; 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate /* open and lock the file; will sleep until lock is available */ 742*0Sstevel@tonic-gate if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 743*0Sstevel@tonic-gate /* kmc_open_and_lock() sets errno appropriately */ 744*0Sstevel@tonic-gate return (-1); 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 750*0Sstevel@tonic-gate rtnerr = EINVAL; 751*0Sstevel@tonic-gate goto error; 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate if (cur_cookie > max_cookie) 755*0Sstevel@tonic-gate max_cookie = cur_cookie; 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if ((!found) && (strcmp(cur_label, label) == 0)) { 758*0Sstevel@tonic-gate found = B_TRUE; 759*0Sstevel@tonic-gate rtn_cookie = cur_cookie; 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate } 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate if (!found) { 764*0Sstevel@tonic-gate rtn_cookie = ++max_cookie; 765*0Sstevel@tonic-gate if ((fprintf(map, "%u\t%s\n", rtn_cookie, label) < 0) || 766*0Sstevel@tonic-gate (fflush(map) < 0)) { 767*0Sstevel@tonic-gate rtnerr = errno; 768*0Sstevel@tonic-gate goto error; 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate } 771*0Sstevel@tonic-gate (void) fclose(map); 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate return (rtn_cookie); 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate error: 776*0Sstevel@tonic-gate (void) fclose(map); 777*0Sstevel@tonic-gate errno = rtnerr; 778*0Sstevel@tonic-gate return (-1); 779*0Sstevel@tonic-gate } 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate /* 782*0Sstevel@tonic-gate * Lookup the given cookie and return its corresponding label. Return 783*0Sstevel@tonic-gate * a pointer to the label on success, NULL on error (or if the label is 784*0Sstevel@tonic-gate * not found). Note that the returned label pointer points to a static 785*0Sstevel@tonic-gate * string, so the label will be overwritten by a subsequent call to the 786*0Sstevel@tonic-gate * function; the function is also not thread-safe as a result. 787*0Sstevel@tonic-gate */ 788*0Sstevel@tonic-gate char * 789*0Sstevel@tonic-gate kmc_lookup_by_cookie(int cookie) 790*0Sstevel@tonic-gate { 791*0Sstevel@tonic-gate FILE *map; 792*0Sstevel@tonic-gate static char linebuf[MAXLINESIZE]; 793*0Sstevel@tonic-gate char *cur_label; 794*0Sstevel@tonic-gate int cur_cookie; 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 797*0Sstevel@tonic-gate return (NULL); 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 803*0Sstevel@tonic-gate (void) fclose(map); 804*0Sstevel@tonic-gate return (NULL); 805*0Sstevel@tonic-gate } 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate if (cookie == cur_cookie) { 808*0Sstevel@tonic-gate (void) fclose(map); 809*0Sstevel@tonic-gate return (cur_label); 810*0Sstevel@tonic-gate } 811*0Sstevel@tonic-gate } 812*0Sstevel@tonic-gate (void) fclose(map); 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate return (NULL); 815*0Sstevel@tonic-gate } 816*0Sstevel@tonic-gate 817*0Sstevel@tonic-gate /* 818*0Sstevel@tonic-gate * Parse basic extension headers and return in the passed-in pointer vector. 819*0Sstevel@tonic-gate * Return values include: 820*0Sstevel@tonic-gate * 821*0Sstevel@tonic-gate * KGE_OK Everything's nice and parsed out. 822*0Sstevel@tonic-gate * If there are no extensions, place NULL in extv[0]. 823*0Sstevel@tonic-gate * KGE_DUP There is a duplicate extension. 824*0Sstevel@tonic-gate * First instance in appropriate bin. First duplicate in 825*0Sstevel@tonic-gate * extv[0]. 826*0Sstevel@tonic-gate * KGE_UNK Unknown extension type encountered. extv[0] contains 827*0Sstevel@tonic-gate * unknown header. 828*0Sstevel@tonic-gate * KGE_LEN Extension length error. 829*0Sstevel@tonic-gate * KGE_CHK High-level reality check failed on specific extension. 830*0Sstevel@tonic-gate * 831*0Sstevel@tonic-gate * My apologies for some of the pointer arithmetic in here. I'm thinking 832*0Sstevel@tonic-gate * like an assembly programmer, yet trying to make the compiler happy. 833*0Sstevel@tonic-gate */ 834*0Sstevel@tonic-gate int 835*0Sstevel@tonic-gate spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize, 836*0Sstevel@tonic-gate char *diag_buf, uint_t diag_buf_len) 837*0Sstevel@tonic-gate { 838*0Sstevel@tonic-gate int i; 839*0Sstevel@tonic-gate 840*0Sstevel@tonic-gate if (diag_buf != NULL) 841*0Sstevel@tonic-gate diag_buf[0] = '\0'; 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate for (i = 1; i <= SPD_EXT_MAX; i++) 844*0Sstevel@tonic-gate extv[i] = NULL; 845*0Sstevel@tonic-gate 846*0Sstevel@tonic-gate i = 0; 847*0Sstevel@tonic-gate /* Use extv[0] as the "current working pointer". */ 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate extv[0] = (spd_ext_t *)(basehdr + 1); 850*0Sstevel@tonic-gate msgsize = SPD_64TO8(msgsize); 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate while ((char *)extv[0] < ((char *)basehdr + msgsize)) { 853*0Sstevel@tonic-gate /* Check for unknown headers. */ 854*0Sstevel@tonic-gate i++; 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate if (extv[0]->spd_ext_type == 0 || 857*0Sstevel@tonic-gate extv[0]->spd_ext_type > SPD_EXT_MAX) { 858*0Sstevel@tonic-gate if (diag_buf != NULL) { 859*0Sstevel@tonic-gate (void) snprintf(diag_buf, diag_buf_len, 860*0Sstevel@tonic-gate "spdsock ext 0x%X unknown: 0x%X", 861*0Sstevel@tonic-gate i, extv[0]->spd_ext_type); 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate return (KGE_UNK); 864*0Sstevel@tonic-gate } 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate /* 867*0Sstevel@tonic-gate * Check length. Use uint64_t because extlen is in units 868*0Sstevel@tonic-gate * of 64-bit words. If length goes beyond the msgsize, 869*0Sstevel@tonic-gate * return an error. (Zero length also qualifies here.) 870*0Sstevel@tonic-gate */ 871*0Sstevel@tonic-gate if (extv[0]->spd_ext_len == 0 || 872*0Sstevel@tonic-gate (uint8_t *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) > 873*0Sstevel@tonic-gate (uint8_t *)((uint8_t *)basehdr + msgsize)) 874*0Sstevel@tonic-gate return (KGE_LEN); 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate /* Check for redundant headers. */ 877*0Sstevel@tonic-gate if (extv[extv[0]->spd_ext_type] != NULL) 878*0Sstevel@tonic-gate return (KGE_DUP); 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate /* If I make it here, assign the appropriate bin. */ 881*0Sstevel@tonic-gate extv[extv[0]->spd_ext_type] = extv[0]; 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate /* Advance pointer (See above for uint64_t ptr reasoning.) */ 884*0Sstevel@tonic-gate extv[0] = (spd_ext_t *) 885*0Sstevel@tonic-gate ((uint64_t *)extv[0] + extv[0]->spd_ext_len); 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate 888*0Sstevel@tonic-gate /* Everything's cool. */ 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gate /* 891*0Sstevel@tonic-gate * If extv[0] == NULL, then there are no extension headers in this 892*0Sstevel@tonic-gate * message. Ensure that this is the case. 893*0Sstevel@tonic-gate */ 894*0Sstevel@tonic-gate if (extv[0] == (spd_ext_t *)(basehdr + 1)) 895*0Sstevel@tonic-gate extv[0] = NULL; 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate return (KGE_OK); 898*0Sstevel@tonic-gate } 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate const char * 901*0Sstevel@tonic-gate spdsock_diag(int diagnostic) 902*0Sstevel@tonic-gate { 903*0Sstevel@tonic-gate switch (diagnostic) { 904*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_NONE: 905*0Sstevel@tonic-gate return (gettext("no error")); 906*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNKNOWN_EXT: 907*0Sstevel@tonic-gate return (gettext("unknown extension")); 908*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_EXTLEN: 909*0Sstevel@tonic-gate return (gettext("bad extension length")); 910*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_NO_RULE_EXT: 911*0Sstevel@tonic-gate return (gettext("no rule extension")); 912*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_ADDR_LEN: 913*0Sstevel@tonic-gate return (gettext("bad address len")); 914*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MIXED_AF: 915*0Sstevel@tonic-gate return (gettext("mixed address family")); 916*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_NO_MEM: 917*0Sstevel@tonic-gate return (gettext("add: no memory")); 918*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT: 919*0Sstevel@tonic-gate return (gettext("add: wrong action count")); 920*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_BAD_TYPE: 921*0Sstevel@tonic-gate return (gettext("add: bad type")); 922*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_BAD_FLAGS: 923*0Sstevel@tonic-gate return (gettext("add: bad flags")); 924*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_INCON_FLAGS: 925*0Sstevel@tonic-gate return (gettext("add: inconsistent flags")); 926*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_LCLPORT: 927*0Sstevel@tonic-gate return (gettext("malformed local port")); 928*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_LCLPORT: 929*0Sstevel@tonic-gate return (gettext("duplicate local port")); 930*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_REMPORT: 931*0Sstevel@tonic-gate return (gettext("malformed remote port")); 932*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_REMPORT: 933*0Sstevel@tonic-gate return (gettext("duplicate remote port")); 934*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_PROTO: 935*0Sstevel@tonic-gate return (gettext("malformed proto")); 936*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_PROTO: 937*0Sstevel@tonic-gate return (gettext("duplicate proto")); 938*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_LCLADDR: 939*0Sstevel@tonic-gate return (gettext("malformed local address")); 940*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_LCLADDR: 941*0Sstevel@tonic-gate return (gettext("duplicate local address")); 942*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_REMADDR: 943*0Sstevel@tonic-gate return (gettext("malformed remote address")); 944*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_REMADDR: 945*0Sstevel@tonic-gate return (gettext("duplicate remote address")); 946*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_ACTION: 947*0Sstevel@tonic-gate return (gettext("malformed action")); 948*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_ACTION: 949*0Sstevel@tonic-gate return (gettext("duplicate action")); 950*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_RULE: 951*0Sstevel@tonic-gate return (gettext("malformed rule")); 952*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_RULE: 953*0Sstevel@tonic-gate return (gettext("duplicate rule")); 954*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_RULESET: 955*0Sstevel@tonic-gate return (gettext("malformed ruleset")); 956*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_RULESET: 957*0Sstevel@tonic-gate return (gettext("duplicate ruleset")); 958*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_INVALID_RULE_INDEX: 959*0Sstevel@tonic-gate return (gettext("invalid rule index")); 960*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_SPDID: 961*0Sstevel@tonic-gate return (gettext("bad spdid")); 962*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_MSG_TYPE: 963*0Sstevel@tonic-gate return (gettext("bad message type")); 964*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_AH_ALG: 965*0Sstevel@tonic-gate return (gettext("unsupported AH algorithm")); 966*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG: 967*0Sstevel@tonic-gate return (gettext("unsupported ESP encryption algorithm")); 968*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG: 969*0Sstevel@tonic-gate return (gettext("unsupported ESP authentication algorithm")); 970*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_AH_KEYSIZE: 971*0Sstevel@tonic-gate return (gettext("unsupported AH key size")); 972*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_KEYSIZE: 973*0Sstevel@tonic-gate return (gettext("unsupported ESP encryption key size")); 974*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_KEYSIZE: 975*0Sstevel@tonic-gate return (gettext("unsupported ESP authentication key size")); 976*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_NO_ACTION_EXT: 977*0Sstevel@tonic-gate return (gettext("No ACTION extension")); 978*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_ID_RANGE: 979*0Sstevel@tonic-gate return (gettext("invalid algorithm identifer")); 980*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES: 981*0Sstevel@tonic-gate return (gettext("number of key sizes inconsistent")); 982*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES: 983*0Sstevel@tonic-gate return (gettext("number of block sizes inconsistent")); 984*0Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN: 985*0Sstevel@tonic-gate return (gettext("invalid mechanism name length")); 986*0Sstevel@tonic-gate default: 987*0Sstevel@tonic-gate return (gettext("unknown diagnostic")); 988*0Sstevel@tonic-gate } 989*0Sstevel@tonic-gate } 990*0Sstevel@tonic-gate 991*0Sstevel@tonic-gate /* 992*0Sstevel@tonic-gate * PF_KEY Diagnostic table. 993*0Sstevel@tonic-gate * 994*0Sstevel@tonic-gate * PF_KEY NOTE: If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is 995*0Sstevel@tonic-gate * where you need to add new messages. 996*0Sstevel@tonic-gate */ 997*0Sstevel@tonic-gate 998*0Sstevel@tonic-gate const char * 999*0Sstevel@tonic-gate keysock_diag(int diagnostic) 1000*0Sstevel@tonic-gate { 1001*0Sstevel@tonic-gate switch (diagnostic) { 1002*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NONE: 1003*0Sstevel@tonic-gate return (gettext("No diagnostic")); 1004*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_MSG: 1005*0Sstevel@tonic-gate return (gettext("Unknown message type")); 1006*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_EXT: 1007*0Sstevel@tonic-gate return (gettext("Unknown extension type")); 1008*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EXTLEN: 1009*0Sstevel@tonic-gate return (gettext("Bad extension length")); 1010*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE: 1011*0Sstevel@tonic-gate return (gettext("Unknown Security Association type")); 1012*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_SATYPE_NEEDED: 1013*0Sstevel@tonic-gate return (gettext("Specific Security Association type needed")); 1014*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NO_SADBS: 1015*0Sstevel@tonic-gate return (gettext("No Security Association Databases present")); 1016*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NO_EXT: 1017*0Sstevel@tonic-gate return (gettext("No extensions needed for message")); 1018*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SRC_AF: 1019*0Sstevel@tonic-gate return (gettext("Bad source address family")); 1020*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_DST_AF: 1021*0Sstevel@tonic-gate return (gettext("Bad destination address family")); 1022*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_PROXY_AF: 1023*0Sstevel@tonic-gate return (gettext("Bad proxy address family")); 1024*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_AF_MISMATCH: 1025*0Sstevel@tonic-gate return (gettext("Source/destination address family mismatch")); 1026*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SRC: 1027*0Sstevel@tonic-gate return (gettext("Bad source address value")); 1028*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_DST: 1029*0Sstevel@tonic-gate return (gettext("Bad destination address value")); 1030*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ALLOC_HSERR: 1031*0Sstevel@tonic-gate return (gettext("Soft allocations limit more than hard limit")); 1032*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BYTES_HSERR: 1033*0Sstevel@tonic-gate return (gettext("Soft bytes limit more than hard limit")); 1034*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ADDTIME_HSERR: 1035*0Sstevel@tonic-gate return (gettext("Soft add expiration time later " 1036*0Sstevel@tonic-gate "than hard expiration time")); 1037*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_USETIME_HSERR: 1038*0Sstevel@tonic-gate return (gettext("Soft use expiration time later " 1039*0Sstevel@tonic-gate "than hard expiration time")); 1040*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_SRC: 1041*0Sstevel@tonic-gate return (gettext("Missing source address")); 1042*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_DST: 1043*0Sstevel@tonic-gate return (gettext("Missing destination address")); 1044*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_SA: 1045*0Sstevel@tonic-gate return (gettext("Missing SA extension")); 1046*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_EKEY: 1047*0Sstevel@tonic-gate return (gettext("Missing encryption key")); 1048*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_AKEY: 1049*0Sstevel@tonic-gate return (gettext("Missing authentication key")); 1050*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_RANGE: 1051*0Sstevel@tonic-gate return (gettext("Missing SPI range")); 1052*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_SRC: 1053*0Sstevel@tonic-gate return (gettext("Duplicate source address")); 1054*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_DST: 1055*0Sstevel@tonic-gate return (gettext("Duplicate destination address")); 1056*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_SA: 1057*0Sstevel@tonic-gate return (gettext("Duplicate SA extension")); 1058*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_EKEY: 1059*0Sstevel@tonic-gate return (gettext("Duplicate encryption key")); 1060*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_AKEY: 1061*0Sstevel@tonic-gate return (gettext("Duplicate authentication key")); 1062*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_RANGE: 1063*0Sstevel@tonic-gate return (gettext("Duplicate SPI range")); 1064*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_SRC: 1065*0Sstevel@tonic-gate return (gettext("Malformed source address")); 1066*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_DST: 1067*0Sstevel@tonic-gate return (gettext("Malformed destination address")); 1068*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_SA: 1069*0Sstevel@tonic-gate return (gettext("Malformed SA extension")); 1070*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_EKEY: 1071*0Sstevel@tonic-gate return (gettext("Malformed encryption key")); 1072*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_AKEY: 1073*0Sstevel@tonic-gate return (gettext("Malformed authentication key")); 1074*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_RANGE: 1075*0Sstevel@tonic-gate return (gettext("Malformed SPI range")); 1076*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_AKEY_PRESENT: 1077*0Sstevel@tonic-gate return (gettext("Authentication key not needed")); 1078*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_EKEY_PRESENT: 1079*0Sstevel@tonic-gate return (gettext("Encryption key not needed")); 1080*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_PROP_PRESENT: 1081*0Sstevel@tonic-gate return (gettext("Proposal extension not needed")); 1082*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_SUPP_PRESENT: 1083*0Sstevel@tonic-gate return (gettext("Supported algorithms extension not needed")); 1084*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_AALG: 1085*0Sstevel@tonic-gate return (gettext("Unsupported authentication algorithm")); 1086*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EALG: 1087*0Sstevel@tonic-gate return (gettext("Unsupported encryption algorithm")); 1088*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SAFLAGS: 1089*0Sstevel@tonic-gate return (gettext("Invalid SA flags")); 1090*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SASTATE: 1091*0Sstevel@tonic-gate return (gettext("Invalid SA state")); 1092*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_AKEYBITS: 1093*0Sstevel@tonic-gate return (gettext("Bad number of authentication bits")); 1094*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EKEYBITS: 1095*0Sstevel@tonic-gate return (gettext("Bad number of encryption bits")); 1096*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ENCR_NOTSUPP: 1097*0Sstevel@tonic-gate return (gettext("Encryption not supported for this SA type")); 1098*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_WEAK_EKEY: 1099*0Sstevel@tonic-gate return (gettext("Weak encryption key")); 1100*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_WEAK_AKEY: 1101*0Sstevel@tonic-gate return (gettext("Weak authentication key")); 1102*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_KMP: 1103*0Sstevel@tonic-gate return (gettext("Duplicate key management protocol")); 1104*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_KMC: 1105*0Sstevel@tonic-gate return (gettext("Duplicate key management cookie")); 1106*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC: 1107*0Sstevel@tonic-gate return (gettext("Missing NATT local address")); 1108*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_NATT_REM: 1109*0Sstevel@tonic-gate return (gettext("Missing NATT remote address")); 1110*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC: 1111*0Sstevel@tonic-gate return (gettext("Duplicate NATT local address")); 1112*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM: 1113*0Sstevel@tonic-gate return (gettext("Duplicate NATT remote address")); 1114*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC: 1115*0Sstevel@tonic-gate return (gettext("Malformed NATT local address")); 1116*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM: 1117*0Sstevel@tonic-gate return (gettext("Malformed NATT remote address")); 1118*0Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS: 1119*0Sstevel@tonic-gate return (gettext("Duplicate NATT ports")); 1120*0Sstevel@tonic-gate default: 1121*0Sstevel@tonic-gate return (gettext("Unknown diagnostic code")); 1122*0Sstevel@tonic-gate } 1123*0Sstevel@tonic-gate } 1124