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>
14 #include <netinet/in.h>
15 #include <netinet/ip.h>
16 #include <netinet/ip6.h>
17 #include <netinet/udp.h>
20 #include "auth-data.h"
22 static char pex_tx_buf
[PEX_BUF_SIZE
];
23 static FILE *pex_urandom
;
24 static struct uloop_fd pex_fd
, pex_unix_fd
;
25 static LIST_HEAD(requests
);
26 static struct uloop_timeout gc_timer
;
27 static int pex_raw_v4_fd
= -1, pex_raw_v6_fd
= -1;
29 static pex_recv_cb_t pex_recv_cb
;
30 static pex_recv_control_cb_t pex_control_cb
;
31 static int pex_unix_tx_fd
= -1;
34 get_mapped_sockaddr(const void *addr
)
36 static struct sockaddr_in6 sin6
;
37 const struct sockaddr_in
*sin
= addr
;
39 if (!sin
|| sin
->sin_family
!= AF_INET
)
42 memset(&sin6
, 0, sizeof(sin6
));
43 sin6
.sin6_family
= AF_INET6
;
44 sin6
.sin6_addr
.s6_addr
[10] = 0xff;
45 sin6
.sin6_addr
.s6_addr
[11] = 0xff;
46 memcpy(&sin6
.sin6_addr
.s6_addr
[12], &sin
->sin_addr
, sizeof(struct in_addr
));
47 sin6
.sin6_port
= sin
->sin_port
;
52 struct pex_msg_update_recv_ctx
{
53 struct list_head list
;
55 union network_endpoint addr
;
57 uint8_t priv_key
[CURVE25519_KEY_SIZE
];
58 uint8_t auth_key
[CURVE25519_KEY_SIZE
];
59 uint8_t e_key
[CURVE25519_KEY_SIZE
];
70 uint64_t pex_network_hash(const uint8_t *auth_key
, uint64_t req_id
)
80 siphash_to_be64(&hash
, auth_key
, CURVE25519_KEY_SIZE
, &key
);
86 struct pex_hdr
*__pex_msg_init(const uint8_t *pubkey
, uint8_t opcode
)
88 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
93 memcpy(hdr
->id
, pubkey
, sizeof(hdr
->id
));
98 struct pex_hdr
*__pex_msg_init_ext(const uint8_t *pubkey
, const uint8_t *auth_key
,
99 uint8_t opcode
, bool ext
)
101 struct pex_hdr
*hdr
= __pex_msg_init(pubkey
, opcode
);
102 struct pex_ext_hdr
*ehdr
= (struct pex_ext_hdr
*)(hdr
+ 1);
108 hdr
->len
= sizeof(*ehdr
);
110 if (fread(&ehdr
->nonce
, sizeof(ehdr
->nonce
), 1, pex_urandom
) != 1)
113 hash
= pex_network_hash(auth_key
, ehdr
->nonce
);
114 *(uint64_t *)hdr
->id
^= hash
;
115 memcpy(ehdr
->auth_id
, auth_key
, sizeof(ehdr
->auth_id
));
120 void *pex_msg_append(size_t len
)
122 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
123 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
124 void *buf
= &pex_tx_buf
[ofs
];
126 if (sizeof(pex_tx_buf
) - ofs
< len
)
136 pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
138 static struct sockaddr_in6 sin6
;
139 static char buf
[PEX_RX_BUF_SIZE
];
140 struct pex_hdr
*hdr
= (struct pex_hdr
*)buf
;
144 static struct iovec iov
[2] = {
145 { .iov_base
= &sin6
},
148 static struct msghdr msg
= {
150 .msg_iovlen
= ARRAY_SIZE(iov
),
152 socklen_t slen
= sizeof(sin6
);
154 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
169 if (IN6_IS_ADDR_V4MAPPED(&sin6
.sin6_addr
)) {
170 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&sin6
;
171 struct in_addr in
= *(struct in_addr
*)&sin6
.sin6_addr
.s6_addr
[12];
172 int port
= sin6
.sin6_port
;
174 memset(&sin6
, 0, sizeof(sin6
));
175 sin
->sin_port
= port
;
176 sin
->sin_family
= AF_INET
;
182 if (pex_unix_tx_fd
>= 0) {
183 iov
[0].iov_len
= slen
;
184 iov
[1].iov_len
= len
;
185 if (sendmsg(pex_unix_tx_fd
, &msg
, 0) < 0) {
195 close(pex_unix_tx_fd
);
202 if (len
< sizeof(*hdr
) + sizeof(struct pex_ext_hdr
))
205 hdr
->len
= ntohs(hdr
->len
);
206 if (len
- sizeof(hdr
) - sizeof(struct pex_ext_hdr
) < hdr
->len
)
209 pex_recv_cb(hdr
, &sin6
);
214 pex_unix_cb(struct uloop_fd
*fd
, unsigned int events
)
216 static char buf
[PEX_RX_BUF_SIZE
];
217 static struct iovec iov
= {
219 .iov_len
= sizeof(buf
),
224 const struct sockaddr
*sa
= (struct sockaddr
*)buf
;
225 uint8_t fd_buf
[CMSG_SPACE(sizeof(int))] = { 0 };
226 struct msghdr msg
= {
229 .msg_control
= fd_buf
,
230 .msg_controllen
= CMSG_LEN(sizeof(int)),
232 struct cmsghdr
*cmsg
;
236 cmsg
= CMSG_FIRSTHDR(&msg
);
237 cmsg
->cmsg_type
= SCM_RIGHTS
;
238 cmsg
->cmsg_level
= SOL_SOCKET
;
239 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
241 pfd
= (int *)CMSG_DATA(cmsg
);
244 len
= recvmsg(fd
->fd
, &msg
, 0);
257 if (pex_unix_tx_fd
>= 0)
258 close(pex_unix_tx_fd
);
260 pex_unix_tx_fd
= *pfd
;
266 if (len
< sizeof(*sa
))
269 if (sa
->sa_family
== AF_LOCAL
) {
270 slen
= sizeof(struct sockaddr
);
272 if (len
< sizeof(struct pex_msg_local_control
))
276 pex_control_cb((struct pex_msg_local_control
*)&buf
[slen
], len
);
281 if (sa
->sa_family
== AF_INET
)
282 slen
= sizeof(struct sockaddr_in
);
283 else if (sa
->sa_family
== AF_INET6
)
284 slen
= sizeof(struct sockaddr_in6
);
288 sa
= get_mapped_sockaddr(sa
);
289 sendto(pex_fd
.fd
, buf
+ slen
, len
- slen
, 0, sa
, sizeof(struct sockaddr_in6
));
293 static inline uint32_t
294 csum_tcpudp_nofold(uint32_t saddr
, uint32_t daddr
, uint32_t len
, uint8_t proto
)
300 #if __BYTE_ORDER == __LITTLE_ENDIAN
301 sum
+= (proto
+ len
) << 8;
306 sum
= (sum
& 0xffffffff) + (sum
>> 32);
307 sum
= (sum
& 0xffffffff) + (sum
>> 32);
309 return (uint32_t)sum
;
312 static inline uint32_t csum_add(uint32_t sum
, uint32_t addend
)
315 return sum
+ (sum
< addend
);
318 static inline uint16_t csum_fold(uint32_t sum
)
320 sum
= (sum
& 0xffff) + (sum
>> 16);
321 sum
= (sum
& 0xffff) + (sum
>> 16);
323 return (uint16_t)~sum
;
326 static uint32_t csum_partial(const void *buf
, int len
)
328 const uint16_t *data
= buf
;
337 #if __BYTE_ORDER == __LITTLE_ENDIAN
338 sum
+= *(uint8_t *)data
;
340 sum
+= *(uint8_t *)data
<< 8;
343 sum
= (sum
& 0xffff) + (sum
>> 16);
344 sum
= (sum
& 0xffff) + (sum
>> 16);
349 static void pex_fixup_udpv4(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
352 struct udphdr
*udp
= hdr
+ ip
->ip_hl
* 4;
353 uint16_t udp_len
= sizeof(*udp
) + len
;
356 if ((void *)&udp
[1] > hdr
+ hdrlen
)
360 udp
->uh_ulen
= htons(udp_len
);
361 sum
= csum_tcpudp_nofold(*(uint32_t *)&ip
->ip_src
, *(uint32_t *)&ip
->ip_dst
,
363 sum
= csum_add(sum
, csum_partial(udp
, sizeof(*udp
)));
364 sum
= csum_add(sum
, csum_partial(data
, len
));
365 udp
->uh_sum
= csum_fold(sum
);
367 ip
->ip_len
= htons(hdrlen
+ len
);
369 ip
->ip_sum
= csum_fold(csum_partial(ip
, sizeof(*ip
)));
372 ip
->ip_len
= hdrlen
+ len
;
376 static void pex_fixup_udpv6(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
378 struct ip6_hdr
*ip
= hdr
;
379 struct udphdr
*udp
= hdr
+ sizeof(*ip
);
380 uint16_t udp_len
= htons(sizeof(*udp
) + len
);
382 if ((void *)&udp
[1] > hdr
+ hdrlen
)
385 ip
->ip6_plen
= htons(sizeof(*udp
) + len
);
387 udp
->uh_ulen
= udp_len
;
388 udp
->uh_sum
= csum_fold(csum_partial(hdr
, sizeof(*ip
) + sizeof(*udp
)));
391 ip
->ip6_plen
= sizeof(*udp
) + len
;
395 static void pex_fixup_header(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
397 if (hdrlen
>= sizeof(struct ip6_hdr
) + sizeof(struct udphdr
))
398 pex_fixup_udpv6(hdr
, hdrlen
, data
, len
);
399 else if (hdrlen
>= sizeof(struct ip
) + sizeof(struct udphdr
))
400 pex_fixup_udpv4(hdr
, hdrlen
, data
, len
);
403 int __pex_msg_send(int fd
, const void *addr
, void *ip_hdr
, size_t ip_hdrlen
)
405 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
406 const struct sockaddr
*sa
= addr
;
407 size_t tx_len
= sizeof(*hdr
) + hdr
->len
;
408 uint16_t orig_len
= hdr
->len
;
412 hdr
->len
-= sizeof(struct pex_ext_hdr
);
414 fd
= sa
->sa_family
== AF_INET6
? pex_raw_v6_fd
: pex_raw_v4_fd
;
417 sa
= addr
= get_mapped_sockaddr(addr
);
424 hdr
->len
= htons(hdr
->len
);
426 struct iovec iov
[2] = {
427 { .iov_base
= (void *)ip_hdr
, .iov_len
= ip_hdrlen
},
428 { .iov_base
= pex_tx_buf
, .iov_len
= tx_len
}
430 struct msghdr msg
= {
431 .msg_name
= (void *)addr
,
433 .msg_iovlen
= ARRAY_SIZE(iov
),
436 if (sa
->sa_family
== AF_INET6
)
437 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
439 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
442 pex_fixup_header(ip_hdr
, ip_hdrlen
, pex_tx_buf
, tx_len
);
448 ret
= sendmsg(fd
, &msg
, 0);
450 ret
= send(fd
, pex_tx_buf
, tx_len
, 0);
458 pex_msg_update_response_fill(struct pex_msg_update_send_ctx
*ctx
)
460 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
461 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
462 int cur_len
= ctx
->rem
;
464 if (cur_len
> PEX_BUF_SIZE
- ofs
)
465 cur_len
= PEX_BUF_SIZE
- ofs
;
467 memcpy(pex_msg_append(cur_len
), ctx
->cur
, cur_len
);
472 void pex_msg_update_response_init(struct pex_msg_update_send_ctx
*ctx
,
473 const uint8_t *pubkey
, const uint8_t *auth_key
,
474 const uint8_t *peer_key
, bool ext
,
475 struct pex_update_request
*req
,
476 const void *data
, int len
)
478 uint8_t e_key_priv
[CURVE25519_KEY_SIZE
];
479 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
480 struct pex_update_response
*res
;
482 ctx
->pubkey
= pubkey
;
483 ctx
->auth_key
= auth_key
;
485 ctx
->req_id
= req
->req_id
;
487 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_RESPONSE
, ext
))
490 res
= pex_msg_append(sizeof(*res
));
491 res
->req_id
= req
->req_id
;
494 if (!fread(e_key_priv
, sizeof(e_key_priv
), 1, pex_urandom
))
497 curve25519_clamp_secret(e_key_priv
);
498 curve25519_generate_public(res
->e_key
, e_key_priv
);
499 curve25519(enc_key
, e_key_priv
, peer_key
);
501 ctx
->data
= ctx
->cur
= malloc(len
);
504 memcpy(ctx
->data
, data
, len
);
505 chacha20_encrypt_msg(ctx
->data
, len
, &req
->req_id
, enc_key
);
507 pex_msg_update_response_fill(ctx
);
510 bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx
*ctx
)
512 struct pex_update_response_data
*res_ext
;
521 if (!__pex_msg_init_ext(ctx
->pubkey
, ctx
->auth_key
,
522 PEX_MSG_UPDATE_RESPONSE_DATA
, ctx
->ext
))
525 res_ext
= pex_msg_append(sizeof(*res_ext
));
526 res_ext
->req_id
= ctx
->req_id
;
527 res_ext
->offset
= ctx
->cur
- ctx
->data
;
528 pex_msg_update_response_fill(ctx
);
534 struct pex_update_request
*
535 pex_msg_update_request_init(const uint8_t *pubkey
, const uint8_t *priv_key
,
536 const uint8_t *auth_key
, union network_endpoint
*addr
,
537 uint64_t cur_version
, bool ext
)
539 struct pex_update_request
*req
;
540 struct pex_msg_update_recv_ctx
*ctx
;
542 list_for_each_entry(ctx
, &requests
, list
) {
543 if (!memcmp(&ctx
->addr
, addr
, sizeof(ctx
->addr
)))
547 ctx
= calloc(1, sizeof(*ctx
));
548 memcpy(&ctx
->addr
, addr
, sizeof(ctx
->addr
));
549 memcpy(ctx
->auth_key
, auth_key
, sizeof(ctx
->auth_key
));
550 memcpy(ctx
->priv_key
, priv_key
, sizeof(ctx
->priv_key
));
551 if (!fread(&ctx
->req_id
, sizeof(ctx
->req_id
), 1, pex_urandom
))
553 list_add_tail(&ctx
->list
, &requests
);
554 if (!gc_timer
.pending
)
555 uloop_timeout_set(&gc_timer
, 1000);
557 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_REQUEST
, ext
)) {
562 req
= pex_msg_append(sizeof(*req
));
563 req
->cur_version
= cpu_to_be64(cur_version
);
564 req
->req_id
= ctx
->req_id
;
569 static struct pex_msg_update_recv_ctx
*
570 pex_msg_update_recv_ctx_get(uint64_t req_id
)
572 struct pex_msg_update_recv_ctx
*ctx
;
574 list_for_each_entry(ctx
, &requests
, list
) {
575 if (ctx
->req_id
== req_id
) {
584 static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx
*ctx
)
586 list_del(&ctx
->list
);
591 void *pex_msg_update_response_recv(const void *data
, int len
, enum pex_opcode op
,
592 int *data_len
, uint64_t *timestamp
)
594 struct pex_msg_update_recv_ctx
*ctx
;
595 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
599 if (op
== PEX_MSG_UPDATE_RESPONSE
) {
600 const struct pex_update_response
*res
= data
;
602 if (len
< sizeof(*res
))
605 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
606 if (!ctx
|| ctx
->data_len
|| !res
->data_len
||
607 res
->data_len
> UNETD_NET_DATA_SIZE_MAX
)
610 data
+= sizeof(*res
);
613 ctx
->data_len
= res
->data_len
;
614 memcpy(ctx
->e_key
, res
->e_key
, sizeof(ctx
->e_key
));
615 ctx
->data
= malloc(ctx
->data_len
);
616 } else if (op
== PEX_MSG_UPDATE_RESPONSE_DATA
) {
617 const struct pex_update_response_data
*res
= data
;
619 if (len
<= sizeof(*res
))
622 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
623 if (!ctx
|| ctx
->data_ofs
!= res
->offset
)
626 data
+= sizeof(*res
);
628 } else if (op
== PEX_MSG_UPDATE_RESPONSE_NO_DATA
) {
629 const struct pex_update_response_no_data
*res
= data
;
631 if (len
< sizeof(*res
))
634 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
643 if (ctx
->data_ofs
+ len
> ctx
->data_len
)
646 memcpy(ctx
->data
+ ctx
->data_ofs
, data
, len
);
647 ctx
->data_ofs
+= len
;
648 if (ctx
->data_ofs
< ctx
->data_len
)
651 curve25519(enc_key
, ctx
->priv_key
, ctx
->e_key
);
652 chacha20_encrypt_msg(ctx
->data
, ctx
->data_len
, &ctx
->req_id
, enc_key
);
653 if (unet_auth_data_validate(ctx
->auth_key
, ctx
->data
, ctx
->data_len
, timestamp
, NULL
))
656 *data_len
= ctx
->data_len
;
659 pex_msg_update_ctx_free(ctx
);
664 pex_msg_update_ctx_free(ctx
);
670 pex_gc_cb(struct uloop_timeout
*t
)
672 struct pex_msg_update_recv_ctx
*ctx
, *tmp
;
674 list_for_each_entry_safe(ctx
, tmp
, &requests
, list
) {
675 if (++ctx
->idle
<= 3)
678 pex_msg_update_ctx_free(ctx
);
681 if (!list_empty(&requests
))
682 uloop_timeout_set(t
, 1000);
685 int pex_open(void *addr
, size_t addr_len
, pex_recv_cb_t cb
, bool server
)
687 struct sockaddr
*sa
= addr
;
694 pex_raw_v4_fd
= fd
= socket(PF_INET
, SOCK_RAW
, IPPROTO_UDP
);
698 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
699 setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &yes
, sizeof(yes
));
702 pex_raw_v6_fd
= fd
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_UDP
);
706 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
707 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
708 setsockopt(fd
, IPPROTO_IPV6
, IPV6_HDRINCL
, &yes
, sizeof(yes
));
712 pex_urandom
= fopen("/dev/urandom", "r");
716 fd
= socket(sa
->sa_family
== AF_INET
? PF_INET
: PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
720 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
721 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
724 if (bind(fd
, addr
, addr_len
) < 0) {
729 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
730 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
731 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
733 if (connect(fd
, addr
, addr_len
) < 0) {
740 pex_fd
.cb
= pex_fd_cb
;
741 uloop_fd_add(&pex_fd
, ULOOP_READ
);
743 gc_timer
.cb
= pex_gc_cb
;
752 if (pex_raw_v4_fd
>= 0)
753 close(pex_raw_v4_fd
);
754 if (pex_raw_v6_fd
>= 0)
755 close(pex_raw_v6_fd
);
761 int pex_unix_open(const char *path
, pex_recv_control_cb_t cb
)
769 prev_mask
= umask(0177);
770 fd
= usock(USOCK_UDP
| USOCK_UNIX
| USOCK_SERVER
| USOCK_NONBLOCK
, path
, NULL
);
775 pex_unix_fd
.cb
= pex_unix_cb
;
777 uloop_fd_add(&pex_unix_fd
, ULOOP_READ
);
784 if (pex_raw_v4_fd
>= 0)
785 close(pex_raw_v4_fd
);
786 if (pex_raw_v6_fd
>= 0)
787 close(pex_raw_v6_fd
);
795 uloop_fd_delete(&pex_fd
);
799 if (pex_unix_fd
.cb
) {
800 uloop_fd_delete(&pex_unix_fd
);
801 close(pex_unix_fd
.fd
);
805 pex_unix_fd
.cb
= NULL
;