1*4235Smarkfen /* 2*4235Smarkfen * CDDL HEADER START 3*4235Smarkfen * 4*4235Smarkfen * The contents of this file are subject to the terms of the 5*4235Smarkfen * Common Development and Distribution License (the "License"). 6*4235Smarkfen * You may not use this file except in compliance with the License. 7*4235Smarkfen * 8*4235Smarkfen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4235Smarkfen * or http://www.opensolaris.org/os/licensing. 10*4235Smarkfen * See the License for the specific language governing permissions 11*4235Smarkfen * and limitations under the License. 12*4235Smarkfen * 13*4235Smarkfen * When distributing Covered Code, include this CDDL HEADER in each 14*4235Smarkfen * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4235Smarkfen * If applicable, add the following below this CDDL HEADER, with the 16*4235Smarkfen * fields enclosed by brackets "[]" replaced with your own identifying 17*4235Smarkfen * information: Portions Copyright [yyyy] [name of copyright owner] 18*4235Smarkfen * 19*4235Smarkfen * CDDL HEADER END 20*4235Smarkfen */ 21*4235Smarkfen /* 22*4235Smarkfen * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*4235Smarkfen * Use is subject to license terms. 24*4235Smarkfen */ 25*4235Smarkfen 26*4235Smarkfen 27*4235Smarkfen #pragma ident "%Z%%M% %I% %E% SMI" 28*4235Smarkfen 29*4235Smarkfen #include <ipsec_util.h> 30*4235Smarkfen #include <netdb.h> 31*4235Smarkfen #include <locale.h> 32*4235Smarkfen #include <stdlib.h> 33*4235Smarkfen #include <stdio.h> 34*4235Smarkfen #include <string.h> 35*4235Smarkfen #include <assert.h> 36*4235Smarkfen #include <unistd.h> 37*4235Smarkfen #include <net/pfpolicy.h> 38*4235Smarkfen #include <strings.h> 39*4235Smarkfen #include <errno.h> 40*4235Smarkfen #include <sys/crypto/common.h> 41*4235Smarkfen #include <zone.h> 42*4235Smarkfen 43*4235Smarkfen #define SPDSOCK_DIAG_BUF_LEN 128 44*4235Smarkfen 45*4235Smarkfen typedef enum cmd_s { 46*4235Smarkfen CMD_NONE = 0, 47*4235Smarkfen CMD_ADD, 48*4235Smarkfen CMD_ADD_PROTO, 49*4235Smarkfen CMD_DEL, 50*4235Smarkfen CMD_DEL_PROTO, 51*4235Smarkfen CMD_EXEC_MODE, 52*4235Smarkfen CMD_LIST_KERNEL 53*4235Smarkfen } cmd_t; 54*4235Smarkfen 55*4235Smarkfen static const char *comma = ","; 56*4235Smarkfen static int adddel_flags, increment = 0, default_keylen; 57*4235Smarkfen static boolean_t synch_kernel; 58*4235Smarkfen static cmd_t cmd = CMD_NONE; 59*4235Smarkfen static int proto_number = -1, alg_number = -1; 60*4235Smarkfen static char *proto_name, *alg_names_string, *block_sizes_string; 61*4235Smarkfen static char *key_sizes_string, *mech_name, *exec_mode_string; 62*4235Smarkfen static ipsecalgs_exec_mode_t proto_exec_mode = LIBIPSEC_ALGS_EXEC_SYNC; 63*4235Smarkfen 64*4235Smarkfen /* 65*4235Smarkfen * Used by the algorithm walker callback to populate a SPD_UPDATEALGS 66*4235Smarkfen * request. 67*4235Smarkfen */ 68*4235Smarkfen 69*4235Smarkfen #define SYNC_REQ_SIZE 2048 70*4235Smarkfen 71*4235Smarkfen static uint64_t sync_req_buf[SYNC_REQ_SIZE]; 72*4235Smarkfen static struct spd_attribute *sync_req_attr; 73*4235Smarkfen static uint_t sync_req_alg_count, sync_req_proto_count; 74*4235Smarkfen 75*4235Smarkfen #define EMIT(ap, tag, value) { \ 76*4235Smarkfen (ap)->spd_attr_tag = (tag); \ 77*4235Smarkfen (ap)->spd_attr_value = (value); \ 78*4235Smarkfen (ap)++; \ 79*4235Smarkfen if ((char *)(ap) + sizeof (*ap) - \ 80*4235Smarkfen (char *)sync_req_buf > SYNC_REQ_SIZE) \ 81*4235Smarkfen bail_nomem(); \ 82*4235Smarkfen } 83*4235Smarkfen 84*4235Smarkfen static void dump_alg(struct ipsecalgent *); 85*4235Smarkfen static void algs_walker(void (*)(struct ipsecalgent *), void (*)(uint_t)); 86*4235Smarkfen 87*4235Smarkfen static void 88*4235Smarkfen usage(void) 89*4235Smarkfen { 90*4235Smarkfen errx(EXIT_FAILURE, gettext("Usage:\tipsecalgs\n" 91*4235Smarkfen "\tipsecalgs -l\n" 92*4235Smarkfen "\tipsecalgs -s\n" 93*4235Smarkfen "\tipsecalgs -a [-P protocol-number | -p protocol-name]\n" 94*4235Smarkfen "\t\t-k keylen-list [-i inc]\n" 95*4235Smarkfen "\t\t[-K default-keylen] -b blocklen-list\n" 96*4235Smarkfen "\t\t-n alg-names -N alg-number -m mech-name [-f] [-s]\n" 97*4235Smarkfen "\tipsecalgs -P protocol-number -p protocol-name\n" 98*4235Smarkfen "\t\t[-e exec-mode] [-f] [-s]\n" 99*4235Smarkfen "\tipsecalgs -r -p protocol-name -n alg-name [-s]\n" 100*4235Smarkfen "\tipsecalgs -r -p protocol-name -N alg-number [-s]\n" 101*4235Smarkfen "\tipsecalgs -R -P protocol-number [-s]\n" 102*4235Smarkfen "\tipsecalgs -R -p protocol-name [-s]\n" 103*4235Smarkfen "\tipsecalgs -e exec-mode -P protocol-number [-s]\n" 104*4235Smarkfen "\tipsecalgs -e exec-mode -p protocol-number [-s]")); 105*4235Smarkfen } 106*4235Smarkfen 107*4235Smarkfen static void 108*4235Smarkfen bail_nomem(void) 109*4235Smarkfen { 110*4235Smarkfen errx(EXIT_FAILURE, gettext("Out of memory.")); 111*4235Smarkfen } 112*4235Smarkfen 113*4235Smarkfen /* 114*4235Smarkfen * Return the number of key or block sizes in the specified array. 115*4235Smarkfen */ 116*4235Smarkfen static uint_t 117*4235Smarkfen num_sizes(int *sizes) 118*4235Smarkfen { 119*4235Smarkfen uint_t nsizes = 0; 120*4235Smarkfen 121*4235Smarkfen while (sizes[nsizes] != 0) 122*4235Smarkfen nsizes++; 123*4235Smarkfen 124*4235Smarkfen return (nsizes); 125*4235Smarkfen } 126*4235Smarkfen 127*4235Smarkfen /* 128*4235Smarkfen * Algorithms walker callback. Adds an algorithm to the current SPD_UPDATEALGS 129*4235Smarkfen * request. 130*4235Smarkfen */ 131*4235Smarkfen static void 132*4235Smarkfen synch_emit_alg(struct ipsecalgent *alg) 133*4235Smarkfen { 134*4235Smarkfen uint_t nkey_sizes, nblock_sizes, i; 135*4235Smarkfen 136*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_ID, alg->a_alg_num); 137*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_PROTO, alg->a_proto_num); 138*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_INCRBITS, alg->a_key_increment); 139*4235Smarkfen 140*4235Smarkfen nkey_sizes = num_sizes(alg->a_key_sizes); 141*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_NKEYSIZES, nkey_sizes); 142*4235Smarkfen for (i = 0; i < nkey_sizes; i++) 143*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_KEYSIZE, alg->a_key_sizes[i]); 144*4235Smarkfen 145*4235Smarkfen nblock_sizes = num_sizes(alg->a_block_sizes); 146*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_NBLOCKSIZES, nblock_sizes); 147*4235Smarkfen for (i = 0; i < nblock_sizes; i++) { 148*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_BLOCKSIZE, 149*4235Smarkfen alg->a_block_sizes[i]); 150*4235Smarkfen } 151*4235Smarkfen 152*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_ALG_MECHNAME, CRYPTO_MAX_MECH_NAME); 153*4235Smarkfen (void) strncpy((char *)sync_req_attr, alg->a_mech_name, 154*4235Smarkfen CRYPTO_MAX_MECH_NAME); 155*4235Smarkfen sync_req_attr = (struct spd_attribute *)((uint64_t *)sync_req_attr + 156*4235Smarkfen SPD_8TO64(CRYPTO_MAX_MECH_NAME)); 157*4235Smarkfen 158*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_NEXT, 0); 159*4235Smarkfen 160*4235Smarkfen sync_req_alg_count++; 161*4235Smarkfen } 162*4235Smarkfen 163*4235Smarkfen /* 164*4235Smarkfen * Protocol walker callback. Add protocol related info to the current 165*4235Smarkfen * SPD_UPDATEALGS request. 166*4235Smarkfen */ 167*4235Smarkfen static void 168*4235Smarkfen synch_emit_proto(uint_t proto_num) 169*4235Smarkfen { 170*4235Smarkfen ipsecalgs_exec_mode_t exec_mode; 171*4235Smarkfen uint32_t exec_mode_spdval; 172*4235Smarkfen 173*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_PROTO_ID, proto_num); 174*4235Smarkfen 175*4235Smarkfen /* execution mode */ 176*4235Smarkfen if (ipsecproto_get_exec_mode(proto_num, &exec_mode) != 0) { 177*4235Smarkfen errx(EXIT_FAILURE, gettext("cannot get execution mode for " 178*4235Smarkfen "proto %d"), proto_num); 179*4235Smarkfen } 180*4235Smarkfen 181*4235Smarkfen switch (exec_mode) { 182*4235Smarkfen case LIBIPSEC_ALGS_EXEC_SYNC: 183*4235Smarkfen exec_mode_spdval = SPD_ALG_EXEC_MODE_SYNC; 184*4235Smarkfen break; 185*4235Smarkfen case LIBIPSEC_ALGS_EXEC_ASYNC: 186*4235Smarkfen exec_mode_spdval = SPD_ALG_EXEC_MODE_ASYNC; 187*4235Smarkfen break; 188*4235Smarkfen } 189*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_PROTO_EXEC_MODE, exec_mode_spdval); 190*4235Smarkfen 191*4235Smarkfen EMIT(sync_req_attr, SPD_ATTR_NEXT, 0); 192*4235Smarkfen 193*4235Smarkfen sync_req_proto_count++; 194*4235Smarkfen } 195*4235Smarkfen 196*4235Smarkfen /* 197*4235Smarkfen * Causes the kernel to be re-synched with the contents of /etc/inet/algs 198*4235Smarkfen */ 199*4235Smarkfen static void 200*4235Smarkfen kernel_synch(void) 201*4235Smarkfen { 202*4235Smarkfen int sfd = socket(PF_POLICY, SOCK_RAW, PF_POLICY_V1); 203*4235Smarkfen int cnt, req_len; 204*4235Smarkfen struct spd_msg *msg; 205*4235Smarkfen struct spd_ext_actions *act; 206*4235Smarkfen struct spd_attribute *attr; 207*4235Smarkfen 208*4235Smarkfen if (sfd < 0) { 209*4235Smarkfen err(EXIT_FAILURE, gettext("Unable to open policy socket")); 210*4235Smarkfen } 211*4235Smarkfen 212*4235Smarkfen /* 213*4235Smarkfen * Initialize the SPD message header and action. Some fields 214*4235Smarkfen * are set after having walked through the algorithms (number 215*4235Smarkfen * of algorithms, sizes, etc.) 216*4235Smarkfen */ 217*4235Smarkfen msg = (struct spd_msg *)sync_req_buf; 218*4235Smarkfen (void) memset(msg, 0, sizeof (*msg)); 219*4235Smarkfen msg->spd_msg_version = PF_POLICY_V1; 220*4235Smarkfen msg->spd_msg_type = SPD_UPDATEALGS; 221*4235Smarkfen 222*4235Smarkfen act = (struct spd_ext_actions *)(msg + 1); 223*4235Smarkfen act->spd_actions_exttype = SPD_EXT_ACTION; 224*4235Smarkfen act->spd_actions_reserved = 0; 225*4235Smarkfen 226*4235Smarkfen /* 227*4235Smarkfen * Walk through the algorithms defined and populate the 228*4235Smarkfen * request buffer. 229*4235Smarkfen */ 230*4235Smarkfen sync_req_alg_count = 0; 231*4235Smarkfen sync_req_proto_count = 0; 232*4235Smarkfen sync_req_attr = (struct spd_attribute *)(act + 1); 233*4235Smarkfen algs_walker(synch_emit_alg, synch_emit_proto); 234*4235Smarkfen act->spd_actions_count = sync_req_alg_count + sync_req_proto_count; 235*4235Smarkfen 236*4235Smarkfen /* 237*4235Smarkfen * Replace the last SPD_ATTR_NEXT attribute by a SPD_ATTR_END. 238*4235Smarkfen */ 239*4235Smarkfen attr = sync_req_attr - 1; 240*4235Smarkfen attr->spd_attr_tag = SPD_ATTR_END; 241*4235Smarkfen 242*4235Smarkfen /* 243*4235Smarkfen * Now that the message is built, compute its total length and 244*4235Smarkfen * update the length fields that depend on this value. 245*4235Smarkfen */ 246*4235Smarkfen req_len = (char *)sync_req_attr - (char *)sync_req_buf; 247*4235Smarkfen msg->spd_msg_len = SPD_8TO64(req_len); 248*4235Smarkfen act->spd_actions_len = SPD_8TO64(req_len - sizeof (*msg)); 249*4235Smarkfen 250*4235Smarkfen /* ship the update request to spdsock */ 251*4235Smarkfen cnt = write(sfd, sync_req_buf, req_len); 252*4235Smarkfen if (cnt != req_len) { 253*4235Smarkfen if (cnt < 0) { 254*4235Smarkfen err(EXIT_FAILURE, gettext("algs update write failed")); 255*4235Smarkfen } else { 256*4235Smarkfen errx(EXIT_FAILURE, gettext("algs update short write")); 257*4235Smarkfen } 258*4235Smarkfen /* err/errx call exit(). */ 259*4235Smarkfen } 260*4235Smarkfen 261*4235Smarkfen cnt = read(sfd, sync_req_buf, req_len); 262*4235Smarkfen 263*4235Smarkfen if (cnt == -1) { 264*4235Smarkfen err(EXIT_FAILURE, gettext("algs update read failed")); 265*4235Smarkfen } 266*4235Smarkfen 267*4235Smarkfen if (cnt < sizeof (struct spd_msg)) { 268*4235Smarkfen errx(EXIT_FAILURE, gettext( 269*4235Smarkfen "algs update failed while reading reply (short read)")); 270*4235Smarkfen } 271*4235Smarkfen 272*4235Smarkfen msg = (struct spd_msg *)sync_req_buf; 273*4235Smarkfen if (msg->spd_msg_errno != 0) { 274*4235Smarkfen errno = msg->spd_msg_errno; 275*4235Smarkfen warn(gettext("algs update failed")); 276*4235Smarkfen if (msg->spd_msg_diagnostic != 0) { 277*4235Smarkfen warnx("%s", spdsock_diag(msg->spd_msg_diagnostic)); 278*4235Smarkfen } 279*4235Smarkfen exit(EXIT_FAILURE); 280*4235Smarkfen } 281*4235Smarkfen 282*4235Smarkfen (void) close(sfd); 283*4235Smarkfen } 284*4235Smarkfen 285*4235Smarkfen static void 286*4235Smarkfen list_kernel_algs(void) 287*4235Smarkfen { 288*4235Smarkfen int sfd = socket(PF_POLICY, SOCK_RAW, PF_POLICY_V1); 289*4235Smarkfen int cnt, retval; 290*4235Smarkfen uint64_t reply_buf[2048]; 291*4235Smarkfen spd_ext_t *exts[SPD_EXT_MAX+1]; 292*4235Smarkfen struct spd_msg msg; 293*4235Smarkfen struct spd_ext_actions *actp; 294*4235Smarkfen struct spd_attribute *attr, *endattr; 295*4235Smarkfen uint64_t *start, *end; 296*4235Smarkfen struct ipsecalgent alg; 297*4235Smarkfen uint_t cur_key, cur_block; 298*4235Smarkfen uint_t nkey_sizes, nblock_sizes; 299*4235Smarkfen char diag_buf[SPDSOCK_DIAG_BUF_LEN]; 300*4235Smarkfen 301*4235Smarkfen if (sfd < 0) { 302*4235Smarkfen err(EXIT_FAILURE, gettext("Unable to open policy socket")); 303*4235Smarkfen } 304*4235Smarkfen 305*4235Smarkfen (void) memset(&msg, 0, sizeof (msg)); 306*4235Smarkfen msg.spd_msg_version = PF_POLICY_V1; 307*4235Smarkfen msg.spd_msg_type = SPD_DUMPALGS; 308*4235Smarkfen msg.spd_msg_len = SPD_8TO64(sizeof (msg)); 309*4235Smarkfen 310*4235Smarkfen cnt = write(sfd, &msg, sizeof (msg)); 311*4235Smarkfen if (cnt != sizeof (msg)) { 312*4235Smarkfen if (cnt < 0) { 313*4235Smarkfen err(EXIT_FAILURE, gettext("dump algs write failed")); 314*4235Smarkfen } else { 315*4235Smarkfen errx(EXIT_FAILURE, gettext("dump algs short write")); 316*4235Smarkfen } 317*4235Smarkfen /* err/errx call exit(). */ 318*4235Smarkfen } 319*4235Smarkfen 320*4235Smarkfen cnt = read(sfd, reply_buf, sizeof (reply_buf)); 321*4235Smarkfen 322*4235Smarkfen if (cnt == -1) { 323*4235Smarkfen err(EXIT_FAILURE, gettext("dump algs read failed")); 324*4235Smarkfen } 325*4235Smarkfen 326*4235Smarkfen if (cnt < sizeof (struct spd_msg)) { 327*4235Smarkfen errx(EXIT_FAILURE, gettext( 328*4235Smarkfen "dump algs failed while reading reply (short read)")); 329*4235Smarkfen } 330*4235Smarkfen 331*4235Smarkfen (void) close(sfd); 332*4235Smarkfen 333*4235Smarkfen retval = spdsock_get_ext(exts, (spd_msg_t *)reply_buf, SPD_8TO64(cnt), 334*4235Smarkfen diag_buf, SPDSOCK_DIAG_BUF_LEN); 335*4235Smarkfen 336*4235Smarkfen if (retval == KGE_LEN && exts[0]->spd_ext_len == 0) { 337*4235Smarkfen /* 338*4235Smarkfen * No algorithms are defined in the kernel, which caused 339*4235Smarkfen * the extension length to be zero, and spdsock_get_ext() 340*4235Smarkfen * to fail with a KGE_LEN error. This is not an error 341*4235Smarkfen * condition, so we return nicely. 342*4235Smarkfen */ 343*4235Smarkfen return; 344*4235Smarkfen } else if (retval != 0) { 345*4235Smarkfen if (strlen(diag_buf) != 0) 346*4235Smarkfen warnx("%s", diag_buf); 347*4235Smarkfen errx(EXIT_FAILURE, gettext("invalid extension " 348*4235Smarkfen "in dump algs reply (%d)"), retval); 349*4235Smarkfen } 350*4235Smarkfen 351*4235Smarkfen if (exts[SPD_EXT_ACTION] == NULL) { 352*4235Smarkfen errx(EXIT_FAILURE, 353*4235Smarkfen gettext("action missing in dump algs reply")); 354*4235Smarkfen } 355*4235Smarkfen 356*4235Smarkfen actp = (struct spd_ext_actions *)exts[SPD_EXT_ACTION]; 357*4235Smarkfen start = (uint64_t *)actp; 358*4235Smarkfen end = (start + actp->spd_actions_len); 359*4235Smarkfen endattr = (struct spd_attribute *)end; 360*4235Smarkfen attr = (struct spd_attribute *)&actp[1]; 361*4235Smarkfen 362*4235Smarkfen bzero(&alg, sizeof (alg)); 363*4235Smarkfen nkey_sizes = nblock_sizes = 0; 364*4235Smarkfen 365*4235Smarkfen (void) printf("Kernel list of algorithms:\n\n"); 366*4235Smarkfen 367*4235Smarkfen while (attr < endattr) { 368*4235Smarkfen switch (attr->spd_attr_tag) { 369*4235Smarkfen case SPD_ATTR_NOP: 370*4235Smarkfen case SPD_ATTR_EMPTY: 371*4235Smarkfen break; 372*4235Smarkfen case SPD_ATTR_END: 373*4235Smarkfen attr = endattr; 374*4235Smarkfen /* FALLTHRU */ 375*4235Smarkfen case SPD_ATTR_NEXT: 376*4235Smarkfen /* 377*4235Smarkfen * Note that if the message received from the spdsock 378*4235Smarkfen * has a premature SPD_ATTR_END or SPD_ATTR_NEXT, this 379*4235Smarkfen * could cause the current algorithm to be only 380*4235Smarkfen * partially initialized. 381*4235Smarkfen */ 382*4235Smarkfen dump_alg(&alg); 383*4235Smarkfen free(alg.a_key_sizes); 384*4235Smarkfen free(alg.a_block_sizes); 385*4235Smarkfen free(alg.a_mech_name); 386*4235Smarkfen bzero(&alg, sizeof (alg)); 387*4235Smarkfen nkey_sizes = nblock_sizes = 0; 388*4235Smarkfen break; 389*4235Smarkfen 390*4235Smarkfen case SPD_ATTR_ALG_ID: 391*4235Smarkfen alg.a_alg_num = attr->spd_attr_value; 392*4235Smarkfen break; 393*4235Smarkfen 394*4235Smarkfen case SPD_ATTR_ALG_PROTO: 395*4235Smarkfen alg.a_proto_num = attr->spd_attr_value; 396*4235Smarkfen break; 397*4235Smarkfen 398*4235Smarkfen case SPD_ATTR_ALG_INCRBITS: 399*4235Smarkfen alg.a_key_increment = attr->spd_attr_value; 400*4235Smarkfen break; 401*4235Smarkfen 402*4235Smarkfen case SPD_ATTR_ALG_NKEYSIZES: 403*4235Smarkfen nkey_sizes = attr->spd_attr_value; 404*4235Smarkfen if (alg.a_key_sizes != NULL) { 405*4235Smarkfen errx(EXIT_FAILURE, gettext("duplicate number " 406*4235Smarkfen "of keys in dump algs reply")); 407*4235Smarkfen } 408*4235Smarkfen alg.a_key_sizes = calloc(nkey_sizes + 1, sizeof (int)); 409*4235Smarkfen if (alg.a_key_sizes == NULL) 410*4235Smarkfen bail_nomem(); 411*4235Smarkfen cur_key = 0; 412*4235Smarkfen break; 413*4235Smarkfen 414*4235Smarkfen case SPD_ATTR_ALG_KEYSIZE: 415*4235Smarkfen if (cur_key >= nkey_sizes) { 416*4235Smarkfen errx(EXIT_FAILURE, gettext("too many key sizes" 417*4235Smarkfen " in dump algs reply")); 418*4235Smarkfen } 419*4235Smarkfen alg.a_key_sizes[cur_key++] = attr->spd_attr_value; 420*4235Smarkfen break; 421*4235Smarkfen 422*4235Smarkfen case SPD_ATTR_ALG_NBLOCKSIZES: 423*4235Smarkfen nblock_sizes = attr->spd_attr_value; 424*4235Smarkfen if (alg.a_block_sizes != NULL) { 425*4235Smarkfen errx(EXIT_FAILURE, gettext("duplicate number " 426*4235Smarkfen "of blocks in dump algs reply")); 427*4235Smarkfen } 428*4235Smarkfen alg.a_block_sizes = calloc(nblock_sizes + 1, 429*4235Smarkfen sizeof (int)); 430*4235Smarkfen if (alg.a_block_sizes == NULL) 431*4235Smarkfen bail_nomem(); 432*4235Smarkfen cur_block = 0; 433*4235Smarkfen break; 434*4235Smarkfen 435*4235Smarkfen case SPD_ATTR_ALG_BLOCKSIZE: 436*4235Smarkfen if (cur_block >= nblock_sizes) { 437*4235Smarkfen errx(EXIT_FAILURE, gettext("too many block " 438*4235Smarkfen "sizes in dump algs reply")); 439*4235Smarkfen } 440*4235Smarkfen alg.a_block_sizes[cur_block++] = attr->spd_attr_value; 441*4235Smarkfen break; 442*4235Smarkfen 443*4235Smarkfen case SPD_ATTR_ALG_MECHNAME: { 444*4235Smarkfen char *mech_name; 445*4235Smarkfen 446*4235Smarkfen if (alg.a_mech_name != NULL) { 447*4235Smarkfen errx(EXIT_FAILURE, gettext( 448*4235Smarkfen "duplicate mech name in dump algs reply")); 449*4235Smarkfen } 450*4235Smarkfen 451*4235Smarkfen alg.a_mech_name = malloc(attr->spd_attr_value); 452*4235Smarkfen if (alg.a_mech_name == NULL) 453*4235Smarkfen bail_nomem(); 454*4235Smarkfen 455*4235Smarkfen mech_name = (char *)(attr + 1); 456*4235Smarkfen bcopy(mech_name, alg.a_mech_name, attr->spd_attr_value); 457*4235Smarkfen attr = (struct spd_attribute *)((uint64_t *)attr + 458*4235Smarkfen SPD_8TO64(attr->spd_attr_value)); 459*4235Smarkfen break; 460*4235Smarkfen } 461*4235Smarkfen } 462*4235Smarkfen attr++; 463*4235Smarkfen } 464*4235Smarkfen 465*4235Smarkfen } 466*4235Smarkfen 467*4235Smarkfen 468*4235Smarkfen static int * 469*4235Smarkfen parse_intlist(char *args, int *num_args) 470*4235Smarkfen { 471*4235Smarkfen int *rc = NULL; 472*4235Smarkfen char *holder = NULL; 473*4235Smarkfen 474*4235Smarkfen while ((holder = strtok((holder == NULL) ? args : NULL, comma)) != 475*4235Smarkfen NULL) { 476*4235Smarkfen (*num_args)++; 477*4235Smarkfen rc = realloc(rc, ((*num_args) + 1) * sizeof (int)); 478*4235Smarkfen if (rc == NULL) 479*4235Smarkfen bail_nomem(); 480*4235Smarkfen rc[(*num_args) - 1] = atoi(holder); 481*4235Smarkfen if (rc[(*num_args) - 1] == 0) 482*4235Smarkfen usage(); /* Malformed integer list! */ 483*4235Smarkfen rc[*num_args] = 0; 484*4235Smarkfen } 485*4235Smarkfen 486*4235Smarkfen return (rc); 487*4235Smarkfen } 488*4235Smarkfen 489*4235Smarkfen static void 490*4235Smarkfen new_alg(void) 491*4235Smarkfen { 492*4235Smarkfen struct ipsecalgent newbie; 493*4235Smarkfen int num_names = 0, num_block_sizes = 0, num_key_sizes = 0; 494*4235Smarkfen int i, rc; 495*4235Smarkfen char *holder = NULL; 496*4235Smarkfen 497*4235Smarkfen /* Parameter reality check... */ 498*4235Smarkfen if (proto_number == -1) { 499*4235Smarkfen if (proto_name == NULL) { 500*4235Smarkfen warnx(gettext("Missing protocol number.")); 501*4235Smarkfen usage(); 502*4235Smarkfen } 503*4235Smarkfen proto_number = getipsecprotobyname(proto_name); 504*4235Smarkfen if (proto_number == -1) { 505*4235Smarkfen warnx(gettext("Unknown protocol.")); 506*4235Smarkfen usage(); 507*4235Smarkfen } 508*4235Smarkfen } 509*4235Smarkfen if (alg_number == -1) { 510*4235Smarkfen warnx(gettext("Missing algorithm number.")); 511*4235Smarkfen usage(); 512*4235Smarkfen } 513*4235Smarkfen if (key_sizes_string == NULL) { 514*4235Smarkfen warnx(gettext("Missing key size(s).")); 515*4235Smarkfen usage(); 516*4235Smarkfen } 517*4235Smarkfen if (alg_names_string == NULL) { 518*4235Smarkfen warnx(gettext("Missing algorithm name(s).")); 519*4235Smarkfen usage(); 520*4235Smarkfen } 521*4235Smarkfen if (block_sizes_string == NULL) { 522*4235Smarkfen warnx(gettext("Missing block/MAC lengths")); 523*4235Smarkfen usage(); 524*4235Smarkfen } 525*4235Smarkfen if (mech_name == NULL) { 526*4235Smarkfen warnx(gettext("Missing mechanism name.")); 527*4235Smarkfen usage(); 528*4235Smarkfen } 529*4235Smarkfen 530*4235Smarkfen newbie.a_proto_num = proto_number; 531*4235Smarkfen newbie.a_alg_num = alg_number; 532*4235Smarkfen newbie.a_key_increment = increment; 533*4235Smarkfen newbie.a_mech_name = mech_name; 534*4235Smarkfen 535*4235Smarkfen newbie.a_names = NULL; 536*4235Smarkfen while ((holder = strtok((holder == NULL) ? alg_names_string : NULL, 537*4235Smarkfen comma)) != NULL) { 538*4235Smarkfen newbie.a_names = realloc(newbie.a_names, 539*4235Smarkfen sizeof (char *) * ((++num_names) + 1)); 540*4235Smarkfen if (newbie.a_names == NULL) 541*4235Smarkfen bail_nomem(); 542*4235Smarkfen newbie.a_names[num_names - 1] = holder; 543*4235Smarkfen newbie.a_names[num_names] = NULL; 544*4235Smarkfen } 545*4235Smarkfen 546*4235Smarkfen /* Extract block sizes. */ 547*4235Smarkfen newbie.a_block_sizes = parse_intlist(block_sizes_string, 548*4235Smarkfen &num_block_sizes); 549*4235Smarkfen 550*4235Smarkfen /* Extract key sizes. */ 551*4235Smarkfen if ((holder = strchr(key_sizes_string, '-')) != NULL) { 552*4235Smarkfen /* key sizes by range, key size increment required */ 553*4235Smarkfen if (newbie.a_key_increment == 0) { 554*4235Smarkfen warnx(gettext("Missing key increment")); 555*4235Smarkfen usage(); 556*4235Smarkfen } 557*4235Smarkfen newbie.a_key_sizes = calloc(sizeof (int), 558*4235Smarkfen LIBIPSEC_ALGS_KEY_NUM_VAL); 559*4235Smarkfen if (newbie.a_key_sizes == NULL) 560*4235Smarkfen bail_nomem(); 561*4235Smarkfen *holder = '\0'; 562*4235Smarkfen holder++; 563*4235Smarkfen /* 564*4235Smarkfen * At this point, holder points to high, key_sizes_string 565*4235Smarkfen * points to low. 566*4235Smarkfen */ 567*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX] = 568*4235Smarkfen atoi(key_sizes_string); 569*4235Smarkfen if (newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX] == 0) { 570*4235Smarkfen warnx(gettext("Invalid lower key size range")); 571*4235Smarkfen usage(); 572*4235Smarkfen } 573*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MAX_IDX] = atoi(holder); 574*4235Smarkfen if (newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MAX_IDX] == 0) { 575*4235Smarkfen warnx(gettext("Invalid higher key size range")); 576*4235Smarkfen usage(); 577*4235Smarkfen } 578*4235Smarkfen 579*4235Smarkfen /* sanity check key range consistency */ 580*4235Smarkfen if (newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX] >= 581*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MAX_IDX]) { 582*4235Smarkfen warnx(gettext("Invalid key size range (min >= max)")); 583*4235Smarkfen usage(); 584*4235Smarkfen } 585*4235Smarkfen 586*4235Smarkfen /* check key increment vs key range */ 587*4235Smarkfen if (((newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MAX_IDX] - 588*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX]) % 589*4235Smarkfen newbie.a_key_increment) != 0) { 590*4235Smarkfen warnx(gettext("Key size increment" 591*4235Smarkfen " not consistent with key size range")); 592*4235Smarkfen usage(); 593*4235Smarkfen } 594*4235Smarkfen 595*4235Smarkfen /* default key size */ 596*4235Smarkfen if (default_keylen != 0) { 597*4235Smarkfen /* check specified default key size */ 598*4235Smarkfen if (default_keylen < 599*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX] || 600*4235Smarkfen default_keylen > 601*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MAX_IDX] || 602*4235Smarkfen ((default_keylen - 603*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX]) % 604*4235Smarkfen newbie.a_key_increment) != 0) { 605*4235Smarkfen warnx(gettext("Default key size not consistent" 606*4235Smarkfen " with key size range")); 607*4235Smarkfen usage(); 608*4235Smarkfen } 609*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_DEF_IDX] = 610*4235Smarkfen default_keylen; 611*4235Smarkfen } else { 612*4235Smarkfen /* min key size in range if not specified */ 613*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_DEF_IDX] = 614*4235Smarkfen newbie.a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX]; 615*4235Smarkfen } 616*4235Smarkfen } else { 617*4235Smarkfen /* key sizes by enumeration */ 618*4235Smarkfen if (newbie.a_key_increment != 0) { 619*4235Smarkfen warnx(gettext("Key increment must " 620*4235Smarkfen "not be specified with key sizes enumeration")); 621*4235Smarkfen usage(); 622*4235Smarkfen } 623*4235Smarkfen newbie.a_key_sizes = parse_intlist(key_sizes_string, 624*4235Smarkfen &num_key_sizes); 625*4235Smarkfen 626*4235Smarkfen /* default key size */ 627*4235Smarkfen if (default_keylen != 0 && default_keylen != 628*4235Smarkfen newbie.a_key_sizes[0]) { 629*4235Smarkfen /* 630*4235Smarkfen * The default key size is not at the front of the 631*4235Smarkfen * list. Swap it with the first element of the list. 632*4235Smarkfen */ 633*4235Smarkfen for (i = 1; i < num_key_sizes; i++) { 634*4235Smarkfen if (newbie.a_key_sizes[i] == default_keylen) 635*4235Smarkfen break; 636*4235Smarkfen if (i >= num_key_sizes) { 637*4235Smarkfen warnx(gettext("Default key size not " 638*4235Smarkfen "in list of key sizes")); 639*4235Smarkfen usage(); 640*4235Smarkfen } 641*4235Smarkfen newbie.a_key_sizes[i] = newbie.a_key_sizes[0]; 642*4235Smarkfen newbie.a_key_sizes[0] = default_keylen; 643*4235Smarkfen } 644*4235Smarkfen } 645*4235Smarkfen } 646*4235Smarkfen 647*4235Smarkfen /* Call things! */ 648*4235Smarkfen if ((rc = addipsecalg(&newbie, adddel_flags)) != 0) { 649*4235Smarkfen errx(EXIT_FAILURE, gettext("addipsecalg() call failed: " 650*4235Smarkfen "%s"), ipsecalgs_diag(rc)); 651*4235Smarkfen } 652*4235Smarkfen 653*4235Smarkfen free(newbie.a_names); 654*4235Smarkfen free(newbie.a_block_sizes); 655*4235Smarkfen free(newbie.a_key_sizes); 656*4235Smarkfen } 657*4235Smarkfen 658*4235Smarkfen static void 659*4235Smarkfen new_proto(void) 660*4235Smarkfen { 661*4235Smarkfen int rc; 662*4235Smarkfen 663*4235Smarkfen if ((rc = addipsecproto(proto_name, proto_number, proto_exec_mode, 664*4235Smarkfen adddel_flags)) 665*4235Smarkfen != 0) { 666*4235Smarkfen errx(EXIT_FAILURE, gettext( 667*4235Smarkfen "Cannot add protocol %1$d \"%2$s\": %3$s"), proto_number, 668*4235Smarkfen proto_name, ipsecalgs_diag(rc)); 669*4235Smarkfen } 670*4235Smarkfen } 671*4235Smarkfen 672*4235Smarkfen static void 673*4235Smarkfen remove_alg(void) 674*4235Smarkfen { 675*4235Smarkfen int rc; 676*4235Smarkfen 677*4235Smarkfen if (proto_number == -1) { 678*4235Smarkfen if (proto_name == NULL) { 679*4235Smarkfen warnx(gettext("Missing protocol number.")); 680*4235Smarkfen usage(); 681*4235Smarkfen } 682*4235Smarkfen proto_number = getipsecprotobyname(proto_name); 683*4235Smarkfen if (proto_number == -1) { 684*4235Smarkfen errx(EXIT_FAILURE, gettext( 685*4235Smarkfen "Unknown protocol \"%s\"."), proto_name); 686*4235Smarkfen } 687*4235Smarkfen } 688*4235Smarkfen 689*4235Smarkfen if (alg_number == -1) { 690*4235Smarkfen if (alg_names_string == NULL) { 691*4235Smarkfen errx(EXIT_FAILURE, gettext("Missing algorithm ID.")); 692*4235Smarkfen } 693*4235Smarkfen if (strchr(alg_names_string, ',') != NULL) { 694*4235Smarkfen errx(EXIT_FAILURE, gettext( 695*4235Smarkfen "Specify a single algorithm name for removal, " 696*4235Smarkfen "not a list.")); 697*4235Smarkfen } 698*4235Smarkfen if ((rc = delipsecalgbyname(alg_names_string, proto_number)) 699*4235Smarkfen != 0) { 700*4235Smarkfen errx(EXIT_FAILURE, gettext( 701*4235Smarkfen "Could not remove algorithm %1$s: %2$s"), 702*4235Smarkfen alg_names_string, ipsecalgs_diag(rc)); 703*4235Smarkfen } 704*4235Smarkfen } else { 705*4235Smarkfen if ((rc = delipsecalgbynum(alg_number, proto_number)) != 0) { 706*4235Smarkfen errx(EXIT_FAILURE, gettext( 707*4235Smarkfen "Could not remove algorithm %1$d: %2$s"), 708*4235Smarkfen alg_number, ipsecalgs_diag(rc)); 709*4235Smarkfen } 710*4235Smarkfen } 711*4235Smarkfen } 712*4235Smarkfen 713*4235Smarkfen static void 714*4235Smarkfen remove_proto(void) 715*4235Smarkfen { 716*4235Smarkfen int rc; 717*4235Smarkfen 718*4235Smarkfen if (proto_number == -1) { 719*4235Smarkfen if (proto_name == NULL) { 720*4235Smarkfen warnx(gettext("Please specify protocol to remove.")); 721*4235Smarkfen usage(); 722*4235Smarkfen } 723*4235Smarkfen if ((rc = delipsecprotobyname(proto_name)) != 0) { 724*4235Smarkfen errx(EXIT_FAILURE, gettext( 725*4235Smarkfen "Could not remove protocol %1$s: %2$s"), 726*4235Smarkfen proto_name, ipsecalgs_diag(rc)); 727*4235Smarkfen } 728*4235Smarkfen } else { 729*4235Smarkfen if ((rc = delipsecprotobynum(proto_number)) != 0) { 730*4235Smarkfen errx(EXIT_FAILURE, gettext( 731*4235Smarkfen "Could not remove protocol %1$d: %2$s"), 732*4235Smarkfen proto_number, ipsecalgs_diag(rc)); 733*4235Smarkfen } 734*4235Smarkfen } 735*4235Smarkfen } 736*4235Smarkfen 737*4235Smarkfen static void 738*4235Smarkfen set_exec_mode(void) 739*4235Smarkfen { 740*4235Smarkfen int rc; 741*4235Smarkfen 742*4235Smarkfen if (proto_number == -1) { 743*4235Smarkfen if (proto_name == NULL) { 744*4235Smarkfen warnx(gettext( 745*4235Smarkfen "Please specify protocol name or number.")); 746*4235Smarkfen usage(); 747*4235Smarkfen } 748*4235Smarkfen proto_number = getipsecprotobyname(proto_name); 749*4235Smarkfen if (proto_number == -1) { 750*4235Smarkfen errx(EXIT_FAILURE, gettext("Unknown protocol %s"), 751*4235Smarkfen proto_name); 752*4235Smarkfen } 753*4235Smarkfen } 754*4235Smarkfen 755*4235Smarkfen if ((rc = ipsecproto_set_exec_mode(proto_number, proto_exec_mode)) 756*4235Smarkfen != 0) { 757*4235Smarkfen errx(EXIT_FAILURE, gettext("Cannot set execution mode: %s"), 758*4235Smarkfen ipsecalgs_diag(rc)); 759*4235Smarkfen } 760*4235Smarkfen } 761*4235Smarkfen 762*4235Smarkfen /* 763*4235Smarkfen * Print a description of an algorithm to standard output. 764*4235Smarkfen */ 765*4235Smarkfen static void 766*4235Smarkfen dump_alg(struct ipsecalgent *alg) 767*4235Smarkfen { 768*4235Smarkfen int *ifloater; 769*4235Smarkfen char **floater; 770*4235Smarkfen 771*4235Smarkfen /* protocol number */ 772*4235Smarkfen (void) printf(gettext("\tProtocol number: %d\n"), alg->a_proto_num); 773*4235Smarkfen 774*4235Smarkfen /* algorithm number */ 775*4235Smarkfen (void) printf(gettext("\tAlgorithm number: %d\n"), alg->a_alg_num); 776*4235Smarkfen 777*4235Smarkfen /* algorithm name(s) */ 778*4235Smarkfen if (alg->a_names != NULL) { 779*4235Smarkfen (void) printf(gettext("\tAlgorithm names: ")); 780*4235Smarkfen floater = alg->a_names; 781*4235Smarkfen assert(floater != NULL && *floater != NULL); 782*4235Smarkfen do { 783*4235Smarkfen /* Assume at least one string. */ 784*4235Smarkfen (void) printf("%s", *floater); 785*4235Smarkfen if (*(++floater) != NULL) 786*4235Smarkfen (void) putchar(','); 787*4235Smarkfen } while (*floater != NULL); 788*4235Smarkfen (void) putchar('\n'); 789*4235Smarkfen } 790*4235Smarkfen 791*4235Smarkfen /* mechanism name */ 792*4235Smarkfen (void) printf(gettext("\tMechanism Name: %s\n"), alg->a_mech_name); 793*4235Smarkfen 794*4235Smarkfen /* block/MAC sizes */ 795*4235Smarkfen (void) printf(gettext("\tBlock sizes or MAC sizes: ")); 796*4235Smarkfen ifloater = alg->a_block_sizes; 797*4235Smarkfen (void) list_ints(stdout, ifloater); 798*4235Smarkfen (void) putchar('\n'); 799*4235Smarkfen 800*4235Smarkfen /* key sizes */ 801*4235Smarkfen (void) printf(gettext("\tKey sizes: ")); 802*4235Smarkfen if (alg->a_key_increment != 0) 803*4235Smarkfen /* key specified by range */ 804*4235Smarkfen (void) printf(gettext( 805*4235Smarkfen "%1$d-%2$d, increment %3$d, default %4$d"), 806*4235Smarkfen alg->a_key_sizes[LIBIPSEC_ALGS_KEY_MIN_IDX], 807*4235Smarkfen alg->a_key_sizes[LIBIPSEC_ALGS_KEY_MAX_IDX], 808*4235Smarkfen alg->a_key_increment, 809*4235Smarkfen alg->a_key_sizes[LIBIPSEC_ALGS_KEY_DEF_IDX]); 810*4235Smarkfen else 811*4235Smarkfen /* key specified by enumeration */ 812*4235Smarkfen (void) list_ints(stdout, alg->a_key_sizes); 813*4235Smarkfen (void) putchar('\n'); 814*4235Smarkfen 815*4235Smarkfen (void) putchar('\n'); 816*4235Smarkfen } 817*4235Smarkfen 818*4235Smarkfen /* 819*4235Smarkfen * Print the description of a protocol. 820*4235Smarkfen */ 821*4235Smarkfen static void 822*4235Smarkfen dump_proto(uint_t proto_id) 823*4235Smarkfen { 824*4235Smarkfen char *proto_name; 825*4235Smarkfen ipsecalgs_exec_mode_t exec_mode; 826*4235Smarkfen 827*4235Smarkfen /* protocol name and number */ 828*4235Smarkfen proto_name = getipsecprotobynum(proto_id); 829*4235Smarkfen (void) printf(gettext("Protocol %1$d/%2$s "), 830*4235Smarkfen proto_id, proto_name != NULL ? proto_name : gettext("<unknown>")); 831*4235Smarkfen 832*4235Smarkfen /* execution mode */ 833*4235Smarkfen (void) printf("(%s", gettext("execution mode: ")); 834*4235Smarkfen 835*4235Smarkfen if (ipsecproto_get_exec_mode(proto_id, &exec_mode) != 0) { 836*4235Smarkfen (void) printf(gettext("<unknown>")); 837*4235Smarkfen } else { 838*4235Smarkfen switch (exec_mode) { 839*4235Smarkfen case LIBIPSEC_ALGS_EXEC_SYNC: 840*4235Smarkfen (void) printf("sync"); 841*4235Smarkfen break; 842*4235Smarkfen case LIBIPSEC_ALGS_EXEC_ASYNC: 843*4235Smarkfen (void) printf("async"); 844*4235Smarkfen break; 845*4235Smarkfen } 846*4235Smarkfen } 847*4235Smarkfen 848*4235Smarkfen (void) printf(")\n\n"); 849*4235Smarkfen 850*4235Smarkfen free(proto_name); 851*4235Smarkfen } 852*4235Smarkfen 853*4235Smarkfen 854*4235Smarkfen /* 855*4235Smarkfen * Algorithm walker table. Call proto_action() for each protocol, 856*4235Smarkfen * and alg_action() for each algorithm. 857*4235Smarkfen */ 858*4235Smarkfen static void 859*4235Smarkfen algs_walker(void (*alg_action)(struct ipsecalgent *), 860*4235Smarkfen void (*proto_action)(uint_t)) 861*4235Smarkfen { 862*4235Smarkfen int *proto_nums, proto_count, i; 863*4235Smarkfen int *alg_nums, alg_count, j; 864*4235Smarkfen struct ipsecalgent *alg; 865*4235Smarkfen 866*4235Smarkfen proto_nums = getipsecprotos(&proto_count); 867*4235Smarkfen if (proto_nums == NULL) { 868*4235Smarkfen errx(EXIT_FAILURE, gettext("getipsecprotos() failed.")); 869*4235Smarkfen } 870*4235Smarkfen 871*4235Smarkfen for (i = 0; i < proto_count; i++) { 872*4235Smarkfen 873*4235Smarkfen if (proto_action != NULL) 874*4235Smarkfen proto_action(proto_nums[i]); 875*4235Smarkfen 876*4235Smarkfen alg_nums = getipsecalgs(&alg_count, proto_nums[i]); 877*4235Smarkfen if (alg_nums == NULL) { 878*4235Smarkfen free(proto_nums); 879*4235Smarkfen errx(EXIT_FAILURE, gettext("getipsecalgs() failed.")); 880*4235Smarkfen } 881*4235Smarkfen 882*4235Smarkfen for (j = 0; j < alg_count; j++) { 883*4235Smarkfen alg = getipsecalgbynum(alg_nums[j], proto_nums[i], 884*4235Smarkfen NULL); 885*4235Smarkfen if (alg == NULL) 886*4235Smarkfen continue; 887*4235Smarkfen if (alg_action != NULL) 888*4235Smarkfen alg_action(alg); 889*4235Smarkfen freeipsecalgent(alg); 890*4235Smarkfen } 891*4235Smarkfen free(alg_nums); 892*4235Smarkfen } 893*4235Smarkfen free(proto_nums); 894*4235Smarkfen } 895*4235Smarkfen 896*4235Smarkfen /* 897*4235Smarkfen * Use just the libnsl/libipsecutil APIs to dump out all of the algorithms. 898*4235Smarkfen */ 899*4235Smarkfen static void 900*4235Smarkfen show_algs(void) 901*4235Smarkfen { 902*4235Smarkfen /* Yes, I'm aware that this'll produce TWO newlines. */ 903*4235Smarkfen (void) puts(gettext( 904*4235Smarkfen "List of algorithms, grouped by IPsec protocol:\n")); 905*4235Smarkfen 906*4235Smarkfen algs_walker(dump_alg, dump_proto); 907*4235Smarkfen } 908*4235Smarkfen 909*4235Smarkfen static int 910*4235Smarkfen try_int(char *optarg, const char *what) 911*4235Smarkfen { 912*4235Smarkfen int rc = atoi(optarg); 913*4235Smarkfen 914*4235Smarkfen if (rc <= 0) { 915*4235Smarkfen warnx(gettext("Invalid %s value"), what); 916*4235Smarkfen usage(); 917*4235Smarkfen } 918*4235Smarkfen return (rc); 919*4235Smarkfen } 920*4235Smarkfen 921*4235Smarkfen static void 922*4235Smarkfen try_cmd(cmd_t newcmd) 923*4235Smarkfen { 924*4235Smarkfen if (cmd != CMD_NONE) 925*4235Smarkfen usage(); 926*4235Smarkfen cmd = newcmd; 927*4235Smarkfen } 928*4235Smarkfen 929*4235Smarkfen int 930*4235Smarkfen main(int argc, char *argv[]) 931*4235Smarkfen { 932*4235Smarkfen int c; 933*4235Smarkfen zoneid_t zoneid; 934*4235Smarkfen ushort_t flags; 935*4235Smarkfen 936*4235Smarkfen (void) setlocale(LC_ALL, ""); 937*4235Smarkfen #if !defined(TEXT_DOMAIN) 938*4235Smarkfen #define TEXT_DOMAIN "SYS_TEST" 939*4235Smarkfen #endif 940*4235Smarkfen (void) textdomain(TEXT_DOMAIN); 941*4235Smarkfen 942*4235Smarkfen if (argc == 1) { 943*4235Smarkfen show_algs(); 944*4235Smarkfen return (EXIT_SUCCESS); 945*4235Smarkfen } 946*4235Smarkfen 947*4235Smarkfen while ((c = getopt(argc, argv, 948*4235Smarkfen "aflrRsb:p:P:i:k:K:m:n:N:e:")) != EOF) { 949*4235Smarkfen switch (c) { 950*4235Smarkfen case 'a': 951*4235Smarkfen try_cmd(CMD_ADD); 952*4235Smarkfen break; 953*4235Smarkfen case 'f': 954*4235Smarkfen /* multiple occurences of -f are harmless */ 955*4235Smarkfen adddel_flags = LIBIPSEC_ALGS_ADD_FORCE; 956*4235Smarkfen break; 957*4235Smarkfen case 'l': 958*4235Smarkfen try_cmd(CMD_LIST_KERNEL); 959*4235Smarkfen break; 960*4235Smarkfen case 'r': 961*4235Smarkfen try_cmd(CMD_DEL); 962*4235Smarkfen break; 963*4235Smarkfen case 'R': 964*4235Smarkfen try_cmd(CMD_DEL_PROTO); 965*4235Smarkfen break; 966*4235Smarkfen case 's': 967*4235Smarkfen /* multiple occurences of -s are harmless */ 968*4235Smarkfen synch_kernel = B_TRUE; 969*4235Smarkfen break; 970*4235Smarkfen case 'n': 971*4235Smarkfen if (alg_names_string != NULL) 972*4235Smarkfen usage(); 973*4235Smarkfen alg_names_string = optarg; 974*4235Smarkfen break; 975*4235Smarkfen case 'b': 976*4235Smarkfen if (block_sizes_string != NULL) 977*4235Smarkfen usage(); 978*4235Smarkfen block_sizes_string = optarg; 979*4235Smarkfen break; 980*4235Smarkfen case 'p': 981*4235Smarkfen if (proto_name != NULL) 982*4235Smarkfen usage(); 983*4235Smarkfen proto_name = optarg; 984*4235Smarkfen break; 985*4235Smarkfen case 'P': 986*4235Smarkfen if (proto_number != -1) 987*4235Smarkfen usage(); 988*4235Smarkfen proto_number = try_int(optarg, 989*4235Smarkfen gettext("protocol number")); 990*4235Smarkfen break; 991*4235Smarkfen case 'e': 992*4235Smarkfen if (exec_mode_string != NULL) 993*4235Smarkfen usage(); 994*4235Smarkfen exec_mode_string = optarg; 995*4235Smarkfen if (_str_to_ipsec_exec_mode(exec_mode_string, 996*4235Smarkfen &proto_exec_mode) == -1) { 997*4235Smarkfen warnx(gettext("Invalid execution mode \"%s\""), 998*4235Smarkfen exec_mode_string); 999*4235Smarkfen usage(); 1000*4235Smarkfen } 1001*4235Smarkfen break; 1002*4235Smarkfen case 'i': 1003*4235Smarkfen if (increment != 0) 1004*4235Smarkfen usage(); 1005*4235Smarkfen increment = try_int(optarg, 1006*4235Smarkfen gettext("key size increment")); 1007*4235Smarkfen break; 1008*4235Smarkfen case 'k': 1009*4235Smarkfen if (key_sizes_string != NULL) 1010*4235Smarkfen usage(); 1011*4235Smarkfen key_sizes_string = optarg; 1012*4235Smarkfen break; 1013*4235Smarkfen case 'K': 1014*4235Smarkfen if (default_keylen != 0) 1015*4235Smarkfen usage(); 1016*4235Smarkfen default_keylen = try_int(optarg, 1017*4235Smarkfen gettext("default key size")); 1018*4235Smarkfen break; 1019*4235Smarkfen case 'm': 1020*4235Smarkfen if (mech_name != NULL) 1021*4235Smarkfen usage(); 1022*4235Smarkfen mech_name = optarg; 1023*4235Smarkfen break; 1024*4235Smarkfen case 'N': 1025*4235Smarkfen if (alg_number != -1) 1026*4235Smarkfen usage(); 1027*4235Smarkfen alg_number = try_int(optarg, 1028*4235Smarkfen gettext("algorithm number")); 1029*4235Smarkfen break; 1030*4235Smarkfen } 1031*4235Smarkfen } 1032*4235Smarkfen 1033*4235Smarkfen /* 1034*4235Smarkfen * When both protocol name (-p) and protocol number (-P) are 1035*4235Smarkfen * specified, a new protocol is being defined. 1036*4235Smarkfen */ 1037*4235Smarkfen if (proto_number != -1 && proto_name != NULL) 1038*4235Smarkfen try_cmd(CMD_ADD_PROTO); 1039*4235Smarkfen else if (exec_mode_string != NULL) 1040*4235Smarkfen try_cmd(CMD_EXEC_MODE); 1041*4235Smarkfen 1042*4235Smarkfen /* 1043*4235Smarkfen * Process specified command. 1044*4235Smarkfen */ 1045*4235Smarkfen switch (cmd) { 1046*4235Smarkfen case CMD_ADD: 1047*4235Smarkfen new_alg(); 1048*4235Smarkfen break; 1049*4235Smarkfen case CMD_ADD_PROTO: 1050*4235Smarkfen new_proto(); 1051*4235Smarkfen break; 1052*4235Smarkfen case CMD_DEL: 1053*4235Smarkfen remove_alg(); 1054*4235Smarkfen break; 1055*4235Smarkfen case CMD_DEL_PROTO: 1056*4235Smarkfen remove_proto(); 1057*4235Smarkfen break; 1058*4235Smarkfen case CMD_EXEC_MODE: 1059*4235Smarkfen set_exec_mode(); 1060*4235Smarkfen break; 1061*4235Smarkfen case CMD_LIST_KERNEL: 1062*4235Smarkfen if (synch_kernel) 1063*4235Smarkfen usage(); 1064*4235Smarkfen list_kernel_algs(); 1065*4235Smarkfen break; 1066*4235Smarkfen default: 1067*4235Smarkfen if (!synch_kernel) 1068*4235Smarkfen usage(); 1069*4235Smarkfen } 1070*4235Smarkfen 1071*4235Smarkfen if (synch_kernel) { 1072*4235Smarkfen /* 1073*4235Smarkfen * This will only work in the global zone or 1074*4235Smarkfen * a zone with an exclusive IP stack. 1075*4235Smarkfen */ 1076*4235Smarkfen if ((zoneid = getzoneid()) == 0) { 1077*4235Smarkfen kernel_synch(); 1078*4235Smarkfen } else { 1079*4235Smarkfen if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags, 1080*4235Smarkfen sizeof (flags)) < 0) { 1081*4235Smarkfen err(EXIT_FAILURE, gettext( 1082*4235Smarkfen "Unable to determine zone IP type")); 1083*4235Smarkfen } 1084*4235Smarkfen if (flags & ZF_NET_EXCL) { 1085*4235Smarkfen kernel_synch(); 1086*4235Smarkfen } else { 1087*4235Smarkfen (void) printf(gettext("Synchronization with " 1088*4235Smarkfen "kernel not appropriate in this zone.\n")); 1089*4235Smarkfen } 1090*4235Smarkfen } 1091*4235Smarkfen } 1092*4235Smarkfen 1093*4235Smarkfen return (EXIT_SUCCESS); 1094*4235Smarkfen } 1095