gresolver: More robust parsing of DNS responses
[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  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General
18  * Public License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "config.h"
24 #include <glib.h>
25 #include "glibintl.h"
26
27 #include "gresolver.h"
28 #include "gnetworkingprivate.h"
29 #include "gasyncresult.h"
30 #include "ginetaddress.h"
31 #include "ginetsocketaddress.h"
32 #include "gsimpleasyncresult.h"
33 #include "gsrvtarget.h"
34 #include "gthreadedresolver.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 G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT)
80
81 static GList *
82 srv_records_to_targets (GList *records)
83 {
84   const gchar *hostname;
85   guint16 port, priority, weight;
86   GSrvTarget *target;
87   GList *l;
88
89   for (l = records; l != NULL; l = g_list_next (l))
90     {
91       g_variant_get (l->data, "(qqq&s)", &priority, &weight, &port, &hostname);
92       target = g_srv_target_new (hostname, port, priority, weight);
93       g_variant_unref (l->data);
94       l->data = target;
95     }
96
97   return g_srv_target_list_sort (records);
98 }
99
100 static GList *
101 g_resolver_real_lookup_service (GResolver            *resolver,
102                                 const gchar          *rrname,
103                                 GCancellable         *cancellable,
104                                 GError              **error)
105 {
106   GList *records;
107
108   records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver,
109                                                              rrname,
110                                                              G_RESOLVER_RECORD_SRV,
111                                                              cancellable,
112                                                              error);
113
114   return srv_records_to_targets (records);
115 }
116
117 static void
118 g_resolver_real_lookup_service_async (GResolver            *resolver,
119                                       const gchar          *rrname,
120                                       GCancellable         *cancellable,
121                                       GAsyncReadyCallback   callback,
122                                       gpointer              user_data)
123 {
124   G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver,
125                                                          rrname,
126                                                          G_RESOLVER_RECORD_SRV,
127                                                          cancellable,
128                                                          callback,
129                                                          user_data);
130 }
131
132 static GList *
133 g_resolver_real_lookup_service_finish (GResolver            *resolver,
134                                        GAsyncResult         *result,
135                                        GError              **error)
136 {
137   GList *records;
138
139   records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver,
140                                                                     result,
141                                                                     error);
142
143   return srv_records_to_targets (records);
144 }
145
146 static void
147 g_resolver_class_init (GResolverClass *resolver_class)
148 {
149   /* Automatically pass these over to the lookup_records methods */
150   resolver_class->lookup_service = g_resolver_real_lookup_service;
151   resolver_class->lookup_service_async = g_resolver_real_lookup_service_async;
152   resolver_class->lookup_service_finish = g_resolver_real_lookup_service_finish;
153
154   g_type_class_add_private (resolver_class, sizeof (GResolverPrivate));
155
156   /* Make sure _g_networking_init() has been called */
157   g_type_ensure (G_TYPE_INET_ADDRESS);
158
159   /* Initialize _g_resolver_addrinfo_hints */
160 #ifdef AI_ADDRCONFIG
161   _g_resolver_addrinfo_hints.ai_flags |= AI_ADDRCONFIG;
162 #endif
163   /* These two don't actually matter, they just get copied into the
164    * returned addrinfo structures (and then we ignore them). But if
165    * we leave them unset, we'll get back duplicate answers.
166    */
167   _g_resolver_addrinfo_hints.ai_socktype = SOCK_STREAM;
168   _g_resolver_addrinfo_hints.ai_protocol = IPPROTO_TCP;
169
170   /**
171    * GResolver::reload:
172    * @resolver: a #GResolver
173    *
174    * Emitted when the resolver notices that the system resolver
175    * configuration has changed.
176    **/
177   signals[RELOAD] =
178     g_signal_new (I_("reload"),
179                   G_TYPE_RESOLVER,
180                   G_SIGNAL_RUN_LAST,
181                   G_STRUCT_OFFSET (GResolverClass, reload),
182                   NULL, NULL,
183                   g_cclosure_marshal_VOID__VOID,
184                   G_TYPE_NONE, 0);
185 }
186
187 static void
188 g_resolver_init (GResolver *resolver)
189 {
190 #ifdef G_OS_UNIX
191   struct stat st;
192 #endif
193
194   resolver->priv = G_TYPE_INSTANCE_GET_PRIVATE (resolver, G_TYPE_RESOLVER, GResolverPrivate);
195
196 #ifdef G_OS_UNIX
197   if (stat (_PATH_RESCONF, &st) == 0)
198     resolver->priv->resolv_conf_timestamp = st.st_mtime;
199 #endif
200 }
201
202 static GResolver *default_resolver;
203
204 /**
205  * g_resolver_get_default:
206  *
207  * Gets the default #GResolver. You should unref it when you are done
208  * with it. #GResolver may use its reference count as a hint about how
209  * many threads it should allocate for concurrent DNS resolutions.
210  *
211  * Return value: (transfer full): the default #GResolver.
212  *
213  * Since: 2.22
214  */
215 GResolver *
216 g_resolver_get_default (void)
217 {
218   if (!default_resolver)
219     default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL);
220
221   return g_object_ref (default_resolver);
222 }
223
224 /**
225  * g_resolver_set_default:
226  * @resolver: the new default #GResolver
227  *
228  * Sets @resolver to be the application's default resolver (reffing
229  * @resolver, and unreffing the previous default resolver, if any).
230  * Future calls to g_resolver_get_default() will return this resolver.
231  *
232  * This can be used if an application wants to perform any sort of DNS
233  * caching or "pinning"; it can implement its own #GResolver that
234  * calls the original default resolver for DNS operations, and
235  * implements its own cache policies on top of that, and then set
236  * itself as the default resolver for all later code to use.
237  *
238  * Since: 2.22
239  */
240 void
241 g_resolver_set_default (GResolver *resolver)
242 {
243   if (default_resolver)
244     g_object_unref (default_resolver);
245   default_resolver = g_object_ref (resolver);
246 }
247
248
249 static void
250 g_resolver_maybe_reload (GResolver *resolver)
251 {
252 #ifdef G_OS_UNIX
253   struct stat st;
254
255   if (stat (_PATH_RESCONF, &st) == 0)
256     {
257       if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
258         {
259           resolver->priv->resolv_conf_timestamp = st.st_mtime;
260           res_init ();
261           g_signal_emit (resolver, signals[RELOAD], 0);
262         }
263     }
264 #endif
265 }
266
267 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
268 static void
269 remove_duplicates (GList *addrs)
270 {
271   GList *l;
272   GList *ll;
273   GList *lll;
274
275   /* TODO: if this is too slow (it's O(n^2) but n is typically really
276    * small), we can do something more clever but note that we must not
277    * change the order of elements...
278    */
279   for (l = addrs; l != NULL; l = l->next)
280     {
281       GInetAddress *address = G_INET_ADDRESS (l->data);
282       for (ll = l->next; ll != NULL; ll = lll)
283         {
284           GInetAddress *other_address = G_INET_ADDRESS (ll->data);
285           lll = ll->next;
286           if (g_inet_address_equal (address, other_address))
287             {
288               g_object_unref (other_address);
289               /* we never return the first element */
290               g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs);
291             }
292         }
293     }
294 }
295
296
297 /**
298  * g_resolver_lookup_by_name:
299  * @resolver: a #GResolver
300  * @hostname: the hostname to look up
301  * @cancellable: (allow-none): a #GCancellable, or %NULL
302  * @error: return location for a #GError, or %NULL
303  *
304  * Synchronously resolves @hostname to determine its associated IP
305  * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
306  * the textual form of an IP address (in which case this just becomes
307  * a wrapper around g_inet_address_new_from_string()).
308  *
309  * On success, g_resolver_lookup_by_name() will return a #GList of
310  * #GInetAddress, sorted in order of preference and guaranteed to not
311  * contain duplicates. That is, if using the result to connect to
312  * @hostname, you should attempt to connect to the first address
313  * first, then the second if the first fails, etc. If you are using
314  * the result to listen on a socket, it is appropriate to add each
315  * result using e.g. g_socket_listener_add_address().
316  *
317  * If the DNS resolution fails, @error (if non-%NULL) will be set to a
318  * value from #GResolverError.
319  *
320  * If @cancellable is non-%NULL, it can be used to cancel the
321  * operation, in which case @error (if non-%NULL) will be set to
322  * %G_IO_ERROR_CANCELLED.
323  *
324  * If you are planning to connect to a socket on the resolved IP
325  * address, it may be easier to create a #GNetworkAddress and use its
326  * #GSocketConnectable interface.
327  *
328  * Return value: (element-type GInetAddress) (transfer full): a #GList
329  * of #GInetAddress, or %NULL on error. You
330  * must unref each of the addresses and free the list when you are
331  * done with it. (You can use g_resolver_free_addresses() to do this.)
332  *
333  * Since: 2.22
334  */
335 GList *
336 g_resolver_lookup_by_name (GResolver     *resolver,
337                            const gchar   *hostname,
338                            GCancellable  *cancellable,
339                            GError       **error)
340 {
341   GInetAddress *addr;
342   GList *addrs;
343   gchar *ascii_hostname = NULL;
344
345   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
346   g_return_val_if_fail (hostname != NULL, NULL);
347
348   /* Check if @hostname is just an IP address */
349   addr = g_inet_address_new_from_string (hostname);
350   if (addr)
351     return g_list_append (NULL, addr);
352
353   if (g_hostname_is_non_ascii (hostname))
354     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
355
356   g_resolver_maybe_reload (resolver);
357   addrs = G_RESOLVER_GET_CLASS (resolver)->
358     lookup_by_name (resolver, hostname, cancellable, error);
359
360   remove_duplicates (addrs);
361
362   g_free (ascii_hostname);
363   return addrs;
364 }
365
366 /**
367  * g_resolver_lookup_by_name_async:
368  * @resolver: a #GResolver
369  * @hostname: the hostname to look up the address of
370  * @cancellable: (allow-none): a #GCancellable, or %NULL
371  * @callback: (scope async): callback to call after resolution completes
372  * @user_data: (closure): data for @callback
373  *
374  * Begins asynchronously resolving @hostname to determine its
375  * associated IP address(es), and eventually calls @callback, which
376  * must call g_resolver_lookup_by_name_finish() to get the result.
377  * See g_resolver_lookup_by_name() for more details.
378  *
379  * Since: 2.22
380  */
381 void
382 g_resolver_lookup_by_name_async (GResolver           *resolver,
383                                  const gchar         *hostname,
384                                  GCancellable        *cancellable,
385                                  GAsyncReadyCallback  callback,
386                                  gpointer             user_data)
387 {
388   GInetAddress *addr;
389   gchar *ascii_hostname = NULL;
390
391   g_return_if_fail (G_IS_RESOLVER (resolver));
392   g_return_if_fail (hostname != NULL);
393
394   /* Check if @hostname is just an IP address */
395   addr = g_inet_address_new_from_string (hostname);
396   if (addr)
397     {
398       GSimpleAsyncResult *simple;
399
400       simple = g_simple_async_result_new (G_OBJECT (resolver),
401                                           callback, user_data,
402                                           g_resolver_lookup_by_name_async);
403
404       g_simple_async_result_set_op_res_gpointer (simple, addr, g_object_unref);
405       g_simple_async_result_complete_in_idle (simple);
406       g_object_unref (simple);
407       return;
408     }
409
410   if (g_hostname_is_non_ascii (hostname))
411     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
412
413   g_resolver_maybe_reload (resolver);
414   G_RESOLVER_GET_CLASS (resolver)->
415     lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
416
417   g_free (ascii_hostname);
418 }
419
420 /**
421  * g_resolver_lookup_by_name_finish:
422  * @resolver: a #GResolver
423  * @result: the result passed to your #GAsyncReadyCallback
424  * @error: return location for a #GError, or %NULL
425  *
426  * Retrieves the result of a call to
427  * g_resolver_lookup_by_name_async().
428  *
429  * If the DNS resolution failed, @error (if non-%NULL) will be set to
430  * a value from #GResolverError. If the operation was cancelled,
431  * @error will be set to %G_IO_ERROR_CANCELLED.
432  *
433  * Return value: (element-type GInetAddress) (transfer full): a #GList
434  * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
435  * for more details.
436  *
437  * Since: 2.22
438  */
439 GList *
440 g_resolver_lookup_by_name_finish (GResolver     *resolver,
441                                   GAsyncResult  *result,
442                                   GError       **error)
443 {
444   GList *addrs;
445
446   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
447
448   if (G_IS_SIMPLE_ASYNC_RESULT (result))
449     {
450       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
451
452       if (g_simple_async_result_propagate_error (simple, error))
453         return NULL;
454
455       /* Handle the stringified-IP-addr case */
456       if (g_simple_async_result_get_source_tag (simple) == g_resolver_lookup_by_name_async)
457         {
458           GInetAddress *addr;
459
460           addr = g_simple_async_result_get_op_res_gpointer (simple);
461           return g_list_append (NULL, g_object_ref (addr));
462         }
463     }
464
465   addrs = G_RESOLVER_GET_CLASS (resolver)->
466     lookup_by_name_finish (resolver, result, error);
467
468   remove_duplicates (addrs);
469
470   return addrs;
471 }
472
473 /**
474  * g_resolver_free_addresses: (skip)
475  * @addresses: a #GList of #GInetAddress
476  *
477  * Frees @addresses (which should be the return value from
478  * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
479  * (This is a convenience method; you can also simply free the results
480  * by hand.)
481  *
482  * Since: 2.22
483  */
484 void
485 g_resolver_free_addresses (GList *addresses)
486 {
487   GList *a;
488
489   for (a = addresses; a; a = a->next)
490     g_object_unref (a->data);
491   g_list_free (addresses);
492 }
493
494 /**
495  * g_resolver_lookup_by_address:
496  * @resolver: a #GResolver
497  * @address: the address to reverse-resolve
498  * @cancellable: (allow-none): a #GCancellable, or %NULL
499  * @error: return location for a #GError, or %NULL
500  *
501  * Synchronously reverse-resolves @address to determine its
502  * associated hostname.
503  *
504  * If the DNS resolution fails, @error (if non-%NULL) will be set to
505  * a value from #GResolverError.
506  *
507  * If @cancellable is non-%NULL, it can be used to cancel the
508  * operation, in which case @error (if non-%NULL) will be set to
509  * %G_IO_ERROR_CANCELLED.
510  *
511  * Return value: a hostname (either ASCII-only, or in ASCII-encoded
512  *     form), or %NULL on error.
513  *
514  * Since: 2.22
515  */
516 gchar *
517 g_resolver_lookup_by_address (GResolver     *resolver,
518                               GInetAddress  *address,
519                               GCancellable  *cancellable,
520                               GError       **error)
521 {
522   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
523   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
524
525   g_resolver_maybe_reload (resolver);
526   return G_RESOLVER_GET_CLASS (resolver)->
527     lookup_by_address (resolver, address, cancellable, error);
528 }
529
530 /**
531  * g_resolver_lookup_by_address_async:
532  * @resolver: a #GResolver
533  * @address: the address to reverse-resolve
534  * @cancellable: (allow-none): a #GCancellable, or %NULL
535  * @callback: (scope async): callback to call after resolution completes
536  * @user_data: (closure): data for @callback
537  *
538  * Begins asynchronously reverse-resolving @address to determine its
539  * associated hostname, and eventually calls @callback, which must
540  * call g_resolver_lookup_by_address_finish() to get the final result.
541  *
542  * Since: 2.22
543  */
544 void
545 g_resolver_lookup_by_address_async (GResolver           *resolver,
546                                     GInetAddress        *address,
547                                     GCancellable        *cancellable,
548                                     GAsyncReadyCallback  callback,
549                                     gpointer             user_data)
550 {
551   g_return_if_fail (G_IS_RESOLVER (resolver));
552   g_return_if_fail (G_IS_INET_ADDRESS (address));
553
554   g_resolver_maybe_reload (resolver);
555   G_RESOLVER_GET_CLASS (resolver)->
556     lookup_by_address_async (resolver, address, cancellable, callback, user_data);
557 }
558
559 /**
560  * g_resolver_lookup_by_address_finish:
561  * @resolver: a #GResolver
562  * @result: the result passed to your #GAsyncReadyCallback
563  * @error: return location for a #GError, or %NULL
564  *
565  * Retrieves the result of a previous call to
566  * g_resolver_lookup_by_address_async().
567  *
568  * If the DNS resolution failed, @error (if non-%NULL) will be set to
569  * a value from #GResolverError. If the operation was cancelled,
570  * @error will be set to %G_IO_ERROR_CANCELLED.
571  *
572  * Return value: a hostname (either ASCII-only, or in ASCII-encoded
573  * form), or %NULL on error.
574  *
575  * Since: 2.22
576  */
577 gchar *
578 g_resolver_lookup_by_address_finish (GResolver     *resolver,
579                                      GAsyncResult  *result,
580                                      GError       **error)
581 {
582   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
583
584   if (G_IS_SIMPLE_ASYNC_RESULT (result))
585     {
586       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
587
588       if (g_simple_async_result_propagate_error (simple, error))
589         return NULL;
590     }
591
592   return G_RESOLVER_GET_CLASS (resolver)->
593     lookup_by_address_finish (resolver, result, error);
594 }
595
596 static gchar *
597 g_resolver_get_service_rrname (const char *service,
598                                const char *protocol,
599                                const char *domain)
600 {
601   gchar *rrname, *ascii_domain = NULL;
602
603   if (g_hostname_is_non_ascii (domain))
604     domain = ascii_domain = g_hostname_to_ascii (domain);
605
606   rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
607
608   g_free (ascii_domain);
609   return rrname;
610 }
611
612 /**
613  * g_resolver_lookup_service:
614  * @resolver: a #GResolver
615  * @service: the service type to look up (eg, "ldap")
616  * @protocol: the networking protocol to use for @service (eg, "tcp")
617  * @domain: the DNS domain to look up the service in
618  * @cancellable: (allow-none): a #GCancellable, or %NULL
619  * @error: return location for a #GError, or %NULL
620  *
621  * Synchronously performs a DNS SRV lookup for the given @service and
622  * @protocol in the given @domain and returns an array of #GSrvTarget.
623  * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
624  * @service and @protocol arguments <emphasis>do not</emphasis>
625  * include the leading underscore that appears in the actual DNS
626  * entry.
627  *
628  * On success, g_resolver_lookup_service() will return a #GList of
629  * #GSrvTarget, sorted in order of preference. (That is, you should
630  * attempt to connect to the first target first, then the second if
631  * the first fails, etc.)
632  *
633  * If the DNS resolution fails, @error (if non-%NULL) will be set to
634  * a value from #GResolverError.
635  *
636  * If @cancellable is non-%NULL, it can be used to cancel the
637  * operation, in which case @error (if non-%NULL) will be set to
638  * %G_IO_ERROR_CANCELLED.
639  *
640  * If you are planning to connect to the service, it is usually easier
641  * to create a #GNetworkService and use its #GSocketConnectable
642  * interface.
643  *
644  * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
645  * or %NULL on error. You must free each of the targets and the list when you are
646  * done with it. (You can use g_resolver_free_targets() to do this.)
647  *
648  * Since: 2.22
649  */
650 GList *
651 g_resolver_lookup_service (GResolver     *resolver,
652                            const gchar   *service,
653                            const gchar   *protocol,
654                            const gchar   *domain,
655                            GCancellable  *cancellable,
656                            GError       **error)
657 {
658   GList *targets;
659   gchar *rrname;
660
661   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
662   g_return_val_if_fail (service != NULL, NULL);
663   g_return_val_if_fail (protocol != NULL, NULL);
664   g_return_val_if_fail (domain != NULL, NULL);
665
666   rrname = g_resolver_get_service_rrname (service, protocol, domain);
667
668   g_resolver_maybe_reload (resolver);
669   targets = G_RESOLVER_GET_CLASS (resolver)->
670     lookup_service (resolver, rrname, cancellable, error);
671
672   g_free (rrname);
673   return targets;
674 }
675
676 /**
677  * g_resolver_lookup_service_async:
678  * @resolver: a #GResolver
679  * @service: the service type to look up (eg, "ldap")
680  * @protocol: the networking protocol to use for @service (eg, "tcp")
681  * @domain: the DNS domain to look up the service in
682  * @cancellable: (allow-none): a #GCancellable, or %NULL
683  * @callback: (scope async): callback to call after resolution completes
684  * @user_data: (closure): data for @callback
685  *
686  * Begins asynchronously performing a DNS SRV lookup for the given
687  * @service and @protocol in the given @domain, and eventually calls
688  * @callback, which must call g_resolver_lookup_service_finish() to
689  * get the final result. See g_resolver_lookup_service() for more
690  * details.
691  *
692  * Since: 2.22
693  */
694 void
695 g_resolver_lookup_service_async (GResolver           *resolver,
696                                  const gchar         *service,
697                                  const gchar         *protocol,
698                                  const gchar         *domain,
699                                  GCancellable        *cancellable,
700                                  GAsyncReadyCallback  callback,
701                                  gpointer             user_data)
702 {
703   gchar *rrname;
704
705   g_return_if_fail (G_IS_RESOLVER (resolver));
706   g_return_if_fail (service != NULL);
707   g_return_if_fail (protocol != NULL);
708   g_return_if_fail (domain != NULL);
709
710   rrname = g_resolver_get_service_rrname (service, protocol, domain);
711
712   g_resolver_maybe_reload (resolver);
713   G_RESOLVER_GET_CLASS (resolver)->
714     lookup_service_async (resolver, rrname, cancellable, callback, user_data);
715
716   g_free (rrname);
717 }
718
719 /**
720  * g_resolver_lookup_service_finish:
721  * @resolver: a #GResolver
722  * @result: the result passed to your #GAsyncReadyCallback
723  * @error: return location for a #GError, or %NULL
724  *
725  * Retrieves the result of a previous call to
726  * g_resolver_lookup_service_async().
727  *
728  * If the DNS resolution failed, @error (if non-%NULL) will be set to
729  * a value from #GResolverError. If the operation was cancelled,
730  * @error will be set to %G_IO_ERROR_CANCELLED.
731  *
732  * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
733  * or %NULL on error. See g_resolver_lookup_service() for more details.
734  *
735  * Since: 2.22
736  */
737 GList *
738 g_resolver_lookup_service_finish (GResolver     *resolver,
739                                   GAsyncResult  *result,
740                                   GError       **error)
741 {
742   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
743
744   if (G_IS_SIMPLE_ASYNC_RESULT (result))
745     {
746       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
747
748       if (g_simple_async_result_propagate_error (simple, error))
749         return NULL;
750     }
751
752   return G_RESOLVER_GET_CLASS (resolver)->
753     lookup_service_finish (resolver, result, error);
754 }
755
756 /**
757  * g_resolver_free_targets: (skip)
758  * @targets: a #GList of #GSrvTarget
759  *
760  * Frees @targets (which should be the return value from
761  * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
762  * (This is a convenience method; you can also simply free the
763  * results by hand.)
764  *
765  * Since: 2.22
766  */
767 void
768 g_resolver_free_targets (GList *targets)
769 {
770   GList *t;
771
772   for (t = targets; t; t = t->next)
773     g_srv_target_free (t->data);
774   g_list_free (targets);
775 }
776
777 /**
778  * g_resolver_lookup_records:
779  * @resolver: a #GResolver
780  * @rrname: the DNS name to lookup the record for
781  * @record_type: the type of DNS record to lookup
782  * @cancellable: (allow-none): a #GCancellable, or %NULL
783  * @error: return location for a #GError, or %NULL
784  *
785  * Synchronously performs a DNS record lookup for the given @rrname and returns
786  * a list of records as #GVariant tuples. See #GResolverRecordType for
787  * information on what the records contain for each @record_type.
788  *
789  * If the DNS resolution fails, @error (if non-%NULL) will be set to
790  * a value from #GResolverError.
791  *
792  * If @cancellable is non-%NULL, it can be used to cancel the
793  * operation, in which case @error (if non-%NULL) will be set to
794  * %G_IO_ERROR_CANCELLED.
795  *
796  * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant,
797  * or %NULL on error. You must free each of the records and the list when you are
798  * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.)
799  *
800  * Since: 2.34
801  */
802 GList *
803 g_resolver_lookup_records (GResolver            *resolver,
804                            const gchar          *rrname,
805                            GResolverRecordType   record_type,
806                            GCancellable         *cancellable,
807                            GError              **error)
808 {
809   GList *records;
810
811   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
812   g_return_val_if_fail (rrname != NULL, NULL);
813
814   g_resolver_maybe_reload (resolver);
815   records = G_RESOLVER_GET_CLASS (resolver)->
816     lookup_records (resolver, rrname, record_type, cancellable, error);
817
818   return records;
819 }
820
821 /**
822  * g_resolver_lookup_records_async:
823  * @resolver: a #GResolver
824  * @rrname: the DNS name to lookup the record for
825  * @record_type: the type of DNS record to lookup
826  * @cancellable: (allow-none): a #GCancellable, or %NULL
827  * @callback: (scope async): callback to call after resolution completes
828  * @user_data: (closure): data for @callback
829  *
830  * Begins asynchronously performing a DNS lookup for the given
831  * @rrname, and eventually calls @callback, which must call
832  * g_resolver_lookup_records_finish() to get the final result. See
833  * g_resolver_lookup_records() for more details.
834  *
835  * Since: 2.34
836  */
837 void
838 g_resolver_lookup_records_async (GResolver           *resolver,
839                                  const gchar         *rrname,
840                                  GResolverRecordType  record_type,
841                                  GCancellable        *cancellable,
842                                  GAsyncReadyCallback  callback,
843                                  gpointer             user_data)
844 {
845   g_return_if_fail (G_IS_RESOLVER (resolver));
846   g_return_if_fail (rrname != NULL);
847
848   g_resolver_maybe_reload (resolver);
849   G_RESOLVER_GET_CLASS (resolver)->
850     lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
851 }
852
853 /**
854  * g_resolver_lookup_records_finish:
855  * @resolver: a #GResolver
856  * @result: the result passed to your #GAsyncReadyCallback
857  * @error: return location for a #GError, or %NULL
858  *
859  * Retrieves the result of a previous call to
860  * g_resolver_lookup_records_async(). Returns a list of records as #GVariant
861  * tuples. See #GResolverRecordType for information on what the records contain.
862  *
863  * If the DNS resolution failed, @error (if non-%NULL) will be set to
864  * a value from #GResolverError. If the operation was cancelled,
865  * @error will be set to %G_IO_ERROR_CANCELLED.
866  *
867  * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant,
868  * or %NULL on error. You must free each of the records and the list when you are
869  * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.)
870  *
871  * Since: 2.34
872  */
873 GList *
874 g_resolver_lookup_records_finish (GResolver     *resolver,
875                                   GAsyncResult  *result,
876                                   GError       **error)
877 {
878   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
879   return G_RESOLVER_GET_CLASS (resolver)->
880     lookup_records_finish (resolver, result, error);
881 }
882
883 /**
884  * g_resolver_error_quark:
885  *
886  * Gets the #GResolver Error Quark.
887  *
888  * Return value: a #GQuark.
889  *
890  * Since: 2.22
891  */
892 GQuark
893 g_resolver_error_quark (void)
894 {
895   return g_quark_from_static_string ("g-resolver-error-quark");
896 }
897
898
899 static GResolverError
900 g_resolver_error_from_addrinfo_error (gint err)
901 {
902   switch (err)
903     {
904     case EAI_FAIL:
905 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
906     case EAI_NODATA:
907 #endif
908     case EAI_NONAME:
909       return G_RESOLVER_ERROR_NOT_FOUND;
910
911     case EAI_AGAIN:
912       return G_RESOLVER_ERROR_TEMPORARY_FAILURE;
913
914     default:
915       return G_RESOLVER_ERROR_INTERNAL;
916     }
917 }
918
919 struct addrinfo _g_resolver_addrinfo_hints;
920
921 /* Private method to process a getaddrinfo() response. */
922 GList *
923 _g_resolver_addresses_from_addrinfo (const char       *hostname,
924                                      struct addrinfo  *res,
925                                      gint              gai_retval,
926                                      GError          **error)
927 {
928   struct addrinfo *ai;
929   GSocketAddress *sockaddr;
930   GInetAddress *addr;
931   GList *addrs;
932
933   if (gai_retval != 0)
934     {
935       g_set_error (error, G_RESOLVER_ERROR,
936                    g_resolver_error_from_addrinfo_error (gai_retval),
937                    _("Error resolving '%s': %s"),
938                    hostname, gai_strerror (gai_retval));
939       return NULL;
940     }
941
942   g_return_val_if_fail (res != NULL, NULL);
943
944   addrs = NULL;
945   for (ai = res; ai; ai = ai->ai_next)
946     {
947       sockaddr = g_socket_address_new_from_native (ai->ai_addr, ai->ai_addrlen);
948       if (!sockaddr || !G_IS_INET_SOCKET_ADDRESS (sockaddr))
949         continue;
950
951       addr = g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress *)sockaddr));
952       addrs = g_list_prepend (addrs, addr);
953       g_object_unref (sockaddr);
954     }
955
956   return g_list_reverse (addrs);
957 }
958
959 /* Private method to set up a getnameinfo() request */
960 void
961 _g_resolver_address_to_sockaddr (GInetAddress            *address,
962                                  struct sockaddr_storage *sa,
963                                  gsize                   *len)
964 {
965   GSocketAddress *sockaddr;
966
967   sockaddr = g_inet_socket_address_new (address, 0);
968   g_socket_address_to_native (sockaddr, (struct sockaddr *)sa, sizeof (*sa), NULL);
969   *len = g_socket_address_get_native_size (sockaddr);
970   g_object_unref (sockaddr);
971 }
972
973 /* Private method to process a getnameinfo() response. */
974 char *
975 _g_resolver_name_from_nameinfo (GInetAddress  *address,
976                                 const gchar   *name,
977                                 gint           gni_retval,
978                                 GError       **error)
979 {
980   if (gni_retval != 0)
981     {
982       gchar *phys;
983
984       phys = g_inet_address_to_string (address);
985       g_set_error (error, G_RESOLVER_ERROR,
986                    g_resolver_error_from_addrinfo_error (gni_retval),
987                    _("Error reverse-resolving '%s': %s"),
988                    phys ? phys : "(unknown)", gai_strerror (gni_retval));
989       g_free (phys);
990       return NULL;
991     }
992
993   return g_strdup (name);
994 }
995
996 #if defined(G_OS_UNIX)
997
998 static gboolean
999 parse_short (guchar  **p,
1000              guchar   *end,
1001              guint16  *value)
1002 {
1003   if (*p + 2 > end)
1004     return FALSE;
1005   GETSHORT (*value, *p);
1006   return TRUE;
1007 }
1008
1009 static gboolean
1010 parse_long (guchar  **p,
1011             guchar   *end,
1012             guint32  *value)
1013 {
1014   if (*p + 4 > end)
1015     return FALSE;
1016   GETLONG (*value, *p);
1017   return TRUE;
1018 }
1019
1020 static GVariant *
1021 parse_res_srv (guchar  *answer,
1022                guchar  *end,
1023                guchar  *p)
1024 {
1025   gchar namebuf[1024];
1026   guint16 priority, weight, port;
1027   gint n;
1028
1029   if (!parse_short (&p, end, &priority) ||
1030       !parse_short (&p, end, &weight) ||
1031       !parse_short (&p, end, &port))
1032     return NULL;
1033
1034   n = dn_expand (answer, end, p, namebuf, sizeof (namebuf));
1035   if (n < 0)
1036     return NULL;
1037   *p += n;
1038
1039   return g_variant_new ("(qqqs)",
1040                         priority,
1041                         weight,
1042                         port,
1043                         namebuf);
1044 }
1045
1046 static GVariant *
1047 parse_res_soa (guchar  *answer,
1048                guchar  *end,
1049                guchar  *p)
1050 {
1051   gchar mnamebuf[1024];
1052   gchar rnamebuf[1024];
1053   guint32 serial, refresh, retry, expire, ttl;
1054   gint n;
1055
1056   n = dn_expand (answer, end, p, mnamebuf, sizeof (mnamebuf));
1057   if (n < 0)
1058     return NULL;
1059   p += n;
1060
1061   n = dn_expand (answer, end, p, rnamebuf, sizeof (rnamebuf));
1062   if (n < 0)
1063     return NULL;
1064   p += n;
1065
1066   if (!parse_long (&p, end, &serial) ||
1067       !parse_long (&p, end, &refresh) ||
1068       !parse_long (&p, end, &retry) ||
1069       !parse_long (&p, end, &expire) ||
1070       !parse_long (&p, end, &ttl))
1071     return NULL;
1072
1073   return g_variant_new ("(ssuuuuu)",
1074                         mnamebuf,
1075                         rnamebuf,
1076                         serial,
1077                         refresh,
1078                         retry,
1079                         expire,
1080                         ttl);
1081 }
1082
1083 static GVariant *
1084 parse_res_ns (guchar  *answer,
1085               guchar  *end,
1086               guchar  *p)
1087 {
1088   gchar namebuf[1024];
1089   gint n;
1090
1091   n = dn_expand (answer, end, p, namebuf, sizeof (namebuf));
1092   if (n < 0)
1093     return NULL;
1094
1095   return g_variant_new ("(s)", namebuf);
1096 }
1097
1098 static GVariant *
1099 parse_res_mx (guchar  *answer,
1100               guchar  *end,
1101               guchar  *p)
1102 {
1103   gchar namebuf[1024];
1104   guint16 preference;
1105   gint n;
1106
1107   if (!parse_short (&p, end, &preference))
1108     return NULL;
1109
1110   n = dn_expand (answer, end, p, namebuf, sizeof (namebuf));
1111   if (n < 0)
1112     return NULL;
1113   p += n;
1114
1115   return g_variant_new ("(qs)",
1116                         preference,
1117                         namebuf);
1118 }
1119
1120 static GVariant *
1121 parse_res_txt (guchar  *answer,
1122                guchar  *end,
1123                guchar  *p)
1124 {
1125   GVariant *record;
1126   GPtrArray *array;
1127   gsize len;
1128
1129   array = g_ptr_array_new_with_free_func (g_free);
1130   while (p < end)
1131     {
1132       len = *(p++);
1133       if (len > p - end)
1134         break;
1135       g_ptr_array_add (array, g_strndup ((gchar *)p, len));
1136       p += len;
1137     }
1138
1139   record = g_variant_new ("(@as)",
1140                           g_variant_new_strv ((const gchar **)array->pdata, array->len));
1141   g_ptr_array_free (array, TRUE);
1142   return record;
1143 }
1144
1145 gint
1146 _g_resolver_record_type_to_rrtype (GResolverRecordType type)
1147 {
1148   switch (type)
1149   {
1150     case G_RESOLVER_RECORD_SRV:
1151       return T_SRV;
1152     case G_RESOLVER_RECORD_TXT:
1153       return T_TXT;
1154     case G_RESOLVER_RECORD_SOA:
1155       return T_SOA;
1156     case G_RESOLVER_RECORD_NS:
1157       return T_NS;
1158     case G_RESOLVER_RECORD_MX:
1159       return T_MX;
1160   }
1161   g_return_val_if_reached (-1);
1162 }
1163
1164 /* Private method to process a res_query response into GSrvTargets */
1165 GList *
1166 _g_resolver_records_from_res_query (const gchar      *rrname,
1167                                     gint              rrtype,
1168                                     guchar           *answer,
1169                                     gint              len,
1170                                     gint              herr,
1171                                     GError          **error)
1172 {
1173   gint count;
1174   guchar *end, *p;
1175   guint16 type, qclass, rdlength;
1176   guint32 ttl;
1177   HEADER *header;
1178   GList *records;
1179   GVariant *record;
1180   gint n, i;
1181
1182   if (len <= 0)
1183     {
1184       GResolverError errnum;
1185       const gchar *format;
1186
1187       if (len == 0 || herr == HOST_NOT_FOUND || herr == NO_DATA)
1188         {
1189           errnum = G_RESOLVER_ERROR_NOT_FOUND;
1190           format = _("No DNS record of the requested type for '%s'");
1191         }
1192       else if (herr == TRY_AGAIN)
1193         {
1194           errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE;
1195           format = _("Temporarily unable to resolve '%s'");
1196         }
1197       else
1198         {
1199           errnum = G_RESOLVER_ERROR_INTERNAL;
1200           format = _("Error resolving '%s'");
1201         }
1202
1203       g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname);
1204       return NULL;
1205     }
1206
1207   records = NULL;
1208
1209   header = (HEADER *)answer;
1210   p = answer + sizeof (HEADER);
1211   end = answer + len;
1212
1213   /* Skip query */
1214   count = ntohs (header->qdcount);
1215   for (i = 0; i < count && p < end; i++)
1216     {
1217       n = dn_skipname (p, end);
1218       if (n < 0)
1219         break;
1220       p += n;
1221       p += 4;
1222     }
1223
1224   /* Incomplete response */
1225   if (i < count)
1226     {
1227       g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
1228                    _("Incomplete data received for '%s'"), rrname);
1229       return NULL;
1230     }
1231
1232   /* Read answers */
1233   count = ntohs (header->ancount);
1234   for (i = 0; i < count && p < end; i++)
1235     {
1236       n = dn_skipname (p, end);
1237       if (n < 0)
1238         break;
1239       p += n;
1240
1241       if (!parse_short (&p, end, &type) ||
1242           !parse_short (&p, end, &qclass) ||
1243           !parse_long (&p, end, &ttl) ||
1244           !parse_short (&p, end, &rdlength))
1245         break;
1246
1247       ttl = ttl; /* To avoid -Wunused-but-set-variable */
1248
1249       if (p + rdlength > end)
1250         break;
1251
1252       if (type == rrtype && qclass == C_IN)
1253         {
1254           switch (rrtype)
1255             {
1256             case T_SRV:
1257               record = parse_res_srv (answer, end, p);
1258               break;
1259             case T_MX:
1260               record = parse_res_mx (answer, end, p);
1261               break;
1262             case T_SOA:
1263               record = parse_res_soa (answer, end, p);
1264               break;
1265             case T_NS:
1266               record = parse_res_ns (answer, end, p);
1267               break;
1268             case T_TXT:
1269               record = parse_res_txt (answer, p + rdlength, p);
1270               break;
1271             default:
1272               g_warn_if_reached ();
1273               record = NULL;
1274               break;
1275             }
1276
1277           if (record != NULL)
1278             records = g_list_prepend (records, record);
1279         }
1280
1281       p += rdlength;
1282     }
1283
1284   /* Somehow got a truncated response */
1285   if (i < count)
1286     {
1287       g_list_free_full (records, (GDestroyNotify)g_variant_unref);
1288       g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
1289                    _("Incomplete data received for '%s'"), rrname);
1290       return NULL;
1291     }
1292
1293   return records;
1294 }
1295
1296 #elif defined(G_OS_WIN32)
1297 static GVariant *
1298 parse_dns_srv (DNS_RECORD *rec)
1299 {
1300   return g_variant_new ("(qqqs)",
1301                         (guint16)rec->Data.SRV.wPriority,
1302                         (guint16)rec->Data.SRV.wWeight,
1303                         (guint16)rec->Data.SRV.wPort,
1304                         rec->Data.SRV.pNameTarget);
1305 }
1306
1307 static GVariant *
1308 parse_dns_soa (DNS_RECORD *rec)
1309 {
1310   return g_variant_new ("(ssuuuuu)",
1311                         rec->Data.SOA.pNamePrimaryServer,
1312                         rec->Data.SOA.pNameAdministrator,
1313                         (guint32)rec->Data.SOA.dwSerialNo,
1314                         (guint32)rec->Data.SOA.dwRefresh,
1315                         (guint32)rec->Data.SOA.dwRetry,
1316                         (guint32)rec->Data.SOA.dwExpire,
1317                         (guint32)rec->Data.SOA.dwDefaultTtl);
1318 }
1319
1320 static GVariant *
1321 parse_dns_ns (DNS_RECORD *rec)
1322 {
1323   return g_variant_new ("(s)", rec->Data.NS.pNameHost);
1324 }
1325
1326 static GVariant *
1327 parse_dns_mx (DNS_RECORD *rec)
1328 {
1329   return g_variant_new ("(qs)",
1330                         (guint16)rec->Data.MX.wPreference,
1331                         rec->Data.MX.pNameExchange);
1332 }
1333
1334 static GVariant *
1335 parse_dns_txt (DNS_RECORD *rec)
1336 {
1337   GVariant *record;
1338   GPtrArray *array;
1339   DWORD i;
1340
1341   array = g_ptr_array_new ();
1342   for (i = 0; i < rec->Data.TXT.dwStringCount; i++)
1343     g_ptr_array_add (array, rec->Data.TXT.pStringArray[i]);
1344   record = g_variant_new ("(@as)",
1345                           g_variant_new_strv ((const gchar **)array->pdata, array->len));
1346   g_ptr_array_free (array, TRUE);
1347   return record;
1348 }
1349
1350 WORD
1351 _g_resolver_record_type_to_dnstype (GResolverRecordType type)
1352 {
1353   switch (type)
1354   {
1355     case G_RESOLVER_RECORD_SRV:
1356       return DNS_TYPE_SRV;
1357     case G_RESOLVER_RECORD_TXT:
1358       return DNS_TYPE_TEXT;
1359     case G_RESOLVER_RECORD_SOA:
1360       return DNS_TYPE_SOA;
1361     case G_RESOLVER_RECORD_NS:
1362       return DNS_TYPE_NS;
1363     case G_RESOLVER_RECORD_MX:
1364       return DNS_TYPE_MX;
1365   }
1366   g_return_val_if_reached (-1);
1367 }
1368
1369 /* Private method to process a DnsQuery response into GVariants */
1370 GList *
1371 _g_resolver_records_from_DnsQuery (const gchar  *rrname,
1372                                    WORD          dnstype,
1373                                    DNS_STATUS    status,
1374                                    DNS_RECORD   *results,
1375                                    GError      **error)
1376 {
1377   DNS_RECORD *rec;
1378   gpointer record;
1379   GList *records;
1380
1381   if (status != ERROR_SUCCESS)
1382     {
1383       GResolverError errnum;
1384       const gchar *format;
1385
1386       if (status == DNS_ERROR_RCODE_NAME_ERROR)
1387         {
1388           errnum = G_RESOLVER_ERROR_NOT_FOUND;
1389           format = _("No DNS record of the requested type for '%s'");
1390         }
1391       else if (status == DNS_ERROR_RCODE_SERVER_FAILURE)
1392         {
1393           errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE;
1394           format = _("Temporarily unable to resolve '%s'");
1395         }
1396       else
1397         {
1398           errnum = G_RESOLVER_ERROR_INTERNAL;
1399           format = _("Error resolving '%s'");
1400         }
1401
1402       g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname);
1403       return NULL;
1404     }
1405
1406   records = NULL;
1407   for (rec = results; rec; rec = rec->pNext)
1408     {
1409       if (rec->wType != dnstype)
1410         continue;
1411       switch (dnstype)
1412         {
1413         case DNS_TYPE_SRV:
1414           record = parse_dns_srv (rec);
1415           break;
1416         case DNS_TYPE_SOA:
1417           record = parse_dns_soa (rec);
1418           break;
1419         case DNS_TYPE_NS:
1420           record = parse_dns_ns (rec);
1421           break;
1422         case DNS_TYPE_MX:
1423           record = parse_dns_mx (rec);
1424           break;
1425         case DNS_TYPE_TEXT:
1426           record = parse_dns_txt (rec);
1427           break;
1428         default:
1429           g_warn_if_reached ();
1430           record = NULL;
1431           break;
1432         }
1433       if (record != NULL)
1434         records = g_list_prepend (records, g_variant_ref_sink (record));
1435     }
1436
1437   return records;
1438 }
1439
1440 #endif