Imported Upstream version 2.64.5
[platform/upstream/glib.git] / gio / gresolver.c
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  */
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 *
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
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 *
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
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
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 *
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
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
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
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
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
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 *
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 *
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 *
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
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       if (addrs)
580         g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses);
581       else
582         g_task_return_error (task, error);
583       g_object_unref (task);
584       return;
585     }
586
587   if (g_hostname_is_non_ascii (hostname))
588     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
589
590   if (!hostname)
591     {
592       GTask *task;
593
594       g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
595                            _("Invalid hostname"));
596       task = g_task_new (resolver, cancellable, callback, user_data);
597       g_task_set_source_tag (task, lookup_by_name_async_real);
598       g_task_return_error (task, error);
599       g_object_unref (task);
600       return;
601     }
602
603   g_resolver_maybe_reload (resolver);
604
605   if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
606     {
607       if (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_async == NULL)
608         {
609           GTask *task;
610
611           g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
612                        /* Translators: The placeholder is for a function name. */
613                        _("%s not implemented"), "lookup_by_name_with_flags_async");
614           task = g_task_new (resolver, cancellable, callback, user_data);
615           g_task_set_source_tag (task, lookup_by_name_async_real);
616           g_task_return_error (task, error);
617           g_object_unref (task);
618         }
619       else
620         G_RESOLVER_GET_CLASS (resolver)->
621           lookup_by_name_with_flags_async (resolver, hostname, flags, cancellable, callback, user_data);
622     }
623   else
624     G_RESOLVER_GET_CLASS (resolver)->
625       lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
626
627   g_free (ascii_hostname);
628 }
629
630 static GList *
631 lookup_by_name_finish_real (GResolver     *resolver,
632                             GAsyncResult  *result,
633                             GError       **error,
634                             gboolean       with_flags)
635 {
636   GList *addrs;
637
638   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
639   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
640   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
641
642   if (g_async_result_legacy_propagate_error (result, error))
643     return NULL;
644   else if (g_async_result_is_tagged (result, lookup_by_name_async_real))
645     {
646       /* Handle the stringified-IP-addr case */
647       return g_task_propagate_pointer (G_TASK (result), error);
648     }
649
650   if (with_flags)
651     {
652       g_assert (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_finish != NULL);
653       addrs = G_RESOLVER_GET_CLASS (resolver)->
654         lookup_by_name_with_flags_finish (resolver, result, error);
655     }
656   else
657     addrs = G_RESOLVER_GET_CLASS (resolver)->
658       lookup_by_name_finish (resolver, result, error);
659
660   remove_duplicates (addrs);
661
662   return addrs;
663 }
664
665 /**
666  * g_resolver_lookup_by_name_with_flags_async:
667  * @resolver: a #GResolver
668  * @hostname: the hostname to look up the address of
669  * @flags: extra #GResolverNameLookupFlags for the lookup
670  * @cancellable: (nullable): a #GCancellable, or %NULL
671  * @callback: (scope async): callback to call after resolution completes
672  * @user_data: (closure): data for @callback
673  *
674  * Begins asynchronously resolving @hostname to determine its
675  * associated IP address(es), and eventually calls @callback, which
676  * must call g_resolver_lookup_by_name_with_flags_finish() to get the result.
677  * See g_resolver_lookup_by_name() for more details.
678  *
679  * Since: 2.60
680  */
681 void
682 g_resolver_lookup_by_name_with_flags_async (GResolver                *resolver,
683                                             const gchar              *hostname,
684                                             GResolverNameLookupFlags  flags,
685                                             GCancellable             *cancellable,
686                                             GAsyncReadyCallback       callback,
687                                             gpointer                  user_data)
688 {
689   lookup_by_name_async_real (resolver,
690                              hostname,
691                              flags,
692                              cancellable,
693                              callback,
694                              user_data);
695 }
696
697 /**
698  * g_resolver_lookup_by_name_async:
699  * @resolver: a #GResolver
700  * @hostname: the hostname to look up the address of
701  * @cancellable: (nullable): a #GCancellable, or %NULL
702  * @callback: (scope async): callback to call after resolution completes
703  * @user_data: (closure): data for @callback
704  *
705  * Begins asynchronously resolving @hostname to determine its
706  * associated IP address(es), and eventually calls @callback, which
707  * must call g_resolver_lookup_by_name_finish() to get the result.
708  * See g_resolver_lookup_by_name() for more details.
709  *
710  * Since: 2.22
711  */
712 void
713 g_resolver_lookup_by_name_async (GResolver           *resolver,
714                                  const gchar         *hostname,
715                                  GCancellable        *cancellable,
716                                  GAsyncReadyCallback  callback,
717                                  gpointer             user_data)
718 {
719   lookup_by_name_async_real (resolver,
720                              hostname,
721                              0,
722                              cancellable,
723                              callback,
724                              user_data);
725 }
726
727 /**
728  * g_resolver_lookup_by_name_finish:
729  * @resolver: a #GResolver
730  * @result: the result passed to your #GAsyncReadyCallback
731  * @error: return location for a #GError, or %NULL
732  *
733  * Retrieves the result of a call to
734  * g_resolver_lookup_by_name_async().
735  *
736  * If the DNS resolution failed, @error (if non-%NULL) will be set to
737  * a value from #GResolverError. If the operation was cancelled,
738  * @error will be set to %G_IO_ERROR_CANCELLED.
739  *
740  * Returns: (element-type GInetAddress) (transfer full): a #GList
741  * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
742  * for more details.
743  *
744  * Since: 2.22
745  */
746 GList *
747 g_resolver_lookup_by_name_finish (GResolver     *resolver,
748                                   GAsyncResult  *result,
749                                   GError       **error)
750 {
751   return lookup_by_name_finish_real (resolver,
752                                      result,
753                                      error,
754                                      FALSE);
755 }
756
757 /**
758  * g_resolver_lookup_by_name_with_flags_finish:
759  * @resolver: a #GResolver
760  * @result: the result passed to your #GAsyncReadyCallback
761  * @error: return location for a #GError, or %NULL
762  *
763  * Retrieves the result of a call to
764  * g_resolver_lookup_by_name_with_flags_async().
765  *
766  * If the DNS resolution failed, @error (if non-%NULL) will be set to
767  * a value from #GResolverError. If the operation was cancelled,
768  * @error will be set to %G_IO_ERROR_CANCELLED.
769  *
770  * Returns: (element-type GInetAddress) (transfer full): a #GList
771  * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
772  * for more details.
773  *
774  * Since: 2.60
775  */
776 GList *
777 g_resolver_lookup_by_name_with_flags_finish (GResolver     *resolver,
778                                              GAsyncResult  *result,
779                                              GError       **error)
780 {
781   return lookup_by_name_finish_real (resolver,
782                                      result,
783                                      error,
784                                      TRUE);
785 }
786
787 /**
788  * g_resolver_free_addresses: (skip)
789  * @addresses: a #GList of #GInetAddress
790  *
791  * Frees @addresses (which should be the return value from
792  * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
793  * (This is a convenience method; you can also simply free the results
794  * by hand.)
795  *
796  * Since: 2.22
797  */
798 void
799 g_resolver_free_addresses (GList *addresses)
800 {
801   GList *a;
802
803   for (a = addresses; a; a = a->next)
804     g_object_unref (a->data);
805   g_list_free (addresses);
806 }
807
808 /**
809  * g_resolver_lookup_by_address:
810  * @resolver: a #GResolver
811  * @address: the address to reverse-resolve
812  * @cancellable: (nullable): a #GCancellable, or %NULL
813  * @error: return location for a #GError, or %NULL
814  *
815  * Synchronously reverse-resolves @address to determine its
816  * associated hostname.
817  *
818  * If the DNS resolution fails, @error (if non-%NULL) will be set to
819  * a value from #GResolverError.
820  *
821  * If @cancellable is non-%NULL, it can be used to cancel the
822  * operation, in which case @error (if non-%NULL) will be set to
823  * %G_IO_ERROR_CANCELLED.
824  *
825  * Returns: a hostname (either ASCII-only, or in ASCII-encoded
826  *     form), or %NULL on error.
827  *
828  * Since: 2.22
829  */
830 gchar *
831 g_resolver_lookup_by_address (GResolver     *resolver,
832                               GInetAddress  *address,
833                               GCancellable  *cancellable,
834                               GError       **error)
835 {
836   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
837   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
838
839   g_resolver_maybe_reload (resolver);
840   return G_RESOLVER_GET_CLASS (resolver)->
841     lookup_by_address (resolver, address, cancellable, error);
842 }
843
844 /**
845  * g_resolver_lookup_by_address_async:
846  * @resolver: a #GResolver
847  * @address: the address to reverse-resolve
848  * @cancellable: (nullable): a #GCancellable, or %NULL
849  * @callback: (scope async): callback to call after resolution completes
850  * @user_data: (closure): data for @callback
851  *
852  * Begins asynchronously reverse-resolving @address to determine its
853  * associated hostname, and eventually calls @callback, which must
854  * call g_resolver_lookup_by_address_finish() to get the final result.
855  *
856  * Since: 2.22
857  */
858 void
859 g_resolver_lookup_by_address_async (GResolver           *resolver,
860                                     GInetAddress        *address,
861                                     GCancellable        *cancellable,
862                                     GAsyncReadyCallback  callback,
863                                     gpointer             user_data)
864 {
865   g_return_if_fail (G_IS_RESOLVER (resolver));
866   g_return_if_fail (G_IS_INET_ADDRESS (address));
867
868   g_resolver_maybe_reload (resolver);
869   G_RESOLVER_GET_CLASS (resolver)->
870     lookup_by_address_async (resolver, address, cancellable, callback, user_data);
871 }
872
873 /**
874  * g_resolver_lookup_by_address_finish:
875  * @resolver: a #GResolver
876  * @result: the result passed to your #GAsyncReadyCallback
877  * @error: return location for a #GError, or %NULL
878  *
879  * Retrieves the result of a previous call to
880  * g_resolver_lookup_by_address_async().
881  *
882  * If the DNS resolution failed, @error (if non-%NULL) will be set to
883  * a value from #GResolverError. If the operation was cancelled,
884  * @error will be set to %G_IO_ERROR_CANCELLED.
885  *
886  * Returns: a hostname (either ASCII-only, or in ASCII-encoded
887  * form), or %NULL on error.
888  *
889  * Since: 2.22
890  */
891 gchar *
892 g_resolver_lookup_by_address_finish (GResolver     *resolver,
893                                      GAsyncResult  *result,
894                                      GError       **error)
895 {
896   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
897
898   if (g_async_result_legacy_propagate_error (result, error))
899     return NULL;
900
901   return G_RESOLVER_GET_CLASS (resolver)->
902     lookup_by_address_finish (resolver, result, error);
903 }
904
905 static gchar *
906 g_resolver_get_service_rrname (const char *service,
907                                const char *protocol,
908                                const char *domain)
909 {
910   gchar *rrname, *ascii_domain = NULL;
911
912   if (g_hostname_is_non_ascii (domain))
913     domain = ascii_domain = g_hostname_to_ascii (domain);
914   if (!domain)
915     return NULL;
916
917   rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
918
919   g_free (ascii_domain);
920   return rrname;
921 }
922
923 /**
924  * g_resolver_lookup_service:
925  * @resolver: a #GResolver
926  * @service: the service type to look up (eg, "ldap")
927  * @protocol: the networking protocol to use for @service (eg, "tcp")
928  * @domain: the DNS domain to look up the service in
929  * @cancellable: (nullable): a #GCancellable, or %NULL
930  * @error: return location for a #GError, or %NULL
931  *
932  * Synchronously performs a DNS SRV lookup for the given @service and
933  * @protocol in the given @domain and returns an array of #GSrvTarget.
934  * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
935  * @service and @protocol arguments do not include the leading underscore
936  * that appears in the actual DNS entry.
937  *
938  * On success, g_resolver_lookup_service() will return a non-empty #GList of
939  * #GSrvTarget, sorted in order of preference. (That is, you should
940  * attempt to connect to the first target first, then the second if
941  * the first fails, etc.)
942  *
943  * If the DNS resolution fails, @error (if non-%NULL) will be set to
944  * a value from #GResolverError and %NULL will be returned.
945  *
946  * If @cancellable is non-%NULL, it can be used to cancel the
947  * operation, in which case @error (if non-%NULL) will be set to
948  * %G_IO_ERROR_CANCELLED.
949  *
950  * If you are planning to connect to the service, it is usually easier
951  * to create a #GNetworkService and use its #GSocketConnectable
952  * interface.
953  *
954  * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
955  * #GSrvTarget, or %NULL on error. You must free each of the targets and the
956  * list when you are done with it. (You can use g_resolver_free_targets() to do
957  * this.)
958  *
959  * Since: 2.22
960  */
961 GList *
962 g_resolver_lookup_service (GResolver     *resolver,
963                            const gchar   *service,
964                            const gchar   *protocol,
965                            const gchar   *domain,
966                            GCancellable  *cancellable,
967                            GError       **error)
968 {
969   GList *targets;
970   gchar *rrname;
971
972   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
973   g_return_val_if_fail (service != NULL, NULL);
974   g_return_val_if_fail (protocol != NULL, NULL);
975   g_return_val_if_fail (domain != NULL, NULL);
976
977   rrname = g_resolver_get_service_rrname (service, protocol, domain);
978   if (!rrname)
979     {
980       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
981                            _("Invalid domain"));
982       return NULL;
983     }
984
985   g_resolver_maybe_reload (resolver);
986   targets = G_RESOLVER_GET_CLASS (resolver)->
987     lookup_service (resolver, rrname, cancellable, error);
988
989   g_free (rrname);
990   return targets;
991 }
992
993 /**
994  * g_resolver_lookup_service_async:
995  * @resolver: a #GResolver
996  * @service: the service type to look up (eg, "ldap")
997  * @protocol: the networking protocol to use for @service (eg, "tcp")
998  * @domain: the DNS domain to look up the service in
999  * @cancellable: (nullable): a #GCancellable, or %NULL
1000  * @callback: (scope async): callback to call after resolution completes
1001  * @user_data: (closure): data for @callback
1002  *
1003  * Begins asynchronously performing a DNS SRV lookup for the given
1004  * @service and @protocol in the given @domain, and eventually calls
1005  * @callback, which must call g_resolver_lookup_service_finish() to
1006  * get the final result. See g_resolver_lookup_service() for more
1007  * details.
1008  *
1009  * Since: 2.22
1010  */
1011 void
1012 g_resolver_lookup_service_async (GResolver           *resolver,
1013                                  const gchar         *service,
1014                                  const gchar         *protocol,
1015                                  const gchar         *domain,
1016                                  GCancellable        *cancellable,
1017                                  GAsyncReadyCallback  callback,
1018                                  gpointer             user_data)
1019 {
1020   gchar *rrname;
1021
1022   g_return_if_fail (G_IS_RESOLVER (resolver));
1023   g_return_if_fail (service != NULL);
1024   g_return_if_fail (protocol != NULL);
1025   g_return_if_fail (domain != NULL);
1026
1027   rrname = g_resolver_get_service_rrname (service, protocol, domain);
1028   if (!rrname)
1029     {
1030       g_task_report_new_error (resolver, callback, user_data,
1031                                g_resolver_lookup_service_async,
1032                                G_IO_ERROR, G_IO_ERROR_FAILED,
1033                                _("Invalid domain"));
1034       return;
1035     }
1036
1037   g_resolver_maybe_reload (resolver);
1038   G_RESOLVER_GET_CLASS (resolver)->
1039     lookup_service_async (resolver, rrname, cancellable, callback, user_data);
1040
1041   g_free (rrname);
1042 }
1043
1044 /**
1045  * g_resolver_lookup_service_finish:
1046  * @resolver: a #GResolver
1047  * @result: the result passed to your #GAsyncReadyCallback
1048  * @error: return location for a #GError, or %NULL
1049  *
1050  * Retrieves the result of a previous call to
1051  * g_resolver_lookup_service_async().
1052  *
1053  * If the DNS resolution failed, @error (if non-%NULL) will be set to
1054  * a value from #GResolverError. If the operation was cancelled,
1055  * @error will be set to %G_IO_ERROR_CANCELLED.
1056  *
1057  * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
1058  * #GSrvTarget, or %NULL on error. See g_resolver_lookup_service() for more
1059  * details.
1060  *
1061  * Since: 2.22
1062  */
1063 GList *
1064 g_resolver_lookup_service_finish (GResolver     *resolver,
1065                                   GAsyncResult  *result,
1066                                   GError       **error)
1067 {
1068   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
1069
1070   if (g_async_result_legacy_propagate_error (result, error))
1071     return NULL;
1072
1073   return G_RESOLVER_GET_CLASS (resolver)->
1074     lookup_service_finish (resolver, result, error);
1075 }
1076
1077 /**
1078  * g_resolver_free_targets: (skip)
1079  * @targets: a #GList of #GSrvTarget
1080  *
1081  * Frees @targets (which should be the return value from
1082  * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
1083  * (This is a convenience method; you can also simply free the
1084  * results by hand.)
1085  *
1086  * Since: 2.22
1087  */
1088 void
1089 g_resolver_free_targets (GList *targets)
1090 {
1091   GList *t;
1092
1093   for (t = targets; t; t = t->next)
1094     g_srv_target_free (t->data);
1095   g_list_free (targets);
1096 }
1097
1098 /**
1099  * g_resolver_lookup_records:
1100  * @resolver: a #GResolver
1101  * @rrname: the DNS name to look up the record for
1102  * @record_type: the type of DNS record to look up
1103  * @cancellable: (nullable): a #GCancellable, or %NULL
1104  * @error: return location for a #GError, or %NULL
1105  *
1106  * Synchronously performs a DNS record lookup for the given @rrname and returns
1107  * a list of records as #GVariant tuples. See #GResolverRecordType for
1108  * information on what the records contain for each @record_type.
1109  *
1110  * If the DNS resolution fails, @error (if non-%NULL) will be set to
1111  * a value from #GResolverError and %NULL will be returned.
1112  *
1113  * If @cancellable is non-%NULL, it can be used to cancel the
1114  * operation, in which case @error (if non-%NULL) will be set to
1115  * %G_IO_ERROR_CANCELLED.
1116  *
1117  * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
1118  * #GVariant, or %NULL on error. You must free each of the records and the list
1119  * when you are done with it. (You can use g_list_free_full() with
1120  * g_variant_unref() to do this.)
1121  *
1122  * Since: 2.34
1123  */
1124 GList *
1125 g_resolver_lookup_records (GResolver            *resolver,
1126                            const gchar          *rrname,
1127                            GResolverRecordType   record_type,
1128                            GCancellable         *cancellable,
1129                            GError              **error)
1130 {
1131   GList *records;
1132
1133   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
1134   g_return_val_if_fail (rrname != NULL, NULL);
1135
1136   g_resolver_maybe_reload (resolver);
1137   records = G_RESOLVER_GET_CLASS (resolver)->
1138     lookup_records (resolver, rrname, record_type, cancellable, error);
1139
1140   return records;
1141 }
1142
1143 /**
1144  * g_resolver_lookup_records_async:
1145  * @resolver: a #GResolver
1146  * @rrname: the DNS name to look up the record for
1147  * @record_type: the type of DNS record to look up
1148  * @cancellable: (nullable): a #GCancellable, or %NULL
1149  * @callback: (scope async): callback to call after resolution completes
1150  * @user_data: (closure): data for @callback
1151  *
1152  * Begins asynchronously performing a DNS lookup for the given
1153  * @rrname, and eventually calls @callback, which must call
1154  * g_resolver_lookup_records_finish() to get the final result. See
1155  * g_resolver_lookup_records() for more details.
1156  *
1157  * Since: 2.34
1158  */
1159 void
1160 g_resolver_lookup_records_async (GResolver           *resolver,
1161                                  const gchar         *rrname,
1162                                  GResolverRecordType  record_type,
1163                                  GCancellable        *cancellable,
1164                                  GAsyncReadyCallback  callback,
1165                                  gpointer             user_data)
1166 {
1167   g_return_if_fail (G_IS_RESOLVER (resolver));
1168   g_return_if_fail (rrname != NULL);
1169
1170   g_resolver_maybe_reload (resolver);
1171   G_RESOLVER_GET_CLASS (resolver)->
1172     lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
1173 }
1174
1175 /**
1176  * g_resolver_lookup_records_finish:
1177  * @resolver: a #GResolver
1178  * @result: the result passed to your #GAsyncReadyCallback
1179  * @error: return location for a #GError, or %NULL
1180  *
1181  * Retrieves the result of a previous call to
1182  * g_resolver_lookup_records_async(). Returns a non-empty list of records as
1183  * #GVariant tuples. See #GResolverRecordType for information on what the
1184  * records contain.
1185  *
1186  * If the DNS resolution failed, @error (if non-%NULL) will be set to
1187  * a value from #GResolverError. If the operation was cancelled,
1188  * @error will be set to %G_IO_ERROR_CANCELLED.
1189  *
1190  * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
1191  * #GVariant, or %NULL on error. You must free each of the records and the list
1192  * when you are done with it. (You can use g_list_free_full() with
1193  * g_variant_unref() to do this.)
1194  *
1195  * Since: 2.34
1196  */
1197 GList *
1198 g_resolver_lookup_records_finish (GResolver     *resolver,
1199                                   GAsyncResult  *result,
1200                                   GError       **error)
1201 {
1202   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
1203   return G_RESOLVER_GET_CLASS (resolver)->
1204     lookup_records_finish (resolver, result, error);
1205 }
1206
1207 guint64
1208 g_resolver_get_serial (GResolver *resolver)
1209 {
1210   g_return_val_if_fail (G_IS_RESOLVER (resolver), 0);
1211
1212   g_resolver_maybe_reload (resolver);
1213
1214 #ifdef G_OS_UNIX
1215   return (guint64) resolver->priv->resolv_conf_timestamp;
1216 #else
1217   return 1;
1218 #endif
1219 }
1220
1221 /**
1222  * g_resolver_error_quark:
1223  *
1224  * Gets the #GResolver Error Quark.
1225  *
1226  * Returns: a #GQuark.
1227  *
1228  * Since: 2.22
1229  */
1230 G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error)