ns_print.c revision 1.2 1 1.2 christos /* $NetBSD: ns_print.c,v 1.2 2004/05/20 20:35:05 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.1 christos static const char rcsid[] = "Id: ns_print.c,v 1.3.2.1.4.4 2004/03/17 01:13:36 marka Exp";
24 1.2 christos #else
25 1.2 christos __RCSID("$NetBSD: ns_print.c,v 1.2 2004/05/20 20:35:05 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.1 christos /* Public. */
78 1.1 christos
79 1.1 christos /*
80 1.1 christos * int
81 1.1 christos * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
82 1.1 christos * Convert an RR to presentation format.
83 1.1 christos * return:
84 1.1 christos * Number of characters written to buf, or -1 (check errno).
85 1.1 christos */
86 1.1 christos int
87 1.1 christos ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
88 1.1 christos const char *name_ctx, const char *origin,
89 1.1 christos char *buf, size_t buflen)
90 1.1 christos {
91 1.1 christos int n;
92 1.1 christos
93 1.1 christos n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
94 1.1 christos ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
95 1.1 christos ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
96 1.1 christos name_ctx, origin, buf, buflen);
97 1.1 christos return (n);
98 1.1 christos }
99 1.1 christos
100 1.1 christos /*
101 1.1 christos * int
102 1.1 christos * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
103 1.1 christos * name_ctx, origin, buf, buflen)
104 1.1 christos * Convert the fields of an RR into presentation format.
105 1.1 christos * return:
106 1.1 christos * 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.1 christos if (rdlen == 0U)
156 1.1 christos return (buf - obuf);
157 1.2 christos T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
158 1.1 christos
159 1.1 christos /*
160 1.1 christos * RData.
161 1.1 christos */
162 1.1 christos switch (type) {
163 1.1 christos case ns_t_a:
164 1.1 christos if (rdlen != (size_t)NS_INADDRSZ)
165 1.1 christos goto formerr;
166 1.1 christos (void) inet_ntop(AF_INET, rdata, buf, buflen);
167 1.1 christos addlen(strlen(buf), &buf, &buflen);
168 1.1 christos break;
169 1.1 christos
170 1.1 christos case ns_t_cname:
171 1.1 christos case ns_t_mb:
172 1.1 christos case ns_t_mg:
173 1.1 christos case ns_t_mr:
174 1.1 christos case ns_t_ns:
175 1.1 christos case ns_t_ptr:
176 1.1 christos case ns_t_dname:
177 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
178 1.1 christos break;
179 1.1 christos
180 1.1 christos case ns_t_hinfo:
181 1.1 christos case ns_t_isdn:
182 1.1 christos /* First word. */
183 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
184 1.1 christos if (len == 0)
185 1.1 christos goto formerr;
186 1.1 christos rdata += len;
187 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
188 1.1 christos
189 1.1 christos
190 1.1 christos /* Second word, optional in ISDN records. */
191 1.1 christos if (type == ns_t_isdn && rdata == edata)
192 1.1 christos break;
193 1.1 christos
194 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
195 1.1 christos if (len == 0)
196 1.1 christos goto formerr;
197 1.1 christos rdata += len;
198 1.1 christos break;
199 1.1 christos
200 1.1 christos case ns_t_soa: {
201 1.1 christos u_long t;
202 1.1 christos
203 1.1 christos /* Server name. */
204 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
205 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
206 1.1 christos
207 1.1 christos /* Administrator name. */
208 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
209 1.2 christos T(addstr(" (\n", (size_t)3, &buf, &buflen));
210 1.1 christos spaced = 0;
211 1.1 christos
212 1.1 christos if ((edata - rdata) != 5*NS_INT32SZ)
213 1.1 christos goto formerr;
214 1.1 christos
215 1.1 christos /* Serial number. */
216 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
217 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
218 1.1 christos len = SPRINTF((tmp, "%lu", t));
219 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
220 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
221 1.2 christos T(addstr("; serial\n", (size_t)9, &buf, &buflen));
222 1.1 christos spaced = 0;
223 1.1 christos
224 1.1 christos /* Refresh interval. */
225 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
226 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
227 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
228 1.2 christos addlen((size_t)len, &buf, &buflen);
229 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
230 1.2 christos T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
231 1.1 christos spaced = 0;
232 1.1 christos
233 1.1 christos /* Retry interval. */
234 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
235 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
236 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
237 1.2 christos addlen((size_t)len, &buf, &buflen);
238 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
239 1.2 christos T(addstr("; retry\n", (size_t)8, &buf, &buflen));
240 1.1 christos spaced = 0;
241 1.1 christos
242 1.1 christos /* Expiry. */
243 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
244 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
245 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
246 1.2 christos addlen((size_t)len, &buf, &buflen);
247 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
248 1.2 christos T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
249 1.1 christos spaced = 0;
250 1.1 christos
251 1.1 christos /* Minimum TTL. */
252 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
253 1.2 christos T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
254 1.1 christos T(len = ns_format_ttl(t, buf, buflen));
255 1.2 christos addlen((size_t)len, &buf, &buflen);
256 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
257 1.2 christos T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
258 1.2 christos T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
259 1.1 christos
260 1.1 christos break;
261 1.1 christos }
262 1.1 christos
263 1.1 christos case ns_t_mx:
264 1.1 christos case ns_t_afsdb:
265 1.1 christos case ns_t_rt: {
266 1.1 christos u_int t;
267 1.1 christos
268 1.1 christos if (rdlen < (size_t)NS_INT16SZ)
269 1.1 christos goto formerr;
270 1.1 christos
271 1.1 christos /* Priority. */
272 1.1 christos t = ns_get16(rdata);
273 1.1 christos rdata += NS_INT16SZ;
274 1.1 christos len = SPRINTF((tmp, "%u ", t));
275 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
276 1.1 christos
277 1.1 christos /* Target. */
278 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
279 1.1 christos
280 1.1 christos break;
281 1.1 christos }
282 1.1 christos
283 1.1 christos case ns_t_px: {
284 1.1 christos u_int t;
285 1.1 christos
286 1.1 christos if (rdlen < (size_t)NS_INT16SZ)
287 1.1 christos goto formerr;
288 1.1 christos
289 1.1 christos /* Priority. */
290 1.1 christos t = ns_get16(rdata);
291 1.1 christos rdata += NS_INT16SZ;
292 1.1 christos len = SPRINTF((tmp, "%u ", t));
293 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
294 1.1 christos
295 1.1 christos /* Name1. */
296 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
297 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
298 1.1 christos
299 1.1 christos /* Name2. */
300 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
301 1.1 christos
302 1.1 christos break;
303 1.1 christos }
304 1.1 christos
305 1.1 christos case ns_t_x25:
306 1.1 christos T(len = charstr(rdata, edata, &buf, &buflen));
307 1.1 christos if (len == 0)
308 1.1 christos goto formerr;
309 1.1 christos rdata += len;
310 1.1 christos break;
311 1.1 christos
312 1.1 christos case ns_t_txt:
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.1 christos case ns_t_key: {
460 1.1 christos char base64_key[NS_MD5RSA_MAX_BASE64];
461 1.1 christos u_int keyflags, protocol, algorithm, key_id;
462 1.1 christos const char *leader;
463 1.1 christos int n;
464 1.1 christos
465 1.1 christos if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
466 1.1 christos goto formerr;
467 1.1 christos
468 1.1 christos /* Key flags, Protocol, Algorithm. */
469 1.1 christos key_id = dst_s_dns_key_id(rdata, edata-rdata);
470 1.1 christos keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
471 1.1 christos protocol = *rdata++;
472 1.1 christos algorithm = *rdata++;
473 1.1 christos len = SPRINTF((tmp, "0x%04x %u %u",
474 1.1 christos keyflags, protocol, algorithm));
475 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
476 1.1 christos
477 1.1 christos /* Public key data. */
478 1.2 christos len = b64_ntop(rdata, (size_t)(edata - rdata),
479 1.1 christos base64_key, sizeof base64_key);
480 1.1 christos if (len < 0)
481 1.1 christos goto formerr;
482 1.1 christos if (len > 15) {
483 1.2 christos T(addstr(" (", (size_t)2, &buf, &buflen));
484 1.1 christos leader = "\n\t\t";
485 1.1 christos spaced = 0;
486 1.1 christos } else
487 1.1 christos leader = " ";
488 1.1 christos for (n = 0; n < len; n += 48) {
489 1.1 christos T(addstr(leader, strlen(leader), &buf, &buflen));
490 1.2 christos T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
491 1.1 christos &buf, &buflen));
492 1.1 christos }
493 1.1 christos if (len > 15)
494 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
495 1.1 christos n = SPRINTF((tmp, " ; key_tag= %u", key_id));
496 1.2 christos T(addstr(tmp, (size_t)n, &buf, &buflen));
497 1.1 christos
498 1.1 christos break;
499 1.1 christos }
500 1.1 christos
501 1.1 christos case ns_t_sig: {
502 1.1 christos char base64_key[NS_MD5RSA_MAX_BASE64];
503 1.2 christos u_int typ, algorithm, labels, footprint;
504 1.1 christos const char *leader;
505 1.1 christos u_long t;
506 1.1 christos int n;
507 1.1 christos
508 1.1 christos if (rdlen < 22U)
509 1.1 christos goto formerr;
510 1.1 christos
511 1.1 christos /* Type covered, Algorithm, Label count, Original TTL. */
512 1.2 christos typ = ns_get16(rdata); rdata += NS_INT16SZ;
513 1.1 christos algorithm = *rdata++;
514 1.1 christos labels = *rdata++;
515 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
516 1.1 christos len = SPRINTF((tmp, "%s %d %d %lu ",
517 1.2 christos p_type((int)typ), algorithm, labels, t));
518 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
519 1.1 christos if (labels > (u_int)dn_count_labels(name))
520 1.1 christos goto formerr;
521 1.1 christos
522 1.1 christos /* Signature expiry. */
523 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
524 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
525 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
526 1.1 christos
527 1.1 christos /* Time signed. */
528 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
529 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
530 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
531 1.1 christos
532 1.1 christos /* Signature Footprint. */
533 1.1 christos footprint = ns_get16(rdata); rdata += NS_INT16SZ;
534 1.1 christos len = SPRINTF((tmp, "%u ", footprint));
535 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
536 1.1 christos
537 1.1 christos /* Signer's name. */
538 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
539 1.1 christos
540 1.1 christos /* Signature. */
541 1.2 christos len = b64_ntop(rdata, (size_t)(edata - rdata),
542 1.1 christos base64_key, sizeof base64_key);
543 1.1 christos if (len > 15) {
544 1.2 christos T(addstr(" (", (size_t)2, &buf, &buflen));
545 1.1 christos leader = "\n\t\t";
546 1.1 christos spaced = 0;
547 1.1 christos } else
548 1.1 christos leader = " ";
549 1.1 christos if (len < 0)
550 1.1 christos goto formerr;
551 1.1 christos for (n = 0; n < len; n += 48) {
552 1.1 christos T(addstr(leader, strlen(leader), &buf, &buflen));
553 1.2 christos T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
554 1.1 christos &buf, &buflen));
555 1.1 christos }
556 1.1 christos if (len > 15)
557 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
558 1.1 christos break;
559 1.1 christos }
560 1.1 christos
561 1.1 christos case ns_t_nxt: {
562 1.1 christos int n, c;
563 1.1 christos
564 1.1 christos /* Next domain name. */
565 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
566 1.1 christos
567 1.1 christos /* Type bit map. */
568 1.1 christos n = edata - rdata;
569 1.1 christos for (c = 0; c < n*8; c++)
570 1.1 christos if (NS_NXT_BIT_ISSET(c, rdata)) {
571 1.1 christos len = SPRINTF((tmp, " %s", p_type(c)));
572 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
573 1.1 christos }
574 1.1 christos break;
575 1.1 christos }
576 1.1 christos
577 1.1 christos case ns_t_cert: {
578 1.1 christos u_int c_type, key_tag, alg;
579 1.1 christos int n;
580 1.1 christos unsigned int siz;
581 1.2 christos char base64_cert[8192], tmp1[40];
582 1.1 christos const char *leader;
583 1.1 christos
584 1.1 christos c_type = ns_get16(rdata); rdata += NS_INT16SZ;
585 1.1 christos key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
586 1.1 christos alg = (u_int) *rdata++;
587 1.1 christos
588 1.2 christos len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
589 1.2 christos T(addstr(tmp1, (size_t)len, &buf, &buflen));
590 1.1 christos siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
591 1.1 christos if (siz > sizeof(base64_cert) * 3/4) {
592 1.1 christos const char *str = "record too long to print";
593 1.1 christos T(addstr(str, strlen(str), &buf, &buflen));
594 1.1 christos }
595 1.1 christos else {
596 1.2 christos len = b64_ntop(rdata, (size_t)(edata-rdata),
597 1.2 christos base64_cert, siz);
598 1.1 christos
599 1.1 christos if (len < 0)
600 1.1 christos goto formerr;
601 1.1 christos else if (len > 15) {
602 1.2 christos T(addstr(" (", (size_t)2, &buf, &buflen));
603 1.1 christos leader = "\n\t\t";
604 1.1 christos spaced = 0;
605 1.1 christos }
606 1.1 christos else
607 1.1 christos leader = " ";
608 1.1 christos
609 1.1 christos for (n = 0; n < len; n += 48) {
610 1.1 christos T(addstr(leader, strlen(leader),
611 1.1 christos &buf, &buflen));
612 1.2 christos T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
613 1.1 christos &buf, &buflen));
614 1.1 christos }
615 1.1 christos if (len > 15)
616 1.2 christos T(addstr(" )", (size_t)2, &buf, &buflen));
617 1.1 christos }
618 1.1 christos break;
619 1.1 christos }
620 1.1 christos
621 1.1 christos case ns_t_tkey: {
622 1.1 christos /* KJD - need to complete this */
623 1.1 christos u_long t;
624 1.1 christos int mode, err, keysize;
625 1.1 christos
626 1.1 christos /* Algorithm name. */
627 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
628 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
629 1.1 christos
630 1.1 christos /* Inception. */
631 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
632 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
633 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
634 1.1 christos
635 1.1 christos /* Experation. */
636 1.1 christos t = ns_get32(rdata); rdata += NS_INT32SZ;
637 1.1 christos len = SPRINTF((tmp, "%s ", p_secstodate(t)));
638 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
639 1.1 christos
640 1.1 christos /* Mode , Error, Key Size. */
641 1.1 christos /* Priority, Weight, Port. */
642 1.1 christos mode = ns_get16(rdata); rdata += NS_INT16SZ;
643 1.1 christos err = ns_get16(rdata); rdata += NS_INT16SZ;
644 1.1 christos keysize = ns_get16(rdata); rdata += NS_INT16SZ;
645 1.1 christos len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
646 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
647 1.1 christos
648 1.1 christos /* XXX need to dump key, print otherdata length & other data */
649 1.1 christos break;
650 1.1 christos }
651 1.1 christos
652 1.1 christos case ns_t_tsig: {
653 1.1 christos /* BEW - need to complete this */
654 1.1 christos int n;
655 1.1 christos
656 1.1 christos T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
657 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
658 1.1 christos rdata += 8; /* time */
659 1.1 christos n = ns_get16(rdata); rdata += INT16SZ;
660 1.1 christos rdata += n; /* sig */
661 1.1 christos n = ns_get16(rdata); rdata += INT16SZ; /* original id */
662 1.1 christos sprintf(buf, "%d", ns_get16(rdata));
663 1.1 christos rdata += INT16SZ;
664 1.1 christos addlen(strlen(buf), &buf, &buflen);
665 1.1 christos break;
666 1.1 christos }
667 1.1 christos
668 1.1 christos case ns_t_a6: {
669 1.1 christos struct in6_addr a;
670 1.1 christos int pbyte, pbit;
671 1.1 christos
672 1.1 christos /* prefix length */
673 1.1 christos if (rdlen == 0U) goto formerr;
674 1.1 christos len = SPRINTF((tmp, "%d ", *rdata));
675 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
676 1.1 christos pbit = *rdata;
677 1.1 christos if (pbit > 128) goto formerr;
678 1.1 christos pbyte = (pbit & ~7) / 8;
679 1.1 christos rdata++;
680 1.1 christos
681 1.1 christos /* address suffix: provided only when prefix len != 128 */
682 1.1 christos if (pbit < 128) {
683 1.1 christos if (rdata + pbyte >= edata) goto formerr;
684 1.1 christos memset(&a, 0, sizeof(a));
685 1.1 christos memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
686 1.1 christos (void) inet_ntop(AF_INET6, &a, buf, buflen);
687 1.1 christos addlen(strlen(buf), &buf, &buflen);
688 1.1 christos rdata += sizeof(a) - pbyte;
689 1.1 christos }
690 1.1 christos
691 1.1 christos /* prefix name: provided only when prefix len > 0 */
692 1.1 christos if (pbit == 0)
693 1.1 christos break;
694 1.1 christos if (rdata >= edata) goto formerr;
695 1.2 christos T(addstr(" ", (size_t)1, &buf, &buflen));
696 1.1 christos T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
697 1.1 christos
698 1.1 christos break;
699 1.1 christos }
700 1.1 christos
701 1.1 christos case ns_t_opt: {
702 1.1 christos len = SPRINTF((tmp, "%u bytes", class));
703 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
704 1.1 christos break;
705 1.1 christos }
706 1.1 christos
707 1.1 christos default:
708 1.1 christos comment = "unknown RR type";
709 1.1 christos goto hexify;
710 1.1 christos }
711 1.1 christos return (buf - obuf);
712 1.1 christos formerr:
713 1.1 christos comment = "RR format error";
714 1.1 christos hexify: {
715 1.1 christos int n, m;
716 1.1 christos char *p;
717 1.1 christos
718 1.1 christos len = SPRINTF((tmp, "\\# %u (\t; %s", edata - rdata, comment));
719 1.2 christos T(addstr(tmp, (size_t)len, &buf, &buflen));
720 1.1 christos while (rdata < edata) {
721 1.1 christos p = tmp;
722 1.1 christos p += SPRINTF((p, "\n\t"));
723 1.1 christos spaced = 0;
724 1.1 christos n = MIN(16, edata - rdata);
725 1.1 christos for (m = 0; m < n; m++)
726 1.1 christos p += SPRINTF((p, "%02x ", rdata[m]));
727 1.2 christos T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
728 1.1 christos if (n < 16) {
729 1.2 christos T(addstr(")", (size_t)1, &buf, &buflen));
730 1.2 christos T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
731 1.1 christos }
732 1.1 christos p = tmp;
733 1.1 christos p += SPRINTF((p, "; "));
734 1.1 christos for (m = 0; m < n; m++)
735 1.1 christos *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
736 1.1 christos ? rdata[m]
737 1.1 christos : '.';
738 1.2 christos T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
739 1.1 christos rdata += n;
740 1.1 christos }
741 1.1 christos return (buf - obuf);
742 1.1 christos }
743 1.1 christos }
744 1.1 christos
745 1.1 christos /* Private. */
746 1.1 christos
747 1.1 christos /*
748 1.1 christos * size_t
749 1.1 christos * prune_origin(name, origin)
750 1.1 christos * Find out if the name is at or under the current origin.
751 1.1 christos * return:
752 1.1 christos * Number of characters in name before start of origin,
753 1.1 christos * or length of name if origin does not match.
754 1.1 christos * notes:
755 1.1 christos * This function should share code with samedomain().
756 1.1 christos */
757 1.1 christos static size_t
758 1.1 christos prune_origin(const char *name, const char *origin) {
759 1.1 christos const char *oname = name;
760 1.1 christos
761 1.1 christos while (*name != '\0') {
762 1.1 christos if (origin != NULL && ns_samename(name, origin) == 1)
763 1.1 christos return (name - oname - (name > oname));
764 1.1 christos while (*name != '\0') {
765 1.1 christos if (*name == '\\') {
766 1.1 christos name++;
767 1.1 christos /* XXX need to handle \nnn form. */
768 1.1 christos if (*name == '\0')
769 1.1 christos break;
770 1.1 christos } else if (*name == '.') {
771 1.1 christos name++;
772 1.1 christos break;
773 1.1 christos }
774 1.1 christos name++;
775 1.1 christos }
776 1.1 christos }
777 1.1 christos return (name - oname);
778 1.1 christos }
779 1.1 christos
780 1.1 christos /*
781 1.1 christos * int
782 1.1 christos * charstr(rdata, edata, buf, buflen)
783 1.1 christos * Format a <character-string> into the presentation buffer.
784 1.1 christos * return:
785 1.1 christos * Number of rdata octets consumed
786 1.1 christos * 0 for protocol format error
787 1.1 christos * -1 for output buffer error
788 1.1 christos * side effects:
789 1.1 christos * buffer is advanced on success.
790 1.1 christos */
791 1.1 christos static int
792 1.1 christos charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
793 1.1 christos const u_char *odata = rdata;
794 1.1 christos size_t save_buflen = *buflen;
795 1.1 christos char *save_buf = *buf;
796 1.1 christos
797 1.2 christos if (addstr("\"", (size_t)1, buf, buflen) < 0)
798 1.1 christos goto enospc;
799 1.1 christos if (rdata < edata) {
800 1.1 christos int n = *rdata;
801 1.1 christos
802 1.1 christos if (rdata + 1 + n <= edata) {
803 1.1 christos rdata++;
804 1.1 christos while (n-- > 0) {
805 1.1 christos if (strchr("\n\"\\", *rdata) != NULL)
806 1.2 christos if (addstr("\\", (size_t)1, buf, buflen) < 0)
807 1.1 christos goto enospc;
808 1.2 christos if (addstr((const char *)rdata, (size_t)1,
809 1.1 christos buf, buflen) < 0)
810 1.1 christos goto enospc;
811 1.1 christos rdata++;
812 1.1 christos }
813 1.1 christos }
814 1.1 christos }
815 1.2 christos if (addstr("\"", (size_t)1, buf, buflen) < 0)
816 1.1 christos goto enospc;
817 1.1 christos return (rdata - odata);
818 1.1 christos enospc:
819 1.1 christos errno = ENOSPC;
820 1.1 christos *buf = save_buf;
821 1.1 christos *buflen = save_buflen;
822 1.1 christos return (-1);
823 1.1 christos }
824 1.1 christos
825 1.1 christos static int
826 1.1 christos addname(const u_char *msg, size_t msglen,
827 1.1 christos const u_char **pp, const char *origin,
828 1.1 christos char **buf, size_t *buflen)
829 1.1 christos {
830 1.1 christos size_t newlen, save_buflen = *buflen;
831 1.1 christos char *save_buf = *buf;
832 1.1 christos int n;
833 1.1 christos
834 1.2 christos n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
835 1.1 christos if (n < 0)
836 1.1 christos goto enospc; /* Guess. */
837 1.1 christos newlen = prune_origin(*buf, origin);
838 1.1 christos if (**buf == '\0') {
839 1.1 christos goto root;
840 1.1 christos } else if (newlen == 0U) {
841 1.1 christos /* Use "@" instead of name. */
842 1.1 christos if (newlen + 2 > *buflen)
843 1.1 christos goto enospc; /* No room for "@\0". */
844 1.1 christos (*buf)[newlen++] = '@';
845 1.1 christos (*buf)[newlen] = '\0';
846 1.1 christos } else {
847 1.1 christos if (((origin == NULL || origin[0] == '\0') ||
848 1.1 christos (origin[0] != '.' && origin[1] != '\0' &&
849 1.1 christos (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
850 1.1 christos /* No trailing dot. */
851 1.1 christos root:
852 1.1 christos if (newlen + 2 > *buflen)
853 1.1 christos goto enospc; /* No room for ".\0". */
854 1.1 christos (*buf)[newlen++] = '.';
855 1.1 christos (*buf)[newlen] = '\0';
856 1.1 christos }
857 1.1 christos }
858 1.1 christos *pp += n;
859 1.1 christos addlen(newlen, buf, buflen);
860 1.1 christos **buf = '\0';
861 1.1 christos return (newlen);
862 1.1 christos enospc:
863 1.1 christos errno = ENOSPC;
864 1.1 christos *buf = save_buf;
865 1.1 christos *buflen = save_buflen;
866 1.1 christos return (-1);
867 1.1 christos }
868 1.1 christos
869 1.1 christos static void
870 1.1 christos addlen(size_t len, char **buf, size_t *buflen) {
871 1.1 christos INSIST(len <= *buflen);
872 1.1 christos *buf += len;
873 1.1 christos *buflen -= len;
874 1.1 christos }
875 1.1 christos
876 1.1 christos static int
877 1.1 christos addstr(const char *src, size_t len, char **buf, size_t *buflen) {
878 1.1 christos if (len >= *buflen) {
879 1.1 christos errno = ENOSPC;
880 1.1 christos return (-1);
881 1.1 christos }
882 1.1 christos memcpy(*buf, src, len);
883 1.1 christos addlen(len, buf, buflen);
884 1.1 christos **buf = '\0';
885 1.1 christos return (0);
886 1.1 christos }
887 1.1 christos
888 1.1 christos static int
889 1.1 christos addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
890 1.1 christos size_t save_buflen = *buflen;
891 1.1 christos char *save_buf = *buf;
892 1.1 christos int t;
893 1.1 christos
894 1.1 christos if (spaced || len >= target - 1) {
895 1.2 christos T(addstr(" ", (size_t)2, buf, buflen));
896 1.1 christos spaced = 1;
897 1.1 christos } else {
898 1.1 christos for (t = (target - len - 1) / 8; t >= 0; t--)
899 1.2 christos if (addstr("\t", (size_t)1, buf, buflen) < 0) {
900 1.1 christos *buflen = save_buflen;
901 1.1 christos *buf = save_buf;
902 1.1 christos return (-1);
903 1.1 christos }
904 1.1 christos spaced = 0;
905 1.1 christos }
906 1.1 christos return (spaced);
907 1.1 christos }
908