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