device: bridge: implement initial bridge setup
This commit is contained in:
parent
8b5af11ebe
commit
8d15854eb5
1 changed files with 118 additions and 4 deletions
|
@ -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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
.free = bridge_free,
|
||||
|
||||
.init = bridge_init,
|
||||
.update = bridge_update,
|
||||
.release = bridge_release,
|
||||
};
|
||||
|
||||
__attribute__((constructor))
|
||||
|
|
Reference in a new issue