1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
6 #include <sys/socket.h>
14 static const char *pex_peer_id_str(const uint8_t *key
)
19 for (i
= 0; i
< 8; i
++)
20 sprintf(str
+ i
* 2, "%02x", key
[i
]);
25 static struct pex_hdr
*
26 pex_msg_init(struct network
*net
, uint8_t opcode
)
28 return __pex_msg_init(net
->config
.pubkey
, opcode
);
31 static struct pex_hdr
*
32 pex_msg_init_ext(struct network
*net
, uint8_t opcode
, bool ext
)
34 return __pex_msg_init_ext(net
->config
.pubkey
, net
->config
.auth_key
, opcode
, ext
);
37 static struct network_peer
*
38 pex_msg_peer(struct network
*net
, const uint8_t *id
)
40 struct network_peer
*peer
;
41 uint8_t key
[WG_KEY_LEN
] = {};
43 memcpy(key
, id
, PEX_ID_LEN
);
44 peer
= avl_find_ge_element(&net
->peers
.avl
, key
, peer
, node
.avl
);
45 if (!peer
|| memcmp(peer
->key
, key
, PEX_ID_LEN
) != 0) {
46 D_NET(net
, "can't find peer %s", pex_peer_id_str(id
));
54 pex_get_peer_addr(struct sockaddr_in6
*sin6
, struct network
*net
,
55 struct network_peer
*peer
)
57 *sin6
= (struct sockaddr_in6
){
58 .sin6_family
= AF_INET6
,
59 .sin6_addr
= peer
->local_addr
.in6
,
60 .sin6_port
= htons(net
->net_config
.pex_port
),
64 static void pex_msg_send(struct network
*net
, struct network_peer
*peer
)
66 struct sockaddr_in6 sin6
= {};
68 if (!peer
|| peer
== &net
->net_config
.local_host
->peer
)
71 pex_get_peer_addr(&sin6
, net
, peer
);
72 if (__pex_msg_send(net
->pex
.fd
.fd
, &sin6
) < 0)
73 D_PEER(net
, peer
, "pex_msg_send failed: %s", strerror(errno
));
76 static void pex_msg_send_ext(struct network
*net
, struct network_peer
*peer
,
77 struct sockaddr_in6
*addr
)
79 char addrbuf
[INET6_ADDRSTRLEN
];
82 return pex_msg_send(net
, peer
);
84 if (__pex_msg_send(-1, addr
) < 0)
85 D_NET(net
, "pex_msg_send_ext(%s) failed: %s",
86 inet_ntop(addr
->sin6_family
, (const void *)&addr
->sin6_addr
, addrbuf
,
92 pex_send_hello(struct network
*net
, struct network_peer
*peer
)
94 struct pex_hello
*data
;
96 pex_msg_init(net
, PEX_MSG_HELLO
);
97 data
= pex_msg_append(sizeof(*data
));
98 if (peer
->state
.endpoint
.sa
.sa_family
== AF_INET6
)
99 data
->flags
|= htons(PEER_EP_F_IPV6
);
100 if (network_get_local_addr(&data
->local_addr
, &peer
->state
.endpoint
))
103 pex_msg_send(net
, peer
);
107 pex_msg_add_peer_endpoint(struct network
*net
, struct network_peer
*peer
,
108 struct network_peer
*receiver
)
110 struct pex_peer_endpoint
*data
;
116 addr
= network_endpoint_addr(&peer
->state
.endpoint
, &len
);
117 port
= peer
->state
.endpoint
.in
.sin_port
;
119 flags
|= PEER_EP_F_IPV6
;
120 if (network_endpoint_addr_equal(&peer
->state
.endpoint
,
121 &receiver
->state
.endpoint
)) {
122 if (!peer
->state
.has_local_ep_addr
) {
123 D_PEER(net
, peer
, "can't send peer to %s, missing local address",
124 network_peer_name(receiver
));
128 addr
= &peer
->state
.local_ep_addr
;
129 port
= htons(peer
->port
);
130 flags
|= PEER_EP_F_LOCAL
;
133 data
= pex_msg_append(sizeof(*data
));
137 memcpy(data
->peer_id
, peer
->key
, sizeof(data
->peer_id
));
138 memcpy(data
->addr
, addr
, len
);
140 data
->flags
= htons(flags
);
141 D_PEER(net
, peer
, "send endpoint to %s", network_peer_name(receiver
));
147 network_pex_handle_endpoint_change(struct network
*net
, struct network_peer
*peer
)
149 struct network_peer
*cur
;
151 vlist_for_each_element(&net
->peers
, cur
, node
) {
152 if (cur
== peer
|| !cur
->state
.connected
)
155 pex_msg_init(net
, PEX_MSG_NOTIFY_PEERS
);
156 if (pex_msg_add_peer_endpoint(net
, peer
, cur
))
159 pex_msg_send(net
, cur
);
164 network_pex_host_request_update(struct network
*net
, struct network_pex_host
*host
)
166 char addrstr
[INET6_ADDRSTRLEN
];
167 uint64_t version
= 0;
169 if (net
->net_data_len
)
170 version
= net
->net_data_version
;
172 D("request network data from host %s",
173 inet_ntop(host
->endpoint
.sa
.sa_family
,
174 (host
->endpoint
.sa
.sa_family
== AF_INET6
?
175 (const void *)&host
->endpoint
.in6
.sin6_addr
:
176 (const void *)&host
->endpoint
.in
.sin_addr
),
177 addrstr
, sizeof(addrstr
)));
179 if (!pex_msg_update_request_init(net
->config
.pubkey
, net
->config
.key
,
180 net
->config
.auth_key
, &host
->endpoint
,
183 __pex_msg_send(-1, &host
->endpoint
);
187 network_pex_request_update_cb(struct uloop_timeout
*t
)
189 struct network
*net
= container_of(t
, struct network
, pex
.request_update_timer
);
190 struct network_pex
*pex
= &net
->pex
;
191 struct network_pex_host
*host
;
193 uloop_timeout_set(t
, 5000);
195 if (list_empty(&pex
->hosts
))
198 host
= list_first_entry(&pex
->hosts
, struct network_pex_host
, list
);
199 list_move_tail(&host
->list
, &pex
->hosts
);
200 network_pex_host_request_update(net
, host
);
203 void network_pex_init(struct network
*net
)
205 struct network_pex
*pex
= &net
->pex
;
207 memset(pex
, 0, sizeof(*pex
));
209 INIT_LIST_HEAD(&pex
->hosts
);
210 pex
->request_update_timer
.cb
= network_pex_request_update_cb
;
214 network_pex_query_hosts(struct network
*net
)
216 struct network_host
*host
;
221 pex_msg_init(net
, PEX_MSG_QUERY
);
223 avl_for_each_element(&net
->hosts
, host
, node
) {
224 struct network_peer
*peer
= &host
->peer
;
227 if (host
== net
->net_config
.local_host
||
228 peer
->state
.connected
||
232 id
= pex_msg_append(PEX_ID_LEN
);
236 memcpy(id
, peer
->key
, PEX_ID_LEN
);
243 rv
%= net
->hosts
.count
;
244 for (i
= 0; i
< 2; i
++) {
245 avl_for_each_element(&net
->hosts
, host
, node
) {
246 struct network_peer
*peer
= &host
->peer
;
253 if (host
== net
->net_config
.local_host
)
256 if (!peer
->state
.connected
)
259 D_PEER(net
, peer
, "send query for %d hosts", hosts
);
260 pex_msg_send(net
, peer
);
268 network_pex_send_ping(struct network
*net
, struct network_peer
*peer
)
270 pex_msg_init(net
, PEX_MSG_PING
);
271 pex_msg_send(net
, peer
);
275 network_pex_send_update_request(struct network
*net
, struct network_peer
*peer
,
276 struct sockaddr_in6
*addr
)
278 union network_endpoint ep
= {};
279 uint64_t version
= 0;
282 memcpy(&ep
.in6
, addr
, sizeof(ep
.in6
));
284 pex_get_peer_addr(&ep
.in6
, net
, peer
);
286 if (net
->net_data_len
)
287 version
= net
->net_data_version
;
289 if (!pex_msg_update_request_init(net
->config
.pubkey
, net
->config
.key
,
290 net
->config
.auth_key
, &ep
,
294 pex_msg_send_ext(net
, peer
, addr
);
297 void network_pex_event(struct network
*net
, struct network_peer
*peer
,
300 if (!network_pex_active(&net
->pex
))
304 D_PEER(net
, peer
, "PEX event type=%d", ev
);
306 D_NET(net
, "PEX event type=%d", ev
);
309 case PEX_EV_HANDSHAKE
:
310 pex_send_hello(net
, peer
);
311 if (net
->config
.type
== NETWORK_TYPE_DYNAMIC
)
312 network_pex_send_update_request(net
, peer
, NULL
);
314 case PEX_EV_ENDPOINT_CHANGE
:
315 network_pex_handle_endpoint_change(net
, peer
);
318 network_pex_query_hosts(net
);
321 network_pex_send_ping(net
, peer
);
327 network_pex_recv_hello(struct network
*net
, struct network_peer
*peer
,
328 const struct pex_hello
*data
, size_t len
)
330 char addrstr
[INET6_ADDRSTRLEN
];
334 if (len
< sizeof(*data
))
337 if (peer
->state
.has_local_ep_addr
&&
338 !memcmp(&peer
->state
.local_ep_addr
, data
->local_addr
, sizeof(data
->local_addr
)))
341 flags
= ntohs(data
->flags
);
342 af
= (flags
& PEER_EP_F_IPV6
) ? AF_INET6
: AF_INET
;
343 D_PEER(net
, peer
, "set local endpoint address to %s",
344 inet_ntop(af
, data
->local_addr
, addrstr
, sizeof(addrstr
)));
345 peer
->state
.has_local_ep_addr
= true;
346 memcpy(&peer
->state
.local_ep_addr
, data
->local_addr
, sizeof(data
->local_addr
));
350 network_pex_recv_peers(struct network
*net
, struct network_peer
*peer
,
351 const struct pex_peer_endpoint
*data
, size_t len
)
353 struct network_peer
*local
= &net
->net_config
.local_host
->peer
;
354 struct network_peer
*cur
;
356 for (; len
>= sizeof(*data
); len
-= sizeof(*data
), data
++) {
357 union network_endpoint
*ep
;
362 cur
= pex_msg_peer(net
, data
->peer_id
);
366 if (cur
== peer
|| cur
== local
)
369 D_PEER(net
, peer
, "received peer address for %s",
370 network_peer_name(cur
));
371 flags
= ntohs(data
->flags
);
372 ep
= &cur
->state
.next_endpoint
;
373 ep
->sa
.sa_family
= (flags
& PEER_EP_F_IPV6
) ? AF_INET6
: AF_INET
;
374 addr
= network_endpoint_addr(ep
, &len
);
375 memcpy(addr
, data
->addr
, len
);
376 ep
->in
.sin_port
= data
->port
;
381 network_pex_recv_query(struct network
*net
, struct network_peer
*peer
,
382 const uint8_t *data
, size_t len
)
384 struct network_peer
*cur
;
387 pex_msg_init(net
, PEX_MSG_NOTIFY_PEERS
);
388 for (; len
>= 8; data
+= 8, len
-= 8) {
389 cur
= pex_msg_peer(net
, data
);
390 if (!cur
|| !cur
->state
.connected
)
393 if (!pex_msg_add_peer_endpoint(net
, cur
, peer
))
400 D_PEER(net
, peer
, "send query response with %d hosts", resp
);
401 pex_msg_send(net
, peer
);
405 network_pex_recv_ping(struct network
*net
, struct network_peer
*peer
)
407 time_t now
= time(NULL
);
409 if (peer
->state
.last_request
== now
)
412 peer
->state
.last_request
= now
;
413 pex_msg_init(net
, PEX_MSG_PONG
);
414 pex_msg_send(net
, peer
);
418 network_pex_recv_update_request(struct network
*net
, struct network_peer
*peer
,
419 const uint8_t *data
, size_t len
,
420 struct sockaddr_in6
*addr
)
422 struct pex_update_request
*req
= (struct pex_update_request
*)data
;
423 struct pex_msg_update_send_ctx ctx
= {};
424 uint64_t req_version
= be64_to_cpu(req
->cur_version
);
428 if (len
< sizeof(struct pex_update_request
))
431 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
435 query_count
= &peer
->state
.num_net_queries
;
437 query_count
= &net
->num_net_queries
;
439 if (++*query_count
> 10)
442 D("receive update request, local version=%"PRIu64
", remote version=%"PRIu64
, net
->net_data_version
, req_version
);
444 if (req_version
>= net
->net_data_version
) {
445 struct pex_update_response_no_data
*res
;
447 pex_msg_init_ext(net
, PEX_MSG_UPDATE_RESPONSE_NO_DATA
, !!addr
);
448 res
= pex_msg_append(sizeof(*res
));
449 res
->req_id
= req
->req_id
;
450 res
->cur_version
= cpu_to_be64(net
->net_data_version
);
451 pex_msg_send_ext(net
, peer
, addr
);
454 if (req_version
> net
->net_data_version
)
455 network_pex_send_update_request(net
, peer
, addr
);
457 if (!peer
|| !net
->net_data_len
)
460 if (req_version
>= net
->net_data_version
)
463 pex_msg_update_response_init(&ctx
, net
->config
.pubkey
, net
->config
.auth_key
,
464 peer
->key
, !!addr
, (void *)data
,
465 net
->net_data
, net
->net_data_len
);
467 pex_msg_send_ext(net
, peer
, addr
);
468 done
= !pex_msg_update_response_continue(&ctx
);
473 network_pex_recv_update_response(struct network
*net
, const uint8_t *data
, size_t len
,
474 struct sockaddr_in6
*addr
, enum pex_opcode op
)
476 struct network_peer
*peer
;
478 int net_data_len
= 0;
479 uint64_t version
= 0;
480 bool no_prev_data
= !net
->net_data_len
;
482 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
485 net_data
= pex_msg_update_response_recv(data
, len
, op
, &net_data_len
, &version
);
489 if (version
<= net
->net_data_version
) {
494 D_NET(net
, "received updated network data, len=%d", net_data_len
);
497 net
->net_data
= net_data
;
498 net
->net_data_len
= net_data_len
;
499 net
->net_data_version
= version
;
500 if (network_save_dynamic(net
) < 0)
503 uloop_timeout_set(&net
->reload_timer
, no_prev_data
? 1 : UNETD_DATA_UPDATE_DELAY
);
504 vlist_for_each_element(&net
->peers
, peer
, node
) {
505 if (!peer
->state
.connected
)
507 network_pex_send_update_request(net
, peer
, NULL
);
512 network_pex_recv(struct network
*net
, struct network_peer
*peer
, struct pex_hdr
*hdr
)
514 const void *data
= hdr
+ 1;
516 if (hdr
->version
!= 0)
519 D_PEER(net
, peer
, "PEX rx op=%d", hdr
->opcode
);
520 switch (hdr
->opcode
) {
522 network_pex_recv_hello(net
, peer
, data
, hdr
->len
);
524 case PEX_MSG_NOTIFY_PEERS
:
525 network_pex_recv_peers(net
, peer
, data
, hdr
->len
);
528 network_pex_recv_query(net
, peer
, data
, hdr
->len
);
531 network_pex_recv_ping(net
, peer
);
535 case PEX_MSG_UPDATE_REQUEST
:
536 network_pex_recv_update_request(net
, peer
, data
, hdr
->len
,
539 case PEX_MSG_UPDATE_RESPONSE
:
540 case PEX_MSG_UPDATE_RESPONSE_DATA
:
541 case PEX_MSG_UPDATE_RESPONSE_NO_DATA
:
542 network_pex_recv_update_response(net
, data
, hdr
->len
,
549 network_pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
551 struct network
*net
= container_of(fd
, struct network
, pex
.fd
);
552 struct network_peer
*local
= &net
->net_config
.local_host
->peer
;
553 struct network_peer
*peer
;
554 struct sockaddr_in6 sin6
;
555 static char buf
[PEX_BUF_SIZE
];
556 struct pex_hdr
*hdr
= (struct pex_hdr
*)buf
;
560 socklen_t slen
= sizeof(sin6
);
562 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
570 D_NET(net
, "recvfrom failed: %s", strerror(errno
));
571 network_pex_close(net
);
578 if (len
< sizeof(*hdr
))
581 hdr
->len
= ntohs(hdr
->len
);
582 if (len
- sizeof(hdr
) < hdr
->len
)
585 peer
= pex_msg_peer(net
, hdr
->id
);
589 if (memcmp(&sin6
.sin6_addr
, &peer
->local_addr
.in6
, sizeof(sin6
.sin6_addr
)) != 0)
595 network_pex_recv(net
, peer
, hdr
);
600 network_pex_create_host(struct network
*net
, union network_endpoint
*ep
)
602 struct network_pex
*pex
= &net
->pex
;
603 struct network_pex_host
*host
;
605 host
= calloc(1, sizeof(*host
));
606 memcpy(&host
->endpoint
, ep
, sizeof(host
->endpoint
));
607 list_add_tail(&host
->list
, &pex
->hosts
);
608 network_pex_host_request_update(net
, host
);
612 network_pex_open_auth_connect(struct network
*net
)
614 struct network_pex
*pex
= &net
->pex
;
615 struct network_peer
*peer
;
616 struct blob_attr
*cur
;
619 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
622 uloop_timeout_set(&pex
->request_update_timer
, 5000);
624 vlist_for_each_element(&net
->peers
, peer
, node
) {
625 union network_endpoint ep
= {};
630 if (network_get_endpoint(&ep
, peer
->endpoint
,
631 UNETD_GLOBAL_PEX_PORT
, 0) < 0)
634 ep
.in
.sin_port
= htons(UNETD_GLOBAL_PEX_PORT
);
635 network_pex_create_host(net
, &ep
);
638 if (!net
->config
.auth_connect
)
641 blobmsg_for_each_attr(cur
, net
->config
.auth_connect
, rem
) {
642 union network_endpoint ep
= {};
644 if (network_get_endpoint(&ep
, blobmsg_get_string(cur
),
645 UNETD_GLOBAL_PEX_PORT
, 0) < 0)
648 network_pex_create_host(net
, &ep
);
653 int network_pex_open(struct network
*net
)
655 struct network_host
*local_host
= net
->net_config
.local_host
;
656 struct network_peer
*local
;
657 struct network_pex
*pex
= &net
->pex
;
658 struct sockaddr_in6 sin6
= {};
662 network_pex_open_auth_connect(net
);
664 if (!local_host
|| !net
->net_config
.pex_port
)
667 local
= &local_host
->peer
;
668 fd
= socket(PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
672 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
673 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
675 sin6
.sin6_family
= AF_INET6
;
676 memcpy(&sin6
.sin6_addr
, &local
->local_addr
.in6
,
677 sizeof(local
->local_addr
.in6
));
678 sin6
.sin6_port
= htons(net
->net_config
.pex_port
);
680 if (bind(fd
, (struct sockaddr
*)&sin6
, sizeof(sin6
)) < 0) {
685 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
686 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
688 setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
689 network_name(net
), strlen(network_name(net
)));
693 pex
->fd
.cb
= network_pex_fd_cb
;
694 uloop_fd_add(&pex
->fd
, ULOOP_READ
);
703 void network_pex_close(struct network
*net
)
705 struct network_pex
*pex
= &net
->pex
;
706 struct network_pex_host
*host
, *tmp
;
708 uloop_timeout_cancel(&pex
->request_update_timer
);
709 list_for_each_entry_safe(host
, tmp
, &pex
->hosts
, list
) {
710 list_del(&host
->list
);
717 uloop_fd_delete(&pex
->fd
);
719 network_pex_init(net
);
722 static struct network
*
723 global_pex_find_network(const uint8_t *id
)
727 avl_for_each_element(&networks
, net
, node
) {
728 if (!memcmp(id
, net
->config
.auth_key
, PEX_ID_LEN
))
736 global_pex_recv(struct pex_hdr
*hdr
, struct sockaddr_in6
*addr
)
738 struct pex_ext_hdr
*ehdr
= (void *)(hdr
+ 1);
739 struct network_peer
*peer
;
741 void *data
= (void *)(ehdr
+ 1);
743 if (hdr
->version
!= 0)
746 net
= global_pex_find_network(ehdr
->auth_id
);
747 if (!net
|| net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
750 *(uint64_t *)hdr
->id
^= pex_network_hash(net
->config
.auth_key
, ehdr
->nonce
);
752 D("PEX global rx op=%d", hdr
->opcode
);
753 switch (hdr
->opcode
) {
755 case PEX_MSG_NOTIFY_PEERS
:
760 case PEX_MSG_UPDATE_REQUEST
:
761 peer
= pex_msg_peer(net
, hdr
->id
);
762 network_pex_recv_update_request(net
, peer
, data
, hdr
->len
,
765 case PEX_MSG_UPDATE_RESPONSE
:
766 case PEX_MSG_UPDATE_RESPONSE_DATA
:
767 case PEX_MSG_UPDATE_RESPONSE_NO_DATA
:
768 network_pex_recv_update_response(net
, data
, hdr
->len
, addr
, hdr
->opcode
);
773 int global_pex_open(void)
775 struct sockaddr_in6 sin6
= {};
777 sin6
.sin6_family
= AF_INET6
;
778 sin6
.sin6_port
= htons(global_pex_port
);
780 return pex_open(&sin6
, sizeof(sin6
), global_pex_recv
, true);