mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
dirmngr: Use IPv4 or IPv6 interface only if available.
* dirmngr/dns-stuff.c (cached_inet_support): New variable. (dns_stuff_housekeeping): New. (check_inet_support): New. * dirmngr/http.c (connect_server): Use only detected interfaces. * dirmngr/dirmngr.c (housekeeping_thread): Flush the new cache. -- This currently works only for Windows but that is where users really ran into problems. The old workaround was to configure disable-ipv4 or disable-ipv6. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
40daa0bc0b
commit
12def3a84e
@ -1962,6 +1962,7 @@ housekeeping_thread (void *arg)
|
|||||||
memset (&ctrlbuf, 0, sizeof ctrlbuf);
|
memset (&ctrlbuf, 0, sizeof ctrlbuf);
|
||||||
dirmngr_init_default_ctrl (&ctrlbuf);
|
dirmngr_init_default_ctrl (&ctrlbuf);
|
||||||
|
|
||||||
|
dns_stuff_housekeeping ();
|
||||||
ks_hkp_housekeeping (curtime);
|
ks_hkp_housekeeping (curtime);
|
||||||
if (network_activity_seen)
|
if (network_activity_seen)
|
||||||
{
|
{
|
||||||
|
@ -149,6 +149,15 @@ static char tor_nameserver[40+20];
|
|||||||
static char tor_socks_user[30];
|
static char tor_socks_user[30];
|
||||||
static char tor_socks_password[20];
|
static char tor_socks_password[20];
|
||||||
|
|
||||||
|
/* To avoid checking the interface too often we cache the result. */
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
unsigned int valid:1;
|
||||||
|
unsigned int v4:1;
|
||||||
|
unsigned int v6:1;
|
||||||
|
} cached_inet_support;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_LIBDNS
|
#ifdef USE_LIBDNS
|
||||||
/* Libdns global data. */
|
/* Libdns global data. */
|
||||||
@ -686,6 +695,21 @@ reload_dns_stuff (int force)
|
|||||||
#else
|
#else
|
||||||
(void)force;
|
(void)force;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* We also flush the IPv4/v6 support flag cache. */
|
||||||
|
cached_inet_support.valid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Called from time to time from the housekeeping thread. */
|
||||||
|
void
|
||||||
|
dns_stuff_housekeeping (void)
|
||||||
|
{
|
||||||
|
/* With the current housekeeping interval of 10 minutes we flush
|
||||||
|
* that case so that a new or removed interface will be detected not
|
||||||
|
* later than 10 minutes after it changed. This way the user does
|
||||||
|
* not need a reload. */
|
||||||
|
cached_inet_support.valid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2387,3 +2411,83 @@ get_dns_cname (ctrl_t ctrl, const char *name, char **r_cname)
|
|||||||
err ? gpg_strerror (err) : *r_cname);
|
err ? gpg_strerror (err) : *r_cname);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether the machine has any usable inet devices up and
|
||||||
|
* running. We put this into dns because on Windows this is
|
||||||
|
* implemented using getaddrinfo and thus easiest done here. */
|
||||||
|
void
|
||||||
|
check_inet_support (int *r_v4, int *r_v6)
|
||||||
|
{
|
||||||
|
if (cached_inet_support.valid)
|
||||||
|
{
|
||||||
|
*r_v4 = cached_inet_support.v4;
|
||||||
|
*r_v6 = cached_inet_support.v6;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*r_v4 = *r_v6 = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
int ret;
|
||||||
|
struct addrinfo *aibuf = NULL;
|
||||||
|
struct addrinfo *ai;
|
||||||
|
|
||||||
|
ret = getaddrinfo ("..localmachine", NULL, NULL, &aibuf);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
err = map_eai_to_gpg_error (ret);
|
||||||
|
log_error ("%s: getaddrinfo failed: %s\n",__func__, gpg_strerror (err));
|
||||||
|
aibuf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ai = aibuf; ai; ai = ai->ai_next)
|
||||||
|
{
|
||||||
|
if (opt_debug)
|
||||||
|
{
|
||||||
|
log_debug ("%s: family: %d\n", __func__, ai->ai_family);
|
||||||
|
if (ai->ai_family == AF_INET6 || ai->ai_family == AF_INET)
|
||||||
|
{
|
||||||
|
char buffer[46];
|
||||||
|
DWORD buflen;
|
||||||
|
buflen = sizeof buffer;
|
||||||
|
if (WSAAddressToString (ai->ai_addr, (DWORD)ai->ai_addrlen,
|
||||||
|
NULL, buffer, &buflen))
|
||||||
|
log_debug ("%s: WSAAddressToString failed: ec=%u\n",
|
||||||
|
__func__, (unsigned int)WSAGetLastError ());
|
||||||
|
else
|
||||||
|
log_debug ("%s: addr: %s\n", __func__, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ai->ai_family == AF_INET6)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *v6addr = (struct sockaddr_in6 *)ai->ai_addr;
|
||||||
|
if (!IN6_IS_ADDR_LINKLOCAL (&v6addr->sin6_addr))
|
||||||
|
*r_v6 = 1;
|
||||||
|
}
|
||||||
|
else if (ai->ai_family == AF_INET)
|
||||||
|
{
|
||||||
|
*r_v4 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aibuf)
|
||||||
|
freeaddrinfo (aibuf);
|
||||||
|
}
|
||||||
|
#else /*!HAVE_W32_SYSTEM*/
|
||||||
|
{
|
||||||
|
/* For now we assume that we have both protocols. */
|
||||||
|
*r_v4 = *r_v6 = 1;
|
||||||
|
}
|
||||||
|
#endif /*!HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
if (opt_verbose)
|
||||||
|
log_info ("detected interfaces:%s%s\n",
|
||||||
|
*r_v4? " IPv4":"", *r_v6? " IPv4":"");
|
||||||
|
|
||||||
|
cached_inet_support.valid = 1;
|
||||||
|
cached_inet_support.v4 = *r_v4;
|
||||||
|
cached_inet_support.v6 = *r_v6;
|
||||||
|
}
|
||||||
|
@ -134,6 +134,9 @@ void set_dns_nameserver (const char *ipaddr);
|
|||||||
/* SIGHUP action handler for this module. */
|
/* SIGHUP action handler for this module. */
|
||||||
void reload_dns_stuff (int force);
|
void reload_dns_stuff (int force);
|
||||||
|
|
||||||
|
/* Housekeeping for this module. */
|
||||||
|
void dns_stuff_housekeeping (void);
|
||||||
|
|
||||||
void free_dns_addrinfo (dns_addrinfo_t ai);
|
void free_dns_addrinfo (dns_addrinfo_t ai);
|
||||||
|
|
||||||
/* Function similar to getaddrinfo. */
|
/* Function similar to getaddrinfo. */
|
||||||
@ -170,4 +173,8 @@ gpg_error_t get_dns_srv (ctrl_t ctrl,
|
|||||||
struct srventry **list, unsigned int *r_count);
|
struct srventry **list, unsigned int *r_count);
|
||||||
|
|
||||||
|
|
||||||
|
/* Store true in the variable if such an IP interface is usable. */
|
||||||
|
void check_inet_support (int *r_v4, int *r_v6);
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_DIRMNGR_DNS_STUFF_H*/
|
#endif /*GNUPG_DIRMNGR_DNS_STUFF_H*/
|
||||||
|
@ -2908,7 +2908,7 @@ connect_server (ctrl_t ctrl, const char *server, unsigned short port,
|
|||||||
unsigned int srvcount = 0;
|
unsigned int srvcount = 0;
|
||||||
int hostfound = 0;
|
int hostfound = 0;
|
||||||
int anyhostaddr = 0;
|
int anyhostaddr = 0;
|
||||||
int srv, connected;
|
int srv, connected, v4_valid, v6_valid;
|
||||||
gpg_error_t last_err = 0;
|
gpg_error_t last_err = 0;
|
||||||
struct srventry *serverlist = NULL;
|
struct srventry *serverlist = NULL;
|
||||||
|
|
||||||
@ -2918,6 +2918,8 @@ connect_server (ctrl_t ctrl, const char *server, unsigned short port,
|
|||||||
init_sockets ();
|
init_sockets ();
|
||||||
#endif /*Windows*/
|
#endif /*Windows*/
|
||||||
|
|
||||||
|
check_inet_support (&v4_valid, &v6_valid);
|
||||||
|
|
||||||
/* Onion addresses require special treatment. */
|
/* Onion addresses require special treatment. */
|
||||||
if (is_onion_address (server))
|
if (is_onion_address (server))
|
||||||
{
|
{
|
||||||
@ -2996,9 +2998,11 @@ connect_server (ctrl_t ctrl, const char *server, unsigned short port,
|
|||||||
|
|
||||||
for (ai = aibuf; ai && !connected; ai = ai->next)
|
for (ai = aibuf; ai && !connected; ai = ai->next)
|
||||||
{
|
{
|
||||||
if (ai->family == AF_INET && (flags & HTTP_FLAG_IGNORE_IPv4))
|
if (ai->family == AF_INET
|
||||||
|
&& ((flags & HTTP_FLAG_IGNORE_IPv4) || !v4_valid))
|
||||||
continue;
|
continue;
|
||||||
if (ai->family == AF_INET6 && (flags & HTTP_FLAG_IGNORE_IPv6))
|
if (ai->family == AF_INET6
|
||||||
|
&& ((flags & HTTP_FLAG_IGNORE_IPv6) || !v6_valid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sock != ASSUAN_INVALID_FD)
|
if (sock != ASSUAN_INVALID_FD)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user