1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
6 #include <sys/socket.h>
11 #include <libubox/list.h>
12 #include <libubox/uloop.h>
13 #include <libubox/usock.h>
16 #include "auth-data.h"
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;
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;
30 get_mapped_sockaddr(const void *addr
)
32 static struct sockaddr_in6 sin6
;
33 const struct sockaddr_in
*sin
= addr
;
35 if (!sin
|| sin
->sin_family
!= AF_INET
)
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
;
48 struct pex_msg_update_recv_ctx
{
49 struct list_head list
;
51 union network_endpoint addr
;
53 uint8_t priv_key
[CURVE25519_KEY_SIZE
];
54 uint8_t auth_key
[CURVE25519_KEY_SIZE
];
55 uint8_t e_key
[CURVE25519_KEY_SIZE
];
66 uint64_t pex_network_hash(const uint8_t *auth_key
, uint64_t req_id
)
76 siphash_to_be64(&hash
, auth_key
, CURVE25519_KEY_SIZE
, &key
);
82 struct pex_hdr
*__pex_msg_init(const uint8_t *pubkey
, uint8_t opcode
)
84 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
89 memcpy(hdr
->id
, pubkey
, sizeof(hdr
->id
));
94 struct pex_hdr
*__pex_msg_init_ext(const uint8_t *pubkey
, const uint8_t *auth_key
,
95 uint8_t opcode
, bool ext
)
97 struct pex_hdr
*hdr
= __pex_msg_init(pubkey
, opcode
);
98 struct pex_ext_hdr
*ehdr
= (struct pex_ext_hdr
*)(hdr
+ 1);
104 hdr
->len
= sizeof(*ehdr
);
106 if (fread(&ehdr
->nonce
, sizeof(ehdr
->nonce
), 1, pex_urandom
) != 1)
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
));
116 void *pex_msg_append(size_t len
)
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
];
122 if (sizeof(pex_tx_buf
) - ofs
< len
)
132 pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
134 static struct sockaddr_in6 sin6
;
135 static char buf
[PEX_RX_BUF_SIZE
];
139 static struct iovec iov
[2] = {
140 { .iov_base
= &sin6
},
143 static struct msghdr msg
= {
145 .msg_iovlen
= ARRAY_SIZE(iov
),
147 socklen_t slen
= sizeof(sin6
);
149 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
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
;
169 memset(&sin6
, 0, sizeof(sin6
));
170 sin
->sin_port
= port
;
171 sin
->sin_family
= AF_INET
;
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) {
190 close(pex_unix_tx_fd
);
197 pex_recv_cb(buf
, len
, &sin6
);
202 pex_unix_cb(struct uloop_fd
*fd
, unsigned int events
)
204 static char buf
[PEX_RX_BUF_SIZE
];
205 static struct iovec iov
= {
207 .iov_len
= sizeof(buf
),
212 const struct sockaddr
*sa
= (struct sockaddr
*)buf
;
213 uint8_t fd_buf
[CMSG_SPACE(sizeof(int))] = { 0 };
214 struct msghdr msg
= {
217 .msg_control
= fd_buf
,
218 .msg_controllen
= CMSG_LEN(sizeof(int)),
220 struct cmsghdr
*cmsg
;
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));
229 pfd
= (int *)CMSG_DATA(cmsg
);
232 len
= recvmsg(fd
->fd
, &msg
, 0);
245 if (pex_unix_tx_fd
>= 0)
246 close(pex_unix_tx_fd
);
248 pex_unix_tx_fd
= *pfd
;
254 if (len
< sizeof(*sa
))
257 if (sa
->sa_family
== AF_LOCAL
) {
258 slen
= sizeof(struct sockaddr
);
260 if (len
< sizeof(struct pex_msg_local_control
))
264 pex_control_cb((struct pex_msg_local_control
*)&buf
[slen
], len
);
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
);
276 sa
= get_mapped_sockaddr(sa
);
277 sendto(pex_fd
.fd
, buf
+ slen
, len
- slen
, 0, sa
, sizeof(struct sockaddr_in6
));
282 int __pex_msg_send(int fd
, const void *addr
, void *ip_hdr
, size_t ip_hdrlen
)
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
;
291 hdr
->len
-= sizeof(struct pex_ext_hdr
);
293 fd
= sa
->sa_family
== AF_INET6
? pex_raw_v6_fd
: pex_raw_v4_fd
;
296 sa
= addr
= get_mapped_sockaddr(addr
);
303 hdr
->len
= htons(hdr
->len
);
305 ret
= sendto_rawudp(fd
, addr
, ip_hdr
, ip_hdrlen
, pex_tx_buf
, tx_len
);
309 if (sa
->sa_family
== AF_INET6
)
310 addr_len
= sizeof(struct sockaddr_in6
);
312 addr_len
= sizeof(struct sockaddr_in
);
314 ret
= sendto(fd
, pex_tx_buf
, tx_len
, 0, addr
, addr_len
);
316 ret
= send(fd
, pex_tx_buf
, tx_len
, 0);
324 pex_msg_update_response_fill(struct pex_msg_update_send_ctx
*ctx
)
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
;
330 if (cur_len
> PEX_BUF_SIZE
- ofs
)
331 cur_len
= PEX_BUF_SIZE
- ofs
;
333 memcpy(pex_msg_append(cur_len
), ctx
->cur
, cur_len
);
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
)
344 uint8_t e_key_priv
[CURVE25519_KEY_SIZE
];
345 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
346 struct pex_update_response
*res
;
348 ctx
->pubkey
= pubkey
;
349 ctx
->auth_key
= auth_key
;
351 ctx
->req_id
= req
->req_id
;
353 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_RESPONSE
, ext
))
356 res
= pex_msg_append(sizeof(*res
));
357 res
->req_id
= req
->req_id
;
360 if (!fread(e_key_priv
, sizeof(e_key_priv
), 1, pex_urandom
))
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
);
367 ctx
->data
= ctx
->cur
= malloc(len
);
370 memcpy(ctx
->data
, data
, len
);
371 chacha20_encrypt_msg(ctx
->data
, len
, &req
->req_id
, enc_key
);
373 pex_msg_update_response_fill(ctx
);
376 bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx
*ctx
)
378 struct pex_update_response_data
*res_ext
;
387 if (!__pex_msg_init_ext(ctx
->pubkey
, ctx
->auth_key
,
388 PEX_MSG_UPDATE_RESPONSE_DATA
, ctx
->ext
))
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
);
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
)
405 struct pex_update_request
*req
;
406 struct pex_msg_update_recv_ctx
*ctx
;
408 list_for_each_entry(ctx
, &requests
, list
) {
409 if (!memcmp(&ctx
->addr
, addr
, sizeof(ctx
->addr
)))
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
))
419 list_add_tail(&ctx
->list
, &requests
);
420 if (!gc_timer
.pending
)
421 uloop_timeout_set(&gc_timer
, 1000);
423 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_REQUEST
, ext
)) {
428 req
= pex_msg_append(sizeof(*req
));
429 req
->cur_version
= cpu_to_be64(cur_version
);
430 req
->req_id
= ctx
->req_id
;
435 static struct pex_msg_update_recv_ctx
*
436 pex_msg_update_recv_ctx_get(uint64_t req_id
)
438 struct pex_msg_update_recv_ctx
*ctx
;
440 list_for_each_entry(ctx
, &requests
, list
) {
441 if (ctx
->req_id
== req_id
) {
450 static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx
*ctx
)
452 list_del(&ctx
->list
);
457 void *pex_msg_update_response_recv(const void *data
, int len
, enum pex_opcode op
,
458 int *data_len
, uint64_t *timestamp
)
460 struct pex_msg_update_recv_ctx
*ctx
;
461 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
465 if (op
== PEX_MSG_UPDATE_RESPONSE
) {
466 const struct pex_update_response
*res
= data
;
468 if (len
< sizeof(*res
))
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
)
476 data
+= sizeof(*res
);
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
;
485 if (len
<= sizeof(*res
))
488 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
489 if (!ctx
|| ctx
->data_ofs
!= res
->offset
)
492 data
+= sizeof(*res
);
494 } else if (op
== PEX_MSG_UPDATE_RESPONSE_NO_DATA
) {
495 const struct pex_update_response_no_data
*res
= data
;
497 if (len
< sizeof(*res
))
500 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
509 if (ctx
->data_ofs
+ len
> ctx
->data_len
)
512 memcpy(ctx
->data
+ ctx
->data_ofs
, data
, len
);
513 ctx
->data_ofs
+= len
;
514 if (ctx
->data_ofs
< ctx
->data_len
)
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
))
522 *data_len
= ctx
->data_len
;
525 pex_msg_update_ctx_free(ctx
);
530 pex_msg_update_ctx_free(ctx
);
535 struct pex_hdr
*pex_rx_accept(void *data
, size_t len
, bool ext
)
537 struct pex_hdr
*hdr
= data
;
541 min_size
= sizeof(*hdr
);
543 min_size
+= sizeof(struct pex_ext_hdr
);
548 hdr_len
= ntohs(hdr
->len
);
549 if (len
< min_size
+ hdr_len
)
558 pex_gc_cb(struct uloop_timeout
*t
)
560 struct pex_msg_update_recv_ctx
*ctx
, *tmp
;
562 list_for_each_entry_safe(ctx
, tmp
, &requests
, list
) {
563 if (++ctx
->idle
<= 3)
566 pex_msg_update_ctx_free(ctx
);
569 if (!list_empty(&requests
))
570 uloop_timeout_set(t
, 1000);
573 int pex_open(void *addr
, size_t addr_len
, pex_recv_cb_t cb
, bool server
)
575 struct sockaddr
*sa
= addr
;
582 pex_raw_v4_fd
= fd
= socket(PF_INET
, SOCK_RAW
, IPPROTO_UDP
);
586 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
587 setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &yes
, sizeof(yes
));
590 pex_raw_v6_fd
= fd
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_UDP
);
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
));
600 pex_urandom
= fopen("/dev/urandom", "r");
604 fd
= socket(sa
->sa_family
== AF_INET
? PF_INET
: PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
608 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
609 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
612 if (bind(fd
, addr
, addr_len
) < 0) {
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
));
621 if (connect(fd
, addr
, addr_len
) < 0) {
628 pex_fd
.cb
= pex_fd_cb
;
629 uloop_fd_add(&pex_fd
, ULOOP_READ
);
631 gc_timer
.cb
= pex_gc_cb
;
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
);
649 int pex_unix_open(const char *path
, pex_recv_control_cb_t cb
)
657 prev_mask
= umask(0177);
658 fd
= usock(USOCK_UDP
| USOCK_UNIX
| USOCK_SERVER
| USOCK_NONBLOCK
, path
, NULL
);
663 pex_unix_fd
.cb
= pex_unix_cb
;
665 uloop_fd_add(&pex_unix_fd
, ULOOP_READ
);
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
);
683 uloop_fd_delete(&pex_fd
);
687 if (pex_unix_fd
.cb
) {
688 uloop_fd_delete(&pex_unix_fd
);
689 close(pex_unix_fd
.fd
);
693 pex_unix_fd
.cb
= NULL
;