summaryrefslogtreecommitdiff
path: root/cleopatre/application/libspid/src
diff options
context:
space:
mode:
Diffstat (limited to 'cleopatre/application/libspid/src')
-rw-r--r--cleopatre/application/libspid/src/config_item.c196
-rw-r--r--cleopatre/application/libspid/src/config_line.c513
-rw-r--r--cleopatre/application/libspid/src/image.c357
-rw-r--r--cleopatre/application/libspid/src/misc.c80
-rw-r--r--cleopatre/application/libspid/src/network.c386
-rw-r--r--cleopatre/application/libspid/src/openssl_sha256.c238
-rw-r--r--cleopatre/application/libspid/src/secu.c128
-rw-r--r--cleopatre/application/libspid/src/system.c414
8 files changed, 2312 insertions, 0 deletions
diff --git a/cleopatre/application/libspid/src/config_item.c b/cleopatre/application/libspid/src/config_item.c
new file mode 100644
index 0000000000..5d78fd2a34
--- /dev/null
+++ b/cleopatre/application/libspid/src/config_item.c
@@ -0,0 +1,196 @@
+/* SPC300 bundle {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/config_item.c
+ * \brief item management in configuration file
+ * \ingroup libspid
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "libspid.h"
+
+#ifdef __UTESTS__
+ #include "config_item_utests.h"
+#endif /* __UTESTS__ */
+
+/**
+ * Read an item value inside a configuration file; put the value
+ * into a provided buffer
+ *
+ * \param filename full path filename of a configuration file
+ * \param label label of wanted item to read
+ * \param value pointer to buffer where read value is written
+ * \param buffer_len length of value buffer
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NOT_FOUND: item has not been found
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ * \return LIBSPID_ERROR_NO_SPACE: not enough space in buffer
+ */
+
+libspid_error_t libspid_config_read_item (const char *filename, const char *label, char *value, int buffer_len)
+{
+ char buffer[LIBSPID_LINE_MAX_LEN];
+ FILE *fp;
+ char *strtok_ctx, *ptr, *blank_ptr;
+
+ /* check input parameters */
+ if((filename == NULL) || (label == NULL) || (value == NULL) || (buffer_len <= 0))
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+ /* check key validity */
+ if ( strstr(label, LIBSPID_CONFIG_DELIMITER) || strchr(label, ' ') || strchr(label, '\t') )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* open config file */
+ if((fp = fopen(filename, "r")) == NULL)
+ {
+ //syslog(LOG_WARNING, "libspid_read_config_param: cannot open %s (errno=%d)\n", filename, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ while( fgets(buffer, LIBSPID_LINE_MAX_LEN - 1, fp) )
+ {
+ /* get the label */
+ ptr = strtok_r(buffer, LIBSPID_CONFIG_DELIMITER " \t", &strtok_ctx);
+ /* check if it is the wanted label */
+ if((ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, label))
+ continue;
+ /* remove space and '=' before the value */
+ ptr += strlen(ptr) + 1;
+ while(isblank(*ptr) || (*ptr == *LIBSPID_CONFIG_DELIMITER))
+ ptr++;
+ ptr = strtok_r(ptr, "\n\r", &strtok_ctx);
+ /* init value to empty */
+ *value = '\0';
+ if(ptr != NULL)
+ {
+ /* remove spaces at the end of value */
+ blank_ptr = ptr + strlen(ptr) - 1;
+ while((blank_ptr >= ptr) && isblank(*blank_ptr))
+ {
+ *blank_ptr = '\0';
+ blank_ptr--;
+ }
+ /* check for buffer space to copy the value */
+ if(strlen(ptr) >= buffer_len)
+ {
+ fclose(fp);
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ strcpy(value, ptr);
+ }
+ fclose(fp);
+ //syslog(LOG_DEBUG, "libspid_read_config_param: '%s' = '%s'", label, value);
+ return LIBSPID_SUCCESS;
+ }
+ /* label not found */
+ fclose(fp);
+ return LIBSPID_ERROR_NOT_FOUND;
+}
+
+/**
+ * Write a value of an item into a configuration file
+ *
+ * \param filename full path filename of a configuration file
+ * \param label label of item value to write; if item does not already exists, it will be added into the configuration file
+ * \param value value of item to write
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ * \return LIBSPID_ERROR_NO_SPACE: not enough space in buffer
+ */
+
+libspid_error_t libspid_config_write_item(const char *filename, const char *label, const char *value)
+{
+ char buffer[LIBSPID_LINE_MAX_LEN];
+ char out_filename[64];
+ char *ptr, *strtok_ctx;
+ FILE *fp_in, *fp_out;
+ int fd_in;
+ int is_found = 0;
+ char *tmp_line;
+
+ /* check input parameters */
+ if ( (filename == NULL) || (label == NULL) || (strlen(label) <= 0) || (value == NULL) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+ /* check key validity */
+ if ( strstr(label, LIBSPID_CONFIG_DELIMITER) || strchr(label, ' ') || strchr(label, '\t') )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* open config file */
+ if ( (fd_in = open(filename, O_RDONLY | O_CREAT, 0666)) < 0 )
+ {
+ //syslog(LOG_WARNING, "libspid_write_config_param: cannot open %s (errno=%d)", filename, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ fp_in = fdopen(fd_in, "r");
+ /* create the modified config file */
+ sprintf(out_filename, "%sXXXXXX", filename);
+ if ( (fp_out = fdopen(mkstemp(out_filename), "w")) == NULL )
+ {
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ /* find the label to modify */
+ while ( fgets(buffer, LIBSPID_LINE_MAX_LEN - 1, fp_in) )
+ {
+ tmp_line = strdup(buffer);
+
+ /* get the label */
+ ptr = strtok_r(buffer, LIBSPID_CONFIG_DELIMITER " \t", &strtok_ctx);
+ /* check if it is the wanted label */
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, label) )
+ {
+ /* print line unchanged back to file */
+ fprintf(fp_out, tmp_line);
+ continue;
+ }
+
+ /* check for buffer overload */
+ if ( LIBSPID_LINE_MAX_LEN - 1/*'\0'*/ - 1 /*'\n'*/ - ( strlen(ptr) + 1/*' '*/ + 1/*'='*/ + 1/*' '*/ ) < strlen(value) )
+ {
+ fclose(fp_out);
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ /* write the new value */
+ fprintf(fp_out, "%s %s %s\n", ptr, LIBSPID_CONFIG_DELIMITER, value); /* make line in format "label = value" */
+ is_found = 1;
+
+ }
+ if (!is_found)
+ {
+ /* add new 'label = value' at the end of file */
+ fprintf(fp_out, "%s %s %s\n", label, LIBSPID_CONFIG_DELIMITER, value);
+ }
+ fclose(fp_out);
+ fclose(fp_in);
+ close(fd_in);
+ if ( rename(out_filename, filename) < 0 )
+ {
+ //syslog(LOG_WARNING, "libspid_write_config_param : rename (errno=%d)\n", errno);
+ }
+ return LIBSPID_SUCCESS;
+}
diff --git a/cleopatre/application/libspid/src/config_line.c b/cleopatre/application/libspid/src/config_line.c
new file mode 100644
index 0000000000..67dba8afe7
--- /dev/null
+++ b/cleopatre/application/libspid/src/config_line.c
@@ -0,0 +1,513 @@
+/* SPC300 bundle {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/config_line.c
+ * \brief line management in configuration file
+ * \ingroup libspid
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "libspid.h"
+
+/**
+ * Read a configuration line from a file.<BR>
+ * A configuration line is composed of a unique key, which
+ * is playing the role of index, and several elements. All are
+ * separated by a delimiter and terminated by a carriage
+ * return.<BR>
+ * When line is read, it is put inside a provided buffer, and
+ * then processed. If the searched key is found, the provided
+ * element table is filled with pointers to each found line
+ * elements.If the key is an empty string, the key of the
+ * first line is returned into the key buffer.<BR>
+ * Key buffer must not be smaller than LIBSPID_MAX_KEY_LEN.<BR>
+ * When line elements are returned, the key buffer if filled
+ * with the next found key in the next line. If there is no more
+ * line to read, the key buffer contains a empty string. The
+ * element number parameter is updated with the number of
+ * elements filled into the element table.
+ *
+ * \param filename full path filename of a configuration file
+ * \param delimiters string containing all accepted delimiters
+ * (usually space and tab characters)
+ * \param key key of the line to read; updated with the key of
+ * the next line
+ * \param elt_number maximum number of elements to read, updated
+ * with the real number of read elements if less is found
+ * \param elt array of pointers where are stored pointers to
+ * elements
+ * \param buffer whole line working buffer
+ * \param buffer_len working buffer length
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NOT_FOUND: key not found or no more
+ * line to read
+ * \return LIBSPID_ERROR_NO_SPACE: no enough space in buffer or
+ * to much elements to put into element table
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_config_read_line(const char *filename, const char* delimiters, char *key, unsigned int *elt_number, char *elt[], char *buffer, unsigned int buffer_len)
+{
+ FILE *fp;
+ char key_buffer[LIBSPID_KEY_MAX_LEN];
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ char *ptr, *strtok_ctx;
+#ifdef USE_LOCK
+ struct flock lock;
+#endif /* USE_LOCK */
+ int max_elt_number;
+ int is_key_found;
+
+ /* check input parameters */
+ if ( (filename == NULL) || (delimiters == NULL) || (key == NULL) || (elt_number == NULL)
+ || (elt == NULL) || (buffer == NULL) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ if ( (strlen(delimiters) <= 0) || (*elt_number > LIBSPID_ELT_MAX_NB)
+ || (buffer_len <= 0) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check delimiter validity */
+ if ( strchr(delimiters, '\n') || strchr(delimiters, '\r') )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check key validity */
+ if ( strlen(key) > LIBSPID_KEY_MAX_LEN )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ if ( strpbrk(key, delimiters) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* open config file */
+ if ( (fp = fopen(filename, "r")) == NULL )
+ {
+ //syslog(LOG_WARNING, "%s: cannot open %s (errno=%d)\n", __FUNCTION__, filename, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+#ifdef USE_LOCK
+ /* set the read lock */
+ lock.l_type = F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if ( fcntl(fileno(fp), F_SETLKW, &lock) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s: lock set failed (errno=%d)\n)", __FUNCTION__, errno);
+ fclose(fp);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+#endif /* USE_LOCK */
+
+ max_elt_number = *elt_number;
+ *elt_number = 0;
+ is_key_found = LIBSPID_FALSE;
+
+ if ( strlen(key) > 0 )
+ {
+ while ( fgets(buffer, buffer_len, fp) )
+ {
+ /* remove the newline character*/
+ if ( buffer[strlen(buffer) - 1] == '\n' )
+ {
+ if ( buffer[strlen(buffer) - 2] == '\r')
+ {
+ /* DOS format */
+ buffer[strlen(buffer) - 2] = '\0';
+ }
+ else
+ {
+ /* Unix format */
+ buffer[strlen(buffer) - 1] = '\0';
+ }
+ }
+ else
+ {
+ /* chops chars until end of line */
+ fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp);
+ }
+ /* get the index */
+ ptr = strtok_r(buffer, delimiters, &strtok_ctx);
+ //printf("key=%s (look for '%s')\n", ptr, key);
+ /* check if it is looked key */
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, key) )
+ continue;
+
+ is_key_found = LIBSPID_TRUE;
+
+ /* get all elements */
+ while ( (ptr = strtok_r(NULL, delimiters, &strtok_ctx)) && (*elt_number < max_elt_number) )
+ {
+ elt[*elt_number] = ptr;
+ //printf("elt[%d]='%s'\n", *elt_number, elt[*elt_number]);
+ *elt_number += 1;
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* just find the first key */
+ is_key_found = LIBSPID_TRUE;
+ }
+ /* check if key has been found */
+ if (!is_key_found)
+ {
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fileno(fp), F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ /* close file */
+ fclose(fp);
+ return LIBSPID_ERROR_NOT_FOUND;
+ }
+ /* get next key */
+ *key = '\0';
+ while ( NULL != fgets(key_buffer, LIBSPID_KEY_MAX_LEN - 1, fp) )
+ {
+ /* remove the newline */
+ if ( key_buffer[strlen(key_buffer) - 1] == '\n' )
+ {
+ key_buffer[strlen(key_buffer) - 1] = '\0';
+ }
+ /* get the index */
+ ptr = strtok_r(key_buffer, delimiters, &strtok_ctx);
+ //printf("key2=%s\n", ptr);
+ /* check if it is looked key */
+ if( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') )
+ continue;
+ strcpy(key, ptr);
+ break;
+ }
+
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fileno(fp), F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ /* close file */
+ fclose(fp);
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Write a configuration line into a configuration file.<BR>
+ * A configuration line is made of a key and several elements,
+ * separated by a delimiter.<BR>
+ * A key item is used as unique line reference. If the key
+ * already exists, the line is updated with new elements.
+ * If the key does not exist, the line is added to the end of
+ * the file.<BR>
+ * The key length must not be longer than LIBSPID_KEY_MAX_LEN.
+ *
+ * \param filename full path filename of a configuration file
+ * \param delimiter char used for delimiting key and elements
+ * \param key the key (index) of the line
+ * \param elt_number number of elements to write
+ * \param elt list of elements to write
+ * \result error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NO_SPACE: no enough space in buffer or
+ * to much elements to put into element table
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_config_write_line(const char *filename, const char delimiter, const char *key, unsigned int elt_number, char *elt[])
+{
+ char buffer[LIBSPID_LINE_MAX_LEN], key_buffer[LIBSPID_KEY_MAX_LEN + 1];
+ char out_filename[64];
+ char *ptr, *strtok_ctx;
+ FILE *fp_in, *fp_out;
+ int fd_in, index = 0;
+ int is_key_found = LIBSPID_FALSE;
+ char delimiters[8] = LIBSPID_CONFIG_DELIMITER " \t";
+#ifdef USE_LOCK
+ struct flock lock;
+#endif /* USE_LOCK */
+
+ /* add given delimiter to the set of delimiters */
+ strncat(delimiters, &delimiter, 1);
+
+ /* check input parameters */
+ if ( (filename == NULL) || (key == NULL) || (elt == NULL) || (elt_number > LIBSPID_ELT_MAX_NB) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check sizes */
+ if ( (strlen(key) == 0) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check delimiter validity */
+ if ( (delimiter == '\n') || (delimiter == '\r') )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check key validity */
+ if ( strchr(key, delimiter) != NULL )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+ if ( strlen(key) > LIBSPID_KEY_MAX_LEN )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* open config file */
+ if ( (fd_in = open(filename, O_RDWR | O_CREAT, 0666)) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s: cannot open %s (errno=%d)", __FUNCTION__, filename, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ fp_in = fdopen(fd_in, "r");
+ /* create the modified config file */
+ sprintf(out_filename, "%sXXXXXX", filename);
+ if ( (fp_out = fdopen(mkstemp(out_filename), "w")) == NULL )
+ {
+ fclose(fp_out);
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+#ifdef USE_LOCK
+ /* set the write lock */
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if (fcntl(fd_in, F_SETLKW, &lock) < 0)
+ {
+ //syslog(LOG_WARNING, "%s: lock set failed (errno=%d)\n)", __FUNCTION__, errno);
+ fclose(fp_out);
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+#endif /* USE_LOCK */
+ /* find the label to modify */
+ while ( fgets(buffer, LIBSPID_LINE_MAX_LEN - 1, fp_in) )
+ {
+ /* fill working copy for key */
+ strncpy(key_buffer, buffer, LIBSPID_KEY_MAX_LEN);
+ /* get the index */
+ ptr = strtok_r(key_buffer, delimiters, &strtok_ctx);
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, key) )
+ {
+ fprintf(fp_out, "%s", buffer);
+ continue;
+ }
+
+ is_key_found = LIBSPID_TRUE;
+ /* create the new line */
+ sprintf(buffer, "%s%c", key, delimiter);
+ for (index = 0; index < elt_number; index++)
+ {
+ /* check for buffer overflow */
+ if ( ( strlen(buffer) + 1 /*delimiter*/ + strlen(elt[index]) + 1 /*'\0'*/ ) > LIBSPID_LINE_MAX_LEN )
+ {
+ fclose(fp_out);
+ fclose(fp_in);
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fd_in, F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ close(fd_in);
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ sprintf(buffer + strlen(buffer), "%s%c", elt[index], delimiter);
+ }
+ /* string should end with last element, so erase last delimiter and finish the line */
+ buffer[strlen(buffer) - 1] = '\n';
+ fprintf(fp_out, "%s", buffer);
+ }
+ if (!is_key_found)
+ {
+ /* add new key + element at the end of file */
+ sprintf(buffer, "%s%c", key, delimiter);
+ for(index = 0; index < elt_number; index++)
+ {
+ /* check for buffer overflow */
+ if ( ( strlen(buffer) + 1 /*delimiter*/ + strlen(elt[index]) + 1 /*'\0'*/ ) > LIBSPID_LINE_MAX_LEN )
+ {
+ fclose(fp_out);
+ fclose(fp_in);
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fd_in, F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ close(fd_in);
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ sprintf(buffer + strlen(buffer), "%s%c", elt[index], delimiter );
+ }
+ /* string should end with last element, so erase last delimiter and finish the line */
+ buffer[strlen(buffer) - 1] = '\n';
+ fprintf(fp_out, "%s", buffer);
+ }
+ fclose(fp_out);
+ fclose(fp_in);
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fd_in, F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ close(fd_in);
+ if ( rename(out_filename, filename) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s : rename (errno=%d)\n", __FUNCTION__, errno);
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Remove a line from a configuration file.<BR>
+ * Line to remove is referred according to a provided key. A
+ * line is composed of a key and several elements, separated by
+ * a common delimiter.<BR>
+ * The provided key must not be longer than LIBSPID_MAX_KEY_LEN.
+ *
+ * \param filename full path filename of a configuration file
+ * \param delimiters chars used for delimiting key and elements
+ * \param key key (index) of the line to remove
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NOT_FOUND: key not found
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_config_remove_line(const char *filename, const char *delimiters, const char *key)
+{
+ char buffer[LIBSPID_LINE_MAX_LEN], key_buffer[LIBSPID_KEY_MAX_LEN + 1];
+ char out_filename[64];
+ char *ptr, *strtok_ctx;
+ FILE *fp_in, *fp_out;
+ int fd_in;
+ int is_key_found = LIBSPID_FALSE;
+#ifdef USE_LOCK
+ struct flock lock;
+#endif /* USE_LOCK */
+
+ /* check input parameters */
+ if ( (filename == NULL) || (delimiters == NULL) || (key == NULL) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check sizes */
+ if ( (strlen(key) == 0) || (strlen(delimiters) == 0) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check delimiter validity */
+ if ( strchr(delimiters, '\n') || strchr(delimiters, '\r') )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* check key validity */
+ if ( strpbrk(key, delimiters) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+ if ( strlen(key) > LIBSPID_KEY_MAX_LEN )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* open config file */
+ if ( (fd_in = open(filename, O_RDWR | O_CREAT, 0666)) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s: cannot open %s (errno=%d)", __FUNCTION__, filename, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ fp_in = fdopen(fd_in, "r");
+ /* create the modified config file */
+ sprintf(out_filename, "%sXXXXXX", filename);
+ if((fp_out = fdopen(mkstemp(out_filename), "w")) == NULL)
+ {
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+#ifdef USE_LOCK
+ /* set the write lock */
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if ( fcntl(fd_in, F_SETLKW, &lock) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s: lock set failed (errno=%d)\n)", __FUNCTION__, errno);
+ fclose(fp_out);
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+#endif /* USE_LOCK */
+ /* find the label to modify */
+ while ( fgets(buffer, LIBSPID_LINE_MAX_LEN - 1, fp_in) )
+ {
+ /* fill working copy for key */
+ memset(key_buffer, '\0', LIBSPID_KEY_MAX_LEN + 1);
+ strncpy(key_buffer, buffer, LIBSPID_KEY_MAX_LEN);
+ /* get the index */
+ ptr = strtok_r(key_buffer, delimiters, &strtok_ctx);
+
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, key) )
+ {
+ fprintf(fp_out, "%s", buffer);
+ continue;
+ }
+
+ is_key_found = LIBSPID_TRUE;
+ }
+ fclose(fp_out);
+ fclose(fp_in);
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fd_in, F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ close(fd_in);
+ if(is_key_found)
+ {
+ if ( rename(out_filename, filename) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s : rename (errno=%d)\n", __FUNCTION__, errno);
+ }
+ }
+ else
+ {
+ remove(out_filename);
+ return LIBSPID_ERROR_NOT_FOUND;
+ }
+ return LIBSPID_SUCCESS;
+}
diff --git a/cleopatre/application/libspid/src/image.c b/cleopatre/application/libspid/src/image.c
new file mode 100644
index 0000000000..fd658067d6
--- /dev/null
+++ b/cleopatre/application/libspid/src/image.c
@@ -0,0 +1,357 @@
+/* SPC300 bundle {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/image.c
+ * \brief firmware image management
+ * \ingroup libspid
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#ifndef __UTESTS__
+ #include <mtd/mtd-user.h>
+#endif /* __UTESTS__ */
+#include "libspid.h"
+
+/**
+ * Give informations on the stored firmware images : current,
+ * alternate, #0 and #1.<BR>
+ * The provided image descriptor structure is fill with requested
+ * image infomration.<BR>
+ * The device name of flash partition where image is stored is
+ * put inside the provided mtd_name buffer. Buffer length must
+ * be >= LIBSPID_MTD_NAME_MAX_LEN (16).
+ *
+ * \param type type of image to get information
+ * \param image_desc pointer to structure where information is
+ * filled
+ * \param mtd_name buffer to get the mtd device name where the
+ * requested image is stored.
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NOT_FOUND: requested image not found
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_image_get_desc(libspid_image_desc_type_t type, spidcom_image_desc_t *image_desc, char *mtd_name)
+{
+ int fd0 = 0;
+ int fd1 = 0;
+ spidcom_image_desc_t image_desc_temp[2];
+ char mtd_name_temp[2][32] = {{0}};
+ int found_index = -1;
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ char *strtok_ctx;
+ int img_desc_0_found = 0;
+ int img_desc_1_found = 0;
+ FILE *fp;
+ char *img_desc_mtd_num;
+ spc300_nvram_t nvram;
+
+ if ( (image_desc == NULL) || (mtd_name == NULL) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ if ( (type < 0) || (type >= LIBSPID_IMAGE_DESC_TYPE_NB) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ if ( LIBSPID_SUCCESS != libspid_system_get_nvram(&nvram) )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ if ( nvram.nb_images == 1 && ( type != LIBSPID_IMAGE_DESC_TYPE_0 && type != LIBSPID_IMAGE_DESC_TYPE_CURRENT ) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ if( (fp = fopen (LIBSPID_SYSTEM_MTD_PATH, "r")) == NULL)
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ while ( fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp) != NULL )
+ {
+ if ( strstr(line_buffer, SPIDCOM_IMG_DESC_MTD_NAME_0) != NULL )
+ {
+ img_desc_0_found = 1;
+ /* Extract mtd path from line mtd<num>: <size> <erasesize> "nvram" */
+ img_desc_mtd_num = strtok_r(line_buffer, ": ", &strtok_ctx);
+ sprintf(mtd_name_temp[0], "%s/%s", LIBSPID_DEV_PATH, img_desc_mtd_num);
+ }
+
+ else if ( nvram.nb_images > 1 && ( strstr(line_buffer, SPIDCOM_IMG_DESC_MTD_NAME_1) != NULL ) )
+ {
+ img_desc_1_found = 1;
+ /* Extract mtd path from line mtd<num>: <size> <erasesize> "nvram" */
+ img_desc_mtd_num = strtok_r(line_buffer, ": ", &strtok_ctx);
+ sprintf(mtd_name_temp[1], "%s/%s",LIBSPID_DEV_PATH, img_desc_mtd_num);
+ }
+ }
+
+ fclose (fp);
+
+ if ( img_desc_0_found == 0 || (nvram.nb_images > 1 && img_desc_1_found == 0) )
+ {
+ return LIBSPID_ERROR_NOT_FOUND;
+ }
+
+ /* open the MTD devices for partition #0 and #1 */
+ if ( (fd0 = open(mtd_name_temp[0], O_RDONLY)) < 0 )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ if ( nvram.nb_images > 1 && (fd1 = open(mtd_name_temp[1], O_RDONLY)) < 0 )
+ {
+ close(fd0);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* get image descriptor infos from both MTD */
+ if ( (read(fd0, &image_desc_temp[0], sizeof(spidcom_image_desc_t)) < sizeof(spidcom_image_desc_t))
+ || ( nvram.nb_images > 1 && ( read(fd1, &image_desc_temp[1], sizeof(spidcom_image_desc_t)) < sizeof(spidcom_image_desc_t) ) ) )
+ {
+ close(fd0);
+ if (nvram.nb_images > 1)
+ close(fd1);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ close(fd0);
+ close(fd1);
+
+ /* give asked type */
+ switch(type)
+ {
+ case LIBSPID_IMAGE_DESC_TYPE_0 :
+ if ( SPIDCOM_IMG_DESC_IS_VALID(image_desc_temp) )
+ {
+ found_index = 0;
+ }
+ break;
+
+ case LIBSPID_IMAGE_DESC_TYPE_1:
+ if ( SPIDCOM_IMG_DESC_IS_VALID(image_desc_temp + 1) )
+ {
+ found_index = 1;
+ }
+ break;
+
+ case LIBSPID_IMAGE_DESC_TYPE_CURRENT:
+ case LIBSPID_IMAGE_DESC_TYPE_ALTERNATE:
+ /* check image validity */
+ if ( nvram.nb_images == 1 )
+ {
+ found_index = 0;
+ }
+ else if ( !SPIDCOM_IMG_DESC_IS_VALID(image_desc_temp) )
+ {
+ found_index = 1;
+ }
+ else if ( !SPIDCOM_IMG_DESC_IS_VALID(image_desc_temp + 1) )
+ {
+ found_index = 0;
+ }
+ else
+ {
+ /* we have two images and both are valid, find the highest index */
+ if ( image_desc_temp[0].index > image_desc_temp[1].index )
+ {
+ found_index = 0;
+ }
+ else
+ {
+ found_index = 1;
+ }
+ }
+ /* give alternate index if asked */
+ if ( type == LIBSPID_IMAGE_DESC_TYPE_ALTERNATE )
+ {
+ found_index = (found_index + 1) % 2;
+ }
+ break;
+
+ default:
+ /* hum : not possible */
+ break;
+ }
+ mtd_name[0] = '\0';
+ if (found_index >= 0)
+ {
+ strcpy(mtd_name, mtd_name_temp[found_index]);
+ }
+
+ if ( (found_index < 0) || !SPIDCOM_IMG_DESC_IS_VALID(image_desc_temp + found_index) )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ memcpy( image_desc, &image_desc_temp[found_index], sizeof(spidcom_image_desc_t) );
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Select the current image firmware to boot on the next time.
+ *
+ * \param select the image to select for nrxt boot
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NOT_FOUND: selected image is not valid
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_image_select(libspid_image_select_t select)
+{
+ int fd;
+ spidcom_image_desc_t image_desc[2], *image_desc_ptr;
+ char mtd_name[2][32], current_mtd_name[32];
+ unsigned char *sector_data;
+ //region_info_t reginfo;
+ //char cmd_buffer[256];
+ spc300_nvram_t nvram;
+#ifndef __UTESTS__
+ volatile mtd_info_t meminfo;
+ erase_info_t erase;
+#else
+ struct meminfo_utests
+ {
+ int erasesize;
+ } meminfo;
+#endif /* __UTESTS__ */
+
+ if ( (select < LIBSPID_IMAGE_SELECT_0) || (select >= LIBSPID_IMAGE_SELECT_NB) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ if ( LIBSPID_SUCCESS != libspid_system_get_nvram(&nvram) )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ if ( nvram.nb_images == 1 )
+ {
+ if ( select != LIBSPID_IMAGE_SELECT_0 )
+ return LIBSPID_ERROR_PARAM;
+ else
+ return LIBSPID_SUCCESS;
+ }
+
+ /* get the current partition mtd_name */
+ if ( LIBSPID_SUCCESS != libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_CURRENT, image_desc, current_mtd_name) )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* fill table with index 0='the new selected', 1='the other' */
+ switch(select)
+ {
+ case LIBSPID_IMAGE_SELECT_0:
+ libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_0, image_desc, mtd_name[0]);
+ libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_1, image_desc + 1, mtd_name[1]);
+ break;
+ case LIBSPID_IMAGE_SELECT_1:
+ libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_1, image_desc, mtd_name[0]);
+ libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_0, image_desc + 1, mtd_name[1]);
+ break;
+ case LIBSPID_IMAGE_SELECT_SWITCH:
+ libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_ALTERNATE, image_desc, mtd_name[0]);
+ libspid_image_get_desc(LIBSPID_IMAGE_DESC_TYPE_CURRENT, image_desc + 1, mtd_name[1]);
+ break;
+ default:
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* check the validity of selected partition */
+ if (!image_desc[0].is_valid)
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* check if we are selecting our current partition */
+ if ( !strcmp(current_mtd_name, mtd_name[0]) )
+ {
+ /* no work to be done
+ * bacause we are demanded to switch to the image
+ * that we are actually already running */
+ return LIBSPID_SUCCESS;
+ }
+
+ /* open the selected mtd partition */
+ if ( (fd = open(mtd_name[0], O_RDWR)) < 0 )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+#ifndef __UTESTS__
+ /* get the flash block erase size */
+ if ( ioctl(fd, MEMGETINFO, &meminfo) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s: cannot get info from %s (errno=%d)", __FUNCTION__, mtd_name[0], errno);
+ close(fd);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+#else
+ meminfo.erasesize = 64000; /* 64K sector */
+#endif /* __UTESTS__ */
+
+ /* allocate memory to copy the 1st sector of new selected partition */
+ if ( (sector_data = malloc(meminfo.erasesize)) == NULL )
+ {
+ //syslog(LOG_WARNING, "%s: memory allocation of %d bytes failed (errno=%d)", __FUNCTION__, meminfo.erasesize, errno);
+ close(fd);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* read the 1st sector data */
+ if ( read(fd, sector_data, meminfo.erasesize) < 0 )
+ {
+ free(sector_data);
+ close(fd);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* set the new index to alternate.index + 1 */
+ image_desc_ptr = (spidcom_image_desc_t *)sector_data;
+ image_desc_ptr->index = image_desc[1].index + 1;
+
+#ifndef __UTESTS__
+ /* erase the 1st sector */
+ erase.start = 0;
+ erase.length = meminfo.erasesize;
+ if (ioctl(fd, MEMERASE, &erase) != 0)
+ {
+ //syslog(LOG_WARNING, "%s: flash erase of %s failed (errno=%d)", __FUNCTION__, mtd_name[0], errno);
+ free(sector_data);
+ close(fd);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+#endif /* __UTESTS__ */
+
+ /* restore the save 1st sector */
+ /*if((fd = open(mtd_name[0], O_RDWR)) < 0)
+ {
+ syslog(LOG_WARNING, "%s: cannot open %s to restore the 1st sector (errno=%d) !!!", __FUNCTION__, mtd_name[0], errno);
+ free(sector_data);
+ return -errno;
+ }*/
+ lseek(fd, 0, SEEK_SET);
+ write(fd, sector_data, meminfo.erasesize);
+ close(fd);
+ free(sector_data);
+
+ /* ok, new sector is selected */
+ return LIBSPID_SUCCESS;
+}
+
diff --git a/cleopatre/application/libspid/src/misc.c b/cleopatre/application/libspid/src/misc.c
new file mode 100644
index 0000000000..1c10bd0ef0
--- /dev/null
+++ b/cleopatre/application/libspid/src/misc.c
@@ -0,0 +1,80 @@
+/* SPC300 bundle {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/misc.c
+ * \brief misc functions
+ * \ingroup libspid
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "libspid.h"
+
+/**
+ * Convert a MAC address in string format aa:bb:cc:dd:ee:ff into a
+ * MAC address in binary format (6 bytes).<br>
+ * The array to store the binary MAC address needs to be provided.<br>
+ * Example : "00:23:54:ae:f5:24" ---> { 0x00, 0x23, 0x54, 0xae, 0xf5, 0x24 }
+ *
+ * \param str MAC address string
+ * \param bin MAC address returned in binary format
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ */
+
+libspid_error_t libspid_mac_str_to_bin(const char *str, unsigned char *bin)
+{
+ int i;
+ char *s, *e;
+
+ if( (bin == NULL) || (str == NULL) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ s = (char *)str;
+ for (i = 0; i < 6; ++i)
+ {
+ bin[i] = s ? strtoul (s, &e, 16) : 0;
+ if (s)
+ s = (*e) ? e + 1 : e;
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Convert a MAC address in binary format (6 bytes) into a MAC address
+ * in string format aa:bb:cc:dd:ee:ff.<br>
+ * The array to store the string MAC address needs to be provided with minimal
+ * size of 18 bytes (LIBSPID_MAC_STR_LEN).<br>
+ * Example : { 0x00, 0x23, 0x54, 0xae, 0xf5, 0x24 } ---> "00:23:54:ae:f5:24"
+ *
+ * \param bin MAC address returned in binary format
+ * \param str MAC address string
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ */
+
+libspid_error_t libspid_mac_bin_to_str(const unsigned char *bin, char *str)
+{
+ if( (bin == NULL) || (str == NULL) )
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ sprintf ( str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ bin[0], bin[1], bin[2], bin[3], bin[4], bin[5] );
+
+ return LIBSPID_SUCCESS;
+}
+
diff --git a/cleopatre/application/libspid/src/network.c b/cleopatre/application/libspid/src/network.c
new file mode 100644
index 0000000000..c7ae34236c
--- /dev/null
+++ b/cleopatre/application/libspid/src/network.c
@@ -0,0 +1,386 @@
+/* SPC300 bundle {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/network.c
+ * \brief networking functions
+ * \ingroup libspid
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <netinet/in.h> /* definition of htons() */
+#include <unistd.h> /* definition of close() */
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "libspid.h"
+
+/**
+ * Give the IP setting of a network interface.<br>
+ * All data are coming from the configuration file content, not from the system status.
+ *
+ * \param interface string containing network interface name (“br0”, “plc0” or “eth0”)
+ * \param ip pointer to structure to get all IP data of interface
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NO_SPACE: no enough space in buffer or
+ * to much elements to put into element table
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+libspid_error_t libspid_network_get_ip (const char *interface, libspid_ip_t *ip)
+{
+ FILE *fp;
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ int record = 0; /* flag that tells if we should process or not found data */
+ char *ptr;
+ char *strtok_ctx;
+ char *value;
+
+ if (interface == NULL || ip == NULL)
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* reset libspid_ip_t structure */
+ memset(ip, 0x0, sizeof(libspid_ip_t));
+
+ fp = fopen (LIBSPID_NETWORK_CONF_PATH, "r");
+ if (fp != NULL)
+ {
+ while ( fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp) )
+ {
+ if ( strstr(line_buffer, "iface") != NULL )
+ {
+ if ( strstr(line_buffer, interface) != NULL )
+ {
+ /* the following data is regarding our inteface - start recording */
+ record = 1;
+
+ if ( strstr(line_buffer, "static") != NULL )
+ {
+ ip->mode = LIBSPID_IP_MODE_STATIC;
+ }
+ else if ( strstr(line_buffer, "dhcp") != NULL )
+ {
+ ip->mode = LIBSPID_IP_MODE_DHCP;
+ }
+ }
+ else
+ {
+ /* we found word "iface", but it is not regarding our inteface - stop recording */
+ record = 0;
+ }
+ }
+
+ if (record == 0)
+ continue;
+
+ ptr = strtok_r(line_buffer, " \t", &strtok_ctx);
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') )
+ {
+ continue;
+ }
+
+ /* --- address --- */
+ if ( strcmp(ptr, "address") == 0 )
+ {
+ value = strtok_r(NULL, " \t", &strtok_ctx);
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) )
+ {
+ /* put empty string into ip->address */
+ strcpy((char *)ip->address, "");
+ continue;
+ }
+ /* suppress '\n' character */
+ value[strlen(value) - 1] = '\0';
+ /* check for buffer overflow */
+ if ( strlen(value) + 1 > LIBSPID_IP_MAX_LEN )
+ {
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ strcpy((char *)ip->address, value);
+ }
+
+ /* --- netmask --- */
+ if ( strcmp(ptr, "netmask") == 0 )
+ {
+ value = strtok_r(NULL, " \t", &strtok_ctx);
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) )
+ {
+ /* put empty string into ip->netmask */
+ strcpy((char *)ip->netmask, "");
+ continue;
+ }
+ /* suppress '\n' character */
+ value[strlen(value) - 1] = '\0';
+ /* check for buffer overflow */
+ if ( strlen(value) + 1 > LIBSPID_IP_MAX_LEN )
+ {
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ strcpy((char *)ip->netmask, value);
+ }
+
+ /* --- broadcast --- */
+ if ( strcmp(ptr, "broadcast") == 0 )
+ {
+ value = strtok_r(NULL, " \t", &strtok_ctx);
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) )
+ {
+ /* put empty string into ip->broadcast */
+ strcpy((char *)ip->broadcast, "");
+ continue;
+ }
+ /* suppress '\n' character */
+ value[strlen(value) - 1] = '\0';
+ /* check for buffer overflow */
+ if ( strlen(value) + 1 > LIBSPID_IP_MAX_LEN )
+ {
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ strcpy((char *)ip->broadcast, value);
+ }
+
+ /* --- gateway --- */
+ if ( strcmp(ptr, "gateway") == 0 )
+ {
+ value = strtok_r(NULL, " \t", &strtok_ctx);
+ if ( (ptr == NULL) || (strlen(ptr) <= 0) )
+ {
+ /* put empty string into ip->gateway */
+ strcpy((char *)ip->gateway, "");
+ continue;
+ }
+ /* suppress '\n' character */
+ value[strlen(value) - 1] = '\0';
+ /* check for buffer overflow */
+ if ( strlen(value) + 1 > LIBSPID_IP_MAX_LEN )
+ {
+ return LIBSPID_ERROR_NO_SPACE;
+ }
+ strcpy((char *)ip->gateway, value);
+ }
+ } /* while */
+
+ fclose (fp);
+ }
+ else
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Change the IP setting of a network interface.<br>
+ * All data set into the configuration file, not into the running system.
+ *
+ * \param interface string containing network interface name (“br0”, “plc0” or “eth0”)
+ * \param ip pointer to structure containing all IP data to set to the interface
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+libspid_error_t libspid_network_set_ip (const char *interface, const libspid_ip_t *ip)
+{
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ int skip = 0; /* flag that tells if we should keep these lines or not */
+ int auto_exists = 0; /* flag set if line auto <our_interface> exists */
+ char out_filename[64];
+ char filename[] = LIBSPID_NETWORK_CONF_PATH;
+ FILE *fp_in, *fp_out;
+ int fd_in = 0;
+
+ if (interface == NULL || ip == NULL)
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* open config file */
+ if ( (fd_in = open(filename, O_RDWR | O_CREAT, 0666)) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s: cannot open %s (errno=%d)", __FUNCTION__, filename, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ if ( (fp_in = fdopen(fd_in, "r")) == NULL )
+ {
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ /* create the modified config file */
+ sprintf(out_filename, "%sXXXXXX", filename);
+ if ( (fp_out = fdopen(mkstemp(out_filename), "w")) == NULL )
+ {
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+#ifdef USE_LOCK
+ /* set the write lock */
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if (fcntl(fd_in, F_SETLKW, &lock) < 0)
+ {
+ //syslog(LOG_WARNING, "%s: lock set failed (errno=%d)\n)", __FUNCTION__, errno);
+ fclose(fp_out);
+ fclose(fp_in);
+ close(fd_in);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+#endif /* USE_LOCK */
+
+ while ( fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp_in) )
+ {
+ /* Start skipping lines (i.e. not writing them to output file)
+ * the moment we saw mentioned our interface,
+ * because section of configuration for a certain interface
+ * always begins with lines:
+ * auto <interface>
+ * or
+ * iface <interface> inet <static_or_dhcp>
+ * This way we will erase all previous configuration.
+ * New configuration will be added always in the end of a file.
+ */
+ if ( ( strstr(line_buffer, "auto") != NULL ) || ( strstr(line_buffer, "iface") != NULL ) )
+ {
+ if ( strstr(line_buffer, interface) != NULL )
+ {
+ skip = 1;
+ /* check if it was a line that starts with "auto" */
+ if ( strstr(line_buffer, "auto") != NULL )
+ {
+ auto_exists = 1;
+ }
+ }
+ else
+ {
+ skip = 0;
+ }
+ }
+
+ if (skip == 1)
+ {
+ continue;
+ }
+ else
+ {
+ fprintf(fp_out, "%s", line_buffer);
+ }
+
+ } /* while */
+
+ /* append new configuration */
+ fputc('\n', fp_out);
+ if (auto_exists)
+ {
+ fprintf(fp_out, "auto %s\n", interface);
+ }
+ switch (ip->mode)
+ {
+ case LIBSPID_IP_MODE_STATIC:
+ fprintf(fp_out, "iface %s inet static\n", interface);
+ break;
+ case LIBSPID_IP_MODE_DHCP:
+ fprintf(fp_out, "iface %s inet dhcp\n", interface);
+ break;
+ default:
+ return LIBSPID_ERROR_PARAM; /* ip->mode not known */
+ break;
+ }
+
+ if ( strlen((char *)ip->address) > 0)
+ {
+ fprintf(fp_out, "\taddress %s\n", ip->address);
+ }
+ if ( strlen((char *)ip->netmask) > 0)
+ {
+ fprintf(fp_out, "\tnetmask %s\n", ip->netmask);
+ }
+ if ( strlen((char *)ip->broadcast) > 0)
+ {
+ fprintf(fp_out, "\tbroadcast %s\n", ip->broadcast);
+ }
+ if ( strlen((char *)ip->gateway) > 0)
+ {
+ fprintf(fp_out, "\tgateway %s\n", ip->gateway);
+ }
+
+ fclose(fp_out);
+ fclose(fp_in);
+#ifdef USE_LOCK
+ /* close lock */
+ fcntl(fd_in, F_UNLCK, &lock);
+#endif /* USE_LOCK */
+ close(fd_in);
+
+ if ( rename(out_filename, filename) < 0 )
+ {
+ //syslog(LOG_WARNING, "%s : rename (errno=%d)\n", __FUNCTION__, errno);
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Get the MAC address of an network interface.<br>
+ * Result is put into a provided buffer in string format aa:bb:cc:dd:ee:ff hexa address. Buffer must be of LIBSPID_MAC_STRING_MAX_LEN.
+ *
+ * \param interface string containing network interface name (“br0”, “plc0” or “eth0”)
+ * \param mac buffer to get the MAC address in hexa string format with ':' inside
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+libspid_error_t libspid_network_get_mac (const char *interface, unsigned char *mac)
+{
+ struct ifreq ifr;
+ int s;
+ struct ether_addr ea;
+
+ if (interface == NULL || mac == NULL)
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ /* reset mac string */
+ *mac = '\0';
+
+ s = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
+ if( s < 0 )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ memset (&ifr, 0, sizeof (struct ifreq));
+ strcpy(ifr.ifr_name, interface);
+ if ( ioctl(s, SIOCGIFHWADDR, &ifr) != 0 )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ memcpy(ea.ether_addr_octet, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+ sprintf ((char *)mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ ea.ether_addr_octet[0], ea.ether_addr_octet[1],
+ ea.ether_addr_octet[2], ea.ether_addr_octet[3],
+ ea.ether_addr_octet[4], ea.ether_addr_octet[5]);
+
+ close(s);
+
+ return LIBSPID_SUCCESS;
+}
+
+
+
diff --git a/cleopatre/application/libspid/src/openssl_sha256.c b/cleopatre/application/libspid/src/openssl_sha256.c
new file mode 100644
index 0000000000..841d7026b1
--- /dev/null
+++ b/cleopatre/application/libspid/src/openssl_sha256.c
@@ -0,0 +1,238 @@
+/* crypto/sha/sha256.c */
+/* ====================================================================
+ * Copyright (c) 2004 The OpenSSL Project. All rights reserved
+ * according to the OpenSSL license [found in ../../LICENSE].
+ * ====================================================================
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "openssl_sha256.h"
+
+void SHA256_Init (SHA256_CTX *c)
+{
+ c->h[0]=0x6a09e667UL; c->h[1]=0xbb67ae85UL;
+ c->h[2]=0x3c6ef372UL; c->h[3]=0xa54ff53aUL;
+ c->h[4]=0x510e527fUL; c->h[5]=0x9b05688cUL;
+ c->h[6]=0x1f83d9abUL; c->h[7]=0x5be0cd19UL;
+ c->Nl=0; c->Nh=0;
+ c->num=0; c->md_len=SHA256_DIGEST_LENGTH;
+}
+
+unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md)
+ {
+ SHA256_CTX c;
+ static unsigned char m[SHA256_DIGEST_LENGTH];
+
+ if (md == NULL) md=m;
+ SHA256_Init(&c);
+ SHA256_Update(&c,d,n);
+ SHA256_Final(md,&c);
+ return(md);
+ }
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG SHA_LONG
+#define HASH_CTX SHA256_CTX
+#define HASH_CBLOCK SHA_CBLOCK
+/*
+ * Note that FIPS180-2 discusses "Truncation of the Hash Function Output."
+ * default: case below covers for it. It's not clear however if it's
+ * permitted to truncate to amount of bytes not divisible by 4. I bet not,
+ * but if it is, then default: case shall be extended. For reference.
+ * Idea behind separate cases for pre-defined lenghts is to let the
+ * compiler decide if it's appropriate to unroll small loops.
+ */
+#define HASH_MAKE_STRING(c,s) do { \
+ unsigned long ll; \
+ unsigned int xn; \
+ switch ((c)->md_len) \
+ { case SHA256_DIGEST_LENGTH: \
+ for (xn=0;xn<SHA256_DIGEST_LENGTH/4;xn++) \
+ { ll=(c)->h[xn]; HOST_l2c(ll,(s)); } \
+ break; \
+ default: \
+ if ((c)->md_len > SHA256_DIGEST_LENGTH) \
+ return 0; \
+ for (xn=0;xn<(c)->md_len/4;xn++) \
+ { ll=(c)->h[xn]; HOST_l2c(ll,(s)); } \
+ break; \
+ } \
+ } while (0)
+
+#define HASH_UPDATE SHA256_Update
+#define HASH_TRANSFORM SHA256_Transform
+#define HASH_FINAL SHA256_Final
+#define HASH_BLOCK_DATA_ORDER sha256_block_data_order
+#ifndef SHA256_ASM
+static
+#endif
+void sha256_block_data_order (SHA256_CTX *ctx, const void *in, size_t num);
+
+#include "openssl_md32_common.h"
+
+#ifndef SHA256_ASM
+static const SHA_LONG K256[64] = {
+ 0x428a2f98UL,0x71374491UL,0xb5c0fbcfUL,0xe9b5dba5UL,
+ 0x3956c25bUL,0x59f111f1UL,0x923f82a4UL,0xab1c5ed5UL,
+ 0xd807aa98UL,0x12835b01UL,0x243185beUL,0x550c7dc3UL,
+ 0x72be5d74UL,0x80deb1feUL,0x9bdc06a7UL,0xc19bf174UL,
+ 0xe49b69c1UL,0xefbe4786UL,0x0fc19dc6UL,0x240ca1ccUL,
+ 0x2de92c6fUL,0x4a7484aaUL,0x5cb0a9dcUL,0x76f988daUL,
+ 0x983e5152UL,0xa831c66dUL,0xb00327c8UL,0xbf597fc7UL,
+ 0xc6e00bf3UL,0xd5a79147UL,0x06ca6351UL,0x14292967UL,
+ 0x27b70a85UL,0x2e1b2138UL,0x4d2c6dfcUL,0x53380d13UL,
+ 0x650a7354UL,0x766a0abbUL,0x81c2c92eUL,0x92722c85UL,
+ 0xa2bfe8a1UL,0xa81a664bUL,0xc24b8b70UL,0xc76c51a3UL,
+ 0xd192e819UL,0xd6990624UL,0xf40e3585UL,0x106aa070UL,
+ 0x19a4c116UL,0x1e376c08UL,0x2748774cUL,0x34b0bcb5UL,
+ 0x391c0cb3UL,0x4ed8aa4aUL,0x5b9cca4fUL,0x682e6ff3UL,
+ 0x748f82eeUL,0x78a5636fUL,0x84c87814UL,0x8cc70208UL,
+ 0x90befffaUL,0xa4506cebUL,0xbef9a3f7UL,0xc67178f2UL };
+
+/*
+ * FIPS specification refers to right rotations, while our ROTATE macro
+ * is left one. This is why you might notice that rotation coefficients
+ * differ from those observed in FIPS document by 32-N...
+ */
+#define Sigma0(x) (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10))
+#define Sigma1(x) (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7))
+#define sigma0(x) (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3))
+#define sigma1(x) (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10))
+
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+#define OPENSSL_SMALL_FOOTPRINT
+#ifdef OPENSSL_SMALL_FOOTPRINT
+
+static void sha256_block_data_order (SHA256_CTX *ctx, const void *in, size_t num)
+ {
+ unsigned MD32_REG_T a,b,c,d,e,f,g,h,s0,s1,T1,T2;
+ SHA_LONG X[16],l;
+ int i;
+ const unsigned char *data=in;
+
+ while (num--) {
+
+ a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3];
+ e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7];
+
+ for (i=0;i<16;i++)
+ {
+ HOST_c2l(data,l); T1 = X[i] = l;
+ T1 += h + Sigma1(e) + Ch(e,f,g) + K256[i];
+ T2 = Sigma0(a) + Maj(a,b,c);
+ h = g; g = f; f = e; e = d + T1;
+ d = c; c = b; b = a; a = T1 + T2;
+ }
+
+ for (;i<64;i++)
+ {
+ s0 = X[(i+1)&0x0f]; s0 = sigma0(s0);
+ s1 = X[(i+14)&0x0f]; s1 = sigma1(s1);
+
+ T1 = X[i&0xf] += s0 + s1 + X[(i+9)&0xf];
+ T1 += h + Sigma1(e) + Ch(e,f,g) + K256[i];
+ T2 = Sigma0(a) + Maj(a,b,c);
+ h = g; g = f; f = e; e = d + T1;
+ d = c; c = b; b = a; a = T1 + T2;
+ }
+
+ ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d;
+ ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h;
+
+ }
+}
+
+#else
+
+#define ROUND_00_15(i,a,b,c,d,e,f,g,h) do { \
+ T1 += h + Sigma1(e) + Ch(e,f,g) + K256[i]; \
+ h = Sigma0(a) + Maj(a,b,c); \
+ d += T1; h += T1; } while (0)
+
+#define ROUND_16_63(i,a,b,c,d,e,f,g,h,X) do { \
+ s0 = X[(i+1)&0x0f]; s0 = sigma0(s0); \
+ s1 = X[(i+14)&0x0f]; s1 = sigma1(s1); \
+ T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f]; \
+ ROUND_00_15(i,a,b,c,d,e,f,g,h); } while (0)
+
+static void sha256_block_data_order (SHA256_CTX *ctx, const void *in, size_t num)
+ {
+ unsigned MD32_REG_T a,b,c,d,e,f,g,h,s0,s1,T1;
+ SHA_LONG X[16];
+ int i;
+ const unsigned char *data=in;
+ const union { long one; char little; } is_endian = {1};
+
+ while (num--) {
+
+ a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3];
+ e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7];
+
+ if (!is_endian.little && sizeof(SHA_LONG)==4 && ((size_t)in%4)==0)
+ {
+ const SHA_LONG *W=(const SHA_LONG *)data;
+
+ T1 = X[0] = W[0]; ROUND_00_15(0,a,b,c,d,e,f,g,h);
+ T1 = X[1] = W[1]; ROUND_00_15(1,h,a,b,c,d,e,f,g);
+ T1 = X[2] = W[2]; ROUND_00_15(2,g,h,a,b,c,d,e,f);
+ T1 = X[3] = W[3]; ROUND_00_15(3,f,g,h,a,b,c,d,e);
+ T1 = X[4] = W[4]; ROUND_00_15(4,e,f,g,h,a,b,c,d);
+ T1 = X[5] = W[5]; ROUND_00_15(5,d,e,f,g,h,a,b,c);
+ T1 = X[6] = W[6]; ROUND_00_15(6,c,d,e,f,g,h,a,b);
+ T1 = X[7] = W[7]; ROUND_00_15(7,b,c,d,e,f,g,h,a);
+ T1 = X[8] = W[8]; ROUND_00_15(8,a,b,c,d,e,f,g,h);
+ T1 = X[9] = W[9]; ROUND_00_15(9,h,a,b,c,d,e,f,g);
+ T1 = X[10] = W[10]; ROUND_00_15(10,g,h,a,b,c,d,e,f);
+ T1 = X[11] = W[11]; ROUND_00_15(11,f,g,h,a,b,c,d,e);
+ T1 = X[12] = W[12]; ROUND_00_15(12,e,f,g,h,a,b,c,d);
+ T1 = X[13] = W[13]; ROUND_00_15(13,d,e,f,g,h,a,b,c);
+ T1 = X[14] = W[14]; ROUND_00_15(14,c,d,e,f,g,h,a,b);
+ T1 = X[15] = W[15]; ROUND_00_15(15,b,c,d,e,f,g,h,a);
+
+ data += SHA256_CBLOCK;
+ }
+ else
+ {
+ SHA_LONG l;
+
+ HOST_c2l(data,l); T1 = X[0] = l; ROUND_00_15(0,a,b,c,d,e,f,g,h);
+ HOST_c2l(data,l); T1 = X[1] = l; ROUND_00_15(1,h,a,b,c,d,e,f,g);
+ HOST_c2l(data,l); T1 = X[2] = l; ROUND_00_15(2,g,h,a,b,c,d,e,f);
+ HOST_c2l(data,l); T1 = X[3] = l; ROUND_00_15(3,f,g,h,a,b,c,d,e);
+ HOST_c2l(data,l); T1 = X[4] = l; ROUND_00_15(4,e,f,g,h,a,b,c,d);
+ HOST_c2l(data,l); T1 = X[5] = l; ROUND_00_15(5,d,e,f,g,h,a,b,c);
+ HOST_c2l(data,l); T1 = X[6] = l; ROUND_00_15(6,c,d,e,f,g,h,a,b);
+ HOST_c2l(data,l); T1 = X[7] = l; ROUND_00_15(7,b,c,d,e,f,g,h,a);
+ HOST_c2l(data,l); T1 = X[8] = l; ROUND_00_15(8,a,b,c,d,e,f,g,h);
+ HOST_c2l(data,l); T1 = X[9] = l; ROUND_00_15(9,h,a,b,c,d,e,f,g);
+ HOST_c2l(data,l); T1 = X[10] = l; ROUND_00_15(10,g,h,a,b,c,d,e,f);
+ HOST_c2l(data,l); T1 = X[11] = l; ROUND_00_15(11,f,g,h,a,b,c,d,e);
+ HOST_c2l(data,l); T1 = X[12] = l; ROUND_00_15(12,e,f,g,h,a,b,c,d);
+ HOST_c2l(data,l); T1 = X[13] = l; ROUND_00_15(13,d,e,f,g,h,a,b,c);
+ HOST_c2l(data,l); T1 = X[14] = l; ROUND_00_15(14,c,d,e,f,g,h,a,b);
+ HOST_c2l(data,l); T1 = X[15] = l; ROUND_00_15(15,b,c,d,e,f,g,h,a);
+ }
+
+ for (i=16;i<64;i+=8)
+ {
+ ROUND_16_63(i+0,a,b,c,d,e,f,g,h,X);
+ ROUND_16_63(i+1,h,a,b,c,d,e,f,g,X);
+ ROUND_16_63(i+2,g,h,a,b,c,d,e,f,X);
+ ROUND_16_63(i+3,f,g,h,a,b,c,d,e,X);
+ ROUND_16_63(i+4,e,f,g,h,a,b,c,d,X);
+ ROUND_16_63(i+5,d,e,f,g,h,a,b,c,X);
+ ROUND_16_63(i+6,c,d,e,f,g,h,a,b,X);
+ ROUND_16_63(i+7,b,c,d,e,f,g,h,a,X);
+ }
+
+ ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d;
+ ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h;
+
+ }
+ }
+
+#endif
+#endif /* SHA256_ASM */
diff --git a/cleopatre/application/libspid/src/secu.c b/cleopatre/application/libspid/src/secu.c
new file mode 100644
index 0000000000..397e359704
--- /dev/null
+++ b/cleopatre/application/libspid/src/secu.c
@@ -0,0 +1,128 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/secu.c
+ * \brief security functions
+ * \ingroup libspid
+ *
+ * Utilities to generate keys and manage security stuffs
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "libspid.h"
+
+static void
+libspid_secu_sha256 (unsigned char *data, unsigned int length, unsigned char *output)
+{
+ assert (data);
+ assert (output);
+
+ output = SHA256(data, length, output);
+}
+
+static void
+secu_pbkdf1 (const unsigned char input[], const unsigned int input_length,
+ const unsigned char salt[LIBSPID_SECU_SALT_SIZE],
+ const unsigned int it_count, unsigned char output[],
+ unsigned int output_length)
+{
+
+ /* Check parameters. */
+ assert (input);
+ assert (input_length);
+ assert (salt);
+ assert (it_count);
+ assert (output);
+ assert (output_length);
+
+ /* Maximum size of dk. */
+ unsigned char dk[LIBSPID_SECU_PWD_SIZE_MAX + LIBSPID_SECU_SALT_SIZE]
+ __attribute__((aligned(128)));
+ unsigned char sha_output[LIBSPID_SECU_SHA256_SIZE]
+ __attribute__((aligned(128)));
+
+ memset (dk, 0, sizeof (dk));
+ memset (sha_output, 0, sizeof (sha_output));
+
+ /* Concatenate input and salt. */
+ /* Add input. */
+ memcpy (dk, input, input_length);
+ /* If there is a salt, add it at the end. */
+ if (salt)
+ memcpy (dk + input_length, salt, LIBSPID_SECU_SALT_SIZE);
+
+ /* Compute the first derived key with sha256. */
+ libspid_secu_sha256 (dk, input_length + (salt ? LIBSPID_SECU_SALT_SIZE : 0),
+ sha_output);
+ /* Compute the following iterations. */
+ unsigned int i;
+ for (i = 1; i < it_count; i++)
+ {
+ libspid_secu_sha256 (sha_output, LIBSPID_SECU_SHA256_SIZE, sha_output);
+ }
+ /* Copy only LIBSPID_SECU_OUTPUT_KEY_SIZE as result. */
+
+ memcpy (output, sha_output, output_length);
+}
+
+
+/**
+ * Compute a key with pbkdf1 algorithm. Key is provided inside the
+ * input buffer, with the key length inside input_length.
+ * Salt and iteration number must be also provided.
+ * Result key is put inside output buffer, with its size known by
+ * output_length.
+ *
+ * \param input buffer where is the key to hash
+ * \param input_length key length inside the buffer
+ * \param salt_type salt type for key generation
+ * \param it_count number of iteration to process
+ * \param output buffer where is stored the result hash
+ * \param output_length length of buffer where to store the result hash
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ */
+libspid_error_t libspid_secu_pbkdf1 (const unsigned char input[], const unsigned int input_length, const libspid_secu_salt_type_t salt_type, const unsigned int it_count, unsigned char output[], unsigned int output_length)
+{
+ unsigned char *pbkdf1;
+ /* The salt to use for the PBKDF1 function. */
+ unsigned char salt[LIBSPID_SECU_SALT_SIZE] = {0x08, 0x85, 0x6d, 0xaf, 0x7c, 0xf5, 0x81, 0x00};
+
+ /* Check parameters. */
+ if((NULL == input) || (0 == input_length)
+ || (salt_type < 0) || (salt_type >= LIBSPID_SECU_SALT_TYPE_NB)
+ || (0 == it_count) || (NULL == output) || (0 == output_length))
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ switch (salt_type)
+ {
+ case LIBSPID_SECU_SALT_TYPE_DAK:
+ salt[7] = 0x85;
+ pbkdf1 = salt;
+ break;
+ case LIBSPID_SECU_SALT_TYPE_NMK:
+ salt[7] = 0x86;
+ pbkdf1 = salt;
+ break;
+ case LIBSPID_SECU_SALT_TYPE_NONE:
+ default:
+ pbkdf1 = NULL;
+ break;
+ }
+
+ secu_pbkdf1 (input, input_length,
+ pbkdf1, it_count,
+ output, output_length);
+ return LIBSPID_SUCCESS;
+}
+
+
diff --git a/cleopatre/application/libspid/src/system.c b/cleopatre/application/libspid/src/system.c
new file mode 100644
index 0000000000..7290b0cf38
--- /dev/null
+++ b/cleopatre/application/libspid/src/system.c
@@ -0,0 +1,414 @@
+/* SPC300 bundle {{{
+ *
+ * Copyright (C) 2009 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file application/libspid/src/system.c
+ * \brief system functions
+ * \ingroup libspid
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "libspid.h"
+
+/**
+ * Give the current Linux OS version inside a provided buffer.
+ *
+ * \param buffer buffer where to put the result
+ * \param buffer_len length of buffer where to put the result
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NO_SPACE: no enough space in buffer
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+
+libspid_error_t libspid_system_get_kernel_version(char *buffer, int buffer_len)
+{
+ FILE *fp;
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ unsigned int len = 0;
+ unsigned int total = 0;
+
+ if (buffer == NULL || buffer_len <= 0)
+ return LIBSPID_ERROR_PARAM;
+
+ /* initialize buffer - important for strcat to work properly */
+ memset(buffer, 0x0, buffer_len);
+
+ fp = fopen (LIBSPID_SYSTEM_VERSION_PATH, "r");
+ if (fp != NULL)
+ {
+ while ( fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp) )
+ {
+ /* check for buffer overload */
+ len = strlen(line_buffer);
+ total += len;
+ if (total > buffer_len)
+ return LIBSPID_ERROR_NO_SPACE;
+
+ strcat(buffer, line_buffer);
+ }
+
+ fclose(fp);
+ }
+ else
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Give the current PLC driver version inside a provided buffer.
+ *
+ * \param buffer buffer where to put the result
+ * \param buffer_len length of buffer where to put the result
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NO_SPACE: no enough space in buffer
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_get_plc_version (char *buffer, const int buffer_len)
+{
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Give the current AV stack version inside a provided buffer.
+ *
+ * \param buffer buffer where to put the result
+ * \param buffer_len length of buffer where to put the result
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NO_SPACE: no enough space in buffer
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_get_av_version (char *buffer, const int buffer_len)
+{
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Give the time spent since the system has started.<BR>
+ * Results are in 'seconds'.
+ *
+ * \param total_s total time in seconds since system start
+ * \param idle_s total time of processor idle state since system
+ * start
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_get_uptime(unsigned int *total_s, unsigned int *idle_s)
+{
+ FILE *fp;
+ char buf[LIBSPID_LINE_MAX_LEN];
+ int res;
+ unsigned int uptotal = 0;
+ unsigned int upidle = 0;
+ unsigned int dummy1, dummy2; /* we use dummy vars to take decimal parts */
+
+ if (total_s == NULL || idle_s == NULL)
+ return LIBSPID_ERROR_PARAM;
+ /*
+ /proc/uptime <--- we will read uptime info from this file
+ This file contains information detailing how long the system
+ has been on since its last restart. The output of /proc/uptime is quite minimal:
+
+ 350735.47 234388.90
+
+ The first number is the total number of seconds the system has been up.
+ The second number is how much of that time the machine has spent idle, in seconds.
+ */
+ fp = fopen (LIBSPID_SYSTEM_UPTIME_PATH, "r");
+ if (fp != NULL)
+ {
+ if ( fgets(buf, LIBSPID_LINE_MAX_LEN - 1, fp) != NULL )
+ {
+ /* we cannot scanf %lf, we do not have double or float type on our ARM */
+ res = sscanf (buf, "%d.%d %d.%d", &uptotal, &dummy1, &upidle, &dummy2);
+ /* check if all 4 values were read */
+ if (res != 4)
+ {
+ fclose(fp);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ }
+
+ fclose (fp);
+ }
+
+ *total_s = uptotal;
+ *idle_s = upidle;
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Get the current memory status of the system. All results are
+ * put into the same provided buffer.
+ *
+ * \param buffer buffer where the result is put
+ * \param buffer_len size of provided buffer
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ * \return LIBSPID_ERROR_NO_SPACE: not enough space in buffer
+ */
+libspid_error_t libspid_system_get_meminfo(char *buffer, int buffer_len)
+{
+ FILE *fp;
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ unsigned int len = 0;
+ unsigned int total = 0;
+
+ if (buffer == NULL || buffer_len <= 0)
+ return LIBSPID_ERROR_PARAM;
+
+ /* initialize buffer - important for strcat to work properly */
+ memset(buffer, 0x0, buffer_len);
+
+ fp = fopen (LIBSPID_SYSTEM_MEMINFO_PATH, "r");
+ if (fp != NULL)
+ {
+ while ( fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp) )
+ {
+ /* check for buffer overload */
+ len = strlen(line_buffer);
+ total += len;
+ if (total > buffer_len)
+ return LIBSPID_ERROR_NO_SPACE;
+
+ strcat(buffer, line_buffer);
+ }
+
+ fclose (fp);
+ }
+ else
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Reboot the whole system.
+ *
+ */
+
+void libspid_system_reboot(void)
+{
+ system("reboot");
+}
+
+/**
+ * Save the system configuration files into the user ffs.
+ *
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_save(void)
+{
+ FILE *fp;
+ char *ptr, filename[128], command_buffer[256];
+ int rc = 0;
+ char prefix[16] = {0};
+
+ if ( (fp = fopen(LIBSPID_SAVE_LIST_PATH, "r")) == NULL )
+ {
+ //syslog(LOG_WARNING, "libspid_save_config: cannot open %s (errno=%d)", LIBSPID_SAVE_LIST_PATH, errno);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ /* check for /usr/local/etc validity */
+ rc = system("mkdir -p /usr/local/etc");
+ if (rc != 0)
+ {
+ fclose(fp);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ while(fgets(filename, 127, fp))
+ {
+ if (strlen(filename) > 0)
+ {
+ filename[strlen(filename) - 1] = '\0';
+ }
+ /* check if the line in cnf file is /etc/<name> or just <name> */
+ sprintf(prefix, "%s/", LIBSPID_CONF_ROOT_PATH);
+ if ( !strncmp(filename, prefix, strlen(prefix)) )
+ ptr = filename + strlen(prefix);
+ else
+ ptr = filename;
+ if (0 == strlen(ptr))
+ {
+ continue;
+ }
+ sprintf(command_buffer, "cp -a %s/%.64s %s", LIBSPID_CONF_ROOT_PATH, ptr, LIBSPID_SAVE_DIR_PATH);
+ //syslog(LOG_DEBUG, "libspid_save_config: %s", command_buffer);
+ rc = system(command_buffer);
+ if (rc !=0)
+ {
+ fclose(fp);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ }
+ fclose(fp);
+ /* make sure that all *.conf files have been copied, even new ones not in save.lst */
+ sprintf(command_buffer, "cp -a %s/*.conf %s", LIBSPID_CONF_ROOT_PATH, LIBSPID_SAVE_DIR_PATH);
+ rc = system(command_buffer);
+ if (rc !=0)
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Save a configuration file inside the user ffs.
+ *
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad parameter
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_save_file(const char *filename)
+{
+ FILE *fp;
+ char *ptr, command_buffer[256];
+ int rc = 0;
+ char prefix[16] = {0};
+
+ if(filename == NULL)
+ {
+ return LIBSPID_ERROR_PARAM;
+ }
+
+ sprintf(command_buffer, "cp -a %s %s", filename, LIBSPID_SAVE_DIR_PATH);
+ //syslog(LOG_DEBUG, "libspid_save_config: %s", command_buffer);
+ rc = system(command_buffer);
+ if (rc !=0)
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Restore the system into the factory configuration.
+ *
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_factory(void)
+{
+ int rc;
+ char cmd[256] = {0};
+
+ sprintf(cmd, "rm -rf %s/*", LIBSPID_SAVE_DIR_PATH);
+ rc = system(cmd);
+ if (rc !=0)
+ return LIBSPID_ERROR_SYSTEM;
+
+ sprintf(cmd, "cp -a %s/* %s", LIBSPID_FACTORY_PATH, LIBSPID_CONF_ROOT_PATH);
+ rc = system(cmd);
+ if (rc !=0)
+ return LIBSPID_ERROR_SYSTEM;
+
+ sprintf(cmd, "cp -a %s/* %s", LIBSPID_FACTORY_PATH, LIBSPID_SAVE_DIR_PATH);
+ rc = system(cmd);
+ if (rc !=0)
+ return LIBSPID_ERROR_SYSTEM;
+
+ //syslog("libspid_factory: returned to factory default");
+ return LIBSPID_SUCCESS;
+}
+
+/**
+ * Get the NVRAM content.
+ *
+ * \return error type (LIBSPID_SUCCESS if success)
+ * \return LIBSPID_ERROR_PARAM: bad input parameters
+ * \return LIBSPID_ERROR_NOT_FOUND: key not found or no more
+ * line to read
+ * \return LIBSPID_ERROR_SYSTEM: system error, see errno
+ */
+
+libspid_error_t libspid_system_get_nvram(spc300_nvram_t *nvram)
+{
+ FILE *fp;
+ int fd;
+ char *nvram_mtd_num;
+ char nvram_mtd_path[128];
+ char line_buffer[LIBSPID_LINE_MAX_LEN];
+ char *strtok_ctx;
+ int is_found = 0;
+
+ if (nvram == NULL)
+ return LIBSPID_ERROR_PARAM;
+
+ fp = fopen (LIBSPID_SYSTEM_MTD_PATH, "r");
+ if (fp != NULL)
+ {
+ while ( fgets(line_buffer, LIBSPID_LINE_MAX_LEN - 1, fp) != NULL )
+ {
+ if ( strstr(line_buffer, NVRAM_MTD_NAME) != NULL )
+ {
+ is_found = 1;
+ /* Extract mtd path from line mtd<num>: <size> <erasesize> "nvram" */
+ nvram_mtd_num = strtok_r(line_buffer, ": ", &strtok_ctx);
+ sprintf(nvram_mtd_path, "%s/%s", LIBSPID_DEV_PATH, nvram_mtd_num);
+ }
+ }
+
+ fclose (fp);
+
+ if (is_found == 0)
+ {
+ return LIBSPID_ERROR_NOT_FOUND;
+ }
+ }
+ else
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ /* open found mtd path using fd, i.e. with open sys call,
+ read NVRAM magic string and verify (done below) */
+ if ( (fd = open(nvram_mtd_path, O_RDONLY)) < 0 )
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ if( read(fd, nvram, sizeof(spc300_nvram_t)) < sizeof(spc300_nvram_t) )
+ {
+ close(fd);
+ return LIBSPID_ERROR_SYSTEM;
+ }
+ close(fd);
+ /* check NVRAM validity */
+ if(!NVRAM_IS_VALID(nvram))
+ {
+ return LIBSPID_ERROR_SYSTEM;
+ }
+
+ return LIBSPID_SUCCESS;
+}