diff options
author | Christian Grothoff <grothoff@gnunet.org> | 2021-07-06 23:16:53 +0200 |
---|---|---|
committer | Christian Grothoff <grothoff@gnunet.org> | 2021-07-06 23:16:53 +0200 |
commit | d0d24c62f4b4a1872c8b52ad902b11aa4962d2c2 (patch) | |
tree | 3c7b51b2d16d9478d9c2efbbeaf04bb18f3d41b7 /src/dhtu/plugin_dhtu_ip.c | |
parent | 7d384a118326f5ce8237281c5b5ffa36c32662fe (diff) | |
download | gnunet-d0d24c62f4b4a1872c8b52ad902b11aa4962d2c2.tar.gz gnunet-d0d24c62f4b4a1872c8b52ad902b11aa4962d2c2.zip |
-rudimentary untested IP DHTU plugin
Diffstat (limited to 'src/dhtu/plugin_dhtu_ip.c')
-rw-r--r-- | src/dhtu/plugin_dhtu_ip.c | 366 |
1 files changed, 268 insertions, 98 deletions
diff --git a/src/dhtu/plugin_dhtu_ip.c b/src/dhtu/plugin_dhtu_ip.c index 19fe19192..a0da9d680 100644 --- a/src/dhtu/plugin_dhtu_ip.c +++ b/src/dhtu/plugin_dhtu_ip.c | |||
@@ -23,6 +23,11 @@ | |||
23 | * | 23 | * |
24 | * @file plugin_dhtu_ip.c | 24 | * @file plugin_dhtu_ip.c |
25 | * @brief plain IP based DHT network underlay | 25 | * @brief plain IP based DHT network underlay |
26 | * | ||
27 | * TODO: | ||
28 | * - call NSE callback | ||
29 | * - expire destination addresses | ||
30 | * - faster lookup of destinations | ||
26 | */ | 31 | */ |
27 | #include "platform.h" | 32 | #include "platform.h" |
28 | #include "gnunet_dhtu_plugin.h" | 33 | #include "gnunet_dhtu_plugin.h" |
@@ -85,11 +90,26 @@ struct GNUNET_DHTU_Source | |||
85 | */ | 90 | */ |
86 | struct GNUNET_DHTU_Target | 91 | struct GNUNET_DHTU_Target |
87 | { | 92 | { |
93 | // FIXME: add mechanism for targets to expire | ||
94 | /** | ||
95 | * Kept in a DLL. | ||
96 | */ | ||
97 | struct GNUNET_DHTU_Target *next; | ||
98 | |||
99 | /** | ||
100 | * Kept in a DLL. | ||
101 | */ | ||
102 | struct GNUNET_DHTU_Target *prev; | ||
88 | 103 | ||
89 | /** | 104 | /** |
90 | * Application context for this target. | 105 | * Application context for this target. |
91 | */ | 106 | */ |
92 | void *app_ctx; | 107 | void *app_ctx; |
108 | |||
109 | /** | ||
110 | * Hash of the IP address. | ||
111 | */ | ||
112 | struct GNUNET_DHTU_Hash id; | ||
93 | 113 | ||
94 | /** | 114 | /** |
95 | * Head of preferences expressed for this target. | 115 | * Head of preferences expressed for this target. |
@@ -162,6 +182,16 @@ struct Plugin | |||
162 | struct GNUNET_DHTU_Source *src_tail; | 182 | struct GNUNET_DHTU_Source *src_tail; |
163 | 183 | ||
164 | /** | 184 | /** |
185 | * Head of destinations that are active. | ||
186 | */ | ||
187 | struct GNUNET_DHTU_Target *dst_head; | ||
188 | |||
189 | /** | ||
190 | * Tail of destinations that are active. | ||
191 | */ | ||
192 | struct GNUNET_DHTU_Target *dst_tail; | ||
193 | |||
194 | /** | ||
165 | * Task that scans for IP address changes. | 195 | * Task that scans for IP address changes. |
166 | */ | 196 | */ |
167 | struct GNUNET_SCHEDULER_Task *scan_task; | 197 | struct GNUNET_SCHEDULER_Task *scan_task; |
@@ -231,6 +261,99 @@ ip_verify (void *cls, | |||
231 | 261 | ||
232 | 262 | ||
233 | /** | 263 | /** |
264 | * Create a target to which we may send traffic. | ||
265 | * | ||
266 | * @param plugin our plugin | ||
267 | * @param addr target address | ||
268 | * @param addrlen number of bytes in @a addr | ||
269 | * @return new target object | ||
270 | */ | ||
271 | static struct GNUNET_DHTU_Target * | ||
272 | create_target (struct Plugin *plugin, | ||
273 | const struct sockaddr *addr, | ||
274 | socklen_t addrlen) | ||
275 | { | ||
276 | static struct GNUNET_DHTU_PublicKey pk; | ||
277 | struct GNUNET_DHTU_Target *dst; | ||
278 | |||
279 | pk.size = htons (sizeof (pk)); | ||
280 | dst = GNUNET_new (struct GNUNET_DHTU_Target); | ||
281 | dst->addrlen = addrlen; | ||
282 | memcpy (&dst->addr, | ||
283 | addr, | ||
284 | addrlen); | ||
285 | switch (addr->sa_family) | ||
286 | { | ||
287 | case AF_INET: | ||
288 | { | ||
289 | const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr; | ||
290 | |||
291 | GNUNET_assert (sizeof (struct sockaddr_in) == addrlen); | ||
292 | GNUNET_CRYPTO_hash (&s4->sin_addr, | ||
293 | sizeof (struct in_addr), | ||
294 | &dst->id.hc); | ||
295 | } | ||
296 | break; | ||
297 | case AF_INET6: | ||
298 | { | ||
299 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr; | ||
300 | |||
301 | GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen); | ||
302 | GNUNET_CRYPTO_hash (&s6->sin6_addr, | ||
303 | sizeof (struct in6_addr), | ||
304 | &dst->id.hc); | ||
305 | } | ||
306 | break; | ||
307 | default: | ||
308 | GNUNET_break (0); | ||
309 | GNUNET_free (dst); | ||
310 | return NULL; | ||
311 | } | ||
312 | GNUNET_CONTAINER_DLL_insert (plugin->dst_head, | ||
313 | plugin->dst_tail, | ||
314 | dst); | ||
315 | plugin->env->connect_cb (plugin->env->cls, | ||
316 | &pk, | ||
317 | &dst->id, | ||
318 | dst, | ||
319 | &dst->app_ctx); | ||
320 | return dst; | ||
321 | } | ||
322 | |||
323 | |||
324 | /** | ||
325 | * Find target matching @a addr. If none exists, | ||
326 | * create one! | ||
327 | * | ||
328 | * @param plugin the plugin handle | ||
329 | * @param src source target is from, or NULL if unknown | ||
330 | * @param addr socket address to find | ||
331 | * @param addrlen number of bytes in @a addr | ||
332 | * @return matching target object | ||
333 | */ | ||
334 | static struct GNUNET_DHTU_Target * | ||
335 | find_target (struct Plugin *plugin, | ||
336 | const void *addr, | ||
337 | size_t addrlen) | ||
338 | { | ||
339 | // FIXME-OPTIMIZE: use hash map instead of linear search | ||
340 | for (struct GNUNET_DHTU_Target *dst = plugin->dst_head; | ||
341 | NULL != dst; | ||
342 | dst = dst->next) | ||
343 | { | ||
344 | if ( (addrlen == dst->addrlen) && | ||
345 | (0 == memcmp (addr, | ||
346 | &dst->addr, | ||
347 | addrlen)) ) | ||
348 | return dst; | ||
349 | } | ||
350 | return create_target (plugin, | ||
351 | (const struct sockaddr *) addr, | ||
352 | addrlen); | ||
353 | } | ||
354 | |||
355 | |||
356 | /** | ||
234 | * Request creation of a session with a peer at the given @a address. | 357 | * Request creation of a session with a peer at the given @a address. |
235 | * | 358 | * |
236 | * @param cls closure (internal context for the plugin) | 359 | * @param cls closure (internal context for the plugin) |
@@ -289,9 +412,9 @@ ip_try_connect (void *cls, | |||
289 | return; | 412 | return; |
290 | } | 413 | } |
291 | GNUNET_free (addr); | 414 | GNUNET_free (addr); |
292 | (void) result->ai_addr; // FIXME: use! | 415 | (void) find_target (plugin, |
293 | 416 | result->ai_addr, | |
294 | // FIXME: create target, etc. | 417 | result->ai_addrlen); |
295 | freeaddrinfo (result); | 418 | freeaddrinfo (result); |
296 | } | 419 | } |
297 | 420 | ||
@@ -533,7 +656,7 @@ scan (void *cls) | |||
533 | * create one! | 656 | * create one! |
534 | * | 657 | * |
535 | * @param plugin the plugin handle | 658 | * @param plugin the plugin handle |
536 | * @param addr IP address to find | 659 | * @param addr socket address to find |
537 | * @param addrlen number of bytes in @a addr | 660 | * @param addrlen number of bytes in @a addr |
538 | * @return matching source object | 661 | * @return matching source object |
539 | */ | 662 | */ |
@@ -546,61 +669,16 @@ find_source (struct Plugin *plugin, | |||
546 | NULL != src; | 669 | NULL != src; |
547 | src = src->next) | 670 | src = src->next) |
548 | { | 671 | { |
549 | if ( (addrlen == sizeof (struct in_addr)) && | 672 | if ( (addrlen == src->addrlen) && |
550 | (src->addrlen == sizeof (struct sockaddr_in)) ) | 673 | (0 == memcmp (addr, |
551 | { | 674 | &src->addr, |
552 | const struct sockaddr_in *sa = | 675 | addrlen)) ) |
553 | (const struct sockaddr_in *) &src->addr; | ||
554 | if (0 == memcmp (addr, | ||
555 | &sa->sin_addr, | ||
556 | addrlen)) | ||
557 | return src; | ||
558 | } | ||
559 | if ( (addrlen == sizeof (struct in6_addr)) && | ||
560 | (src->addrlen == sizeof (struct sockaddr_in6)) ) | ||
561 | { | ||
562 | const struct sockaddr_in6 *sa = | ||
563 | (const struct sockaddr_in6 *) &src->addr; | ||
564 | if (0 == memcmp (addr, | ||
565 | &sa->sin6_addr, | ||
566 | addrlen)) | ||
567 | return src; | 676 | return src; |
568 | } | ||
569 | } | 677 | } |
570 | 678 | ||
571 | { | 679 | return create_source (plugin, |
572 | struct sockaddr_storage sa; | 680 | (const struct sockaddr *) addr, |
573 | socklen_t salen; | 681 | addrlen); |
574 | |||
575 | memset (&sa, | ||
576 | 0, | ||
577 | sizeof (sa)); | ||
578 | if (addrlen == sizeof (struct in_addr)) | ||
579 | { | ||
580 | struct sockaddr_in *s4 = | ||
581 | (struct sockaddr_in *) &sa; | ||
582 | |||
583 | s4->sin_family = AF_INET; | ||
584 | memcpy (&s4->sin_addr, | ||
585 | addr, | ||
586 | addrlen); | ||
587 | salen = sizeof (*s4); | ||
588 | } | ||
589 | if (addrlen == sizeof (struct in6_addr)) | ||
590 | { | ||
591 | struct sockaddr_in6 *s6 = | ||
592 | (struct sockaddr_in6 *) &sa; | ||
593 | |||
594 | s6->sin6_family = AF_INET6; | ||
595 | memcpy (&s6->sin6_addr, | ||
596 | addr, | ||
597 | addrlen); | ||
598 | salen = sizeof (*s6); | ||
599 | } | ||
600 | return create_source (plugin, | ||
601 | (const struct sockaddr *) &sa, | ||
602 | salen); | ||
603 | } | ||
604 | } | 682 | } |
605 | 683 | ||
606 | 684 | ||
@@ -620,7 +698,7 @@ read_cb (void *cls) | |||
620 | .iov_base = buf, | 698 | .iov_base = buf, |
621 | .iov_len = sizeof (buf) | 699 | .iov_len = sizeof (buf) |
622 | }; | 700 | }; |
623 | char ctl[1024]; | 701 | char ctl[128]; |
624 | struct msghdr mh = { | 702 | struct msghdr mh = { |
625 | .msg_name = &sa, | 703 | .msg_name = &sa, |
626 | .msg_namelen = sizeof (sa), | 704 | .msg_namelen = sizeof (sa), |
@@ -629,7 +707,7 @@ read_cb (void *cls) | |||
629 | .msg_control = ctl, | 707 | .msg_control = ctl, |
630 | .msg_controllen = sizeof (ctl) | 708 | .msg_controllen = sizeof (ctl) |
631 | }; | 709 | }; |
632 | 710 | ||
633 | ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock), | 711 | ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock), |
634 | &mh, | 712 | &mh, |
635 | MSG_DONTWAIT); | 713 | MSG_DONTWAIT); |
@@ -638,54 +716,70 @@ read_cb (void *cls) | |||
638 | struct GNUNET_DHTU_Target *dst = NULL; | 716 | struct GNUNET_DHTU_Target *dst = NULL; |
639 | struct GNUNET_DHTU_Source *src = NULL; | 717 | struct GNUNET_DHTU_Source *src = NULL; |
640 | struct cmsghdr *cmsg; | 718 | struct cmsghdr *cmsg; |
641 | struct msghdr *msh = mh.msg_control; | ||
642 | 719 | ||
643 | /* find IP where we received message */ | 720 | /* find IP where we received message */ |
644 | for (cmsg = CMSG_FIRSTHDR (msh); | 721 | for (cmsg = CMSG_FIRSTHDR (&mh); |
645 | NULL != cmsg; | 722 | NULL != cmsg; |
646 | cmsg = CMSG_NXTHDR (msh, | 723 | cmsg = CMSG_NXTHDR (&mh, |
647 | cmsg)) | 724 | cmsg)) |
648 | { | 725 | { |
649 | if ( (cmsg->cmsg_level == IPPROTO_IP) && | 726 | if ( (cmsg->cmsg_level == IPPROTO_IP) && |
650 | (cmsg->cmsg_type == IP_ORIGDSTADDR) ) | 727 | (cmsg->cmsg_type == IP_PKTINFO) ) |
651 | { | 728 | { |
652 | if (CMSG_LEN (sizeof (struct in_addr)) == | 729 | if (CMSG_LEN (sizeof (struct in_pktinfo)) == |
653 | cmsg->cmsg_len) | 730 | cmsg->cmsg_len) |
654 | { | 731 | { |
655 | struct in6_addr ia; | 732 | struct in_pktinfo pi; |
656 | 733 | ||
657 | memcpy (&ia, | 734 | memcpy (&pi, |
658 | CMSG_DATA (cmsg), | 735 | CMSG_DATA (cmsg), |
659 | sizeof (ia)); | 736 | sizeof (pi)); |
660 | src = find_source (plugin, | 737 | { |
661 | &ia, | 738 | struct sockaddr_in sa = { |
662 | sizeof (ia)); | 739 | .sin_family = AF_INET, |
740 | .sin_addr = pi.ipi_addr | ||
741 | }; | ||
742 | |||
743 | src = find_source (plugin, | ||
744 | &sa, | ||
745 | sizeof (sa)); | ||
746 | } | ||
663 | break; | 747 | break; |
664 | } | 748 | } |
665 | else | 749 | else |
666 | GNUNET_break (0); | 750 | GNUNET_break (0); |
667 | } | 751 | } |
668 | if ( (cmsg->cmsg_level == IPPROTO_IPV6) && | 752 | if ( (cmsg->cmsg_level == IPPROTO_IPV6) && |
669 | (cmsg->cmsg_type == IP_ORIGDSTADDR) ) | 753 | (cmsg->cmsg_type == IPV6_RECVPKTINFO) ) |
670 | { | 754 | { |
671 | if (CMSG_LEN (sizeof (struct in6_addr)) == | 755 | if (CMSG_LEN (sizeof (struct in6_pktinfo)) == |
672 | cmsg->cmsg_len) | 756 | cmsg->cmsg_len) |
673 | { | 757 | { |
674 | struct in6_addr ia; | 758 | struct in6_pktinfo pi; |
675 | 759 | ||
676 | memcpy (&ia, | 760 | memcpy (&pi, |
677 | CMSG_DATA (cmsg), | 761 | CMSG_DATA (cmsg), |
678 | sizeof (ia)); | 762 | sizeof (pi)); |
679 | src = find_source (plugin, | 763 | { |
680 | &ia, | 764 | struct sockaddr_in6 sa = { |
681 | sizeof (ia)); | 765 | .sin6_family = AF_INET6, |
682 | break; | 766 | .sin6_addr = pi.ipi6_addr, |
767 | .sin6_scope_id = pi.ipi6_ifindex | ||
768 | }; | ||
769 | |||
770 | src = find_source (plugin, | ||
771 | &sa, | ||
772 | sizeof (sa)); | ||
773 | break; | ||
774 | } | ||
683 | } | 775 | } |
684 | else | 776 | else |
685 | GNUNET_break (0); | 777 | GNUNET_break (0); |
686 | } | 778 | } |
687 | } | 779 | } |
688 | // FIXME: find or create 'dst'! | 780 | dst = find_target (plugin, |
781 | &sa, | ||
782 | mh.msg_namelen); | ||
689 | if ( (NULL == src) || | 783 | if ( (NULL == src) || |
690 | (NULL == dst) ) | 784 | (NULL == dst) ) |
691 | { | 785 | { |
@@ -723,6 +817,7 @@ libgnunet_plugin_dhtu_ip_init (void *cls) | |||
723 | char *port; | 817 | char *port; |
724 | unsigned int nport; | 818 | unsigned int nport; |
725 | int sock; | 819 | int sock; |
820 | int af; | ||
726 | 821 | ||
727 | if (GNUNET_OK != | 822 | if (GNUNET_OK != |
728 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | 823 | GNUNET_CONFIGURATION_get_value_string (env->cfg, |
@@ -755,7 +850,8 @@ libgnunet_plugin_dhtu_ip_init (void *cls) | |||
755 | plugin = GNUNET_new (struct Plugin); | 850 | plugin = GNUNET_new (struct Plugin); |
756 | plugin->env = env; | 851 | plugin->env = env; |
757 | plugin->port = port; | 852 | plugin->port = port; |
758 | sock = socket (AF_INET6, | 853 | af = AF_INET6; |
854 | sock = socket (af, | ||
759 | SOCK_DGRAM, | 855 | SOCK_DGRAM, |
760 | IPPROTO_UDP); | 856 | IPPROTO_UDP); |
761 | if (-1 == sock) | 857 | if (-1 == sock) |
@@ -766,25 +862,79 @@ libgnunet_plugin_dhtu_ip_init (void *cls) | |||
766 | GNUNET_free (plugin); | 862 | GNUNET_free (plugin); |
767 | return NULL; | 863 | return NULL; |
768 | } | 864 | } |
769 | { | 865 | switch (af) { |
770 | struct sockaddr_in6 sa = { | 866 | case AF_INET: |
771 | .sin6_family = AF_INET6, | ||
772 | .sin6_port = htons ((uint16_t) nport) | ||
773 | }; | ||
774 | |||
775 | if (0 != | ||
776 | bind (sock, | ||
777 | &sa, | ||
778 | sizeof (sa))) | ||
779 | { | 867 | { |
780 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | 868 | int on = 1; |
781 | "socket"); | 869 | |
782 | GNUNET_break (0 == | 870 | if (0 != |
783 | close (sock)); | 871 | setsockopt (sock, |
784 | GNUNET_free (plugin->port); | 872 | IPPROTO_IP, |
785 | GNUNET_free (plugin); | 873 | IP_PKTINFO, |
786 | return NULL; | 874 | &on, |
875 | sizeof (on))) | ||
876 | { | ||
877 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
878 | "setsockopt"); | ||
879 | } | ||
880 | } | ||
881 | { | ||
882 | struct sockaddr_in sa = { | ||
883 | .sin_family = AF_INET, | ||
884 | .sin_port = htons ((uint16_t) nport) | ||
885 | }; | ||
886 | |||
887 | if (0 != | ||
888 | bind (sock, | ||
889 | &sa, | ||
890 | sizeof (sa))) | ||
891 | { | ||
892 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
893 | "socket"); | ||
894 | GNUNET_break (0 == | ||
895 | close (sock)); | ||
896 | GNUNET_free (plugin->port); | ||
897 | GNUNET_free (plugin); | ||
898 | return NULL; | ||
899 | } | ||
787 | } | 900 | } |
901 | break; | ||
902 | case AF_INET6: | ||
903 | { | ||
904 | int on = 1; | ||
905 | |||
906 | if (0 != | ||
907 | setsockopt (sock, | ||
908 | IPPROTO_IPV6, | ||
909 | IPV6_RECVPKTINFO, | ||
910 | &on, | ||
911 | sizeof (on))) | ||
912 | { | ||
913 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
914 | "setsockopt"); | ||
915 | } | ||
916 | } | ||
917 | { | ||
918 | struct sockaddr_in6 sa = { | ||
919 | .sin6_family = AF_INET6, | ||
920 | .sin6_port = htons ((uint16_t) nport) | ||
921 | }; | ||
922 | |||
923 | if (0 != | ||
924 | bind (sock, | ||
925 | &sa, | ||
926 | sizeof (sa))) | ||
927 | { | ||
928 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
929 | "socket"); | ||
930 | GNUNET_break (0 == | ||
931 | close (sock)); | ||
932 | GNUNET_free (plugin->port); | ||
933 | GNUNET_free (plugin); | ||
934 | return NULL; | ||
935 | } | ||
936 | } | ||
937 | break; | ||
788 | } | 938 | } |
789 | plugin->sock = GNUNET_NETWORK_socket_box_native (sock); | 939 | plugin->sock = GNUNET_NETWORK_socket_box_native (sock); |
790 | plugin->read_task = GNUNET_SCHEDULER_add_read_net ( | 940 | plugin->read_task = GNUNET_SCHEDULER_add_read_net ( |
@@ -818,6 +968,26 @@ libgnunet_plugin_dhtu_ip_done (void *cls) | |||
818 | { | 968 | { |
819 | struct GNUNET_DHTU_PluginFunctions *api = cls; | 969 | struct GNUNET_DHTU_PluginFunctions *api = cls; |
820 | struct Plugin *plugin = api->cls; | 970 | struct Plugin *plugin = api->cls; |
971 | struct GNUNET_DHTU_Source *src; | ||
972 | struct GNUNET_DHTU_Target *dst; | ||
973 | |||
974 | while (NULL != (dst = plugin->dst_head)) | ||
975 | { | ||
976 | plugin->env->disconnect_cb (dst->app_ctx); | ||
977 | GNUNET_CONTAINER_DLL_remove (plugin->dst_head, | ||
978 | plugin->dst_tail, | ||
979 | dst); | ||
980 | GNUNET_free (dst); | ||
981 | } | ||
982 | while (NULL != (src = plugin->src_head)) | ||
983 | { | ||
984 | plugin->env->address_del_cb (src->app_ctx); | ||
985 | GNUNET_CONTAINER_DLL_remove (plugin->src_head, | ||
986 | plugin->src_tail, | ||
987 | src); | ||
988 | GNUNET_free (src->address); | ||
989 | GNUNET_free (src); | ||
990 | } | ||
821 | 991 | ||
822 | GNUNET_SCHEDULER_cancel (plugin->scan_task); | 992 | GNUNET_SCHEDULER_cancel (plugin->scan_task); |
823 | GNUNET_break (0 == | 993 | GNUNET_break (0 == |