• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2  
3  /* GIO - GLib Input, Output and Streaming Library
4   *
5   * Copyright (C) 2008 Red Hat, Inc.
6   * Copyright (C) 2018 Igalia S.L.
7   *
8   * This library is free software; you can redistribute it and/or
9   * modify it under the terms of the GNU Lesser General Public
10   * License as published by the Free Software Foundation; either
11   * version 2.1 of the License, or (at your option) any later version.
12   *
13   * This library is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   * Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General
19   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20   */
21  
22  #include "config.h"
23  #include <glib.h>
24  #include "glibintl.h"
25  
26  #include "gresolver.h"
27  #include "gnetworkingprivate.h"
28  #include "gasyncresult.h"
29  #include "ginetaddress.h"
30  #include "gtask.h"
31  #include "gsrvtarget.h"
32  #include "gthreadedresolver.h"
33  #include "gioerror.h"
34  #include "gcancellable.h"
35  
36  #ifdef G_OS_UNIX
37  #include <sys/stat.h>
38  #endif
39  
40  #include <stdlib.h>
41  
42  
43  /**
44   * SECTION:gresolver
45   * @short_description: Asynchronous and cancellable DNS resolver
46   * @include: gio/gio.h
47   *
48   * #GResolver provides cancellable synchronous and asynchronous DNS
49   * resolution, for hostnames (g_resolver_lookup_by_address(),
50   * g_resolver_lookup_by_name() and their async variants) and SRV
51   * (service) records (g_resolver_lookup_service()).
52   *
53   * #GNetworkAddress and #GNetworkService provide wrappers around
54   * #GResolver functionality that also implement #GSocketConnectable,
55   * making it easy to connect to a remote host/service.
56   */
57  
58  enum {
59    RELOAD,
60    LAST_SIGNAL
61  };
62  
63  static guint signals[LAST_SIGNAL] = { 0 };
64  
65  struct _GResolverPrivate {
66  #ifdef G_OS_UNIX
67    time_t resolv_conf_timestamp;
68  #else
69    int dummy;
70  #endif
71  };
72  
73  /**
74   * GResolver:
75   *
76   * The object that handles DNS resolution. Use g_resolver_get_default()
77   * to get the default resolver.
78   *
79   * This is an abstract type; subclasses of it implement different resolvers for
80   * different platforms and situations.
81   */
G_DEFINE_ABSTRACT_TYPE_WITH_CODE(GResolver,g_resolver,G_TYPE_OBJECT,G_ADD_PRIVATE (GResolver)g_networking_init ();)82  G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GResolver, g_resolver, G_TYPE_OBJECT,
83                                    G_ADD_PRIVATE (GResolver)
84                                    g_networking_init ();)
85  
86  static GList *
87  srv_records_to_targets (GList *records)
88  {
89    const gchar *hostname;
90    guint16 port, priority, weight;
91    GSrvTarget *target;
92    GList *l;
93  
94    for (l = records; l != NULL; l = g_list_next (l))
95      {
96        g_variant_get (l->data, "(qqq&s)", &priority, &weight, &port, &hostname);
97        target = g_srv_target_new (hostname, port, priority, weight);
98        g_variant_unref (l->data);
99        l->data = target;
100      }
101  
102    return g_srv_target_list_sort (records);
103  }
104  
105  static GList *
g_resolver_real_lookup_service(GResolver * resolver,const gchar * rrname,GCancellable * cancellable,GError ** error)106  g_resolver_real_lookup_service (GResolver            *resolver,
107                                  const gchar          *rrname,
108                                  GCancellable         *cancellable,
109                                  GError              **error)
110  {
111    GList *records;
112  
113    records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver,
114                                                               rrname,
115                                                               G_RESOLVER_RECORD_SRV,
116                                                               cancellable,
117                                                               error);
118  
119    return srv_records_to_targets (records);
120  }
121  
122  static void
g_resolver_real_lookup_service_async(GResolver * resolver,const gchar * rrname,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)123  g_resolver_real_lookup_service_async (GResolver            *resolver,
124                                        const gchar          *rrname,
125                                        GCancellable         *cancellable,
126                                        GAsyncReadyCallback   callback,
127                                        gpointer              user_data)
128  {
129    G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver,
130                                                           rrname,
131                                                           G_RESOLVER_RECORD_SRV,
132                                                           cancellable,
133                                                           callback,
134                                                           user_data);
135  }
136  
137  static GList *
g_resolver_real_lookup_service_finish(GResolver * resolver,GAsyncResult * result,GError ** error)138  g_resolver_real_lookup_service_finish (GResolver            *resolver,
139                                         GAsyncResult         *result,
140                                         GError              **error)
141  {
142    GList *records;
143  
144    records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver,
145                                                                      result,
146                                                                      error);
147  
148    return srv_records_to_targets (records);
149  }
150  
151  static void
g_resolver_class_init(GResolverClass * resolver_class)152  g_resolver_class_init (GResolverClass *resolver_class)
153  {
154    /* Automatically pass these over to the lookup_records methods */
155    resolver_class->lookup_service = g_resolver_real_lookup_service;
156    resolver_class->lookup_service_async = g_resolver_real_lookup_service_async;
157    resolver_class->lookup_service_finish = g_resolver_real_lookup_service_finish;
158  
159    /**
160     * GResolver::reload:
161     * @resolver: a #GResolver
162     *
163     * Emitted when the resolver notices that the system resolver
164     * configuration has changed.
165     **/
166    signals[RELOAD] =
167      g_signal_new (I_("reload"),
168  		  G_TYPE_RESOLVER,
169  		  G_SIGNAL_RUN_LAST,
170  		  G_STRUCT_OFFSET (GResolverClass, reload),
171  		  NULL, NULL,
172  		  NULL,
173  		  G_TYPE_NONE, 0);
174  }
175  
176  static void
g_resolver_init(GResolver * resolver)177  g_resolver_init (GResolver *resolver)
178  {
179  #ifdef G_OS_UNIX
180    struct stat st;
181  #endif
182  
183    resolver->priv = g_resolver_get_instance_private (resolver);
184  
185  #ifdef G_OS_UNIX
186    if (stat (_PATH_RESCONF, &st) == 0)
187      resolver->priv->resolv_conf_timestamp = st.st_mtime;
188  #endif
189  }
190  
191  G_LOCK_DEFINE_STATIC (default_resolver);
192  static GResolver *default_resolver;
193  
194  /**
195   * g_resolver_get_default:
196   *
197   * Gets the default #GResolver. You should unref it when you are done
198   * with it. #GResolver may use its reference count as a hint about how
199   * many threads it should allocate for concurrent DNS resolutions.
200   *
201   * Returns: (transfer full): the default #GResolver.
202   *
203   * Since: 2.22
204   */
205  GResolver *
g_resolver_get_default(void)206  g_resolver_get_default (void)
207  {
208    GResolver *ret;
209  
210    G_LOCK (default_resolver);
211    if (!default_resolver)
212      default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL);
213    ret = g_object_ref (default_resolver);
214    G_UNLOCK (default_resolver);
215  
216    return ret;
217  }
218  
219  /**
220   * g_resolver_set_default:
221   * @resolver: the new default #GResolver
222   *
223   * Sets @resolver to be the application's default resolver (reffing
224   * @resolver, and unreffing the previous default resolver, if any).
225   * Future calls to g_resolver_get_default() will return this resolver.
226   *
227   * This can be used if an application wants to perform any sort of DNS
228   * caching or "pinning"; it can implement its own #GResolver that
229   * calls the original default resolver for DNS operations, and
230   * implements its own cache policies on top of that, and then set
231   * itself as the default resolver for all later code to use.
232   *
233   * Since: 2.22
234   */
235  void
g_resolver_set_default(GResolver * resolver)236  g_resolver_set_default (GResolver *resolver)
237  {
238    G_LOCK (default_resolver);
239    if (default_resolver)
240      g_object_unref (default_resolver);
241    default_resolver = g_object_ref (resolver);
242    G_UNLOCK (default_resolver);
243  }
244  
245  /* Bionic has res_init() but it's not in any header */
246  #ifdef __BIONIC__
247  int res_init (void);
248  #endif
249  
250  static void
g_resolver_maybe_reload(GResolver * resolver)251  g_resolver_maybe_reload (GResolver *resolver)
252  {
253  #ifdef G_OS_UNIX
254    struct stat st;
255  
256    if (stat (_PATH_RESCONF, &st) == 0)
257      {
258        if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
259          {
260            resolver->priv->resolv_conf_timestamp = st.st_mtime;
261  #ifdef HAVE_RES_INIT
262            res_init ();
263  #endif
264            g_signal_emit (resolver, signals[RELOAD], 0);
265          }
266      }
267  #endif
268  }
269  
270  /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
271  static void
remove_duplicates(GList * addrs)272  remove_duplicates (GList *addrs)
273  {
274    GList *l;
275    GList *ll;
276    GList *lll;
277  
278    /* TODO: if this is too slow (it's O(n^2) but n is typically really
279     * small), we can do something more clever but note that we must not
280     * change the order of elements...
281     */
282    for (l = addrs; l != NULL; l = l->next)
283      {
284        GInetAddress *address = G_INET_ADDRESS (l->data);
285        for (ll = l->next; ll != NULL; ll = lll)
286          {
287            GInetAddress *other_address = G_INET_ADDRESS (ll->data);
288            lll = ll->next;
289            if (g_inet_address_equal (address, other_address))
290              {
291                g_object_unref (other_address);
292                /* we never return the first element */
293                g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs);
294              }
295          }
296      }
297  }
298  
299  static gboolean
hostname_is_localhost(const char * hostname)300  hostname_is_localhost (const char *hostname)
301  {
302    size_t len = strlen (hostname);
303    const char *p;
304  
305    /* Match "localhost", "localhost.", "*.localhost" and "*.localhost." */
306    if (len < strlen ("localhost"))
307      return FALSE;
308  
309    if (hostname[len - 1] == '.')
310        len--;
311  
312    /* Scan backwards in @hostname to find the right-most dot (excluding the final dot, if it exists, as it was chopped off above).
313     * We can’t use strrchr() because because we need to operate with string lengths.
314     * End with @p pointing to the character after the right-most dot. */
315    p = hostname + len - 1;
316    while (p >= hostname)
317      {
318        if (*p == '.')
319         {
320           p++;
321           break;
322         }
323        else if (p == hostname)
324          break;
325        p--;
326      }
327  
328    len -= p - hostname;
329  
330    return g_ascii_strncasecmp (p, "localhost", MAX (len, strlen ("localhost"))) == 0;
331  }
332  
333  /* Note that this does not follow the "FALSE means @error is set"
334   * convention. The return value tells the caller whether it should
335   * return @addrs and @error to the caller right away, or if it should
336   * continue and trying to resolve the name as a hostname.
337   */
338  static gboolean
handle_ip_address_or_localhost(const char * hostname,GList ** addrs,GResolverNameLookupFlags flags,GError ** error)339  handle_ip_address_or_localhost (const char                *hostname,
340                                  GList                    **addrs,
341                                  GResolverNameLookupFlags   flags,
342                                  GError                   **error)
343  {
344    GInetAddress *addr;
345  
346  #ifndef G_OS_WIN32
347    struct in_addr ip4addr;
348  #endif
349  
350    addr = g_inet_address_new_from_string (hostname);
351    if (addr)
352      {
353        *addrs = g_list_append (NULL, addr);
354        return TRUE;
355      }
356  
357    *addrs = NULL;
358  
359  #ifdef G_OS_WIN32
360  
361    /* Reject IPv6 addresses that have brackets ('[' or ']') and/or port numbers,
362     * as no valid addresses should contain these at this point.
363     * Non-standard IPv4 addresses would be rejected during the call to
364     * getaddrinfo() later.
365     */
366    if (strrchr (hostname, '[') != NULL ||
367        strrchr (hostname, ']') != NULL)
368  #else
369  
370    /* Reject non-standard IPv4 numbers-and-dots addresses.
371     * g_inet_address_new_from_string() will have accepted any "real" IP
372     * address, so if inet_aton() succeeds, then it's an address we want
373     * to reject.
374     */
375    if (inet_aton (hostname, &ip4addr))
376  #endif
377      {
378  #ifdef G_OS_WIN32
379        gchar *error_message = g_win32_error_message (WSAHOST_NOT_FOUND);
380  #else
381        gchar *error_message = g_locale_to_utf8 (gai_strerror (EAI_NONAME), -1, NULL, NULL, NULL);
382        if (error_message == NULL)
383          error_message = g_strdup ("[Invalid UTF-8]");
384  #endif
385        g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
386                     _("Error resolving “%s”: %s"),
387                     hostname, error_message);
388        g_free (error_message);
389  
390        return TRUE;
391      }
392  
393    /* Always resolve localhost to a loopback address so it can be reliably considered secure.
394       This behavior is being adopted by browsers:
395       - https://w3c.github.io/webappsec-secure-contexts/
396       - https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/RC9dSw-O3fE/E3_0XaT0BAAJ
397       - https://chromium.googlesource.com/chromium/src.git/+/8da2a80724a9b896890602ff77ef2216cb951399
398       - https://bugs.webkit.org/show_bug.cgi?id=171934
399       - https://tools.ietf.org/html/draft-west-let-localhost-be-localhost-06
400    */
401    if (hostname_is_localhost (hostname))
402      {
403        if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY)
404          *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6));
405        if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY)
406          *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4));
407        if (*addrs == NULL)
408          {
409            *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6));
410            *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4));
411          }
412        return TRUE;
413      }
414  
415    return FALSE;
416  }
417  
418  static GList *
lookup_by_name_real(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GError ** error)419  lookup_by_name_real (GResolver                 *resolver,
420                       const gchar               *hostname,
421                       GResolverNameLookupFlags   flags,
422                       GCancellable              *cancellable,
423                       GError                    **error)
424  {
425    GList *addrs;
426    gchar *ascii_hostname = NULL;
427  
428    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
429    g_return_val_if_fail (hostname != NULL, NULL);
430    g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
431    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
432  
433    /* Check if @hostname is just an IP address */
434    if (handle_ip_address_or_localhost (hostname, &addrs, flags, error))
435      return addrs;
436  
437    if (g_hostname_is_non_ascii (hostname))
438      hostname = ascii_hostname = g_hostname_to_ascii (hostname);
439  
440    if (!hostname)
441      {
442        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
443                             _("Invalid hostname"));
444        return NULL;
445      }
446  
447    g_resolver_maybe_reload (resolver);
448  
449    if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
450      {
451        if (!G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags)
452          {
453            g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
454                         /* Translators: The placeholder is for a function name. */
455                         _("%s not implemented"), "lookup_by_name_with_flags");
456            g_free (ascii_hostname);
457            return NULL;
458          }
459        addrs = G_RESOLVER_GET_CLASS (resolver)->
460          lookup_by_name_with_flags (resolver, hostname, flags, cancellable, error);
461      }
462    else
463      addrs = G_RESOLVER_GET_CLASS (resolver)->
464        lookup_by_name (resolver, hostname, cancellable, error);
465  
466    remove_duplicates (addrs);
467  
468    g_free (ascii_hostname);
469    return addrs;
470  }
471  
472  /**
473   * g_resolver_lookup_by_name:
474   * @resolver: a #GResolver
475   * @hostname: the hostname to look up
476   * @cancellable: (nullable): a #GCancellable, or %NULL
477   * @error: return location for a #GError, or %NULL
478   *
479   * Synchronously resolves @hostname to determine its associated IP
480   * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
481   * the textual form of an IP address (in which case this just becomes
482   * a wrapper around g_inet_address_new_from_string()).
483   *
484   * On success, g_resolver_lookup_by_name() will return a non-empty #GList of
485   * #GInetAddress, sorted in order of preference and guaranteed to not
486   * contain duplicates. That is, if using the result to connect to
487   * @hostname, you should attempt to connect to the first address
488   * first, then the second if the first fails, etc. If you are using
489   * the result to listen on a socket, it is appropriate to add each
490   * result using e.g. g_socket_listener_add_address().
491   *
492   * If the DNS resolution fails, @error (if non-%NULL) will be set to a
493   * value from #GResolverError and %NULL will be returned.
494   *
495   * If @cancellable is non-%NULL, it can be used to cancel the
496   * operation, in which case @error (if non-%NULL) will be set to
497   * %G_IO_ERROR_CANCELLED.
498   *
499   * If you are planning to connect to a socket on the resolved IP
500   * address, it may be easier to create a #GNetworkAddress and use its
501   * #GSocketConnectable interface.
502   *
503   * Returns: (element-type GInetAddress) (transfer full): a non-empty #GList
504   * of #GInetAddress, or %NULL on error. You
505   * must unref each of the addresses and free the list when you are
506   * done with it. (You can use g_resolver_free_addresses() to do this.)
507   *
508   * Since: 2.22
509   */
510  GList *
g_resolver_lookup_by_name(GResolver * resolver,const gchar * hostname,GCancellable * cancellable,GError ** error)511  g_resolver_lookup_by_name (GResolver     *resolver,
512                             const gchar   *hostname,
513                             GCancellable  *cancellable,
514                             GError       **error)
515  {
516    return lookup_by_name_real (resolver,
517                                hostname,
518                                G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT,
519                                cancellable,
520                                error);
521  }
522  
523  /**
524   * g_resolver_lookup_by_name_with_flags:
525   * @resolver: a #GResolver
526   * @hostname: the hostname to look up
527   * @flags: extra #GResolverNameLookupFlags for the lookup
528   * @cancellable: (nullable): a #GCancellable, or %NULL
529   * @error: (nullable): return location for a #GError, or %NULL
530   *
531   * This differs from g_resolver_lookup_by_name() in that you can modify
532   * the lookup behavior with @flags. For example this can be used to limit
533   * results with #G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY.
534   *
535   * Returns: (element-type GInetAddress) (transfer full): a non-empty #GList
536   * of #GInetAddress, or %NULL on error. You
537   * must unref each of the addresses and free the list when you are
538   * done with it. (You can use g_resolver_free_addresses() to do this.)
539   *
540   * Since: 2.60
541   */
542  GList *
g_resolver_lookup_by_name_with_flags(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GError ** error)543  g_resolver_lookup_by_name_with_flags (GResolver                 *resolver,
544                                        const gchar               *hostname,
545                                        GResolverNameLookupFlags   flags,
546                                        GCancellable              *cancellable,
547                                        GError                   **error)
548  {
549    return lookup_by_name_real (resolver,
550                                hostname,
551                                flags,
552                                cancellable,
553                                error);
554  }
555  
556  static void
lookup_by_name_async_real(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)557  lookup_by_name_async_real (GResolver                *resolver,
558                             const gchar              *hostname,
559                             GResolverNameLookupFlags  flags,
560                             GCancellable             *cancellable,
561                             GAsyncReadyCallback       callback,
562                             gpointer                  user_data)
563  {
564    gchar *ascii_hostname = NULL;
565    GList *addrs;
566    GError *error = NULL;
567  
568    g_return_if_fail (G_IS_RESOLVER (resolver));
569    g_return_if_fail (hostname != NULL);
570    g_return_if_fail (!(flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY && flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY));
571  
572    /* Check if @hostname is just an IP address */
573    if (handle_ip_address_or_localhost (hostname, &addrs, flags, &error))
574      {
575        GTask *task;
576  
577        task = g_task_new (resolver, cancellable, callback, user_data);
578        g_task_set_source_tag (task, lookup_by_name_async_real);
579        g_task_set_name (task, "[gio] resolver lookup");
580        if (addrs)
581          g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses);
582        else
583          g_task_return_error (task, error);
584        g_object_unref (task);
585        return;
586      }
587  
588    if (g_hostname_is_non_ascii (hostname))
589      hostname = ascii_hostname = g_hostname_to_ascii (hostname);
590  
591    if (!hostname)
592      {
593        GTask *task;
594  
595        g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
596                             _("Invalid hostname"));
597        task = g_task_new (resolver, cancellable, callback, user_data);
598        g_task_set_source_tag (task, lookup_by_name_async_real);
599        g_task_set_name (task, "[gio] resolver lookup");
600        g_task_return_error (task, error);
601        g_object_unref (task);
602        return;
603      }
604  
605    g_resolver_maybe_reload (resolver);
606  
607    if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
608      {
609        if (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_async == NULL)
610          {
611            GTask *task;
612  
613            g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
614                         /* Translators: The placeholder is for a function name. */
615                         _("%s not implemented"), "lookup_by_name_with_flags_async");
616            task = g_task_new (resolver, cancellable, callback, user_data);
617            g_task_set_source_tag (task, lookup_by_name_async_real);
618            g_task_set_name (task, "[gio] resolver lookup");
619            g_task_return_error (task, error);
620            g_object_unref (task);
621          }
622        else
623          G_RESOLVER_GET_CLASS (resolver)->
624            lookup_by_name_with_flags_async (resolver, hostname, flags, cancellable, callback, user_data);
625      }
626    else
627      G_RESOLVER_GET_CLASS (resolver)->
628        lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
629  
630    g_free (ascii_hostname);
631  }
632  
633  static GList *
lookup_by_name_finish_real(GResolver * resolver,GAsyncResult * result,GError ** error,gboolean with_flags)634  lookup_by_name_finish_real (GResolver     *resolver,
635                              GAsyncResult  *result,
636                              GError       **error,
637                              gboolean       with_flags)
638  {
639    GList *addrs;
640  
641    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
642    g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
643    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
644  
645    if (g_async_result_legacy_propagate_error (result, error))
646      return NULL;
647    else if (g_async_result_is_tagged (result, lookup_by_name_async_real))
648      {
649        /* Handle the stringified-IP-addr case */
650        return g_task_propagate_pointer (G_TASK (result), error);
651      }
652  
653    if (with_flags)
654      {
655        g_assert (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_finish != NULL);
656        addrs = G_RESOLVER_GET_CLASS (resolver)->
657          lookup_by_name_with_flags_finish (resolver, result, error);
658      }
659    else
660      addrs = G_RESOLVER_GET_CLASS (resolver)->
661        lookup_by_name_finish (resolver, result, error);
662  
663    remove_duplicates (addrs);
664  
665    return addrs;
666  }
667  
668  /**
669   * g_resolver_lookup_by_name_with_flags_async:
670   * @resolver: a #GResolver
671   * @hostname: the hostname to look up the address of
672   * @flags: extra #GResolverNameLookupFlags for the lookup
673   * @cancellable: (nullable): a #GCancellable, or %NULL
674   * @callback: (scope async): callback to call after resolution completes
675   * @user_data: (closure): data for @callback
676   *
677   * Begins asynchronously resolving @hostname to determine its
678   * associated IP address(es), and eventually calls @callback, which
679   * must call g_resolver_lookup_by_name_with_flags_finish() to get the result.
680   * See g_resolver_lookup_by_name() for more details.
681   *
682   * Since: 2.60
683   */
684  void
g_resolver_lookup_by_name_with_flags_async(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)685  g_resolver_lookup_by_name_with_flags_async (GResolver                *resolver,
686                                              const gchar              *hostname,
687                                              GResolverNameLookupFlags  flags,
688                                              GCancellable             *cancellable,
689                                              GAsyncReadyCallback       callback,
690                                              gpointer                  user_data)
691  {
692    lookup_by_name_async_real (resolver,
693                               hostname,
694                               flags,
695                               cancellable,
696                               callback,
697                               user_data);
698  }
699  
700  /**
701   * g_resolver_lookup_by_name_async:
702   * @resolver: a #GResolver
703   * @hostname: the hostname to look up the address of
704   * @cancellable: (nullable): a #GCancellable, or %NULL
705   * @callback: (scope async): callback to call after resolution completes
706   * @user_data: (closure): data for @callback
707   *
708   * Begins asynchronously resolving @hostname to determine its
709   * associated IP address(es), and eventually calls @callback, which
710   * must call g_resolver_lookup_by_name_finish() to get the result.
711   * See g_resolver_lookup_by_name() for more details.
712   *
713   * Since: 2.22
714   */
715  void
g_resolver_lookup_by_name_async(GResolver * resolver,const gchar * hostname,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)716  g_resolver_lookup_by_name_async (GResolver           *resolver,
717                                   const gchar         *hostname,
718                                   GCancellable        *cancellable,
719                                   GAsyncReadyCallback  callback,
720                                   gpointer             user_data)
721  {
722    lookup_by_name_async_real (resolver,
723                               hostname,
724                               0,
725                               cancellable,
726                               callback,
727                               user_data);
728  }
729  
730  /**
731   * g_resolver_lookup_by_name_finish:
732   * @resolver: a #GResolver
733   * @result: the result passed to your #GAsyncReadyCallback
734   * @error: return location for a #GError, or %NULL
735   *
736   * Retrieves the result of a call to
737   * g_resolver_lookup_by_name_async().
738   *
739   * If the DNS resolution failed, @error (if non-%NULL) will be set to
740   * a value from #GResolverError. If the operation was cancelled,
741   * @error will be set to %G_IO_ERROR_CANCELLED.
742   *
743   * Returns: (element-type GInetAddress) (transfer full): a #GList
744   * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
745   * for more details.
746   *
747   * Since: 2.22
748   */
749  GList *
g_resolver_lookup_by_name_finish(GResolver * resolver,GAsyncResult * result,GError ** error)750  g_resolver_lookup_by_name_finish (GResolver     *resolver,
751                                    GAsyncResult  *result,
752                                    GError       **error)
753  {
754    return lookup_by_name_finish_real (resolver,
755                                       result,
756                                       error,
757                                       FALSE);
758  }
759  
760  /**
761   * g_resolver_lookup_by_name_with_flags_finish:
762   * @resolver: a #GResolver
763   * @result: the result passed to your #GAsyncReadyCallback
764   * @error: return location for a #GError, or %NULL
765   *
766   * Retrieves the result of a call to
767   * g_resolver_lookup_by_name_with_flags_async().
768   *
769   * If the DNS resolution failed, @error (if non-%NULL) will be set to
770   * a value from #GResolverError. If the operation was cancelled,
771   * @error will be set to %G_IO_ERROR_CANCELLED.
772   *
773   * Returns: (element-type GInetAddress) (transfer full): a #GList
774   * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
775   * for more details.
776   *
777   * Since: 2.60
778   */
779  GList *
g_resolver_lookup_by_name_with_flags_finish(GResolver * resolver,GAsyncResult * result,GError ** error)780  g_resolver_lookup_by_name_with_flags_finish (GResolver     *resolver,
781                                               GAsyncResult  *result,
782                                               GError       **error)
783  {
784    return lookup_by_name_finish_real (resolver,
785                                       result,
786                                       error,
787                                       TRUE);
788  }
789  
790  /**
791   * g_resolver_free_addresses: (skip)
792   * @addresses: a #GList of #GInetAddress
793   *
794   * Frees @addresses (which should be the return value from
795   * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
796   * (This is a convenience method; you can also simply free the results
797   * by hand.)
798   *
799   * Since: 2.22
800   */
801  void
g_resolver_free_addresses(GList * addresses)802  g_resolver_free_addresses (GList *addresses)
803  {
804    GList *a;
805  
806    for (a = addresses; a; a = a->next)
807      g_object_unref (a->data);
808    g_list_free (addresses);
809  }
810  
811  /**
812   * g_resolver_lookup_by_address:
813   * @resolver: a #GResolver
814   * @address: the address to reverse-resolve
815   * @cancellable: (nullable): a #GCancellable, or %NULL
816   * @error: return location for a #GError, or %NULL
817   *
818   * Synchronously reverse-resolves @address to determine its
819   * associated hostname.
820   *
821   * If the DNS resolution fails, @error (if non-%NULL) will be set to
822   * a value from #GResolverError.
823   *
824   * If @cancellable is non-%NULL, it can be used to cancel the
825   * operation, in which case @error (if non-%NULL) will be set to
826   * %G_IO_ERROR_CANCELLED.
827   *
828   * Returns: a hostname (either ASCII-only, or in ASCII-encoded
829   *     form), or %NULL on error.
830   *
831   * Since: 2.22
832   */
833  gchar *
g_resolver_lookup_by_address(GResolver * resolver,GInetAddress * address,GCancellable * cancellable,GError ** error)834  g_resolver_lookup_by_address (GResolver     *resolver,
835                                GInetAddress  *address,
836                                GCancellable  *cancellable,
837                                GError       **error)
838  {
839    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
840    g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
841  
842    g_resolver_maybe_reload (resolver);
843    return G_RESOLVER_GET_CLASS (resolver)->
844      lookup_by_address (resolver, address, cancellable, error);
845  }
846  
847  /**
848   * g_resolver_lookup_by_address_async:
849   * @resolver: a #GResolver
850   * @address: the address to reverse-resolve
851   * @cancellable: (nullable): a #GCancellable, or %NULL
852   * @callback: (scope async): callback to call after resolution completes
853   * @user_data: (closure): data for @callback
854   *
855   * Begins asynchronously reverse-resolving @address to determine its
856   * associated hostname, and eventually calls @callback, which must
857   * call g_resolver_lookup_by_address_finish() to get the final result.
858   *
859   * Since: 2.22
860   */
861  void
g_resolver_lookup_by_address_async(GResolver * resolver,GInetAddress * address,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)862  g_resolver_lookup_by_address_async (GResolver           *resolver,
863                                      GInetAddress        *address,
864                                      GCancellable        *cancellable,
865                                      GAsyncReadyCallback  callback,
866                                      gpointer             user_data)
867  {
868    g_return_if_fail (G_IS_RESOLVER (resolver));
869    g_return_if_fail (G_IS_INET_ADDRESS (address));
870  
871    g_resolver_maybe_reload (resolver);
872    G_RESOLVER_GET_CLASS (resolver)->
873      lookup_by_address_async (resolver, address, cancellable, callback, user_data);
874  }
875  
876  /**
877   * g_resolver_lookup_by_address_finish:
878   * @resolver: a #GResolver
879   * @result: the result passed to your #GAsyncReadyCallback
880   * @error: return location for a #GError, or %NULL
881   *
882   * Retrieves the result of a previous call to
883   * g_resolver_lookup_by_address_async().
884   *
885   * If the DNS resolution failed, @error (if non-%NULL) will be set to
886   * a value from #GResolverError. If the operation was cancelled,
887   * @error will be set to %G_IO_ERROR_CANCELLED.
888   *
889   * Returns: a hostname (either ASCII-only, or in ASCII-encoded
890   * form), or %NULL on error.
891   *
892   * Since: 2.22
893   */
894  gchar *
g_resolver_lookup_by_address_finish(GResolver * resolver,GAsyncResult * result,GError ** error)895  g_resolver_lookup_by_address_finish (GResolver     *resolver,
896                                       GAsyncResult  *result,
897                                       GError       **error)
898  {
899    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
900  
901    if (g_async_result_legacy_propagate_error (result, error))
902      return NULL;
903  
904    return G_RESOLVER_GET_CLASS (resolver)->
905      lookup_by_address_finish (resolver, result, error);
906  }
907  
908  static gchar *
g_resolver_get_service_rrname(const char * service,const char * protocol,const char * domain)909  g_resolver_get_service_rrname (const char *service,
910                                 const char *protocol,
911                                 const char *domain)
912  {
913    gchar *rrname, *ascii_domain = NULL;
914  
915    if (g_hostname_is_non_ascii (domain))
916      domain = ascii_domain = g_hostname_to_ascii (domain);
917    if (!domain)
918      return NULL;
919  
920    rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
921  
922    g_free (ascii_domain);
923    return rrname;
924  }
925  
926  /**
927   * g_resolver_lookup_service:
928   * @resolver: a #GResolver
929   * @service: the service type to look up (eg, "ldap")
930   * @protocol: the networking protocol to use for @service (eg, "tcp")
931   * @domain: the DNS domain to look up the service in
932   * @cancellable: (nullable): a #GCancellable, or %NULL
933   * @error: return location for a #GError, or %NULL
934   *
935   * Synchronously performs a DNS SRV lookup for the given @service and
936   * @protocol in the given @domain and returns an array of #GSrvTarget.
937   * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
938   * @service and @protocol arguments do not include the leading underscore
939   * that appears in the actual DNS entry.
940   *
941   * On success, g_resolver_lookup_service() will return a non-empty #GList of
942   * #GSrvTarget, sorted in order of preference. (That is, you should
943   * attempt to connect to the first target first, then the second if
944   * the first fails, etc.)
945   *
946   * If the DNS resolution fails, @error (if non-%NULL) will be set to
947   * a value from #GResolverError and %NULL will be returned.
948   *
949   * If @cancellable is non-%NULL, it can be used to cancel the
950   * operation, in which case @error (if non-%NULL) will be set to
951   * %G_IO_ERROR_CANCELLED.
952   *
953   * If you are planning to connect to the service, it is usually easier
954   * to create a #GNetworkService and use its #GSocketConnectable
955   * interface.
956   *
957   * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
958   * #GSrvTarget, or %NULL on error. You must free each of the targets and the
959   * list when you are done with it. (You can use g_resolver_free_targets() to do
960   * this.)
961   *
962   * Since: 2.22
963   */
964  GList *
g_resolver_lookup_service(GResolver * resolver,const gchar * service,const gchar * protocol,const gchar * domain,GCancellable * cancellable,GError ** error)965  g_resolver_lookup_service (GResolver     *resolver,
966                             const gchar   *service,
967                             const gchar   *protocol,
968                             const gchar   *domain,
969                             GCancellable  *cancellable,
970                             GError       **error)
971  {
972    GList *targets;
973    gchar *rrname;
974  
975    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
976    g_return_val_if_fail (service != NULL, NULL);
977    g_return_val_if_fail (protocol != NULL, NULL);
978    g_return_val_if_fail (domain != NULL, NULL);
979  
980    rrname = g_resolver_get_service_rrname (service, protocol, domain);
981    if (!rrname)
982      {
983        g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
984                             _("Invalid domain"));
985        return NULL;
986      }
987  
988    g_resolver_maybe_reload (resolver);
989    targets = G_RESOLVER_GET_CLASS (resolver)->
990      lookup_service (resolver, rrname, cancellable, error);
991  
992    g_free (rrname);
993    return targets;
994  }
995  
996  /**
997   * g_resolver_lookup_service_async:
998   * @resolver: a #GResolver
999   * @service: the service type to look up (eg, "ldap")
1000   * @protocol: the networking protocol to use for @service (eg, "tcp")
1001   * @domain: the DNS domain to look up the service in
1002   * @cancellable: (nullable): a #GCancellable, or %NULL
1003   * @callback: (scope async): callback to call after resolution completes
1004   * @user_data: (closure): data for @callback
1005   *
1006   * Begins asynchronously performing a DNS SRV lookup for the given
1007   * @service and @protocol in the given @domain, and eventually calls
1008   * @callback, which must call g_resolver_lookup_service_finish() to
1009   * get the final result. See g_resolver_lookup_service() for more
1010   * details.
1011   *
1012   * Since: 2.22
1013   */
1014  void
g_resolver_lookup_service_async(GResolver * resolver,const gchar * service,const gchar * protocol,const gchar * domain,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1015  g_resolver_lookup_service_async (GResolver           *resolver,
1016                                   const gchar         *service,
1017                                   const gchar         *protocol,
1018                                   const gchar         *domain,
1019                                   GCancellable        *cancellable,
1020                                   GAsyncReadyCallback  callback,
1021                                   gpointer             user_data)
1022  {
1023    gchar *rrname;
1024  
1025    g_return_if_fail (G_IS_RESOLVER (resolver));
1026    g_return_if_fail (service != NULL);
1027    g_return_if_fail (protocol != NULL);
1028    g_return_if_fail (domain != NULL);
1029  
1030    rrname = g_resolver_get_service_rrname (service, protocol, domain);
1031    if (!rrname)
1032      {
1033        g_task_report_new_error (resolver, callback, user_data,
1034                                 g_resolver_lookup_service_async,
1035                                 G_IO_ERROR, G_IO_ERROR_FAILED,
1036                                 _("Invalid domain"));
1037        return;
1038      }
1039  
1040    g_resolver_maybe_reload (resolver);
1041    G_RESOLVER_GET_CLASS (resolver)->
1042      lookup_service_async (resolver, rrname, cancellable, callback, user_data);
1043  
1044    g_free (rrname);
1045  }
1046  
1047  /**
1048   * g_resolver_lookup_service_finish:
1049   * @resolver: a #GResolver
1050   * @result: the result passed to your #GAsyncReadyCallback
1051   * @error: return location for a #GError, or %NULL
1052   *
1053   * Retrieves the result of a previous call to
1054   * g_resolver_lookup_service_async().
1055   *
1056   * If the DNS resolution failed, @error (if non-%NULL) will be set to
1057   * a value from #GResolverError. If the operation was cancelled,
1058   * @error will be set to %G_IO_ERROR_CANCELLED.
1059   *
1060   * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
1061   * #GSrvTarget, or %NULL on error. See g_resolver_lookup_service() for more
1062   * details.
1063   *
1064   * Since: 2.22
1065   */
1066  GList *
g_resolver_lookup_service_finish(GResolver * resolver,GAsyncResult * result,GError ** error)1067  g_resolver_lookup_service_finish (GResolver     *resolver,
1068                                    GAsyncResult  *result,
1069                                    GError       **error)
1070  {
1071    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
1072  
1073    if (g_async_result_legacy_propagate_error (result, error))
1074      return NULL;
1075  
1076    return G_RESOLVER_GET_CLASS (resolver)->
1077      lookup_service_finish (resolver, result, error);
1078  }
1079  
1080  /**
1081   * g_resolver_free_targets: (skip)
1082   * @targets: a #GList of #GSrvTarget
1083   *
1084   * Frees @targets (which should be the return value from
1085   * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
1086   * (This is a convenience method; you can also simply free the
1087   * results by hand.)
1088   *
1089   * Since: 2.22
1090   */
1091  void
g_resolver_free_targets(GList * targets)1092  g_resolver_free_targets (GList *targets)
1093  {
1094    GList *t;
1095  
1096    for (t = targets; t; t = t->next)
1097      g_srv_target_free (t->data);
1098    g_list_free (targets);
1099  }
1100  
1101  /**
1102   * g_resolver_lookup_records:
1103   * @resolver: a #GResolver
1104   * @rrname: the DNS name to look up the record for
1105   * @record_type: the type of DNS record to look up
1106   * @cancellable: (nullable): a #GCancellable, or %NULL
1107   * @error: return location for a #GError, or %NULL
1108   *
1109   * Synchronously performs a DNS record lookup for the given @rrname and returns
1110   * a list of records as #GVariant tuples. See #GResolverRecordType for
1111   * information on what the records contain for each @record_type.
1112   *
1113   * If the DNS resolution fails, @error (if non-%NULL) will be set to
1114   * a value from #GResolverError and %NULL will be returned.
1115   *
1116   * If @cancellable is non-%NULL, it can be used to cancel the
1117   * operation, in which case @error (if non-%NULL) will be set to
1118   * %G_IO_ERROR_CANCELLED.
1119   *
1120   * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
1121   * #GVariant, or %NULL on error. You must free each of the records and the list
1122   * when you are done with it. (You can use g_list_free_full() with
1123   * g_variant_unref() to do this.)
1124   *
1125   * Since: 2.34
1126   */
1127  GList *
g_resolver_lookup_records(GResolver * resolver,const gchar * rrname,GResolverRecordType record_type,GCancellable * cancellable,GError ** error)1128  g_resolver_lookup_records (GResolver            *resolver,
1129                             const gchar          *rrname,
1130                             GResolverRecordType   record_type,
1131                             GCancellable         *cancellable,
1132                             GError              **error)
1133  {
1134    GList *records;
1135  
1136    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
1137    g_return_val_if_fail (rrname != NULL, NULL);
1138  
1139    g_resolver_maybe_reload (resolver);
1140    records = G_RESOLVER_GET_CLASS (resolver)->
1141      lookup_records (resolver, rrname, record_type, cancellable, error);
1142  
1143    return records;
1144  }
1145  
1146  /**
1147   * g_resolver_lookup_records_async:
1148   * @resolver: a #GResolver
1149   * @rrname: the DNS name to look up the record for
1150   * @record_type: the type of DNS record to look up
1151   * @cancellable: (nullable): a #GCancellable, or %NULL
1152   * @callback: (scope async): callback to call after resolution completes
1153   * @user_data: (closure): data for @callback
1154   *
1155   * Begins asynchronously performing a DNS lookup for the given
1156   * @rrname, and eventually calls @callback, which must call
1157   * g_resolver_lookup_records_finish() to get the final result. See
1158   * g_resolver_lookup_records() for more details.
1159   *
1160   * Since: 2.34
1161   */
1162  void
g_resolver_lookup_records_async(GResolver * resolver,const gchar * rrname,GResolverRecordType record_type,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1163  g_resolver_lookup_records_async (GResolver           *resolver,
1164                                   const gchar         *rrname,
1165                                   GResolverRecordType  record_type,
1166                                   GCancellable        *cancellable,
1167                                   GAsyncReadyCallback  callback,
1168                                   gpointer             user_data)
1169  {
1170    g_return_if_fail (G_IS_RESOLVER (resolver));
1171    g_return_if_fail (rrname != NULL);
1172  
1173    g_resolver_maybe_reload (resolver);
1174    G_RESOLVER_GET_CLASS (resolver)->
1175      lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
1176  }
1177  
1178  /**
1179   * g_resolver_lookup_records_finish:
1180   * @resolver: a #GResolver
1181   * @result: the result passed to your #GAsyncReadyCallback
1182   * @error: return location for a #GError, or %NULL
1183   *
1184   * Retrieves the result of a previous call to
1185   * g_resolver_lookup_records_async(). Returns a non-empty list of records as
1186   * #GVariant tuples. See #GResolverRecordType for information on what the
1187   * records contain.
1188   *
1189   * If the DNS resolution failed, @error (if non-%NULL) will be set to
1190   * a value from #GResolverError. If the operation was cancelled,
1191   * @error will be set to %G_IO_ERROR_CANCELLED.
1192   *
1193   * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
1194   * #GVariant, or %NULL on error. You must free each of the records and the list
1195   * when you are done with it. (You can use g_list_free_full() with
1196   * g_variant_unref() to do this.)
1197   *
1198   * Since: 2.34
1199   */
1200  GList *
g_resolver_lookup_records_finish(GResolver * resolver,GAsyncResult * result,GError ** error)1201  g_resolver_lookup_records_finish (GResolver     *resolver,
1202                                    GAsyncResult  *result,
1203                                    GError       **error)
1204  {
1205    g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
1206    return G_RESOLVER_GET_CLASS (resolver)->
1207      lookup_records_finish (resolver, result, error);
1208  }
1209  
1210  guint64
g_resolver_get_serial(GResolver * resolver)1211  g_resolver_get_serial (GResolver *resolver)
1212  {
1213    g_return_val_if_fail (G_IS_RESOLVER (resolver), 0);
1214  
1215    g_resolver_maybe_reload (resolver);
1216  
1217  #ifdef G_OS_UNIX
1218    return (guint64) resolver->priv->resolv_conf_timestamp;
1219  #else
1220    return 1;
1221  #endif
1222  }
1223  
1224  /**
1225   * g_resolver_error_quark:
1226   *
1227   * Gets the #GResolver Error Quark.
1228   *
1229   * Returns: a #GQuark.
1230   *
1231   * Since: 2.22
1232   */
1233  G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error)
1234