diff options
Diffstat (limited to 'usr/src/lib/libipsecutil/common/ipsec_util.c')
-rw-r--r-- | usr/src/lib/libipsecutil/common/ipsec_util.c | 1418 |
1 files changed, 1403 insertions, 15 deletions
diff --git a/usr/src/lib/libipsecutil/common/ipsec_util.c b/usr/src/lib/libipsecutil/common/ipsec_util.c index 2a40f50202..3674c71fdc 100644 --- a/usr/src/lib/libipsecutil/common/ipsec_util.c +++ b/usr/src/lib/libipsecutil/common/ipsec_util.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -118,13 +117,15 @@ bail_msg(char *fmt, ...) */ int -dump_sockaddr(struct sockaddr *sa, boolean_t addr_only, FILE *where) +dump_sockaddr(struct sockaddr *sa, uint8_t prefixlen, boolean_t addr_only, + FILE *where) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; char *printable_addr, *protocol; uint8_t *addrptr; - char storage[INET6_ADDRSTRLEN]; + /* Add 4 chars to hold '/nnn' for prefixes. */ + char storage[INET6_ADDRSTRLEN + 4]; uint16_t port; boolean_t unspec; struct hostent *hp; @@ -157,7 +158,14 @@ dump_sockaddr(struct sockaddr *sa, boolean_t addr_only, FILE *where) NULL) { printable_addr = gettext("<inet_ntop() failed>"); } else { + char prefix[5]; /* "/nnn" with terminator. */ + + (void) snprintf(prefix, sizeof (prefix), "/%d", prefixlen); printable_addr = storage; + if (prefixlen != 0) { + (void) strlcat(printable_addr, prefix, + sizeof (storage)); + } } if (addr_only) { if (fprintf(where, "%s", printable_addr) < 0) @@ -983,6 +991,10 @@ spdsock_diag(int diagnostic) return (gettext("number of block sizes inconsistent")); case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN: return (gettext("invalid mechanism name length")); + case SPD_DIAGNOSTIC_NOT_GLOBAL_OP: + return (gettext("operation not applicable to all policies")); + case SPD_DIAGNOSTIC_NO_TUNNEL_SELECTORS: + return (gettext("using selectors on a transport-mode tunnel")); default: return (gettext("unknown diagnostic")); } @@ -999,7 +1011,7 @@ const char * keysock_diag(int diagnostic) { switch (diagnostic) { - case SADB_X_DIAGNOSTIC_NONE: + case SADB_X_DIAGNOSTIC_NONE: return (gettext("No diagnostic")); case SADB_X_DIAGNOSTIC_UNKNOWN_MSG: return (gettext("Unknown message type")); @@ -1020,7 +1032,7 @@ keysock_diag(int diagnostic) case SADB_X_DIAGNOSTIC_BAD_DST_AF: return (gettext("Bad destination address family")); case SADB_X_DIAGNOSTIC_BAD_PROXY_AF: - return (gettext("Bad proxy address family")); + return (gettext("Bad inner-source address family")); case SADB_X_DIAGNOSTIC_AF_MISMATCH: return (gettext("Source/destination address family mismatch")); case SADB_X_DIAGNOSTIC_BAD_SRC: @@ -1104,20 +1116,1396 @@ keysock_diag(int diagnostic) case SADB_X_DIAGNOSTIC_DUPLICATE_KMC: return (gettext("Duplicate key management cookie")); case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC: - return (gettext("Missing NATT local address")); + return (gettext("Missing NAT-T local address")); case SADB_X_DIAGNOSTIC_MISSING_NATT_REM: - return (gettext("Missing NATT remote address")); + return (gettext("Missing NAT-T remote address")); case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC: - return (gettext("Duplicate NATT local address")); + return (gettext("Duplicate NAT-T local address")); case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM: - return (gettext("Duplicate NATT remote address")); + return (gettext("Duplicate NAT-T remote address")); case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC: - return (gettext("Malformed NATT local address")); + return (gettext("Malformed NAT-T local address")); case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM: - return (gettext("Malformed NATT remote address")); + return (gettext("Malformed NAT-T remote address")); case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS: - return (gettext("Duplicate NATT ports")); + return (gettext("Duplicate NAT-T ports")); + case SADB_X_DIAGNOSTIC_MISSING_INNER_SRC: + return (gettext("Missing inner source address")); + case SADB_X_DIAGNOSTIC_MISSING_INNER_DST: + return (gettext("Missing inner destination address")); + case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_SRC: + return (gettext("Duplicate inner source address")); + case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_DST: + return (gettext("Duplicate inner destination address")); + case SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC: + return (gettext("Malformed inner source address")); + case SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST: + return (gettext("Malformed inner destination address")); + case SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC: + return (gettext("Invalid inner-source prefix length ")); + case SADB_X_DIAGNOSTIC_PREFIX_INNER_DST: + return (gettext("Invalid inner-destination prefix length")); + case SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF: + return (gettext("Bad inner-destination address family")); + case SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH: + return (gettext( + "Inner source/destination address family mismatch")); + case SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF: + return (gettext("Bad NAT-T remote address family")); + case SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF: + return (gettext("Bad NAT-T local address family")); + case SADB_X_DIAGNOSTIC_PROTO_MISMATCH: + return (gettext("Source/desination protocol mismatch")); + case SADB_X_DIAGNOSTIC_INNER_PROTO_MISMATCH: + return (gettext("Inner source/desination protocol mismatch")); + case SADB_X_DIAGNOSTIC_DUAL_PORT_SETS: + return (gettext("Both inner ports and outer ports are set")); default: return (gettext("Unknown diagnostic code")); } } + +/* + * Convert an IPv6 mask to a prefix len. I assume all IPv6 masks are + * contiguous, so I stop at the first zero bit! + */ +int +in_masktoprefix(uint8_t *mask, boolean_t is_v4mapped) +{ + int rc = 0; + uint8_t last; + int limit = IPV6_ABITS; + + if (is_v4mapped) { + mask += ((IPV6_ABITS - IP_ABITS)/8); + limit = IP_ABITS; + } + + while (*mask == 0xff) { + rc += 8; + if (rc == limit) + return (limit); + mask++; + } + + last = *mask; + while (last != 0) { + rc++; + last = (last << 1) & 0xff; + } + + return (rc); +} + +/* + * Expand the diagnostic code into a message. + */ +void +print_diagnostic(FILE *file, uint16_t diagnostic) +{ + /* Use two spaces so above strings can fit on the line. */ + (void) fprintf(file, gettext(" Diagnostic code %u: %s.\n"), + diagnostic, keysock_diag(diagnostic)); +} + +/* + * Prints the base PF_KEY message. + */ +void +print_sadb_msg(struct sadb_msg *samsg, time_t wallclock, boolean_t vflag) +{ + if (wallclock != 0) + printsatime(wallclock, gettext("%sTimestamp: %s\n"), "", NULL, + vflag); + + (void) printf(gettext("Base message (version %u) type "), + samsg->sadb_msg_version); + switch (samsg->sadb_msg_type) { + case SADB_RESERVED: + (void) printf(gettext("RESERVED (warning: set to 0)")); + break; + case SADB_GETSPI: + (void) printf("GETSPI"); + break; + case SADB_UPDATE: + (void) printf("UPDATE"); + break; + case SADB_ADD: + (void) printf("ADD"); + break; + case SADB_DELETE: + (void) printf("DELETE"); + break; + case SADB_GET: + (void) printf("GET"); + break; + case SADB_ACQUIRE: + (void) printf("ACQUIRE"); + break; + case SADB_REGISTER: + (void) printf("REGISTER"); + break; + case SADB_EXPIRE: + (void) printf("EXPIRE"); + break; + case SADB_FLUSH: + (void) printf("FLUSH"); + break; + case SADB_DUMP: + (void) printf("DUMP"); + break; + case SADB_X_PROMISC: + (void) printf("X_PROMISC"); + break; + case SADB_X_INVERSE_ACQUIRE: + (void) printf("X_INVERSE_ACQUIRE"); + break; + default: + (void) printf(gettext("Unknown (%u)"), samsg->sadb_msg_type); + break; + } + (void) printf(gettext(", SA type ")); + + switch (samsg->sadb_msg_satype) { + case SADB_SATYPE_UNSPEC: + (void) printf(gettext("<unspecified/all>")); + break; + case SADB_SATYPE_AH: + (void) printf("AH"); + break; + case SADB_SATYPE_ESP: + (void) printf("ESP"); + break; + case SADB_SATYPE_RSVP: + (void) printf("RSVP"); + break; + case SADB_SATYPE_OSPFV2: + (void) printf("OSPFv2"); + break; + case SADB_SATYPE_RIPV2: + (void) printf("RIPv2"); + break; + case SADB_SATYPE_MIP: + (void) printf(gettext("Mobile IP")); + break; + default: + (void) printf(gettext("<unknown %u>"), samsg->sadb_msg_satype); + break; + } + + (void) printf(".\n"); + + if (samsg->sadb_msg_errno != 0) { + (void) printf(gettext("Error %s from PF_KEY.\n"), + strerror(samsg->sadb_msg_errno)); + print_diagnostic(stdout, samsg->sadb_x_msg_diagnostic); + } + + (void) printf(gettext("Message length %u bytes, seq=%u, pid=%u.\n"), + SADB_64TO8(samsg->sadb_msg_len), samsg->sadb_msg_seq, + samsg->sadb_msg_pid); +} + +/* + * Print the SA extension for PF_KEY. + */ +void +print_sa(char *prefix, struct sadb_sa *assoc) +{ + if (assoc->sadb_sa_len != SADB_8TO64(sizeof (*assoc))) { + warnx(gettext("WARNING: SA info extension length (%u) is bad."), + SADB_64TO8(assoc->sadb_sa_len)); + } + + (void) printf(gettext("%sSADB_ASSOC spi=0x%x, replay=%u, state="), + prefix, ntohl(assoc->sadb_sa_spi), assoc->sadb_sa_replay); + switch (assoc->sadb_sa_state) { + case SADB_SASTATE_LARVAL: + (void) printf(gettext("LARVAL")); + break; + case SADB_SASTATE_MATURE: + (void) printf(gettext("MATURE")); + break; + case SADB_SASTATE_DYING: + (void) printf(gettext("DYING")); + break; + case SADB_SASTATE_DEAD: + (void) printf(gettext("DEAD")); + break; + default: + (void) printf(gettext("<unknown %u>"), assoc->sadb_sa_state); + } + + if (assoc->sadb_sa_auth != SADB_AALG_NONE) { + (void) printf(gettext("\n%sAuthentication algorithm = "), + prefix); + (void) dump_aalg(assoc->sadb_sa_auth, stdout); + } + + if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { + (void) printf(gettext("\n%sEncryption algorithm = "), prefix); + (void) dump_ealg(assoc->sadb_sa_encrypt, stdout); + } + + (void) printf(gettext("\n%sflags=0x%x < "), prefix, + assoc->sadb_sa_flags); + if (assoc->sadb_sa_flags & SADB_SAFLAGS_PFS) + (void) printf("PFS "); + if (assoc->sadb_sa_flags & SADB_SAFLAGS_NOREPLAY) + (void) printf("NOREPLAY "); + + /* BEGIN Solaris-specific flags. */ + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_USED) + (void) printf("X_USED "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_UNIQUE) + (void) printf("X_UNIQUE "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG1) + (void) printf("X_AALG1 "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG2) + (void) printf("X_AALG2 "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG1) + (void) printf("X_EALG1 "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG2) + (void) printf("X_EALG2 "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_LOC) + (void) printf("X_NATT_LOC "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_REM) + (void) printf("X_NATT_REM "); + if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL) + (void) printf("X_TUNNEL "); + /* END Solaris-specific flags. */ + + (void) printf(">\n"); +} + +void +printsatime(int64_t lt, const char *msg, const char *pfx, const char *pfx2, + boolean_t vflag) +{ + char tbuf[TBUF_SIZE]; /* For strftime() call. */ + const char *tp = tbuf; + time_t t = lt; + struct tm res; + + if (t != lt) { + if (lt > 0) + t = LONG_MAX; + else + t = LONG_MIN; + } + + if (strftime(tbuf, TBUF_SIZE, NULL, localtime_r(&t, &res)) == 0) + tp = gettext("<time conversion failed>"); + (void) printf(msg, pfx, tp); + if (vflag && (pfx2 != NULL)) + (void) printf(gettext("%s\t(raw time value %llu)\n"), pfx2, lt); +} + +/* + * Print the SA lifetime information. (An SADB_EXT_LIFETIME_* extension.) + */ +void +print_lifetimes(time_t wallclock, struct sadb_lifetime *current, + struct sadb_lifetime *hard, struct sadb_lifetime *soft, boolean_t vflag) +{ + int64_t scratch; + char *soft_prefix = gettext("SLT: "); + char *hard_prefix = gettext("HLT: "); + char *current_prefix = gettext("CLT: "); + + if (current != NULL && + current->sadb_lifetime_len != SADB_8TO64(sizeof (*current))) { + warnx(gettext("WARNING: CURRENT lifetime extension length " + "(%u) is bad."), + SADB_64TO8(current->sadb_lifetime_len)); + } + + if (hard != NULL && + hard->sadb_lifetime_len != SADB_8TO64(sizeof (*hard))) { + warnx(gettext("WARNING: HARD lifetime " + "extension length (%u) is bad."), + SADB_64TO8(hard->sadb_lifetime_len)); + } + + if (soft != NULL && + soft->sadb_lifetime_len != SADB_8TO64(sizeof (*soft))) { + warnx(gettext("WARNING: SOFT lifetime " + "extension length (%u) is bad."), + SADB_64TO8(soft->sadb_lifetime_len)); + } + + (void) printf(" LT: Lifetime information\n"); + + if (current != NULL) { + /* Express values as current values. */ + (void) printf(gettext( + "%s%llu bytes protected, %u allocations used.\n"), + current_prefix, current->sadb_lifetime_bytes, + current->sadb_lifetime_allocations); + printsatime(current->sadb_lifetime_addtime, + gettext("%sSA added at time %s\n"), + current_prefix, current_prefix, vflag); + if (current->sadb_lifetime_usetime != 0) { + printsatime(current->sadb_lifetime_usetime, + gettext("%sSA first used at time %s\n"), + current_prefix, current_prefix, vflag); + } + printsatime(wallclock, gettext("%sTime now is %s\n"), + current_prefix, current_prefix, vflag); + } + + if (soft != NULL) { + (void) printf(gettext("%sSoft lifetime information: "), + soft_prefix); + (void) printf(gettext("%llu bytes of lifetime, %u " + "allocations.\n"), soft->sadb_lifetime_bytes, + soft->sadb_lifetime_allocations); + (void) printf(gettext("%s%llu seconds of post-add lifetime.\n"), + soft_prefix, soft->sadb_lifetime_addtime); + (void) printf(gettext("%s%llu seconds of post-use lifetime.\n"), + soft_prefix, soft->sadb_lifetime_usetime); + /* If possible, express values as time remaining. */ + if (current != NULL) { + if (soft->sadb_lifetime_bytes != 0) + (void) printf(gettext( + "%s%llu more bytes can be protected.\n"), + soft_prefix, + (soft->sadb_lifetime_bytes > + current->sadb_lifetime_bytes) ? + (soft->sadb_lifetime_bytes - + current->sadb_lifetime_bytes) : (0)); + if (soft->sadb_lifetime_addtime != 0 || + (soft->sadb_lifetime_usetime != 0 && + current->sadb_lifetime_usetime != 0)) { + int64_t adddelta, usedelta; + + if (soft->sadb_lifetime_addtime != 0) { + adddelta = + current->sadb_lifetime_addtime + + soft->sadb_lifetime_addtime - + wallclock; + } else { + adddelta = TIME_MAX; + } + + if (soft->sadb_lifetime_usetime != 0 && + current->sadb_lifetime_usetime != 0) { + usedelta = + current->sadb_lifetime_usetime + + soft->sadb_lifetime_usetime - + wallclock; + } else { + usedelta = TIME_MAX; + } + (void) printf("%s", soft_prefix); + scratch = MIN(adddelta, usedelta); + if (scratch >= 0) { + (void) printf(gettext("Soft expiration " + "occurs in %lld seconds, "), + scratch); + } else { + (void) printf(gettext( + "Soft expiration occurred ")); + } + scratch += wallclock; + printsatime(scratch, gettext("%sat %s.\n"), "", + soft_prefix, vflag); + } + } + } + + if (hard != NULL) { + (void) printf(gettext("%sHard lifetime information: "), + hard_prefix); + (void) printf(gettext("%llu bytes of lifetime, " + "%u allocations.\n"), hard->sadb_lifetime_bytes, + hard->sadb_lifetime_allocations); + (void) printf(gettext("%s%llu seconds of post-add lifetime.\n"), + hard_prefix, hard->sadb_lifetime_addtime); + (void) printf(gettext("%s%llu seconds of post-use lifetime.\n"), + hard_prefix, hard->sadb_lifetime_usetime); + /* If possible, express values as time remaining. */ + if (current != NULL) { + if (hard->sadb_lifetime_bytes != 0) + (void) printf(gettext( + "%s%llu more bytes can be protected.\n"), + hard_prefix, + (hard->sadb_lifetime_bytes > + current->sadb_lifetime_bytes) ? + (hard->sadb_lifetime_bytes - + current->sadb_lifetime_bytes) : (0)); + if (hard->sadb_lifetime_addtime != 0 || + (hard->sadb_lifetime_usetime != 0 && + current->sadb_lifetime_usetime != 0)) { + int64_t adddelta, usedelta; + + if (hard->sadb_lifetime_addtime != 0) { + adddelta = + current->sadb_lifetime_addtime + + hard->sadb_lifetime_addtime - + wallclock; + } else { + adddelta = TIME_MAX; + } + + if (hard->sadb_lifetime_usetime != 0 && + current->sadb_lifetime_usetime != 0) { + usedelta = + current->sadb_lifetime_usetime + + hard->sadb_lifetime_usetime - + wallclock; + } else { + usedelta = TIME_MAX; + } + (void) printf("%s", hard_prefix); + scratch = MIN(adddelta, usedelta); + if (scratch >= 0) { + (void) printf(gettext("Hard expiration " + "occurs in %lld seconds, "), + scratch); + } else { + (void) printf(gettext( + "Hard expiration occured ")); + } + scratch += wallclock; + printsatime(scratch, gettext("%sat %s.\n"), "", + hard_prefix, vflag); + } + } + } +} + +/* + * Print an SADB_EXT_ADDRESS_* extension. + */ +void +print_address(char *prefix, struct sadb_address *addr) +{ + struct protoent *pe; + + (void) printf("%s", prefix); + switch (addr->sadb_address_exttype) { + case SADB_EXT_ADDRESS_SRC: + (void) printf(gettext("Source address ")); + break; + case SADB_X_EXT_ADDRESS_INNER_SRC: + (void) printf(gettext("Inner source address ")); + break; + case SADB_EXT_ADDRESS_DST: + (void) printf(gettext("Destination address ")); + break; + case SADB_X_EXT_ADDRESS_INNER_DST: + (void) printf(gettext("Inner destination address ")); + break; + case SADB_X_EXT_ADDRESS_NATT_LOC: + (void) printf(gettext("NATT local address ")); + break; + case SADB_X_EXT_ADDRESS_NATT_REM: + (void) printf(gettext("NATT remote address ")); + break; + } + + (void) printf(gettext("(proto=%d"), addr->sadb_address_proto); + if (!nflag) { + if (addr->sadb_address_proto == 0) { + (void) printf(gettext("/<unspecified>")); + } else if ((pe = getprotobynumber(addr->sadb_address_proto)) + != NULL) { + (void) printf("/%s", pe->p_name); + } else { + (void) printf(gettext("/<unknown>")); + } + } + (void) printf(gettext(")\n%s"), prefix); + (void) dump_sockaddr((struct sockaddr *)(addr + 1), + addr->sadb_address_prefixlen, B_FALSE, stdout); +} + +/* + * Print an SADB_EXT_KEY extension. + */ +void +print_key(char *prefix, struct sadb_key *key) +{ + (void) printf("%s", prefix); + + switch (key->sadb_key_exttype) { + case SADB_EXT_KEY_AUTH: + (void) printf(gettext("Authentication")); + break; + case SADB_EXT_KEY_ENCRYPT: + (void) printf(gettext("Encryption")); + break; + } + + (void) printf(gettext(" key.\n%s"), prefix); + (void) dump_key((uint8_t *)(key + 1), key->sadb_key_bits, stdout); + (void) putchar('\n'); +} + +/* + * Print an SADB_EXT_IDENTITY_* extension. + */ +void +print_ident(char *prefix, struct sadb_ident *id) +{ + boolean_t canprint = B_TRUE; + + (void) printf("%s", prefix); + switch (id->sadb_ident_exttype) { + case SADB_EXT_IDENTITY_SRC: + (void) printf(gettext("Source")); + break; + case SADB_EXT_IDENTITY_DST: + (void) printf(gettext("Destination")); + break; + } + + (void) printf(gettext(" identity, uid=%d, type "), id->sadb_ident_id); + canprint = dump_sadb_idtype(id->sadb_ident_type, stdout, NULL); + (void) printf("\n%s", prefix); + if (canprint) + (void) printf("%s\n", (char *)(id + 1)); + else + (void) printf(gettext("<cannot print>\n")); +} + +/* + * Print an SADB_SENSITIVITY extension. + */ +void +print_sens(char *prefix, struct sadb_sens *sens) +{ + uint64_t *bitmap = (uint64_t *)(sens + 1); + int i; + + (void) printf( + gettext("%sSensitivity DPD %d, sens level=%d, integ level=%d\n"), + prefix, sens->sadb_sens_dpd, sens->sadb_sens_sens_level, + sens->sadb_sens_integ_level); + for (i = 0; sens->sadb_sens_sens_len-- > 0; i++, bitmap++) + (void) printf( + gettext("%s Sensitivity BM extended word %d 0x%llx\n"), + i, *bitmap); + for (i = 0; sens->sadb_sens_integ_len-- > 0; i++, bitmap++) + (void) printf( + gettext("%s Integrity BM extended word %d 0x%llx\n"), + i, *bitmap); +} + +/* + * Print an SADB_EXT_PROPOSAL extension. + */ +void +print_prop(char *prefix, struct sadb_prop *prop) +{ + struct sadb_comb *combs; + int i, numcombs; + + (void) printf(gettext("%sProposal, replay counter = %u.\n"), prefix, + prop->sadb_prop_replay); + + numcombs = prop->sadb_prop_len - SADB_8TO64(sizeof (*prop)); + numcombs /= SADB_8TO64(sizeof (*combs)); + + combs = (struct sadb_comb *)(prop + 1); + + for (i = 0; i < numcombs; i++) { + (void) printf(gettext("%s Combination #%u "), prefix, i + 1); + if (combs[i].sadb_comb_auth != SADB_AALG_NONE) { + (void) printf(gettext("Authentication = ")); + (void) dump_aalg(combs[i].sadb_comb_auth, stdout); + (void) printf(gettext(" minbits=%u, maxbits=%u.\n%s "), + combs[i].sadb_comb_auth_minbits, + combs[i].sadb_comb_auth_maxbits, prefix); + } + + if (combs[i].sadb_comb_encrypt != SADB_EALG_NONE) { + (void) printf(gettext("Encryption = ")); + (void) dump_ealg(combs[i].sadb_comb_encrypt, stdout); + (void) printf(gettext(" minbits=%u, maxbits=%u.\n%s "), + combs[i].sadb_comb_encrypt_minbits, + combs[i].sadb_comb_encrypt_maxbits, prefix); + } + + (void) printf(gettext("HARD: ")); + if (combs[i].sadb_comb_hard_allocations) + (void) printf(gettext("alloc=%u "), + combs[i].sadb_comb_hard_allocations); + if (combs[i].sadb_comb_hard_bytes) + (void) printf(gettext("bytes=%llu "), + combs[i].sadb_comb_hard_bytes); + if (combs[i].sadb_comb_hard_addtime) + (void) printf(gettext("post-add secs=%llu "), + combs[i].sadb_comb_hard_addtime); + if (combs[i].sadb_comb_hard_usetime) + (void) printf(gettext("post-use secs=%llu"), + combs[i].sadb_comb_hard_usetime); + + (void) printf(gettext("\n%s SOFT: "), prefix); + if (combs[i].sadb_comb_soft_allocations) + (void) printf(gettext("alloc=%u "), + combs[i].sadb_comb_soft_allocations); + if (combs[i].sadb_comb_soft_bytes) + (void) printf(gettext("bytes=%llu "), + combs[i].sadb_comb_soft_bytes); + if (combs[i].sadb_comb_soft_addtime) + (void) printf(gettext("post-add secs=%llu "), + combs[i].sadb_comb_soft_addtime); + if (combs[i].sadb_comb_soft_usetime) + (void) printf(gettext("post-use secs=%llu"), + combs[i].sadb_comb_soft_usetime); + (void) putchar('\n'); + } +} + +/* + * Print an extended proposal (SADB_X_EXT_EPROP). + */ +void +print_eprop(char *prefix, struct sadb_prop *eprop) +{ + uint64_t *sofar; + struct sadb_x_ecomb *ecomb; + struct sadb_x_algdesc *algdesc; + int i, j; + + (void) printf(gettext("%sExtended Proposal, replay counter = %u, "), + prefix, eprop->sadb_prop_replay); + (void) printf(gettext("number of combinations = %u.\n"), + eprop->sadb_x_prop_numecombs); + + sofar = (uint64_t *)(eprop + 1); + ecomb = (struct sadb_x_ecomb *)sofar; + + for (i = 0; i < eprop->sadb_x_prop_numecombs; ) { + (void) printf(gettext("%s Extended combination #%u:\n"), + prefix, ++i); + + (void) printf(gettext("%s HARD: "), prefix); + (void) printf(gettext("alloc=%u, "), + ecomb->sadb_x_ecomb_hard_allocations); + (void) printf(gettext("bytes=%llu, "), + ecomb->sadb_x_ecomb_hard_bytes); + (void) printf(gettext("post-add secs=%llu, "), + ecomb->sadb_x_ecomb_hard_addtime); + (void) printf(gettext("post-use secs=%llu\n"), + ecomb->sadb_x_ecomb_hard_usetime); + + (void) printf(gettext("%s SOFT: "), prefix); + (void) printf(gettext("alloc=%u, "), + ecomb->sadb_x_ecomb_soft_allocations); + (void) printf(gettext("bytes=%llu, "), + ecomb->sadb_x_ecomb_soft_bytes); + (void) printf(gettext("post-add secs=%llu, "), + ecomb->sadb_x_ecomb_soft_addtime); + (void) printf(gettext("post-use secs=%llu\n"), + ecomb->sadb_x_ecomb_soft_usetime); + + sofar = (uint64_t *)(ecomb + 1); + algdesc = (struct sadb_x_algdesc *)sofar; + + for (j = 0; j < ecomb->sadb_x_ecomb_numalgs; ) { + (void) printf(gettext("%s Alg #%u "), prefix, ++j); + switch (algdesc->sadb_x_algdesc_satype) { + case SADB_SATYPE_ESP: + (void) printf(gettext("for ESP ")); + break; + case SADB_SATYPE_AH: + (void) printf(gettext("for AH ")); + break; + default: + (void) printf(gettext("for satype=%d "), + algdesc->sadb_x_algdesc_satype); + } + switch (algdesc->sadb_x_algdesc_algtype) { + case SADB_X_ALGTYPE_CRYPT: + (void) printf(gettext("Encryption = ")); + (void) dump_ealg(algdesc->sadb_x_algdesc_alg, + stdout); + break; + case SADB_X_ALGTYPE_AUTH: + (void) printf(gettext("Authentication = ")); + (void) dump_aalg(algdesc->sadb_x_algdesc_alg, + stdout); + break; + default: + (void) printf(gettext("algtype(%d) = alg(%d)"), + algdesc->sadb_x_algdesc_algtype, + algdesc->sadb_x_algdesc_alg); + break; + } + + (void) printf(gettext(" minbits=%u, maxbits=%u.\n"), + algdesc->sadb_x_algdesc_minbits, + algdesc->sadb_x_algdesc_maxbits); + + sofar = (uint64_t *)(++algdesc); + } + ecomb = (struct sadb_x_ecomb *)sofar; + } +} + +/* + * Print an SADB_EXT_SUPPORTED extension. + */ +void +print_supp(char *prefix, struct sadb_supported *supp) +{ + struct sadb_alg *algs; + int i, numalgs; + + (void) printf(gettext("%sSupported "), prefix); + switch (supp->sadb_supported_exttype) { + case SADB_EXT_SUPPORTED_AUTH: + (void) printf(gettext("authentication")); + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + (void) printf(gettext("encryption")); + break; + } + (void) printf(gettext(" algorithms.\n")); + + algs = (struct sadb_alg *)(supp + 1); + numalgs = supp->sadb_supported_len - SADB_8TO64(sizeof (*supp)); + numalgs /= SADB_8TO64(sizeof (*algs)); + for (i = 0; i < numalgs; i++) { + (void) printf("%s", prefix); + switch (supp->sadb_supported_exttype) { + case SADB_EXT_SUPPORTED_AUTH: + (void) dump_aalg(algs[i].sadb_alg_id, stdout); + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + (void) dump_ealg(algs[i].sadb_alg_id, stdout); + break; + } + (void) printf(gettext(" minbits=%u, maxbits=%u, ivlen=%u.\n"), + algs[i].sadb_alg_minbits, algs[i].sadb_alg_maxbits, + algs[i].sadb_alg_ivlen); + } +} + +/* + * Print an SADB_EXT_SPIRANGE extension. + */ +void +print_spirange(char *prefix, struct sadb_spirange *range) +{ + (void) printf(gettext("%sSPI Range, min=0x%x, max=0x%x\n"), prefix, + htonl(range->sadb_spirange_min), + htonl(range->sadb_spirange_max)); +} + +/* + * Print an SADB_X_EXT_KM_COOKIE extension. + */ + +void +print_kmc(char *prefix, struct sadb_x_kmc *kmc) +{ + char *cookie_label; + + if ((cookie_label = kmc_lookup_by_cookie(kmc->sadb_x_kmc_cookie)) == + NULL) + cookie_label = gettext("<Label not found.>"); + + (void) printf(gettext("%sProtocol %u, cookie=\"%s\" (%u)\n"), prefix, + kmc->sadb_x_kmc_proto, cookie_label, kmc->sadb_x_kmc_cookie); +} + +/* + * Take a PF_KEY message pointed to buffer and print it. Useful for DUMP + * and GET. + */ +void +print_samsg(uint64_t *buffer, boolean_t want_timestamp, boolean_t vflag) +{ + uint64_t *current; + struct sadb_msg *samsg = (struct sadb_msg *)buffer; + struct sadb_ext *ext; + struct sadb_lifetime *currentlt = NULL, *hardlt = NULL, *softlt = NULL; + int i; + time_t wallclock; + + (void) time(&wallclock); + + print_sadb_msg(samsg, want_timestamp ? wallclock : 0, vflag); + current = (uint64_t *)(samsg + 1); + while (current - buffer < samsg->sadb_msg_len) { + int lenbytes; + + ext = (struct sadb_ext *)current; + lenbytes = SADB_64TO8(ext->sadb_ext_len); + switch (ext->sadb_ext_type) { + case SADB_EXT_SA: + print_sa(gettext("SA: "), (struct sadb_sa *)current); + break; + /* + * Pluck out lifetimes and print them at the end. This is + * to show relative lifetimes. + */ + case SADB_EXT_LIFETIME_CURRENT: + currentlt = (struct sadb_lifetime *)current; + break; + case SADB_EXT_LIFETIME_HARD: + hardlt = (struct sadb_lifetime *)current; + break; + case SADB_EXT_LIFETIME_SOFT: + softlt = (struct sadb_lifetime *)current; + break; + + case SADB_EXT_ADDRESS_SRC: + print_address(gettext("SRC: "), + (struct sadb_address *)current); + break; + case SADB_X_EXT_ADDRESS_INNER_SRC: + print_address(gettext("INS: "), + (struct sadb_address *)current); + break; + case SADB_EXT_ADDRESS_DST: + print_address(gettext("DST: "), + (struct sadb_address *)current); + break; + case SADB_X_EXT_ADDRESS_INNER_DST: + print_address(gettext("IND: "), + (struct sadb_address *)current); + break; + case SADB_EXT_KEY_AUTH: + print_key(gettext("AKY: "), (struct sadb_key *)current); + break; + case SADB_EXT_KEY_ENCRYPT: + print_key(gettext("EKY: "), (struct sadb_key *)current); + break; + case SADB_EXT_IDENTITY_SRC: + print_ident(gettext("SID: "), + (struct sadb_ident *)current); + break; + case SADB_EXT_IDENTITY_DST: + print_ident(gettext("DID: "), + (struct sadb_ident *)current); + break; + case SADB_EXT_SENSITIVITY: + print_sens(gettext("SNS: "), + (struct sadb_sens *)current); + break; + case SADB_EXT_PROPOSAL: + print_prop(gettext("PRP: "), + (struct sadb_prop *)current); + break; + case SADB_EXT_SUPPORTED_AUTH: + print_supp(gettext("SUA: "), + (struct sadb_supported *)current); + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + print_supp(gettext("SUE: "), + (struct sadb_supported *)current); + break; + case SADB_EXT_SPIRANGE: + print_spirange(gettext("SPR: "), + (struct sadb_spirange *)current); + break; + case SADB_X_EXT_EPROP: + print_eprop(gettext("EPR: "), + (struct sadb_prop *)current); + break; + case SADB_X_EXT_KM_COOKIE: + print_kmc(gettext("KMC: "), + (struct sadb_x_kmc *)current); + break; + case SADB_X_EXT_ADDRESS_NATT_REM: + print_address(gettext("NRM: "), + (struct sadb_address *)current); + break; + case SADB_X_EXT_ADDRESS_NATT_LOC: + print_address(gettext("NLC: "), + (struct sadb_address *)current); + break; + default: + (void) printf(gettext( + "UNK: Unknown ext. %d, len %d.\n"), + ext->sadb_ext_type, lenbytes); + for (i = 0; i < ext->sadb_ext_len; i++) + (void) printf(gettext("UNK: 0x%llx\n"), + ((uint64_t *)ext)[i]); + break; + } + current += (lenbytes == 0) ? + SADB_8TO64(sizeof (struct sadb_ext)) : ext->sadb_ext_len; + } + /* + * Print lifetimes NOW. + */ + if (currentlt != NULL || hardlt != NULL || softlt != NULL) + print_lifetimes(wallclock, currentlt, hardlt, softlt, vflag); + + if (current - buffer != samsg->sadb_msg_len) { + warnx(gettext("WARNING: insufficient buffer " + "space or corrupt message.")); + } + + (void) fflush(stdout); /* Make sure our message is out there. */ +} + +/* + * save_XXX functions are used when "saving" the SA tables to either a + * file or standard output. They use the dump_XXX functions where needed, + * but mostly they use the rparseXXX functions. + */ + +/* + * Print save information for a lifetime extension. + * + * NOTE : It saves the lifetime in absolute terms. For example, if you + * had a hard_usetime of 60 seconds, you'll save it as 60 seconds, even though + * there may have been 59 seconds burned off the clock. + */ +boolean_t +save_lifetime(struct sadb_lifetime *lifetime, FILE *ofile) +{ + char *prefix; + + prefix = (lifetime->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT) ? + "soft" : "hard"; + + if (putc('\t', ofile) == EOF) + return (B_FALSE); + + if (lifetime->sadb_lifetime_allocations != 0 && fprintf(ofile, + "%s_alloc %u ", prefix, lifetime->sadb_lifetime_allocations) < 0) + return (B_FALSE); + + if (lifetime->sadb_lifetime_bytes != 0 && fprintf(ofile, + "%s_bytes %llu ", prefix, lifetime->sadb_lifetime_bytes) < 0) + return (B_FALSE); + + if (lifetime->sadb_lifetime_addtime != 0 && fprintf(ofile, + "%s_addtime %llu ", prefix, lifetime->sadb_lifetime_addtime) < 0) + return (B_FALSE); + + if (lifetime->sadb_lifetime_usetime != 0 && fprintf(ofile, + "%s_usetime %llu ", prefix, lifetime->sadb_lifetime_usetime) < 0) + return (B_FALSE); + + return (B_TRUE); +} + +/* + * Print save information for an address extension. + */ +boolean_t +save_address(struct sadb_address *addr, FILE *ofile) +{ + char *printable_addr, buf[INET6_ADDRSTRLEN]; + const char *prefix, *pprefix; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(addr + 1); + struct sockaddr_in *sin = (struct sockaddr_in *)sin6; + int af = sin->sin_family; + + /* + * Address-family reality check. + */ + if (af != AF_INET6 && af != AF_INET) + return (B_FALSE); + + switch (addr->sadb_address_exttype) { + case SADB_EXT_ADDRESS_SRC: + prefix = "src"; + pprefix = "sport"; + break; + case SADB_X_EXT_ADDRESS_INNER_SRC: + prefix = "isrc"; + pprefix = "isport"; + break; + case SADB_EXT_ADDRESS_DST: + prefix = "dst"; + pprefix = "dport"; + break; + case SADB_X_EXT_ADDRESS_INNER_DST: + prefix = "idst"; + pprefix = "idport"; + break; + case SADB_X_EXT_ADDRESS_NATT_LOC: + prefix = "nat_loc "; + pprefix = "nat_lport"; + break; + case SADB_X_EXT_ADDRESS_NATT_REM: + prefix = "nat_rem "; + pprefix = "nat_rport"; + break; + } + + if (fprintf(ofile, " %s ", prefix) < 0) + return (B_FALSE); + + /* + * Do not do address-to-name translation, given that we live in + * an age of names that explode into many addresses. + */ + printable_addr = (char *)inet_ntop(af, + (af == AF_INET) ? (char *)&sin->sin_addr : (char *)&sin6->sin6_addr, + buf, sizeof (buf)); + if (printable_addr == NULL) + printable_addr = "<inet_ntop() failed>"; + if (fprintf(ofile, "%s", printable_addr) < 0) + return (B_FALSE); + if (addr->sadb_address_prefixlen != 0 && + !((addr->sadb_address_prefixlen == 32 && af == AF_INET) || + (addr->sadb_address_prefixlen == 128 && af == AF_INET6))) { + if (fprintf(ofile, "/%d", addr->sadb_address_prefixlen) < 0) + return (B_FALSE); + } + + /* + * The port is in the same position for struct sockaddr_in and + * struct sockaddr_in6. We exploit that property here. + */ + if ((pprefix != NULL) && (sin->sin_port != 0)) + (void) fprintf(ofile, " %s %d", pprefix, ntohs(sin->sin_port)); + + return (B_TRUE); +} + +/* + * Print save information for a key extension. Returns whether writing + * to the specified output file was successful or not. + */ +boolean_t +save_key(struct sadb_key *key, FILE *ofile) +{ + char *prefix; + + if (putc('\t', ofile) == EOF) + return (B_FALSE); + + prefix = (key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ? "auth" : "encr"; + + if (fprintf(ofile, "%skey ", prefix) < 0) + return (B_FALSE); + + if (dump_key((uint8_t *)(key + 1), key->sadb_key_bits, ofile) == -1) + return (B_FALSE); + + return (B_TRUE); +} + +/* + * Print save information for an identity extension. + */ +boolean_t +save_ident(struct sadb_ident *ident, FILE *ofile) +{ + char *prefix; + + if (putc('\t', ofile) == EOF) + return (B_FALSE); + + prefix = (ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ? "src" : + "dst"; + + if (fprintf(ofile, "%sidtype %s ", prefix, + rparseidtype(ident->sadb_ident_type)) < 0) + return (B_FALSE); + + if (ident->sadb_ident_type == SADB_X_IDENTTYPE_DN || + ident->sadb_ident_type == SADB_X_IDENTTYPE_GN) { + if (fprintf(ofile, gettext("<can-not-print>")) < 0) + return (B_FALSE); + } else { + if (fprintf(ofile, "%s", (char *)(ident + 1)) < 0) + return (B_FALSE); + } + + return (B_TRUE); +} + +/* + * "Save" a security association to an output file. + * + * NOTE the lack of calls to gettext() because I'm outputting parseable stuff. + * ALSO NOTE that if you change keywords (see parsecmd()), you'll have to + * change them here as well. + */ +void +save_assoc(uint64_t *buffer, FILE *ofile) +{ + int seen_proto = 0; + uint64_t *current; + struct sadb_address *addr; + struct sadb_msg *samsg = (struct sadb_msg *)buffer; + struct sadb_ext *ext; +#define bail2(s) do { \ + int t = errno; \ + (void) fclose(ofile); \ + errno = t; \ + interactive = B_FALSE; /* Guarantees exit. */ \ + Bail(s); \ + } while (B_FALSE) /* How do I lint-clean this? */ + +#define savenl() if (fputs(" \\\n", ofile) == EOF) { bail2("savenl"); } + + if (fputs("# begin assoc\n", ofile) == EOF) + Bail("save_assoc: Opening comment of SA"); + if (fprintf(ofile, "add %s ", rparsesatype(samsg->sadb_msg_satype)) < 0) + Bail("save_assoc: First line of SA"); + /* LINTED E_CONST_COND */ + savenl(); + + current = (uint64_t *)(samsg + 1); + while (current - buffer < samsg->sadb_msg_len) { + struct sadb_sa *assoc; + + ext = (struct sadb_ext *)current; + switch (ext->sadb_ext_type) { + case SADB_EXT_SA: + assoc = (struct sadb_sa *)ext; + if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) { + if (fprintf(ofile, "# WARNING: SA was dying " + "or dead.\n") < 0) { + /* LINTED E_CONST_COND */ + bail2("save_assoc: fprintf not mature"); + } + } + if (fprintf(ofile, " spi 0x%x ", + ntohl(assoc->sadb_sa_spi)) < 0) + /* LINTED E_CONST_COND */ + bail2("save_assoc: fprintf spi"); + if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) { + if (fprintf(ofile, "encr_alg %s ", + rparsealg(assoc->sadb_sa_encrypt, + IPSEC_PROTO_ESP)) < 0) + /* LINTED E_CONST_COND */ + bail2("save_assoc: fprintf encrypt"); + } + if (assoc->sadb_sa_auth != SADB_AALG_NONE) { + if (fprintf(ofile, "auth_alg %s ", + rparsealg(assoc->sadb_sa_auth, + IPSEC_PROTO_AH)) < 0) + /* LINTED E_CONST_COND */ + bail2("save_assoc: fprintf auth"); + } + if (fprintf(ofile, "replay %d ", + assoc->sadb_sa_replay) < 0) + /* LINTED E_CONST_COND */ + bail2("save_assoc: fprintf replay"); + if (assoc->sadb_sa_flags & (SADB_X_SAFLAGS_NATT_LOC | + SADB_X_SAFLAGS_NATT_REM)) { + if (fprintf(ofile, "encap udp") < 0) + /* LINTED E_CONST_COND */ + bail2("save_assoc: fprintf encap"); + } + /* LINTED E_CONST_COND */ + savenl(); + break; + case SADB_EXT_LIFETIME_HARD: + case SADB_EXT_LIFETIME_SOFT: + if (!save_lifetime((struct sadb_lifetime *)ext, ofile)) + /* LINTED E_CONST_COND */ + bail2("save_lifetime"); + /* LINTED E_CONST_COND */ + savenl(); + break; + case SADB_EXT_ADDRESS_SRC: + case SADB_EXT_ADDRESS_DST: + case SADB_X_EXT_ADDRESS_INNER_SRC: + case SADB_X_EXT_ADDRESS_INNER_DST: + case SADB_X_EXT_ADDRESS_NATT_REM: + case SADB_X_EXT_ADDRESS_NATT_LOC: + addr = (struct sadb_address *)ext; + if (!seen_proto && addr->sadb_address_proto) { + (void) fprintf(ofile, " proto %d", + addr->sadb_address_proto); + /* LINTED E_CONST_COND */ + savenl(); + seen_proto = 1; + } + if (!save_address(addr, ofile)) + /* LINTED E_CONST_COND */ + bail2("save_address"); + /* LINTED E_CONST_COND */ + savenl(); + break; + case SADB_EXT_KEY_AUTH: + case SADB_EXT_KEY_ENCRYPT: + if (!save_key((struct sadb_key *)ext, ofile)) + /* LINTED E_CONST_COND */ + bail2("save_address"); + /* LINTED E_CONST_COND */ + savenl(); + break; + case SADB_EXT_IDENTITY_SRC: + case SADB_EXT_IDENTITY_DST: + if (!save_ident((struct sadb_ident *)ext, ofile)) + /* LINTED E_CONST_COND */ + bail2("save_address"); + /* LINTED E_CONST_COND */ + savenl(); + break; + case SADB_EXT_SENSITIVITY: + default: + /* Skip over irrelevant extensions. */ + break; + } + current += ext->sadb_ext_len; + } + + if (fputs(gettext("\n# end assoc\n\n"), ofile) == EOF) + /* LINTED E_CONST_COND */ + bail2("save_assoc: last fputs"); +} + +/* + * Open the output file for the "save" command. + */ +FILE * +opensavefile(char *filename) +{ + int fd; + FILE *retval; + struct stat buf; + + /* + * If the user specifies "-" or doesn't give a filename, then + * dump to stdout. Make sure to document the dangers of files + * that are NFS, directing your output to strange places, etc. + */ + if (filename == NULL || strcmp("-", filename) == 0) + return (stdout); + + /* + * open the file with the create bits set. Since I check for + * real UID == root in main(), I won't worry about the ownership + * problem. + */ + fd = open(filename, O_WRONLY | O_EXCL | O_CREAT | O_TRUNC, S_IRUSR); + if (fd == -1) { + if (errno != EEXIST) + bail_msg("%s %s: %s", filename, gettext("open error"), + strerror(errno)); + fd = open(filename, O_WRONLY | O_TRUNC, 0); + if (fd == -1) + bail_msg("%s %s: %s", filename, gettext("open error"), + strerror(errno)); + if (fstat(fd, &buf) == -1) { + (void) close(fd); + bail_msg("%s fstat: %s", filename, strerror(errno)); + } + if (S_ISREG(buf.st_mode) && + ((buf.st_mode & S_IAMB) != S_IRUSR)) { + warnx(gettext("WARNING: Save file already exists with " + "permission %o."), buf.st_mode & S_IAMB); + warnx(gettext("Normal users may be able to read IPsec " + "keying material.")); + } + } + + /* Okay, we have an FD. Assign it to a stdio FILE pointer. */ + retval = fdopen(fd, "w"); + if (retval == NULL) { + (void) close(fd); + bail_msg("%s %s: %s", filename, gettext("fdopen error"), + strerror(errno)); + } + return (retval); +} + +const char * +do_inet_ntop(const void *addr, char *cp, size_t size) +{ + boolean_t isv4; + struct in6_addr *inaddr6 = (struct in6_addr *)addr; + struct in_addr inaddr; + + if ((isv4 = IN6_IS_ADDR_V4MAPPED(inaddr6)) == B_TRUE) { + IN6_V4MAPPED_TO_INADDR(inaddr6, &inaddr); + } + + return (inet_ntop(isv4 ? AF_INET : AF_INET6, + isv4 ? (void *)&inaddr : inaddr6, cp, size)); +} + +char numprint[NBUF_SIZE]; + +/* + * Parse and reverse parse a specific SA type (AH, ESP, etc.). + */ +static struct typetable { + char *type; + int token; +} type_table[] = { + {"all", SADB_SATYPE_UNSPEC}, + {"ah", SADB_SATYPE_AH}, + {"esp", SADB_SATYPE_ESP}, + /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */ + {NULL, 0} /* Token value is irrelevant for this entry. */ +}; + +char * +rparsesatype(int type) +{ + struct typetable *tt = type_table; + + while (tt->type != NULL && type != tt->token) + tt++; + + if (tt->type == NULL) { + (void) snprintf(numprint, NBUF_SIZE, "%d", type); + } else { + return (tt->type); + } + + return (numprint); +} + + +/* + * Return a string containing the name of the specified numerical algorithm + * identifier. + */ +char * +rparsealg(uint8_t alg, int proto_num) +{ + static struct ipsecalgent *holder = NULL; /* we're single-threaded */ + + if (holder != NULL) + freeipsecalgent(holder); + + holder = getipsecalgbynum(alg, proto_num, NULL); + if (holder == NULL) { + (void) snprintf(numprint, NBUF_SIZE, "%d", alg); + return (numprint); + } + + return (*(holder->a_names)); +} + +/* + * Parse and reverse parse out a source/destination ID type. + */ +static struct idtypes { + char *idtype; + uint8_t retval; +} idtypes[] = { + {"prefix", SADB_IDENTTYPE_PREFIX}, + {"fqdn", SADB_IDENTTYPE_FQDN}, + {"domain", SADB_IDENTTYPE_FQDN}, + {"domainname", SADB_IDENTTYPE_FQDN}, + {"user_fqdn", SADB_IDENTTYPE_USER_FQDN}, + {"mailbox", SADB_IDENTTYPE_USER_FQDN}, + {"der_dn", SADB_X_IDENTTYPE_DN}, + {"der_gn", SADB_X_IDENTTYPE_GN}, + {NULL, 0} +}; + +char * +rparseidtype(uint16_t type) +{ + struct idtypes *idp; + + for (idp = idtypes; idp->idtype != NULL; idp++) { + if (type == idp->retval) + return (idp->idtype); + } + + (void) snprintf(numprint, NBUF_SIZE, "%d", type); + return (numprint); +} |