diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2022-09-03 22:29:46 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2022-09-03 22:29:46 +0200 |
commit | e8524ea2c41beb087bd8ee0c9f03498ebc5d3d42 (patch) | |
tree | b40d3232d3fa16342b6379609842547c0b3f0d6b /src/plugins/xfer | |
parent | 7cf939961606f079e9b097a7310e86f4e21c7535 (diff) | |
download | weechat-e8524ea2c41beb087bd8ee0c9f03498ebc5d3d42.zip |
xfer: fix DCC file receive on Termux (closes #1811)
This fixes such error displayed on Termux when receiving a DCC file:
xfer: invalid address "96747949": error 8 hostname nor servname provided, or not known
Diffstat (limited to 'src/plugins/xfer')
-rw-r--r-- | src/plugins/xfer/xfer-network.c | 108 | ||||
-rw-r--r-- | src/plugins/xfer/xfer-network.h | 7 | ||||
-rw-r--r-- | src/plugins/xfer/xfer.c | 75 |
3 files changed, 124 insertions, 66 deletions
diff --git a/src/plugins/xfer/xfer-network.c b/src/plugins/xfer/xfer-network.c index aa19be6a8..446c13db1 100644 --- a/src/plugins/xfer/xfer-network.c +++ b/src/plugins/xfer/xfer-network.c @@ -29,9 +29,11 @@ #include <sys/wait.h> #include <sys/socket.h> #include <netinet/in.h> +#include <arpa/nameser.h> +#include <netdb.h> +#include <resolv.h> #include <signal.h> #include <time.h> -#include <netdb.h> #include "../weechat-plugin.h" #include "xfer.h" @@ -43,6 +45,110 @@ /* + * Converts integer address (as string) to IPv4 string using notation + * "a.b.c.d". + * + * For example: "3232235778" -> "192.168.1.2" + * + * Note: result must be freed after use. + */ + +char * +xfer_network_convert_integer_to_ipv4 (const char *str_address) +{ + char *error, result[64]; + long number; + + if (!str_address || !str_address[0]) + return NULL; + + number = strtol (str_address, &error, 10); + if (!error || error[0] || (number <= 0)) + return NULL; + + snprintf (result, sizeof (result), + "%ld.%ld.%ld.%ld", + (number >> 24) & 0xFF, + (number >> 16) & 0xFF, + (number >> 8) & 0xFF, + number & 0xFF); + + return strdup (result); +} + +/* + * Resolves address. + * + * Returns: + * 1: OK + * 0: error + */ + +int +xfer_network_resolve_addr (const char *str_address, const char *str_port, + struct sockaddr *addr, socklen_t *addr_len, + int ai_flags) +{ + struct addrinfo *ainfo, hints; + char *converted_address; + int rc; + + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_flags = ai_flags; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + res_init (); + + rc = getaddrinfo (str_address, str_port, &hints, &ainfo); + + /* + * workaround for termux where an IP address as integer is not supported: + * it returns an error EAI_NONAME (8); in this case we manually convert + * the integer to IPv4 string, for example: 3232235778 -> 192.168.1.2 + */ + if (rc == EAI_NONAME) + { + converted_address = xfer_network_convert_integer_to_ipv4 (str_address); + if (converted_address) + { + rc = getaddrinfo (converted_address, str_port, &hints, &ainfo); + free (converted_address); + } + } + + if ((rc == 0) && ainfo && ainfo->ai_addr) + { + if (ainfo->ai_addrlen > *addr_len) + { + weechat_printf (NULL, + _("%s%s: address \"%s\" resolved to a larger " + "sockaddr than expected"), + weechat_prefix ("error"), XFER_PLUGIN_NAME, + str_address); + freeaddrinfo (ainfo); + return 0; + } + memcpy (addr, ainfo->ai_addr, ainfo->ai_addrlen); + *addr_len = ainfo->ai_addrlen; + freeaddrinfo (ainfo); + return 1; + } + + weechat_printf (NULL, + _("%s%s: invalid address \"%s\": error %d %s"), + weechat_prefix ("error"), XFER_PLUGIN_NAME, + str_address, rc, gai_strerror (rc)); + if ((rc == 0) && ainfo) + freeaddrinfo (ainfo); + return 0; +} + +/* * Creates pipe for communication with child process. * * Returns: diff --git a/src/plugins/xfer/xfer-network.h b/src/plugins/xfer/xfer-network.h index cb9be323e..1790d3494 100644 --- a/src/plugins/xfer/xfer-network.h +++ b/src/plugins/xfer/xfer-network.h @@ -20,6 +20,13 @@ #ifndef WEECHAT_PLUGIN_XFER_NETWORK_H #define WEECHAT_PLUGIN_XFER_NETWORK_H +#include <sys/socket.h> + +extern int xfer_network_resolve_addr (const char *str_address, + const char *str_port, + struct sockaddr *addr, + socklen_t *addr_len, + int ai_flags); extern void xfer_network_write_pipe (struct t_xfer *xfer, int status, int error); extern void xfer_network_connect_init (struct t_xfer *xfer); diff --git a/src/plugins/xfer/xfer.c b/src/plugins/xfer/xfer.c index 331c5f521..20879836b 100644 --- a/src/plugins/xfer/xfer.c +++ b/src/plugins/xfer/xfer.c @@ -28,10 +28,7 @@ #include <sys/stat.h> #include <time.h> #include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/nameser.h> #include <netdb.h> -#include <resolv.h> #include <gcrypt.h> #include <arpa/inet.h> @@ -971,59 +968,6 @@ xfer_free_all () } /* - * Resolves address. - * - * Returns: - * 1: OK - * 0: error - */ - -int -xfer_resolve_addr (const char *str_address, const char *str_port, - struct sockaddr *addr, socklen_t *addr_len, int ai_flags) -{ - struct addrinfo *ainfo, hints; - int rc; - - memset (&hints, 0, sizeof (struct addrinfo)); - hints.ai_flags = ai_flags; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - res_init (); - rc = getaddrinfo (str_address, str_port, &hints, &ainfo); - if ((rc == 0) && ainfo && ainfo->ai_addr) - { - if (ainfo->ai_addrlen > *addr_len) - { - weechat_printf (NULL, - _("%s%s: address \"%s\" resolved to a larger " - "sockaddr than expected"), - weechat_prefix ("error"), XFER_PLUGIN_NAME, - str_address); - freeaddrinfo (ainfo); - return 0; - } - memcpy (addr, ainfo->ai_addr, ainfo->ai_addrlen); - *addr_len = ainfo->ai_addrlen; - freeaddrinfo (ainfo); - return 1; - } - - weechat_printf (NULL, - _("%s%s: invalid address \"%s\": error %d %s"), - weechat_prefix ("error"), XFER_PLUGIN_NAME, - str_address, rc, gai_strerror (rc)); - if ((rc == 0) && ainfo) - freeaddrinfo (ainfo); - return 0; -} - -/* * Callback for signal "xfer_add". */ @@ -1208,9 +1152,9 @@ xfer_add_cb (const void *pointer, void *data, snprintf (str_port_temp, sizeof (str_port_temp), "%d", port); str_port = str_port_temp; length = sizeof (addr); - if (!xfer_resolve_addr (str_address, str_port, - (struct sockaddr*)&addr, &length, - AI_NUMERICSERV | AI_NUMERICHOST)) + if (!xfer_network_resolve_addr (str_address, str_port, + (struct sockaddr*)&addr, &length, + AI_NUMERICSERV | AI_NUMERICHOST)) { goto error; } @@ -1227,9 +1171,10 @@ xfer_add_cb (const void *pointer, void *data, str_address = weechat_config_string (xfer_config_network_own_ip); length = sizeof (own_ip_addr); - if (!xfer_resolve_addr (str_address, NULL, - (struct sockaddr*)&own_ip_addr, &length, - AI_NUMERICSERV)) + if (!xfer_network_resolve_addr (str_address, NULL, + (struct sockaddr*)&own_ip_addr, + &length, + AI_NUMERICSERV)) { goto error; } @@ -1245,9 +1190,9 @@ xfer_add_cb (const void *pointer, void *data, /* no own_ip, so bind_addr's family comes from irc connection */ str_address = weechat_infolist_string (infolist, "local_address"); length = sizeof (addr); - if (!xfer_resolve_addr (str_address, NULL, - (struct sockaddr*)&addr, &length, - AI_NUMERICSERV | AI_NUMERICHOST)) + if (!xfer_network_resolve_addr (str_address, NULL, + (struct sockaddr*)&addr, &length, + AI_NUMERICSERV | AI_NUMERICHOST)) { goto error; } |