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