| // SPDX-License-Identifier: GPL-2.0 OR MIT |
| /* |
| * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. |
| */ |
| |
| #include <string.h> |
| #include <stdlib.h> |
| #include <errno.h> |
| #include "containers.h" |
| #include "ipc.h" |
| |
| struct string_list { |
| char *buffer; |
| size_t len; |
| size_t cap; |
| }; |
| |
| static int string_list_add(struct string_list *list, const char *str) |
| { |
| size_t len = strlen(str) + 1; |
| |
| if (len == 1) |
| return 0; |
| |
| if (len >= list->cap - list->len) { |
| char *new_buffer; |
| size_t new_cap = list->cap * 2; |
| |
| if (new_cap < list->len + len + 1) |
| new_cap = list->len + len + 1; |
| new_buffer = realloc(list->buffer, new_cap); |
| if (!new_buffer) |
| return -errno; |
| list->buffer = new_buffer; |
| list->cap = new_cap; |
| } |
| memcpy(list->buffer + list->len, str, len); |
| list->len += len; |
| list->buffer[list->len] = '\0'; |
| return 0; |
| } |
| |
| #include "ipc-uapi.h" |
| #if defined(__linux__) |
| #include "ipc-linux.h" |
| #elif defined(__OpenBSD__) |
| #include "ipc-openbsd.h" |
| #elif defined(__FreeBSD__) |
| #include "ipc-freebsd.h" |
| #elif defined(_WIN32) |
| #include "ipc-windows.h" |
| #endif |
| |
| /* first\0second\0third\0forth\0last\0\0 */ |
| char *ipc_list_devices(void) |
| { |
| struct string_list list = { 0 }; |
| int ret; |
| |
| #ifdef IPC_SUPPORTS_KERNEL_INTERFACE |
| ret = kernel_get_wireguard_interfaces(&list); |
| if (ret < 0) |
| goto cleanup; |
| #endif |
| ret = userspace_get_wireguard_interfaces(&list); |
| if (ret < 0) |
| goto cleanup; |
| |
| cleanup: |
| errno = -ret; |
| if (errno) { |
| free(list.buffer); |
| return NULL; |
| } |
| return list.buffer ?: strdup("\0"); |
| } |
| |
| int ipc_get_device(struct wgdevice **dev, const char *iface) |
| { |
| #ifdef IPC_SUPPORTS_KERNEL_INTERFACE |
| if (userspace_has_wireguard_interface(iface)) |
| return userspace_get_device(dev, iface); |
| return kernel_get_device(dev, iface); |
| #else |
| return userspace_get_device(dev, iface); |
| #endif |
| } |
| |
| int ipc_set_device(struct wgdevice *dev) |
| { |
| #ifdef IPC_SUPPORTS_KERNEL_INTERFACE |
| if (userspace_has_wireguard_interface(dev->name)) |
| return userspace_set_device(dev); |
| return kernel_set_device(dev); |
| #else |
| return userspace_set_device(dev); |
| #endif |
| } |