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 "ginetsocketaddress.h"
32 #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 g_resolver_class_init (GResolverClass
*resolver_class
)
86 g_type_class_add_private (resolver_class
, sizeof (GResolverPrivate
));
88 /* Make sure _g_networking_init() has been called */
89 type
= g_inet_address_get_type ();
90 (type
); /* To avoid -Wunused-but-set-variable */
92 /* Initialize _g_resolver_addrinfo_hints */
94 _g_resolver_addrinfo_hints
.ai_flags
|= AI_ADDRCONFIG
;
96 /* These two don't actually matter, they just get copied into the
97 * returned addrinfo structures (and then we ignore them). But if
98 * we leave them unset, we'll get back duplicate answers.
100 _g_resolver_addrinfo_hints
.ai_socktype
= SOCK_STREAM
;
101 _g_resolver_addrinfo_hints
.ai_protocol
= IPPROTO_TCP
;
105 * @resolver: a #GResolver
107 * Emitted when the resolver notices that the system resolver
108 * configuration has changed.
111 g_signal_new (I_("reload"),
114 G_STRUCT_OFFSET (GResolverClass
, reload
),
116 g_cclosure_marshal_VOID__VOID
,
121 g_resolver_init (GResolver
*resolver
)
127 resolver
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (resolver
, G_TYPE_RESOLVER
, GResolverPrivate
);
130 if (stat (_PATH_RESCONF
, &st
) == 0)
131 resolver
->priv
->resolv_conf_timestamp
= st
.st_mtime
;
135 static GResolver
*default_resolver
;
138 * g_resolver_get_default:
140 * Gets the default #GResolver. You should unref it when you are done
141 * with it. #GResolver may use its reference count as a hint about how
142 * many threads it should allocate for concurrent DNS resolutions.
144 * Return value: (transfer full): the default #GResolver.
149 g_resolver_get_default (void)
151 if (!default_resolver
)
152 default_resolver
= g_object_new (G_TYPE_THREADED_RESOLVER
, NULL
);
154 return g_object_ref (default_resolver
);
158 * g_resolver_set_default:
159 * @resolver: the new default #GResolver
161 * Sets @resolver to be the application's default resolver (reffing
162 * @resolver, and unreffing the previous default resolver, if any).
163 * Future calls to g_resolver_get_default() will return this resolver.
165 * This can be used if an application wants to perform any sort of DNS
166 * caching or "pinning"; it can implement its own #GResolver that
167 * calls the original default resolver for DNS operations, and
168 * implements its own cache policies on top of that, and then set
169 * itself as the default resolver for all later code to use.
174 g_resolver_set_default (GResolver
*resolver
)
176 if (default_resolver
)
177 g_object_unref (default_resolver
);
178 default_resolver
= g_object_ref (resolver
);
183 g_resolver_maybe_reload (GResolver
*resolver
)
188 if (stat (_PATH_RESCONF
, &st
) == 0)
190 if (st
.st_mtime
!= resolver
->priv
->resolv_conf_timestamp
)
192 resolver
->priv
->resolv_conf_timestamp
= st
.st_mtime
;
194 g_signal_emit (resolver
, signals
[RELOAD
], 0);
200 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
202 remove_duplicates (GList
*addrs
)
208 /* TODO: if this is too slow (it's O(n^2) but n is typically really
209 * small), we can do something more clever but note that we must not
210 * change the order of elements...
212 for (l
= addrs
; l
!= NULL
; l
= l
->next
)
214 GInetAddress
*address
= G_INET_ADDRESS (l
->data
);
215 for (ll
= l
->next
; ll
!= NULL
; ll
= lll
)
217 GInetAddress
*other_address
= G_INET_ADDRESS (ll
->data
);
219 if (g_inet_address_equal (address
, other_address
))
221 g_object_unref (other_address
);
222 /* we never return the first element */
223 g_warn_if_fail (g_list_delete_link (addrs
, ll
) == addrs
);
231 * g_resolver_lookup_by_name:
232 * @resolver: a #GResolver
233 * @hostname: the hostname to look up
234 * @cancellable: (allow-none): a #GCancellable, or %NULL
235 * @error: return location for a #GError, or %NULL
237 * Synchronously resolves @hostname to determine its associated IP
238 * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
239 * the textual form of an IP address (in which case this just becomes
240 * a wrapper around g_inet_address_new_from_string()).
242 * On success, g_resolver_lookup_by_name() will return a #GList of
243 * #GInetAddress, sorted in order of preference and guaranteed to not
244 * contain duplicates. That is, if using the result to connect to
245 * @hostname, you should attempt to connect to the first address
246 * first, then the second if the first fails, etc. If you are using
247 * the result to listen on a socket, it is appropriate to add each
248 * result using e.g. g_socket_listener_add_address().
250 * If the DNS resolution fails, @error (if non-%NULL) will be set to a
251 * value from #GResolverError.
253 * If @cancellable is non-%NULL, it can be used to cancel the
254 * operation, in which case @error (if non-%NULL) will be set to
255 * %G_IO_ERROR_CANCELLED.
257 * If you are planning to connect to a socket on the resolved IP
258 * address, it may be easier to create a #GNetworkAddress and use its
259 * #GSocketConnectable interface.
261 * Return value: (element-type GInetAddress) (transfer full): a #GList
262 * of #GInetAddress, or %NULL on error. You
263 * must unref each of the addresses and free the list when you are
264 * done with it. (You can use g_resolver_free_addresses() to do this.)
269 g_resolver_lookup_by_name (GResolver
*resolver
,
270 const gchar
*hostname
,
271 GCancellable
*cancellable
,
276 gchar
*ascii_hostname
= NULL
;
278 g_return_val_if_fail (G_IS_RESOLVER (resolver
), NULL
);
279 g_return_val_if_fail (hostname
!= NULL
, NULL
);
281 /* Check if @hostname is just an IP address */
282 addr
= g_inet_address_new_from_string (hostname
);
284 return g_list_append (NULL
, addr
);
286 if (g_hostname_is_non_ascii (hostname
))
287 hostname
= ascii_hostname
= g_hostname_to_ascii (hostname
);
289 g_resolver_maybe_reload (resolver
);
290 addrs
= G_RESOLVER_GET_CLASS (resolver
)->
291 lookup_by_name (resolver
, hostname
, cancellable
, error
);
293 remove_duplicates (addrs
);
295 g_free (ascii_hostname
);
300 * g_resolver_lookup_by_name_async:
301 * @resolver: a #GResolver
302 * @hostname: the hostname to look up the address of
303 * @cancellable: (allow-none): a #GCancellable, or %NULL
304 * @callback: (scope async): callback to call after resolution completes
305 * @user_data: (closure): data for @callback
307 * Begins asynchronously resolving @hostname to determine its
308 * associated IP address(es), and eventually calls @callback, which
309 * must call g_resolver_lookup_by_name_finish() to get the result.
310 * See g_resolver_lookup_by_name() for more details.
315 g_resolver_lookup_by_name_async (GResolver
*resolver
,
316 const gchar
*hostname
,
317 GCancellable
*cancellable
,
318 GAsyncReadyCallback callback
,
322 gchar
*ascii_hostname
= NULL
;
324 g_return_if_fail (G_IS_RESOLVER (resolver
));
325 g_return_if_fail (hostname
!= NULL
);
327 /* Check if @hostname is just an IP address */
328 addr
= g_inet_address_new_from_string (hostname
);
331 GSimpleAsyncResult
*simple
;
333 simple
= g_simple_async_result_new (G_OBJECT (resolver
),
335 g_resolver_lookup_by_name_async
);
337 g_simple_async_result_set_op_res_gpointer (simple
, addr
, g_object_unref
);
338 g_simple_async_result_complete_in_idle (simple
);
339 g_object_unref (simple
);
343 if (g_hostname_is_non_ascii (hostname
))
344 hostname
= ascii_hostname
= g_hostname_to_ascii (hostname
);
346 g_resolver_maybe_reload (resolver
);
347 G_RESOLVER_GET_CLASS (resolver
)->
348 lookup_by_name_async (resolver
, hostname
, cancellable
, callback
, user_data
);
350 g_free (ascii_hostname
);
354 * g_resolver_lookup_by_name_finish:
355 * @resolver: a #GResolver
356 * @result: the result passed to your #GAsyncReadyCallback
357 * @error: return location for a #GError, or %NULL
359 * Retrieves the result of a call to
360 * g_resolver_lookup_by_name_async().
362 * If the DNS resolution failed, @error (if non-%NULL) will be set to
363 * a value from #GResolverError. If the operation was cancelled,
364 * @error will be set to %G_IO_ERROR_CANCELLED.
366 * Return value: (element-type GInetAddress) (transfer full): a #GList
367 * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
373 g_resolver_lookup_by_name_finish (GResolver
*resolver
,
374 GAsyncResult
*result
,
379 g_return_val_if_fail (G_IS_RESOLVER (resolver
), NULL
);
381 if (G_IS_SIMPLE_ASYNC_RESULT (result
))
383 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (result
);
385 if (g_simple_async_result_propagate_error (simple
, error
))
388 /* Handle the stringified-IP-addr case */
389 if (g_simple_async_result_get_source_tag (simple
) == g_resolver_lookup_by_name_async
)
393 addr
= g_simple_async_result_get_op_res_gpointer (simple
);
394 return g_list_append (NULL
, g_object_ref (addr
));
398 addrs
= G_RESOLVER_GET_CLASS (resolver
)->
399 lookup_by_name_finish (resolver
, result
, error
);
401 remove_duplicates (addrs
);
407 * g_resolver_free_addresses: (skip)
408 * @addresses: a #GList of #GInetAddress
410 * Frees @addresses (which should be the return value from
411 * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
412 * (This is a convenience method; you can also simply free the results
418 g_resolver_free_addresses (GList
*addresses
)
422 for (a
= addresses
; a
; a
= a
->next
)
423 g_object_unref (a
->data
);
424 g_list_free (addresses
);
428 * g_resolver_lookup_by_address:
429 * @resolver: a #GResolver
430 * @address: the address to reverse-resolve
431 * @cancellable: (allow-none): a #GCancellable, or %NULL
432 * @error: return location for a #GError, or %NULL
434 * Synchronously reverse-resolves @address to determine its
435 * associated hostname.
437 * If the DNS resolution fails, @error (if non-%NULL) will be set to
438 * a value from #GResolverError.
440 * If @cancellable is non-%NULL, it can be used to cancel the
441 * operation, in which case @error (if non-%NULL) will be set to
442 * %G_IO_ERROR_CANCELLED.
444 * Return value: a hostname (either ASCII-only, or in ASCII-encoded
445 * form), or %NULL on error.
450 g_resolver_lookup_by_address (GResolver
*resolver
,
451 GInetAddress
*address
,
452 GCancellable
*cancellable
,
455 g_return_val_if_fail (G_IS_RESOLVER (resolver
), NULL
);
456 g_return_val_if_fail (G_IS_INET_ADDRESS (address
), NULL
);
458 g_resolver_maybe_reload (resolver
);
459 return G_RESOLVER_GET_CLASS (resolver
)->
460 lookup_by_address (resolver
, address
, cancellable
, error
);
464 * g_resolver_lookup_by_address_async:
465 * @resolver: a #GResolver
466 * @address: the address to reverse-resolve
467 * @cancellable: (allow-none): a #GCancellable, or %NULL
468 * @callback: (scope async): callback to call after resolution completes
469 * @user_data: (closure): data for @callback
471 * Begins asynchronously reverse-resolving @address to determine its
472 * associated hostname, and eventually calls @callback, which must
473 * call g_resolver_lookup_by_address_finish() to get the final result.
478 g_resolver_lookup_by_address_async (GResolver
*resolver
,
479 GInetAddress
*address
,
480 GCancellable
*cancellable
,
481 GAsyncReadyCallback callback
,
484 g_return_if_fail (G_IS_RESOLVER (resolver
));
485 g_return_if_fail (G_IS_INET_ADDRESS (address
));
487 g_resolver_maybe_reload (resolver
);
488 G_RESOLVER_GET_CLASS (resolver
)->
489 lookup_by_address_async (resolver
, address
, cancellable
, callback
, user_data
);
493 * g_resolver_lookup_by_address_finish:
494 * @resolver: a #GResolver
495 * @result: the result passed to your #GAsyncReadyCallback
496 * @error: return location for a #GError, or %NULL
498 * Retrieves the result of a previous call to
499 * g_resolver_lookup_by_address_async().
501 * If the DNS resolution failed, @error (if non-%NULL) will be set to
502 * a value from #GResolverError. If the operation was cancelled,
503 * @error will be set to %G_IO_ERROR_CANCELLED.
505 * Return value: a hostname (either ASCII-only, or in ASCII-encoded
506 * form), or %NULL on error.
511 g_resolver_lookup_by_address_finish (GResolver
*resolver
,
512 GAsyncResult
*result
,
515 g_return_val_if_fail (G_IS_RESOLVER (resolver
), NULL
);
517 if (G_IS_SIMPLE_ASYNC_RESULT (result
))
519 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (result
);
521 if (g_simple_async_result_propagate_error (simple
, error
))
525 return G_RESOLVER_GET_CLASS (resolver
)->
526 lookup_by_address_finish (resolver
, result
, error
);
530 g_resolver_get_service_rrname (const char *service
,
531 const char *protocol
,
534 gchar
*rrname
, *ascii_domain
= NULL
;
536 if (g_hostname_is_non_ascii (domain
))
537 domain
= ascii_domain
= g_hostname_to_ascii (domain
);
539 rrname
= g_strdup_printf ("_%s._%s.%s", service
, protocol
, domain
);
541 g_free (ascii_domain
);
546 * g_resolver_lookup_service:
547 * @resolver: a #GResolver
548 * @service: the service type to look up (eg, "ldap")
549 * @protocol: the networking protocol to use for @service (eg, "tcp")
550 * @domain: the DNS domain to look up the service in
551 * @cancellable: (allow-none): a #GCancellable, or %NULL
552 * @error: return location for a #GError, or %NULL
554 * Synchronously performs a DNS SRV lookup for the given @service and
555 * @protocol in the given @domain and returns an array of #GSrvTarget.
556 * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
557 * @service and @protocol arguments <emphasis>do not</emphasis>
558 * include the leading underscore that appears in the actual DNS
561 * On success, g_resolver_lookup_service() will return a #GList of
562 * #GSrvTarget, sorted in order of preference. (That is, you should
563 * attempt to connect to the first target first, then the second if
564 * the first fails, etc.)
566 * If the DNS resolution fails, @error (if non-%NULL) will be set to
567 * a value from #GResolverError.
569 * If @cancellable is non-%NULL, it can be used to cancel the
570 * operation, in which case @error (if non-%NULL) will be set to
571 * %G_IO_ERROR_CANCELLED.
573 * If you are planning to connect to the service, it is usually easier
574 * to create a #GNetworkService and use its #GSocketConnectable
577 * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
578 * or %NULL on error. You must free each of the targets and the list when you are
579 * done with it. (You can use g_resolver_free_targets() to do this.)
584 g_resolver_lookup_service (GResolver
*resolver
,
585 const gchar
*service
,
586 const gchar
*protocol
,
588 GCancellable
*cancellable
,
594 g_return_val_if_fail (G_IS_RESOLVER (resolver
), NULL
);
595 g_return_val_if_fail (service
!= NULL
, NULL
);
596 g_return_val_if_fail (protocol
!= NULL
, NULL
);
597 g_return_val_if_fail (domain
!= NULL
, NULL
);
599 rrname
= g_resolver_get_service_rrname (service
, protocol
, domain
);
601 g_resolver_maybe_reload (resolver
);
602 targets
= G_RESOLVER_GET_CLASS (resolver
)->
603 lookup_service (resolver
, rrname
, cancellable
, error
);
610 * g_resolver_lookup_service_async:
611 * @resolver: a #GResolver
612 * @service: the service type to look up (eg, "ldap")
613 * @protocol: the networking protocol to use for @service (eg, "tcp")
614 * @domain: the DNS domain to look up the service in
615 * @cancellable: (allow-none): a #GCancellable, or %NULL
616 * @callback: (scope async): callback to call after resolution completes
617 * @user_data: (closure): data for @callback
619 * Begins asynchronously performing a DNS SRV lookup for the given
620 * @service and @protocol in the given @domain, and eventually calls
621 * @callback, which must call g_resolver_lookup_service_finish() to
622 * get the final result. See g_resolver_lookup_service() for more
628 g_resolver_lookup_service_async (GResolver
*resolver
,
629 const gchar
*service
,
630 const gchar
*protocol
,
632 GCancellable
*cancellable
,
633 GAsyncReadyCallback callback
,
638 g_return_if_fail (G_IS_RESOLVER (resolver
));
639 g_return_if_fail (service
!= NULL
);
640 g_return_if_fail (protocol
!= NULL
);
641 g_return_if_fail (domain
!= NULL
);
643 rrname
= g_resolver_get_service_rrname (service
, protocol
, domain
);
645 g_resolver_maybe_reload (resolver
);
646 G_RESOLVER_GET_CLASS (resolver
)->
647 lookup_service_async (resolver
, rrname
, cancellable
, callback
, user_data
);
653 * g_resolver_lookup_service_finish:
654 * @resolver: a #GResolver
655 * @result: the result passed to your #GAsyncReadyCallback
656 * @error: return location for a #GError, or %NULL
658 * Retrieves the result of a previous call to
659 * g_resolver_lookup_service_async().
661 * If the DNS resolution failed, @error (if non-%NULL) will be set to
662 * a value from #GResolverError. If the operation was cancelled,
663 * @error will be set to %G_IO_ERROR_CANCELLED.
665 * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
666 * or %NULL on error. See g_resolver_lookup_service() for more details.
671 g_resolver_lookup_service_finish (GResolver
*resolver
,
672 GAsyncResult
*result
,
675 g_return_val_if_fail (G_IS_RESOLVER (resolver
), NULL
);
677 if (G_IS_SIMPLE_ASYNC_RESULT (result
))
679 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (result
);
681 if (g_simple_async_result_propagate_error (simple
, error
))
685 return G_RESOLVER_GET_CLASS (resolver
)->
686 lookup_service_finish (resolver
, result
, error
);
690 * g_resolver_free_targets: (skip)
691 * @targets: a #GList of #GSrvTarget
693 * Frees @targets (which should be the return value from
694 * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
695 * (This is a convenience method; you can also simply free the
701 g_resolver_free_targets (GList
*targets
)
705 for (t
= targets
; t
; t
= t
->next
)
706 g_srv_target_free (t
->data
);
707 g_list_free (targets
);
711 * g_resolver_error_quark:
713 * Gets the #GResolver Error Quark.
715 * Return value: a #GQuark.
720 g_resolver_error_quark (void)
722 return g_quark_from_static_string ("g-resolver-error-quark");
726 static GResolverError
727 g_resolver_error_from_addrinfo_error (gint err
)
732 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
736 return G_RESOLVER_ERROR_NOT_FOUND
;
739 return G_RESOLVER_ERROR_TEMPORARY_FAILURE
;
742 return G_RESOLVER_ERROR_INTERNAL
;
746 struct addrinfo _g_resolver_addrinfo_hints
;
748 /* Private method to process a getaddrinfo() response. */
750 _g_resolver_addresses_from_addrinfo (const char *hostname
,
751 struct addrinfo
*res
,
756 GSocketAddress
*sockaddr
;
762 g_set_error (error
, G_RESOLVER_ERROR
,
763 g_resolver_error_from_addrinfo_error (gai_retval
),
764 _("Error resolving '%s': %s"),
765 hostname
, gai_strerror (gai_retval
));
769 g_return_val_if_fail (res
!= NULL
, NULL
);
772 for (ai
= res
; ai
; ai
= ai
->ai_next
)
774 sockaddr
= g_socket_address_new_from_native (ai
->ai_addr
, ai
->ai_addrlen
);
775 if (!sockaddr
|| !G_IS_INET_SOCKET_ADDRESS (sockaddr
))
778 addr
= g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress
*)sockaddr
));
779 addrs
= g_list_prepend (addrs
, addr
);
780 g_object_unref (sockaddr
);
783 return g_list_reverse (addrs
);
786 /* Private method to set up a getnameinfo() request */
788 _g_resolver_address_to_sockaddr (GInetAddress
*address
,
789 struct sockaddr_storage
*sa
,
792 GSocketAddress
*sockaddr
;
794 sockaddr
= g_inet_socket_address_new (address
, 0);
795 g_socket_address_to_native (sockaddr
, (struct sockaddr
*)sa
, sizeof (*sa
), NULL
);
796 *len
= g_socket_address_get_native_size (sockaddr
);
797 g_object_unref (sockaddr
);
800 /* Private method to process a getnameinfo() response. */
802 _g_resolver_name_from_nameinfo (GInetAddress
*address
,
811 phys
= g_inet_address_to_string (address
);
812 g_set_error (error
, G_RESOLVER_ERROR
,
813 g_resolver_error_from_addrinfo_error (gni_retval
),
814 _("Error reverse-resolving '%s': %s"),
815 phys
? phys
: "(unknown)", gai_strerror (gni_retval
));
820 return g_strdup (name
);
823 #if defined(G_OS_UNIX)
824 /* Private method to process a res_query response into GSrvTargets */
826 _g_resolver_targets_from_res_query (const gchar
*rrname
,
835 guint16 type
, qclass
, rdlength
, priority
, weight
, port
;
843 GResolverError errnum
;
846 if (len
== 0 || herr
== HOST_NOT_FOUND
|| herr
== NO_DATA
)
848 errnum
= G_RESOLVER_ERROR_NOT_FOUND
;
849 format
= _("No service record for '%s'");
851 else if (herr
== TRY_AGAIN
)
853 errnum
= G_RESOLVER_ERROR_TEMPORARY_FAILURE
;
854 format
= _("Temporarily unable to resolve '%s'");
858 errnum
= G_RESOLVER_ERROR_INTERNAL
;
859 format
= _("Error resolving '%s'");
862 g_set_error (error
, G_RESOLVER_ERROR
, errnum
, format
, rrname
);
868 header
= (HEADER
*)answer
;
869 p
= answer
+ sizeof (HEADER
);
873 count
= ntohs (header
->qdcount
);
874 while (count
-- && p
< end
)
876 p
+= dn_expand (answer
, end
, p
, namebuf
, sizeof (namebuf
));
881 count
= ntohs (header
->ancount
);
882 while (count
-- && p
< end
)
884 p
+= dn_expand (answer
, end
, p
, namebuf
, sizeof (namebuf
));
886 GETSHORT (qclass
, p
);
888 ttl
= ttl
; /* To avoid -Wunused-but-set-variable */
889 GETSHORT (rdlength
, p
);
891 if (type
!= T_SRV
|| qclass
!= C_IN
)
897 GETSHORT (priority
, p
);
898 GETSHORT (weight
, p
);
900 p
+= dn_expand (answer
, end
, p
, namebuf
, sizeof (namebuf
));
902 target
= g_srv_target_new (namebuf
, port
, priority
, weight
);
903 targets
= g_list_prepend (targets
, target
);
906 return g_srv_target_list_sort (targets
);
908 #elif defined(G_OS_WIN32)
909 /* Private method to process a DnsQuery response into GSrvTargets */
911 _g_resolver_targets_from_DnsQuery (const gchar
*rrname
,
920 if (status
!= ERROR_SUCCESS
)
922 GResolverError errnum
;
925 if (status
== DNS_ERROR_RCODE_NAME_ERROR
)
927 errnum
= G_RESOLVER_ERROR_NOT_FOUND
;
928 format
= _("No service record for '%s'");
930 else if (status
== DNS_ERROR_RCODE_SERVER_FAILURE
)
932 errnum
= G_RESOLVER_ERROR_TEMPORARY_FAILURE
;
933 format
= _("Temporarily unable to resolve '%s'");
937 errnum
= G_RESOLVER_ERROR_INTERNAL
;
938 format
= _("Error resolving '%s'");
941 g_set_error (error
, G_RESOLVER_ERROR
, errnum
, format
, rrname
);
946 for (rec
= results
; rec
; rec
= rec
->pNext
)
948 if (rec
->wType
!= DNS_TYPE_SRV
)
951 target
= g_srv_target_new (rec
->Data
.SRV
.pNameTarget
,
953 rec
->Data
.SRV
.wPriority
,
954 rec
->Data
.SRV
.wWeight
);
955 targets
= g_list_prepend (targets
, target
);
958 return g_srv_target_list_sort (targets
);