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;
34 int pex_raw_socket(int family
)
36 return family
== AF_INET
? pex_raw_v4_fd
: pex_raw_v6_fd
;
40 get_mapped_sockaddr(const void *addr
)
42 static struct sockaddr_in6 sin6
;
43 const struct sockaddr_in
*sin
= addr
;
45 if (!sin
|| sin
->sin_family
!= AF_INET
)
48 memset(&sin6
, 0, sizeof(sin6
));
49 sin6
.sin6_family
= AF_INET6
;
50 sin6
.sin6_addr
.s6_addr
[10] = 0xff;
51 sin6
.sin6_addr
.s6_addr
[11] = 0xff;
52 memcpy(&sin6
.sin6_addr
.s6_addr
[12], &sin
->sin_addr
, sizeof(struct in_addr
));
53 sin6
.sin6_port
= sin
->sin_port
;
58 struct pex_msg_update_recv_ctx
{
59 struct list_head list
;
61 union network_endpoint addr
;
63 uint8_t priv_key
[CURVE25519_KEY_SIZE
];
64 uint8_t auth_key
[CURVE25519_KEY_SIZE
];
65 uint8_t e_key
[CURVE25519_KEY_SIZE
];
76 uint64_t pex_network_hash(const uint8_t *auth_key
, uint64_t req_id
)
86 siphash_to_be64(&hash
, auth_key
, CURVE25519_KEY_SIZE
, &key
);
92 struct pex_hdr
*__pex_msg_init(const uint8_t *pubkey
, uint8_t opcode
)
94 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
99 memcpy(hdr
->id
, pubkey
, sizeof(hdr
->id
));
104 struct pex_hdr
*__pex_msg_init_ext(const uint8_t *pubkey
, const uint8_t *auth_key
,
105 uint8_t opcode
, bool ext
)
107 struct pex_hdr
*hdr
= __pex_msg_init(pubkey
, opcode
);
108 struct pex_ext_hdr
*ehdr
= (struct pex_ext_hdr
*)(hdr
+ 1);
114 hdr
->len
= sizeof(*ehdr
);
116 if (fread(&ehdr
->nonce
, sizeof(ehdr
->nonce
), 1, pex_urandom
) != 1)
119 hash
= pex_network_hash(auth_key
, ehdr
->nonce
);
120 *(uint64_t *)hdr
->id
^= hash
;
121 memcpy(ehdr
->auth_id
, auth_key
, sizeof(ehdr
->auth_id
));
126 void *pex_msg_append(size_t len
)
128 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
129 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
130 void *buf
= &pex_tx_buf
[ofs
];
132 if (sizeof(pex_tx_buf
) - ofs
< len
)
142 pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
144 static struct sockaddr_in6 sin6
;
145 static char buf
[PEX_RX_BUF_SIZE
];
149 static struct iovec iov
[2] = {
150 { .iov_base
= &sin6
},
153 static struct msghdr msg
= {
155 .msg_iovlen
= ARRAY_SIZE(iov
),
157 socklen_t slen
= sizeof(sin6
);
159 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
174 if (IN6_IS_ADDR_V4MAPPED(&sin6
.sin6_addr
)) {
175 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&sin6
;
176 struct in_addr in
= *(struct in_addr
*)&sin6
.sin6_addr
.s6_addr
[12];
177 int port
= sin6
.sin6_port
;
179 memset(&sin6
, 0, sizeof(sin6
));
180 sin
->sin_port
= port
;
181 sin
->sin_family
= AF_INET
;
187 if (pex_unix_tx_fd
>= 0) {
188 iov
[0].iov_len
= slen
;
189 iov
[1].iov_len
= len
;
190 if (sendmsg(pex_unix_tx_fd
, &msg
, 0) < 0) {
200 close(pex_unix_tx_fd
);
207 pex_recv_cb(buf
, len
, &sin6
);
212 pex_unix_cb(struct uloop_fd
*fd
, unsigned int events
)
214 static char buf
[PEX_RX_BUF_SIZE
];
215 static struct iovec iov
= {
217 .iov_len
= sizeof(buf
),
222 const struct sockaddr
*sa
= (struct sockaddr
*)buf
;
223 uint8_t fd_buf
[CMSG_SPACE(sizeof(int))] = { 0 };
224 struct msghdr msg
= {
227 .msg_control
= fd_buf
,
228 .msg_controllen
= CMSG_LEN(sizeof(int)),
230 struct cmsghdr
*cmsg
;
234 cmsg
= CMSG_FIRSTHDR(&msg
);
235 cmsg
->cmsg_type
= SCM_RIGHTS
;
236 cmsg
->cmsg_level
= SOL_SOCKET
;
237 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
239 pfd
= (int *)CMSG_DATA(cmsg
);
242 len
= recvmsg(fd
->fd
, &msg
, 0);
255 if (pex_unix_tx_fd
>= 0)
256 close(pex_unix_tx_fd
);
258 pex_unix_tx_fd
= *pfd
;
264 if (len
< sizeof(*sa
))
267 if (sa
->sa_family
== AF_LOCAL
) {
268 slen
= sizeof(struct sockaddr
);
270 if (len
< sizeof(struct pex_msg_local_control
))
274 pex_control_cb((struct pex_msg_local_control
*)&buf
[slen
], len
);
279 if (sa
->sa_family
== AF_INET
)
280 slen
= sizeof(struct sockaddr_in
);
281 else if (sa
->sa_family
== AF_INET6
)
282 slen
= sizeof(struct sockaddr_in6
);
286 sa
= get_mapped_sockaddr(sa
);
287 sendto(pex_fd
.fd
, buf
+ slen
, len
- slen
, 0, sa
, sizeof(struct sockaddr_in6
));
292 int __pex_msg_send(int fd
, const void *addr
, void *ip_hdr
, size_t ip_hdrlen
)
294 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
295 const struct sockaddr
*sa
= addr
;
296 size_t tx_len
= sizeof(*hdr
) + hdr
->len
;
297 uint16_t orig_len
= hdr
->len
;
301 hdr
->len
-= sizeof(struct pex_ext_hdr
);
303 fd
= pex_raw_socket(sa
->sa_family
);
306 sa
= addr
= get_mapped_sockaddr(addr
);
313 hdr
->len
= htons(hdr
->len
);
315 ret
= sendto_rawudp(fd
, addr
, ip_hdr
, ip_hdrlen
, pex_tx_buf
, tx_len
);
319 if (sa
->sa_family
== AF_INET6
)
320 addr_len
= sizeof(struct sockaddr_in6
);
322 addr_len
= sizeof(struct sockaddr_in
);
324 ret
= sendto(fd
, pex_tx_buf
, tx_len
, 0, addr
, addr_len
);
326 ret
= send(fd
, pex_tx_buf
, tx_len
, 0);
334 pex_msg_update_response_fill(struct pex_msg_update_send_ctx
*ctx
)
336 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
337 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
338 int cur_len
= ctx
->rem
;
340 if (cur_len
> PEX_BUF_SIZE
- ofs
)
341 cur_len
= PEX_BUF_SIZE
- ofs
;
343 memcpy(pex_msg_append(cur_len
), ctx
->cur
, cur_len
);
348 void pex_msg_update_response_init(struct pex_msg_update_send_ctx
*ctx
,
349 const uint8_t *pubkey
, const uint8_t *auth_key
,
350 const uint8_t *peer_key
, bool ext
,
351 struct pex_update_request
*req
,
352 const void *data
, int len
)
354 uint8_t e_key_priv
[CURVE25519_KEY_SIZE
];
355 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
356 struct pex_update_response
*res
;
358 ctx
->pubkey
= pubkey
;
359 ctx
->auth_key
= auth_key
;
361 ctx
->req_id
= req
->req_id
;
363 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_RESPONSE
, ext
))
366 res
= pex_msg_append(sizeof(*res
));
367 res
->req_id
= req
->req_id
;
370 if (!fread(e_key_priv
, sizeof(e_key_priv
), 1, pex_urandom
))
373 curve25519_clamp_secret(e_key_priv
);
374 curve25519_generate_public(res
->e_key
, e_key_priv
);
375 curve25519(enc_key
, e_key_priv
, peer_key
);
377 ctx
->data
= ctx
->cur
= malloc(len
);
380 memcpy(ctx
->data
, data
, len
);
381 chacha20_encrypt_msg(ctx
->data
, len
, &req
->req_id
, enc_key
);
383 pex_msg_update_response_fill(ctx
);
386 bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx
*ctx
)
388 struct pex_update_response_data
*res_ext
;
397 if (!__pex_msg_init_ext(ctx
->pubkey
, ctx
->auth_key
,
398 PEX_MSG_UPDATE_RESPONSE_DATA
, ctx
->ext
))
401 res_ext
= pex_msg_append(sizeof(*res_ext
));
402 res_ext
->req_id
= ctx
->req_id
;
403 res_ext
->offset
= ctx
->cur
- ctx
->data
;
404 pex_msg_update_response_fill(ctx
);
410 struct pex_update_request
*
411 pex_msg_update_request_init(const uint8_t *pubkey
, const uint8_t *priv_key
,
412 const uint8_t *auth_key
, union network_endpoint
*addr
,
413 uint64_t cur_version
, bool ext
)
415 struct pex_update_request
*req
;
416 struct pex_msg_update_recv_ctx
*ctx
;
418 list_for_each_entry(ctx
, &requests
, list
) {
419 if (!memcmp(&ctx
->addr
, addr
, sizeof(ctx
->addr
)))
423 ctx
= calloc(1, sizeof(*ctx
));
424 memcpy(&ctx
->addr
, addr
, sizeof(ctx
->addr
));
425 memcpy(ctx
->auth_key
, auth_key
, sizeof(ctx
->auth_key
));
426 memcpy(ctx
->priv_key
, priv_key
, sizeof(ctx
->priv_key
));
427 if (!fread(&ctx
->req_id
, sizeof(ctx
->req_id
), 1, pex_urandom
))
429 list_add_tail(&ctx
->list
, &requests
);
430 if (!gc_timer
.pending
)
431 uloop_timeout_set(&gc_timer
, 1000);
433 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_REQUEST
, ext
)) {
438 req
= pex_msg_append(sizeof(*req
));
439 req
->cur_version
= cpu_to_be64(cur_version
);
440 req
->req_id
= ctx
->req_id
;
445 static struct pex_msg_update_recv_ctx
*
446 pex_msg_update_recv_ctx_get(uint64_t req_id
)
448 struct pex_msg_update_recv_ctx
*ctx
;
450 list_for_each_entry(ctx
, &requests
, list
) {
451 if (ctx
->req_id
== req_id
) {
460 static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx
*ctx
)
462 list_del(&ctx
->list
);
467 void *pex_msg_update_response_recv(const void *data
, int len
, enum pex_opcode op
,
468 int *data_len
, uint64_t *timestamp
)
470 struct pex_msg_update_recv_ctx
*ctx
;
471 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
475 if (op
== PEX_MSG_UPDATE_RESPONSE
) {
476 const struct pex_update_response
*res
= data
;
478 if (len
< sizeof(*res
))
481 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
482 if (!ctx
|| ctx
->data_len
|| !res
->data_len
||
483 res
->data_len
> UNETD_NET_DATA_SIZE_MAX
)
486 data
+= sizeof(*res
);
489 ctx
->data_len
= res
->data_len
;
490 memcpy(ctx
->e_key
, res
->e_key
, sizeof(ctx
->e_key
));
491 ctx
->data
= malloc(ctx
->data_len
);
492 } else if (op
== PEX_MSG_UPDATE_RESPONSE_DATA
) {
493 const struct pex_update_response_data
*res
= data
;
495 if (len
<= sizeof(*res
))
498 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
499 if (!ctx
|| ctx
->data_ofs
!= res
->offset
)
502 data
+= sizeof(*res
);
504 } else if (op
== PEX_MSG_UPDATE_RESPONSE_NO_DATA
) {
505 const struct pex_update_response_no_data
*res
= data
;
507 if (len
< sizeof(*res
))
510 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
519 if (ctx
->data_ofs
+ len
> ctx
->data_len
)
522 memcpy(ctx
->data
+ ctx
->data_ofs
, data
, len
);
523 ctx
->data_ofs
+= len
;
524 if (ctx
->data_ofs
< ctx
->data_len
)
527 curve25519(enc_key
, ctx
->priv_key
, ctx
->e_key
);
528 chacha20_encrypt_msg(ctx
->data
, ctx
->data_len
, &ctx
->req_id
, enc_key
);
529 if (unet_auth_data_validate(ctx
->auth_key
, ctx
->data
, ctx
->data_len
, timestamp
, NULL
))
532 *data_len
= ctx
->data_len
;
535 pex_msg_update_ctx_free(ctx
);
540 pex_msg_update_ctx_free(ctx
);
545 struct pex_hdr
*pex_rx_accept(void *data
, size_t len
, bool ext
)
547 struct pex_hdr
*hdr
= data
;
551 min_size
= sizeof(*hdr
);
553 min_size
+= sizeof(struct pex_ext_hdr
);
558 hdr_len
= ntohs(hdr
->len
);
559 if (len
< min_size
+ hdr_len
)
568 pex_gc_cb(struct uloop_timeout
*t
)
570 struct pex_msg_update_recv_ctx
*ctx
, *tmp
;
572 list_for_each_entry_safe(ctx
, tmp
, &requests
, list
) {
573 if (++ctx
->idle
<= 3)
576 pex_msg_update_ctx_free(ctx
);
579 if (!list_empty(&requests
))
580 uloop_timeout_set(t
, 1000);
583 int pex_open(void *addr
, size_t addr_len
, pex_recv_cb_t cb
, bool server
)
585 struct sockaddr
*sa
= addr
;
592 pex_raw_v4_fd
= fd
= socket(PF_INET
, SOCK_RAW
, IPPROTO_UDP
);
596 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
597 setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &yes
, sizeof(yes
));
600 pex_raw_v6_fd
= fd
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_UDP
);
604 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
605 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
606 setsockopt(fd
, IPPROTO_IPV6
, IPV6_HDRINCL
, &yes
, sizeof(yes
));
610 pex_urandom
= fopen("/dev/urandom", "r");
614 fd
= socket(sa
->sa_family
== AF_INET
? PF_INET
: PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
618 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
619 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
622 if (bind(fd
, addr
, addr_len
) < 0) {
627 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
628 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
629 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
631 if (connect(fd
, addr
, addr_len
) < 0) {
638 pex_fd
.cb
= pex_fd_cb
;
639 uloop_fd_add(&pex_fd
, ULOOP_READ
);
641 gc_timer
.cb
= pex_gc_cb
;
650 if (pex_raw_v4_fd
>= 0)
651 close(pex_raw_v4_fd
);
652 if (pex_raw_v6_fd
>= 0)
653 close(pex_raw_v6_fd
);
659 int pex_unix_open(const char *path
, pex_recv_control_cb_t cb
)
667 prev_mask
= umask(0177);
668 fd
= usock(USOCK_UDP
| USOCK_UNIX
| USOCK_SERVER
| USOCK_NONBLOCK
, path
, NULL
);
673 pex_unix_fd
.cb
= pex_unix_cb
;
675 uloop_fd_add(&pex_unix_fd
, ULOOP_READ
);
682 if (pex_raw_v4_fd
>= 0)
683 close(pex_raw_v4_fd
);
684 if (pex_raw_v6_fd
>= 0)
685 close(pex_raw_v6_fd
);
693 uloop_fd_delete(&pex_fd
);
697 if (pex_unix_fd
.cb
) {
698 uloop_fd_delete(&pex_unix_fd
);
699 close(pex_unix_fd
.fd
);
703 pex_unix_fd
.cb
= NULL
;