Skip to content

Commit d4a32c9

Browse files
committed
ipc: cleanup openbsd support
We also add a wg_if.h in the fallback include path. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 parent 5c66f6e commit d4a32c9

5 files changed

Lines changed: 212 additions & 94 deletions

File tree

src/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ endif
3838
PLATFORM ?= $(shell uname -s | tr '[:upper:]' '[:lower:]')
3939

4040
CFLAGS ?= -O3
41-
CFLAGS += -idirafter uapi
41+
ifneq ($(wildcard uapi/$(PLATFORM)/.),)
42+
CFLAGS += -idirafter uapi/$(PLATFORM)
43+
endif
4244
CFLAGS += -std=gnu99 -D_GNU_SOURCE
4345
CFLAGS += -Wall -Wextra
4446
CFLAGS += -MMD -MP

src/containers.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@
1212
#include <sys/socket.h>
1313
#include <net/if.h>
1414
#include <netinet/in.h>
15+
#if defined(__linux__)
1516
#include <linux/wireguard.h>
17+
#elif defined(__OpenBSD__)
18+
#include <net/if_wg.h>
19+
#endif
20+
21+
#ifndef WG_KEY_LEN
22+
#define WG_KEY_LEN 32
23+
#endif
1624

1725
/* Cross platform __kernel_timespec */
1826
struct timespec64 {

src/ipc.c

Lines changed: 100 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ static void coalesce_peers(struct wgdevice *device)
862862
struct wgpeer *old_next_peer, *peer = device->first_peer;
863863

864864
while (peer && peer->next_peer) {
865-
if (memcmp(peer->public_key, peer->next_peer->public_key, WG_KEY_LEN)) {
865+
if (memcmp(peer->public_key, peer->next_peer->public_key, sizeof(peer->public_key))) {
866866
peer = peer->next_peer;
867867
continue;
868868
}
@@ -926,42 +926,38 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
926926
#endif
927927

928928
#ifdef __OpenBSD__
929-
int s = -1;
930-
931-
void
932-
getsock()
929+
static int get_dgram_socket(void)
933930
{
934-
if (s < 0)
935-
s = socket(AF_INET, SOCK_DGRAM, 0);
931+
static int sock = -1;
932+
if (sock < 0)
933+
sock = socket(AF_INET, SOCK_DGRAM, 0);
934+
return sock;
936935
}
937936

938937
static int kernel_get_wireguard_interfaces(struct string_list *list)
939938
{
940-
struct ifgroupreq ifgr;
939+
struct ifgroupreq ifgr = { .ifgr_name = "wg" };
941940
struct ifg_req *ifg;
942-
size_t len = 0;
943-
int ret = 0;
944-
945-
getsock();
941+
int s = get_dgram_socket(), ret = 0;
946942

947-
bzero(&ifgr, sizeof(ifgr));
948-
strlcpy(ifgr.ifgr_name, "wg", sizeof(ifgr.ifgr_name));
943+
if (s < 0)
944+
return -errno;
949945

950-
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
951-
return errno;
946+
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
947+
return errno == ENOENT ? 0 : -errno;
952948

953-
len = ifgr.ifgr_len;
954-
if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
955-
return errno;
956-
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
957-
ret = errno;
949+
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
950+
if (!ifgr.ifgr_groups)
951+
return -errno;
952+
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) {
953+
ret = -errno;
958954
goto out;
959955
}
960956

961-
for (ifg = ifgr.ifgr_groups; ifg && len > 0; ifg++) {
957+
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) {
962958
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
963959
goto out;
964-
len -= sizeof(struct ifg_req);
960+
ifgr.ifgr_len -= sizeof(struct ifg_req);
965961
}
966962

967963
out:
@@ -971,40 +967,34 @@ static int kernel_get_wireguard_interfaces(struct string_list *list)
971967

972968
static int kernel_get_device(struct wgdevice **device, const char *iface)
973969
{
974-
struct wg_data_io wgdata;
970+
struct wg_data_io wgdata = { .wgd_size = 0 };
975971
struct wg_interface_io *wg_iface;
976972
struct wg_peer_io *wg_peer;
977973
struct wg_aip_io *wg_aip;
978-
979974
struct wgdevice *dev;
980975
struct wgpeer *peer;
981976
struct wgallowedip *aip;
977+
int s = get_dgram_socket(), ret;
982978

983-
size_t size;
984-
985-
getsock();
979+
if (s < 0)
980+
return -errno;
986981

987982
*device = NULL;
988-
989983
strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name));
990-
wgdata.wgd_size = size = 0;
991-
wgdata.wgd_mem = NULL;
992-
993-
if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) == -1 &&
994-
(errno == ENOTTY || errno == EPERM))
995-
return -errno;
996-
997-
while (size < wgdata.wgd_size) {
998-
size = wgdata.wgd_size;
999-
wgdata.wgd_mem = realloc(wgdata.wgd_mem, size);
1000-
if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) == -1)
1001-
return -errno;
984+
for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) {
985+
if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0)
986+
goto out;
987+
if (last_size >= wgdata.wgd_size)
988+
break;
989+
wgdata.wgd_mem = realloc(wgdata.wgd_mem, wgdata.wgd_size);
990+
if (!wgdata.wgd_mem)
991+
goto out;
1002992
}
1003993

