summaryrefslogtreecommitdiffstats
path: root/src/device-common.c
blob: 4a10bf547f42484d253e71c695e4122d2c00d337 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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;
}