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