xref: /freebsd/contrib/wireguard-tools/ipc.c (revision ccb59683b98360afaf5b5bb641a68fea22c68d0b)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4  */
5 
6 #include <string.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include "containers.h"
10 #include "ipc.h"
11 
12 struct string_list {
13 	char *buffer;
14 	size_t len;
15 	size_t cap;
16 };
17 
18 static int string_list_add(struct string_list *list, const char *str)
19 {
20 	size_t len = strlen(str) + 1;
21 
22 	if (len == 1)
23 		return 0;
24 
25 	if (len >= list->cap - list->len) {
26 		char *new_buffer;
27 		size_t new_cap = list->cap * 2;
28 
29 		if (new_cap < list->len + len + 1)
30 			new_cap = list->len + len + 1;
31 		new_buffer = realloc(list->buffer, new_cap);
32 		if (!new_buffer)
33 			return -errno;
34 		list->buffer = new_buffer;
35 		list->cap = new_cap;
36 	}
37 	memcpy(list->buffer + list->len, str, len);
38 	list->len += len;
39 	list->buffer[list->len] = '\0';
40 	return 0;
41 }
42 
43 #include "ipc-uapi.h"
44 #if defined(__linux__)
45 #include "ipc-linux.h"
46 #elif defined(__OpenBSD__)
47 #include "ipc-openbsd.h"
48 #elif defined(__FreeBSD__)
49 #include "ipc-freebsd.h"
50 #elif defined(_WIN32)
51 #include "ipc-windows.h"
52 #endif
53 
54 /* first\0second\0third\0forth\0last\0\0 */
55 char *ipc_list_devices(void)
56 {
57 	struct string_list list = { 0 };
58 	int ret;
59 
60 #ifdef IPC_SUPPORTS_KERNEL_INTERFACE
61 	ret = kernel_get_wireguard_interfaces(&list);
62 	if (ret < 0)
63 		goto cleanup;
64 #endif
65 	ret = userspace_get_wireguard_interfaces(&list);
66 	if (ret < 0)
67 		goto cleanup;
68 
69 cleanup:
70 	errno = -ret;
71 	if (errno) {
72 		free(list.buffer);
73 		return NULL;
74 	}
75 	return list.buffer ?: strdup("\0");
76 }
77 
78 int ipc_get_device(struct wgdevice **dev, const char *iface)
79 {
80 #ifdef IPC_SUPPORTS_KERNEL_INTERFACE
81 	if (userspace_has_wireguard_interface(iface))
82 		return userspace_get_device(dev, iface);
83 	return kernel_get_device(dev, iface);
84 #else
85 	return userspace_get_device(dev, iface);
86 #endif
87 }
88 
89 int ipc_set_device(struct wgdevice *dev)
90 {
91 #ifdef IPC_SUPPORTS_KERNEL_INTERFACE
92 	if (userspace_has_wireguard_interface(dev->name))
93 		return userspace_set_device(dev);
94 	return kernel_set_device(dev);
95 #else
96 	return userspace_set_device(dev);
97 #endif
98 }
99