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