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
52char   *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