resolv_context.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* Temporary, thread-local resolver state.
  2. Copyright (C) 2017-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. /* struct resolv_context objects are allocated on the heap,
  16. initialized by __resolv_context_get (and its variants), and
  17. destroyed by __resolv_context_put.
  18. A nested call to __resolv_context_get (after another call to
  19. __resolv_context_get without a matching __resolv_context_put call,
  20. on the same thread) returns the original pointer, instead of
  21. allocating a new context. This prevents unexpected reloading of
  22. the resolver configuration. Care is taken to keep the context in
  23. sync with the thread-local _res object. (This does not happen with
  24. __resolv_context_get_override, and __resolv_context_get_no_inet6 may
  25. also interpose another context object if RES_USE_INET6 needs to be
  26. disabled.)
  27. In contrast to struct __res_state, struct resolv_context is not
  28. affected by ABI compatibility concerns.
  29. For the benefit of the res_n* functions, a struct __res_state
  30. pointer is included in the context object, and a separate
  31. initialization function is provided. */
  32. #ifndef _RESOLV_CONTEXT_H
  33. #define _RESOLV_CONTEXT_H
  34. #include <bits/types/res_state.h>
  35. #include <resolv/resolv_conf.h>
  36. #include <stdbool.h>
  37. #include <stddef.h>
  38. /* Temporary resolver state. */
  39. struct resolv_context
  40. {
  41. struct __res_state *resp; /* Backing resolver state. */
  42. /* Extended resolver state. This is set to NULL if the
  43. __resolv_context_get functions are unable to locate an associated
  44. extended state. In this case, the configuration data in *resp
  45. has to be used; otherwise, the data from *conf should be
  46. preferred (because it is a superset). */
  47. struct resolv_conf *conf;
  48. /* The following fields are for internal use within the
  49. resolv_context module. */
  50. size_t __refcount; /* Count of reusages by the get functions. */
  51. bool __from_res; /* True if created from _res. */
  52. /* If RES_USE_INET6 was disabled at this level, this field points to
  53. the previous context. */
  54. struct resolv_context *__next;
  55. };
  56. /* Return the current temporary resolver context, or NULL if there was
  57. an error (indicated by errno). A call to this function must be
  58. paired with a call to __resolv_context_put. */
  59. struct resolv_context *__resolv_context_get (void)
  60. __attribute__ ((warn_unused_result));
  61. libc_hidden_proto (__resolv_context_get)
  62. /* Deallocate the temporary resolver context. Converse of
  63. __resolv_context_get. Restore the RES_USE_INET6 flag if necessary.
  64. Do nothing if CTX is NULL. */
  65. void __resolv_context_put (struct resolv_context *ctx);
  66. libc_hidden_proto (__resolv_context_put)
  67. /* Like __resolv_context_get, but the _res structure can be partially
  68. initialzed and those changes will not be overwritten. */
  69. struct resolv_context *__resolv_context_get_preinit (void)
  70. __attribute__ ((warn_unused_result));
  71. libc_hidden_proto (__resolv_context_get_preinit)
  72. /* Wrap a struct __res_state object in a struct resolv_context object.
  73. A call to this function must be paired with a call to
  74. __resolv_context_put. */
  75. struct resolv_context *__resolv_context_get_override (struct __res_state *)
  76. __attribute__ ((nonnull (1), warn_unused_result));
  77. libc_hidden_proto (__resolv_context_get_override)
  78. /* Return the search path entry at INDEX, or NULL if there are fewer
  79. than INDEX entries. */
  80. static __attribute__ ((nonnull (1), unused)) const char *
  81. __resolv_context_search_list (const struct resolv_context *ctx, size_t index)
  82. {
  83. if (ctx->conf != NULL)
  84. {
  85. if (index < ctx->conf->search_list_size)
  86. return ctx->conf->search_list[index];
  87. else
  88. return NULL;
  89. }
  90. /* Fallback. ctx->resp->dnsrch is a NULL-terminated array. */
  91. for (size_t i = 0; ctx->resp->dnsrch[i] != NULL && i < MAXDNSRCH; ++i)
  92. if (i == index)
  93. return ctx->resp->dnsrch[i];
  94. return NULL;
  95. }
  96. /* Return the number of name servers. */
  97. static __attribute__ ((nonnull (1), unused)) size_t
  98. __resolv_context_nameserver_count (const struct resolv_context *ctx)
  99. {
  100. if (ctx->conf != NULL)
  101. return ctx->conf->nameserver_list_size;
  102. else
  103. return ctx->resp->nscount;
  104. }
  105. /* Return a pointer to the socket address of the name server INDEX, or
  106. NULL if the index is out of bounds. */
  107. static __attribute__ ((nonnull (1), unused)) const struct sockaddr *
  108. __resolv_context_nameserver (const struct resolv_context *ctx, size_t index)
  109. {
  110. if (ctx->conf != NULL)
  111. {
  112. if (index < ctx->conf->nameserver_list_size)
  113. return ctx->conf->nameserver_list[index];
  114. }
  115. else
  116. if (index < ctx->resp->nscount)
  117. {
  118. if (ctx->resp->nsaddr_list[index].sin_family != 0)
  119. return (const struct sockaddr *) &ctx->resp->nsaddr_list[index];
  120. else
  121. return (const struct sockaddr *) &ctx->resp->_u._ext.nsaddrs[index];
  122. }
  123. return NULL;
  124. }
  125. /* Return the number of sort list entries. */
  126. static __attribute__ ((nonnull (1), unused)) size_t
  127. __resolv_context_sort_count (const struct resolv_context *ctx)
  128. {
  129. if (ctx->conf != NULL)
  130. return ctx->conf->sort_list_size;
  131. else
  132. return ctx->resp->nsort;
  133. }
  134. /* Return the sort list entry at INDEX. */
  135. static __attribute__ ((nonnull (1), unused)) struct resolv_sortlist_entry
  136. __resolv_context_sort_entry (const struct resolv_context *ctx, size_t index)
  137. {
  138. if (ctx->conf != NULL)
  139. {
  140. if (index < ctx->conf->sort_list_size)
  141. return ctx->conf->sort_list[index];
  142. /* Fall through. */
  143. }
  144. else if (index < ctx->resp->nsort)
  145. return (struct resolv_sortlist_entry)
  146. {
  147. .addr = ctx->resp->sort_list[index].addr,
  148. .mask = ctx->resp->sort_list[index].mask,
  149. };
  150. return (struct resolv_sortlist_entry) { .mask = 0, };
  151. }
  152. /* Called during thread shutdown to free the associated resolver
  153. context (mostly in response to cancellation, otherwise the
  154. __resolv_context_get/__resolv_context_put pairing will already have
  155. deallocated the context object). */
  156. void __resolv_context_freeres (void) attribute_hidden;
  157. #endif /* _RESOLV_CONTEXT_H */