source: rtems/cpukit/libnetworking/libc/res_debug.c @ 300c914c

4.104.114.84.95
Last change on this file since 300c914c was 300c914c, checked in by Joel Sherrill <joel.sherrill@…>, on 09/01/06 at 18:15:01

* empty log message *

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