1*e6e30c83Schristos /* $NetBSD: ns_print.c,v 1.1.1.2 2012/09/09 16:08:03 christos Exp $ */
2b5677b36Schristos
3b5677b36Schristos /*
4b5677b36Schristos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5b5677b36Schristos * Copyright (c) 1996-1999 by Internet Software Consortium.
6b5677b36Schristos *
7b5677b36Schristos * Permission to use, copy, modify, and distribute this software for any
8b5677b36Schristos * purpose with or without fee is hereby granted, provided that the above
9b5677b36Schristos * copyright notice and this permission notice appear in all copies.
10b5677b36Schristos *
11b5677b36Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12b5677b36Schristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13b5677b36Schristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14b5677b36Schristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15b5677b36Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16b5677b36Schristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17b5677b36Schristos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18b5677b36Schristos */
19b5677b36Schristos
20b5677b36Schristos #ifndef lint
21b5677b36Schristos static const char rcsid[] = "Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp ";
22b5677b36Schristos #endif
23b5677b36Schristos
24b5677b36Schristos /* Import. */
25b5677b36Schristos
26b5677b36Schristos #include "port_before.h"
27b5677b36Schristos
28b5677b36Schristos #include <sys/types.h>
29b5677b36Schristos #include <sys/socket.h>
30b5677b36Schristos
31b5677b36Schristos #include <netinet/in.h>
32b5677b36Schristos #include <arpa/nameser.h>
33b5677b36Schristos #include <arpa/inet.h>
34b5677b36Schristos
35b5677b36Schristos #include <isc/assertions.h>
36b5677b36Schristos #include <isc/dst.h>
37b5677b36Schristos #include <errno.h>
38b5677b36Schristos #include <resolv.h>
39b5677b36Schristos #include <string.h>
40b5677b36Schristos #include <ctype.h>
41b5677b36Schristos
42b5677b36Schristos #include "port_after.h"
43b5677b36Schristos
44b5677b36Schristos #ifdef SPRINTF_CHAR
45b5677b36Schristos # define SPRINTF(x) strlen(sprintf/**/x)
46b5677b36Schristos #else
47b5677b36Schristos # define SPRINTF(x) ((size_t)sprintf x)
48b5677b36Schristos #endif
49b5677b36Schristos
50b5677b36Schristos /* Forward. */
51b5677b36Schristos
52b5677b36Schristos static size_t prune_origin(const char *name, const char *origin);
53b5677b36Schristos static int charstr(const u_char *rdata, const u_char *edata,
54b5677b36Schristos char **buf, size_t *buflen);
55b5677b36Schristos static int addname(const u_char *msg, size_t msglen,
56b5677b36Schristos const u_char **p, const char *origin,
57b5677b36Schristos char **buf, size_t *buflen);
58b5677b36Schristos static void addlen(size_t len, char **buf, size_t *buflen);
59b5677b36Schristos static int addstr(const char *src, size_t len,
60b5677b36Schristos char **buf, size_t *buflen);
61b5677b36Schristos static int addtab(size_t len, size_t target, int spaced,
62b5677b36Schristos char **buf, size_t *buflen);
63b5677b36Schristos
64b5677b36Schristos /* Macros. */
65b5677b36Schristos
66b5677b36Schristos #define T(x) \
67b5677b36Schristos do { \
68b5677b36Schristos if ((x) < 0) \
69b5677b36Schristos return (-1); \
70b5677b36Schristos } while (0)
71b5677b36Schristos
72b5677b36Schristos static const char base32hex[] =
73b5677b36Schristos "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
74b5677b36Schristos
75b5677b36Schristos /* Public. */
76b5677b36Schristos
77b5677b36Schristos /*%
78b5677b36Schristos * Convert an RR to presentation format.
79b5677b36Schristos *
80b5677b36Schristos * return:
81b5677b36Schristos *\li Number of characters written to buf, or -1 (check errno).
82b5677b36Schristos */
83b5677b36Schristos int
ns_sprintrr(const ns_msg * handle,const ns_rr * rr,const char * name_ctx,const char * origin,char * buf,size_t buflen)84b5677b36Schristos ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
85b5677b36Schristos const char *name_ctx, const char *origin,
86b5677b36Schristos char *buf, size_t buflen)
87b5677b36Schristos {
88b5677b36Schristos int n;
89b5677b36Schristos
90b5677b36Schristos n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
91b5677b36Schristos ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
92b5677b36Schristos ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
93b5677b36Schristos name_ctx, origin, buf, buflen);
94b5677b36Schristos return (n);
95b5677b36Schristos }
96b5677b36Schristos
97b5677b36Schristos /*%
98b5677b36Schristos * Convert the fields of an RR into presentation format.
99b5677b36Schristos *
100b5677b36Schristos * return:
101b5677b36Schristos *\li Number of characters written to buf, or -1 (check errno).
102b5677b36Schristos */
103b5677b36Schristos int
ns_sprintrrf(const u_char * msg,size_t msglen,const char * name,ns_class class,ns_type type,u_long ttl,const u_char * rdata,size_t rdlen,const char * name_ctx,const char * origin,char * buf,size_t buflen)104b5677b36Schristos ns_sprintrrf(const u_char *msg, size_t msglen,
105b5677b36Schristos const char *name, ns_class class, ns_type type,
106b5677b36Schristos u_long ttl, const u_char *rdata, size_t rdlen,
107b5677b36Schristos const char *name_ctx, const char *origin,
108b5677b36Schristos char *buf, size_t buflen)
109b5677b36Schristos {
110b5677b36Schristos const char *obuf = buf;
111b5677b36Schristos const u_char *edata = rdata + rdlen;
112b5677b36Schristos int spaced = 0;
113b5677b36Schristos
114b5677b36Schristos const char *comment;
115b5677b36Schristos char tmp[100];
116b5677b36Schristos int len, x;
117b5677b36Schristos
118b5677b36Schristos /*
119b5677b36Schristos * Owner.
120b5677b36Schristos */
121b5677b36Schristos if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
122b5677b36Schristos T(addstr("\t\t\t", 3, &buf, &buflen));
123b5677b36Schristos } else {
124b5677b36Schristos len = prune_origin(name, origin);
125b5677b36Schristos if (*name == '\0') {
126b5677b36Schristos goto root;
127b5677b36Schristos } else if (len == 0) {
128b5677b36Schristos T(addstr("@\t\t\t", 4, &buf, &buflen));
129b5677b36Schristos } else {
130b5677b36Schristos T(addstr(name, len, &buf, &buflen));
131b5677b36Schristos /* Origin not used or not root, and no trailing dot? */
132b5677b36Schristos if (((origin == NULL || origin[0] == '\0') ||
133b5677b36Schristos (origin[0] != '.' && origin[1] != '\0' &&
134b5677b36Schristos name[len] == '\0')) && name[len - 1] != '.') {
135b5677b36Schristos root:
136b5677b36Schristos T(addstr(".", 1, &buf, &buflen));
137b5677b36Schristos len++;
138b5677b36Schristos }
139b5677b36Schristos T(spaced = addtab(len, 24, spaced, &buf, &buflen));
140b5677b36Schristos }
141b5677b36Schristos }
142b5677b36Schristos
143b5677b36Schristos /*
144b5677b36Schristos * TTL, Class, Type.
145b5677b36Schristos */
146b5677b36Schristos T(x = ns_format_ttl(ttl, buf, buflen));
147b5677b36Schristos addlen(x, &buf, &buflen);
148b5677b36Schristos len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
149b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
150b5677b36Schristos T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
151b5677b36Schristos
152b5677b36Schristos /*
153b5677b36Schristos * RData.
154b5677b36Schristos */
155b5677b36Schristos switch (type) {
156b5677b36Schristos case ns_t_a:
157b5677b36Schristos if (rdlen != (size_t)NS_INADDRSZ)
158b5677b36Schristos goto formerr;
159b5677b36Schristos (void) inet_ntop(AF_INET, rdata, buf, buflen);
160b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
161b5677b36Schristos break;
162b5677b36Schristos
163b5677b36Schristos case ns_t_cname:
164b5677b36Schristos case ns_t_mb:
165b5677b36Schristos case ns_t_mg:
166b5677b36Schristos case ns_t_mr:
167b5677b36Schristos case ns_t_ns:
168b5677b36Schristos case ns_t_ptr:
169b5677b36Schristos case ns_t_dname:
170b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
171b5677b36Schristos break;
172b5677b36Schristos
173b5677b36Schristos case ns_t_hinfo:
174b5677b36Schristos case ns_t_isdn:
175b5677b36Schristos /* First word. */
176b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
177b5677b36Schristos if (len == 0)
178b5677b36Schristos goto formerr;
179b5677b36Schristos rdata += len;
180b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
181b5677b36Schristos
182b5677b36Schristos
183b5677b36Schristos /* Second word, optional in ISDN records. */
184b5677b36Schristos if (type == ns_t_isdn && rdata == edata)
185b5677b36Schristos break;
186b5677b36Schristos
187b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
188b5677b36Schristos if (len == 0)
189b5677b36Schristos goto formerr;
190b5677b36Schristos rdata += len;
191b5677b36Schristos break;
192b5677b36Schristos
193b5677b36Schristos case ns_t_soa: {
194b5677b36Schristos u_long t;
195b5677b36Schristos
196b5677b36Schristos /* Server name. */
197b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
198b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
199b5677b36Schristos
200b5677b36Schristos /* Administrator name. */
201b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
202b5677b36Schristos T(addstr(" (\n", 3, &buf, &buflen));
203b5677b36Schristos spaced = 0;
204b5677b36Schristos
205b5677b36Schristos if ((edata - rdata) != 5*NS_INT32SZ)
206b5677b36Schristos goto formerr;
207b5677b36Schristos
208b5677b36Schristos /* Serial number. */
209b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
210b5677b36Schristos T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
211b5677b36Schristos len = SPRINTF((tmp, "%lu", t));
212b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
213b5677b36Schristos T(spaced = addtab(len, 16, spaced, &buf, &buflen));
214b5677b36Schristos T(addstr("; serial\n", 9, &buf, &buflen));
215b5677b36Schristos spaced = 0;
216b5677b36Schristos
217b5677b36Schristos /* Refresh interval. */
218b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
219b5677b36Schristos T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
220b5677b36Schristos T(len = ns_format_ttl(t, buf, buflen));
221b5677b36Schristos addlen(len, &buf, &buflen);
222b5677b36Schristos T(spaced = addtab(len, 16, spaced, &buf, &buflen));
223b5677b36Schristos T(addstr("; refresh\n", 10, &buf, &buflen));
224b5677b36Schristos spaced = 0;
225b5677b36Schristos
226b5677b36Schristos /* Retry interval. */
227b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
228b5677b36Schristos T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
229b5677b36Schristos T(len = ns_format_ttl(t, buf, buflen));
230b5677b36Schristos addlen(len, &buf, &buflen);
231b5677b36Schristos T(spaced = addtab(len, 16, spaced, &buf, &buflen));
232b5677b36Schristos T(addstr("; retry\n", 8, &buf, &buflen));
233b5677b36Schristos spaced = 0;
234b5677b36Schristos
235b5677b36Schristos /* Expiry. */
236b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
237b5677b36Schristos T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
238b5677b36Schristos T(len = ns_format_ttl(t, buf, buflen));
239b5677b36Schristos addlen(len, &buf, &buflen);
240b5677b36Schristos T(spaced = addtab(len, 16, spaced, &buf, &buflen));
241b5677b36Schristos T(addstr("; expiry\n", 9, &buf, &buflen));
242b5677b36Schristos spaced = 0;
243b5677b36Schristos
244b5677b36Schristos /* Minimum TTL. */
245b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
246b5677b36Schristos T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
247b5677b36Schristos T(len = ns_format_ttl(t, buf, buflen));
248b5677b36Schristos addlen(len, &buf, &buflen);
249b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
250b5677b36Schristos T(spaced = addtab(len, 16, spaced, &buf, &buflen));
251b5677b36Schristos T(addstr("; minimum\n", 10, &buf, &buflen));
252b5677b36Schristos
253b5677b36Schristos break;
254b5677b36Schristos }
255b5677b36Schristos
256b5677b36Schristos case ns_t_mx:
257b5677b36Schristos case ns_t_afsdb:
258b5677b36Schristos case ns_t_rt:
259b5677b36Schristos case ns_t_kx: {
260b5677b36Schristos u_int t;
261b5677b36Schristos
262b5677b36Schristos if (rdlen < (size_t)NS_INT16SZ)
263b5677b36Schristos goto formerr;
264b5677b36Schristos
265b5677b36Schristos /* Priority. */
266b5677b36Schristos t = ns_get16(rdata);
267b5677b36Schristos rdata += NS_INT16SZ;
268b5677b36Schristos len = SPRINTF((tmp, "%u ", t));
269b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
270b5677b36Schristos
271b5677b36Schristos /* Target. */
272b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
273b5677b36Schristos
274b5677b36Schristos break;
275b5677b36Schristos }
276b5677b36Schristos
277b5677b36Schristos case ns_t_px: {
278b5677b36Schristos u_int t;
279b5677b36Schristos
280b5677b36Schristos if (rdlen < (size_t)NS_INT16SZ)
281b5677b36Schristos goto formerr;
282b5677b36Schristos
283b5677b36Schristos /* Priority. */
284b5677b36Schristos t = ns_get16(rdata);
285b5677b36Schristos rdata += NS_INT16SZ;
286b5677b36Schristos len = SPRINTF((tmp, "%u ", t));
287b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
288b5677b36Schristos
289b5677b36Schristos /* Name1. */
290b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
291b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
292b5677b36Schristos
293b5677b36Schristos /* Name2. */
294b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
295b5677b36Schristos
296b5677b36Schristos break;
297b5677b36Schristos }
298b5677b36Schristos
299b5677b36Schristos case ns_t_x25:
300b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
301b5677b36Schristos if (len == 0)
302b5677b36Schristos goto formerr;
303b5677b36Schristos rdata += len;
304b5677b36Schristos break;
305b5677b36Schristos
306b5677b36Schristos case ns_t_txt:
307b5677b36Schristos case ns_t_spf:
308b5677b36Schristos while (rdata < edata) {
309b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
310b5677b36Schristos if (len == 0)
311b5677b36Schristos goto formerr;
312b5677b36Schristos rdata += len;
313b5677b36Schristos if (rdata < edata)
314b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
315b5677b36Schristos }
316b5677b36Schristos break;
317b5677b36Schristos
318b5677b36Schristos case ns_t_nsap: {
319b5677b36Schristos char t[2+255*3];
320b5677b36Schristos
321b5677b36Schristos (void) inet_nsap_ntoa(rdlen, rdata, t);
322b5677b36Schristos T(addstr(t, strlen(t), &buf, &buflen));
323b5677b36Schristos break;
324b5677b36Schristos }
325b5677b36Schristos
326b5677b36Schristos case ns_t_aaaa:
327b5677b36Schristos if (rdlen != (size_t)NS_IN6ADDRSZ)
328b5677b36Schristos goto formerr;
329b5677b36Schristos (void) inet_ntop(AF_INET6, rdata, buf, buflen);
330b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
331b5677b36Schristos break;
332b5677b36Schristos
333b5677b36Schristos case ns_t_loc: {
334b5677b36Schristos char t[255];
335b5677b36Schristos
336b5677b36Schristos /* XXX protocol format checking? */
337b5677b36Schristos (void) loc_ntoa(rdata, t);
338b5677b36Schristos T(addstr(t, strlen(t), &buf, &buflen));
339b5677b36Schristos break;
340b5677b36Schristos }
341b5677b36Schristos
342b5677b36Schristos case ns_t_naptr: {
343b5677b36Schristos u_int order, preference;
344b5677b36Schristos char t[50];
345b5677b36Schristos
346b5677b36Schristos if (rdlen < 2U*NS_INT16SZ)
347b5677b36Schristos goto formerr;
348b5677b36Schristos
349b5677b36Schristos /* Order, Precedence. */
350b5677b36Schristos order = ns_get16(rdata); rdata += NS_INT16SZ;
351b5677b36Schristos preference = ns_get16(rdata); rdata += NS_INT16SZ;
352b5677b36Schristos len = SPRINTF((t, "%u %u ", order, preference));
353b5677b36Schristos T(addstr(t, len, &buf, &buflen));
354b5677b36Schristos
355b5677b36Schristos /* Flags. */
356b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
357b5677b36Schristos if (len == 0)
358b5677b36Schristos goto formerr;
359b5677b36Schristos rdata += len;
360b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
361b5677b36Schristos
362b5677b36Schristos /* Service. */
363b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
364b5677b36Schristos if (len == 0)
365b5677b36Schristos goto formerr;
366b5677b36Schristos rdata += len;
367b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
368b5677b36Schristos
369b5677b36Schristos /* Regexp. */
370b5677b36Schristos T(len = charstr(rdata, edata, &buf, &buflen));
371b5677b36Schristos if (len < 0)
372b5677b36Schristos return (-1);
373b5677b36Schristos if (len == 0)
374b5677b36Schristos goto formerr;
375b5677b36Schristos rdata += len;
376b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
377b5677b36Schristos
378b5677b36Schristos /* Server. */
379b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
380b5677b36Schristos break;
381b5677b36Schristos }
382b5677b36Schristos
383b5677b36Schristos case ns_t_srv: {
384b5677b36Schristos u_int priority, weight, port;
385b5677b36Schristos char t[50];
386b5677b36Schristos
387b5677b36Schristos if (rdlen < 3U*NS_INT16SZ)
388b5677b36Schristos goto formerr;
389b5677b36Schristos
390b5677b36Schristos /* Priority, Weight, Port. */
391b5677b36Schristos priority = ns_get16(rdata); rdata += NS_INT16SZ;
392b5677b36Schristos weight = ns_get16(rdata); rdata += NS_INT16SZ;
393b5677b36Schristos port = ns_get16(rdata); rdata += NS_INT16SZ;
394b5677b36Schristos len = SPRINTF((t, "%u %u %u ", priority, weight, port));
395b5677b36Schristos T(addstr(t, len, &buf, &buflen));
396b5677b36Schristos
397b5677b36Schristos /* Server. */
398b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
399b5677b36Schristos break;
400b5677b36Schristos }
401b5677b36Schristos
402b5677b36Schristos case ns_t_minfo:
403b5677b36Schristos case ns_t_rp:
404b5677b36Schristos /* Name1. */
405b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
406b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
407b5677b36Schristos
408b5677b36Schristos /* Name2. */
409b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
410b5677b36Schristos
411b5677b36Schristos break;
412b5677b36Schristos
413b5677b36Schristos case ns_t_wks: {
414b5677b36Schristos int n, lcnt;
415b5677b36Schristos
416b5677b36Schristos if (rdlen < 1U + NS_INT32SZ)
417b5677b36Schristos goto formerr;
418b5677b36Schristos
419b5677b36Schristos /* Address. */
420b5677b36Schristos (void) inet_ntop(AF_INET, rdata, buf, buflen);
421b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
422b5677b36Schristos rdata += NS_INADDRSZ;
423b5677b36Schristos
424b5677b36Schristos /* Protocol. */
425b5677b36Schristos len = SPRINTF((tmp, " %u ( ", *rdata));
426b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
427b5677b36Schristos rdata += NS_INT8SZ;
428b5677b36Schristos
429b5677b36Schristos /* Bit map. */
430b5677b36Schristos n = 0;
431b5677b36Schristos lcnt = 0;
432b5677b36Schristos while (rdata < edata) {
433b5677b36Schristos u_int c = *rdata++;
434b5677b36Schristos do {
435b5677b36Schristos if (c & 0200) {
436b5677b36Schristos if (lcnt == 0) {
437b5677b36Schristos T(addstr("\n\t\t\t\t", 5,
438b5677b36Schristos &buf, &buflen));
439b5677b36Schristos lcnt = 10;
440b5677b36Schristos spaced = 0;
441b5677b36Schristos }
442b5677b36Schristos len = SPRINTF((tmp, "%d ", n));
443b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
444b5677b36Schristos lcnt--;
445b5677b36Schristos }
446b5677b36Schristos c <<= 1;
447b5677b36Schristos } while (++n & 07);
448b5677b36Schristos }
449b5677b36Schristos T(addstr(")", 1, &buf, &buflen));
450b5677b36Schristos
451b5677b36Schristos break;
452b5677b36Schristos }
453b5677b36Schristos
454b5677b36Schristos case ns_t_key:
455b5677b36Schristos case ns_t_dnskey: {
456b5677b36Schristos char base64_key[NS_MD5RSA_MAX_BASE64];
457b5677b36Schristos u_int keyflags, protocol, algorithm, key_id;
458b5677b36Schristos const char *leader;
459b5677b36Schristos int n;
460b5677b36Schristos
461b5677b36Schristos if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
462b5677b36Schristos goto formerr;
463b5677b36Schristos
464b5677b36Schristos /* Key flags, Protocol, Algorithm. */
465b5677b36Schristos key_id = dst_s_dns_key_id(rdata, edata-rdata);
466b5677b36Schristos keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
467b5677b36Schristos protocol = *rdata++;
468b5677b36Schristos algorithm = *rdata++;
469b5677b36Schristos len = SPRINTF((tmp, "0x%04x %u %u",
470b5677b36Schristos keyflags, protocol, algorithm));
471b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
472b5677b36Schristos
473b5677b36Schristos /* Public key data. */
474b5677b36Schristos len = b64_ntop(rdata, edata - rdata,
475b5677b36Schristos base64_key, sizeof base64_key);
476b5677b36Schristos if (len < 0)
477b5677b36Schristos goto formerr;
478b5677b36Schristos if (len > 15) {
479b5677b36Schristos T(addstr(" (", 2, &buf, &buflen));
480b5677b36Schristos leader = "\n\t\t";
481b5677b36Schristos spaced = 0;
482b5677b36Schristos } else
483b5677b36Schristos leader = " ";
484b5677b36Schristos for (n = 0; n < len; n += 48) {
485b5677b36Schristos T(addstr(leader, strlen(leader), &buf, &buflen));
486b5677b36Schristos T(addstr(base64_key + n, MIN(len - n, 48),
487b5677b36Schristos &buf, &buflen));
488b5677b36Schristos }
489b5677b36Schristos if (len > 15)
490b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
491b5677b36Schristos n = SPRINTF((tmp, " ; key_tag= %u", key_id));
492b5677b36Schristos T(addstr(tmp, n, &buf, &buflen));
493b5677b36Schristos
494b5677b36Schristos break;
495b5677b36Schristos }
496b5677b36Schristos
497b5677b36Schristos case ns_t_sig:
498b5677b36Schristos case ns_t_rrsig: {
499b5677b36Schristos char base64_key[NS_MD5RSA_MAX_BASE64];
500b5677b36Schristos u_int type, algorithm, labels, footprint;
501b5677b36Schristos const char *leader;
502b5677b36Schristos u_long t;
503b5677b36Schristos int n;
504b5677b36Schristos
505b5677b36Schristos if (rdlen < 22U)
506b5677b36Schristos goto formerr;
507b5677b36Schristos
508b5677b36Schristos /* Type covered, Algorithm, Label count, Original TTL. */
509b5677b36Schristos type = ns_get16(rdata); rdata += NS_INT16SZ;
510b5677b36Schristos algorithm = *rdata++;
511b5677b36Schristos labels = *rdata++;
512b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
513b5677b36Schristos len = SPRINTF((tmp, "%s %d %d %lu ",
514b5677b36Schristos p_type(type), algorithm, labels, t));
515b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
516b5677b36Schristos if (labels > (u_int)dn_count_labels(name))
517b5677b36Schristos goto formerr;
518b5677b36Schristos
519b5677b36Schristos /* Signature expiry. */
520b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
521b5677b36Schristos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
522b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
523b5677b36Schristos
524b5677b36Schristos /* Time signed. */
525b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
526b5677b36Schristos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
527b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
528b5677b36Schristos
529b5677b36Schristos /* Signature Footprint. */
530b5677b36Schristos footprint = ns_get16(rdata); rdata += NS_INT16SZ;
531b5677b36Schristos len = SPRINTF((tmp, "%u ", footprint));
532b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
533b5677b36Schristos
534b5677b36Schristos /* Signer's name. */
535b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
536b5677b36Schristos
537b5677b36Schristos /* Signature. */
538b5677b36Schristos len = b64_ntop(rdata, edata - rdata,
539b5677b36Schristos base64_key, sizeof base64_key);
540b5677b36Schristos if (len > 15) {
541b5677b36Schristos T(addstr(" (", 2, &buf, &buflen));
542b5677b36Schristos leader = "\n\t\t";
543b5677b36Schristos spaced = 0;
544b5677b36Schristos } else
545b5677b36Schristos leader = " ";
546b5677b36Schristos if (len < 0)
547b5677b36Schristos goto formerr;
548b5677b36Schristos for (n = 0; n < len; n += 48) {
549b5677b36Schristos T(addstr(leader, strlen(leader), &buf, &buflen));
550b5677b36Schristos T(addstr(base64_key + n, MIN(len - n, 48),
551b5677b36Schristos &buf, &buflen));
552b5677b36Schristos }
553b5677b36Schristos if (len > 15)
554b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
555b5677b36Schristos break;
556b5677b36Schristos }
557b5677b36Schristos
558b5677b36Schristos case ns_t_nxt: {
559b5677b36Schristos int n, c;
560b5677b36Schristos
561b5677b36Schristos /* Next domain name. */
562b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
563b5677b36Schristos
564b5677b36Schristos /* Type bit map. */
565b5677b36Schristos n = edata - rdata;
566b5677b36Schristos for (c = 0; c < n*8; c++)
567b5677b36Schristos if (NS_NXT_BIT_ISSET(c, rdata)) {
568b5677b36Schristos len = SPRINTF((tmp, " %s", p_type(c)));
569b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
570b5677b36Schristos }
571b5677b36Schristos break;
572b5677b36Schristos }
573b5677b36Schristos
574b5677b36Schristos case ns_t_cert: {
575b5677b36Schristos u_int c_type, key_tag, alg;
576b5677b36Schristos int n;
577b5677b36Schristos unsigned int siz;
578b5677b36Schristos char base64_cert[8192], tmp[40];
579b5677b36Schristos const char *leader;
580b5677b36Schristos
581b5677b36Schristos c_type = ns_get16(rdata); rdata += NS_INT16SZ;
582b5677b36Schristos key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
583b5677b36Schristos alg = (u_int) *rdata++;
584b5677b36Schristos
585b5677b36Schristos len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
586b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
587b5677b36Schristos siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
588b5677b36Schristos if (siz > sizeof(base64_cert) * 3/4) {
589b5677b36Schristos const char *str = "record too long to print";
590b5677b36Schristos T(addstr(str, strlen(str), &buf, &buflen));
591b5677b36Schristos }
592b5677b36Schristos else {
593b5677b36Schristos len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
594b5677b36Schristos
595b5677b36Schristos if (len < 0)
596b5677b36Schristos goto formerr;
597b5677b36Schristos else if (len > 15) {
598b5677b36Schristos T(addstr(" (", 2, &buf, &buflen));
599b5677b36Schristos leader = "\n\t\t";
600b5677b36Schristos spaced = 0;
601b5677b36Schristos }
602b5677b36Schristos else
603b5677b36Schristos leader = " ";
604b5677b36Schristos
605b5677b36Schristos for (n = 0; n < len; n += 48) {
606b5677b36Schristos T(addstr(leader, strlen(leader),
607b5677b36Schristos &buf, &buflen));
608b5677b36Schristos T(addstr(base64_cert + n, MIN(len - n, 48),
609b5677b36Schristos &buf, &buflen));
610b5677b36Schristos }
611b5677b36Schristos if (len > 15)
612b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
613b5677b36Schristos }
614b5677b36Schristos break;
615b5677b36Schristos }
616b5677b36Schristos
617b5677b36Schristos case ns_t_tkey: {
618b5677b36Schristos /* KJD - need to complete this */
619b5677b36Schristos u_long t;
620b5677b36Schristos int mode, err, keysize;
621b5677b36Schristos
622b5677b36Schristos /* Algorithm name. */
623b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
624b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
625b5677b36Schristos
626b5677b36Schristos /* Inception. */
627b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
628b5677b36Schristos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
629b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
630b5677b36Schristos
631b5677b36Schristos /* Experation. */
632b5677b36Schristos t = ns_get32(rdata); rdata += NS_INT32SZ;
633b5677b36Schristos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
634b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
635b5677b36Schristos
636b5677b36Schristos /* Mode , Error, Key Size. */
637b5677b36Schristos /* Priority, Weight, Port. */
638b5677b36Schristos mode = ns_get16(rdata); rdata += NS_INT16SZ;
639b5677b36Schristos err = ns_get16(rdata); rdata += NS_INT16SZ;
640b5677b36Schristos keysize = ns_get16(rdata); rdata += NS_INT16SZ;
641b5677b36Schristos len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
642b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
643b5677b36Schristos
644b5677b36Schristos /* XXX need to dump key, print otherdata length & other data */
645b5677b36Schristos break;
646b5677b36Schristos }
647b5677b36Schristos
648b5677b36Schristos case ns_t_tsig: {
649b5677b36Schristos /* BEW - need to complete this */
650b5677b36Schristos int n;
651b5677b36Schristos
652b5677b36Schristos T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
653b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
654b5677b36Schristos rdata += 8; /*%< time */
655b5677b36Schristos n = ns_get16(rdata); rdata += INT16SZ;
656b5677b36Schristos rdata += n; /*%< sig */
657b5677b36Schristos n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
658b5677b36Schristos sprintf(buf, "%d", ns_get16(rdata));
659b5677b36Schristos rdata += INT16SZ;
660b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
661b5677b36Schristos break;
662b5677b36Schristos }
663b5677b36Schristos
664b5677b36Schristos case ns_t_a6: {
665b5677b36Schristos struct in6_addr a;
666b5677b36Schristos int pbyte, pbit;
667b5677b36Schristos
668b5677b36Schristos /* prefix length */
669b5677b36Schristos if (rdlen == 0U) goto formerr;
670b5677b36Schristos len = SPRINTF((tmp, "%d ", *rdata));
671b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
672b5677b36Schristos pbit = *rdata;
673b5677b36Schristos if (pbit > 128) goto formerr;
674b5677b36Schristos pbyte = (pbit & ~7) / 8;
675b5677b36Schristos rdata++;
676b5677b36Schristos
677b5677b36Schristos /* address suffix: provided only when prefix len != 128 */
678b5677b36Schristos if (pbit < 128) {
679b5677b36Schristos if (rdata + pbyte >= edata) goto formerr;
680b5677b36Schristos memset(&a, 0, sizeof(a));
681b5677b36Schristos memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
682b5677b36Schristos (void) inet_ntop(AF_INET6, &a, buf, buflen);
683b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
684b5677b36Schristos rdata += sizeof(a) - pbyte;
685b5677b36Schristos }
686b5677b36Schristos
687b5677b36Schristos /* prefix name: provided only when prefix len > 0 */
688b5677b36Schristos if (pbit == 0)
689b5677b36Schristos break;
690b5677b36Schristos if (rdata >= edata) goto formerr;
691b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
692b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
693b5677b36Schristos
694b5677b36Schristos break;
695b5677b36Schristos }
696b5677b36Schristos
697b5677b36Schristos case ns_t_opt: {
698b5677b36Schristos len = SPRINTF((tmp, "%u bytes", class));
699b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
700b5677b36Schristos break;
701b5677b36Schristos }
702b5677b36Schristos
703b5677b36Schristos case ns_t_ds:
704b5677b36Schristos case ns_t_dlv:
705b5677b36Schristos case ns_t_sshfp: {
706b5677b36Schristos u_int t;
707b5677b36Schristos
708b5677b36Schristos if (type == ns_t_ds || type == ns_t_dlv) {
709b5677b36Schristos if (rdlen < 4U) goto formerr;
710b5677b36Schristos t = ns_get16(rdata);
711b5677b36Schristos rdata += NS_INT16SZ;
712b5677b36Schristos len = SPRINTF((tmp, "%u ", t));
713b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
714b5677b36Schristos } else
715b5677b36Schristos if (rdlen < 2U) goto formerr;
716b5677b36Schristos
717b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
718b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
719b5677b36Schristos rdata++;
720b5677b36Schristos
721b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
722b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
723b5677b36Schristos rdata++;
724b5677b36Schristos
725b5677b36Schristos while (rdata < edata) {
726b5677b36Schristos len = SPRINTF((tmp, "%02X", *rdata));
727b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
728b5677b36Schristos rdata++;
729b5677b36Schristos }
730b5677b36Schristos break;
731b5677b36Schristos }
732b5677b36Schristos
733b5677b36Schristos case ns_t_nsec3:
734b5677b36Schristos case ns_t_nsec3param: {
735b5677b36Schristos u_int t, w, l, j, k, c;
736b5677b36Schristos
737b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
738b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
739b5677b36Schristos rdata++;
740b5677b36Schristos
741b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
742b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
743b5677b36Schristos rdata++;
744b5677b36Schristos
745b5677b36Schristos t = ns_get16(rdata);
746b5677b36Schristos rdata += NS_INT16SZ;
747b5677b36Schristos len = SPRINTF((tmp, "%u ", t));
748b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
749b5677b36Schristos
750b5677b36Schristos t = *rdata++;
751b5677b36Schristos if (t == 0) {
752b5677b36Schristos T(addstr("-", 1, &buf, &buflen));
753b5677b36Schristos } else {
754b5677b36Schristos while (t-- > 0) {
755b5677b36Schristos len = SPRINTF((tmp, "%02X", *rdata));
756b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
757b5677b36Schristos rdata++;
758b5677b36Schristos }
759b5677b36Schristos }
760b5677b36Schristos if (type == ns_t_nsec3param)
761b5677b36Schristos break;
762b5677b36Schristos T(addstr(" ", 1, &buf, &buflen));
763b5677b36Schristos
764b5677b36Schristos t = *rdata++;
765b5677b36Schristos while (t > 0) {
766b5677b36Schristos switch (t) {
767b5677b36Schristos case 1:
768b5677b36Schristos tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
769b5677b36Schristos tmp[1] = base32hex[((rdata[0]<<2)&0x1c)];
770b5677b36Schristos tmp[2] = tmp[3] = tmp[4] = '=';
771b5677b36Schristos tmp[5] = tmp[6] = tmp[7] = '=';
772b5677b36Schristos break;
773b5677b36Schristos case 2:
774b5677b36Schristos tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
775b5677b36Schristos tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
776b5677b36Schristos ((rdata[1]>>6)&0x03)];
777b5677b36Schristos tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
778b5677b36Schristos tmp[3] = base32hex[((rdata[1]<<4)&0x10)];
779b5677b36Schristos tmp[4] = tmp[5] = tmp[6] = tmp[7] = '=';
780b5677b36Schristos break;
781b5677b36Schristos case 3:
782b5677b36Schristos tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
783b5677b36Schristos tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
784b5677b36Schristos ((rdata[1]>>6)&0x03)];
785b5677b36Schristos tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
786b5677b36Schristos tmp[3] = base32hex[((rdata[1]<<4)&0x10)|
787b5677b36Schristos ((rdata[2]>>4)&0x0f)];
788b5677b36Schristos tmp[4] = base32hex[((rdata[2]<<1)&0x1e)];
789b5677b36Schristos tmp[5] = tmp[6] = tmp[7] = '=';
790b5677b36Schristos break;
791b5677b36Schristos case 4:
792b5677b36Schristos tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
793b5677b36Schristos tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
794b5677b36Schristos ((rdata[1]>>6)&0x03)];
795b5677b36Schristos tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
796b5677b36Schristos tmp[3] = base32hex[((rdata[1]<<4)&0x10)|
797b5677b36Schristos ((rdata[2]>>4)&0x0f)];
798b5677b36Schristos tmp[4] = base32hex[((rdata[2]<<1)&0x1e)|
799b5677b36Schristos ((rdata[3]>>7)&0x01)];
800b5677b36Schristos tmp[5] = base32hex[((rdata[3]>>2)&0x1f)];
801b5677b36Schristos tmp[6] = base32hex[(rdata[3]<<3)&0x18];
802b5677b36Schristos tmp[7] = '=';
803b5677b36Schristos break;
804b5677b36Schristos default:
805b5677b36Schristos tmp[0] = base32hex[((rdata[0]>>3)&0x1f)];
806b5677b36Schristos tmp[1] = base32hex[((rdata[0]<<2)&0x1c)|
807b5677b36Schristos ((rdata[1]>>6)&0x03)];
808b5677b36Schristos tmp[2] = base32hex[((rdata[1]>>1)&0x1f)];
809b5677b36Schristos tmp[3] = base32hex[((rdata[1]<<4)&0x10)|
810b5677b36Schristos ((rdata[2]>>4)&0x0f)];
811b5677b36Schristos tmp[4] = base32hex[((rdata[2]<<1)&0x1e)|
812b5677b36Schristos ((rdata[3]>>7)&0x01)];
813b5677b36Schristos tmp[5] = base32hex[((rdata[3]>>2)&0x1f)];
814b5677b36Schristos tmp[6] = base32hex[((rdata[3]<<3)&0x18)|
815b5677b36Schristos ((rdata[4]>>5)&0x07)];
816b5677b36Schristos tmp[7] = base32hex[(rdata[4]&0x1f)];
817b5677b36Schristos break;
818b5677b36Schristos }
819b5677b36Schristos T(addstr(tmp, 8, &buf, &buflen));
820b5677b36Schristos if (t >= 5) {
821b5677b36Schristos rdata += 5;
822b5677b36Schristos t -= 5;
823b5677b36Schristos } else {
824b5677b36Schristos rdata += t;
825b5677b36Schristos t -= t;
826b5677b36Schristos }
827b5677b36Schristos }
828b5677b36Schristos
829b5677b36Schristos while (rdata < edata) {
830b5677b36Schristos w = *rdata++;
831b5677b36Schristos l = *rdata++;
832b5677b36Schristos for (j = 0; j < l; j++) {
833b5677b36Schristos if (rdata[j] == 0)
834b5677b36Schristos continue;
835b5677b36Schristos for (k = 0; k < 8; k++) {
836b5677b36Schristos if ((rdata[j] & (0x80 >> k)) == 0)
837b5677b36Schristos continue;
838b5677b36Schristos c = w * 256 + j * 8 + k;
839b5677b36Schristos len = SPRINTF((tmp, " %s", p_type(c)));
840b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
841b5677b36Schristos }
842b5677b36Schristos }
843b5677b36Schristos rdata += l;
844b5677b36Schristos }
845b5677b36Schristos break;
846b5677b36Schristos }
847b5677b36Schristos
848b5677b36Schristos case ns_t_nsec: {
849b5677b36Schristos u_int w, l, j, k, c;
850b5677b36Schristos
851b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
852b5677b36Schristos
853b5677b36Schristos while (rdata < edata) {
854b5677b36Schristos w = *rdata++;
855b5677b36Schristos l = *rdata++;
856b5677b36Schristos for (j = 0; j < l; j++) {
857b5677b36Schristos if (rdata[j] == 0)
858b5677b36Schristos continue;
859b5677b36Schristos for (k = 0; k < 8; k++) {
860b5677b36Schristos if ((rdata[j] & (0x80 >> k)) == 0)
861b5677b36Schristos continue;
862b5677b36Schristos c = w * 256 + j * 8 + k;
863b5677b36Schristos len = SPRINTF((tmp, " %s", p_type(c)));
864b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
865b5677b36Schristos }
866b5677b36Schristos }
867b5677b36Schristos rdata += l;
868b5677b36Schristos }
869b5677b36Schristos break;
870b5677b36Schristos }
871b5677b36Schristos
872b5677b36Schristos case ns_t_dhcid: {
873b5677b36Schristos int n;
874b5677b36Schristos unsigned int siz;
875b5677b36Schristos char base64_dhcid[8192];
876b5677b36Schristos const char *leader;
877b5677b36Schristos
878b5677b36Schristos siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
879b5677b36Schristos if (siz > sizeof(base64_dhcid) * 3/4) {
880b5677b36Schristos const char *str = "record too long to print";
881b5677b36Schristos T(addstr(str, strlen(str), &buf, &buflen));
882b5677b36Schristos } else {
883b5677b36Schristos len = b64_ntop(rdata, edata-rdata, base64_dhcid, siz);
884b5677b36Schristos
885b5677b36Schristos if (len < 0)
886b5677b36Schristos goto formerr;
887b5677b36Schristos
888b5677b36Schristos else if (len > 15) {
889b5677b36Schristos T(addstr(" (", 2, &buf, &buflen));
890b5677b36Schristos leader = "\n\t\t";
891b5677b36Schristos spaced = 0;
892b5677b36Schristos }
893b5677b36Schristos else
894b5677b36Schristos leader = " ";
895b5677b36Schristos
896b5677b36Schristos for (n = 0; n < len; n += 48) {
897b5677b36Schristos T(addstr(leader, strlen(leader),
898b5677b36Schristos &buf, &buflen));
899b5677b36Schristos T(addstr(base64_dhcid + n, MIN(len - n, 48),
900b5677b36Schristos &buf, &buflen));
901b5677b36Schristos }
902b5677b36Schristos if (len > 15)
903b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
904b5677b36Schristos }
905b5677b36Schristos }
906b5677b36Schristos
907b5677b36Schristos case ns_t_ipseckey: {
908b5677b36Schristos int n;
909b5677b36Schristos unsigned int siz;
910b5677b36Schristos char base64_key[8192];
911b5677b36Schristos const char *leader;
912b5677b36Schristos
913b5677b36Schristos if (rdlen < 2)
914b5677b36Schristos goto formerr;
915b5677b36Schristos
916b5677b36Schristos switch (rdata[1]) {
917b5677b36Schristos case 0:
918b5677b36Schristos case 3:
919b5677b36Schristos if (rdlen < 3)
920b5677b36Schristos goto formerr;
921b5677b36Schristos break;
922b5677b36Schristos case 1:
923b5677b36Schristos if (rdlen < 7)
924b5677b36Schristos goto formerr;
925b5677b36Schristos break;
926b5677b36Schristos case 2:
927b5677b36Schristos if (rdlen < 19)
928b5677b36Schristos goto formerr;
929b5677b36Schristos break;
930b5677b36Schristos default:
931b5677b36Schristos comment = "unknown IPSECKEY gateway type";
932b5677b36Schristos goto hexify;
933b5677b36Schristos }
934b5677b36Schristos
935b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
936b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
937b5677b36Schristos rdata++;
938b5677b36Schristos
939b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
940b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
941b5677b36Schristos rdata++;
942b5677b36Schristos
943b5677b36Schristos len = SPRINTF((tmp, "%u ", *rdata));
944b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
945b5677b36Schristos rdata++;
946b5677b36Schristos
947b5677b36Schristos switch (rdata[-2]) {
948b5677b36Schristos case 0:
949b5677b36Schristos T(addstr(".", 1, &buf, &buflen));
950b5677b36Schristos break;
951b5677b36Schristos case 1:
952b5677b36Schristos (void) inet_ntop(AF_INET, rdata, buf, buflen);
953b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
954b5677b36Schristos rdata += 4;
955b5677b36Schristos break;
956b5677b36Schristos case 2:
957b5677b36Schristos (void) inet_ntop(AF_INET6, rdata, buf, buflen);
958b5677b36Schristos addlen(strlen(buf), &buf, &buflen);
959b5677b36Schristos rdata += 16;
960b5677b36Schristos break;
961b5677b36Schristos case 3:
962b5677b36Schristos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
963b5677b36Schristos break;
964b5677b36Schristos }
965b5677b36Schristos
966b5677b36Schristos if (rdata >= edata)
967b5677b36Schristos break;
968b5677b36Schristos
969b5677b36Schristos siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
970b5677b36Schristos if (siz > sizeof(base64_key) * 3/4) {
971b5677b36Schristos const char *str = "record too long to print";
972b5677b36Schristos T(addstr(str, strlen(str), &buf, &buflen));
973b5677b36Schristos } else {
974b5677b36Schristos len = b64_ntop(rdata, edata-rdata, base64_key, siz);
975b5677b36Schristos
976b5677b36Schristos if (len < 0)
977b5677b36Schristos goto formerr;
978b5677b36Schristos
979b5677b36Schristos else if (len > 15) {
980b5677b36Schristos T(addstr(" (", 2, &buf, &buflen));
981b5677b36Schristos leader = "\n\t\t";
982b5677b36Schristos spaced = 0;
983b5677b36Schristos }
984b5677b36Schristos else
985b5677b36Schristos leader = " ";
986b5677b36Schristos
987b5677b36Schristos for (n = 0; n < len; n += 48) {
988b5677b36Schristos T(addstr(leader, strlen(leader),
989b5677b36Schristos &buf, &buflen));
990b5677b36Schristos T(addstr(base64_key + n, MIN(len - n, 48),
991b5677b36Schristos &buf, &buflen));
992b5677b36Schristos }
993b5677b36Schristos if (len > 15)
994b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
995b5677b36Schristos }
996b5677b36Schristos }
997b5677b36Schristos
998b5677b36Schristos case ns_t_hip: {
999b5677b36Schristos unsigned int i, hip_len, algorithm, key_len;
1000b5677b36Schristos char base64_key[NS_MD5RSA_MAX_BASE64];
1001b5677b36Schristos unsigned int siz;
1002b5677b36Schristos const char *leader = "\n\t\t\t\t\t";
1003b5677b36Schristos
1004b5677b36Schristos hip_len = *rdata++;
1005b5677b36Schristos algorithm = *rdata++;
1006b5677b36Schristos key_len = ns_get16(rdata);
1007b5677b36Schristos rdata += NS_INT16SZ;
1008b5677b36Schristos
1009b5677b36Schristos siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */
1010b5677b36Schristos if (siz > sizeof(base64_key) * 3/4) {
1011b5677b36Schristos const char *str = "record too long to print";
1012b5677b36Schristos T(addstr(str, strlen(str), &buf, &buflen));
1013b5677b36Schristos } else {
1014b5677b36Schristos len = sprintf(tmp, "( %u ", algorithm);
1015b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
1016b5677b36Schristos
1017b5677b36Schristos for (i = 0; i < hip_len; i++) {
1018b5677b36Schristos len = sprintf(tmp, "%02X", *rdata);
1019b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
1020b5677b36Schristos rdata++;
1021b5677b36Schristos }
1022b5677b36Schristos T(addstr(leader, strlen(leader), &buf, &buflen));
1023b5677b36Schristos
1024b5677b36Schristos len = b64_ntop(rdata, key_len, base64_key, siz);
1025b5677b36Schristos if (len < 0)
1026b5677b36Schristos goto formerr;
1027b5677b36Schristos
1028b5677b36Schristos T(addstr(base64_key, len, &buf, &buflen));
1029b5677b36Schristos
1030b5677b36Schristos rdata += key_len;
1031b5677b36Schristos while (rdata < edata) {
1032b5677b36Schristos T(addstr(leader, strlen(leader), &buf, &buflen));
1033b5677b36Schristos T(addname(msg, msglen, &rdata, origin,
1034b5677b36Schristos &buf, &buflen));
1035b5677b36Schristos }
1036b5677b36Schristos T(addstr(" )", 2, &buf, &buflen));
1037b5677b36Schristos }
1038b5677b36Schristos break;
1039b5677b36Schristos }
1040b5677b36Schristos
1041b5677b36Schristos default:
1042b5677b36Schristos comment = "unknown RR type";
1043b5677b36Schristos goto hexify;
1044b5677b36Schristos }
1045b5677b36Schristos return (buf - obuf);
1046b5677b36Schristos formerr:
1047b5677b36Schristos comment = "RR format error";
1048b5677b36Schristos hexify: {
1049b5677b36Schristos int n, m;
1050b5677b36Schristos char *p;
1051b5677b36Schristos
1052b5677b36Schristos len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
1053b5677b36Schristos rdlen != 0U ? " (" : "", comment));
1054b5677b36Schristos T(addstr(tmp, len, &buf, &buflen));
1055b5677b36Schristos while (rdata < edata) {
1056b5677b36Schristos p = tmp;
1057b5677b36Schristos p += SPRINTF((p, "\n\t"));
1058b5677b36Schristos spaced = 0;
1059b5677b36Schristos n = MIN(16, edata - rdata);
1060b5677b36Schristos for (m = 0; m < n; m++)
1061b5677b36Schristos p += SPRINTF((p, "%02x ", rdata[m]));
1062b5677b36Schristos T(addstr(tmp, p - tmp, &buf, &buflen));
1063b5677b36Schristos if (n < 16) {
1064b5677b36Schristos T(addstr(")", 1, &buf, &buflen));
1065b5677b36Schristos T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
1066b5677b36Schristos }
1067b5677b36Schristos p = tmp;
1068b5677b36Schristos p += SPRINTF((p, "; "));
1069b5677b36Schristos for (m = 0; m < n; m++)
1070b5677b36Schristos *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
1071b5677b36Schristos ? rdata[m]
1072b5677b36Schristos : '.';
1073b5677b36Schristos T(addstr(tmp, p - tmp, &buf, &buflen));
1074b5677b36Schristos rdata += n;
1075b5677b36Schristos }
1076b5677b36Schristos return (buf - obuf);
1077b5677b36Schristos }
1078b5677b36Schristos }
1079b5677b36Schristos
1080b5677b36Schristos /* Private. */
1081b5677b36Schristos
1082b5677b36Schristos /*%
1083b5677b36Schristos * size_t
1084b5677b36Schristos * prune_origin(name, origin)
1085b5677b36Schristos * Find out if the name is at or under the current origin.
1086b5677b36Schristos * return:
1087b5677b36Schristos * Number of characters in name before start of origin,
1088b5677b36Schristos * or length of name if origin does not match.
1089b5677b36Schristos * notes:
1090b5677b36Schristos * This function should share code with samedomain().
1091b5677b36Schristos */
1092b5677b36Schristos static size_t
prune_origin(const char * name,const char * origin)1093b5677b36Schristos prune_origin(const char *name, const char *origin) {
1094b5677b36Schristos const char *oname = name;
1095b5677b36Schristos
1096b5677b36Schristos while (*name != '\0') {
1097b5677b36Schristos if (origin != NULL && ns_samename(name, origin) == 1)
1098b5677b36Schristos return (name - oname - (name > oname));
1099b5677b36Schristos while (*name != '\0') {
1100b5677b36Schristos if (*name == '\\') {
1101b5677b36Schristos name++;
1102b5677b36Schristos /* XXX need to handle \nnn form. */
1103b5677b36Schristos if (*name == '\0')
1104b5677b36Schristos break;
1105b5677b36Schristos } else if (*name == '.') {
1106b5677b36Schristos name++;
1107b5677b36Schristos break;
1108b5677b36Schristos }
1109b5677b36Schristos name++;
1110b5677b36Schristos }
1111b5677b36Schristos }
1112b5677b36Schristos return (name - oname);
1113b5677b36Schristos }
1114b5677b36Schristos
1115b5677b36Schristos /*%
1116b5677b36Schristos * int
1117b5677b36Schristos * charstr(rdata, edata, buf, buflen)
1118b5677b36Schristos * Format a <character-string> into the presentation buffer.
1119b5677b36Schristos * return:
1120b5677b36Schristos * Number of rdata octets consumed
1121b5677b36Schristos * 0 for protocol format error
1122b5677b36Schristos * -1 for output buffer error
1123b5677b36Schristos * side effects:
1124b5677b36Schristos * buffer is advanced on success.
1125b5677b36Schristos */
1126b5677b36Schristos static int
charstr(const u_char * rdata,const u_char * edata,char ** buf,size_t * buflen)1127b5677b36Schristos charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
1128b5677b36Schristos const u_char *odata = rdata;
1129b5677b36Schristos size_t save_buflen = *buflen;
1130b5677b36Schristos char *save_buf = *buf;
1131b5677b36Schristos
1132b5677b36Schristos if (addstr("\"", 1, buf, buflen) < 0)
1133b5677b36Schristos goto enospc;
1134b5677b36Schristos if (rdata < edata) {
1135b5677b36Schristos int n = *rdata;
1136b5677b36Schristos
1137b5677b36Schristos if (rdata + 1 + n <= edata) {
1138b5677b36Schristos rdata++;
1139b5677b36Schristos while (n-- > 0) {
1140b5677b36Schristos if (strchr("\n\"\\", *rdata) != NULL)
1141b5677b36Schristos if (addstr("\\", 1, buf, buflen) < 0)
1142b5677b36Schristos goto enospc;
1143b5677b36Schristos if (addstr((const char *)rdata, 1,
1144b5677b36Schristos buf, buflen) < 0)
1145b5677b36Schristos goto enospc;
1146b5677b36Schristos rdata++;
1147b5677b36Schristos }
1148b5677b36Schristos }
1149b5677b36Schristos }
1150b5677b36Schristos if (addstr("\"", 1, buf, buflen) < 0)
1151b5677b36Schristos goto enospc;
1152b5677b36Schristos return (rdata - odata);
1153b5677b36Schristos enospc:
1154b5677b36Schristos errno = ENOSPC;
1155b5677b36Schristos *buf = save_buf;
1156b5677b36Schristos *buflen = save_buflen;
1157b5677b36Schristos return (-1);
1158b5677b36Schristos }
1159b5677b36Schristos
1160b5677b36Schristos static int
addname(const u_char * msg,size_t msglen,const u_char ** pp,const char * origin,char ** buf,size_t * buflen)1161b5677b36Schristos addname(const u_char *msg, size_t msglen,
1162b5677b36Schristos const u_char **pp, const char *origin,
1163b5677b36Schristos char **buf, size_t *buflen)
1164b5677b36Schristos {
1165b5677b36Schristos size_t newlen, save_buflen = *buflen;
1166b5677b36Schristos char *save_buf = *buf;
1167b5677b36Schristos int n;
1168b5677b36Schristos
1169b5677b36Schristos n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
1170b5677b36Schristos if (n < 0)
1171b5677b36Schristos goto enospc; /*%< Guess. */
1172b5677b36Schristos newlen = prune_origin(*buf, origin);
1173b5677b36Schristos if (**buf == '\0') {
1174b5677b36Schristos goto root;
1175b5677b36Schristos } else if (newlen == 0U) {
1176b5677b36Schristos /* Use "@" instead of name. */
1177b5677b36Schristos if (newlen + 2 > *buflen)
1178b5677b36Schristos goto enospc; /* No room for "@\0". */
1179b5677b36Schristos (*buf)[newlen++] = '@';
1180b5677b36Schristos (*buf)[newlen] = '\0';
1181b5677b36Schristos } else {
1182b5677b36Schristos if (((origin == NULL || origin[0] == '\0') ||
1183b5677b36Schristos (origin[0] != '.' && origin[1] != '\0' &&
1184b5677b36Schristos (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
1185b5677b36Schristos /* No trailing dot. */
1186b5677b36Schristos root:
1187b5677b36Schristos if (newlen + 2 > *buflen)
1188b5677b36Schristos goto enospc; /* No room for ".\0". */
1189b5677b36Schristos (*buf)[newlen++] = '.';
1190b5677b36Schristos (*buf)[newlen] = '\0';
1191b5677b36Schristos }
1192b5677b36Schristos }
1193b5677b36Schristos *pp += n;
1194b5677b36Schristos addlen(newlen, buf, buflen);
1195b5677b36Schristos **buf = '\0';
1196b5677b36Schristos return (newlen);
1197b5677b36Schristos enospc:
1198b5677b36Schristos errno = ENOSPC;
1199b5677b36Schristos *buf = save_buf;
1200b5677b36Schristos *buflen = save_buflen;
1201b5677b36Schristos return (-1);
1202b5677b36Schristos }
1203b5677b36Schristos
1204b5677b36Schristos static void
addlen(size_t len,char ** buf,size_t * buflen)1205b5677b36Schristos addlen(size_t len, char **buf, size_t *buflen) {
1206b5677b36Schristos INSIST(len <= *buflen);
1207b5677b36Schristos *buf += len;
1208b5677b36Schristos *buflen -= len;
1209b5677b36Schristos }
1210b5677b36Schristos
1211b5677b36Schristos static int
addstr(const char * src,size_t len,char ** buf,size_t * buflen)1212b5677b36Schristos addstr(const char *src, size_t len, char **buf, size_t *buflen) {
1213b5677b36Schristos if (len >= *buflen) {
1214b5677b36Schristos errno = ENOSPC;
1215b5677b36Schristos return (-1);
1216b5677b36Schristos }
1217b5677b36Schristos memcpy(*buf, src, len);
1218b5677b36Schristos addlen(len, buf, buflen);
1219b5677b36Schristos **buf = '\0';
1220b5677b36Schristos return (0);
1221b5677b36Schristos }
1222b5677b36Schristos
1223b5677b36Schristos static int
addtab(size_t len,size_t target,int spaced,char ** buf,size_t * buflen)1224b5677b36Schristos addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
1225b5677b36Schristos size_t save_buflen = *buflen;
1226b5677b36Schristos char *save_buf = *buf;
1227b5677b36Schristos int t;
1228b5677b36Schristos
1229b5677b36Schristos if (spaced || len >= target - 1) {
1230b5677b36Schristos T(addstr(" ", 2, buf, buflen));
1231b5677b36Schristos spaced = 1;
1232b5677b36Schristos } else {
1233b5677b36Schristos for (t = (target - len - 1) / 8; t >= 0; t--)
1234b5677b36Schristos if (addstr("\t", 1, buf, buflen) < 0) {
1235b5677b36Schristos *buflen = save_buflen;
1236b5677b36Schristos *buf = save_buf;
1237b5677b36Schristos return (-1);
1238b5677b36Schristos }
1239b5677b36Schristos spaced = 0;
1240b5677b36Schristos }
1241b5677b36Schristos return (spaced);
1242b5677b36Schristos }
1243b5677b36Schristos
1244b5677b36Schristos /*! \file */
1245