10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1519Sdanmcd * Common Development and Distribution License (the "License"). 6*1519Sdanmcd * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1519Sdanmcd * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/stat.h> 300Sstevel@tonic-gate #include <ipsec_util.h> 310Sstevel@tonic-gate #include <stdlib.h> 320Sstevel@tonic-gate #include <strings.h> 330Sstevel@tonic-gate #include <netdb.h> 340Sstevel@tonic-gate #include <fcntl.h> 350Sstevel@tonic-gate #include <unistd.h> 360Sstevel@tonic-gate #include <libintl.h> 370Sstevel@tonic-gate #include <errno.h> 380Sstevel@tonic-gate 390Sstevel@tonic-gate static char *preamble = 400Sstevel@tonic-gate "# /etc/inet/ipsecalgs output from ipsecalgs(1m)\n" 410Sstevel@tonic-gate "#\n" 420Sstevel@tonic-gate "# DO NOT EDIT OR PARSE THIS FILE!\n" 430Sstevel@tonic-gate "#\n" 440Sstevel@tonic-gate "# Use the ipsecalgs(1m) command to change the contents of this file.\n" 450Sstevel@tonic-gate "\n"; 460Sstevel@tonic-gate 470Sstevel@tonic-gate #define CFG_PERMS S_IRUSR | S_IRGRP | S_IROTH /* Perms 0444. */ 480Sstevel@tonic-gate #define CFG_OWNER 0 /* root */ 490Sstevel@tonic-gate #define CFG_GROUP 1 /* "other" */ 500Sstevel@tonic-gate 510Sstevel@tonic-gate /* 520Sstevel@tonic-gate * write_new_algfile() helper macros to check for write errors. 530Sstevel@tonic-gate */ 540Sstevel@tonic-gate 550Sstevel@tonic-gate #define FPRINTF_ERR(fcall) if ((fcall) < 0) { \ 560Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; \ 570Sstevel@tonic-gate goto bail; \ 580Sstevel@tonic-gate } 590Sstevel@tonic-gate 600Sstevel@tonic-gate #define FPUT_ERR(fcall) if ((fcall) == EOF) { \ 610Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; \ 620Sstevel@tonic-gate goto bail; \ 630Sstevel@tonic-gate } 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* 660Sstevel@tonic-gate * Helper macros to start and finish a list of entries that were added 670Sstevel@tonic-gate * as part of a package installation. 680Sstevel@tonic-gate */ 690Sstevel@tonic-gate 700Sstevel@tonic-gate #define PKG_SEC_START(pkgname, doing_pkg, cur_pkg) { \ 710Sstevel@tonic-gate (void) strcpy((cur_pkg), (pkgname)); \ 720Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "%s%s\n", \ 730Sstevel@tonic-gate LIBIPSEC_ALGS_LINE_PKGSTART, (cur_pkg))); \ 740Sstevel@tonic-gate (doing_pkg) = B_TRUE; \ 750Sstevel@tonic-gate } 760Sstevel@tonic-gate 770Sstevel@tonic-gate #define PKG_SEC_END(doing_pkg, cur_pkg) { \ 780Sstevel@tonic-gate if (doing_pkg) { \ 790Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "%s%s\n", \ 800Sstevel@tonic-gate LIBIPSEC_ALGS_LINE_PKGEND, (cur_pkg))); \ 810Sstevel@tonic-gate (doing_pkg) = B_FALSE; \ 820Sstevel@tonic-gate } \ 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * Take a zero-terminated int array and print int1,int2...,intN. 870Sstevel@tonic-gate * If zero-only, then print a single '0'. 880Sstevel@tonic-gate * Returns 0 on success, -1 if an error occurred while writing to 890Sstevel@tonic-gate * the specified file. 900Sstevel@tonic-gate */ 910Sstevel@tonic-gate int 920Sstevel@tonic-gate list_ints(FILE *f, int *floater) 930Sstevel@tonic-gate { 940Sstevel@tonic-gate boolean_t executed = B_FALSE; 950Sstevel@tonic-gate 960Sstevel@tonic-gate while (*floater != 0) { 970Sstevel@tonic-gate executed = B_TRUE; 980Sstevel@tonic-gate if (fprintf(f, "%d", *floater) < 0) 990Sstevel@tonic-gate return (-1); 1000Sstevel@tonic-gate if (*(++floater) != 0) 1010Sstevel@tonic-gate if (fputc(',', f) == EOF) 1020Sstevel@tonic-gate return (-1); 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate if (!executed) 1060Sstevel@tonic-gate if (fputc('0', f) == EOF) 1070Sstevel@tonic-gate return (-1); 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate return (0); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * If the specified algorithm was defined within a package section, i.e. 1140Sstevel@tonic-gate * between the lines "# Start <pkgname>" and "# End <pkgname>", returns 1150Sstevel@tonic-gate * the value of <pkgname>. 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate static char * 1180Sstevel@tonic-gate alg_has_pkg(ipsec_proto_t *proto, struct ipsecalgent *alg) 1190Sstevel@tonic-gate { 1200Sstevel@tonic-gate int i; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if (proto->proto_algs_pkgs == NULL) 1230Sstevel@tonic-gate return (NULL); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate for (i = 0; i < proto->proto_algs_npkgs; i++) 1260Sstevel@tonic-gate if (proto->proto_algs_pkgs[i].alg_num == alg->a_alg_num) 1270Sstevel@tonic-gate return (proto->proto_algs_pkgs[i].pkg_name); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate return (NULL); 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate /* 1330Sstevel@tonic-gate * Writes the package start/end delimiters according to the package 1340Sstevel@tonic-gate * name associated with the current protocol or algorithm, and 1350Sstevel@tonic-gate * the state of the packaging information already written to the file. 1360Sstevel@tonic-gate * Called by write_new_algfile(). Returns 0 on success, one of the 1370Sstevel@tonic-gate * LIBIPSEC_DIAG codes on failure. 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate static int 1400Sstevel@tonic-gate pkg_section(FILE *f, char *pkg_name, boolean_t *doing_pkg, char *cur_pkg) 1410Sstevel@tonic-gate { 1420Sstevel@tonic-gate int rc = 0; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate if (pkg_name != NULL) { 1450Sstevel@tonic-gate /* protocol or algorithm is associated with a package */ 1460Sstevel@tonic-gate if (!*doing_pkg) { 1470Sstevel@tonic-gate /* start of a new package section */ 1480Sstevel@tonic-gate PKG_SEC_START(pkg_name, *doing_pkg, cur_pkg); 1490Sstevel@tonic-gate } else { 1500Sstevel@tonic-gate /* already in a package section */ 1510Sstevel@tonic-gate if (strcmp(pkg_name, cur_pkg) != 0) { 1520Sstevel@tonic-gate /* different package name */ 1530Sstevel@tonic-gate PKG_SEC_END(*doing_pkg, cur_pkg); 1540Sstevel@tonic-gate PKG_SEC_START(pkg_name, *doing_pkg, cur_pkg); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate } else if (*doing_pkg) { 1580Sstevel@tonic-gate /* in a package section when the entry isn't */ 1590Sstevel@tonic-gate PKG_SEC_END(*doing_pkg, cur_pkg); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate bail: 1620Sstevel@tonic-gate return (rc); 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate /* 1660Sstevel@tonic-gate * Given a list of protocols and number, write them to a new algorithm file. 1670Sstevel@tonic-gate * This function takes num_protos + num_protos * dois-per-alg operations. 1680Sstevel@tonic-gate * Also free the protocol structure. 1690Sstevel@tonic-gate * 1700Sstevel@tonic-gate * Note that no locking spans the read/update/write phases that can be 1710Sstevel@tonic-gate * used by callers of this routine. This could cause this function to suffer 1720Sstevel@tonic-gate * from the "lost update" problem. Since updates to the IPsec protocols 1730Sstevel@tonic-gate * and algorithm tables are very infrequent, this should not be a issue in 1740Sstevel@tonic-gate * practice. 1750Sstevel@tonic-gate */ 1760Sstevel@tonic-gate static int 1770Sstevel@tonic-gate write_new_algfile(ipsec_proto_t *protos, int num_protos) 1780Sstevel@tonic-gate { 1790Sstevel@tonic-gate FILE *f; 1800Sstevel@tonic-gate int fd, i, j, k; 1810Sstevel@tonic-gate int rc = 0; 1820Sstevel@tonic-gate struct ipsecalgent *alg; 1830Sstevel@tonic-gate char cur_pkg[1024]; 1840Sstevel@tonic-gate boolean_t doing_pkg = B_FALSE; 1850Sstevel@tonic-gate char *alg_pkg; 186*1519Sdanmcd char tmp_name_template[] = INET_IPSECALGSPATH "ipsecalgsXXXXXX"; 1870Sstevel@tonic-gate char *tmp_name; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate /* 1900Sstevel@tonic-gate * In order to avoid potentially corrupting the configuration 1910Sstevel@tonic-gate * file on file system failure, write the new configuration info 1920Sstevel@tonic-gate * to a temporary file which is then renamed to the configuration 1930Sstevel@tonic-gate * file (INET_IPSECALGSFILE.) 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate tmp_name = mktemp(tmp_name_template); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate fd = open(tmp_name, O_WRONLY|O_CREAT|O_EXCL, CFG_PERMS); 1980Sstevel@tonic-gate if (fd == -1) { 1990Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILEOPEN; 2000Sstevel@tonic-gate goto bail; 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate f = fdopen(fd, "w"); 2040Sstevel@tonic-gate if (f == NULL) { 2050Sstevel@tonic-gate (void) close(fd); 2060Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILEFDOPEN; 2070Sstevel@tonic-gate goto bail; 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate FPUT_ERR(fputs(preamble, f)); 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* Write protocol entries. */ 2130Sstevel@tonic-gate for (i = 0; i < num_protos; i++) { 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* add package section delimiters if needed */ 2160Sstevel@tonic-gate rc = pkg_section(f, protos[i].proto_pkg, &doing_pkg, cur_pkg); 2170Sstevel@tonic-gate if (rc != 0) 2180Sstevel@tonic-gate goto bail; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "%s%d|%s|", 2210Sstevel@tonic-gate LIBIPSEC_ALGS_LINE_PROTO, 2220Sstevel@tonic-gate protos[i].proto_num, protos[i].proto_name)); 2230Sstevel@tonic-gate switch (protos[i].proto_exec_mode) { 2240Sstevel@tonic-gate case LIBIPSEC_ALGS_EXEC_SYNC: 2250Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "sync\n")); 2260Sstevel@tonic-gate break; 2270Sstevel@tonic-gate case LIBIPSEC_ALGS_EXEC_ASYNC: 2280Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "async\n")); 2290Sstevel@tonic-gate break; 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* terminate the package section for the protocols if needed */ 2340Sstevel@tonic-gate PKG_SEC_END(doing_pkg, cur_pkg); 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate FPUT_ERR(fputs("\n", f)); 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* Write algorithm entries. */ 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate for (i = 0; i < num_protos; i++) { 2410Sstevel@tonic-gate for (j = 0; j < protos[i].proto_numalgs; j++) { 2420Sstevel@tonic-gate alg = protos[i].proto_algs[j]; 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* add package section delimiters if needed */ 2450Sstevel@tonic-gate alg_pkg = alg_has_pkg(&protos[i], alg); 2460Sstevel@tonic-gate rc = pkg_section(f, alg_pkg, &doing_pkg, cur_pkg); 2470Sstevel@tonic-gate if (rc != 0) 2480Sstevel@tonic-gate goto bail; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* protocol and algorithm numbers */ 2510Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "%s%d|%d|", 2520Sstevel@tonic-gate LIBIPSEC_ALGS_LINE_ALG, 2530Sstevel@tonic-gate alg->a_proto_num, alg->a_alg_num)); 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* algorithm names */ 2560Sstevel@tonic-gate for (k = 0; alg->a_names[k] != NULL; k++) { 2570Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "%s", alg->a_names[k])); 2580Sstevel@tonic-gate if (alg->a_names[k+1] != NULL) 2590Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, ",")); 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* mechanism name */ 2630Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "|%s|", alg->a_mech_name)); 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate /* key sizes */ 2660Sstevel@tonic-gate if (alg->a_key_increment == 0) { 2670Sstevel@tonic-gate /* key sizes defined by enumeration */ 2680Sstevel@tonic-gate if (list_ints(f, alg->a_key_sizes) == -1) { 2690Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; 2700Sstevel@tonic-gate goto bail; 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate } else { 2730Sstevel@tonic-gate /* key sizes defined by range */ 2740Sstevel@tonic-gate FPRINTF_ERR(fprintf(f, "%d/%d-%d,%d", 2750Sstevel@tonic-gate alg->a_key_sizes[0], alg->a_key_sizes[1], 2760Sstevel@tonic-gate alg->a_key_sizes[2], alg->a_key_increment)); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate FPUT_ERR(fputc('|', f)); 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* block sizes */ 2810Sstevel@tonic-gate if (list_ints(f, alg->a_block_sizes) == -1) { 2820Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE; 2830Sstevel@tonic-gate goto bail; 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate FPUT_ERR(fputc('\n', f)); 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* terminate the package section for the algorithms if needed */ 2900Sstevel@tonic-gate PKG_SEC_END(doing_pkg, cur_pkg); 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate if (fchmod(fd, CFG_PERMS) == -1) { 2930Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILECHMOD; 2940Sstevel@tonic-gate goto bail; 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate if (fchown(fd, CFG_OWNER, CFG_GROUP) == -1) { 2970Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILECHOWN; 2980Sstevel@tonic-gate goto bail; 2990Sstevel@tonic-gate } 3000Sstevel@tonic-gate if (fclose(f) == EOF) { 3010Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILECLOSE; 3020Sstevel@tonic-gate goto bail; 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate if (rename(tmp_name, INET_IPSECALGSFILE) == -1) 3060Sstevel@tonic-gate rc = LIBIPSEC_ALGS_DIAG_ALGSFILERENAME; 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate bail: 3090Sstevel@tonic-gate _clean_trash(protos, num_protos); 3100Sstevel@tonic-gate return (rc); 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate /* 3140Sstevel@tonic-gate * Return a pointer to the protocol entry corresponding to the specified 3150Sstevel@tonic-gate * protocol num proto_num. Also builds the list of currently defined 3160Sstevel@tonic-gate * protocols. 3170Sstevel@tonic-gate */ 3180Sstevel@tonic-gate static ipsec_proto_t * 3190Sstevel@tonic-gate proto_setup(ipsec_proto_t **protos, int *num_protos, int proto_num, 3200Sstevel@tonic-gate boolean_t cleanup) 3210Sstevel@tonic-gate { 3220Sstevel@tonic-gate int i; 3230Sstevel@tonic-gate ipsec_proto_t *current_proto, *ret_proto = NULL; 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate _build_internal_algs(protos, num_protos); 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate if (*protos == NULL) 3280Sstevel@tonic-gate return (NULL); 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate for (i = 0; i < *num_protos; i++) { 3310Sstevel@tonic-gate current_proto = (*protos) + i; 3320Sstevel@tonic-gate if (current_proto->proto_num == proto_num) { 3330Sstevel@tonic-gate ret_proto = current_proto; 3340Sstevel@tonic-gate break; 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate if (ret_proto == NULL) { 3390Sstevel@tonic-gate if (cleanup) 3400Sstevel@tonic-gate _clean_trash(*protos, *num_protos); 3410Sstevel@tonic-gate /* else caller wants parsed /etc/inet/ipsecalgs anyway */ 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate return (ret_proto); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Delete the first found algorithm of the specified protocol which 3490Sstevel@tonic-gate * has the same name as the one specified by alg_name. Deletion of 3500Sstevel@tonic-gate * the entry takes place only if the delete_it flag is set. If an 3510Sstevel@tonic-gate * entry was found, return B_TRUE, otherwise return B_FALSE. 3520Sstevel@tonic-gate */ 3530Sstevel@tonic-gate static boolean_t 3540Sstevel@tonic-gate delipsecalgbyname_common(const char *name, ipsec_proto_t *proto, 3550Sstevel@tonic-gate boolean_t delete_it) 3560Sstevel@tonic-gate { 3570Sstevel@tonic-gate int i; 3580Sstevel@tonic-gate char **name_check; 3590Sstevel@tonic-gate boolean_t found_match = B_FALSE; 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate for (i = 0; i < proto->proto_numalgs; i++) { 3620Sstevel@tonic-gate if (!found_match) { 3630Sstevel@tonic-gate for (name_check = 3640Sstevel@tonic-gate proto->proto_algs[i]->a_names; 3650Sstevel@tonic-gate *name_check != NULL; name_check++) { 3660Sstevel@tonic-gate /* 3670Sstevel@tonic-gate * Can use strcmp because the algorithm names 3680Sstevel@tonic-gate * are bound. 3690Sstevel@tonic-gate */ 3700Sstevel@tonic-gate if (strcmp(*name_check, name) == 0) { 3710Sstevel@tonic-gate found_match = B_TRUE; 3720Sstevel@tonic-gate if (!delete_it) 3730Sstevel@tonic-gate return (found_match); 3740Sstevel@tonic-gate freeipsecalgent(proto->proto_algs[i]); 3750Sstevel@tonic-gate break; 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate } else { 3790Sstevel@tonic-gate proto->proto_algs[i - 1] = proto->proto_algs[i]; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate if (found_match) 3840Sstevel@tonic-gate proto->proto_numalgs--; 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate return (found_match); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* 3900Sstevel@tonic-gate * Returns B_TRUE if the specified 0-terminated lists of key or 3910Sstevel@tonic-gate * block sizes match, B_FALSE otherwise. 3920Sstevel@tonic-gate */ 3930Sstevel@tonic-gate static boolean_t 3940Sstevel@tonic-gate sizes_match(int *a1, int *a2) 3950Sstevel@tonic-gate { 3960Sstevel@tonic-gate int i; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate for (i = 0; (a1[i] != 0) && (a2[i] != 0); i++) { 3990Sstevel@tonic-gate if (a1[i] != a2[i]) 4000Sstevel@tonic-gate return (B_FALSE); 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate if ((a1[i] != 0) || (a2[i] != 0)) 4030Sstevel@tonic-gate return (B_FALSE); 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate return (B_TRUE); 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate /* 4090Sstevel@tonic-gate * Returns B_TRUE if an _exact_ equivalent of the specified algorithm 4100Sstevel@tonic-gate * already exists, B_FALSE otherwise. 4110Sstevel@tonic-gate */ 4120Sstevel@tonic-gate static boolean_t 4130Sstevel@tonic-gate ipsecalg_exists(struct ipsecalgent *newbie, ipsec_proto_t *proto) 4140Sstevel@tonic-gate { 4150Sstevel@tonic-gate struct ipsecalgent *curalg; 4160Sstevel@tonic-gate char **curname, **newbiename; 4170Sstevel@tonic-gate int i; 4180Sstevel@tonic-gate boolean_t match; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate for (i = 0; i < proto->proto_numalgs; i++) { 4210Sstevel@tonic-gate curalg = proto->proto_algs[i]; 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate if (curalg->a_alg_num != newbie->a_alg_num) 4240Sstevel@tonic-gate continue; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate if (curalg->a_key_increment != newbie->a_key_increment) 4270Sstevel@tonic-gate continue; 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate if (strcmp(curalg->a_mech_name, newbie->a_mech_name) != 0) 4300Sstevel@tonic-gate continue; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate curname = curalg->a_names; 4330Sstevel@tonic-gate newbiename = newbie->a_names; 4340Sstevel@tonic-gate match = B_TRUE; 4350Sstevel@tonic-gate while ((*curname != NULL) && (*newbiename != NULL) && match) { 4360Sstevel@tonic-gate match = (strcmp(*curname, *newbiename) == 0); 4370Sstevel@tonic-gate curname++; 4380Sstevel@tonic-gate newbiename++; 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate if (!match || (*curname != NULL) || (*newbiename != NULL)) 4410Sstevel@tonic-gate continue; 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate if (!sizes_match(curalg->a_block_sizes, newbie->a_block_sizes)) 4440Sstevel@tonic-gate continue; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if (!sizes_match(curalg->a_key_sizes, newbie->a_key_sizes)) 4470Sstevel@tonic-gate continue; 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate /* we found an exact match */ 4500Sstevel@tonic-gate return (B_TRUE); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate return (B_FALSE); 4540Sstevel@tonic-gate } 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate /* 4570Sstevel@tonic-gate * Add a new algorithm to the /etc/inet/ipsecalgs file. Caller must free 4580Sstevel@tonic-gate * or otherwise address "newbie". 4590Sstevel@tonic-gate */ 4600Sstevel@tonic-gate int 4610Sstevel@tonic-gate addipsecalg(struct ipsecalgent *newbie, uint_t flags) 4620Sstevel@tonic-gate { 4630Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto; 4640Sstevel@tonic-gate struct ipsecalgent *clone, **holder; 4650Sstevel@tonic-gate int num_protos, i; 4660Sstevel@tonic-gate char **name_check; 4670Sstevel@tonic-gate boolean_t forced_add = (flags & LIBIPSEC_ALGS_ADD_FORCE) != 0; 4680Sstevel@tonic-gate boolean_t found_match; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate if ((current_proto = proto_setup(&protos, &num_protos, 4710Sstevel@tonic-gate newbie->a_proto_num, B_TRUE)) == NULL) 4720Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* 4750Sstevel@tonic-gate * If an algorithm that matches _exactly_ the new algorithm 4760Sstevel@tonic-gate * already exists, we're done. 4770Sstevel@tonic-gate */ 4780Sstevel@tonic-gate if (ipsecalg_exists(newbie, current_proto)) 4790Sstevel@tonic-gate return (0); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * We don't allow a new algorithm to be created if one of 4830Sstevel@tonic-gate * its names is already defined for an existing algorithm, 4840Sstevel@tonic-gate * unless the operation is forced, in which case existing 4850Sstevel@tonic-gate * algorithm entries that conflict with the new one are 4860Sstevel@tonic-gate * deleted. 4870Sstevel@tonic-gate */ 4880Sstevel@tonic-gate for (name_check = newbie->a_names; *name_check != NULL; name_check++) { 4890Sstevel@tonic-gate found_match = delipsecalgbyname_common(*name_check, 4900Sstevel@tonic-gate current_proto, forced_add); 4910Sstevel@tonic-gate if (found_match && !forced_add) { 4920Sstevel@tonic-gate /* 4930Sstevel@tonic-gate * Duplicate entry found, but the addition was 4940Sstevel@tonic-gate * not forced. 4950Sstevel@tonic-gate */ 4960Sstevel@tonic-gate _clean_trash(protos, num_protos); 4970Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate for (i = 0; i < current_proto->proto_numalgs; i++) { 5020Sstevel@tonic-gate if (current_proto->proto_algs[i]->a_alg_num == 5030Sstevel@tonic-gate newbie->a_alg_num) { 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * An algorithm with the same protocol number 5060Sstevel@tonic-gate * and algorithm number already exists. Fail 5070Sstevel@tonic-gate * addition unless the operation is forced. 5080Sstevel@tonic-gate */ 5090Sstevel@tonic-gate if (flags & LIBIPSEC_ALGS_ADD_FORCE) { 5100Sstevel@tonic-gate clone = _duplicate_alg(newbie); 5110Sstevel@tonic-gate if (clone != NULL) { 5120Sstevel@tonic-gate freeipsecalgent( 5130Sstevel@tonic-gate current_proto->proto_algs[i]); 5140Sstevel@tonic-gate current_proto->proto_algs[i] = clone; 5150Sstevel@tonic-gate return (write_new_algfile(protos, 5160Sstevel@tonic-gate num_protos)); 5170Sstevel@tonic-gate } else { 5180Sstevel@tonic-gate _clean_trash(protos, num_protos); 5190Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_NOMEM); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate } else { 5220Sstevel@tonic-gate _clean_trash(protos, num_protos); 5230Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS); 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate /* append the new algorithm */ 5290Sstevel@tonic-gate holder = realloc(current_proto->proto_algs, 5300Sstevel@tonic-gate sizeof (struct ipsecalgent *) * (i + 1)); 5310Sstevel@tonic-gate if (holder == NULL) { 5320Sstevel@tonic-gate _clean_trash(protos, num_protos); 5330Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_NOMEM); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate clone = _duplicate_alg(newbie); 5360Sstevel@tonic-gate if (clone == NULL) { 5370Sstevel@tonic-gate free(holder); 5380Sstevel@tonic-gate _clean_trash(protos, num_protos); 5390Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_NOMEM); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate current_proto->proto_numalgs++; 5420Sstevel@tonic-gate current_proto->proto_algs = holder; 5430Sstevel@tonic-gate current_proto->proto_algs[i] = clone; 5440Sstevel@tonic-gate return (write_new_algfile(protos, num_protos)); 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate /* 5480Sstevel@tonic-gate * Delete an algorithm by name & protocol number from /etc/inet/ipsecalgs. 5490Sstevel@tonic-gate * Only deletes the first encountered instance. 5500Sstevel@tonic-gate */ 5510Sstevel@tonic-gate int 5520Sstevel@tonic-gate delipsecalgbyname(const char *name, int proto_num) 5530Sstevel@tonic-gate { 5540Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto; 5550Sstevel@tonic-gate int num_protos; 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 5580Sstevel@tonic-gate B_TRUE)) == NULL) 5590Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate if (delipsecalgbyname_common(name, current_proto, B_TRUE)) 5620Sstevel@tonic-gate return (write_new_algfile(protos, num_protos)); 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate _clean_trash(protos, num_protos); 5650Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_ALG); 5660Sstevel@tonic-gate } 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate /* 5690Sstevel@tonic-gate * Delete an algorithm by num + protocol num from /etc/inet/ipsecalgs. 5700Sstevel@tonic-gate */ 5710Sstevel@tonic-gate int 5720Sstevel@tonic-gate delipsecalgbynum(int alg_num, int proto_num) 5730Sstevel@tonic-gate { 5740Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto; 5750Sstevel@tonic-gate int i, num_protos; 5760Sstevel@tonic-gate boolean_t found_match = B_FALSE; 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 5790Sstevel@tonic-gate B_TRUE)) == NULL) 5800Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate for (i = 0; i < current_proto->proto_numalgs; i++) { 5830Sstevel@tonic-gate if (!found_match) { 5840Sstevel@tonic-gate if (current_proto->proto_algs[i]->a_alg_num == 5850Sstevel@tonic-gate alg_num) { 5860Sstevel@tonic-gate found_match = B_TRUE; 5870Sstevel@tonic-gate freeipsecalgent(current_proto->proto_algs[i]); 5880Sstevel@tonic-gate } 5890Sstevel@tonic-gate } else { 5900Sstevel@tonic-gate current_proto->proto_algs[i - 1] = 5910Sstevel@tonic-gate current_proto->proto_algs[i]; 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate if (found_match) { 5960Sstevel@tonic-gate current_proto->proto_numalgs--; 5970Sstevel@tonic-gate return (write_new_algfile(protos, num_protos)); 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate _clean_trash(protos, num_protos); 6010Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_ALG); 6020Sstevel@tonic-gate } 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * Remove the specified protocol entry from the list of protocols. 6060Sstevel@tonic-gate */ 6070Sstevel@tonic-gate static void 6080Sstevel@tonic-gate delipsecproto_common(ipsec_proto_t *protos, int num_protos, 6090Sstevel@tonic-gate ipsec_proto_t *proto) 6100Sstevel@tonic-gate { 6110Sstevel@tonic-gate int i; 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* free protocol storage */ 6140Sstevel@tonic-gate free(proto->proto_name); 6150Sstevel@tonic-gate for (i = 0; i < proto->proto_numalgs; i++) 6160Sstevel@tonic-gate freeipsecalgent(proto->proto_algs[i]); 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate /* remove from list of prototocols */ 6190Sstevel@tonic-gate for (i = (proto - protos + 1); i < num_protos; i++) 6200Sstevel@tonic-gate protos[i - 1] = protos[i]; 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate /* 6240Sstevel@tonic-gate * Add an IPsec protocol to /etc/inet/ipsecalgs. 6250Sstevel@tonic-gate */ 6260Sstevel@tonic-gate int 6270Sstevel@tonic-gate addipsecproto(const char *proto_name, int proto_num, 6280Sstevel@tonic-gate ipsecalgs_exec_mode_t proto_exec_mode, uint_t flags) 6290Sstevel@tonic-gate { 6300Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto, *new_proto; 6310Sstevel@tonic-gate int i, num_protos; 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* 6340Sstevel@tonic-gate * NOTE:If build_internal_algs returns NULL for any 6350Sstevel@tonic-gate * reason, we will end up clobbering /etc/inet/ipsecalgs! 6360Sstevel@tonic-gate */ 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate current_proto = proto_setup(&protos, &num_protos, proto_num, B_FALSE); 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate /* check for protocol with duplicate id */ 6410Sstevel@tonic-gate if (current_proto != NULL) { 6420Sstevel@tonic-gate if ((strcmp(proto_name, current_proto->proto_name) == 0) && 6430Sstevel@tonic-gate (proto_exec_mode == current_proto->proto_exec_mode)) { 6440Sstevel@tonic-gate /* 6450Sstevel@tonic-gate * The current protocol being added matches 6460Sstevel@tonic-gate * exactly an existing protocol, we're done. 6470Sstevel@tonic-gate */ 6480Sstevel@tonic-gate return (0); 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate if (!(flags & LIBIPSEC_ALGS_ADD_FORCE)) 6510Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS); 6520Sstevel@tonic-gate delipsecproto_common(protos, num_protos--, current_proto); 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate /* check for protocol with duplicate name */ 6560Sstevel@tonic-gate for (i = 0; i < num_protos; i++) { 6570Sstevel@tonic-gate if (strcmp(protos[i].proto_name, proto_name) == 0) { 6580Sstevel@tonic-gate if (!(flags & LIBIPSEC_ALGS_ADD_FORCE)) 6590Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS); 6600Sstevel@tonic-gate delipsecproto_common(protos, num_protos--, &protos[i]); 6610Sstevel@tonic-gate break; 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate /* add new protocol */ 6660Sstevel@tonic-gate num_protos++; 6670Sstevel@tonic-gate new_proto = realloc(protos, num_protos * 6680Sstevel@tonic-gate sizeof (ipsec_proto_t)); 6690Sstevel@tonic-gate if (new_proto == NULL) { 6700Sstevel@tonic-gate _clean_trash(protos, num_protos - 1); 6710Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_NOMEM); 6720Sstevel@tonic-gate } 6730Sstevel@tonic-gate protos = new_proto; 6740Sstevel@tonic-gate new_proto += (num_protos - 1); 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate /* initialize protocol entry */ 6770Sstevel@tonic-gate new_proto->proto_num = proto_num; 6780Sstevel@tonic-gate new_proto->proto_numalgs = 0; 6790Sstevel@tonic-gate new_proto->proto_algs = NULL; 6800Sstevel@tonic-gate new_proto->proto_name = strdup(proto_name); 6810Sstevel@tonic-gate if (new_proto->proto_name == NULL) { 6820Sstevel@tonic-gate _clean_trash(protos, num_protos); 6830Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_NOMEM); 6840Sstevel@tonic-gate } 6850Sstevel@tonic-gate new_proto->proto_pkg = NULL; 6860Sstevel@tonic-gate new_proto->proto_algs_pkgs = NULL; 6870Sstevel@tonic-gate new_proto->proto_algs_npkgs = 0; 6880Sstevel@tonic-gate new_proto->proto_exec_mode = proto_exec_mode; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate return (write_new_algfile(protos, num_protos)); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate /* 6940Sstevel@tonic-gate * Delete an IPsec protocol entry from /etc/inet/ipsecalgs. This also 6950Sstevel@tonic-gate * nukes the associated algorithms. 6960Sstevel@tonic-gate */ 6970Sstevel@tonic-gate int 6980Sstevel@tonic-gate delipsecprotobynum(int proto_num) 6990Sstevel@tonic-gate { 7000Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto; 7010Sstevel@tonic-gate int num_protos; 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 7040Sstevel@tonic-gate B_TRUE)) == NULL) 7050Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate delipsecproto_common(protos, num_protos--, current_proto); 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate return (write_new_algfile(protos, num_protos)); 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate int 7130Sstevel@tonic-gate delipsecprotobyname(const char *proto_name) 7140Sstevel@tonic-gate { 7150Sstevel@tonic-gate int proto_num; 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate proto_num = getipsecprotobyname(proto_name); 7180Sstevel@tonic-gate if (proto_num == -1) 7190Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate return (delipsecprotobynum(proto_num)); 7220Sstevel@tonic-gate } 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate /* 7250Sstevel@tonic-gate * Implement these in libnsl since these are read-only operations. 7260Sstevel@tonic-gate */ 7270Sstevel@tonic-gate int * 7280Sstevel@tonic-gate getipsecprotos(int *nentries) 7290Sstevel@tonic-gate { 7300Sstevel@tonic-gate return (_real_getipsecprotos(nentries)); 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate int * 7340Sstevel@tonic-gate getipsecalgs(int *nentries, int proto_num) 7350Sstevel@tonic-gate { 7360Sstevel@tonic-gate return (_real_getipsecalgs(nentries, proto_num)); 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate const char * 7400Sstevel@tonic-gate ipsecalgs_diag(int diag) 7410Sstevel@tonic-gate { 7420Sstevel@tonic-gate switch (diag) { 7430Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALG_EXISTS: 7440Sstevel@tonic-gate return (gettext("Algorithm already exists")); 7450Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_PROTO_EXISTS: 7460Sstevel@tonic-gate return (gettext("Protocol already exists")); 7470Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_UNKN_PROTO: 7480Sstevel@tonic-gate return (gettext("Unknown protocol")); 7490Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_UNKN_ALG: 7500Sstevel@tonic-gate return (gettext("Unknown algorithm")); 7510Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_NOMEM: 7520Sstevel@tonic-gate return (gettext("Out of memory")); 7530Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILEOPEN: 7540Sstevel@tonic-gate return (gettext("open() failed")); 7550Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILEFDOPEN: 7560Sstevel@tonic-gate return (gettext("fdopen() failed")); 7570Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILELOCK: 7580Sstevel@tonic-gate return (gettext("lockf() failed")); 7590Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILERENAME: 7600Sstevel@tonic-gate return (gettext("rename() failed")); 7610Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILEWRITE: 7620Sstevel@tonic-gate return (gettext("write to file failed")); 7630Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILECHMOD: 7640Sstevel@tonic-gate return (gettext("chmod() failed")); 7650Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILECHOWN: 7660Sstevel@tonic-gate return (gettext("chown() failed")); 7670Sstevel@tonic-gate case LIBIPSEC_ALGS_DIAG_ALGSFILECLOSE: 7680Sstevel@tonic-gate return (gettext("close() failed")); 7690Sstevel@tonic-gate default: 7700Sstevel@tonic-gate return (gettext("failed")); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate /* 7750Sstevel@tonic-gate * Get the execution mode corresponding to the specified protocol. 7760Sstevel@tonic-gate * Returns 0 on success, one of the LIBIPSEC_ALGS_DIAG_* values on 7770Sstevel@tonic-gate * failure. 7780Sstevel@tonic-gate */ 7790Sstevel@tonic-gate int 7800Sstevel@tonic-gate ipsecproto_get_exec_mode(int proto_num, ipsecalgs_exec_mode_t *exec_mode) 7810Sstevel@tonic-gate { 7820Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto; 7830Sstevel@tonic-gate int num_protos; 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 7860Sstevel@tonic-gate B_TRUE)) == NULL) 7870Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate *exec_mode = current_proto->proto_exec_mode; 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate _clean_trash(protos, num_protos); 7920Sstevel@tonic-gate return (0); 7930Sstevel@tonic-gate } 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate /* 7960Sstevel@tonic-gate * Set the execution mode of the specified protocol. Returns 0 on success, 7970Sstevel@tonic-gate * or one of the LIBIPSEC_ALGS_DIAG_* values on failure. 7980Sstevel@tonic-gate */ 7990Sstevel@tonic-gate int 8000Sstevel@tonic-gate ipsecproto_set_exec_mode(int proto_num, ipsecalgs_exec_mode_t exec_mode) 8010Sstevel@tonic-gate { 8020Sstevel@tonic-gate ipsec_proto_t *protos, *current_proto; 8030Sstevel@tonic-gate int num_protos; 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate if ((current_proto = proto_setup(&protos, &num_protos, proto_num, 8060Sstevel@tonic-gate B_TRUE)) == NULL) 8070Sstevel@tonic-gate return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO); 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate current_proto->proto_exec_mode = exec_mode; 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate return (write_new_algfile(protos, num_protos)); 8120Sstevel@tonic-gate } 813