Coverage Report

Created: 2025-07-01 07:09

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