PageRenderTime 28ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/binutils-2.17/newlib/libc/sys/linux/net/res_query.c

https://bitbucket.org/pizzafactory/blackfin-toolchain
C | 424 lines | 257 code | 28 blank | 139 comment | 84 complexity | bff04e296a71ae5ab79970f33b31cfce MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, GPL-3.0, AGPL-1.0, LGPL-2.1
  1. /*
  2. * Copyright (c) 1988, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by the University of
  16. * California, Berkeley and its contributors.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. /*
  34. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  35. *
  36. * Permission to use, copy, modify, and distribute this software for any
  37. * purpose with or without fee is hereby granted, provided that the above
  38. * copyright notice and this permission notice appear in all copies, and that
  39. * the name of Digital Equipment Corporation not be used in advertising or
  40. * publicity pertaining to distribution of the document or software without
  41. * specific, written prior permission.
  42. *
  43. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  44. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  45. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  46. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  47. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  48. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  49. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  50. * SOFTWARE.
  51. */
  52. /*
  53. * Portions Copyright (c) 1996 by Internet Software Consortium.
  54. *
  55. * Permission to use, copy, modify, and distribute this software for any
  56. * purpose with or without fee is hereby granted, provided that the above
  57. * copyright notice and this permission notice appear in all copies.
  58. *
  59. * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
  60. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
  61. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
  62. * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  63. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  64. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  65. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  66. * SOFTWARE.
  67. */
  68. #if defined(LIBC_SCCS) && !defined(lint)
  69. static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
  70. static char orig_rcsid = "From: Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $";
  71. #endif /* LIBC_SCCS and not lint */
  72. #include <sys/cdefs.h>
  73. #include <sys/types.h>
  74. #include <sys/types.h>
  75. #include <sys/param.h>
  76. #include <netinet/in.h>
  77. #include <arpa/inet.h>
  78. #include <arpa/nameser.h>
  79. #include <ctype.h>
  80. #include <errno.h>
  81. #include <netdb.h>
  82. #include <resolv.h>
  83. #include <stdio.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86. #include "res_config.h"
  87. #if PACKETSZ > 1024
  88. #define MAXPACKET PACKETSZ
  89. #else
  90. #define MAXPACKET 1024
  91. #endif
  92. /*
  93. * Formulate a normal query, send, and await answer.
  94. * Returned answer is placed in supplied buffer "answer".
  95. * Perform preliminary check of answer, returning success only
  96. * if no error is indicated and the answer count is nonzero.
  97. * Return the size of the response on success, -1 on error.
  98. * Error number is left in h_errno.
  99. *
  100. * Caller must parse answer and determine whether it answers the question.
  101. */
  102. int
  103. res_query(name, class, type, answer, anslen)
  104. const char *name; /* domain name */
  105. int class, type; /* class and type of query */
  106. u_char *answer; /* buffer to put answer */
  107. int anslen; /* size of answer buffer */
  108. {
  109. u_char buf[MAXPACKET];
  110. HEADER *hp = (HEADER *) answer;
  111. int n;
  112. hp->rcode = NOERROR; /* default */
  113. if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
  114. h_errno = NETDB_INTERNAL;
  115. return (-1);
  116. }
  117. #ifdef DEBUG
  118. if (_res.options & RES_DEBUG)
  119. printf(";; res_query(%s, %d, %d)\n", name, class, type);
  120. #endif
  121. n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
  122. buf, sizeof(buf));
  123. if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
  124. n = res_opt(n, buf, sizeof(buf), anslen);
  125. if (n <= 0) {
  126. #ifdef DEBUG
  127. if (_res.options & RES_DEBUG)
  128. printf(";; res_query: mkquery failed\n");
  129. #endif
  130. h_errno = NO_RECOVERY;
  131. return (n);
  132. }
  133. n = res_send(buf, n, answer, anslen);
  134. if (n < 0) {
  135. #ifdef DEBUG
  136. if (_res.options & RES_DEBUG)
  137. printf(";; res_query: send error\n");
  138. #endif
  139. h_errno = TRY_AGAIN;
  140. return (n);
  141. }
  142. if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  143. #ifdef DEBUG
  144. if (_res.options & RES_DEBUG)
  145. printf(";; rcode = %d, ancount=%d\n", hp->rcode,
  146. ntohs(hp->ancount));
  147. #endif
  148. switch (hp->rcode) {
  149. case NXDOMAIN:
  150. h_errno = HOST_NOT_FOUND;
  151. break;
  152. case SERVFAIL:
  153. h_errno = TRY_AGAIN;
  154. break;
  155. case NOERROR:
  156. h_errno = NO_DATA;
  157. break;
  158. case FORMERR:
  159. case NOTIMP:
  160. case REFUSED:
  161. default:
  162. h_errno = NO_RECOVERY;
  163. break;
  164. }
  165. return (-1);
  166. }
  167. return (n);
  168. }
  169. /*
  170. * Formulate a normal query, send, and retrieve answer in supplied buffer.
  171. * Return the size of the response on success, -1 on error.
  172. * If enabled, implement search rules until answer or unrecoverable failure
  173. * is detected. Error code, if any, is left in h_errno.
  174. */
  175. int
  176. res_search(name, class, type, answer, anslen)
  177. const char *name; /* domain name */
  178. int class, type; /* class and type of query */
  179. u_char *answer; /* buffer to put answer */
  180. int anslen; /* size of answer */
  181. {
  182. const char *cp, * const *domain;
  183. HEADER *hp = (HEADER *) answer;
  184. u_int dots;
  185. int trailing_dot, ret, saved_herrno;
  186. int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
  187. if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
  188. h_errno = NETDB_INTERNAL;
  189. return (-1);
  190. }
  191. errno = 0;
  192. h_errno = HOST_NOT_FOUND; /* default, if we never query */
  193. dots = 0;
  194. for (cp = name; *cp; cp++)
  195. dots += (*cp == '.');
  196. trailing_dot = 0;
  197. if (cp > name && *--cp == '.')
  198. trailing_dot++;
  199. /* If there aren't any dots, it could be a user-level alias */
  200. if (!dots && (cp = hostalias(name)) != NULL)
  201. return (res_query(cp, class, type, answer, anslen));
  202. /*
  203. * If there are dots in the name already, let's just give it a try
  204. * 'as is'. The threshold can be set with the "ndots" option.
  205. */
  206. saved_herrno = -1;
  207. if (dots >= _res.ndots) {
  208. ret = res_querydomain(name, NULL, class, type, answer, anslen);
  209. if (ret > 0)
  210. return (ret);
  211. saved_herrno = h_errno;
  212. tried_as_is++;
  213. }
  214. /*
  215. * We do at least one level of search if
  216. * - there is no dot and RES_DEFNAME is set, or
  217. * - there is at least one dot, there is no trailing dot,
  218. * and RES_DNSRCH is set.
  219. */
  220. if ((!dots && (_res.options & RES_DEFNAMES)) ||
  221. (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
  222. int done = 0;
  223. for (domain = (const char * const *)_res.dnsrch;
  224. *domain && !done;
  225. domain++) {
  226. ret = res_querydomain(name, *domain, class, type,
  227. answer, anslen);
  228. if (ret > 0)
  229. return (ret);
  230. /*
  231. * If no server present, give up.
  232. * If name isn't found in this domain,
  233. * keep trying higher domains in the search list
  234. * (if that's enabled).
  235. * On a NO_DATA error, keep trying, otherwise
  236. * a wildcard entry of another type could keep us
  237. * from finding this entry higher in the domain.
  238. * If we get some other error (negative answer or
  239. * server failure), then stop searching up,
  240. * but try the input name below in case it's
  241. * fully-qualified.
  242. */
  243. if (errno == ECONNREFUSED) {
  244. h_errno = TRY_AGAIN;
  245. return (-1);
  246. }
  247. switch (h_errno) {
  248. case NO_DATA:
  249. got_nodata++;
  250. /* FALLTHROUGH */
  251. case HOST_NOT_FOUND:
  252. /* keep trying */
  253. break;
  254. case TRY_AGAIN:
  255. if (hp->rcode == SERVFAIL) {
  256. /* try next search element, if any */
  257. got_servfail++;
  258. break;
  259. }
  260. /* FALLTHROUGH */
  261. default:
  262. /* anything else implies that we're done */
  263. done++;
  264. }
  265. /* if we got here for some reason other than DNSRCH,
  266. * we only wanted one iteration of the loop, so stop.
  267. */
  268. if (!(_res.options & RES_DNSRCH))
  269. done++;
  270. }
  271. }
  272. /*
  273. * If we have not already tried the name "as is", do that now.
  274. * note that we do this regardless of how many dots were in the
  275. * name or whether it ends with a dot unless NOTLDQUERY is set.
  276. */
  277. if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
  278. ret = res_querydomain(name, NULL, class, type, answer, anslen);
  279. if (ret > 0)
  280. return (ret);
  281. }
  282. /* if we got here, we didn't satisfy the search.
  283. * if we did an initial full query, return that query's h_errno
  284. * (note that we wouldn't be here if that query had succeeded).
  285. * else if we ever got a nodata, send that back as the reason.
  286. * else send back meaningless h_errno, that being the one from
  287. * the last DNSRCH we did.
  288. */
  289. if (saved_herrno != -1)
  290. h_errno = saved_herrno;
  291. else if (got_nodata)
  292. h_errno = NO_DATA;
  293. else if (got_servfail)
  294. h_errno = TRY_AGAIN;
  295. return (-1);
  296. }
  297. /*
  298. * Perform a call on res_query on the concatenation of name and domain,
  299. * removing a trailing dot from name if domain is NULL.
  300. */
  301. int
  302. res_querydomain(name, domain, class, type, answer, anslen)
  303. const char *name, *domain;
  304. int class, type; /* class and type of query */
  305. u_char *answer; /* buffer to put answer */
  306. int anslen; /* size of answer */
  307. {
  308. char nbuf[MAXDNAME];
  309. const char *longname = nbuf;
  310. int n, d;
  311. if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
  312. h_errno = NETDB_INTERNAL;
  313. return (-1);
  314. }
  315. #ifdef DEBUG
  316. if (_res.options & RES_DEBUG)
  317. printf(";; res_querydomain(%s, %s, %d, %d)\n",
  318. name, domain?domain:"<Nil>", class, type);
  319. #endif
  320. if (domain == NULL) {
  321. /*
  322. * Check for trailing '.';
  323. * copy without '.' if present.
  324. */
  325. n = strlen(name);
  326. if (n >= MAXDNAME) {
  327. h_errno = NO_RECOVERY;
  328. return (-1);
  329. }
  330. n--;
  331. if (n >= 0 && name[n] == '.') {
  332. strncpy(nbuf, name, n);
  333. nbuf[n] = '\0';
  334. } else
  335. longname = name;
  336. } else {
  337. n = strlen(name);
  338. d = strlen(domain);
  339. if (n + d + 1 >= MAXDNAME) {
  340. h_errno = NO_RECOVERY;
  341. return (-1);
  342. }
  343. sprintf(nbuf, "%s.%s", name, domain);
  344. }
  345. return (res_query(longname, class, type, answer, anslen));
  346. }
  347. const char *
  348. hostalias(name)
  349. const char *name;
  350. {
  351. char *cp1, *cp2;
  352. FILE *fp;
  353. char *file;
  354. char buf[BUFSIZ];
  355. static char abuf[MAXDNAME];
  356. if (_res.options & RES_NOALIASES)
  357. return (NULL);
  358. if (issetugid())
  359. return (NULL);
  360. file = getenv("HOSTALIASES");
  361. if (file == NULL || (fp = fopen(file, "r")) == NULL)
  362. return (NULL);
  363. setbuf(fp, NULL);
  364. buf[sizeof(buf) - 1] = '\0';
  365. while (fgets(buf, sizeof(buf), fp)) {
  366. for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1)
  367. ;
  368. if (!*cp1)
  369. break;
  370. *cp1 = '\0';
  371. if (!strcasecmp(buf, name)) {
  372. while (isspace((unsigned char)*++cp1))
  373. ;
  374. if (!*cp1)
  375. break;
  376. for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2)
  377. ;
  378. abuf[sizeof(abuf) - 1] = *cp2 = '\0';
  379. strncpy(abuf, cp1, sizeof(abuf) - 1);
  380. fclose(fp);
  381. return (abuf);
  382. }
  383. }
  384. fclose(fp);
  385. return (NULL);
  386. }
  387. /*
  388. * Weak aliases for applications that use certain private entry points,
  389. * and fail to include <resolv.h>.
  390. */
  391. #undef res_query
  392. __weak_reference(__res_query, res_query);
  393. #undef res_search
  394. __weak_reference(__res_search, res_search);
  395. #undef res_querydomain
  396. __weak_reference(__res_querydomain, res_querydomain);