device: move more common functions
This commit is contained in:
parent
f43788c947
commit
8b5af11ebe
3 changed files with 121 additions and 111 deletions
|
@ -1,4 +1,5 @@
|
||||||
#include "device-common.h"
|
#include "device-common.h"
|
||||||
|
#include "netlink.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -9,6 +10,10 @@
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
static unsigned long strtoul_safe(const char *str) {
|
static unsigned long strtoul_safe(const char *str) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
|
@ -119,3 +124,110 @@ bool device_common_process_config(device_common_t *device, struct json_object *c
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool device_common_set_link_flags(unsigned ifindex, unsigned change, unsigned flags) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
ifi->ifi_change = change;
|
||||||
|
ifi->ifi_flags = flags;
|
||||||
|
|
||||||
|
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 bool device_common_set_link_state(unsigned ifindex, bool up) {
|
||||||
|
return device_common_set_link_flags(ifindex, IFF_UP, up ? IFF_UP : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool device_common_set_ipaddr(unsigned ifindex, ipaddr_prefix_t *addr, bool add) {
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
struct mnl_socket *nl = nl_socket();
|
||||||
|
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = add ? RTM_NEWADDR : RTM_DELADDR;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
if (add)
|
||||||
|
nlh->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
|
||||||
|
|
||||||
|
int seq = nlh->nlmsg_seq = nl_seq();
|
||||||
|
|
||||||
|
struct ifaddrmsg *ifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa));
|
||||||
|
ifa->ifa_index = ifindex;
|
||||||
|
ifa->ifa_family = addr->addr.af;
|
||||||
|
|
||||||
|
ifa->ifa_prefixlen = addr->plen;
|
||||||
|
|
||||||
|
switch (addr->addr.af) {
|
||||||
|
case AF_INET:
|
||||||
|
mnl_attr_put(nlh, IFA_LOCAL, 4, &addr->addr.addr4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AF_INET6:
|
||||||
|
mnl_attr_put(nlh, IFA_LOCAL, 16, &addr->addr.addr6);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
device_common_set_link_state(ifindex, false);
|
||||||
|
}
|
||||||
|
|
|
@ -29,3 +29,6 @@ typedef struct _device_common {
|
||||||
} device_common_t;
|
} device_common_t;
|
||||||
|
|
||||||
bool device_common_process_config(device_common_t *device, struct json_object *config);
|
bool device_common_process_config(device_common_t *device, struct json_object *config);
|
||||||
|
|
||||||
|
void device_common_init(device_common_t *device, int ifindex);
|
||||||
|
void device_common_release(device_common_t *device, int ifindex);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "device-common.h"
|
#include "device-common.h"
|
||||||
#include "netlink.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
|
@ -9,10 +8,6 @@
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
#include <linux/if.h>
|
|
||||||
#include <linux/if_link.h>
|
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
|
|
||||||
static device_type_t device_type_interface;
|
static device_type_t device_type_interface;
|
||||||
|
|
||||||
typedef struct _device_interface {
|
typedef struct _device_interface {
|
||||||
|
@ -52,111 +47,14 @@ err:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool interface_set_link_flags(unsigned index, unsigned change, unsigned flags) {
|
|
||||||
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 = index;
|
|
||||||
ifi->ifi_family = AF_UNSPEC;
|
|
||||||
|
|
||||||
ifi->ifi_change = change;
|
|
||||||
ifi->ifi_flags = flags;
|
|
||||||
|
|
||||||
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 bool interface_set_link_state(unsigned index, bool up) {
|
|
||||||
return interface_set_link_flags(index, IFF_UP, up ? IFF_UP : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool interface_set_ipaddr(unsigned index, ipaddr_prefix_t *addr, bool add) {
|
|
||||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
|
||||||
|
|
||||||
struct mnl_socket *nl = nl_socket();
|
|
||||||
|
|
||||||
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
|
||||||
nlh->nlmsg_type = add ? RTM_NEWADDR : RTM_DELADDR;
|
|
||||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
|
||||||
if (add)
|
|
||||||
nlh->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
|
|
||||||
|
|
||||||
int seq = nlh->nlmsg_seq = nl_seq();
|
|
||||||
|
|
||||||
struct ifaddrmsg *ifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa));
|
|
||||||
ifa->ifa_index = index;
|
|
||||||
ifa->ifa_family = addr->addr.af;
|
|
||||||
|
|
||||||
ifa->ifa_prefixlen = addr->plen;
|
|
||||||
|
|
||||||
switch (addr->addr.af) {
|
|
||||||
case AF_INET:
|
|
||||||
mnl_attr_put(nlh, IFA_LOCAL, 4, &addr->addr.addr4);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AF_INET6:
|
|
||||||
mnl_attr_put(nlh, IFA_LOCAL, 16, &addr->addr.addr6);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
errno = EINVAL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 interface_init(device_t *dev) {
|
static void interface_init(device_t *dev) {
|
||||||
device_interface_t *iface = container_of(dev, device_interface_t, device);
|
device_interface_t *iface = container_of(dev, device_interface_t, device);
|
||||||
|
|
||||||
unsigned index = if_nametoindex(NODE_NAME(dev));
|
unsigned ifindex = if_nametoindex(NODE_NAME(dev));
|
||||||
if (!index)
|
if (!ifindex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
interface_set_link_state(index, true);
|
device_common_init(&iface->common, ifindex);
|
||||||
|
|
||||||
for (size_t i = 0; i < VECTOR_LEN(iface->common.addrs); i++)
|
|
||||||
interface_set_ipaddr(index, &VECTOR_INDEX(iface->common.addrs, i), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void interface_update(device_t *dev) {
|
static void interface_update(device_t *dev) {
|
||||||
|
@ -165,14 +63,11 @@ static void interface_update(device_t *dev) {
|
||||||
static void interface_release(device_t *dev) {
|
static void interface_release(device_t *dev) {
|
||||||
device_interface_t *iface = container_of(dev, device_interface_t, device);
|
device_interface_t *iface = container_of(dev, device_interface_t, device);
|
||||||
|
|
||||||
unsigned index = if_nametoindex(NODE_NAME(dev));
|
unsigned ifindex = if_nametoindex(NODE_NAME(dev));
|
||||||
if (!index)
|
if (!ifindex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t i = 0; i < VECTOR_LEN(iface->common.addrs); i++)
|
device_common_release(&iface->common, ifindex);
|
||||||
interface_set_ipaddr(index, &VECTOR_INDEX(iface->common.addrs, i), false);
|
|
||||||
|
|
||||||
interface_set_link_state(index, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static device_type_t device_type_interface = {
|
static device_type_t device_type_interface = {
|
||||||
|
|
Reference in a new issue