PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/newlib/libc/sys/linux/net/res_debug.c

https://github.com/atgreen/moxiedev
C | 1058 lines | 754 code | 140 blank | 164 comment | 180 complexity | 54e607080904edd9d56c9a654866e416 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, BSD-3-Clause-No-Nuclear-License-2014, BSD-3-Clause, GPL-3.0, LGPL-2.0, CC-BY-SA-3.0
  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. * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
  74. *
  75. * Permission to use, copy, modify, and distribute this software for any
  76. * purpose with or without fee is hereby granted, provided that the above
  77. * copyright notice and this permission notice appear in all copies.
  78. *
  79. * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
  80. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
  81. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
  82. * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  83. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  84. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  85. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  86. * 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[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vixie Exp $";
  91. #endif /* LIBC_SCCS and not lint */
  92. #include <sys/types.h>
  93. #include <sys/param.h>
  94. #include <sys/socket.h>
  95. #include <netinet/in.h>
  96. #include <arpa/inet.h>
  97. #include <arpa/nameser.h>
  98. #include <ctype.h>
  99. #include <errno.h>
  100. #include <math.h>
  101. #include <netdb.h>
  102. #include <resolv.h>
  103. #include <stdio.h>
  104. #include <stdlib.h>
  105. #include <string.h>
  106. #include <time.h>
  107. #include "local.h"
  108. #ifdef SPRINTF_CHAR
  109. # define SPRINTF(x) strlen(sprintf/**/x)
  110. #else
  111. # define SPRINTF(x) sprintf x
  112. #endif
  113. extern const char *_res_sectioncodes[] attribute_hidden;
  114. /*
  115. * Print the current options.
  116. */
  117. void
  118. fp_resstat(const res_state statp, FILE *file) {
  119. u_long mask;
  120. fprintf(file, ";; res options:");
  121. for (mask = 1; mask != 0; mask <<= 1)
  122. if (statp->options & mask)
  123. fprintf(file, " %s", p_option(mask));
  124. putc('\n', file);
  125. }
  126. static void
  127. do_section(const res_state statp,
  128. ns_msg *handle, ns_sect section,
  129. int pflag, FILE *file)
  130. {
  131. int n, sflag, rrnum;
  132. static int buflen = 2048;
  133. char *buf;
  134. ns_opcode opcode;
  135. ns_rr rr;
  136. /*
  137. * Print answer records.
  138. */
  139. sflag = (statp->pfcode & pflag);
  140. if (statp->pfcode && !sflag)
  141. return;
  142. buf = malloc(buflen);
  143. if (buf == NULL) {
  144. fprintf(file, ";; memory allocation failure\n");
  145. return;
  146. }
  147. opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
  148. rrnum = 0;
  149. for (;;) {
  150. if (ns_parserr(handle, section, rrnum, &rr)) {
  151. if (errno != ENODEV)
  152. fprintf(file, ";; ns_parserr: %s\n",
  153. strerror(errno));
  154. else if (rrnum > 0 && sflag != 0 &&
  155. (statp->pfcode & RES_PRF_HEAD1))
  156. putc('\n', file);
  157. goto cleanup;
  158. }
  159. if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
  160. fprintf(file, ";; %s SECTION:\n",
  161. p_section(section, opcode));
  162. if (section == ns_s_qd)
  163. fprintf(file, ";;\t%s, type = %s, class = %s\n",
  164. ns_rr_name(rr),
  165. p_type(ns_rr_type(rr)),
  166. p_class(ns_rr_class(rr)));
  167. else {
  168. n = ns_sprintrr(handle, &rr, NULL, NULL,
  169. buf, buflen);
  170. if (n < 0) {
  171. if (errno == ENOSPC) {
  172. free(buf);
  173. buf = NULL;
  174. if (buflen < 131072)
  175. buf = malloc(buflen += 1024);
  176. if (buf == NULL) {
  177. fprintf(file,
  178. ";; memory allocation failure\n");
  179. return;
  180. }
  181. continue;
  182. }
  183. fprintf(file, ";; ns_sprintrr: %s\n",
  184. strerror(errno));
  185. goto cleanup;
  186. }
  187. fputs(buf, file);
  188. fputc('\n', file);
  189. }
  190. rrnum++;
  191. }
  192. cleanup:
  193. if (buf != NULL)
  194. free(buf);
  195. }
  196. /*
  197. * Print the contents of a query.
  198. * This is intended to be primarily a debugging routine.
  199. */
  200. void
  201. res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
  202. ns_msg handle;
  203. int qdcount, ancount, nscount, arcount;
  204. u_int opcode, rcode, id;
  205. if (ns_initparse(msg, len, &handle) < 0) {
  206. fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
  207. return;
  208. }
  209. opcode = ns_msg_getflag(handle, ns_f_opcode);
  210. rcode = ns_msg_getflag(handle, ns_f_rcode);
  211. id = ns_msg_id(handle);
  212. qdcount = ns_msg_count(handle, ns_s_qd);
  213. ancount = ns_msg_count(handle, ns_s_an);
  214. nscount = ns_msg_count(handle, ns_s_ns);
  215. arcount = ns_msg_count(handle, ns_s_ar);
  216. /*
  217. * Print header fields.
  218. */
  219. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
  220. fprintf(file,
  221. ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
  222. _res_opcodes[opcode], p_rcode(rcode), id);
  223. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
  224. putc(';', file);
  225. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
  226. fprintf(file, "; flags:");
  227. if (ns_msg_getflag(handle, ns_f_qr))
  228. fprintf(file, " qr");
  229. if (ns_msg_getflag(handle, ns_f_aa))
  230. fprintf(file, " aa");
  231. if (ns_msg_getflag(handle, ns_f_tc))
  232. fprintf(file, " tc");
  233. if (ns_msg_getflag(handle, ns_f_rd))
  234. fprintf(file, " rd");
  235. if (ns_msg_getflag(handle, ns_f_ra))
  236. fprintf(file, " ra");
  237. if (ns_msg_getflag(handle, ns_f_z))
  238. fprintf(file, " ??");
  239. if (ns_msg_getflag(handle, ns_f_ad))
  240. fprintf(file, " ad");
  241. if (ns_msg_getflag(handle, ns_f_cd))
  242. fprintf(file, " cd");
  243. }
  244. if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
  245. fprintf(file, "; %s: %d",
  246. p_section(ns_s_qd, opcode), qdcount);
  247. fprintf(file, ", %s: %d",
  248. p_section(ns_s_an, opcode), ancount);
  249. fprintf(file, ", %s: %d",
  250. p_section(ns_s_ns, opcode), nscount);
  251. fprintf(file, ", %s: %d",
  252. p_section(ns_s_ar, opcode), arcount);
  253. }
  254. if ((!statp->pfcode) || (statp->pfcode &
  255. (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
  256. putc('\n',file);
  257. }
  258. /*
  259. * Print the various sections.
  260. */
  261. do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
  262. do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
  263. do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
  264. do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
  265. if (qdcount == 0 && ancount == 0 &&
  266. nscount == 0 && arcount == 0)
  267. putc('\n', file);
  268. }
  269. const u_char *
  270. p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
  271. char name[MAXDNAME];
  272. int n;
  273. if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
  274. return (NULL);
  275. if (name[0] == '\0')
  276. putc('.', file);
  277. else
  278. fputs(name, file);
  279. return (cp + n);
  280. }
  281. libresolv_hidden_def (p_cdnname)
  282. const u_char *
  283. p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
  284. return (p_cdnname(cp, msg, PACKETSZ, file));
  285. }
  286. /* Return a fully-qualified domain name from a compressed name (with
  287. length supplied). */
  288. const u_char *
  289. p_fqnname(cp, msg, msglen, name, namelen)
  290. const u_char *cp, *msg;
  291. int msglen;
  292. char *name;
  293. int namelen;
  294. {
  295. int n, newlen;
  296. if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
  297. return (NULL);
  298. newlen = strlen(name);
  299. if (newlen == 0 || name[newlen - 1] != '.') {
  300. if (newlen + 1 >= namelen) /* Lack space for final dot */
  301. return (NULL);
  302. else
  303. strcpy(name + newlen, ".");
  304. }
  305. return (cp + n);
  306. }
  307. libresolv_hidden_def (p_fqnname)
  308. /* XXX: the rest of these functions need to become length-limited, too. */
  309. const u_char *
  310. p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
  311. char name[MAXDNAME];
  312. const u_char *n;
  313. n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
  314. if (n == NULL)
  315. return (NULL);
  316. fputs(name, file);
  317. return (n);
  318. }
  319. /*
  320. * Names of RR classes and qclasses. Classes and qclasses are the same, except
  321. * that C_ANY is a qclass but not a class. (You can ask for records of class
  322. * C_ANY, but you can't have any records of that class in the database.)
  323. */
  324. extern const struct res_sym __p_class_syms[];
  325. libresolv_hidden_proto (__p_class_syms)
  326. const struct res_sym __p_class_syms[] = {
  327. {C_IN, "IN"},
  328. {C_CHAOS, "CHAOS"},
  329. {C_HS, "HS"},
  330. {C_HS, "HESIOD"},
  331. {C_ANY, "ANY"},
  332. {C_NONE, "NONE"},
  333. {C_IN, (char *)0}
  334. };
  335. libresolv_hidden_data_def (__p_class_syms)
  336. /*
  337. * Names of message sections.
  338. */
  339. const struct res_sym __p_default_section_syms[] attribute_hidden = {
  340. {ns_s_qd, "QUERY"},
  341. {ns_s_an, "ANSWER"},
  342. {ns_s_ns, "AUTHORITY"},
  343. {ns_s_ar, "ADDITIONAL"},
  344. {0, (char *)0}
  345. };
  346. const struct res_sym __p_update_section_syms[] attribute_hidden = {
  347. {S_ZONE, "ZONE"},
  348. {S_PREREQ, "PREREQUISITE"},
  349. {S_UPDATE, "UPDATE"},
  350. {S_ADDT, "ADDITIONAL"},
  351. {0, (char *)0}
  352. };
  353. const struct res_sym __p_key_syms[] attribute_hidden = {
  354. {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
  355. {NS_ALG_DH, "DH", "Diffie Hellman"},
  356. {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
  357. {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
  358. {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
  359. {0, NULL, NULL}
  360. };
  361. const struct res_sym __p_cert_syms[] attribute_hidden = {
  362. {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
  363. {cert_t_spki, "SPKI", "SPKI certificate"},
  364. {cert_t_pgp, "PGP", "PGP certificate"},
  365. {cert_t_url, "URL", "URL Private"},
  366. {cert_t_oid, "OID", "OID Private"},
  367. {0, NULL, NULL}
  368. };
  369. /*
  370. * Names of RR types and qtypes. Types and qtypes are the same, except
  371. * that T_ANY is a qtype but not a type. (You can ask for records of type
  372. * T_ANY, but you can't have any records of that type in the database.)
  373. */
  374. extern const struct res_sym __p_type_syms[];
  375. libresolv_hidden_proto (__p_type_syms)
  376. const struct res_sym __p_type_syms[] = {
  377. {ns_t_a, "A", "address"},
  378. {ns_t_ns, "NS", "name server"},
  379. {ns_t_md, "MD", "mail destination (deprecated)"},
  380. {ns_t_mf, "MF", "mail forwarder (deprecated)"},
  381. {ns_t_cname, "CNAME", "canonical name"},
  382. {ns_t_soa, "SOA", "start of authority"},
  383. {ns_t_mb, "MB", "mailbox"},
  384. {ns_t_mg, "MG", "mail group member"},
  385. {ns_t_mr, "MR", "mail rename"},
  386. {ns_t_null, "NULL", "null"},
  387. {ns_t_wks, "WKS", "well-known service (deprecated)"},
  388. {ns_t_ptr, "PTR", "domain name pointer"},
  389. {ns_t_hinfo, "HINFO", "host information"},
  390. {ns_t_minfo, "MINFO", "mailbox information"},
  391. {ns_t_mx, "MX", "mail exchanger"},
  392. {ns_t_txt, "TXT", "text"},
  393. {ns_t_rp, "RP", "responsible person"},
  394. {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
  395. {ns_t_x25, "X25", "X25 address"},
  396. {ns_t_isdn, "ISDN", "ISDN address"},
  397. {ns_t_rt, "RT", "router"},
  398. {ns_t_nsap, "NSAP", "nsap address"},
  399. {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
  400. {ns_t_sig, "SIG", "signature"},
  401. {ns_t_key, "KEY", "key"},
  402. {ns_t_px, "PX", "mapping information"},
  403. {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
  404. {ns_t_aaaa, "AAAA", "IPv6 address"},
  405. {ns_t_loc, "LOC", "location"},
  406. {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
  407. {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
  408. {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
  409. {ns_t_srv, "SRV", "server selection"},
  410. {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
  411. {ns_t_tsig, "TSIG", "transaction signature"},
  412. {ns_t_ixfr, "IXFR", "incremental zone transfer"},
  413. {ns_t_axfr, "AXFR", "zone transfer"},
  414. {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
  415. {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
  416. {ns_t_maila, "MAILA", "mail agent (deprecated)"},
  417. {ns_t_naptr, "NAPTR", "URN Naming Authority"},
  418. {ns_t_kx, "KX", "Key Exchange"},
  419. {ns_t_cert, "CERT", "Certificate"},
  420. {ns_t_any, "ANY", "\"any\""},
  421. {0, NULL, NULL}
  422. };
  423. libresolv_hidden_data_def (__p_type_syms)
  424. /*
  425. * Names of DNS rcodes.
  426. */
  427. const struct res_sym __p_rcode_syms[] attribute_hidden = {
  428. {ns_r_noerror, "NOERROR", "no error"},
  429. {ns_r_formerr, "FORMERR", "format error"},
  430. {ns_r_servfail, "SERVFAIL", "server failed"},
  431. {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
  432. {ns_r_notimpl, "NOTIMP", "not implemented"},
  433. {ns_r_refused, "REFUSED", "refused"},
  434. {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
  435. {ns_r_yxrrset, "YXRRSET", "rrset exists"},
  436. {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
  437. {ns_r_notauth, "NOTAUTH", "not authoritative"},
  438. {ns_r_notzone, "NOTZONE", "Not in zone"},
  439. {ns_r_max, "", ""},
  440. {ns_r_badsig, "BADSIG", "bad signature"},
  441. {ns_r_badkey, "BADKEY", "bad key"},
  442. {ns_r_badtime, "BADTIME", "bad time"},
  443. {0, NULL, NULL}
  444. };
  445. int
  446. sym_ston(const struct res_sym *syms, const char *name, int *success) {
  447. for ((void)NULL; syms->name != 0; syms++) {
  448. if (strcasecmp (name, syms->name) == 0) {
  449. if (success)
  450. *success = 1;
  451. return (syms->number);
  452. }
  453. }
  454. if (success)
  455. *success = 0;
  456. return (syms->number); /* The default value. */
  457. }
  458. const char *
  459. sym_ntos(const struct res_sym *syms, int number, int *success) {
  460. static char unname[20];
  461. for ((void)NULL; syms->name != 0; syms++) {
  462. if (number == syms->number) {
  463. if (success)
  464. *success = 1;
  465. return (syms->name);
  466. }
  467. }
  468. sprintf(unname, "%d", number); /* XXX nonreentrant */
  469. if (success)
  470. *success = 0;
  471. return (unname);
  472. }
  473. libresolv_hidden_def (sym_ntos)
  474. const char *
  475. sym_ntop(const struct res_sym *syms, int number, int *success) {
  476. static char unname[20];
  477. for ((void)NULL; syms->name != 0; syms++) {
  478. if (number == syms->number) {
  479. if (success)
  480. *success = 1;
  481. return (syms->humanname);
  482. }
  483. }
  484. sprintf(unname, "%d", number); /* XXX nonreentrant */
  485. if (success)
  486. *success = 0;
  487. return (unname);
  488. }
  489. /*
  490. * Return a string for the type.
  491. */
  492. const char *
  493. p_type(int type) {
  494. return (sym_ntos(__p_type_syms, type, (int *)0));
  495. }
  496. libresolv_hidden_def (p_type)
  497. /*
  498. * Return a string for the type.
  499. */
  500. const char *
  501. p_section(int section, int opcode) {
  502. const struct res_sym *symbols;
  503. switch (opcode) {
  504. case ns_o_update:
  505. symbols = __p_update_section_syms;
  506. break;
  507. default:
  508. symbols = __p_default_section_syms;
  509. break;
  510. }
  511. return (sym_ntos(symbols, section, (int *)0));
  512. }
  513. /*
  514. * Return a mnemonic for class.
  515. */
  516. const char *
  517. p_class(int class) {
  518. return (sym_ntos(__p_class_syms, class, (int *)0));
  519. }
  520. libresolv_hidden_def (p_class)
  521. /*
  522. * Return a mnemonic for an option
  523. */
  524. const char *
  525. p_option(u_long option) {
  526. static char nbuf[40];
  527. switch (option) {
  528. case RES_INIT: return "init";
  529. case RES_DEBUG: return "debug";
  530. case RES_AAONLY: return "aaonly(unimpl)";
  531. case RES_USEVC: return "usevc";
  532. case RES_PRIMARY: return "primry(unimpl)";
  533. case RES_IGNTC: return "igntc";
  534. case RES_RECURSE: return "recurs";
  535. case RES_DEFNAMES: return "defnam";
  536. case RES_STAYOPEN: return "styopn";
  537. case RES_DNSRCH: return "dnsrch";
  538. case RES_INSECURE1: return "insecure1";
  539. case RES_INSECURE2: return "insecure2";
  540. case RES_USE_INET6: return "inet6";
  541. case RES_ROTATE: return "rotate";
  542. case RES_NOCHECKNAME: return "no-check-names";
  543. case RES_USEBSTRING: return "ip6-bytstring";
  544. /* XXX nonreentrant */
  545. default: sprintf(nbuf, "?0x%lx?", (u_long)option);
  546. return (nbuf);
  547. }
  548. }
  549. libresolv_hidden_def (p_option)
  550. /*
  551. * Return a mnemonic for a time to live.
  552. */
  553. const char *
  554. p_time(u_int32_t value) {
  555. static char nbuf[40]; /* XXX nonreentrant */
  556. if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
  557. sprintf(nbuf, "%u", value);
  558. return (nbuf);
  559. }
  560. /*
  561. * Return a string for the rcode.
  562. */
  563. const char *
  564. p_rcode(int rcode) {
  565. return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
  566. }
  567. libresolv_hidden_def (p_rcode)
  568. /*
  569. * routines to convert between on-the-wire RR format and zone file format.
  570. * Does not contain conversion to/from decimal degrees; divide or multiply
  571. * by 60*60*1000 for that.
  572. */
  573. static const unsigned int poweroften[10]=
  574. { 1, 10, 100, 1000, 10000, 100000,
  575. 1000000,10000000,100000000,1000000000};
  576. /* takes an XeY precision/size value, returns a string representation. */
  577. static const char *
  578. precsize_ntoa(prec)
  579. u_int8_t prec;
  580. {
  581. static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
  582. unsigned long val;
  583. int mantissa, exponent;
  584. mantissa = (int)((prec >> 4) & 0x0f) % 10;
  585. exponent = (int)((prec >> 0) & 0x0f) % 10;
  586. val = mantissa * poweroften[exponent];
  587. (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
  588. return (retbuf);
  589. }
  590. /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
  591. static u_int8_t
  592. precsize_aton(strptr)
  593. const char **strptr;
  594. {
  595. unsigned int mval = 0, cmval = 0;
  596. u_int8_t retval = 0;
  597. const char *cp;
  598. int exponent;
  599. int mantissa;
  600. cp = *strptr;
  601. while (isdigit(*cp))
  602. mval = mval * 10 + (*cp++ - '0');
  603. if (*cp == '.') { /* centimeters */
  604. cp++;
  605. if (isdigit(*cp)) {
  606. cmval = (*cp++ - '0') * 10;
  607. if (isdigit(*cp)) {
  608. cmval += (*cp++ - '0');
  609. }
  610. }
  611. }
  612. cmval = (mval * 100) + cmval;
  613. for (exponent = 0; exponent < 9; exponent++)
  614. if (cmval < poweroften[exponent+1])
  615. break;
  616. mantissa = cmval / poweroften[exponent];
  617. if (mantissa > 9)
  618. mantissa = 9;
  619. retval = (mantissa << 4) | exponent;
  620. *strptr = cp;
  621. return (retval);
  622. }
  623. /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
  624. static u_int32_t
  625. latlon2ul(latlonstrptr,which)
  626. const char **latlonstrptr;
  627. int *which;
  628. {
  629. const char *cp;
  630. u_int32_t retval;
  631. int deg = 0, min = 0, secs = 0, secsfrac = 0;
  632. cp = *latlonstrptr;
  633. while (isdigit(*cp))
  634. deg = deg * 10 + (*cp++ - '0');
  635. while (isspace(*cp))
  636. cp++;
  637. if (!(isdigit(*cp)))
  638. goto fndhemi;
  639. while (isdigit(*cp))
  640. min = min * 10 + (*cp++ - '0');
  641. while (isspace(*cp))
  642. cp++;
  643. if (!(isdigit(*cp)))
  644. goto fndhemi;
  645. while (isdigit(*cp))
  646. secs = secs * 10 + (*cp++ - '0');
  647. if (*cp == '.') { /* decimal seconds */
  648. cp++;
  649. if (isdigit(*cp)) {
  650. secsfrac = (*cp++ - '0') * 100;
  651. if (isdigit(*cp)) {
  652. secsfrac += (*cp++ - '0') * 10;
  653. if (isdigit(*cp)) {
  654. secsfrac += (*cp++ - '0');
  655. }
  656. }
  657. }
  658. }
  659. while (!isspace(*cp)) /* if any trailing garbage */
  660. cp++;
  661. while (isspace(*cp))
  662. cp++;
  663. fndhemi:
  664. switch (*cp) {
  665. case 'N': case 'n':
  666. case 'E': case 'e':
  667. retval = ((unsigned)1<<31)
  668. + (((((deg * 60) + min) * 60) + secs) * 1000)
  669. + secsfrac;
  670. break;
  671. case 'S': case 's':
  672. case 'W': case 'w':
  673. retval = ((unsigned)1<<31)
  674. - (((((deg * 60) + min) * 60) + secs) * 1000)
  675. - secsfrac;
  676. break;
  677. default:
  678. retval = 0; /* invalid value -- indicates error */
  679. break;
  680. }
  681. switch (*cp) {
  682. case 'N': case 'n':
  683. case 'S': case 's':
  684. *which = 1; /* latitude */
  685. break;
  686. case 'E': case 'e':
  687. case 'W': case 'w':
  688. *which = 2; /* longitude */
  689. break;
  690. default:
  691. *which = 0; /* error */
  692. break;
  693. }
  694. cp++; /* skip the hemisphere */
  695. while (!isspace(*cp)) /* if any trailing garbage */
  696. cp++;
  697. while (isspace(*cp)) /* move to next field */
  698. cp++;
  699. *latlonstrptr = cp;
  700. return (retval);
  701. }
  702. /* converts a zone file representation in a string to an RDATA on-the-wire
  703. * representation. */
  704. int
  705. loc_aton(ascii, binary)
  706. const char *ascii;
  707. u_char *binary;
  708. {
  709. const char *cp, *maxcp;
  710. u_char *bcp;
  711. u_int32_t latit = 0, longit = 0, alt = 0;
  712. u_int32_t lltemp1 = 0, lltemp2 = 0;
  713. int altmeters = 0, altfrac = 0, altsign = 1;
  714. u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
  715. u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
  716. u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
  717. int which1 = 0, which2 = 0;
  718. cp = ascii;
  719. maxcp = cp + strlen(ascii);
  720. lltemp1 = latlon2ul(&cp, &which1);
  721. lltemp2 = latlon2ul(&cp, &which2);
  722. switch (which1 + which2) {
  723. case 3: /* 1 + 2, the only valid combination */
  724. if ((which1 == 1) && (which2 == 2)) { /* normal case */
  725. latit = lltemp1;
  726. longit = lltemp2;
  727. } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
  728. longit = lltemp1;
  729. latit = lltemp2;
  730. } else { /* some kind of brokenness */
  731. return (0);
  732. }
  733. break;
  734. default: /* we didn't get one of each */
  735. return (0);
  736. }
  737. /* altitude */
  738. if (*cp == '-') {
  739. altsign = -1;
  740. cp++;
  741. }
  742. if (*cp == '+')
  743. cp++;
  744. while (isdigit(*cp))
  745. altmeters = altmeters * 10 + (*cp++ - '0');
  746. if (*cp == '.') { /* decimal meters */
  747. cp++;
  748. if (isdigit(*cp)) {
  749. altfrac = (*cp++ - '0') * 10;
  750. if (isdigit(*cp)) {
  751. altfrac += (*cp++ - '0');
  752. }
  753. }
  754. }
  755. alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
  756. while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
  757. cp++;
  758. while (isspace(*cp) && (cp < maxcp))
  759. cp++;
  760. if (cp >= maxcp)
  761. goto defaults;
  762. siz = precsize_aton(&cp);
  763. while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
  764. cp++;
  765. while (isspace(*cp) && (cp < maxcp))
  766. cp++;
  767. if (cp >= maxcp)
  768. goto defaults;
  769. hp = precsize_aton(&cp);
  770. while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
  771. cp++;
  772. while (isspace(*cp) && (cp < maxcp))
  773. cp++;
  774. if (cp >= maxcp)
  775. goto defaults;
  776. vp = precsize_aton(&cp);
  777. defaults:
  778. bcp = binary;
  779. *bcp++ = (u_int8_t) 0; /* version byte */
  780. *bcp++ = siz;
  781. *bcp++ = hp;
  782. *bcp++ = vp;
  783. PUTLONG(latit,bcp);
  784. PUTLONG(longit,bcp);
  785. PUTLONG(alt,bcp);
  786. return (16); /* size of RR in octets */
  787. }
  788. /* takes an on-the-wire LOC RR and formats it in a human readable format. */
  789. const char *
  790. loc_ntoa(binary, ascii)
  791. const u_char *binary;
  792. char *ascii;
  793. {
  794. static char *error = "?";
  795. static char tmpbuf[sizeof
  796. "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
  797. const u_char *cp = binary;
  798. int latdeg, latmin, latsec, latsecfrac;
  799. int longdeg, longmin, longsec, longsecfrac;
  800. char northsouth, eastwest;
  801. int altmeters, altfrac, altsign;
  802. const u_int32_t referencealt = 100000 * 100;
  803. int32_t latval, longval, altval;
  804. u_int32_t templ;
  805. u_int8_t sizeval, hpval, vpval, versionval;
  806. char *sizestr, *hpstr, *vpstr;
  807. versionval = *cp++;
  808. if (ascii == NULL)
  809. ascii = tmpbuf;
  810. if (versionval) {
  811. (void) sprintf(ascii, "; error: unknown LOC RR version");
  812. return (ascii);
  813. }
  814. sizeval = *cp++;
  815. hpval = *cp++;
  816. vpval = *cp++;
  817. GETLONG(templ, cp);
  818. latval = (templ - ((unsigned)1<<31));
  819. GETLONG(templ, cp);
  820. longval = (templ - ((unsigned)1<<31));
  821. GETLONG(templ, cp);
  822. if (templ < referencealt) { /* below WGS 84 spheroid */
  823. altval = referencealt - templ;
  824. altsign = -1;
  825. } else {
  826. altval = templ - referencealt;
  827. altsign = 1;
  828. }
  829. if (latval < 0) {
  830. northsouth = 'S';
  831. latval = -latval;
  832. } else
  833. northsouth = 'N';
  834. latsecfrac = latval % 1000;
  835. latval = latval / 1000;
  836. latsec = latval % 60;
  837. latval = latval / 60;
  838. latmin = latval % 60;
  839. latval = latval / 60;
  840. latdeg = latval;
  841. if (longval < 0) {
  842. eastwest = 'W';
  843. longval = -longval;
  844. } else
  845. eastwest = 'E';
  846. longsecfrac = longval % 1000;
  847. longval = longval / 1000;
  848. longsec = longval % 60;
  849. longval = longval / 60;
  850. longmin = longval % 60;
  851. longval = longval / 60;
  852. longdeg = longval;
  853. altfrac = altval % 100;
  854. altmeters = (altval / 100) * altsign;
  855. if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
  856. sizestr = error;
  857. if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
  858. hpstr = error;
  859. if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
  860. vpstr = error;
  861. sprintf(ascii,
  862. "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
  863. latdeg, latmin, latsec, latsecfrac, northsouth,
  864. longdeg, longmin, longsec, longsecfrac, eastwest,
  865. altmeters, altfrac, sizestr, hpstr, vpstr);
  866. if (sizestr != error)
  867. free(sizestr);
  868. if (hpstr != error)
  869. free(hpstr);
  870. if (vpstr != error)
  871. free(vpstr);
  872. return (ascii);
  873. }
  874. libresolv_hidden_def (loc_ntoa)
  875. /* Return the number of DNS hierarchy levels in the name. */
  876. int
  877. dn_count_labels(const char *name) {
  878. int i, len, count;
  879. len = strlen(name);
  880. for (i = 0, count = 0; i < len; i++) {
  881. /* XXX need to check for \. or use named's nlabels(). */
  882. if (name[i] == '.')
  883. count++;
  884. }
  885. /* don't count initial wildcard */
  886. if (name[0] == '*')
  887. if (count)
  888. count--;
  889. /* don't count the null label for root. */
  890. /* if terminating '.' not found, must adjust */
  891. /* count to include last label */
  892. if (len > 0 && name[len-1] != '.')
  893. count++;
  894. return (count);
  895. }
  896. /*
  897. * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
  898. * SIG records are required to be printed like this, by the Secure DNS RFC.
  899. */
  900. char *
  901. p_secstodate (u_long secs) {
  902. /* XXX nonreentrant */
  903. static char output[15]; /* YYYYMMDDHHMMSS and null */
  904. time_t clock = secs;
  905. struct tm *time;
  906. #ifdef HAVE_TIME_R
  907. struct tm timebuf;
  908. time = gmtime_r(&clock, &timebuf);
  909. #else
  910. time = gmtime(&clock);
  911. #endif
  912. time->tm_year += 1900;
  913. time->tm_mon += 1;
  914. sprintf(output, "%04d%02d%02d%02d%02d%02d",
  915. time->tm_year, time->tm_mon, time->tm_mday,
  916. time->tm_hour, time->tm_min, time->tm_sec);
  917. return (output);
  918. }