mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 15:56:23 +01:00
GNetworkAddress: drop cached addresses on resolver reload
If the resolver reloads (ie, if /etc/resolv.conf changes), GNetworkAddress needs to re-resolve its addresses the next time it's enumerated. Otherwise hosts that have different IP addresses inside and outside a VPN won't work correctly if you hold on to a GNetworkAddress for them for a long time. https://bugzilla.gnome.org/show_bug.cgi?id=694181
This commit is contained in:
parent
cfafad5aef
commit
c6c1166566
@ -65,6 +65,8 @@ struct _GNetworkAddressPrivate {
|
|||||||
guint16 port;
|
guint16 port;
|
||||||
GList *sockaddrs;
|
GList *sockaddrs;
|
||||||
gchar *scheme;
|
gchar *scheme;
|
||||||
|
|
||||||
|
gint64 resolver_serial;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -226,7 +228,8 @@ g_network_address_get_property (GObject *object,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
g_network_address_set_addresses (GNetworkAddress *addr,
|
g_network_address_set_addresses (GNetworkAddress *addr,
|
||||||
GList *addresses)
|
GList *addresses,
|
||||||
|
guint64 resolver_serial)
|
||||||
{
|
{
|
||||||
GList *a;
|
GList *a;
|
||||||
GSocketAddress *sockaddr;
|
GSocketAddress *sockaddr;
|
||||||
@ -241,6 +244,8 @@ g_network_address_set_addresses (GNetworkAddress *addr,
|
|||||||
}
|
}
|
||||||
g_list_free (addresses);
|
g_list_free (addresses);
|
||||||
addr->priv->sockaddrs = g_list_reverse (addr->priv->sockaddrs);
|
addr->priv->sockaddrs = g_list_reverse (addr->priv->sockaddrs);
|
||||||
|
|
||||||
|
addr->priv->resolver_serial = resolver_serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -846,26 +851,39 @@ g_network_address_address_enumerator_next (GSocketAddressEnumerator *enumerator
|
|||||||
|
|
||||||
if (addr_enum->addresses == NULL)
|
if (addr_enum->addresses == NULL)
|
||||||
{
|
{
|
||||||
if (!addr_enum->addr->priv->sockaddrs)
|
GNetworkAddress *addr = addr_enum->addr;
|
||||||
g_network_address_parse_sockaddr (addr_enum->addr);
|
GResolver *resolver = g_resolver_get_default ();
|
||||||
if (!addr_enum->addr->priv->sockaddrs)
|
gint64 serial = g_resolver_get_serial (resolver);
|
||||||
|
|
||||||
|
if (addr->priv->resolver_serial != 0 &&
|
||||||
|
addr->priv->resolver_serial != serial)
|
||||||
|
{
|
||||||
|
/* Resolver has reloaded, discard cached addresses */
|
||||||
|
g_list_free_full (addr->priv->sockaddrs, g_object_unref);
|
||||||
|
addr->priv->sockaddrs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addr->priv->sockaddrs)
|
||||||
|
g_network_address_parse_sockaddr (addr);
|
||||||
|
if (!addr->priv->sockaddrs)
|
||||||
{
|
{
|
||||||
GResolver *resolver = g_resolver_get_default ();
|
|
||||||
GList *addresses;
|
GList *addresses;
|
||||||
|
|
||||||
addresses = g_resolver_lookup_by_name (resolver,
|
addresses = g_resolver_lookup_by_name (resolver,
|
||||||
addr_enum->addr->priv->hostname,
|
addr->priv->hostname,
|
||||||
cancellable, error);
|
cancellable, error);
|
||||||
g_object_unref (resolver);
|
|
||||||
|
|
||||||
if (!addresses)
|
if (!addresses)
|
||||||
return NULL;
|
{
|
||||||
|
g_object_unref (resolver);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_network_address_set_addresses (addr_enum->addr, addresses);
|
g_network_address_set_addresses (addr, addresses, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_enum->addresses = addr_enum->addr->priv->sockaddrs;
|
addr_enum->addresses = addr->priv->sockaddrs;
|
||||||
addr_enum->next = addr_enum->addresses;
|
addr_enum->next = addr_enum->addresses;
|
||||||
|
g_object_unref (resolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr_enum->next == NULL)
|
if (addr_enum->next == NULL)
|
||||||
@ -916,7 +934,10 @@ got_addresses (GObject *source_object,
|
|||||||
addresses = g_resolver_lookup_by_name_finish (resolver, result, &error);
|
addresses = g_resolver_lookup_by_name_finish (resolver, result, &error);
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
g_network_address_set_addresses (addr_enum->addr, addresses);
|
{
|
||||||
|
g_network_address_set_addresses (addr_enum->addr, addresses,
|
||||||
|
g_resolver_get_serial (resolver));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
have_addresses (addr_enum, task, error);
|
have_addresses (addr_enum, task, error);
|
||||||
}
|
}
|
||||||
@ -936,25 +957,36 @@ g_network_address_address_enumerator_next_async (GSocketAddressEnumerator *enum
|
|||||||
|
|
||||||
if (addr_enum->addresses == NULL)
|
if (addr_enum->addresses == NULL)
|
||||||
{
|
{
|
||||||
if (!addr_enum->addr->priv->sockaddrs)
|
GNetworkAddress *addr = addr_enum->addr;
|
||||||
|
GResolver *resolver = g_resolver_get_default ();
|
||||||
|
gint64 serial = g_resolver_get_serial (resolver);
|
||||||
|
|
||||||
|
if (addr->priv->resolver_serial != 0 &&
|
||||||
|
addr->priv->resolver_serial != serial)
|
||||||
{
|
{
|
||||||
if (g_network_address_parse_sockaddr (addr_enum->addr))
|
/* Resolver has reloaded, discard cached addresses */
|
||||||
|
g_list_free_full (addr->priv->sockaddrs, g_object_unref);
|
||||||
|
addr->priv->sockaddrs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addr->priv->sockaddrs)
|
||||||
|
{
|
||||||
|
if (g_network_address_parse_sockaddr (addr))
|
||||||
have_addresses (addr_enum, task, NULL);
|
have_addresses (addr_enum, task, NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GResolver *resolver = g_resolver_get_default ();
|
|
||||||
|
|
||||||
g_resolver_lookup_by_name_async (resolver,
|
g_resolver_lookup_by_name_async (resolver,
|
||||||
addr_enum->addr->priv->hostname,
|
addr->priv->hostname,
|
||||||
cancellable,
|
cancellable,
|
||||||
got_addresses, task);
|
got_addresses, task);
|
||||||
g_object_unref (resolver);
|
|
||||||
}
|
}
|
||||||
|
g_object_unref (resolver);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_enum->addresses = addr_enum->addr->priv->sockaddrs;
|
addr_enum->addresses = addr->priv->sockaddrs;
|
||||||
addr_enum->next = addr_enum->addresses;
|
addr_enum->next = addr_enum->addresses;
|
||||||
|
g_object_unref (resolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr_enum->next)
|
if (addr_enum->next)
|
||||||
|
@ -34,6 +34,8 @@ gchar * _g_uri_from_authority (const gchar *protocol,
|
|||||||
guint port,
|
guint port,
|
||||||
const gchar *userinfo);
|
const gchar *userinfo);
|
||||||
|
|
||||||
|
guint64 g_resolver_get_serial (GResolver *resolver);
|
||||||
|
|
||||||
gint g_socket (gint domain,
|
gint g_socket (gint domain,
|
||||||
gint type,
|
gint type,
|
||||||
gint protocol,
|
gint protocol,
|
||||||
|
@ -846,6 +846,20 @@ g_resolver_lookup_records_finish (GResolver *resolver,
|
|||||||
lookup_records_finish (resolver, result, error);
|
lookup_records_finish (resolver, result, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint64
|
||||||
|
g_resolver_get_serial (GResolver *resolver)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_RESOLVER (resolver), 0);
|
||||||
|
|
||||||
|
g_resolver_maybe_reload (resolver);
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
return (guint64) resolver->priv->resolv_conf_timestamp;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_resolver_error_quark:
|
* g_resolver_error_quark:
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user