sethostent.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* $NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $ */
  2. /*
  3. * Copyright (c) 1985, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #include <arpa/inet.h>
  31. #include <arpa/nameser.h>
  32. #include <assert.h>
  33. #include <errno.h>
  34. #include <netdb.h>
  35. #include <netinet/in.h>
  36. #include <resolv.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <sys/param.h>
  41. #include "hostent.h"
  42. #include "resolv_private.h"
  43. #define ALIGNBYTES (sizeof(uintptr_t) - 1)
  44. #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
  45. static void sethostent_r(FILE** hf) {
  46. if (!*hf)
  47. *hf = fopen(_PATH_HOSTS, "re");
  48. else
  49. rewind(*hf);
  50. }
  51. static void endhostent_r(FILE** hf) {
  52. if (*hf) {
  53. (void) fclose(*hf);
  54. *hf = NULL;
  55. }
  56. }
  57. // TODO: Consider returning a boolean result as files_getaddrinfo() does because the error code
  58. // does not currently return to netd.
  59. int _hf_gethtbyname2(const char* name, int af, getnamaddr* info) {
  60. struct hostent *hp, hent;
  61. char *buf, *ptr;
  62. size_t len, num, i;
  63. char* aliases[MAXALIASES];
  64. char* addr_ptrs[MAXADDRS];
  65. FILE* hf = NULL;
  66. sethostent_r(&hf);
  67. if (hf == NULL) {
  68. // TODO: Consider converting to a private extended EAI_* error code.
  69. // Currently, the EAI_* value has no corresponding error code for invalid argument socket
  70. // length. In order to not rely on errno, convert the original error code pair, EAI_SYSTEM
  71. // and EINVAL, to EAI_FAIL.
  72. return EAI_FAIL;
  73. }
  74. if ((ptr = buf = (char*) malloc(len = info->buflen)) == NULL) {
  75. return EAI_MEMORY;
  76. }
  77. hent.h_name = NULL;
  78. hent.h_addrtype = 0;
  79. hent.h_length = 0;
  80. size_t anum = 0;
  81. for (num = 0; num < MAXADDRS; /**/) {
  82. info->hp->h_addrtype = af;
  83. info->hp->h_length = 0;
  84. int he;
  85. hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, &he);
  86. if (hp == NULL) {
  87. if (he == NETDB_INTERNAL && errno == ENOSPC) {
  88. goto nospc; // glibc compatibility.
  89. }
  90. break;
  91. }
  92. if (strcasecmp(hp->h_name, name) != 0) {
  93. char** cp;
  94. for (cp = hp->h_aliases; *cp != NULL; cp++)
  95. if (strcasecmp(*cp, name) == 0) break;
  96. // NOTE: does not increment num
  97. if (*cp == NULL) continue;
  98. }
  99. if (num == 0) {
  100. hent.h_addrtype = hp->h_addrtype;
  101. hent.h_length = hp->h_length;
  102. HENT_SCOPY(hent.h_name, hp->h_name, ptr, len);
  103. for (anum = 0; hp->h_aliases[anum]; anum++) {
  104. if (anum >= MAXALIASES) goto nospc;
  105. HENT_SCOPY(aliases[anum], hp->h_aliases[anum], ptr, len);
  106. }
  107. ptr = (char*) ALIGN(ptr);
  108. if ((size_t)(ptr - buf) >= info->buflen) goto nospc;
  109. }
  110. if (num >= MAXADDRS) goto nospc;
  111. HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr, len);
  112. num++;
  113. }
  114. endhostent_r(&hf);
  115. if (num == 0) {
  116. free(buf);
  117. // TODO: Perhaps convert HOST_NOT_FOUND to EAI_NONAME instead.
  118. // The original return error number is h_errno HOST_NOT_FOUND which was converted to
  119. // EAI_NODATA.
  120. return EAI_NODATA;
  121. }
  122. hp = info->hp;
  123. ptr = info->buf;
  124. len = info->buflen;
  125. hp->h_addrtype = hent.h_addrtype;
  126. hp->h_length = hent.h_length;
  127. HENT_ARRAY(hp->h_aliases, anum, ptr, len);
  128. HENT_ARRAY(hp->h_addr_list, num, ptr, len);
  129. for (i = 0; i < num; i++) {
  130. HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr, len);
  131. // reserve space for mapping IPv4 address to IPv6 address in place
  132. if (hp->h_addrtype == AF_INET) {
  133. HENT_COPY(ptr, NAT64_PAD, sizeof(NAT64_PAD), ptr, len);
  134. }
  135. }
  136. hp->h_addr_list[num] = NULL;
  137. HENT_SCOPY(hp->h_name, hent.h_name, ptr, len);
  138. for (i = 0; i < anum; i++) {
  139. HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
  140. }
  141. hp->h_aliases[anum] = NULL;
  142. free(buf);
  143. return 0;
  144. nospc:
  145. free(buf);
  146. return EAI_MEMORY;
  147. }
  148. // TODO: Consider returning a boolean result as files_getaddrinfo() does because the error code
  149. // does not currently return to netd.
  150. int _hf_gethtbyaddr(const unsigned char* uaddr, int len, int af, getnamaddr* info) {
  151. info->hp->h_length = len;
  152. info->hp->h_addrtype = af;
  153. FILE* hf = NULL;
  154. sethostent_r(&hf);
  155. if (hf == NULL) {
  156. // TODO: Consider converting to a private extended EAI_* error code.
  157. // Currently, the EAI_* value has no corresponding error code for invalid argument socket
  158. // length. In order to not rely on errno, convert the original error code pair, EAI_SYSTEM
  159. // and EINVAL, to EAI_FAIL.
  160. return EAI_FAIL;
  161. }
  162. struct hostent* hp;
  163. int he;
  164. while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, &he)) != NULL)
  165. if (!memcmp(hp->h_addr_list[0], uaddr, (size_t) hp->h_length)) break;
  166. endhostent_r(&hf);
  167. if (hp == NULL) {
  168. if (errno == ENOSPC) return EAI_MEMORY; // glibc compatibility.
  169. // TODO: Perhaps convert HOST_NOT_FOUND to EAI_NONAME instead.
  170. // The original return error number is h_errno HOST_NOT_FOUND which was converted to
  171. // EAI_NODATA.
  172. return EAI_NODATA;
  173. }
  174. return 0;
  175. }