summaryrefslogtreecommitdiffstats
path: root/src/device-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/device-common.c')
-rw-r--r--src/device-common.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/device-common.c b/src/device-common.c
new file mode 100644
index 0000000..4a10bf5
--- /dev/null
+++ b/src/device-common.c
@@ -0,0 +1,121 @@
+#include "device-common.h"
+#include "util.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arpa/inet.h>
+
+static unsigned long strtoul_safe(const char *str) {
+ char *endptr;
+
+ errno = 0;
+ unsigned long val = strtoul(str, &endptr, 10);
+ if (endptr == str || *endptr)
+ errno = EINVAL;
+
+ return val;
+}
+
+static bool parse_address(ipaddr_t *addr, const char *str) {
+ if (inet_pton(AF_INET, str, &addr->addr4)) {
+ addr->af = AF_INET;
+ return true;
+ }
+
+ if (inet_pton(AF_INET6, str, &addr->addr6)) {
+ addr->af = AF_INET6;
+ return true;
+ }
+
+ return false;
+}
+
+static bool parse_prefix(ipaddr_prefix_t *prefix, const char *str, bool allow_host) {
+ const char *slash = strrchr(str, '/');
+ if (!slash)
+ return false;
+
+ size_t len = slash - str;
+ char buf[len+1];
+ memcpy(buf, str, len);
+ buf[len] = 0;
+
+ if (!parse_address(&prefix->addr, buf))
+ return false;
+
+ long plen = strtoul_safe(slash + 1);
+ if (errno)
+ return false;
+
+ switch (prefix->addr.af) {
+ case AF_INET:
+ if (plen > 32)
+ return false;
+ break;
+
+ case AF_INET6:
+ if (plen > 128)
+ return false;
+ break;
+
+ default:
+ assert(false);
+ __builtin_unreachable();
+ }
+
+ prefix->plen = plen;
+
+ // TODO: Implement allow_host
+
+ return true;
+}
+
+static bool process_section_device(device_common_t *device, struct json_object *section) {
+ return true;
+}
+
+static bool process_section_static(device_common_t *device, struct json_object *section) {
+ struct json_object *addresses = neco_json_get_value(section, "addresses", json_type_array);
+ if (addresses) {
+ for (size_t i = 0; i < json_object_array_length(addresses); i++) {
+ struct json_object *address = json_object_array_get_idx(addresses, i);
+ if (!json_object_is_type(address, json_type_string)) {
+ fprintf(stderr, "interface: static: invalid address entry of type %s\n", json_type_to_name(json_object_get_type(address)));
+ continue;
+ }
+
+ ipaddr_prefix_t p;
+ if (!parse_prefix(&p, json_object_get_string(address), true)) {
+ fprintf(stderr, "interface: static: unable to parse Address %s\n", json_object_get_string(address));
+ break;
+ }
+
+ if (!VECTOR_ADD(device->addrs, p)) {
+ fprintf(stderr, "interface: static: adding address failed\n");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool device_common_process_config(device_common_t *device, struct json_object *config) {
+ struct json_object *sec_device = neco_json_get_value(config, "device", json_type_object);
+ if (sec_device) {
+ if (!process_section_device(device, sec_device))
+ return false;
+ }
+
+ struct json_object *sec_static = neco_json_get_value(config, "static", json_type_object);
+ if (sec_static) {
+ if (!process_section_static(device, sec_static))
+ return false;
+ }
+
+ return true;
+}