contrib: embedded-wg-library: add ability to add and del interfaces
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									d29e0bad7d
								
							
						
					
					
						commit
						295c9ff274
					
				
					 3 changed files with 109 additions and 3 deletions
				
			
		| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[])
 | 
					void list_devices(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *device_names, *device_name;
 | 
						char *device_names, *device_name;
 | 
				
			||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ int main(int argc, char *argv[])
 | 
				
			||||||
	device_names = wg_list_device_names();
 | 
						device_names = wg_list_device_names();
 | 
				
			||||||
	if (!device_names) {
 | 
						if (!device_names) {
 | 
				
			||||||
		perror("Unable to get device names");
 | 
							perror("Unable to get device names");
 | 
				
			||||||
		return 1;
 | 
							exit(1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wg_for_each_device_name(device_names, device_name, len) {
 | 
						wg_for_each_device_name(device_names, device_name, len) {
 | 
				
			||||||
		wg_device *device;
 | 
							wg_device *device;
 | 
				
			||||||
| 
						 | 
					@ -36,5 +36,40 @@ int main(int argc, char *argv[])
 | 
				
			||||||
		wg_free_device(device);
 | 
							wg_free_device(device);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	free(device_names);
 | 
						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;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -910,7 +910,7 @@ static int parse_linkinfo(const struct nlattr *attr, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inflatable_buffer *buffer = 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;
 | 
							buffer->good = true;
 | 
				
			||||||
	return MNL_CB_OK;
 | 
						return MNL_CB_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1006,6 +1006,65 @@ cleanup:
 | 
				
			||||||
	return ret;
 | 
						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 wg_set_device(wg_device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
| 
						 | 
					@ -1424,6 +1483,16 @@ err:
 | 
				
			||||||
	return buffer.buffer;
 | 
						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)
 | 
					void wg_free_device(wg_device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	wg_peer *peer, *np;
 | 
						wg_peer *peer, *np;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,8 @@ typedef struct wg_device {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int wg_set_device(wg_device *dev);
 | 
					int wg_set_device(wg_device *dev);
 | 
				
			||||||
int wg_get_device(wg_device **dev, const char *device_name);
 | 
					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);
 | 
					void wg_free_device(wg_device *dev);
 | 
				
			||||||
char *wg_list_device_names(void); /* first\0second\0third\0forth\0last\0\0 */
 | 
					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);
 | 
					void wg_key_to_base64(wg_key_b64_string base64, const wg_key key);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue