From adf27a6356d67c4bef76f3560aa4abce5f71528f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 20 Jun 2012 18:45:30 +0000 Subject: [PATCH] -fixing #2439 --- src/util/client.c | 57 +++++++++++++++++++++++----------------------- src/util/network.c | 48 +++++++++++++++++++++++++++++++++++--- src/util/service.c | 10 ++++---- 3 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/util/client.c b/src/util/client.c index c29b48e6b..d9be7f46e 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -738,40 +738,41 @@ GNUNET_CLIENT_service_test (const char *service, { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, - sizeof (s_un.sun_path)); + (unsigned long long) sizeof (s_un.sun_path)); + unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); } - else + } + if (NULL != unixpath) + { + sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); + if (NULL != sock) { - sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); - if (NULL != sock) - { - memset (&s_un, 0, sizeof (s_un)); - s_un.sun_family = AF_UNIX; - slen = strlen (unixpath) + 1; - if (slen >= sizeof (s_un.sun_path)) - slen = sizeof (s_un.sun_path) - 1; - memcpy (s_un.sun_path, unixpath, slen); - s_un.sun_path[slen] = '\0'; - slen = sizeof (struct sockaddr_un); + memset (&s_un, 0, sizeof (s_un)); + s_un.sun_family = AF_UNIX; + slen = strlen (unixpath) + 1; + if (slen >= sizeof (s_un.sun_path)) + slen = sizeof (s_un.sun_path) - 1; + memcpy (s_un.sun_path, unixpath, slen); + s_un.sun_path[slen] = '\0'; + slen = sizeof (struct sockaddr_un); #if LINUX - s_un.sun_path[0] = '\0'; + s_un.sun_path[0] = '\0'; #endif #if HAVE_SOCKADDR_IN_SIN_LEN - s_un.sun_len = (u_char) slen; + s_un.sun_len = (u_char) slen; #endif - if (GNUNET_OK != - GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un, - slen)) - { - /* failed to bind => service must be running */ - GNUNET_free (unixpath); - (void) GNUNET_NETWORK_socket_close (sock); - GNUNET_SCHEDULER_add_continuation (task, task_cls, - GNUNET_SCHEDULER_REASON_PREREQ_DONE); - return; - } - (void) GNUNET_NETWORK_socket_close (sock); - } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un, + slen)) + { + /* failed to bind => service must be running */ + GNUNET_free (unixpath); + (void) GNUNET_NETWORK_socket_close (sock); + GNUNET_SCHEDULER_add_continuation (task, task_cls, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return; + } + (void) GNUNET_NETWORK_socket_close (sock); /* let's try IP */ } } diff --git a/src/util/network.c b/src/util/network.c index ed7e8be30..ca8105fc7 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -22,12 +22,11 @@ * @file util/network.c * @brief basic, low-level networking interface * @author Nils Durner + * @author Christian Grothoff */ - #include "platform.h" -#include "gnunet_disk_lib.h" #include "disk.h" -#include "gnunet_container_lib.h" +#include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) @@ -67,6 +66,49 @@ struct GNUNET_NETWORK_Handle }; +/** + * Given a unixpath that is too long (larger than UNIX_PATH_MAX), + * shorten it to an acceptable length while keeping it unique + * and making sure it remains a valid filename (if possible). + * + * @param unixpath long path, will be freed (or same pointer returned + * with moved 0-termination). + * @return shortened unixpath, NULL on error + */ +char * +GNUNET_NETWORK_shorten_unixpath (char *unixpath) +{ + struct sockaddr_un dummy; + size_t slen; + char *end; + struct GNUNET_CRYPTO_ShortHashCode sh; + struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae; + size_t upm; + + upm = sizeof (dummy.sun_path); + slen = strlen (unixpath); + if (slen < upm) + return unixpath; /* no shortening required */ + GNUNET_CRYPTO_short_hash (unixpath, slen, &sh); + while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) + + strlen (unixpath) >= upm) + { + if (NULL == (end = strrchr (unixpath, '/'))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to shorten unix path `%s' while keeping name unique\n"), + unixpath); + GNUNET_free (unixpath); + return NULL; + } + *end = '\0'; + } + GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae); + strcat (unixpath, (char*) ae.short_encoding); + return unixpath; +} + + #ifndef FD_COPY #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) #endif diff --git a/src/util/service.c b/src/util/service.c index 2e75125ce..c9bbee3c8 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -973,12 +973,12 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name, { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, - sizeof (s_un.sun_path)); - GNUNET_free_non_null (hostname); - GNUNET_free (unixpath); - return GNUNET_SYSERR; + (unsigned long long) sizeof (s_un.sun_path)); + unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); } - + } + if (NULL != unixpath) + { desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); if (NULL == desc) { -- 2.25.1