Thu Aug 27 02:50:44 2020 UTC ()
Paranoia: use strlcpy rather than strcpy here and detect truncation.

Not an issue for the one caller in tree, but let's not leave rakes to
step on.


(riastradh)
diff -r1.1 -r1.2 src/sys/rump/net/lib/libwg/wg_user.c

cvs diff -r1.1 -r1.2 src/sys/rump/net/lib/libwg/wg_user.c (switch to unified diff)

--- src/sys/rump/net/lib/libwg/wg_user.c 2020/08/26 16:03:42 1.1
+++ src/sys/rump/net/lib/libwg/wg_user.c 2020/08/27 02:50:44 1.2
@@ -1,423 +1,428 @@ @@ -1,423 +1,428 @@
1/* $NetBSD: wg_user.c,v 1.1 2020/08/26 16:03:42 riastradh Exp $ */ 1/* $NetBSD: wg_user.c,v 1.2 2020/08/27 02:50:44 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> 4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Based on wg_user.c by Antti Kantee. 7 * Based on wg_user.c by Antti Kantee.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: wg_user.c,v 1.1 2020/08/26 16:03:42 riastradh Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: wg_user.c,v 1.2 2020/08/27 02:50:44 riastradh Exp $");
33 33
34#ifndef _KERNEL 34#ifndef _KERNEL
35#include <sys/types.h> 35#include <sys/types.h>
36#include <sys/ioctl.h> 36#include <sys/ioctl.h>
37#include <sys/uio.h> 37#include <sys/uio.h>
38#include <sys/socket.h> 38#include <sys/socket.h>
39#include <sys/param.h> 39#include <sys/param.h>
40 40
41#include <net/if.h> 41#include <net/if.h>
42#include <net/if_tun.h> 42#include <net/if_tun.h>
43 43
44#include <netinet/in.h> 44#include <netinet/in.h>
45 45
46#include <assert.h> 46#include <assert.h>
47#include <errno.h> 47#include <errno.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#include <inttypes.h> 49#include <inttypes.h>
50#include <poll.h> 50#include <poll.h>
51#include <pthread.h> 51#include <pthread.h>
52#include <stdio.h> 52#include <stdio.h>
53#include <stdlib.h> 53#include <stdlib.h>
54#include <string.h> 54#include <string.h>
55#include <unistd.h> 55#include <unistd.h>
56 56
57#include <rump/rumpuser_component.h> 57#include <rump/rumpuser_component.h>
58 58
59#include "wg_user.h" 59#include "wg_user.h"
60 60
61struct wg_user { 61struct wg_user {
62 struct wg_softc *wgu_sc; 62 struct wg_softc *wgu_sc;
63 int wgu_devnum; 63 int wgu_devnum;
64 char wgu_tun_name[IFNAMSIZ]; 64 char wgu_tun_name[IFNAMSIZ];
65 65
66 int wgu_fd; 66 int wgu_fd;
67 int wgu_sock4; 67 int wgu_sock4;
68 int wgu_sock6; 68 int wgu_sock6;
69 int wgu_pipe[2]; 69 int wgu_pipe[2];
70 pthread_t wgu_rcvthr; 70 pthread_t wgu_rcvthr;
71 71
72 int wgu_dying; 72 int wgu_dying;
73 73
74 char wgu_rcvbuf[9018]; /* jumbo frame max len */ 74 char wgu_rcvbuf[9018]; /* jumbo frame max len */
75}; 75};
76 76
77static int 77static int
78open_tun(const char *tun_name) 78open_tun(const char *tun_name)
79{ 79{
80 char tun_path[MAXPATHLEN]; 80 char tun_path[MAXPATHLEN];
81 int n, fd, error; 81 int n, fd, error;
82 82
83 n = snprintf(tun_path, sizeof(tun_path), "/dev/%s", tun_name); 83 n = snprintf(tun_path, sizeof(tun_path), "/dev/%s", tun_name);
84 if (n == MAXPATHLEN) 84 if (n == MAXPATHLEN)
85 return E2BIG; 85 return E2BIG;
86 86
87 fd = open(tun_path, O_RDWR); 87 fd = open(tun_path, O_RDWR);
88 if (fd == -1) { 88 if (fd == -1) {
89 fprintf(stderr, "%s: can't open %s: %s\n", 89 fprintf(stderr, "%s: can't open %s: %s\n",
90 __func__, tun_name, strerror(errno)); 90 __func__, tun_name, strerror(errno));
91 } 91 }
92 92
93 int i = 1; 93 int i = 1;
94 error = ioctl(fd, TUNSLMODE, &i); 94 error = ioctl(fd, TUNSLMODE, &i);
95 if (error == -1) { 95 if (error == -1) {
96 close(fd); 96 close(fd);
97 fd = -1; 97 fd = -1;
98 } 98 }
99 99
100 return fd; 100 return fd;
101} 101}
102 102
103static void 103static void
104close_tun(struct wg_user *wgu) 104close_tun(struct wg_user *wgu)
105{ 105{
106 int s; 106 int s;
107 struct ifreq ifr = {}; 107 struct ifreq ifr = {};
108 108
109 close(wgu->wgu_fd); 109 close(wgu->wgu_fd);
110 110
111 s = socket(AF_INET, SOCK_DGRAM, 0); 111 s = socket(AF_INET, SOCK_DGRAM, 0);
112 if (s == -1) 112 if (s == -1)
113 return; /* XXX */ 113 return; /* XXX */
114 strcpy(ifr.ifr_name, wgu->wgu_tun_name); 114 strcpy(ifr.ifr_name, wgu->wgu_tun_name);
115 (void)ioctl(s, SIOCIFDESTROY, &ifr); 115 (void)ioctl(s, SIOCIFDESTROY, &ifr);
116 close(s); 116 close(s);
117} 117}
118 118
119static void * 119static void *
120wg_user_rcvthread(void *aaargh) 120wg_user_rcvthread(void *aaargh)
121{ 121{
122 struct wg_user *wgu = aaargh; 122 struct wg_user *wgu = aaargh;
123 struct pollfd pfd[4]; 123 struct pollfd pfd[4];
124 ssize_t nn = 0; 124 ssize_t nn = 0;
125 int prv; 125 int prv;
126 126
127 rumpuser_component_kthread(); 127 rumpuser_component_kthread();
128 128
129 pfd[0].fd = wgu->wgu_fd; 129 pfd[0].fd = wgu->wgu_fd;
130 pfd[0].events = POLLIN; 130 pfd[0].events = POLLIN;
131 pfd[1].fd = wgu->wgu_pipe[0]; 131 pfd[1].fd = wgu->wgu_pipe[0];
132 pfd[1].events = POLLIN; 132 pfd[1].events = POLLIN;
133 pfd[2].fd = wgu->wgu_sock4; 133 pfd[2].fd = wgu->wgu_sock4;
134 pfd[2].events = POLLIN; 134 pfd[2].events = POLLIN;
135 pfd[3].fd = wgu->wgu_sock6; 135 pfd[3].fd = wgu->wgu_sock6;
136 pfd[3].events = POLLIN; 136 pfd[3].events = POLLIN;
137 137
138 while (!wgu->wgu_dying) { 138 while (!wgu->wgu_dying) {
139 struct iovec iov[2]; 139 struct iovec iov[2];
140 140
141 prv = poll(pfd, 4, -1); 141 prv = poll(pfd, 4, -1);
142 if (prv == 0) 142 if (prv == 0)
143 continue; 143 continue;
144 if (prv == -1) { 144 if (prv == -1) {
145 /* XXX */ 145 /* XXX */
146 fprintf(stderr, "%s: poll error: %d\n", 146 fprintf(stderr, "%s: poll error: %d\n",
147 wgu->wgu_tun_name, errno); 147 wgu->wgu_tun_name, errno);
148 sleep(1); 148 sleep(1);
149 continue; 149 continue;
150 } 150 }
151 if (pfd[1].revents & POLLIN) 151 if (pfd[1].revents & POLLIN)
152 continue; 152 continue;
153 153
154 /* Receive user packets from tun */ 154 /* Receive user packets from tun */
155 if (pfd[0].revents & POLLIN) { 155 if (pfd[0].revents & POLLIN) {
156 nn = read(wgu->wgu_fd, wgu->wgu_rcvbuf, sizeof(wgu->wgu_rcvbuf)); 156 nn = read(wgu->wgu_fd, wgu->wgu_rcvbuf, sizeof(wgu->wgu_rcvbuf));
157 if (nn == -1 && errno == EAGAIN) 157 if (nn == -1 && errno == EAGAIN)
158 continue; 158 continue;
159 159
160 if (nn < 1) { 160 if (nn < 1) {
161 /* XXX */ 161 /* XXX */
162 fprintf(stderr, "%s: receive failed\n", 162 fprintf(stderr, "%s: receive failed\n",
163 wgu->wgu_tun_name); 163 wgu->wgu_tun_name);
164 sleep(1); 164 sleep(1);
165 continue; 165 continue;
166 } 166 }
167 167
168 iov[0].iov_base = wgu->wgu_rcvbuf; 168 iov[0].iov_base = wgu->wgu_rcvbuf;
169 iov[0].iov_len = ((struct sockaddr *)wgu->wgu_rcvbuf)->sa_len; 169 iov[0].iov_len = ((struct sockaddr *)wgu->wgu_rcvbuf)->sa_len;
170 170
171 iov[1].iov_base = (char *)wgu->wgu_rcvbuf + iov[0].iov_len; 171 iov[1].iov_base = (char *)wgu->wgu_rcvbuf + iov[0].iov_len;
172 iov[1].iov_len = nn - iov[0].iov_len; 172 iov[1].iov_len = nn - iov[0].iov_len;
173 173
174 rumpuser_component_schedule(NULL); 174 rumpuser_component_schedule(NULL);
175 rumpkern_wg_recv_user(wgu->wgu_sc, iov, 2); 175 rumpkern_wg_recv_user(wgu->wgu_sc, iov, 2);
176 rumpuser_component_unschedule(); 176 rumpuser_component_unschedule();
177 } 177 }
178 178
179 /* Receive wg UDP/IPv4 packets from a peer */ 179 /* Receive wg UDP/IPv4 packets from a peer */
180 if (pfd[2].revents & POLLIN) { 180 if (pfd[2].revents & POLLIN) {
181 struct sockaddr_in sin; 181 struct sockaddr_in sin;
182 socklen_t len = sizeof(sin); 182 socklen_t len = sizeof(sin);
183 nn = recvfrom(wgu->wgu_sock4, wgu->wgu_rcvbuf, 183 nn = recvfrom(wgu->wgu_sock4, wgu->wgu_rcvbuf,
184 sizeof(wgu->wgu_rcvbuf), 0, (struct sockaddr *)&sin, 184 sizeof(wgu->wgu_rcvbuf), 0, (struct sockaddr *)&sin,
185 &len); 185 &len);
186 if (nn == -1 && errno == EAGAIN) 186 if (nn == -1 && errno == EAGAIN)
187 continue; 187 continue;
188 if (len != sizeof(sin)) 188 if (len != sizeof(sin))
189 continue; 189 continue;
190 iov[0].iov_base = &sin; 190 iov[0].iov_base = &sin;
191 iov[0].iov_len = sin.sin_len; 191 iov[0].iov_len = sin.sin_len;
192 192
193 iov[1].iov_base = wgu->wgu_rcvbuf; 193 iov[1].iov_base = wgu->wgu_rcvbuf;
194 iov[1].iov_len = nn; 194 iov[1].iov_len = nn;
195 195
196 rumpuser_component_schedule(NULL); 196 rumpuser_component_schedule(NULL);
197 rumpkern_wg_recv_peer(wgu->wgu_sc, iov, 2); 197 rumpkern_wg_recv_peer(wgu->wgu_sc, iov, 2);
198 rumpuser_component_unschedule(); 198 rumpuser_component_unschedule();
199 } 199 }
200 200
201 /* Receive wg UDP/IPv6 packets from a peer */ 201 /* Receive wg UDP/IPv6 packets from a peer */
202 if (pfd[3].revents & POLLIN) { 202 if (pfd[3].revents & POLLIN) {
203 struct sockaddr_in6 sin6; 203 struct sockaddr_in6 sin6;
204 socklen_t len = sizeof(sin6); 204 socklen_t len = sizeof(sin6);
205 nn = recvfrom(wgu->wgu_sock6, wgu->wgu_rcvbuf, 205 nn = recvfrom(wgu->wgu_sock6, wgu->wgu_rcvbuf,
206 sizeof(wgu->wgu_rcvbuf), 0, (struct sockaddr *)&sin6, 206 sizeof(wgu->wgu_rcvbuf), 0, (struct sockaddr *)&sin6,
207 &len); 207 &len);
208 if (nn == -1 && errno == EAGAIN) 208 if (nn == -1 && errno == EAGAIN)
209 continue; 209 continue;
210 if (len != sizeof(sin6)) 210 if (len != sizeof(sin6))
211 continue; 211 continue;
212 iov[0].iov_base = &sin6; 212 iov[0].iov_base = &sin6;
213 iov[0].iov_len = sin6.sin6_len; 213 iov[0].iov_len = sin6.sin6_len;
214 214
215 iov[1].iov_base = wgu->wgu_rcvbuf; 215 iov[1].iov_base = wgu->wgu_rcvbuf;
216 iov[1].iov_len = nn; 216 iov[1].iov_len = nn;
217 217
218 rumpuser_component_schedule(NULL); 218 rumpuser_component_schedule(NULL);
219 rumpkern_wg_recv_peer(wgu->wgu_sc, iov, 2); 219 rumpkern_wg_recv_peer(wgu->wgu_sc, iov, 2);
220 rumpuser_component_unschedule(); 220 rumpuser_component_unschedule();
221 } 221 }
222 } 222 }
223 223
224 assert(wgu->wgu_dying); 224 assert(wgu->wgu_dying);
225 225
226 rumpuser_component_kthread_release(); 226 rumpuser_component_kthread_release();
227 return NULL; 227 return NULL;
228} 228}
229 229
230int 230int
231rumpuser_wg_create(const char *tun_name, struct wg_softc *wg, 231rumpuser_wg_create(const char *tun_name, struct wg_softc *wg,
232 struct wg_user **wgup) 232 struct wg_user **wgup)
233{ 233{
234 struct wg_user *wgu = NULL; 234 struct wg_user *wgu = NULL;
235 void *cookie; 235 void *cookie;
236 int rv; 236 int rv;
237 237
238 cookie = rumpuser_component_unschedule(); 238 cookie = rumpuser_component_unschedule();
239 239
240 wgu = malloc(sizeof(*wgu)); 240 wgu = malloc(sizeof(*wgu));
241 if (wgu == NULL) { 241 if (wgu == NULL) {
242 rv = errno; 242 rv = errno;
243 goto oerr1; 243 goto oerr1;
244 } 244 }
245 245
 246 if (strlcpy(wgu->wgu_tun_name, tun_name, sizeof(wgu->wgu_tun_name))
 247 >= sizeof(wgu->wgu_tun_name)) {
 248 rv = EINVAL;
 249 goto oerr2;
 250 }
 251 wgu->wgu_sc = wg;
 252
246 wgu->wgu_fd = open_tun(tun_name); 253 wgu->wgu_fd = open_tun(tun_name);
247 if (wgu->wgu_fd == -1) { 254 if (wgu->wgu_fd == -1) {
248 rv = errno; 255 rv = errno;
249 goto oerr2; 256 goto oerr2;
250 } 257 }
251 strcpy(wgu->wgu_tun_name, tun_name); 
252 wgu->wgu_sc = wg; 
253 258
254 if (pipe(wgu->wgu_pipe) == -1) { 259 if (pipe(wgu->wgu_pipe) == -1) {
255 rv = errno; 260 rv = errno;
256 goto oerr3; 261 goto oerr3;
257 } 262 }
258 263
259 wgu->wgu_sock4 = socket(AF_INET, SOCK_DGRAM, 0); 264 wgu->wgu_sock4 = socket(AF_INET, SOCK_DGRAM, 0);
260 wgu->wgu_sock6 = socket(AF_INET6, SOCK_DGRAM, 0); 265 wgu->wgu_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
261 if (wgu->wgu_sock4 == -1 || wgu->wgu_sock6 == -1) { 266 if (wgu->wgu_sock4 == -1 || wgu->wgu_sock6 == -1) {
262 rv = errno; 267 rv = errno;
263 goto oerr4; 268 goto oerr4;
264 } 269 }
265 270
266 rv = pthread_create(&wgu->wgu_rcvthr, NULL, wg_user_rcvthread, wgu); 271 rv = pthread_create(&wgu->wgu_rcvthr, NULL, wg_user_rcvthread, wgu);
267 if (rv != 0) 272 if (rv != 0)
268 goto oerr5; 273 goto oerr5;
269 274
270 rumpuser_component_schedule(cookie); 275 rumpuser_component_schedule(cookie);
271 *wgup = wgu; 276 *wgup = wgu;
272 return 0; 277 return 0;
273 278
274 oerr5: 279 oerr5:
275 close(wgu->wgu_pipe[0]); 280 close(wgu->wgu_pipe[0]);
276 close(wgu->wgu_pipe[1]); 281 close(wgu->wgu_pipe[1]);
277 oerr4: 282 oerr4:
278 if (wgu->wgu_sock4 != -1) 283 if (wgu->wgu_sock4 != -1)
279 close(wgu->wgu_sock4); 284 close(wgu->wgu_sock4);
280 if (wgu->wgu_sock6 != -1) 285 if (wgu->wgu_sock6 != -1)
281 close(wgu->wgu_sock6); 286 close(wgu->wgu_sock6);
282 oerr3: 287 oerr3:
283 close_tun(wgu); 288 close_tun(wgu);
284 oerr2: 289 oerr2:
285 free(wgu); 290 free(wgu);
286 oerr1: 291 oerr1:
287 rumpuser_component_schedule(cookie); 292 rumpuser_component_schedule(cookie);
288 return rumpuser_component_errtrans(rv); 293 return rumpuser_component_errtrans(rv);
289} 294}
290 295
291/* 296/*
292 * Send decrypted packets to users via a tun. 297 * Send decrypted packets to users via a tun.
293 */ 298 */
294void 299void
295rumpuser_wg_send_user(struct wg_user *wgu, struct iovec *iov, size_t iovlen) 300rumpuser_wg_send_user(struct wg_user *wgu, struct iovec *iov, size_t iovlen)
296{ 301{
297 void *cookie = rumpuser_component_unschedule(); 302 void *cookie = rumpuser_component_unschedule();
298 ssize_t idontcare __attribute__((__unused__)); 303 ssize_t idontcare __attribute__((__unused__));
299 304
300 /* 305 /*
301 * no need to check for return value; packets may be dropped 306 * no need to check for return value; packets may be dropped
302 * 307 *
303 * ... sorry, I spoke too soon. We need to check it because 308 * ... sorry, I spoke too soon. We need to check it because
304 * apparently gcc reinvented const poisoning and it's very 309 * apparently gcc reinvented const poisoning and it's very
305 * hard to say "thanks, I know I'm not using the result, 310 * hard to say "thanks, I know I'm not using the result,
306 * but please STFU and let's get on with something useful". 311 * but please STFU and let's get on with something useful".
307 * So let's trick gcc into letting us share the compiler 312 * So let's trick gcc into letting us share the compiler
308 * experience. 313 * experience.
309 */ 314 */
310 idontcare = writev(wgu->wgu_fd, iov, iovlen); 315 idontcare = writev(wgu->wgu_fd, iov, iovlen);
311 316
312 rumpuser_component_schedule(cookie); 317 rumpuser_component_schedule(cookie);
313} 318}
314 319
315/* 320/*
316 * Send wg messages to a peer. 321 * Send wg messages to a peer.
317 */ 322 */
318int 323int
319rumpuser_wg_send_peer(struct wg_user *wgu, struct sockaddr *sa, 324rumpuser_wg_send_peer(struct wg_user *wgu, struct sockaddr *sa,
320 struct iovec *iov, size_t iovlen) 325 struct iovec *iov, size_t iovlen)
321{ 326{
322 void *cookie = rumpuser_component_unschedule(); 327 void *cookie = rumpuser_component_unschedule();
323 int s, error = 0; 328 int s, error = 0;
324 size_t i; 329 size_t i;
325 ssize_t sent; 330 ssize_t sent;
326 331
327 if (sa->sa_family == AF_INET) 332 if (sa->sa_family == AF_INET)
328 s = wgu->wgu_sock4; 333 s = wgu->wgu_sock4;
329 else 334 else
330 s = wgu->wgu_sock6; 335 s = wgu->wgu_sock6;
331 336
332 for (i = 0; i < iovlen; i++) { 337 for (i = 0; i < iovlen; i++) {
333 sent = sendto(s, iov[i].iov_base, iov[i].iov_len, 0, sa, 338 sent = sendto(s, iov[i].iov_base, iov[i].iov_len, 0, sa,
334 sa->sa_len); 339 sa->sa_len);
335 if (sent == -1 || (size_t)sent != iov[i].iov_len) { 340 if (sent == -1 || (size_t)sent != iov[i].iov_len) {
336 error = errno; 341 error = errno;
337 break; 342 break;
338 } 343 }
339 } 344 }
340 345
341 rumpuser_component_schedule(cookie); 346 rumpuser_component_schedule(cookie);
342 347
343 return error; 348 return error;
344} 349}
345 350
346int 351int
347rumpuser_wg_ioctl(struct wg_user *wgu, u_long cmd, void *data, int af) 352rumpuser_wg_ioctl(struct wg_user *wgu, u_long cmd, void *data, int af)
348{ 353{
349 void *cookie = rumpuser_component_unschedule(); 354 void *cookie = rumpuser_component_unschedule();
350 int s, error; 355 int s, error;
351 356
352 s = socket(af, SOCK_DGRAM, 0); 357 s = socket(af, SOCK_DGRAM, 0);
353 if (s == -1) 358 if (s == -1)
354 return errno; 359 return errno;
355 error = ioctl(s, cmd, data); 360 error = ioctl(s, cmd, data);
356 close(s); 361 close(s);
357 362
358 rumpuser_component_schedule(cookie); 363 rumpuser_component_schedule(cookie);
359 364
360 return error == -1 ? errno : 0; 365 return error == -1 ? errno : 0;
361} 366}
362 367
363int 368int
364rumpuser_wg_sock_bind(struct wg_user *wgu, const uint16_t port) 369rumpuser_wg_sock_bind(struct wg_user *wgu, const uint16_t port)
365{ 370{
366 int error; 371 int error;
367 struct sockaddr_in sin; 372 struct sockaddr_in sin;
368 struct sockaddr_in6 sin6; 373 struct sockaddr_in6 sin6;
369 374
370 memset(&sin, 0, sizeof(sin)); 375 memset(&sin, 0, sizeof(sin));
371 sin.sin_family = AF_INET; 376 sin.sin_family = AF_INET;
372 sin.sin_len = sizeof(sin); 377 sin.sin_len = sizeof(sin);
373 sin.sin_addr.s_addr = INADDR_ANY; 378 sin.sin_addr.s_addr = INADDR_ANY;
374 sin.sin_port = htons(port); 379 sin.sin_port = htons(port);
375 380
376 error = bind(wgu->wgu_sock4, (struct sockaddr *)&sin, sizeof(sin)); 381 error = bind(wgu->wgu_sock4, (struct sockaddr *)&sin, sizeof(sin));
377 if (error == -1) 382 if (error == -1)
378 return errno; 383 return errno;
379 384
380 memset(&sin6, 0, sizeof(sin6)); 385 memset(&sin6, 0, sizeof(sin6));
381 sin6.sin6_family = AF_INET6; 386 sin6.sin6_family = AF_INET6;
382 sin6.sin6_len = sizeof(sin6); 387 sin6.sin6_len = sizeof(sin6);
383 sin6.sin6_addr = in6addr_any; 388 sin6.sin6_addr = in6addr_any;
384 sin6.sin6_port = htons(port); 389 sin6.sin6_port = htons(port);
385 390
386 error = bind(wgu->wgu_sock6, (struct sockaddr *)&sin6, sizeof(sin6)); 391 error = bind(wgu->wgu_sock6, (struct sockaddr *)&sin6, sizeof(sin6));
387 if (error == -1) 392 if (error == -1)
388 return errno; 393 return errno;
389 394
390 return 0; 395 return 0;
391} 396}
392 397
393void 398void
394rumpuser_wg_destroy(struct wg_user *wgu) 399rumpuser_wg_destroy(struct wg_user *wgu)
395{ 400{
396 void *cookie = rumpuser_component_unschedule(); 401 void *cookie = rumpuser_component_unschedule();
397 402
398 wgu->wgu_dying = 1; 403 wgu->wgu_dying = 1;
399 if (write(wgu->wgu_pipe[1], 404 if (write(wgu->wgu_pipe[1],
400 &wgu->wgu_dying, sizeof(wgu->wgu_dying)) == -1) { 405 &wgu->wgu_dying, sizeof(wgu->wgu_dying)) == -1) {
401 /* 406 /*
402 * this is here mostly to avoid a compiler warning 407 * this is here mostly to avoid a compiler warning
403 * about ignoring the return value of write() 408 * about ignoring the return value of write()
404 */ 409 */
405 fprintf(stderr, "%s: failed to signal thread\n", 410 fprintf(stderr, "%s: failed to signal thread\n",
406 wgu->wgu_tun_name); 411 wgu->wgu_tun_name);
407 } 412 }
408 pthread_join(wgu->wgu_rcvthr, NULL); 413 pthread_join(wgu->wgu_rcvthr, NULL);
409 close_tun(wgu); 414 close_tun(wgu);
410 close(wgu->wgu_pipe[0]); 415 close(wgu->wgu_pipe[0]);
411 close(wgu->wgu_pipe[1]); 416 close(wgu->wgu_pipe[1]);
412 free(wgu); 417 free(wgu);
413 418
414 rumpuser_component_schedule(cookie); 419 rumpuser_component_schedule(cookie);
415} 420}
416 421
417char * 422char *
418rumpuser_wg_get_tunname(struct wg_user *wgu) 423rumpuser_wg_get_tunname(struct wg_user *wgu)
419{ 424{
420 425
421 return wgu->wgu_tun_name; 426 return wgu->wgu_tun_name;
422} 427}
423#endif 428#endif