pex: move raw ip send code to sendto_rawudp() in utils.c
[project/unetd.git] / pex-msg.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
4 */
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/un.h>
8 #include <arpa/inet.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <libubox/list.h>
12 #include <libubox/uloop.h>
13 #include <libubox/usock.h>
14 #include "pex-msg.h"
15 #include "chacha20.h"
16 #include "auth-data.h"
17
18 static char pex_tx_buf[PEX_BUF_SIZE];
19 static FILE *pex_urandom;
20 static struct uloop_fd pex_fd, pex_unix_fd;
21 static LIST_HEAD(requests);
22 static struct uloop_timeout gc_timer;
23 static int pex_raw_v4_fd = -1, pex_raw_v6_fd = -1;
24
25 static pex_recv_cb_t pex_recv_cb;
26 static pex_recv_control_cb_t pex_control_cb;
27 static int pex_unix_tx_fd = -1;
28
29 static const void *
30 get_mapped_sockaddr(const void *addr)
31 {
32 static struct sockaddr_in6 sin6;
33 const struct sockaddr_in *sin = addr;
34
35 if (!sin || sin->sin_family != AF_INET)
36 return addr;
37
38 memset(&sin6, 0, sizeof(sin6));
39 sin6.sin6_family = AF_INET6;
40 sin6.sin6_addr.s6_addr[10] = 0xff;
41 sin6.sin6_addr.s6_addr[11] = 0xff;
42 memcpy(&sin6.sin6_addr.s6_addr[12], &sin->sin_addr, sizeof(struct in_addr));
43 sin6.sin6_port = sin->sin_port;
44
45 return &sin6;
46 }
47
48 struct pex_msg_update_recv_ctx {
49 struct list_head list;
50
51 union network_endpoint addr;
52
53 uint8_t priv_key[CURVE25519_KEY_SIZE];
54 uint8_t auth_key[CURVE25519_KEY_SIZE];
55 uint8_t e_key[CURVE25519_KEY_SIZE];
56
57 uint64_t req_id;
58
59 void *data;
60 int data_len;
61 int data_ofs;
62
63 int idle;
64 };
65
66 uint64_t pex_network_hash(const uint8_t *auth_key, uint64_t req_id)
67 {
68 siphash_key_t key = {
69 .key = {
70 be64_to_cpu(req_id),
71 be64_to_cpu(req_id)
72 }
73 };
74 uint64_t hash;
75
76 siphash_to_be64(&hash, auth_key, CURVE25519_KEY_SIZE, &key);
77
78 return hash;
79 }
80
81
82 struct pex_hdr *__pex_msg_init(const uint8_t *pubkey, uint8_t opcode)
83 {
84 struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
85
86 hdr->version = 0;
87 hdr->opcode = opcode;
88 hdr->len = 0;
89 memcpy(hdr->id, pubkey, sizeof(hdr->id));
90
91 return hdr;
92 }
93
94 struct pex_hdr *__pex_msg_init_ext(const uint8_t *pubkey, const uint8_t *auth_key,
95 uint8_t opcode, bool ext)
96 {
97 struct pex_hdr *hdr = __pex_msg_init(pubkey, opcode);
98 struct pex_ext_hdr *ehdr = (struct pex_ext_hdr *)(hdr + 1);
99 uint64_t hash;
100
101 if (!ext)
102 return hdr;
103
104 hdr->len = sizeof(*ehdr);
105
106 if (fread(&ehdr->nonce, sizeof(ehdr->nonce), 1, pex_urandom) != 1)
107 return NULL;
108
109 hash = pex_network_hash(auth_key, ehdr->nonce);
110 *(uint64_t *)hdr->id ^= hash;
111 memcpy(ehdr->auth_id, auth_key, sizeof(ehdr->auth_id));
112
113 return hdr;
114 }
115
116 void *pex_msg_append(size_t len)
117 {
118 struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
119 int ofs = hdr->len + sizeof(struct pex_hdr);
120 void *buf = &pex_tx_buf[ofs];
121
122 if (sizeof(pex_tx_buf) - ofs < len)
123 return NULL;
124
125 hdr->len += len;
126 memset(buf, 0, len);
127
128 return buf;
129 }
130
131 static void
132 pex_fd_cb(struct uloop_fd *fd, unsigned int events)
133 {
134 static struct sockaddr_in6 sin6;
135 static char buf[PEX_RX_BUF_SIZE];
136 ssize_t len;
137
138 while (1) {
139 static struct iovec iov[2] = {
140 { .iov_base = &sin6 },
141 { .iov_base = buf },
142 };
143 static struct msghdr msg = {
144 .msg_iov = iov,
145 .msg_iovlen = ARRAY_SIZE(iov),
146 };
147 socklen_t slen = sizeof(sin6);
148
149 len = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6, &slen);
150 if (len < 0) {
151 if (errno == EINTR)
152 continue;
153
154 if (errno == EAGAIN)
155 break;
156
157 pex_close();
158 return;
159 }
160
161 if (!len)
162 continue;
163
164 if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
165 struct sockaddr_in *sin = (struct sockaddr_in *)&sin6;
166 struct in_addr in = *(struct in_addr *)&sin6.sin6_addr.s6_addr[12];
167 int port = sin6.sin6_port;
168
169 memset(&sin6, 0, sizeof(sin6));
170 sin->sin_port = port;
171 sin->sin_family = AF_INET;
172 sin->sin_addr = in;
173 slen = sizeof(*sin);
174 }
175
176 retry:
177 if (pex_unix_tx_fd >= 0) {
178 iov[0].iov_len = slen;
179 iov[1].iov_len = len;
180 if (sendmsg(pex_unix_tx_fd, &msg, 0) < 0) {
181 switch (errno) {
182 case EINTR:
183 goto retry;
184 case EMSGSIZE:
185 case ENOBUFS:
186 case EAGAIN:
187 continue;
188 default:
189 perror("sendmsg");
190 close(pex_unix_tx_fd);
191 pex_unix_tx_fd = -1;
192 break;
193 }
194 }
195 }
196
197 pex_recv_cb(buf, len, &sin6);
198 }
199 }
200
201 static void
202 pex_unix_cb(struct uloop_fd *fd, unsigned int events)
203 {
204 static char buf[PEX_RX_BUF_SIZE];
205 static struct iovec iov = {
206 .iov_base = buf,
207 .iov_len = sizeof(buf),
208 };
209 ssize_t len;
210
211 while (1) {
212 const struct sockaddr *sa = (struct sockaddr *)buf;
213 uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
214 struct msghdr msg = {
215 .msg_iov = &iov,
216 .msg_iovlen = 1,
217 .msg_control = fd_buf,
218 .msg_controllen = CMSG_LEN(sizeof(int)),
219 };
220 struct cmsghdr *cmsg;
221 socklen_t slen;
222 int *pfd;
223
224 cmsg = CMSG_FIRSTHDR(&msg);
225 cmsg->cmsg_type = SCM_RIGHTS;
226 cmsg->cmsg_level = SOL_SOCKET;
227 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
228
229 pfd = (int *)CMSG_DATA(cmsg);
230 *pfd = -1;
231
232 len = recvmsg(fd->fd, &msg, 0);
233 if (len < 0) {
234 if (errno == EINTR)
235 continue;
236
237 if (errno == EAGAIN)
238 break;
239
240 pex_close();
241 return;
242 }
243
244 if (*pfd >= 0) {
245 if (pex_unix_tx_fd >= 0)
246 close(pex_unix_tx_fd);
247
248 pex_unix_tx_fd = *pfd;
249 }
250
251 if (!len)
252 continue;
253
254 if (len < sizeof(*sa))
255 continue;
256
257 if (sa->sa_family == AF_LOCAL) {
258 slen = sizeof(struct sockaddr);
259 len -= slen;
260 if (len < sizeof(struct pex_msg_local_control))
261 continue;
262
263 if (pex_control_cb)
264 pex_control_cb((struct pex_msg_local_control *)&buf[slen], len);
265
266 continue;
267 }
268
269 if (sa->sa_family == AF_INET)
270 slen = sizeof(struct sockaddr_in);
271 else if (sa->sa_family == AF_INET6)
272 slen = sizeof(struct sockaddr_in6);
273 else
274 continue;
275
276 sa = get_mapped_sockaddr(sa);
277 sendto(pex_fd.fd, buf + slen, len - slen, 0, sa, sizeof(struct sockaddr_in6));
278 }
279 }
280
281
282 int __pex_msg_send(int fd, const void *addr, void *ip_hdr, size_t ip_hdrlen)
283 {
284 struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
285 const struct sockaddr *sa = addr;
286 size_t tx_len = sizeof(*hdr) + hdr->len;
287 uint16_t orig_len = hdr->len;
288 int ret;
289
290 if (fd < 0) {
291 hdr->len -= sizeof(struct pex_ext_hdr);
292 if (ip_hdrlen)
293 fd = sa->sa_family == AF_INET6 ? pex_raw_v6_fd : pex_raw_v4_fd;
294 else {
295 fd = pex_fd.fd;
296 sa = addr = get_mapped_sockaddr(addr);
297 }
298
299 if (fd < 0)
300 return -1;
301 }
302
303 hdr->len = htons(hdr->len);
304 if (ip_hdr) {
305 ret = sendto_rawudp(fd, addr, ip_hdr, ip_hdrlen, pex_tx_buf, tx_len);
306 } else if (addr) {
307 socklen_t addr_len;
308
309 if (sa->sa_family == AF_INET6)
310 addr_len = sizeof(struct sockaddr_in6);
311 else
312 addr_len = sizeof(struct sockaddr_in);
313
314 ret = sendto(fd, pex_tx_buf, tx_len, 0, addr, addr_len);
315 } else {
316 ret = send(fd, pex_tx_buf, tx_len, 0);
317 }
318 hdr->len = orig_len;
319
320 return ret;
321 }
322
323 static void
324 pex_msg_update_response_fill(struct pex_msg_update_send_ctx *ctx)
325 {
326 struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
327 int ofs = hdr->len + sizeof(struct pex_hdr);
328 int cur_len = ctx->rem;
329
330 if (cur_len > PEX_BUF_SIZE - ofs)
331 cur_len = PEX_BUF_SIZE - ofs;
332
333 memcpy(pex_msg_append(cur_len), ctx->cur, cur_len);
334 ctx->cur += cur_len;
335 ctx->rem -= cur_len;
336 }
337
338 void pex_msg_update_response_init(struct pex_msg_update_send_ctx *ctx,
339 const uint8_t *pubkey, const uint8_t *auth_key,
340 const uint8_t *peer_key, bool ext,
341 struct pex_update_request *req,
342 const void *data, int len)
343 {
344 uint8_t e_key_priv[CURVE25519_KEY_SIZE];
345 uint8_t enc_key[CURVE25519_KEY_SIZE];
346 struct pex_update_response *res;
347
348 ctx->pubkey = pubkey;
349 ctx->auth_key = auth_key;
350 ctx->ext = ext;
351 ctx->req_id = req->req_id;
352
353 if (!__pex_msg_init_ext(pubkey, auth_key, PEX_MSG_UPDATE_RESPONSE, ext))
354 return;
355
356 res = pex_msg_append(sizeof(*res));
357 res->req_id = req->req_id;
358 res->data_len = len;
359
360 if (!fread(e_key_priv, sizeof(e_key_priv), 1, pex_urandom))
361 return;
362
363 curve25519_clamp_secret(e_key_priv);
364 curve25519_generate_public(res->e_key, e_key_priv);
365 curve25519(enc_key, e_key_priv, peer_key);
366
367 ctx->data = ctx->cur = malloc(len);
368 ctx->rem = len;
369
370 memcpy(ctx->data, data, len);
371 chacha20_encrypt_msg(ctx->data, len, &req->req_id, enc_key);
372
373 pex_msg_update_response_fill(ctx);
374 }
375
376 bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx *ctx)
377 {
378 struct pex_update_response_data *res_ext;
379
380 if (ctx->rem <= 0) {
381 free(ctx->data);
382 ctx->data = NULL;
383
384 return false;
385 }
386
387 if (!__pex_msg_init_ext(ctx->pubkey, ctx->auth_key,
388 PEX_MSG_UPDATE_RESPONSE_DATA, ctx->ext))
389 return false;
390
391 res_ext = pex_msg_append(sizeof(*res_ext));
392 res_ext->req_id = ctx->req_id;
393 res_ext->offset = ctx->cur - ctx->data;
394 pex_msg_update_response_fill(ctx);
395
396 return true;
397 }
398
399
400 struct pex_update_request *
401 pex_msg_update_request_init(const uint8_t *pubkey, const uint8_t *priv_key,
402 const uint8_t *auth_key, union network_endpoint *addr,
403 uint64_t cur_version, bool ext)
404 {
405 struct pex_update_request *req;
406 struct pex_msg_update_recv_ctx *ctx;
407
408 list_for_each_entry(ctx, &requests, list) {
409 if (!memcmp(&ctx->addr, addr, sizeof(ctx->addr)))
410 return NULL;
411 }
412
413 ctx = calloc(1, sizeof(*ctx));
414 memcpy(&ctx->addr, addr, sizeof(ctx->addr));
415 memcpy(ctx->auth_key, auth_key, sizeof(ctx->auth_key));
416 memcpy(ctx->priv_key, priv_key, sizeof(ctx->priv_key));
417 if (!fread(&ctx->req_id, sizeof(ctx->req_id), 1, pex_urandom))
418 return NULL;
419 list_add_tail(&ctx->list, &requests);
420 if (!gc_timer.pending)
421 uloop_timeout_set(&gc_timer, 1000);
422
423 if (!__pex_msg_init_ext(pubkey, auth_key, PEX_MSG_UPDATE_REQUEST, ext)) {
424 free(ctx);
425 return NULL;
426 }
427
428 req = pex_msg_append(sizeof(*req));
429 req->cur_version = cpu_to_be64(cur_version);
430 req->req_id = ctx->req_id;
431
432 return req;
433 }
434
435 static struct pex_msg_update_recv_ctx *
436 pex_msg_update_recv_ctx_get(uint64_t req_id)
437 {
438 struct pex_msg_update_recv_ctx *ctx;
439
440 list_for_each_entry(ctx, &requests, list) {
441 if (ctx->req_id == req_id) {
442 ctx->idle = 0;
443 return ctx;
444 }
445 }
446
447 return NULL;
448 }
449
450 static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx *ctx)
451 {
452 list_del(&ctx->list);
453 free(ctx->data);
454 free(ctx);
455 }
456
457 void *pex_msg_update_response_recv(const void *data, int len, enum pex_opcode op,
458 int *data_len, uint64_t *timestamp)
459 {
460 struct pex_msg_update_recv_ctx *ctx;
461 uint8_t enc_key[CURVE25519_KEY_SIZE];
462 void *ret;
463
464 *data_len = 0;
465 if (op == PEX_MSG_UPDATE_RESPONSE) {
466 const struct pex_update_response *res = data;
467
468 if (len < sizeof(*res))
469 return NULL;
470
471 ctx = pex_msg_update_recv_ctx_get(res->req_id);
472 if (!ctx || ctx->data_len || !res->data_len ||
473 res->data_len > UNETD_NET_DATA_SIZE_MAX)
474 return NULL;
475
476 data += sizeof(*res);
477 len -= sizeof(*res);
478
479 ctx->data_len = res->data_len;
480 memcpy(ctx->e_key, res->e_key, sizeof(ctx->e_key));
481 ctx->data = malloc(ctx->data_len);
482 } else if (op == PEX_MSG_UPDATE_RESPONSE_DATA) {
483 const struct pex_update_response_data *res = data;
484
485 if (len <= sizeof(*res))
486 return NULL;
487
488 ctx = pex_msg_update_recv_ctx_get(res->req_id);
489 if (!ctx || ctx->data_ofs != res->offset)
490 return NULL;
491
492 data += sizeof(*res);
493 len -= sizeof(*res);
494 } else if (op == PEX_MSG_UPDATE_RESPONSE_NO_DATA) {
495 const struct pex_update_response_no_data *res = data;
496
497 if (len < sizeof(*res))
498 return NULL;
499
500 ctx = pex_msg_update_recv_ctx_get(res->req_id);
501 if (!ctx)
502 return NULL;
503
504 goto error;
505 } else {
506 return NULL;
507 }
508
509 if (ctx->data_ofs + len > ctx->data_len)
510 goto error;
511
512 memcpy(ctx->data + ctx->data_ofs, data, len);
513 ctx->data_ofs += len;
514 if (ctx->data_ofs < ctx->data_len)
515 return NULL;
516
517 curve25519(enc_key, ctx->priv_key, ctx->e_key);
518 chacha20_encrypt_msg(ctx->data, ctx->data_len, &ctx->req_id, enc_key);
519 if (unet_auth_data_validate(ctx->auth_key, ctx->data, ctx->data_len, timestamp, NULL))
520 goto error;
521
522 *data_len = ctx->data_len;
523 ret = ctx->data;
524 ctx->data = NULL;
525 pex_msg_update_ctx_free(ctx);
526
527 return ret;
528
529 error:
530 pex_msg_update_ctx_free(ctx);
531 *data_len = -1;
532 return NULL;
533 }
534
535 struct pex_hdr *pex_rx_accept(void *data, size_t len, bool ext)
536 {
537 struct pex_hdr *hdr = data;
538 uint16_t hdr_len;
539 size_t min_size;
540
541 min_size = sizeof(*hdr);
542 if (ext)
543 min_size += sizeof(struct pex_ext_hdr);
544
545 if (len < min_size)
546 return NULL;
547
548 hdr_len = ntohs(hdr->len);
549 if (len < min_size + hdr_len)
550 return NULL;
551
552 hdr->len = hdr_len;
553
554 return hdr;
555 }
556
557 static void
558 pex_gc_cb(struct uloop_timeout *t)
559 {
560 struct pex_msg_update_recv_ctx *ctx, *tmp;
561
562 list_for_each_entry_safe(ctx, tmp, &requests, list) {
563 if (++ctx->idle <= 3)
564 continue;
565
566 pex_msg_update_ctx_free(ctx);
567 }
568
569 if (!list_empty(&requests))
570 uloop_timeout_set(t, 1000);
571 }
572
573 int pex_open(void *addr, size_t addr_len, pex_recv_cb_t cb, bool server)
574 {
575 struct sockaddr *sa = addr;
576 int yes = 1, no = 0;
577 int fd;
578
579 pex_recv_cb = cb;
580
581 if (server) {
582 pex_raw_v4_fd = fd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
583 if (fd < 0)
584 return -1;
585
586 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
587 setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &yes, sizeof(yes));
588
589 #ifdef linux
590 pex_raw_v6_fd = fd = socket(PF_INET6, SOCK_RAW, IPPROTO_UDP);
591 if (fd < 0)
592 goto close_raw;
593
594 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
595 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
596 setsockopt(fd, IPPROTO_IPV6, IPV6_HDRINCL, &yes, sizeof(yes));
597 #endif
598 }
599
600 pex_urandom = fopen("/dev/urandom", "r");
601 if (!pex_urandom)
602 goto close_raw;
603
604 fd = socket(sa->sa_family == AF_INET ? PF_INET : PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
605 if (fd < 0)
606 goto close_urandom;
607
608 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
609 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
610
611 if (server) {
612 if (bind(fd, addr, addr_len) < 0) {
613 perror("bind");
614 goto close_socket;
615 }
616
617 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
618 setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
619 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
620 } else {
621 if (connect(fd, addr, addr_len) < 0) {
622 perror("connect");
623 goto close_socket;
624 }
625 }
626
627 pex_fd.fd = fd;
628 pex_fd.cb = pex_fd_cb;
629 uloop_fd_add(&pex_fd, ULOOP_READ);
630
631 gc_timer.cb = pex_gc_cb;
632
633 return 0;
634
635 close_socket:
636 close(fd);
637 close_urandom:
638 fclose(pex_urandom);
639 close_raw:
640 if (pex_raw_v4_fd >= 0)
641 close(pex_raw_v4_fd);
642 if (pex_raw_v6_fd >= 0)
643 close(pex_raw_v6_fd);
644 pex_raw_v4_fd = -1;
645 pex_raw_v6_fd = -1;
646 return -1;
647 }
648
649 int pex_unix_open(const char *path, pex_recv_control_cb_t cb)
650 {
651 mode_t prev_mask;
652 int fd;
653
654 pex_control_cb = cb;
655 unlink(path);
656
657 prev_mask = umask(0177);
658 fd = usock(USOCK_UDP | USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, path, NULL);
659 umask(prev_mask);
660 if (fd < 0)
661 return -1;
662
663 pex_unix_fd.cb = pex_unix_cb;
664 pex_unix_fd.fd = fd;
665 uloop_fd_add(&pex_unix_fd, ULOOP_READ);
666
667 return 0;
668 }
669
670 void pex_close(void)
671 {
672 if (pex_raw_v4_fd >= 0)
673 close(pex_raw_v4_fd);
674 if (pex_raw_v6_fd >= 0)
675 close(pex_raw_v6_fd);
676 pex_raw_v4_fd = -1;
677 pex_raw_v6_fd = -1;
678
679 if (pex_urandom)
680 fclose(pex_urandom);
681
682 if (pex_fd.cb) {
683 uloop_fd_delete(&pex_fd);
684 close(pex_fd.fd);
685 }
686
687 if (pex_unix_fd.cb) {
688 uloop_fd_delete(&pex_unix_fd);
689 close(pex_unix_fd.fd);
690 }
691
692 pex_fd.cb = NULL;
693 pex_unix_fd.cb = NULL;
694 pex_urandom = NULL;
695 }