dns-host.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388
  1. /* Copyright (C) 1996-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
  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. /* Parts of this file are plain copies of the file `gethtnamadr.c' from
  16. the bind package and it has the following copyright. */
  17. /*
  18. * ++Copyright++ 1985, 1988, 1993
  19. * -
  20. * Copyright (c) 1985, 1988, 1993
  21. * The Regents of the University of California. All rights reserved.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the above copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 4. Neither the name of the University nor the names of its contributors
  32. * may be used to endorse or promote products derived from this software
  33. * without specific prior written permission.
  34. *
  35. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  36. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  38. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  39. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  40. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  41. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  42. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  43. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  44. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  45. * SUCH DAMAGE.
  46. * -
  47. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  48. *
  49. * Permission to use, copy, modify, and distribute this software for any
  50. * purpose with or without fee is hereby granted, provided that the above
  51. * copyright notice and this permission notice appear in all copies, and that
  52. * the name of Digital Equipment Corporation not be used in advertising or
  53. * publicity pertaining to distribution of the document or software without
  54. * specific, written prior permission.
  55. *
  56. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  57. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  58. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  59. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  60. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  61. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  62. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  63. * SOFTWARE.
  64. * -
  65. * --Copyright--
  66. */
  67. #include <assert.h>
  68. #include <ctype.h>
  69. #include <errno.h>
  70. #include <netdb.h>
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <stddef.h>
  74. #include <string.h>
  75. #include "nsswitch.h"
  76. #include <arpa/nameser.h>
  77. #include <resolv/resolv-internal.h>
  78. #include <resolv/resolv_context.h>
  79. /* Get implementations of some internal functions. */
  80. #include <resolv/mapv4v6addr.h>
  81. #include <resolv/mapv4v6hostent.h>
  82. #define RESOLVSORT
  83. #if PACKETSZ > 65536
  84. # define MAXPACKET PACKETSZ
  85. #else
  86. # define MAXPACKET 65536
  87. #endif
  88. /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
  89. #ifdef MAXHOSTNAMELEN
  90. # undef MAXHOSTNAMELEN
  91. #endif
  92. #define MAXHOSTNAMELEN 256
  93. /* We need this time later. */
  94. typedef union querybuf
  95. {
  96. HEADER hdr;
  97. u_char buf[MAXPACKET];
  98. } querybuf;
  99. static enum nss_status getanswer_r (struct resolv_context *ctx,
  100. const querybuf *answer, int anslen,
  101. const char *qname, int qtype,
  102. struct hostent *result, char *buffer,
  103. size_t buflen, int *errnop, int *h_errnop,
  104. int map, int32_t *ttlp, char **canonp);
  105. static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
  106. const querybuf *answer2, int anslen2,
  107. const char *qname,
  108. struct gaih_addrtuple **pat,
  109. char *buffer, size_t buflen,
  110. int *errnop, int *h_errnop,
  111. int32_t *ttlp);
  112. static enum nss_status gethostbyname3_context (struct resolv_context *ctx,
  113. const char *name, int af,
  114. struct hostent *result,
  115. char *buffer, size_t buflen,
  116. int *errnop, int *h_errnop,
  117. int32_t *ttlp,
  118. char **canonp);
  119. /* Return the expected RDATA length for an address record type (A or
  120. AAAA). */
  121. static int
  122. rrtype_to_rdata_length (int type)
  123. {
  124. switch (type)
  125. {
  126. case T_A:
  127. return INADDRSZ;
  128. case T_AAAA:
  129. return IN6ADDRSZ;
  130. default:
  131. return -1;
  132. }
  133. }
  134. enum nss_status
  135. _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
  136. char *buffer, size_t buflen, int *errnop,
  137. int *h_errnop, int32_t *ttlp, char **canonp)
  138. {
  139. struct resolv_context *ctx = __resolv_context_get ();
  140. if (ctx == NULL)
  141. {
  142. *errnop = errno;
  143. *h_errnop = NETDB_INTERNAL;
  144. return NSS_STATUS_UNAVAIL;
  145. }
  146. enum nss_status status = gethostbyname3_context
  147. (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
  148. __resolv_context_put (ctx);
  149. return status;
  150. }
  151. static enum nss_status
  152. gethostbyname3_context (struct resolv_context *ctx,
  153. const char *name, int af, struct hostent *result,
  154. char *buffer, size_t buflen, int *errnop,
  155. int *h_errnop, int32_t *ttlp, char **canonp)
  156. {
  157. union
  158. {
  159. querybuf *buf;
  160. u_char *ptr;
  161. } host_buffer;
  162. querybuf *orig_host_buffer;
  163. char tmp[NS_MAXDNAME];
  164. int size, type, n;
  165. const char *cp;
  166. int map = 0;
  167. int olderr = errno;
  168. enum nss_status status;
  169. switch (af) {
  170. case AF_INET:
  171. size = INADDRSZ;
  172. type = T_A;
  173. break;
  174. case AF_INET6:
  175. size = IN6ADDRSZ;
  176. type = T_AAAA;
  177. break;
  178. default:
  179. *h_errnop = NO_DATA;
  180. *errnop = EAFNOSUPPORT;
  181. return NSS_STATUS_UNAVAIL;
  182. }
  183. result->h_addrtype = af;
  184. result->h_length = size;
  185. /*
  186. * if there aren't any dots, it could be a user-level alias.
  187. * this is also done in res_query() since we are not the only
  188. * function that looks up host names.
  189. */
  190. if (strchr (name, '.') == NULL
  191. && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
  192. name = cp;
  193. host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
  194. n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf,
  195. 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
  196. if (n < 0)
  197. {
  198. switch (errno)
  199. {
  200. case ESRCH:
  201. status = NSS_STATUS_TRYAGAIN;
  202. h_errno = TRY_AGAIN;
  203. break;
  204. /* System has run out of file descriptors. */
  205. case EMFILE:
  206. case ENFILE:
  207. h_errno = NETDB_INTERNAL;
  208. /* Fall through. */
  209. case ECONNREFUSED:
  210. case ETIMEDOUT:
  211. status = NSS_STATUS_UNAVAIL;
  212. break;
  213. default:
  214. status = NSS_STATUS_NOTFOUND;
  215. break;
  216. }
  217. *h_errnop = h_errno;
  218. if (h_errno == TRY_AGAIN)
  219. *errnop = EAGAIN;
  220. else
  221. __set_errno (olderr);
  222. /* If we are looking for an IPv6 address and mapping is enabled
  223. by having the RES_USE_INET6 bit in _res.options set, we try
  224. another lookup. */
  225. if (af == AF_INET6 && res_use_inet6 ())
  226. n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf,
  227. host_buffer.buf != orig_host_buffer
  228. ? MAXPACKET : 1024, &host_buffer.ptr,
  229. NULL, NULL, NULL, NULL);
  230. if (n < 0)
  231. {
  232. if (host_buffer.buf != orig_host_buffer)
  233. free (host_buffer.buf);
  234. return status;
  235. }
  236. map = 1;
  237. result->h_addrtype = AF_INET;
  238. result->h_length = INADDRSZ;
  239. }
  240. status = getanswer_r
  241. (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
  242. errnop, h_errnop, map, ttlp, canonp);
  243. if (host_buffer.buf != orig_host_buffer)
  244. free (host_buffer.buf);
  245. return status;
  246. }
  247. /* Verify that the name looks like a host name. There is no point in
  248. sending a query which will not produce a usable name in the
  249. response. */
  250. static enum nss_status
  251. check_name (const char *name, int *h_errnop)
  252. {
  253. if (res_hnok (name))
  254. return NSS_STATUS_SUCCESS;
  255. *h_errnop = HOST_NOT_FOUND;
  256. return NSS_STATUS_NOTFOUND;
  257. }
  258. enum nss_status
  259. _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
  260. char *buffer, size_t buflen, int *errnop,
  261. int *h_errnop)
  262. {
  263. enum nss_status status = check_name (name, h_errnop);
  264. if (status != NSS_STATUS_SUCCESS)
  265. return status;
  266. return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
  267. h_errnop, NULL, NULL);
  268. }
  269. enum nss_status
  270. _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
  271. char *buffer, size_t buflen, int *errnop,
  272. int *h_errnop)
  273. {
  274. enum nss_status status = check_name (name, h_errnop);
  275. if (status != NSS_STATUS_SUCCESS)
  276. return status;
  277. struct resolv_context *ctx = __resolv_context_get ();
  278. if (ctx == NULL)
  279. {
  280. *errnop = errno;
  281. *h_errnop = NETDB_INTERNAL;
  282. return NSS_STATUS_UNAVAIL;
  283. }
  284. status = NSS_STATUS_NOTFOUND;
  285. if (res_use_inet6 ())
  286. status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
  287. buflen, errnop, h_errnop, NULL, NULL);
  288. if (status == NSS_STATUS_NOTFOUND)
  289. status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
  290. buflen, errnop, h_errnop, NULL, NULL);
  291. __resolv_context_put (ctx);
  292. return status;
  293. }
  294. enum nss_status
  295. _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
  296. char *buffer, size_t buflen, int *errnop,
  297. int *herrnop, int32_t *ttlp)
  298. {
  299. enum nss_status status = check_name (name, herrnop);
  300. if (status != NSS_STATUS_SUCCESS)
  301. return status;
  302. struct resolv_context *ctx = __resolv_context_get ();
  303. if (ctx == NULL)
  304. {
  305. *errnop = errno;
  306. *herrnop = NETDB_INTERNAL;
  307. return NSS_STATUS_UNAVAIL;
  308. }
  309. /*
  310. * if there aren't any dots, it could be a user-level alias.
  311. * this is also done in res_query() since we are not the only
  312. * function that looks up host names.
  313. */
  314. if (strchr (name, '.') == NULL)
  315. {
  316. char *tmp = alloca (NS_MAXDNAME);
  317. const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME);
  318. if (cp != NULL)
  319. name = cp;
  320. }
  321. union
  322. {
  323. querybuf *buf;
  324. u_char *ptr;
  325. } host_buffer;
  326. querybuf *orig_host_buffer;
  327. host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
  328. u_char *ans2p = NULL;
  329. int nans2p = 0;
  330. int resplen2 = 0;
  331. int ans2p_malloced = 0;
  332. int olderr = errno;
  333. int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
  334. host_buffer.buf->buf, 2048, &host_buffer.ptr,
  335. &ans2p, &nans2p, &resplen2, &ans2p_malloced);
  336. if (n >= 0)
  337. {
  338. status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
  339. resplen2, name, pat, buffer, buflen,
  340. errnop, herrnop, ttlp);
  341. }
  342. else
  343. {
  344. switch (errno)
  345. {
  346. case ESRCH:
  347. status = NSS_STATUS_TRYAGAIN;
  348. h_errno = TRY_AGAIN;
  349. break;
  350. /* System has run out of file descriptors. */
  351. case EMFILE:
  352. case ENFILE:
  353. h_errno = NETDB_INTERNAL;
  354. /* Fall through. */
  355. case ECONNREFUSED:
  356. case ETIMEDOUT:
  357. status = NSS_STATUS_UNAVAIL;
  358. break;
  359. default:
  360. status = NSS_STATUS_NOTFOUND;
  361. break;
  362. }
  363. *herrnop = h_errno;
  364. if (h_errno == TRY_AGAIN)
  365. *errnop = EAGAIN;
  366. else
  367. __set_errno (olderr);
  368. }
  369. /* Check whether ans2p was separately allocated. */
  370. if (ans2p_malloced)
  371. free (ans2p);
  372. if (host_buffer.buf != orig_host_buffer)
  373. free (host_buffer.buf);
  374. __resolv_context_put (ctx);
  375. return status;
  376. }
  377. extern enum nss_status _nss_dns_gethostbyaddr2_r (const void *addr,
  378. socklen_t len, int af,
  379. struct hostent *result,
  380. char *buffer, size_t buflen,
  381. int *errnop, int *h_errnop,
  382. int32_t *ttlp);
  383. hidden_proto (_nss_dns_gethostbyaddr2_r)
  384. enum nss_status
  385. _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
  386. struct hostent *result, char *buffer, size_t buflen,
  387. int *errnop, int *h_errnop, int32_t *ttlp)
  388. {
  389. static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
  390. static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
  391. static const u_char v6local[] = { 0,0, 0,1 };
  392. const u_char *uaddr = (const u_char *)addr;
  393. struct host_data
  394. {
  395. char *aliases[MAX_NR_ALIASES];
  396. unsigned char host_addr[16]; /* IPv4 or IPv6 */
  397. char *h_addr_ptrs[MAX_NR_ADDRS + 1];
  398. char linebuffer[0];
  399. } *host_data = (struct host_data *) buffer;
  400. union
  401. {
  402. querybuf *buf;
  403. u_char *ptr;
  404. } host_buffer;
  405. querybuf *orig_host_buffer;
  406. char qbuf[MAXDNAME+1], *qp = NULL;
  407. size_t size;
  408. int n, status;
  409. int olderr = errno;
  410. uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
  411. buffer += pad;
  412. buflen = buflen > pad ? buflen - pad : 0;
  413. if (__glibc_unlikely (buflen < sizeof (struct host_data)))
  414. {
  415. *errnop = ERANGE;
  416. *h_errnop = NETDB_INTERNAL;
  417. return NSS_STATUS_TRYAGAIN;
  418. }
  419. host_data = (struct host_data *) buffer;
  420. struct resolv_context *ctx = __resolv_context_get ();
  421. if (ctx == NULL)
  422. {
  423. *errnop = errno;
  424. *h_errnop = NETDB_INTERNAL;
  425. return NSS_STATUS_UNAVAIL;
  426. }
  427. if (af == AF_INET6 && len == IN6ADDRSZ
  428. && (memcmp (uaddr, mapped, sizeof mapped) == 0
  429. || (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0
  430. && memcmp (&uaddr[sizeof tunnelled], v6local, sizeof v6local))))
  431. {
  432. /* Unmap. */
  433. addr += sizeof mapped;
  434. uaddr += sizeof mapped;
  435. af = AF_INET;
  436. len = INADDRSZ;
  437. }
  438. switch (af)
  439. {
  440. case AF_INET:
  441. size = INADDRSZ;
  442. break;
  443. case AF_INET6:
  444. size = IN6ADDRSZ;
  445. break;
  446. default:
  447. *errnop = EAFNOSUPPORT;
  448. *h_errnop = NETDB_INTERNAL;
  449. __resolv_context_put (ctx);
  450. return NSS_STATUS_UNAVAIL;
  451. }
  452. if (size > len)
  453. {
  454. *errnop = EAFNOSUPPORT;
  455. *h_errnop = NETDB_INTERNAL;
  456. __resolv_context_put (ctx);
  457. return NSS_STATUS_UNAVAIL;
  458. }
  459. host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
  460. switch (af)
  461. {
  462. case AF_INET:
  463. sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
  464. (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
  465. break;
  466. case AF_INET6:
  467. qp = qbuf;
  468. for (n = IN6ADDRSZ - 1; n >= 0; n--)
  469. {
  470. static const char nibblechar[16] = "0123456789abcdef";
  471. *qp++ = nibblechar[uaddr[n] & 0xf];
  472. *qp++ = '.';
  473. *qp++ = nibblechar[(uaddr[n] >> 4) & 0xf];
  474. *qp++ = '.';
  475. }
  476. strcpy(qp, "ip6.arpa");
  477. break;
  478. default:
  479. /* Cannot happen. */
  480. break;
  481. }
  482. n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
  483. 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
  484. if (n < 0)
  485. {
  486. *h_errnop = h_errno;
  487. __set_errno (olderr);
  488. if (host_buffer.buf != orig_host_buffer)
  489. free (host_buffer.buf);
  490. __resolv_context_put (ctx);
  491. return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
  492. }
  493. status = getanswer_r
  494. (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
  495. errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
  496. if (host_buffer.buf != orig_host_buffer)
  497. free (host_buffer.buf);
  498. if (status != NSS_STATUS_SUCCESS)
  499. {
  500. __resolv_context_put (ctx);
  501. return status;
  502. }
  503. result->h_addrtype = af;
  504. result->h_length = len;
  505. memcpy (host_data->host_addr, addr, len);
  506. host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
  507. host_data->h_addr_ptrs[1] = NULL;
  508. *h_errnop = NETDB_SUCCESS;
  509. __resolv_context_put (ctx);
  510. return NSS_STATUS_SUCCESS;
  511. }
  512. hidden_def (_nss_dns_gethostbyaddr2_r)
  513. enum nss_status
  514. _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
  515. struct hostent *result, char *buffer, size_t buflen,
  516. int *errnop, int *h_errnop)
  517. {
  518. return _nss_dns_gethostbyaddr2_r (addr, len, af, result, buffer, buflen,
  519. errnop, h_errnop, NULL);
  520. }
  521. static void
  522. addrsort (struct resolv_context *ctx, char **ap, int num)
  523. {
  524. int i, j;
  525. char **p;
  526. short aval[MAX_NR_ADDRS];
  527. int needsort = 0;
  528. size_t nsort = __resolv_context_sort_count (ctx);
  529. p = ap;
  530. if (num > MAX_NR_ADDRS)
  531. num = MAX_NR_ADDRS;
  532. for (i = 0; i < num; i++, p++)
  533. {
  534. for (j = 0 ; (unsigned)j < nsort; j++)
  535. {
  536. struct resolv_sortlist_entry e
  537. = __resolv_context_sort_entry (ctx, j);
  538. if (e.addr.s_addr == (((struct in_addr *)(*p))->s_addr & e.mask))
  539. break;
  540. }
  541. aval[i] = j;
  542. if (needsort == 0 && i > 0 && j < aval[i-1])
  543. needsort = i;
  544. }
  545. if (!needsort)
  546. return;
  547. while (needsort++ < num)
  548. for (j = needsort - 2; j >= 0; j--)
  549. if (aval[j] > aval[j+1])
  550. {
  551. char *hp;
  552. i = aval[j];
  553. aval[j] = aval[j+1];
  554. aval[j+1] = i;
  555. hp = ap[j];
  556. ap[j] = ap[j+1];
  557. ap[j+1] = hp;
  558. }
  559. else
  560. break;
  561. }
  562. static enum nss_status
  563. getanswer_r (struct resolv_context *ctx,
  564. const querybuf *answer, int anslen, const char *qname, int qtype,
  565. struct hostent *result, char *buffer, size_t buflen,
  566. int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
  567. {
  568. struct host_data
  569. {
  570. char *aliases[MAX_NR_ALIASES];
  571. unsigned char host_addr[16]; /* IPv4 or IPv6 */
  572. char *h_addr_ptrs[0];
  573. } *host_data;
  574. int linebuflen;
  575. const HEADER *hp;
  576. const u_char *end_of_message, *cp;
  577. int n, ancount, qdcount;
  578. int haveanswer, had_error;
  579. char *bp, **ap, **hap;
  580. char tbuf[MAXDNAME];
  581. const char *tname;
  582. int (*name_ok) (const char *);
  583. u_char packtmp[NS_MAXCDNAME];
  584. int have_to_map = 0;
  585. uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
  586. buffer += pad;
  587. buflen = buflen > pad ? buflen - pad : 0;
  588. if (__glibc_unlikely (buflen < sizeof (struct host_data)))
  589. {
  590. /* The buffer is too small. */
  591. too_small:
  592. *errnop = ERANGE;
  593. *h_errnop = NETDB_INTERNAL;
  594. return NSS_STATUS_TRYAGAIN;
  595. }
  596. host_data = (struct host_data *) buffer;
  597. linebuflen = buflen - sizeof (struct host_data);
  598. if (buflen - sizeof (struct host_data) != linebuflen)
  599. linebuflen = INT_MAX;
  600. tname = qname;
  601. result->h_name = NULL;
  602. end_of_message = answer->buf + anslen;
  603. switch (qtype)
  604. {
  605. case T_A:
  606. case T_AAAA:
  607. name_ok = res_hnok;
  608. break;
  609. case T_PTR:
  610. name_ok = res_dnok;
  611. break;
  612. default:
  613. *errnop = ENOENT;
  614. return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
  615. }
  616. /*
  617. * find first satisfactory answer
  618. */
  619. hp = &answer->hdr;
  620. ancount = ntohs (hp->ancount);
  621. qdcount = ntohs (hp->qdcount);
  622. cp = answer->buf + HFIXEDSZ;
  623. if (__glibc_unlikely (qdcount != 1))
  624. {
  625. *h_errnop = NO_RECOVERY;
  626. return NSS_STATUS_UNAVAIL;
  627. }
  628. if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
  629. goto too_small;
  630. bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
  631. linebuflen -= (ancount + 1) * sizeof (char *);
  632. n = __ns_name_unpack (answer->buf, end_of_message, cp,
  633. packtmp, sizeof packtmp);
  634. if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
  635. {
  636. if (__glibc_unlikely (errno == EMSGSIZE))
  637. goto too_small;
  638. n = -1;
  639. }
  640. if (n > 0 && bp[0] == '.')
  641. bp[0] = '\0';
  642. if (__glibc_unlikely (n < 0))
  643. {
  644. *errnop = errno;
  645. *h_errnop = NO_RECOVERY;
  646. return NSS_STATUS_UNAVAIL;
  647. }
  648. if (__glibc_unlikely (name_ok (bp) == 0))
  649. {
  650. errno = EBADMSG;
  651. *errnop = EBADMSG;
  652. *h_errnop = NO_RECOVERY;
  653. return NSS_STATUS_UNAVAIL;
  654. }
  655. cp += n + QFIXEDSZ;
  656. if (qtype == T_A || qtype == T_AAAA)
  657. {
  658. /* res_send() has already verified that the query name is the
  659. * same as the one we sent; this just gets the expanded name
  660. * (i.e., with the succeeding search-domain tacked on).
  661. */
  662. n = strlen (bp) + 1; /* for the \0 */
  663. if (n >= MAXHOSTNAMELEN)
  664. {
  665. *h_errnop = NO_RECOVERY;
  666. *errnop = ENOENT;
  667. return NSS_STATUS_TRYAGAIN;
  668. }
  669. result->h_name = bp;
  670. bp += n;
  671. linebuflen -= n;
  672. if (linebuflen < 0)
  673. goto too_small;
  674. /* The qname can be abbreviated, but h_name is now absolute. */
  675. qname = result->h_name;
  676. }
  677. ap = host_data->aliases;
  678. *ap = NULL;
  679. result->h_aliases = host_data->aliases;
  680. hap = host_data->h_addr_ptrs;
  681. *hap = NULL;
  682. result->h_addr_list = host_data->h_addr_ptrs;
  683. haveanswer = 0;
  684. had_error = 0;
  685. while (ancount-- > 0 && cp < end_of_message && had_error == 0)
  686. {
  687. int type, class;
  688. n = __ns_name_unpack (answer->buf, end_of_message, cp,
  689. packtmp, sizeof packtmp);
  690. if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
  691. {
  692. if (__glibc_unlikely (errno == EMSGSIZE))
  693. goto too_small;
  694. n = -1;
  695. }
  696. if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
  697. {
  698. ++had_error;
  699. continue;
  700. }
  701. cp += n; /* name */
  702. if (__glibc_unlikely (cp + 10 > end_of_message))
  703. {
  704. ++had_error;
  705. continue;
  706. }
  707. type = __ns_get16 (cp);
  708. cp += INT16SZ; /* type */
  709. class = __ns_get16 (cp);
  710. cp += INT16SZ; /* class */
  711. int32_t ttl = __ns_get32 (cp);
  712. cp += INT32SZ; /* TTL */
  713. n = __ns_get16 (cp);
  714. cp += INT16SZ; /* len */
  715. if (end_of_message - cp < n)
  716. {
  717. /* RDATA extends beyond the end of the packet. */
  718. ++had_error;
  719. continue;
  720. }
  721. if (__glibc_unlikely (class != C_IN))
  722. {
  723. /* XXX - debug? syslog? */
  724. cp += n;
  725. continue; /* XXX - had_error++ ? */
  726. }
  727. if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
  728. {
  729. /* A CNAME could also have a TTL entry. */
  730. if (ttlp != NULL && ttl < *ttlp)
  731. *ttlp = ttl;
  732. if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
  733. continue;
  734. n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
  735. if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
  736. {
  737. ++had_error;
  738. continue;
  739. }
  740. cp += n;
  741. /* Store alias. */
  742. *ap++ = bp;
  743. n = strlen (bp) + 1; /* For the \0. */
  744. if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
  745. {
  746. ++had_error;
  747. continue;
  748. }
  749. bp += n;
  750. linebuflen -= n;
  751. /* Get canonical name. */
  752. n = strlen (tbuf) + 1; /* For the \0. */
  753. if (__glibc_unlikely (n > linebuflen))
  754. goto too_small;
  755. if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
  756. {
  757. ++had_error;
  758. continue;
  759. }
  760. result->h_name = bp;
  761. bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
  762. linebuflen -= n;
  763. continue;
  764. }
  765. if (qtype == T_PTR && type == T_CNAME)
  766. {
  767. /* A CNAME could also have a TTL entry. */
  768. if (ttlp != NULL && ttl < *ttlp)
  769. *ttlp = ttl;
  770. n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
  771. if (__glibc_unlikely (n < 0 || res_dnok (tbuf) == 0))
  772. {
  773. ++had_error;
  774. continue;
  775. }
  776. cp += n;
  777. /* Get canonical name. */
  778. n = strlen (tbuf) + 1; /* For the \0. */
  779. if (__glibc_unlikely (n > linebuflen))
  780. goto too_small;
  781. if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
  782. {
  783. ++had_error;
  784. continue;
  785. }
  786. tname = bp;
  787. bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
  788. linebuflen -= n;
  789. continue;
  790. }
  791. if (type == T_A && qtype == T_AAAA && map)
  792. have_to_map = 1;
  793. else if (__glibc_unlikely (type != qtype))
  794. {
  795. cp += n;
  796. continue; /* XXX - had_error++ ? */
  797. }
  798. switch (type)
  799. {
  800. case T_PTR:
  801. if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
  802. {
  803. cp += n;
  804. continue; /* XXX - had_error++ ? */
  805. }
  806. n = __ns_name_unpack (answer->buf, end_of_message, cp,
  807. packtmp, sizeof packtmp);
  808. if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
  809. {
  810. if (__glibc_unlikely (errno == EMSGSIZE))
  811. goto too_small;
  812. n = -1;
  813. }
  814. if (__glibc_unlikely (n < 0 || res_hnok (bp) == 0))
  815. {
  816. ++had_error;
  817. break;
  818. }
  819. if (ttlp != NULL && ttl < *ttlp)
  820. *ttlp = ttl;
  821. /* bind would put multiple PTR records as aliases, but we don't do
  822. that. */
  823. result->h_name = bp;
  824. *h_errnop = NETDB_SUCCESS;
  825. return NSS_STATUS_SUCCESS;
  826. case T_A:
  827. case T_AAAA:
  828. if (__glibc_unlikely (strcasecmp (result->h_name, bp) != 0))
  829. {
  830. cp += n;
  831. continue; /* XXX - had_error++ ? */
  832. }
  833. /* Stop parsing at a record whose length is incorrect. */
  834. if (n != rrtype_to_rdata_length (type))
  835. {
  836. ++had_error;
  837. break;
  838. }
  839. /* Skip records of the wrong type. */
  840. if (n != result->h_length)
  841. {
  842. cp += n;
  843. continue;
  844. }
  845. if (!haveanswer)
  846. {
  847. int nn;
  848. /* We compose a single hostent out of the entire chain of
  849. entries, so the TTL of the hostent is essentially the lowest
  850. TTL in the chain. */
  851. if (ttlp != NULL && ttl < *ttlp)
  852. *ttlp = ttl;
  853. if (canonp != NULL)
  854. *canonp = bp;
  855. result->h_name = bp;
  856. nn = strlen (bp) + 1; /* for the \0 */
  857. bp += nn;
  858. linebuflen -= nn;
  859. }
  860. linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align));
  861. bp += sizeof (align) - ((u_long) bp % sizeof (align));
  862. if (__glibc_unlikely (n > linebuflen))
  863. goto too_small;
  864. bp = __mempcpy (*hap++ = bp, cp, n);
  865. cp += n;
  866. linebuflen -= n;
  867. break;
  868. default:
  869. abort ();
  870. }
  871. if (had_error == 0)
  872. ++haveanswer;
  873. }
  874. if (haveanswer > 0)
  875. {
  876. *ap = NULL;
  877. *hap = NULL;
  878. /*
  879. * Note: we sort even if host can take only one address
  880. * in its return structures - should give it the "best"
  881. * address in that case, not some random one
  882. */
  883. if (haveanswer > 1 && qtype == T_A
  884. && __resolv_context_sort_count (ctx) > 0)
  885. addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
  886. if (result->h_name == NULL)
  887. {
  888. n = strlen (qname) + 1; /* For the \0. */
  889. if (n > linebuflen)
  890. goto too_small;
  891. if (n >= MAXHOSTNAMELEN)
  892. goto no_recovery;
  893. result->h_name = bp;
  894. bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
  895. linebuflen -= n;
  896. }
  897. if (have_to_map)
  898. if (map_v4v6_hostent (result, &bp, &linebuflen))
  899. goto too_small;
  900. *h_errnop = NETDB_SUCCESS;
  901. return NSS_STATUS_SUCCESS;
  902. }
  903. no_recovery:
  904. *h_errnop = NO_RECOVERY;
  905. *errnop = ENOENT;
  906. /* Special case here: if the resolver sent a result but it only
  907. contains a CNAME while we are looking for a T_A or T_AAAA record,
  908. we fail with NOTFOUND instead of TRYAGAIN. */
  909. return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
  910. ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
  911. }
  912. static enum nss_status
  913. gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
  914. struct gaih_addrtuple ***patp,
  915. char **bufferp, size_t *buflenp,
  916. int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
  917. {
  918. char *buffer = *bufferp;
  919. size_t buflen = *buflenp;
  920. struct gaih_addrtuple **pat = *patp;
  921. const HEADER *hp = &answer->hdr;
  922. int ancount = ntohs (hp->ancount);
  923. int qdcount = ntohs (hp->qdcount);
  924. const u_char *cp = answer->buf + HFIXEDSZ;
  925. const u_char *end_of_message = answer->buf + anslen;
  926. if (__glibc_unlikely (qdcount != 1))
  927. {
  928. *h_errnop = NO_RECOVERY;
  929. return NSS_STATUS_UNAVAIL;
  930. }
  931. u_char packtmp[NS_MAXCDNAME];
  932. int n = __ns_name_unpack (answer->buf, end_of_message, cp,
  933. packtmp, sizeof packtmp);
  934. /* We unpack the name to check it for validity. But we do not need
  935. it later. */
  936. if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
  937. {
  938. if (__glibc_unlikely (errno == EMSGSIZE))
  939. {
  940. too_small:
  941. *errnop = ERANGE;
  942. *h_errnop = NETDB_INTERNAL;
  943. return NSS_STATUS_TRYAGAIN;
  944. }
  945. n = -1;
  946. }
  947. if (__glibc_unlikely (n < 0))
  948. {
  949. *errnop = errno;
  950. *h_errnop = NO_RECOVERY;
  951. return NSS_STATUS_UNAVAIL;
  952. }
  953. if (__glibc_unlikely (res_hnok (buffer) == 0))
  954. {
  955. errno = EBADMSG;
  956. *errnop = EBADMSG;
  957. *h_errnop = NO_RECOVERY;
  958. return NSS_STATUS_UNAVAIL;
  959. }
  960. cp += n + QFIXEDSZ;
  961. int haveanswer = 0;
  962. int had_error = 0;
  963. char *canon = NULL;
  964. char *h_name = NULL;
  965. int h_namelen = 0;
  966. if (ancount == 0)
  967. {
  968. *h_errnop = HOST_NOT_FOUND;
  969. return NSS_STATUS_NOTFOUND;
  970. }
  971. while (ancount-- > 0 && cp < end_of_message && had_error == 0)
  972. {
  973. n = __ns_name_unpack (answer->buf, end_of_message, cp,
  974. packtmp, sizeof packtmp);
  975. if (n != -1 &&
  976. (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
  977. {
  978. if (__glibc_unlikely (errno == EMSGSIZE))
  979. goto too_small;
  980. n = -1;
  981. }
  982. if (__glibc_unlikely (n < 0 || res_hnok (buffer) == 0))
  983. {
  984. ++had_error;
  985. continue;
  986. }
  987. if (*firstp && canon == NULL)
  988. {
  989. h_name = buffer;
  990. buffer += h_namelen;
  991. buflen -= h_namelen;
  992. }
  993. cp += n; /* name */
  994. if (__glibc_unlikely (cp + 10 > end_of_message))
  995. {
  996. ++had_error;
  997. continue;
  998. }
  999. int type = __ns_get16 (cp);
  1000. cp += INT16SZ; /* type */
  1001. int class = __ns_get16 (cp);
  1002. cp += INT16SZ; /* class */
  1003. int32_t ttl = __ns_get32 (cp);
  1004. cp += INT32SZ; /* TTL */
  1005. n = __ns_get16 (cp);
  1006. cp += INT16SZ; /* len */
  1007. if (end_of_message - cp < n)
  1008. {
  1009. /* RDATA extends beyond the end of the packet. */
  1010. ++had_error;
  1011. continue;
  1012. }
  1013. if (class != C_IN)
  1014. {
  1015. cp += n;
  1016. continue;
  1017. }
  1018. if (type == T_CNAME)
  1019. {
  1020. char tbuf[MAXDNAME];
  1021. /* A CNAME could also have a TTL entry. */
  1022. if (ttlp != NULL && ttl < *ttlp)
  1023. *ttlp = ttl;
  1024. n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
  1025. if (__glibc_unlikely (n < 0 || res_hnok (tbuf) == 0))
  1026. {
  1027. ++had_error;
  1028. continue;
  1029. }
  1030. cp += n;
  1031. if (*firstp)
  1032. {
  1033. /* Reclaim buffer space. */
  1034. if (h_name + h_namelen == buffer)
  1035. {
  1036. buffer = h_name;
  1037. buflen += h_namelen;
  1038. }
  1039. n = strlen (tbuf) + 1;
  1040. if (__glibc_unlikely (n > buflen))
  1041. goto too_small;
  1042. if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
  1043. {
  1044. ++had_error;
  1045. continue;
  1046. }
  1047. canon = buffer;
  1048. buffer = __mempcpy (buffer, tbuf, n);
  1049. buflen -= n;
  1050. h_namelen = 0;
  1051. }
  1052. continue;
  1053. }
  1054. /* Stop parsing if we encounter a record with incorrect RDATA
  1055. length. */
  1056. if (type == T_A || type == T_AAAA)
  1057. {
  1058. if (n != rrtype_to_rdata_length (type))
  1059. {
  1060. ++had_error;
  1061. continue;
  1062. }
  1063. }
  1064. else
  1065. {
  1066. /* Skip unknown records. */
  1067. cp += n;
  1068. continue;
  1069. }
  1070. assert (type == T_A || type == T_AAAA);
  1071. if (*pat == NULL)
  1072. {
  1073. uintptr_t pad = (-(uintptr_t) buffer
  1074. % __alignof__ (struct gaih_addrtuple));
  1075. buffer += pad;
  1076. buflen = buflen > pad ? buflen - pad : 0;
  1077. if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
  1078. goto too_small;
  1079. *pat = (struct gaih_addrtuple *) buffer;
  1080. buffer += sizeof (struct gaih_addrtuple);
  1081. buflen -= sizeof (struct gaih_addrtuple);
  1082. }
  1083. (*pat)->name = NULL;
  1084. (*pat)->next = NULL;
  1085. if (*firstp)
  1086. {
  1087. /* We compose a single hostent out of the entire chain of
  1088. entries, so the TTL of the hostent is essentially the lowest
  1089. TTL in the chain. */
  1090. if (ttlp != NULL && ttl < *ttlp)
  1091. *ttlp = ttl;
  1092. (*pat)->name = canon ?: h_name;
  1093. *firstp = 0;
  1094. }
  1095. (*pat)->family = type == T_A ? AF_INET : AF_INET6;
  1096. memcpy ((*pat)->addr, cp, n);
  1097. cp += n;
  1098. (*pat)->scopeid = 0;
  1099. pat = &((*pat)->next);
  1100. haveanswer = 1;
  1101. }
  1102. if (haveanswer)
  1103. {
  1104. *patp = pat;
  1105. *bufferp = buffer;
  1106. *buflenp = buflen;
  1107. *h_errnop = NETDB_SUCCESS;
  1108. return NSS_STATUS_SUCCESS;
  1109. }
  1110. /* Special case here: if the resolver sent a result but it only
  1111. contains a CNAME while we are looking for a T_A or T_AAAA record,
  1112. we fail with NOTFOUND instead of TRYAGAIN. */
  1113. if (canon != NULL)
  1114. {
  1115. *h_errnop = HOST_NOT_FOUND;
  1116. return NSS_STATUS_NOTFOUND;
  1117. }
  1118. *h_errnop = NETDB_INTERNAL;
  1119. return NSS_STATUS_TRYAGAIN;
  1120. }
  1121. static enum nss_status
  1122. gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
  1123. int anslen2, const char *qname,
  1124. struct gaih_addrtuple **pat, char *buffer, size_t buflen,
  1125. int *errnop, int *h_errnop, int32_t *ttlp)
  1126. {
  1127. int first = 1;
  1128. enum nss_status status = NSS_STATUS_NOTFOUND;
  1129. /* Combining the NSS status of two distinct queries requires some
  1130. compromise and attention to symmetry (A or AAAA queries can be
  1131. returned in any order). What follows is a breakdown of how this
  1132. code is expected to work and why. We discuss only SUCCESS,
  1133. TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
  1134. that apply (though RETURN and MERGE exist). We make a distinction
  1135. between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
  1136. A recoverable TRYAGAIN is almost always due to buffer size issues
  1137. and returns ERANGE in errno and the caller is expected to retry
  1138. with a larger buffer.
  1139. Lastly, you may be tempted to make significant changes to the
  1140. conditions in this code to bring about symmetry between responses.
  1141. Please don't change anything without due consideration for
  1142. expected application behaviour. Some of the synthesized responses
  1143. aren't very well thought out and sometimes appear to imply that
  1144. IPv4 responses are always answer 1, and IPv6 responses are always
  1145. answer 2, but that's not true (see the implementation of send_dg
  1146. and send_vc to see response can arrive in any order, particularly
  1147. for UDP). However, we expect it holds roughly enough of the time
  1148. that this code works, but certainly needs to be fixed to make this
  1149. a more robust implementation.
  1150. ----------------------------------------------
  1151. | Answer 1 Status / | Synthesized | Reason |
  1152. | Answer 2 Status | Status | |
  1153. |--------------------------------------------|
  1154. | SUCCESS/SUCCESS | SUCCESS | [1] |
  1155. | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
  1156. | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
  1157. | SUCCESS/NOTFOUND | SUCCESS | [1] |
  1158. | SUCCESS/UNAVAIL | SUCCESS | [1] |
  1159. | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
  1160. | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
  1161. | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
  1162. | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
  1163. | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
  1164. | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
  1165. | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
  1166. | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
  1167. | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
  1168. | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
  1169. | NOTFOUND/SUCCESS | SUCCESS | [3] |
  1170. | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
  1171. | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
  1172. | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
  1173. | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
  1174. | UNAVAIL/SUCCESS | UNAVAIL | [4] |
  1175. | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
  1176. | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
  1177. | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
  1178. | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
  1179. ----------------------------------------------
  1180. [1] If the first response is a success we return success.
  1181. This ignores the state of the second answer and in fact
  1182. incorrectly sets errno and h_errno to that of the second
  1183. answer. However because the response is a success we ignore
  1184. *errnop and *h_errnop (though that means you touched errno on
  1185. success). We are being conservative here and returning the
  1186. likely IPv4 response in the first answer as a success.
  1187. [2] If the first response is a recoverable TRYAGAIN we return
  1188. that instead of looking at the second response. The
  1189. expectation here is that we have failed to get an IPv4 response
  1190. and should retry both queries.
  1191. [3] If the first response was not a SUCCESS and the second
  1192. response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
  1193. or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
  1194. result from the second response, otherwise the first responses
  1195. status is used. Again we have some odd side-effects when the
  1196. second response is NOTFOUND because we overwrite *errnop and
  1197. *h_errnop that means that a first answer of NOTFOUND might see
  1198. its *errnop and *h_errnop values altered. Whether it matters
  1199. in practice that a first response NOTFOUND has the wrong
  1200. *errnop and *h_errnop is undecided.
  1201. [4] If the first response is UNAVAIL we return that instead of
  1202. looking at the second response. The expectation here is that
  1203. it will have failed similarly e.g. configuration failure.
  1204. [5] Testing this code is complicated by the fact that truncated
  1205. second response buffers might be returned as SUCCESS if the
  1206. first answer is a SUCCESS. To fix this we add symmetry to
  1207. TRYAGAIN with the second response. If the second response
  1208. is a recoverable error we now return TRYAGIN even if the first
  1209. response was SUCCESS. */
  1210. if (anslen1 > 0)
  1211. status = gaih_getanswer_slice(answer1, anslen1, qname,
  1212. &pat, &buffer, &buflen,
  1213. errnop, h_errnop, ttlp,
  1214. &first);
  1215. if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
  1216. || (status == NSS_STATUS_TRYAGAIN
  1217. /* We want to look at the second answer in case of an
  1218. NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
  1219. *h_errnop is NO_RECOVERY. If not, and if the failure was due to
  1220. an insufficient buffer (ERANGE), then we need to drop the results
  1221. and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
  1222. repeat the query with a larger buffer. */
  1223. && (*errnop != ERANGE || *h_errnop == NO_RECOVERY)))
  1224. && answer2 != NULL && anslen2 > 0)
  1225. {
  1226. enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
  1227. &pat, &buffer, &buflen,
  1228. errnop, h_errnop, ttlp,
  1229. &first);
  1230. /* Use the second response status in some cases. */
  1231. if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
  1232. status = status2;
  1233. /* Do not return a truncated second response (unless it was
  1234. unavoidable e.g. unrecoverable TRYAGAIN). */
  1235. if (status == NSS_STATUS_SUCCESS
  1236. && (status2 == NSS_STATUS_TRYAGAIN
  1237. && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
  1238. status = NSS_STATUS_TRYAGAIN;
  1239. }
  1240. return status;
  1241. }