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
)
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
));
58 pex_get_peer_addr(struct sockaddr_in6
*sin6
, struct network
*net
,
59 struct network_peer
*peer
)
61 *sin6
= (struct sockaddr_in6
){
62 .sin6_family
= AF_INET6
,
63 .sin6_addr
= peer
->local_addr
.in6
,
64 .sin6_port
= htons(peer
->pex_port
),
68 static void pex_msg_send(struct network
*net
, struct network_peer
*peer
)
70 struct sockaddr_in6 sin6
= {};
72 if (!peer
|| peer
== &net
->net_config
.local_host
->peer
||
76 pex_get_peer_addr(&sin6
, net
, peer
);
77 if (__pex_msg_send(net
->pex
.fd
.fd
, &sin6
, NULL
, 0) < 0)
78 D_PEER(net
, peer
, "pex_msg_send failed: %s", strerror(errno
));
81 static void pex_msg_send_ext(struct network
*net
, struct network_peer
*peer
,
82 struct sockaddr_in6
*addr
)
84 char addrbuf
[INET6_ADDRSTRLEN
];
87 return pex_msg_send(net
, peer
);
89 if (__pex_msg_send(-1, addr
, NULL
, 0) < 0)
90 D_NET(net
, "pex_msg_send_ext(%s) failed: %s",
91 inet_ntop(addr
->sin6_family
, (const void *)&addr
->sin6_addr
, addrbuf
,
97 pex_send_hello(struct network
*net
, struct network_peer
*peer
)
99 struct pex_hello
*data
;
101 pex_msg_init(net
, PEX_MSG_HELLO
);
102 data
= pex_msg_append(sizeof(*data
));
103 if (peer
->state
.endpoint
.sa
.sa_family
== AF_INET6
)
104 data
->flags
|= htons(PEER_EP_F_IPV6
);
105 if (network_get_local_addr(&data
->local_addr
, &peer
->state
.endpoint
))
108 pex_msg_send(net
, peer
);
112 pex_msg_add_peer_endpoint(struct network
*net
, struct network_peer
*peer
,
113 struct network_peer
*receiver
)
115 struct pex_peer_endpoint
*data
;
121 addr
= network_endpoint_addr(&peer
->state
.endpoint
, &len
);
122 port
= peer
->state
.endpoint
.in
.sin_port
;
124 flags
|= PEER_EP_F_IPV6
;
125 if (network_endpoint_addr_equal(&peer
->state
.endpoint
,
126 &receiver
->state
.endpoint
)) {
127 if (!peer
->state
.has_local_ep_addr
) {
128 D_PEER(net
, peer
, "can't send peer to %s, missing local address",
129 network_peer_name(receiver
));
133 addr
= &peer
->state
.local_ep_addr
;
134 port
= htons(peer
->port
);
135 flags
|= PEER_EP_F_LOCAL
;
138 data
= pex_msg_append(sizeof(*data
));
142 memcpy(data
->peer_id
, peer
->key
, sizeof(data
->peer_id
));
143 memcpy(data
->addr
, addr
, len
);
145 data
->flags
= htons(flags
);
146 D_PEER(net
, peer
, "send endpoint to %s", network_peer_name(receiver
));
152 network_pex_handle_endpoint_change(struct network
*net
, struct network_peer
*peer
)
154 struct network_peer
*cur
;
156 vlist_for_each_element(&net
->peers
, cur
, node
) {
157 if (cur
== peer
|| !cur
->state
.connected
)
160 pex_msg_init(net
, PEX_MSG_NOTIFY_PEERS
);
161 if (pex_msg_add_peer_endpoint(net
, peer
, cur
))
164 pex_msg_send(net
, cur
);
169 network_pex_host_request_update(struct network
*net
, struct network_pex_host
*host
)
182 char addrstr
[INET6_ADDRSTRLEN
];
183 union network_endpoint dest_ep
;
184 union network_addr local_addr
= {};
185 uint64_t version
= 0;
188 if (net
->net_data_len
)
189 version
= net
->net_data_version
;
191 D("request network data from host %s",
192 inet_ntop(host
->endpoint
.sa
.sa_family
,
193 (host
->endpoint
.sa
.sa_family
== AF_INET6
?
194 (const void *)&host
->endpoint
.in6
.sin6_addr
:
195 (const void *)&host
->endpoint
.in
.sin_addr
),
196 addrstr
, sizeof(addrstr
)));
198 if (!pex_msg_update_request_init(net
->config
.pubkey
, net
->config
.key
,
199 net
->config
.auth_key
, &host
->endpoint
,
203 __pex_msg_send(-1, &host
->endpoint
, NULL
, 0);
205 if (!net
->net_config
.local_host
)
208 pex_msg_init_ext(net
, PEX_MSG_ENDPOINT_NOTIFY
, true);
210 memcpy(&dest_ep
, &host
->endpoint
, sizeof(dest_ep
));
212 /* work around issue with local address lookup for local broadcast */
213 if (host
->endpoint
.sa
.sa_family
== AF_INET
) {
214 uint8_t *data
= (uint8_t *)&dest_ep
.in
.sin_addr
;
219 network_get_local_addr(&local_addr
, &dest_ep
);
221 memset(&dest_ep
, 0, sizeof(dest_ep
));
222 dest_ep
.sa
.sa_family
= host
->endpoint
.sa
.sa_family
;
223 if (host
->endpoint
.sa
.sa_family
== AF_INET
) {
224 packet
.ipv4
.ip
= (struct ip
){
229 .ip_src
= local_addr
.in
,
230 .ip_dst
= host
->endpoint
.in
.sin_addr
,
232 dest_ep
.in
.sin_addr
= host
->endpoint
.in
.sin_addr
;
233 udp
= &packet
.ipv4
.udp
;
234 len
= sizeof(packet
.ipv4
);
236 packet
.ipv6
.ip
= (struct ip6_hdr
){
237 .ip6_flow
= htonl(6 << 28),
239 .ip6_nxt
= IPPROTO_UDP
,
240 .ip6_src
= local_addr
.in6
,
241 .ip6_dst
= host
->endpoint
.in6
.sin6_addr
,
243 dest_ep
.in6
.sin6_addr
= host
->endpoint
.in6
.sin6_addr
;
244 udp
= &packet
.ipv6
.udp
;
245 len
= sizeof(packet
.ipv6
);
248 udp
->uh_sport
= htons(net
->net_config
.local_host
->peer
.port
);
249 udp
->uh_dport
= host
->endpoint
.in6
.sin6_port
;
251 if (__pex_msg_send(-1, &dest_ep
, &packet
, len
) < 0)
252 D_NET(net
, "pex_msg_send_raw failed: %s", strerror(errno
));
256 network_pex_request_update_cb(struct uloop_timeout
*t
)
258 struct network
*net
= container_of(t
, struct network
, pex
.request_update_timer
);
259 struct network_pex
*pex
= &net
->pex
;
260 struct network_pex_host
*host
;
262 uloop_timeout_set(t
, 5000);
265 if (list_empty(&pex
->hosts
))
268 host
= list_first_entry(&pex
->hosts
, struct network_pex_host
, list
);
269 if (host
->timeout
&& host
->timeout
< unet_gettime()) {
270 list_del(&host
->list
);
275 list_move_tail(&host
->list
, &pex
->hosts
);
276 network_pex_host_request_update(net
, host
);
279 void network_pex_init(struct network
*net
)
281 struct network_pex
*pex
= &net
->pex
;
283 memset(pex
, 0, sizeof(*pex
));
285 INIT_LIST_HEAD(&pex
->hosts
);
286 pex
->request_update_timer
.cb
= network_pex_request_update_cb
;
290 network_pex_query_hosts(struct network
*net
)
292 struct network_host
*host
;
297 pex_msg_init(net
, PEX_MSG_QUERY
);
299 avl_for_each_element(&net
->hosts
, host
, node
) {
300 struct network_peer
*peer
= &host
->peer
;
303 if (host
== net
->net_config
.local_host
||
304 peer
->state
.connected
||
308 id
= pex_msg_append(PEX_ID_LEN
);
312 memcpy(id
, peer
->key
, PEX_ID_LEN
);
319 rv
%= net
->hosts
.count
;
320 for (i
= 0; i
< 2; i
++) {
321 avl_for_each_element(&net
->hosts
, host
, node
) {
322 struct network_peer
*peer
= &host
->peer
;
329 if (host
== net
->net_config
.local_host
)
332 if (!peer
->state
.connected
)
335 D_PEER(net
, peer
, "send query for %d hosts", hosts
);
336 pex_msg_send(net
, peer
);
344 network_pex_send_ping(struct network
*net
, struct network_peer
*peer
)
346 if (peer
->state
.pinged
|| !peer
->state
.endpoint
.sa
.sa_family
)
349 pex_msg_init(net
, PEX_MSG_PING
);
350 pex_msg_send(net
, peer
);
351 peer
->state
.pinged
= true;
355 network_pex_send_update_request(struct network
*net
, struct network_peer
*peer
,
356 struct sockaddr_in6
*addr
)
358 union network_endpoint ep
= {};
359 uint64_t version
= 0;
362 memcpy(&ep
.in6
, addr
, sizeof(ep
.in6
));
364 pex_get_peer_addr(&ep
.in6
, net
, peer
);
366 if (net
->net_data_len
)
367 version
= net
->net_data_version
;
369 if (!pex_msg_update_request_init(net
->config
.pubkey
, net
->config
.key
,
370 net
->config
.auth_key
, &ep
,
374 pex_msg_send_ext(net
, peer
, addr
);
377 void network_pex_event(struct network
*net
, struct network_peer
*peer
,
380 if (!network_pex_active(&net
->pex
))
384 D_PEER(net
, peer
, "PEX event type=%d", ev
);
386 D_NET(net
, "PEX event type=%d", ev
);
389 case PEX_EV_HANDSHAKE
:
390 pex_send_hello(net
, peer
);
391 if (net
->config
.type
== NETWORK_TYPE_DYNAMIC
)
392 network_pex_send_update_request(net
, peer
, NULL
);
394 case PEX_EV_ENDPOINT_CHANGE
:
395 network_pex_handle_endpoint_change(net
, peer
);
398 network_pex_query_hosts(net
);
401 network_pex_send_ping(net
, peer
);
407 network_pex_recv_hello(struct network
*net
, struct network_peer
*peer
,
408 const struct pex_hello
*data
, size_t len
)
410 char addrstr
[INET6_ADDRSTRLEN
];
414 if (len
< sizeof(*data
))
417 if (peer
->state
.has_local_ep_addr
&&
418 !memcmp(&peer
->state
.local_ep_addr
, data
->local_addr
, sizeof(data
->local_addr
)))
421 flags
= ntohs(data
->flags
);
422 af
= (flags
& PEER_EP_F_IPV6
) ? AF_INET6
: AF_INET
;
423 D_PEER(net
, peer
, "set local endpoint address to %s",
424 inet_ntop(af
, data
->local_addr
, addrstr
, sizeof(addrstr
)));
425 peer
->state
.has_local_ep_addr
= true;
426 memcpy(&peer
->state
.local_ep_addr
, data
->local_addr
, sizeof(data
->local_addr
));
430 network_pex_recv_peers(struct network
*net
, struct network_peer
*peer
,
431 const struct pex_peer_endpoint
*data
, size_t len
)
433 struct network_peer
*local
= &net
->net_config
.local_host
->peer
;
434 struct network_peer
*cur
;
436 for (; len
>= sizeof(*data
); len
-= sizeof(*data
), data
++) {
437 union network_endpoint
*ep
;
442 cur
= pex_msg_peer(net
, data
->peer_id
);
446 if (cur
== peer
|| cur
== local
)
449 D_PEER(net
, peer
, "received peer address for %s",
450 network_peer_name(cur
));
451 flags
= ntohs(data
->flags
);
452 ep
= &cur
->state
.next_endpoint
;
453 ep
->sa
.sa_family
= (flags
& PEER_EP_F_IPV6
) ? AF_INET6
: AF_INET
;
454 addr
= network_endpoint_addr(ep
, &len
);
455 memcpy(addr
, data
->addr
, len
);
456 ep
->in
.sin_port
= data
->port
;
461 network_pex_recv_query(struct network
*net
, struct network_peer
*peer
,
462 const uint8_t *data
, size_t len
)
464 struct network_peer
*cur
;
467 pex_msg_init(net
, PEX_MSG_NOTIFY_PEERS
);
468 for (; len
>= 8; data
+= 8, len
-= 8) {
469 cur
= pex_msg_peer(net
, data
);
470 if (!cur
|| !cur
->state
.connected
)
473 if (!pex_msg_add_peer_endpoint(net
, cur
, peer
))
480 D_PEER(net
, peer
, "send query response with %d hosts", resp
);
481 pex_msg_send(net
, peer
);
485 network_pex_recv_ping(struct network
*net
, struct network_peer
*peer
)
487 time_t now
= time(NULL
);
489 if (peer
->state
.last_request
== now
)
492 peer
->state
.last_request
= now
;
493 pex_msg_init(net
, PEX_MSG_PONG
);
494 pex_msg_send(net
, peer
);
498 network_pex_recv_update_request(struct network
*net
, struct network_peer
*peer
,
499 const uint8_t *data
, size_t len
,
500 struct sockaddr_in6
*addr
)
502 struct pex_update_request
*req
= (struct pex_update_request
*)data
;
503 struct pex_msg_update_send_ctx ctx
= {};
504 uint64_t req_version
= be64_to_cpu(req
->cur_version
);
508 if (len
< sizeof(struct pex_update_request
))
511 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
515 query_count
= &peer
->state
.num_net_queries
;
517 query_count
= &net
->num_net_queries
;
519 if (++*query_count
> 10)
522 D("receive update request, local version=%"PRIu64
", remote version=%"PRIu64
, net
->net_data_version
, req_version
);
524 if (req_version
>= net
->net_data_version
) {
525 struct pex_update_response_no_data
*res
;
527 pex_msg_init_ext(net
, PEX_MSG_UPDATE_RESPONSE_NO_DATA
, !!addr
);
528 res
= pex_msg_append(sizeof(*res
));
529 res
->req_id
= req
->req_id
;
530 res
->cur_version
= cpu_to_be64(net
->net_data_version
);
531 pex_msg_send_ext(net
, peer
, addr
);
534 if (req_version
> net
->net_data_version
)
535 network_pex_send_update_request(net
, peer
, addr
);
537 if (!peer
|| !net
->net_data_len
)
540 if (req_version
>= net
->net_data_version
)
543 pex_msg_update_response_init(&ctx
, net
->config
.pubkey
, net
->config
.auth_key
,
544 peer
->key
, !!addr
, (void *)data
,
545 net
->net_data
, net
->net_data_len
);
547 pex_msg_send_ext(net
, peer
, addr
);
548 done
= !pex_msg_update_response_continue(&ctx
);
553 network_pex_recv_update_response(struct network
*net
, const uint8_t *data
, size_t len
,
554 struct sockaddr_in6
*addr
, enum pex_opcode op
)
556 struct network_peer
*peer
;
558 int net_data_len
= 0;
559 uint64_t version
= 0;
560 bool no_prev_data
= !net
->net_data_len
;
562 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
565 net_data
= pex_msg_update_response_recv(data
, len
, op
, &net_data_len
, &version
);
569 if (version
<= net
->net_data_version
) {
574 D_NET(net
, "received updated network data, len=%d", net_data_len
);
577 net
->net_data
= net_data
;
578 net
->net_data_len
= net_data_len
;
579 net
->net_data_version
= version
;
580 if (network_save_dynamic(net
) < 0)
583 uloop_timeout_set(&net
->reload_timer
, no_prev_data
? 1 : UNETD_DATA_UPDATE_DELAY
);
584 vlist_for_each_element(&net
->peers
, peer
, node
) {
585 if (!peer
->state
.connected
|| !peer
->pex_port
)
587 network_pex_send_update_request(net
, peer
, NULL
);
592 network_pex_recv(struct network
*net
, struct network_peer
*peer
, struct pex_hdr
*hdr
)
594 const void *data
= hdr
+ 1;
596 if (hdr
->version
!= 0)
599 D_PEER(net
, peer
, "PEX rx op=%d", hdr
->opcode
);
600 switch (hdr
->opcode
) {
602 network_pex_recv_hello(net
, peer
, data
, hdr
->len
);
604 case PEX_MSG_NOTIFY_PEERS
:
605 network_pex_recv_peers(net
, peer
, data
, hdr
->len
);
608 network_pex_recv_query(net
, peer
, data
, hdr
->len
);
611 network_pex_recv_ping(net
, peer
);
615 case PEX_MSG_UPDATE_REQUEST
:
616 network_pex_recv_update_request(net
, peer
, data
, hdr
->len
,
619 case PEX_MSG_UPDATE_RESPONSE
:
620 case PEX_MSG_UPDATE_RESPONSE_DATA
:
621 case PEX_MSG_UPDATE_RESPONSE_NO_DATA
:
622 network_pex_recv_update_response(net
, data
, hdr
->len
,
625 case PEX_MSG_ENDPOINT_NOTIFY
:
631 network_pex_fd_cb(struct uloop_fd
*fd
, unsigned int events
)
633 struct network
*net
= container_of(fd
, struct network
, pex
.fd
);
634 struct network_peer
*local
= &net
->net_config
.local_host
->peer
;
635 struct network_peer
*peer
;
636 struct sockaddr_in6 sin6
;
637 static char buf
[PEX_BUF_SIZE
];
638 struct pex_hdr
*hdr
= (struct pex_hdr
*)buf
;
642 socklen_t slen
= sizeof(sin6
);
644 len
= recvfrom(fd
->fd
, buf
, sizeof(buf
), 0, (struct sockaddr
*)&sin6
, &slen
);
652 D_NET(net
, "recvfrom failed: %s", strerror(errno
));
653 network_pex_close(net
);
660 if (len
< sizeof(*hdr
))
663 hdr
->len
= ntohs(hdr
->len
);
664 if (len
- sizeof(hdr
) < hdr
->len
)
667 peer
= pex_msg_peer(net
, hdr
->id
);
671 if (memcmp(&sin6
.sin6_addr
, &peer
->local_addr
.in6
, sizeof(sin6
.sin6_addr
)) != 0)
677 network_pex_recv(net
, peer
, hdr
);
681 void network_pex_create_host(struct network
*net
, union network_endpoint
*ep
,
682 unsigned int timeout
)
684 struct network_pex
*pex
= &net
->pex
;
685 struct network_pex_host
*host
;
686 bool new_host
= false;
688 list_for_each_entry(host
, &pex
->hosts
, list
) {
689 if (memcmp(&host
->endpoint
, ep
, sizeof(host
->endpoint
)) != 0)
692 list_move_tail(&host
->list
, &pex
->hosts
);
696 host
= calloc(1, sizeof(*host
));
698 memcpy(&host
->endpoint
, ep
, sizeof(host
->endpoint
));
699 list_add_tail(&host
->list
, &pex
->hosts
);
702 if (timeout
&& (new_host
|| host
->timeout
))
703 host
->timeout
= timeout
+ unet_gettime();
704 network_pex_host_request_update(net
, host
);
708 network_pex_open_auth_connect(struct network
*net
)
710 struct network_pex
*pex
= &net
->pex
;
711 struct network_peer
*peer
;
712 struct blob_attr
*cur
;
715 if (net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
718 uloop_timeout_set(&pex
->request_update_timer
, 5000);
720 vlist_for_each_element(&net
->peers
, peer
, node
) {
721 union network_endpoint ep
= {};
723 if (!peer
->endpoint
|| peer
->dynamic
)
726 if (network_get_endpoint(&ep
, peer
->endpoint
,
727 UNETD_GLOBAL_PEX_PORT
, 0) < 0)
730 ep
.in
.sin_port
= htons(UNETD_GLOBAL_PEX_PORT
);
731 network_pex_create_host(net
, &ep
, 0);
734 if (!net
->config
.auth_connect
)
737 blobmsg_for_each_attr(cur
, net
->config
.auth_connect
, rem
) {
738 union network_endpoint ep
= {};
740 if (network_get_endpoint(&ep
, blobmsg_get_string(cur
),
741 UNETD_GLOBAL_PEX_PORT
, 0) < 0)
744 network_pex_create_host(net
, &ep
, 0);
749 int network_pex_open(struct network
*net
)
751 struct network_host
*local_host
= net
->net_config
.local_host
;
752 struct network_peer
*local
;
753 struct network_pex
*pex
= &net
->pex
;
754 struct sockaddr_in6 sin6
= {};
758 network_pex_open_auth_connect(net
);
760 if (!local_host
|| !local_host
->peer
.pex_port
)
763 local
= &local_host
->peer
;
764 fd
= socket(PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
768 fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
);
769 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
771 sin6
.sin6_family
= AF_INET6
;
772 memcpy(&sin6
.sin6_addr
, &local
->local_addr
.in6
,
773 sizeof(local
->local_addr
.in6
));
774 sin6
.sin6_port
= htons(local_host
->peer
.pex_port
);
776 if (bind(fd
, (struct sockaddr
*)&sin6
, sizeof(sin6
)) < 0) {
781 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
782 setsockopt(fd
, SOL_SOCKET
, SO_REUSEPORT
, &yes
, sizeof(yes
));
784 setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
785 network_name(net
), strlen(network_name(net
)));
789 pex
->fd
.cb
= network_pex_fd_cb
;
790 uloop_fd_add(&pex
->fd
, ULOOP_READ
);
799 void network_pex_close(struct network
*net
)
801 struct network_pex
*pex
= &net
->pex
;
802 struct network_pex_host
*host
, *tmp
;
804 uloop_timeout_cancel(&pex
->request_update_timer
);
805 list_for_each_entry_safe(host
, tmp
, &pex
->hosts
, list
) {
809 list_del(&host
->list
);
816 uloop_fd_delete(&pex
->fd
);
818 network_pex_init(net
);
821 void network_pex_free(struct network
*net
)
823 struct network_pex
*pex
= &net
->pex
;
824 struct network_pex_host
*host
, *tmp
;
826 list_for_each_entry_safe(host
, tmp
, &pex
->hosts
, list
) {
827 list_del(&host
->list
);
832 static struct network
*
833 global_pex_find_network(const uint8_t *id
)
837 avl_for_each_element(&networks
, net
, node
) {
838 if (!memcmp(id
, net
->config
.auth_key
, PEX_ID_LEN
))
846 global_pex_recv(struct pex_hdr
*hdr
, struct sockaddr_in6
*addr
)
848 struct pex_ext_hdr
*ehdr
= (void *)(hdr
+ 1);
849 struct network_peer
*peer
;
851 void *data
= (void *)(ehdr
+ 1);
852 char buf
[INET6_ADDRSTRLEN
];
855 if (hdr
->version
!= 0)
858 net
= global_pex_find_network(ehdr
->auth_id
);
859 if (!net
|| net
->config
.type
!= NETWORK_TYPE_DYNAMIC
)
862 *(uint64_t *)hdr
->id
^= pex_network_hash(net
->config
.auth_key
, ehdr
->nonce
);
864 D("PEX global rx op=%d", hdr
->opcode
);
865 switch (hdr
->opcode
) {
867 case PEX_MSG_NOTIFY_PEERS
:
872 case PEX_MSG_UPDATE_REQUEST
:
873 peer
= pex_msg_peer(net
, hdr
->id
);
874 network_pex_recv_update_request(net
, peer
, data
, hdr
->len
,
877 case PEX_MSG_UPDATE_RESPONSE
:
878 case PEX_MSG_UPDATE_RESPONSE_DATA
:
879 case PEX_MSG_UPDATE_RESPONSE_NO_DATA
:
880 network_pex_recv_update_response(net
, data
, hdr
->len
, addr
, hdr
->opcode
);
882 case PEX_MSG_ENDPOINT_NOTIFY
:
883 peer
= pex_msg_peer(net
, hdr
->id
);
887 if (IN6_IS_ADDR_V4MAPPED(&addr
->sin6_addr
)) {
888 struct sockaddr_in
*sin
= (struct sockaddr_in
*)addr
;
889 struct in_addr in
= *(struct in_addr
*)&addr
->sin6_addr
.s6_addr
[12];
890 int port
= addr
->sin6_port
;
892 memset(addr
, 0, sizeof(*addr
));
893 sin
->sin_port
= port
;
894 sin
->sin_family
= AF_INET
;
898 D_PEER(net
, peer
, "receive endpoint notification from %s",
899 inet_ntop(addr
->sin6_family
, network_endpoint_addr((void *)addr
, &addr_len
),
902 memcpy(&peer
->state
.next_endpoint
, addr
, sizeof(*addr
));
907 int global_pex_open(void)
909 struct sockaddr_in6 sin6
= {};
911 sin6
.sin6_family
= AF_INET6
;
912 sin6
.sin6_port
= htons(global_pex_port
);
914 return pex_open(&sin6
, sizeof(sin6
), global_pex_recv
, true);