1004994
wg_iface = wgdata.wgd_mem;
1005-
1006-
if ((dev = calloc(1, sizeof(*dev))) == NULL)
1007-
return -errno;
995+
dev = calloc(1, sizeof(*dev));
996+
if (!dev)
997+
goto out;
1008998
strlcpy(dev->name, iface, sizeof(dev->name));
1009999

10101000
if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE) {
@@ -1013,23 +1003,24 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
10131003
}
10141004

10151005
if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT) {
1016-
dev->listen_port = ntohs(wg_iface->i_port);
1006+
dev->listen_port = wg_iface->i_port;
10171007
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
10181008
}
10191009

10201010
if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC) {
1021-
memcpy(dev->public_key, wg_iface->i_public, WG_KEY_SIZE);
1011+
memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key));
10221012
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
10231013
}
10241014

10251015
if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE) {
1026-
memcpy(dev->private_key, wg_iface->i_private, WG_KEY_SIZE);
1016+
memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key));
10271017
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
10281018
}
10291019

1030-
for (wg_peer = wg_iface->i_peers; wg_peer != NULL; wg_peer = wg_peer->p_next) {
1031-
if ((peer = calloc(1, sizeof(*peer))) == NULL)
1032-
return -errno;
1020+
for (wg_peer = wg_iface->i_peers; wg_peer; wg_peer = wg_peer->p_next) {
1021+
peer = calloc(1, sizeof(*peer));
1022+
if (!peer)
1023+
goto out;
10331024

10341025
if (dev->first_peer == NULL)
10351026
dev->first_peer = peer;
@@ -1038,12 +1029,12 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
10381029
dev->last_peer = peer;
10391030

10401031
if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC) {
1041-
memcpy(peer->public_key, wg_peer->p_public, WG_KEY_SIZE);
1032+
memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key));
10421033
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
10431034
}
10441035

10451036
if (wg_peer->p_flags & WG_PEER_HAS_PSK) {
1046-
memcpy(peer->preshared_key, wg_peer->p_psk, WG_KEY_SIZE);
1037+
memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key));
10471038
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
10481039
}
10491040

@@ -1052,19 +1043,19 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
10521043
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
10531044
}
10541045

1055-
if (wg_peer->p_flags & WG_PEER_HAS_SOCKADDR)
1056-
memcpy(&peer->endpoint.addr, &wg_peer->p_sa,
1057-
wg_peer->p_sa.sa_len);
1046+
if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT && wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr))
1047+
memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len);
10581048

