device: bridge: implement initial bridge setup

This commit is contained in:
Matthias Schiffer 2019-06-01 14:28:03 +02:00
parent 8b5af11ebe
commit 8d15854eb5
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C

View file

@ -1,14 +1,128 @@
#include "device.h" #include "device-common.h"
#include "netlink.h"
#include "util.h"
#include <stdio.h> #include <string.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/if_link.h>
#include <linux/rtnetlink.h>
static device_type_t device_type_bridge;
typedef struct _device_bridge {
device_t device;
device_common_t common;
} device_bridge_t;
static void bridge_free(device_t *dev) {
device_bridge_t *iface = container_of(dev, device_bridge_t, device);
VECTOR_FREE(iface->common.addrs);
free(NODE_NAME(dev));
free(iface);
}
static device_t * bridge_process_config(const char *name, struct json_object *config) { static device_t * bridge_process_config(const char *name, struct json_object *config) {
printf("Bridge: %s\n", name); device_bridge_t *iface = calloc(1, sizeof(*iface));
if (!iface)
return NULL;
device_t *dev = &iface->device;
dev->type = &device_type_bridge;
NODE_NAME(dev) = strdup(name);
if (!NODE_NAME(dev)) {
free(iface);
return NULL;
}
if (!device_common_process_config(&iface->common, config))
goto err;
return dev;
err:
bridge_free(dev);
return NULL; return NULL;
} }
device_type_t device_type_bridge = { static bool bridge_nl_create(device_bridge_t *bridge) {
char buf[MNL_SOCKET_BUFFER_SIZE];
struct mnl_socket *nl = nl_socket();
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = RTM_NEWLINK;
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE;
int seq = nlh->nlmsg_seq = nl_seq();
struct ifinfomsg *ifi = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifi));
ifi->ifi_family = AF_UNSPEC;
mnl_attr_put_str(nlh, IFLA_IFNAME, NODE_NAME(&bridge->device));
struct nlattr *linkinfo = mnl_attr_nest_start(nlh, IFLA_LINKINFO);
mnl_attr_put_str(nlh, IFLA_INFO_KIND, "bridge");
mnl_attr_nest_end(nlh, linkinfo);
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;
}
static void bridge_init(device_t *dev) {
device_bridge_t *bridge = container_of(dev, device_bridge_t, device);
if (!bridge_nl_create(bridge))
return;
unsigned ifindex = if_nametoindex(NODE_NAME(dev));
if (!ifindex)
return;
device_common_init(&bridge->common, ifindex);
}
static void bridge_update(device_t *dev) {
}
static void bridge_release(device_t *dev) {
/*
device_bridge_t *bridge = container_of(dev, device_bridge_t, device);
unsigned ifindex = if_nametoindex(NODE_NAME(dev));
if (!ifindex)
return;
device_common_release(&bridge->common, ifindex);
*/
}
static device_type_t device_type_bridge = {
.process_config = bridge_process_config, .process_config = bridge_process_config,
.free = bridge_free,
.init = bridge_init,
.update = bridge_update,
.release = bridge_release,
}; };
__attribute__((constructor)) __attribute__((constructor))