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 53055Sdanmcd * Common Development and Distribution License (the "License"). 63055Sdanmcd * 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*4064Smarkfen * Copyright 2007 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 67*4064Smarkfen * The error string *what should be dgettext()'d before calling bail(). 680Sstevel@tonic-gate */ 690Sstevel@tonic-gate void 700Sstevel@tonic-gate bail(char *what) 710Sstevel@tonic-gate { 720Sstevel@tonic-gate if (errno != 0) 730Sstevel@tonic-gate warn(what); 740Sstevel@tonic-gate else 75*4064Smarkfen warnx("Error: %s", what); 760Sstevel@tonic-gate if (readfile) { 77*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, 78*4064Smarkfen "System error on line %u."), lineno); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate if (interactive && !readfile) 810Sstevel@tonic-gate longjmp(env, 2); 820Sstevel@tonic-gate exit(1); 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * Print caller-supplied variable-arg error msg, then exit if cmdline or 870Sstevel@tonic-gate * readfile, or reset state if interactive. 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate /*PRINTFLIKE1*/ 900Sstevel@tonic-gate void 910Sstevel@tonic-gate bail_msg(char *fmt, ...) 920Sstevel@tonic-gate { 930Sstevel@tonic-gate va_list ap; 940Sstevel@tonic-gate char msgbuf[BUFSIZ]; 950Sstevel@tonic-gate 960Sstevel@tonic-gate va_start(ap, fmt); 970Sstevel@tonic-gate (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap); 980Sstevel@tonic-gate va_end(ap); 990Sstevel@tonic-gate if (readfile) 100*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, 101*4064Smarkfen "ERROR on line %u:\n%s\n"), lineno, msgbuf); 1020Sstevel@tonic-gate else 103*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, "ERROR: %s\n"), msgbuf); 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (interactive && !readfile) 1060Sstevel@tonic-gate longjmp(env, 1); 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate exit(1); 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * dump_XXX functions produce ASCII output from various structures. 1140Sstevel@tonic-gate * 1150Sstevel@tonic-gate * Because certain errors need to do this to stderr, dump_XXX functions 1160Sstevel@tonic-gate * take a FILE pointer. 1170Sstevel@tonic-gate * 1180Sstevel@tonic-gate * If an error occured while writing to the specified file, these 1190Sstevel@tonic-gate * functions return -1, zero otherwise. 1200Sstevel@tonic-gate */ 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate int 1233055Sdanmcd dump_sockaddr(struct sockaddr *sa, uint8_t prefixlen, boolean_t addr_only, 1243055Sdanmcd FILE *where) 1250Sstevel@tonic-gate { 1260Sstevel@tonic-gate struct sockaddr_in *sin; 1270Sstevel@tonic-gate struct sockaddr_in6 *sin6; 1280Sstevel@tonic-gate char *printable_addr, *protocol; 1290Sstevel@tonic-gate uint8_t *addrptr; 1303055Sdanmcd /* Add 4 chars to hold '/nnn' for prefixes. */ 1313055Sdanmcd char storage[INET6_ADDRSTRLEN + 4]; 1320Sstevel@tonic-gate uint16_t port; 1330Sstevel@tonic-gate boolean_t unspec; 1340Sstevel@tonic-gate struct hostent *hp; 1350Sstevel@tonic-gate int getipnode_errno, addrlen; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate switch (sa->sa_family) { 1380Sstevel@tonic-gate case AF_INET: 1390Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 1400Sstevel@tonic-gate sin = (struct sockaddr_in *)sa; 1410Sstevel@tonic-gate addrptr = (uint8_t *)&sin->sin_addr; 1420Sstevel@tonic-gate port = sin->sin_port; 1430Sstevel@tonic-gate protocol = "AF_INET"; 1440Sstevel@tonic-gate unspec = (sin->sin_addr.s_addr == 0); 1450Sstevel@tonic-gate addrlen = sizeof (sin->sin_addr); 1460Sstevel@tonic-gate break; 1470Sstevel@tonic-gate case AF_INET6: 1480Sstevel@tonic-gate /* LINTED E_BAD_PTR_CAST_ALIGN */ 1490Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)sa; 1500Sstevel@tonic-gate addrptr = (uint8_t *)&sin6->sin6_addr; 1510Sstevel@tonic-gate port = sin6->sin6_port; 1520Sstevel@tonic-gate protocol = "AF_INET6"; 1530Sstevel@tonic-gate unspec = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr); 1540Sstevel@tonic-gate addrlen = sizeof (sin6->sin6_addr); 1550Sstevel@tonic-gate break; 1560Sstevel@tonic-gate default: 1570Sstevel@tonic-gate return (0); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate if (inet_ntop(sa->sa_family, addrptr, storage, INET6_ADDRSTRLEN) == 1610Sstevel@tonic-gate NULL) { 162*4064Smarkfen printable_addr = dgettext(TEXT_DOMAIN, "Invalid IP address."); 1630Sstevel@tonic-gate } else { 1643055Sdanmcd char prefix[5]; /* "/nnn" with terminator. */ 1653055Sdanmcd 1663055Sdanmcd (void) snprintf(prefix, sizeof (prefix), "/%d", prefixlen); 1670Sstevel@tonic-gate printable_addr = storage; 1683055Sdanmcd if (prefixlen != 0) { 1693055Sdanmcd (void) strlcat(printable_addr, prefix, 1703055Sdanmcd sizeof (storage)); 1713055Sdanmcd } 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate if (addr_only) { 1740Sstevel@tonic-gate if (fprintf(where, "%s", printable_addr) < 0) 1750Sstevel@tonic-gate return (-1); 1760Sstevel@tonic-gate } else { 177*4064Smarkfen if (fprintf(where, dgettext(TEXT_DOMAIN, 178*4064Smarkfen "%s: port %d, %s"), protocol, 1790Sstevel@tonic-gate ntohs(port), printable_addr) < 0) 1800Sstevel@tonic-gate return (-1); 1810Sstevel@tonic-gate if (!nflag) { 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * Do AF_independent reverse hostname lookup here. 1840Sstevel@tonic-gate */ 1850Sstevel@tonic-gate if (unspec) { 1860Sstevel@tonic-gate if (fprintf(where, 187*4064Smarkfen dgettext(TEXT_DOMAIN, 188*4064Smarkfen " <unspecified>")) < 0) 1890Sstevel@tonic-gate return (-1); 1900Sstevel@tonic-gate } else { 1910Sstevel@tonic-gate hp = getipnodebyaddr((char *)addrptr, addrlen, 1920Sstevel@tonic-gate sa->sa_family, &getipnode_errno); 1930Sstevel@tonic-gate if (hp != NULL) { 1940Sstevel@tonic-gate if (fprintf(where, 1950Sstevel@tonic-gate " (%s)", hp->h_name) < 0) 1960Sstevel@tonic-gate return (-1); 1970Sstevel@tonic-gate freehostent(hp); 1980Sstevel@tonic-gate } else { 1990Sstevel@tonic-gate if (fprintf(where, 200*4064Smarkfen dgettext(TEXT_DOMAIN, 201*4064Smarkfen " <unknown>")) < 0) 2020Sstevel@tonic-gate return (-1); 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate if (fputs(".\n", where) == EOF) 2070Sstevel@tonic-gate return (-1); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate return (0); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* 2130Sstevel@tonic-gate * Dump a key and bitlen 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate int 2160Sstevel@tonic-gate dump_key(uint8_t *keyp, uint_t bitlen, FILE *where) 2170Sstevel@tonic-gate { 2180Sstevel@tonic-gate int numbytes; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate numbytes = SADB_1TO8(bitlen); 2210Sstevel@tonic-gate /* The & 0x7 is to check for leftover bits. */ 2220Sstevel@tonic-gate if ((bitlen & 0x7) != 0) 2230Sstevel@tonic-gate numbytes++; 2240Sstevel@tonic-gate while (numbytes-- != 0) { 2250Sstevel@tonic-gate if (pflag) { 2260Sstevel@tonic-gate /* Print no keys if paranoid */ 2270Sstevel@tonic-gate if (fprintf(where, "XX") < 0) 2280Sstevel@tonic-gate return (-1); 2290Sstevel@tonic-gate } else { 2300Sstevel@tonic-gate if (fprintf(where, "%02x", *keyp++) < 0) 2310Sstevel@tonic-gate return (-1); 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate } 2340Sstevel@tonic-gate if (fprintf(where, "/%u", bitlen) < 0) 2350Sstevel@tonic-gate return (-1); 2360Sstevel@tonic-gate return (0); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /* 2400Sstevel@tonic-gate * Print an authentication or encryption algorithm 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate static int 2430Sstevel@tonic-gate dump_generic_alg(uint8_t alg_num, int proto_num, FILE *where) 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate struct ipsecalgent *alg; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate alg = getipsecalgbynum(alg_num, proto_num, NULL); 2480Sstevel@tonic-gate if (alg == NULL) { 249*4064Smarkfen if (fprintf(where, dgettext(TEXT_DOMAIN, 250*4064Smarkfen "<unknown %u>"), alg_num) < 0) 2510Sstevel@tonic-gate return (-1); 2520Sstevel@tonic-gate return (0); 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* 2560Sstevel@tonic-gate * Special-case <none> for backward output compat. 2570Sstevel@tonic-gate * Assume that SADB_AALG_NONE == SADB_EALG_NONE. 2580Sstevel@tonic-gate */ 2590Sstevel@tonic-gate if (alg_num == SADB_AALG_NONE) { 260*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, 261*4064Smarkfen "<none>"), where) == EOF) 2620Sstevel@tonic-gate return (-1); 2630Sstevel@tonic-gate } else { 2640Sstevel@tonic-gate if (fputs(alg->a_names[0], where) == EOF) 2650Sstevel@tonic-gate return (-1); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate freeipsecalgent(alg); 2690Sstevel@tonic-gate return (0); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate int 2730Sstevel@tonic-gate dump_aalg(uint8_t aalg, FILE *where) 2740Sstevel@tonic-gate { 2750Sstevel@tonic-gate return (dump_generic_alg(aalg, IPSEC_PROTO_AH, where)); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate int 2790Sstevel@tonic-gate dump_ealg(uint8_t ealg, FILE *where) 2800Sstevel@tonic-gate { 2810Sstevel@tonic-gate return (dump_generic_alg(ealg, IPSEC_PROTO_ESP, where)); 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate /* 2850Sstevel@tonic-gate * Print an SADB_IDENTTYPE string 2860Sstevel@tonic-gate * 2870Sstevel@tonic-gate * Also return TRUE if the actual ident may be printed, FALSE if not. 2880Sstevel@tonic-gate * 2890Sstevel@tonic-gate * If rc is not NULL, set its value to -1 if an error occured while writing 2900Sstevel@tonic-gate * to the specified file, zero otherwise. 2910Sstevel@tonic-gate */ 2920Sstevel@tonic-gate boolean_t 2930Sstevel@tonic-gate dump_sadb_idtype(uint8_t idtype, FILE *where, int *rc) 2940Sstevel@tonic-gate { 2950Sstevel@tonic-gate boolean_t canprint = B_TRUE; 2960Sstevel@tonic-gate int rc_val = 0; 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate switch (idtype) { 2990Sstevel@tonic-gate case SADB_IDENTTYPE_PREFIX: 300*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "prefix"), where) == EOF) 3010Sstevel@tonic-gate rc_val = -1; 3020Sstevel@tonic-gate break; 3030Sstevel@tonic-gate case SADB_IDENTTYPE_FQDN: 304*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "FQDN"), where) == EOF) 3050Sstevel@tonic-gate rc_val = -1; 3060Sstevel@tonic-gate break; 3070Sstevel@tonic-gate case SADB_IDENTTYPE_USER_FQDN: 308*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, 309*4064Smarkfen "user-FQDN (mbox)"), where) == EOF) 3100Sstevel@tonic-gate rc_val = -1; 3110Sstevel@tonic-gate break; 3120Sstevel@tonic-gate case SADB_X_IDENTTYPE_DN: 313*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "ASN.1 DER Distinguished Name"), 3140Sstevel@tonic-gate where) == EOF) 3150Sstevel@tonic-gate rc_val = -1; 3160Sstevel@tonic-gate canprint = B_FALSE; 3170Sstevel@tonic-gate break; 3180Sstevel@tonic-gate case SADB_X_IDENTTYPE_GN: 319*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "ASN.1 DER Generic Name"), 320*4064Smarkfen where) == EOF) 3210Sstevel@tonic-gate rc_val = -1; 3220Sstevel@tonic-gate canprint = B_FALSE; 3230Sstevel@tonic-gate break; 3240Sstevel@tonic-gate case SADB_X_IDENTTYPE_KEY_ID: 325*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "Generic key id"), 326*4064Smarkfen where) == EOF) 3270Sstevel@tonic-gate rc_val = -1; 3280Sstevel@tonic-gate break; 3290Sstevel@tonic-gate case SADB_X_IDENTTYPE_ADDR_RANGE: 330*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "Address range"), where) == EOF) 3310Sstevel@tonic-gate rc_val = -1; 3320Sstevel@tonic-gate break; 3330Sstevel@tonic-gate default: 334*4064Smarkfen if (fprintf(where, dgettext(TEXT_DOMAIN, 335*4064Smarkfen "<unknown %u>"), idtype) < 0) 3360Sstevel@tonic-gate rc_val = -1; 3370Sstevel@tonic-gate break; 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate if (rc != NULL) 3410Sstevel@tonic-gate *rc = rc_val; 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate return (canprint); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate /* 3470Sstevel@tonic-gate * Slice an argv/argc vector from an interactive line or a read-file line. 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate static int 3500Sstevel@tonic-gate create_argv(char *ibuf, int *newargc, char ***thisargv) 3510Sstevel@tonic-gate { 3520Sstevel@tonic-gate unsigned int argvlen = START_ARG; 3530Sstevel@tonic-gate char **current; 3540Sstevel@tonic-gate boolean_t firstchar = B_TRUE; 3550Sstevel@tonic-gate boolean_t inquotes = B_FALSE; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate *thisargv = malloc(sizeof (char *) * argvlen); 3580Sstevel@tonic-gate if ((*thisargv) == NULL) 3590Sstevel@tonic-gate return (MEMORY_ALLOCATION); 3600Sstevel@tonic-gate current = *thisargv; 3610Sstevel@tonic-gate *current = NULL; 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate for (; *ibuf != '\0'; ibuf++) { 3640Sstevel@tonic-gate if (isspace(*ibuf)) { 3650Sstevel@tonic-gate if (inquotes) { 3660Sstevel@tonic-gate continue; 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate if (*current != NULL) { 3690Sstevel@tonic-gate *ibuf = '\0'; 3700Sstevel@tonic-gate current++; 3710Sstevel@tonic-gate if (*thisargv + argvlen == current) { 3720Sstevel@tonic-gate /* Regrow ***thisargv. */ 3730Sstevel@tonic-gate if (argvlen == TOO_MANY_ARGS) { 3740Sstevel@tonic-gate free(*thisargv); 3750Sstevel@tonic-gate return (TOO_MANY_TOKENS); 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate /* Double the allocation. */ 3780Sstevel@tonic-gate current = realloc(*thisargv, 3790Sstevel@tonic-gate sizeof (char *) * (argvlen << 1)); 3800Sstevel@tonic-gate if (current == NULL) { 3810Sstevel@tonic-gate free(*thisargv); 3820Sstevel@tonic-gate return (MEMORY_ALLOCATION); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate *thisargv = current; 3850Sstevel@tonic-gate current += argvlen; 3860Sstevel@tonic-gate argvlen <<= 1; /* Double the size. */ 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate *current = NULL; 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate } else { 3910Sstevel@tonic-gate if (firstchar) { 3920Sstevel@tonic-gate firstchar = B_FALSE; 3930Sstevel@tonic-gate if (*ibuf == COMMENT_CHAR) { 3940Sstevel@tonic-gate free(*thisargv); 3950Sstevel@tonic-gate return (COMMENT_LINE); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate if (*ibuf == QUOTE_CHAR) { 3990Sstevel@tonic-gate if (inquotes) { 4000Sstevel@tonic-gate inquotes = B_FALSE; 4010Sstevel@tonic-gate *ibuf = '\0'; 4020Sstevel@tonic-gate } else { 4030Sstevel@tonic-gate inquotes = B_TRUE; 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate continue; 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate if (*current == NULL) { 4080Sstevel@tonic-gate *current = ibuf; 4090Sstevel@tonic-gate (*newargc)++; 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate /* 4150Sstevel@tonic-gate * Tricky corner case... 4160Sstevel@tonic-gate * I've parsed _exactly_ the amount of args as I have space. It 4170Sstevel@tonic-gate * won't return NULL-terminated, and bad things will happen to 4180Sstevel@tonic-gate * the caller. 4190Sstevel@tonic-gate */ 4200Sstevel@tonic-gate if (argvlen == *newargc) { 4210Sstevel@tonic-gate current = realloc(*thisargv, sizeof (char *) * (argvlen + 1)); 4220Sstevel@tonic-gate if (current == NULL) { 4230Sstevel@tonic-gate free(*thisargv); 4240Sstevel@tonic-gate return (MEMORY_ALLOCATION); 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate *thisargv = current; 4270Sstevel@tonic-gate current[argvlen] = NULL; 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate return (SUCCESS); 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate /* 4340Sstevel@tonic-gate * Enter a mode where commands are read from a file. Treat stdin special. 4350Sstevel@tonic-gate */ 4360Sstevel@tonic-gate void 4370Sstevel@tonic-gate do_interactive(FILE *infile, char *promptstring, parse_cmdln_fn parseit) 4380Sstevel@tonic-gate { 4390Sstevel@tonic-gate char ibuf[IBUF_SIZE], holder[IBUF_SIZE]; 4400Sstevel@tonic-gate char *hptr, **thisargv; 4410Sstevel@tonic-gate int thisargc; 4420Sstevel@tonic-gate boolean_t continue_in_progress = B_FALSE; 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate (void) setjmp(env); 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate interactive = B_TRUE; 4470Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate if (infile == stdin) { 4500Sstevel@tonic-gate (void) printf("%s", promptstring); 4510Sstevel@tonic-gate (void) fflush(stdout); 4520Sstevel@tonic-gate } else { 4530Sstevel@tonic-gate readfile = B_TRUE; 4540Sstevel@tonic-gate } 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate while (fgets(ibuf, IBUF_SIZE, infile) != NULL) { 4570Sstevel@tonic-gate if (readfile) 4580Sstevel@tonic-gate lineno++; 4590Sstevel@tonic-gate thisargc = 0; 4600Sstevel@tonic-gate thisargv = NULL; 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* 4630Sstevel@tonic-gate * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will 4640Sstevel@tonic-gate * be null-terminated because of fgets(). 4650Sstevel@tonic-gate */ 4660Sstevel@tonic-gate if (ibuf[IBUF_SIZE - 2] != '\0') { 4670Sstevel@tonic-gate (void) fprintf(stderr, 468*4064Smarkfen dgettext(TEXT_DOMAIN, 469*4064Smarkfen "Line %d too big.\n"), lineno); 4700Sstevel@tonic-gate exit(1); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate if (!continue_in_progress) { 4740Sstevel@tonic-gate /* Use -2 because of \n from fgets. */ 4750Sstevel@tonic-gate if (ibuf[strlen(ibuf) - 2] == CONT_CHAR) { 4760Sstevel@tonic-gate /* 4770Sstevel@tonic-gate * Can use strcpy here, I've checked the 4780Sstevel@tonic-gate * length already. 4790Sstevel@tonic-gate */ 4800Sstevel@tonic-gate (void) strcpy(holder, ibuf); 4810Sstevel@tonic-gate hptr = &(holder[strlen(holder)]); 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* Remove the CONT_CHAR from the string. */ 4840Sstevel@tonic-gate hptr[-2] = ' '; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate continue_in_progress = B_TRUE; 4870Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 4880Sstevel@tonic-gate continue; 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate } else { 4910Sstevel@tonic-gate /* Handle continuations... */ 4920Sstevel@tonic-gate (void) strncpy(hptr, ibuf, 4930Sstevel@tonic-gate (size_t)(&(holder[IBUF_SIZE]) - hptr)); 4940Sstevel@tonic-gate if (holder[IBUF_SIZE - 1] != '\0') { 4950Sstevel@tonic-gate (void) fprintf(stderr, 496*4064Smarkfen dgettext(TEXT_DOMAIN, 497*4064Smarkfen "Command buffer overrun.\n")); 4980Sstevel@tonic-gate exit(1); 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate /* Use - 2 because of \n from fgets. */ 5010Sstevel@tonic-gate if (hptr[strlen(hptr) - 2] == CONT_CHAR) { 5020Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 5030Sstevel@tonic-gate hptr += strlen(hptr); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate /* Remove the CONT_CHAR from the string. */ 5060Sstevel@tonic-gate hptr[-2] = ' '; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate continue; 5090Sstevel@tonic-gate } else { 5100Sstevel@tonic-gate continue_in_progress = B_FALSE; 5110Sstevel@tonic-gate /* 5120Sstevel@tonic-gate * I've already checked the length... 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate (void) strcpy(ibuf, holder); 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate switch (create_argv(ibuf, &thisargc, &thisargv)) { 5190Sstevel@tonic-gate case TOO_MANY_TOKENS: 5200Sstevel@tonic-gate (void) fprintf(stderr, 521*4064Smarkfen dgettext(TEXT_DOMAIN, "Too many input tokens.\n")); 5220Sstevel@tonic-gate exit(1); 5230Sstevel@tonic-gate break; 5240Sstevel@tonic-gate case MEMORY_ALLOCATION: 5250Sstevel@tonic-gate (void) fprintf(stderr, 526*4064Smarkfen dgettext(TEXT_DOMAIN, 527*4064Smarkfen "Memory allocation error.\n")); 5280Sstevel@tonic-gate exit(1); 5290Sstevel@tonic-gate break; 5300Sstevel@tonic-gate case COMMENT_LINE: 5310Sstevel@tonic-gate /* Comment line. */ 5320Sstevel@tonic-gate break; 5330Sstevel@tonic-gate default: 5340Sstevel@tonic-gate parseit(thisargc, thisargv); 5350Sstevel@tonic-gate free(thisargv); 5360Sstevel@tonic-gate if (infile == stdin) { 5370Sstevel@tonic-gate (void) printf("%s", promptstring); 5380Sstevel@tonic-gate (void) fflush(stdout); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate break; 5410Sstevel@tonic-gate } 5420Sstevel@tonic-gate bzero(ibuf, IBUF_SIZE); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate if (!readfile) { 5450Sstevel@tonic-gate (void) putchar('\n'); 5460Sstevel@tonic-gate (void) fflush(stdout); 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate exit(0); 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate /* 5520Sstevel@tonic-gate * Functions to parse strings that represent a debug or privilege level. 5530Sstevel@tonic-gate * These functions are copied from main.c and door.c in usr.lib/in.iked/common. 5540Sstevel@tonic-gate * If this file evolves into a common library that may be used by in.iked 5550Sstevel@tonic-gate * as well as the usr.sbin utilities, those duplicate functions should be 5560Sstevel@tonic-gate * deleted. 5570Sstevel@tonic-gate * 5580Sstevel@tonic-gate * A privilege level may be represented by a simple keyword, corresponding 5590Sstevel@tonic-gate * to one of the possible levels. A debug level may be represented by a 5600Sstevel@tonic-gate * series of keywords, separated by '+' or '-', indicating categories to 5610Sstevel@tonic-gate * be added or removed from the set of categories in the debug level. 5620Sstevel@tonic-gate * For example, +all-op corresponds to level 0xfffffffb (all flags except 5630Sstevel@tonic-gate * for D_OP set); while p1+p2+pfkey corresponds to level 0x38. Note that 5640Sstevel@tonic-gate * the leading '+' is implicit; the first keyword in the list must be for 5650Sstevel@tonic-gate * a category that is to be added. 5660Sstevel@tonic-gate * 5670Sstevel@tonic-gate * These parsing functions make use of a local version of strtok, strtok_d, 5680Sstevel@tonic-gate * which includes an additional parameter, char *delim. This param is filled 5690Sstevel@tonic-gate * in with the character which ends the returned token. In other words, 5700Sstevel@tonic-gate * this version of strtok, in addition to returning the token, also returns 5710Sstevel@tonic-gate * the single character delimiter from the original string which marked the 5720Sstevel@tonic-gate * end of the token. 5730Sstevel@tonic-gate */ 5740Sstevel@tonic-gate static char * 5750Sstevel@tonic-gate strtok_d(char *string, const char *sepset, char *delim) 5760Sstevel@tonic-gate { 5770Sstevel@tonic-gate static char *lasts; 5780Sstevel@tonic-gate char *q, *r; 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* first or subsequent call */ 5810Sstevel@tonic-gate if (string == NULL) 5820Sstevel@tonic-gate string = lasts; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate if (string == 0) /* return if no tokens remaining */ 5850Sstevel@tonic-gate return (NULL); 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate q = string + strspn(string, sepset); /* skip leading separators */ 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate if (*q == '\0') /* return if no tokens remaining */ 5900Sstevel@tonic-gate return (NULL); 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL) { /* move past token */ 5930Sstevel@tonic-gate lasts = 0; /* indicate that this is last token */ 5940Sstevel@tonic-gate } else { 5950Sstevel@tonic-gate *delim = *r; /* save delimitor */ 5960Sstevel@tonic-gate *r = '\0'; 5970Sstevel@tonic-gate lasts = r + 1; 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate return (q); 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate static keywdtab_t privtab[] = { 6030Sstevel@tonic-gate { IKE_PRIV_MINIMUM, "base" }, 6040Sstevel@tonic-gate { IKE_PRIV_MODKEYS, "modkeys" }, 6050Sstevel@tonic-gate { IKE_PRIV_KEYMAT, "keymat" }, 6060Sstevel@tonic-gate { IKE_PRIV_MINIMUM, "0" }, 6070Sstevel@tonic-gate }; 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate int 6100Sstevel@tonic-gate privstr2num(char *str) 6110Sstevel@tonic-gate { 6120Sstevel@tonic-gate keywdtab_t *pp; 6130Sstevel@tonic-gate char *endp; 6140Sstevel@tonic-gate int priv; 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate for (pp = privtab; pp < A_END(privtab); pp++) { 6170Sstevel@tonic-gate if (strcasecmp(str, pp->kw_str) == 0) 6180Sstevel@tonic-gate return (pp->kw_tag); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate priv = strtol(str, &endp, 0); 6220Sstevel@tonic-gate if (*endp == '\0') 6230Sstevel@tonic-gate return (priv); 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate return (-1); 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate static keywdtab_t dbgtab[] = { 6290Sstevel@tonic-gate { D_CERT, "cert" }, 6300Sstevel@tonic-gate { D_KEY, "key" }, 6310Sstevel@tonic-gate { D_OP, "op" }, 6320Sstevel@tonic-gate { D_P1, "p1" }, 6330Sstevel@tonic-gate { D_P1, "phase1" }, 6340Sstevel@tonic-gate { D_P2, "p2" }, 6350Sstevel@tonic-gate { D_P2, "phase2" }, 6360Sstevel@tonic-gate { D_PFKEY, "pfkey" }, 6370Sstevel@tonic-gate { D_POL, "pol" }, 6380Sstevel@tonic-gate { D_POL, "policy" }, 6390Sstevel@tonic-gate { D_PROP, "prop" }, 6400Sstevel@tonic-gate { D_DOOR, "door" }, 6410Sstevel@tonic-gate { D_CONFIG, "config" }, 6420Sstevel@tonic-gate { D_ALL, "all" }, 6430Sstevel@tonic-gate { 0, "0" }, 6440Sstevel@tonic-gate }; 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate int 6470Sstevel@tonic-gate dbgstr2num(char *str) 6480Sstevel@tonic-gate { 6490Sstevel@tonic-gate keywdtab_t *dp; 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate for (dp = dbgtab; dp < A_END(dbgtab); dp++) { 6520Sstevel@tonic-gate if (strcasecmp(str, dp->kw_str) == 0) 6530Sstevel@tonic-gate return (dp->kw_tag); 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate return (D_INVALID); 6560Sstevel@tonic-gate } 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate int 6590Sstevel@tonic-gate parsedbgopts(char *optarg) 6600Sstevel@tonic-gate { 6610Sstevel@tonic-gate char *argp, *endp, op, nextop; 6620Sstevel@tonic-gate int mask = 0, new; 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate mask = strtol(optarg, &endp, 0); 6650Sstevel@tonic-gate if (*endp == '\0') 6660Sstevel@tonic-gate return (mask); 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate op = optarg[0]; 6690Sstevel@tonic-gate if (op != '-') 6700Sstevel@tonic-gate op = '+'; 6710Sstevel@tonic-gate argp = strtok_d(optarg, "+-", &nextop); 6720Sstevel@tonic-gate do { 6730Sstevel@tonic-gate new = dbgstr2num(argp); 6740Sstevel@tonic-gate if (new == D_INVALID) { 6750Sstevel@tonic-gate /* we encountered an invalid keywd */ 6760Sstevel@tonic-gate return (new); 6770Sstevel@tonic-gate } 6780Sstevel@tonic-gate if (op == '+') { 6790Sstevel@tonic-gate mask |= new; 6800Sstevel@tonic-gate } else { 6810Sstevel@tonic-gate mask &= ~new; 6820Sstevel@tonic-gate } 6830Sstevel@tonic-gate op = nextop; 6840Sstevel@tonic-gate } while ((argp = strtok_d(NULL, "+-", &nextop)) != NULL); 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate return (mask); 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate /* 6910Sstevel@tonic-gate * functions to manipulate the kmcookie-label mapping file 6920Sstevel@tonic-gate */ 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate /* 6950Sstevel@tonic-gate * Open, lockf, fdopen the given file, returning a FILE * on success, 6960Sstevel@tonic-gate * or NULL on failure. 6970Sstevel@tonic-gate */ 6980Sstevel@tonic-gate FILE * 6990Sstevel@tonic-gate kmc_open_and_lock(char *name) 7000Sstevel@tonic-gate { 7010Sstevel@tonic-gate int fd, rtnerr; 7020Sstevel@tonic-gate FILE *fp; 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate if ((fd = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { 7050Sstevel@tonic-gate return (NULL); 7060Sstevel@tonic-gate } 7070Sstevel@tonic-gate if (lockf(fd, F_LOCK, 0) < 0) { 7080Sstevel@tonic-gate return (NULL); 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate if ((fp = fdopen(fd, "a+")) == NULL) { 7110Sstevel@tonic-gate return (NULL); 7120Sstevel@tonic-gate } 7130Sstevel@tonic-gate if (fseek(fp, 0, SEEK_SET) < 0) { 7140Sstevel@tonic-gate /* save errno in case fclose changes it */ 7150Sstevel@tonic-gate rtnerr = errno; 7160Sstevel@tonic-gate (void) fclose(fp); 7170Sstevel@tonic-gate errno = rtnerr; 7180Sstevel@tonic-gate return (NULL); 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate return (fp); 7210Sstevel@tonic-gate } 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate /* 7240Sstevel@tonic-gate * Extract an integer cookie and string label from a line from the 7250Sstevel@tonic-gate * kmcookie-label file. Return -1 on failure, 0 on success. 7260Sstevel@tonic-gate */ 7270Sstevel@tonic-gate int 7280Sstevel@tonic-gate kmc_parse_line(char *line, int *cookie, char **label) 7290Sstevel@tonic-gate { 7300Sstevel@tonic-gate char *cookiestr; 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate *cookie = 0; 7330Sstevel@tonic-gate *label = NULL; 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate cookiestr = strtok(line, " \t\n"); 7360Sstevel@tonic-gate if (cookiestr == NULL) { 7370Sstevel@tonic-gate return (-1); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate /* Everything that follows, up to the newline, is the label. */ 7410Sstevel@tonic-gate *label = strtok(NULL, "\n"); 7420Sstevel@tonic-gate if (*label == NULL) { 7430Sstevel@tonic-gate return (-1); 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate *cookie = atoi(cookiestr); 7470Sstevel@tonic-gate return (0); 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate /* 7510Sstevel@tonic-gate * Insert a mapping into the file (if it's not already there), given the 7520Sstevel@tonic-gate * new label. Return the assigned cookie, or -1 on error. 7530Sstevel@tonic-gate */ 7540Sstevel@tonic-gate int 7550Sstevel@tonic-gate kmc_insert_mapping(char *label) 7560Sstevel@tonic-gate { 7570Sstevel@tonic-gate FILE *map; 7580Sstevel@tonic-gate char linebuf[MAXLINESIZE]; 7590Sstevel@tonic-gate char *cur_label; 7600Sstevel@tonic-gate int max_cookie = 0, cur_cookie, rtn_cookie; 7610Sstevel@tonic-gate int rtnerr = 0; 7620Sstevel@tonic-gate boolean_t found = B_FALSE; 7630Sstevel@tonic-gate 7640Sstevel@tonic-gate /* open and lock the file; will sleep until lock is available */ 7650Sstevel@tonic-gate if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 7660Sstevel@tonic-gate /* kmc_open_and_lock() sets errno appropriately */ 7670Sstevel@tonic-gate return (-1); 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 7730Sstevel@tonic-gate rtnerr = EINVAL; 7740Sstevel@tonic-gate goto error; 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate if (cur_cookie > max_cookie) 7780Sstevel@tonic-gate max_cookie = cur_cookie; 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate if ((!found) && (strcmp(cur_label, label) == 0)) { 7810Sstevel@tonic-gate found = B_TRUE; 7820Sstevel@tonic-gate rtn_cookie = cur_cookie; 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate } 7850Sstevel@tonic-gate 7860Sstevel@tonic-gate if (!found) { 7870Sstevel@tonic-gate rtn_cookie = ++max_cookie; 7880Sstevel@tonic-gate if ((fprintf(map, "%u\t%s\n", rtn_cookie, label) < 0) || 7890Sstevel@tonic-gate (fflush(map) < 0)) { 7900Sstevel@tonic-gate rtnerr = errno; 7910Sstevel@tonic-gate goto error; 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate } 7940Sstevel@tonic-gate (void) fclose(map); 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate return (rtn_cookie); 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate error: 7990Sstevel@tonic-gate (void) fclose(map); 8000Sstevel@tonic-gate errno = rtnerr; 8010Sstevel@tonic-gate return (-1); 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate /* 8050Sstevel@tonic-gate * Lookup the given cookie and return its corresponding label. Return 8060Sstevel@tonic-gate * a pointer to the label on success, NULL on error (or if the label is 8070Sstevel@tonic-gate * not found). Note that the returned label pointer points to a static 8080Sstevel@tonic-gate * string, so the label will be overwritten by a subsequent call to the 8090Sstevel@tonic-gate * function; the function is also not thread-safe as a result. 8100Sstevel@tonic-gate */ 8110Sstevel@tonic-gate char * 8120Sstevel@tonic-gate kmc_lookup_by_cookie(int cookie) 8130Sstevel@tonic-gate { 8140Sstevel@tonic-gate FILE *map; 8150Sstevel@tonic-gate static char linebuf[MAXLINESIZE]; 8160Sstevel@tonic-gate char *cur_label; 8170Sstevel@tonic-gate int cur_cookie; 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate if ((map = kmc_open_and_lock(KMCFILE)) == NULL) { 8200Sstevel@tonic-gate return (NULL); 8210Sstevel@tonic-gate } 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate while (fgets(linebuf, sizeof (linebuf), map) != NULL) { 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) { 8260Sstevel@tonic-gate (void) fclose(map); 8270Sstevel@tonic-gate return (NULL); 8280Sstevel@tonic-gate } 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate if (cookie == cur_cookie) { 8310Sstevel@tonic-gate (void) fclose(map); 8320Sstevel@tonic-gate return (cur_label); 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate (void) fclose(map); 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate return (NULL); 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate /* 8410Sstevel@tonic-gate * Parse basic extension headers and return in the passed-in pointer vector. 8420Sstevel@tonic-gate * Return values include: 8430Sstevel@tonic-gate * 8440Sstevel@tonic-gate * KGE_OK Everything's nice and parsed out. 8450Sstevel@tonic-gate * If there are no extensions, place NULL in extv[0]. 8460Sstevel@tonic-gate * KGE_DUP There is a duplicate extension. 8470Sstevel@tonic-gate * First instance in appropriate bin. First duplicate in 8480Sstevel@tonic-gate * extv[0]. 8490Sstevel@tonic-gate * KGE_UNK Unknown extension type encountered. extv[0] contains 8500Sstevel@tonic-gate * unknown header. 8510Sstevel@tonic-gate * KGE_LEN Extension length error. 8520Sstevel@tonic-gate * KGE_CHK High-level reality check failed on specific extension. 8530Sstevel@tonic-gate * 8540Sstevel@tonic-gate * My apologies for some of the pointer arithmetic in here. I'm thinking 8550Sstevel@tonic-gate * like an assembly programmer, yet trying to make the compiler happy. 8560Sstevel@tonic-gate */ 8570Sstevel@tonic-gate int 8580Sstevel@tonic-gate spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize, 8590Sstevel@tonic-gate char *diag_buf, uint_t diag_buf_len) 8600Sstevel@tonic-gate { 8610Sstevel@tonic-gate int i; 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate if (diag_buf != NULL) 8640Sstevel@tonic-gate diag_buf[0] = '\0'; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate for (i = 1; i <= SPD_EXT_MAX; i++) 8670Sstevel@tonic-gate extv[i] = NULL; 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate i = 0; 8700Sstevel@tonic-gate /* Use extv[0] as the "current working pointer". */ 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate extv[0] = (spd_ext_t *)(basehdr + 1); 8730Sstevel@tonic-gate msgsize = SPD_64TO8(msgsize); 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate while ((char *)extv[0] < ((char *)basehdr + msgsize)) { 8760Sstevel@tonic-gate /* Check for unknown headers. */ 8770Sstevel@tonic-gate i++; 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate if (extv[0]->spd_ext_type == 0 || 8800Sstevel@tonic-gate extv[0]->spd_ext_type > SPD_EXT_MAX) { 8810Sstevel@tonic-gate if (diag_buf != NULL) { 8820Sstevel@tonic-gate (void) snprintf(diag_buf, diag_buf_len, 8830Sstevel@tonic-gate "spdsock ext 0x%X unknown: 0x%X", 8840Sstevel@tonic-gate i, extv[0]->spd_ext_type); 8850Sstevel@tonic-gate } 8860Sstevel@tonic-gate return (KGE_UNK); 8870Sstevel@tonic-gate } 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate /* 8900Sstevel@tonic-gate * Check length. Use uint64_t because extlen is in units 8910Sstevel@tonic-gate * of 64-bit words. If length goes beyond the msgsize, 8920Sstevel@tonic-gate * return an error. (Zero length also qualifies here.) 8930Sstevel@tonic-gate */ 8940Sstevel@tonic-gate if (extv[0]->spd_ext_len == 0 || 8950Sstevel@tonic-gate (uint8_t *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) > 8960Sstevel@tonic-gate (uint8_t *)((uint8_t *)basehdr + msgsize)) 8970Sstevel@tonic-gate return (KGE_LEN); 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate /* Check for redundant headers. */ 9000Sstevel@tonic-gate if (extv[extv[0]->spd_ext_type] != NULL) 9010Sstevel@tonic-gate return (KGE_DUP); 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate /* If I make it here, assign the appropriate bin. */ 9040Sstevel@tonic-gate extv[extv[0]->spd_ext_type] = extv[0]; 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate /* Advance pointer (See above for uint64_t ptr reasoning.) */ 9070Sstevel@tonic-gate extv[0] = (spd_ext_t *) 9080Sstevel@tonic-gate ((uint64_t *)extv[0] + extv[0]->spd_ext_len); 9090Sstevel@tonic-gate } 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate /* Everything's cool. */ 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate /* 9140Sstevel@tonic-gate * If extv[0] == NULL, then there are no extension headers in this 9150Sstevel@tonic-gate * message. Ensure that this is the case. 9160Sstevel@tonic-gate */ 9170Sstevel@tonic-gate if (extv[0] == (spd_ext_t *)(basehdr + 1)) 9180Sstevel@tonic-gate extv[0] = NULL; 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate return (KGE_OK); 9210Sstevel@tonic-gate } 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate const char * 9240Sstevel@tonic-gate spdsock_diag(int diagnostic) 9250Sstevel@tonic-gate { 9260Sstevel@tonic-gate switch (diagnostic) { 9270Sstevel@tonic-gate case SPD_DIAGNOSTIC_NONE: 928*4064Smarkfen return (dgettext(TEXT_DOMAIN, "no error")); 9290Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNKNOWN_EXT: 930*4064Smarkfen return (dgettext(TEXT_DOMAIN, "unknown extension")); 9310Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_EXTLEN: 932*4064Smarkfen return (dgettext(TEXT_DOMAIN, "bad extension length")); 9330Sstevel@tonic-gate case SPD_DIAGNOSTIC_NO_RULE_EXT: 934*4064Smarkfen return (dgettext(TEXT_DOMAIN, "no rule extension")); 9350Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_ADDR_LEN: 936*4064Smarkfen return (dgettext(TEXT_DOMAIN, "bad address len")); 9370Sstevel@tonic-gate case SPD_DIAGNOSTIC_MIXED_AF: 938*4064Smarkfen return (dgettext(TEXT_DOMAIN, "mixed address family")); 9390Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_NO_MEM: 940*4064Smarkfen return (dgettext(TEXT_DOMAIN, "add: no memory")); 9410Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT: 942*4064Smarkfen return (dgettext(TEXT_DOMAIN, "add: wrong action count")); 9430Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_BAD_TYPE: 944*4064Smarkfen return (dgettext(TEXT_DOMAIN, "add: bad type")); 9450Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_BAD_FLAGS: 946*4064Smarkfen return (dgettext(TEXT_DOMAIN, "add: bad flags")); 9470Sstevel@tonic-gate case SPD_DIAGNOSTIC_ADD_INCON_FLAGS: 948*4064Smarkfen return (dgettext(TEXT_DOMAIN, "add: inconsistent flags")); 9490Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_LCLPORT: 950*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed local port")); 9510Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_LCLPORT: 952*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate local port")); 9530Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_REMPORT: 954*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed remote port")); 9550Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_REMPORT: 956*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate remote port")); 9570Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_PROTO: 958*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed proto")); 9590Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_PROTO: 960*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate proto")); 9610Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_LCLADDR: 962*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed local address")); 9630Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_LCLADDR: 964*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate local address")); 9650Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_REMADDR: 966*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed remote address")); 9670Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_REMADDR: 968*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate remote address")); 9690Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_ACTION: 970*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed action")); 9710Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_ACTION: 972*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate action")); 9730Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_RULE: 974*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed rule")); 9750Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_RULE: 976*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate rule")); 9770Sstevel@tonic-gate case SPD_DIAGNOSTIC_MALFORMED_RULESET: 978*4064Smarkfen return (dgettext(TEXT_DOMAIN, "malformed ruleset")); 9790Sstevel@tonic-gate case SPD_DIAGNOSTIC_DUPLICATE_RULESET: 980*4064Smarkfen return (dgettext(TEXT_DOMAIN, "duplicate ruleset")); 9810Sstevel@tonic-gate case SPD_DIAGNOSTIC_INVALID_RULE_INDEX: 982*4064Smarkfen return (dgettext(TEXT_DOMAIN, "invalid rule index")); 9830Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_SPDID: 984*4064Smarkfen return (dgettext(TEXT_DOMAIN, "bad spdid")); 9850Sstevel@tonic-gate case SPD_DIAGNOSTIC_BAD_MSG_TYPE: 986*4064Smarkfen return (dgettext(TEXT_DOMAIN, "bad message type")); 9870Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_AH_ALG: 988*4064Smarkfen return (dgettext(TEXT_DOMAIN, "unsupported AH algorithm")); 9890Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG: 990*4064Smarkfen return (dgettext(TEXT_DOMAIN, 991*4064Smarkfen "unsupported ESP encryption algorithm")); 9920Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG: 993*4064Smarkfen return (dgettext(TEXT_DOMAIN, 994*4064Smarkfen "unsupported ESP authentication algorithm")); 9950Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_AH_KEYSIZE: 996*4064Smarkfen return (dgettext(TEXT_DOMAIN, "unsupported AH key size")); 9970Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_KEYSIZE: 998*4064Smarkfen return (dgettext(TEXT_DOMAIN, 999*4064Smarkfen "unsupported ESP encryption key size")); 10000Sstevel@tonic-gate case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_KEYSIZE: 1001*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1002*4064Smarkfen "unsupported ESP authentication key size")); 10030Sstevel@tonic-gate case SPD_DIAGNOSTIC_NO_ACTION_EXT: 1004*4064Smarkfen return (dgettext(TEXT_DOMAIN, "No ACTION extension")); 10050Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_ID_RANGE: 1006*4064Smarkfen return (dgettext(TEXT_DOMAIN, "invalid algorithm identifer")); 10070Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES: 1008*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1009*4064Smarkfen "number of key sizes inconsistent")); 10100Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES: 1011*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1012*4064Smarkfen "number of block sizes inconsistent")); 10130Sstevel@tonic-gate case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN: 1014*4064Smarkfen return (dgettext(TEXT_DOMAIN, "invalid mechanism name length")); 10153055Sdanmcd case SPD_DIAGNOSTIC_NOT_GLOBAL_OP: 1016*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1017*4064Smarkfen "operation not applicable to all policies")); 10183055Sdanmcd case SPD_DIAGNOSTIC_NO_TUNNEL_SELECTORS: 1019*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1020*4064Smarkfen "using selectors on a transport-mode tunnel")); 10210Sstevel@tonic-gate default: 1022*4064Smarkfen return (dgettext(TEXT_DOMAIN, "unknown diagnostic")); 10230Sstevel@tonic-gate } 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate /* 10270Sstevel@tonic-gate * PF_KEY Diagnostic table. 10280Sstevel@tonic-gate * 10290Sstevel@tonic-gate * PF_KEY NOTE: If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is 10300Sstevel@tonic-gate * where you need to add new messages. 10310Sstevel@tonic-gate */ 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate const char * 10340Sstevel@tonic-gate keysock_diag(int diagnostic) 10350Sstevel@tonic-gate { 10360Sstevel@tonic-gate switch (diagnostic) { 10373055Sdanmcd case SADB_X_DIAGNOSTIC_NONE: 1038*4064Smarkfen return (dgettext(TEXT_DOMAIN, "No diagnostic")); 10390Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_MSG: 1040*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Unknown message type")); 10410Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_EXT: 1042*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Unknown extension type")); 10430Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EXTLEN: 1044*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Bad extension length")); 10450Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE: 1046*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1047*4064Smarkfen "Unknown Security Association type")); 10480Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_SATYPE_NEEDED: 1049*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1050*4064Smarkfen "Specific Security Association type needed")); 10510Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NO_SADBS: 1052*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1053*4064Smarkfen "No Security Association Databases present")); 10540Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_NO_EXT: 1055*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1056*4064Smarkfen "No extensions needed for message")); 10570Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SRC_AF: 1058*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Bad source address family")); 10590Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_DST_AF: 1060*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1061*4064Smarkfen "Bad destination address family")); 10620Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_PROXY_AF: 1063*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1064*4064Smarkfen "Bad inner-source address family")); 10650Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_AF_MISMATCH: 1066*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1067*4064Smarkfen "Source/destination address family mismatch")); 10680Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SRC: 1069*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Bad source address value")); 10700Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_DST: 1071*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Bad destination address value")); 10720Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ALLOC_HSERR: 1073*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1074*4064Smarkfen "Soft allocations limit more than hard limit")); 10750Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BYTES_HSERR: 1076*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1077*4064Smarkfen "Soft bytes limit more than hard limit")); 10780Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ADDTIME_HSERR: 1079*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Soft add expiration time later " 10800Sstevel@tonic-gate "than hard expiration time")); 10810Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_USETIME_HSERR: 1082*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Soft use expiration time later " 10830Sstevel@tonic-gate "than hard expiration time")); 10840Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_SRC: 1085*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing source address")); 10860Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_DST: 1087*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing destination address")); 10880Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_SA: 1089*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing SA extension")); 10900Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_EKEY: 1091*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing encryption key")); 10920Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_AKEY: 1093*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing authentication key")); 10940Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_RANGE: 1095*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing SPI range")); 10960Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_SRC: 1097*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate source address")); 10980Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_DST: 1099*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate destination address")); 11000Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_SA: 1101*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate SA extension")); 11020Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_EKEY: 1103*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate encryption key")); 11040Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_AKEY: 1105*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate authentication key")); 11060Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_RANGE: 1107*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate SPI range")); 11080Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_SRC: 1109*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed source address")); 11100Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_DST: 1111*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed destination address")); 11120Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_SA: 1113*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed SA extension")); 11140Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_EKEY: 1115*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed encryption key")); 11160Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_AKEY: 1117*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed authentication key")); 11180Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_RANGE: 1119*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed SPI range")); 11200Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_AKEY_PRESENT: 1121*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Authentication key not needed")); 11220Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_EKEY_PRESENT: 1123*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Encryption key not needed")); 11240Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_PROP_PRESENT: 1125*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Proposal extension not needed")); 11260Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_SUPP_PRESENT: 1127*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1128*4064Smarkfen "Supported algorithms extension not needed")); 11290Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_AALG: 1130*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1131*4064Smarkfen "Unsupported authentication algorithm")); 11320Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EALG: 1133*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1134*4064Smarkfen "Unsupported encryption algorithm")); 11350Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SAFLAGS: 1136*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Invalid SA flags")); 11370Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_SASTATE: 1138*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Invalid SA state")); 11390Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_AKEYBITS: 1140*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1141*4064Smarkfen "Bad number of authentication bits")); 11420Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_BAD_EKEYBITS: 1143*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1144*4064Smarkfen "Bad number of encryption bits")); 11450Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_ENCR_NOTSUPP: 1146*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1147*4064Smarkfen "Encryption not supported for this SA type")); 11480Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_WEAK_EKEY: 1149*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Weak encryption key")); 11500Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_WEAK_AKEY: 1151*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Weak authentication key")); 11520Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_KMP: 1153*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1154*4064Smarkfen "Duplicate key management protocol")); 11550Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_KMC: 1156*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1157*4064Smarkfen "Duplicate key management cookie")); 11580Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC: 1159*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing NAT-T local address")); 11600Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MISSING_NATT_REM: 1161*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing NAT-T remote address")); 11620Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC: 1163*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate NAT-T local address")); 11640Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM: 1165*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1166*4064Smarkfen "Duplicate NAT-T remote address")); 11670Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC: 1168*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Malformed NAT-T local address")); 11690Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM: 1170*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1171*4064Smarkfen "Malformed NAT-T remote address")); 11720Sstevel@tonic-gate case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS: 1173*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Duplicate NAT-T ports")); 11743055Sdanmcd case SADB_X_DIAGNOSTIC_MISSING_INNER_SRC: 1175*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Missing inner source address")); 11763055Sdanmcd case SADB_X_DIAGNOSTIC_MISSING_INNER_DST: 1177*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1178*4064Smarkfen "Missing inner destination address")); 11793055Sdanmcd case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_SRC: 1180*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1181*4064Smarkfen "Duplicate inner source address")); 11823055Sdanmcd case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_DST: 1183*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1184*4064Smarkfen "Duplicate inner destination address")); 11853055Sdanmcd case SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC: 1186*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1187*4064Smarkfen "Malformed inner source address")); 11883055Sdanmcd case SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST: 1189*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1190*4064Smarkfen "Malformed inner destination address")); 11913055Sdanmcd case SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC: 1192*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1193*4064Smarkfen "Invalid inner-source prefix length ")); 11943055Sdanmcd case SADB_X_DIAGNOSTIC_PREFIX_INNER_DST: 1195*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1196*4064Smarkfen "Invalid inner-destination prefix length")); 11973055Sdanmcd case SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF: 1198*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1199*4064Smarkfen "Bad inner-destination address family")); 12003055Sdanmcd case SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH: 1201*4064Smarkfen return (dgettext(TEXT_DOMAIN, 12023055Sdanmcd "Inner source/destination address family mismatch")); 12033055Sdanmcd case SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF: 1204*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1205*4064Smarkfen "Bad NAT-T remote address family")); 12063055Sdanmcd case SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF: 1207*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1208*4064Smarkfen "Bad NAT-T local address family")); 12093055Sdanmcd case SADB_X_DIAGNOSTIC_PROTO_MISMATCH: 1210*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1211*4064Smarkfen "Source/desination protocol mismatch")); 12123055Sdanmcd case SADB_X_DIAGNOSTIC_INNER_PROTO_MISMATCH: 1213*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1214*4064Smarkfen "Inner source/desination protocol mismatch")); 12153055Sdanmcd case SADB_X_DIAGNOSTIC_DUAL_PORT_SETS: 1216*4064Smarkfen return (dgettext(TEXT_DOMAIN, 1217*4064Smarkfen "Both inner ports and outer ports are set")); 12180Sstevel@tonic-gate default: 1219*4064Smarkfen return (dgettext(TEXT_DOMAIN, "Unknown diagnostic code")); 12200Sstevel@tonic-gate } 12210Sstevel@tonic-gate } 12223055Sdanmcd 12233055Sdanmcd /* 12243055Sdanmcd * Convert an IPv6 mask to a prefix len. I assume all IPv6 masks are 12253055Sdanmcd * contiguous, so I stop at the first zero bit! 12263055Sdanmcd */ 12273055Sdanmcd int 12283055Sdanmcd in_masktoprefix(uint8_t *mask, boolean_t is_v4mapped) 12293055Sdanmcd { 12303055Sdanmcd int rc = 0; 12313055Sdanmcd uint8_t last; 12323055Sdanmcd int limit = IPV6_ABITS; 12333055Sdanmcd 12343055Sdanmcd if (is_v4mapped) { 12353055Sdanmcd mask += ((IPV6_ABITS - IP_ABITS)/8); 12363055Sdanmcd limit = IP_ABITS; 12373055Sdanmcd } 12383055Sdanmcd 12393055Sdanmcd while (*mask == 0xff) { 12403055Sdanmcd rc += 8; 12413055Sdanmcd if (rc == limit) 12423055Sdanmcd return (limit); 12433055Sdanmcd mask++; 12443055Sdanmcd } 12453055Sdanmcd 12463055Sdanmcd last = *mask; 12473055Sdanmcd while (last != 0) { 12483055Sdanmcd rc++; 12493055Sdanmcd last = (last << 1) & 0xff; 12503055Sdanmcd } 12513055Sdanmcd 12523055Sdanmcd return (rc); 12533055Sdanmcd } 12543055Sdanmcd 12553055Sdanmcd /* 12563055Sdanmcd * Expand the diagnostic code into a message. 12573055Sdanmcd */ 12583055Sdanmcd void 12593055Sdanmcd print_diagnostic(FILE *file, uint16_t diagnostic) 12603055Sdanmcd { 12613055Sdanmcd /* Use two spaces so above strings can fit on the line. */ 1262*4064Smarkfen (void) fprintf(file, dgettext(TEXT_DOMAIN, 1263*4064Smarkfen " Diagnostic code %u: %s.\n"), 12643055Sdanmcd diagnostic, keysock_diag(diagnostic)); 12653055Sdanmcd } 12663055Sdanmcd 12673055Sdanmcd /* 12683055Sdanmcd * Prints the base PF_KEY message. 12693055Sdanmcd */ 12703055Sdanmcd void 12713055Sdanmcd print_sadb_msg(struct sadb_msg *samsg, time_t wallclock, boolean_t vflag) 12723055Sdanmcd { 12733055Sdanmcd if (wallclock != 0) 1274*4064Smarkfen printsatime(wallclock, dgettext(TEXT_DOMAIN, 1275*4064Smarkfen "%sTimestamp: %s\n"), "", NULL, 12763055Sdanmcd vflag); 12773055Sdanmcd 1278*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Base message (version %u) type "), 12793055Sdanmcd samsg->sadb_msg_version); 12803055Sdanmcd switch (samsg->sadb_msg_type) { 12813055Sdanmcd case SADB_RESERVED: 1282*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1283*4064Smarkfen "RESERVED (warning: set to 0)")); 12843055Sdanmcd break; 12853055Sdanmcd case SADB_GETSPI: 12863055Sdanmcd (void) printf("GETSPI"); 12873055Sdanmcd break; 12883055Sdanmcd case SADB_UPDATE: 12893055Sdanmcd (void) printf("UPDATE"); 12903055Sdanmcd break; 12913055Sdanmcd case SADB_ADD: 12923055Sdanmcd (void) printf("ADD"); 12933055Sdanmcd break; 12943055Sdanmcd case SADB_DELETE: 12953055Sdanmcd (void) printf("DELETE"); 12963055Sdanmcd break; 12973055Sdanmcd case SADB_GET: 12983055Sdanmcd (void) printf("GET"); 12993055Sdanmcd break; 13003055Sdanmcd case SADB_ACQUIRE: 13013055Sdanmcd (void) printf("ACQUIRE"); 13023055Sdanmcd break; 13033055Sdanmcd case SADB_REGISTER: 13043055Sdanmcd (void) printf("REGISTER"); 13053055Sdanmcd break; 13063055Sdanmcd case SADB_EXPIRE: 13073055Sdanmcd (void) printf("EXPIRE"); 13083055Sdanmcd break; 13093055Sdanmcd case SADB_FLUSH: 13103055Sdanmcd (void) printf("FLUSH"); 13113055Sdanmcd break; 13123055Sdanmcd case SADB_DUMP: 13133055Sdanmcd (void) printf("DUMP"); 13143055Sdanmcd break; 13153055Sdanmcd case SADB_X_PROMISC: 13163055Sdanmcd (void) printf("X_PROMISC"); 13173055Sdanmcd break; 13183055Sdanmcd case SADB_X_INVERSE_ACQUIRE: 13193055Sdanmcd (void) printf("X_INVERSE_ACQUIRE"); 13203055Sdanmcd break; 13213055Sdanmcd default: 1322*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1323*4064Smarkfen "Unknown (%u)"), samsg->sadb_msg_type); 13243055Sdanmcd break; 13253055Sdanmcd } 1326*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, ", SA type ")); 13273055Sdanmcd 13283055Sdanmcd switch (samsg->sadb_msg_satype) { 13293055Sdanmcd case SADB_SATYPE_UNSPEC: 1330*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "<unspecified/all>")); 13313055Sdanmcd break; 13323055Sdanmcd case SADB_SATYPE_AH: 13333055Sdanmcd (void) printf("AH"); 13343055Sdanmcd break; 13353055Sdanmcd case SADB_SATYPE_ESP: 13363055Sdanmcd (void) printf("ESP"); 13373055Sdanmcd break; 13383055Sdanmcd case SADB_SATYPE_RSVP: 13393055Sdanmcd (void) printf("RSVP"); 13403055Sdanmcd break; 13413055Sdanmcd case SADB_SATYPE_OSPFV2: 13423055Sdanmcd (void) printf("OSPFv2"); 13433055Sdanmcd break; 13443055Sdanmcd case SADB_SATYPE_RIPV2: 13453055Sdanmcd (void) printf("RIPv2"); 13463055Sdanmcd break; 13473055Sdanmcd case SADB_SATYPE_MIP: 1348*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Mobile IP")); 13493055Sdanmcd break; 13503055Sdanmcd default: 1351*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1352*4064Smarkfen "<unknown %u>"), samsg->sadb_msg_satype); 13533055Sdanmcd break; 13543055Sdanmcd } 13553055Sdanmcd 13563055Sdanmcd (void) printf(".\n"); 13573055Sdanmcd 13583055Sdanmcd if (samsg->sadb_msg_errno != 0) { 1359*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Error %s from PF_KEY.\n"), 13603055Sdanmcd strerror(samsg->sadb_msg_errno)); 13613055Sdanmcd print_diagnostic(stdout, samsg->sadb_x_msg_diagnostic); 13623055Sdanmcd } 13633055Sdanmcd 1364*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1365*4064Smarkfen "Message length %u bytes, seq=%u, pid=%u.\n"), 13663055Sdanmcd SADB_64TO8(samsg->sadb_msg_len), samsg->sadb_msg_seq, 13673055Sdanmcd samsg->sadb_msg_pid); 13683055Sdanmcd } 13693055Sdanmcd 13703055Sdanmcd /* 13713055Sdanmcd * Print the SA extension for PF_KEY. 13723055Sdanmcd */ 13733055Sdanmcd void 13743055Sdanmcd print_sa(char *prefix, struct sadb_sa *assoc) 13753055Sdanmcd { 13763055Sdanmcd if (assoc->sadb_sa_len != SADB_8TO64(sizeof (*assoc))) { 1377*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, 1378*4064Smarkfen "WARNING: SA info extension length (%u) is bad."), 13793055Sdanmcd SADB_64TO8(assoc->sadb_sa_len)); 13803055Sdanmcd } 13813055Sdanmcd 1382*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1383*4064Smarkfen "%sSADB_ASSOC spi=0x%x, replay=%u, state="), 13843055Sdanmcd prefix, ntohl(assoc->sadb_sa_spi), assoc->sadb_sa_replay); 13853055Sdanmcd switch (assoc->sadb_sa_state) { 13863055Sdanmcd case SADB_SASTATE_LARVAL: 1387*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "LARVAL")); 13883055Sdanmcd break; 13893055Sdanmcd case SADB_SASTATE_MATURE: 1390*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "MATURE")); 13913055Sdanmcd break; 13923055Sdanmcd case SADB_SASTATE_DYING: 1393*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "DYING")); 13943055Sdanmcd break; 13953055Sdanmcd case SADB_SASTATE_DEAD: 1396*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "DEAD")); 13973055Sdanmcd break; 13983055Sdanmcd default: 1399*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1400*4064Smarkfen "<unknown %u>"), assoc->sadb_sa_state); 14013055Sdanmcd } 14023055Sdanmcd 14033055Sdanmcd if (assoc->sadb_sa_auth != SADB_AALG_NONE) { 1404*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1405*4064Smarkfen "\n%sAuthentication algorithm = "), 14063055Sdanmcd prefix); 14073055Sdanmcd (void) dump_aalg(assoc->sadb_sa_auth, stdout); 14083055Sdanmcd } 14093055Sdanmcd 14103055Sdanmcd if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { 1411*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1412*4064Smarkfen "\n%sEncryption algorithm = "), prefix); 14133055Sdanmcd (void) dump_ealg(assoc->sadb_sa_encrypt, stdout); 14143055Sdanmcd } 14153055Sdanmcd 1416*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "\n%sflags=0x%x < "), prefix, 14173055Sdanmcd assoc->sadb_sa_flags); 14183055Sdanmcd if (assoc->sadb_sa_flags & SADB_SAFLAGS_PFS) 14193055Sdanmcd (void) printf("PFS "); 14203055Sdanmcd if (assoc->sadb_sa_flags & SADB_SAFLAGS_NOREPLAY) 14213055Sdanmcd (void) printf("NOREPLAY "); 14223055Sdanmcd 14233055Sdanmcd /* BEGIN Solaris-specific flags. */ 14243055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_USED) 14253055Sdanmcd (void) printf("X_USED "); 14263055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_UNIQUE) 14273055Sdanmcd (void) printf("X_UNIQUE "); 14283055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG1) 14293055Sdanmcd (void) printf("X_AALG1 "); 14303055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG2) 14313055Sdanmcd (void) printf("X_AALG2 "); 14323055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG1) 14333055Sdanmcd (void) printf("X_EALG1 "); 14343055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG2) 14353055Sdanmcd (void) printf("X_EALG2 "); 14363055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_LOC) 14373055Sdanmcd (void) printf("X_NATT_LOC "); 14383055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_REM) 14393055Sdanmcd (void) printf("X_NATT_REM "); 14403055Sdanmcd if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL) 14413055Sdanmcd (void) printf("X_TUNNEL "); 14423055Sdanmcd /* END Solaris-specific flags. */ 14433055Sdanmcd 14443055Sdanmcd (void) printf(">\n"); 14453055Sdanmcd } 14463055Sdanmcd 14473055Sdanmcd void 14483055Sdanmcd printsatime(int64_t lt, const char *msg, const char *pfx, const char *pfx2, 14493055Sdanmcd boolean_t vflag) 14503055Sdanmcd { 14513055Sdanmcd char tbuf[TBUF_SIZE]; /* For strftime() call. */ 14523055Sdanmcd const char *tp = tbuf; 14533055Sdanmcd time_t t = lt; 14543055Sdanmcd struct tm res; 14553055Sdanmcd 14563055Sdanmcd if (t != lt) { 14573055Sdanmcd if (lt > 0) 14583055Sdanmcd t = LONG_MAX; 14593055Sdanmcd else 14603055Sdanmcd t = LONG_MIN; 14613055Sdanmcd } 14623055Sdanmcd 14633055Sdanmcd if (strftime(tbuf, TBUF_SIZE, NULL, localtime_r(&t, &res)) == 0) 1464*4064Smarkfen tp = dgettext(TEXT_DOMAIN, "<time conversion failed>"); 14653055Sdanmcd (void) printf(msg, pfx, tp); 14663055Sdanmcd if (vflag && (pfx2 != NULL)) 1467*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1468*4064Smarkfen "%s\t(raw time value %llu)\n"), pfx2, lt); 14693055Sdanmcd } 14703055Sdanmcd 14713055Sdanmcd /* 14723055Sdanmcd * Print the SA lifetime information. (An SADB_EXT_LIFETIME_* extension.) 14733055Sdanmcd */ 14743055Sdanmcd void 14753055Sdanmcd print_lifetimes(time_t wallclock, struct sadb_lifetime *current, 14763055Sdanmcd struct sadb_lifetime *hard, struct sadb_lifetime *soft, boolean_t vflag) 14773055Sdanmcd { 14783055Sdanmcd int64_t scratch; 1479*4064Smarkfen char *soft_prefix = dgettext(TEXT_DOMAIN, "SLT: "); 1480*4064Smarkfen char *hard_prefix = dgettext(TEXT_DOMAIN, "HLT: "); 1481*4064Smarkfen char *current_prefix = dgettext(TEXT_DOMAIN, "CLT: "); 14823055Sdanmcd 14833055Sdanmcd if (current != NULL && 14843055Sdanmcd current->sadb_lifetime_len != SADB_8TO64(sizeof (*current))) { 1485*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, 1486*4064Smarkfen "WARNING: CURRENT lifetime extension length (%u) is bad."), 14873055Sdanmcd SADB_64TO8(current->sadb_lifetime_len)); 14883055Sdanmcd } 14893055Sdanmcd 14903055Sdanmcd if (hard != NULL && 14913055Sdanmcd hard->sadb_lifetime_len != SADB_8TO64(sizeof (*hard))) { 1492*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, "WARNING: HARD lifetime " 14933055Sdanmcd "extension length (%u) is bad."), 14943055Sdanmcd SADB_64TO8(hard->sadb_lifetime_len)); 14953055Sdanmcd } 14963055Sdanmcd 14973055Sdanmcd if (soft != NULL && 14983055Sdanmcd soft->sadb_lifetime_len != SADB_8TO64(sizeof (*soft))) { 1499*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, "WARNING: SOFT lifetime " 15003055Sdanmcd "extension length (%u) is bad."), 15013055Sdanmcd SADB_64TO8(soft->sadb_lifetime_len)); 15023055Sdanmcd } 15033055Sdanmcd 15043055Sdanmcd (void) printf(" LT: Lifetime information\n"); 15053055Sdanmcd 15063055Sdanmcd if (current != NULL) { 15073055Sdanmcd /* Express values as current values. */ 1508*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 15093055Sdanmcd "%s%llu bytes protected, %u allocations used.\n"), 15103055Sdanmcd current_prefix, current->sadb_lifetime_bytes, 15113055Sdanmcd current->sadb_lifetime_allocations); 15123055Sdanmcd printsatime(current->sadb_lifetime_addtime, 1513*4064Smarkfen dgettext(TEXT_DOMAIN, "%sSA added at time %s\n"), 15143055Sdanmcd current_prefix, current_prefix, vflag); 15153055Sdanmcd if (current->sadb_lifetime_usetime != 0) { 15163055Sdanmcd printsatime(current->sadb_lifetime_usetime, 1517*4064Smarkfen dgettext(TEXT_DOMAIN, 1518*4064Smarkfen "%sSA first used at time %s\n"), 15193055Sdanmcd current_prefix, current_prefix, vflag); 15203055Sdanmcd } 1521*4064Smarkfen printsatime(wallclock, dgettext(TEXT_DOMAIN, 1522*4064Smarkfen "%sTime now is %s\n"), current_prefix, current_prefix, 1523*4064Smarkfen vflag); 15243055Sdanmcd } 15253055Sdanmcd 15263055Sdanmcd if (soft != NULL) { 1527*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1528*4064Smarkfen "%sSoft lifetime information: "), 15293055Sdanmcd soft_prefix); 1530*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1531*4064Smarkfen "%llu bytes of lifetime, %u " 15323055Sdanmcd "allocations.\n"), soft->sadb_lifetime_bytes, 15333055Sdanmcd soft->sadb_lifetime_allocations); 1534*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1535*4064Smarkfen "%s%llu seconds of post-add lifetime.\n"), 15363055Sdanmcd soft_prefix, soft->sadb_lifetime_addtime); 1537*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1538*4064Smarkfen "%s%llu seconds of post-use lifetime.\n"), 15393055Sdanmcd soft_prefix, soft->sadb_lifetime_usetime); 15403055Sdanmcd /* If possible, express values as time remaining. */ 15413055Sdanmcd if (current != NULL) { 15423055Sdanmcd if (soft->sadb_lifetime_bytes != 0) 1543*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 15443055Sdanmcd "%s%llu more bytes can be protected.\n"), 15453055Sdanmcd soft_prefix, 15463055Sdanmcd (soft->sadb_lifetime_bytes > 15473055Sdanmcd current->sadb_lifetime_bytes) ? 15483055Sdanmcd (soft->sadb_lifetime_bytes - 15493055Sdanmcd current->sadb_lifetime_bytes) : (0)); 15503055Sdanmcd if (soft->sadb_lifetime_addtime != 0 || 15513055Sdanmcd (soft->sadb_lifetime_usetime != 0 && 15523055Sdanmcd current->sadb_lifetime_usetime != 0)) { 15533055Sdanmcd int64_t adddelta, usedelta; 15543055Sdanmcd 15553055Sdanmcd if (soft->sadb_lifetime_addtime != 0) { 15563055Sdanmcd adddelta = 15573055Sdanmcd current->sadb_lifetime_addtime + 15583055Sdanmcd soft->sadb_lifetime_addtime - 15593055Sdanmcd wallclock; 15603055Sdanmcd } else { 15613055Sdanmcd adddelta = TIME_MAX; 15623055Sdanmcd } 15633055Sdanmcd 15643055Sdanmcd if (soft->sadb_lifetime_usetime != 0 && 15653055Sdanmcd current->sadb_lifetime_usetime != 0) { 15663055Sdanmcd usedelta = 15673055Sdanmcd current->sadb_lifetime_usetime + 15683055Sdanmcd soft->sadb_lifetime_usetime - 15693055Sdanmcd wallclock; 15703055Sdanmcd } else { 15713055Sdanmcd usedelta = TIME_MAX; 15723055Sdanmcd } 15733055Sdanmcd (void) printf("%s", soft_prefix); 15743055Sdanmcd scratch = MIN(adddelta, usedelta); 15753055Sdanmcd if (scratch >= 0) { 1576*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1577*4064Smarkfen "Soft expiration occurs in %lld " 1578*4064Smarkfen "seconds, "), scratch); 15793055Sdanmcd } else { 1580*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 15813055Sdanmcd "Soft expiration occurred ")); 15823055Sdanmcd } 15833055Sdanmcd scratch += wallclock; 1584*4064Smarkfen printsatime(scratch, dgettext(TEXT_DOMAIN, 1585*4064Smarkfen "%sat %s.\n"), "", soft_prefix, vflag); 15863055Sdanmcd } 15873055Sdanmcd } 15883055Sdanmcd } 15893055Sdanmcd 15903055Sdanmcd if (hard != NULL) { 1591*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1592*4064Smarkfen "%sHard lifetime information: "), hard_prefix); 1593*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "%llu bytes of lifetime, " 15943055Sdanmcd "%u allocations.\n"), hard->sadb_lifetime_bytes, 15953055Sdanmcd hard->sadb_lifetime_allocations); 1596*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1597*4064Smarkfen "%s%llu seconds of post-add lifetime.\n"), 15983055Sdanmcd hard_prefix, hard->sadb_lifetime_addtime); 1599*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1600*4064Smarkfen "%s%llu seconds of post-use lifetime.\n"), 16013055Sdanmcd hard_prefix, hard->sadb_lifetime_usetime); 16023055Sdanmcd /* If possible, express values as time remaining. */ 16033055Sdanmcd if (current != NULL) { 16043055Sdanmcd if (hard->sadb_lifetime_bytes != 0) 1605*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 16063055Sdanmcd "%s%llu more bytes can be protected.\n"), 16073055Sdanmcd hard_prefix, 16083055Sdanmcd (hard->sadb_lifetime_bytes > 16093055Sdanmcd current->sadb_lifetime_bytes) ? 16103055Sdanmcd (hard->sadb_lifetime_bytes - 16113055Sdanmcd current->sadb_lifetime_bytes) : (0)); 16123055Sdanmcd if (hard->sadb_lifetime_addtime != 0 || 16133055Sdanmcd (hard->sadb_lifetime_usetime != 0 && 16143055Sdanmcd current->sadb_lifetime_usetime != 0)) { 16153055Sdanmcd int64_t adddelta, usedelta; 16163055Sdanmcd 16173055Sdanmcd if (hard->sadb_lifetime_addtime != 0) { 16183055Sdanmcd adddelta = 16193055Sdanmcd current->sadb_lifetime_addtime + 16203055Sdanmcd hard->sadb_lifetime_addtime - 16213055Sdanmcd wallclock; 16223055Sdanmcd } else { 16233055Sdanmcd adddelta = TIME_MAX; 16243055Sdanmcd } 16253055Sdanmcd 16263055Sdanmcd if (hard->sadb_lifetime_usetime != 0 && 16273055Sdanmcd current->sadb_lifetime_usetime != 0) { 16283055Sdanmcd usedelta = 16293055Sdanmcd current->sadb_lifetime_usetime + 16303055Sdanmcd hard->sadb_lifetime_usetime - 16313055Sdanmcd wallclock; 16323055Sdanmcd } else { 16333055Sdanmcd usedelta = TIME_MAX; 16343055Sdanmcd } 16353055Sdanmcd (void) printf("%s", hard_prefix); 16363055Sdanmcd scratch = MIN(adddelta, usedelta); 16373055Sdanmcd if (scratch >= 0) { 1638*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1639*4064Smarkfen "Hard expiration occurs in %lld " 1640*4064Smarkfen "seconds, "), scratch); 16413055Sdanmcd } else { 1642*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 16433055Sdanmcd "Hard expiration occured ")); 16443055Sdanmcd } 16453055Sdanmcd scratch += wallclock; 1646*4064Smarkfen printsatime(scratch, dgettext(TEXT_DOMAIN, 1647*4064Smarkfen "%sat %s.\n"), "", hard_prefix, vflag); 16483055Sdanmcd } 16493055Sdanmcd } 16503055Sdanmcd } 16513055Sdanmcd } 16523055Sdanmcd 16533055Sdanmcd /* 16543055Sdanmcd * Print an SADB_EXT_ADDRESS_* extension. 16553055Sdanmcd */ 16563055Sdanmcd void 16573055Sdanmcd print_address(char *prefix, struct sadb_address *addr) 16583055Sdanmcd { 16593055Sdanmcd struct protoent *pe; 16603055Sdanmcd 16613055Sdanmcd (void) printf("%s", prefix); 16623055Sdanmcd switch (addr->sadb_address_exttype) { 16633055Sdanmcd case SADB_EXT_ADDRESS_SRC: 1664*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Source address ")); 16653055Sdanmcd break; 16663055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 1667*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Inner source address ")); 16683055Sdanmcd break; 16693055Sdanmcd case SADB_EXT_ADDRESS_DST: 1670*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Destination address ")); 16713055Sdanmcd break; 16723055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 1673*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1674*4064Smarkfen "Inner destination address ")); 16753055Sdanmcd break; 16763055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 1677*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "NAT-T local address ")); 16783055Sdanmcd break; 16793055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 1680*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "NAT-T remote address ")); 16813055Sdanmcd break; 16823055Sdanmcd } 16833055Sdanmcd 1684*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1685*4064Smarkfen "(proto=%d"), addr->sadb_address_proto); 16863055Sdanmcd if (!nflag) { 16873055Sdanmcd if (addr->sadb_address_proto == 0) { 1688*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "/<unspecified>")); 16893055Sdanmcd } else if ((pe = getprotobynumber(addr->sadb_address_proto)) 16903055Sdanmcd != NULL) { 16913055Sdanmcd (void) printf("/%s", pe->p_name); 16923055Sdanmcd } else { 1693*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "/<unknown>")); 16943055Sdanmcd } 16953055Sdanmcd } 1696*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, ")\n%s"), prefix); 16973055Sdanmcd (void) dump_sockaddr((struct sockaddr *)(addr + 1), 16983055Sdanmcd addr->sadb_address_prefixlen, B_FALSE, stdout); 16993055Sdanmcd } 17003055Sdanmcd 17013055Sdanmcd /* 17023055Sdanmcd * Print an SADB_EXT_KEY extension. 17033055Sdanmcd */ 17043055Sdanmcd void 17053055Sdanmcd print_key(char *prefix, struct sadb_key *key) 17063055Sdanmcd { 17073055Sdanmcd (void) printf("%s", prefix); 17083055Sdanmcd 17093055Sdanmcd switch (key->sadb_key_exttype) { 17103055Sdanmcd case SADB_EXT_KEY_AUTH: 1711*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Authentication")); 17123055Sdanmcd break; 17133055Sdanmcd case SADB_EXT_KEY_ENCRYPT: 1714*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Encryption")); 17153055Sdanmcd break; 17163055Sdanmcd } 17173055Sdanmcd 1718*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, " key.\n%s"), prefix); 17193055Sdanmcd (void) dump_key((uint8_t *)(key + 1), key->sadb_key_bits, stdout); 17203055Sdanmcd (void) putchar('\n'); 17213055Sdanmcd } 17223055Sdanmcd 17233055Sdanmcd /* 17243055Sdanmcd * Print an SADB_EXT_IDENTITY_* extension. 17253055Sdanmcd */ 17263055Sdanmcd void 17273055Sdanmcd print_ident(char *prefix, struct sadb_ident *id) 17283055Sdanmcd { 17293055Sdanmcd boolean_t canprint = B_TRUE; 17303055Sdanmcd 17313055Sdanmcd (void) printf("%s", prefix); 17323055Sdanmcd switch (id->sadb_ident_exttype) { 17333055Sdanmcd case SADB_EXT_IDENTITY_SRC: 1734*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Source")); 17353055Sdanmcd break; 17363055Sdanmcd case SADB_EXT_IDENTITY_DST: 1737*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Destination")); 17383055Sdanmcd break; 17393055Sdanmcd } 17403055Sdanmcd 1741*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1742*4064Smarkfen " identity, uid=%d, type "), id->sadb_ident_id); 17433055Sdanmcd canprint = dump_sadb_idtype(id->sadb_ident_type, stdout, NULL); 17443055Sdanmcd (void) printf("\n%s", prefix); 17453055Sdanmcd if (canprint) 17463055Sdanmcd (void) printf("%s\n", (char *)(id + 1)); 17473055Sdanmcd else 1748*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "<cannot print>\n")); 17493055Sdanmcd } 17503055Sdanmcd 17513055Sdanmcd /* 17523055Sdanmcd * Print an SADB_SENSITIVITY extension. 17533055Sdanmcd */ 17543055Sdanmcd void 17553055Sdanmcd print_sens(char *prefix, struct sadb_sens *sens) 17563055Sdanmcd { 17573055Sdanmcd uint64_t *bitmap = (uint64_t *)(sens + 1); 17583055Sdanmcd int i; 17593055Sdanmcd 17603055Sdanmcd (void) printf( 1761*4064Smarkfen dgettext(TEXT_DOMAIN, 1762*4064Smarkfen "%sSensitivity DPD %d, sens level=%d, integ level=%d\n"), 17633055Sdanmcd prefix, sens->sadb_sens_dpd, sens->sadb_sens_sens_level, 17643055Sdanmcd sens->sadb_sens_integ_level); 17653055Sdanmcd for (i = 0; sens->sadb_sens_sens_len-- > 0; i++, bitmap++) 17663055Sdanmcd (void) printf( 1767*4064Smarkfen dgettext(TEXT_DOMAIN, 1768*4064Smarkfen "%s Sensitivity BM extended word %d 0x%llx\n"), i, *bitmap); 17693055Sdanmcd for (i = 0; sens->sadb_sens_integ_len-- > 0; i++, bitmap++) 17703055Sdanmcd (void) printf( 1771*4064Smarkfen dgettext(TEXT_DOMAIN, 1772*4064Smarkfen "%s Integrity BM extended word %d 0x%llx\n"), i, *bitmap); 17733055Sdanmcd } 17743055Sdanmcd 17753055Sdanmcd /* 17763055Sdanmcd * Print an SADB_EXT_PROPOSAL extension. 17773055Sdanmcd */ 17783055Sdanmcd void 17793055Sdanmcd print_prop(char *prefix, struct sadb_prop *prop) 17803055Sdanmcd { 17813055Sdanmcd struct sadb_comb *combs; 17823055Sdanmcd int i, numcombs; 17833055Sdanmcd 1784*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1785*4064Smarkfen "%sProposal, replay counter = %u.\n"), prefix, 17863055Sdanmcd prop->sadb_prop_replay); 17873055Sdanmcd 17883055Sdanmcd numcombs = prop->sadb_prop_len - SADB_8TO64(sizeof (*prop)); 17893055Sdanmcd numcombs /= SADB_8TO64(sizeof (*combs)); 17903055Sdanmcd 17913055Sdanmcd combs = (struct sadb_comb *)(prop + 1); 17923055Sdanmcd 17933055Sdanmcd for (i = 0; i < numcombs; i++) { 1794*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1795*4064Smarkfen "%s Combination #%u "), prefix, i + 1); 17963055Sdanmcd if (combs[i].sadb_comb_auth != SADB_AALG_NONE) { 1797*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1798*4064Smarkfen "Authentication = ")); 17993055Sdanmcd (void) dump_aalg(combs[i].sadb_comb_auth, stdout); 1800*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1801*4064Smarkfen " minbits=%u, maxbits=%u.\n%s "), 18023055Sdanmcd combs[i].sadb_comb_auth_minbits, 18033055Sdanmcd combs[i].sadb_comb_auth_maxbits, prefix); 18043055Sdanmcd } 18053055Sdanmcd 18063055Sdanmcd if (combs[i].sadb_comb_encrypt != SADB_EALG_NONE) { 1807*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "Encryption = ")); 18083055Sdanmcd (void) dump_ealg(combs[i].sadb_comb_encrypt, stdout); 1809*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1810*4064Smarkfen " minbits=%u, maxbits=%u.\n%s "), 18113055Sdanmcd combs[i].sadb_comb_encrypt_minbits, 18123055Sdanmcd combs[i].sadb_comb_encrypt_maxbits, prefix); 18133055Sdanmcd } 18143055Sdanmcd 1815*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "HARD: ")); 18163055Sdanmcd if (combs[i].sadb_comb_hard_allocations) 1817*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "alloc=%u "), 18183055Sdanmcd combs[i].sadb_comb_hard_allocations); 18193055Sdanmcd if (combs[i].sadb_comb_hard_bytes) 1820*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "bytes=%llu "), 18213055Sdanmcd combs[i].sadb_comb_hard_bytes); 18223055Sdanmcd if (combs[i].sadb_comb_hard_addtime) 1823*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1824*4064Smarkfen "post-add secs=%llu "), 18253055Sdanmcd combs[i].sadb_comb_hard_addtime); 18263055Sdanmcd if (combs[i].sadb_comb_hard_usetime) 1827*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1828*4064Smarkfen "post-use secs=%llu"), 18293055Sdanmcd combs[i].sadb_comb_hard_usetime); 18303055Sdanmcd 1831*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "\n%s SOFT: "), prefix); 18323055Sdanmcd if (combs[i].sadb_comb_soft_allocations) 1833*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "alloc=%u "), 18343055Sdanmcd combs[i].sadb_comb_soft_allocations); 18353055Sdanmcd if (combs[i].sadb_comb_soft_bytes) 1836*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "bytes=%llu "), 18373055Sdanmcd combs[i].sadb_comb_soft_bytes); 18383055Sdanmcd if (combs[i].sadb_comb_soft_addtime) 1839*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1840*4064Smarkfen "post-add secs=%llu "), 18413055Sdanmcd combs[i].sadb_comb_soft_addtime); 18423055Sdanmcd if (combs[i].sadb_comb_soft_usetime) 1843*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1844*4064Smarkfen "post-use secs=%llu"), 18453055Sdanmcd combs[i].sadb_comb_soft_usetime); 18463055Sdanmcd (void) putchar('\n'); 18473055Sdanmcd } 18483055Sdanmcd } 18493055Sdanmcd 18503055Sdanmcd /* 18513055Sdanmcd * Print an extended proposal (SADB_X_EXT_EPROP). 18523055Sdanmcd */ 18533055Sdanmcd void 18543055Sdanmcd print_eprop(char *prefix, struct sadb_prop *eprop) 18553055Sdanmcd { 18563055Sdanmcd uint64_t *sofar; 18573055Sdanmcd struct sadb_x_ecomb *ecomb; 18583055Sdanmcd struct sadb_x_algdesc *algdesc; 18593055Sdanmcd int i, j; 18603055Sdanmcd 1861*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1862*4064Smarkfen "%sExtended Proposal, replay counter = %u, "), prefix, 1863*4064Smarkfen eprop->sadb_prop_replay); 1864*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "number of combinations = %u.\n"), 18653055Sdanmcd eprop->sadb_x_prop_numecombs); 18663055Sdanmcd 18673055Sdanmcd sofar = (uint64_t *)(eprop + 1); 18683055Sdanmcd ecomb = (struct sadb_x_ecomb *)sofar; 18693055Sdanmcd 18703055Sdanmcd for (i = 0; i < eprop->sadb_x_prop_numecombs; ) { 1871*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1872*4064Smarkfen "%s Extended combination #%u:\n"), prefix, ++i); 18733055Sdanmcd 1874*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "%s HARD: "), prefix); 1875*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "alloc=%u, "), 18763055Sdanmcd ecomb->sadb_x_ecomb_hard_allocations); 1877*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "bytes=%llu, "), 18783055Sdanmcd ecomb->sadb_x_ecomb_hard_bytes); 1879*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "post-add secs=%llu, "), 18803055Sdanmcd ecomb->sadb_x_ecomb_hard_addtime); 1881*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "post-use secs=%llu\n"), 18823055Sdanmcd ecomb->sadb_x_ecomb_hard_usetime); 18833055Sdanmcd 1884*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "%s SOFT: "), prefix); 1885*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "alloc=%u, "), 18863055Sdanmcd ecomb->sadb_x_ecomb_soft_allocations); 1887*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "bytes=%llu, "), 18883055Sdanmcd ecomb->sadb_x_ecomb_soft_bytes); 1889*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "post-add secs=%llu, "), 18903055Sdanmcd ecomb->sadb_x_ecomb_soft_addtime); 1891*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "post-use secs=%llu\n"), 18923055Sdanmcd ecomb->sadb_x_ecomb_soft_usetime); 18933055Sdanmcd 18943055Sdanmcd sofar = (uint64_t *)(ecomb + 1); 18953055Sdanmcd algdesc = (struct sadb_x_algdesc *)sofar; 18963055Sdanmcd 18973055Sdanmcd for (j = 0; j < ecomb->sadb_x_ecomb_numalgs; ) { 1898*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1899*4064Smarkfen "%s Alg #%u "), prefix, ++j); 19003055Sdanmcd switch (algdesc->sadb_x_algdesc_satype) { 19013055Sdanmcd case SADB_SATYPE_ESP: 1902*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1903*4064Smarkfen "for ESP ")); 19043055Sdanmcd break; 19053055Sdanmcd case SADB_SATYPE_AH: 1906*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "for AH ")); 19073055Sdanmcd break; 19083055Sdanmcd default: 1909*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1910*4064Smarkfen "for satype=%d "), 19113055Sdanmcd algdesc->sadb_x_algdesc_satype); 19123055Sdanmcd } 19133055Sdanmcd switch (algdesc->sadb_x_algdesc_algtype) { 19143055Sdanmcd case SADB_X_ALGTYPE_CRYPT: 1915*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1916*4064Smarkfen "Encryption = ")); 19173055Sdanmcd (void) dump_ealg(algdesc->sadb_x_algdesc_alg, 19183055Sdanmcd stdout); 19193055Sdanmcd break; 19203055Sdanmcd case SADB_X_ALGTYPE_AUTH: 1921*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1922*4064Smarkfen "Authentication = ")); 19233055Sdanmcd (void) dump_aalg(algdesc->sadb_x_algdesc_alg, 19243055Sdanmcd stdout); 19253055Sdanmcd break; 19263055Sdanmcd default: 1927*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1928*4064Smarkfen "algtype(%d) = alg(%d)"), 19293055Sdanmcd algdesc->sadb_x_algdesc_algtype, 19303055Sdanmcd algdesc->sadb_x_algdesc_alg); 19313055Sdanmcd break; 19323055Sdanmcd } 19333055Sdanmcd 1934*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1935*4064Smarkfen " minbits=%u, maxbits=%u.\n"), 19363055Sdanmcd algdesc->sadb_x_algdesc_minbits, 19373055Sdanmcd algdesc->sadb_x_algdesc_maxbits); 19383055Sdanmcd 19393055Sdanmcd sofar = (uint64_t *)(++algdesc); 19403055Sdanmcd } 19413055Sdanmcd ecomb = (struct sadb_x_ecomb *)sofar; 19423055Sdanmcd } 19433055Sdanmcd } 19443055Sdanmcd 19453055Sdanmcd /* 19463055Sdanmcd * Print an SADB_EXT_SUPPORTED extension. 19473055Sdanmcd */ 19483055Sdanmcd void 19493055Sdanmcd print_supp(char *prefix, struct sadb_supported *supp) 19503055Sdanmcd { 19513055Sdanmcd struct sadb_alg *algs; 19523055Sdanmcd int i, numalgs; 19533055Sdanmcd 1954*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "%sSupported "), prefix); 19553055Sdanmcd switch (supp->sadb_supported_exttype) { 19563055Sdanmcd case SADB_EXT_SUPPORTED_AUTH: 1957*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "authentication")); 19583055Sdanmcd break; 19593055Sdanmcd case SADB_EXT_SUPPORTED_ENCRYPT: 1960*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, "encryption")); 19613055Sdanmcd break; 19623055Sdanmcd } 1963*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, " algorithms.\n")); 19643055Sdanmcd 19653055Sdanmcd algs = (struct sadb_alg *)(supp + 1); 19663055Sdanmcd numalgs = supp->sadb_supported_len - SADB_8TO64(sizeof (*supp)); 19673055Sdanmcd numalgs /= SADB_8TO64(sizeof (*algs)); 19683055Sdanmcd for (i = 0; i < numalgs; i++) { 19693055Sdanmcd (void) printf("%s", prefix); 19703055Sdanmcd switch (supp->sadb_supported_exttype) { 19713055Sdanmcd case SADB_EXT_SUPPORTED_AUTH: 19723055Sdanmcd (void) dump_aalg(algs[i].sadb_alg_id, stdout); 19733055Sdanmcd break; 19743055Sdanmcd case SADB_EXT_SUPPORTED_ENCRYPT: 19753055Sdanmcd (void) dump_ealg(algs[i].sadb_alg_id, stdout); 19763055Sdanmcd break; 19773055Sdanmcd } 1978*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1979*4064Smarkfen " minbits=%u, maxbits=%u, ivlen=%u.\n"), 19803055Sdanmcd algs[i].sadb_alg_minbits, algs[i].sadb_alg_maxbits, 19813055Sdanmcd algs[i].sadb_alg_ivlen); 19823055Sdanmcd } 19833055Sdanmcd } 19843055Sdanmcd 19853055Sdanmcd /* 19863055Sdanmcd * Print an SADB_EXT_SPIRANGE extension. 19873055Sdanmcd */ 19883055Sdanmcd void 19893055Sdanmcd print_spirange(char *prefix, struct sadb_spirange *range) 19903055Sdanmcd { 1991*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 1992*4064Smarkfen "%sSPI Range, min=0x%x, max=0x%x\n"), prefix, 19933055Sdanmcd htonl(range->sadb_spirange_min), 19943055Sdanmcd htonl(range->sadb_spirange_max)); 19953055Sdanmcd } 19963055Sdanmcd 19973055Sdanmcd /* 19983055Sdanmcd * Print an SADB_X_EXT_KM_COOKIE extension. 19993055Sdanmcd */ 20003055Sdanmcd 20013055Sdanmcd void 20023055Sdanmcd print_kmc(char *prefix, struct sadb_x_kmc *kmc) 20033055Sdanmcd { 20043055Sdanmcd char *cookie_label; 20053055Sdanmcd 20063055Sdanmcd if ((cookie_label = kmc_lookup_by_cookie(kmc->sadb_x_kmc_cookie)) == 20073055Sdanmcd NULL) 2008*4064Smarkfen cookie_label = dgettext(TEXT_DOMAIN, "<Label not found.>"); 20093055Sdanmcd 2010*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 2011*4064Smarkfen "%sProtocol %u, cookie=\"%s\" (%u)\n"), prefix, 20123055Sdanmcd kmc->sadb_x_kmc_proto, cookie_label, kmc->sadb_x_kmc_cookie); 20133055Sdanmcd } 20143055Sdanmcd 20153055Sdanmcd /* 20163055Sdanmcd * Take a PF_KEY message pointed to buffer and print it. Useful for DUMP 20173055Sdanmcd * and GET. 20183055Sdanmcd */ 20193055Sdanmcd void 20203055Sdanmcd print_samsg(uint64_t *buffer, boolean_t want_timestamp, boolean_t vflag) 20213055Sdanmcd { 20223055Sdanmcd uint64_t *current; 20233055Sdanmcd struct sadb_msg *samsg = (struct sadb_msg *)buffer; 20243055Sdanmcd struct sadb_ext *ext; 20253055Sdanmcd struct sadb_lifetime *currentlt = NULL, *hardlt = NULL, *softlt = NULL; 20263055Sdanmcd int i; 20273055Sdanmcd time_t wallclock; 20283055Sdanmcd 20293055Sdanmcd (void) time(&wallclock); 20303055Sdanmcd 20313055Sdanmcd print_sadb_msg(samsg, want_timestamp ? wallclock : 0, vflag); 20323055Sdanmcd current = (uint64_t *)(samsg + 1); 20333055Sdanmcd while (current - buffer < samsg->sadb_msg_len) { 20343055Sdanmcd int lenbytes; 20353055Sdanmcd 20363055Sdanmcd ext = (struct sadb_ext *)current; 20373055Sdanmcd lenbytes = SADB_64TO8(ext->sadb_ext_len); 20383055Sdanmcd switch (ext->sadb_ext_type) { 20393055Sdanmcd case SADB_EXT_SA: 2040*4064Smarkfen print_sa(dgettext(TEXT_DOMAIN, 2041*4064Smarkfen "SA: "), (struct sadb_sa *)current); 20423055Sdanmcd break; 20433055Sdanmcd /* 20443055Sdanmcd * Pluck out lifetimes and print them at the end. This is 20453055Sdanmcd * to show relative lifetimes. 20463055Sdanmcd */ 20473055Sdanmcd case SADB_EXT_LIFETIME_CURRENT: 20483055Sdanmcd currentlt = (struct sadb_lifetime *)current; 20493055Sdanmcd break; 20503055Sdanmcd case SADB_EXT_LIFETIME_HARD: 20513055Sdanmcd hardlt = (struct sadb_lifetime *)current; 20523055Sdanmcd break; 20533055Sdanmcd case SADB_EXT_LIFETIME_SOFT: 20543055Sdanmcd softlt = (struct sadb_lifetime *)current; 20553055Sdanmcd break; 20563055Sdanmcd 20573055Sdanmcd case SADB_EXT_ADDRESS_SRC: 2058*4064Smarkfen print_address(dgettext(TEXT_DOMAIN, "SRC: "), 20593055Sdanmcd (struct sadb_address *)current); 20603055Sdanmcd break; 20613055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 2062*4064Smarkfen print_address(dgettext(TEXT_DOMAIN, "INS: "), 20633055Sdanmcd (struct sadb_address *)current); 20643055Sdanmcd break; 20653055Sdanmcd case SADB_EXT_ADDRESS_DST: 2066*4064Smarkfen print_address(dgettext(TEXT_DOMAIN, "DST: "), 20673055Sdanmcd (struct sadb_address *)current); 20683055Sdanmcd break; 20693055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 2070*4064Smarkfen print_address(dgettext(TEXT_DOMAIN, "IND: "), 20713055Sdanmcd (struct sadb_address *)current); 20723055Sdanmcd break; 20733055Sdanmcd case SADB_EXT_KEY_AUTH: 2074*4064Smarkfen print_key(dgettext(TEXT_DOMAIN, 2075*4064Smarkfen "AKY: "), (struct sadb_key *)current); 20763055Sdanmcd break; 20773055Sdanmcd case SADB_EXT_KEY_ENCRYPT: 2078*4064Smarkfen print_key(dgettext(TEXT_DOMAIN, 2079*4064Smarkfen "EKY: "), (struct sadb_key *)current); 20803055Sdanmcd break; 20813055Sdanmcd case SADB_EXT_IDENTITY_SRC: 2082*4064Smarkfen print_ident(dgettext(TEXT_DOMAIN, "SID: "), 20833055Sdanmcd (struct sadb_ident *)current); 20843055Sdanmcd break; 20853055Sdanmcd case SADB_EXT_IDENTITY_DST: 2086*4064Smarkfen print_ident(dgettext(TEXT_DOMAIN, "DID: "), 20873055Sdanmcd (struct sadb_ident *)current); 20883055Sdanmcd break; 20893055Sdanmcd case SADB_EXT_SENSITIVITY: 2090*4064Smarkfen print_sens(dgettext(TEXT_DOMAIN, "SNS: "), 20913055Sdanmcd (struct sadb_sens *)current); 20923055Sdanmcd break; 20933055Sdanmcd case SADB_EXT_PROPOSAL: 2094*4064Smarkfen print_prop(dgettext(TEXT_DOMAIN, "PRP: "), 20953055Sdanmcd (struct sadb_prop *)current); 20963055Sdanmcd break; 20973055Sdanmcd case SADB_EXT_SUPPORTED_AUTH: 2098*4064Smarkfen print_supp(dgettext(TEXT_DOMAIN, "SUA: "), 20993055Sdanmcd (struct sadb_supported *)current); 21003055Sdanmcd break; 21013055Sdanmcd case SADB_EXT_SUPPORTED_ENCRYPT: 2102*4064Smarkfen print_supp(dgettext(TEXT_DOMAIN, "SUE: "), 21033055Sdanmcd (struct sadb_supported *)current); 21043055Sdanmcd break; 21053055Sdanmcd case SADB_EXT_SPIRANGE: 2106*4064Smarkfen print_spirange(dgettext(TEXT_DOMAIN, "SPR: "), 21073055Sdanmcd (struct sadb_spirange *)current); 21083055Sdanmcd break; 21093055Sdanmcd case SADB_X_EXT_EPROP: 2110*4064Smarkfen print_eprop(dgettext(TEXT_DOMAIN, "EPR: "), 21113055Sdanmcd (struct sadb_prop *)current); 21123055Sdanmcd break; 21133055Sdanmcd case SADB_X_EXT_KM_COOKIE: 2114*4064Smarkfen print_kmc(dgettext(TEXT_DOMAIN, "KMC: "), 21153055Sdanmcd (struct sadb_x_kmc *)current); 21163055Sdanmcd break; 21173055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 2118*4064Smarkfen print_address(dgettext(TEXT_DOMAIN, "NRM: "), 21193055Sdanmcd (struct sadb_address *)current); 21203055Sdanmcd break; 21213055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 2122*4064Smarkfen print_address(dgettext(TEXT_DOMAIN, "NLC: "), 21233055Sdanmcd (struct sadb_address *)current); 21243055Sdanmcd break; 21253055Sdanmcd default: 2126*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 21273055Sdanmcd "UNK: Unknown ext. %d, len %d.\n"), 21283055Sdanmcd ext->sadb_ext_type, lenbytes); 21293055Sdanmcd for (i = 0; i < ext->sadb_ext_len; i++) 2130*4064Smarkfen (void) printf(dgettext(TEXT_DOMAIN, 2131*4064Smarkfen "UNK: 0x%llx\n"), ((uint64_t *)ext)[i]); 21323055Sdanmcd break; 21333055Sdanmcd } 21343055Sdanmcd current += (lenbytes == 0) ? 21353055Sdanmcd SADB_8TO64(sizeof (struct sadb_ext)) : ext->sadb_ext_len; 21363055Sdanmcd } 21373055Sdanmcd /* 21383055Sdanmcd * Print lifetimes NOW. 21393055Sdanmcd */ 21403055Sdanmcd if (currentlt != NULL || hardlt != NULL || softlt != NULL) 21413055Sdanmcd print_lifetimes(wallclock, currentlt, hardlt, softlt, vflag); 21423055Sdanmcd 21433055Sdanmcd if (current - buffer != samsg->sadb_msg_len) { 2144*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, "WARNING: insufficient buffer " 21453055Sdanmcd "space or corrupt message.")); 21463055Sdanmcd } 21473055Sdanmcd 21483055Sdanmcd (void) fflush(stdout); /* Make sure our message is out there. */ 21493055Sdanmcd } 21503055Sdanmcd 21513055Sdanmcd /* 21523055Sdanmcd * save_XXX functions are used when "saving" the SA tables to either a 21533055Sdanmcd * file or standard output. They use the dump_XXX functions where needed, 21543055Sdanmcd * but mostly they use the rparseXXX functions. 21553055Sdanmcd */ 21563055Sdanmcd 21573055Sdanmcd /* 21583055Sdanmcd * Print save information for a lifetime extension. 21593055Sdanmcd * 21603055Sdanmcd * NOTE : It saves the lifetime in absolute terms. For example, if you 21613055Sdanmcd * had a hard_usetime of 60 seconds, you'll save it as 60 seconds, even though 21623055Sdanmcd * there may have been 59 seconds burned off the clock. 21633055Sdanmcd */ 21643055Sdanmcd boolean_t 21653055Sdanmcd save_lifetime(struct sadb_lifetime *lifetime, FILE *ofile) 21663055Sdanmcd { 21673055Sdanmcd char *prefix; 21683055Sdanmcd 21693055Sdanmcd prefix = (lifetime->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT) ? 21703055Sdanmcd "soft" : "hard"; 21713055Sdanmcd 21723055Sdanmcd if (putc('\t', ofile) == EOF) 21733055Sdanmcd return (B_FALSE); 21743055Sdanmcd 21753055Sdanmcd if (lifetime->sadb_lifetime_allocations != 0 && fprintf(ofile, 21763055Sdanmcd "%s_alloc %u ", prefix, lifetime->sadb_lifetime_allocations) < 0) 21773055Sdanmcd return (B_FALSE); 21783055Sdanmcd 21793055Sdanmcd if (lifetime->sadb_lifetime_bytes != 0 && fprintf(ofile, 21803055Sdanmcd "%s_bytes %llu ", prefix, lifetime->sadb_lifetime_bytes) < 0) 21813055Sdanmcd return (B_FALSE); 21823055Sdanmcd 21833055Sdanmcd if (lifetime->sadb_lifetime_addtime != 0 && fprintf(ofile, 21843055Sdanmcd "%s_addtime %llu ", prefix, lifetime->sadb_lifetime_addtime) < 0) 21853055Sdanmcd return (B_FALSE); 21863055Sdanmcd 21873055Sdanmcd if (lifetime->sadb_lifetime_usetime != 0 && fprintf(ofile, 21883055Sdanmcd "%s_usetime %llu ", prefix, lifetime->sadb_lifetime_usetime) < 0) 21893055Sdanmcd return (B_FALSE); 21903055Sdanmcd 21913055Sdanmcd return (B_TRUE); 21923055Sdanmcd } 21933055Sdanmcd 21943055Sdanmcd /* 21953055Sdanmcd * Print save information for an address extension. 21963055Sdanmcd */ 21973055Sdanmcd boolean_t 21983055Sdanmcd save_address(struct sadb_address *addr, FILE *ofile) 21993055Sdanmcd { 22003055Sdanmcd char *printable_addr, buf[INET6_ADDRSTRLEN]; 22013055Sdanmcd const char *prefix, *pprefix; 22023055Sdanmcd struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(addr + 1); 22033055Sdanmcd struct sockaddr_in *sin = (struct sockaddr_in *)sin6; 22043055Sdanmcd int af = sin->sin_family; 22053055Sdanmcd 22063055Sdanmcd /* 22073055Sdanmcd * Address-family reality check. 22083055Sdanmcd */ 22093055Sdanmcd if (af != AF_INET6 && af != AF_INET) 22103055Sdanmcd return (B_FALSE); 22113055Sdanmcd 22123055Sdanmcd switch (addr->sadb_address_exttype) { 22133055Sdanmcd case SADB_EXT_ADDRESS_SRC: 22143055Sdanmcd prefix = "src"; 22153055Sdanmcd pprefix = "sport"; 22163055Sdanmcd break; 22173055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 22183055Sdanmcd prefix = "isrc"; 22193055Sdanmcd pprefix = "isport"; 22203055Sdanmcd break; 22213055Sdanmcd case SADB_EXT_ADDRESS_DST: 22223055Sdanmcd prefix = "dst"; 22233055Sdanmcd pprefix = "dport"; 22243055Sdanmcd break; 22253055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 22263055Sdanmcd prefix = "idst"; 22273055Sdanmcd pprefix = "idport"; 22283055Sdanmcd break; 22293055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 22303055Sdanmcd prefix = "nat_loc "; 22313055Sdanmcd pprefix = "nat_lport"; 22323055Sdanmcd break; 22333055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 22343055Sdanmcd prefix = "nat_rem "; 22353055Sdanmcd pprefix = "nat_rport"; 22363055Sdanmcd break; 22373055Sdanmcd } 22383055Sdanmcd 22393055Sdanmcd if (fprintf(ofile, " %s ", prefix) < 0) 22403055Sdanmcd return (B_FALSE); 22413055Sdanmcd 22423055Sdanmcd /* 22433055Sdanmcd * Do not do address-to-name translation, given that we live in 22443055Sdanmcd * an age of names that explode into many addresses. 22453055Sdanmcd */ 22463055Sdanmcd printable_addr = (char *)inet_ntop(af, 22473055Sdanmcd (af == AF_INET) ? (char *)&sin->sin_addr : (char *)&sin6->sin6_addr, 22483055Sdanmcd buf, sizeof (buf)); 22493055Sdanmcd if (printable_addr == NULL) 2250*4064Smarkfen printable_addr = "Invalid IP address."; 22513055Sdanmcd if (fprintf(ofile, "%s", printable_addr) < 0) 22523055Sdanmcd return (B_FALSE); 22533055Sdanmcd if (addr->sadb_address_prefixlen != 0 && 22543055Sdanmcd !((addr->sadb_address_prefixlen == 32 && af == AF_INET) || 22553055Sdanmcd (addr->sadb_address_prefixlen == 128 && af == AF_INET6))) { 22563055Sdanmcd if (fprintf(ofile, "/%d", addr->sadb_address_prefixlen) < 0) 22573055Sdanmcd return (B_FALSE); 22583055Sdanmcd } 22593055Sdanmcd 22603055Sdanmcd /* 22613055Sdanmcd * The port is in the same position for struct sockaddr_in and 22623055Sdanmcd * struct sockaddr_in6. We exploit that property here. 22633055Sdanmcd */ 22643055Sdanmcd if ((pprefix != NULL) && (sin->sin_port != 0)) 22653055Sdanmcd (void) fprintf(ofile, " %s %d", pprefix, ntohs(sin->sin_port)); 22663055Sdanmcd 22673055Sdanmcd return (B_TRUE); 22683055Sdanmcd } 22693055Sdanmcd 22703055Sdanmcd /* 22713055Sdanmcd * Print save information for a key extension. Returns whether writing 22723055Sdanmcd * to the specified output file was successful or not. 22733055Sdanmcd */ 22743055Sdanmcd boolean_t 22753055Sdanmcd save_key(struct sadb_key *key, FILE *ofile) 22763055Sdanmcd { 22773055Sdanmcd char *prefix; 22783055Sdanmcd 22793055Sdanmcd if (putc('\t', ofile) == EOF) 22803055Sdanmcd return (B_FALSE); 22813055Sdanmcd 22823055Sdanmcd prefix = (key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ? "auth" : "encr"; 22833055Sdanmcd 22843055Sdanmcd if (fprintf(ofile, "%skey ", prefix) < 0) 22853055Sdanmcd return (B_FALSE); 22863055Sdanmcd 22873055Sdanmcd if (dump_key((uint8_t *)(key + 1), key->sadb_key_bits, ofile) == -1) 22883055Sdanmcd return (B_FALSE); 22893055Sdanmcd 22903055Sdanmcd return (B_TRUE); 22913055Sdanmcd } 22923055Sdanmcd 22933055Sdanmcd /* 22943055Sdanmcd * Print save information for an identity extension. 22953055Sdanmcd */ 22963055Sdanmcd boolean_t 22973055Sdanmcd save_ident(struct sadb_ident *ident, FILE *ofile) 22983055Sdanmcd { 22993055Sdanmcd char *prefix; 23003055Sdanmcd 23013055Sdanmcd if (putc('\t', ofile) == EOF) 23023055Sdanmcd return (B_FALSE); 23033055Sdanmcd 23043055Sdanmcd prefix = (ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ? "src" : 23053055Sdanmcd "dst"; 23063055Sdanmcd 23073055Sdanmcd if (fprintf(ofile, "%sidtype %s ", prefix, 23083055Sdanmcd rparseidtype(ident->sadb_ident_type)) < 0) 23093055Sdanmcd return (B_FALSE); 23103055Sdanmcd 23113055Sdanmcd if (ident->sadb_ident_type == SADB_X_IDENTTYPE_DN || 23123055Sdanmcd ident->sadb_ident_type == SADB_X_IDENTTYPE_GN) { 2313*4064Smarkfen if (fprintf(ofile, dgettext(TEXT_DOMAIN, 2314*4064Smarkfen "<can-not-print>")) < 0) 23153055Sdanmcd return (B_FALSE); 23163055Sdanmcd } else { 23173055Sdanmcd if (fprintf(ofile, "%s", (char *)(ident + 1)) < 0) 23183055Sdanmcd return (B_FALSE); 23193055Sdanmcd } 23203055Sdanmcd 23213055Sdanmcd return (B_TRUE); 23223055Sdanmcd } 23233055Sdanmcd 23243055Sdanmcd /* 23253055Sdanmcd * "Save" a security association to an output file. 23263055Sdanmcd * 2327*4064Smarkfen * NOTE the lack of calls to dgettext() because I'm outputting parseable stuff. 23283055Sdanmcd * ALSO NOTE that if you change keywords (see parsecmd()), you'll have to 23293055Sdanmcd * change them here as well. 23303055Sdanmcd */ 23313055Sdanmcd void 23323055Sdanmcd save_assoc(uint64_t *buffer, FILE *ofile) 23333055Sdanmcd { 2334*4064Smarkfen int terrno; 23353055Sdanmcd int seen_proto = 0; 23363055Sdanmcd uint64_t *current; 23373055Sdanmcd struct sadb_address *addr; 23383055Sdanmcd struct sadb_msg *samsg = (struct sadb_msg *)buffer; 23393055Sdanmcd struct sadb_ext *ext; 23403055Sdanmcd 2341*4064Smarkfen #define tidyup() \ 2342*4064Smarkfen terrno = errno; (void) fclose(ofile); errno = terrno; \ 2343*4064Smarkfen interactive = B_FALSE 2344*4064Smarkfen 2345*4064Smarkfen #define savenl() if (fputs(" \\\n", ofile) == EOF) \ 2346*4064Smarkfen { bail(dgettext(TEXT_DOMAIN, "savenl")); } 23473055Sdanmcd 23483055Sdanmcd if (fputs("# begin assoc\n", ofile) == EOF) 2349*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2350*4064Smarkfen "save_assoc: Opening comment of SA")); 23513055Sdanmcd if (fprintf(ofile, "add %s ", rparsesatype(samsg->sadb_msg_satype)) < 0) 2352*4064Smarkfen bail(dgettext(TEXT_DOMAIN, "save_assoc: First line of SA")); 23533055Sdanmcd savenl(); 23543055Sdanmcd 23553055Sdanmcd current = (uint64_t *)(samsg + 1); 23563055Sdanmcd while (current - buffer < samsg->sadb_msg_len) { 23573055Sdanmcd struct sadb_sa *assoc; 23583055Sdanmcd 23593055Sdanmcd ext = (struct sadb_ext *)current; 23603055Sdanmcd switch (ext->sadb_ext_type) { 23613055Sdanmcd case SADB_EXT_SA: 23623055Sdanmcd assoc = (struct sadb_sa *)ext; 23633055Sdanmcd if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) { 23643055Sdanmcd if (fprintf(ofile, "# WARNING: SA was dying " 23653055Sdanmcd "or dead.\n") < 0) { 2366*4064Smarkfen tidyup(); 2367*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2368*4064Smarkfen "save_assoc: fprintf not mature")); 23693055Sdanmcd } 23703055Sdanmcd } 23713055Sdanmcd if (fprintf(ofile, " spi 0x%x ", 2372*4064Smarkfen ntohl(assoc->sadb_sa_spi)) < 0) { 2373*4064Smarkfen tidyup(); 2374*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2375*4064Smarkfen "save_assoc: fprintf spi")); 2376*4064Smarkfen } 23773055Sdanmcd if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { 23783055Sdanmcd if (fprintf(ofile, "encr_alg %s ", 23793055Sdanmcd rparsealg(assoc->sadb_sa_encrypt, 2380*4064Smarkfen IPSEC_PROTO_ESP)) < 0) { 2381*4064Smarkfen tidyup(); 2382*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2383*4064Smarkfen "save_assoc: fprintf encrypt")); 2384*4064Smarkfen } 23853055Sdanmcd } 23863055Sdanmcd if (assoc->sadb_sa_auth != SADB_AALG_NONE) { 23873055Sdanmcd if (fprintf(ofile, "auth_alg %s ", 23883055Sdanmcd rparsealg(assoc->sadb_sa_auth, 2389*4064Smarkfen IPSEC_PROTO_AH)) < 0) { 2390*4064Smarkfen tidyup(); 2391*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2392*4064Smarkfen "save_assoc: fprintf auth")); 2393*4064Smarkfen } 23943055Sdanmcd } 23953055Sdanmcd if (fprintf(ofile, "replay %d ", 2396*4064Smarkfen assoc->sadb_sa_replay) < 0) { 2397*4064Smarkfen tidyup(); 2398*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2399*4064Smarkfen "save_assoc: fprintf replay")); 2400*4064Smarkfen } 24013055Sdanmcd if (assoc->sadb_sa_flags & (SADB_X_SAFLAGS_NATT_LOC | 24023055Sdanmcd SADB_X_SAFLAGS_NATT_REM)) { 2403*4064Smarkfen if (fprintf(ofile, "encap udp") < 0) { 2404*4064Smarkfen tidyup(); 2405*4064Smarkfen bail(dgettext(TEXT_DOMAIN, 2406*4064Smarkfen "save_assoc: fprintf encap")); 2407*4064Smarkfen } 24083055Sdanmcd } 24093055Sdanmcd savenl(); 24103055Sdanmcd break; 24113055Sdanmcd case SADB_EXT_LIFETIME_HARD: 24123055Sdanmcd case SADB_EXT_LIFETIME_SOFT: 2413*4064Smarkfen if (!save_lifetime((struct sadb_lifetime *)ext, 2414*4064Smarkfen ofile)) { 2415*4064Smarkfen tidyup(); 2416*4064Smarkfen bail(dgettext(TEXT_DOMAIN, "save_lifetime")); 2417*4064Smarkfen } 24183055Sdanmcd savenl(); 24193055Sdanmcd break; 24203055Sdanmcd case SADB_EXT_ADDRESS_SRC: 24213055Sdanmcd case SADB_EXT_ADDRESS_DST: 24223055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_SRC: 24233055Sdanmcd case SADB_X_EXT_ADDRESS_INNER_DST: 24243055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_REM: 24253055Sdanmcd case SADB_X_EXT_ADDRESS_NATT_LOC: 24263055Sdanmcd addr = (struct sadb_address *)ext; 24273055Sdanmcd if (!seen_proto && addr->sadb_address_proto) { 24283055Sdanmcd (void) fprintf(ofile, " proto %d", 24293055Sdanmcd addr->sadb_address_proto); 24303055Sdanmcd savenl(); 24313055Sdanmcd seen_proto = 1; 24323055Sdanmcd } 2433*4064Smarkfen if (!save_address(addr, ofile)) { 2434*4064Smarkfen tidyup(); 2435*4064Smarkfen bail(dgettext(TEXT_DOMAIN, "save_address")); 2436*4064Smarkfen } 24373055Sdanmcd savenl(); 24383055Sdanmcd break; 24393055Sdanmcd case SADB_EXT_KEY_AUTH: 24403055Sdanmcd case SADB_EXT_KEY_ENCRYPT: 2441*4064Smarkfen if (!save_key((struct sadb_key *)ext, ofile)) { 2442*4064Smarkfen tidyup(); 2443*4064Smarkfen bail(dgettext(TEXT_DOMAIN, "save_address")); 2444*4064Smarkfen } 24453055Sdanmcd savenl(); 24463055Sdanmcd break; 24473055Sdanmcd case SADB_EXT_IDENTITY_SRC: 24483055Sdanmcd case SADB_EXT_IDENTITY_DST: 2449*4064Smarkfen if (!save_ident((struct sadb_ident *)ext, ofile)) { 2450*4064Smarkfen tidyup(); 2451*4064Smarkfen bail(dgettext(TEXT_DOMAIN, "save_address")); 2452*4064Smarkfen } 24533055Sdanmcd savenl(); 24543055Sdanmcd break; 24553055Sdanmcd case SADB_EXT_SENSITIVITY: 24563055Sdanmcd default: 24573055Sdanmcd /* Skip over irrelevant extensions. */ 24583055Sdanmcd break; 24593055Sdanmcd } 24603055Sdanmcd current += ext->sadb_ext_len; 24613055Sdanmcd } 24623055Sdanmcd 2463*4064Smarkfen if (fputs(dgettext(TEXT_DOMAIN, "\n# end assoc\n\n"), ofile) == EOF) { 2464*4064Smarkfen tidyup(); 2465*4064Smarkfen bail(dgettext(TEXT_DOMAIN, "save_assoc: last fputs")); 2466*4064Smarkfen } 24673055Sdanmcd } 24683055Sdanmcd 24693055Sdanmcd /* 24703055Sdanmcd * Open the output file for the "save" command. 24713055Sdanmcd */ 24723055Sdanmcd FILE * 24733055Sdanmcd opensavefile(char *filename) 24743055Sdanmcd { 24753055Sdanmcd int fd; 24763055Sdanmcd FILE *retval; 24773055Sdanmcd struct stat buf; 24783055Sdanmcd 24793055Sdanmcd /* 24803055Sdanmcd * If the user specifies "-" or doesn't give a filename, then 24813055Sdanmcd * dump to stdout. Make sure to document the dangers of files 24823055Sdanmcd * that are NFS, directing your output to strange places, etc. 24833055Sdanmcd */ 24843055Sdanmcd if (filename == NULL || strcmp("-", filename) == 0) 24853055Sdanmcd return (stdout); 24863055Sdanmcd 24873055Sdanmcd /* 24883055Sdanmcd * open the file with the create bits set. Since I check for 24893055Sdanmcd * real UID == root in main(), I won't worry about the ownership 24903055Sdanmcd * problem. 24913055Sdanmcd */ 24923055Sdanmcd fd = open(filename, O_WRONLY | O_EXCL | O_CREAT | O_TRUNC, S_IRUSR); 24933055Sdanmcd if (fd == -1) { 24943055Sdanmcd if (errno != EEXIST) 2495*4064Smarkfen bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN, 2496*4064Smarkfen "open error"), 24973055Sdanmcd strerror(errno)); 24983055Sdanmcd fd = open(filename, O_WRONLY | O_TRUNC, 0); 24993055Sdanmcd if (fd == -1) 2500*4064Smarkfen bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN, 2501*4064Smarkfen "open error"), strerror(errno)); 25023055Sdanmcd if (fstat(fd, &buf) == -1) { 25033055Sdanmcd (void) close(fd); 25043055Sdanmcd bail_msg("%s fstat: %s", filename, strerror(errno)); 25053055Sdanmcd } 25063055Sdanmcd if (S_ISREG(buf.st_mode) && 25073055Sdanmcd ((buf.st_mode & S_IAMB) != S_IRUSR)) { 2508*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, 2509*4064Smarkfen "WARNING: Save file already exists with " 2510*4064Smarkfen "permission %o."), buf.st_mode & S_IAMB); 2511*4064Smarkfen warnx(dgettext(TEXT_DOMAIN, 2512*4064Smarkfen "Normal users may be able to read IPsec " 2513*4064Smarkfen "keying material.")); 25143055Sdanmcd } 25153055Sdanmcd } 25163055Sdanmcd 25173055Sdanmcd /* Okay, we have an FD. Assign it to a stdio FILE pointer. */ 25183055Sdanmcd retval = fdopen(fd, "w"); 25193055Sdanmcd if (retval == NULL) { 25203055Sdanmcd (void) close(fd); 2521*4064Smarkfen bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN, 2522*4064Smarkfen "fdopen error"), strerror(errno)); 25233055Sdanmcd } 25243055Sdanmcd return (retval); 25253055Sdanmcd } 25263055Sdanmcd 25273055Sdanmcd const char * 25283055Sdanmcd do_inet_ntop(const void *addr, char *cp, size_t size) 25293055Sdanmcd { 25303055Sdanmcd boolean_t isv4; 25313055Sdanmcd struct in6_addr *inaddr6 = (struct in6_addr *)addr; 25323055Sdanmcd struct in_addr inaddr; 25333055Sdanmcd 25343055Sdanmcd if ((isv4 = IN6_IS_ADDR_V4MAPPED(inaddr6)) == B_TRUE) { 25353055Sdanmcd IN6_V4MAPPED_TO_INADDR(inaddr6, &inaddr); 25363055Sdanmcd } 25373055Sdanmcd 25383055Sdanmcd return (inet_ntop(isv4 ? AF_INET : AF_INET6, 25393055Sdanmcd isv4 ? (void *)&inaddr : inaddr6, cp, size)); 25403055Sdanmcd } 25413055Sdanmcd 25423055Sdanmcd char numprint[NBUF_SIZE]; 25433055Sdanmcd 25443055Sdanmcd /* 25453055Sdanmcd * Parse and reverse parse a specific SA type (AH, ESP, etc.). 25463055Sdanmcd */ 25473055Sdanmcd static struct typetable { 25483055Sdanmcd char *type; 25493055Sdanmcd int token; 25503055Sdanmcd } type_table[] = { 25513055Sdanmcd {"all", SADB_SATYPE_UNSPEC}, 25523055Sdanmcd {"ah", SADB_SATYPE_AH}, 25533055Sdanmcd {"esp", SADB_SATYPE_ESP}, 25543055Sdanmcd /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */ 25553055Sdanmcd {NULL, 0} /* Token value is irrelevant for this entry. */ 25563055Sdanmcd }; 25573055Sdanmcd 25583055Sdanmcd char * 25593055Sdanmcd rparsesatype(int type) 25603055Sdanmcd { 25613055Sdanmcd struct typetable *tt = type_table; 25623055Sdanmcd 25633055Sdanmcd while (tt->type != NULL && type != tt->token) 25643055Sdanmcd tt++; 25653055Sdanmcd 25663055Sdanmcd if (tt->type == NULL) { 25673055Sdanmcd (void) snprintf(numprint, NBUF_SIZE, "%d", type); 25683055Sdanmcd } else { 25693055Sdanmcd return (tt->type); 25703055Sdanmcd } 25713055Sdanmcd 25723055Sdanmcd return (numprint); 25733055Sdanmcd } 25743055Sdanmcd 25753055Sdanmcd 25763055Sdanmcd /* 25773055Sdanmcd * Return a string containing the name of the specified numerical algorithm 25783055Sdanmcd * identifier. 25793055Sdanmcd */ 25803055Sdanmcd char * 25813055Sdanmcd rparsealg(uint8_t alg, int proto_num) 25823055Sdanmcd { 25833055Sdanmcd static struct ipsecalgent *holder = NULL; /* we're single-threaded */ 25843055Sdanmcd 25853055Sdanmcd if (holder != NULL) 25863055Sdanmcd freeipsecalgent(holder); 25873055Sdanmcd 25883055Sdanmcd holder = getipsecalgbynum(alg, proto_num, NULL); 25893055Sdanmcd if (holder == NULL) { 25903055Sdanmcd (void) snprintf(numprint, NBUF_SIZE, "%d", alg); 25913055Sdanmcd return (numprint); 25923055Sdanmcd } 25933055Sdanmcd 25943055Sdanmcd return (*(holder->a_names)); 25953055Sdanmcd } 25963055Sdanmcd 25973055Sdanmcd /* 25983055Sdanmcd * Parse and reverse parse out a source/destination ID type. 25993055Sdanmcd */ 26003055Sdanmcd static struct idtypes { 26013055Sdanmcd char *idtype; 26023055Sdanmcd uint8_t retval; 26033055Sdanmcd } idtypes[] = { 26043055Sdanmcd {"prefix", SADB_IDENTTYPE_PREFIX}, 26053055Sdanmcd {"fqdn", SADB_IDENTTYPE_FQDN}, 26063055Sdanmcd {"domain", SADB_IDENTTYPE_FQDN}, 26073055Sdanmcd {"domainname", SADB_IDENTTYPE_FQDN}, 26083055Sdanmcd {"user_fqdn", SADB_IDENTTYPE_USER_FQDN}, 26093055Sdanmcd {"mailbox", SADB_IDENTTYPE_USER_FQDN}, 26103055Sdanmcd {"der_dn", SADB_X_IDENTTYPE_DN}, 26113055Sdanmcd {"der_gn", SADB_X_IDENTTYPE_GN}, 26123055Sdanmcd {NULL, 0} 26133055Sdanmcd }; 26143055Sdanmcd 26153055Sdanmcd char * 26163055Sdanmcd rparseidtype(uint16_t type) 26173055Sdanmcd { 26183055Sdanmcd struct idtypes *idp; 26193055Sdanmcd 26203055Sdanmcd for (idp = idtypes; idp->idtype != NULL; idp++) { 26213055Sdanmcd if (type == idp->retval) 26223055Sdanmcd return (idp->idtype); 26233055Sdanmcd } 26243055Sdanmcd 26253055Sdanmcd (void) snprintf(numprint, NBUF_SIZE, "%d", type); 26263055Sdanmcd return (numprint); 26273055Sdanmcd } 2628