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
12struct string_list {
13	char *buffer;
14	size_t len;
15	size_t cap;
16};
17
18static 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 */
55char *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
69cleanup:
70	errno = -ret;
71	if (errno) {
72		free(list.buffer);
73		return NULL;
74	}
75	return list.buffer ?: strdup("\0");
76}
77
78int 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
89int 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