From: Michael Tremer Date: Mon, 30 Jan 2023 03:04:01 +0000 (+0000) Subject: networkd: Implement setting configuration values X-Git-Url: http://git.ipfire.org/?p=network.git;a=commitdiff_plain;h=4237caa2ed47385e3471822348d908846c745b29 networkd: Implement setting configuration values Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 50a6034a..1b18f62b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -311,7 +311,8 @@ dist_networkd_SOURCES = \ 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) diff --git a/src/networkd/config.c b/src/networkd/config.c index e808531b..72a0cfbb 100644 --- a/src/networkd/config.c +++ b/src/networkd/config.c @@ -18,17 +18,72 @@ # # #############################################################################*/ +#include #include #include +#include +#include #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); } @@ -40,6 +95,9 @@ int nw_config_create(struct nw_config** config) { // Initialize reference counter c->nrefs = 1; + // Initialise entries + STAILQ_INIT(&c->entries); + *config = c; return 0; @@ -106,3 +164,59 @@ ERROR: 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); +} diff --git a/src/networkd/config.h b/src/networkd/config.h index 559ba948..a793229c 100644 --- a/src/networkd/config.h +++ b/src/networkd/config.h @@ -21,6 +21,9 @@ #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); @@ -31,4 +34,8 @@ struct nw_config* nw_config_unref(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 */ diff --git a/src/networkd/string.h b/src/networkd/string.h new file mode 100644 index 00000000..3ac4846d --- /dev/null +++ b/src/networkd/string.h @@ -0,0 +1,76 @@ +/*############################################################################# +# # +# 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 . # +# # +#############################################################################*/ + +#ifndef NETWORKD_STRING_H +#define NETWORKD_STRING_H + +#include + +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 */