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
];
143 static struct iovec iov
[2] = {
144 { .iov_base
= &sin6
},
147 static struct msghdr msg
= {
149 .msg_iovlen
= ARRAY_SIZE(iov
),
151 socklen_t slen
= sizeof(sin6
);
153 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
168 if (IN6_IS_ADDR_V4MAPPED(&sin6
.sin6_addr
)) {
169 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&sin6
;
170 struct in_addr in
= *(struct in_addr
*)&sin6
.sin6_addr
.s6_addr
[12];
171 int port
= sin6
.sin6_port
;
173 memset(&sin6
, 0, sizeof(sin6
));
174 sin
->sin_port
= port
;
175 sin
->sin_family
= AF_INET
;
181 if (pex_unix_tx_fd
>= 0) {
182 iov
[0].iov_len
= slen
;
183 iov
[1].iov_len
= len
;
184 if (sendmsg(pex_unix_tx_fd
, &msg
, 0) < 0) {
194 close(pex_unix_tx_fd
);
201 pex_recv_cb(buf
, len
, &sin6
);
206 pex_unix_cb(struct uloop_fd
*fd
, unsigned int events
)
208 static char buf
[PEX_RX_BUF_SIZE
];
209 static struct iovec iov
= {
211 .iov_len
= sizeof(buf
),
216 const struct sockaddr
*sa
= (struct sockaddr
*)buf
;
217 uint8_t fd_buf
[CMSG_SPACE(sizeof(int))] = { 0 };
218 struct msghdr msg
= {
221 .msg_control
= fd_buf
,
222 .msg_controllen
= CMSG_LEN(sizeof(int)),
224 struct cmsghdr
*cmsg
;
228 cmsg
= CMSG_FIRSTHDR(&msg
);
229 cmsg
->cmsg_type
= SCM_RIGHTS
;
230 cmsg
->cmsg_level
= SOL_SOCKET
;
231 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
233 pfd
= (int *)CMSG_DATA(cmsg
);
236 len
= recvmsg(fd
->fd
, &msg
, 0);
249 if (pex_unix_tx_fd
>= 0)
250 close(pex_unix_tx_fd
);
252 pex_unix_tx_fd
= *pfd
;
258 if (len
< sizeof(*sa
))
261 if (sa
->sa_family
== AF_LOCAL
) {
262 slen
= sizeof(struct sockaddr
);
264 if (len
< sizeof(struct pex_msg_local_control
))
268 pex_control_cb((struct pex_msg_local_control
*)&buf
[slen
], len
);
273 if (sa
->sa_family
== AF_INET
)
274 slen
= sizeof(struct sockaddr_in
);
275 else if (sa
->sa_family
== AF_INET6
)
276 slen
= sizeof(struct sockaddr_in6
);
280 sa
= get_mapped_sockaddr(sa
);
281 sendto(pex_fd
.fd
, buf
+ slen
, len
- slen
, 0, sa
, sizeof(struct sockaddr_in6
));
285 static inline uint32_t
286 csum_tcpudp_nofold(uint32_t saddr
, uint32_t daddr
, uint32_t len
, uint8_t proto
)
292 #if __BYTE_ORDER == __LITTLE_ENDIAN
293 sum
+= (proto
+ len
) << 8;
298 sum
= (sum
& 0xffffffff) + (sum
>> 32);
299 sum
= (sum
& 0xffffffff) + (sum
>> 32);
301 return (uint32_t)sum
;
304 static inline uint32_t csum_add(uint32_t sum
, uint32_t addend
)
307 return sum
+ (sum
< addend
);
310 static inline uint16_t csum_fold(uint32_t sum
)
312 sum
= (sum
& 0xffff) + (sum
>> 16);
313 sum
= (sum
& 0xffff) + (sum
>> 16);
315 return (uint16_t)~sum
;
318 static uint32_t csum_partial(const void *buf
, int len
)
320 const uint16_t *data
= buf
;
329 #if __BYTE_ORDER == __LITTLE_ENDIAN
330 sum
+= *(uint8_t *)data
;
332 sum
+= *(uint8_t *)data
<< 8;
335 sum
= (sum
& 0xffff) + (sum
>> 16);
336 sum
= (sum
& 0xffff) + (sum
>> 16);
341 static void pex_fixup_udpv4(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
344 struct udphdr
*udp
= hdr
+ ip
->ip_hl
* 4;
345 uint16_t udp_len
= sizeof(*udp
) + len
;
348 if ((void *)&udp
[1] > hdr
+ hdrlen
)
352 udp
->uh_ulen
= htons(udp_len
);
353 sum
= csum_tcpudp_nofold(*(uint32_t *)&ip
->ip_src
, *(uint32_t *)&ip
->ip_dst
,
355 sum
= csum_add(sum
, csum_partial(udp
, sizeof(*udp
)));
356 sum
= csum_add(sum
, csum_partial(data
, len
));
357 udp
->uh_sum
= csum_fold(sum
);
359 ip
->ip_len
= htons(hdrlen
+ len
);
361 ip
->ip_sum
= csum_fold(csum_partial(ip
, sizeof(*ip
)));
364 ip
->ip_len
= hdrlen
+ len
;
368 static void pex_fixup_udpv6(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
370 struct ip6_hdr
*ip
= hdr
;
371 struct udphdr
*udp
= hdr
+ sizeof(*ip
);
372 uint16_t udp_len
= htons(sizeof(*udp
) + len
);
374 if ((void *)&udp
[1] > hdr
+ hdrlen
)
377 ip
->ip6_plen
= htons(sizeof(*udp
) + len
);
379 udp
->uh_ulen
= udp_len
;
380 udp
->uh_sum
= csum_fold(csum_partial(hdr
, sizeof(*ip
) + sizeof(*udp
)));
383 ip
->ip6_plen
= sizeof(*udp
) + len
;
387 static void pex_fixup_header(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
389 if (hdrlen
>= sizeof(struct ip6_hdr
) + sizeof(struct udphdr
))
390 pex_fixup_udpv6(hdr
, hdrlen
, data
, len
);
391 else if (hdrlen
>= sizeof(struct ip
) + sizeof(struct udphdr
))
392 pex_fixup_udpv4(hdr
, hdrlen
, data
, len
);
395 int __pex_msg_send(int fd
, const void *addr
, void *ip_hdr
, size_t ip_hdrlen
)
397 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
398 const struct sockaddr
*sa
= addr
;
399 size_t tx_len
= sizeof(*hdr
) + hdr
->len
;
400 uint16_t orig_len
= hdr
->len
;
404 hdr
->len
-= sizeof(struct pex_ext_hdr
);
406 fd
= sa
->sa_family
== AF_INET6
? pex_raw_v6_fd
: pex_raw_v4_fd
;
409 sa
= addr
= get_mapped_sockaddr(addr
);
416 hdr
->len
= htons(hdr
->len
);
418 struct iovec iov
[2] = {
419 { .iov_base
= (void *)ip_hdr
, .iov_len
= ip_hdrlen
},
420 { .iov_base
= pex_tx_buf
, .iov_len
= tx_len
}
422 struct msghdr msg
= {
423 .msg_name
= (void *)addr
,
425 .msg_iovlen
= ARRAY_SIZE(iov
),
428 if (sa
->sa_family
== AF_INET6
)
429 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
431 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
434 pex_fixup_header(ip_hdr
, ip_hdrlen
, pex_tx_buf
, tx_len
);
440 ret
= sendmsg(fd
, &msg
, 0);
442 ret
= send(fd
, pex_tx_buf
, tx_len
, 0);
450 pex_msg_update_response_fill(struct pex_msg_update_send_ctx
*ctx
)
452 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
453 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
454 int cur_len
= ctx
->rem
;
456 if (cur_len
> PEX_BUF_SIZE
- ofs
)
457 cur_len
= PEX_BUF_SIZE
- ofs
;
459 memcpy(pex_msg_append(cur_len
), ctx
->cur
, cur_len
);
464 void pex_msg_update_response_init(struct pex_msg_update_send_ctx
*ctx
,
465 const uint8_t *pubkey
, const uint8_t *auth_key
,
466 const uint8_t *peer_key
, bool ext
,
467 struct pex_update_request
*req
,
468 const void *data
, int len
)
470 uint8_t e_key_priv
[CURVE25519_KEY_SIZE
];
471 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
472 struct pex_update_response
*res
;
474 ctx
->pubkey
= pubkey
;
475 ctx
->auth_key
= auth_key
;
477 ctx
->req_id
= req
->req_id
;
479 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_RESPONSE
, ext
))
482 res
= pex_msg_append(sizeof(*res
));
483 res
->req_id
= req
->req_id
;
486 if (!fread(e_key_priv
, sizeof(e_key_priv
), 1, pex_urandom
))
489 curve25519_clamp_secret(e_key_priv
);
490 curve25519_generate_public(res
->e_key
, e_key_priv
);
491 curve25519(enc_key
, e_key_priv
, peer_key
);
493 ctx
->data
= ctx
->cur
= malloc(len
);
496 memcpy(ctx
->data
, data
, len
);
497 chacha20_encrypt_msg(ctx
->data
, len
, &req
->req_id
, enc_key
);
499 pex_msg_update_response_fill(ctx
);
502 bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx
*ctx
)
504 struct pex_update_response_data
*res_ext
;
513 if (!__pex_msg_init_ext(ctx
->pubkey
, ctx
->auth_key
,
514 PEX_MSG_UPDATE_RESPONSE_DATA
, ctx
->ext
))
517 res_ext
= pex_msg_append(sizeof(*res_ext
));
518 res_ext
->req_id
= ctx
->req_id
;
519 res_ext
->offset
= ctx
->cur
- ctx
->data
;
520 pex_msg_update_response_fill(ctx
);
526 struct pex_update_request
*
527 pex_msg_update_request_init(const uint8_t *pubkey
, const uint8_t *priv_key
,
528 const uint8_t *auth_key
, union network_endpoint
*addr
,
529 uint64_t cur_version
, bool ext
)
531 struct pex_update_request
*req
;
532 struct pex_msg_update_recv_ctx
*ctx
;
534 list_for_each_entry(ctx
, &requests
, list
) {
535 if (!memcmp(&ctx
->addr
, addr
, sizeof(ctx
->addr
)))
539 ctx
= calloc(1, sizeof(*ctx
));
540 memcpy(&ctx
->addr
, addr
, sizeof(ctx
->addr
));
541 memcpy(ctx
->auth_key
, auth_key
, sizeof(ctx
->auth_key
));
542 memcpy(ctx
->priv_key
, priv_key
, sizeof(ctx
->priv_key
));
543 if (!fread(&ctx
->req_id
, sizeof(ctx
->req_id
), 1, pex_urandom
))
545 list_add_tail(&ctx
->list
, &requests
);
546 if (!gc_timer
.pending
)
547 uloop_timeout_set(&gc_timer
, 1000);
549 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_REQUEST
, ext
)) {
554 req
= pex_msg_append(sizeof(*req
));
555 req
->cur_version
= cpu_to_be64(cur_version
);
556 req
->req_id
= ctx
->req_id
;
561 static struct pex_msg_update_recv_ctx
*
562 pex_msg_update_recv_ctx_get(uint64_t req_id
)
564 struct pex_msg_update_recv_ctx
*ctx
;
566 list_for_each_entry(ctx
, &requests
, list
) {
567 if (ctx
->req_id
== req_id
) {
576 static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx
*ctx
)
578 list_del(&ctx
->list
);
583 void *pex_msg_update_response_recv(const void *data
, int len
, enum pex_opcode op
,
584 int *data_len
, uint64_t *timestamp
)
586 struct pex_msg_update_recv_ctx
*ctx
;
587 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
591 if (op
== PEX_MSG_UPDATE_RESPONSE
) {
592 const struct pex_update_response
*res
= data
;
594 if (len
< sizeof(*res
))
597 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
598 if (!ctx
|| ctx
->data_len
|| !res
->data_len
||
599 res
->data_len
> UNETD_NET_DATA_SIZE_MAX
)
602 data
+= sizeof(*res
);
605 ctx
->data_len
= res
->data_len
;
606 memcpy(ctx
->e_key
, res
->e_key
, sizeof(ctx
->e_key
));
607 ctx
->data
= malloc(ctx
->data_len
);
608 } else if (op
== PEX_MSG_UPDATE_RESPONSE_DATA
) {
609 const struct pex_update_response_data
*res
= data
;
611 if (len
<= sizeof(*res
))
614 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
615 if (!ctx
|| ctx
->data_ofs
!= res
->offset
)
618 data
+= sizeof(*res
);
620 } else if (op
== PEX_MSG_UPDATE_RESPONSE_NO_DATA
) {
621 const struct pex_update_response_no_data
*res
= data
;
623 if (len
< sizeof(*res
))
626 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
635 if (ctx
->data_ofs
+ len
> ctx
->data_len
)
638 memcpy(ctx
->data
+ ctx
->data_ofs
, data
, len
);
639 ctx
->data_ofs
+= len
;
640 if (ctx
->data_ofs
< ctx
->data_len
)
643 curve25519(enc_key
, ctx
->priv_key
, ctx
->e_key
);
644 chacha20_encrypt_msg(ctx
->data
, ctx
->data_len
, &ctx
->req_id
, enc_key
);
645 if (unet_auth_data_validate(ctx
->auth_key
, ctx
->data
, ctx
->data_len
, timestamp
, NULL
))
648 *data_len
= ctx
->data_len
;
651 pex_msg_update_ctx_free(ctx
);
656 pex_msg_update_ctx_free(ctx
);
661 struct pex_hdr
*pex_rx_accept(void *data
, size_t len
, bool ext
)
663 struct pex_hdr
*hdr
= data
;
667 min_size
= sizeof(*hdr
);
669 min_size
+= sizeof(struct pex_ext_hdr
);
674 hdr_len
= ntohs(hdr
->len
);
675 if (len
< min_size
+ hdr_len
)
684 pex_gc_cb(struct uloop_timeout
*t
)
686 struct pex_msg_update_recv_ctx
*ctx
, *tmp
;
688 list_for_each_entry_safe(ctx
, tmp
, &requests
, list
) {
689 if (++ctx
->idle
<= 3)
692 pex_msg_update_ctx_free(ctx
);
695 if (!list_empty(&requests
))
696 uloop_timeout_set(t
, 1000);
699 int pex_open(void *addr
, size_t addr_len
, pex_recv_cb_t cb
, bool server
)
701 struct sockaddr
*sa
= addr
;
708 pex_raw_v4_fd
= fd
= socket(PF_INET
, SOCK_RAW
, IPPROTO_UDP
);
712 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
713 setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &yes
, sizeof(yes
));
716 pex_raw_v6_fd
= fd
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_UDP
);
720 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
721 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
722 setsockopt(fd
, IPPROTO_IPV6
, IPV6_HDRINCL
, &yes
, sizeof(yes
));
726 pex_urandom
= fopen("/dev/urandom", "r");
730 fd
= socket(sa
->sa_family
== AF_INET
? PF_INET
: PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
734 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
735 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
738 if (bind(fd
, addr
, addr_len
) < 0) {
743 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
744 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
745 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
747 if (connect(fd
, addr
, addr_len
) < 0) {
754 pex_fd
.cb
= pex_fd_cb
;
755 uloop_fd_add(&pex_fd
, ULOOP_READ
);
757 gc_timer
.cb
= pex_gc_cb
;
766 if (pex_raw_v4_fd
>= 0)
767 close(pex_raw_v4_fd
);
768 if (pex_raw_v6_fd
>= 0)
769 close(pex_raw_v6_fd
);
775 int pex_unix_open(const char *path
, pex_recv_control_cb_t cb
)
783 prev_mask
= umask(0177);
784 fd
= usock(USOCK_UDP
| USOCK_UNIX
| USOCK_SERVER
| USOCK_NONBLOCK
, path
, NULL
);
789 pex_unix_fd
.cb
= pex_unix_cb
;
791 uloop_fd_add(&pex_unix_fd
, ULOOP_READ
);
798 if (pex_raw_v4_fd
>= 0)
799 close(pex_raw_v4_fd
);
800 if (pex_raw_v6_fd
>= 0)
801 close(pex_raw_v6_fd
);
809 uloop_fd_delete(&pex_fd
);
813 if (pex_unix_fd
.cb
) {
814 uloop_fd_delete(&pex_unix_fd
);
815 close(pex_unix_fd
.fd
);
819 pex_unix_fd
.cb
= NULL
;