digits_dots.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /* Copyright (C) 1997-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by H.J. Lu <hjl@gnu.ai.mit.edu>, 1997.
  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. #include <assert.h>
  16. #include <errno.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <ctype.h>
  20. #include <wctype.h>
  21. #include <resolv/resolv-internal.h>
  22. #include <resolv/resolv_context.h>
  23. #include <netdb.h>
  24. #include <arpa/inet.h>
  25. #include "nsswitch.h"
  26. #ifdef USE_NSCD
  27. # include <nscd/nscd_proto.h>
  28. #endif
  29. int
  30. __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
  31. char **buffer, size_t *buffer_size,
  32. size_t buflen, struct hostent **result,
  33. enum nss_status *status, int af, int *h_errnop)
  34. {
  35. /* We have to test for the use of IPv6 which can only be done by
  36. examining `_res'. */
  37. struct resolv_context *ctx = __resolv_context_get ();
  38. if (ctx == NULL)
  39. {
  40. if (h_errnop)
  41. *h_errnop = NETDB_INTERNAL;
  42. if (buffer_size == NULL)
  43. *status = NSS_STATUS_TRYAGAIN;
  44. else
  45. *result = NULL;
  46. return -1;
  47. }
  48. int ret = __nss_hostname_digits_dots_context
  49. (ctx, name, resbuf, buffer, buffer_size, buflen,
  50. result, status, af, h_errnop);
  51. __resolv_context_put (ctx);
  52. return ret;
  53. }
  54. int
  55. __nss_hostname_digits_dots_context (struct resolv_context *ctx,
  56. const char *name, struct hostent *resbuf,
  57. char **buffer, size_t *buffer_size,
  58. size_t buflen, struct hostent **result,
  59. enum nss_status *status, int af, int *h_errnop)
  60. {
  61. int save;
  62. /*
  63. * disallow names consisting only of digits/dots, unless
  64. * they end in a dot.
  65. */
  66. if (isdigit (name[0]) || isxdigit (name[0]) || name[0] == ':')
  67. {
  68. const char *cp;
  69. char *hostname;
  70. typedef unsigned char host_addr_t[16];
  71. host_addr_t *host_addr;
  72. typedef char *host_addr_list_t[2];
  73. host_addr_list_t *h_addr_ptrs;
  74. char **h_alias_ptr;
  75. size_t size_needed;
  76. int addr_size;
  77. switch (af)
  78. {
  79. case AF_INET:
  80. addr_size = INADDRSZ;
  81. break;
  82. case AF_INET6:
  83. addr_size = IN6ADDRSZ;
  84. break;
  85. default:
  86. af = res_use_inet6 () ? AF_INET6 : AF_INET;
  87. addr_size = af == AF_INET6 ? IN6ADDRSZ : INADDRSZ;
  88. break;
  89. }
  90. size_needed = (sizeof (*host_addr)
  91. + sizeof (*h_addr_ptrs)
  92. + sizeof (*h_alias_ptr) + strlen (name) + 1);
  93. if (buffer_size == NULL)
  94. {
  95. if (buflen < size_needed)
  96. {
  97. *status = NSS_STATUS_TRYAGAIN;
  98. if (h_errnop != NULL)
  99. *h_errnop = NETDB_INTERNAL;
  100. __set_errno (ERANGE);
  101. goto done;
  102. }
  103. }
  104. else if (buffer_size != NULL && *buffer_size < size_needed)
  105. {
  106. char *new_buf;
  107. *buffer_size = size_needed;
  108. new_buf = (char *) realloc (*buffer, *buffer_size);
  109. if (new_buf == NULL)
  110. {
  111. save = errno;
  112. free (*buffer);
  113. *buffer = NULL;
  114. *buffer_size = 0;
  115. __set_errno (save);
  116. if (h_errnop != NULL)
  117. *h_errnop = NETDB_INTERNAL;
  118. *result = NULL;
  119. goto done;
  120. }
  121. *buffer = new_buf;
  122. }
  123. memset (*buffer, '\0', size_needed);
  124. host_addr = (host_addr_t *) *buffer;
  125. h_addr_ptrs = (host_addr_list_t *)
  126. ((char *) host_addr + sizeof (*host_addr));
  127. h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs));
  128. hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr);
  129. if (isdigit (name[0]))
  130. {
  131. for (cp = name;; ++cp)
  132. {
  133. if (*cp == '\0')
  134. {
  135. int ok;
  136. if (*--cp == '.')
  137. break;
  138. /* All-numeric, no dot at the end. Fake up a hostent as if
  139. we'd actually done a lookup. What if someone types
  140. 255.255.255.255? The test below will succeed
  141. spuriously... ??? */
  142. if (af == AF_INET)
  143. ok = __inet_aton_exact (name, (struct in_addr *) host_addr);
  144. else
  145. {
  146. assert (af == AF_INET6);
  147. ok = inet_pton (af, name, host_addr) > 0;
  148. }
  149. if (! ok)
  150. {
  151. *h_errnop = HOST_NOT_FOUND;
  152. if (buffer_size == NULL)
  153. *status = NSS_STATUS_NOTFOUND;
  154. else
  155. *result = NULL;
  156. goto done;
  157. }
  158. resbuf->h_name = strcpy (hostname, name);
  159. h_alias_ptr[0] = NULL;
  160. resbuf->h_aliases = h_alias_ptr;
  161. (*h_addr_ptrs)[0] = (char *) host_addr;
  162. (*h_addr_ptrs)[1] = NULL;
  163. resbuf->h_addr_list = *h_addr_ptrs;
  164. if (af == AF_INET && res_use_inet6 ())
  165. {
  166. /* We need to change the IP v4 address into the
  167. IP v6 address. */
  168. char tmp[INADDRSZ];
  169. char *p = (char *) host_addr;
  170. int i;
  171. /* Save a copy of the IP v4 address. */
  172. memcpy (tmp, host_addr, INADDRSZ);
  173. /* Mark this ipv6 addr as a mapped ipv4. */
  174. for (i = 0; i < 10; i++)
  175. *p++ = 0x00;
  176. *p++ = 0xff;
  177. *p++ = 0xff;
  178. /* Copy the IP v4 address. */
  179. memcpy (p, tmp, INADDRSZ);
  180. resbuf->h_addrtype = AF_INET6;
  181. resbuf->h_length = IN6ADDRSZ;
  182. }
  183. else
  184. {
  185. resbuf->h_addrtype = af;
  186. resbuf->h_length = addr_size;
  187. }
  188. if (h_errnop != NULL)
  189. *h_errnop = NETDB_SUCCESS;
  190. if (buffer_size == NULL)
  191. *status = NSS_STATUS_SUCCESS;
  192. else
  193. *result = resbuf;
  194. goto done;
  195. }
  196. if (!isdigit (*cp) && *cp != '.')
  197. break;
  198. }
  199. }
  200. if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':')
  201. {
  202. switch (af)
  203. {
  204. default:
  205. af = res_use_inet6 () ? AF_INET6 : AF_INET;
  206. if (af == AF_INET6)
  207. {
  208. addr_size = IN6ADDRSZ;
  209. break;
  210. }
  211. /* FALLTHROUGH */
  212. case AF_INET:
  213. /* This is not possible. We cannot represent an IPv6 address
  214. in an `struct in_addr' variable. */
  215. *h_errnop = HOST_NOT_FOUND;
  216. if (buffer_size == NULL)
  217. *status = NSS_STATUS_NOTFOUND;
  218. else
  219. *result = NULL;
  220. goto done;
  221. case AF_INET6:
  222. addr_size = IN6ADDRSZ;
  223. break;
  224. }
  225. for (cp = name;; ++cp)
  226. {
  227. if (!*cp)
  228. {
  229. if (*--cp == '.')
  230. break;
  231. /* All-IPv6-legal, no dot at the end. Fake up a
  232. hostent as if we'd actually done a lookup. */
  233. if (inet_pton (AF_INET6, name, host_addr) <= 0)
  234. {
  235. *h_errnop = HOST_NOT_FOUND;
  236. if (buffer_size == NULL)
  237. *status = NSS_STATUS_NOTFOUND;
  238. else
  239. *result = NULL;
  240. goto done;
  241. }
  242. resbuf->h_name = strcpy (hostname, name);
  243. h_alias_ptr[0] = NULL;
  244. resbuf->h_aliases = h_alias_ptr;
  245. (*h_addr_ptrs)[0] = (char *) host_addr;
  246. (*h_addr_ptrs)[1] = (char *) 0;
  247. resbuf->h_addr_list = *h_addr_ptrs;
  248. resbuf->h_addrtype = AF_INET6;
  249. resbuf->h_length = addr_size;
  250. *h_errnop = NETDB_SUCCESS;
  251. if (buffer_size == NULL)
  252. *status = NSS_STATUS_SUCCESS;
  253. else
  254. *result = resbuf;
  255. goto done;
  256. }
  257. if (!isxdigit (*cp) && *cp != ':' && *cp != '.')
  258. break;
  259. }
  260. }
  261. }
  262. return 0;
  263. done:
  264. return 1;
  265. }
  266. libc_hidden_def (__nss_hostname_digits_dots)