conflib.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file implements windows style INI files. It caches
* files in memory, so they are not parsed on each read.
*
* WARNING: This library is completely UN-THREAD-SAFE and NON-REENTRANT.
*/
/* LINTLIBRARY */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "conflib.h"
/* ********************* Internal Structures ******************** */
/* This is the simplest part. A label. This is the atom of the ini file */
typedef struct {
char Label[MAX_LABEL_LEN];
char Value[MAX_VALUE_LEN];
} LabelType;
/* A section contains an array list of labels */
typedef struct {
int NumLabels;
char SectionName[MAX_FILENAME_LEN];
} SectionType;
/* An ini file contains an array list of Sections */
typedef struct {
int NumSections;
char Filename[MAX_FILENAME_LEN];
} IniFileType;
/* An IniFileList Contains a linked list of ini files */
typedef struct s {
struct s *Next;
} IniFileList;
#define INI_SECTION 1
#define INI_LABEL 2
#define INI_ERROR 0
char ErrorString[ERROR_STRING_LEN];
/* These are the valid ipsec actions mipagent and friends support. */
char *validIPsecAction[] = {
"apply", /* outbound IPsec Policy */
"permit", /* inbound IPsec Policy */
};
/* Each entry in our various ipsec algorithm tables is one of these */
struct ipsec_alg {
char *alg;
};
/* Some macroed values */
#define NO_AH_AALG 256
#define NO_ESP_AALG 256
#define NO_ESP_EALG 256
/* valid encr_algs to match with user config */
{"any", SADB_EALG_NONE},
{"des", SADB_EALG_DESCBC},
{"des-cbc", SADB_EALG_DESCBC},
{"3des", SADB_EALG_3DESCBC},
{"3des-cbc", SADB_EALG_3DESCBC},
{"blowfish", SADB_EALG_BLOWFISH},
{"blowfish-cbc", SADB_EALG_BLOWFISH},
{"aes", SADB_EALG_AES},
{"aes-cbc", SADB_EALG_AES},
{"null", SADB_EALG_NULL},
{"none", NO_ESP_EALG},
{NULL, 0}
};
/* one auth_algs to match with user configs */
{"any", SADB_AALG_NONE},
{"md5", SADB_AALG_MD5HMAC},
{"hmac-md5", SADB_AALG_MD5HMAC},
{"sha1", SADB_AALG_SHA1HMAC},
{"hmac-sha1", SADB_AALG_SHA1HMAC},
{"sha", SADB_AALG_SHA1HMAC},
{"hmac-sha", SADB_AALG_SHA1HMAC},
{"none", NO_AH_AALG},
{NULL, 0}
};
#define SADB_SA_SHARED 0
#define SADB_SA_UNIQUE 1
/*
* One for sa_algs. OK, these aren't algs, but in order to make the parsing
* of properties easy, they're laid out "<tag> <alg> <tag> <alg> ...", so it's
* designed so <tag> maps directly to the function that parses <alg>. The
* "... sa (shared | unique)" bit then needs to be done analogously.
*/
{"shared", SADB_SA_SHARED},
{"unique", SADB_SA_UNIQUE},
{NULL, 0},
};
/*
* Internal prototypes
*/
static int IniLoadFile(char *Filename);
char *Data);
char *Data);
static int IniCheckComment(char *buffer);
char *Data);
#ifndef lint /* this function is not used for now */
int *elementSize);
#endif /* lint */
static int IniUnloadFile(char *Filename);
char *Data);
static void CheckAndAllocateCacheSpace();
/* ipsec algorithm parsing routines */
int parse_algs(int, int, ipsec_req_t *);
int parse_esp_auth_alg(char *, ipsec_req_t *);
int parse_esp_encr_alg(char *, ipsec_req_t *);
int parse_ah_alg(char *, ipsec_req_t *);
int parse_sa_alg(char *, ipsec_req_t *);
uint_t isIPsecActionValid(char *);
/* something to switch on */
/* table for parsing IPSEC related algs */
struct ipsec_cmd {
char *c_name;
int (*c_func)(char *, ipsec_req_t *);
} ipseccmd[] = {
{ "encr_auth_algs", parse_esp_auth_alg },
{ "encr_algs", parse_esp_encr_alg },
{ "auth_algs", parse_ah_alg },
{ "sa", parse_sa_alg },
{ 0, 0 },
};
/*
* Function: InitializeIniFile
*
* Arguments: IniFileList *
*
* Description: This function will Initialize an ini file
*
* Returns: void
*
*/
static void
{
} /* InitializeIniFile */
/*
* Function: FileHasChanged
*
* Arguments: ModificationTime, Filename
*
* Description: This function will return true if the filename's
* modification time is different than the one passed in.
* It also returns true on error. If we aren't able to get a
* stat() of the file, just assume it has changed.
*
* Returns: int (non zero if time has changed)
*
*/
static int
{
struct stat file_stats;
return (TRUE); /* file does not exist */
/*
* Some kind of error. Just return TRUE.
* Note: we come in here twice, once via IniLoaded(), and
* (if that fails) again from IniLoadFile(). It would be
* mostly innocuous to overwrite ErrorString with this [same]
* message, but why bother?
*/
if (ErrorString[0] == '\0') {
"unable to retrieve stats on <%s>. %s.", Filename,
}
return (TRUE);
}
/*
* Now return the change state
*/
} /* FileHasChanged */
/*
* Function: IniLoadFile
*
* Arguments: Filename
*
* Description: This function loads in a configuration file.
* It caches files by moving them to the head of the linked
* list. It also checks for files that have changed on the disk
* by using stat().
*
* Returns: int (zero on success)
*
*/
static int
IniLoadFile(char *Filename)
{
/* Check to see if it is already loaded */
/*
* Found it, we already have it cached.
*/
ModificationTime, Filename)) {
/* Reload the file */
(void) IniUnloadFile(Filename);
break; /* Leave loop */
} else {
/*
* It is our file, and it hasn't changed,
* Cache our entry by moving it to the head
* of the list and return success.
*/
if (Last) {
/*
* Only move it if this is not the
* first entry.
*/
}
return (0);
}
} /* strcmp checking filename */
} /* For loop searching for file */
/*
* Now, we know that we don't have the file cached or loaded, so
* allocate memory and load it.
* Note: IniFileList is the bucket that holds a STATIC IniFileType.
*/
if (!NewIniFileNode) {
(void) strcpy(ErrorString,
"Unable to allocate memory for new ini file.");
return (-1);
}
/*
* Add it to our head. But first, remove the last entry if we have
* Too many items in our cache.
*/
/*
* Now we have a pointer to New. Clear it, and parse in the
* new file
*/
/* Remove ini file from list */
return (-2);
}
return (0);
} /* IniLoadFile */
/*
* Function: CheckAndAllocateCacheSpace
*
* Arguments: none
*
* Description: This routine will check to see if our INI cache is full, and
* if so, will delete the last (least recently used) entry.
*
* Returns: void
*
*/
static void
{
int count;
/* Return if the cache is empty (or nearly empty) */
return;
/*
* Send Probe to next to end of list, and last to one before probe,
* while counting with count.
*/
if (count >= INI_MAX_CACHED) {
/* Our cache is full. Free the last entry */
}
} /* CheckAndAllocateCacheSpace */
/*
* Function: IniParseFile
*
* Arguments: IniFileType *File, char *Filename
*
* Description: This routine will parse the INI file and load the Section
* and Label arrays.
*
* Returns: int
*/
static int
{
int LineNo;
char CurrentSection[MAX_LABEL_LEN];
int rc;
/*
* Copy the filename...
*/
/* Set the modification time */
} else {
"Unable to stat <%s>. %s.", Filename,
return (-1);
}
/* Open the file */
"Unable to open file <%s>. %s.", Filename,
return (-1);
}
LineNo = 0;
LineNo++;
/* If it is a comment or a blank line, don't process it */
if (IniCheckComment(buffer))
continue;
case INI_SECTION:
/* Call our add section function */
/* If an error occurs, AddSection sets ErrorString */
if (rc < 0) {
return (rc);
}
break;
case INI_LABEL:
/*
* check to see if we are before our first
* section label
*/
if (!File->NumSections) {
"section on line %d.", LineNo);
return (-2);
}
/* If an error occurs, AddLabel sets ErrorString */
if (rc < 0) {
return (rc);
}
break;
case INI_ERROR:
default:
"Error parsing INI file (%s) on line %d.",
return (-3);
}
}
/* Success! */
return (0);
} /* IniParseFile */
/*
* Function: TrimWhiteSpace
*
* Arguments: char *buffer
*
* Description: This function removes leading and trailing white space
* from a string.
*
* Returns: static void
*/
static void
TrimWhiteSpace(char *buffer)
{
int i, j;
/* First, find first non-whitespace character */
/*
* Now, i is pointing to the first non-white space
* character in buffer
*/
/* Find the last non-whitespace character */
if ((i > j) || (j < 0)) {
/* Empty */
buffer[0] = 0;
} else {
/* copy the usable buffer */
/* and Null-terminate it */
buffer[(j-i)+1] = 0;
}
} /* TrimWhiteSpace */
/*
* Function: ParseLine
*
* Arguments: char *buffer, char *TempTag, char *TempValue
*
* Description: This routine will return either the section or label
* information. If it finds a section line in the buffer,
* it will return the section name in the TempTag Field.
* If it finds a Label, it will fill out TempValue and
* TempTag.
*
* Returns: int
*/
static int
{
int i = 0, j = 0;
int EqualFound = FALSE;
/* Trim the white space of the entire buffer first */
if (buffer[0] == '[') {
/* Must be a section */
/* Check to make sure we got an end-bracket */
if (buffer[i] != ']')
/* Bad Section! */
return (INI_ERROR);
TempTag[j] = 0;
return (INI_SECTION);
}
for (i = 0; buffer[i]; i++) {
if (buffer[i] == '=') {
EqualFound = TRUE;
TempTag[j] = 0;
j = 0;
} else {
if (!EqualFound)
else
}
}
if (!EqualFound) {
/* Bad Label! */
return (INI_ERROR);
}
TempValue[j] = 0;
/* Handle EOLN */
TempValue[j-1] = 0;
/* And finally, trim the white space off of our return strings */
return (INI_LABEL);
} /* ParseLine */
/*
* Function: IniUpdateFile
*
* Arguments: char *Filename, char *Section, char *Label, char *Data
*
* Description: This will update our INI file. It copies the file from
* it's original position to a temp one, then renames to
* overwrite the original.
*
* Returns: int (zero on success)
*/
static int
{
char TempFile[MAX_FILENAME_LEN];
int DeleteSection = 0;
int DeleteLabel = 0;
/* Set our deletion flags */
DeleteSection = 1;
if (!Data)
DeleteLabel = 1;
/*
* Don't worry about checking the handle right away. It's checked
* later. If the input file open fails, we assume that the file just
* does not exist. It will be created when the output file is renamed
* into the input file (or it is copied).
*/
/* Create a temporary file name in the same directory as the INI file */
sizeof (TempFile));
if (!out) {
"Unable to copy <%s>, can't open temp file <%s>. %s.",
return (-1);
}
if (in) {
/* Our input file exists */
/*
* Section did not exist, make one
* If DeleteSection or DeleteLabel is set, it's a nop.
*/
if (!DeleteSection && !DeleteLabel) {
}
} else {
if (DeleteSection) {
/*
* Delete the section.
* Copy to EOF with NULL as the label
*/
} else {
/*
* Section did exist, just dump label, and
* search for next section or same label line,
* so we can erase it.
*/
if (!DeleteLabel) {
/*
* Dump the new label, only if
* we're not deleting it
*/
}
}
}
} else {
/* no input file, just put output */
}
/*
* The rename could file for many reasons, but all of them are very
* bad ones. Assume that Rename has set ErrorString.
*/
return (-1);
}
/* Let our internal update set the return code now */
} /* IniUpdateFile */
/*
* Function: Rename
*
* Arguments: char *source, char *dest
*
* Description: This function tries a rename. If it fails, it tries a copy.
* It should never fail, since the temp file is in the same
* directory as the input file.
*
* Returns: int (zero on success)
*/
int
{
int rc;
/* Do copy! */
int nchars;
if (!in) {
"Error opening source file <%s> for rename. %s.",
return (-1);
}
if (!out) {
"Error opening target file <%s> for rename. %s.",
return (-2);
}
/* Ok, now do copy */
do {
if (nchars > 0) {
(void) snprintf(ErrorString,
sizeof (ErrorString),
"Error writing target file <%s> "
"during rename. %s.", dest,
"Unknown error.");
return (rc);
}
}
} while (nchars > 0);
/* if fread() fails... */
if (nchars < 0) {
"Error reading source file <%s>. %s.", source,
return (nchars);
}
}
return (rc);
} /* Rename */
/*
* Function: dirname
*
* Arguments: char *FullPath
*
* Description: This function will return the directory name of the
* passed in filename. This is for out temporary file.
* MV does not work across filesystems.
*
* Returns: char *
*/
static char *
{
int len;
return (Dirname);
}
}
/*
* If we got here, then we searched the whole string, return NULL
*/
return (NULL);
} /* dirname */
/*
* Function: RemoveSection
*
* Arguments: int SectionNdx, IniFileType *File
*
* Description: This function will remove a section from the given INI file.
* It does all the necessary garbage collection.
*
* Returns: int (zero on success)
*/
static int
{
/* First, remove all the labels */
/* Finally, remove the Section */
if (File->NumSections &&
SectionNdx >= 0) {
int NumToMove;
/* Copy the rest down a notch */
if (NumToMove > 0) {
sizeof (SectionType) * NumToMove);
}
/* Free the last one */
File->NumSections--;
return (0);
} /* Sanity Check */
"Unable to remove section <%s> in INI file <%s>",
return (-1);
} /*RemoveSection*/
/*
* Function: RemoveLabel
*
* Arguments: SectionType *Section, int LabelNdx
*
* Description: This function will remove a label from the given INI
* file. (No GC is necessary, since the Arrays are Static)
*
* Returns: int
*/
static int
{
/* Sanity Check */
LabelNdx >= 0) {
int NumToMove;
/* Copy the rest down a notch */
if (NumToMove > 0) {
}
/* Free the last one */
return (0);
} /* Sanity Check */
"Unable to remove label <%s> from INI file ",
return (-1);
} /* RemoveLabel */
/*
* Function: IniUpdateLocalCopy
*
* Arguments: char *Filename, char *Section, char *Label, char *Data
*
* Description: This function will update the internal copy of the data
* we have. (It is called form IniUpdateFile)
*
* Returns: int
*/
static int
{
int SectionNdx, LabelNdx;
struct stat file_stats;
int DeleteSection = 0;
int DeleteLabel = 0;
int rc;
/* Set our deletion flags */
DeleteSection = 1;
if (!Data)
DeleteLabel = 1;
/*
* First, search for the file
*/
Filename) == 0)
break;
}
if (!FileProbe) {
/*
* We did not find the file. Someone did a write without
* a read. Return an error. (The file is still written to,
* and the next read will parse it in.)
*/
return (0);
}
/*
* Now let's update our statistics, so our cache is up to date.
*/
"Error: Unable to retrieve statistics on <%s>. %s.",
return (-2);
} else
/*
* now, File contains our file pointer. Check
* to see if our section exists.
*/
/* We have the section! */
break;
}
}
if (DeleteSection || DeleteLabel) {
"Error IniUpdateLocalCopy: "
"Section not found in <%s>",
Filename);
return (-1); /* Error, not found */
}
if (SectionNdx < 0)
return (SectionNdx);
} else {
if (DeleteSection) {
}
/* We have the section. Search for the label */
for (LabelNdx = 0;
LabelNdx++) {
if (strcasecmp(Label,
== 0) {
if (DeleteLabel) {
return (RemoveLabel(
LabelNdx));
}
/* Found the label. Update the data */
break;
}
}
if (DeleteLabel) {
(void) snprintf(ErrorString,
sizeof (ErrorString),
"Error IniUpdateLocalCopy: "
"Label not found in <%s>",
Filename);
return (-1); /* Error, not found */
}
/* Need to add a label! */
if (rc < 0)
return (rc);
}
}
return (0);
} /* IniUpdateLocalCopy */
/*
* Function: AddSection
*
* Arguments: IniFileType *IniFile, char *Section
*
* Description: This function will add a section to the passed in file.
*
* Returns: int
*/
static int
{
/*
* Set up new section Array
*/
if (!SectionPointer) {
return (-1);
}
/*
* Copy old sections over - including pointers
*/
if (IniFile->NumSections) {
}
/*
* Update new section
*/
IniFile->NumSections++;
/* Return an index to the newly added one */
} /* AddSection */
/*
* Function: AddLabel
*
* Arguments: IniFileType *IniFile, int SectionNdx, char *Label, char *Data
*
* Description: This function adds a label to a section.
*
* Returns: static int
*/
static int
{
/*
* Set up CurrentSection pointer for ease of typing.
*/
/*
* Allocate enough room for new label
*/
if (!LabelPointer) {
return (-3);
}
if (SectionPointer->NumLabels) {
/* Do the copy */
}
/* return the index of the new label */
} /* AddLabel */
/*
* Function: ModifyLabel
*
* Arguments: IniFileType *IniFile, int SectionNdx, int LabelNdx, char *Data
*
* Description: This function will just modify the data of a label in memory.
*
* Returns: void
*/
static void
{
0, MAX_VALUE_LEN);
} /* ModifyLabel */
/*
* Function: SectionCmp
*
* Arguments: char *line, char *Section
*
* Description: This function returns zero if the line is a section line,
* and contains our section.
*
* Returns: int
*/
static int
{
case INI_SECTION:
default: /* Not a section */
return (-1);
}
} /* SectionCmp */
/*
* Function: CopyToSection
*
* Arguments: char *Section, FILE *in, FILE *out, int CopySection
*
* Description: Copies the files from in to out, until it gets to
* the namedSection. If CopySection is non-zero, it
* will also copy the section line. If it is zero
* the section line will not be copied (for deletion)
*
* Returns: int (non-zero if the section was found)
*/
static int
{
/* We have the section */
if (CopySection)
return (TRUE);
}
}
return (FALSE);
} /* CopyToSection */
/*
* Function: CopyToEOF
*
* Arguments: FILE *in, FILE *out, char *Label
*
* Description: Copies from *in to *out, deleting Label in the current
* section. If Lable is NULL, then all labels are deleted until
* the next section is reached.
*
* Returns: void
*/
static void
{
char tempbuffer[BUF_LEN];
int SectionFound = FALSE;
char TempLabel[MAX_LABEL_LEN];
char TempValue[MAX_VALUE_LEN];
if (!SectionFound) {
case INI_SECTION:
SectionFound = TRUE;
break;
case INI_LABEL:
if (Label) {
/*
* If label is non-null, then copy
* everything EXCEPT the given label.
*/
}
}
break;
default:
break;
}
} else {
/*
* If the next section has been found,
* just write everything
*/
} /* if SectionFound */
} /* end While */
} /* CopyToEOF */
/*
* Function: GetSectionList
*
* Arguments: IniFileType *IniFile, char *argv, int *NumSections,
* int *elementSize
*
* Description: This routine returns a list of sections in a newly
* allocated array.
*
* Returns: char *, and modifies NumSections and elementSize
*/
static char *
int *elementSize)
{
int i;
/*
* Do garbage collection
*/
if (argv) {
}
if (!IniFile->NumSections)
return (argv);
if (!argv) {
(void) sprintf(ErrorString,
"Out of memory getting section list.");
return (NULL);
}
for (i = 0; i < IniFile->NumSections; i++) {
}
return (argv);
} /* GetSectionList */
/*
* Function: IniLoaded
*
* Arguments: char *Filename
*
* Description: Returns true if the specified file is loaded and has
* not changed.
*
* Returns: int
*/
static int
{
Filename)) {
return (FALSE);
} else {
return (TRUE);
}
}
}
return (FALSE);
} /* IniLoaded */
/*
* Function: IniCheckComment
*
* Arguments: char *buffer
*
* Description: Returns true if the given line is a comment, or if it is
* blank. Also removes any partial-line comments by
* replacing the semi-colon with a NULL;
*
* A comment is of the form :
* ; comment
* or
* # comment
*
* Returns: int
*/
static int
IniCheckComment(char *buffer)
{
int i;
if (i) {
/* check for \; or \# */
continue;
}
/*
* Otherwise, mark it as a null, and check for an
* empty string
*/
buffer[i] = 0;
break;
}
}
return (0);
}
return (1); /* This is a blank (or commented) line */
} /* IniCheckComment */
/*
* Function: IniUnloadFile
*
* Arguments: char *Filename
*
* Description: This routine will remove an ini file from our list,
* and free up memory.
*
* Returns: int (zero on success)
*/
static int
IniUnloadFile(char *Filename)
{
if (!File)
return (-1);
return (0);
} /* IniUnloadFile */
/*
* Function: IniFreeFile
*
* Arguments: IniFileList *File
*
* Description: Does the garbage collection on a file. (frees all data)
*
* Returns: void
*/
static void
{
int CurrentSection;
/*
* Now, free up all the memory
*/
CurrentSection++) {
/*
* Free up label array
*/
}
/* Now free up the sections */
/* and finally... */
} /* IniFreeFile */
/*
* Function: UnlinkFile
*
* Arguments: char *Filename
*
* Description: This routine will remove the file from the linked list, and
* return a pointer to it, so it can be freed.
*
* Returns: IniFileList *
*/
static IniFileList *
UnlinkFile(char *Filename)
{
if (!PrevProbe) {
} else {
}
return (Probe);
}
}
return (NULL);
} /* UnlinkFile */
/*
* Function: GetSectionProfileString
*
* Arguments: char *Section, char *Label, dest, destLen
*
* Description: This function is part of GetPrivateProfileString. It was
* Only Added to improve the C-Style formatting. (Fors got
* nested too deep.)
*
* Returns: static int
*/
static int
{
int i;
/* We have the file */
if (strcasecmp(Section,
== 0) {
return (GetLabelProfileString(IniFile,
}
} /* end section for */
"Unable to find section <%s>.", Section);
return (-1);
} /* GetSectionProfileString */
/*
* Function: GetLabelProfileString
*
* Arguments: char *Section, char *Label, char *dest, int destLen
*
* Description: This function is part of GetPrivateProfileString. It was
* Only Added to improve the C-Style formatting. (Fors got
* nested too deep.)
*
* Returns: static int
*/
static int
{
int j;
/* We have the section */
for (j = 0;
j++) {
if (strcasecmp(Label,
/* We finally have it! */
destLen);
return (0);
}
} /* end label for */
"Unable to find label <%s>.", Label);
return (-1);
} /* GetLabelProfileString */
/*
*
* E X T E R N A L F U N C T I O N S
*
* These functions are called by external programs. (They are non-static)
*
*/
/*
* Function: WritePrivateProfileString
*
* Arguments: char *Section, char *Label, char *data
*
* Description: Sets the new string into [Section] Label=data
*
* Returns: int (zero on success)
*/
int
char *Filename)
{
/*
* Unload the file, if it is loaded. The next read will load it.
*/
} /* WritePrivateProfileString */
/*
* Function: DeletePrivateProfileSection
*
* Arguments: char *Section, char *Filename
*
* Description: Deletes an entire section (and all labels)
*
* Returns: int (zero on success)
*/
int
{
} /* DeletePrivateProfileSection*/
/*
* Function: DeletePrivateProfileLabel
*
* Arguments: char *Section, char *Label, char *Filename
*
* Description: Deletes a label from a section.
*
* Returns: int (zero on success)
*/
int
{
} /* DeletePrivateProfileLabel */
/*
* Function: WritePrivateProfileInt
*
* Arguments: char *Section, char *Label, int data, char *Filename
*
* Description: Sets the new int into [Section] Label=data
*
* Returns: int (zero on success)
*/
int
{
} /* WritePrivateProfileInt */
/*
* Function: GetPrivateProfileString
*
* Arguments: char *Section, char *Label, char *defaultValue
*
* Description: retrieves data from a section
*
* Returns: int (zero on success)
*/
int
{
char errMsg[ERROR_SUBSTRING_LEN];
int rc;
/*
* First, Lookup the file, then lookup the section,
* then lookup the label, then copy the string
*/
ErrorString[0] = 0; /* Clear the error string */
/* set default value */
if (rc < 0) {
return (rc);
}
}
} /* end file for */
/*
* IniLoaded() and IniLoadFile() call FileHasChanged() which may have
* something to say via ErrorString - don't overwrite it!
*/
"Unable to find file <%s>. ", Filename);
return (-1);
} /* GetPrivateProfileString */
/*
* Function: GetPrivateProfileInt
*
* Arguments: char *Section, char *Label, int defaultValue
*
* Description: Returns the int associated with [Section], Label=Int
*
* Returns: int
*/
int
char *Filename)
{
char String[MAX_LONG_LEN];
if (!String[0]) /* Our default return value is "" */
return (defaultValue);
else
} /* GetPrivateProfileInt */
/*
* Function: IniListSections
*
* Arguments: char *Filename, int *NumSections, int *elementSize
*
* Description: Returns a list of sections. (allocates an array)
*
* Returns: char *
*/
char *
{
char errMsg[ERROR_SUBSTRING_LEN];
int rc;
if (rc < 0) {
return (NULL);
}
}
return (argv);
}
}
/*
* IniLoaded() and IniLoadFile() call FileHasChanged() which may have
* something to say via ErrorString - don't overwrite it!
*/
"Unable to find file <%s>. ", Filename);
return (NULL);
} /* IniListSections */
/*
* Function: parsealg
*
* Arguments: char *algname, struct ipsec_alg *table
*
* Description: finds the ipsec algorithm value associated with the ipsec
* algorithm string.
*
* Returns: valid alg value on success, -1 on failure.
*/
int
{
return (-1);
}
/* no match */
return (-1);
}
/*
* Function: parse_algs
*
* Arguments: int which_alg, int alg, ipsec_req_t *ipsr
*
* Description: sets the values in the ipsec_req_t passed in based on
* the algorithm, and which protection scheme it belongs to (ah_auth,
* esp_auth, or esp_encr. SA is also passed through here as a sanity
* check measure, and because of the way the parsing routines are
* designed - the user specifies all this as part of a the properties
* of a single IPsec policy.
*
* Returns: valid alg value on success, -1 on failure.
*/
int
{
if (alg == -1)
/* alg is bad */
return (-1);
/* user didn't pass a pointer to set, alg is valid, OK */
return (0);
switch (which_alg) {
case ESP_ENCR_ALG:
if (alg == NO_ESP_AALG) {
ipsr->ipsr_esp_req = 0;
} else {
ipsr->ipsr_esp_req =
}
break;
case ESP_AUTH_ALG:
if (alg == NO_ESP_AALG) {
ipsr->ipsr_esp_req = 0;
} else {
ipsr->ipsr_esp_req =
/* Let the user specify NULL encryption implicitly. */
}
break;
case AH_AUTH_ALG:
if (alg == NO_AH_AALG) {
ipsr->ipsr_ah_req = 0;
} else {
ipsr->ipsr_ah_req =
}
break;
case SA_ALG:
if ((alg != SADB_SA_SHARED) &&
(alg != SADB_SA_UNIQUE))
return (-1);
break;
default:
/* don't know what to do! Fail. */
return (-1);
}
return (0);
}
/* ipsec algorithm parsing routines */
int
{
}
int
{
}
int
{
}
int
{
}
/*
* Function: isIPsecActionValid
*
* Parameters: action - the string containing the action in question.
*
* Description: Verifies the action is a valid ipsec action. Note that this
* function is NOT tollerant to leading whitespace!
*
* Returns: 0 on failure.
* strlen of the action on success (so the caller can index past it).
*/
isIPsecActionValid(char *action)
{
int i;
for (i = 0; validIPsecAction[i] != NULL; i++) {
/* match check */
strlen(validIPsecAction[i])) == 0)
return (strlen(validIPsecAction[i]));
/* try the next action */
}
return (0);
}
/*
* Function: parseIPsecProps
*
* Parameters: props - the string containing "{<props>}" for validation.
* ipsr - place to put parsed policy, NULL if not required.
* In this case parseIPsecProps() just tests to see
* if props are valid.
*
* Description: Verify properties are valid, and if so, put their values
* in the struct ipsec_req_t passed in. Valid properties are
* of the form "<tag> <alg>". Supported <tags> are in ipseccmd[],
* and the corresponding algs are in auth_algs[], and encr_algs[].
* Note: this function is tollerant to properties begining with
* blank spaces, but an open bracket MUST preceed <tag><alg>.
*
* Returns: 0 on failure in which case the values in ipsr are incomplete.
* number of bytes parsed on success in which case the values in ipsr,
* if passed in, are complete.
*/
int
{
if (p == NULL)
return (0);
freeP = p; /* strtok_r() is destructive */
/*
* What did strtok_r() return if we have " { <properties..."?
* Skip white-space in general. ^^^
*/
if ((*p != '\0') && (isspace(*p))) {
p = NULL;
continue;
}
if (!bopen_found) {
/* Every property begins with an open-bracket */
if (*p != '{') {
return (0);
}
/* move on */
p++;
}
if (*p == '}') {
/* this means we should be done */
if ((!bopen_found) || (bclose_found)) {
return (0);
}
p = NULL;
continue;
}
if (bclose_found) {
/* Stuff after the close! */
return (0);
}
/* once for each <tag> the user wants set */
/* valid <tag>? */
/* <alg> follows <tag>> */
p = NULL;
if (p == NULL) {
/* nothing follows <tag> = error */
return (0);
}
/* last <alg> may have a "}" at the end */
if (bclose_found) {
/* already found one = fail */
return (0);
}
/* char shortcuts are cool */
ioff = 1;
}
/*
* Call the parse command for this <alg>, but
* only if we're filling in the ipsec_req_t.
*/
/* make sure it's valid in context */
else
/* also parse it into ipsr */
if (ret < 0) {
/* the parse command failed */
return (0);
} else {
/* how far have we've come */
/* parsed->next */
p = NULL;
break;
}
}
}
/* cmd->c_func = NULL, next alg */
p = NULL;
}
/* calculate how many bytes we've parsed */
/* finished with this */
/* reset the per-policy parsing boolean */
/* as long as we got to a valid close bracket, we're fine */
if (!bclose_found)
return (0);
return (bytes_parsed);
}
/*
* Function:isIPsecPolicyValid
*
* Arguments: policy what the user is trying to set as policy properties.
*
* Description: This function validates an IPSec policy. The policy MUST be
* a single valid action, followed by a valid set of properties
* as specified by ipsec(7P). Note that we don't necessarily
* support all the actions that ipsec supports, see
* validIPsecActions[].
*
* Returns: _B_TRUE if the policy is valid, _B_FALSE if the policy is not.
*
* Note: this function only exists because ipSec has no API at this time.
*/
{
int c_len = 0;
char *cp;
return (_B_FALSE);
/* Parse the policy */
/* actions first */
return (_B_FALSE);
cp++;
/* now "{<properties>}" */
return (_B_FALSE);
/* trailing blanks are OK... */
cp++;
/* ...but nothing else! */
return (*cp == '\0');
}