PageRenderTime 83ms CodeModel.GetById 48ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/libc/resolv/res_debug.c

https://github.com/okuoku/freebsd-head
C | 1229 lines | 901 code | 155 blank | 173 comment | 222 complexity | fae41d838fd1cc06af17e57278b3a4c6 MD5 | raw file
  1. /*
  2. * Copyright (c) 1985
  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. * 4. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  31. *
  32. * Permission to use, copy, modify, and distribute this software for any
  33. * purpose with or without fee is hereby granted, provided that the above
  34. * copyright notice and this permission notice appear in all copies, and that
  35. * the name of Digital Equipment Corporation not be used in advertising or
  36. * publicity pertaining to distribution of the document or software without
  37. * specific, written prior permission.
  38. *
  39. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  40. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  41. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  42. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  43. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  44. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  45. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  46. * SOFTWARE.
  47. */
  48. /*
  49. * Portions Copyright (c) 1995 by International Business Machines, Inc.
  50. *
  51. * International Business Machines, Inc. (hereinafter called IBM) grants
  52. * permission under its copyrights to use, copy, modify, and distribute this
  53. * Software with or without fee, provided that the above copyright notice and
  54. * all paragraphs of this notice appear in all copies, and that the name of IBM
  55. * not be used in connection with the marketing of any product incorporating
  56. * the Software or modifications thereof, without specific, written prior
  57. * permission.
  58. *
  59. * To the extent it has a right to do so, IBM grants an immunity from suit
  60. * under its patents, if any, for the use, sale or manufacture of products to
  61. * the extent that such products are used for performing Domain Name System
  62. * dynamic updates in TCP/IP networks by means of the Software. No immunity is
  63. * granted for any product per se or for any other function of any product.
  64. *
  65. * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
  66. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  67. * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
  68. * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
  69. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
  70. * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
  71. */
  72. /*
  73. * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  74. * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
  75. *
  76. * Permission to use, copy, modify, and distribute this software for any
  77. * purpose with or without fee is hereby granted, provided that the above
  78. * copyright notice and this permission notice appear in all copies.
  79. *
  80. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
  81. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  82. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
  83. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  84. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  85. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  86. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  87. */
  88. #if defined(LIBC_SCCS) && !defined(lint)
  89. static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
  90. static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.6 2008/04/03 23:15:15 marka Exp $";
  91. #endif /* LIBC_SCCS and not lint */
  92. #include <sys/cdefs.h>
  93. __FBSDID("$FreeBSD$");
  94. #include "port_before.h"
  95. #include <sys/types.h>
  96. #include <sys/param.h>
  97. #include <sys/socket.h>
  98. #include <netinet/in.h>
  99. #include <arpa/inet.h>
  100. #include <arpa/nameser.h>
  101. #include <ctype.h>
  102. #include <errno.h>
  103. #include <math.h>
  104. #include <netdb.h>
  105. #include <resolv.h>
  106. #include <resolv_mt.h>
  107. #include <stdio.h>
  108. #include <stdlib.h>
  109. #include <string.h>
  110. #include <time.h>
  111. #include "port_after.h"
  112. #ifdef SPRINTF_CHAR
  113. # define SPRINTF(x) strlen(sprintf/**/x)
  114. #else
  115. # define SPRINTF(x) sprintf x
  116. #endif
  117. extern const char *_res_opcodes[];
  118. extern const char *_res_sectioncodes[];
  119. /*%
  120. * Print the current options.
  121. */
  122. void
  123. fp_resstat(const res_state statp, FILE *file) {
  124. u_long mask;
  125. fprintf(file, ";; res options:");
  126. for (mask = 1; mask != 0U; mask <<= 1)
  127. if (statp->options & mask)
  128. fprintf(file, " %s", p_option(mask));
  129. putc('\n', file);
  130. }
  131. static void
  132. do_section(const res_state statp,
  133. ns_msg *handle, ns_sect section,
  134. int pflag, FILE *file)
  135. {
  136. int n, sflag, rrnum;
  137. static int buflen = 2048;
  138. char *buf;
  139. ns_opcode opcode;
  140. ns_rr rr;
  141. /*
  142. * Print answer records.
  143. */
  144. sflag = (statp->pfcode & pflag);
  145. if (statp->pfcode && !sflag)
  146. return;
  147. buf = malloc(buflen);
  148. if (buf == NULL) {
  149. fprintf(file, ";; memory allocation failure\n");
  150. return;
  151. }
  152. opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
  153. rrnum = 0;
  154. for (;;) {
  155. if (ns_parserr(handle, section, rrnum, &rr)) {
  156. if (errno != ENODEV)
  157. fprintf(file, ";; ns_parserr: %s\n",
  158. strerror(errno));
  159. else if (rrnum > 0 && sflag != 0 &&
  160. (statp->pfcode & RES_PRF_HEAD1))
  161. putc('\n', file);
  162. goto cleanup;
  163. }
  164. if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
  165. fprintf(file, ";; %s SECTION:\n",
  166. p_section(section, opcode));
  167. if (section == ns_s_qd)
  168. fprintf(file, ";;\t%s, type = %s, class = %s\n",
  169. ns_rr_name(rr),
  170. p_type(ns_rr_type(rr)),
  171. p_class(ns_rr_class(rr)));
  172. else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
  173. u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
  174. u_int32_t ttl = ns_rr_ttl(rr);
  175. fprintf(file,
  176. "; EDNS: version: %u, udp=%u, flags=%04x\n",
  177. (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
  178. while (rdatalen >= 4) {
  179. const u_char *cp = ns_rr_rdata(rr);
  180. int i;
  181. GETSHORT(optcode, cp);
  182. GETSHORT(optlen, cp);
  183. if (optcode == NS_OPT_NSID) {
  184. fputs("; NSID: ", file);
  185. if (optlen == 0) {
  186. fputs("; NSID\n", file);
  187. } else {
  188. fputs("; NSID: ", file);
  189. for (i = 0; i < optlen; i++)
  190. fprintf(file, "%02x ",
  191. cp[i]);
  192. fputs(" (",file);
  193. for (i = 0; i < optlen; i++)
  194. fprintf(file, "%c",
  195. isprint(cp[i])?
  196. cp[i] : '.');
  197. fputs(")\n", file);
  198. }
  199. } else {
  200. if (optlen == 0) {
  201. fprintf(file, "; OPT=%u\n",
  202. optcode);
  203. } else {
  204. fprintf(file, "; OPT=%u: ",
  205. optcode);
  206. for (i = 0; i < optlen; i++)
  207. fprintf(file, "%02x ",
  208. cp[i]);
  209. fputs(" (",file);
  210. for (i = 0; i < optlen; i++)
  211. fprintf(file, "%c",
  212. isprint(cp[i]) ?
  213. cp[i] : '.');
  214. fputs(")\n", file);
  215. }
  216. }
  217. rdatalen -= 4 + optlen;
  218. }
  219. } else {
  220. n = ns_sprintrr(handle, &rr, NULL, NULL,
  221. buf, buflen);
  222. if (n < 0) {
  223. if (errno == ENOSPC) {
  224. free(buf);
  225. buf = NULL;
  226. if (buflen < 131072)
  227. buf = malloc(buflen += 1024);
  228. if (buf == NULL) {
  229. fprintf(file,
  230. ";; memory allocation failure\n");
  231. return;
  232. }
  233. continue;
  234. }
  235. fprintf(file, ";; ns_sprintrr: %s\n",
  236. strerror(errno));
  237. goto cleanup;
  238. }
  239. fputs(buf, file);
  240. fputc('\n', file);
  241. }
  242. rrnum++;
  243. }
  244. cleanup:
  245. if (buf != NULL)
  246. free(buf);
  247. }
  248. /*%
  249. * Print the contents of a query.
  250. * This is intended to be primarily a debugging routine.
  251. */
  252. void
  253. res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
  254. ns_msg handle;
  255. int qdcount, ancount, nscount, arcount;
  256. u_int opcode, rcode, id;
  257. if (ns_initparse(msg, len, &handle) < 0) {
  258. fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
  259. return;
  260. }
  261. opcode = ns_msg_getflag(handle, ns_f_opcode);
  262. rcode = ns_msg_getflag(handle, ns_f_rcode);
  263. id = ns_msg_id(handle);
  264. qdcount = ns_msg_count(handle, ns_s_qd);
  265. ancount = ns_msg_count(handle, ns_s_an);
  266. nscount = ns_msg_count(handle, ns_s_ns);
  267. arcount = ns_msg_count(handle, ns_s_ar);
  268. /*
  269. * Print header fields.
  270. */
  271. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
  272. fprintf(file,
  273. ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
  274. _res_opcodes[opcode], p_rcode(rcode), id);
  275. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
  276. putc(';', file);
  277. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
  278. fprintf(file, "; flags:");
  279. if (ns_msg_getflag(handle, ns_f_qr))
  280. fprintf(file, " qr");
  281. if (ns_msg_getflag(handle, ns_f_aa))
  282. fprintf(file, " aa");
  283. if (ns_msg_getflag(handle, ns_f_tc))
  284. fprintf(file, " tc");
  285. if (ns_msg_getflag(handle, ns_f_rd))
  286. fprintf(file, " rd");
  287. if (ns_msg_getflag(handle, ns_f_ra))
  288. fprintf(file, " ra");
  289. if (ns_msg_getflag(handle, ns_f_z))
  290. fprintf(file, " ??");
  291. if (ns_msg_getflag(handle, ns_f_ad))
  292. fprintf(file, " ad");
  293. if (ns_msg_getflag(handle, ns_f_cd))
  294. fprintf(file, " cd");
  295. }
  296. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
  297. fprintf(file, "; %s: %d",
  298. p_section(ns_s_qd, opcode), qdcount);
  299. fprintf(file, ", %s: %d",
  300. p_section(ns_s_an, opcode), ancount);
  301. fprintf(file, ", %s: %d",
  302. p_section(ns_s_ns, opcode), nscount);
  303. fprintf(file, ", %s: %d",
  304. p_section(ns_s_ar, opcode), arcount);
  305. }
  306. if ((!statp->pfcode) || (statp->pfcode &
  307. (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
  308. putc('\n',file);
  309. }
  310. /*
  311. * Print the various sections.
  312. */
  313. do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
  314. do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
  315. do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
  316. do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
  317. if (qdcount == 0 && ancount == 0 &&
  318. nscount == 0 && arcount == 0)
  319. putc('\n', file);
  320. }
  321. const u_char *
  322. p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
  323. char name[MAXDNAME];
  324. int n;
  325. if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
  326. return (NULL);
  327. if (name[0] == '\0')
  328. putc('.', file);
  329. else
  330. fputs(name, file);
  331. return (cp + n);
  332. }
  333. const u_char *
  334. p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
  335. return (p_cdnname(cp, msg, PACKETSZ, file));
  336. }
  337. /*%
  338. * Return a fully-qualified domain name from a compressed name (with
  339. length supplied). */
  340. const u_char *
  341. p_fqnname(cp, msg, msglen, name, namelen)
  342. const u_char *cp, *msg;
  343. int msglen;
  344. char *name;
  345. int namelen;
  346. {
  347. int n, newlen;
  348. if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
  349. return (NULL);
  350. newlen = strlen(name);
  351. if (newlen == 0 || name[newlen - 1] != '.') {
  352. if (newlen + 1 >= namelen) /*%< Lack space for final dot */
  353. return (NULL);
  354. else
  355. strcpy(name + newlen, ".");
  356. }
  357. return (cp + n);
  358. }
  359. /* XXX: the rest of these functions need to become length-limited, too. */
  360. const u_char *
  361. p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
  362. char name[MAXDNAME];
  363. const u_char *n;
  364. n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
  365. if (n == NULL)
  366. return (NULL);
  367. fputs(name, file);
  368. return (n);
  369. }
  370. /*%
  371. * Names of RR classes and qclasses. Classes and qclasses are the same, except
  372. * that C_ANY is a qclass but not a class. (You can ask for records of class
  373. * C_ANY, but you can't have any records of that class in the database.)
  374. */
  375. const struct res_sym __p_class_syms[] = {
  376. {C_IN, "IN", (char *)0},
  377. {C_CHAOS, "CH", (char *)0},
  378. {C_CHAOS, "CHAOS", (char *)0},
  379. {C_HS, "HS", (char *)0},
  380. {C_HS, "HESIOD", (char *)0},
  381. {C_ANY, "ANY", (char *)0},
  382. {C_NONE, "NONE", (char *)0},
  383. {C_IN, (char *)0, (char *)0}
  384. };
  385. /*%
  386. * Names of message sections.
  387. */
  388. static const struct res_sym __p_default_section_syms[] = {
  389. {ns_s_qd, "QUERY", (char *)0},
  390. {ns_s_an, "ANSWER", (char *)0},
  391. {ns_s_ns, "AUTHORITY", (char *)0},
  392. {ns_s_ar, "ADDITIONAL", (char *)0},
  393. {0, (char *)0, (char *)0}
  394. };
  395. static const struct res_sym __p_update_section_syms[] = {
  396. {S_ZONE, "ZONE", (char *)0},
  397. {S_PREREQ, "PREREQUISITE", (char *)0},
  398. {S_UPDATE, "UPDATE", (char *)0},
  399. {S_ADDT, "ADDITIONAL", (char *)0},
  400. {0, (char *)0, (char *)0}
  401. };
  402. const struct res_sym __p_key_syms[] = {
  403. {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
  404. {NS_ALG_DH, "DH", "Diffie Hellman"},
  405. {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
  406. {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
  407. {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
  408. {0, NULL, NULL}
  409. };
  410. const struct res_sym __p_cert_syms[] = {
  411. {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
  412. {cert_t_spki, "SPKI", "SPKI certificate"},
  413. {cert_t_pgp, "PGP", "PGP certificate"},
  414. {cert_t_url, "URL", "URL Private"},
  415. {cert_t_oid, "OID", "OID Private"},
  416. {0, NULL, NULL}
  417. };
  418. /*%
  419. * Names of RR types and qtypes. Types and qtypes are the same, except
  420. * that T_ANY is a qtype but not a type. (You can ask for records of type
  421. * T_ANY, but you can't have any records of that type in the database.)
  422. */
  423. const struct res_sym __p_type_syms[] = {
  424. {ns_t_a, "A", "address"},
  425. {ns_t_ns, "NS", "name server"},
  426. {ns_t_md, "MD", "mail destination (deprecated)"},
  427. {ns_t_mf, "MF", "mail forwarder (deprecated)"},
  428. {ns_t_cname, "CNAME", "canonical name"},
  429. {ns_t_soa, "SOA", "start of authority"},
  430. {ns_t_mb, "MB", "mailbox"},
  431. {ns_t_mg, "MG", "mail group member"},
  432. {ns_t_mr, "MR", "mail rename"},
  433. {ns_t_null, "NULL", "null"},
  434. {ns_t_wks, "WKS", "well-known service (deprecated)"},
  435. {ns_t_ptr, "PTR", "domain name pointer"},
  436. {ns_t_hinfo, "HINFO", "host information"},
  437. {ns_t_minfo, "MINFO", "mailbox information"},
  438. {ns_t_mx, "MX", "mail exchanger"},
  439. {ns_t_txt, "TXT", "text"},
  440. {ns_t_rp, "RP", "responsible person"},
  441. {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
  442. {ns_t_x25, "X25", "X25 address"},
  443. {ns_t_isdn, "ISDN", "ISDN address"},
  444. {ns_t_rt, "RT", "router"},
  445. {ns_t_nsap, "NSAP", "nsap address"},
  446. {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
  447. {ns_t_sig, "SIG", "signature"},
  448. {ns_t_key, "KEY", "key"},
  449. {ns_t_px, "PX", "mapping information"},
  450. {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
  451. {ns_t_aaaa, "AAAA", "IPv6 address"},
  452. {ns_t_loc, "LOC", "location"},
  453. {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
  454. {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
  455. {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
  456. {ns_t_srv, "SRV", "server selection"},
  457. {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
  458. {ns_t_tkey, "TKEY", "tkey"},
  459. {ns_t_tsig, "TSIG", "transaction signature"},
  460. {ns_t_ixfr, "IXFR", "incremental zone transfer"},
  461. {ns_t_axfr, "AXFR", "zone transfer"},
  462. {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
  463. {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
  464. {ns_t_maila, "MAILA", "mail agent (deprecated)"},
  465. {ns_t_naptr, "NAPTR", "URN Naming Authority"},
  466. {ns_t_kx, "KX", "Key Exchange"},
  467. {ns_t_cert, "CERT", "Certificate"},
  468. {ns_t_a6, "A6", "IPv6 Address"},
  469. {ns_t_dname, "DNAME", "dname"},
  470. {ns_t_sink, "SINK", "Kitchen Sink (experimental)"},
  471. {ns_t_opt, "OPT", "EDNS Options"},
  472. {ns_t_any, "ANY", "\"any\""},
  473. {0, NULL, NULL}
  474. };
  475. /*%
  476. * Names of DNS rcodes.
  477. */
  478. const struct res_sym __p_rcode_syms[] = {
  479. {ns_r_noerror, "NOERROR", "no error"},
  480. {ns_r_formerr, "FORMERR", "format error"},
  481. {ns_r_servfail, "SERVFAIL", "server failed"},
  482. {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
  483. {ns_r_notimpl, "NOTIMP", "not implemented"},
  484. {ns_r_refused, "REFUSED", "refused"},
  485. {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
  486. {ns_r_yxrrset, "YXRRSET", "rrset exists"},
  487. {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
  488. {ns_r_notauth, "NOTAUTH", "not authoritative"},
  489. {ns_r_notzone, "NOTZONE", "Not in zone"},
  490. {ns_r_max, "", ""},
  491. {ns_r_badsig, "BADSIG", "bad signature"},
  492. {ns_r_badkey, "BADKEY", "bad key"},
  493. {ns_r_badtime, "BADTIME", "bad time"},
  494. {0, NULL, NULL}
  495. };
  496. int
  497. sym_ston(const struct res_sym *syms, const char *name, int *success) {
  498. for ((void)NULL; syms->name != 0; syms++) {
  499. if (strcasecmp (name, syms->name) == 0) {
  500. if (success)
  501. *success = 1;
  502. return (syms->number);
  503. }
  504. }
  505. if (success)
  506. *success = 0;
  507. return (syms->number); /*%< The default value. */
  508. }
  509. const char *
  510. sym_ntos(const struct res_sym *syms, int number, int *success) {
  511. char *unname = sym_ntos_unname;
  512. for ((void)NULL; syms->name != 0; syms++) {
  513. if (number == syms->number) {
  514. if (success)
  515. *success = 1;
  516. return (syms->name);
  517. }
  518. }
  519. sprintf(unname, "%d", number); /*%< XXX nonreentrant */
  520. if (success)
  521. *success = 0;
  522. return (unname);
  523. }
  524. const char *
  525. sym_ntop(const struct res_sym *syms, int number, int *success) {
  526. char *unname = sym_ntop_unname;
  527. for ((void)NULL; syms->name != 0; syms++) {
  528. if (number == syms->number) {
  529. if (success)
  530. *success = 1;
  531. return (syms->humanname);
  532. }
  533. }
  534. sprintf(unname, "%d", number); /*%< XXX nonreentrant */
  535. if (success)
  536. *success = 0;
  537. return (unname);
  538. }
  539. /*%
  540. * Return a string for the type.
  541. */
  542. const char *
  543. p_type(int type) {
  544. int success;
  545. const char *result;
  546. static char typebuf[20];
  547. result = sym_ntos(__p_type_syms, type, &success);
  548. if (success)
  549. return (result);
  550. if (type < 0 || type > 0xffff)
  551. return ("BADTYPE");
  552. sprintf(typebuf, "TYPE%d", type);
  553. return (typebuf);
  554. }
  555. /*%
  556. * Return a string for the type.
  557. */
  558. const char *
  559. p_section(int section, int opcode) {
  560. const struct res_sym *symbols;
  561. switch (opcode) {
  562. case ns_o_update:
  563. symbols = __p_update_section_syms;
  564. break;
  565. default:
  566. symbols = __p_default_section_syms;
  567. break;
  568. }
  569. return (sym_ntos(symbols, section, (int *)0));
  570. }
  571. /*%
  572. * Return a mnemonic for class.
  573. */
  574. const char *
  575. p_class(int class) {
  576. int success;
  577. const char *result;
  578. static char classbuf[20];
  579. result = sym_ntos(__p_class_syms, class, &success);
  580. if (success)
  581. return (result);
  582. if (class < 0 || class > 0xffff)
  583. return ("BADCLASS");
  584. sprintf(classbuf, "CLASS%d", class);
  585. return (classbuf);
  586. }
  587. /*%
  588. * Return a mnemonic for an option
  589. */
  590. const char *
  591. p_option(u_long option) {
  592. char *nbuf = p_option_nbuf;
  593. switch (option) {
  594. case RES_INIT: return "init";
  595. case RES_DEBUG: return "debug";
  596. case RES_AAONLY: return "aaonly(unimpl)";
  597. case RES_USEVC: return "usevc";
  598. case RES_PRIMARY: return "primry(unimpl)";
  599. case RES_IGNTC: return "igntc";
  600. case RES_RECURSE: return "recurs";
  601. case RES_DEFNAMES: return "defnam";
  602. case RES_STAYOPEN: return "styopn";
  603. case RES_DNSRCH: return "dnsrch";
  604. case RES_INSECURE1: return "insecure1";
  605. case RES_INSECURE2: return "insecure2";
  606. case RES_NOALIASES: return "noaliases";
  607. case RES_USE_INET6: return "inet6";
  608. #ifdef RES_USE_EDNS0 /*%< KAME extension */
  609. case RES_USE_EDNS0: return "edns0";
  610. case RES_NSID: return "nsid";
  611. #endif
  612. #ifdef RES_USE_DNAME
  613. case RES_USE_DNAME: return "dname";
  614. #endif
  615. #ifdef RES_USE_DNSSEC
  616. case RES_USE_DNSSEC: return "dnssec";
  617. #endif
  618. #ifdef RES_NOTLDQUERY
  619. case RES_NOTLDQUERY: return "no-tld-query";
  620. #endif
  621. #ifdef RES_NO_NIBBLE2
  622. case RES_NO_NIBBLE2: return "no-nibble2";
  623. #endif
  624. /* XXX nonreentrant */
  625. default: sprintf(nbuf, "?0x%lx?", (u_long)option);
  626. return (nbuf);
  627. }
  628. }
  629. /*%
  630. * Return a mnemonic for a time to live.
  631. */
  632. const char *
  633. p_time(u_int32_t value) {
  634. char *nbuf = p_time_nbuf;
  635. if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
  636. sprintf(nbuf, "%u", value);
  637. return (nbuf);
  638. }
  639. /*%
  640. * Return a string for the rcode.
  641. */
  642. const char *
  643. p_rcode(int rcode) {
  644. return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
  645. }
  646. /*%
  647. * Return a string for a res_sockaddr_union.
  648. */
  649. const char *
  650. p_sockun(union res_sockaddr_union u, char *buf, size_t size) {
  651. char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"];
  652. switch (u.sin.sin_family) {
  653. case AF_INET:
  654. inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret);
  655. break;
  656. #ifdef HAS_INET6_STRUCTS
  657. case AF_INET6:
  658. inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret);
  659. break;
  660. #endif
  661. default:
  662. sprintf(ret, "[af%d]", u.sin.sin_family);
  663. break;
  664. }
  665. if (size > 0U) {
  666. strncpy(buf, ret, size - 1);
  667. buf[size - 1] = '0';
  668. }
  669. return (buf);
  670. }
  671. /*%
  672. * routines to convert between on-the-wire RR format and zone file format.
  673. * Does not contain conversion to/from decimal degrees; divide or multiply
  674. * by 60*60*1000 for that.
  675. */
  676. static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
  677. 1000000,10000000,100000000,1000000000};
  678. /*% takes an XeY precision/size value, returns a string representation. */
  679. static const char *
  680. precsize_ntoa(prec)
  681. u_int8_t prec;
  682. {
  683. char *retbuf = precsize_ntoa_retbuf;
  684. unsigned long val;
  685. int mantissa, exponent;
  686. mantissa = (int)((prec >> 4) & 0x0f) % 10;
  687. exponent = (int)((prec >> 0) & 0x0f) % 10;
  688. val = mantissa * poweroften[exponent];
  689. (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100);
  690. return (retbuf);
  691. }
  692. /*% converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
  693. static u_int8_t
  694. precsize_aton(const char **strptr) {
  695. unsigned int mval = 0, cmval = 0;
  696. u_int8_t retval = 0;
  697. const char *cp;
  698. int exponent;
  699. int mantissa;
  700. cp = *strptr;
  701. while (isdigit((unsigned char)*cp))
  702. mval = mval * 10 + (*cp++ - '0');
  703. if (*cp == '.') { /*%< centimeters */
  704. cp++;
  705. if (isdigit((unsigned char)*cp)) {
  706. cmval = (*cp++ - '0') * 10;
  707. if (isdigit((unsigned char)*cp)) {
  708. cmval += (*cp++ - '0');
  709. }
  710. }
  711. }
  712. cmval = (mval * 100) + cmval;
  713. for (exponent = 0; exponent < 9; exponent++)
  714. if (cmval < poweroften[exponent+1])
  715. break;
  716. mantissa = cmval / poweroften[exponent];
  717. if (mantissa > 9)
  718. mantissa = 9;
  719. retval = (mantissa << 4) | exponent;
  720. *strptr = cp;
  721. return (retval);
  722. }
  723. /*% converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
  724. static u_int32_t
  725. latlon2ul(const char **latlonstrptr, int *which) {
  726. const char *cp;
  727. u_int32_t retval;
  728. int deg = 0, min = 0, secs = 0, secsfrac = 0;
  729. cp = *latlonstrptr;
  730. while (isdigit((unsigned char)*cp))
  731. deg = deg * 10 + (*cp++ - '0');
  732. while (isspace((unsigned char)*cp))
  733. cp++;
  734. if (!(isdigit((unsigned char)*cp)))
  735. goto fndhemi;
  736. while (isdigit((unsigned char)*cp))
  737. min = min * 10 + (*cp++ - '0');
  738. while (isspace((unsigned char)*cp))
  739. cp++;
  740. if (!(isdigit((unsigned char)*cp)))
  741. goto fndhemi;
  742. while (isdigit((unsigned char)*cp))
  743. secs = secs * 10 + (*cp++ - '0');
  744. if (*cp == '.') { /*%< decimal seconds */
  745. cp++;
  746. if (isdigit((unsigned char)*cp)) {
  747. secsfrac = (*cp++ - '0') * 100;
  748. if (isdigit((unsigned char)*cp)) {
  749. secsfrac += (*cp++ - '0') * 10;
  750. if (isdigit((unsigned char)*cp)) {
  751. secsfrac += (*cp++ - '0');
  752. }
  753. }
  754. }
  755. }
  756. while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */
  757. cp++;
  758. while (isspace((unsigned char)*cp))
  759. cp++;
  760. fndhemi:
  761. switch (*cp) {
  762. case 'N': case 'n':
  763. case 'E': case 'e':
  764. retval = ((unsigned)1<<31)
  765. + (((((deg * 60) + min) * 60) + secs) * 1000)
  766. + secsfrac;
  767. break;
  768. case 'S': case 's':
  769. case 'W': case 'w':
  770. retval = ((unsigned)1<<31)
  771. - (((((deg * 60) + min) * 60) + secs) * 1000)
  772. - secsfrac;
  773. break;
  774. default:
  775. retval = 0; /*%< invalid value -- indicates error */
  776. break;
  777. }
  778. switch (*cp) {
  779. case 'N': case 'n':
  780. case 'S': case 's':
  781. *which = 1; /*%< latitude */
  782. break;
  783. case 'E': case 'e':
  784. case 'W': case 'w':
  785. *which = 2; /*%< longitude */
  786. break;
  787. default:
  788. *which = 0; /*%< error */
  789. break;
  790. }
  791. cp++; /*%< skip the hemisphere */
  792. while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */
  793. cp++;
  794. while (isspace((unsigned char)*cp)) /*%< move to next field */
  795. cp++;
  796. *latlonstrptr = cp;
  797. return (retval);
  798. }
  799. /*%
  800. * converts a zone file representation in a string to an RDATA on-the-wire
  801. * representation. */
  802. int
  803. loc_aton(ascii, binary)
  804. const char *ascii;
  805. u_char *binary;
  806. {
  807. const char *cp, *maxcp;
  808. u_char *bcp;
  809. u_int32_t latit = 0, longit = 0, alt = 0;
  810. u_int32_t lltemp1 = 0, lltemp2 = 0;
  811. int altmeters = 0, altfrac = 0, altsign = 1;
  812. u_int8_t hp = 0x16; /*%< default = 1e6 cm = 10000.00m = 10km */
  813. u_int8_t vp = 0x13; /*%< default = 1e3 cm = 10.00m */
  814. u_int8_t siz = 0x12; /*%< default = 1e2 cm = 1.00m */
  815. int which1 = 0, which2 = 0;
  816. cp = ascii;
  817. maxcp = cp + strlen(ascii);
  818. lltemp1 = latlon2ul(&cp, &which1);
  819. lltemp2 = latlon2ul(&cp, &which2);
  820. switch (which1 + which2) {
  821. case 3: /*%< 1 + 2, the only valid combination */
  822. if ((which1 == 1) && (which2 == 2)) { /*%< normal case */
  823. latit = lltemp1;
  824. longit = lltemp2;
  825. } else if ((which1 == 2) && (which2 == 1)) { /*%< reversed */
  826. longit = lltemp1;
  827. latit = lltemp2;
  828. } else { /*%< some kind of brokenness */
  829. return (0);
  830. }
  831. break;
  832. default: /*%< we didn't get one of each */
  833. return (0);
  834. }
  835. /* altitude */
  836. if (*cp == '-') {
  837. altsign = -1;
  838. cp++;
  839. }
  840. if (*cp == '+')
  841. cp++;
  842. while (isdigit((unsigned char)*cp))
  843. altmeters = altmeters * 10 + (*cp++ - '0');
  844. if (*cp == '.') { /*%< decimal meters */
  845. cp++;
  846. if (isdigit((unsigned char)*cp)) {
  847. altfrac = (*cp++ - '0') * 10;
  848. if (isdigit((unsigned char)*cp)) {
  849. altfrac += (*cp++ - '0');
  850. }
  851. }
  852. }
  853. alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
  854. while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
  855. cp++;
  856. while (isspace((unsigned char)*cp) && (cp < maxcp))
  857. cp++;
  858. if (cp >= maxcp)
  859. goto defaults;
  860. siz = precsize_aton(&cp);
  861. while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
  862. cp++;
  863. while (isspace((unsigned char)*cp) && (cp < maxcp))
  864. cp++;
  865. if (cp >= maxcp)
  866. goto defaults;
  867. hp = precsize_aton(&cp);
  868. while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
  869. cp++;
  870. while (isspace((unsigned char)*cp) && (cp < maxcp))
  871. cp++;
  872. if (cp >= maxcp)
  873. goto defaults;
  874. vp = precsize_aton(&cp);
  875. defaults:
  876. bcp = binary;
  877. *bcp++ = (u_int8_t) 0; /*%< version byte */
  878. *bcp++ = siz;
  879. *bcp++ = hp;
  880. *bcp++ = vp;
  881. PUTLONG(latit,bcp);
  882. PUTLONG(longit,bcp);
  883. PUTLONG(alt,bcp);
  884. return (16); /*%< size of RR in octets */
  885. }
  886. /*% takes an on-the-wire LOC RR and formats it in a human readable format. */
  887. const char *
  888. loc_ntoa(binary, ascii)
  889. const u_char *binary;
  890. char *ascii;
  891. {
  892. static const char *error = "?";
  893. static char tmpbuf[sizeof
  894. "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
  895. const u_char *cp = binary;
  896. int latdeg, latmin, latsec, latsecfrac;
  897. int longdeg, longmin, longsec, longsecfrac;
  898. char northsouth, eastwest;
  899. const char *altsign;
  900. int altmeters, altfrac;
  901. const u_int32_t referencealt = 100000 * 100;
  902. int32_t latval, longval, altval;
  903. u_int32_t templ;
  904. u_int8_t sizeval, hpval, vpval, versionval;
  905. char *sizestr, *hpstr, *vpstr;
  906. versionval = *cp++;
  907. if (ascii == NULL)
  908. ascii = tmpbuf;
  909. if (versionval) {
  910. (void) sprintf(ascii, "; error: unknown LOC RR version");
  911. return (ascii);
  912. }
  913. sizeval = *cp++;
  914. hpval = *cp++;
  915. vpval = *cp++;
  916. GETLONG(templ, cp);
  917. latval = (templ - ((unsigned)1<<31));
  918. GETLONG(templ, cp);
  919. longval = (templ - ((unsigned)1<<31));
  920. GETLONG(templ, cp);
  921. if (templ < referencealt) { /*%< below WGS 84 spheroid */
  922. altval = referencealt - templ;
  923. altsign = "-";
  924. } else {
  925. altval = templ - referencealt;
  926. altsign = "";
  927. }
  928. if (latval < 0) {
  929. northsouth = 'S';
  930. latval = -latval;
  931. } else
  932. northsouth = 'N';
  933. latsecfrac = latval % 1000;
  934. latval = latval / 1000;
  935. latsec = latval % 60;
  936. latval = latval / 60;
  937. latmin = latval % 60;
  938. latval = latval / 60;
  939. latdeg = latval;
  940. if (longval < 0) {
  941. eastwest = 'W';
  942. longval = -longval;
  943. } else
  944. eastwest = 'E';
  945. longsecfrac = longval % 1000;
  946. longval = longval / 1000;
  947. longsec = longval % 60;
  948. longval = longval / 60;
  949. longmin = longval % 60;
  950. longval = longval / 60;
  951. longdeg = longval;
  952. altfrac = altval % 100;
  953. altmeters = (altval / 100);
  954. sizestr = strdup(precsize_ntoa(sizeval));
  955. hpstr = strdup(precsize_ntoa(hpval));
  956. vpstr = strdup(precsize_ntoa(vpval));
  957. sprintf(ascii,
  958. "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm",
  959. latdeg, latmin, latsec, latsecfrac, northsouth,
  960. longdeg, longmin, longsec, longsecfrac, eastwest,
  961. altsign, altmeters, altfrac,
  962. (sizestr != NULL) ? sizestr : error,
  963. (hpstr != NULL) ? hpstr : error,
  964. (vpstr != NULL) ? vpstr : error);
  965. if (sizestr != NULL)
  966. free(sizestr);
  967. if (hpstr != NULL)
  968. free(hpstr);
  969. if (vpstr != NULL)
  970. free(vpstr);
  971. return (ascii);
  972. }
  973. /*% Return the number of DNS hierarchy levels in the name. */
  974. int
  975. dn_count_labels(const char *name) {
  976. int i, len, count;
  977. len = strlen(name);
  978. for (i = 0, count = 0; i < len; i++) {
  979. /* XXX need to check for \. or use named's nlabels(). */
  980. if (name[i] == '.')
  981. count++;
  982. }
  983. /* don't count initial wildcard */
  984. if (name[0] == '*')
  985. if (count)
  986. count--;
  987. /* don't count the null label for root. */
  988. /* if terminating '.' not found, must adjust */
  989. /* count to include last label */
  990. if (len > 0 && name[len-1] != '.')
  991. count++;
  992. return (count);
  993. }
  994. /*%
  995. * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
  996. * SIG records are required to be printed like this, by the Secure DNS RFC.
  997. */
  998. char *
  999. p_secstodate (u_long secs) {
  1000. char *output = p_secstodate_output;
  1001. time_t clock = secs;
  1002. struct tm *time;
  1003. #ifdef HAVE_TIME_R
  1004. struct tm res;
  1005. time = gmtime_r(&clock, &res);
  1006. #else
  1007. time = gmtime(&clock);
  1008. #endif
  1009. time->tm_year += 1900;
  1010. time->tm_mon += 1;
  1011. sprintf(output, "%04d%02d%02d%02d%02d%02d",
  1012. time->tm_year, time->tm_mon, time->tm_mday,
  1013. time->tm_hour, time->tm_min, time->tm_sec);
  1014. return (output);
  1015. }
  1016. u_int16_t
  1017. res_nametoclass(const char *buf, int *successp) {
  1018. unsigned long result;
  1019. char *endptr;
  1020. int success;
  1021. result = sym_ston(__p_class_syms, buf, &success);
  1022. if (success)
  1023. goto done;
  1024. if (strncasecmp(buf, "CLASS", 5) != 0 ||
  1025. !isdigit((unsigned char)buf[5]))
  1026. goto done;
  1027. errno = 0;
  1028. result = strtoul(buf + 5, &endptr, 10);
  1029. if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
  1030. success = 1;
  1031. done:
  1032. if (successp)
  1033. *successp = success;
  1034. return (result);
  1035. }
  1036. u_int16_t
  1037. res_nametotype(const char *buf, int *successp) {
  1038. unsigned long result;
  1039. char *endptr;
  1040. int success;
  1041. result = sym_ston(__p_type_syms, buf, &success);
  1042. if (success)
  1043. goto done;
  1044. if (strncasecmp(buf, "type", 4) != 0 ||
  1045. !isdigit((unsigned char)buf[4]))
  1046. goto done;
  1047. errno = 0;
  1048. result = strtoul(buf + 4, &endptr, 10);
  1049. if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
  1050. success = 1;
  1051. done:
  1052. if (successp)
  1053. *successp = success;
  1054. return (result);
  1055. }
  1056. /*
  1057. * Weak aliases for applications that use certain private entry points,
  1058. * and fail to include <resolv.h>.
  1059. */
  1060. #undef fp_resstat
  1061. __weak_reference(__fp_resstat, fp_resstat);
  1062. #undef p_fqnname
  1063. __weak_reference(__p_fqnname, p_fqnname);
  1064. #undef sym_ston
  1065. __weak_reference(__sym_ston, sym_ston);
  1066. #undef sym_ntos
  1067. __weak_reference(__sym_ntos, sym_ntos);
  1068. #undef sym_ntop
  1069. __weak_reference(__sym_ntop, sym_ntop);
  1070. #undef dn_count_labels
  1071. __weak_reference(__dn_count_labels, dn_count_labels);
  1072. #undef p_secstodate
  1073. __weak_reference(__p_secstodate, p_secstodate);
  1074. /*! \file */