/* ** Copyright (C) 2006-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ /* ** Add your description here ** */ #define DECLARE_FILEFORMAT_VARIABLES 1 #define DEFINE_FILEFORMAT_VARIABLES 1 #define DEFINE_SITE_VARIABLES 1 #include "silk.h" RCSIDENT("$SiLK: sksite.c 7800 2007-07-06 15:32:43Z mthomas $"); #include "sksite.h" #include "sksiteconfig.h" #include "utils.h" #include "skvector.h" #define SILK_DATA_ROOTDIR_ENVVAR "SILK_DATA_ROOTDIR" #define SILK_CONFIG_FILE_ENVVAR "SILK_CONFIG_FILE" #define SILK_CONFIG_FILE_NAME "silk.conf" #define SILK_DEFAULT_PATH_FORMAT "%T/%Y/%m/%d/%x" static char data_rootdir[PATH_MAX]; static char silk_config_file[PATH_MAX]; static char path_format[PATH_MAX]; /* If TEST_SITE is defined; some macros are redefined as functions */ /* #define TEST_SITE 1 */ /** Local Datatypes ***************************************************/ typedef struct { /* the sensor's id--must be its position in the array */ sensorID_t sn_id; /* unique name for this sensor */ const char *sn_name; /* length of the name */ size_t sn_name_strlen; /* vector of classes it belongs to */ sk_vector_t *sn_class_list; } sensor_struct_t; typedef struct { /* the group's id--must be its position in the array */ sensorgroupID_t sg_id; /* unique name for this group */ const char *sg_name; /* length of the name */ size_t sg_name_strlen; /* vector of sensors in this group */ sk_vector_t *sg_sensor_list; } sensorgroup_struct_t; typedef struct { /* the class's id--must be its position in the array */ classID_t cl_id; /* unique name for this class */ const char *cl_name; /* length of the name */ size_t cl_name_strlen; /* vector of sensors in class */ sk_vector_t *cl_sensor_list; /* vector of flowtypes in class */ sk_vector_t *cl_flowtype_list; /* vector of class's default flowtypes */ sk_vector_t *cl_default_flowtype_list; } class_struct_t; typedef struct { /* the flowtype's id--must be its position in the array */ flowtypeID_t ft_id; /* unique name for this flowtype */ const char *ft_name; /* length of name */ size_t ft_name_strlen; /* the class ID */ classID_t ft_class; /* unique name for this flowtype within its class */ const char *ft_type; /* length of type */ size_t ft_type_strlen; } flowtype_struct_t; typedef struct _fileformat_struct { /* the output format's id--must be its position in the array */ fileFormat_t ff_id; /* unique name of this output format */ const char *ff_name; } fileformat_struct_t; typedef struct _compmethod_struct { /* the compression method's id--must be its position in the array */ sk_compmethod_t cm_id; /* unique name of this compression method */ const char *cm_name; } compmethod_struct_t; static struct _fileformat_list { fileformat_struct_t *fl_list; uint8_t fl_count; } fileformats; static struct _compmethod_list { compmethod_struct_t *cml_list; sk_compmethod_t cml_count; } compmethods; /** Options ***********************************************************/ typedef enum { OPT_SITE_CONFIG_FILE } siteOptionsEnum; /* switch */ static struct option siteOptions[] = { {"site-config-file", REQUIRED_ARG, 0, OPT_SITE_CONFIG_FILE}, {0,0,0,0} /* sentinel */ }; /** Config Storage ****************************************************/ #define MIN_FIELD_SIZE 3 #define INVALID_LABEL "?" /* flags the caller passed to sksiteOptionsRegister() */ static uint32_t site_opt_flags = 0; /* 0 if not yet configured, 1 if configuration succeeded, -1 if it * failed due to parse errors. Calling sksiteConfigure() with a * non-existent file does not change its value */ static int configured = 0; /* The list of sensors, plus the max field and max known ID. * Other types are broken down similarly. */ static sk_vector_t *sensor_list; /* sensor_struct_t * */ static size_t sensor_max_name_strlen = MIN_FIELD_SIZE; static int sensor_max_id = -1; /* Default class for fglob. */ static classID_t default_class = SK_INVALID_CLASS; static sk_vector_t *class_list; /* class_struct_t * */ static size_t class_max_name_strlen = MIN_FIELD_SIZE; static int class_max_id = -1; static sk_vector_t *sensorgroup_list; /* sensorgroup_struct_t * */ static size_t sensorgroup_max_name_strlen = MIN_FIELD_SIZE; static int sensorgroup_max_id = -1; static sk_vector_t *flowtype_list; /* flowtype_struct_t * */ static size_t flowtype_max_name_strlen = MIN_FIELD_SIZE; static size_t flowtype_max_type_strlen = MIN_FIELD_SIZE; static int flowtype_max_id = -1; /** Local Function Prototypes *****************************************/ static int _siteOptionsHandler(clientData cData, int opt_index, char *opt_arg); static int _siteInitializeFileformats(size_t sz); static fileFormat_t _siteFileformatAdd(const char *name, uint8_t id); #ifdef TEST_SITE static uint8_t _siteGetFileformatCount(void); static const char *_siteFileformatGetNameFast(fileFormat_t ffid); static const char *_siteFileformatGetName(fileFormat_t ffid); #else /* TEST_SITE */ #define _siteGetFileformatCount() \ (fileformats.fl_count) #define _siteFileformatGetNameFast(ffid) \ (fileformats.fl_list[(ffid)].ff_name) #define _siteFileformatGetName(ffid) \ (((ffid) >= _siteGetFileformatCount()) \ ? NULL \ : _siteFileformatGetNameFast(ffid)) #endif /* TEST_SITE */ static int _siteInitializeCompmethods(size_t sz); static sk_compmethod_t _siteCompmethodAdd(const char *name, uint8_t id); #ifdef TEST_SITE static uint8_t _siteGetCompmethodCount(void); static const char *_siteCompmethodGetNameFast(sk_compmethod_t cmid); static const char *_siteCompmethodGetName(sk_compmethod_t cmid); #else /* TEST_SITE */ #define _siteGetCompmethodCount() \ (compmethods.cml_count) #define _siteCompmethodGetNameFast(cmid) \ (compmethods.cml_list[(cmid)].cm_name) #define _siteCompmethodGetName(cmid) \ (((cmid) >= _siteGetCompmethodCount()) \ ? NULL \ : _siteCompmethodGetNameFast(cmid)) #endif /* TEST_SITE */ static void _siteSensorFree( sensor_struct_t *sn); static void _siteClassFree( class_struct_t *cl); static void _siteSensorgroupFree( sensorgroup_struct_t *sg); static void _siteFlowtypeFree( flowtype_struct_t *ft); /**********************************************************************/ int sksiteInitialize( int UNUSED(levels)) { static int initialized = 0; uint8_t i; uint8_t j; size_t numFormats; size_t numCompr; const char *silk_data_rootdir_env; int silk_data_rootdir_set = 0; const char *silk_config_file_env; if (initialized) { return 0; } initialized = 1; /* store the root_directory from configure, or the env var if given */ silk_data_rootdir_env = getenv(SILK_DATA_ROOTDIR_ENVVAR); if ( silk_data_rootdir_env ) { /* env var is defined, is it instead */ while ( isspace((int)*silk_data_rootdir_env) ) { silk_data_rootdir_env++; } if ( *silk_data_rootdir_env ) { if ( sksiteSetRootDir(silk_data_rootdir_env) ) { skAppPrintErr("Problem setting data root directory " "from environment"); abort(); } silk_data_rootdir_set = 1; } } if ( !silk_data_rootdir_set ) { if ( sksiteSetRootDir(SILK_DATA_ROOTDIR) ) { skAppPrintErr("Data root directory is too long"); abort(); } } silk_config_file_env = getenv(SILK_CONFIG_FILE_ENVVAR); if ( silk_config_file_env ) { while ( isspace((int)*silk_config_file_env) ) { silk_config_file_env++; } if ( *silk_config_file_env ) { if ( sksiteSetConfigPath(silk_config_file_env) ) { skAppPrintErr("Problem setting config file from environment"); abort(); } } } /* compute number of file formats: FT_* macros; if the final entry * in the array is the empty string; remove it from format * count. */ numFormats = (sizeof(fileOutputFormats)/sizeof(char*)); if (fileOutputFormats[numFormats-1][0] == '\0') { --numFormats; } _siteInitializeFileformats(numFormats); /* loop over fileOutputFormats[] and create the file formats */ for (i = 0; i < numFormats && fileOutputFormats[i][0]; ++i) { _siteFileformatAdd(fileOutputFormats[i], i); } if (_siteGetFileformatCount() != numFormats) { skAppPrintErr("Inconsistency in fileOutputFormats[] array.\n" "\tFix your site header and recompile. Abort!"); assert(_siteGetFileformatCount() == numFormats); abort(); } /* compute number of compression methods: SK_COMPMETHOD_* macros; * if the final entry in the array is the empty string; remove it * from method count. */ numCompr = (sizeof(skCompressionMethods)/sizeof(char*)); if (skCompressionMethods[numCompr-1][0] == '\0') { --numCompr; } _siteInitializeCompmethods(numCompr); /* loop over skCompressionMethods[] to create the compr methods */ for (j = 0; j < numCompr && skCompressionMethods[j][0]; ++j) { _siteCompmethodAdd(skCompressionMethods[j], j); } if (_siteGetCompmethodCount() != numCompr) { skAppPrintErr("Inconsistency in skCompressionMethods[] array.\n" "\tFix your site header and recompile. Abort!"); assert(_siteGetCompmethodCount() == numCompr); abort(); } /* Basic initialization of site config data structures */ strncpy(path_format, SILK_DEFAULT_PATH_FORMAT, sizeof(path_format)); sensor_list = skVectorNew(sizeof(sensor_struct_t *)); class_list = skVectorNew(sizeof(class_struct_t *)); sensorgroup_list = skVectorNew(sizeof(sensorgroup_struct_t *)); flowtype_list = skVectorNew(sizeof(flowtype_struct_t *)); return 0; } int sksiteOptionsRegister(uint32_t flags) { site_opt_flags = flags; /* Add a --site-config-file option if requested */ if (site_opt_flags & SK_SITE_FLAG_CONFIG_FILE) { if (optionsRegister(siteOptions, (optHandler)_siteOptionsHandler,NULL)) { return -1; } } return 0; } void sksiteOptionsUsage( FILE *fh) { if (site_opt_flags & SK_SITE_FLAG_CONFIG_FILE) { fprintf(fh, ("--%s %s. Location of the site configuration file.\n" "\tDef. $%s or $%s/silk.conf\n"), siteOptions[OPT_SITE_CONFIG_FILE].name, SK_OPTION_HAS_ARG(siteOptions[OPT_SITE_CONFIG_FILE]), SILK_CONFIG_FILE_ENVVAR, SILK_DATA_ROOTDIR_ENVVAR); } } static int _siteOptionsHandler( clientData UNUSED(cData), int opt_index, char *opt_arg) { switch ((siteOptionsEnum)opt_index) { case OPT_SITE_CONFIG_FILE: assert(site_opt_flags & SK_SITE_FLAG_CONFIG_FILE); if (sksiteSetConfigPath(opt_arg)) { skAppPrintErr("Problem setting %s to '%s': name too long", siteOptions[opt_index].name, opt_arg); return 1; } break; } return 0; } int sksiteConfigure( int verbose) { int rv = 0; if (configured != 0) { rv = ((configured == -1) ? -1 : 0); } else { /* Configuration hasn't happened yet. Attempt configuration. */ const char *config_path = sksiteGetConfigPath(); if ( !(config_path && config_path[0] && fileExists(config_path))) { /* Missing file---do not modify configured */ rv = -2; if (verbose) { skAppPrintErr("Site configuration file not found"); } } else { if ( sksiteconfigParse(config_path, verbose) ) { /* Failed */ configured = -1; } else { /* Success */ configured = 1; } rv = ((configured == -1) ? -1 : 0); } } return rv; } int sksiteSetConfigPath( const char *filename) { if ( strlen(filename) >= sizeof(silk_config_file) ) { return -1; /* Too long */ } else { strncpy(silk_config_file, filename, sizeof(silk_config_file)); } return 0; } const char *sksiteGetConfigPath( void) { if ( silk_config_file[0] == '\0' ) { /* Config file path has not been set, give default */ unsigned int len; len = snprintf(silk_config_file, sizeof(silk_config_file), "%s/%s", data_rootdir, SILK_CONFIG_FILE_NAME); if ( len > (sizeof(silk_config_file) - 1) ) { skAppPrintErr("Config file path is too long"); abort(); } /* Not in data rootdir, try SILK_PATH */ if (!fileExists(silk_config_file)) { char path[PATH_MAX]; if (skFindFile(SILK_CONFIG_FILE_NAME, path, sizeof(path), 0)) { strncpy(silk_config_file, path, sizeof(silk_config_file)); if (silk_config_file[sizeof(silk_config_file)-1]) { skAppPrintErr("Config file path is too long"); exit(EXIT_FAILURE); } } } } /* Config file path has been set explicitly or implicitly */ return silk_config_file; } void sksiteTeardown(void) { static int teardown = 0; size_t count; size_t i; if (teardown) { return; } teardown = 1; if (fileformats.fl_list) { free(fileformats.fl_list); fileformats.fl_list = NULL; } if (compmethods.cml_list) { free(compmethods.cml_list); compmethods.cml_list = NULL; } if (class_list) { class_struct_t *cl; count = skVectorGetCount(class_list); for (i = 0; i < count; ++i) { skVectorGetValue(&cl, class_list, i); _siteClassFree(cl); } skVectorDestroy(class_list); } if (flowtype_list) { flowtype_struct_t *ft; count = skVectorGetCount(flowtype_list); for (i = 0; i < count; ++i) { skVectorGetValue(&ft, flowtype_list, i); _siteFlowtypeFree(ft); } skVectorDestroy(flowtype_list); } if (sensorgroup_list) { sensorgroup_struct_t *sg; count = skVectorGetCount(sensorgroup_list); for (i = 0; i < count; ++i) { skVectorGetValue(&sg, sensorgroup_list, i); _siteSensorgroupFree(sg); } skVectorDestroy(sensorgroup_list); } if (sensor_list) { sensor_struct_t *sn; count = skVectorGetCount(sensor_list); for (i = 0; i < count; ++i) { skVectorGetValue(&sn, sensor_list, i); _siteSensorFree(sn); } skVectorDestroy(sensor_list); } } /** Iterators *********************************************************/ int sksiteSensorIteratorNext( sensor_iter_t *iter, sensorID_t *out_sensor_id) { sensor_struct_t *sn = NULL; if ( iter->si_vector == NULL ) { return 0; } if ( iter->si_contains_pointers ) { while ( sn == NULL ) { if ( skVectorGetValue(&sn, iter->si_vector, iter->si_index) ) { return 0; } if ( sn == NULL ) { iter->si_index++; } } *out_sensor_id = sn->sn_id; iter->si_index++; return 1; } else { if ( skVectorGetValue(out_sensor_id, iter->si_vector, iter->si_index) ) { return 0; } iter->si_index++; return 1; } } int sksiteClassIteratorNext( class_iter_t *iter, classID_t *out_class_id) { class_struct_t *cl = NULL; if ( iter->ci_vector == NULL ) { return 0; } if ( iter->ci_contains_pointers ) { while ( cl == NULL ) { if ( skVectorGetValue(&cl, iter->ci_vector, iter->ci_index) ) { return 0; } if ( cl == NULL ) { iter->ci_index++; } } *out_class_id = cl->cl_id; iter->ci_index++; return 1; } else { if ( skVectorGetValue(out_class_id, iter->ci_vector, iter->ci_index) ) { return 0; } iter->ci_index++; return 1; } } int sksiteSensorgroupIteratorNext( sensorgroup_iter_t *iter, sensorgroupID_t *out_group_id) { sensorgroup_struct_t *sg = NULL; if ( iter->gi_vector == NULL ) { return 0; } if ( iter->gi_contains_pointers ) { while ( sg == NULL ) { if ( skVectorGetValue(&sg, iter->gi_vector, iter->gi_index) ) { return 0; } if ( sg == NULL ) { iter->gi_index++; } } *out_group_id = sg->sg_id; iter->gi_index++; return 1; } else { if ( skVectorGetValue(out_group_id, iter->gi_vector, iter->gi_index) ) { return 0; } iter->gi_index++; return 1; } } int sksiteFlowtypeIteratorNext( flowtype_iter_t *iter, flowtypeID_t *out_flowtype_id) { flowtype_struct_t *ft = NULL; if ( iter->fi_vector == NULL ) { return 0; } if ( iter->fi_contains_pointers ) { if ( skVectorGetValue(&ft, iter->fi_vector, iter->fi_index) ) { return 0; } *out_flowtype_id = ft->ft_id; iter->fi_index++; return 1; } else { if ( skVectorGetValue(out_flowtype_id, iter->fi_vector, iter->fi_index) ) { return 0; } iter->fi_index++; return 1; } } /** Sensors ***********************************************************/ int sksiteSensorCreate( sensorID_t sensor_id, const char *sensor_name) { sensor_struct_t *sn = NULL; size_t l = skVectorGetCapacity(sensor_list); if ( sensor_id >= SK_MAX_NUM_SENSORS ) { return -1; } if ( sksiteSensorNameIsLegal(sensor_name) != 0 ) { return -1; } if ( sksiteSensorExists(sensor_id) ) { return -1; } if ( sensor_id >= l ) { if ( skVectorSetCapacity(sensor_list, sensor_id + 1) ) { goto alloc_error; } } sn = (sensor_struct_t *) calloc(1, sizeof(sensor_struct_t)); if ( sn == NULL ) { goto alloc_error; } sn->sn_name = strdup(sensor_name); sn->sn_class_list = skVectorNew(sizeof(classID_t)); if ( (sn->sn_name == NULL) || (sn->sn_class_list == NULL) ) { goto alloc_error; } sn->sn_id = sensor_id; sn->sn_name_strlen = strlen(sensor_name); if ( sn->sn_name_strlen > sensor_max_name_strlen ) { sensor_max_name_strlen = sn->sn_name_strlen; } if ( sensor_id > sensor_max_id ) { sensor_max_id = sensor_id; } if ( skVectorSetValue(sensor_list, sensor_id, &sn) ) { goto alloc_error; } return 0; alloc_error: _siteSensorFree(sn); return -1; } /* * _siteSensorFree(sn); * * Free all memory associated with the Sensor 'sn'; 'sn' may be * NULL. */ static void _siteSensorFree( sensor_struct_t *sn) { if ( sn != NULL ) { if ( sn->sn_class_list != NULL ) { skVectorDestroy(sn->sn_class_list); } if ( sn->sn_name != NULL ) { free((char*)sn->sn_name); } free(sn); } } sensorID_t sksiteSensorLookup( const char *sensor_name) { sensorID_t id; sensor_struct_t *sn; for ( id = 0; !skVectorGetValue(&sn, sensor_list, id); id++ ) { if ( (sn != NULL) && (strcmp(sn->sn_name, sensor_name) == 0) ) { return id; } } return SK_INVALID_SENSOR; } int sksiteSensorExists( sensorID_t sensor_id) { sensor_struct_t *sn; if ( skVectorGetValue(&sn, sensor_list, sensor_id) ) { return 0; } if ( NULL == sn ) { return 0; } return 1; } sensorID_t sksiteSensorGetMaxID( void) { return sensor_max_id; } size_t sksiteSensorGetMaxNameStrLen( void) { return sensor_max_name_strlen; } int sksiteSensorGetName( char *buffer, size_t buffer_size, sensorID_t sensor_id) { sensor_struct_t *sn; if ( sensor_id == SK_INVALID_SENSOR ) { /* Invalid sensor, give message */ return snprintf(buffer, buffer_size, "%s", INVALID_LABEL); } else if ( skVectorGetValue(&sn, sensor_list, sensor_id) || (NULL == sn) ) { /* Unknown sensor, give numeric value */ return snprintf(buffer, buffer_size, "%u", sensor_id); } else { /* Known sensor, give name */ return snprintf(buffer, buffer_size, "%s", sn->sn_name); } } int sksiteIsSensorInClass( sensorID_t sensor_id, classID_t class_id) { class_iter_t ci; classID_t check_id; sksiteSensorClassIterator(sensor_id, &ci); while ( sksiteClassIteratorNext(&ci, &check_id) ) { if ( check_id == class_id ) { return 1; } } return 0; } void sksiteSensorIterator( sensor_iter_t *iter) { iter->si_index = 0; iter->si_vector = sensor_list; iter->si_contains_pointers = 1; } void sksiteSensorClassIterator( sensorID_t sensor_id, class_iter_t *iter) { sensor_struct_t *sn; if ( skVectorGetValue(&sn, sensor_list, sensor_id) ) { iter->ci_vector = NULL; return; } iter->ci_index = 0; iter->ci_vector = sn->sn_class_list; iter->ci_contains_pointers = 0; } int sksiteSensorNameIsLegal( const char *name) { size_t len; const char *cp; /* check length; should be between 1 and SK_MAX_STRLEN_SENSOR */ len = strlen(name); if (len < 1) { /* skAppPrintErr("Sensor name must contain at least 1 character"); */ return -2; } if (len > SK_MAX_STRLEN_SENSOR) { /*skAppPrintErr("Sensor name can contain no more than %d characters", * SK_MAX_STRLEN_SENSOR); */ return -3; } /* check for bad characters */ for (cp = name; *cp; ++cp) { if (isspace((int)*cp)) { return (1 + cp - name); /*skAppPrintErr("Sensor name cannot contain whitespace characters"); *return 1; */ } if (('/' == *cp) || ('_' == *cp)) { return (1 + cp - name); /*skAppPrintErr("Sensor name contains illegal character '%c'", * *cp); *return 1; */ } } /* check that begins with a letter */ if ( !isalpha((int)*name)) { /* skAppPrintErr("Sensors must begin with a letter"); */ return -1; } return 0; } int sksiteSensorGetClassCount( sensorID_t sensor_id) { sensor_struct_t *sn; if ( skVectorGetValue(&sn, sensor_list, sensor_id) ) { return 0; } return skVectorGetCount(sn->sn_class_list); } /** Classes ***********************************************************/ int sksiteClassCreate( classID_t class_id, const char *class_name) { class_struct_t *cl = NULL; size_t l = skVectorGetCapacity(class_list); if ( class_id >= SK_MAX_NUM_CLASSES ) { return -1; } if ( sksiteClassExists(class_id) ) { return -1; } if ( class_id >= l ) { if ( skVectorSetCapacity(class_list, class_id + 1) ) { goto alloc_error; } } cl = (class_struct_t *) calloc(1, sizeof(class_struct_t)); if ( cl == NULL ) { goto alloc_error; } cl->cl_name = strdup(class_name); cl->cl_sensor_list = skVectorNew(sizeof(sensorID_t)); cl->cl_flowtype_list = skVectorNew(sizeof(flowtypeID_t)); cl->cl_default_flowtype_list = skVectorNew(sizeof(flowtypeID_t)); if ( (cl->cl_name == NULL) || (cl->cl_sensor_list == NULL) || (cl->cl_flowtype_list == NULL) || (cl->cl_default_flowtype_list == NULL ) ) { goto alloc_error; } cl->cl_id = class_id; cl->cl_name_strlen = strlen(class_name); if ( cl->cl_name_strlen > class_max_name_strlen ) { class_max_name_strlen = cl->cl_name_strlen; } if ( class_id > class_max_id ) { class_max_id = class_id; } if ( skVectorSetValue(class_list, class_id, &cl) ) { goto alloc_error; } return 0; alloc_error: _siteClassFree(cl); return -1; } /* * _siteClassFree(sg); * * Free all memory associated with the Class 'cl'; 'cl' may * be NULL. Does not free any sensors or flowtypes. */ static void _siteClassFree( class_struct_t *cl) { if ( cl != NULL ) { if ( cl->cl_default_flowtype_list != NULL ) { skVectorDestroy(cl->cl_default_flowtype_list); } if ( cl->cl_flowtype_list != NULL ) { skVectorDestroy(cl->cl_flowtype_list); } if ( cl->cl_sensor_list != NULL ) { skVectorDestroy(cl->cl_sensor_list); } if ( cl->cl_name != NULL ) { free((char*)cl->cl_name); } free(cl); } } int sksiteClassSetDefault( classID_t class_id) { default_class = class_id; return 0; } classID_t sksiteClassGetDefault( void) { return default_class; } classID_t sksiteClassLookup( const char *class_name) { classID_t id; class_struct_t *cl; for ( id = 0; !skVectorGetValue(&cl, class_list, id); id++ ) { if ( (cl != NULL) && (strcmp(cl->cl_name, class_name) == 0) ) { return id; } } return SK_INVALID_CLASS; } int sksiteClassExists( classID_t class_id) { class_struct_t *cl; if ( skVectorGetValue(&cl, class_list, class_id) ) { return 0; } if ( NULL == cl ) { return 0; } return 1; } classID_t sksiteClassGetMaxID( void) { return class_max_id; } size_t sksiteClassGetMaxNameStrLen( void) { return class_max_name_strlen; } int sksiteClassGetName( char *buffer, size_t buffer_size, classID_t class_id) { class_struct_t *cl; if ( class_id == SK_INVALID_CLASS ) { /* Invalid class, give message */ return snprintf(buffer, buffer_size, "%s", INVALID_LABEL); } else if ( skVectorGetValue(&cl, class_list, class_id) || (NULL == cl) ) { /* Unknown class, give numeric value */ return snprintf(buffer, buffer_size, "%u", class_id); } else { /* Known value, print name */ return snprintf(buffer, buffer_size, "%s", cl->cl_name); } } int sksiteClassAddSensor( classID_t class_id, sensorID_t sensor_id) { int i; class_struct_t *cl; sensor_struct_t *sn; sensorID_t id; if ( skVectorGetValue(&cl, class_list, class_id) ) { return -1; /* Invalid class_id */ } if ( NULL == cl ) { return -1; /* Invalid class_id */ } if ( skVectorGetValue(&sn, sensor_list, sensor_id) ) { return -1; /* Invalid sensor_id */ } if ( NULL == sn ) { return -1; /* Invalid sensor_id */ } for ( i = 0; !skVectorGetValue(&id, cl->cl_sensor_list, i); i++ ) { if ( id == sensor_id ) { return 0; } } /* XXX Recover and not add to class list either? */ if ( skVectorAppendValue(sn->sn_class_list, &class_id) ) { return -1; } if ( skVectorAppendValue(cl->cl_sensor_list, &sensor_id) ) { return -1; } return 0; } int sksiteClassAddSensorgroup( classID_t class_id, sensorgroupID_t group_id) { int i; class_struct_t *cl; sensorgroup_struct_t *sg; sensorID_t id; if ( skVectorGetValue(&cl, class_list, class_id) ) { return -1; /* Invalid class_id */ } if ( NULL == cl ) { return -1; /* Invalid class_id */ } if ( skVectorGetValue(&sg, sensorgroup_list, group_id) ) { return -1; /* Invalid group_id */ } if ( NULL == sg ) { return -1; /* Invalid group_id */ } for ( i = 0; !skVectorGetValue(&id, sg->sg_sensor_list, i); i++ ) { if ( sksiteClassAddSensor(class_id, id) ) { return -1; } } return 0; } void sksiteClassIterator( class_iter_t *iter) { iter->ci_index = 0; iter->ci_vector = class_list; iter->ci_contains_pointers = 1; } void sksiteClassSensorIterator( classID_t class_id, sensor_iter_t *iter) { class_struct_t *cl; if ( skVectorGetValue(&cl, class_list, class_id) ) { iter->si_vector = NULL; return; } iter->si_index = 0; iter->si_vector = cl->cl_sensor_list; iter->si_contains_pointers = 0; } void sksiteClassFlowtypeIterator( classID_t class_id, flowtype_iter_t *iter) { class_struct_t *cl; if ( skVectorGetValue(&cl, class_list, class_id) ) { iter->fi_vector = NULL; return; } iter->fi_index = 0; iter->fi_vector = cl->cl_flowtype_list; iter->fi_contains_pointers = 0; } void sksiteClassDefaultFlowtypeIterator( flowtypeID_t class_id, flowtype_iter_t *iter) { class_struct_t *cl; if ( skVectorGetValue(&cl, class_list, class_id) ) { iter->fi_vector = NULL; return; } iter->fi_index = 0; iter->fi_vector = cl->cl_default_flowtype_list; iter->fi_contains_pointers = 0; } int sksiteClassGetSensorCount( classID_t class_id) { class_struct_t *cl; if ( skVectorGetValue(&cl, class_list, class_id) ) { return 0; } return skVectorGetCount(cl->cl_sensor_list); } int sksiteClassAddDefaultFlowtype( classID_t class_id, flowtypeID_t flowtype_id) { int i; class_struct_t *cl; flowtype_struct_t *ft; flowtypeID_t id; if ( skVectorGetValue(&ft, flowtype_list, flowtype_id) ) { return -1; } if ( ft == NULL ) { return -1; } if ( skVectorGetValue(&cl, class_list, class_id) ) { return -1; } if ( cl == NULL ) { return -1; } if ( ft->ft_class != class_id ) { return -1; } for ( i = 0; !skVectorGetValue(&id, cl->cl_default_flowtype_list, i);i++ ) { if ( id == flowtype_id ) { return 0; } } if ( skVectorAppendValue(cl->cl_default_flowtype_list, &flowtype_id)) { return -1; } return 0; } /** Sensorgroups ******************************************************/ int sksiteSensorgroupCreate( sensorgroupID_t sensorgroup_id, const char *sensorgroup_name) { sensorgroup_struct_t *sg = NULL; size_t l = skVectorGetCapacity(sensorgroup_list); if ( sensorgroup_id >= SK_MAX_NUM_SENSORGROUPS ) { return -1; } if ( sensorgroup_id >= l ) { if ( skVectorSetCapacity(sensorgroup_list, sensorgroup_id + 1) ) { goto alloc_error; } } if ( sksiteSensorgroupLookup(sensorgroup_name) != SK_INVALID_SENSORGROUP) { return -1; } if ( sksiteSensorgroupExists(sensorgroup_id) ) { return -1; } sg = (sensorgroup_struct_t *) calloc(1, sizeof(sensorgroup_struct_t)); if ( sg == NULL ) { goto alloc_error; } sg->sg_name = strdup(sensorgroup_name); sg->sg_sensor_list = skVectorNew(sizeof(sensorID_t)); if ( (sg->sg_name == NULL) || (sg->sg_sensor_list == NULL) ) { goto alloc_error; } sg->sg_id = sensorgroup_id; sg->sg_name_strlen = strlen(sensorgroup_name); if ( sg->sg_name_strlen > sensorgroup_max_name_strlen ) { sensorgroup_max_name_strlen = sg->sg_name_strlen; } if ( sensorgroup_id > sensorgroup_max_id ) { sensorgroup_max_id = sensorgroup_id; } if ( skVectorSetValue(sensorgroup_list, sensorgroup_id, &sg) ) { goto alloc_error; } return 0; alloc_error: _siteSensorgroupFree(sg); return -1; } /* * _siteSensorgroupFree(sg); * * Free all memory associated with the Sensorgroup 'sg'; 'sg' may * be NULL. */ static void _siteSensorgroupFree( sensorgroup_struct_t *sg) { if ( sg != NULL ) { if ( sg->sg_sensor_list != NULL ) { skVectorDestroy(sg->sg_sensor_list); } if ( sg->sg_name != NULL ) { free((char *)sg->sg_name); } free(sg); } } sensorgroupID_t sksiteSensorgroupLookup( const char *sensorgroup_name) { sensorgroupID_t id; sensorgroup_struct_t *sg; for ( id = 0; !skVectorGetValue(&sg, sensorgroup_list, id); id++ ) { if ( (sg != NULL) && (strcmp(sg->sg_name, sensorgroup_name) == 0) ) { return id; } } return SK_INVALID_SENSORGROUP; } int sksiteSensorgroupExists( sensorgroupID_t sensorgroup_id) { sensorgroup_struct_t *sg; if ( skVectorGetValue(&sg, sensorgroup_list, sensorgroup_id) ) { return 0; } if ( NULL == sg ) { return 0; } return 1; } sensorgroupID_t sksiteSensorgroupGetMaxID( void) { return sensorgroup_max_id; } size_t sksiteSensorgroupGetMaxNameStrLen( void) { return sensorgroup_max_name_strlen; } int sksiteSensorgroupGetName( char *buffer, size_t buffer_size, sensorgroupID_t group_id) { sensorgroup_struct_t *sg; if ( group_id == SK_INVALID_SENSORGROUP ) { /* Invalid group, give message */ return snprintf(buffer, buffer_size, "%s", INVALID_LABEL); } else if ( skVectorGetValue(&sg, sensorgroup_list, group_id) || (NULL == sg) ) { /* Unknown sensorgroup, give numeric value */ return snprintf(buffer, buffer_size, "%u", group_id); } else { /* Known sensorgroup, give name */ return snprintf(buffer, buffer_size, "%s", sg->sg_name); } } int sksiteSensorgroupAddSensor( sensorgroupID_t group_id, sensorID_t sensor_id) { int i; sensorgroup_struct_t *sg; sensor_struct_t *sn; sensorID_t id; if ( skVectorGetValue(&sg, sensorgroup_list, group_id) ) { return -1; /* Invalid group_id */ } if ( NULL == sg ) { return -1; /* Invalid group_id */ } if ( skVectorGetValue(&sn, sensor_list, sensor_id) ) { return -1; /* Invalid sensor_id */ } if ( NULL == sn ) { return -1; /* Invalid sensor_id */ } for ( i = 0; !skVectorGetValue(&id, sg->sg_sensor_list, i); i++ ) { if ( id == sensor_id ) { return 0; /* Already there */ } } if ( skVectorAppendValue(sg->sg_sensor_list, &sensor_id) ) { return -1; /* Memory failure */ } return 0; } int sksiteSensorgroupAddSensorgroup( sensorgroupID_t dest, sensorgroupID_t src) { int i; sensorgroup_struct_t *sg_src; sensorgroup_struct_t *sg_dest; sensorID_t id; if ( skVectorGetValue(&sg_src, sensorgroup_list, src) ) { return -1; /* Invalid source group_id */ } if ( NULL == sg_src ) { return -1; /* Invalid source group_id */ } if ( skVectorGetValue(&sg_dest, sensorgroup_list, dest) ) { return -1; /* Invalid dest group_id */ } if ( NULL == sg_dest ) { return -1; /* Invalid dest group_id */ } for ( i = 0; skVectorGetValue(&id, sg_src->sg_sensor_list, i); i++ ) { if ( sksiteSensorgroupAddSensor(dest, id) ) { return -1; } } return 0; } void sksiteSensorgroupIterator( sensorgroup_iter_t *iter) { iter->gi_index = 0; iter->gi_vector = sensorgroup_list; iter->gi_contains_pointers = 1; } void sksiteSensorgroupSensorIterator( sensorgroupID_t group_id, sensorgroup_iter_t *iter) { sensorgroup_struct_t *sg; if ( skVectorGetValue(&sg, sensorgroup_list, group_id) ) { iter->gi_vector = NULL; return; } iter->gi_index = 0; iter->gi_vector = sg->sg_sensor_list; iter->gi_contains_pointers = 0; } /** Flowtypes *********************************************************/ int sksiteFlowtypeCreate( flowtypeID_t flowtype_id, const char *flowtype_name, classID_t class_id, const char *type_name) /* const char *prefix, fileFormat_t file_format, fileVersion_t file_version, */ { flowtype_struct_t *ft = NULL; class_struct_t *cl = NULL; size_t l = skVectorGetCapacity(flowtype_list); if ( skVectorGetValue(&cl, class_list, class_id) || (cl == NULL) ) { return -1; } if ( sksiteFlowtypeExists(flowtype_id) ) { return -1; } if ( flowtype_id >= SK_MAX_NUM_FLOWTYPES ) { return -1; } if ( sksiteFlowtypeLookup(flowtype_name) != SK_INVALID_FLOWTYPE ) { return -1; } if ( sksiteFlowtypeLookupByClassType(class_id, type_name) != SK_INVALID_FLOWTYPE ) { return -1; } if ( flowtype_id >= l ) { if ( skVectorSetCapacity(flowtype_list, flowtype_id + 1) ) { goto alloc_error; } } ft = (flowtype_struct_t *) calloc(1, sizeof(flowtype_struct_t)); if ( ft == NULL ) { goto alloc_error; } ft->ft_name = strdup(flowtype_name); ft->ft_type = strdup(type_name); if ( (ft->ft_name == NULL) ) { goto alloc_error; } ft->ft_class = class_id; ft->ft_name_strlen = strlen(flowtype_name); if ( ft->ft_name_strlen > flowtype_max_name_strlen ) { flowtype_max_name_strlen = ft->ft_name_strlen; } ft->ft_type_strlen = strlen(type_name); if ( ft->ft_type_strlen > flowtype_max_type_strlen ) { flowtype_max_type_strlen = ft->ft_type_strlen; } /* Now register it on the list */ if ( skVectorAppendValue(cl->cl_flowtype_list, &flowtype_id) ) { goto alloc_error; } if ( flowtype_id > flowtype_max_id ) { flowtype_max_id = flowtype_id; } if ( skVectorSetValue(flowtype_list, flowtype_id, &ft) ) { goto alloc_error; } return 0; alloc_error: _siteFlowtypeFree(ft); return -1; } /* * _siteFlowtypeFree(sg); * * Free all memory associated with the Flowtype 'ft'; 'ft' may * be NULL. */ static void _siteFlowtypeFree( flowtype_struct_t *ft) { if ( ft != NULL ) { if ( ft->ft_name != NULL ) { free((char*)ft->ft_name); } if ( ft->ft_type != NULL ) { free((char*)ft->ft_type); } free(ft); } } flowtypeID_t sksiteFlowtypeLookup( const char *flowtype_name) { flowtypeID_t id; flowtype_struct_t *ft; for ( id = 0; !skVectorGetValue(&ft, flowtype_list, id); id++ ) { if ((ft != NULL) && (strcmp(ft->ft_name, flowtype_name) == 0) ) { return id; } } return SK_INVALID_FLOWTYPE; } flowtypeID_t sksiteFlowtypeLookupByClassType( classID_t class_id, const char *type) { flowtype_struct_t *ft; flowtype_iter_t iter; flowtypeID_t id; if ( type == NULL ) { return SK_INVALID_FLOWTYPE; } sksiteClassFlowtypeIterator(class_id, &iter); while ( sksiteFlowtypeIteratorNext(&iter, &id) ) { if ( !skVectorGetValue(&ft, flowtype_list, id) ) { if ( (ft != NULL) && (strcmp(ft->ft_type, type) == 0) ) { return id; } } } /* not found */ return SK_INVALID_FLOWTYPE; } int sksiteFlowtypeExists( flowtypeID_t flowtype_id) { flowtype_struct_t *ft; if ( skVectorGetValue(&ft, flowtype_list, flowtype_id) ) { return 0; } if ( NULL == ft ) { return 0; } return 1; } flowtypeID_t sksiteFlowtypeGetMaxID( void) { return flowtype_max_id; } classID_t sksiteFlowtypeGetClass( flowtypeID_t flowtype_id) { flowtype_struct_t *ft; if ( skVectorGetValue(&ft, flowtype_list, flowtype_id) ) { return SK_INVALID_CLASS; } return ft->ft_class; } size_t sksiteFlowtypeGetMaxNameStrLen( void) { return flowtype_max_name_strlen; } int sksiteFlowtypeGetName( char *buffer, size_t buffer_size, flowtypeID_t flowtype_id) { flowtype_struct_t *ft; if ( flowtype_id == SK_INVALID_FLOWTYPE ) { /* Invalid flowtype, give message */ return snprintf(buffer, buffer_size, "%s", INVALID_LABEL); } else if ( skVectorGetValue(&ft, flowtype_list, flowtype_id) || (NULL == ft) ) { /* Unknown flowtype, give numeric value */ return snprintf(buffer, buffer_size, "%u", flowtype_id); } else { /* Known filetype, give name */ return snprintf(buffer, buffer_size, "%s", ft->ft_name); } } size_t sksiteFlowtypeGetMaxTypeStrLen( void) { return flowtype_max_type_strlen; } int sksiteFlowtypeGetType( char *buffer, size_t buffer_size, flowtypeID_t flowtype_id) { flowtype_struct_t *ft; if ( skVectorGetValue(&ft, flowtype_list, flowtype_id) || (NULL == ft) ) { /* Unknown flowtype, give numeric flowtype value */ return snprintf(buffer, buffer_size, "%u", flowtype_id); } else { /* Known flowtype, give string flowtype value */ return snprintf(buffer, buffer_size, "%s", ft->ft_type); } } void sksiteFlowtypeAssert( flowtypeID_t flowtype_id, const char *class_name, const char *type) { classID_t class_id = SK_INVALID_CLASS; flowtypeID_t check_id = SK_INVALID_FLOWTYPE; class_id = sksiteClassLookup(class_name); if ( class_id == SK_INVALID_CLASS ) { goto FAIL_ASSERT; } check_id = sksiteFlowtypeLookupByClassType(class_id, type); if ( check_id == SK_INVALID_FLOWTYPE ) { goto FAIL_ASSERT; } if ( check_id != flowtype_id ) { goto FAIL_ASSERT; } /* all is well */ return; FAIL_ASSERT: #define ERRMSG \ "Packing logic in 'probeconf-" SILK_SITE ".c' does not match site\n" \ "\tconfiguration file '%s':\n" if ( class_id == SK_INVALID_CLASS ) { skAppPrintErr((ERRMSG "\tClass '%s' does not exist"), silk_config_file, class_name); } else if ( check_id == SK_INVALID_FLOWTYPE ) { skAppPrintErr((ERRMSG "\tNo flowtype for class '%s' type '%s' exists"), silk_config_file, class_name, type); } else if ( check_id != flowtype_id ) { skAppPrintErr((ERRMSG "\tFlowtype for class '%s' type '%s' (%d) does " "not have ID '%d'"), silk_config_file, class_name, type, check_id, flowtype_id); } abort(); #undef ERRMSG } /** Compatibility Functions *******************************************/ int sksiteCreateTemporarySensor( const char *s, const sk_vector_t *class_list) { int i; int class_count; classID_t class_id; const char *class_name; sensorID_t sensor_id; if ( (s == NULL) || (class_list == NULL) ) { return -1; /* Invalid input */ } if ( skVectorGetElementSize(class_list) != sizeof(const char *) ) { return -1; } if ( sksiteSensorNameIsLegal(s) != 0 ) { return -2; /* Invalid sensor name */ } sensor_id = sksiteSensorLookup(s); if ( sensor_id != SK_INVALID_SENSOR ) { return -3; /* Duplicate sensor name */ } /* Let's confirm that all of the classes exist before we do anything. */ class_count = skVectorGetCount(class_list); for ( i = 0; i < class_count; i++ ) { if ( skVectorGetValue(&class_name, class_list, i) != 0 ) { return -1; /* Bad input */ } class_id = sksiteClassLookup(class_name); if ( class_id == SK_INVALID_CLASS ) { return i + 1; /* Invalid class name at position i */ } } /* Okay. All is well. Make everything go. */ sensor_id = sksiteSensorGetMaxID() + 1; if ( sksiteSensorCreate(sensor_id, s) != 0 ) { return -5; /* Something's horribly wrong */ } for ( i = 0; i < class_count; i++ ) { if ( skVectorGetValue(&class_name, class_list, i) != 0 ) { return -1; /* Why didn't we already find this? */ } class_id = sksiteClassLookup(class_name); if ( sksiteClassAddSensor(class_id, sensor_id) != 0 ) { return -5; /* Something's horribly wrong */ } } return 0; } int sksiteParseSensorList( sk_vector_t *out_sensors, const char *name_list) { sensorID_t sensor_id; char *cp; char *ep; char *name_list_copy = NULL; int matches = 0; int rv; if ( (name_list == NULL) || (out_sensors == NULL) ) { rv = -1; goto END; } if ( skVectorGetElementSize(out_sensors) != sizeof(sensorID_t) ) { rv = -1; goto END; } name_list_copy = strdup(name_list); if ( name_list_copy == NULL ) { rv = -1; goto END; } cp = name_list_copy; while ( *cp ) { ep = strchr(cp, ','); if ( ep == cp ) { /* double comma, ignore */ ++cp; continue; } if ( ep == NULL ) { /* no more commas, jump to end of string */ ep = cp + strlen(cp); } else { *ep = '\0'; ep++; } sensor_id = sksiteSensorLookup(cp); if ( sensor_id == SK_INVALID_SENSOR ) { rv = 0; goto END; } /* add to vector */ if ( skVectorAppendValue(out_sensors, &sensor_id) ) { rv = -1; goto END; } cp = ep; matches++; } rv = matches; END: if ( name_list_copy != NULL ) { free(name_list_copy); } return rv; } /** File Output Formats ***********************************************/ #ifdef TEST_SITE static uint8_t _siteGetFileformatCount( void) { return fileformats.fl_count; } static const char *_siteFileformatGetNameFast( fileFormat_t ffid) { return fileformats.fl_list[(ffid)].ff_name; } static const char *_siteFileformatGetName( fileFormat_t ffid) { return (((ffid) >= _siteGetFileformatCount()) ? NULL : _siteFileformatGetNameFast(ffid)); } #endif /* TEST_SITE */ static int _siteInitializeFileformats( size_t sz) { if (sz > UINT8_MAX) { return -1; } fileformats.fl_list = calloc(1+sz, sizeof(fileformat_struct_t)); fileformats.fl_count = (uint8_t)sz; if (fileformats.fl_list == NULL) { return -1; } return 0; } static fileFormat_t _siteFileformatAdd( const char *name, uint8_t id) { fileformat_struct_t *ffi; /* check length of file format */ if (strlen(name) > SK_MAX_STRLEN_FILE_FORMAT) { skAppPrintErr(("File format name '%s' is longer than allowed (%u)\n" "\tFix you site header and recompile. Abort!"), name, SK_MAX_STRLEN_FILE_FORMAT); assert(strlen(name) <= SK_MAX_STRLEN_FILE_FORMAT); abort(); } /* check id is o.k. */ if (id >= _siteGetFileformatCount()) { skAppPrintErr(("File format id '%u' is larger than allowed (%u)\n" "\tFix you site header and recompile. Abort!"), id, _siteGetFileformatCount()); assert(id < _siteGetFileformatCount()); abort(); } ffi = &fileformats.fl_list[id]; ffi->ff_id = (fileFormat_t)id; ffi->ff_name = name; return ffi->ff_id; } int sksiteFileformatGetName( char *buffer, size_t buffer_size, fileFormat_t id) { const char *name = _siteFileformatGetName(id); if ( name == NULL ) { /* Unknown file format, give integer */ return snprintf(buffer, buffer_size, "%u", id); } else { /* Known file format, give name */ return snprintf(buffer, buffer_size, "%s", name); } } int sksiteFileformatIsValid( fileFormat_t id) { return (id < _siteGetFileformatCount()); } #ifdef TEST_SITE # define fileformats #endif /** Compression Methods ***********************************************/ #ifdef TEST_SITE static uint8_t _siteGetCompmethodCount( void) { return compmethods.cml_count; } static const char *_siteCompmethodGetNameFast( sk_compmethod_t cmid) { return compmethods.cml_list[cmid].cm_name; } static const char *_siteCompmethodGetName( sk_compmethod_t cmid) { return (((cmid) >= _siteGetCompmethodCount()) ? NULL : _siteCompmethodGetNameFast(cmid)); } #endif /* TEST_SITE */ static int _siteInitializeCompmethods( size_t sz) { if (sz > UINT8_MAX) { return -1; } compmethods.cml_list = calloc(1+sz, sizeof(compmethod_struct_t)); compmethods.cml_count = (uint8_t)sz; if (compmethods.cml_list == NULL) { return -1; } return 0; } static sk_compmethod_t _siteCompmethodAdd( const char *name, uint8_t id) { compmethod_struct_t *cmi; #if 0 /* check length of compression method name */ if (strlen(name) > SK_MAX_STRLEN_FILE_FORMAT) { skAppPrintErr(("Compression method name '%s'" " is longer than allowed (%u)\n" "\tFix you site header and recompile. Abort!"), name, SK_MAX_STRLEN_FILE_FORMAT); assert(strlen(cmi->cm_name) <= SK_MAX_STRLEN_FILE_FORMAT); abort(); } #endif /* check id is o.k. */ if (id >= _siteGetCompmethodCount()) { skAppPrintErr(("Compression method id '%u'" " is larger than allowed (%u)\n" "\tFix you site header and recompile. Abort!"), id, _siteGetCompmethodCount()); assert(id < _siteGetCompmethodCount()); abort(); } cmi = &compmethods.cml_list[id]; cmi->cm_id = (sk_compmethod_t)id; cmi->cm_name = name; return cmi->cm_id; } int sksiteCompmethodGetName( char *buffer, size_t buffer_size, sk_compmethod_t id) { const char *name = _siteCompmethodGetName(id); if ( name == NULL ) { /* Unknown compression method, give integer */ return snprintf(buffer, buffer_size, "%u", id); } else { /* Known compression method, give name */ return snprintf(buffer, buffer_size, "%s", name); } } int sksiteCompmethodIsAvailable( sk_compmethod_t id) { switch (id) { case SK_COMPMETHOD_NONE: #ifdef HAVE_ZLIB_H case SK_COMPMETHOD_ZLIB: #endif #ifdef SK_LZO_HEADER_NAME case SK_COMPMETHOD_LZO1X: #endif return 1; } return 0; } int sksiteCompmethodIsValid( sk_compmethod_t id) { return (((uint8_t)id) < _siteGetCompmethodCount()); } sk_compmethod_t sksiteCompmethodGetBest( void) { #if defined(SK_LZO_HEADER_NAME) return SK_COMPMETHOD_LZO1X; #elif defined(HAVE_ZLIB_H) return SK_COMPMETHOD_ZLIB; #else return SK_COMPMETHOD_NONE; #endif } sk_compmethod_t sksiteCompmethodGetDefault( void) { /* return the value from configure */ return SK_ENABLE_OUTPUT_COMPRESSION; } /* ======================================================================== */ #define COMPMETHOD_STRING_BEST "best" typedef enum { OPT_COMPRESSION_METHOD } site_compmethod_opts_enum_t; static struct option site_compmethod_opts[] = { {"compression-method", REQUIRED_ARG, 0, OPT_COMPRESSION_METHOD}, {0,0,0,0} /* sentinel entry */ }; static int _siteCompmethodOptionsHandler( clientData cData, int opt_index, char *opt_arg) { sk_compmethod_t *compression_method = (sk_compmethod_t*)cData; sk_stringmap_t *str_map = NULL; sk_stringmap_status_t rv_map; sk_stringmap_entry_t *map_entry; sk_compmethod_t cm; int rv = 1; assert(opt_index == OPT_COMPRESSION_METHOD); if (opt_index != OPT_COMPRESSION_METHOD) { abort(); } /* create a stringmap of the available entries */ if (SKSTRINGMAP_OK != skStringMapCreate(&str_map)) { skAppPrintErr("Unable to create stringmap"); goto END; } if (skStringMapAddID(str_map, COMPMETHOD_STRING_BEST, (sk_stringmap_id_t)sksiteCompmethodGetBest()) != SKSTRINGMAP_OK) { goto END; } for (cm = 0; cm < _siteGetCompmethodCount(); ++cm) { if ( !sksiteCompmethodIsAvailable(cm)) { continue; } if (skStringMapAddID(str_map, _siteCompmethodGetNameFast(cm), (sk_stringmap_id_t)cm) != SKSTRINGMAP_OK) { goto END; } } /* attempt to match */ rv_map = skStringMapGetEntry(&map_entry, str_map, opt_arg); switch (rv_map) { case SKSTRINGMAP_OK: *compression_method = (uint8_t)map_entry->id; rv = 0; break; case SKSTRINGMAP_PARSE_AMBIGUOUS: skAppPrintErr("%s value '%s' is ambiguous", site_compmethod_opts[OPT_COMPRESSION_METHOD].name, opt_arg); goto END; case SKSTRINGMAP_PARSE_NO_MATCH: skAppPrintErr("%s value '%s' does not match any known method", site_compmethod_opts[OPT_COMPRESSION_METHOD].name, opt_arg); goto END; default: skAppPrintErr("Unexpected return value from string-map parser (%d)", rv_map); goto END; } END: if (str_map) { skStringMapDestroy(str_map); } return rv; } int sksiteCompmethodOptionsRegister( sk_compmethod_t *compression_method) { *compression_method = sksiteCompmethodGetDefault(); return optionsRegister(site_compmethod_opts, &_siteCompmethodOptionsHandler, compression_method); } void sksiteCompmethodOptionsUsage( FILE *fh) { int i; sk_compmethod_t cm; for (i = 0; site_compmethod_opts[i].name; ++i) { fprintf(fh, "--%s %s. ", site_compmethod_opts[i].name, SK_OPTION_HAS_ARG(site_compmethod_opts[i])); switch ((site_compmethod_opts_enum_t)(site_compmethod_opts[i].val)) { case OPT_COMPRESSION_METHOD: fprintf(fh, ("Set compression for binary output file(s).\n" "\tDef. %s. Choices: %s [=%s]"), _siteCompmethodGetNameFast(sksiteCompmethodGetDefault()), COMPMETHOD_STRING_BEST, _siteCompmethodGetNameFast(sksiteCompmethodGetBest())); for (cm = 0; cm < _siteGetCompmethodCount(); ++cm) { if ( !sksiteCompmethodIsAvailable(cm)) { continue; } fprintf(fh, ", %s", _siteCompmethodGetNameFast(cm)); } break; } fprintf(fh, "\n"); } } /* ========================================================================= */ #ifdef TEST_SITE # define compmethods #endif /** Utilities and Global Info *****************************************/ char *sksiteGetRootDir( char *buffer, size_t bufsize) { if (bufsize < 1+strlen(data_rootdir)) { return NULL; } strncpy(buffer, data_rootdir, bufsize); return buffer; } int sksiteSetRootDir( const char *rootdir) { if (rootdir == NULL || rootdir[0] == '\0') { return -1; } if (strlen(rootdir)+1 > sizeof(data_rootdir)) { return -1; } strncpy(data_rootdir, rootdir, sizeof(data_rootdir)); return 0; } int sksiteSetPathFormat( const char *format) { if ( (format == NULL) || (format[0] == '\0') ) { return -1; } if ( strlen(format) + 1 > sizeof(path_format) ) { return -1; } strncpy(path_format, format, PATH_MAX); path_format[PATH_MAX-1] = '\0'; return 0; } char *sksiteGeneratePathname( char *buffer, size_t bufsize, flowtypeID_t flowtype_id, sensorID_t sensor_id, uint32_t timestamp, const char *suffix, char **reldir_begin, char **filename_begin) { /* convert to time_t for 64bit platforms */ const time_t tt = (time_t)timestamp; struct tm trec; char name_buffer[SK_MAX_STRLEN_FLOWTYPE+1]; char sensor_name_buffer[SK_MAX_STRLEN_SENSOR+1]; const char *suf = NULL; const char *pos; const char *next_pos; char *buf; size_t len; if ( buffer == NULL || bufsize == 0 ) { return NULL; } if ( !sksiteFlowtypeExists(flowtype_id) ) { return NULL; } if ( !sksiteSensorExists(sensor_id) ) { return NULL; } /* set 'suf' to the suffix if it was provided and not the empty * string; ignore the leading '.' if suffix, it is added later. */ if ( suffix && *suffix ) { suf = suffix; if ( *suf == '.' ) { ++suf; } } gmtime_r(&tt, &trec); buf = buffer; /* First, add the data_rootdir */ len = snprintf(buf, bufsize, "%s/", data_rootdir); if ( len >= bufsize ) { return NULL; } buf += len; bufsize -= len; /* Apply the format */ pos = path_format; while ( *pos != '\0' ) { if ( *pos == '%' ) { pos++; switch ( *pos ) { case 'C': len = sksiteClassGetName(buf, bufsize, sksiteFlowtypeGetClass(flowtype_id)); break; case 'F': len = sksiteFlowtypeGetName(buf, bufsize, flowtype_id); break; case 'H': len = snprintf(buf, bufsize, "%02d", trec.tm_hour); break; case 'N': len = sksiteSensorGetName(buf, bufsize, sensor_id); break; case 'T': len = sksiteFlowtypeGetType(buf, bufsize, flowtype_id); break; case 'Y': len = snprintf(buf, bufsize, "%04d", trec.tm_year + 1900); break; case 'd': len = snprintf(buf, bufsize, "%02d", trec.tm_mday); break; case 'f': len = snprintf(buf, bufsize, "%u", flowtype_id); break; case 'm': len = snprintf(buf, bufsize, "%02d", trec.tm_mon + 1); break; case 'n': len = snprintf(buf, bufsize, "%u", sensor_id); break; case 'x': sksiteFlowtypeGetName(name_buffer, sizeof(name_buffer), flowtype_id); sksiteSensorGetName(sensor_name_buffer, sizeof(sensor_name_buffer), sensor_id); len = snprintf(buf, bufsize, "%s-%s_%04d%02d%02d.%02d", name_buffer, sensor_name_buffer, trec.tm_year + 1900, trec.tm_mon + 1, trec.tm_mday, trec.tm_hour); break; case '\0': len = snprintf(buf, bufsize, "%%"); break; default: len = snprintf(buf, bufsize, "%%%c", *pos); break; } if ( *pos != '\0' ) { pos++; } } else { next_pos = strchr(pos, '%'); if ( next_pos == NULL ) { len = snprintf(buf, bufsize, "%s", pos); } else { len = next_pos - pos; if ( len <= bufsize ) { strncpy(buf, pos, len); } pos = next_pos; } } if ( len >= bufsize ) { return NULL; } buf += len; bufsize -= len; } /* Optionally add suffix */ if ( suf ) { len = snprintf(buf, bufsize, ".%s", suf); if ( len >= bufsize ) { return NULL; } buf += len; bufsize -= len; } /* And finally, add NUL */ if ( len >= bufsize ) { return NULL; } *buf = '\0'; if (reldir_begin) { *reldir_begin = &buffer[1+strlen(data_rootdir)]; } if (filename_begin) { *filename_begin = strrchr(buffer, '/') + 1; } return buffer; } flowtypeID_t sksiteParseFilename( flowtypeID_t *out_flowtype, sensorID_t *out_sensor, uint32_t *out_timestamp, char **out_suffix, const char *filename) { char buf[PATH_MAX]; const char *sp; char *ep; flowtypeID_t ft; unsigned long temp1, temp2; /* check input */ if (!filename) { return SK_INVALID_FLOWTYPE; } /* copy file portion of filename into buf */ sp = baseName_r(buf, filename, sizeof(buf)); if (sp == NULL) { /* input name too long */ return SK_INVALID_FLOWTYPE; } /* find the end of the prefix, e.g., "in-" */ ep = strchr(sp, '-'); if (NULL == ep) { return SK_INVALID_FLOWTYPE; } *ep = '\0'; ++ep; /* lookup file type */ ft = sksiteFlowtypeLookup(sp); if (ft == SK_INVALID_FLOWTYPE) { return SK_INVALID_FLOWTYPE; } if (out_flowtype) { *out_flowtype = ft; } /* find the sensor/timestamp separator */ sp = ep; ep = strchr(sp, '_'); if (NULL == ep) { return SK_INVALID_FLOWTYPE; } *ep = '\0'; ++ep; if (out_sensor) { *out_sensor = sksiteSensorLookup(sp); } /* move to start of time; convert "YYYYMMDD." into a single * integer, then pull out each part */ sp = ep; errno = 0; temp1 = strtoul(sp, &ep, 10); if (sp == ep || *ep != '.' || (temp1 == ULONG_MAX && errno == ERANGE) || (temp1 < 19700101 || temp1 >= 20380119)) { return SK_INVALID_FLOWTYPE; } /* now handle the hour "HH." or "HH\0" */ sp = ep + 1; errno = 0; temp2 = strtoul(sp, &ep, 10); if (sp == ep || (*ep != '.' && *ep != '\0') || (temp2 == ULONG_MAX && errno == ERANGE) || (temp2 > 23)) { return SK_INVALID_FLOWTYPE; } if (out_timestamp) { struct tm trec; time_t t; memset(&trec, 0, sizeof(struct tm)); trec.tm_mday = temp1 % 100; temp1 /= 100; trec.tm_mon = temp1 % 100 - 1; trec.tm_year = (temp1 / 100) - 1900; trec.tm_hour = temp2; t = timegm(&trec); if (t == (time_t)(-1)) { return SK_INVALID_FLOWTYPE; } *out_timestamp = (uint32_t)t; } if (out_suffix) { *out_suffix = ep; } return ft; } char *sksiteParseGeneratePath( char *buffer, size_t bufsize, const char *filename, const char *suffix, char **reldir_begin, char **filename_begin) { flowtypeID_t flowtype; sensorID_t sensor; uint32_t timestamp; char *old_suffix; char new_suffix[PATH_MAX]; if (sksiteParseFilename(&flowtype, &sensor, ×tamp, &old_suffix, filename) == SK_INVALID_FLOWTYPE) { return NULL; } if (*old_suffix != '\0' && suffix == NULL) { /* there was a suffix on 'filename' and the caller didn't * provide a new suffix; append old suffix to new name */ strncpy(new_suffix, old_suffix, sizeof(new_suffix)); if (new_suffix[sizeof(new_suffix)-1] != '\0') { /* suffix too long */ return NULL; } suffix = new_suffix; } return sksiteGeneratePathname(buffer, bufsize, flowtype, sensor, timestamp, suffix, reldir_begin, filename_begin); } /* ** Local Variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */