diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2019-06-01 19:10:17 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2019-06-01 19:10:17 +0200 |
commit | 29f3ef36af7bb387a51fe8ad968d9770d3b54a6d (patch) | |
tree | 82509a3a4792010f27395ec99e57b6dfcf45f3fd | |
parent | 8d15854eb57c8a16523a986aa72e3a2c993a8c50 (diff) | |
download | neco-29f3ef36af7bb387a51fe8ad968d9770d3b54a6d.tar neco-29f3ef36af7bb387a51fe8ad968d9770d3b54a6d.zip |
-rw-r--r-- | src/device-common.c | 74 | ||||
-rw-r--r-- | src/device-common.h | 2 |
2 files changed, 72 insertions, 4 deletions
diff --git a/src/device-common.c b/src/device-common.c index 9e7605e..1dc4490 100644 --- a/src/device-common.c +++ b/src/device-common.c @@ -109,6 +109,14 @@ static bool process_section_static(device_common_t *device, struct json_object * return true; } +static bool process_section_bridge(device_common_t *device, struct json_object *section) { + const char *master = neco_json_get_string(section, "master"); + if (master) + strncpy(device->master, master, sizeof(device->master)-1); + + 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) { @@ -122,6 +130,12 @@ bool device_common_process_config(device_common_t *device, struct json_object *c return false; } + struct json_object *sec_bridge = neco_json_get_value(config, "bridge", json_type_object); + if (sec_bridge) { + if (!process_section_bridge(device, sec_bridge)) + return false; + } + return true; } @@ -218,16 +232,68 @@ static bool device_common_set_ipaddr(unsigned ifindex, ipaddr_prefix_t *addr, bo return true; } + +static bool device_common_set_master(unsigned ifindex, unsigned master) { + char buf[MNL_SOCKET_BUFFER_SIZE]; + + struct mnl_socket *nl = nl_socket(); + + struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = RTM_SETLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + int seq = nlh->nlmsg_seq = nl_seq(); + + struct ifinfomsg *ifi = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifi)); + ifi->ifi_index = ifindex; + ifi->ifi_family = AF_UNSPEC; + + mnl_attr_put_u32(nlh, IFLA_MASTER, master); + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror("mnl_socket_sendto"); + return false; + } + + int ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + if (ret == -1) { + perror("mnl_socket_recvfrom"); + return false; + } + + ret = mnl_cb_run(buf, ret, seq, mnl_socket_get_portid(nl), NULL, NULL); + if (ret == -1) { + perror("mnl_cb_run"); + return false; + } + + return true; +} + void device_common_init(device_common_t *device, int ifindex) { + if (*device->master) { + unsigned master = if_nametoindex(device->master); + if (!master) + return; + + device_common_set_master(ifindex, master); + } + device_common_set_link_state(ifindex, true); - for (size_t i = 0; i < VECTOR_LEN(device->addrs); i++) - device_common_set_ipaddr(ifindex, &VECTOR_INDEX(device->addrs, i), true); + if (!*device->master) { + for (size_t i = 0; i < VECTOR_LEN(device->addrs); i++) + device_common_set_ipaddr(ifindex, &VECTOR_INDEX(device->addrs, i), true); + } } void device_common_release(device_common_t *device, int ifindex) { - for (size_t i = 0; i < VECTOR_LEN(device->addrs); i++) - device_common_set_ipaddr(ifindex, &VECTOR_INDEX(device->addrs, i), false); + if (!*device->master) { + for (size_t i = 0; i < VECTOR_LEN(device->addrs); i++) + device_common_set_ipaddr(ifindex, &VECTOR_INDEX(device->addrs, i), false); + } device_common_set_link_state(ifindex, false); + + if (*device->master) + device_common_set_master(ifindex, 0); } diff --git a/src/device-common.h b/src/device-common.h index 398c5a1..dc0fe28 100644 --- a/src/device-common.h +++ b/src/device-common.h @@ -3,6 +3,7 @@ #include "device.h" #include "vector.h" +#include <net/if.h> #include <netinet/ether.h> #include <netinet/in.h> @@ -26,6 +27,7 @@ typedef struct _device_common { uint16_t mtu; ipaddr_prefix_vector_t addrs; + char master[IF_NAMESIZE]; } device_common_t; bool device_common_process_config(device_common_t *device, struct json_object *config); |