source: trunk/libs/newlib/src/newlib/libc/sys/linux/net/res_debug.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

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