From 295c9ff274f489b3eaec8c4e342938eef864f769 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Feb 2018 02:53:06 +0100 Subject: [PATCH] contrib: embedded-wg-library: add ability to add and del interfaces Signed-off-by: Jason A. Donenfeld --- contrib/embeddable-wg-library/test.c | 39 ++++++++++++- contrib/embeddable-wg-library/wireguard.c | 71 ++++++++++++++++++++++- contrib/embeddable-wg-library/wireguard.h | 2 + 3 files changed, 109 insertions(+), 3 deletions(-) diff --git a/contrib/embeddable-wg-library/test.c b/contrib/embeddable-wg-library/test.c index b738481..aad24de 100644 --- a/contrib/embeddable-wg-library/test.c +++ b/contrib/embeddable-wg-library/test.c @@ -8,7 +8,7 @@ #include #include -int main(int argc, char *argv[]) +void list_devices(void) { char *device_names, *device_name; size_t len; @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) device_names = wg_list_device_names(); if (!device_names) { perror("Unable to get device names"); - return 1; + exit(1); } wg_for_each_device_name(device_names, device_name, len) { wg_device *device; @@ -36,5 +36,40 @@ int main(int argc, char *argv[]) wg_free_device(device); } free(device_names); +} + +int main(int argc, char *argv[]) +{ + wg_peer new_peer = { + .flags = WGPEER_HAS_PUBLIC_KEY | WGPEER_REPLACE_ALLOWEDIPS + }; + wg_device new_device = { + .name = "wgtest0", + .listen_port = 1234, + .flags = WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_LISTEN_PORT, + .first_peer = &new_peer, + .last_peer = &new_peer + }; + + wg_key_from_base64(new_device.private_key, "SFLKy56SOiFoAvQDSCBRrH/nyYonuAQnyr/JTQRPDlU="); + wg_key_from_base64(new_peer.public_key, "aNoLvvCfgbtTf4f2Eb/CWVNvIc5AJt/4C4pKrxMUZlM="); + + if (wg_add_device(new_device.name) < 0) { + perror("Unable to add device"); + exit(1); + } + + if (wg_set_device(&new_device) < 0) { + perror("Unable to set device"); + exit(1); + } + + list_devices(); + + if (wg_del_device(new_device.name) < 0) { + perror("Unable to delete device"); + exit(1); + } + return 0; } diff --git a/contrib/embeddable-wg-library/wireguard.c b/contrib/embeddable-wg-library/wireguard.c index a7b25de..692d285 100644 --- a/contrib/embeddable-wg-library/wireguard.c +++ b/contrib/embeddable-wg-library/wireguard.c @@ -910,7 +910,7 @@ static int parse_linkinfo(const struct nlattr *attr, void *data) { struct inflatable_buffer *buffer = data; - if (mnl_attr_get_type(attr) == IFLA_INFO_KIND && !strcmp("wireguard", mnl_attr_get_str(attr))) + if (mnl_attr_get_type(attr) == IFLA_INFO_KIND && !strcmp(WG_GENL_NAME, mnl_attr_get_str(attr))) buffer->good = true; return MNL_CB_OK; } @@ -1006,6 +1006,65 @@ cleanup: return ret; } +static int add_del_iface(const char *ifname, bool add) +{ + struct mnl_socket *nl = NULL; + char *rtnl_buffer; + ssize_t len; + int ret; + struct nlmsghdr *nlh; + struct ifinfomsg *ifm; + struct nlattr *nest; + + rtnl_buffer = calloc(MNL_SOCKET_BUFFER_SIZE, 1); + if (!rtnl_buffer) { + ret = -ENOMEM; + goto cleanup; + } + + nl = mnl_socket_open(NETLINK_ROUTE); + if (!nl) { + ret = -errno; + goto cleanup; + } + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + ret = -errno; + goto cleanup; + } + + nlh = mnl_nlmsg_put_header(rtnl_buffer); + nlh->nlmsg_type = add ? RTM_NEWLINK : RTM_DELLINK; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (add ? NLM_F_CREATE | NLM_F_EXCL : 0); + nlh->nlmsg_seq = time(NULL); + ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); + ifm->ifi_family = AF_UNSPEC; + mnl_attr_put_strz(nlh, IFLA_IFNAME, ifname); + nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO); + mnl_attr_put_strz(nlh, IFLA_INFO_KIND, WG_GENL_NAME); + mnl_attr_nest_end(nlh, nest); + + if (mnl_socket_sendto(nl, rtnl_buffer, nlh->nlmsg_len) < 0) { + ret = -errno; + goto cleanup; + } + if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, MNL_SOCKET_BUFFER_SIZE)) < 0) { + ret = -errno; + goto cleanup; + } + if (mnl_cb_run(rtnl_buffer, len, nlh->nlmsg_seq, mnl_socket_get_portid(nl), NULL, NULL) < 0) { + ret = -errno; + goto cleanup; + } + ret = 0; + +cleanup: + free(rtnl_buffer); + if (nl) + mnl_socket_close(nl); + return ret; +} + int wg_set_device(wg_device *dev) { int ret = 0; @@ -1424,6 +1483,16 @@ err: return buffer.buffer; } +int wg_add_device(const char *device_name) +{ + return add_del_iface(device_name, true); +} + +int wg_del_device(const char *device_name) +{ + return add_del_iface(device_name, false); +} + void wg_free_device(wg_device *dev) { wg_peer *peer, *np; diff --git a/contrib/embeddable-wg-library/wireguard.h b/contrib/embeddable-wg-library/wireguard.h index 514ede1..350de7d 100644 --- a/contrib/embeddable-wg-library/wireguard.h +++ b/contrib/embeddable-wg-library/wireguard.h @@ -83,6 +83,8 @@ typedef struct wg_device { int wg_set_device(wg_device *dev); int wg_get_device(wg_device **dev, const char *device_name); +int wg_add_device(const char *device_name); +int wg_del_device(const char *device_name); void wg_free_device(wg_device *dev); char *wg_list_device_names(void); /* first\0second\0third\0forth\0last\0\0 */ void wg_key_to_base64(wg_key_b64_string base64, const wg_key key);