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
parse_flag(char * flag_str,uint_t flag)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
usage(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
bail_nomem(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
num_sizes(int * sizes)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
synch_emit_alg(struct ipsecalgent * alg)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
synch_emit_proto(uint_t proto_num)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
kernel_synch(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
list_kernel_algs(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 *
parse_intlist(char * args,int * num_args)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
new_alg(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
new_proto(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
remove_alg(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
remove_proto(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
set_exec_mode(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
dump_alg(struct ipsecalgent * alg)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
dump_proto(uint_t proto_id)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
algs_walker(void (* alg_action)(struct ipsecalgent *),void (* proto_action)(uint_t))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
show_algs(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
try_int(char * optarg,const char * what)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
try_cmd(cmd_t newcmd)1022e3320f40Smarkfen try_cmd(cmd_t newcmd)
1023e3320f40Smarkfen {
1024e3320f40Smarkfen if (cmd != CMD_NONE)
1025e3320f40Smarkfen usage();
1026e3320f40Smarkfen cmd = newcmd;
1027e3320f40Smarkfen }
1028e3320f40Smarkfen
1029e3320f40Smarkfen int
main(int argc,char * argv[])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