dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libipsecutil / common / algs.c
blobd59951c232441e0ad81ddef07df840cd0b8518e7
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <ipsec_util.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <netdb.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <libintl.h>
35 #include <errno.h>
37 static char *preamble =
38 "# /etc/inet/ipsecalgs output from ipsecalgs(1m)\n"
39 "#\n"
40 "# DO NOT EDIT OR PARSE THIS FILE!\n"
41 "#\n"
42 "# Use the ipsecalgs(1m) command to change the contents of this file.\n"
43 "# The algorithm descriptions contained in this file are synchronised to the\n"
44 "# kernel with ipsecalgs -s, the kernel validates the entries at this point."
45 "\n\n"
46 "# PROTO|protocol-id|protocol-name|exec-mode\n"
47 "## NOTE: Some protocol numbers are well-known and defined in <netdb.h>\n\n"
48 "# ALG|protocol-id|alg-id|name,name,...|ef-id| \n"
49 "# {default/}{key,key..}or{key-key,inc}|block_size or MAC-size|\n"
50 "# [parameter,parameter..]|[flags]\n\n"
51 "#\n"
52 "## Note: Parameters and flags only apply to certain algorithms.\n\n";
54 #define CFG_PERMS S_IRUSR | S_IRGRP | S_IROTH /* Perms 0444. */
55 #define CFG_OWNER 0 /* root */
56 #define CFG_GROUP 1 /* "other" */
59 * write_new_algfile() helper macros to check for write errors.
62 #define FPRINTF_ERR(fcall) if ((fcall) < 0) { \
63 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; \
64 goto bail; \
67 #define FPUT_ERR(fcall) if ((fcall) == EOF) { \
68 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; \
69 goto bail; \
73 * Helper macros to start and finish a list of entries that were added
74 * as part of a package installation.
77 #define PKG_SEC_START(pkgname, doing_pkg, cur_pkg) { \
78 (void) strcpy((cur_pkg), (pkgname)); \
79 FPRINTF_ERR(fprintf(f, "%s%s\n", \
80 LIBIPSEC_ALGS_LINE_PKGSTART, (cur_pkg))); \
81 (doing_pkg) = B_TRUE; \
84 #define PKG_SEC_END(doing_pkg, cur_pkg) { \
85 if (doing_pkg) { \
86 FPRINTF_ERR(fprintf(f, "%s%s\n", \
87 LIBIPSEC_ALGS_LINE_PKGEND, (cur_pkg))); \
88 (doing_pkg) = B_FALSE; \
89 } \
93 * Take a zero-terminated int array and print int1,int2...,intN.
94 * If zero-only, then print a single '0'.
95 * Returns 0 on success, -1 if an error occurred while writing to
96 * the specified file.
98 int
99 list_ints(FILE *f, int *floater)
101 boolean_t executed = B_FALSE;
103 while (*floater != 0) {
104 executed = B_TRUE;
105 if (fprintf(f, "%d", *floater) < 0)
106 return (-1);
107 if (*(++floater) != 0)
108 if (fputc(',', f) == EOF)
109 return (-1);
112 if (!executed)
113 if (fputc('0', f) == EOF)
114 return (-1);
116 return (0);
120 * If the specified algorithm was defined within a package section, i.e.
121 * between the lines "# Start <pkgname>" and "# End <pkgname>", returns
122 * the value of <pkgname>.
124 static char *
125 alg_has_pkg(ipsec_proto_t *proto, struct ipsecalgent *alg)
127 int i;
129 if (proto->proto_algs_pkgs == NULL)
130 return (NULL);
132 for (i = 0; i < proto->proto_algs_npkgs; i++)
133 if (proto->proto_algs_pkgs[i].alg_num == alg->a_alg_num)
134 return (proto->proto_algs_pkgs[i].pkg_name);
136 return (NULL);
140 * Writes the package start/end delimiters according to the package
141 * name associated with the current protocol or algorithm, and
142 * the state of the packaging information already written to the file.
143 * Called by write_new_algfile(). Returns 0 on success, one of the
144 * LIBIPSEC_DIAG codes on failure.
146 static int
147 pkg_section(FILE *f, char *pkg_name, boolean_t *doing_pkg, char *cur_pkg)
149 int rc = 0;
151 if (pkg_name != NULL) {
152 /* protocol or algorithm is associated with a package */
153 if (!*doing_pkg) {
154 /* start of a new package section */
155 PKG_SEC_START(pkg_name, *doing_pkg, cur_pkg);
156 } else {
157 /* already in a package section */
158 if (strcmp(pkg_name, cur_pkg) != 0) {
159 /* different package name */
160 PKG_SEC_END(*doing_pkg, cur_pkg);
161 PKG_SEC_START(pkg_name, *doing_pkg, cur_pkg);
164 } else if (*doing_pkg) {
165 /* in a package section when the entry isn't */
166 PKG_SEC_END(*doing_pkg, cur_pkg);
168 bail:
169 return (rc);
173 * Given a list of protocols and number, write them to a new algorithm file.
174 * This function takes num_protos + num_protos * dois-per-alg operations.
175 * Also free the protocol structure.
177 * Note that no locking spans the read/update/write phases that can be
178 * used by callers of this routine. This could cause this function to suffer
179 * from the "lost update" problem. Since updates to the IPsec protocols
180 * and algorithm tables are very infrequent, this should not be a issue in
181 * practice.
183 static int
184 write_new_algfile(ipsec_proto_t *protos, int num_protos)
186 FILE *f;
187 int fd, i, j, k;
188 int rc = 0;
189 struct ipsecalgent *alg;
190 char cur_pkg[1024];
191 boolean_t doing_pkg = B_FALSE;
192 char *alg_pkg;
193 char tmp_name_template[] = INET_IPSECALGSPATH "ipsecalgsXXXXXX";
194 char *tmp_name;
197 * In order to avoid potentially corrupting the configuration
198 * file on file system failure, write the new configuration info
199 * to a temporary file which is then renamed to the configuration
200 * file (INET_IPSECALGSFILE.)
202 tmp_name = mktemp(tmp_name_template);
204 fd = open(tmp_name, O_WRONLY|O_CREAT|O_EXCL, CFG_PERMS);
205 if (fd == -1) {
206 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEOPEN;
207 goto bail;
210 f = fdopen(fd, "w");
211 if (f == NULL) {
212 (void) close(fd);
213 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEFDOPEN;
214 goto bail;
217 FPUT_ERR(fputs(preamble, f));
219 /* Write protocol entries. */
220 for (i = 0; i < num_protos; i++) {
222 /* add package section delimiters if needed */
223 rc = pkg_section(f, protos[i].proto_pkg, &doing_pkg, cur_pkg);
224 if (rc != 0)
225 goto bail;
227 FPRINTF_ERR(fprintf(f, "%s%d|%s|",
228 LIBIPSEC_ALGS_LINE_PROTO,
229 protos[i].proto_num, protos[i].proto_name));
230 switch (protos[i].proto_exec_mode) {
231 case LIBIPSEC_ALGS_EXEC_SYNC:
232 FPRINTF_ERR(fprintf(f, "sync\n"));
233 break;
234 case LIBIPSEC_ALGS_EXEC_ASYNC:
235 FPRINTF_ERR(fprintf(f, "async\n"));
236 break;
240 /* terminate the package section for the protocols if needed */
241 PKG_SEC_END(doing_pkg, cur_pkg);
243 FPUT_ERR(fputs("\n", f));
245 /* Write algorithm entries. */
247 for (i = 0; i < num_protos; i++) {
248 for (j = 0; j < protos[i].proto_numalgs; j++) {
249 alg = protos[i].proto_algs[j];
251 /* add package section delimiters if needed */
252 alg_pkg = alg_has_pkg(&protos[i], alg);
253 rc = pkg_section(f, alg_pkg, &doing_pkg, cur_pkg);
254 if (rc != 0)
255 goto bail;
257 /* protocol and algorithm numbers */
258 FPRINTF_ERR(fprintf(f, "%s%d|%d|",
259 LIBIPSEC_ALGS_LINE_ALG,
260 alg->a_proto_num, alg->a_alg_num));
262 /* algorithm names */
263 for (k = 0; alg->a_names[k] != NULL; k++) {
264 FPRINTF_ERR(fprintf(f, "%s", alg->a_names[k]));
265 if (alg->a_names[k+1] != NULL)
266 FPRINTF_ERR(fprintf(f, ","));
269 /* mechanism name */
270 FPRINTF_ERR(fprintf(f, "|%s|", alg->a_mech_name));
272 /* key sizes */
273 if (alg->a_key_increment == 0) {
274 /* key sizes defined by enumeration */
275 if (list_ints(f, alg->a_key_sizes) == -1) {
276 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE;
277 goto bail;
279 } else {
280 /* key sizes defined by range */
281 FPRINTF_ERR(fprintf(f, "%d/%d-%d,%d",
282 alg->a_key_sizes[0], alg->a_key_sizes[1],
283 alg->a_key_sizes[2], alg->a_key_increment));
285 FPUT_ERR(fputc('|', f));
287 /* block sizes */
288 if (list_ints(f, alg->a_block_sizes) == -1) {
289 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE;
290 goto bail;
292 FPUT_ERR(fputc('|', f));
295 * Some algorithms require extra parameters, these
296 * are stored in an array. For algorithms that don't
297 * need these parameters, or flags (below), these
298 * extra fields in the ipsecalgs file must contain a
299 * zero. This fuction will get called if a algorithm
300 * entry is added, at this point the extra fields will
301 * be added to the file.
303 if (list_ints(f, alg->a_mech_params) == -1) {
304 rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE;
305 goto bail;
307 /* flags */
308 FPRINTF_ERR(fprintf(f, "|%d\n", alg->a_alg_flags));
312 /* terminate the package section for the algorithms if needed */
313 PKG_SEC_END(doing_pkg, cur_pkg);
315 if (fchmod(fd, CFG_PERMS) == -1) {
316 rc = LIBIPSEC_ALGS_DIAG_ALGSFILECHMOD;
317 goto bail;
319 if (fchown(fd, CFG_OWNER, CFG_GROUP) == -1) {
320 rc = LIBIPSEC_ALGS_DIAG_ALGSFILECHOWN;
321 goto bail;
323 if (fclose(f) == EOF) {
324 rc = LIBIPSEC_ALGS_DIAG_ALGSFILECLOSE;
325 goto bail;
328 if (rename(tmp_name, INET_IPSECALGSFILE) == -1)
329 rc = LIBIPSEC_ALGS_DIAG_ALGSFILERENAME;
331 bail:
332 _clean_trash(protos, num_protos);
333 return (rc);
337 * Return a pointer to the protocol entry corresponding to the specified
338 * protocol num proto_num. Also builds the list of currently defined
339 * protocols.
341 static ipsec_proto_t *
342 proto_setup(ipsec_proto_t **protos, int *num_protos, int proto_num,
343 boolean_t cleanup)
345 int i;
346 ipsec_proto_t *current_proto, *ret_proto = NULL;
348 _build_internal_algs(protos, num_protos);
350 if (*protos == NULL)
351 return (NULL);
353 for (i = 0; i < *num_protos; i++) {
354 current_proto = (*protos) + i;
355 if (current_proto->proto_num == proto_num) {
356 ret_proto = current_proto;
357 break;
361 if (ret_proto == NULL) {
362 if (cleanup)
363 _clean_trash(*protos, *num_protos);
364 /* else caller wants parsed /etc/inet/ipsecalgs anyway */
367 return (ret_proto);
371 * Delete the first found algorithm of the specified protocol which
372 * has the same name as the one specified by alg_name. Deletion of
373 * the entry takes place only if the delete_it flag is set. If an
374 * entry was found, return B_TRUE, otherwise return B_FALSE.
376 static boolean_t
377 delipsecalgbyname_common(const char *name, ipsec_proto_t *proto,
378 boolean_t delete_it)
380 int i;
381 char **name_check;
382 boolean_t found_match = B_FALSE;
384 for (i = 0; i < proto->proto_numalgs; i++) {
385 if (!found_match) {
386 for (name_check =
387 proto->proto_algs[i]->a_names;
388 *name_check != NULL; name_check++) {
390 * Can use strcmp because the algorithm names
391 * are bound.
393 if (strcmp(*name_check, name) == 0) {
394 found_match = B_TRUE;
395 if (!delete_it)
396 return (found_match);
397 freeipsecalgent(proto->proto_algs[i]);
398 break;
401 } else {
402 proto->proto_algs[i - 1] = proto->proto_algs[i];
406 if (found_match)
407 proto->proto_numalgs--;
409 return (found_match);
413 * Returns B_TRUE if the specified 0-terminated lists of key or
414 * block sizes match, B_FALSE otherwise.
416 static boolean_t
417 sizes_match(int *a1, int *a2)
419 int i;
421 for (i = 0; (a1[i] != 0) && (a2[i] != 0); i++) {
422 if (a1[i] != a2[i])
423 return (B_FALSE);
425 if ((a1[i] != 0) || (a2[i] != 0))
426 return (B_FALSE);
428 return (B_TRUE);
432 * Returns B_TRUE if an _exact_ equivalent of the specified algorithm
433 * already exists, B_FALSE otherwise.
435 static boolean_t
436 ipsecalg_exists(struct ipsecalgent *newbie, ipsec_proto_t *proto)
438 struct ipsecalgent *curalg;
439 char **curname, **newbiename;
440 int i;
441 boolean_t match;
443 for (i = 0; i < proto->proto_numalgs; i++) {
444 curalg = proto->proto_algs[i];
446 if (curalg->a_alg_num != newbie->a_alg_num)
447 continue;
449 if (curalg->a_key_increment != newbie->a_key_increment)
450 continue;
452 if (strcmp(curalg->a_mech_name, newbie->a_mech_name) != 0)
453 continue;
455 curname = curalg->a_names;
456 newbiename = newbie->a_names;
457 match = B_TRUE;
458 while ((*curname != NULL) && (*newbiename != NULL) && match) {
459 match = (strcmp(*curname, *newbiename) == 0);
460 curname++;
461 newbiename++;
463 if (!match || (*curname != NULL) || (*newbiename != NULL))
464 continue;
466 if (!sizes_match(curalg->a_block_sizes, newbie->a_block_sizes))
467 continue;
469 if (!sizes_match(curalg->a_key_sizes, newbie->a_key_sizes))
470 continue;
472 /* we found an exact match */
473 return (B_TRUE);
476 return (B_FALSE);
480 * Add a new algorithm to the /etc/inet/ipsecalgs file. Caller must free
481 * or otherwise address "newbie".
484 addipsecalg(struct ipsecalgent *newbie, uint_t flags)
486 ipsec_proto_t *protos, *current_proto;
487 struct ipsecalgent *clone, **holder;
488 int num_protos, i;
489 char **name_check;
490 boolean_t forced_add = (flags & LIBIPSEC_ALGS_ADD_FORCE) != 0;
491 boolean_t found_match;
493 if ((current_proto = proto_setup(&protos, &num_protos,
494 newbie->a_proto_num, B_TRUE)) == NULL)
495 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
498 * If an algorithm that matches _exactly_ the new algorithm
499 * already exists, we're done.
501 if (ipsecalg_exists(newbie, current_proto))
502 return (0);
505 * We don't allow a new algorithm to be created if one of
506 * its names is already defined for an existing algorithm,
507 * unless the operation is forced, in which case existing
508 * algorithm entries that conflict with the new one are
509 * deleted.
511 for (name_check = newbie->a_names; *name_check != NULL; name_check++) {
512 found_match = delipsecalgbyname_common(*name_check,
513 current_proto, forced_add);
514 if (found_match && !forced_add) {
516 * Duplicate entry found, but the addition was
517 * not forced.
519 _clean_trash(protos, num_protos);
520 return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS);
524 for (i = 0; i < current_proto->proto_numalgs; i++) {
525 if (current_proto->proto_algs[i]->a_alg_num ==
526 newbie->a_alg_num) {
528 * An algorithm with the same protocol number
529 * and algorithm number already exists. Fail
530 * addition unless the operation is forced.
532 if (flags & LIBIPSEC_ALGS_ADD_FORCE) {
533 clone = _duplicate_alg(newbie);
534 if (clone != NULL) {
535 freeipsecalgent(
536 current_proto->proto_algs[i]);
537 current_proto->proto_algs[i] = clone;
538 return (write_new_algfile(protos,
539 num_protos));
540 } else {
541 _clean_trash(protos, num_protos);
542 return (LIBIPSEC_ALGS_DIAG_NOMEM);
544 } else {
545 _clean_trash(protos, num_protos);
546 return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS);
551 /* append the new algorithm */
552 holder = reallocarray(current_proto->proto_algs, i + 1,
553 sizeof (struct ipsecalgent *));
554 if (holder == NULL) {
555 _clean_trash(protos, num_protos);
556 return (LIBIPSEC_ALGS_DIAG_NOMEM);
558 clone = _duplicate_alg(newbie);
559 if (clone == NULL) {
560 free(holder);
561 _clean_trash(protos, num_protos);
562 return (LIBIPSEC_ALGS_DIAG_NOMEM);
564 current_proto->proto_numalgs++;
565 current_proto->proto_algs = holder;
566 current_proto->proto_algs[i] = clone;
567 return (write_new_algfile(protos, num_protos));
571 * Delete an algorithm by name & protocol number from /etc/inet/ipsecalgs.
572 * Only deletes the first encountered instance.
575 delipsecalgbyname(const char *name, int proto_num)
577 ipsec_proto_t *protos, *current_proto;
578 int num_protos;
580 if ((current_proto = proto_setup(&protos, &num_protos, proto_num,
581 B_TRUE)) == NULL)
582 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
584 if (delipsecalgbyname_common(name, current_proto, B_TRUE))
585 return (write_new_algfile(protos, num_protos));
587 _clean_trash(protos, num_protos);
588 return (LIBIPSEC_ALGS_DIAG_UNKN_ALG);
592 * Delete an algorithm by num + protocol num from /etc/inet/ipsecalgs.
595 delipsecalgbynum(int alg_num, int proto_num)
597 ipsec_proto_t *protos, *current_proto;
598 int i, num_protos;
599 boolean_t found_match = B_FALSE;
601 if ((current_proto = proto_setup(&protos, &num_protos, proto_num,
602 B_TRUE)) == NULL)
603 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
605 for (i = 0; i < current_proto->proto_numalgs; i++) {
606 if (!found_match) {
607 if (current_proto->proto_algs[i]->a_alg_num ==
608 alg_num) {
609 found_match = B_TRUE;
610 freeipsecalgent(current_proto->proto_algs[i]);
612 } else {
613 current_proto->proto_algs[i - 1] =
614 current_proto->proto_algs[i];
618 if (found_match) {
619 current_proto->proto_numalgs--;
620 return (write_new_algfile(protos, num_protos));
623 _clean_trash(protos, num_protos);
624 return (LIBIPSEC_ALGS_DIAG_UNKN_ALG);
628 * Remove the specified protocol entry from the list of protocols.
630 static void
631 delipsecproto_common(ipsec_proto_t *protos, int num_protos,
632 ipsec_proto_t *proto)
634 int i;
636 /* free protocol storage */
637 free(proto->proto_name);
638 for (i = 0; i < proto->proto_numalgs; i++)
639 freeipsecalgent(proto->proto_algs[i]);
641 /* remove from list of prototocols */
642 for (i = (proto - protos + 1); i < num_protos; i++)
643 protos[i - 1] = protos[i];
647 * Add an IPsec protocol to /etc/inet/ipsecalgs.
650 addipsecproto(const char *proto_name, int proto_num,
651 ipsecalgs_exec_mode_t proto_exec_mode, uint_t flags)
653 ipsec_proto_t *protos, *current_proto, *new_proto;
654 int i, num_protos;
657 * NOTE:If build_internal_algs returns NULL for any
658 * reason, we will end up clobbering /etc/inet/ipsecalgs!
661 current_proto = proto_setup(&protos, &num_protos, proto_num, B_FALSE);
663 /* check for protocol with duplicate id */
664 if (current_proto != NULL) {
665 if ((strcmp(proto_name, current_proto->proto_name) == 0) &&
666 (proto_exec_mode == current_proto->proto_exec_mode)) {
668 * The current protocol being added matches
669 * exactly an existing protocol, we're done.
671 return (0);
673 if (!(flags & LIBIPSEC_ALGS_ADD_FORCE))
674 return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS);
675 delipsecproto_common(protos, num_protos--, current_proto);
678 /* check for protocol with duplicate name */
679 for (i = 0; i < num_protos; i++) {
680 if (strcmp(protos[i].proto_name, proto_name) == 0) {
681 if (!(flags & LIBIPSEC_ALGS_ADD_FORCE))
682 return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS);
683 delipsecproto_common(protos, num_protos--, &protos[i]);
684 break;
688 /* add new protocol */
689 num_protos++;
690 new_proto = reallocarray(protos, num_protos, sizeof (ipsec_proto_t));
691 if (new_proto == NULL) {
692 _clean_trash(protos, num_protos - 1);
693 return (LIBIPSEC_ALGS_DIAG_NOMEM);
695 protos = new_proto;
696 new_proto += (num_protos - 1);
698 /* initialize protocol entry */
699 new_proto->proto_num = proto_num;
700 new_proto->proto_numalgs = 0;
701 new_proto->proto_algs = NULL;
702 new_proto->proto_name = strdup(proto_name);
703 if (new_proto->proto_name == NULL) {
704 _clean_trash(protos, num_protos);
705 return (LIBIPSEC_ALGS_DIAG_NOMEM);
707 new_proto->proto_pkg = NULL;
708 new_proto->proto_algs_pkgs = NULL;
709 new_proto->proto_algs_npkgs = 0;
710 new_proto->proto_exec_mode = proto_exec_mode;
712 return (write_new_algfile(protos, num_protos));
716 * Delete an IPsec protocol entry from /etc/inet/ipsecalgs. This also
717 * nukes the associated algorithms.
720 delipsecprotobynum(int proto_num)
722 ipsec_proto_t *protos, *current_proto;
723 int num_protos;
725 if ((current_proto = proto_setup(&protos, &num_protos, proto_num,
726 B_TRUE)) == NULL)
727 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
729 delipsecproto_common(protos, num_protos--, current_proto);
731 return (write_new_algfile(protos, num_protos));
735 delipsecprotobyname(const char *proto_name)
737 int proto_num;
739 proto_num = getipsecprotobyname(proto_name);
740 if (proto_num == -1)
741 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
743 return (delipsecprotobynum(proto_num));
747 * Implement these in libnsl since these are read-only operations.
749 int *
750 getipsecprotos(int *nentries)
752 return (_real_getipsecprotos(nentries));
755 int *
756 getipsecalgs(int *nentries, int proto_num)
758 return (_real_getipsecalgs(nentries, proto_num));
761 const char *
762 ipsecalgs_diag(int diag)
764 switch (diag) {
765 case LIBIPSEC_ALGS_DIAG_ALG_EXISTS:
766 return (dgettext(TEXT_DOMAIN, "Algorithm already exists"));
767 case LIBIPSEC_ALGS_DIAG_PROTO_EXISTS:
768 return (dgettext(TEXT_DOMAIN, "Protocol already exists"));
769 case LIBIPSEC_ALGS_DIAG_UNKN_PROTO:
770 return (dgettext(TEXT_DOMAIN, "Unknown protocol"));
771 case LIBIPSEC_ALGS_DIAG_UNKN_ALG:
772 return (dgettext(TEXT_DOMAIN, "Unknown algorithm"));
773 case LIBIPSEC_ALGS_DIAG_NOMEM:
774 return (dgettext(TEXT_DOMAIN, "Out of memory"));
775 case LIBIPSEC_ALGS_DIAG_ALGSFILEOPEN:
776 return (dgettext(TEXT_DOMAIN, "open() failed"));
777 case LIBIPSEC_ALGS_DIAG_ALGSFILEFDOPEN:
778 return (dgettext(TEXT_DOMAIN, "fdopen() failed"));
779 case LIBIPSEC_ALGS_DIAG_ALGSFILELOCK:
780 return (dgettext(TEXT_DOMAIN, "lockf() failed"));
781 case LIBIPSEC_ALGS_DIAG_ALGSFILERENAME:
782 return (dgettext(TEXT_DOMAIN, "rename() failed"));
783 case LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE:
784 return (dgettext(TEXT_DOMAIN, "write to file failed"));
785 case LIBIPSEC_ALGS_DIAG_ALGSFILECHMOD:
786 return (dgettext(TEXT_DOMAIN, "chmod() failed"));
787 case LIBIPSEC_ALGS_DIAG_ALGSFILECHOWN:
788 return (dgettext(TEXT_DOMAIN, "chown() failed"));
789 case LIBIPSEC_ALGS_DIAG_ALGSFILECLOSE:
790 return (dgettext(TEXT_DOMAIN, "close() failed"));
791 default:
792 return (dgettext(TEXT_DOMAIN, "failed"));
797 * Get the execution mode corresponding to the specified protocol.
798 * Returns 0 on success, one of the LIBIPSEC_ALGS_DIAG_* values on
799 * failure.
802 ipsecproto_get_exec_mode(int proto_num, ipsecalgs_exec_mode_t *exec_mode)
804 ipsec_proto_t *protos, *current_proto;
805 int num_protos;
807 if ((current_proto = proto_setup(&protos, &num_protos, proto_num,
808 B_TRUE)) == NULL)
809 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
811 *exec_mode = current_proto->proto_exec_mode;
813 _clean_trash(protos, num_protos);
814 return (0);
818 * Set the execution mode of the specified protocol. Returns 0 on success,
819 * or one of the LIBIPSEC_ALGS_DIAG_* values on failure.
822 ipsecproto_set_exec_mode(int proto_num, ipsecalgs_exec_mode_t exec_mode)
824 ipsec_proto_t *protos, *current_proto;
825 int num_protos;
827 if ((current_proto = proto_setup(&protos, &num_protos, proto_num,
828 B_TRUE)) == NULL)
829 return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
831 current_proto->proto_exec_mode = exec_mode;
833 return (write_new_algfile(protos, num_protos));