From 78ef40f28e08ef786292429a4257fb82cf244635 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 2 May 2012 19:38:20 +0000 Subject: [PATCH] -fixing #2294, #2295 and #2296 --- src/include/gnunet_strings_lib.h | 4 +- src/peerinfo-tool/gnunet-peerinfo.c | 84 +++++++++++++++-------- src/util/strings.c | 101 +++++++++++----------------- 3 files changed, 97 insertions(+), 92 deletions(-) diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h index 2eebfecff..54d2e3034 100644 --- a/src/include/gnunet_strings_lib.h +++ b/src/include/gnunet_strings_lib.h @@ -342,6 +342,7 @@ GNUNET_STRINGS_check_filename (const char *filename, /** * Tries to convert 'zt_addr' string to an IPv6 address. + * The string is expected to have the format "[ABCD::01]:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of zt_addr (not counting 0-terminator). @@ -358,6 +359,7 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, /** * Tries to convert 'zt_addr' string to an IPv4 address. + * The string is expected to have the format "1.2.3.4:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of zt_addr (not counting 0-terminator). @@ -373,8 +375,6 @@ GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, /** * Tries to convert 'addr' string to an IP (v4 or v6) address. - * IPv6 address must have its address part enclosed in '()' parens - * instead of '[]'. * Will automatically decide whether to treat 'addr' as v4 or v6 address. * * @param addr a string, may not be 0-terminated. diff --git a/src/peerinfo-tool/gnunet-peerinfo.c b/src/peerinfo-tool/gnunet-peerinfo.c index 2c26c4599..8bb7392d9 100644 --- a/src/peerinfo-tool/gnunet-peerinfo.c +++ b/src/peerinfo-tool/gnunet-peerinfo.c @@ -228,6 +228,42 @@ state_machine (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + +/** + * Replace all characters in the input 'in' according + * to the mapping. The mapping says to map each character + * in 'oldchars' to the corresponding character (by offset) + * in 'newchars'. + * + * @param in input string to remap + * @param oldchars characters to replace + * @param newchars replacement characters, must have same length as 'oldchars' + * @return copy of string with replacement applied. + */ +static char * +map_characters (const char *in, + const char *oldchars, + const char *newchars) +{ + char *ret; + const char *off; + size_t i; + + GNUNET_assert (strlen (oldchars) == strlen (newchars)); + ret = GNUNET_strdup (in); + i = 0; + while (ret[i] != '\0') + { + off = strchr (oldchars, ret[i]); + if (NULL != off) + ret[i] = newchars[off - oldchars]; + i++; + } + return ret; +} + + + /* ********************* 'get_info' ******************* */ /** @@ -412,6 +448,7 @@ compose_uri (void *cls, const struct GNUNET_HELLO_Address *address, struct GetUriContext *guc = cls; struct GNUNET_TRANSPORT_PluginFunctions *papi; const char *addr; + char *uri_addr; char *ret; char tbuf[16]; struct tm *t; @@ -433,6 +470,9 @@ compose_uri (void *cls, const struct GNUNET_HELLO_Address *address, addr = papi->address_to_string (papi->cls, address->address, address->address_length); if ( (addr == NULL) || (strlen(addr) == 0) ) return GNUNET_OK; + /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved + characters in URIs */ + uri_addr = map_characters (addr, "[]", "()"); seconds = expiration.abs_value / 1000; t = gmtime (&seconds); GNUNET_assert (0 != strftime (tbuf, sizeof (tbuf), @@ -443,7 +483,8 @@ compose_uri (void *cls, const struct GNUNET_HELLO_Address *address, guc->uri, tbuf, address->transport_name, - addr); + uri_addr); + GNUNET_free (uri_addr); GNUNET_free (guc->uri); guc->uri = ret; return GNUNET_OK; @@ -501,7 +542,8 @@ add_address_to_hello (void *cls, size_t max, void *buffer) struct GNUNET_PEERINFO_HelloAddressParsingContext *ctx = cls; const char *tname; const char *address; - char * address_terminated; + char *uri_address; + char *plugin_address; const char *end; char *plugin_name; struct tm expiration_time; @@ -512,6 +554,7 @@ add_address_to_hello (void *cls, size_t max, void *buffer) size_t addr_len; struct GNUNET_HELLO_Address haddr; size_t ret; + if (NULL == ctx->pos) return 0; if ('!' != ctx->pos[0]) @@ -564,23 +607,7 @@ add_address_to_hello (void *cls, size_t max, void *buffer) } address++; end = strchr (address, (int) '!'); - if (NULL == end) - { - /* Last address */ - end = address + strlen (address); - address_terminated = strdup (address); - ctx->pos = NULL; - } - else - { - /* More addresses follow */ - size_t len = (end - address); - address_terminated = GNUNET_malloc (len + 1); - memcpy (address_terminated, address, len); - address_terminated[len] = '\0'; - ctx->pos = end; - - } + ctx->pos = end; plugin_name = GNUNET_strndup (tname, address - (tname+1)); papi = GPI_plugins_find (plugin_name); if (NULL == papi) @@ -593,9 +620,7 @@ add_address_to_hello (void *cls, size_t max, void *buffer) _("Plugin `%s' not found\n"), plugin_name); GNUNET_free (plugin_name); - GNUNET_break (0); - GNUNET_free (address_terminated); return 0; } if (NULL == papi->string_to_address) @@ -604,25 +629,29 @@ add_address_to_hello (void *cls, size_t max, void *buffer) _("Plugin `%s' does not support URIs yet\n"), plugin_name); GNUNET_free (plugin_name); - GNUNET_free (address_terminated); GNUNET_break (0); return 0; } - + uri_address = GNUNET_strndup (address, end - address); + /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved + characters in URIs; need to convert back to '[]' for the plugin */ + plugin_address = map_characters (uri_address, "()", "[]"); + GNUNET_free (uri_address); if (GNUNET_OK != papi->string_to_address (papi->cls, - address_terminated, - strlen (address_terminated) + 1, + plugin_address, + strlen (plugin_address), &addr, &addr_len)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse `%s'\n"), - address_terminated); + plugin_address); GNUNET_free (plugin_name); - GNUNET_free (address_terminated); + GNUNET_free (plugin_address); return 0; } + GNUNET_free (plugin_address); /* address.peer is unset - not used by add_address() */ haddr.address_length = addr_len; haddr.address = addr; @@ -630,7 +659,6 @@ add_address_to_hello (void *cls, size_t max, void *buffer) ret = GNUNET_HELLO_add_address (&haddr, expire, buffer, max); GNUNET_free (addr); GNUNET_free (plugin_name); - GNUNET_free (address_terminated); return ret; } diff --git a/src/util/strings.c b/src/util/strings.c index f9e2d8da6..dcc1a8250 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -940,6 +940,7 @@ GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) #endif + /** * Perform 'checks' on 'filename' * @@ -953,39 +954,37 @@ GNUNET_STRINGS_check_filename (const char *filename, enum GNUNET_STRINGS_FilenameCheck checks) { struct stat st; - if (filename == NULL || filename[0] == '\0') + if ( (NULL == filename) || (filename[0] == '\0') ) return GNUNET_SYSERR; - if (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE) + if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE)) if (!GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL)) return GNUNET_NO; - if (checks & (GNUNET_STRINGS_CHECK_EXISTS - | GNUNET_STRINGS_CHECK_IS_DIRECTORY - | GNUNET_STRINGS_CHECK_IS_LINK)) + if (0 != (checks & (GNUNET_STRINGS_CHECK_EXISTS + | GNUNET_STRINGS_CHECK_IS_DIRECTORY + | GNUNET_STRINGS_CHECK_IS_LINK))) { - if (STAT (filename, &st)) + if (0 != STAT (filename, &st)) { - if (checks & GNUNET_STRINGS_CHECK_EXISTS) + if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS)) return GNUNET_NO; else return GNUNET_SYSERR; } } - if (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY) + if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY)) if (!S_ISDIR (st.st_mode)) return GNUNET_NO; - if (checks & GNUNET_STRINGS_CHECK_IS_LINK) + if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK)) if (!S_ISLNK (st.st_mode)) return GNUNET_NO; return GNUNET_YES; } -#define MAX_IPV6_ADDRLEN 47 -#define MAX_IPV4_ADDRLEN 21 -#define MAX_IP_ADDRLEN MAX_IPV6_ADDRLEN /** * Tries to convert 'zt_addr' string to an IPv6 address. + * The string is expected to have the format "[ABCD::01]:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of zt_addr (not counting 0-terminator). @@ -999,32 +998,42 @@ GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, uint16_t addrlen, struct sockaddr_in6 *r_buf) { + char zbuf[addrlen + 1]; int ret; char *port_colon; unsigned int port; if (addrlen < 6) + return GNUNET_SYSERR; + memcpy (zbuf, zt_addr, addrlen); + if ('[' != zbuf[0]) return GNUNET_SYSERR; - - port_colon = strrchr (zt_addr, ':'); - if (port_colon == NULL) + zbuf[addrlen] = '\0'; + port_colon = strrchr (zbuf, ':'); + if (NULL == port_colon) + return GNUNET_SYSERR; + if (']' != *(port_colon - 1)) return GNUNET_SYSERR; ret = SSCANF (port_colon, ":%u", &port); - if (ret != 1 || port > 65535) + if ( (-1 != ret) || (port > 65535) ) return GNUNET_SYSERR; - port_colon[0] = '\0'; + *(port_colon-1) = '\0'; memset (r_buf, 0, sizeof (struct sockaddr_in6)); - ret = inet_pton (AF_INET6, zt_addr, &r_buf->sin6_addr); + ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr); if (ret <= 0) return GNUNET_SYSERR; r_buf->sin6_port = htons (port); r_buf->sin6_family = AF_INET6; +#if HAVE_SOCKADDR_IN_SIN_LEN + r_buf->sin6_len = (u_char) sizeof (struct sockaddr_in6); +#endif return GNUNET_OK; } /** * Tries to convert 'zt_addr' string to an IPv4 address. + * The string is expected to have the format "1.2.3.4:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of zt_addr (not counting 0-terminator). @@ -1036,36 +1045,33 @@ int GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen, struct sockaddr_in *r_buf) { - unsigned int temps[5]; + unsigned int temps[4]; unsigned int port; - int cnt; + unsigned int cnt; if (addrlen < 9) return GNUNET_SYSERR; - cnt = SSCANF (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port); - if (cnt != 5) + if (5 != cnt) return GNUNET_SYSERR; - for (cnt = 0; cnt < 4; cnt++) if (temps[cnt] > 0xFF) return GNUNET_SYSERR; if (port > 65535) return GNUNET_SYSERR; - - - r_buf->sin_family = AF_INET; r_buf->sin_port = htons (port); r_buf->sin_addr.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) + - (temps[2] << 8) + temps[3]); + (temps[2] << 8) + temps[3]); +#if HAVE_SOCKADDR_IN_SIN_LEN + r_buf->sin_len = (u_char) sizeof (struct sockaddr_in); +#endif return GNUNET_OK; } + /** * Tries to convert 'addr' string to an IP (v4 or v6) address. - * IPv6 address must have its address part enclosed in '()' parens - * instead of '[]'. * Will automatically decide whether to treat 'addr' as v4 or v6 address. * * @param addr a string, may not be 0-terminated. @@ -1080,39 +1086,10 @@ GNUNET_STRINGS_to_address_ip (const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf) { - uint16_t i; - char zt_addr[MAX_IP_ADDRLEN + 1]; - uint16_t zt_len = addrlen <= MAX_IP_ADDRLEN ? addrlen : MAX_IP_ADDRLEN; - - if (addrlen < 1) - return GNUNET_SYSERR; - - memset (zt_addr, 0, MAX_IP_ADDRLEN + 1); - strncpy (zt_addr, addr, zt_len); - - /* For URIs we use '(' and ')' instead of '[' and ']'. Do the substitution - * now, as GNUNET_STRINGS_to_address_ipv6() takes a proper []-enclosed IPv6 - * address. - */ - if (zt_addr[0] == '(') - { - for (i = 0; i < zt_len; i++) - { - switch (zt_addr[i]) - { - case '(': - zt_addr[i] = '['; - break; - case ')': - zt_addr[i] = ']'; - break; - default: - break; - } - } - return GNUNET_STRINGS_to_address_ipv6 (zt_addr, zt_len, (struct sockaddr_in6 *) r_buf); - } - return GNUNET_STRINGS_to_address_ipv4 (zt_addr, zt_len, (struct sockaddr_in *) r_buf); + if (GNUNET_OK == + GNUNET_STRINGS_to_address_ipv6 (addr, addrlen, (struct sockaddr_in6 *) r_buf)) + return GNUNET_OK; + return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *) r_buf); } /* end of strings.c */ -- 2.25.1