diff options
Diffstat (limited to 'src/device-common.c')
-rw-r--r-- | src/device-common.c | 121 |
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; +} |