device: split out common device settings
This commit is contained in:
parent
7745aa34ad
commit
f43788c947
4 changed files with 162 additions and 161 deletions
121
src/device-common.c
Normal file
121
src/device-common.c
Normal file
|
@ -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;
|
||||||
|
}
|
31
src/device-common.h
Normal file
31
src/device-common.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
typedef struct _ipaddr {
|
||||||
|
int af;
|
||||||
|
union {
|
||||||
|
struct in_addr addr4;
|
||||||
|
struct in6_addr addr6;
|
||||||
|
};
|
||||||
|
} ipaddr_t;
|
||||||
|
|
||||||
|
typedef struct _ipprefix {
|
||||||
|
ipaddr_t addr;
|
||||||
|
uint8_t plen;
|
||||||
|
} ipaddr_prefix_t;
|
||||||
|
|
||||||
|
typedef VECTOR(ipaddr_prefix_t) ipaddr_prefix_vector_t;
|
||||||
|
|
||||||
|
typedef struct _device_common {
|
||||||
|
struct ether_addr macaddr;
|
||||||
|
uint16_t mtu;
|
||||||
|
|
||||||
|
ipaddr_prefix_vector_t addrs;
|
||||||
|
} device_common_t;
|
||||||
|
|
||||||
|
bool device_common_process_config(device_common_t *device, struct json_object *config);
|
|
@ -1,17 +1,13 @@
|
||||||
#include "device.h"
|
#include "device-common.h"
|
||||||
#include "netlink.h"
|
#include "netlink.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/ether.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/if_link.h>
|
#include <linux/if_link.h>
|
||||||
|
@ -19,158 +15,19 @@
|
||||||
|
|
||||||
static device_type_t device_type_interface;
|
static device_type_t device_type_interface;
|
||||||
|
|
||||||
typedef struct _ipaddr {
|
|
||||||
int af;
|
|
||||||
union {
|
|
||||||
struct in_addr addr4;
|
|
||||||
struct in6_addr addr6;
|
|
||||||
};
|
|
||||||
} ipaddr_t;
|
|
||||||
|
|
||||||
typedef struct _ipprefix {
|
|
||||||
ipaddr_t addr;
|
|
||||||
uint8_t plen;
|
|
||||||
} ipaddr_prefix_t;
|
|
||||||
|
|
||||||
typedef VECTOR(ipaddr_prefix_t) ipaddr_prefix_vector_t;
|
|
||||||
|
|
||||||
typedef struct _device_interface {
|
typedef struct _device_interface {
|
||||||
device_t device;
|
device_t device;
|
||||||
|
device_common_t common;
|
||||||
struct ether_addr macaddr;
|
|
||||||
uint16_t mtu;
|
|
||||||
|
|
||||||
ipaddr_prefix_vector_t addrs;
|
|
||||||
} device_interface_t;
|
} device_interface_t;
|
||||||
|
|
||||||
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 void interface_free(device_t *dev) {
|
static void interface_free(device_t *dev) {
|
||||||
device_interface_t *iface = container_of(dev, device_interface_t, device);
|
device_interface_t *iface = container_of(dev, device_interface_t, device);
|
||||||
|
|
||||||
VECTOR_FREE(iface->addrs);
|
VECTOR_FREE(iface->common.addrs);
|
||||||
free(NODE_NAME(dev));
|
free(NODE_NAME(dev));
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool process_section_device(device_interface_t *iface, struct json_object *section) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool process_section_static(device_interface_t *iface, 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(iface->addrs, p)) {
|
|
||||||
fprintf(stderr, "interface: static: adding address failed\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
list_for_each_entry(field, §ion->fields, node) {
|
|
||||||
switch (lookup_keyword(field->key)) {
|
|
||||||
case KW_Address: {
|
|
||||||
ipaddr_prefix_t p;
|
|
||||||
if (!parse_prefix(&p, field->value, true)) {
|
|
||||||
fprintf(stderr, "interface: [Static]: unable to parse Address %s\n", field->value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!VECTOR_ADD(iface->addrs, p)) {
|
|
||||||
fprintf(stderr, "interface: [Static]: adding address failed\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "interface: [Static]: unknown field %s\n", field->key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static device_t * interface_process_config(const char *name, struct json_object *config) {
|
static device_t * interface_process_config(const char *name, struct json_object *config) {
|
||||||
device_interface_t *iface = calloc(1, sizeof(*iface));
|
device_interface_t *iface = calloc(1, sizeof(*iface));
|
||||||
if (!iface)
|
if (!iface)
|
||||||
|
@ -185,17 +42,8 @@ static device_t * interface_process_config(const char *name, struct json_object
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct json_object *sec_device = neco_json_get_value(config, "device", json_type_object);
|
if (!device_common_process_config(&iface->common, config))
|
||||||
if (sec_device) {
|
goto err;
|
||||||
if (!process_section_device(iface, sec_device))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct json_object *sec_static = neco_json_get_value(config, "static", json_type_object);
|
|
||||||
if (sec_static) {
|
|
||||||
if (!process_section_static(iface, sec_static))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
|
@ -307,8 +155,8 @@ static void interface_init(device_t *dev) {
|
||||||
|
|
||||||
interface_set_link_state(index, true);
|
interface_set_link_state(index, true);
|
||||||
|
|
||||||
for (size_t i = 0; i < VECTOR_LEN(iface->addrs); i++)
|
for (size_t i = 0; i < VECTOR_LEN(iface->common.addrs); i++)
|
||||||
interface_set_ipaddr(index, &VECTOR_INDEX(iface->addrs, i), true);
|
interface_set_ipaddr(index, &VECTOR_INDEX(iface->common.addrs, i), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void interface_update(device_t *dev) {
|
static void interface_update(device_t *dev) {
|
||||||
|
@ -321,8 +169,8 @@ static void interface_release(device_t *dev) {
|
||||||
if (!index)
|
if (!index)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t i = 0; i < VECTOR_LEN(iface->addrs); i++)
|
for (size_t i = 0; i < VECTOR_LEN(iface->common.addrs); i++)
|
||||||
interface_set_ipaddr(index, &VECTOR_INDEX(iface->addrs, i), false);
|
interface_set_ipaddr(index, &VECTOR_INDEX(iface->common.addrs, i), false);
|
||||||
|
|
||||||
interface_set_link_state(index, false);
|
interface_set_link_state(index, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ src = [
|
||||||
'config-process.c',
|
'config-process.c',
|
||||||
'device.c',
|
'device.c',
|
||||||
'device-bridge.c',
|
'device-bridge.c',
|
||||||
|
'device-common.c',
|
||||||
'device-interface.c',
|
'device-interface.c',
|
||||||
'netlink.c',
|
'netlink.c',
|
||||||
'vector.c',
|
'vector.c',
|
||||||
|
|
Reference in a new issue