1 /*        $NetBSD: dns_strrecord.c,v 1.3 2023/12/23 20:30:43 christos Exp $     */
2 
3 /*++
4 /* NAME
5 /*        dns_strrecord 3
6 /* SUMMARY
7 /*        name service resource record printable forms
8 /* SYNOPSIS
9 /*        #include <dns.h>
10 /*
11 /*        char      *dns_strrecord(buf, record)
12 /*        VSTRING   *buf;
13 /*        DNS_RR    *record;
14 /* DESCRIPTION
15 /*        dns_strrecord() formats a DNS resource record as "name ttl
16 /*        class type preference value", where the class field is
17 /*        always "IN", the preference field exists only for MX records,
18 /*        and all names end in ".". The result value is the payload
19 /*        of the buffer argument.
20 /* LICENSE
21 /* .ad
22 /* .fi
23 /*        The Secure Mailer license must be distributed with this software.
24 /* AUTHOR(S)
25 /*        Wietse Venema
26 /*        IBM T.J. Watson Research
27 /*        P.O. Box 704
28 /*        Yorktown Heights, NY 10598, USA
29 /*
30 /*        Wietse Venema
31 /*        Google, Inc.
32 /*        111 8th Avenue
33 /*        New York, NY 10011, USA
34 /*--*/
35 
36 /* System library. */
37 
38 #include <sys_defs.h>
39 #include <string.h>                     /* memcpy */
40 
41 /* Utility library. */
42 
43 #include <vstring.h>
44 #include <msg.h>
45 
46 /* DNS library. */
47 
48 #include <dns.h>
49 
50 /* dns_strrecord - format resource record as generic string */
51 
dns_strrecord(VSTRING * buf,DNS_RR * rr)52 char   *dns_strrecord(VSTRING *buf, DNS_RR *rr)
53 {
54     const char myname[] = "dns_strrecord";
55     MAI_HOSTADDR_STR host;
56     UINT32_TYPE soa_buf[5];
57 
58     vstring_sprintf(buf, "%s. %u IN %s ",
59                         rr->rname, rr->ttl, dns_strtype(rr->type));
60     switch (rr->type) {
61     case T_A:
62 #ifdef T_AAAA
63     case T_AAAA:
64 #endif
65           if (dns_rr_to_pa(rr, &host) == 0)
66               msg_fatal("%s: conversion error for resource record type %s: %m",
67                           myname, dns_strtype(rr->type));
68           vstring_sprintf_append(buf, "%s", host.buf);
69           break;
70     case T_CNAME:
71     case T_DNAME:
72     case T_MB:
73     case T_MG:
74     case T_MR:
75     case T_NS:
76     case T_PTR:
77           vstring_sprintf_append(buf, "%s.", rr->data);
78           break;
79     case T_TXT:
80           vstring_sprintf_append(buf, "%s", rr->data);
81           break;
82     case T_MX:
83           vstring_sprintf_append(buf, "%u %s.", rr->pref, rr->data);
84           break;
85     case T_SRV:
86           vstring_sprintf_append(buf, "%u %u %u %s.", rr->pref, rr->weight,
87                                      rr->port, rr->data);
88           break;
89     case T_TLSA:
90           if (rr->data_len >= 3) {
91               uint8_t *ip = (uint8_t *) rr->data;
92               uint8_t usage = *ip++;
93               uint8_t selector = *ip++;
94               uint8_t mtype = *ip++;
95               unsigned i;
96 
97               /* /\.example\. \d+ IN TLSA \d+ \d+ \d+ [\da-f]*$/ IGNORE */
98               vstring_sprintf_append(buf, "%d %d %d ", usage, selector, mtype);
99               for (i = 3; i < rr->data_len; ++i)
100                     vstring_sprintf_append(buf, "%02x", *ip++);
101           } else {
102               vstring_sprintf_append(buf, "[truncated record]");
103           }
104 
105           /*
106            * We use the SOA record TTL to determine the negative reply TTL. We
107            * save the time fields in the SOA record for debugging, but for now
108            * we don't bother saving the source host and mailbox information, as
109            * that would require changes to the DNS_RR structure. See also code
110            * in dns_get_rr().
111            */
112     case T_SOA:
113           memcpy(soa_buf, rr->data, sizeof(soa_buf));
114           vstring_sprintf_append(buf, "- - %u %u %u %u %u",
115                                      soa_buf[0], soa_buf[1], soa_buf[2],
116                                      soa_buf[3], soa_buf[4]);
117           break;
118     default:
119           msg_fatal("%s: don't know how to print type %s",
120                       myname, dns_strtype(rr->type));
121     }
122     return (vstring_str(buf));
123 }
124