source: rtems-libbsd/freebsd/lib/libc/nameser/ns_print.c @ e599318

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since e599318 was e599318, checked in by Sebastian Huber <sebastian.huber@…>, on 10/09/13 at 20:52:54

Update files to match FreeBSD layout

Add compatibility with Newlib header files. Some FreeBSD header files
are mapped by the translation script:

o rtems/bsd/sys/_types.h
o rtems/bsd/sys/errno.h
o rtems/bsd/sys/lock.h
o rtems/bsd/sys/param.h
o rtems/bsd/sys/resource.h
o rtems/bsd/sys/time.h
o rtems/bsd/sys/timespec.h
o rtems/bsd/sys/types.h
o rtems/bsd/sys/unistd.h

It is now possible to include <sys/socket.h> directly for example.

Generate one Makefile which builds everything including tests.

  • Property mode set to 100644
File size: 21.1 KB
Line 
1#include "port_before.h"
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996-1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef lint
21static const char rcsid[] = "$Id: ns_print.c,v 1.6.18.4 2005/04/27 05:01:09 sra Exp $";
22#endif
23#include <sys/cdefs.h>
24__FBSDID("$FreeBSD$");
25
26/* Import. */
27
28#include "port_before.h"
29
30#include <rtems/bsd/sys/types.h>
31#include <sys/socket.h>
32
33#include <netinet/in.h>
34#include <arpa/nameser.h>
35#include <arpa/inet.h>
36
37#ifdef _LIBC
38#include <assert.h>
39#define INSIST(cond)    assert(cond)
40#else
41#include <isc/assertions.h>
42#include <isc/dst.h>
43#endif
44#include <errno.h>
45#include <resolv.h>
46#include <string.h>
47#include <ctype.h>
48
49#include "port_after.h"
50
51#ifdef SPRINTF_CHAR
52# define SPRINTF(x) strlen(sprintf/**/x)
53#else
54# define SPRINTF(x) ((size_t)sprintf x)
55#endif
56
57/* Forward. */
58
59static size_t   prune_origin(const char *name, const char *origin);
60static int      charstr(const u_char *rdata, const u_char *edata,
61                        char **buf, size_t *buflen);
62static int      addname(const u_char *msg, size_t msglen,
63                        const u_char **p, const char *origin,
64                        char **buf, size_t *buflen);
65static void     addlen(size_t len, char **buf, size_t *buflen);
66static int      addstr(const char *src, size_t len,
67                       char **buf, size_t *buflen);
68static int      addtab(size_t len, size_t target, int spaced,
69                       char **buf, size_t *buflen);
70
71/* Macros. */
72
73#define T(x) \
74        do { \
75                if ((x) < 0) \
76                        return (-1); \
77        } while (0)
78
79/* Public. */
80
81/*%
82 *      Convert an RR to presentation format.
83 *
84 * return:
85 *\li   Number of characters written to buf, or -1 (check errno).
86 */
87int
88ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
89            const char *name_ctx, const char *origin,
90            char *buf, size_t buflen)
91{
92        int n;
93
94        n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
95                         ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
96                         ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
97                         name_ctx, origin, buf, buflen);
98        return (n);
99}
100
101/*%
102 *      Convert the fields of an RR into presentation format.
103 *
104 * return:
105 *\li   Number of characters written to buf, or -1 (check errno).
106 */
107int
108ns_sprintrrf(const u_char *msg, size_t msglen,
109            const char *name, ns_class class, ns_type type,
110            u_long ttl, const u_char *rdata, size_t rdlen,
111            const char *name_ctx, const char *origin,
112            char *buf, size_t buflen)
113{
114        const char *obuf = buf;
115        const u_char *edata = rdata + rdlen;
116        int spaced = 0;
117
118        const char *comment;
119        char tmp[100];
120        int len, x;
121
122        /*
123         * Owner.
124         */
125        if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
126                T(addstr("\t\t\t", 3, &buf, &buflen));
127        } else {
128                len = prune_origin(name, origin);
129                if (*name == '\0') {
130                        goto root;
131                } else if (len == 0) {
132                        T(addstr("@\t\t\t", 4, &buf, &buflen));
133                } else {
134                        T(addstr(name, len, &buf, &buflen));
135                        /* Origin not used or not root, and no trailing dot? */
136                        if (((origin == NULL || origin[0] == '\0') ||
137                            (origin[0] != '.' && origin[1] != '\0' &&
138                            name[len] == '\0')) && name[len - 1] != '.') {
139 root:
140                                T(addstr(".", 1, &buf, &buflen));
141                                len++;
142                        }
143                        T(spaced = addtab(len, 24, spaced, &buf, &buflen));
144                }
145        }
146
147        /*
148         * TTL, Class, Type.
149         */
150        T(x = ns_format_ttl(ttl, buf, buflen));
151        addlen(x, &buf, &buflen);
152        len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
153        T(addstr(tmp, len, &buf, &buflen));
154        T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
155
156        /*
157         * RData.
158         */
159        switch (type) {
160        case ns_t_a:
161                if (rdlen != (size_t)NS_INADDRSZ)
162                        goto formerr;
163                (void) inet_ntop(AF_INET, rdata, buf, buflen);
164                addlen(strlen(buf), &buf, &buflen);
165                break;
166
167        case ns_t_cname:
168        case ns_t_mb:
169        case ns_t_mg:
170        case ns_t_mr:
171        case ns_t_ns:
172        case ns_t_ptr:
173        case ns_t_dname:
174                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
175                break;
176
177        case ns_t_hinfo:
178        case ns_t_isdn:
179                /* First word. */
180                T(len = charstr(rdata, edata, &buf, &buflen));
181                if (len == 0)
182                        goto formerr;
183                rdata += len;
184                T(addstr(" ", 1, &buf, &buflen));
185
186                   
187                /* Second word, optional in ISDN records. */
188                if (type == ns_t_isdn && rdata == edata)
189                        break;
190                   
191                T(len = charstr(rdata, edata, &buf, &buflen));
192                if (len == 0)
193                        goto formerr;
194                rdata += len;
195                break;
196
197        case ns_t_soa: {
198                u_long t;
199
200                /* Server name. */
201                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
202                T(addstr(" ", 1, &buf, &buflen));
203
204                /* Administrator name. */
205                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
206                T(addstr(" (\n", 3, &buf, &buflen));
207                spaced = 0;
208
209                if ((edata - rdata) != 5*NS_INT32SZ)
210                        goto formerr;
211
212                /* Serial number. */
213                t = ns_get32(rdata);  rdata += NS_INT32SZ;
214                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
215                len = SPRINTF((tmp, "%lu", t));
216                T(addstr(tmp, len, &buf, &buflen));
217                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
218                T(addstr("; serial\n", 9, &buf, &buflen));
219                spaced = 0;
220
221                /* Refresh interval. */
222                t = ns_get32(rdata);  rdata += NS_INT32SZ;
223                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
224                T(len = ns_format_ttl(t, buf, buflen));
225                addlen(len, &buf, &buflen);
226                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
227                T(addstr("; refresh\n", 10, &buf, &buflen));
228                spaced = 0;
229
230                /* Retry interval. */
231                t = ns_get32(rdata);  rdata += NS_INT32SZ;
232                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
233                T(len = ns_format_ttl(t, buf, buflen));
234                addlen(len, &buf, &buflen);
235                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
236                T(addstr("; retry\n", 8, &buf, &buflen));
237                spaced = 0;
238
239                /* Expiry. */
240                t = ns_get32(rdata);  rdata += NS_INT32SZ;
241                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
242                T(len = ns_format_ttl(t, buf, buflen));
243                addlen(len, &buf, &buflen);
244                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
245                T(addstr("; expiry\n", 9, &buf, &buflen));
246                spaced = 0;
247
248                /* Minimum TTL. */
249                t = ns_get32(rdata);  rdata += NS_INT32SZ;
250                T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
251                T(len = ns_format_ttl(t, buf, buflen));
252                addlen(len, &buf, &buflen);
253                T(addstr(" )", 2, &buf, &buflen));
254                T(spaced = addtab(len, 16, spaced, &buf, &buflen));
255                T(addstr("; minimum\n", 10, &buf, &buflen));
256
257                break;
258            }
259
260        case ns_t_mx:
261        case ns_t_afsdb:
262        case ns_t_rt: {
263                u_int t;
264
265                if (rdlen < (size_t)NS_INT16SZ)
266                        goto formerr;
267
268                /* Priority. */
269                t = ns_get16(rdata);
270                rdata += NS_INT16SZ;
271                len = SPRINTF((tmp, "%u ", t));
272                T(addstr(tmp, len, &buf, &buflen));
273
274                /* Target. */
275                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
276
277                break;
278            }
279
280        case ns_t_px: {
281                u_int t;
282
283                if (rdlen < (size_t)NS_INT16SZ)
284                        goto formerr;
285
286                /* Priority. */
287                t = ns_get16(rdata);
288                rdata += NS_INT16SZ;
289                len = SPRINTF((tmp, "%u ", t));
290                T(addstr(tmp, len, &buf, &buflen));
291
292                /* Name1. */
293                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
294                T(addstr(" ", 1, &buf, &buflen));
295
296                /* Name2. */
297                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
298
299                break;
300            }
301
302        case ns_t_x25:
303                T(len = charstr(rdata, edata, &buf, &buflen));
304                if (len == 0)
305                        goto formerr;
306                rdata += len;
307                break;
308
309        case ns_t_txt:
310                while (rdata < edata) {
311                        T(len = charstr(rdata, edata, &buf, &buflen));
312                        if (len == 0)
313                                goto formerr;
314                        rdata += len;
315                        if (rdata < edata)
316                                T(addstr(" ", 1, &buf, &buflen));
317                }
318                break;
319
320        case ns_t_nsap: {
321                char t[2+255*3];
322
323                (void) inet_nsap_ntoa(rdlen, rdata, t);
324                T(addstr(t, strlen(t), &buf, &buflen));
325                break;
326            }
327
328        case ns_t_aaaa:
329                if (rdlen != (size_t)NS_IN6ADDRSZ)
330                        goto formerr;
331                (void) inet_ntop(AF_INET6, rdata, buf, buflen);
332                addlen(strlen(buf), &buf, &buflen);
333                break;
334
335        case ns_t_loc: {
336                char t[255];
337
338                /* XXX protocol format checking? */
339                (void) loc_ntoa(rdata, t);
340                T(addstr(t, strlen(t), &buf, &buflen));
341                break;
342            }
343
344        case ns_t_naptr: {
345                u_int order, preference;
346                char t[50];
347
348                if (rdlen < 2U*NS_INT16SZ)
349                        goto formerr;
350
351                /* Order, Precedence. */
352                order = ns_get16(rdata);        rdata += NS_INT16SZ;
353                preference = ns_get16(rdata);   rdata += NS_INT16SZ;
354                len = SPRINTF((t, "%u %u ", order, preference));
355                T(addstr(t, len, &buf, &buflen));
356
357                /* Flags. */
358                T(len = charstr(rdata, edata, &buf, &buflen));
359                if (len == 0)
360                        goto formerr;
361                rdata += len;
362                T(addstr(" ", 1, &buf, &buflen));
363
364                /* Service. */
365                T(len = charstr(rdata, edata, &buf, &buflen));
366                if (len == 0)
367                        goto formerr;
368                rdata += len;
369                T(addstr(" ", 1, &buf, &buflen));
370
371                /* Regexp. */
372                T(len = charstr(rdata, edata, &buf, &buflen));
373                if (len < 0)
374                        return (-1);
375                if (len == 0)
376                        goto formerr;
377                rdata += len;
378                T(addstr(" ", 1, &buf, &buflen));
379
380                /* Server. */
381                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
382                break;
383            }
384
385        case ns_t_srv: {
386                u_int priority, weight, port;
387                char t[50];
388
389                if (rdlen < 3U*NS_INT16SZ)
390                        goto formerr;
391
392                /* Priority, Weight, Port. */
393                priority = ns_get16(rdata);  rdata += NS_INT16SZ;
394                weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
395                port     = ns_get16(rdata);  rdata += NS_INT16SZ;
396                len = SPRINTF((t, "%u %u %u ", priority, weight, port));
397                T(addstr(t, len, &buf, &buflen));
398
399                /* Server. */
400                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
401                break;
402            }
403
404        case ns_t_minfo:
405        case ns_t_rp:
406                /* Name1. */
407                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
408                T(addstr(" ", 1, &buf, &buflen));
409
410                /* Name2. */
411                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
412
413                break;
414
415        case ns_t_wks: {
416                int n, lcnt;
417
418                if (rdlen < 1U + NS_INT32SZ)
419                        goto formerr;
420
421                /* Address. */
422                (void) inet_ntop(AF_INET, rdata, buf, buflen);
423                addlen(strlen(buf), &buf, &buflen);
424                rdata += NS_INADDRSZ;
425
426                /* Protocol. */
427                len = SPRINTF((tmp, " %u ( ", *rdata));
428                T(addstr(tmp, len, &buf, &buflen));
429                rdata += NS_INT8SZ;
430
431                /* Bit map. */
432                n = 0;
433                lcnt = 0;
434                while (rdata < edata) {
435                        u_int c = *rdata++;
436                        do {
437                                if (c & 0200) {
438                                        if (lcnt == 0) {
439                                                T(addstr("\n\t\t\t\t", 5,
440                                                         &buf, &buflen));
441                                                lcnt = 10;
442                                                spaced = 0;
443                                        }
444                                        len = SPRINTF((tmp, "%d ", n));
445                                        T(addstr(tmp, len, &buf, &buflen));
446                                        lcnt--;
447                                }
448                                c <<= 1;
449                        } while (++n & 07);
450                }
451                T(addstr(")", 1, &buf, &buflen));
452
453                break;
454            }
455
456        case ns_t_key: {
457                char base64_key[NS_MD5RSA_MAX_BASE64];
458                u_int keyflags, protocol, algorithm, key_id;
459                const char *leader;
460                int n;
461
462                if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
463                        goto formerr;
464
465                /* Key flags, Protocol, Algorithm. */
466#ifndef _LIBC
467                key_id = dst_s_dns_key_id(rdata, edata-rdata);
468#else
469                key_id = 0;
470#endif
471                keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
472                protocol = *rdata++;
473                algorithm = *rdata++;
474                len = SPRINTF((tmp, "0x%04x %u %u",
475                               keyflags, protocol, algorithm));
476                T(addstr(tmp, len, &buf, &buflen));
477
478                /* Public key data. */
479                len = b64_ntop(rdata, edata - rdata,
480                               base64_key, sizeof base64_key);
481                if (len < 0)
482                        goto formerr;
483                if (len > 15) {
484                        T(addstr(" (", 2, &buf, &buflen));
485                        leader = "\n\t\t";
486                        spaced = 0;
487                } else
488                        leader = " ";
489                for (n = 0; n < len; n += 48) {
490                        T(addstr(leader, strlen(leader), &buf, &buflen));
491                        T(addstr(base64_key + n, MIN(len - n, 48),
492                                 &buf, &buflen));
493                }
494                if (len > 15)
495                        T(addstr(" )", 2, &buf, &buflen));
496                n = SPRINTF((tmp, " ; key_tag= %u", key_id));
497                T(addstr(tmp, n, &buf, &buflen));
498
499                break;
500            }
501
502        case ns_t_sig: {
503                char base64_key[NS_MD5RSA_MAX_BASE64];
504                u_int type, algorithm, labels, footprint;
505                const char *leader;
506                u_long t;
507                int n;
508
509                if (rdlen < 22U)
510                        goto formerr;
511
512                /* Type covered, Algorithm, Label count, Original TTL. */
513                type = ns_get16(rdata);  rdata += NS_INT16SZ;
514                algorithm = *rdata++;
515                labels = *rdata++;
516                t = ns_get32(rdata);  rdata += NS_INT32SZ;
517                len = SPRINTF((tmp, "%s %d %d %lu ",
518                               p_type(type), algorithm, labels, t));
519                T(addstr(tmp, len, &buf, &buflen));
520                if (labels > (u_int)dn_count_labels(name))
521                        goto formerr;
522
523                /* Signature expiry. */
524                t = ns_get32(rdata);  rdata += NS_INT32SZ;
525                len = SPRINTF((tmp, "%s ", p_secstodate(t)));
526                T(addstr(tmp, len, &buf, &buflen));
527
528                /* Time signed. */
529                t = ns_get32(rdata);  rdata += NS_INT32SZ;
530                len = SPRINTF((tmp, "%s ", p_secstodate(t)));
531                T(addstr(tmp, len, &buf, &buflen));
532
533                /* Signature Footprint. */
534                footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
535                len = SPRINTF((tmp, "%u ", footprint));
536                T(addstr(tmp, len, &buf, &buflen));
537
538                /* Signer's name. */
539                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
540
541                /* Signature. */
542                len = b64_ntop(rdata, edata - rdata,
543                               base64_key, sizeof base64_key);
544                if (len > 15) {
545                        T(addstr(" (", 2, &buf, &buflen));
546                        leader = "\n\t\t";
547                        spaced = 0;
548                } else
549                        leader = " ";
550                if (len < 0)
551                        goto formerr;
552                for (n = 0; n < len; n += 48) {
553                        T(addstr(leader, strlen(leader), &buf, &buflen));
554                        T(addstr(base64_key + n, MIN(len - n, 48),
555                                 &buf, &buflen));
556                }
557                if (len > 15)
558                        T(addstr(" )", 2, &buf, &buflen));
559                break;
560            }
561
562        case ns_t_nxt: {
563                int n, c;
564
565                /* Next domain name. */
566                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
567
568                /* Type bit map. */
569                n = edata - rdata;
570                for (c = 0; c < n*8; c++)
571                        if (NS_NXT_BIT_ISSET(c, rdata)) {
572                                len = SPRINTF((tmp, " %s", p_type(c)));
573                                T(addstr(tmp, len, &buf, &buflen));
574                        }
575                break;
576            }
577
578        case ns_t_cert: {
579                u_int c_type, key_tag, alg;
580                int n;
581                unsigned int siz;
582                char base64_cert[8192], tmp[40];
583                const char *leader;
584
585                c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
586                key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
587                alg = (u_int) *rdata++;
588
589                len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
590                T(addstr(tmp, len, &buf, &buflen));
591                siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
592                if (siz > sizeof(base64_cert) * 3/4) {
593                        const char *str = "record too long to print";
594                        T(addstr(str, strlen(str), &buf, &buflen));
595                }
596                else {
597                        len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
598
599                        if (len < 0)
600                                goto formerr;
601                        else if (len > 15) {
602                                T(addstr(" (", 2, &buf, &buflen));
603                                leader = "\n\t\t";
604                                spaced = 0;
605                        }
606                        else
607                                leader = " ";
608       
609                        for (n = 0; n < len; n += 48) {
610                                T(addstr(leader, strlen(leader),
611                                         &buf, &buflen));
612                                T(addstr(base64_cert + n, MIN(len - n, 48),
613                                         &buf, &buflen));
614                        }
615                        if (len > 15)
616                                T(addstr(" )", 2, &buf, &buflen));
617                }
618                break;
619            }
620
621        case ns_t_tkey: {
622                /* KJD - need to complete this */
623                u_long t;
624                int mode, err, keysize;
625
626                /* Algorithm name. */
627                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
628                T(addstr(" ", 1, &buf, &buflen));
629
630                /* Inception. */
631                t = ns_get32(rdata);  rdata += NS_INT32SZ;
632                len = SPRINTF((tmp, "%s ", p_secstodate(t)));
633                T(addstr(tmp, len, &buf, &buflen));
634
635                /* Experation. */
636                t = ns_get32(rdata);  rdata += NS_INT32SZ;
637                len = SPRINTF((tmp, "%s ", p_secstodate(t)));
638                T(addstr(tmp, len, &buf, &buflen));
639
640                /* Mode , Error, Key Size. */
641                /* Priority, Weight, Port. */
642                mode = ns_get16(rdata);  rdata += NS_INT16SZ;
643                err  = ns_get16(rdata);  rdata += NS_INT16SZ;
644                keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
645                len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
646                T(addstr(tmp, len, &buf, &buflen));
647
648                /* XXX need to dump key, print otherdata length & other data */
649                break;
650            }
651
652        case ns_t_tsig: {
653                /* BEW - need to complete this */
654                int n;
655
656                T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
657                T(addstr(" ", 1, &buf, &buflen));
658                rdata += 8; /*%< time */
659                n = ns_get16(rdata); rdata += INT16SZ;
660                rdata += n; /*%< sig */
661                n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
662                sprintf(buf, "%d", ns_get16(rdata));
663                rdata += INT16SZ;
664                addlen(strlen(buf), &buf, &buflen);
665                break;
666            }
667
668        case ns_t_a6: {
669                struct in6_addr a;
670                int pbyte, pbit;
671
672                /* prefix length */
673                if (rdlen == 0U) goto formerr;
674                len = SPRINTF((tmp, "%d ", *rdata));
675                T(addstr(tmp, len, &buf, &buflen));
676                pbit = *rdata;
677                if (pbit > 128) goto formerr;
678                pbyte = (pbit & ~7) / 8;
679                rdata++;
680
681                /* address suffix: provided only when prefix len != 128 */
682                if (pbit < 128) {
683                        if (rdata + pbyte >= edata) goto formerr;
684                        memset(&a, 0, sizeof(a));
685                        memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
686                        (void) inet_ntop(AF_INET6, &a, buf, buflen);
687                        addlen(strlen(buf), &buf, &buflen);
688                        rdata += sizeof(a) - pbyte;
689                }
690
691                /* prefix name: provided only when prefix len > 0 */
692                if (pbit == 0)
693                        break;
694                if (rdata >= edata) goto formerr;
695                T(addstr(" ", 1, &buf, &buflen));
696                T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
697               
698                break;
699            }
700
701        case ns_t_opt: {
702                len = SPRINTF((tmp, "%u bytes", class));
703                T(addstr(tmp, len, &buf, &buflen));
704                break;
705            }
706
707        default:
708                comment = "unknown RR type";
709                goto hexify;
710        }
711        return (buf - obuf);
712 formerr:
713        comment = "RR format error";
714 hexify: {
715        int n, m;
716        char *p;
717
718        len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
719                       rdlen != 0U ? " (" : "", comment));
720        T(addstr(tmp, len, &buf, &buflen));
721        while (rdata < edata) {
722                p = tmp;
723                p += SPRINTF((p, "\n\t"));
724                spaced = 0;
725                n = MIN(16, edata - rdata);
726                for (m = 0; m < n; m++)
727                        p += SPRINTF((p, "%02x ", rdata[m]));
728                T(addstr(tmp, p - tmp, &buf, &buflen));
729                if (n < 16) {
730                        T(addstr(")", 1, &buf, &buflen));
731                        T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
732                }
733                p = tmp;
734                p += SPRINTF((p, "; "));
735                for (m = 0; m < n; m++)
736                        *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
737                                ? rdata[m]
738                                : '.';
739                T(addstr(tmp, p - tmp, &buf, &buflen));
740                rdata += n;
741        }
742        return (buf - obuf);
743    }
744}
745
746/* Private. */
747
748/*%
749 * size_t
750 * prune_origin(name, origin)
751 *      Find out if the name is at or under the current origin.
752 * return:
753 *      Number of characters in name before start of origin,
754 *      or length of name if origin does not match.
755 * notes:
756 *      This function should share code with samedomain().
757 */
758static size_t
759prune_origin(const char *name, const char *origin) {
760        const char *oname = name;
761
762        while (*name != '\0') {
763                if (origin != NULL && ns_samename(name, origin) == 1)
764                        return (name - oname - (name > oname));
765                while (*name != '\0') {
766                        if (*name == '\\') {
767                                name++;
768                                /* XXX need to handle \nnn form. */
769                                if (*name == '\0')
770                                        break;
771                        } else if (*name == '.') {
772                                name++;
773                                break;
774                        }
775                        name++;
776                }
777        }
778        return (name - oname);
779}
780
781/*%
782 * int
783 * charstr(rdata, edata, buf, buflen)
784 *      Format a <character-string> into the presentation buffer.
785 * return:
786 *      Number of rdata octets consumed
787 *      0 for protocol format error
788 *      -1 for output buffer error
789 * side effects:
790 *      buffer is advanced on success.
791 */
792static int
793charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
794        const u_char *odata = rdata;
795        size_t save_buflen = *buflen;
796        char *save_buf = *buf;
797
798        if (addstr("\"", 1, buf, buflen) < 0)
799                goto enospc;
800        if (rdata < edata) {
801                int n = *rdata;
802
803                if (rdata + 1 + n <= edata) {
804                        rdata++;
805                        while (n-- > 0) {
806                                if (strchr("\n\"\\", *rdata) != NULL)
807                                        if (addstr("\\", 1, buf, buflen) < 0)
808                                                goto enospc;
809                                if (addstr((const char *)rdata, 1,
810                                           buf, buflen) < 0)
811                                        goto enospc;
812                                rdata++;
813                        }
814                }
815        }
816        if (addstr("\"", 1, buf, buflen) < 0)
817                goto enospc;
818        return (rdata - odata);
819 enospc:
820        errno = ENOSPC;
821        *buf = save_buf;
822        *buflen = save_buflen;
823        return (-1);
824}
825
826static int
827addname(const u_char *msg, size_t msglen,
828        const u_char **pp, const char *origin,
829        char **buf, size_t *buflen)
830{
831        size_t newlen, save_buflen = *buflen;
832        char *save_buf = *buf;
833        int n;
834
835        n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
836        if (n < 0)
837                goto enospc;    /*%< Guess. */
838        newlen = prune_origin(*buf, origin);
839        if (**buf == '\0') {
840                goto root;
841        } else if (newlen == 0U) {
842                /* Use "@" instead of name. */
843                if (newlen + 2 > *buflen)
844                        goto enospc;        /* No room for "@\0". */
845                (*buf)[newlen++] = '@';
846                (*buf)[newlen] = '\0';
847        } else {
848                if (((origin == NULL || origin[0] == '\0') ||
849                    (origin[0] != '.' && origin[1] != '\0' &&
850                    (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
851                        /* No trailing dot. */
852 root:
853                        if (newlen + 2 > *buflen)
854                                goto enospc;    /* No room for ".\0". */
855                        (*buf)[newlen++] = '.';
856                        (*buf)[newlen] = '\0';
857                }
858        }
859        *pp += n;
860        addlen(newlen, buf, buflen);
861        **buf = '\0';
862        return (newlen);
863 enospc:
864        errno = ENOSPC;
865        *buf = save_buf;
866        *buflen = save_buflen;
867        return (-1);
868}
869
870static void
871addlen(size_t len, char **buf, size_t *buflen) {
872        INSIST(len <= *buflen);
873        *buf += len;
874        *buflen -= len;
875}
876
877static int
878addstr(const char *src, size_t len, char **buf, size_t *buflen) {
879        if (len >= *buflen) {
880                errno = ENOSPC;
881                return (-1);
882        }
883        memcpy(*buf, src, len);
884        addlen(len, buf, buflen);
885        **buf = '\0';
886        return (0);
887}
888
889static int
890addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
891        size_t save_buflen = *buflen;
892        char *save_buf = *buf;
893        int t;
894
895        if (spaced || len >= target - 1) {
896                T(addstr("  ", 2, buf, buflen));
897                spaced = 1;
898        } else {
899                for (t = (target - len - 1) / 8; t >= 0; t--)
900                        if (addstr("\t", 1, buf, buflen) < 0) {
901                                *buflen = save_buflen;
902                                *buf = save_buf;
903                                return (-1);
904                        }
905                spaced = 0;
906        }
907        return (spaced);
908}
909
910/*! \file */
Note: See TracBrowser for help on using the repository browser.