10591049
peer->rx_bytes = wg_peer->p_rxbytes;
10601050
peer->tx_bytes = wg_peer->p_txbytes;
10611051

10621052
peer->last_handshake_time.tv_sec = wg_peer->p_last_handshake.tv_sec;
10631053
peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec;
10641054

1065-
for (wg_aip = wg_peer->p_aips; wg_aip != NULL; wg_aip = wg_aip->a_next) {
1066-
if ((aip = calloc(1, sizeof(*aip))) == NULL)
1067-
return -errno;
1055+
for (wg_aip = wg_peer->p_aips; wg_aip; wg_aip = wg_aip->a_next) {
1056+
aip = calloc(1, sizeof(*aip));
1057+
if (!aip)
1058+
goto out;
10681059

10691060
if (peer->first_allowedip == NULL)
10701061
peer->first_allowedip = aip;
@@ -1075,43 +1066,44 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
10751066
aip->family = wg_aip->a_af;
10761067
if (wg_aip->a_af == AF_INET) {
10771068
memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4));
1078-
aip->cidr = wg_aip->a_mask;
1069+
aip->cidr = wg_aip->a_cidr;
10791070
} else if (wg_aip->a_af == AF_INET6) {
10801071
memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6));
1081-
aip->cidr = wg_aip->a_mask;
1072+
aip->cidr = wg_aip->a_cidr;
10821073
}
10831074
}
10841075
}
1085-
10861076
*device = dev;
1077+
errno = 0;
1078+
out:
1079+
ret = -errno;
10871080
free(wgdata.wgd_mem);
1088-
return 0;
1081+
return ret;
10891082
}
10901083

10911084
static int kernel_set_device(struct wgdevice *dev)
10921085
{
1093-
struct wg_data_io wgdata;
1094-
struct wg_interface_io wg_iface;
1095-
struct wg_peer_io *wg_peer;
1096-
struct wg_aip_io *wg_aip;
1097-
1086+
struct wg_data_io wgdata = { .wgd_size = 0 };
1087+
struct wg_interface_io wg_iface = { 0 };
1088+
struct wg_peer_io *wg_peer, *wg_peer_next;
1089+
struct wg_aip_io *wg_aip, *wg_aip_next;
10981090
struct wgpeer *peer;
10991091
struct wgallowedip *aip;
1092+
int s = get_dgram_socket(), ret;
11001093

1101-
getsock();
1094+
if (s < 0)
1095+
return -errno;
11021096

11031097
strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name));
11041098
wgdata.wgd_mem = &wg_iface;
11051099

1106-
bzero(&wg_iface, sizeof(wg_iface));
1107-
11081100
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
1109-
memcpy(wg_iface.i_private, dev->private_key, WG_KEY_SIZE);
1101+
memcpy(wg_iface.i_private, dev->private_key, sizeof(wg_iface.i_private));
11101102
wg_iface.i_flags |= WG_INTERFACE_HAS_PRIVATE;
11111103
}
11121104

11131105
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) {
1114-
wg_iface.i_port = htons(dev->listen_port);
1106+
wg_iface.i_port = dev->listen_port;
11151107
wg_iface.i_flags |= WG_INTERFACE_HAS_PORT;
11161108
}
11171109

@@ -1124,14 +1116,15 @@ static int kernel_set_device(struct wgdevice *dev)
11241116
wg_iface.i_flags |= WG_INTERFACE_REPLACE_PEERS;
11251117

11261118
for_each_wgpeer(dev, peer) {
1127-
if ((wg_peer = calloc(1, sizeof(*wg_peer))) == NULL)
1128-
return -errno;
1119+
wg_peer = calloc(1, sizeof(*wg_peer));
1120+
if (!wg_peer)
1121+
goto out;
11291122

11301123
wg_peer->p_flags = WG_PEER_HAS_PUBLIC;
1131-
memcpy(wg_peer->p_public, peer->public_key, WG_KEY_SIZE);
1124+
memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public));
11321125

