dns_resolve.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // SPDX-License-Identifier: LGPL-2.1
  2. /*
  3. *
  4. * Copyright (c) 2007 Igor Mammedov
  5. * Author(s): Igor Mammedov (niallain@gmail.com)
  6. * Steve French (sfrench@us.ibm.com)
  7. * Wang Lei (wang840925@gmail.com)
  8. * David Howells (dhowells@redhat.com)
  9. *
  10. * Contains the CIFS DFS upcall routines used for hostname to
  11. * IP address translation.
  12. *
  13. */
  14. #include <linux/inet.h>
  15. #include <linux/slab.h>
  16. #include <linux/dns_resolver.h>
  17. #include "dns_resolve.h"
  18. #include "cifsglob.h"
  19. #include "cifsproto.h"
  20. #include "cifs_debug.h"
  21. /**
  22. * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address.
  23. * @unc: UNC path specifying the server (with '/' as delimiter)
  24. * @ip_addr: Where to return the IP address.
  25. * @expiry: Where to return the expiry time for the dns record.
  26. *
  27. * Returns zero success, -ve on error.
  28. */
  29. int
  30. dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry)
  31. {
  32. const char *hostname, *sep;
  33. char *ip;
  34. int len, rc;
  35. if (!ip_addr || !unc)
  36. return -EINVAL;
  37. len = strlen(unc);
  38. if (len < 3) {
  39. cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc);
  40. return -EINVAL;
  41. }
  42. /* Discount leading slashes for cifs */
  43. len -= 2;
  44. hostname = unc + 2;
  45. /* Search for server name delimiter */
  46. sep = memchr(hostname, '/', len);
  47. if (sep)
  48. len = sep - hostname;
  49. else
  50. cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n",
  51. __func__, unc);
  52. /* Try to interpret hostname as an IPv4 or IPv6 address */
  53. rc = cifs_convert_address(ip_addr, hostname, len);
  54. if (rc > 0) {
  55. cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", __func__, len, len,
  56. hostname);
  57. return 0;
  58. }
  59. /* Perform the upcall */
  60. rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
  61. NULL, &ip, expiry, false);
  62. if (rc < 0) {
  63. cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
  64. __func__, len, len, hostname);
  65. } else {
  66. cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n",
  67. __func__, len, len, hostname, ip,
  68. expiry ? (*expiry) : 0);
  69. rc = cifs_convert_address(ip_addr, ip, strlen(ip));
  70. kfree(ip);
  71. if (!rc) {
  72. cifs_dbg(FYI, "%s: unable to determine ip address\n", __func__);
  73. rc = -EHOSTUNREACH;
  74. } else
  75. rc = 0;
  76. }
  77. return rc;
  78. }