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