aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_tcp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-10-21 22:24:53 +0000
committerChristian Grothoff <christian@grothoff.org>2016-10-21 22:24:53 +0000
commit89809e9bdb637537c832c775bb3c2d03b6562b79 (patch)
treea188eabbb485cb8858a86e2caaca7fdf20507467 /src/transport/plugin_transport_tcp.c
parent4ab32191fbd53680ff5192fc7d53a21c67ae772d (diff)
downloadgnunet-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.c393
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 */
536static void
537add_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 */
585static int
586get_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,