diff options
Diffstat (limited to 'src/util/service.c')
-rw-r--r-- | src/util/service.c | 190 |
1 files changed, 154 insertions, 36 deletions
diff --git a/src/util/service.c b/src/util/service.c index 82e7070a1..9ab99de3e 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -612,6 +612,10 @@ check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen) | |||
612 | && ((sctx->v6_denied == NULL) || | 612 | && ((sctx->v6_denied == NULL) || |
613 | (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr))); | 613 | (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr))); |
614 | break; | 614 | break; |
615 | case AF_UNIX: | ||
616 | /* FIXME: support checking UID/GID in the future... */ | ||
617 | ret = GNUNET_OK; /* always OK for now */ | ||
618 | break; | ||
615 | default: | 619 | default: |
616 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 620 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
617 | _("Unknown address family %d\n"), addr->sa_family); | 621 | _("Unknown address family %d\n"), addr->sa_family); |
@@ -702,6 +706,46 @@ process_acl6 (struct IPv6NetworkSet **ret, | |||
702 | return GNUNET_OK; | 706 | return GNUNET_OK; |
703 | } | 707 | } |
704 | 708 | ||
709 | /** | ||
710 | * Add the given UNIX domain path as an address to the | ||
711 | * list (as the first entry). | ||
712 | * | ||
713 | * @param saddrs array to update | ||
714 | * @param saddrlens where to store the address length | ||
715 | * @param unixpath path to add | ||
716 | */ | ||
717 | static void | ||
718 | add_unixpath (struct sockaddr **saddrs, | ||
719 | socklen_t *saddrlens, | ||
720 | const char *unixpath) | ||
721 | { | ||
722 | #ifdef AF_UNIX | ||
723 | struct sockaddr_un *un; | ||
724 | size_t slen; | ||
725 | |||
726 | un = GNUNET_malloc (sizeof (struct sockaddr_un)); | ||
727 | un->sun_family = AF_UNIX; | ||
728 | slen = strlen (unixpath) + 1; | ||
729 | if (slen >= sizeof (un->sun_path)) | ||
730 | slen = sizeof (un->sun_path) - 1; | ||
731 | memcpy (un->sun_path, | ||
732 | unixpath, | ||
733 | slen); | ||
734 | un->sun_path[slen] = '\0'; | ||
735 | slen += sizeof (sa_family_t); | ||
736 | #if LINUX | ||
737 | un->sun_path[0] = '\0'; | ||
738 | slen = sizeof (struct sockaddr_un); | ||
739 | #endif | ||
740 | *saddrs = (struct sockaddr*) un; | ||
741 | *saddrlens = slen; | ||
742 | #else | ||
743 | /* this function should never be called | ||
744 | unless AF_UNIX is defined! */ | ||
745 | GNUNET_assert (0); | ||
746 | #endif | ||
747 | } | ||
748 | |||
705 | 749 | ||
706 | /** | 750 | /** |
707 | * Get the list of addresses that a server for the given service | 751 | * Get the list of addresses that a server for the given service |
@@ -732,6 +776,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, | |||
732 | int disablev6; | 776 | int disablev6; |
733 | struct GNUNET_NETWORK_Handle *desc; | 777 | struct GNUNET_NETWORK_Handle *desc; |
734 | unsigned long long port; | 778 | unsigned long long port; |
779 | char *unixpath; | ||
735 | struct addrinfo hints; | 780 | struct addrinfo hints; |
736 | struct addrinfo *res; | 781 | struct addrinfo *res; |
737 | struct addrinfo *pos; | 782 | struct addrinfo *pos; |
@@ -781,19 +826,25 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, | |||
781 | } | 826 | } |
782 | } | 827 | } |
783 | 828 | ||
784 | 829 | port = 0; | |
785 | if ((GNUNET_OK != | 830 | if (GNUNET_CONFIGURATION_have_value (cfg, |
786 | GNUNET_CONFIGURATION_get_value_number (cfg, | 831 | serviceName, "PORT")) |
787 | serviceName, | ||
788 | "PORT", | ||
789 | &port)) || (port > 65535)) | ||
790 | { | 832 | { |
791 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 833 | GNUNET_break (GNUNET_OK == |
792 | _ | 834 | GNUNET_CONFIGURATION_get_value_number (cfg, |
793 | ("Require valid port number for service `%s' in configuration!\n"), | 835 | serviceName, |
794 | serviceName); | 836 | "PORT", |
795 | return GNUNET_SYSERR; | 837 | &port)); |
838 | if (port > 65535) | ||
839 | { | ||
840 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
841 | _ | ||
842 | ("Require valid port number for service `%s' in configuration!\n"), | ||
843 | serviceName); | ||
844 | return GNUNET_SYSERR; | ||
845 | } | ||
796 | } | 846 | } |
847 | |||
797 | if (GNUNET_CONFIGURATION_have_value (cfg, | 848 | if (GNUNET_CONFIGURATION_have_value (cfg, |
798 | serviceName, "BINDTO")) | 849 | serviceName, "BINDTO")) |
799 | { | 850 | { |
@@ -806,6 +857,49 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, | |||
806 | else | 857 | else |
807 | hostname = NULL; | 858 | hostname = NULL; |
808 | 859 | ||
860 | #ifdef AF_UNIX | ||
861 | if (GNUNET_CONFIGURATION_have_value (cfg, | ||
862 | serviceName, "UNIXPATH")) | ||
863 | { | ||
864 | GNUNET_break (GNUNET_OK == | ||
865 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
866 | serviceName, | ||
867 | "UNIXPATH", | ||
868 | &unixpath)); | ||
869 | |||
870 | /* probe UNIX support */ | ||
871 | desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); | ||
872 | if (NULL == desc) | ||
873 | { | ||
874 | if ((errno == ENOBUFS) || | ||
875 | (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES)) | ||
876 | { | ||
877 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); | ||
878 | return GNUNET_SYSERR; | ||
879 | } | ||
880 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
881 | _ | ||
882 | ("Disabling UNIX domainn socket support for service `%s', failed to create UNIX domain socket: %s\n"), | ||
883 | serviceName, STRERROR (errno)); | ||
884 | GNUNET_free (unixpath); | ||
885 | unixpath = NULL; | ||
886 | } | ||
887 | } | ||
888 | else | ||
889 | unixpath = NULL; | ||
890 | #else | ||
891 | unixpath = NULL; | ||
892 | #endif | ||
893 | |||
894 | if ( (port == 0) && | ||
895 | (unixpath == NULL) ) | ||
896 | { | ||
897 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
898 | _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"), | ||
899 | serviceName); | ||
900 | return GNUNET_SYSERR; | ||
901 | } | ||
902 | |||
809 | if (hostname != NULL) | 903 | if (hostname != NULL) |
810 | { | 904 | { |
811 | #if DEBUG_SERVICE | 905 | #if DEBUG_SERVICE |
@@ -845,9 +939,16 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, | |||
845 | return GNUNET_SYSERR; | 939 | return GNUNET_SYSERR; |
846 | } | 940 | } |
847 | resi = i; | 941 | resi = i; |
848 | saddrs = GNUNET_malloc ((i+1) * sizeof(struct sockaddr*)); | 942 | if (NULL != unixpath) |
849 | saddrlens = GNUNET_malloc ((i+1) * sizeof (socklen_t)); | 943 | resi++; |
944 | saddrs = GNUNET_malloc ((resi+1) * sizeof(struct sockaddr*)); | ||
945 | saddrlens = GNUNET_malloc ((resi+1) * sizeof (socklen_t)); | ||
850 | i = 0; | 946 | i = 0; |
947 | if (NULL != unixpath) | ||
948 | { | ||
949 | add_unixpath (saddrs, saddrlens, unixpath); | ||
950 | i++; | ||
951 | } | ||
851 | next = res; | 952 | next = res; |
852 | while (NULL != (pos = next)) | 953 | while (NULL != (pos = next)) |
853 | { | 954 | { |
@@ -890,40 +991,56 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, | |||
890 | { | 991 | { |
891 | /* V4-only */ | 992 | /* V4-only */ |
892 | resi = 1; | 993 | resi = 1; |
893 | saddrs = GNUNET_malloc (2 * sizeof(struct sockaddr*)); | 994 | if (NULL != unixpath) |
894 | saddrlens = GNUNET_malloc (2 * sizeof (socklen_t)); | 995 | resi++; |
895 | saddrlens[0] = sizeof (struct sockaddr_in); | 996 | i = 0; |
896 | saddrs[0] = GNUNET_malloc (saddrlens[0]); | 997 | saddrs = GNUNET_malloc ((resi+1) * sizeof(struct sockaddr*)); |
998 | saddrlens = GNUNET_malloc ((resi+1) * sizeof (socklen_t)); | ||
999 | if (NULL != unixpath) | ||
1000 | { | ||
1001 | add_unixpath (saddrs, saddrlens, unixpath); | ||
1002 | i++; | ||
1003 | } | ||
1004 | saddrlens[i] = sizeof (struct sockaddr_in); | ||
1005 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
897 | #if HAVE_SOCKADDR_IN_SIN_LEN | 1006 | #if HAVE_SOCKADDR_IN_SIN_LEN |
898 | ((struct sockaddr_in *) saddrs[0])->sin_len = saddrlens[0]; | 1007 | ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i]; |
899 | #endif | 1008 | #endif |
900 | ((struct sockaddr_in *) saddrs[0])->sin_family = AF_INET; | 1009 | ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; |
901 | ((struct sockaddr_in *) saddrs[0])->sin_port = htons (port); | 1010 | ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); |
902 | } | 1011 | } |
903 | else | 1012 | else |
904 | { | 1013 | { |
905 | /* dual stack */ | 1014 | /* dual stack */ |
906 | resi = 2; | 1015 | resi = 2; |
907 | saddrs = GNUNET_malloc (3 * sizeof(struct sockaddr*)); | 1016 | if (NULL != unixpath) |
908 | saddrlens = GNUNET_malloc (3 * sizeof (socklen_t)); | 1017 | resi++; |
909 | 1018 | saddrs = GNUNET_malloc ((resi+1) * sizeof(struct sockaddr*)); | |
910 | saddrlens[0] = sizeof (struct sockaddr_in6); | 1019 | saddrlens = GNUNET_malloc ((resi+1) * sizeof (socklen_t)); |
911 | saddrs[0] = GNUNET_malloc (saddrlens[0]); | 1020 | i = 0; |
1021 | if (NULL != unixpath) | ||
1022 | { | ||
1023 | add_unixpath (saddrs, saddrlens, unixpath); | ||
1024 | i++; | ||
1025 | } | ||
1026 | saddrlens[i] = sizeof (struct sockaddr_in6); | ||
1027 | saddrs[i] = GNUNET_malloc (saddrlens[i]); | ||
912 | #if HAVE_SOCKADDR_IN_SIN_LEN | 1028 | #if HAVE_SOCKADDR_IN_SIN_LEN |
913 | ((struct sockaddr_in6 *) saddrs[0])->sin6_len = saddrlens[0]; | 1029 | ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0]; |
914 | #endif | 1030 | #endif |
915 | ((struct sockaddr_in6 *) saddrs[0])->sin6_family = AF_INET6; | 1031 | ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6; |
916 | ((struct sockaddr_in6 *) saddrs[0])->sin6_port = htons (port); | 1032 | ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); |
917 | 1033 | i++; | |
918 | saddrlens[1] = sizeof (struct sockaddr_in); | 1034 | saddrlens[i] = sizeof (struct sockaddr_in); |
919 | saddrs[1] = GNUNET_malloc (saddrlens[1]); | 1035 | saddrs[i] = GNUNET_malloc (saddrlens[i]); |
920 | #if HAVE_SOCKADDR_IN_SIN_LEN | 1036 | #if HAVE_SOCKADDR_IN_SIN_LEN |
921 | ((struct sockaddr_in *) saddrs[1])->sin_len = saddrlens[1]; | 1037 | ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1]; |
922 | #endif | 1038 | #endif |
923 | ((struct sockaddr_in *) saddrs[1])->sin_family = AF_INET; | 1039 | ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; |
924 | ((struct sockaddr_in *) saddrs[1])->sin_port = htons (port); | 1040 | ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); |
925 | } | 1041 | } |
926 | } | 1042 | } |
1043 | GNUNET_free_non_null (unixpath); | ||
927 | *addrs = saddrs; | 1044 | *addrs = saddrs; |
928 | *addr_lens = saddrlens; | 1045 | *addr_lens = saddrlens; |
929 | return resi; | 1046 | return resi; |
@@ -934,8 +1051,9 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, | |||
934 | * Setup addr, addrlen, maxbuf, idle_timeout | 1051 | * Setup addr, addrlen, maxbuf, idle_timeout |
935 | * based on configuration! | 1052 | * based on configuration! |
936 | * | 1053 | * |
937 | * Configuration must specify a "PORT". It may | 1054 | * Configuration may specify: |
938 | * specify: | 1055 | * - PORT (where to bind to for TCP) |
1056 | * - UNIXPATH (where to bind to for UNIX domain sockets) | ||
939 | * - TIMEOUT (after how many ms does an inactive service timeout); | 1057 | * - TIMEOUT (after how many ms does an inactive service timeout); |
940 | * - MAXBUF (maximum incoming message size supported) | 1058 | * - MAXBUF (maximum incoming message size supported) |
941 | * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack) | 1059 | * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack) |