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 */ G_DEFINE_ABSTRACT_TYPE_WITH_CODE(GResolver,g_resolver,G_TYPE_OBJECT,G_ADD_PRIVATE (GResolver)g_networking_init ();)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 { 89 const gchar *hostname; 90 guint16 port, priority, weight; 91 GSrvTarget *target; 92 GList *l; 93 94 for (l = records; l != NULL; l = g_list_next (l)) 95 { 96 g_variant_get (l->data, "(qqq&s)", &priority, &weight, &port, &hostname); 97 target = g_srv_target_new (hostname, port, priority, weight); 98 g_variant_unref (l->data); 99 l->data = target; 100 } 101 102 return g_srv_target_list_sort (records); 103 } 104 105 static GList * g_resolver_real_lookup_service(GResolver * resolver,const gchar * rrname,GCancellable * cancellable,GError ** error)106 g_resolver_real_lookup_service (GResolver *resolver, 107 const gchar *rrname, 108 GCancellable *cancellable, 109 GError **error) 110 { 111 GList *records; 112 113 records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver, 114 rrname, 115 G_RESOLVER_RECORD_SRV, 116 cancellable, 117 error); 118 119 return srv_records_to_targets (records); 120 } 121 122 static void g_resolver_real_lookup_service_async(GResolver * resolver,const gchar * rrname,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)123 g_resolver_real_lookup_service_async (GResolver *resolver, 124 const gchar *rrname, 125 GCancellable *cancellable, 126 GAsyncReadyCallback callback, 127 gpointer user_data) 128 { 129 G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver, 130 rrname, 131 G_RESOLVER_RECORD_SRV, 132 cancellable, 133 callback, 134 user_data); 135 } 136 137 static GList * g_resolver_real_lookup_service_finish(GResolver * resolver,GAsyncResult * result,GError ** error)138 g_resolver_real_lookup_service_finish (GResolver *resolver, 139 GAsyncResult *result, 140 GError **error) 141 { 142 GList *records; 143 144 records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver, 145 result, 146 error); 147 148 return srv_records_to_targets (records); 149 } 150 151 static void g_resolver_class_init(GResolverClass * resolver_class)152 g_resolver_class_init (GResolverClass *resolver_class) 153 { 154 /* Automatically pass these over to the lookup_records methods */ 155 resolver_class->lookup_service = g_resolver_real_lookup_service; 156 resolver_class->lookup_service_async = g_resolver_real_lookup_service_async; 157 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 signals[RELOAD] = 167 g_signal_new (I_("reload"), 168 G_TYPE_RESOLVER, 169 G_SIGNAL_RUN_LAST, 170 G_STRUCT_OFFSET (GResolverClass, reload), 171 NULL, NULL, 172 NULL, 173 G_TYPE_NONE, 0); 174 } 175 176 static void g_resolver_init(GResolver * resolver)177 g_resolver_init (GResolver *resolver) 178 { 179 #ifdef G_OS_UNIX 180 struct stat st; 181 #endif 182 183 resolver->priv = g_resolver_get_instance_private (resolver); 184 185 #ifdef G_OS_UNIX 186 if (stat (_PATH_RESCONF, &st) == 0) 187 resolver->priv->resolv_conf_timestamp = st.st_mtime; 188 #endif 189 } 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 * g_resolver_get_default(void)206 g_resolver_get_default (void) 207 { 208 GResolver *ret; 209 210 G_LOCK (default_resolver); 211 if (!default_resolver) 212 default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL); 213 ret = g_object_ref (default_resolver); 214 G_UNLOCK (default_resolver); 215 216 return ret; 217 } 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 g_resolver_set_default(GResolver * resolver)236 g_resolver_set_default (GResolver *resolver) 237 { 238 G_LOCK (default_resolver); 239 if (default_resolver) 240 g_object_unref (default_resolver); 241 default_resolver = g_object_ref (resolver); 242 G_UNLOCK (default_resolver); 243 } 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 g_resolver_maybe_reload(GResolver * resolver)251 g_resolver_maybe_reload (GResolver *resolver) 252 { 253 #ifdef G_OS_UNIX 254 struct stat st; 255 256 if (stat (_PATH_RESCONF, &st) == 0) 257 { 258 if (st.st_mtime != resolver->priv->resolv_conf_timestamp) 259 { 260 resolver->priv->resolv_conf_timestamp = st.st_mtime; 261 #ifdef HAVE_RES_INIT 262 res_init (); 263 #endif 264 g_signal_emit (resolver, signals[RELOAD], 0); 265 } 266 } 267 #endif 268 } 269 270 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */ 271 static void remove_duplicates(GList * addrs)272 remove_duplicates (GList *addrs) 273 { 274 GList *l; 275 GList *ll; 276 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 for (l = addrs; l != NULL; l = l->next) 283 { 284 GInetAddress *address = G_INET_ADDRESS (l->data); 285 for (ll = l->next; ll != NULL; ll = lll) 286 { 287 GInetAddress *other_address = G_INET_ADDRESS (ll->data); 288 lll = ll->next; 289 if (g_inet_address_equal (address, other_address)) 290 { 291 g_object_unref (other_address); 292 /* we never return the first element */ 293 g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs); 294 } 295 } 296 } 297 } 298 299 static gboolean hostname_is_localhost(const char * hostname)300 hostname_is_localhost (const char *hostname) 301 { 302 size_t len = strlen (hostname); 303 const char *p; 304 305 /* Match "localhost", "localhost.", "*.localhost" and "*.localhost." */ 306 if (len < strlen ("localhost")) 307 return FALSE; 308 309 if (hostname[len - 1] == '.') 310 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 p = hostname + len - 1; 316 while (p >= hostname) 317 { 318 if (*p == '.') 319 { 320 p++; 321 break; 322 } 323 else if (p == hostname) 324 break; 325 p--; 326 } 327 328 len -= p - hostname; 329 330 return g_ascii_strncasecmp (p, "localhost", MAX (len, strlen ("localhost"))) == 0; 331 } 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 handle_ip_address_or_localhost(const char * hostname,GList ** addrs,GResolverNameLookupFlags flags,GError ** error)339 handle_ip_address_or_localhost (const char *hostname, 340 GList **addrs, 341 GResolverNameLookupFlags flags, 342 GError **error) 343 { 344 GInetAddress *addr; 345 346 #ifndef G_OS_WIN32 347 struct in_addr ip4addr; 348 #endif 349 350 addr = g_inet_address_new_from_string (hostname); 351 if (addr) 352 { 353 *addrs = g_list_append (NULL, addr); 354 return TRUE; 355 } 356 357 *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 if (inet_aton (hostname, &ip4addr)) 376 #endif 377 { 378 #ifdef G_OS_WIN32 379 gchar *error_message = g_win32_error_message (WSAHOST_NOT_FOUND); 380 #else 381 gchar *error_message = g_locale_to_utf8 (gai_strerror (EAI_NONAME), -1, NULL, NULL, NULL); 382 if (error_message == NULL) 383 error_message = g_strdup ("[Invalid UTF-8]"); 384 #endif 385 g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, 386 _("Error resolving “%s”: %s"), 387 hostname, error_message); 388 g_free (error_message); 389 390 return TRUE; 391 } 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 if (hostname_is_localhost (hostname)) 402 { 403 if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY) 404 *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6)); 405 if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY) 406 *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4)); 407 if (*addrs == NULL) 408 { 409 *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV6)); 410 *addrs = g_list_append (*addrs, g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4)); 411 } 412 return TRUE; 413 } 414 415 return FALSE; 416 } 417 418 static GList * lookup_by_name_real(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GError ** error)419 lookup_by_name_real (GResolver *resolver, 420 const gchar *hostname, 421 GResolverNameLookupFlags flags, 422 GCancellable *cancellable, 423 GError **error) 424 { 425 GList *addrs; 426 gchar *ascii_hostname = NULL; 427 428 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 429 g_return_val_if_fail (hostname != NULL, NULL); 430 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); 431 g_return_val_if_fail (error == NULL || *error == NULL, NULL); 432 433 /* Check if @hostname is just an IP address */ 434 if (handle_ip_address_or_localhost (hostname, &addrs, flags, error)) 435 return addrs; 436 437 if (g_hostname_is_non_ascii (hostname)) 438 hostname = ascii_hostname = g_hostname_to_ascii (hostname); 439 440 if (!hostname) 441 { 442 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, 443 _("Invalid hostname")); 444 return NULL; 445 } 446 447 g_resolver_maybe_reload (resolver); 448 449 if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT) 450 { 451 if (!G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags) 452 { 453 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, 454 /* Translators: The placeholder is for a function name. */ 455 _("%s not implemented"), "lookup_by_name_with_flags"); 456 g_free (ascii_hostname); 457 return NULL; 458 } 459 addrs = G_RESOLVER_GET_CLASS (resolver)-> 460 lookup_by_name_with_flags (resolver, hostname, flags, cancellable, error); 461 } 462 else 463 addrs = G_RESOLVER_GET_CLASS (resolver)-> 464 lookup_by_name (resolver, hostname, cancellable, error); 465 466 remove_duplicates (addrs); 467 468 g_free (ascii_hostname); 469 return addrs; 470 } 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 * g_resolver_lookup_by_name(GResolver * resolver,const gchar * hostname,GCancellable * cancellable,GError ** error)511 g_resolver_lookup_by_name (GResolver *resolver, 512 const gchar *hostname, 513 GCancellable *cancellable, 514 GError **error) 515 { 516 return lookup_by_name_real (resolver, 517 hostname, 518 G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT, 519 cancellable, 520 error); 521 } 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 * g_resolver_lookup_by_name_with_flags(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GError ** error)543 g_resolver_lookup_by_name_with_flags (GResolver *resolver, 544 const gchar *hostname, 545 GResolverNameLookupFlags flags, 546 GCancellable *cancellable, 547 GError **error) 548 { 549 return lookup_by_name_real (resolver, 550 hostname, 551 flags, 552 cancellable, 553 error); 554 } 555 556 static void lookup_by_name_async_real(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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 { 564 gchar *ascii_hostname = NULL; 565 GList *addrs; 566 GError *error = NULL; 567 568 g_return_if_fail (G_IS_RESOLVER (resolver)); 569 g_return_if_fail (hostname != NULL); 570 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 if (handle_ip_address_or_localhost (hostname, &addrs, flags, &error)) 574 { 575 GTask *task; 576 577 task = g_task_new (resolver, cancellable, callback, user_data); 578 g_task_set_source_tag (task, lookup_by_name_async_real); 579 g_task_set_name (task, "[gio] resolver lookup"); 580 if (addrs) 581 g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses); 582 else 583 g_task_return_error (task, error); 584 g_object_unref (task); 585 return; 586 } 587 588 if (g_hostname_is_non_ascii (hostname)) 589 hostname = ascii_hostname = g_hostname_to_ascii (hostname); 590 591 if (!hostname) 592 { 593 GTask *task; 594 595 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, 596 _("Invalid hostname")); 597 task = g_task_new (resolver, cancellable, callback, user_data); 598 g_task_set_source_tag (task, lookup_by_name_async_real); 599 g_task_set_name (task, "[gio] resolver lookup"); 600 g_task_return_error (task, error); 601 g_object_unref (task); 602 return; 603 } 604 605 g_resolver_maybe_reload (resolver); 606 607 if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT) 608 { 609 if (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_async == NULL) 610 { 611 GTask *task; 612 613 g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, 614 /* Translators: The placeholder is for a function name. */ 615 _("%s not implemented"), "lookup_by_name_with_flags_async"); 616 task = g_task_new (resolver, cancellable, callback, user_data); 617 g_task_set_source_tag (task, lookup_by_name_async_real); 618 g_task_set_name (task, "[gio] resolver lookup"); 619 g_task_return_error (task, error); 620 g_object_unref (task); 621 } 622 else 623 G_RESOLVER_GET_CLASS (resolver)-> 624 lookup_by_name_with_flags_async (resolver, hostname, flags, cancellable, callback, user_data); 625 } 626 else 627 G_RESOLVER_GET_CLASS (resolver)-> 628 lookup_by_name_async (resolver, hostname, cancellable, callback, user_data); 629 630 g_free (ascii_hostname); 631 } 632 633 static GList * lookup_by_name_finish_real(GResolver * resolver,GAsyncResult * result,GError ** error,gboolean with_flags)634 lookup_by_name_finish_real (GResolver *resolver, 635 GAsyncResult *result, 636 GError **error, 637 gboolean with_flags) 638 { 639 GList *addrs; 640 641 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 642 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); 643 g_return_val_if_fail (error == NULL || *error == NULL, NULL); 644 645 if (g_async_result_legacy_propagate_error (result, error)) 646 return NULL; 647 else if (g_async_result_is_tagged (result, lookup_by_name_async_real)) 648 { 649 /* Handle the stringified-IP-addr case */ 650 return g_task_propagate_pointer (G_TASK (result), error); 651 } 652 653 if (with_flags) 654 { 655 g_assert (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_finish != NULL); 656 addrs = G_RESOLVER_GET_CLASS (resolver)-> 657 lookup_by_name_with_flags_finish (resolver, result, error); 658 } 659 else 660 addrs = G_RESOLVER_GET_CLASS (resolver)-> 661 lookup_by_name_finish (resolver, result, error); 662 663 remove_duplicates (addrs); 664 665 return addrs; 666 } 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 g_resolver_lookup_by_name_with_flags_async(GResolver * resolver,const gchar * hostname,GResolverNameLookupFlags flags,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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 { 692 lookup_by_name_async_real (resolver, 693 hostname, 694 flags, 695 cancellable, 696 callback, 697 user_data); 698 } 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 g_resolver_lookup_by_name_async(GResolver * resolver,const gchar * hostname,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)716 g_resolver_lookup_by_name_async (GResolver *resolver, 717 const gchar *hostname, 718 GCancellable *cancellable, 719 GAsyncReadyCallback callback, 720 gpointer user_data) 721 { 722 lookup_by_name_async_real (resolver, 723 hostname, 724 0, 725 cancellable, 726 callback, 727 user_data); 728 } 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 * g_resolver_lookup_by_name_finish(GResolver * resolver,GAsyncResult * result,GError ** error)750 g_resolver_lookup_by_name_finish (GResolver *resolver, 751 GAsyncResult *result, 752 GError **error) 753 { 754 return lookup_by_name_finish_real (resolver, 755 result, 756 error, 757 FALSE); 758 } 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 * g_resolver_lookup_by_name_with_flags_finish(GResolver * resolver,GAsyncResult * result,GError ** error)780 g_resolver_lookup_by_name_with_flags_finish (GResolver *resolver, 781 GAsyncResult *result, 782 GError **error) 783 { 784 return lookup_by_name_finish_real (resolver, 785 result, 786 error, 787 TRUE); 788 } 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 g_resolver_free_addresses(GList * addresses)802 g_resolver_free_addresses (GList *addresses) 803 { 804 GList *a; 805 806 for (a = addresses; a; a = a->next) 807 g_object_unref (a->data); 808 g_list_free (addresses); 809 } 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 * g_resolver_lookup_by_address(GResolver * resolver,GInetAddress * address,GCancellable * cancellable,GError ** error)834 g_resolver_lookup_by_address (GResolver *resolver, 835 GInetAddress *address, 836 GCancellable *cancellable, 837 GError **error) 838 { 839 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 840 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL); 841 842 g_resolver_maybe_reload (resolver); 843 return G_RESOLVER_GET_CLASS (resolver)-> 844 lookup_by_address (resolver, address, cancellable, error); 845 } 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 g_resolver_lookup_by_address_async(GResolver * resolver,GInetAddress * address,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)862 g_resolver_lookup_by_address_async (GResolver *resolver, 863 GInetAddress *address, 864 GCancellable *cancellable, 865 GAsyncReadyCallback callback, 866 gpointer user_data) 867 { 868 g_return_if_fail (G_IS_RESOLVER (resolver)); 869 g_return_if_fail (G_IS_INET_ADDRESS (address)); 870 871 g_resolver_maybe_reload (resolver); 872 G_RESOLVER_GET_CLASS (resolver)-> 873 lookup_by_address_async (resolver, address, cancellable, callback, user_data); 874 } 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 * g_resolver_lookup_by_address_finish(GResolver * resolver,GAsyncResult * result,GError ** error)895 g_resolver_lookup_by_address_finish (GResolver *resolver, 896 GAsyncResult *result, 897 GError **error) 898 { 899 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 900 901 if (g_async_result_legacy_propagate_error (result, error)) 902 return NULL; 903 904 return G_RESOLVER_GET_CLASS (resolver)-> 905 lookup_by_address_finish (resolver, result, error); 906 } 907 908 static gchar * g_resolver_get_service_rrname(const char * service,const char * protocol,const char * domain)909 g_resolver_get_service_rrname (const char *service, 910 const char *protocol, 911 const char *domain) 912 { 913 gchar *rrname, *ascii_domain = NULL; 914 915 if (g_hostname_is_non_ascii (domain)) 916 domain = ascii_domain = g_hostname_to_ascii (domain); 917 if (!domain) 918 return NULL; 919 920 rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain); 921 922 g_free (ascii_domain); 923 return rrname; 924 } 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 * g_resolver_lookup_service(GResolver * resolver,const gchar * service,const gchar * protocol,const gchar * domain,GCancellable * cancellable,GError ** error)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 { 972 GList *targets; 973 gchar *rrname; 974 975 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 976 g_return_val_if_fail (service != NULL, NULL); 977 g_return_val_if_fail (protocol != NULL, NULL); 978 g_return_val_if_fail (domain != NULL, NULL); 979 980 rrname = g_resolver_get_service_rrname (service, protocol, domain); 981 if (!rrname) 982 { 983 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, 984 _("Invalid domain")); 985 return NULL; 986 } 987 988 g_resolver_maybe_reload (resolver); 989 targets = G_RESOLVER_GET_CLASS (resolver)-> 990 lookup_service (resolver, rrname, cancellable, error); 991 992 g_free (rrname); 993 return targets; 994 } 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 g_resolver_lookup_service_async(GResolver * resolver,const gchar * service,const gchar * protocol,const gchar * domain,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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 { 1023 gchar *rrname; 1024 1025 g_return_if_fail (G_IS_RESOLVER (resolver)); 1026 g_return_if_fail (service != NULL); 1027 g_return_if_fail (protocol != NULL); 1028 g_return_if_fail (domain != NULL); 1029 1030 rrname = g_resolver_get_service_rrname (service, protocol, domain); 1031 if (!rrname) 1032 { 1033 g_task_report_new_error (resolver, callback, user_data, 1034 g_resolver_lookup_service_async, 1035 G_IO_ERROR, G_IO_ERROR_FAILED, 1036 _("Invalid domain")); 1037 return; 1038 } 1039 1040 g_resolver_maybe_reload (resolver); 1041 G_RESOLVER_GET_CLASS (resolver)-> 1042 lookup_service_async (resolver, rrname, cancellable, callback, user_data); 1043 1044 g_free (rrname); 1045 } 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 * g_resolver_lookup_service_finish(GResolver * resolver,GAsyncResult * result,GError ** error)1067 g_resolver_lookup_service_finish (GResolver *resolver, 1068 GAsyncResult *result, 1069 GError **error) 1070 { 1071 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 1072 1073 if (g_async_result_legacy_propagate_error (result, error)) 1074 return NULL; 1075 1076 return G_RESOLVER_GET_CLASS (resolver)-> 1077 lookup_service_finish (resolver, result, error); 1078 } 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 g_resolver_free_targets(GList * targets)1092 g_resolver_free_targets (GList *targets) 1093 { 1094 GList *t; 1095 1096 for (t = targets; t; t = t->next) 1097 g_srv_target_free (t->data); 1098 g_list_free (targets); 1099 } 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 * g_resolver_lookup_records(GResolver * resolver,const gchar * rrname,GResolverRecordType record_type,GCancellable * cancellable,GError ** error)1128 g_resolver_lookup_records (GResolver *resolver, 1129 const gchar *rrname, 1130 GResolverRecordType record_type, 1131 GCancellable *cancellable, 1132 GError **error) 1133 { 1134 GList *records; 1135 1136 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 1137 g_return_val_if_fail (rrname != NULL, NULL); 1138 1139 g_resolver_maybe_reload (resolver); 1140 records = G_RESOLVER_GET_CLASS (resolver)-> 1141 lookup_records (resolver, rrname, record_type, cancellable, error); 1142 1143 return records; 1144 } 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 g_resolver_lookup_records_async(GResolver * resolver,const gchar * rrname,GResolverRecordType record_type,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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 { 1170 g_return_if_fail (G_IS_RESOLVER (resolver)); 1171 g_return_if_fail (rrname != NULL); 1172 1173 g_resolver_maybe_reload (resolver); 1174 G_RESOLVER_GET_CLASS (resolver)-> 1175 lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data); 1176 } 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 * g_resolver_lookup_records_finish(GResolver * resolver,GAsyncResult * result,GError ** error)1201 g_resolver_lookup_records_finish (GResolver *resolver, 1202 GAsyncResult *result, 1203 GError **error) 1204 { 1205 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL); 1206 return G_RESOLVER_GET_CLASS (resolver)-> 1207 lookup_records_finish (resolver, result, error); 1208 } 1209 1210 guint64 g_resolver_get_serial(GResolver * resolver)1211 g_resolver_get_serial (GResolver *resolver) 1212 { 1213 g_return_val_if_fail (G_IS_RESOLVER (resolver), 0); 1214 1215 g_resolver_maybe_reload (resolver); 1216 1217 #ifdef G_OS_UNIX 1218 return (guint64) resolver->priv->resolv_conf_timestamp; 1219 #else 1220 return 1; 1221 #endif 1222 } 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) 1234