/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <ipsec_util.h>
#include <stdlib.h>
#include <strings.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <libintl.h>
#include <errno.h>
static char *preamble =
"#\n"
"# DO NOT EDIT OR PARSE THIS FILE!\n"
"#\n"
"# Use the ipsecalgs(1m) command to change the contents of this file.\n"
"# The algorithm descriptions contained in this file are synchronised to the\n"
"# kernel with ipsecalgs -s, the kernel validates the entries at this point."
"\n\n"
"# PROTO|protocol-id|protocol-name|exec-mode\n"
"## NOTE: Some protocol numbers are well-known and defined in <netdb.h>\n\n"
"# ALG|protocol-id|alg-id|name,name,...|ef-id| \n"
"# {default/}{key,key..}or{key-key,inc}|block_size or MAC-size|\n"
"# [parameter,parameter..]|[flags]\n\n"
"#\n"
"## Note: Parameters and flags only apply to certain algorithms.\n\n";
/*
* write_new_algfile() helper macros to check for write errors.
*/
goto bail; \
}
goto bail; \
}
/*
* Helper macros to start and finish a list of entries that were added
* as part of a package installation.
*/
LIBIPSEC_ALGS_LINE_PKGSTART, (cur_pkg))); \
}
if (doing_pkg) { \
LIBIPSEC_ALGS_LINE_PKGEND, (cur_pkg))); \
} \
}
/*
* Take a zero-terminated int array and print int1,int2...,intN.
* If zero-only, then print a single '0'.
* Returns 0 on success, -1 if an error occurred while writing to
* the specified file.
*/
int
{
while (*floater != 0) {
return (-1);
if (*(++floater) != 0)
return (-1);
}
if (!executed)
return (-1);
return (0);
}
/*
* If the specified algorithm was defined within a package section, i.e.
* between the lines "# Start <pkgname>" and "# End <pkgname>", returns
* the value of <pkgname>.
*/
static char *
{
int i;
return (NULL);
for (i = 0; i < proto->proto_algs_npkgs; i++)
return (NULL);
}
/*
* name associated with the current protocol or algorithm, and
* the state of the packaging information already written to the file.
* Called by write_new_algfile(). Returns 0 on success, one of the
* LIBIPSEC_DIAG codes on failure.
*/
static int
{
int rc = 0;
/* protocol or algorithm is associated with a package */
if (!*doing_pkg) {
/* start of a new package section */
} else {
/* already in a package section */
/* different package name */
}
}
} else if (*doing_pkg) {
/* in a package section when the entry isn't */
}
bail:
return (rc);
}
/*
* Given a list of protocols and number, write them to a new algorithm file.
* This function takes num_protos + num_protos * dois-per-alg operations.
* Also free the protocol structure.
*
* used by callers of this routine. This could cause this function to suffer
* from the "lost update" problem. Since updates to the IPsec protocols
* and algorithm tables are very infrequent, this should not be a issue in
* practice.
*/
static int
{
FILE *f;
int fd, i, j, k;
int rc = 0;
char *alg_pkg;
char *tmp_name;
/*
* In order to avoid potentially corrupting the configuration
* file on file system failure, write the new configuration info
* to a temporary file which is then renamed to the configuration
* file (INET_IPSECALGSFILE.)
*/
if (fd == -1) {
goto bail;
}
if (f == NULL) {
goto bail;
}
/* Write protocol entries. */
for (i = 0; i < num_protos; i++) {
/* add package section delimiters if needed */
if (rc != 0)
goto bail;
switch (protos[i].proto_exec_mode) {
case LIBIPSEC_ALGS_EXEC_SYNC:
break;
case LIBIPSEC_ALGS_EXEC_ASYNC:
break;
}
}
/* terminate the package section for the protocols if needed */
/* Write algorithm entries. */
for (i = 0; i < num_protos; i++) {
for (j = 0; j < protos[i].proto_numalgs; j++) {
/* add package section delimiters if needed */
if (rc != 0)
goto bail;
/* protocol and algorithm numbers */
/* algorithm names */
}
/* mechanism name */
/* key sizes */
if (alg->a_key_increment == 0) {
/* key sizes defined by enumeration */
goto bail;
}
} else {
/* key sizes defined by range */
}
/* block sizes */
goto bail;
}
/*
* Some algorithms require extra parameters, these
* are stored in an array. For algorithms that don't
* need these parameters, or flags (below), these
* extra fields in the ipsecalgs file must contain a
* zero. This fuction will get called if a algorithm
* entry is added, at this point the extra fields will
* be added to the file.
*/
goto bail;
}
/* flags */
}
}
/* terminate the package section for the algorithms if needed */
goto bail;
}
goto bail;
}
goto bail;
}
bail:
return (rc);
}
/*
* Return a pointer to the protocol entry corresponding to the specified
* protocol num proto_num. Also builds the list of currently defined
* protocols.
*/
static ipsec_proto_t *
{
int i;
return (NULL);
for (i = 0; i < *num_protos; i++) {
current_proto = (*protos) + i;
break;
}
}
if (cleanup)
}
return (ret_proto);
}
/*
* Delete the first found algorithm of the specified protocol which
* has the same name as the one specified by alg_name. Deletion of
* the entry takes place only if the delete_it flag is set. If an
* entry was found, return B_TRUE, otherwise return B_FALSE.
*/
static boolean_t
{
int i;
char **name_check;
for (i = 0; i < proto->proto_numalgs; i++) {
if (!found_match) {
for (name_check =
/*
* Can use strcmp because the algorithm names
* are bound.
*/
if (!delete_it)
return (found_match);
break;
}
}
} else {
}
}
if (found_match)
proto->proto_numalgs--;
return (found_match);
}
/*
* Returns B_TRUE if the specified 0-terminated lists of key or
* block sizes match, B_FALSE otherwise.
*/
static boolean_t
{
int i;
return (B_FALSE);
}
return (B_FALSE);
return (B_TRUE);
}
/*
* Returns B_TRUE if an _exact_ equivalent of the specified algorithm
* already exists, B_FALSE otherwise.
*/
static boolean_t
{
int i;
for (i = 0; i < proto->proto_numalgs; i++) {
continue;
continue;
continue;
curname++;
newbiename++;
}
continue;
continue;
continue;
/* we found an exact match */
return (B_TRUE);
}
return (B_FALSE);
}
/*
* or otherwise address "newbie".
*/
int
{
int num_protos, i;
char **name_check;
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
/*
* If an algorithm that matches _exactly_ the new algorithm
* already exists, we're done.
*/
return (0);
/*
* We don't allow a new algorithm to be created if one of
* its names is already defined for an existing algorithm,
* unless the operation is forced, in which case existing
* algorithm entries that conflict with the new one are
* deleted.
*/
if (found_match && !forced_add) {
/*
* Duplicate entry found, but the addition was
* not forced.
*/
return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS);
}
}
for (i = 0; i < current_proto->proto_numalgs; i++) {
/*
* An algorithm with the same protocol number
* and algorithm number already exists. Fail
* addition unless the operation is forced.
*/
if (flags & LIBIPSEC_ALGS_ADD_FORCE) {
current_proto->proto_algs[i]);
return (write_new_algfile(protos,
num_protos));
} else {
return (LIBIPSEC_ALGS_DIAG_NOMEM);
}
} else {
return (LIBIPSEC_ALGS_DIAG_ALG_EXISTS);
}
}
}
/* append the new algorithm */
sizeof (struct ipsecalgent *) * (i + 1));
return (LIBIPSEC_ALGS_DIAG_NOMEM);
}
return (LIBIPSEC_ALGS_DIAG_NOMEM);
}
}
/*
* Only deletes the first encountered instance.
*/
int
{
int num_protos;
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
return (LIBIPSEC_ALGS_DIAG_UNKN_ALG);
}
/*
*/
int
{
int i, num_protos;
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
for (i = 0; i < current_proto->proto_numalgs; i++) {
if (!found_match) {
alg_num) {
}
} else {
current_proto->proto_algs[i];
}
}
if (found_match) {
}
return (LIBIPSEC_ALGS_DIAG_UNKN_ALG);
}
/*
* Remove the specified protocol entry from the list of protocols.
*/
static void
{
int i;
/* free protocol storage */
for (i = 0; i < proto->proto_numalgs; i++)
/* remove from list of prototocols */
}
/*
*/
int
{
int i, num_protos;
/*
* NOTE:If build_internal_algs returns NULL for any
*/
/* check for protocol with duplicate id */
if (current_proto != NULL) {
/*
* The current protocol being added matches
* exactly an existing protocol, we're done.
*/
return (0);
}
if (!(flags & LIBIPSEC_ALGS_ADD_FORCE))
return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS);
}
/* check for protocol with duplicate name */
for (i = 0; i < num_protos; i++) {
if (!(flags & LIBIPSEC_ALGS_ADD_FORCE))
return (LIBIPSEC_ALGS_DIAG_PROTO_EXISTS);
break;
}
}
/* add new protocol */
num_protos++;
sizeof (ipsec_proto_t));
return (LIBIPSEC_ALGS_DIAG_NOMEM);
}
/* initialize protocol entry */
new_proto->proto_numalgs = 0;
return (LIBIPSEC_ALGS_DIAG_NOMEM);
}
new_proto->proto_algs_npkgs = 0;
}
/*
* nukes the associated algorithms.
*/
int
{
int num_protos;
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
}
int
{
int proto_num;
if (proto_num == -1)
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
return (delipsecprotobynum(proto_num));
}
/*
* Implement these in libnsl since these are read-only operations.
*/
int *
{
return (_real_getipsecprotos(nentries));
}
int *
{
}
const char *
{
switch (diag) {
case LIBIPSEC_ALGS_DIAG_NOMEM:
default:
}
}
/*
* Get the execution mode corresponding to the specified protocol.
* Returns 0 on success, one of the LIBIPSEC_ALGS_DIAG_* values on
* failure.
*/
int
{
int num_protos;
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
return (0);
}
/*
* Set the execution mode of the specified protocol. Returns 0 on success,
* or one of the LIBIPSEC_ALGS_DIAG_* values on failure.
*/
int
{
int num_protos;
return (LIBIPSEC_ALGS_DIAG_UNKN_PROTO);
}