1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
6 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <netinet/ip.h>
10 #include <netinet/ip6.h>
11 #include <netinet/udp.h>
18 static const char *pex_peer_id_str(const uint8_t *key
)
23 for (i
= 0; i
< 8; i
++)
24 sprintf(str
+ i
* 2, "%02x", key
[i
]);
29 static struct pex_hdr
*
30 pex_msg_init(struct network
*net
, uint8_t opcode
)
32 return __pex_msg_init(net
->config
.pubkey
, opcode
);
35 static struct pex_hdr
*
36 pex_msg_init_ext(struct network
*net
, uint8_t opcode
, bool ext
)
38 return __pex_msg_init_ext(net
->config
.pubkey
, net
->config
.auth_key
, opcode
, ext
);
41 static struct network_peer
*
42 pex_msg_peer(struct network
*net
, const uint8_t *id
, bool allow_indirect
)
44 struct network_peer
*peer
;
45 uint8_t key
[WG_KEY_LEN
] = {};
47 memcpy(key
, id
, PEX_ID_LEN
);
48 peer
= avl_find_ge_element(&net
->peers
.avl
, key
, peer
, node
.avl
);
49 if (!peer
|| memcmp(peer
->key
, key
, PEX_ID_LEN
) != 0) {
50 D_NET(net
, "can't find peer %s", pex_peer_id_str(id
));
53 if (peer
->indirect
&& !allow_indirect
)
60 pex_get_peer_addr(struct sockaddr_in6
*sin6
, struct network
*net
,
61 struct network_peer
*peer
)
63 *sin6
= (struct sockaddr_in6
){
64 .sin6_family
= AF_INET6
,
65 .sin6_addr
= peer
->local_addr
.in6
,
66 .sin6_port
= htons(peer
->pex_port
),
70 static void pex_msg_send(struct network
*net
, struct network_peer
*peer
)
72 struct sockaddr_in6 sin6
= {};
74 if (!peer
|| peer
== &net
->net_config
.local_host
->peer
||
78 pex_get_peer_addr(&sin6
, net
, peer
);
79 if (__pex_msg_send(net
->pex
.fd
.fd
, &sin6
, NULL
, 0) < 0)
80 D_PEER(net
, peer
, "pex_msg_send failed: %s", strerror(errno
));
83 static void pex_msg_send_ext(struct network
*net
, struct network_peer
*peer
,
84 struct sockaddr_in6
*addr
)
86 char addrbuf
[INET6_ADDRSTRLEN
];
89 return pex_msg_send(net
, peer
);
91 if (__pex_msg_send(-1, addr
, NULL
, 0) < 0)
92 D_NET(net
, "pex_msg_send_ext(%s) failed: %s",
93 inet_ntop(addr
->sin6_family
, (const void *)&addr
->sin6_addr
, addrbuf
,
99 pex_send_hello(struct network
*net
, struct network_peer
*peer
)
101 struct pex_hello
*data
;
103 pex_msg_init(net
, PEX_MSG_HELLO
);
104 data
= pex_msg_append(sizeof(*data
));
105 if (peer
->state
.endpoint
.sa
.sa_family
== AF_INET6
)
106 data
->flags
|= htons(PEER_EP_F_IPV6
);
107 if (network_get_local_addr(&data
->local_addr
, &peer
->state
.endpoint
))
110 pex_msg_send(net
, peer
);
114 pex_msg_add_peer_endpoint(struct network
*net
, struct network_peer
*peer
,
115 struct network_peer
*receiver
)
117 struct pex_peer_endpoint
*data
;
123 addr
= network_endpoint_addr(&peer
->state
.endpoint
, &len
);
124 port
= peer
->state
.endpoint
.in
.sin_port
;
126 flags
|= PEER_EP_F_IPV6
;
127 if (network_endpoint_addr_equal(&peer
->state
.endpoint
,
128 &receiver
->state
.endpoint
)) {
129 if (!peer
->state
.has_local_ep_addr
) {
130 D_PEER(net
, peer
, "can't send peer to %s, missing local address",
131 network_peer_name(receiver
));
135 addr
= &peer
->state
.local_ep_addr
;
136 port
= htons(peer
->port
);
137 flags
|= PEER_EP_F_LOCAL
;
140 data
= pex_msg_append(sizeof(*data
));
144 memcpy(data
->peer_id
, peer
->key
, sizeof(data
->peer_id
));
145 memcpy(data
->addr
, addr
, len
);
147 data
->flags
= htons(flags
);
148 D_PEER(net
, peer
, "send endpoint to %s", network_peer_name(receiver
));
154 network_pex_handle_endpoint_change(struct network
*net
, struct network_peer
*peer
)
156 struct network_peer
*cur
;
158 vlist_for_each_element(&net
->peers
, cur
, node
) {
159 if (cur
== peer
|| !cur
->state
.connected
|| cur
->indirect
)
162 pex_msg_init(net
, PEX_MSG_NOTIFY_PEERS
);
163 if (pex_msg_add_peer_endpoint(net
, peer
, cur
))
166 pex_msg_send(net
, cur
);
171 network_pex_host_send_endpoint_notify(struct network
*net
, struct network_pex_host
*host
)
184 union network_endpoint dest_ep
;
185 union network_addr local_addr
= {};
188 pex_msg_init_ext(net
, PEX_MSG_ENDPOINT_NOTIFY
, true);
190 memcpy(&dest_ep
, &host
->endpoint
, sizeof(dest_ep
));
192 /* work around issue with local address lookup for local broadcast */
193 if (host
->endpoint
.sa
.sa_family
== AF_INET
) {
194 uint8_t *data
= (uint8_t *)&dest_ep
.in
.sin_addr
;
199 network_get_local_addr(&local_addr
, &dest_ep
);
201 memset(&dest_ep
, 0, sizeof(dest_ep
));
202 dest_ep
.sa
.sa_family
= host
->endpoint
.sa
.sa_family
;
203 if (host
->endpoint
.sa
.sa_family
== AF_INET
) {
204 packet
.ipv4
.ip
= (struct ip
){
209 .ip_src
= local_addr
.in
,
210 .ip_dst
= host
->endpoint
.in
.sin_addr
,
212 dest_ep
.in
.sin_addr
= host
->endpoint
.in
.sin_addr
;
213 udp
= &packet
.ipv4
.udp
;
214 len
= sizeof(packet
.ipv4
);
216 packet
.ipv6
.ip
= (struct ip6_hdr
){
217 .ip6_flow
= htonl(6 << 28),
219 .ip6_nxt
= IPPROTO_UDP
,
220 .ip6_src
= local_addr
.in6
,
221 .ip6_dst
= host
->endpoint
.in6
.sin6_addr
,
223 dest_ep
.in6
.sin6_addr
= host
->endpoint
.in6
.sin6_addr
;
224 udp
= &packet
.ipv6
.udp
;
225 len
= sizeof(packet
.ipv6
);
228 udp
->uh_sport
= htons(net
->net_config
.local_host
->peer
.port
);
229 udp
->uh_dport
= host
->endpoint
.in6
.sin6_port
;
231 if (__pex_msg_send(-1, &dest_ep
, &packet
, len
) < 0)
232 D_NET(net
, "pex_msg_send_raw failed: %s", strerror(errno
));
237 network_pex_host_send_port_notify(struct network
*net
, struct network_pex_host
*host
)
239 struct pex_endpoint_port_notify
*data
;
241 if (!net
->stun
.port_ext
)
244 pex_msg_init_ext(net
, PEX_MSG_ENDPOINT_PORT_NOTIFY
, true);
246 data
= pex_msg_append(sizeof(*data
));
247 data
->port
= htons(net
->stun
.port_ext
);
249 __pex_msg_send(-1, &host
->endpoint
, NULL
, 0);
253 network_pex_host_request_update(struct network
*net
, struct network_pex_host
*host
)
255 char addrstr
[INET6_ADDRSTRLEN
];
256 uint64_t version
= 0;
258 host
->last_ping
= unet_gettime();
260 if (net
->net_data_len
)
261 version
= net
->net_data_version
;
263 D("request network data from host %s",
264 inet_ntop(host
->endpoint
.sa
.sa_family
,
265 (host
->endpoint
.sa
.sa_family
== AF_INET6
?
266 (const void *)&host
->endpoint
.in6
.sin6_addr
:
267 (const void *)&host
->endpoint
.in
.sin_addr
),
268 addrstr
, sizeof(addrstr
)));
270 if (!pex_msg_update_request_init(net
->config
.pubkey
, net
->config
.key
,
271 net
->config
.auth_key
, &host
->endpoint
,
275 __pex_msg_send(-1, &host
->endpoint
, NULL
, 0);
277 if (!net
->net_config
.local_host
)
280 network_pex_host_send_port_notify(net
, host
);
281 network_pex_host_send_endpoint_notify(net
, host
);
285 network_pex_free_host(struct network
*net
, struct network_pex_host
*host
)
287 struct network_pex
*pex
= &net
->pex
;
290 list_del(&host
->list
);
295 network_pex_request_update_cb(struct uloop_timeout
*t
)
297 struct network
*net
= container_of(t
, struct network
, pex
.request_update_timer
);
298 struct network_pex
*pex
= &net
->pex
;
299 struct network_pex_host
*host
, *tmp
;
300 uint64_t now
= unet_gettime();
302 uloop_timeout_set(t
, 500);
304 if (list_empty(&pex
->hosts
))
307 list_for_each_entry_safe(host
, tmp
, &pex
->hosts
, list
) {
308 if (host
->timeout
&& host
->timeout
< now
) {
309 network_pex_free_host(net
, host
);
313 if (host
->last_ping
+ 10 >= now
)
316 list_move_tail(&host
->list
, &pex
->hosts
);
317 network_pex_host_request_update(net
, host
);
321 void network_pex_init(struct network
*net
)
323 struct network_pex
*pex
= &net
->pex
;
325 memset(pex
, 0, sizeof(*pex
));
327 INIT_LIST_HEAD(&pex
->hosts
);
328 pex
->request_update_timer
.cb
= network_pex_request_update_cb
;
332 network_pex_query_hosts(struct network
*net
)
334 struct network_host
*host
;
340 pex_msg_init(net
, PEX_MSG_QUERY
);
342 avl_for_each_element(&net
->hosts
, host
, node
) {
343 struct network_peer
*peer
= &host
->peer
;
346 if ((net
->stun
.port_ext
&& host
== net
->net_config
.local_host
) ||
347 peer
->state
.connected
|| peer
->endpoint
|| host
->gateway
)
350 id
= pex_msg_append(PEX_ID_LEN
);
354 memcpy(id
, peer
->key
, PEX_ID_LEN
);
361 now
= unet_gettime();
362 rv
%= net
->hosts
.count
;
363 for (i
= 0; i
< 2; i
++) {
364 avl_for_each_element(&net
->hosts
, host
, node
) {
365 struct network_peer
*peer
= &host
->peer
;
372 if (host
== net
->net_config
.local_host
)
375 if (!peer
->state
.connected
||
376 peer
->state
.last_query_sent
+ 15 >= now
)
379 D_PEER(net
, peer
, "send query for %d hosts", hosts
);
380 pex_msg_send(net
, peer
);
381 peer
->state
.last_query_sent
= now
;
389 network_pex_send_ping(struct network
*net
, struct network_peer
*peer
)
391 if (peer
->state
.pinged
|| !peer
->state
.endpoint
.sa
.sa_family
)
394 pex_msg_init(net
, PEX_MSG_PING
);
395 pex_msg_send(net
, peer
);
396 peer
->state
.pinged
= true;
400 network_pex_send_update_request(struct network
*net
, struct network_peer
*peer
,
401 struct sockaddr_in6
*addr
)
403 union network_endpoint ep
= {};
404 uint64_t version
= 0;
407 memcpy(&ep
.in6
, addr
, sizeof(ep
.in6
));
409 pex_get_peer_addr(&ep
.in6
, net
, peer
);
411 if (net
->net_data_len
)
412 version
= net
->net_data_version
;
414 if (!pex_msg_update_request_init(net
->config
.pubkey
, net
->config
.key
,
415 net
->config
.auth_key
, &ep
,
419 pex_msg_send_ext(net
, peer
, addr
);
422 void network_pex_event(struct network
*net
, struct network_peer
*peer
,
425 if (!network_pex_active(&net
->pex
))
429 case PEX_EV_HANDSHAKE
:
430 peer
->state
.last_query_sent
= 0;
431 pex_send_hello(net
, peer
);
432 if (net
->config
.type
== NETWORK_TYPE_DYNAMIC
)
433 network_pex_send_update_request(net
, peer
, NULL
);
435 case PEX_EV_ENDPOINT_CHANGE
:
436 network_pex_handle_endpoint_change(net
, peer
);
439 network_pex_query_hosts(net
);
442 network_pex_send_ping(net
, peer
);
448 network_pex_recv_hello(struct network
*net
, struct network_peer
*peer
,
449 const struct pex_hello
*data
, size_t len
)
451 char addrstr
[INET6_ADDRSTRLEN
];
455 if (len
< sizeof(*data
))
458 if (peer
->state
.has_local_ep_addr
&&
459 !memcmp(&peer
->state
.local_ep_addr
, data
->local_addr
, sizeof(data
->local_addr
)))
462 flags
= ntohs(data
->flags
);
463 af
= (flags
& PEER_EP_F_IPV6
) ? AF_INET6
: AF_INET
;
464 D_PEER(net
, peer
, "set local endpoint address to %s",
465 inet_ntop(af
, data
->local_addr
, addrstr
, sizeof(addrstr
)));
466 peer
->state
.has_local_ep_addr
= true;
467 memcpy(&peer
->state
.local_ep_addr
, data
->local_addr
, sizeof(data
->local_addr
));
471 network_pex_recv_peers(struct network
*net
, struct network_peer
*peer
,
472 const struct pex_peer_endpoint
*data
, size_t len
)
474 struct network_peer
*local
= &net
->net_config
.local_host
->peer
;
475 struct network_peer
*cur
;
477 for (; len
>= sizeof(*data
); len
-= sizeof(*data
), data
++) {
478 union network_endpoint
*ep
;
483 if (!memcmp(data
->peer_id
, &local
->key
, PEX_ID_LEN
)) {
484 network_stun_update_port(net
, false, ntohs(data
->port
));
488 cur
= pex_msg_peer(net
, data
->peer_id
, false);
489 if (!cur
|| cur
== peer
)
492 D_PEER(net
, peer
, "received peer address for %s",
493 network_peer_name(cur
));
494 flags
= ntohs(data
->flags
);
495 ep
= &cur
->state
.next_endpoint
[ENDPOINT_TYPE_PEX
];
496 ep
->sa
.sa_family
= (flags
& PEER_EP_F_IPV6
) ? AF_INET6
: AF_INET
;
497 addr
= network_endpoint_addr(ep
, &len
);
498 memcpy(addr
, data
->addr
, len
);
499 ep
->in
.sin_port
= data
->port
;
504 network_pex_recv_query(struct network
*net
, struct network_peer
*peer
,
505 const uint8_t *data
, size_t len
)
507 struct network_peer
*cur
;
510 pex_msg_init(net
, PEX_MSG_NOTIFY_PEERS
);
511 for (; len
>= 8; data
+= 8, len
-= 8) {
512 struct network_host
*host
;
514 cur
= pex_msg_peer(net
, data
, false);
515 if (!cur
|| !cur
->state
.connected
)
518 host
= container_of(peer
, struct network_host
, peer
);
522 if (!pex_msg_add_peer_endpoint(net
, cur
, peer
))
529 D_PEER(net
, peer
, "send query response with %d hosts", resp
);
530 pex_msg_send(net
, peer
);
534 network_pex_recv_ping(struct network
*net
, struct network_peer
*peer
)
536 time_t now
= time(NULL
);
538 if (peer
->state
.last_request
== now
)
541 peer
->state
.last_request
= now
;
542 pex_msg_init(net
, PEX_MSG_PONG
);
543 pex_msg_send(net
, peer
);
547 network_pex_recv_update_request(struct network
*net
, struct network_peer
*peer
,
548 const uint8_t *data
, size_t len
,
549 struct sockaddr_in6
*addr
)
551 struct pex_update_request
*req
= (struct pex_update_request
*)data
;
552 struct pex_endpoint_port_notify
*port_data
;
553 struct pex_msg_update_send_ctx ctx
= {};
554 uint64_t req_version
= be64_to_cpu(req
->cur_version
);
558 if (len
< sizeof(struct pex_update_request
))
561 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
565 query_count
= &peer
->state
.num_net_queries
;
567 query_count
= &net
->num_net_queries
;
569 if (++*query_count
> 10)
572 D("receive update request, local version=%"PRIu64
", remote version=%"PRIu64
, net
->net_data_version
, req_version
);
574 if (req_version
>= net
->net_data_version
) {
575 struct pex_update_response_no_data
*res
;
577 pex_msg_init_ext(net
, PEX_MSG_UPDATE_RESPONSE_NO_DATA
, !!addr
);
578 res
= pex_msg_append(sizeof(*res
));
579 res
->req_id
= req
->req_id
;
580 res
->cur_version
= cpu_to_be64(net
->net_data_version
);
581 pex_msg_send_ext(net
, peer
, addr
);
584 if (req_version
> net
->net_data_version
)
585 network_pex_send_update_request(net
, peer
, addr
);
587 if (!peer
|| !net
->net_data_len
)
590 if (req_version
>= net
->net_data_version
)
593 pex_msg_update_response_init(&ctx
, net
->config
.pubkey
, net
->config
.auth_key
,
594 peer
->key
, !!addr
, (void *)data
,
595 net
->net_data
, net
->net_data_len
);
597 pex_msg_send_ext(net
, peer
, addr
);
598 done
= !pex_msg_update_response_continue(&ctx
);
602 if (peer
->state
.connected
|| !net
->net_config
.local_host
)
605 pex_msg_init_ext(net
, PEX_MSG_ENDPOINT_PORT_NOTIFY
, !!addr
);
607 port_data
= pex_msg_append(sizeof(*port_data
));
608 if (net
->stun
.port_ext
)
609 port_data
->port
= htons(net
->stun
.port_ext
);
611 port_data
->port
= htons(net
->net_config
.local_host
->peer
.port
);
613 pex_msg_send_ext(net
, peer
, addr
);
617 network_pex_recv_update_response(struct network
*net
, const uint8_t *data
, size_t len
,
618 struct sockaddr_in6
*addr
, enum pex_opcode op
)
620 struct network_peer
*peer
;
622 int net_data_len
= 0;
623 uint64_t version
= 0;
624 bool no_prev_data
= !net
->net_data_len
;
626 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
629 net_data
= pex_msg_update_response_recv(data
, len
, op
, &net_data_len
, &version
);
633 if (version
<= net
->net_data_version
) {
638 D_NET(net
, "received updated network data, len=%d", net_data_len
);
641 net
->net_data
= net_data
;
642 net
->net_data_len
= net_data_len
;
643 net
->net_data_version
= version
;
644 if (network_save_dynamic(net
) < 0)
647 uloop_timeout_set(&net
->reload_timer
, no_prev_data
? 1 : UNETD_DATA_UPDATE_DELAY
);
648 vlist_for_each_element(&net
->peers
, peer
, node
) {
649 if (!peer
->state
.connected
|| !peer
->pex_port
)
651 network_pex_send_update_request(net
, peer
, NULL
);
656 network_pex_recv(struct network
*net
, struct network_peer
*peer
, struct pex_hdr
*hdr
)
658 const void *data
= hdr
+ 1;
660 if (hdr
->version
!= 0)
663 D_PEER(net
, peer
, "PEX rx op=%d", hdr
->opcode
);
664 switch (hdr
->opcode
) {
666 network_pex_recv_hello(net
, peer
, data
, hdr
->len
);
668 case PEX_MSG_NOTIFY_PEERS
:
669 network_pex_recv_peers(net
, peer
, data
, hdr
->len
);
672 network_pex_recv_query(net
, peer
, data
, hdr
->len
);
675 network_pex_recv_ping(net
, peer
);
679 case PEX_MSG_UPDATE_REQUEST
:
680 network_pex_recv_update_request(net
, peer
, data
, hdr
->len
,
683 case PEX_MSG_UPDATE_RESPONSE
:
684 case PEX_MSG_UPDATE_RESPONSE_DATA
:
685 case PEX_MSG_UPDATE_RESPONSE_NO_DATA
:
686 network_pex_recv_update_response(net
, data
, hdr
->len
,
689 case PEX_MSG_ENDPOINT_NOTIFY
:
695 network_pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
697 struct network
*net
= container_of(fd
, struct network
, pex
.fd
);
698 struct network_peer
*local
= &net
->net_config
.local_host
->peer
;
699 struct network_peer
*peer
;
700 struct sockaddr_in6 sin6
;
701 static char buf
[PEX_BUF_SIZE
];
702 struct pex_hdr
*hdr
= (struct pex_hdr
*)buf
;
706 socklen_t slen
= sizeof(sin6
);
708 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
716 D_NET(net
, "recvfrom failed: %s", strerror(errno
));
717 network_pex_close(net
);
724 hdr
= pex_rx_accept(buf
, len
, false);
728 peer
= pex_msg_peer(net
, hdr
->id
, false);
732 if (memcmp(&sin6
.sin6_addr
, &peer
->local_addr
.in6
, sizeof(sin6
.sin6_addr
)) != 0)
738 network_pex_recv(net
, peer
, hdr
);
742 void network_pex_create_host(struct network
*net
, union network_endpoint
*ep
,
743 unsigned int timeout
)
745 struct network_pex
*pex
= &net
->pex
;
746 struct network_pex_host
*host
;
747 uint64_t now
= unet_gettime();
748 bool new_host
= false;
750 list_for_each_entry(host
, &pex
->hosts
, list
) {
751 if (memcmp(&host
->endpoint
, ep
, sizeof(host
->endpoint
)) != 0)
754 if (host
->last_ping
+ 10 < now
) {
755 list_move_tail(&host
->list
, &pex
->hosts
);
756 network_pex_host_request_update(net
, host
);
761 host
= calloc(1, sizeof(*host
));
763 memcpy(&host
->endpoint
, ep
, sizeof(host
->endpoint
));
764 list_add_tail(&host
->list
, &pex
->hosts
);
768 if (timeout
&& (new_host
|| host
->timeout
))
769 host
->timeout
= timeout
+ unet_gettime();
773 network_pex_open_auth_connect(struct network
*net
)
775 struct network_pex
*pex
= &net
->pex
;
776 struct network_peer
*peer
;
777 struct blob_attr
*cur
;
780 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
783 uloop_timeout_set(&pex
->request_update_timer
, 5000);
785 vlist_for_each_element(&net
->peers
, peer
, node
) {
786 union network_endpoint ep
= {};
788 if (!peer
->endpoint
|| peer
->dynamic
)
791 if (network_get_endpoint(&ep
, AF_UNSPEC
, peer
->endpoint
,
792 UNETD_GLOBAL_PEX_PORT
, 0) < 0)
795 ep
.in
.sin_port
= htons(UNETD_GLOBAL_PEX_PORT
);
796 network_pex_create_host(net
, &ep
, 0);
799 if (!net
->config
.auth_connect
)
802 blobmsg_for_each_attr(cur
, net
->config
.auth_connect
, rem
) {
803 union network_endpoint ep
= {};
805 if (network_get_endpoint(&ep
, AF_UNSPEC
, blobmsg_get_string(cur
),
806 UNETD_GLOBAL_PEX_PORT
, 0) < 0)
809 network_pex_create_host(net
, &ep
, 0);
814 int network_pex_open(struct network
*net
)
816 struct network_host
*local_host
= net
->net_config
.local_host
;
817 struct network_peer
*local
;
818 struct network_pex
*pex
= &net
->pex
;
819 struct sockaddr_in6 sin6
= {};
823 network_pex_open_auth_connect(net
);
825 if (!local_host
|| !local_host
->peer
.pex_port
)
828 local
= &local_host
->peer
;
829 fd
= socket(PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
833 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
834 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
836 sin6
.sin6_family
= AF_INET6
;
837 memcpy(&sin6
.sin6_addr
, &local
->local_addr
.in6
,
838 sizeof(local
->local_addr
.in6
));
839 sin6
.sin6_port
= htons(local_host
->peer
.pex_port
);
841 if (bind(fd
, (struct sockaddr
*)&sin6
, sizeof(sin6
)) < 0) {
846 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
847 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
849 setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
850 network_name(net
), strlen(network_name(net
)));
854 pex
->fd
.cb
= network_pex_fd_cb
;
855 uloop_fd_add(&pex
->fd
, ULOOP_READ
);
864 void network_pex_close(struct network
*net
)
866 struct network_pex
*pex
= &net
->pex
;
867 struct network_pex_host
*host
, *tmp
;
868 uint64_t now
= unet_gettime();
870 uloop_timeout_cancel(&pex
->request_update_timer
);
871 list_for_each_entry_safe(host
, tmp
, &pex
->hosts
, list
) {
875 if (host
->last_active
+ UNETD_PEX_HOST_ACITVE_TIMEOUT
>= now
)
878 network_pex_free_host(net
, host
);
884 uloop_fd_delete(&pex
->fd
);
886 network_pex_init(net
);
889 void network_pex_free(struct network
*net
)
891 struct network_pex
*pex
= &net
->pex
;
892 struct network_pex_host
*host
, *tmp
;
894 list_for_each_entry_safe(host
, tmp
, &pex
->hosts
, list
)
895 network_pex_free_host(net
, host
);
898 static struct network
*
899 global_pex_find_network(const uint8_t *id
)
903 avl_for_each_element(&networks
, net
, node
) {
904 if (!memcmp(id
, net
->config
.auth_key
, PEX_ID_LEN
))
912 global_pex_set_active(struct network
*net
, struct sockaddr_in6
*addr
)
914 struct network_pex
*pex
= &net
->pex
;
915 struct network_pex_host
*host
;
917 list_for_each_entry(host
, &pex
->hosts
, list
) {
918 if (memcmp(&host
->endpoint
.in6
, addr
, sizeof(*addr
)) != 0)
921 host
->last_active
= unet_gettime();
926 global_pex_recv(void *msg
, size_t msg_len
, struct sockaddr_in6
*addr
)
929 struct pex_ext_hdr
*ehdr
;
930 struct network_peer
*peer
;
932 char buf
[INET6_ADDRSTRLEN
];
935 int ep_idx
= ENDPOINT_TYPE_ENDPOINT_NOTIFY
;
937 if (stun_msg_is_valid(msg
, msg_len
)) {
938 avl_for_each_element(&networks
, net
, node
)
939 network_stun_rx_packet(net
, msg
, msg_len
);
942 hdr
= pex_rx_accept(msg
, msg_len
, true);
946 ehdr
= (void *)(hdr
+ 1);
947 data
= (void *)(ehdr
+ 1);
949 if (hdr
->version
!= 0)
952 net
= global_pex_find_network(ehdr
->auth_id
);
953 if (!net
|| net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
956 *(uint64_t *)hdr
->id
^= pex_network_hash(net
->config
.auth_key
, ehdr
->nonce
);
958 global_pex_set_active(net
, addr
);
960 D("PEX global rx op=%d", hdr
->opcode
);
961 switch (hdr
->opcode
) {
963 case PEX_MSG_NOTIFY_PEERS
:
968 case PEX_MSG_UPDATE_REQUEST
:
969 peer
= pex_msg_peer(net
, hdr
->id
, true);
970 network_pex_recv_update_request(net
, peer
, data
, hdr
->len
,
973 case PEX_MSG_UPDATE_RESPONSE
:
974 case PEX_MSG_UPDATE_RESPONSE_DATA
:
975 case PEX_MSG_UPDATE_RESPONSE_NO_DATA
:
976 network_pex_recv_update_response(net
, data
, hdr
->len
, addr
, hdr
->opcode
);
978 case PEX_MSG_ENDPOINT_PORT_NOTIFY
:
979 if (hdr
->len
< sizeof(struct pex_endpoint_port_notify
))
982 ep_idx
= ENDPOINT_TYPE_ENDPOINT_PORT_NOTIFY
;
984 case PEX_MSG_ENDPOINT_NOTIFY
:
985 peer
= pex_msg_peer(net
, hdr
->id
, true);
989 D_PEER(net
, peer
, "receive endpoint notification from %s",
990 inet_ntop(addr
->sin6_family
, network_endpoint_addr((void *)addr
, &addr_len
),
993 memcpy(&peer
->state
.next_endpoint
[ep_idx
], addr
, sizeof(*addr
));
994 if (hdr
->opcode
== PEX_MSG_ENDPOINT_PORT_NOTIFY
) {
995 struct pex_endpoint_port_notify
*port
= data
;
996 union network_endpoint host_ep
= {
1000 peer
->state
.next_endpoint
[ep_idx
].in
.sin_port
= port
->port
;
1001 if (net
->pex
.num_hosts
< NETWORK_PEX_HOSTS_LIMIT
)
1002 network_pex_create_host(net
, &host_ep
, 120);
1009 pex_recv_control(struct pex_msg_local_control
*msg
, int len
)
1011 struct network
*net
;
1013 if (msg
->msg_type
!= 0)
1016 net
= global_pex_find_network(msg
->auth_id
);
1022 network_pex_create_host(net
, &msg
->ep
, msg
->timeout
);
1025 int global_pex_open(const char *unix_path
)
1027 struct sockaddr_in6 sin6
= {};
1030 sin6
.sin6_family
= AF_INET6
;
1031 sin6
.sin6_port
= htons(global_pex_port
);
1033 ret
= pex_open(&sin6
, sizeof(sin6
), global_pex_recv
, true);
1036 pex_unix_open(unix_path
, pex_recv_control
);