dns-network.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 `getnetnamadr.c' from
  16. the bind package and it has the following copyright. */
  17. /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
  18. * Dep. Matematica Universidade de Coimbra, Portugal, Europe
  19. *
  20. * Permission to use, copy, modify, and distribute this software for any
  21. * purpose with or without fee is hereby granted, provided that the above
  22. * copyright notice and this permission notice appear in all copies.
  23. */
  24. /*
  25. * Copyright (c) 1983, 1993
  26. * The Regents of the University of California. All rights reserved.
  27. *
  28. * Redistribution and use in source and binary forms, with or without
  29. * modification, are permitted provided that the following conditions
  30. * are met:
  31. * 1. Redistributions of source code must retain the above copyright
  32. * notice, this list of conditions and the following disclaimer.
  33. * 2. Redistributions in binary form must reproduce the above copyright
  34. * notice, this list of conditions and the following disclaimer in the
  35. * documentation and/or other materials provided with the distribution.
  36. * 4. Neither the name of the University nor the names of its contributors
  37. * may be used to endorse or promote products derived from this software
  38. * without specific prior written permission.
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. */
  52. #include <ctype.h>
  53. #include <errno.h>
  54. #include <netdb.h>
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <stdint.h>
  59. #include <stddef.h>
  60. #include "nsswitch.h"
  61. #include <arpa/inet.h>
  62. #include <arpa/nameser.h>
  63. #include <resolv/resolv-internal.h>
  64. #include <resolv/resolv_context.h>
  65. /* Maximum number of aliases we allow. */
  66. #define MAX_NR_ALIASES 48
  67. #if PACKETSZ > 65536
  68. # define MAXPACKET PACKETSZ
  69. #else
  70. # define MAXPACKET 65536
  71. #endif
  72. typedef enum
  73. {
  74. BYADDR,
  75. BYNAME
  76. } lookup_method;
  77. /* We need this time later. */
  78. typedef union querybuf
  79. {
  80. HEADER hdr;
  81. u_char buf[MAXPACKET];
  82. } querybuf;
  83. /* Prototypes for local functions. */
  84. static enum nss_status getanswer_r (const querybuf *answer, int anslen,
  85. struct netent *result, char *buffer,
  86. size_t buflen, int *errnop, int *h_errnop,
  87. lookup_method net_i);
  88. enum nss_status
  89. _nss_dns_getnetbyname_r (const char *name, struct netent *result,
  90. char *buffer, size_t buflen, int *errnop,
  91. int *herrnop)
  92. {
  93. /* Return entry for network with NAME. */
  94. union
  95. {
  96. querybuf *buf;
  97. u_char *ptr;
  98. } net_buffer;
  99. querybuf *orig_net_buffer;
  100. int anslen;
  101. enum nss_status status;
  102. struct resolv_context *ctx = __resolv_context_get ();
  103. if (ctx == NULL)
  104. {
  105. *errnop = errno;
  106. *herrnop = NETDB_INTERNAL;
  107. return NSS_STATUS_UNAVAIL;
  108. }
  109. net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
  110. anslen = __res_context_search
  111. (ctx, name, C_IN, T_PTR, net_buffer.buf->buf,
  112. 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
  113. if (anslen < 0)
  114. {
  115. /* Nothing found. */
  116. *errnop = errno;
  117. if (net_buffer.buf != orig_net_buffer)
  118. free (net_buffer.buf);
  119. __resolv_context_put (ctx);
  120. return (errno == ECONNREFUSED
  121. || errno == EPFNOSUPPORT
  122. || errno == EAFNOSUPPORT)
  123. ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
  124. }
  125. status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen,
  126. errnop, herrnop, BYNAME);
  127. if (net_buffer.buf != orig_net_buffer)
  128. free (net_buffer.buf);
  129. __resolv_context_put (ctx);
  130. return status;
  131. }
  132. enum nss_status
  133. _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
  134. char *buffer, size_t buflen, int *errnop,
  135. int *herrnop)
  136. {
  137. /* Return entry for network with NAME. */
  138. enum nss_status status;
  139. union
  140. {
  141. querybuf *buf;
  142. u_char *ptr;
  143. } net_buffer;
  144. querybuf *orig_net_buffer;
  145. unsigned int net_bytes[4];
  146. char qbuf[MAXDNAME];
  147. int cnt, anslen;
  148. uint32_t net2;
  149. int olderr = errno;
  150. /* No net address lookup for IPv6 yet. */
  151. if (type != AF_INET)
  152. return NSS_STATUS_UNAVAIL;
  153. struct resolv_context *ctx = __resolv_context_get ();
  154. if (ctx == NULL)
  155. {
  156. *errnop = errno;
  157. *herrnop = NETDB_INTERNAL;
  158. return NSS_STATUS_UNAVAIL;
  159. }
  160. net2 = (uint32_t) net;
  161. for (cnt = 4; net2 != 0; net2 >>= 8)
  162. net_bytes[--cnt] = net2 & 0xff;
  163. switch (cnt)
  164. {
  165. case 3:
  166. /* Class A network. */
  167. sprintf (qbuf, "0.0.0.%u.in-addr.arpa", net_bytes[3]);
  168. break;
  169. case 2:
  170. /* Class B network. */
  171. sprintf (qbuf, "0.0.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2]);
  172. break;
  173. case 1:
  174. /* Class C network. */
  175. sprintf (qbuf, "0.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
  176. net_bytes[1]);
  177. break;
  178. case 0:
  179. /* Class D - E network. */
  180. sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
  181. net_bytes[1], net_bytes[0]);
  182. break;
  183. }
  184. net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
  185. anslen = __res_context_query (ctx, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
  186. 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
  187. if (anslen < 0)
  188. {
  189. /* Nothing found. */
  190. int err = errno;
  191. __set_errno (olderr);
  192. if (net_buffer.buf != orig_net_buffer)
  193. free (net_buffer.buf);
  194. __resolv_context_put (ctx);
  195. return (err == ECONNREFUSED
  196. || err == EPFNOSUPPORT
  197. || err == EAFNOSUPPORT)
  198. ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
  199. }
  200. status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen,
  201. errnop, herrnop, BYADDR);
  202. if (net_buffer.buf != orig_net_buffer)
  203. free (net_buffer.buf);
  204. if (status == NSS_STATUS_SUCCESS)
  205. {
  206. /* Strip trailing zeros. */
  207. unsigned int u_net = net; /* Maybe net should be unsigned? */
  208. while ((u_net & 0xff) == 0 && u_net != 0)
  209. u_net >>= 8;
  210. result->n_net = u_net;
  211. }
  212. __resolv_context_put (ctx);
  213. return status;
  214. }
  215. static enum nss_status
  216. getanswer_r (const querybuf *answer, int anslen, struct netent *result,
  217. char *buffer, size_t buflen, int *errnop, int *h_errnop,
  218. lookup_method net_i)
  219. {
  220. /*
  221. * Find first satisfactory answer
  222. *
  223. * answer --> +------------+ ( MESSAGE )
  224. * | Header |
  225. * +------------+
  226. * | Question | the question for the name server
  227. * +------------+
  228. * | Answer | RRs answering the question
  229. * +------------+
  230. * | Authority | RRs pointing toward an authority
  231. * | Additional | RRs holding additional information
  232. * +------------+
  233. */
  234. struct net_data
  235. {
  236. char *aliases[MAX_NR_ALIASES];
  237. char linebuffer[0];
  238. } *net_data;
  239. uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct net_data);
  240. buffer += pad;
  241. if (__glibc_unlikely (buflen < sizeof (*net_data) + pad))
  242. {
  243. /* The buffer is too small. */
  244. too_small:
  245. *errnop = ERANGE;
  246. *h_errnop = NETDB_INTERNAL;
  247. return NSS_STATUS_TRYAGAIN;
  248. }
  249. buflen -= pad;
  250. net_data = (struct net_data *) buffer;
  251. int linebuflen = buflen - offsetof (struct net_data, linebuffer);
  252. if (buflen - offsetof (struct net_data, linebuffer) != linebuflen)
  253. linebuflen = INT_MAX;
  254. const unsigned char *end_of_message = &answer->buf[anslen];
  255. const HEADER *header_pointer = &answer->hdr;
  256. /* #/records in the answer section. */
  257. int answer_count = ntohs (header_pointer->ancount);
  258. /* #/entries in the question section. */
  259. int question_count = ntohs (header_pointer->qdcount);
  260. char *bp = net_data->linebuffer;
  261. const unsigned char *cp = &answer->buf[HFIXEDSZ];
  262. char **alias_pointer;
  263. int have_answer;
  264. u_char packtmp[NS_MAXCDNAME];
  265. if (question_count == 0)
  266. {
  267. /* FIXME: the Sun version uses for host name lookup an additional
  268. parameter for pointing to h_errno. this is missing here.
  269. OSF/1 has a per-thread h_errno variable. */
  270. if (header_pointer->aa != 0)
  271. {
  272. __set_h_errno (HOST_NOT_FOUND);
  273. return NSS_STATUS_NOTFOUND;
  274. }
  275. else
  276. {
  277. __set_h_errno (TRY_AGAIN);
  278. return NSS_STATUS_TRYAGAIN;
  279. }
  280. }
  281. /* Skip the question part. */
  282. while (question_count-- > 0)
  283. {
  284. int n = __dn_skipname (cp, end_of_message);
  285. if (n < 0 || end_of_message - (cp + n) < QFIXEDSZ)
  286. {
  287. __set_h_errno (NO_RECOVERY);
  288. return NSS_STATUS_UNAVAIL;
  289. }
  290. cp += n + QFIXEDSZ;
  291. }
  292. alias_pointer = result->n_aliases = &net_data->aliases[0];
  293. *alias_pointer = NULL;
  294. have_answer = 0;
  295. while (--answer_count >= 0 && cp < end_of_message)
  296. {
  297. int n = __ns_name_unpack (answer->buf, end_of_message, cp,
  298. packtmp, sizeof packtmp);
  299. if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
  300. {
  301. if (errno == EMSGSIZE)
  302. goto too_small;
  303. n = -1;
  304. }
  305. if (n > 0 && bp[0] == '.')
  306. bp[0] = '\0';
  307. if (n < 0 || res_dnok (bp) == 0)
  308. break;
  309. cp += n;
  310. if (end_of_message - cp < 10)
  311. {
  312. __set_h_errno (NO_RECOVERY);
  313. return NSS_STATUS_UNAVAIL;
  314. }
  315. int type, class;
  316. GETSHORT (type, cp);
  317. GETSHORT (class, cp);
  318. cp += INT32SZ; /* TTL */
  319. uint16_t rdatalen;
  320. GETSHORT (rdatalen, cp);
  321. if (end_of_message - cp < rdatalen)
  322. {
  323. __set_h_errno (NO_RECOVERY);
  324. return NSS_STATUS_UNAVAIL;
  325. }
  326. if (class == C_IN && type == T_PTR)
  327. {
  328. n = __ns_name_unpack (answer->buf, end_of_message, cp,
  329. packtmp, sizeof packtmp);
  330. if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
  331. {
  332. if (errno == EMSGSIZE)
  333. goto too_small;
  334. n = -1;
  335. }
  336. if (n < 0 || !res_hnok (bp))
  337. {
  338. /* XXX What does this mean? The original form from bind
  339. returns NULL. Incrementing cp has no effect in any case.
  340. What should I return here. ??? */
  341. cp += n;
  342. return NSS_STATUS_UNAVAIL;
  343. }
  344. cp += rdatalen;
  345. if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
  346. {
  347. *alias_pointer++ = bp;
  348. n = strlen (bp) + 1;
  349. bp += n;
  350. linebuflen -= n;
  351. result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
  352. ++have_answer;
  353. }
  354. }
  355. else
  356. /* Skip over unknown record data. */
  357. cp += rdatalen;
  358. }
  359. if (have_answer)
  360. {
  361. *alias_pointer = NULL;
  362. switch (net_i)
  363. {
  364. case BYADDR:
  365. result->n_name = *result->n_aliases++;
  366. result->n_net = 0L;
  367. return NSS_STATUS_SUCCESS;
  368. case BYNAME:
  369. {
  370. char **ap;
  371. for (ap = result->n_aliases; *ap != NULL; ++ap)
  372. {
  373. /* Check each alias name for being of the forms:
  374. 4.3.2.1.in-addr.arpa = net 1.2.3.4
  375. 3.2.1.in-addr.arpa = net 0.1.2.3
  376. 2.1.in-addr.arpa = net 0.0.1.2
  377. 1.in-addr.arpa = net 0.0.0.1
  378. */
  379. uint32_t val = 0; /* Accumulator for n_net value. */
  380. unsigned int shift = 0; /* Which part we are parsing now. */
  381. const char *p = *ap; /* Consuming the string. */
  382. do
  383. {
  384. /* Match the leading 0 or 0[xX] base indicator. */
  385. unsigned int base = 10;
  386. if (*p == '0' && p[1] != '.')
  387. {
  388. base = 8;
  389. ++p;
  390. if (*p == 'x' || *p == 'X')
  391. {
  392. base = 16;
  393. ++p;
  394. if (*p == '.')
  395. break; /* No digit here. Give up on alias. */
  396. }
  397. if (*p == '\0')
  398. break;
  399. }
  400. uint32_t part = 0; /* Accumulates this part's number. */
  401. do
  402. {
  403. if (isdigit (*p) && (*p - '0' < base))
  404. part = (part * base) + (*p - '0');
  405. else if (base == 16 && isxdigit (*p))
  406. part = (part << 4) + 10 + (tolower (*p) - 'a');
  407. ++p;
  408. } while (*p != '\0' && *p != '.');
  409. if (*p != '.')
  410. break; /* Bad form. Give up on this name. */
  411. /* Install this as the next more significant byte. */
  412. val |= part << shift;
  413. shift += 8;
  414. ++p;
  415. /* If we are out of digits now, there are two cases:
  416. 1. We are done with digits and now see "in-addr.arpa".
  417. 2. This is not the droid we are looking for. */
  418. if (!isdigit (*p) && !strcasecmp (p, "in-addr.arpa"))
  419. {
  420. result->n_net = val;
  421. return NSS_STATUS_SUCCESS;
  422. }
  423. /* Keep going when we have seen fewer than 4 parts. */
  424. } while (shift < 32);
  425. }
  426. }
  427. break;
  428. }
  429. }
  430. __set_h_errno (TRY_AGAIN);
  431. return NSS_STATUS_TRYAGAIN;
  432. }