1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
6 #include <sys/socket.h>
10 #include <libubox/list.h>
11 #include <libubox/uloop.h>
12 #include <netinet/in.h>
13 #include <netinet/ip.h>
14 #include <netinet/ip6.h>
15 #include <netinet/udp.h>
18 #include "auth-data.h"
20 static char pex_tx_buf
[PEX_BUF_SIZE
];
21 static FILE *pex_urandom
;
22 static struct uloop_fd pex_fd
;
23 static LIST_HEAD(requests
);
24 static struct uloop_timeout gc_timer
;
25 static int pex_raw_v4_fd
= -1, pex_raw_v6_fd
= -1;
27 static pex_recv_cb_t pex_recv_cb
;
29 struct pex_msg_update_recv_ctx
{
30 struct list_head list
;
32 union network_endpoint addr
;
34 uint8_t priv_key
[CURVE25519_KEY_SIZE
];
35 uint8_t auth_key
[CURVE25519_KEY_SIZE
];
36 uint8_t e_key
[CURVE25519_KEY_SIZE
];
47 uint64_t pex_network_hash(const uint8_t *auth_key
, uint64_t req_id
)
57 siphash_to_be64(&hash
, auth_key
, CURVE25519_KEY_SIZE
, &key
);
63 struct pex_hdr
*__pex_msg_init(const uint8_t *pubkey
, uint8_t opcode
)
65 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
70 memcpy(hdr
->id
, pubkey
, sizeof(hdr
->id
));
75 struct pex_hdr
*__pex_msg_init_ext(const uint8_t *pubkey
, const uint8_t *auth_key
,
76 uint8_t opcode
, bool ext
)
78 struct pex_hdr
*hdr
= __pex_msg_init(pubkey
, opcode
);
79 struct pex_ext_hdr
*ehdr
= (struct pex_ext_hdr
*)(hdr
+ 1);
85 hdr
->len
= sizeof(*ehdr
);
87 if (fread(&ehdr
->nonce
, sizeof(ehdr
->nonce
), 1, pex_urandom
) != 1)
90 hash
= pex_network_hash(auth_key
, ehdr
->nonce
);
91 *(uint64_t *)hdr
->id
^= hash
;
92 memcpy(ehdr
->auth_id
, auth_key
, sizeof(ehdr
->auth_id
));
97 void *pex_msg_append(size_t len
)
99 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
100 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
101 void *buf
= &pex_tx_buf
[ofs
];
103 if (sizeof(pex_tx_buf
) - ofs
< len
)
113 pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
115 struct sockaddr_in6 sin6
;
116 static char buf
[PEX_BUF_SIZE
];
117 struct pex_hdr
*hdr
= (struct pex_hdr
*)buf
;
121 socklen_t slen
= sizeof(sin6
);
123 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
138 if (len
< sizeof(*hdr
) + sizeof(struct pex_ext_hdr
))
141 hdr
->len
= ntohs(hdr
->len
);
142 if (len
- sizeof(hdr
) - sizeof(struct pex_ext_hdr
) < hdr
->len
)
145 pex_recv_cb(hdr
, &sin6
);
149 static inline uint32_t
150 csum_tcpudp_nofold(uint32_t saddr
, uint32_t daddr
, uint32_t len
, uint8_t proto
)
156 #if __BYTE_ORDER == __LITTLE_ENDIAN
157 sum
+= (proto
+ len
) << 8;
162 sum
= (sum
& 0xffffffff) + (sum
>> 32);
163 sum
= (sum
& 0xffffffff) + (sum
>> 32);
165 return (uint32_t)sum
;
168 static inline uint32_t csum_add(uint32_t sum
, uint32_t addend
)
171 return sum
+ (sum
< addend
);
174 static inline uint16_t csum_fold(uint32_t sum
)
176 sum
= (sum
& 0xffff) + (sum
>> 16);
177 sum
= (sum
& 0xffff) + (sum
>> 16);
179 return (uint16_t)~sum
;
182 static uint32_t csum_partial(const void *buf
, int len
)
184 const uint16_t *data
= buf
;
193 #if __BYTE_ORDER == __LITTLE_ENDIAN
194 sum
+= *(uint8_t *)data
;
196 sum
+= *(uint8_t *)data
<< 8;
199 sum
= (sum
& 0xffff) + (sum
>> 16);
200 sum
= (sum
& 0xffff) + (sum
>> 16);
205 static void pex_fixup_udpv4(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
208 struct udphdr
*udp
= hdr
+ ip
->ip_hl
* 4;
209 uint16_t udp_len
= sizeof(*udp
) + len
;
212 if ((void *)&udp
[1] > hdr
+ hdrlen
)
216 udp
->uh_ulen
= htons(udp_len
);
217 sum
= csum_tcpudp_nofold(*(uint32_t *)&ip
->ip_src
, *(uint32_t *)&ip
->ip_dst
,
219 sum
= csum_add(sum
, csum_partial(udp
, sizeof(*udp
)));
220 sum
= csum_add(sum
, csum_partial(data
, len
));
221 udp
->uh_sum
= csum_fold(sum
);
223 ip
->ip_len
= htons(hdrlen
+ len
);
225 ip
->ip_sum
= csum_fold(csum_partial(ip
, sizeof(*ip
)));
228 ip
->ip_len
= hdrlen
+ len
;
232 static void pex_fixup_udpv6(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
234 struct ip6_hdr
*ip
= hdr
;
235 struct udphdr
*udp
= hdr
+ sizeof(*ip
);
236 uint16_t udp_len
= htons(sizeof(*udp
) + len
);
238 if ((void *)&udp
[1] > hdr
+ hdrlen
)
241 ip
->ip6_plen
= htons(sizeof(*udp
) + len
);
243 udp
->uh_ulen
= udp_len
;
244 udp
->uh_sum
= csum_fold(csum_partial(hdr
, sizeof(*ip
) + sizeof(*udp
)));
247 ip
->ip6_plen
= sizeof(*udp
) + len
;
251 static void pex_fixup_header(void *hdr
, size_t hdrlen
, const void *data
, size_t len
)
253 if (hdrlen
>= sizeof(struct ip6_hdr
) + sizeof(struct udphdr
))
254 pex_fixup_udpv6(hdr
, hdrlen
, data
, len
);
255 else if (hdrlen
>= sizeof(struct ip
) + sizeof(struct udphdr
))
256 pex_fixup_udpv4(hdr
, hdrlen
, data
, len
);
259 int __pex_msg_send(int fd
, const void *addr
, void *ip_hdr
, size_t ip_hdrlen
)
261 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
262 const struct sockaddr
*sa
= addr
;
263 size_t tx_len
= sizeof(*hdr
) + hdr
->len
;
264 uint16_t orig_len
= hdr
->len
;
268 hdr
->len
-= sizeof(struct pex_ext_hdr
);
270 fd
= sa
->sa_family
== AF_INET6
? pex_raw_v6_fd
: pex_raw_v4_fd
;
278 hdr
->len
= htons(hdr
->len
);
280 struct iovec iov
[2] = {
281 { .iov_base
= (void *)ip_hdr
, .iov_len
= ip_hdrlen
},
282 { .iov_base
= pex_tx_buf
, .iov_len
= tx_len
}
284 struct msghdr msg
= {
285 .msg_name
= (void *)addr
,
287 .msg_iovlen
= ARRAY_SIZE(iov
),
290 if (sa
->sa_family
== AF_INET6
)
291 msg
.msg_namelen
= sizeof(struct sockaddr_in6
);
293 msg
.msg_namelen
= sizeof(struct sockaddr_in
);
296 pex_fixup_header(ip_hdr
, ip_hdrlen
, pex_tx_buf
, tx_len
);
302 ret
= sendmsg(fd
, &msg
, 0);
304 ret
= send(fd
, pex_tx_buf
, tx_len
, 0);
312 pex_msg_update_response_fill(struct pex_msg_update_send_ctx
*ctx
)
314 struct pex_hdr
*hdr
= (struct pex_hdr
*)pex_tx_buf
;
315 int ofs
= hdr
->len
+ sizeof(struct pex_hdr
);
316 int cur_len
= ctx
->rem
;
318 if (cur_len
> PEX_BUF_SIZE
- ofs
)
319 cur_len
= PEX_BUF_SIZE
- ofs
;
321 memcpy(pex_msg_append(cur_len
), ctx
->cur
, cur_len
);
326 void pex_msg_update_response_init(struct pex_msg_update_send_ctx
*ctx
,
327 const uint8_t *pubkey
, const uint8_t *auth_key
,
328 const uint8_t *peer_key
, bool ext
,
329 struct pex_update_request
*req
,
330 const void *data
, int len
)
332 uint8_t e_key_priv
[CURVE25519_KEY_SIZE
];
333 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
334 struct pex_update_response
*res
;
336 ctx
->pubkey
= pubkey
;
337 ctx
->auth_key
= auth_key
;
339 ctx
->req_id
= req
->req_id
;
341 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_RESPONSE
, ext
))
344 res
= pex_msg_append(sizeof(*res
));
345 res
->req_id
= req
->req_id
;
348 if (!fread(e_key_priv
, sizeof(e_key_priv
), 1, pex_urandom
))
351 curve25519_clamp_secret(e_key_priv
);
352 curve25519_generate_public(res
->e_key
, e_key_priv
);
353 curve25519(enc_key
, e_key_priv
, peer_key
);
355 ctx
->data
= ctx
->cur
= malloc(len
);
358 memcpy(ctx
->data
, data
, len
);
359 chacha20_encrypt_msg(ctx
->data
, len
, &req
->req_id
, enc_key
);
361 pex_msg_update_response_fill(ctx
);
364 bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx
*ctx
)
366 struct pex_update_response_data
*res_ext
;
375 if (!__pex_msg_init_ext(ctx
->pubkey
, ctx
->auth_key
,
376 PEX_MSG_UPDATE_RESPONSE_DATA
, ctx
->ext
))
379 res_ext
= pex_msg_append(sizeof(*res_ext
));
380 res_ext
->req_id
= ctx
->req_id
;
381 res_ext
->offset
= ctx
->cur
- ctx
->data
;
382 pex_msg_update_response_fill(ctx
);
388 struct pex_update_request
*
389 pex_msg_update_request_init(const uint8_t *pubkey
, const uint8_t *priv_key
,
390 const uint8_t *auth_key
, union network_endpoint
*addr
,
391 uint64_t cur_version
, bool ext
)
393 struct pex_update_request
*req
;
394 struct pex_msg_update_recv_ctx
*ctx
;
396 list_for_each_entry(ctx
, &requests
, list
) {
397 if (!memcmp(&ctx
->addr
, addr
, sizeof(ctx
->addr
)))
401 ctx
= calloc(1, sizeof(*ctx
));
402 memcpy(&ctx
->addr
, addr
, sizeof(ctx
->addr
));
403 memcpy(ctx
->auth_key
, auth_key
, sizeof(ctx
->auth_key
));
404 memcpy(ctx
->priv_key
, priv_key
, sizeof(ctx
->priv_key
));
405 if (!fread(&ctx
->req_id
, sizeof(ctx
->req_id
), 1, pex_urandom
))
407 list_add_tail(&ctx
->list
, &requests
);
408 if (!gc_timer
.pending
)
409 uloop_timeout_set(&gc_timer
, 1000);
411 if (!__pex_msg_init_ext(pubkey
, auth_key
, PEX_MSG_UPDATE_REQUEST
, ext
)) {
416 req
= pex_msg_append(sizeof(*req
));
417 req
->cur_version
= cpu_to_be64(cur_version
);
418 req
->req_id
= ctx
->req_id
;
423 static struct pex_msg_update_recv_ctx
*
424 pex_msg_update_recv_ctx_get(uint64_t req_id
)
426 struct pex_msg_update_recv_ctx
*ctx
;
428 list_for_each_entry(ctx
, &requests
, list
) {
429 if (ctx
->req_id
== req_id
) {
438 static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx
*ctx
)
440 list_del(&ctx
->list
);
445 void *pex_msg_update_response_recv(const void *data
, int len
, enum pex_opcode op
,
446 int *data_len
, uint64_t *timestamp
)
448 struct pex_msg_update_recv_ctx
*ctx
;
449 uint8_t enc_key
[CURVE25519_KEY_SIZE
];
453 if (op
== PEX_MSG_UPDATE_RESPONSE
) {
454 const struct pex_update_response
*res
= data
;
456 if (len
< sizeof(*res
))
459 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
460 if (!ctx
|| ctx
->data_len
|| !res
->data_len
||
461 res
->data_len
> UNETD_NET_DATA_SIZE_MAX
)
464 data
+= sizeof(*res
);
467 ctx
->data_len
= res
->data_len
;
468 memcpy(ctx
->e_key
, res
->e_key
, sizeof(ctx
->e_key
));
469 ctx
->data
= malloc(ctx
->data_len
);
470 } else if (op
== PEX_MSG_UPDATE_RESPONSE_DATA
) {
471 const struct pex_update_response_data
*res
= data
;
473 if (len
<= sizeof(*res
))
476 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
477 if (!ctx
|| ctx
->data_ofs
!= res
->offset
)
480 data
+= sizeof(*res
);
482 } else if (op
== PEX_MSG_UPDATE_RESPONSE_NO_DATA
) {
483 const struct pex_update_response_no_data
*res
= data
;
485 if (len
< sizeof(*res
))
488 ctx
= pex_msg_update_recv_ctx_get(res
->req_id
);
497 if (ctx
->data_ofs
+ len
> ctx
->data_len
)
500 memcpy(ctx
->data
+ ctx
->data_ofs
, data
, len
);
501 ctx
->data_ofs
+= len
;
502 if (ctx
->data_ofs
< ctx
->data_len
)
505 curve25519(enc_key
, ctx
->priv_key
, ctx
->e_key
);
506 chacha20_encrypt_msg(ctx
->data
, ctx
->data_len
, &ctx
->req_id
, enc_key
);
507 if (unet_auth_data_validate(ctx
->auth_key
, ctx
->data
, ctx
->data_len
, timestamp
, NULL
))
510 *data_len
= ctx
->data_len
;
513 pex_msg_update_ctx_free(ctx
);
518 pex_msg_update_ctx_free(ctx
);
524 pex_gc_cb(struct uloop_timeout
*t
)
526 struct pex_msg_update_recv_ctx
*ctx
, *tmp
;
528 list_for_each_entry_safe(ctx
, tmp
, &requests
, list
) {
529 if (++ctx
->idle
<= 3)
532 pex_msg_update_ctx_free(ctx
);
535 if (!list_empty(&requests
))
536 uloop_timeout_set(t
, 1000);
539 int pex_open(void *addr
, size_t addr_len
, pex_recv_cb_t cb
, bool server
)
541 struct sockaddr
*sa
= addr
;
548 pex_raw_v4_fd
= fd
= socket(PF_INET
, SOCK_RAW
, IPPROTO_UDP
);
552 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
553 setsockopt(fd
, IPPROTO_IP
, IP_HDRINCL
, &yes
, sizeof(yes
));
556 pex_raw_v6_fd
= fd
= socket(PF_INET6
, SOCK_RAW
, IPPROTO_UDP
);
560 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &yes
, sizeof(yes
));
561 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
562 setsockopt(fd
, IPPROTO_IPV6
, IPV6_HDRINCL
, &yes
, sizeof(yes
));
566 pex_urandom
= fopen("/dev/urandom", "r");
570 fd
= socket(sa
->sa_family
== AF_INET
? PF_INET
: PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
574 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
575 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
578 if (bind(fd
, addr
, addr_len
) < 0) {
583 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
584 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
585 setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &no
, sizeof(no
));
587 if (connect(fd
, addr
, addr_len
) < 0) {
594 pex_fd
.cb
= pex_fd_cb
;
595 uloop_fd_add(&pex_fd
, ULOOP_READ
);
597 gc_timer
.cb
= pex_gc_cb
;
606 if (pex_raw_v4_fd
>= 0)
607 close(pex_raw_v4_fd
);
608 if (pex_raw_v6_fd
>= 0)
609 close(pex_raw_v6_fd
);
620 if (pex_raw_v4_fd
>= 0)
621 close(pex_raw_v4_fd
);
622 if (pex_raw_v6_fd
>= 0)
623 close(pex_raw_v6_fd
);
628 uloop_fd_delete(&pex_fd
);