]> git.ipfire.org Git - thirdparty/wireguard-tools.git/commitdiff
contrib: embedded-wg-library: add ability to add and del interfaces
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 21 Feb 2018 01:53:06 +0000 (02:53 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Wed, 21 Feb 2018 01:53:06 +0000 (02:53 +0100)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
contrib/embeddable-wg-library/test.c
contrib/embeddable-wg-library/wireguard.c
contrib/embeddable-wg-library/wireguard.h

index b738481f535872982e0fd3799692fc4d75e1e6d7..aad24de05ff86294006abe367cfad6532f164bd6 100644 (file)
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-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;
 }
index a7b25de508c10cd2500a513fbbcd76238d5685ff..692d285b1c683e50cc2207e16f3a0ac976d00a7b 100644 (file)
@@ -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;
index 514ede18f304403092a9ba4e0fe915cae2800332..350de7dd849f14be0c836000f7a849b7522965bd 100644 (file)
@@ -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);