diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-10-21 22:24:53 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-10-21 22:24:53 +0000 |
commit | 89809e9bdb637537c832c775bb3c2d03b6562b79 (patch) | |
tree | a188eabbb485cb8858a86e2caaca7fdf20507467 /src/transport/plugin_transport_tcp.c | |
parent | 4ab32191fbd53680ff5192fc7d53a21c67ae772d (diff) | |
download | gnunet-89809e9bdb637537c832c775bb3c2d03b6562b79.tar.gz gnunet-89809e9bdb637537c832c775bb3c2d03b6562b79.zip |
eliminate last residue of old service api in transport
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 393 |
1 files changed, 389 insertions, 4 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 79361d3f2..79c70138f 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -521,6 +521,391 @@ struct Plugin | |||
521 | }; | 521 | }; |
522 | 522 | ||
523 | 523 | ||
524 | /* begin of ancient copy-and-pasted code that should be | ||
525 | specialized for TCP ...*/ | ||
526 | /** | ||
527 | * Add the given UNIX domain path as an address to the | ||
528 | * list (as the first entry). | ||
529 | * | ||
530 | * @param saddrs array to update | ||
531 | * @param saddrlens where to store the address length | ||
532 | * @param unixpath path to add | ||
533 | * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This | ||
534 | * parameter is ignore on systems other than LINUX | ||
535 | */ | ||
536 | static void | ||
537 | add_unixpath (struct sockaddr **saddrs, | ||
538 | socklen_t *saddrlens, | ||
539 | const char *unixpath, | ||
540 | int abstract) | ||
541 | { | ||
542 | #ifdef AF_UNIX | ||
543 | struct sockaddr_un *un; | ||
544 | |||
545 | un = GNUNET_new (struct sockaddr_un); | ||
546 | un->sun_family = AF_UNIX; | ||
547 | strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1); | ||
548 | #ifdef LINUX | ||
549 | if (GNUNET_YES == abstract) | ||
550 | un->sun_path[0] = '\0'; | ||
551 | #endif | ||
552 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
553 | un->sun_len = (u_char) sizeof (struct sockaddr_un); | ||
554 | #endif | ||
555 | *saddrs = (struct sockaddr *) un; | ||
556 | *saddrlens = sizeof (struct sockaddr_un); | ||
557 | #else | ||
558 | /* this function should never be called | ||
559 | * unless AF_UNIX is defined! */ | ||
560 | GNUNET_assert (0); | ||
561 | #endif | ||
562 | } | ||
563 | |||
564 | |||
565 | /** | ||
566 | * Get the list of addresses that a server for the given service | ||
567 | * should bind to. | ||
568 | * | ||
569 | * @param service_name name of the service | ||
570 | * @param cfg configuration (which specifies the addresses) | ||
571 | * @param addrs set (call by reference) to an array of pointers to the | ||
572 | * addresses the server should bind to and listen on; the | ||
573 | * array will be NULL-terminated (on success) | ||
574 | * @param addr_lens set (call by reference) to an array of the lengths | ||
575 | * of the respective `struct sockaddr` struct in the @a addrs | ||
576 | * array (on success) | ||
577 | * @return number of addresses found on success, | ||
578 | * #GNUNET_SYSERR if the configuration | ||
579 | * did not specify reasonable finding information or | ||
580 | * if it specified a hostname that could not be resolved; | ||
581 | * #GNUNET_NO if the number of addresses configured is | ||
582 | * zero (in this case, `*addrs` and `*addr_lens` will be | ||
583 | * set to NULL). | ||
584 | */ | ||
585 | static int | ||
586 | get_server_addresses (const char *service_name, | ||
587 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
588 | struct sockaddr ***addrs, | ||
589 | socklen_t ** addr_lens) | ||
590 | { | ||
591 | int disablev6; | ||
592 | struct GNUNET_NETWORK_Handle *desc; | ||
593 | unsigned long long port; | ||
594 | char *unixpath; | ||
595 | struct addrinfo hints; | ||
596 | struct addrinfo *res; | ||
597 | struct addrinfo *pos; | ||
598 | struct addrinfo *next; | ||
599 | unsigned int i; | ||
600 | int resi; | ||
601 | int ret; | ||
602 | int abstract; | ||
603 | struct sockaddr **saddrs; | ||
604 | socklen_t *saddrlens; | ||
605 | char *hostname; | ||
606 | |||
607 | *addrs = NULL; | ||
608 | *addr_lens = NULL; | ||
609 | desc = NULL; | ||
610 | if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6")) | ||
611 | { | ||
612 | if (GNUNET_SYSERR == | ||
613 | (disablev6 = | ||
614 | GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6"))) | ||
615 | return GNUNET_SYSERR; | ||
616 | } | ||
617 | else | ||
618 | disablev6 = GNUNET_NO; | ||
619 | |||
620 | if (! disablev6) | ||
621 | { | ||
622 | /* probe IPv6 support */ | ||
623 | desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); | ||
624 | if (NULL == desc) | ||
625 | { | ||
626 | if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) || | ||
627 | (EACCES == errno)) | ||
628 | { | ||
629 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); | ||
630 | return GNUNET_SYSERR; | ||
631 | } | ||
632 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
633 | _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"), | ||
634 | service_name, STRERROR (errno)); | ||
635 | disablev6 = GNUNET_YES; | ||
636 | } | ||
637 | else | ||
638 | { | ||
639 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); | ||
640 | desc = NULL; | ||
641 | } | ||
642 | } | ||
643 | |||
644 | port = 0; | ||
645 | if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) | ||
646 | { | ||
647 | if (GNUNET_OK != | ||
648 | GNUNET_CONFIGURATION_get_value_number (cfg, service_name, | ||
649 | "PORT", &port)) | ||
650 | { | ||
651 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
652 | _("Require valid port number for service `%s' in configuration!\n"), | ||
653 | service_name); | ||
654 | } | ||
655 | if (port > 65535) | ||
656 | { | ||
657 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
658 | _("Require valid port number for service `%s' in configuration!\n"), | ||
659 | service_name); | ||
660 | return GNUNET_SYSERR; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO")) | ||
665 | { | ||
666 | GNUNET_break (GNUNET_OK == | ||
667 | GNUNET_CONFIGURATION_get_value_string (cfg, service_name, | ||
668 | "BINDTO", &hostname)); | ||
669 | } | ||
670 | else | ||
671 | hostname = NULL; | ||
672 | |||
673 | unixpath = NULL; | ||
674 | abstract = GNUNET_NO; | ||
675 | #ifdef AF_UNIX | ||
676 | if ((GNUNET_YES == | ||
677 | GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) && | ||
678 | (GNUNET_OK == | ||
679 | GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", | ||
680 | &unixpath)) && | ||
681 | (0 < strlen (unixpath))) | ||
682 | { | ||
683 | /* probe UNIX support */ | ||
684 | struct sockaddr_un s_un; | ||
685 | |||
686 | if (strlen (unixpath) >= sizeof (s_un.sun_path)) | ||
687 | { | ||
688 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
689 | _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, | ||
690 | (unsigned long long) sizeof (s_un.sun_path)); | ||
691 | unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); | ||
692 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
693 | _("Using `%s' instead\n"), | ||
694 | unixpath); | ||
695 | } | ||
696 | #ifdef LINUX | ||
697 | abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
698 | "TESTING", | ||
699 | "USE_ABSTRACT_SOCKETS"); | ||
700 | if (GNUNET_SYSERR == abstract) | ||
701 | abstract = GNUNET_NO; | ||
702 | #endif | ||
703 | if ((GNUNET_YES != abstract) | ||
704 | && (GNUNET_OK != | ||
705 | GNUNET_DISK_directory_create_for_file (unixpath))) | ||
706 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
707 | "mkdir", | ||
708 | unixpath); | ||
709 | } | ||
710 | if (NULL != unixpath) | ||
711 | { | ||
712 | desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); | ||
713 | if (NULL == desc) | ||
714 | { | ||
715 | if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) || | ||
716 | (EACCES == errno)) | ||
717 | { | ||
718 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); | ||
719 | GNUNET_free_non_null (hostname); | ||
720 | GNUNET_free (unixpath); | ||
721 | return GNUNET_SYSERR; | ||
722 | } | ||
723 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
724 | _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"), | ||
725 | service_name, | ||
726 | STRERROR (errno)); | ||
727 | GNUNET_free (unixpath); | ||
728 | unixpath = NULL; | ||
729 | } | ||
730 | else | ||
731 | { | ||
732 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); | ||
733 | desc = NULL; | ||
734 | } | ||
735 | } | ||
736 | #endif | ||
737 | |||
738 | if ((0 == port) && (NULL == unixpath)) | ||
739 | { | ||
740 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
741 | _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"), | ||
742 | service_name); | ||
743 | GNUNET_free_non_null (hostname); | ||
744 | return GNUNET_SYSERR; | ||
745 | } | ||
746 | if (0 == port) | ||
747 | { | ||
748 | saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *)); | ||
749 | saddrlens = GNUNET_malloc (2 * sizeof (socklen_t)); | ||
750 | add_unixpath (saddrs, saddrlens, unixpath, abstract); | ||
751 | GNUNET_free_non_null (unixpath); | ||
752 | GNUNET_free_non_null (hostname); | ||
753 | *addrs = saddrs; | ||
754 | *addr_lens = saddrlens; | ||
755 | return 1; | ||
756 | } | ||
757 | |||
758 | if (NULL != hostname) | ||
759 | { | ||
760 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
761 | "Resolving `%s' since that is where `%s' will bind to.\n", | ||
762 | hostname, | ||
763 | service_name); | ||
764 | memset (&hints, 0, sizeof (struct addrinfo)); | ||
765 | if (disablev6) | ||
766 | hints.ai_family = AF_INET; | ||
767 | hints.ai_protocol = IPPROTO_TCP; | ||
768 | if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) || | ||
769 | (NULL == res)) | ||
770 | { | ||
771 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
772 | _("Failed to resolve `%s': %s\n"), | ||
773 | hostname, | ||
774 | gai_strerror (ret)); | ||
775 | GNUNET_free (hostname); | ||
776 | GNUNET_free_non_null (unixpath); | ||
777 | return GNUNET_SYSERR; | ||
778 | } | ||
779 | next = res; | ||
780 | i = 0; | ||
781 | while (NULL != (pos = next)) | ||
782 | { | ||
783 | next = pos->ai_next; | ||
784 | if ((disablev6) && (pos->ai_family == AF_INET6)) | ||
785 | continue; | ||
786 | i++; | ||
787 | } | ||
788 | if (0 == i) | ||
789 | { | ||
790 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
791 | _("Failed to find %saddress for `%s'.\n"), | ||
792 | disablev6 ? "IPv4 " : "", | ||
793 | hostname); | ||
794 | freeaddrinfo (res); | ||
795 | GNUNET_free (hostname); | ||
796 | GNUNET_free_non_null (unixpath); | ||
797 | return GNUNET_SYSERR; | ||
798 | } | ||
799 | resi = i; | ||
800 | if (NULL != unixpath) | ||
801 | resi++; | ||
802 | saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); | ||
803 | saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); | ||
804 | i = 0; | ||
805 | if (NULL != unixpath) | ||
806 | { | ||
807 | add_unixpath (saddrs, saddrlens, unixpath, abstract); | ||
808 | i++; | ||
809 | } | ||
810 | next = res; | ||
811 | while (NULL != (pos = next)) | ||
812 | { | ||
813 | next = pos->ai_next; | ||
814 | if ((disablev6) && (AF_INET6 == pos->ai_family)) | ||
815 | continue; | ||
816 | if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol)) | ||
817 | continue; /* not TCP */ | ||
818 | if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype)) | ||
819 | continue; /* huh? */ | ||
820 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n", | ||
821 | service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen)); | ||
822 | if (AF_INET == pos->ai_family) | ||
823 | { | ||
824 | GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen); | ||
825 | saddrlens[i] = pos->ai_addrlen; | ||
826 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
827 | GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); | ||
828 | ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); | ||
829 | } | ||
830 | else | ||
831 | { | ||
832 | GNUNET_assert (AF_INET6 == pos->ai_family); | ||
833 | GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen); | ||
834 | saddrlens[i] = pos->ai_addrlen; | ||
835 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
836 | GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); | ||
837 | ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); | ||
838 | } | ||
839 | i++; | ||
840 | } | ||
841 | GNUNET_free (hostname); | ||
842 | freeaddrinfo (res); | ||
843 | resi = i; | ||
844 | } | ||
845 | else | ||
846 | { | ||
847 | /* will bind against everything, just set port */ | ||
848 | if (disablev6) | ||
849 | { | ||
850 | /* V4-only */ | ||
851 | resi = 1; | ||
852 | if (NULL != unixpath) | ||
853 | resi++; | ||
854 | i = 0; | ||
855 | saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); | ||
856 | saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); | ||
857 | if (NULL != unixpath) | ||
858 | { | ||
859 | add_unixpath (saddrs, saddrlens, unixpath, abstract); | ||
860 | i++; | ||
861 | } | ||
862 | saddrlens[i] = sizeof (struct sockaddr_in); | ||
863 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
864 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
865 | ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i]; | ||
866 | #endif | ||
867 | ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; | ||
868 | ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); | ||
869 | } | ||
870 | else | ||
871 | { | ||
872 | /* dual stack */ | ||
873 | resi = 2; | ||
874 | if (NULL != unixpath) | ||
875 | resi++; | ||
876 | saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); | ||
877 | saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); | ||
878 | i = 0; | ||
879 | if (NULL != unixpath) | ||
880 | { | ||
881 | add_unixpath (saddrs, saddrlens, unixpath, abstract); | ||
882 | i++; | ||
883 | } | ||
884 | saddrlens[i] = sizeof (struct sockaddr_in6); | ||
885 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
886 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
887 | ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0]; | ||
888 | #endif | ||
889 | ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6; | ||
890 | ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); | ||
891 | i++; | ||
892 | saddrlens[i] = sizeof (struct sockaddr_in); | ||
893 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
894 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
895 | ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1]; | ||
896 | #endif | ||
897 | ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; | ||
898 | ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); | ||
899 | } | ||
900 | } | ||
901 | GNUNET_free_non_null (unixpath); | ||
902 | *addrs = saddrs; | ||
903 | *addr_lens = saddrlens; | ||
904 | return resi; | ||
905 | } | ||
906 | /* end ancient copy-and-paste */ | ||
907 | |||
908 | |||
524 | /** | 909 | /** |
525 | * If a session monitor is attached, notify it about the new | 910 | * If a session monitor is attached, notify it about the new |
526 | * session state. | 911 | * session state. |
@@ -2992,10 +3377,10 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
2992 | if ( (NULL != service) && | 3377 | if ( (NULL != service) && |
2993 | (GNUNET_SYSERR != | 3378 | (GNUNET_SYSERR != |
2994 | (ret_s = | 3379 | (ret_s = |
2995 | GNUNET_SERVICE_get_server_addresses ("transport-tcp", | 3380 | get_server_addresses ("transport-tcp", |
2996 | env->cfg, | 3381 | env->cfg, |
2997 | &addrs, | 3382 | &addrs, |
2998 | &addrlens)))) | 3383 | &addrlens)))) |
2999 | { | 3384 | { |
3000 | for (ret = ret_s-1; ret >= 0; ret--) | 3385 | for (ret = ret_s-1; ret >= 0; ret--) |
3001 | LOG (GNUNET_ERROR_TYPE_INFO, | 3386 | LOG (GNUNET_ERROR_TYPE_INFO, |