10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*3055Sdanmcd * Common Development and Distribution License (the "License"). 6*3055Sdanmcd * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*3055Sdanmcd * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <unistd.h> 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <stdlib.h> 310Sstevel@tonic-gate #include <stdarg.h> 320Sstevel@tonic-gate #include <sys/types.h> 330Sstevel@tonic-gate #include <sys/stat.h> 340Sstevel@tonic-gate #include <fcntl.h> 350Sstevel@tonic-gate #include <sys/sysconf.h> 360Sstevel@tonic-gate #include <strings.h> 370Sstevel@tonic-gate #include <ctype.h> 380Sstevel@tonic-gate #include <errno.h> 390Sstevel@tonic-gate #include <sys/socket.h> 400Sstevel@tonic-gate #include <netdb.h> 410Sstevel@tonic-gate #include <netinet/in.h> 420Sstevel@tonic-gate #include <arpa/inet.h> 430Sstevel@tonic-gate #include <net/pfkeyv2.h> 440Sstevel@tonic-gate #include <net/pfpolicy.h> 450Sstevel@tonic-gate #include <libintl.h> 460Sstevel@tonic-gate #include <setjmp.h> 470Sstevel@tonic-gate #include <libgen.h> 480Sstevel@tonic-gate 490Sstevel@tonic-gate #include "ipsec_util.h" 500Sstevel@tonic-gate #include "ikedoor.h" 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * This file contains support functions that are shared by the ipsec 540Sstevel@tonic-gate * utilities including ipseckey(1m) and ikeadm(1m). 550Sstevel@tonic-gate */ 560Sstevel@tonic-gate 570Sstevel@tonic-gate /* Set standard default/initial values for globals... */ 580Sstevel@tonic-gate boolean_t pflag = B_FALSE; /* paranoid w.r.t. printing keying material */ 590Sstevel@tonic-gate boolean_t nflag = B_FALSE; /* avoid nameservice? */ 600Sstevel@tonic-gate boolean_t interactive = B_FALSE; /* util not running on cmdline */ 610Sstevel@tonic-gate boolean_t readfile = B_FALSE; /* cmds are being read from a file */ 620Sstevel@tonic-gate uint_t lineno = 0; /* track location if reading cmds from file */ 630Sstevel@tonic-gate jmp_buf env; /* for error recovery in interactive/readfile modes */ 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* 660Sstevel@tonic-gate * Print errno and exit if cmdline or readfile, reset state if interactive 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate void 690Sstevel@tonic-gate bail(char *what) 700Sstevel@tonic-gate { 710Sstevel@tonic-gate if (errno != 0) 720Sstevel@tonic-gate warn(what); 730Sstevel@tonic-gate else 740Sstevel@tonic-gate warnx(gettext("Error: %s"), what); 750Sstevel@tonic-gate if (readfile) { 760Sstevel@tonic-gate warnx(gettext("System error on line %u."), lineno); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate if (interactive && !readfile) 790Sstevel@tonic-gate longjmp(env, 2); 800Sstevel@tonic-gate exit(1); 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate /* 840Sstevel@tonic-gate * Print caller-supplied variable-arg error msg, then exit if cmdline or 850Sstevel@tonic-gate * readfile, or reset state if interactive. 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate /*PRINTFLIKE1*/ 880Sstevel@tonic-gate void 890Sstevel@tonic-gate bail_msg(char *fmt, ...) 900Sstevel@tonic-gate { 910Sstevel@tonic-gate va_list ap; 920Sstevel@tonic-gate char msgbuf[BUFSIZ]; 930Sstevel@tonic-gate 940Sstevel@tonic-gate va_start(ap, fmt); 950Sstevel@tonic-gate (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap); 960Sstevel@tonic-gate va_end(ap); 970Sstevel@tonic-gate if (readfile) 980Sstevel@tonic-gate warnx(gettext("ERROR on line %u:\n%s\n"), lineno, msgbuf); 990Sstevel@tonic-gate else 1000Sstevel@tonic-gate warnx(gettext("ERROR: %s\n"), msgbuf); 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate if (interactive && !readfile) 1030Sstevel@tonic-gate longjmp(env, 1); 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate exit(1); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* 1100Sstevel@tonic-gate * dump_XXX functions produce ASCII output from various structures. 1110Sstevel@tonic-gate * 1120Sstevel@tonic-gate * Because certain errors need to do this to stderr, dump_XXX functions 1130Sstevel@tonic-gate * take a FILE pointer. 1140Sstevel@tonic-gate * 1150Sstevel@tonic-gate * If an error occured while writing to the specified file, these 1160Sstevel@tonic-gate * functions return -1, zero otherwise. 1170Sstevel@tonic-gate */ 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate int 120*3055Sdanmcd dump_sockaddr(struct sockaddr *sa, uint8_t prefixlen, boolean_t addr_only, 121*3055Sdanmcd FILE *where) 1220Sstevel@tonic-gate { 1230Sstevel@tonic-gate struct sockaddr_in *sin; 1240Sstevel@tonic-gate struct sockaddr_in6 *sin6; 1250Sstevel@tonic-gate char *printable_addr, *protocol; 1260Sstevel@tonic-gate uint8_t *addrptr; 127*3055Sdanmcd /* Add 4 chars to hold '/nnn' for prefixes. */ 128*3055Sdanmcd char storage[INET6_ADDRSTRLEN + 4]; 1290Sstevel@tonic-gate uint16_t port; 1300Sstevel@tonic-gate boolean_t unspec; 1310Sstevel@tonic-gate struct hostent *hp; 1320Sstevel@tonic-gate int getipnode_errno, addrlen; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate switch (sa->sa_family) { 1350Sstevel@tonic-gate case AF_INET: 1360Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 1370Sstevel@tonic-gate sin = (struct sockaddr_in *)sa; 1380Sstevel@tonic-gate addrptr = (uint8_t *)&sin->sin_addr; 1390Sstevel@tonic-gate port = sin->sin_port; 1400Sstevel@tonic-gate protocol = "AF_INET"; 1410Sstevel@tonic-gate unspec = (sin->sin_addr.s_addr == 0); 1420Sstevel@tonic-gate addrlen = sizeof (sin->sin_addr); 1430Sstevel@tonic-gate break; 1440Sstevel@tonic-gate case AF_INET6: 1450Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 1460Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)sa; 1470Sstevel@tonic-gate addrptr = (uint8_t *)&sin6->sin6_addr; 1480Sstevel@tonic-gate port = sin6->sin6_port; 1490Sstevel@tonic-gate protocol = "AF_INET6"; 1500Sstevel@tonic-gate unspec = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr); 1510Sstevel@tonic-gate addrlen = sizeof (sin6->sin6_addr); 1520Sstevel@tonic-gate break; 1530Sstevel@tonic-gate default: 1540Sstevel@tonic-gate return (0); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if (inet_ntop(sa->sa_family, addrptr, storage, INET6_ADDRSTRLEN) == 1580Sstevel@tonic-gate NULL) { 1590Sstevel@tonic-gate printable_addr = gettext("<inet_ntop() failed>"); 1600Sstevel@tonic-gate } else { 161*3055Sdanmcd char prefix[5]; /* "/nnn" with terminator. */ 162*3055Sdanmcd 163*3055Sdanmcd (void) snprintf(prefix, sizeof (prefix), "/%d", prefixlen); 1640Sstevel@tonic-gate printable_addr = storage; 165*3055Sdanmcd if (prefixlen != 0) { 166*3055Sdanmcd (void) strlcat(printable_addr, prefix, 167*3055Sdanmcd sizeof (storage)); 168*3055Sdanmcd } 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate if (addr_only) { 1710Sstevel@tonic-gate if (fprintf(where, "%s", printable_addr) < 0) 1720Sstevel@tonic-gate return (-1); 1730Sstevel@tonic-gate } else { 1740Sstevel@tonic-gate if (fprintf(where, gettext("%s: port %d, %s"), protocol, 1750Sstevel@tonic-gate ntohs(port), printable_addr) < 0) 1760Sstevel@tonic-gate return (-1); 1770Sstevel@tonic-gate if (!nflag) { 1780Sstevel@tonic-gate /* 1790Sstevel@tonic-gate * Do AF_independent reverse hostname lookup here. 1800Sstevel@tonic-gate */ 1810Sstevel@tonic-gate if (unspec) { 1820Sstevel@tonic-gate if (fprintf(where, 1830Sstevel@tonic-gate gettext(" <unspecified>")) < 0) 1840Sstevel@tonic-gate return (-1); 1850Sstevel@tonic-gate } else { 1860Sstevel@tonic-gate hp = getipnodebyaddr((char *)addrptr, addrlen, 1870Sstevel@tonic-gate sa->sa_family, &getipnode_errno); 1880Sstevel@tonic-gate if (hp != NULL) { 1890Sstevel@tonic-gate if (fprintf(where, 1900Sstevel@tonic-gate " (%s)", hp->h_name) < 0) 1910Sstevel@tonic-gate return (-1); 1920Sstevel@tonic-gate freehostent(hp); 1930Sstevel@tonic-gate } else { 1940Sstevel@tonic-gate if (fprintf(where, 1950Sstevel@tonic-gate gettext(" <unknown>")) < 0) 1960Sstevel@tonic-gate return (-1); 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate if (fputs(".\n", where) == EOF) 2010Sstevel@tonic-gate return (-1); 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate return (0); 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate /* 2070Sstevel@tonic-gate * Dump a key and bitlen 2080Sstevel@tonic-gate */ 2090Sstevel@tonic-gate int 2100Sstevel@tonic-gate dump_key(uint8_t *keyp, uint_t bitlen, FILE *where) 2110Sstevel@tonic-gate { 2120Sstevel@tonic-gate int numbytes; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate numbytes = SADB_1TO8(bitlen); 2150Sstevel@tonic-gate /* The & 0x7 is to check for leftover bits. */ 2160Sstevel@tonic-gate if ((bitlen & 0x7) != 0) 2170Sstevel@tonic-gate numbytes++; 2180Sstevel@tonic-gate while (numbytes-- != 0) { 2190Sstevel@tonic-gate if (pflag) { 2200Sstevel@tonic-gate /* Print no keys if paranoid */ 2210Sstevel@tonic-gate if (fprintf(where, "XX") < 0) 2220Sstevel@tonic-gate return (-1); 2230Sstevel@tonic-gate } else { 2240Sstevel@tonic-gate if (fprintf(where, "%02x", *keyp++) < 0) 2250Sstevel@tonic-gate return (-1); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate if (fprintf(where, "/%u", bitlen) < 0) 2290Sstevel@tonic-gate return (-1); 2300Sstevel@tonic-gate return (0); 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* 2340Sstevel@tonic-gate * Print an authentication or encryption algorithm 2350Sstevel@tonic-gate */ 2360Sstevel@tonic-gate static int 2370Sstevel@tonic-gate dump_generic_alg(uint8_t alg_num, int proto_num, FILE *where) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate struct ipsecalgent *alg; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate alg = getipsecalgbynum(alg_num, proto_num, NULL); 2420Sstevel@tonic-gate if (alg == NULL) { 2430Sstevel@tonic-gate if (fprintf(where, gettext("<unknown %u>"), alg_num) < 0) 2440Sstevel@tonic-gate return (-1); 2450Sstevel@tonic-gate return (0); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * Special-case <none> for backward output compat. 2500Sstevel@tonic-gate * Assume that SADB_AALG_NONE == SADB_EALG_NONE. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate if (alg_num == SADB_AALG_NONE) { 2530Sstevel@tonic-gate if (fputs(gettext("<none>"), where) == EOF) 2540Sstevel@tonic-gate return (-1); 2550Sstevel@tonic-gate } else { 2560Sstevel@tonic-gate if (fputs(alg->a_names[0], where) == EOF) 2570Sstevel@tonic-gate return (-1); 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate freeipsecalgent(alg); 2610Sstevel@tonic-gate return (0); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate int 2650Sstevel@tonic-gate dump_aalg(uint8_t aalg, FILE *where) 2660Sstevel@tonic-gate { 2670Sstevel@tonic-gate return (dump_generic_alg(aalg, IPSEC_PROTO_AH, where)); 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate int 2710Sstevel@tonic-gate dump_ealg(uint8_t ealg, FILE *where) 2720Sstevel@tonic-gate { 2730Sstevel@tonic-gate return (dump_generic_alg(ealg, IPSEC_PROTO_ESP, where)); 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate /* 2770Sstevel@tonic-gate * Print an SADB_IDENTTYPE string 2780Sstevel@tonic-gate * 2790Sstevel@tonic-gate * Also return TRUE if the actual ident may be printed, FALSE if not. 2800Sstevel@tonic-gate * 2810Sstevel@tonic-gate * If rc is not NULL, set its value to -1 if an error occured while writing 2820Sstevel@tonic-gate * to the specified file, zero otherwise. 2830Sstevel@tonic-gate */ 2840Sstevel@tonic-gate boolean_t 2850Sstevel@tonic-gate dump_sadb_idtype(uint8_t idtype, FILE *where, int *rc) 2860Sstevel@tonic-gate { 2870Sstevel@tonic-gate boolean_t canprint = B_TRUE; 2880Sstevel@tonic-gate int rc_val = 0; 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate switch (idtype) { 2910Sstevel@tonic-gate case SADB_IDENTTYPE_PREFIX: 2920Sstevel@tonic-gate if (fputs(gettext("prefix"), where) == EOF) 2930Sstevel@tonic-gate rc_val = -1; 2940Sstevel@tonic-gate break; 2950Sstevel@tonic-gate case SADB_IDENTTYPE_FQDN: 2960Sstevel@tonic-gate if (fputs(gettext("FQDN"), where) == EOF) 2970Sstevel@tonic-gate rc_val = -1; 2980Sstevel@tonic-gate break; 2990Sstevel@tonic-gate case SADB_IDENTTYPE_USER_FQDN: 3000Sstevel@tonic-gate if (fputs(gettext("user-FQDN (mbox)"), where) == EOF) 3010Sstevel@tonic-gate rc_val = -1; 3020Sstevel@tonic-gate break; 3030Sstevel@tonic-gate case SADB_X_IDENTTYPE_DN: 3040Sstevel@tonic-gate if (fputs(gettext("ASN.1 DER Distinguished Name"), 3050Sstevel@tonic-gate where) == EOF) 3060Sstevel@tonic-gate rc_val = -1; 3070Sstevel@tonic-gate canprint = B_FALSE; 3080Sstevel@tonic-gate break; 3090Sstevel@tonic-gate case SADB_X_IDENTTYPE_GN: 3100Sstevel@tonic-gate if (fputs(gettext("ASN.1 DER Generic Name"), where) == EOF) 3110Sstevel@tonic-gate rc_val = -1; 3120Sstevel@tonic-gate canprint = B_FALSE; 3130Sstevel@tonic-gate break; 3140Sstevel@tonic-gate case SADB_X_IDENTTYPE_KEY_ID: 3150Sstevel@tonic-gate if (fputs(gettext("Generic key id"), where) == EOF) 3160Sstevel@tonic-gate rc_val = -1; 3170Sstevel@tonic-gate break; 3180Sstevel@tonic-gate case SADB_X_IDENTTYPE_ADDR_RANGE: 3190Sstevel@tonic-gate if (fputs(gettext("Address range"), where) == EOF) 3200Sstevel@tonic-gate rc_val = -1; 3210Sstevel@tonic-gate break; 3220Sstevel@tonic-gate default: 3230Sstevel@tonic-gate if (fprintf(where, gettext("<unknown %u>"), idtype) < 0) 3240Sstevel@tonic-gate rc_val = -1; 3250Sstevel@tonic-gate break; 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate if (rc != NULL) 3290Sstevel@tonic-gate *rc = rc_val; 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate return (canprint); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* 3350Sstevel@tonic-gate * Slice an argv/argc vector from an interactive line or a read-file line. 3360Sstevel@tonic-gate */ 3370Sstevel@tonic-gate static int 3380Sstevel@tonic-gate create_argv(char *ibuf, int *newargc, char ***thisargv) 3390Sstevel@tonic-gate { 3400Sstevel@tonic-gate unsigned int argvlen = START_ARG; 3410Sstevel@tonic-gate char **current; 3420Sstevel@tonic-gate boolean_t firstchar = B_TRUE; 3430Sstevel@tonic-gate boolean_t inquotes = B_FALSE; 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate *thisargv = malloc(sizeof (char *) * argvlen); 3460Sstevel@tonic-gate if ((*thisargv) == NULL) 3470Sstevel@tonic-gate return (MEMORY_ALLOCATION); 3480Sstevel@tonic-gate current = *thisargv; 3490Sstevel@tonic-gate *current = NULL; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate for (; *ibuf != '\0'; ibuf++) { 3520Sstevel@tonic-gate if (isspace(*ibuf)) { 3530Sstevel@tonic-gate if (inquotes) { 3540Sstevel@tonic-gate continue; 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate if (*current != NULL) { 3570Sstevel@tonic-gate *ibuf = '\0'; 3580Sstevel@tonic-gate current++; 3590Sstevel@tonic-gate if (*thisargv + argvlen == current) { 3600Sstevel@tonic-gate /* Regrow ***thisargv. */ 3610Sstevel@tonic-gate if (argvlen == TOO_MANY_ARGS) { 3620Sstevel@tonic-gate free(*thisargv); 3630Sstevel@tonic-gate return (TOO_MANY_TOKENS); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate /* Double the allocation. */ 3660Sstevel@tonic-gate current = realloc(*thisargv, 3670Sstevel@tonic-gate sizeof (char *) * (argvlen << 1)); 3680Sstevel@tonic-gate if (current == NULL) { 3690Sstevel@tonic-gate free(*thisargv); 3700Sstevel@tonic-gate return (MEMORY_ALLOCATION); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate *thisargv = current; 3730Sstevel@tonic-gate current += argvlen; 3740Sstevel@tonic-gate argvlen <<= 1; /* Double the size. */ 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate *current = NULL; 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate } else { 3790Sstevel@tonic-gate if (firstchar) { 3800Sstevel@tonic-gate firstchar = B_FALSE; 3810Sstevel@tonic-gate if (*ibuf == COMMENT_CHAR) { 3820Sstevel@tonic-gate free(*thisargv); 3830Sstevel@tonic-gate return (COMMENT_LINE); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate if (*ibuf == QUOTE_CHAR) { 3870Sstevel@tonic-gate if (inquotes) { 3880Sstevel@tonic-gate inquotes = B_FALSE; 3890Sstevel@tonic-gate *ibuf = '\0'; 3900Sstevel@tonic-gate } else { 3910Sstevel@tonic-gate inquotes = B_TRUE; 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate continue; 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate if (*current == NULL) { 3960Sstevel@tonic-gate *current = ibuf; 3970Sstevel@tonic-gate (*newargc)++; 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate /* 4030Sstevel@tonic-gate * Tricky corner case... 4040Sstevel@tonic-gate * I've parsed _exactly_ the amount of args as I have space. It 4050Sstevel@tonic-gate * won't return NULL-terminated, and bad things will happen to 4060Sstevel@tonic-gate * the caller. 4070Sstevel@tonic-gate */ 4080Sstevel@tonic-gate if (argvlen == *newargc) { 4090Sstevel@tonic-gate current = realloc(*thisargv, sizeof (char *) * (argvlen + 1)); 4100Sstevel@tonic-gate if (current == NULL) { 4110Sstevel@tonic-gate free(*thisargv); 4120Sstevel@tonic-gate return (MEMORY_ALLOCATION); 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate *thisargv = current; 4150Sstevel@tonic-gate current[argvlen] = NULL; 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate return (SUCCESS); 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate /* 4220Sstevel@tonic-gate * Enter a mode where commands are read from a file. Treat stdin special. 4230Sstevel@tonic-gate */ 4240Sstevel@tonic-gate void 4250Sstevel@tonic-gate do_interactive(FILE *infile, char *promptstring, parse_cmdln_fn parseit) 4260Sstevel@tonic-gate { 4270Sstevel@tonic-gate char ibuf[IBUF_SIZE], holder[IBUF_SIZE]; 4280Sstevel@tonic-gate char *hptr, **thisargv; 4290Sstevel@tonic-gate int thisargc; 4300Sstevel@tonic-gate boolean_t continue_in_progress = B_FALSE; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate (void) setjmp(env); 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate interactive = B_TRUE; 4350Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate if (infile == stdin) { 4380Sstevel@tonic-gate (void) printf("%s", promptstring); 4390Sstevel@tonic-gate (void) fflush(stdout); 4400Sstevel@tonic-gate } else { 4410Sstevel@tonic-gate readfile = B_TRUE; 4420Sstevel@tonic-gate } 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate while (fgets(ibuf, IBUF_SIZE, infile) != NULL) { 4450Sstevel@tonic-gate if (readfile) 4460Sstevel@tonic-gate lineno++; 4470Sstevel@tonic-gate thisargc = 0; 4480Sstevel@tonic-gate thisargv = NULL; 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate /* 4510Sstevel@tonic-gate * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will 4520Sstevel@tonic-gate * be null-terminated because of fgets(). 4530Sstevel@tonic-gate */ 4540Sstevel@tonic-gate if (ibuf[IBUF_SIZE - 2] != '\0') { 4550Sstevel@tonic-gate (void) fprintf(stderr, 4560Sstevel@tonic-gate gettext("Line %d too big.\n"), lineno); 4570Sstevel@tonic-gate exit(1); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate if (!continue_in_progress) { 4610Sstevel@tonic-gate /* Use -2 because of \n from fgets. */ 4620Sstevel@tonic-gate if (ibuf[strlen(ibuf) - 2] == CONT_CHAR) { 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate * Can use strcpy here, I've checked the 4650Sstevel@tonic-gate * length already. 4660Sstevel@tonic-gate */ 4670Sstevel@tonic-gate (void) strcpy(holder, ibuf); 4680Sstevel@tonic-gate hptr = &(holder[strlen(holder)]); 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* Remove the CONT_CHAR from the string. */ 4710Sstevel@tonic-gate hptr[-2] = ' '; 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate continue_in_progress = B_TRUE; 4740Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 4750Sstevel@tonic-gate continue; 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate } else { 4780Sstevel@tonic-gate /* Handle continuations... */ 4790Sstevel@tonic-gate (void) strncpy(hptr, ibuf, 4800Sstevel@tonic-gate (size_t)(&(holder[IBUF_SIZE]) - hptr)); 4810Sstevel@tonic-gate if (holder[IBUF_SIZE - 1] != '\0') { 4820Sstevel@tonic-gate (void) fprintf(stderr, 4830Sstevel@tonic-gate gettext("Command buffer overrun.\n")); 4840Sstevel@tonic-gate exit(1); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate /* Use - 2 because of \n from fgets. */ 4870Sstevel@tonic-gate if (hptr[strlen(hptr) - 2] == CONT_CHAR) { 4880Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 4890Sstevel@tonic-gate hptr += strlen(hptr); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate /* Remove the CONT_CHAR from the string. */ 4920Sstevel@tonic-gate hptr[-2] = ' '; 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate continue; 4950Sstevel@tonic-gate } else { 4960Sstevel@tonic-gate continue_in_progress = B_FALSE; 4970Sstevel@tonic-gate /* 4980Sstevel@tonic-gate * I've already checked the length... 4990Sstevel@tonic-gate */ 5000Sstevel@tonic-gate (void) strcpy(ibuf, holder); 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate switch (create_argv(ibuf, &thisargc, &thisargv)) { 5050Sstevel@tonic-gate case TOO_MANY_TOKENS: 5060Sstevel@tonic-gate (void) fprintf(stderr, 5070Sstevel@tonic-gate gettext("Too many input tokens.\n")); 5080Sstevel@tonic-gate exit(1); 5090Sstevel@tonic-gate break; 5100Sstevel@tonic-gate case MEMORY_ALLOCATION: 5110Sstevel@tonic-gate (void) fprintf(stderr, 5120Sstevel@tonic-gate gettext("Memory allocation error.\n")); 5130Sstevel@tonic-gate exit(1); 5140Sstevel@tonic-gate break; 5150Sstevel@tonic-gate case COMMENT_LINE: 5160Sstevel@tonic-gate /* Comment line. */ 5170Sstevel@tonic-gate break; 5180Sstevel@tonic-gate default: 5190Sstevel@tonic-gate parseit(thisargc, thisargv); 5200Sstevel@tonic-gate free(thisargv); 5210Sstevel@tonic-gate if (infile == stdin) { 5220Sstevel@tonic-gate (void) printf("%s", promptstring); 5230Sstevel@tonic-gate (void) fflush(stdout); 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate break; 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate if (!readfile) { 5300Sstevel@tonic-gate (void) putchar('\n'); 5310Sstevel@tonic-gate (void) fflush(stdout); 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate exit(0); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate /* 5370Sstevel@tonic-gate * Functions to parse strings that represent a debug or privilege level. 5380Sstevel@tonic-gate * These functions are copied from main.c and door.c in usr.lib/in.iked/common. 5390Sstevel@tonic-gate * If this file evolves into a common library that may be used by in.iked 5400Sstevel@tonic-gate * as well as the usr.sbin utilities, those duplicate functions should be 5410Sstevel@tonic-gate * deleted. 5420Sstevel@tonic-gate * 5430Sstevel@tonic-gate * A privilege level may be represented by a simple keyword, corresponding 5440Sstevel@tonic-gate * to one of the possible levels. A debug level may be represented by a 5450Sstevel@tonic-gate * series of keywords, separated by '+' or '-', indicating categories to 5460Sstevel@tonic-gate * be added or removed from the set of categories in the debug level. 5470Sstevel@tonic-gate * For example, +all-op corresponds to level 0xfffffffb (all flags except 5480Sstevel@tonic-gate * for D_OP set); while p1+p2+pfkey corresponds to level 0x38. Note that 5490Sstevel@tonic-gate * the leading '+' is implicit; the first keyword in the list must be for 5500Sstevel@tonic-gate * a category that is to be added. 5510Sstevel@tonic-gate * 5520Sstevel@tonic-gate * These parsing functions make use of a local version of strtok, strtok_d, 5530Sstevel@tonic-gate * which includes an additional parameter, char *delim. This param is filled 5540Sstevel@tonic-gate * in with the character which ends the returned token. In other words, 5550Sstevel@tonic-gate * this version of strtok, in addition to returning the token, also returns 5560Sstevel@tonic-gate * the single character delimiter from the original string which marked the 5570Sstevel@tonic-gate * end of the token. 5580Sstevel@tonic-gate */ 5590Sstevel@tonic-gate static char * 5600Sstevel@tonic-gate strtok_d(char *string, const char *sepset, char *delim) 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate static char *lasts; 5630Sstevel@tonic-gate char *q, *r; 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate /* first or subsequent call */ 5660Sstevel@tonic-gate if (string == NULL) 5670Sstevel@tonic-gate string = lasts; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate if (string == 0) /* return if no tokens remaining */ 5700Sstevel@tonic-gate return (NULL); 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate q = string + strspn(string, sepset); /* skip leading separators */ 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate if (*q == '\0') /* return if no tokens remaining */ 5750Sstevel@tonic-gate return (NULL); 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL) { /* move past token */ 5780Sstevel@tonic-gate lasts = 0; /* indicate that this is last token */ 5790Sstevel@tonic-gate } else { 5800Sstevel@tonic-gate *delim = *r; /* save delimitor */ 5810Sstevel@tonic-gate *r = '\0'; 5820Sstevel@tonic-gate lasts = r + 1; 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate return (q); 5850Sstevel@tonic-gate } 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate static keywdtab_t privtab[] = { 5880Sstevel@tonic-gate { IKE_PRIV_MINIMUM, "base" }, 5890Sstevel@tonic-gate { IKE_PRIV_MODKEYS, "modkeys" }, 5900Sstevel@tonic-gate { IKE_PRIV_KEYMAT, "keymat" }, 5910Sstevel@tonic-gate { IKE_PRIV_MINIMUM, "0" }, 5920Sstevel@tonic-gate }; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate int 5950Sstevel@tonic-gate privstr2num(char *str) 5960Sstevel@tonic-gate { 5970Sstevel@tonic-gate keywdtab_t *pp; 5980Sstevel@tonic-gate char *endp; 5990Sstevel@tonic-gate int priv; 6000Sstevel@tonic-gate 6010Sstevel@tonic-gate for (pp = privtab; pp < A_END(privtab); pp++) { 6020Sstevel@tonic-gate if (strcasecmp(str, pp->kw_str) == 0) 6030Sstevel@tonic-gate return (pp->kw_tag); 6040Sstevel@tonic-gate } 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate priv = strtol(str, &endp, 0); 6070Sstevel@tonic-gate if (*endp == '\0') 6080Sstevel@tonic-gate return (priv); 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate return (-1); 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate static keywdtab_t dbgtab[] = { 6140Sstevel@tonic-gate { D_CERT, "cert" }, 6150Sstevel@tonic-gate { D_KEY, "key" }, 6160Sstevel@tonic-gate { D_OP, "op" }, 6170Sstevel@tonic-gate { D_P1, "p1" }, 6180Sstevel@tonic-gate { D_P1, "phase1" }, 6190Sstevel@tonic-gate { D_P2, "p2" }, 6200Sstevel@tonic-gate { D_P2, "phase2" }, 6210Sstevel@tonic-gate { D_PFKEY, "pfkey" }, 6220Sstevel@tonic-gate { D_POL, "pol" }, 6230Sstevel@tonic-gate { D_POL, "policy" }, 6240Sstevel@tonic-gate { D_PROP, "prop" }, 6250Sstevel@tonic-gate { D_DOOR, "door" }, 6260Sstevel@tonic-gate { D_CONFIG, "config" }, 6270Sstevel@tonic-gate { D_ALL, "all" }, 6280Sstevel@tonic-gate { 0, "0" }, 6290Sstevel@tonic-gate }; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate int 6320Sstevel@tonic-gate dbgstr2num(char *str) 6330Sstevel@tonic-gate { 6340Sstevel@tonic-gate keywdtab_t *dp; 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate for (dp = dbgtab; dp < A_END(dbgtab); dp++) { 6370Sstevel@tonic-gate if (strcasecmp(str, dp->kw_str) == 0) 6380Sstevel@tonic-gate return (dp->kw_tag); 6390Sstevel@tonic-gate } 6400Sstevel@tonic-gate return (D_INVALID); 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate int 6440Sstevel@tonic-gate parsedbgopts(char *optarg) 6450Sstevel@tonic-gate { 6460Sstevel@tonic-gate char *argp, *endp, op, nextop; 6470Sstevel@tonic-gate int mask = 0, new; 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate mask = strtol(optarg, &endp, 0); 6500Sstevel@tonic-gate if (*endp == '\0') 6510Sstevel@tonic-gate return (mask); 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate op = optarg[0]; 6540Sstevel@tonic-gate if (op != '-') 6550Sstevel@tonic-gate op = '+'; 6560Sstevel@tonic-gate argp = strtok_d(optarg, "+-", &nextop); 6570Sstevel@tonic-gate do { 6580Sstevel@tonic-gate new = dbgstr2num(argp); 6590Sstevel@tonic-gate if (new == D_INVALID) { 6600Sstevel@tonic-gate /* we encountered an invalid keywd */ 6610Sstevel@tonic-gate return (new); 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate if (op == '+') { 6640Sstevel@tonic-gate mask |= new; 6650Sstevel@tonic-gate } else { 6660Sstevel@tonic-gate mask &= ~new; 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate op = nextop; 6690Sstevel@tonic-gate } while ((argp = strtok_d(NULL, "+-", &nextop)) != NULL); 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate return (mask); 6720Sstevel@tonic-gate } 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate /* 6760Sstevel@tonic-gate * functions to manipulate the kmcookie-label mapping file 6770Sstevel@tonic-gate */ 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate /* 6800Sstevel@tonic-gate * Open, lockf, fdopen the given file, returning a FILE * on success, 6810Sstevel@tonic-gate * or NULL on failure. 6820Sstevel@tonic-gate */ 6830Sstevel@tonic-gate FILE * 6840Sstevel@tonic-gate kmc_open_and_lock(char *name) 6850Sstevel@tonic-gate { 6860Sstevel@tonic-gate int fd, rtnerr; 6870Sstevel@tonic-gate FILE *fp; 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if ((fd = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { 6900Sstevel@tonic-gate return (NULL); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate if (lockf(fd, F_LOCK, 0) < 0) { 6930Sstevel@tonic-gate return (NULL); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate if ((fp = fdopen(fd, "a+")) == NULL) { 6960Sstevel@tonic-gate return (NULL); 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate if (fseek(fp, 0, SEEK_SET) < 0) { 6990Sstevel@tonic-gate /* save errno in case fclose changes it */ 7000Sstevel@tonic-gate rtnerr = errno; 7010Sstevel@tonic-gate (void) fclose(fp); 7020Sstevel@tonic-gate errno = rtnerr; 7030Sstevel@tonic-gate return (NULL); 7040Sstevel@tonic-gate } 7050Sstevel@tonic-gate return (fp); 7060Sstevel@tonic-gate } 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate /* 7090Sstevel@tonic-gate * Extract an integer cookie and string label from a line from the 7100Sstevel@tonic-gate * kmcookie-label file. Return -1 on failure, 0 on success. 7110Sstevel@tonic-gate */ 7120Sstevel@tonic-gate int 7130Sstevel@tonic-gate kmc_parse_line(char *line, int *cookie, char **label) 7140Sstevel@tonic-gate { 7150Sstevel@tonic-gate char *cookiestr; 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate *cookie = 0; 7180Sstevel@tonic-gate *label = NULL; 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate cookiestr = strtok(line, " \t\n"); 7210Sstevel@tonic-gate if (cookiestr == NULL) { 7220Sstevel@tonic-gate return (-1); 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate /* Everything that follows, up to the newline, is the label. */ 7260Sstevel@tonic-gate *label = strtok(NULL, "\n"); 7270Sstevel@tonic-gate if (*label == NULL) { 7280Sstevel@tonic-gate return (-1); 7290Sstevel@tonic-gate } 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate *cookie = atoi(cookiestr); 7320Sstevel@tonic-gate return (0); 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate /* 7360Sstevel@tonic-gate * Insert a mapping into the file (if it's not already there), given the 7370Sstevel@tonic-gate * new label. Return the assigned cookie, or -1 on error. 7380Sstevel@tonic-gate */ 7390Sstevel@tonic-gate int 7400Sstevel@tonic-gate kmc_insert_mapping(char *label) 7410Sstevel@tonic-gate { 7420Sstevel@tonic-gate FILE *map; 7430Sstevel@tonic-gate char linebuf[MAXLINESIZE]; 7440Sstevel@tonic-gate char *cur_label; 7450Sstevel@tonic-gate int max_cookie = 0, cur_cookie, rtn_cookie; 7460Sstevel@tonic-gate int rtnerr = 0; 7470Sstevel@tonic-gate boolean_t found = B_FALSE; 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate /* open and lock the file; will sleep until lock is available */ 7500Sstevel@tonic-gate if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 7510Sstevel@tonic-gate /* kmc_open_and_lock() sets errno appropriately */ 7520Sstevel@tonic-gate return (-1); 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 7580Sstevel@tonic-gate rtnerr = EINVAL; 7590Sstevel@tonic-gate goto error; 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate if (cur_cookie > max_cookie) 7630Sstevel@tonic-gate max_cookie = cur_cookie; 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate if ((!found) && (strcmp(cur_label, label) == 0)) { 7660Sstevel@tonic-gate found = B_TRUE; 7670Sstevel@tonic-gate rtn_cookie = cur_cookie; 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate } 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate if (!found) { 7720Sstevel@tonic-gate rtn_cookie = ++max_cookie; 7730Sstevel@tonic-gate if ((fprintf(map, "%u\t%s\n", rtn_cookie, label) < 0) || 7740Sstevel@tonic-gate (fflush(map) < 0)) { 7750Sstevel@tonic-gate rtnerr = errno; 7760Sstevel@tonic-gate goto error; 7770Sstevel@tonic-gate } 7780Sstevel@tonic-gate } 7790Sstevel@tonic-gate (void) fclose(map); 7800Sstevel@tonic-gate 7810Sstevel@tonic-gate return (rtn_cookie); 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate error: 7840Sstevel@tonic-gate (void) fclose(map); 7850Sstevel@tonic-gate errno = rtnerr; 7860Sstevel@tonic-gate return (-1); 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate /* 7900Sstevel@tonic-gate * Lookup the given cookie and return its corresponding label. Return 7910Sstevel@tonic-gate * a pointer to the label on success, NULL on error (or if the label is 7920Sstevel@tonic-gate * not found). Note that the returned label pointer points to a static 7930Sstevel@tonic-gate * string, so the label will be overwritten by a subsequent call to the 7940Sstevel@tonic-gate * function; the function is also not thread-safe as a result. 7950Sstevel@tonic-gate */ 7960Sstevel@tonic-gate char * 7970Sstevel@tonic-gate kmc_lookup_by_cookie(int cookie) 7980Sstevel@tonic-gate { 7990Sstevel@tonic-gate FILE *map; 8000Sstevel@tonic-gate static char linebuf[MAXLINESIZE]; 8010Sstevel@tonic-gate char *cur_label; 8020Sstevel@tonic-gate int cur_cookie; 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 8050Sstevel@tonic-gate return (NULL); 8060Sstevel@tonic-gate } 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 8110Sstevel@tonic-gate (void) fclose(map); 8120Sstevel@tonic-gate return (NULL); 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate if (cookie == cur_cookie) { 8160Sstevel@tonic-gate (void) fclose(map); 8170Sstevel@tonic-gate return (cur_label); 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate (void) fclose(map); 8210Sstevel@tonic-gate 8220Sstevel@tonic-gate return (NULL); 8230Sstevel@tonic-gate } 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate /* 8260Sstevel@tonic-gate * Parse basic extension headers and return in the passed-in pointer vector. 8270Sstevel@tonic-gate * Return values include: 8280Sstevel@tonic-gate * 8290Sstevel@tonic-gate * KGE_OK Everything's nice and parsed out. 8300Sstevel@tonic-gate * If there are no extensions, place NULL in extv[0]. 8310Sstevel@tonic-gate * KGE_DUP There is a duplicate extension. 8320Sstevel@tonic-gate * First instance in appropriate bin. First duplicate in 8330Sstevel@tonic-gate * extv[0]. 8340Sstevel@tonic-gate * KGE_UNK Unknown extension type encountered. extv[0] contains 8350Sstevel@tonic-gate * unknown header. 8360Sstevel@tonic-gate * KGE_LEN Extension length error. 8370Sstevel@tonic-gate * KGE_CHK High-level reality check failed on specific extension. 8380Sstevel@tonic-gate * 8390Sstevel@tonic-gate * My apologies for some of the pointer arithmetic in here. I'm thinking 8400Sstevel@tonic-gate * like an assembly programmer, yet trying to make the compiler happy. 8410Sstevel@tonic-gate */ 8420Sstevel@tonic-gate int 8430Sstevel@tonic-gate spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize, 8440Sstevel@tonic-gate char *diag_buf, uint_t diag_buf_len) 8450Sstevel@tonic-gate { 8460Sstevel@tonic-gate int i; 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate if (diag_buf != NULL) 8490Sstevel@tonic-gate diag_buf[0] = '\0'; 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate for (i = 1; i <= SPD_EXT_MAX; i++) 8520Sstevel@tonic-gate extv[i] = NULL; 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate i = 0; 8550Sstevel@tonic-gate /* Use extv[0] as the "current working pointer". */ 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate extv[0] = (spd_ext_t *)(basehdr + 1); 8580Sstevel@tonic-gate msgsize = SPD_64TO8(msgsize); 8590Sstevel@tonic-gate 8600Sstevel@tonic-gate while ((char *)extv[0] < ((char *)basehdr + msgsize)) { 8610Sstevel@tonic-gate /* Check for unknown headers. */ 8620Sstevel@tonic-gate i++; 8630Sstevel@tonic-gate 8640Sstevel@tonic-gate if (extv[0]->spd_ext_type == 0 || 8650Sstevel@tonic-gate extv[0]->spd_ext_type > SPD_EXT_MAX) { 8660Sstevel@tonic-gate if (diag_buf != NULL) { 8670Sstevel@tonic-gate (void) snprintf(diag_buf, diag_buf_len, 8680Sstevel@tonic-gate "spdsock ext 0x%X unknown: 0x%X", 8690Sstevel@tonic-gate i, extv[0]->spd_ext_type); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate return (KGE_UNK); 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate /* 8750Sstevel@tonic-gate * Check length. Use uint64_t because extlen is in units 8760Sstevel@tonic-gate * of 64-bit words. If length goes beyond the msgsize, 8770Sstevel@tonic-gate * return an error. (Zero length also qualifies here.) 8780Sstevel@tonic-gate */ 8790Sstevel@tonic-gate if (extv[0]->spd_ext_len == 0 || 8800Sstevel@tonic-gate (uint8_t *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) > 8810Sstevel@tonic-gate (uint8_t *)((uint8_t *)basehdr + msgsize)) 8820Sstevel@tonic-gate return (KGE_LEN); 8830Sstevel@tonic-gate 8840Sstevel@tonic-gate /* Check for redundant headers. */ 8850Sstevel@tonic-gate if (extv[extv[0]->spd_ext_type] != NULL) 8860Sstevel@tonic-gate return (KGE_DUP); 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate /* If I make it here, assign the appropriate bin. */ 8890Sstevel@tonic-gate extv[extv[0]->spd_ext_type] = extv[0]; 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate /* Advance pointer (See above for uint64_t ptr reasoning.) */ 8920Sstevel@tonic-gate extv[0] = (spd_ext_t *) 8930Sstevel@tonic-gate ((uint64_t *)extv[0] + extv[0]->spd_ext_len); 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate /* Everything's cool. */ 8970Sstevel@tonic-gate 8980Sstevel@tonic-gate /* 8990Sstevel@tonic-gate * If extv[0] == NULL, then there are no extension headers in this 9000Sstevel@tonic-gate * message. Ensure that this is the case. 9010Sstevel@tonic-gate */ 9020Sstevel@tonic-gate if (extv[0] == (spd_ext_t *)(basehdr + 1)) 9030Sstevel@tonic-gate extv[0] = NULL; 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate return (KGE_OK); 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate const char * 9090Sstevel@tonic-gate spdsock_diag(int diagnostic) 9100Sstevel@tonic-gate { 9110Sstevel@tonic-gate switch (diagnostic) { 9120Sstevel@tonic-gate case SPD_DIAGNOSTIC_NONE: 9130Sstevel@tonic-gate return (gettext("no error")); 9140Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNKNOWN_EXT: 9150Sstevel@tonic-gate return (gettext("unknown extension")); 9160Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_EXTLEN: 9170Sstevel@tonic-gate return (gettext("bad extension length")); 9180Sstevel@tonic-gate case SPD_DIAGNOSTIC_NO_RULE_EXT: 9190Sstevel@tonic-gate return (gettext("no rule extension")); 9200Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_ADDR_LEN: 9210Sstevel@tonic-gate return (gettext("bad address len")); 9220Sstevel@tonic-gate case SPD_DIAGNOSTIC_MIXED_AF: 9230Sstevel@tonic-gate return (gettext("mixed address family")); 9240Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_NO_MEM: 9250Sstevel@tonic-gate return (gettext("add: no memory")); 9260Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT: 9270Sstevel@tonic-gate return (gettext("add: wrong action count")); 9280Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_BAD_TYPE: 9290Sstevel@tonic-gate return (gettext("add: bad type")); 9300Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_BAD_FLAGS: 9310Sstevel@tonic-gate return (gettext("add: bad flags")); 9320Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_INCON_FLAGS: 9330Sstevel@tonic-gate return (gettext("add: inconsistent flags")); 9340Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_LCLPORT: 9350Sstevel@tonic-gate return (gettext("malformed local port")); 9360Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_LCLPORT: 9370Sstevel@tonic-gate return (gettext("duplicate local port")); 9380Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_REMPORT: 9390Sstevel@tonic-gate return (gettext("malformed remote port")); 9400Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_REMPORT: 9410Sstevel@tonic-gate return (gettext("duplicate remote port")); 9420Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_PROTO: 9430Sstevel@tonic-gate return (gettext("malformed proto")); 9440Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_PROTO: 9450Sstevel@tonic-gate return (gettext("duplicate proto")); 9460Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_LCLADDR: 9470Sstevel@tonic-gate return (gettext("malformed local address")); 9480Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_LCLADDR: 9490Sstevel@tonic-gate return (gettext("duplicate local address")); 9500Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_REMADDR: 9510Sstevel@tonic-gate return (gettext("malformed remote address")); 9520Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_REMADDR: 9530Sstevel@tonic-gate return (gettext("duplicate remote address")); 9540Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_ACTION: 9550Sstevel@tonic-gate return (gettext("malformed action")); 9560Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_ACTION: 9570Sstevel@tonic-gate return (gettext("duplicate action")); 9580Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_RULE: 9590Sstevel@tonic-gate return (gettext("malformed rule")); 9600Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_RULE: 9610Sstevel@tonic-gate return (gettext("duplicate rule")); 9620Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_RULESET: 9630Sstevel@tonic-gate return (gettext("malformed ruleset")); 9640Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_RULESET: 9650Sstevel@tonic-gate return (gettext("duplicate ruleset")); 9660Sstevel@tonic-gate case SPD_DIAGNOSTIC_INVALID_RULE_INDEX: 9670Sstevel@tonic-gate return (gettext("invalid rule index")); 9680Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_SPDID: 9690Sstevel@tonic-gate return (gettext("bad spdid")); 9700Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_MSG_TYPE: 9710Sstevel@tonic-gate return (gettext("bad message type")); 9720Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_AH_ALG: 9730Sstevel@tonic-gate return (gettext("unsupported AH algorithm")); 9740Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG: 9750Sstevel@tonic-gate return (gettext("unsupported ESP encryption algorithm")); 9760Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG: 9770Sstevel@tonic-gate return (gettext("unsupported ESP authentication algorithm")); 9780Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_AH_KEYSIZE: 9790Sstevel@tonic-gate return (gettext("unsupported AH key size")); 9800Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_KEYSIZE: 9810Sstevel@tonic-gate return (gettext("unsupported ESP encryption key size")); 9820Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_KEYSIZE: 9830Sstevel@tonic-gate return (gettext("unsupported ESP authentication key size")); 9840Sstevel@tonic-gate case SPD_DIAGNOSTIC_NO_ACTION_EXT: 9850Sstevel@tonic-gate return (gettext("No ACTION extension")); 9860Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_ID_RANGE: 9870Sstevel@tonic-gate return (gettext("invalid algorithm identifer")); 9880Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES: 9890Sstevel@tonic-gate return (gettext("number of key sizes inconsistent")); 9900Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES: 9910Sstevel@tonic-gate return (gettext("number of block sizes inconsistent")); 9920Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN: 9930Sstevel@tonic-gate return (gettext("invalid mechanism name length")); 994*3055Sdanmcd case SPD_DIAGNOSTIC_NOT_GLOBAL_OP: 995*3055Sdanmcd return (gettext("operation not applicable to all policies")); 996*3055Sdanmcd case SPD_DIAGNOSTIC_NO_TUNNEL_SELECTORS: 997*3055Sdanmcd return (gettext("using selectors on a transport-mode tunnel")); 9980Sstevel@tonic-gate default: 9990Sstevel@tonic-gate return (gettext("unknown diagnostic")); 10000Sstevel@tonic-gate } 10010Sstevel@tonic-gate } 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate /* 10040Sstevel@tonic-gate * PF_KEY Diagnostic table. 10050Sstevel@tonic-gate * 10060Sstevel@tonic-gate * PF_KEY NOTE: If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is 10070Sstevel@tonic-gate * where you need to add new messages. 10080Sstevel@tonic-gate */ 10090Sstevel@tonic-gate 10100Sstevel@tonic-gate const char * 10110Sstevel@tonic-gate keysock_diag(int diagnostic) 10120Sstevel@tonic-gate { 10130Sstevel@tonic-gate switch (diagnostic) { 1014*3055Sdanmcd case SADB_X_DIAGNOSTIC_NONE: 10150Sstevel@tonic-gate return (gettext("No diagnostic")); 10160Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_MSG: 10170Sstevel@tonic-gate return (gettext("Unknown message type")); 10180Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_EXT: 10190Sstevel@tonic-gate return (gettext("Unknown extension type")); 10200Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EXTLEN: 10210Sstevel@tonic-gate return (gettext("Bad extension length")); 10220Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE: 10230Sstevel@tonic-gate return (gettext("Unknown Security Association type")); 10240Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_SATYPE_NEEDED: 10250Sstevel@tonic-gate return (gettext("Specific Security Association type needed")); 10260Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NO_SADBS: 10270Sstevel@tonic-gate return (gettext("No Security Association Databases present")); 10280Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NO_EXT: 10290Sstevel@tonic-gate return (gettext("No extensions needed for message")); 10300Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SRC_AF: 10310Sstevel@tonic-gate return (gettext("Bad source address family")); 10320Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_DST_AF: 10330Sstevel@tonic-gate return (gettext("Bad destination address family")); 10340Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_PROXY_AF: 1035*3055Sdanmcd return (gettext("Bad inner-source address family")); 10360Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_AF_MISMATCH: 10370Sstevel@tonic-gate return (gettext("Source/destination address family mismatch")); 10380Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SRC: 10390Sstevel@tonic-gate return (gettext("Bad source address value")); 10400Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_DST: 10410Sstevel@tonic-gate return (gettext("Bad destination address value")); 10420Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ALLOC_HSERR: 10430Sstevel@tonic-gate return (gettext("Soft allocations limit more than hard limit")); 10440Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BYTES_HSERR: 10450Sstevel@tonic-gate return (gettext("Soft bytes limit more than hard limit")); 10460Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ADDTIME_HSERR: 10470Sstevel@tonic-gate return (gettext("Soft add expiration time later " 10480Sstevel@tonic-gate "than hard expiration time")); 10490Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_USETIME_HSERR: 10500Sstevel@tonic-gate return (gettext("Soft use expiration time later " 10510Sstevel@tonic-gate "than hard expiration time")); 10520Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_SRC: 10530Sstevel@tonic-gate return (gettext("Missing source address")); 10540Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_DST: 10550Sstevel@tonic-gate return (gettext("Missing destination address")); 10560Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_SA: 10570Sstevel@tonic-gate return (gettext("Missing SA extension")); 10580Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_EKEY: 10590Sstevel@tonic-gate return (gettext("Missing encryption key")); 10600Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_AKEY: 10610Sstevel@tonic-gate return (gettext("Missing authentication key")); 10620Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_RANGE: 10630Sstevel@tonic-gate return (gettext("Missing SPI range")); 10640Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_SRC: 10650Sstevel@tonic-gate return (gettext("Duplicate source address")); 10660Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_DST: 10670Sstevel@tonic-gate return (gettext("Duplicate destination address")); 10680Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_SA: 10690Sstevel@tonic-gate return (gettext("Duplicate SA extension")); 10700Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_EKEY: 10710Sstevel@tonic-gate return (gettext("Duplicate encryption key")); 10720Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_AKEY: 10730Sstevel@tonic-gate return (gettext("Duplicate authentication key")); 10740Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_RANGE: 10750Sstevel@tonic-gate return (gettext("Duplicate SPI range")); 10760Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_SRC: 10770Sstevel@tonic-gate return (gettext("Malformed source address")); 10780Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_DST: 10790Sstevel@tonic-gate return (gettext("Malformed destination address")); 10800Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_SA: 10810Sstevel@tonic-gate return (gettext("Malformed SA extension")); 10820Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_EKEY: 10830Sstevel@tonic-gate return (gettext("Malformed encryption key")); 10840Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_AKEY: 10850Sstevel@tonic-gate return (gettext("Malformed authentication key")); 10860Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_RANGE: 10870Sstevel@tonic-gate return (gettext("Malformed SPI range")); 10880Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_AKEY_PRESENT: 10890Sstevel@tonic-gate return (gettext("Authentication key not needed")); 10900Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_EKEY_PRESENT: 10910Sstevel@tonic-gate return (gettext("Encryption key not needed")); 10920Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_PROP_PRESENT: 10930Sstevel@tonic-gate return (gettext("Proposal extension not needed")); 10940Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_SUPP_PRESENT: 10950Sstevel@tonic-gate return (gettext("Supported algorithms extension not needed")); 10960Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_AALG: 10970Sstevel@tonic-gate return (gettext("Unsupported authentication algorithm")); 10980Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EALG: 10990Sstevel@tonic-gate return (gettext("Unsupported encryption algorithm")); 11000Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SAFLAGS: 11010Sstevel@tonic-gate return (gettext("Invalid SA flags")); 11020Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SASTATE: 11030Sstevel@tonic-gate return (gettext("Invalid SA state")); 11040Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_AKEYBITS: 11050Sstevel@tonic-gate return (gettext("Bad number of authentication bits")); 11060Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EKEYBITS: 11070Sstevel@tonic-gate return (gettext("Bad number of encryption bits")); 11080Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ENCR_NOTSUPP: 11090Sstevel@tonic-gate return (gettext("Encryption not supported for this SA type")); 11100Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_WEAK_EKEY: 11110Sstevel@tonic-gate return (gettext("Weak encryption key")); 11120Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_WEAK_AKEY: 11130Sstevel@tonic-gate return (gettext("Weak authentication key")); 11140Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_KMP: 11150Sstevel@tonic-gate return (gettext("Duplicate key management protocol")); 11160Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_KMC: 11170Sstevel@tonic-gate return (gettext("Duplicate key management cookie")); 11180Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC: 1119*3055Sdanmcd return (gettext("Missing NAT-T local address")); 11200Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_NATT_REM: 1121*3055Sdanmcd return (gettext("Missing NAT-T remote address")); 11220Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC: 1123*3055Sdanmcd return (gettext("Duplicate NAT-T local address")); 11240Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM: 1125*3055Sdanmcd return (gettext("Duplicate NAT-T remote address")); 11260Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC: 1127*3055Sdanmcd return (gettext("Malformed NAT-T local address")); 11280Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM: 1129*3055Sdanmcd return (gettext("Malformed NAT-T remote address")); 11300Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS: 1131*3055Sdanmcd return (gettext("Duplicate NAT-T ports")); 1132*3055Sdanmcd case SADB_X_DIAGNOSTIC_MISSING_INNER_SRC: 1133*3055Sdanmcd return (gettext("Missing inner source address")); 1134*3055Sdanmcd case SADB_X_DIAGNOSTIC_MISSING_INNER_DST: 1135*3055Sdanmcd return (gettext("Missing inner destination address")); 1136*3055Sdanmcd case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_SRC: 1137*3055Sdanmcd return (gettext("Duplicate inner source address")); 1138*3055Sdanmcd case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_DST: 1139*3055Sdanmcd return (gettext("Duplicate inner destination address")); 1140*3055Sdanmcd case SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC: 1141*3055Sdanmcd return (gettext("Malformed inner source address")); 1142*3055Sdanmcd case SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST: 1143*3055Sdanmcd return (gettext("Malformed inner destination address")); 1144*3055Sdanmcd case SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC: 1145*3055Sdanmcd return (gettext("Invalid inner-source prefix length ")); 1146*3055Sdanmcd case SADB_X_DIAGNOSTIC_PREFIX_INNER_DST: 1147*3055Sdanmcd return (gettext("Invalid inner-destination prefix length")); 1148*3055Sdanmcd case SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF: 1149*3055Sdanmcd return (gettext("Bad inner-destination address family")); 1150*3055Sdanmcd case SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH: 1151*3055Sdanmcd return (gettext( 1152*3055Sdanmcd "Inner source/destination address family mismatch")); 1153*3055Sdanmcd case SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF: 1154*3055Sdanmcd return (gettext("Bad NAT-T remote address family")); 1155*3055Sdanmcd case SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF: 1156*3055Sdanmcd return (gettext("Bad NAT-T local address family")); 1157*3055Sdanmcd case SADB_X_DIAGNOSTIC_PROTO_MISMATCH: 1158*3055Sdanmcd return (gettext("Source/desination protocol mismatch")); 1159*3055Sdanmcd case SADB_X_DIAGNOSTIC_INNER_PROTO_MISMATCH: 1160*3055Sdanmcd return (gettext("Inner source/desination protocol mismatch")); 1161*3055Sdanmcd case SADB_X_DIAGNOSTIC_DUAL_PORT_SETS: 1162*3055Sdanmcd return (gettext("Both inner ports and outer ports are set")); 11630Sstevel@tonic-gate default: 11640Sstevel@tonic-gate return (gettext("Unknown diagnostic code")); 11650Sstevel@tonic-gate } 11660Sstevel@tonic-gate } 1167*3055Sdanmcd 1168*3055Sdanmcd /* 1169*3055Sdanmcd * Convert an IPv6 mask to a prefix len. I assume all IPv6 masks are 1170*3055Sdanmcd * contiguous, so I stop at the first zero bit! 1171*3055Sdanmcd */ 1172*3055Sdanmcd int 1173*3055Sdanmcd in_masktoprefix(uint8_t *mask, boolean_t is_v4mapped) 1174*3055Sdanmcd { 1175*3055Sdanmcd int rc = 0; 1176*3055Sdanmcd uint8_t last; 1177*3055Sdanmcd int limit = IPV6_ABITS; 1178*3055Sdanmcd 1179*3055Sdanmcd if (is_v4mapped) { 1180*3055Sdanmcd mask += ((IPV6_ABITS - IP_ABITS)/8); 1181*3055Sdanmcd limit = IP_ABITS; 1182*3055Sdanmcd } 1183*3055Sdanmcd 1184*3055Sdanmcd while (*mask == 0xff) { 1185*3055Sdanmcd rc += 8; 1186*3055Sdanmcd if (rc == limit) 1187*3055Sdanmcd return (limit); 1188*3055Sdanmcd mask++; 1189*3055Sdanmcd } 1190*3055Sdanmcd 1191*3055Sdanmcd last = *mask; 1192*3055Sdanmcd while (last != 0) { 1193*3055Sdanmcd rc++; 1194*3055Sdanmcd last = (last << 1) & 0xff; 1195*3055Sdanmcd } 1196*3055Sdanmcd 1197*3055Sdanmcd return (rc); 1198*3055Sdanmcd } 1199*3055Sdanmcd 1200*3055Sdanmcd /* 1201*3055Sdanmcd * Expand the diagnostic code into a message. 1202*3055Sdanmcd */ 1203*3055Sdanmcd void 1204*3055Sdanmcd print_diagnostic(FILE *file, uint16_t diagnostic) 1205*3055Sdanmcd { 1206*3055Sdanmcd /* Use two spaces so above strings can fit on the line. */ 1207*3055Sdanmcd (void) fprintf(file, gettext(" Diagnostic code %u: %s.\n"), 1208*3055Sdanmcd diagnostic, keysock_diag(diagnostic)); 1209*3055Sdanmcd } 1210*3055Sdanmcd 1211*3055Sdanmcd /* 1212*3055Sdanmcd * Prints the base PF_KEY message. 1213*3055Sdanmcd */ 1214*3055Sdanmcd void 1215*3055Sdanmcd print_sadb_msg(struct sadb_msg *samsg, time_t wallclock, boolean_t vflag) 1216*3055Sdanmcd { 1217*3055Sdanmcd if (wallclock != 0) 1218*3055Sdanmcd printsatime(wallclock, gettext("%sTimestamp: %s\n"), "", NULL, 1219*3055Sdanmcd vflag); 1220*3055Sdanmcd 1221*3055Sdanmcd (void) printf(gettext("Base message (version %u) type "), 1222*3055Sdanmcd samsg->sadb_msg_version); 1223*3055Sdanmcd switch (samsg->sadb_msg_type) { 1224*3055Sdanmcd case SADB_RESERVED: 1225*3055Sdanmcd (void) printf(gettext("RESERVED (warning: set to 0)")); 1226*3055Sdanmcd break; 1227*3055Sdanmcd case SADB_GETSPI: 1228*3055Sdanmcd (void) printf("GETSPI"); 1229*3055Sdanmcd break; 1230*3055Sdanmcd case SADB_UPDATE: 1231*3055Sdanmcd (void) printf("UPDATE"); 1232*3055Sdanmcd break; 1233*3055Sdanmcd case SADB_ADD: 1234*3055Sdanmcd (void) printf("ADD"); 1235*3055Sdanmcd break; 1236*3055Sdanmcd case SADB_DELETE: 1237*3055Sdanmcd (void) printf("DELETE"); 1238*3055Sdanmcd break; 1239*3055Sdanmcd case SADB_GET: 1240*3055Sdanmcd (void) printf("GET"); 1241*3055Sdanmcd break; 1242*3055Sdanmcd case SADB_ACQUIRE: 1243*3055Sdanmcd (void) printf("ACQUIRE"); 1244*3055Sdanmcd break; 1245*3055Sdanmcd case SADB_REGISTER: 1246*3055Sdanmcd (void) printf("REGISTER"); 1247*3055Sdanmcd break; 1248*3055Sdanmcd case SADB_EXPIRE: 1249*3055Sdanmcd (void) printf("EXPIRE"); 1250*3055Sdanmcd break; 1251*3055Sdanmcd case SADB_FLUSH: 1252*3055Sdanmcd (void) printf("FLUSH"); 1253*3055Sdanmcd break; 1254*3055Sdanmcd case SADB_DUMP: 1255*3055Sdanmcd (void) printf("DUMP"); 1256*3055Sdanmcd break; 1257*3055Sdanmcd case SADB_X_PROMISC: 1258*3055Sdanmcd (void) printf("X_PROMISC"); 1259*3055Sdanmcd break; 1260*3055Sdanmcd case SADB_X_INVERSE_ACQUIRE: 1261*3055Sdanmcd (void) printf("X_INVERSE_ACQUIRE"); 1262*3055Sdanmcd break; 1263*3055Sdanmcd default: 1264*3055Sdanmcd (void) printf(gettext("Unknown (%u)"), samsg->sadb_msg_type); 1265*3055Sdanmcd break; 1266*3055Sdanmcd } 1267*3055Sdanmcd (void) printf(gettext(", SA type ")); 1268*3055Sdanmcd 1269*3055Sdanmcd switch (samsg->sadb_msg_satype) { 1270*3055Sdanmcd case SADB_SATYPE_UNSPEC: 1271*3055Sdanmcd (void) printf(gettext("<unspecified/all>")); 1272*3055Sdanmcd break; 1273*3055Sdanmcd case SADB_SATYPE_AH: 1274*3055Sdanmcd (void) printf("AH"); 1275*3055Sdanmcd break; 1276*3055Sdanmcd case SADB_SATYPE_ESP: 1277*3055Sdanmcd (void) printf("ESP"); 1278*3055Sdanmcd break; 1279*3055Sdanmcd case SADB_SATYPE_RSVP: 1280*3055Sdanmcd (void) printf("RSVP"); 1281*3055Sdanmcd break; 1282*3055Sdanmcd case SADB_SATYPE_OSPFV2: 1283*3055Sdanmcd (void) printf("OSPFv2"); 1284*3055Sdanmcd break; 1285*3055Sdanmcd case SADB_SATYPE_RIPV2: 1286*3055Sdanmcd (void) printf("RIPv2"); 1287*3055Sdanmcd break; 1288*3055Sdanmcd case SADB_SATYPE_MIP: 1289*3055Sdanmcd (void) printf(gettext("Mobile IP")); 1290*3055Sdanmcd break; 1291*3055Sdanmcd default: 1292*3055Sdanmcd (void) printf(gettext("<unknown %u>"), samsg->sadb_msg_satype); 1293*3055Sdanmcd break; 1294*3055Sdanmcd } 1295*3055Sdanmcd 1296*3055Sdanmcd (void) printf(".\n"); 1297*3055Sdanmcd 1298*3055Sdanmcd if (samsg->sadb_msg_errno != 0) { 1299*3055Sdanmcd (void) printf(gettext("Error %s from PF_KEY.\n"), 1300*3055Sdanmcd strerror(samsg->sadb_msg_errno)); 1301*3055Sdanmcd print_diagnostic(stdout, samsg->sadb_x_msg_diagnostic); 1302*3055Sdanmcd } 1303*3055Sdanmcd 1304*3055Sdanmcd (void) printf(gettext("Message length %u bytes, seq=%u, pid=%u.\n"), 1305*3055Sdanmcd SADB_64TO8(samsg->sadb_msg_len), samsg->sadb_msg_seq, 1306*3055Sdanmcd samsg->sadb_msg_pid); 1307*3055Sdanmcd } 1308*3055Sdanmcd 1309*3055Sdanmcd /* 1310*3055Sdanmcd * Print the SA extension for PF_KEY. 1311*3055Sdanmcd */ 1312*3055Sdanmcd void 1313*3055Sdanmcd print_sa(char *prefix, struct sadb_sa *assoc) 1314*3055Sdanmcd { 1315*3055Sdanmcd if (assoc->sadb_sa_len != SADB_8TO64(sizeof (*assoc))) { 1316*3055Sdanmcd warnx(gettext("WARNING: SA info extension length (%u) is bad."), 1317*3055Sdanmcd SADB_64TO8(assoc->sadb_sa_len)); 1318*3055Sdanmcd } 1319*3055Sdanmcd 1320*3055Sdanmcd (void) printf(gettext("%sSADB_ASSOC spi=0x%x, replay=%u, state="), 1321*3055Sdanmcd prefix, ntohl(assoc->sadb_sa_spi), assoc->sadb_sa_replay); 1322*3055Sdanmcd switch (assoc->sadb_sa_state) { 1323*3055Sdanmcd case SADB_SASTATE_LARVAL: 1324*3055Sdanmcd (void) printf(gettext("LARVAL")); 1325*3055Sdanmcd break; 1326*3055Sdanmcd case SADB_SASTATE_MATURE: 1327*3055Sdanmcd (void) printf(gettext("MATURE")); 1328*3055Sdanmcd break; 1329*3055Sdanmcd case SADB_SASTATE_DYING: 1330*3055Sdanmcd (void) printf(gettext("DYING")); 1331*3055Sdanmcd break; 1332*3055Sdanmcd case SADB_SASTATE_DEAD: 1333*3055Sdanmcd (void) printf(gettext("DEAD")); 1334*3055Sdanmcd break; 1335*3055Sdanmcd default: 1336*3055Sdanmcd (void) printf(gettext("<unknown %u>"), assoc->sadb_sa_state); 1337*3055Sdanmcd } 1338*3055Sdanmcd 1339*3055Sdanmcd if (assoc->sadb_sa_auth != SADB_AALG_NONE) { 1340*3055Sdanmcd (void) printf(gettext("\n%sAuthentication algorithm = "), 1341*3055Sdanmcd prefix); 1342*3055Sdanmcd (void) dump_aalg(assoc->sadb_sa_auth, stdout); 1343*3055Sdanmcd } 1344*3055Sdanmcd 1345*3055Sdanmcd if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { 1346*3055Sdanmcd (void) printf(gettext("\n%sEncryption algorithm = "), prefix); 1347*3055Sdanmcd (void) dump_ealg(assoc->sadb_sa_encrypt, stdout); 1348*3055Sdanmcd } 1349*3055Sdanmcd 1350*3055Sdanmcd (void) printf(gettext("\n%sflags=0x%x < "), prefix, 1351*3055Sdanmcd assoc->sadb_sa_flags); 1352*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_SAFLAGS_PFS) 1353*3055Sdanmcd (void) printf("PFS "); 1354*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_SAFLAGS_NOREPLAY) 1355*3055Sdanmcd (void) printf("NOREPLAY "); 1356*3055Sdanmcd 1357*3055Sdanmcd /* BEGIN Solaris-specific flags. */ 1358*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_USED) 1359*3055Sdanmcd (void) printf("X_USED "); 1360*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_UNIQUE) 1361*3055Sdanmcd (void) printf("X_UNIQUE "); 1362*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG1) 1363*3055Sdanmcd (void) printf("X_AALG1 "); 1364*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG2) 1365*3055Sdanmcd (void) printf("X_AALG2 "); 1366*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG1) 1367*3055Sdanmcd (void) printf("X_EALG1 "); 1368*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG2) 1369*3055Sdanmcd (void) printf("X_EALG2 "); 1370*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_LOC) 1371*3055Sdanmcd (void) printf("X_NATT_LOC "); 1372*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_REM) 1373*3055Sdanmcd (void) printf("X_NATT_REM "); 1374*3055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL) 1375*3055Sdanmcd (void) printf("X_TUNNEL "); 1376*3055Sdanmcd /* END Solaris-specific flags. */ 1377*3055Sdanmcd 1378*3055Sdanmcd (void) printf(">\n"); 1379*3055Sdanmcd } 1380*3055Sdanmcd 1381*3055Sdanmcd void 1382*3055Sdanmcd printsatime(int64_t lt, const char *msg, const char *pfx, const char *pfx2, 1383*3055Sdanmcd boolean_t vflag) 1384*3055Sdanmcd { 1385*3055Sdanmcd char tbuf[TBUF_SIZE]; /* For strftime() call. */ 1386*3055Sdanmcd const char *tp = tbuf; 1387*3055Sdanmcd time_t t = lt; 1388*3055Sdanmcd struct tm res; 1389*3055Sdanmcd 1390*3055Sdanmcd if (t != lt) { 1391*3055Sdanmcd if (lt > 0) 1392*3055Sdanmcd t = LONG_MAX; 1393*3055Sdanmcd else 1394*3055Sdanmcd t = LONG_MIN; 1395*3055Sdanmcd } 1396*3055Sdanmcd 1397*3055Sdanmcd if (strftime(tbuf, TBUF_SIZE, NULL, localtime_r(&t, &res)) == 0) 1398*3055Sdanmcd tp = gettext("<time conversion failed>"); 1399*3055Sdanmcd (void) printf(msg, pfx, tp); 1400*3055Sdanmcd if (vflag && (pfx2 != NULL)) 1401*3055Sdanmcd (void) printf(gettext("%s\t(raw time value %llu)\n"), pfx2, lt); 1402*3055Sdanmcd } 1403*3055Sdanmcd 1404*3055Sdanmcd /* 1405*3055Sdanmcd * Print the SA lifetime information. (An SADB_EXT_LIFETIME_* extension.) 1406*3055Sdanmcd */ 1407*3055Sdanmcd void 1408*3055Sdanmcd print_lifetimes(time_t wallclock, struct sadb_lifetime *current, 1409*3055Sdanmcd struct sadb_lifetime *hard, struct sadb_lifetime *soft, boolean_t vflag) 1410*3055Sdanmcd { 1411*3055Sdanmcd int64_t scratch; 1412*3055Sdanmcd char *soft_prefix = gettext("SLT: "); 1413*3055Sdanmcd char *hard_prefix = gettext("HLT: "); 1414*3055Sdanmcd char *current_prefix = gettext("CLT: "); 1415*3055Sdanmcd 1416*3055Sdanmcd if (current != NULL && 1417*3055Sdanmcd current->sadb_lifetime_len != SADB_8TO64(sizeof (*current))) { 1418*3055Sdanmcd warnx(gettext("WARNING: CURRENT lifetime extension length " 1419*3055Sdanmcd "(%u) is bad."), 1420*3055Sdanmcd SADB_64TO8(current->sadb_lifetime_len)); 1421*3055Sdanmcd } 1422*3055Sdanmcd 1423*3055Sdanmcd if (hard != NULL && 1424*3055Sdanmcd hard->sadb_lifetime_len != SADB_8TO64(sizeof (*hard))) { 1425*3055Sdanmcd warnx(gettext("WARNING: HARD lifetime " 1426*3055Sdanmcd "extension length (%u) is bad."), 1427*3055Sdanmcd SADB_64TO8(hard->sadb_lifetime_len)); 1428*3055Sdanmcd } 1429*3055Sdanmcd 1430*3055Sdanmcd if (soft != NULL && 1431*3055Sdanmcd soft->sadb_lifetime_len != SADB_8TO64(sizeof (*soft))) { 1432*3055Sdanmcd warnx(gettext("WARNING: SOFT lifetime " 1433*3055Sdanmcd "extension length (%u) is bad."), 1434*3055Sdanmcd SADB_64TO8(soft->sadb_lifetime_len)); 1435*3055Sdanmcd } 1436*3055Sdanmcd 1437*3055Sdanmcd (void) printf(" LT: Lifetime information\n"); 1438*3055Sdanmcd 1439*3055Sdanmcd if (current != NULL) { 1440*3055Sdanmcd /* Express values as current values. */ 1441*3055Sdanmcd (void) printf(gettext( 1442*3055Sdanmcd "%s%llu bytes protected, %u allocations used.\n"), 1443*3055Sdanmcd current_prefix, current->sadb_lifetime_bytes, 1444*3055Sdanmcd current->sadb_lifetime_allocations); 1445*3055Sdanmcd printsatime(current->sadb_lifetime_addtime, 1446*3055Sdanmcd gettext("%sSA added at time %s\n"), 1447*3055Sdanmcd current_prefix, current_prefix, vflag); 1448*3055Sdanmcd if (current->sadb_lifetime_usetime != 0) { 1449*3055Sdanmcd printsatime(current->sadb_lifetime_usetime, 1450*3055Sdanmcd gettext("%sSA first used at time %s\n"), 1451*3055Sdanmcd current_prefix, current_prefix, vflag); 1452*3055Sdanmcd } 1453*3055Sdanmcd printsatime(wallclock, gettext("%sTime now is %s\n"), 1454*3055Sdanmcd current_prefix, current_prefix, vflag); 1455*3055Sdanmcd } 1456*3055Sdanmcd 1457*3055Sdanmcd if (soft != NULL) { 1458*3055Sdanmcd (void) printf(gettext("%sSoft lifetime information: "), 1459*3055Sdanmcd soft_prefix); 1460*3055Sdanmcd (void) printf(gettext("%llu bytes of lifetime, %u " 1461*3055Sdanmcd "allocations.\n"), soft->sadb_lifetime_bytes, 1462*3055Sdanmcd soft->sadb_lifetime_allocations); 1463*3055Sdanmcd (void) printf(gettext("%s%llu seconds of post-add lifetime.\n"), 1464*3055Sdanmcd soft_prefix, soft->sadb_lifetime_addtime); 1465*3055Sdanmcd (void) printf(gettext("%s%llu seconds of post-use lifetime.\n"), 1466*3055Sdanmcd soft_prefix, soft->sadb_lifetime_usetime); 1467*3055Sdanmcd /* If possible, express values as time remaining. */ 1468*3055Sdanmcd if (current != NULL) { 1469*3055Sdanmcd if (soft->sadb_lifetime_bytes != 0) 1470*3055Sdanmcd (void) printf(gettext( 1471*3055Sdanmcd "%s%llu more bytes can be protected.\n"), 1472*3055Sdanmcd soft_prefix, 1473*3055Sdanmcd (soft->sadb_lifetime_bytes > 1474*3055Sdanmcd current->sadb_lifetime_bytes) ? 1475*3055Sdanmcd (soft->sadb_lifetime_bytes - 1476*3055Sdanmcd current->sadb_lifetime_bytes) : (0)); 1477*3055Sdanmcd if (soft->sadb_lifetime_addtime != 0 || 1478*3055Sdanmcd (soft->sadb_lifetime_usetime != 0 && 1479*3055Sdanmcd current->sadb_lifetime_usetime != 0)) { 1480*3055Sdanmcd int64_t adddelta, usedelta; 1481*3055Sdanmcd 1482*3055Sdanmcd if (soft->sadb_lifetime_addtime != 0) { 1483*3055Sdanmcd adddelta = 1484*3055Sdanmcd current->sadb_lifetime_addtime + 1485*3055Sdanmcd soft->sadb_lifetime_addtime - 1486*3055Sdanmcd wallclock; 1487*3055Sdanmcd } else { 1488*3055Sdanmcd adddelta = TIME_MAX; 1489*3055Sdanmcd } 1490*3055Sdanmcd 1491*3055Sdanmcd if (soft->sadb_lifetime_usetime != 0 && 1492*3055Sdanmcd current->sadb_lifetime_usetime != 0) { 1493*3055Sdanmcd usedelta = 1494*3055Sdanmcd current->sadb_lifetime_usetime + 1495*3055Sdanmcd soft->sadb_lifetime_usetime - 1496*3055Sdanmcd wallclock; 1497*3055Sdanmcd } else { 1498*3055Sdanmcd usedelta = TIME_MAX; 1499*3055Sdanmcd } 1500*3055Sdanmcd (void) printf("%s", soft_prefix); 1501*3055Sdanmcd scratch = MIN(adddelta, usedelta); 1502*3055Sdanmcd if (scratch >= 0) { 1503*3055Sdanmcd (void) printf(gettext("Soft expiration " 1504*3055Sdanmcd "occurs in %lld seconds, "), 1505*3055Sdanmcd scratch); 1506*3055Sdanmcd } else { 1507*3055Sdanmcd (void) printf(gettext( 1508*3055Sdanmcd "Soft expiration occurred ")); 1509*3055Sdanmcd } 1510*3055Sdanmcd scratch += wallclock; 1511*3055Sdanmcd printsatime(scratch, gettext("%sat %s.\n"), "", 1512*3055Sdanmcd soft_prefix, vflag); 1513*3055Sdanmcd } 1514*3055Sdanmcd } 1515*3055Sdanmcd } 1516*3055Sdanmcd 1517*3055Sdanmcd if (hard != NULL) { 1518*3055Sdanmcd (void) printf(gettext("%sHard lifetime information: "), 1519*3055Sdanmcd hard_prefix); 1520*3055Sdanmcd (void) printf(gettext("%llu bytes of lifetime, " 1521*3055Sdanmcd "%u allocations.\n"), hard->sadb_lifetime_bytes, 1522*3055Sdanmcd hard->sadb_lifetime_allocations); 1523*3055Sdanmcd (void) printf(gettext("%s%llu seconds of post-add lifetime.\n"), 1524*3055Sdanmcd hard_prefix, hard->sadb_lifetime_addtime); 1525*3055Sdanmcd (void) printf(gettext("%s%llu seconds of post-use lifetime.\n"), 1526*3055Sdanmcd hard_prefix, hard->sadb_lifetime_usetime); 1527*3055Sdanmcd /* If possible, express values as time remaining. */ 1528*3055Sdanmcd if (current != NULL) { 1529*3055Sdanmcd if (hard->sadb_lifetime_bytes != 0) 1530*3055Sdanmcd (void) printf(gettext( 1531*3055Sdanmcd "%s%llu more bytes can be protected.\n"), 1532*3055Sdanmcd hard_prefix, 1533*3055Sdanmcd (hard->sadb_lifetime_bytes > 1534*3055Sdanmcd current->sadb_lifetime_bytes) ? 1535*3055Sdanmcd (hard->sadb_lifetime_bytes - 1536*3055Sdanmcd current->sadb_lifetime_bytes) : (0)); 1537*3055Sdanmcd if (hard->sadb_lifetime_addtime != 0 || 1538*3055Sdanmcd (hard->sadb_lifetime_usetime != 0 && 1539*3055Sdanmcd current->sadb_lifetime_usetime != 0)) { 1540*3055Sdanmcd int64_t adddelta, usedelta; 1541*3055Sdanmcd 1542*3055Sdanmcd if (hard->sadb_lifetime_addtime != 0) { 1543*3055Sdanmcd adddelta = 1544*3055Sdanmcd current->sadb_lifetime_addtime + 1545*3055Sdanmcd hard->sadb_lifetime_addtime - 1546*3055Sdanmcd wallclock; 1547*3055Sdanmcd } else { 1548*3055Sdanmcd adddelta = TIME_MAX; 1549*3055Sdanmcd } 1550*3055Sdanmcd 1551*3055Sdanmcd if (hard->sadb_lifetime_usetime != 0 && 1552*3055Sdanmcd current->sadb_lifetime_usetime != 0) { 1553*3055Sdanmcd usedelta = 1554*3055Sdanmcd current->sadb_lifetime_usetime + 1555*3055Sdanmcd hard->sadb_lifetime_usetime - 1556*3055Sdanmcd wallclock; 1557*3055Sdanmcd } else { 1558*3055Sdanmcd usedelta = TIME_MAX; 1559*3055Sdanmcd } 1560*3055Sdanmcd (void) printf("%s", hard_prefix); 1561*3055Sdanmcd scratch = MIN(adddelta, usedelta); 1562*3055Sdanmcd if (scratch >= 0) { 1563*3055Sdanmcd (void) printf(gettext("Hard expiration " 1564*3055Sdanmcd "occurs in %lld seconds, "), 1565*3055Sdanmcd scratch); 1566*3055Sdanmcd } else { 1567*3055Sdanmcd (void) printf(gettext( 1568*3055Sdanmcd "Hard expiration occured ")); 1569*3055Sdanmcd } 1570*3055Sdanmcd scratch += wallclock; 1571*3055Sdanmcd printsatime(scratch, gettext("%sat %s.\n"), "", 1572*3055Sdanmcd hard_prefix, vflag); 1573*3055Sdanmcd } 1574*3055Sdanmcd } 1575*3055Sdanmcd } 1576*3055Sdanmcd } 1577*3055Sdanmcd 1578*3055Sdanmcd /* 1579*3055Sdanmcd * Print an SADB_EXT_ADDRESS_* extension. 1580*3055Sdanmcd */ 1581*3055Sdanmcd void 1582*3055Sdanmcd print_address(char *prefix, struct sadb_address *addr) 1583*3055Sdanmcd { 1584*3055Sdanmcd struct protoent *pe; 1585*3055Sdanmcd 1586*3055Sdanmcd (void) printf("%s", prefix); 1587*3055Sdanmcd switch (addr->sadb_address_exttype) { 1588*3055Sdanmcd case SADB_EXT_ADDRESS_SRC: 1589*3055Sdanmcd (void) printf(gettext("Source address ")); 1590*3055Sdanmcd break; 1591*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 1592*3055Sdanmcd (void) printf(gettext("Inner source address ")); 1593*3055Sdanmcd break; 1594*3055Sdanmcd case SADB_EXT_ADDRESS_DST: 1595*3055Sdanmcd (void) printf(gettext("Destination address ")); 1596*3055Sdanmcd break; 1597*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 1598*3055Sdanmcd (void) printf(gettext("Inner destination address ")); 1599*3055Sdanmcd break; 1600*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 1601*3055Sdanmcd (void) printf(gettext("NATT local address ")); 1602*3055Sdanmcd break; 1603*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 1604*3055Sdanmcd (void) printf(gettext("NATT remote address ")); 1605*3055Sdanmcd break; 1606*3055Sdanmcd } 1607*3055Sdanmcd 1608*3055Sdanmcd (void) printf(gettext("(proto=%d"), addr->sadb_address_proto); 1609*3055Sdanmcd if (!nflag) { 1610*3055Sdanmcd if (addr->sadb_address_proto == 0) { 1611*3055Sdanmcd (void) printf(gettext("/<unspecified>")); 1612*3055Sdanmcd } else if ((pe = getprotobynumber(addr->sadb_address_proto)) 1613*3055Sdanmcd != NULL) { 1614*3055Sdanmcd (void) printf("/%s", pe->p_name); 1615*3055Sdanmcd } else { 1616*3055Sdanmcd (void) printf(gettext("/<unknown>")); 1617*3055Sdanmcd } 1618*3055Sdanmcd } 1619*3055Sdanmcd (void) printf(gettext(")\n%s"), prefix); 1620*3055Sdanmcd (void) dump_sockaddr((struct sockaddr *)(addr + 1), 1621*3055Sdanmcd addr->sadb_address_prefixlen, B_FALSE, stdout); 1622*3055Sdanmcd } 1623*3055Sdanmcd 1624*3055Sdanmcd /* 1625*3055Sdanmcd * Print an SADB_EXT_KEY extension. 1626*3055Sdanmcd */ 1627*3055Sdanmcd void 1628*3055Sdanmcd print_key(char *prefix, struct sadb_key *key) 1629*3055Sdanmcd { 1630*3055Sdanmcd (void) printf("%s", prefix); 1631*3055Sdanmcd 1632*3055Sdanmcd switch (key->sadb_key_exttype) { 1633*3055Sdanmcd case SADB_EXT_KEY_AUTH: 1634*3055Sdanmcd (void) printf(gettext("Authentication")); 1635*3055Sdanmcd break; 1636*3055Sdanmcd case SADB_EXT_KEY_ENCRYPT: 1637*3055Sdanmcd (void) printf(gettext("Encryption")); 1638*3055Sdanmcd break; 1639*3055Sdanmcd } 1640*3055Sdanmcd 1641*3055Sdanmcd (void) printf(gettext(" key.\n%s"), prefix); 1642*3055Sdanmcd (void) dump_key((uint8_t *)(key + 1), key->sadb_key_bits, stdout); 1643*3055Sdanmcd (void) putchar('\n'); 1644*3055Sdanmcd } 1645*3055Sdanmcd 1646*3055Sdanmcd /* 1647*3055Sdanmcd * Print an SADB_EXT_IDENTITY_* extension. 1648*3055Sdanmcd */ 1649*3055Sdanmcd void 1650*3055Sdanmcd print_ident(char *prefix, struct sadb_ident *id) 1651*3055Sdanmcd { 1652*3055Sdanmcd boolean_t canprint = B_TRUE; 1653*3055Sdanmcd 1654*3055Sdanmcd (void) printf("%s", prefix); 1655*3055Sdanmcd switch (id->sadb_ident_exttype) { 1656*3055Sdanmcd case SADB_EXT_IDENTITY_SRC: 1657*3055Sdanmcd (void) printf(gettext("Source")); 1658*3055Sdanmcd break; 1659*3055Sdanmcd case SADB_EXT_IDENTITY_DST: 1660*3055Sdanmcd (void) printf(gettext("Destination")); 1661*3055Sdanmcd break; 1662*3055Sdanmcd } 1663*3055Sdanmcd 1664*3055Sdanmcd (void) printf(gettext(" identity, uid=%d, type "), id->sadb_ident_id); 1665*3055Sdanmcd canprint = dump_sadb_idtype(id->sadb_ident_type, stdout, NULL); 1666*3055Sdanmcd (void) printf("\n%s", prefix); 1667*3055Sdanmcd if (canprint) 1668*3055Sdanmcd (void) printf("%s\n", (char *)(id + 1)); 1669*3055Sdanmcd else 1670*3055Sdanmcd (void) printf(gettext("<cannot print>\n")); 1671*3055Sdanmcd } 1672*3055Sdanmcd 1673*3055Sdanmcd /* 1674*3055Sdanmcd * Print an SADB_SENSITIVITY extension. 1675*3055Sdanmcd */ 1676*3055Sdanmcd void 1677*3055Sdanmcd print_sens(char *prefix, struct sadb_sens *sens) 1678*3055Sdanmcd { 1679*3055Sdanmcd uint64_t *bitmap = (uint64_t *)(sens + 1); 1680*3055Sdanmcd int i; 1681*3055Sdanmcd 1682*3055Sdanmcd (void) printf( 1683*3055Sdanmcd gettext("%sSensitivity DPD %d, sens level=%d, integ level=%d\n"), 1684*3055Sdanmcd prefix, sens->sadb_sens_dpd, sens->sadb_sens_sens_level, 1685*3055Sdanmcd sens->sadb_sens_integ_level); 1686*3055Sdanmcd for (i = 0; sens->sadb_sens_sens_len-- > 0; i++, bitmap++) 1687*3055Sdanmcd (void) printf( 1688*3055Sdanmcd gettext("%s Sensitivity BM extended word %d 0x%llx\n"), 1689*3055Sdanmcd i, *bitmap); 1690*3055Sdanmcd for (i = 0; sens->sadb_sens_integ_len-- > 0; i++, bitmap++) 1691*3055Sdanmcd (void) printf( 1692*3055Sdanmcd gettext("%s Integrity BM extended word %d 0x%llx\n"), 1693*3055Sdanmcd i, *bitmap); 1694*3055Sdanmcd } 1695*3055Sdanmcd 1696*3055Sdanmcd /* 1697*3055Sdanmcd * Print an SADB_EXT_PROPOSAL extension. 1698*3055Sdanmcd */ 1699*3055Sdanmcd void 1700*3055Sdanmcd print_prop(char *prefix, struct sadb_prop *prop) 1701*3055Sdanmcd { 1702*3055Sdanmcd struct sadb_comb *combs; 1703*3055Sdanmcd int i, numcombs; 1704*3055Sdanmcd 1705*3055Sdanmcd (void) printf(gettext("%sProposal, replay counter = %u.\n"), prefix, 1706*3055Sdanmcd prop->sadb_prop_replay); 1707*3055Sdanmcd 1708*3055Sdanmcd numcombs = prop->sadb_prop_len - SADB_8TO64(sizeof (*prop)); 1709*3055Sdanmcd numcombs /= SADB_8TO64(sizeof (*combs)); 1710*3055Sdanmcd 1711*3055Sdanmcd combs = (struct sadb_comb *)(prop + 1); 1712*3055Sdanmcd 1713*3055Sdanmcd for (i = 0; i < numcombs; i++) { 1714*3055Sdanmcd (void) printf(gettext("%s Combination #%u "), prefix, i + 1); 1715*3055Sdanmcd if (combs[i].sadb_comb_auth != SADB_AALG_NONE) { 1716*3055Sdanmcd (void) printf(gettext("Authentication = ")); 1717*3055Sdanmcd (void) dump_aalg(combs[i].sadb_comb_auth, stdout); 1718*3055Sdanmcd (void) printf(gettext(" minbits=%u, maxbits=%u.\n%s "), 1719*3055Sdanmcd combs[i].sadb_comb_auth_minbits, 1720*3055Sdanmcd combs[i].sadb_comb_auth_maxbits, prefix); 1721*3055Sdanmcd } 1722*3055Sdanmcd 1723*3055Sdanmcd if (combs[i].sadb_comb_encrypt != SADB_EALG_NONE) { 1724*3055Sdanmcd (void) printf(gettext("Encryption = ")); 1725*3055Sdanmcd (void) dump_ealg(combs[i].sadb_comb_encrypt, stdout); 1726*3055Sdanmcd (void) printf(gettext(" minbits=%u, maxbits=%u.\n%s "), 1727*3055Sdanmcd combs[i].sadb_comb_encrypt_minbits, 1728*3055Sdanmcd combs[i].sadb_comb_encrypt_maxbits, prefix); 1729*3055Sdanmcd } 1730*3055Sdanmcd 1731*3055Sdanmcd (void) printf(gettext("HARD: ")); 1732*3055Sdanmcd if (combs[i].sadb_comb_hard_allocations) 1733*3055Sdanmcd (void) printf(gettext("alloc=%u "), 1734*3055Sdanmcd combs[i].sadb_comb_hard_allocations); 1735*3055Sdanmcd if (combs[i].sadb_comb_hard_bytes) 1736*3055Sdanmcd (void) printf(gettext("bytes=%llu "), 1737*3055Sdanmcd combs[i].sadb_comb_hard_bytes); 1738*3055Sdanmcd if (combs[i].sadb_comb_hard_addtime) 1739*3055Sdanmcd (void) printf(gettext("post-add secs=%llu "), 1740*3055Sdanmcd combs[i].sadb_comb_hard_addtime); 1741*3055Sdanmcd if (combs[i].sadb_comb_hard_usetime) 1742*3055Sdanmcd (void) printf(gettext("post-use secs=%llu"), 1743*3055Sdanmcd combs[i].sadb_comb_hard_usetime); 1744*3055Sdanmcd 1745*3055Sdanmcd (void) printf(gettext("\n%s SOFT: "), prefix); 1746*3055Sdanmcd if (combs[i].sadb_comb_soft_allocations) 1747*3055Sdanmcd (void) printf(gettext("alloc=%u "), 1748*3055Sdanmcd combs[i].sadb_comb_soft_allocations); 1749*3055Sdanmcd if (combs[i].sadb_comb_soft_bytes) 1750*3055Sdanmcd (void) printf(gettext("bytes=%llu "), 1751*3055Sdanmcd combs[i].sadb_comb_soft_bytes); 1752*3055Sdanmcd if (combs[i].sadb_comb_soft_addtime) 1753*3055Sdanmcd (void) printf(gettext("post-add secs=%llu "), 1754*3055Sdanmcd combs[i].sadb_comb_soft_addtime); 1755*3055Sdanmcd if (combs[i].sadb_comb_soft_usetime) 1756*3055Sdanmcd (void) printf(gettext("post-use secs=%llu"), 1757*3055Sdanmcd combs[i].sadb_comb_soft_usetime); 1758*3055Sdanmcd (void) putchar('\n'); 1759*3055Sdanmcd } 1760*3055Sdanmcd } 1761*3055Sdanmcd 1762*3055Sdanmcd /* 1763*3055Sdanmcd * Print an extended proposal (SADB_X_EXT_EPROP). 1764*3055Sdanmcd */ 1765*3055Sdanmcd void 1766*3055Sdanmcd print_eprop(char *prefix, struct sadb_prop *eprop) 1767*3055Sdanmcd { 1768*3055Sdanmcd uint64_t *sofar; 1769*3055Sdanmcd struct sadb_x_ecomb *ecomb; 1770*3055Sdanmcd struct sadb_x_algdesc *algdesc; 1771*3055Sdanmcd int i, j; 1772*3055Sdanmcd 1773*3055Sdanmcd (void) printf(gettext("%sExtended Proposal, replay counter = %u, "), 1774*3055Sdanmcd prefix, eprop->sadb_prop_replay); 1775*3055Sdanmcd (void) printf(gettext("number of combinations = %u.\n"), 1776*3055Sdanmcd eprop->sadb_x_prop_numecombs); 1777*3055Sdanmcd 1778*3055Sdanmcd sofar = (uint64_t *)(eprop + 1); 1779*3055Sdanmcd ecomb = (struct sadb_x_ecomb *)sofar; 1780*3055Sdanmcd 1781*3055Sdanmcd for (i = 0; i < eprop->sadb_x_prop_numecombs; ) { 1782*3055Sdanmcd (void) printf(gettext("%s Extended combination #%u:\n"), 1783*3055Sdanmcd prefix, ++i); 1784*3055Sdanmcd 1785*3055Sdanmcd (void) printf(gettext("%s HARD: "), prefix); 1786*3055Sdanmcd (void) printf(gettext("alloc=%u, "), 1787*3055Sdanmcd ecomb->sadb_x_ecomb_hard_allocations); 1788*3055Sdanmcd (void) printf(gettext("bytes=%llu, "), 1789*3055Sdanmcd ecomb->sadb_x_ecomb_hard_bytes); 1790*3055Sdanmcd (void) printf(gettext("post-add secs=%llu, "), 1791*3055Sdanmcd ecomb->sadb_x_ecomb_hard_addtime); 1792*3055Sdanmcd (void) printf(gettext("post-use secs=%llu\n"), 1793*3055Sdanmcd ecomb->sadb_x_ecomb_hard_usetime); 1794*3055Sdanmcd 1795*3055Sdanmcd (void) printf(gettext("%s SOFT: "), prefix); 1796*3055Sdanmcd (void) printf(gettext("alloc=%u, "), 1797*3055Sdanmcd ecomb->sadb_x_ecomb_soft_allocations); 1798*3055Sdanmcd (void) printf(gettext("bytes=%llu, "), 1799*3055Sdanmcd ecomb->sadb_x_ecomb_soft_bytes); 1800*3055Sdanmcd (void) printf(gettext("post-add secs=%llu, "), 1801*3055Sdanmcd ecomb->sadb_x_ecomb_soft_addtime); 1802*3055Sdanmcd (void) printf(gettext("post-use secs=%llu\n"), 1803*3055Sdanmcd ecomb->sadb_x_ecomb_soft_usetime); 1804*3055Sdanmcd 1805*3055Sdanmcd sofar = (uint64_t *)(ecomb + 1); 1806*3055Sdanmcd algdesc = (struct sadb_x_algdesc *)sofar; 1807*3055Sdanmcd 1808*3055Sdanmcd for (j = 0; j < ecomb->sadb_x_ecomb_numalgs; ) { 1809*3055Sdanmcd (void) printf(gettext("%s Alg #%u "), prefix, ++j); 1810*3055Sdanmcd switch (algdesc->sadb_x_algdesc_satype) { 1811*3055Sdanmcd case SADB_SATYPE_ESP: 1812*3055Sdanmcd (void) printf(gettext("for ESP ")); 1813*3055Sdanmcd break; 1814*3055Sdanmcd case SADB_SATYPE_AH: 1815*3055Sdanmcd (void) printf(gettext("for AH ")); 1816*3055Sdanmcd break; 1817*3055Sdanmcd default: 1818*3055Sdanmcd (void) printf(gettext("for satype=%d "), 1819*3055Sdanmcd algdesc->sadb_x_algdesc_satype); 1820*3055Sdanmcd } 1821*3055Sdanmcd switch (algdesc->sadb_x_algdesc_algtype) { 1822*3055Sdanmcd case SADB_X_ALGTYPE_CRYPT: 1823*3055Sdanmcd (void) printf(gettext("Encryption = ")); 1824*3055Sdanmcd (void) dump_ealg(algdesc->sadb_x_algdesc_alg, 1825*3055Sdanmcd stdout); 1826*3055Sdanmcd break; 1827*3055Sdanmcd case SADB_X_ALGTYPE_AUTH: 1828*3055Sdanmcd (void) printf(gettext("Authentication = ")); 1829*3055Sdanmcd (void) dump_aalg(algdesc->sadb_x_algdesc_alg, 1830*3055Sdanmcd stdout); 1831*3055Sdanmcd break; 1832*3055Sdanmcd default: 1833*3055Sdanmcd (void) printf(gettext("algtype(%d) = alg(%d)"), 1834*3055Sdanmcd algdesc->sadb_x_algdesc_algtype, 1835*3055Sdanmcd algdesc->sadb_x_algdesc_alg); 1836*3055Sdanmcd break; 1837*3055Sdanmcd } 1838*3055Sdanmcd 1839*3055Sdanmcd (void) printf(gettext(" minbits=%u, maxbits=%u.\n"), 1840*3055Sdanmcd algdesc->sadb_x_algdesc_minbits, 1841*3055Sdanmcd algdesc->sadb_x_algdesc_maxbits); 1842*3055Sdanmcd 1843*3055Sdanmcd sofar = (uint64_t *)(++algdesc); 1844*3055Sdanmcd } 1845*3055Sdanmcd ecomb = (struct sadb_x_ecomb *)sofar; 1846*3055Sdanmcd } 1847*3055Sdanmcd } 1848*3055Sdanmcd 1849*3055Sdanmcd /* 1850*3055Sdanmcd * Print an SADB_EXT_SUPPORTED extension. 1851*3055Sdanmcd */ 1852*3055Sdanmcd void 1853*3055Sdanmcd print_supp(char *prefix, struct sadb_supported *supp) 1854*3055Sdanmcd { 1855*3055Sdanmcd struct sadb_alg *algs; 1856*3055Sdanmcd int i, numalgs; 1857*3055Sdanmcd 1858*3055Sdanmcd (void) printf(gettext("%sSupported "), prefix); 1859*3055Sdanmcd switch (supp->sadb_supported_exttype) { 1860*3055Sdanmcd case SADB_EXT_SUPPORTED_AUTH: 1861*3055Sdanmcd (void) printf(gettext("authentication")); 1862*3055Sdanmcd break; 1863*3055Sdanmcd case SADB_EXT_SUPPORTED_ENCRYPT: 1864*3055Sdanmcd (void) printf(gettext("encryption")); 1865*3055Sdanmcd break; 1866*3055Sdanmcd } 1867*3055Sdanmcd (void) printf(gettext(" algorithms.\n")); 1868*3055Sdanmcd 1869*3055Sdanmcd algs = (struct sadb_alg *)(supp + 1); 1870*3055Sdanmcd numalgs = supp->sadb_supported_len - SADB_8TO64(sizeof (*supp)); 1871*3055Sdanmcd numalgs /= SADB_8TO64(sizeof (*algs)); 1872*3055Sdanmcd for (i = 0; i < numalgs; i++) { 1873*3055Sdanmcd (void) printf("%s", prefix); 1874*3055Sdanmcd switch (supp->sadb_supported_exttype) { 1875*3055Sdanmcd case SADB_EXT_SUPPORTED_AUTH: 1876*3055Sdanmcd (void) dump_aalg(algs[i].sadb_alg_id, stdout); 1877*3055Sdanmcd break; 1878*3055Sdanmcd case SADB_EXT_SUPPORTED_ENCRYPT: 1879*3055Sdanmcd (void) dump_ealg(algs[i].sadb_alg_id, stdout); 1880*3055Sdanmcd break; 1881*3055Sdanmcd } 1882*3055Sdanmcd (void) printf(gettext(" minbits=%u, maxbits=%u, ivlen=%u.\n"), 1883*3055Sdanmcd algs[i].sadb_alg_minbits, algs[i].sadb_alg_maxbits, 1884*3055Sdanmcd algs[i].sadb_alg_ivlen); 1885*3055Sdanmcd } 1886*3055Sdanmcd } 1887*3055Sdanmcd 1888*3055Sdanmcd /* 1889*3055Sdanmcd * Print an SADB_EXT_SPIRANGE extension. 1890*3055Sdanmcd */ 1891*3055Sdanmcd void 1892*3055Sdanmcd print_spirange(char *prefix, struct sadb_spirange *range) 1893*3055Sdanmcd { 1894*3055Sdanmcd (void) printf(gettext("%sSPI Range, min=0x%x, max=0x%x\n"), prefix, 1895*3055Sdanmcd htonl(range->sadb_spirange_min), 1896*3055Sdanmcd htonl(range->sadb_spirange_max)); 1897*3055Sdanmcd } 1898*3055Sdanmcd 1899*3055Sdanmcd /* 1900*3055Sdanmcd * Print an SADB_X_EXT_KM_COOKIE extension. 1901*3055Sdanmcd */ 1902*3055Sdanmcd 1903*3055Sdanmcd void 1904*3055Sdanmcd print_kmc(char *prefix, struct sadb_x_kmc *kmc) 1905*3055Sdanmcd { 1906*3055Sdanmcd char *cookie_label; 1907*3055Sdanmcd 1908*3055Sdanmcd if ((cookie_label = kmc_lookup_by_cookie(kmc->sadb_x_kmc_cookie)) == 1909*3055Sdanmcd NULL) 1910*3055Sdanmcd cookie_label = gettext("<Label not found.>"); 1911*3055Sdanmcd 1912*3055Sdanmcd (void) printf(gettext("%sProtocol %u, cookie=\"%s\" (%u)\n"), prefix, 1913*3055Sdanmcd kmc->sadb_x_kmc_proto, cookie_label, kmc->sadb_x_kmc_cookie); 1914*3055Sdanmcd } 1915*3055Sdanmcd 1916*3055Sdanmcd /* 1917*3055Sdanmcd * Take a PF_KEY message pointed to buffer and print it. Useful for DUMP 1918*3055Sdanmcd * and GET. 1919*3055Sdanmcd */ 1920*3055Sdanmcd void 1921*3055Sdanmcd print_samsg(uint64_t *buffer, boolean_t want_timestamp, boolean_t vflag) 1922*3055Sdanmcd { 1923*3055Sdanmcd uint64_t *current; 1924*3055Sdanmcd struct sadb_msg *samsg = (struct sadb_msg *)buffer; 1925*3055Sdanmcd struct sadb_ext *ext; 1926*3055Sdanmcd struct sadb_lifetime *currentlt = NULL, *hardlt = NULL, *softlt = NULL; 1927*3055Sdanmcd int i; 1928*3055Sdanmcd time_t wallclock; 1929*3055Sdanmcd 1930*3055Sdanmcd (void) time(&wallclock); 1931*3055Sdanmcd 1932*3055Sdanmcd print_sadb_msg(samsg, want_timestamp ? wallclock : 0, vflag); 1933*3055Sdanmcd current = (uint64_t *)(samsg + 1); 1934*3055Sdanmcd while (current - buffer < samsg->sadb_msg_len) { 1935*3055Sdanmcd int lenbytes; 1936*3055Sdanmcd 1937*3055Sdanmcd ext = (struct sadb_ext *)current; 1938*3055Sdanmcd lenbytes = SADB_64TO8(ext->sadb_ext_len); 1939*3055Sdanmcd switch (ext->sadb_ext_type) { 1940*3055Sdanmcd case SADB_EXT_SA: 1941*3055Sdanmcd print_sa(gettext("SA: "), (struct sadb_sa *)current); 1942*3055Sdanmcd break; 1943*3055Sdanmcd /* 1944*3055Sdanmcd * Pluck out lifetimes and print them at the end. This is 1945*3055Sdanmcd * to show relative lifetimes. 1946*3055Sdanmcd */ 1947*3055Sdanmcd case SADB_EXT_LIFETIME_CURRENT: 1948*3055Sdanmcd currentlt = (struct sadb_lifetime *)current; 1949*3055Sdanmcd break; 1950*3055Sdanmcd case SADB_EXT_LIFETIME_HARD: 1951*3055Sdanmcd hardlt = (struct sadb_lifetime *)current; 1952*3055Sdanmcd break; 1953*3055Sdanmcd case SADB_EXT_LIFETIME_SOFT: 1954*3055Sdanmcd softlt = (struct sadb_lifetime *)current; 1955*3055Sdanmcd break; 1956*3055Sdanmcd 1957*3055Sdanmcd case SADB_EXT_ADDRESS_SRC: 1958*3055Sdanmcd print_address(gettext("SRC: "), 1959*3055Sdanmcd (struct sadb_address *)current); 1960*3055Sdanmcd break; 1961*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 1962*3055Sdanmcd print_address(gettext("INS: "), 1963*3055Sdanmcd (struct sadb_address *)current); 1964*3055Sdanmcd break; 1965*3055Sdanmcd case SADB_EXT_ADDRESS_DST: 1966*3055Sdanmcd print_address(gettext("DST: "), 1967*3055Sdanmcd (struct sadb_address *)current); 1968*3055Sdanmcd break; 1969*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 1970*3055Sdanmcd print_address(gettext("IND: "), 1971*3055Sdanmcd (struct sadb_address *)current); 1972*3055Sdanmcd break; 1973*3055Sdanmcd case SADB_EXT_KEY_AUTH: 1974*3055Sdanmcd print_key(gettext("AKY: "), (struct sadb_key *)current); 1975*3055Sdanmcd break; 1976*3055Sdanmcd case SADB_EXT_KEY_ENCRYPT: 1977*3055Sdanmcd print_key(gettext("EKY: "), (struct sadb_key *)current); 1978*3055Sdanmcd break; 1979*3055Sdanmcd case SADB_EXT_IDENTITY_SRC: 1980*3055Sdanmcd print_ident(gettext("SID: "), 1981*3055Sdanmcd (struct sadb_ident *)current); 1982*3055Sdanmcd break; 1983*3055Sdanmcd case SADB_EXT_IDENTITY_DST: 1984*3055Sdanmcd print_ident(gettext("DID: "), 1985*3055Sdanmcd (struct sadb_ident *)current); 1986*3055Sdanmcd break; 1987*3055Sdanmcd case SADB_EXT_SENSITIVITY: 1988*3055Sdanmcd print_sens(gettext("SNS: "), 1989*3055Sdanmcd (struct sadb_sens *)current); 1990*3055Sdanmcd break; 1991*3055Sdanmcd case SADB_EXT_PROPOSAL: 1992*3055Sdanmcd print_prop(gettext("PRP: "), 1993*3055Sdanmcd (struct sadb_prop *)current); 1994*3055Sdanmcd break; 1995*3055Sdanmcd case SADB_EXT_SUPPORTED_AUTH: 1996*3055Sdanmcd print_supp(gettext("SUA: "), 1997*3055Sdanmcd (struct sadb_supported *)current); 1998*3055Sdanmcd break; 1999*3055Sdanmcd case SADB_EXT_SUPPORTED_ENCRYPT: 2000*3055Sdanmcd print_supp(gettext("SUE: "), 2001*3055Sdanmcd (struct sadb_supported *)current); 2002*3055Sdanmcd break; 2003*3055Sdanmcd case SADB_EXT_SPIRANGE: 2004*3055Sdanmcd print_spirange(gettext("SPR: "), 2005*3055Sdanmcd (struct sadb_spirange *)current); 2006*3055Sdanmcd break; 2007*3055Sdanmcd case SADB_X_EXT_EPROP: 2008*3055Sdanmcd print_eprop(gettext("EPR: "), 2009*3055Sdanmcd (struct sadb_prop *)current); 2010*3055Sdanmcd break; 2011*3055Sdanmcd case SADB_X_EXT_KM_COOKIE: 2012*3055Sdanmcd print_kmc(gettext("KMC: "), 2013*3055Sdanmcd (struct sadb_x_kmc *)current); 2014*3055Sdanmcd break; 2015*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 2016*3055Sdanmcd print_address(gettext("NRM: "), 2017*3055Sdanmcd (struct sadb_address *)current); 2018*3055Sdanmcd break; 2019*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 2020*3055Sdanmcd print_address(gettext("NLC: "), 2021*3055Sdanmcd (struct sadb_address *)current); 2022*3055Sdanmcd break; 2023*3055Sdanmcd default: 2024*3055Sdanmcd (void) printf(gettext( 2025*3055Sdanmcd "UNK: Unknown ext. %d, len %d.\n"), 2026*3055Sdanmcd ext->sadb_ext_type, lenbytes); 2027*3055Sdanmcd for (i = 0; i < ext->sadb_ext_len; i++) 2028*3055Sdanmcd (void) printf(gettext("UNK: 0x%llx\n"), 2029*3055Sdanmcd ((uint64_t *)ext)[i]); 2030*3055Sdanmcd break; 2031*3055Sdanmcd } 2032*3055Sdanmcd current += (lenbytes == 0) ? 2033*3055Sdanmcd SADB_8TO64(sizeof (struct sadb_ext)) : ext->sadb_ext_len; 2034*3055Sdanmcd } 2035*3055Sdanmcd /* 2036*3055Sdanmcd * Print lifetimes NOW. 2037*3055Sdanmcd */ 2038*3055Sdanmcd if (currentlt != NULL || hardlt != NULL || softlt != NULL) 2039*3055Sdanmcd print_lifetimes(wallclock, currentlt, hardlt, softlt, vflag); 2040*3055Sdanmcd 2041*3055Sdanmcd if (current - buffer != samsg->sadb_msg_len) { 2042*3055Sdanmcd warnx(gettext("WARNING: insufficient buffer " 2043*3055Sdanmcd "space or corrupt message.")); 2044*3055Sdanmcd } 2045*3055Sdanmcd 2046*3055Sdanmcd (void) fflush(stdout); /* Make sure our message is out there. */ 2047*3055Sdanmcd } 2048*3055Sdanmcd 2049*3055Sdanmcd /* 2050*3055Sdanmcd * save_XXX functions are used when "saving" the SA tables to either a 2051*3055Sdanmcd * file or standard output. They use the dump_XXX functions where needed, 2052*3055Sdanmcd * but mostly they use the rparseXXX functions. 2053*3055Sdanmcd */ 2054*3055Sdanmcd 2055*3055Sdanmcd /* 2056*3055Sdanmcd * Print save information for a lifetime extension. 2057*3055Sdanmcd * 2058*3055Sdanmcd * NOTE : It saves the lifetime in absolute terms. For example, if you 2059*3055Sdanmcd * had a hard_usetime of 60 seconds, you'll save it as 60 seconds, even though 2060*3055Sdanmcd * there may have been 59 seconds burned off the clock. 2061*3055Sdanmcd */ 2062*3055Sdanmcd boolean_t 2063*3055Sdanmcd save_lifetime(struct sadb_lifetime *lifetime, FILE *ofile) 2064*3055Sdanmcd { 2065*3055Sdanmcd char *prefix; 2066*3055Sdanmcd 2067*3055Sdanmcd prefix = (lifetime->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT) ? 2068*3055Sdanmcd "soft" : "hard"; 2069*3055Sdanmcd 2070*3055Sdanmcd if (putc('\t', ofile) == EOF) 2071*3055Sdanmcd return (B_FALSE); 2072*3055Sdanmcd 2073*3055Sdanmcd if (lifetime->sadb_lifetime_allocations != 0 && fprintf(ofile, 2074*3055Sdanmcd "%s_alloc %u ", prefix, lifetime->sadb_lifetime_allocations) < 0) 2075*3055Sdanmcd return (B_FALSE); 2076*3055Sdanmcd 2077*3055Sdanmcd if (lifetime->sadb_lifetime_bytes != 0 && fprintf(ofile, 2078*3055Sdanmcd "%s_bytes %llu ", prefix, lifetime->sadb_lifetime_bytes) < 0) 2079*3055Sdanmcd return (B_FALSE); 2080*3055Sdanmcd 2081*3055Sdanmcd if (lifetime->sadb_lifetime_addtime != 0 && fprintf(ofile, 2082*3055Sdanmcd "%s_addtime %llu ", prefix, lifetime->sadb_lifetime_addtime) < 0) 2083*3055Sdanmcd return (B_FALSE); 2084*3055Sdanmcd 2085*3055Sdanmcd if (lifetime->sadb_lifetime_usetime != 0 && fprintf(ofile, 2086*3055Sdanmcd "%s_usetime %llu ", prefix, lifetime->sadb_lifetime_usetime) < 0) 2087*3055Sdanmcd return (B_FALSE); 2088*3055Sdanmcd 2089*3055Sdanmcd return (B_TRUE); 2090*3055Sdanmcd } 2091*3055Sdanmcd 2092*3055Sdanmcd /* 2093*3055Sdanmcd * Print save information for an address extension. 2094*3055Sdanmcd */ 2095*3055Sdanmcd boolean_t 2096*3055Sdanmcd save_address(struct sadb_address *addr, FILE *ofile) 2097*3055Sdanmcd { 2098*3055Sdanmcd char *printable_addr, buf[INET6_ADDRSTRLEN]; 2099*3055Sdanmcd const char *prefix, *pprefix; 2100*3055Sdanmcd struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(addr + 1); 2101*3055Sdanmcd struct sockaddr_in *sin = (struct sockaddr_in *)sin6; 2102*3055Sdanmcd int af = sin->sin_family; 2103*3055Sdanmcd 2104*3055Sdanmcd /* 2105*3055Sdanmcd * Address-family reality check. 2106*3055Sdanmcd */ 2107*3055Sdanmcd if (af != AF_INET6 && af != AF_INET) 2108*3055Sdanmcd return (B_FALSE); 2109*3055Sdanmcd 2110*3055Sdanmcd switch (addr->sadb_address_exttype) { 2111*3055Sdanmcd case SADB_EXT_ADDRESS_SRC: 2112*3055Sdanmcd prefix = "src"; 2113*3055Sdanmcd pprefix = "sport"; 2114*3055Sdanmcd break; 2115*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 2116*3055Sdanmcd prefix = "isrc"; 2117*3055Sdanmcd pprefix = "isport"; 2118*3055Sdanmcd break; 2119*3055Sdanmcd case SADB_EXT_ADDRESS_DST: 2120*3055Sdanmcd prefix = "dst"; 2121*3055Sdanmcd pprefix = "dport"; 2122*3055Sdanmcd break; 2123*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 2124*3055Sdanmcd prefix = "idst"; 2125*3055Sdanmcd pprefix = "idport"; 2126*3055Sdanmcd break; 2127*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 2128*3055Sdanmcd prefix = "nat_loc "; 2129*3055Sdanmcd pprefix = "nat_lport"; 2130*3055Sdanmcd break; 2131*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 2132*3055Sdanmcd prefix = "nat_rem "; 2133*3055Sdanmcd pprefix = "nat_rport"; 2134*3055Sdanmcd break; 2135*3055Sdanmcd } 2136*3055Sdanmcd 2137*3055Sdanmcd if (fprintf(ofile, " %s ", prefix) < 0) 2138*3055Sdanmcd return (B_FALSE); 2139*3055Sdanmcd 2140*3055Sdanmcd /* 2141*3055Sdanmcd * Do not do address-to-name translation, given that we live in 2142*3055Sdanmcd * an age of names that explode into many addresses. 2143*3055Sdanmcd */ 2144*3055Sdanmcd printable_addr = (char *)inet_ntop(af, 2145*3055Sdanmcd (af == AF_INET) ? (char *)&sin->sin_addr : (char *)&sin6->sin6_addr, 2146*3055Sdanmcd buf, sizeof (buf)); 2147*3055Sdanmcd if (printable_addr == NULL) 2148*3055Sdanmcd printable_addr = "<inet_ntop() failed>"; 2149*3055Sdanmcd if (fprintf(ofile, "%s", printable_addr) < 0) 2150*3055Sdanmcd return (B_FALSE); 2151*3055Sdanmcd if (addr->sadb_address_prefixlen != 0 && 2152*3055Sdanmcd !((addr->sadb_address_prefixlen == 32 && af == AF_INET) || 2153*3055Sdanmcd (addr->sadb_address_prefixlen == 128 && af == AF_INET6))) { 2154*3055Sdanmcd if (fprintf(ofile, "/%d", addr->sadb_address_prefixlen) < 0) 2155*3055Sdanmcd return (B_FALSE); 2156*3055Sdanmcd } 2157*3055Sdanmcd 2158*3055Sdanmcd /* 2159*3055Sdanmcd * The port is in the same position for struct sockaddr_in and 2160*3055Sdanmcd * struct sockaddr_in6. We exploit that property here. 2161*3055Sdanmcd */ 2162*3055Sdanmcd if ((pprefix != NULL) && (sin->sin_port != 0)) 2163*3055Sdanmcd (void) fprintf(ofile, " %s %d", pprefix, ntohs(sin->sin_port)); 2164*3055Sdanmcd 2165*3055Sdanmcd return (B_TRUE); 2166*3055Sdanmcd } 2167*3055Sdanmcd 2168*3055Sdanmcd /* 2169*3055Sdanmcd * Print save information for a key extension. Returns whether writing 2170*3055Sdanmcd * to the specified output file was successful or not. 2171*3055Sdanmcd */ 2172*3055Sdanmcd boolean_t 2173*3055Sdanmcd save_key(struct sadb_key *key, FILE *ofile) 2174*3055Sdanmcd { 2175*3055Sdanmcd char *prefix; 2176*3055Sdanmcd 2177*3055Sdanmcd if (putc('\t', ofile) == EOF) 2178*3055Sdanmcd return (B_FALSE); 2179*3055Sdanmcd 2180*3055Sdanmcd prefix = (key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ? "auth" : "encr"; 2181*3055Sdanmcd 2182*3055Sdanmcd if (fprintf(ofile, "%skey ", prefix) < 0) 2183*3055Sdanmcd return (B_FALSE); 2184*3055Sdanmcd 2185*3055Sdanmcd if (dump_key((uint8_t *)(key + 1), key->sadb_key_bits, ofile) == -1) 2186*3055Sdanmcd return (B_FALSE); 2187*3055Sdanmcd 2188*3055Sdanmcd return (B_TRUE); 2189*3055Sdanmcd } 2190*3055Sdanmcd 2191*3055Sdanmcd /* 2192*3055Sdanmcd * Print save information for an identity extension. 2193*3055Sdanmcd */ 2194*3055Sdanmcd boolean_t 2195*3055Sdanmcd save_ident(struct sadb_ident *ident, FILE *ofile) 2196*3055Sdanmcd { 2197*3055Sdanmcd char *prefix; 2198*3055Sdanmcd 2199*3055Sdanmcd if (putc('\t', ofile) == EOF) 2200*3055Sdanmcd return (B_FALSE); 2201*3055Sdanmcd 2202*3055Sdanmcd prefix = (ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ? "src" : 2203*3055Sdanmcd "dst"; 2204*3055Sdanmcd 2205*3055Sdanmcd if (fprintf(ofile, "%sidtype %s ", prefix, 2206*3055Sdanmcd rparseidtype(ident->sadb_ident_type)) < 0) 2207*3055Sdanmcd return (B_FALSE); 2208*3055Sdanmcd 2209*3055Sdanmcd if (ident->sadb_ident_type == SADB_X_IDENTTYPE_DN || 2210*3055Sdanmcd ident->sadb_ident_type == SADB_X_IDENTTYPE_GN) { 2211*3055Sdanmcd if (fprintf(ofile, gettext("<can-not-print>")) < 0) 2212*3055Sdanmcd return (B_FALSE); 2213*3055Sdanmcd } else { 2214*3055Sdanmcd if (fprintf(ofile, "%s", (char *)(ident + 1)) < 0) 2215*3055Sdanmcd return (B_FALSE); 2216*3055Sdanmcd } 2217*3055Sdanmcd 2218*3055Sdanmcd return (B_TRUE); 2219*3055Sdanmcd } 2220*3055Sdanmcd 2221*3055Sdanmcd /* 2222*3055Sdanmcd * "Save" a security association to an output file. 2223*3055Sdanmcd * 2224*3055Sdanmcd * NOTE the lack of calls to gettext() because I'm outputting parseable stuff. 2225*3055Sdanmcd * ALSO NOTE that if you change keywords (see parsecmd()), you'll have to 2226*3055Sdanmcd * change them here as well. 2227*3055Sdanmcd */ 2228*3055Sdanmcd void 2229*3055Sdanmcd save_assoc(uint64_t *buffer, FILE *ofile) 2230*3055Sdanmcd { 2231*3055Sdanmcd int seen_proto = 0; 2232*3055Sdanmcd uint64_t *current; 2233*3055Sdanmcd struct sadb_address *addr; 2234*3055Sdanmcd struct sadb_msg *samsg = (struct sadb_msg *)buffer; 2235*3055Sdanmcd struct sadb_ext *ext; 2236*3055Sdanmcd #define bail2(s) do { \ 2237*3055Sdanmcd int t = errno; \ 2238*3055Sdanmcd (void) fclose(ofile); \ 2239*3055Sdanmcd errno = t; \ 2240*3055Sdanmcd interactive = B_FALSE; /* Guarantees exit. */ \ 2241*3055Sdanmcd Bail(s); \ 2242*3055Sdanmcd } while (B_FALSE) /* How do I lint-clean this? */ 2243*3055Sdanmcd 2244*3055Sdanmcd #define savenl() if (fputs(" \\\n", ofile) == EOF) { bail2("savenl"); } 2245*3055Sdanmcd 2246*3055Sdanmcd if (fputs("# begin assoc\n", ofile) == EOF) 2247*3055Sdanmcd Bail("save_assoc: Opening comment of SA"); 2248*3055Sdanmcd if (fprintf(ofile, "add %s ", rparsesatype(samsg->sadb_msg_satype)) < 0) 2249*3055Sdanmcd Bail("save_assoc: First line of SA"); 2250*3055Sdanmcd /* LINTED E_CONST_COND */ 2251*3055Sdanmcd savenl(); 2252*3055Sdanmcd 2253*3055Sdanmcd current = (uint64_t *)(samsg + 1); 2254*3055Sdanmcd while (current - buffer < samsg->sadb_msg_len) { 2255*3055Sdanmcd struct sadb_sa *assoc; 2256*3055Sdanmcd 2257*3055Sdanmcd ext = (struct sadb_ext *)current; 2258*3055Sdanmcd switch (ext->sadb_ext_type) { 2259*3055Sdanmcd case SADB_EXT_SA: 2260*3055Sdanmcd assoc = (struct sadb_sa *)ext; 2261*3055Sdanmcd if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) { 2262*3055Sdanmcd if (fprintf(ofile, "# WARNING: SA was dying " 2263*3055Sdanmcd "or dead.\n") < 0) { 2264*3055Sdanmcd /* LINTED E_CONST_COND */ 2265*3055Sdanmcd bail2("save_assoc: fprintf not mature"); 2266*3055Sdanmcd } 2267*3055Sdanmcd } 2268*3055Sdanmcd if (fprintf(ofile, " spi 0x%x ", 2269*3055Sdanmcd ntohl(assoc->sadb_sa_spi)) < 0) 2270*3055Sdanmcd /* LINTED E_CONST_COND */ 2271*3055Sdanmcd bail2("save_assoc: fprintf spi"); 2272*3055Sdanmcd if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { 2273*3055Sdanmcd if (fprintf(ofile, "encr_alg %s ", 2274*3055Sdanmcd rparsealg(assoc->sadb_sa_encrypt, 2275*3055Sdanmcd IPSEC_PROTO_ESP)) < 0) 2276*3055Sdanmcd /* LINTED E_CONST_COND */ 2277*3055Sdanmcd bail2("save_assoc: fprintf encrypt"); 2278*3055Sdanmcd } 2279*3055Sdanmcd if (assoc->sadb_sa_auth != SADB_AALG_NONE) { 2280*3055Sdanmcd if (fprintf(ofile, "auth_alg %s ", 2281*3055Sdanmcd rparsealg(assoc->sadb_sa_auth, 2282*3055Sdanmcd IPSEC_PROTO_AH)) < 0) 2283*3055Sdanmcd /* LINTED E_CONST_COND */ 2284*3055Sdanmcd bail2("save_assoc: fprintf auth"); 2285*3055Sdanmcd } 2286*3055Sdanmcd if (fprintf(ofile, "replay %d ", 2287*3055Sdanmcd assoc->sadb_sa_replay) < 0) 2288*3055Sdanmcd /* LINTED E_CONST_COND */ 2289*3055Sdanmcd bail2("save_assoc: fprintf replay"); 2290*3055Sdanmcd if (assoc->sadb_sa_flags & (SADB_X_SAFLAGS_NATT_LOC | 2291*3055Sdanmcd SADB_X_SAFLAGS_NATT_REM)) { 2292*3055Sdanmcd if (fprintf(ofile, "encap udp") < 0) 2293*3055Sdanmcd /* LINTED E_CONST_COND */ 2294*3055Sdanmcd bail2("save_assoc: fprintf encap"); 2295*3055Sdanmcd } 2296*3055Sdanmcd /* LINTED E_CONST_COND */ 2297*3055Sdanmcd savenl(); 2298*3055Sdanmcd break; 2299*3055Sdanmcd case SADB_EXT_LIFETIME_HARD: 2300*3055Sdanmcd case SADB_EXT_LIFETIME_SOFT: 2301*3055Sdanmcd if (!save_lifetime((struct sadb_lifetime *)ext, ofile)) 2302*3055Sdanmcd /* LINTED E_CONST_COND */ 2303*3055Sdanmcd bail2("save_lifetime"); 2304*3055Sdanmcd /* LINTED E_CONST_COND */ 2305*3055Sdanmcd savenl(); 2306*3055Sdanmcd break; 2307*3055Sdanmcd case SADB_EXT_ADDRESS_SRC: 2308*3055Sdanmcd case SADB_EXT_ADDRESS_DST: 2309*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 2310*3055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 2311*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 2312*3055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 2313*3055Sdanmcd addr = (struct sadb_address *)ext; 2314*3055Sdanmcd if (!seen_proto && addr->sadb_address_proto) { 2315*3055Sdanmcd (void) fprintf(ofile, " proto %d", 2316*3055Sdanmcd addr->sadb_address_proto); 2317*3055Sdanmcd /* LINTED E_CONST_COND */ 2318*3055Sdanmcd savenl(); 2319*3055Sdanmcd seen_proto = 1; 2320*3055Sdanmcd } 2321*3055Sdanmcd if (!save_address(addr, ofile)) 2322*3055Sdanmcd /* LINTED E_CONST_COND */ 2323*3055Sdanmcd bail2("save_address"); 2324*3055Sdanmcd /* LINTED E_CONST_COND */ 2325*3055Sdanmcd savenl(); 2326*3055Sdanmcd break; 2327*3055Sdanmcd case SADB_EXT_KEY_AUTH: 2328*3055Sdanmcd case SADB_EXT_KEY_ENCRYPT: 2329*3055Sdanmcd if (!save_key((struct sadb_key *)ext, ofile)) 2330*3055Sdanmcd /* LINTED E_CONST_COND */ 2331*3055Sdanmcd bail2("save_address"); 2332*3055Sdanmcd /* LINTED E_CONST_COND */ 2333*3055Sdanmcd savenl(); 2334*3055Sdanmcd break; 2335*3055Sdanmcd case SADB_EXT_IDENTITY_SRC: 2336*3055Sdanmcd case SADB_EXT_IDENTITY_DST: 2337*3055Sdanmcd if (!save_ident((struct sadb_ident *)ext, ofile)) 2338*3055Sdanmcd /* LINTED E_CONST_COND */ 2339*3055Sdanmcd bail2("save_address"); 2340*3055Sdanmcd /* LINTED E_CONST_COND */ 2341*3055Sdanmcd savenl(); 2342*3055Sdanmcd break; 2343*3055Sdanmcd case SADB_EXT_SENSITIVITY: 2344*3055Sdanmcd default: 2345*3055Sdanmcd /* Skip over irrelevant extensions. */ 2346*3055Sdanmcd break; 2347*3055Sdanmcd } 2348*3055Sdanmcd current += ext->sadb_ext_len; 2349*3055Sdanmcd } 2350*3055Sdanmcd 2351*3055Sdanmcd if (fputs(gettext("\n# end assoc\n\n"), ofile) == EOF) 2352*3055Sdanmcd /* LINTED E_CONST_COND */ 2353*3055Sdanmcd bail2("save_assoc: last fputs"); 2354*3055Sdanmcd } 2355*3055Sdanmcd 2356*3055Sdanmcd /* 2357*3055Sdanmcd * Open the output file for the "save" command. 2358*3055Sdanmcd */ 2359*3055Sdanmcd FILE * 2360*3055Sdanmcd opensavefile(char *filename) 2361*3055Sdanmcd { 2362*3055Sdanmcd int fd; 2363*3055Sdanmcd FILE *retval; 2364*3055Sdanmcd struct stat buf; 2365*3055Sdanmcd 2366*3055Sdanmcd /* 2367*3055Sdanmcd * If the user specifies "-" or doesn't give a filename, then 2368*3055Sdanmcd * dump to stdout. Make sure to document the dangers of files 2369*3055Sdanmcd * that are NFS, directing your output to strange places, etc. 2370*3055Sdanmcd */ 2371*3055Sdanmcd if (filename == NULL || strcmp("-", filename) == 0) 2372*3055Sdanmcd return (stdout); 2373*3055Sdanmcd 2374*3055Sdanmcd /* 2375*3055Sdanmcd * open the file with the create bits set. Since I check for 2376*3055Sdanmcd * real UID == root in main(), I won't worry about the ownership 2377*3055Sdanmcd * problem. 2378*3055Sdanmcd */ 2379*3055Sdanmcd fd = open(filename, O_WRONLY | O_EXCL | O_CREAT | O_TRUNC, S_IRUSR); 2380*3055Sdanmcd if (fd == -1) { 2381*3055Sdanmcd if (errno != EEXIST) 2382*3055Sdanmcd bail_msg("%s %s: %s", filename, gettext("open error"), 2383*3055Sdanmcd strerror(errno)); 2384*3055Sdanmcd fd = open(filename, O_WRONLY | O_TRUNC, 0); 2385*3055Sdanmcd if (fd == -1) 2386*3055Sdanmcd bail_msg("%s %s: %s", filename, gettext("open error"), 2387*3055Sdanmcd strerror(errno)); 2388*3055Sdanmcd if (fstat(fd, &buf) == -1) { 2389*3055Sdanmcd (void) close(fd); 2390*3055Sdanmcd bail_msg("%s fstat: %s", filename, strerror(errno)); 2391*3055Sdanmcd } 2392*3055Sdanmcd if (S_ISREG(buf.st_mode) && 2393*3055Sdanmcd ((buf.st_mode & S_IAMB) != S_IRUSR)) { 2394*3055Sdanmcd warnx(gettext("WARNING: Save file already exists with " 2395*3055Sdanmcd "permission %o."), buf.st_mode & S_IAMB); 2396*3055Sdanmcd warnx(gettext("Normal users may be able to read IPsec " 2397*3055Sdanmcd "keying material.")); 2398*3055Sdanmcd } 2399*3055Sdanmcd } 2400*3055Sdanmcd 2401*3055Sdanmcd /* Okay, we have an FD. Assign it to a stdio FILE pointer. */ 2402*3055Sdanmcd retval = fdopen(fd, "w"); 2403*3055Sdanmcd if (retval == NULL) { 2404*3055Sdanmcd (void) close(fd); 2405*3055Sdanmcd bail_msg("%s %s: %s", filename, gettext("fdopen error"), 2406*3055Sdanmcd strerror(errno)); 2407*3055Sdanmcd } 2408*3055Sdanmcd return (retval); 2409*3055Sdanmcd } 2410*3055Sdanmcd 2411*3055Sdanmcd const char * 2412*3055Sdanmcd do_inet_ntop(const void *addr, char *cp, size_t size) 2413*3055Sdanmcd { 2414*3055Sdanmcd boolean_t isv4; 2415*3055Sdanmcd struct in6_addr *inaddr6 = (struct in6_addr *)addr; 2416*3055Sdanmcd struct in_addr inaddr; 2417*3055Sdanmcd 2418*3055Sdanmcd if ((isv4 = IN6_IS_ADDR_V4MAPPED(inaddr6)) == B_TRUE) { 2419*3055Sdanmcd IN6_V4MAPPED_TO_INADDR(inaddr6, &inaddr); 2420*3055Sdanmcd } 2421*3055Sdanmcd 2422*3055Sdanmcd return (inet_ntop(isv4 ? AF_INET : AF_INET6, 2423*3055Sdanmcd isv4 ? (void *)&inaddr : inaddr6, cp, size)); 2424*3055Sdanmcd } 2425*3055Sdanmcd 2426*3055Sdanmcd char numprint[NBUF_SIZE]; 2427*3055Sdanmcd 2428*3055Sdanmcd /* 2429*3055Sdanmcd * Parse and reverse parse a specific SA type (AH, ESP, etc.). 2430*3055Sdanmcd */ 2431*3055Sdanmcd static struct typetable { 2432*3055Sdanmcd char *type; 2433*3055Sdanmcd int token; 2434*3055Sdanmcd } type_table[] = { 2435*3055Sdanmcd {"all", SADB_SATYPE_UNSPEC}, 2436*3055Sdanmcd {"ah", SADB_SATYPE_AH}, 2437*3055Sdanmcd {"esp", SADB_SATYPE_ESP}, 2438*3055Sdanmcd /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */ 2439*3055Sdanmcd {NULL, 0} /* Token value is irrelevant for this entry. */ 2440*3055Sdanmcd }; 2441*3055Sdanmcd 2442*3055Sdanmcd char * 2443*3055Sdanmcd rparsesatype(int type) 2444*3055Sdanmcd { 2445*3055Sdanmcd struct typetable *tt = type_table; 2446*3055Sdanmcd 2447*3055Sdanmcd while (tt->type != NULL && type != tt->token) 2448*3055Sdanmcd tt++; 2449*3055Sdanmcd 2450*3055Sdanmcd if (tt->type == NULL) { 2451*3055Sdanmcd (void) snprintf(numprint, NBUF_SIZE, "%d", type); 2452*3055Sdanmcd } else { 2453*3055Sdanmcd return (tt->type); 2454*3055Sdanmcd } 2455*3055Sdanmcd 2456*3055Sdanmcd return (numprint); 2457*3055Sdanmcd } 2458*3055Sdanmcd 2459*3055Sdanmcd 2460*3055Sdanmcd /* 2461*3055Sdanmcd * Return a string containing the name of the specified numerical algorithm 2462*3055Sdanmcd * identifier. 2463*3055Sdanmcd */ 2464*3055Sdanmcd char * 2465*3055Sdanmcd rparsealg(uint8_t alg, int proto_num) 2466*3055Sdanmcd { 2467*3055Sdanmcd static struct ipsecalgent *holder = NULL; /* we're single-threaded */ 2468*3055Sdanmcd 2469*3055Sdanmcd if (holder != NULL) 2470*3055Sdanmcd freeipsecalgent(holder); 2471*3055Sdanmcd 2472*3055Sdanmcd holder = getipsecalgbynum(alg, proto_num, NULL); 2473*3055Sdanmcd if (holder == NULL) { 2474*3055Sdanmcd (void) snprintf(numprint, NBUF_SIZE, "%d", alg); 2475*3055Sdanmcd return (numprint); 2476*3055Sdanmcd } 2477*3055Sdanmcd 2478*3055Sdanmcd return (*(holder->a_names)); 2479*3055Sdanmcd } 2480*3055Sdanmcd 2481*3055Sdanmcd /* 2482*3055Sdanmcd * Parse and reverse parse out a source/destination ID type. 2483*3055Sdanmcd */ 2484*3055Sdanmcd static struct idtypes { 2485*3055Sdanmcd char *idtype; 2486*3055Sdanmcd uint8_t retval; 2487*3055Sdanmcd } idtypes[] = { 2488*3055Sdanmcd {"prefix", SADB_IDENTTYPE_PREFIX}, 2489*3055Sdanmcd {"fqdn", SADB_IDENTTYPE_FQDN}, 2490*3055Sdanmcd {"domain", SADB_IDENTTYPE_FQDN}, 2491*3055Sdanmcd {"domainname", SADB_IDENTTYPE_FQDN}, 2492*3055Sdanmcd {"user_fqdn", SADB_IDENTTYPE_USER_FQDN}, 2493*3055Sdanmcd {"mailbox", SADB_IDENTTYPE_USER_FQDN}, 2494*3055Sdanmcd {"der_dn", SADB_X_IDENTTYPE_DN}, 2495*3055Sdanmcd {"der_gn", SADB_X_IDENTTYPE_GN}, 2496*3055Sdanmcd {NULL, 0} 2497*3055Sdanmcd }; 2498*3055Sdanmcd 2499*3055Sdanmcd char * 2500*3055Sdanmcd rparseidtype(uint16_t type) 2501*3055Sdanmcd { 2502*3055Sdanmcd struct idtypes *idp; 2503*3055Sdanmcd 2504*3055Sdanmcd for (idp = idtypes; idp->idtype != NULL; idp++) { 2505*3055Sdanmcd if (type == idp->retval) 2506*3055Sdanmcd return (idp->idtype); 2507*3055Sdanmcd } 2508*3055Sdanmcd 2509*3055Sdanmcd (void) snprintf(numprint, NBUF_SIZE, "%d", type); 2510*3055Sdanmcd return (numprint); 2511*3055Sdanmcd } 2512