11331126
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
1134-
memcpy(wg_peer->p_psk, peer->preshared_key, WG_KEY_SIZE);
1127+
memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk));
11351128
wg_peer->p_flags |= WG_PEER_HAS_PSK;
11361129
}
11371130

@@ -1140,10 +1133,10 @@ static int kernel_set_device(struct wgdevice *dev)
11401133
wg_peer->p_flags |= WG_PEER_HAS_PKA;
11411134
}
11421135

1143-
if (peer->endpoint.addr.sa_family == AF_INET ||
1144-
peer->endpoint.addr.sa_family == AF_INET6) {
1145-
memcpy(&wg_peer->p_sa, &peer->endpoint.addr, peer->endpoint.addr.sa_len);
1146-
wg_peer->p_flags |= WG_PEER_HAS_SOCKADDR;
1136+
if ((peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) &&
1137+
peer->endpoint.addr.sa_len <= sizeof(wg_peer->p_endpoint)) {
1138+
memcpy(&wg_peer->p_endpoint, &peer->endpoint.addr, peer->endpoint.addr.sa_len);
1139+
wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT;
11471140
}
11481141

11491142
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
@@ -1156,30 +1149,44 @@ static int kernel_set_device(struct wgdevice *dev)
11561149
wg_iface.i_peers = wg_peer;
11571150

11581151
for_each_wgallowedip(peer, aip) {
1159-
if ((wg_aip = calloc(1, sizeof(*wg_aip))) == NULL)
1160-
return -errno;
1152+
wg_aip = calloc(1, sizeof(*wg_aip));
1153+
if (!wg_aip)
1154+
goto out;
11611155

11621156
wg_aip->a_af = aip->family;
1163-
wg_aip->a_mask = aip->cidr;
1157+
wg_aip->a_cidr = aip->cidr;
11641158

1165-
if (aip->family == AF_INET)
1166-
memcpy(&wg_aip->a_ipv4, &aip->ip4, sizeof(aip->ip4));
1167-
else if (aip->family == AF_INET6)
1168-
memcpy(&wg_aip->a_ipv6, &aip->ip6, sizeof(aip->ip6));
1169-
else
1170-
return -1;
1159+
if (aip->family == AF_INET) {
1160+
memcpy(&wg_aip->a_ipv4, &aip->ip4, sizeof(wg_aip->a_ipv4));
1161+
} else if (aip->family == AF_INET6) {
1162+
memcpy(&wg_aip->a_ipv6, &aip->ip6, sizeof(wg_aip->a_ipv6));
1163+
} else {
1164+
free(wg_aip);
1165+
continue;
1166+
}
11711167

11721168
wg_aip->a_next = wg_peer->p_aips;
11731169
wg_peer->p_aips = wg_aip;
11741170
}
11751171
}
11761172

1177-
if (ioctl(s, SIOCSWG, (caddr_t)&wgdata) == -1)
1178-
return -errno;
1173+
if (ioctl(s, SIOCSWG, (caddr_t)&wgdata) < 0)
1174+
goto out;
1175+
errno = 0;
11791176

1180-
return 0;
1177+
out:
1178+
ret = -errno;
1179+
for (wg_peer = wg_iface.i_peers; wg_peer; wg_peer = wg_peer_next) {
1180+
for (wg_aip = wg_peer->p_aips; wg_aip; wg_aip = wg_aip_next) {
1181+
wg_aip_next = wg_aip->a_next;
1182+
free(wg_aip);
1183+
}
1184+
wg_peer_next = wg_peer->p_next;
1185+
free(wg_peer);
1186+
}
1187+
return ret;
11811188
}
1182-
#endif /* OpenBSD */
1189+
#endif
11831190

11841191
/* first\0second\0third\0forth\0last\0\0 */
11851192
char *ipc_list_devices(void)

0 commit comments

Comments
 (0)