1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3 /* GIO - GLib Input, Output and Streaming Library
5 * Copyright (C) 2008 Red Hat, Inc.
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.
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.
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.
27 #include "gresolver.h"
28 #include "gnetworkingprivate.h"
29 #include "gasyncresult.h"
30 #include "ginetaddress.h"
31 #include "gsimpleasyncresult.h"
33 #include "gsrvtarget.h"
34 #include "gthreadedresolver.h"
45 * @short_description: Asynchronous and cancellable DNS resolver
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()).
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.
63 static guint signals[LAST_SIGNAL] = { 0 };
65 struct _GResolverPrivate {
67 time_t resolv_conf_timestamp;
76 * The object that handles DNS resolution. Use g_resolver_get_default()
77 * to get the default resolver.
79 G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT)
82 srv_records_to_targets (GList *records)
84 const gchar *hostname;
85 guint16 port, priority, weight;
89 for (l = records; l != NULL; l = g_list_next (l))
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);
97 return g_srv_target_list_sort (records);
101 g_resolver_real_lookup_service (GResolver *resolver,
103 GCancellable *cancellable,
108 records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver,
110 G_RESOLVER_RECORD_SRV,
114 return srv_records_to_targets (records);
118 g_resolver_real_lookup_service_async (GResolver *resolver,
120 GCancellable *cancellable,
121 GAsyncReadyCallback callback,
124 G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver,
126 G_RESOLVER_RECORD_SRV,
133 g_resolver_real_lookup_service_finish (GResolver *resolver,
134 GAsyncResult *result,
139 records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver,
143 return srv_records_to_targets (records);
147 g_resolver_class_init (GResolverClass *resolver_class)
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;
154 g_type_class_add_private (resolver_class, sizeof (GResolverPrivate));
156 /* Make sure _g_networking_init() has been called */
157 g_type_ensure (G_TYPE_INET_ADDRESS);
161 * @resolver: a #GResolver
163 * Emitted when the resolver notices that the system resolver
164 * configuration has changed.
167 g_signal_new (I_("reload"),
170 G_STRUCT_OFFSET (GResolverClass, reload),
172 g_cclosure_marshal_VOID__VOID,
177 g_resolver_init (GResolver *resolver)
183 resolver->priv = G_TYPE_INSTANCE_GET_PRIVATE (resolver, G_TYPE_RESOLVER, GResolverPrivate);
186 if (stat (_PATH_RESCONF, &st) == 0)
187 resolver->priv->resolv_conf_timestamp = st.st_mtime;
191 static GResolver *default_resolver;
194 * g_resolver_get_default:
196 * Gets the default #GResolver. You should unref it when you are done
197 * with it. #GResolver may use its reference count as a hint about how
198 * many threads it should allocate for concurrent DNS resolutions.
200 * Return value: (transfer full): the default #GResolver.
205 g_resolver_get_default (void)
207 if (!default_resolver)
208 default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL);
210 return g_object_ref (default_resolver);
214 * g_resolver_set_default:
215 * @resolver: the new default #GResolver
217 * Sets @resolver to be the application's default resolver (reffing
218 * @resolver, and unreffing the previous default resolver, if any).
219 * Future calls to g_resolver_get_default() will return this resolver.
221 * This can be used if an application wants to perform any sort of DNS
222 * caching or "pinning"; it can implement its own #GResolver that
223 * calls the original default resolver for DNS operations, and
224 * implements its own cache policies on top of that, and then set
225 * itself as the default resolver for all later code to use.
230 g_resolver_set_default (GResolver *resolver)
232 if (default_resolver)
233 g_object_unref (default_resolver);
234 default_resolver = g_object_ref (resolver);
239 g_resolver_maybe_reload (GResolver *resolver)
244 if (stat (_PATH_RESCONF, &st) == 0)
246 if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
248 resolver->priv->resolv_conf_timestamp = st.st_mtime;
250 g_signal_emit (resolver, signals[RELOAD], 0);
256 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
258 remove_duplicates (GList *addrs)
264 /* TODO: if this is too slow (it's O(n^2) but n is typically really
265 * small), we can do something more clever but note that we must not
266 * change the order of elements...
268 for (l = addrs; l != NULL; l = l->next)
270 GInetAddress *address = G_INET_ADDRESS (l->data);
271 for (ll = l->next; ll != NULL; ll = lll)
273 GInetAddress *other_address = G_INET_ADDRESS (ll->data);
275 if (g_inet_address_equal (address, other_address))
277 g_object_unref (other_address);
278 /* we never return the first element */
279 g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs);
287 * g_resolver_lookup_by_name:
288 * @resolver: a #GResolver
289 * @hostname: the hostname to look up
290 * @cancellable: (allow-none): a #GCancellable, or %NULL
291 * @error: return location for a #GError, or %NULL
293 * Synchronously resolves @hostname to determine its associated IP
294 * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
295 * the textual form of an IP address (in which case this just becomes
296 * a wrapper around g_inet_address_new_from_string()).
298 * On success, g_resolver_lookup_by_name() will return a #GList of
299 * #GInetAddress, sorted in order of preference and guaranteed to not
300 * contain duplicates. That is, if using the result to connect to
301 * @hostname, you should attempt to connect to the first address
302 * first, then the second if the first fails, etc. If you are using
303 * the result to listen on a socket, it is appropriate to add each
304 * result using e.g. g_socket_listener_add_address().
306 * If the DNS resolution fails, @error (if non-%NULL) will be set to a
307 * value from #GResolverError.
309 * If @cancellable is non-%NULL, it can be used to cancel the
310 * operation, in which case @error (if non-%NULL) will be set to
311 * %G_IO_ERROR_CANCELLED.
313 * If you are planning to connect to a socket on the resolved IP
314 * address, it may be easier to create a #GNetworkAddress and use its
315 * #GSocketConnectable interface.
317 * Return value: (element-type GInetAddress) (transfer full): a #GList
318 * of #GInetAddress, or %NULL on error. You
319 * must unref each of the addresses and free the list when you are
320 * done with it. (You can use g_resolver_free_addresses() to do this.)
325 g_resolver_lookup_by_name (GResolver *resolver,
326 const gchar *hostname,
327 GCancellable *cancellable,
332 gchar *ascii_hostname = NULL;
334 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
335 g_return_val_if_fail (hostname != NULL, NULL);
337 /* Check if @hostname is just an IP address */
338 addr = g_inet_address_new_from_string (hostname);
340 return g_list_append (NULL, addr);
342 if (g_hostname_is_non_ascii (hostname))
343 hostname = ascii_hostname = g_hostname_to_ascii (hostname);
345 g_resolver_maybe_reload (resolver);
346 addrs = G_RESOLVER_GET_CLASS (resolver)->
347 lookup_by_name (resolver, hostname, cancellable, error);
349 remove_duplicates (addrs);
351 g_free (ascii_hostname);
356 * g_resolver_lookup_by_name_async:
357 * @resolver: a #GResolver
358 * @hostname: the hostname to look up the address of
359 * @cancellable: (allow-none): a #GCancellable, or %NULL
360 * @callback: (scope async): callback to call after resolution completes
361 * @user_data: (closure): data for @callback
363 * Begins asynchronously resolving @hostname to determine its
364 * associated IP address(es), and eventually calls @callback, which
365 * must call g_resolver_lookup_by_name_finish() to get the result.
366 * See g_resolver_lookup_by_name() for more details.
371 g_resolver_lookup_by_name_async (GResolver *resolver,
372 const gchar *hostname,
373 GCancellable *cancellable,
374 GAsyncReadyCallback callback,
378 gchar *ascii_hostname = NULL;
380 g_return_if_fail (G_IS_RESOLVER (resolver));
381 g_return_if_fail (hostname != NULL);
383 /* Check if @hostname is just an IP address */
384 addr = g_inet_address_new_from_string (hostname);
389 task = g_task_new (resolver, cancellable, callback, user_data);
390 g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
391 g_task_return_pointer (task, g_list_append (NULL, addr),
392 (GDestroyNotify) g_resolver_free_addresses);
393 g_object_unref (task);
397 if (g_hostname_is_non_ascii (hostname))
398 hostname = ascii_hostname = g_hostname_to_ascii (hostname);
400 g_resolver_maybe_reload (resolver);
401 G_RESOLVER_GET_CLASS (resolver)->
402 lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
404 g_free (ascii_hostname);
408 * g_resolver_lookup_by_name_finish:
409 * @resolver: a #GResolver
410 * @result: the result passed to your #GAsyncReadyCallback
411 * @error: return location for a #GError, or %NULL
413 * Retrieves the result of a call to
414 * g_resolver_lookup_by_name_async().
416 * If the DNS resolution failed, @error (if non-%NULL) will be set to
417 * a value from #GResolverError. If the operation was cancelled,
418 * @error will be set to %G_IO_ERROR_CANCELLED.
420 * Return value: (element-type GInetAddress) (transfer full): a #GList
421 * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
427 g_resolver_lookup_by_name_finish (GResolver *resolver,
428 GAsyncResult *result,
433 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
435 if (g_async_result_legacy_propagate_error (result, error))
437 else if (g_async_result_is_tagged (result, g_resolver_lookup_by_name_async))
439 /* Handle the stringified-IP-addr case */
440 return g_task_propagate_pointer (G_TASK (result), error);
443 addrs = G_RESOLVER_GET_CLASS (resolver)->
444 lookup_by_name_finish (resolver, result, error);
446 remove_duplicates (addrs);
452 * g_resolver_free_addresses: (skip)
453 * @addresses: a #GList of #GInetAddress
455 * Frees @addresses (which should be the return value from
456 * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
457 * (This is a convenience method; you can also simply free the results
463 g_resolver_free_addresses (GList *addresses)
467 for (a = addresses; a; a = a->next)
468 g_object_unref (a->data);
469 g_list_free (addresses);
473 * g_resolver_lookup_by_address:
474 * @resolver: a #GResolver
475 * @address: the address to reverse-resolve
476 * @cancellable: (allow-none): a #GCancellable, or %NULL
477 * @error: return location for a #GError, or %NULL
479 * Synchronously reverse-resolves @address to determine its
480 * associated hostname.
482 * If the DNS resolution fails, @error (if non-%NULL) will be set to
483 * a value from #GResolverError.
485 * If @cancellable is non-%NULL, it can be used to cancel the
486 * operation, in which case @error (if non-%NULL) will be set to
487 * %G_IO_ERROR_CANCELLED.
489 * Return value: a hostname (either ASCII-only, or in ASCII-encoded
490 * form), or %NULL on error.
495 g_resolver_lookup_by_address (GResolver *resolver,
496 GInetAddress *address,
497 GCancellable *cancellable,
500 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
501 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
503 g_resolver_maybe_reload (resolver);
504 return G_RESOLVER_GET_CLASS (resolver)->
505 lookup_by_address (resolver, address, cancellable, error);
509 * g_resolver_lookup_by_address_async:
510 * @resolver: a #GResolver
511 * @address: the address to reverse-resolve
512 * @cancellable: (allow-none): a #GCancellable, or %NULL
513 * @callback: (scope async): callback to call after resolution completes
514 * @user_data: (closure): data for @callback
516 * Begins asynchronously reverse-resolving @address to determine its
517 * associated hostname, and eventually calls @callback, which must
518 * call g_resolver_lookup_by_address_finish() to get the final result.
523 g_resolver_lookup_by_address_async (GResolver *resolver,
524 GInetAddress *address,
525 GCancellable *cancellable,
526 GAsyncReadyCallback callback,
529 g_return_if_fail (G_IS_RESOLVER (resolver));
530 g_return_if_fail (G_IS_INET_ADDRESS (address));
532 g_resolver_maybe_reload (resolver);
533 G_RESOLVER_GET_CLASS (resolver)->
534 lookup_by_address_async (resolver, address, cancellable, callback, user_data);
538 * g_resolver_lookup_by_address_finish:
539 * @resolver: a #GResolver
540 * @result: the result passed to your #GAsyncReadyCallback
541 * @error: return location for a #GError, or %NULL
543 * Retrieves the result of a previous call to
544 * g_resolver_lookup_by_address_async().
546 * If the DNS resolution failed, @error (if non-%NULL) will be set to
547 * a value from #GResolverError. If the operation was cancelled,
548 * @error will be set to %G_IO_ERROR_CANCELLED.
550 * Return value: a hostname (either ASCII-only, or in ASCII-encoded
551 * form), or %NULL on error.
556 g_resolver_lookup_by_address_finish (GResolver *resolver,
557 GAsyncResult *result,
560 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
562 if (g_async_result_legacy_propagate_error (result, error))
565 return G_RESOLVER_GET_CLASS (resolver)->
566 lookup_by_address_finish (resolver, result, error);
570 g_resolver_get_service_rrname (const char *service,
571 const char *protocol,
574 gchar *rrname, *ascii_domain = NULL;
576 if (g_hostname_is_non_ascii (domain))
577 domain = ascii_domain = g_hostname_to_ascii (domain);
579 rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
581 g_free (ascii_domain);
586 * g_resolver_lookup_service:
587 * @resolver: a #GResolver
588 * @service: the service type to look up (eg, "ldap")
589 * @protocol: the networking protocol to use for @service (eg, "tcp")
590 * @domain: the DNS domain to look up the service in
591 * @cancellable: (allow-none): a #GCancellable, or %NULL
592 * @error: return location for a #GError, or %NULL
594 * Synchronously performs a DNS SRV lookup for the given @service and
595 * @protocol in the given @domain and returns an array of #GSrvTarget.
596 * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
597 * @service and @protocol arguments <emphasis>do not</emphasis>
598 * include the leading underscore that appears in the actual DNS
601 * On success, g_resolver_lookup_service() will return a #GList of
602 * #GSrvTarget, sorted in order of preference. (That is, you should
603 * attempt to connect to the first target first, then the second if
604 * the first fails, etc.)
606 * If the DNS resolution fails, @error (if non-%NULL) will be set to
607 * a value from #GResolverError.
609 * If @cancellable is non-%NULL, it can be used to cancel the
610 * operation, in which case @error (if non-%NULL) will be set to
611 * %G_IO_ERROR_CANCELLED.
613 * If you are planning to connect to the service, it is usually easier
614 * to create a #GNetworkService and use its #GSocketConnectable
617 * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
618 * or %NULL on error. You must free each of the targets and the list when you are
619 * done with it. (You can use g_resolver_free_targets() to do this.)
624 g_resolver_lookup_service (GResolver *resolver,
625 const gchar *service,
626 const gchar *protocol,
628 GCancellable *cancellable,
634 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
635 g_return_val_if_fail (service != NULL, NULL);
636 g_return_val_if_fail (protocol != NULL, NULL);
637 g_return_val_if_fail (domain != NULL, NULL);
639 rrname = g_resolver_get_service_rrname (service, protocol, domain);
641 g_resolver_maybe_reload (resolver);
642 targets = G_RESOLVER_GET_CLASS (resolver)->
643 lookup_service (resolver, rrname, cancellable, error);
650 * g_resolver_lookup_service_async:
651 * @resolver: a #GResolver
652 * @service: the service type to look up (eg, "ldap")
653 * @protocol: the networking protocol to use for @service (eg, "tcp")
654 * @domain: the DNS domain to look up the service in
655 * @cancellable: (allow-none): a #GCancellable, or %NULL
656 * @callback: (scope async): callback to call after resolution completes
657 * @user_data: (closure): data for @callback
659 * Begins asynchronously performing a DNS SRV lookup for the given
660 * @service and @protocol in the given @domain, and eventually calls
661 * @callback, which must call g_resolver_lookup_service_finish() to
662 * get the final result. See g_resolver_lookup_service() for more
668 g_resolver_lookup_service_async (GResolver *resolver,
669 const gchar *service,
670 const gchar *protocol,
672 GCancellable *cancellable,
673 GAsyncReadyCallback callback,
678 g_return_if_fail (G_IS_RESOLVER (resolver));
679 g_return_if_fail (service != NULL);
680 g_return_if_fail (protocol != NULL);
681 g_return_if_fail (domain != NULL);
683 rrname = g_resolver_get_service_rrname (service, protocol, domain);
685 g_resolver_maybe_reload (resolver);
686 G_RESOLVER_GET_CLASS (resolver)->
687 lookup_service_async (resolver, rrname, cancellable, callback, user_data);
693 * g_resolver_lookup_service_finish:
694 * @resolver: a #GResolver
695 * @result: the result passed to your #GAsyncReadyCallback
696 * @error: return location for a #GError, or %NULL
698 * Retrieves the result of a previous call to
699 * g_resolver_lookup_service_async().
701 * If the DNS resolution failed, @error (if non-%NULL) will be set to
702 * a value from #GResolverError. If the operation was cancelled,
703 * @error will be set to %G_IO_ERROR_CANCELLED.
705 * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
706 * or %NULL on error. See g_resolver_lookup_service() for more details.
711 g_resolver_lookup_service_finish (GResolver *resolver,
712 GAsyncResult *result,
715 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
717 if (g_async_result_legacy_propagate_error (result, error))
720 return G_RESOLVER_GET_CLASS (resolver)->
721 lookup_service_finish (resolver, result, error);
725 * g_resolver_free_targets: (skip)
726 * @targets: a #GList of #GSrvTarget
728 * Frees @targets (which should be the return value from
729 * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
730 * (This is a convenience method; you can also simply free the
736 g_resolver_free_targets (GList *targets)
740 for (t = targets; t; t = t->next)
741 g_srv_target_free (t->data);
742 g_list_free (targets);
746 * g_resolver_lookup_records:
747 * @resolver: a #GResolver
748 * @rrname: the DNS name to lookup the record for
749 * @record_type: the type of DNS record to lookup
750 * @cancellable: (allow-none): a #GCancellable, or %NULL
751 * @error: return location for a #GError, or %NULL
753 * Synchronously performs a DNS record lookup for the given @rrname and returns
754 * a list of records as #GVariant tuples. See #GResolverRecordType for
755 * information on what the records contain for each @record_type.
757 * If the DNS resolution fails, @error (if non-%NULL) will be set to
758 * a value from #GResolverError.
760 * If @cancellable is non-%NULL, it can be used to cancel the
761 * operation, in which case @error (if non-%NULL) will be set to
762 * %G_IO_ERROR_CANCELLED.
764 * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant,
765 * or %NULL on error. You must free each of the records and the list when you are
766 * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.)
771 g_resolver_lookup_records (GResolver *resolver,
773 GResolverRecordType record_type,
774 GCancellable *cancellable,
779 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
780 g_return_val_if_fail (rrname != NULL, NULL);
782 g_resolver_maybe_reload (resolver);
783 records = G_RESOLVER_GET_CLASS (resolver)->
784 lookup_records (resolver, rrname, record_type, cancellable, error);
790 * g_resolver_lookup_records_async:
791 * @resolver: a #GResolver
792 * @rrname: the DNS name to lookup the record for
793 * @record_type: the type of DNS record to lookup
794 * @cancellable: (allow-none): a #GCancellable, or %NULL
795 * @callback: (scope async): callback to call after resolution completes
796 * @user_data: (closure): data for @callback
798 * Begins asynchronously performing a DNS lookup for the given
799 * @rrname, and eventually calls @callback, which must call
800 * g_resolver_lookup_records_finish() to get the final result. See
801 * g_resolver_lookup_records() for more details.
806 g_resolver_lookup_records_async (GResolver *resolver,
808 GResolverRecordType record_type,
809 GCancellable *cancellable,
810 GAsyncReadyCallback callback,
813 g_return_if_fail (G_IS_RESOLVER (resolver));
814 g_return_if_fail (rrname != NULL);
816 g_resolver_maybe_reload (resolver);
817 G_RESOLVER_GET_CLASS (resolver)->
818 lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
822 * g_resolver_lookup_records_finish:
823 * @resolver: a #GResolver
824 * @result: the result passed to your #GAsyncReadyCallback
825 * @error: return location for a #GError, or %NULL
827 * Retrieves the result of a previous call to
828 * g_resolver_lookup_records_async(). Returns a list of records as #GVariant
829 * tuples. See #GResolverRecordType for information on what the records contain.
831 * If the DNS resolution failed, @error (if non-%NULL) will be set to
832 * a value from #GResolverError. If the operation was cancelled,
833 * @error will be set to %G_IO_ERROR_CANCELLED.
835 * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant,
836 * or %NULL on error. You must free each of the records and the list when you are
837 * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.)
842 g_resolver_lookup_records_finish (GResolver *resolver,
843 GAsyncResult *result,
846 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
847 return G_RESOLVER_GET_CLASS (resolver)->
848 lookup_records_finish (resolver, result, error);
852 * g_resolver_error_quark:
854 * Gets the #GResolver Error Quark.
856 * Return value: a #GQuark.
860 G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error)