7a76cf7e4f76f842a541aee270099ffaadd99627
[project/unetd.git] / pex.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
4 */
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9 #include <netinet/ip.h>
10 #include <netinet/ip6.h>
11 #include <netinet/udp.h>
12 #include <fcntl.h>
13 #include <stdlib.h>
14 #include <inttypes.h>
15 #include "unetd.h"
16 #include "pex-msg.h"
17
18 static const char *pex_peer_id_str(const uint8_t *key)
19 {
20 static char str[20];
21 int i;
22
23 for (i = 0; i < 8; i++)
24 sprintf(str + i * 2, "%02x", key[i]);
25
26 return str;
27 }
28
29 static struct pex_hdr *
30 pex_msg_init(struct network *net, uint8_t opcode)
31 {
32 return __pex_msg_init(net->config.pubkey, opcode);
33 }
34
35 static struct pex_hdr *
36 pex_msg_init_ext(struct network *net, uint8_t opcode, bool ext)
37 {
38 return __pex_msg_init_ext(net->config.pubkey, net->config.auth_key, opcode, ext);
39 }
40
41 static struct network_peer *
42 pex_msg_peer(struct network *net, const uint8_t *id)
43 {
44 struct network_peer *peer;
45 uint8_t key[WG_KEY_LEN] = {};
46
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));
51 return NULL;
52 }
53
54 return peer;
55 }
56
57 static void
58 pex_get_peer_addr(struct sockaddr_in6 *sin6, struct network *net,
59 struct network_peer *peer)
60 {
61 *sin6 = (struct sockaddr_in6){
62 .sin6_family = AF_INET6,
63 .sin6_addr = peer->local_addr.in6,
64 .sin6_port = htons(peer->pex_port),
65 };
66 }
67
68 static void pex_msg_send(struct network *net, struct network_peer *peer)
69 {
70 struct sockaddr_in6 sin6 = {};
71
72 if (!peer || peer == &net->net_config.local_host->peer ||
73 !peer->pex_port)
74 return;
75
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));
79 }
80
81 static void pex_msg_send_ext(struct network *net, struct network_peer *peer,
82 struct sockaddr_in6 *addr)
83 {
84 char addrbuf[INET6_ADDRSTRLEN];
85
86 if (!addr)
87 return pex_msg_send(net, peer);
88
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,
92 sizeof(addrbuf)),
93 strerror(errno));
94 }
95
96 static void
97 pex_send_hello(struct network *net, struct network_peer *peer)
98 {
99 struct pex_hello *data;
100
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))
106 return;
107
108 pex_msg_send(net, peer);
109 }
110
111 static int
112 pex_msg_add_peer_endpoint(struct network *net, struct network_peer *peer,
113 struct network_peer *receiver)
114 {
115 struct pex_peer_endpoint *data;
116 uint16_t flags = 0;
117 const void *addr;
118 int port;
119 int len;
120
121 addr = network_endpoint_addr(&peer->state.endpoint, &len);
122 port = peer->state.endpoint.in.sin_port;
123 if (len > 4)
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));
130 return -1;
131 }
132
133 addr = &peer->state.local_ep_addr;
134 port = htons(peer->port);
135 flags |= PEER_EP_F_LOCAL;
136 }
137
138 data = pex_msg_append(sizeof(*data));
139 if (!data)
140 return -1;
141
142 memcpy(data->peer_id, peer->key, sizeof(data->peer_id));
143 memcpy(data->addr, addr, len);
144 data->port = port;
145 data->flags = htons(flags);
146 D_PEER(net, peer, "send endpoint to %s", network_peer_name(receiver));
147
148 return 0;
149 }
150
151 static void
152 network_pex_handle_endpoint_change(struct network *net, struct network_peer *peer)
153 {
154 struct network_peer *cur;
155
156 vlist_for_each_element(&net->peers, cur, node) {
157 if (cur == peer || !cur->state.connected)
158 continue;
159
160 pex_msg_init(net, PEX_MSG_NOTIFY_PEERS);
161 if (pex_msg_add_peer_endpoint(net, peer, cur))
162 continue;
163
164 pex_msg_send(net, cur);
165 }
166 }
167
168 static void
169 network_pex_host_request_update(struct network *net, struct network_pex_host *host)
170 {
171 union {
172 struct {
173 struct ip ip;
174 struct udphdr udp;
175 } ipv4;
176 struct {
177 struct ip6_hdr ip;
178 struct udphdr udp;
179 } ipv6;
180 } packet = {};
181 struct udphdr *udp;
182 char addrstr[INET6_ADDRSTRLEN];
183 union network_endpoint dest_ep;
184 union network_addr local_addr = {};
185 uint64_t version = 0;
186 int len;
187
188 if (net->net_data_len)
189 version = net->net_data_version;
190
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)));
197
198 if (!pex_msg_update_request_init(net->config.pubkey, net->config.key,
199 net->config.auth_key, &host->endpoint,
200 version, true))
201 return;
202
203 __pex_msg_send(-1, &host->endpoint, NULL, 0);
204
205 if (!net->net_config.local_host)
206 return;
207
208 pex_msg_init_ext(net, PEX_MSG_ENDPOINT_NOTIFY, true);
209
210 memcpy(&dest_ep, &host->endpoint, sizeof(dest_ep));
211
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;
215
216 if (data[3] == 0xff)
217 data[3] = 0xfe;
218 }
219 network_get_local_addr(&local_addr, &dest_ep);
220
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){
225 .ip_hl = 5,
226 .ip_v = 4,
227 .ip_ttl = 64,
228 .ip_p = IPPROTO_UDP,
229 .ip_src = local_addr.in,
230 .ip_dst = host->endpoint.in.sin_addr,
231 };
232 dest_ep.in.sin_addr = host->endpoint.in.sin_addr;
233 udp = &packet.ipv4.udp;
234 len = sizeof(packet.ipv4);
235 } else {
236 packet.ipv6.ip = (struct ip6_hdr){
237 .ip6_flow = htonl(6 << 28),
238 .ip6_hops = 128,
239 .ip6_nxt = IPPROTO_UDP,
240 .ip6_src = local_addr.in6,
241 .ip6_dst = host->endpoint.in6.sin6_addr,
242 };
243 dest_ep.in6.sin6_addr = host->endpoint.in6.sin6_addr;
244 udp = &packet.ipv6.udp;
245 len = sizeof(packet.ipv6);
246 }
247
248 udp->uh_sport = htons(net->net_config.local_host->peer.port);
249 udp->uh_dport = host->endpoint.in6.sin6_port;
250
251 if (__pex_msg_send(-1, &dest_ep, &packet, len) < 0)
252 D_NET(net, "pex_msg_send_raw failed: %s", strerror(errno));
253 }
254
255 static void
256 network_pex_request_update_cb(struct uloop_timeout *t)
257 {
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;
261
262 uloop_timeout_set(t, 5000);
263
264 retry:
265 if (list_empty(&pex->hosts))
266 return;
267
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);
271 free(host);
272 goto retry;
273 }
274
275 list_move_tail(&host->list, &pex->hosts);
276 network_pex_host_request_update(net, host);
277 }
278
279 void network_pex_init(struct network *net)
280 {
281 struct network_pex *pex = &net->pex;
282
283 memset(pex, 0, sizeof(*pex));
284 pex->fd.fd = -1;
285 INIT_LIST_HEAD(&pex->hosts);
286 pex->request_update_timer.cb = network_pex_request_update_cb;
287 }
288
289 static void
290 network_pex_query_hosts(struct network *net)
291 {
292 struct network_host *host;
293 int rv = rand();
294 int hosts = 0;
295 int i;
296
297 pex_msg_init(net, PEX_MSG_QUERY);
298
299 avl_for_each_element(&net->hosts, host, node) {
300 struct network_peer *peer = &host->peer;
301 void *id;
302
303 if (host == net->net_config.local_host ||
304 peer->state.connected ||
305 peer->endpoint)
306 continue;
307
308 id = pex_msg_append(PEX_ID_LEN);
309 if (!id)
310 break;
311
312 memcpy(id, peer->key, PEX_ID_LEN);
313 hosts++;
314 }
315
316 if (!hosts)
317 return;
318
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;
323
324 if (rv > 0) {
325 rv--;
326 continue;
327 }
328
329 if (host == net->net_config.local_host)
330 continue;
331
332 if (!peer->state.connected)
333 continue;
334
335 D_PEER(net, peer, "send query for %d hosts", hosts);
336 pex_msg_send(net, peer);
337 return;
338 }
339 }
340
341 }
342
343 static void
344 network_pex_send_ping(struct network *net, struct network_peer *peer)
345 {
346 if (peer->state.pinged || !peer->state.endpoint.sa.sa_family)
347 return;
348
349 pex_msg_init(net, PEX_MSG_PING);
350 pex_msg_send(net, peer);
351 peer->state.pinged = true;
352 }
353
354 static void
355 network_pex_send_update_request(struct network *net, struct network_peer *peer,
356 struct sockaddr_in6 *addr)
357 {
358 union network_endpoint ep = {};
359 uint64_t version = 0;
360
361 if (addr)
362 memcpy(&ep.in6, addr, sizeof(ep.in6));
363 else
364 pex_get_peer_addr(&ep.in6, net, peer);
365
366 if (net->net_data_len)
367 version = net->net_data_version;
368
369 if (!pex_msg_update_request_init(net->config.pubkey, net->config.key,
370 net->config.auth_key, &ep,
371 version, !!addr))
372 return;
373
374 pex_msg_send_ext(net, peer, addr);
375 }
376
377 void network_pex_event(struct network *net, struct network_peer *peer,
378 enum pex_event ev)
379 {
380 if (!network_pex_active(&net->pex))
381 return;
382
383 switch (ev) {
384 case PEX_EV_HANDSHAKE:
385 pex_send_hello(net, peer);
386 if (net->config.type == NETWORK_TYPE_DYNAMIC)
387 network_pex_send_update_request(net, peer, NULL);
388 break;
389 case PEX_EV_ENDPOINT_CHANGE:
390 network_pex_handle_endpoint_change(net, peer);
391 break;
392 case PEX_EV_QUERY:
393 network_pex_query_hosts(net);
394 break;
395 case PEX_EV_PING:
396 network_pex_send_ping(net, peer);
397 break;
398 }
399 }
400
401 static void
402 network_pex_recv_hello(struct network *net, struct network_peer *peer,
403 const struct pex_hello *data, size_t len)
404 {
405 char addrstr[INET6_ADDRSTRLEN];
406 uint16_t flags;
407 int af;
408
409 if (len < sizeof(*data))
410 return;
411
412 if (peer->state.has_local_ep_addr &&
413 !memcmp(&peer->state.local_ep_addr, data->local_addr, sizeof(data->local_addr)))
414 return;
415
416 flags = ntohs(data->flags);
417 af = (flags & PEER_EP_F_IPV6) ? AF_INET6 : AF_INET;
418 D_PEER(net, peer, "set local endpoint address to %s",
419 inet_ntop(af, data->local_addr, addrstr, sizeof(addrstr)));
420 peer->state.has_local_ep_addr = true;
421 memcpy(&peer->state.local_ep_addr, data->local_addr, sizeof(data->local_addr));
422 }
423
424 static void
425 network_pex_recv_peers(struct network *net, struct network_peer *peer,
426 const struct pex_peer_endpoint *data, size_t len)
427 {
428 struct network_peer *local = &net->net_config.local_host->peer;
429 struct network_peer *cur;
430
431 for (; len >= sizeof(*data); len -= sizeof(*data), data++) {
432 union network_endpoint *ep;
433 uint16_t flags;
434 void *addr;
435 int len;
436
437 cur = pex_msg_peer(net, data->peer_id);
438 if (!cur)
439 continue;
440
441 if (cur == peer || cur == local)
442 continue;
443
444 D_PEER(net, peer, "received peer address for %s",
445 network_peer_name(cur));
446 flags = ntohs(data->flags);
447 ep = &cur->state.next_endpoint;
448 ep->sa.sa_family = (flags & PEER_EP_F_IPV6) ? AF_INET6 : AF_INET;
449 addr = network_endpoint_addr(ep, &len);
450 memcpy(addr, data->addr, len);
451 ep->in.sin_port = data->port;
452 }
453 }
454
455 static void
456 network_pex_recv_query(struct network *net, struct network_peer *peer,
457 const uint8_t *data, size_t len)
458 {
459 struct network_peer *cur;
460 int resp = 0;
461
462 pex_msg_init(net, PEX_MSG_NOTIFY_PEERS);
463 for (; len >= 8; data += 8, len -= 8) {
464 cur = pex_msg_peer(net, data);
465 if (!cur || !cur->state.connected)
466 continue;
467
468 if (!pex_msg_add_peer_endpoint(net, cur, peer))
469 resp++;
470 }
471
472 if (!resp)
473 return;
474
475 D_PEER(net, peer, "send query response with %d hosts", resp);
476 pex_msg_send(net, peer);
477 }
478
479 static void
480 network_pex_recv_ping(struct network *net, struct network_peer *peer)
481 {
482 time_t now = time(NULL);
483
484 if (peer->state.last_request == now)
485 return;
486
487 peer->state.last_request = now;
488 pex_msg_init(net, PEX_MSG_PONG);
489 pex_msg_send(net, peer);
490 }
491
492 static void
493 network_pex_recv_update_request(struct network *net, struct network_peer *peer,
494 const uint8_t *data, size_t len,
495 struct sockaddr_in6 *addr)
496 {
497 struct pex_update_request *req = (struct pex_update_request *)data;
498 struct pex_msg_update_send_ctx ctx = {};
499 uint64_t req_version = be64_to_cpu(req->cur_version);
500 int *query_count;
501 bool done = false;
502
503 if (len < sizeof(struct pex_update_request))
504 return;
505
506 if (net->config.type != NETWORK_TYPE_DYNAMIC)
507 return;
508
509 if (peer)
510 query_count = &peer->state.num_net_queries;
511 else
512 query_count = &net->num_net_queries;
513
514 if (++*query_count > 10)
515 return;
516
517 D("receive update request, local version=%"PRIu64", remote version=%"PRIu64, net->net_data_version, req_version);
518
519 if (req_version >= net->net_data_version) {
520 struct pex_update_response_no_data *res;
521
522 pex_msg_init_ext(net, PEX_MSG_UPDATE_RESPONSE_NO_DATA, !!addr);
523 res = pex_msg_append(sizeof(*res));
524 res->req_id = req->req_id;
525 res->cur_version = cpu_to_be64(net->net_data_version);
526 pex_msg_send_ext(net, peer, addr);
527 }
528
529 if (req_version > net->net_data_version)
530 network_pex_send_update_request(net, peer, addr);
531
532 if (!peer || !net->net_data_len)
533 return;
534
535 if (req_version >= net->net_data_version)
536 return;
537
538 pex_msg_update_response_init(&ctx, net->config.pubkey, net->config.auth_key,
539 peer->key, !!addr, (void *)data,
540 net->net_data, net->net_data_len);
541 while (!done) {
542 pex_msg_send_ext(net, peer, addr);
543 done = !pex_msg_update_response_continue(&ctx);
544 }
545 }
546
547 static void
548 network_pex_recv_update_response(struct network *net, const uint8_t *data, size_t len,
549 struct sockaddr_in6 *addr, enum pex_opcode op)
550 {
551 struct network_peer *peer;
552 void *net_data;
553 int net_data_len = 0;
554 uint64_t version = 0;
555 bool no_prev_data = !net->net_data_len;
556
557 if (net->config.type != NETWORK_TYPE_DYNAMIC)
558 return;
559
560 net_data = pex_msg_update_response_recv(data, len, op, &net_data_len, &version);
561 if (!net_data)
562 return;
563
564 if (version <= net->net_data_version) {
565 free(net_data);
566 return;
567 }
568
569 D_NET(net, "received updated network data, len=%d", net_data_len);
570 free(net->net_data);
571
572 net->net_data = net_data;
573 net->net_data_len = net_data_len;
574 net->net_data_version = version;
575 if (network_save_dynamic(net) < 0)
576 return;
577
578 uloop_timeout_set(&net->reload_timer, no_prev_data ? 1 : UNETD_DATA_UPDATE_DELAY);
579 vlist_for_each_element(&net->peers, peer, node) {
580 if (!peer->state.connected || !peer->pex_port)
581 continue;
582 network_pex_send_update_request(net, peer, NULL);
583 }
584 }
585
586 static void
587 network_pex_recv(struct network *net, struct network_peer *peer, struct pex_hdr *hdr)
588 {
589 const void *data = hdr + 1;
590
591 if (hdr->version != 0)
592 return;
593
594 D_PEER(net, peer, "PEX rx op=%d", hdr->opcode);
595 switch (hdr->opcode) {
596 case PEX_MSG_HELLO:
597 network_pex_recv_hello(net, peer, data, hdr->len);
598 break;
599 case PEX_MSG_NOTIFY_PEERS:
600 network_pex_recv_peers(net, peer, data, hdr->len);
601 break;
602 case PEX_MSG_QUERY:
603 network_pex_recv_query(net, peer, data, hdr->len);
604 break;
605 case PEX_MSG_PING:
606 network_pex_recv_ping(net, peer);
607 break;
608 case PEX_MSG_PONG:
609 break;
610 case PEX_MSG_UPDATE_REQUEST:
611 network_pex_recv_update_request(net, peer, data, hdr->len,
612 NULL);
613 break;
614 case PEX_MSG_UPDATE_RESPONSE:
615 case PEX_MSG_UPDATE_RESPONSE_DATA:
616 case PEX_MSG_UPDATE_RESPONSE_NO_DATA:
617 network_pex_recv_update_response(net, data, hdr->len,
618 NULL, hdr->opcode);
619 break;
620 case PEX_MSG_ENDPOINT_NOTIFY:
621 break;
622 }
623 }
624
625 static void
626 network_pex_fd_cb(struct uloop_fd *fd, unsigned int events)
627 {
628 struct network *net = container_of(fd, struct network, pex.fd);
629 struct network_peer *local = &net->net_config.local_host->peer;
630 struct network_peer *peer;
631 struct sockaddr_in6 sin6;
632 static char buf[PEX_BUF_SIZE];
633 struct pex_hdr *hdr = (struct pex_hdr *)buf;
634 ssize_t len;
635
636 while (1) {
637 socklen_t slen = sizeof(sin6);
638
639 len = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6, &slen);
640 if (len < 0) {
641 if (errno == EINTR)
642 continue;
643
644 if (errno == EAGAIN)
645 break;
646
647 D_NET(net, "recvfrom failed: %s", strerror(errno));
648 network_pex_close(net);
649 return;
650 }
651
652 if (!len)
653 continue;
654
655 if (len < sizeof(*hdr))
656 continue;
657
658 hdr->len = ntohs(hdr->len);
659 if (len - sizeof(hdr) < hdr->len)
660 continue;
661
662 peer = pex_msg_peer(net, hdr->id);
663 if (!peer)
664 continue;
665
666 if (memcmp(&sin6.sin6_addr, &peer->local_addr.in6, sizeof(sin6.sin6_addr)) != 0)
667 continue;
668
669 if (peer == local)
670 continue;
671
672 network_pex_recv(net, peer, hdr);
673 }
674 }
675
676 void network_pex_create_host(struct network *net, union network_endpoint *ep,
677 unsigned int timeout)
678 {
679 struct network_pex *pex = &net->pex;
680 struct network_pex_host *host;
681 bool new_host = false;
682
683 list_for_each_entry(host, &pex->hosts, list) {
684 if (memcmp(&host->endpoint, ep, sizeof(host->endpoint)) != 0)
685 continue;
686
687 list_move_tail(&host->list, &pex->hosts);
688 goto out;
689 }
690
691 host = calloc(1, sizeof(*host));
692 new_host = true;
693 memcpy(&host->endpoint, ep, sizeof(host->endpoint));
694 list_add_tail(&host->list, &pex->hosts);
695
696 out:
697 if (timeout && (new_host || host->timeout))
698 host->timeout = timeout + unet_gettime();
699 network_pex_host_request_update(net, host);
700 }
701
702 static void
703 network_pex_open_auth_connect(struct network *net)
704 {
705 struct network_pex *pex = &net->pex;
706 struct network_peer *peer;
707 struct blob_attr *cur;
708 int rem;
709
710 if (net->config.type != NETWORK_TYPE_DYNAMIC)
711 return;
712
713 uloop_timeout_set(&pex->request_update_timer, 5000);
714
715 vlist_for_each_element(&net->peers, peer, node) {
716 union network_endpoint ep = {};
717
718 if (!peer->endpoint || peer->dynamic)
719 continue;
720
721 if (network_get_endpoint(&ep, peer->endpoint,
722 UNETD_GLOBAL_PEX_PORT, 0) < 0)
723 continue;
724
725 ep.in.sin_port = htons(UNETD_GLOBAL_PEX_PORT);
726 network_pex_create_host(net, &ep, 0);
727 }
728
729 if (!net->config.auth_connect)
730 return;
731
732 blobmsg_for_each_attr(cur, net->config.auth_connect, rem) {
733 union network_endpoint ep = {};
734
735 if (network_get_endpoint(&ep, blobmsg_get_string(cur),
736 UNETD_GLOBAL_PEX_PORT, 0) < 0)
737 continue;
738
739 network_pex_create_host(net, &ep, 0);
740 }
741 }
742
743
744 int network_pex_open(struct network *net)
745 {
746 struct network_host *local_host = net->net_config.local_host;
747 struct network_peer *local;
748 struct network_pex *pex = &net->pex;
749 struct sockaddr_in6 sin6 = {};
750 int yes = 1;
751 int fd;
752
753 network_pex_open_auth_connect(net);
754
755 if (!local_host || !local_host->peer.pex_port)
756 return 0;
757
758 local = &local_host->peer;
759 fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
760 if (fd < 0)
761 return -1;
762
763 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
764 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
765
766 sin6.sin6_family = AF_INET6;
767 memcpy(&sin6.sin6_addr, &local->local_addr.in6,
768 sizeof(local->local_addr.in6));
769 sin6.sin6_port = htons(local_host->peer.pex_port);
770
771 if (bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
772 perror("bind");
773 goto close;
774 }
775
776 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
777 setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
778 #ifdef linux
779 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
780 network_name(net), strlen(network_name(net)));
781 #endif
782
783 pex->fd.fd = fd;
784 pex->fd.cb = network_pex_fd_cb;
785 uloop_fd_add(&pex->fd, ULOOP_READ);
786
787 return 0;
788
789 close:
790 close(fd);
791 return -1;
792 }
793
794 void network_pex_close(struct network *net)
795 {
796 struct network_pex *pex = &net->pex;
797 struct network_pex_host *host, *tmp;
798 uint64_t now = unet_gettime();
799
800 uloop_timeout_cancel(&pex->request_update_timer);
801 list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
802 if (host->timeout)
803 continue;
804
805 if (host->last_active + UNETD_PEX_HOST_ACITVE_TIMEOUT >= now)
806 continue;
807
808 list_del(&host->list);
809 free(host);
810 }
811
812 if (pex->fd.fd < 0)
813 return;
814
815 uloop_fd_delete(&pex->fd);
816 close(pex->fd.fd);
817 network_pex_init(net);
818 }
819
820 void network_pex_free(struct network *net)
821 {
822 struct network_pex *pex = &net->pex;
823 struct network_pex_host *host, *tmp;
824
825 list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
826 list_del(&host->list);
827 free(host);
828 }
829 }
830
831 static struct network *
832 global_pex_find_network(const uint8_t *id)
833 {
834 struct network *net;
835
836 avl_for_each_element(&networks, net, node) {
837 if (!memcmp(id, net->config.auth_key, PEX_ID_LEN))
838 return net;
839 }
840
841 return NULL;
842 }
843
844 static void
845 global_pex_set_active(struct network *net, struct sockaddr_in6 *addr)
846 {
847 struct network_pex *pex = &net->pex;
848 struct network_pex_host *host;
849
850 list_for_each_entry(host, &pex->hosts, list) {
851 if (memcmp(&host->endpoint.in6, addr, sizeof(*addr)) != 0)
852 continue;
853
854 host->last_active = unet_gettime();
855 }
856 }
857
858 static void
859 global_pex_recv(struct pex_hdr *hdr, struct sockaddr_in6 *addr)
860 {
861 struct pex_ext_hdr *ehdr = (void *)(hdr + 1);
862 struct network_peer *peer;
863 struct network *net;
864 void *data = (void *)(ehdr + 1);
865 char buf[INET6_ADDRSTRLEN];
866 int addr_len;
867
868 if (hdr->version != 0)
869 return;
870
871 net = global_pex_find_network(ehdr->auth_id);
872 if (!net || net->config.type != NETWORK_TYPE_DYNAMIC)
873 return;
874
875 *(uint64_t *)hdr->id ^= pex_network_hash(net->config.auth_key, ehdr->nonce);
876
877 global_pex_set_active(net, addr);
878
879 D("PEX global rx op=%d", hdr->opcode);
880 switch (hdr->opcode) {
881 case PEX_MSG_HELLO:
882 case PEX_MSG_NOTIFY_PEERS:
883 case PEX_MSG_QUERY:
884 case PEX_MSG_PING:
885 case PEX_MSG_PONG:
886 break;
887 case PEX_MSG_UPDATE_REQUEST:
888 peer = pex_msg_peer(net, hdr->id);
889 network_pex_recv_update_request(net, peer, data, hdr->len,
890 addr);
891 break;
892 case PEX_MSG_UPDATE_RESPONSE:
893 case PEX_MSG_UPDATE_RESPONSE_DATA:
894 case PEX_MSG_UPDATE_RESPONSE_NO_DATA:
895 network_pex_recv_update_response(net, data, hdr->len, addr, hdr->opcode);
896 break;
897 case PEX_MSG_ENDPOINT_NOTIFY:
898 peer = pex_msg_peer(net, hdr->id);
899 if (!peer)
900 break;
901
902 D_PEER(net, peer, "receive endpoint notification from %s",
903 inet_ntop(addr->sin6_family, network_endpoint_addr((void *)addr, &addr_len),
904 buf, sizeof(buf)));
905
906 memcpy(&peer->state.next_endpoint, addr, sizeof(*addr));
907 break;
908 }
909 }
910
911 static void
912 pex_recv_control(struct pex_msg_local_control *msg, int len)
913 {
914 struct network *net;
915
916 if (msg->msg_type != 0)
917 return;
918
919 net = global_pex_find_network(msg->auth_id);
920 if (!net)
921 return;
922
923 if (!msg->timeout)
924 msg->timeout = 60;
925 network_pex_create_host(net, &msg->ep, msg->timeout);
926 }
927
928 int global_pex_open(const char *unix_path)
929 {
930 struct sockaddr_in6 sin6 = {};
931 int ret;
932
933 sin6.sin6_family = AF_INET6;
934 sin6.sin6_port = htons(global_pex_port);
935
936 ret = pex_open(&sin6, sizeof(sin6), global_pex_recv, true);
937
938 if (unix_path)
939 pex_unix_open(unix_path, pex_recv_control);
940
941 return ret;
942 }