src/networkd/daemon.c \
src/networkd/daemon.h \
src/networkd/logging.h \
- src/networkd/main.c
+ src/networkd/main.c \
+ src/networkd/string.h
networkd_CPPFLAGS = \
$(AM_CPPFLAGS)
# #
#############################################################################*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/queue.h>
#include "config.h"
#include "logging.h"
+#include "string.h"
+
+struct nw_config_entry {
+ STAILQ_ENTRY(nw_config_entry) nodes;
+
+ char key[NETWORK_CONFIG_KEY_MAX_LENGTH];
+ char value[NETWORK_CONFIG_KEY_MAX_LENGTH];
+};
struct nw_config {
int nrefs;
+
+ STAILQ_HEAD(entries, nw_config_entry) entries;
};
+static void nw_config_entry_free(struct nw_config_entry* entry) {
+ free(entry);
+}
+
+static struct nw_config_entry* nw_config_entry_create(
+ struct nw_config* config, const char* key) {
+ int r;
+
+ // Check input value
+ if (!key) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ // Allocate a new object
+ struct nw_config_entry* entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ return NULL;
+
+ // Store the key
+ r = nw_string_set(entry->key, key);
+ if (r)
+ goto ERROR;
+
+ // Append the new entry
+ STAILQ_INSERT_TAIL(&config->entries, entry, nodes);
+
+ERROR:
+ nw_config_entry_free(entry);
+ return NULL;
+}
+
static void nw_config_free(struct nw_config* config) {
+ struct nw_config_entry* entry = NULL;
+
+ while (!STAILQ_EMPTY(&config->entries)) {
+ entry = STAILQ_FIRST(&config->entries);
+ STAILQ_REMOVE_HEAD(&config->entries, nodes);
+
+ // Free the entry
+ nw_config_entry_free(entry);
+ }
+
free(config);
}
// Initialize reference counter
c->nrefs = 1;
+ // Initialise entries
+ STAILQ_INIT(&c->entries);
+
*config = c;
return 0;
return r;
}
+
+static struct nw_config_entry* nw_config_find(struct nw_config* config, const char* key) {
+ struct nw_config_entry* entry = NULL;
+
+ STAILQ_FOREACH(entry, &config->entries, nodes) {
+ // Key must match
+ if (strcmp(entry->key, key) != 0)
+ continue;
+
+ // Match!
+ return entry;
+ }
+
+ // No match
+ return NULL;
+}
+
+int nw_config_del(struct nw_config* config, const char* key) {
+ struct nw_config_entry* entry = NULL;
+
+ // Find an entry matching the key
+ entry = nw_config_find(config, key);
+
+ // If there is no entry, there is nothing to do
+ if (!entry)
+ return 0;
+
+ // Otherwise remove the object
+ STAILQ_REMOVE(&config->entries, entry, nw_config_entry, nodes);
+
+ // Free the entry
+ nw_config_entry_free(entry);
+
+ return 0;
+}
+
+int nw_config_set(struct nw_config* config, const char* key, const char* value) {
+ struct nw_config_entry* entry = NULL;
+
+ // Delete the entry if val is NULL
+ if (!value)
+ return nw_config_del(config, key);
+
+ // Find any existing entries
+ entry = nw_config_find(config, key);
+
+ // Create a new entry if it doesn't exist, yet
+ if (!entry) {
+ entry = nw_config_entry_create(config, key);
+ if (!entry)
+ return 1;
+ }
+
+ // Store the new value
+ return nw_string_set(entry->value, value);
+}
#ifndef NETWORKD_CONFIG_H
#define NETWORKD_CONFIG_H
+#define NETWORK_CONFIG_KEY_MAX_LENGTH 128
+#define NETWORK_CONFIG_VALUE_MAX_LENGTH 2048
+
struct nw_config;
int nw_config_create(struct nw_config** config);
int nw_config_readf(struct nw_config** config, FILE* f);
int nw_config_read(struct nw_config** config, const char* path);
+int nw_config_del(struct nw_config* config, const char* key);
+
+int nw_config_set(struct nw_config* config, const char* key, const char* value);
+
#endif /* NETWORKD_CONFIG_H */
--- /dev/null
+/*#############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2023 IPFire Network Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef NETWORKD_STRING_H
+#define NETWORKD_STRING_H
+
+#include <stdarg.h>
+
+static inline int __nw_string_vformat(char* s, const size_t length,
+ const char* format, va_list args) {
+ // Write string to buffer
+ const ssize_t required = vsnprintf(s, length, format, args);
+
+ // Catch any errors
+ if (required < 0)
+ return 1;
+
+ // Check if the entire string could be written
+ if ((size_t)required >= length) {
+ errno = ENOMEM;
+ return 1;
+ }
+
+ // Success
+ return 0;
+}
+
+#define nw_string_format(s, format, ...) \
+ __nw_string_format(s, sizeof(s), format, __VA_ARGS__)
+
+static inline int __nw_string_format(char* s, const size_t length,
+ const char* format, ...) {
+ va_list args;
+ int r;
+
+ // Call __nw_string_vformat
+ va_start(args, format);
+ r = __nw_string_vformat(s, length, format, args);
+ va_end(args);
+
+ return r;
+}
+
+#define nw_string_set(s, value) __nw_string_set(s, sizeof(s), value)
+
+static inline int __nw_string_set(char* s, const size_t length, const char* value) {
+ // If value is NULL, we will overwrite the buffer with just zeros
+ if (!value) {
+ for (unsigned int i = 0; i < length; i++)
+ s[i] = '\0';
+
+ return 0;
+ }
+
+ // Otherwise just copy
+ return __nw_string_format(s, length, "%s", value);
+}
+
+#endif /* NETWORKD_STRING_H */