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.c74
1 files changed, 70 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);
}