#include "device-common.h" #include "netlink.h" #include "util.h" #include #include #include #include #include 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) { 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; } 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)) static void bridge_constructor(void) { register_device_type("bridge", &device_type_bridge); }