|
1 /* $NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $ */ |
|
2 |
|
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 /* |
|
21 * This version of this file is derived from Android 2.3 "Gingerbread", |
|
22 * which contains uncredited changes by Android/Google developers. It has |
|
23 * been modified in 2011 for use in the Android build of Mozilla Firefox by |
|
24 * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>, |
|
25 * and Steve Workman <sjhworkman@gmail.com>). |
|
26 * These changes are offered under the same license as the original NetBSD |
|
27 * file, whose copyright and license are unchanged above. |
|
28 */ |
|
29 |
|
30 #define ANDROID_CHANGES 1 |
|
31 #define MOZILLA_NECKO_EXCLUDE_CODE 1 |
|
32 |
|
33 #include <sys/cdefs.h> |
|
34 #ifndef lint |
|
35 #ifdef notdef |
|
36 static const char rcsid[] = "Id: ns_print.c,v 1.3.2.1.4.5 2004/07/28 20:16:45 marka Exp"; |
|
37 #else |
|
38 __RCSID("$NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $"); |
|
39 #endif |
|
40 #endif |
|
41 |
|
42 /* Import. */ |
|
43 |
|
44 #include <sys/types.h> |
|
45 #include <sys/socket.h> |
|
46 |
|
47 #include <netinet/in.h> |
|
48 #include "arpa_nameser.h" |
|
49 #include <arpa/inet.h> |
|
50 |
|
51 #include "assertions.h" |
|
52 #include "dst.h" |
|
53 #include <errno.h> |
|
54 #ifdef ANDROID_CHANGES |
|
55 #include "resolv_private.h" |
|
56 #else |
|
57 #include <resolv.h> |
|
58 #endif |
|
59 #include <string.h> |
|
60 #include <ctype.h> |
|
61 #include <assert.h> |
|
62 |
|
63 #ifdef SPRINTF_CHAR |
|
64 # define SPRINTF(x) strlen(sprintf/**/x) |
|
65 #else |
|
66 # define SPRINTF(x) ((size_t)sprintf x) |
|
67 #endif |
|
68 |
|
69 #ifndef MIN |
|
70 #define MIN(x,y) ((x)<(y)?(x):(y)) |
|
71 #endif |
|
72 |
|
73 /* Forward. */ |
|
74 |
|
75 static size_t prune_origin(const char *name, const char *origin); |
|
76 static int charstr(const u_char *rdata, const u_char *edata, |
|
77 char **buf, size_t *buflen); |
|
78 static int addname(const u_char *msg, size_t msglen, |
|
79 const u_char **p, const char *origin, |
|
80 char **buf, size_t *buflen); |
|
81 static void addlen(size_t len, char **buf, size_t *buflen); |
|
82 static int addstr(const char *src, size_t len, |
|
83 char **buf, size_t *buflen); |
|
84 static int addtab(size_t len, size_t target, int spaced, |
|
85 char **buf, size_t *buflen); |
|
86 |
|
87 /* Macros. */ |
|
88 |
|
89 #define T(x) \ |
|
90 do { \ |
|
91 if ((x) < 0) \ |
|
92 return (-1); \ |
|
93 } while (/*CONSTCOND*/0) |
|
94 |
|
95 /* Public. */ |
|
96 |
|
97 /* |
|
98 * int |
|
99 * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) |
|
100 * Convert an RR to presentation format. |
|
101 * return: |
|
102 * Number of characters written to buf, or -1 (check errno). |
|
103 */ |
|
104 int |
|
105 ns_sprintrr(const ns_msg *handle, const ns_rr *rr, |
|
106 const char *name_ctx, const char *origin, |
|
107 char *buf, size_t buflen) |
|
108 { |
|
109 int n; |
|
110 |
|
111 n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), |
|
112 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), |
|
113 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), |
|
114 name_ctx, origin, buf, buflen); |
|
115 return (n); |
|
116 } |
|
117 |
|
118 /* |
|
119 * int |
|
120 * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, |
|
121 * name_ctx, origin, buf, buflen) |
|
122 * Convert the fields of an RR into presentation format. |
|
123 * return: |
|
124 * Number of characters written to buf, or -1 (check errno). |
|
125 */ |
|
126 int |
|
127 ns_sprintrrf(const u_char *msg, size_t msglen, |
|
128 const char *name, ns_class class, ns_type type, |
|
129 u_long ttl, const u_char *rdata, size_t rdlen, |
|
130 const char *name_ctx, const char *origin, |
|
131 char *buf, size_t buflen) |
|
132 { |
|
133 const char *obuf = buf; |
|
134 const u_char *edata = rdata + rdlen; |
|
135 int spaced = 0; |
|
136 |
|
137 const char *comment; |
|
138 char tmp[100]; |
|
139 int len, x; |
|
140 |
|
141 /* |
|
142 * Owner. |
|
143 */ |
|
144 if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { |
|
145 T(addstr("\t\t\t", (size_t)3, &buf, &buflen)); |
|
146 } else { |
|
147 len = prune_origin(name, origin); |
|
148 if (*name == '\0') { |
|
149 goto root; |
|
150 } else if (len == 0) { |
|
151 T(addstr("@\t\t\t", (size_t)4, &buf, &buflen)); |
|
152 } else { |
|
153 T(addstr(name, (size_t)len, &buf, &buflen)); |
|
154 /* Origin not used or not root, and no trailing dot? */ |
|
155 if (((origin == NULL || origin[0] == '\0') || |
|
156 (origin[0] != '.' && origin[1] != '\0' && |
|
157 name[len] == '\0')) && name[len - 1] != '.') { |
|
158 root: |
|
159 T(addstr(".", (size_t)1, &buf, &buflen)); |
|
160 len++; |
|
161 } |
|
162 T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen)); |
|
163 } |
|
164 } |
|
165 |
|
166 /* |
|
167 * TTL, Class, Type. |
|
168 */ |
|
169 T(x = ns_format_ttl(ttl, buf, buflen)); |
|
170 addlen((size_t)x, &buf, &buflen); |
|
171 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); |
|
172 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
173 T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen)); |
|
174 |
|
175 /* |
|
176 * RData. |
|
177 */ |
|
178 switch (type) { |
|
179 case ns_t_a: |
|
180 if (rdlen != (size_t)NS_INADDRSZ) |
|
181 goto formerr; |
|
182 (void) inet_ntop(AF_INET, rdata, buf, buflen); |
|
183 addlen(strlen(buf), &buf, &buflen); |
|
184 break; |
|
185 |
|
186 case ns_t_cname: |
|
187 case ns_t_mb: |
|
188 case ns_t_mg: |
|
189 case ns_t_mr: |
|
190 case ns_t_ns: |
|
191 case ns_t_ptr: |
|
192 case ns_t_dname: |
|
193 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
194 break; |
|
195 |
|
196 case ns_t_hinfo: |
|
197 case ns_t_isdn: |
|
198 /* First word. */ |
|
199 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
200 if (len == 0) |
|
201 goto formerr; |
|
202 rdata += len; |
|
203 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
204 |
|
205 |
|
206 /* Second word, optional in ISDN records. */ |
|
207 if (type == ns_t_isdn && rdata == edata) |
|
208 break; |
|
209 |
|
210 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
211 if (len == 0) |
|
212 goto formerr; |
|
213 rdata += len; |
|
214 break; |
|
215 |
|
216 case ns_t_soa: { |
|
217 u_long t; |
|
218 |
|
219 /* Server name. */ |
|
220 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
221 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
222 |
|
223 /* Administrator name. */ |
|
224 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
225 T(addstr(" (\n", (size_t)3, &buf, &buflen)); |
|
226 spaced = 0; |
|
227 |
|
228 if ((edata - rdata) != 5*NS_INT32SZ) |
|
229 goto formerr; |
|
230 |
|
231 /* Serial number. */ |
|
232 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
233 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); |
|
234 len = SPRINTF((tmp, "%lu", t)); |
|
235 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
236 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); |
|
237 T(addstr("; serial\n", (size_t)9, &buf, &buflen)); |
|
238 spaced = 0; |
|
239 |
|
240 /* Refresh interval. */ |
|
241 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
242 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); |
|
243 T(len = ns_format_ttl(t, buf, buflen)); |
|
244 addlen((size_t)len, &buf, &buflen); |
|
245 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); |
|
246 T(addstr("; refresh\n", (size_t)10, &buf, &buflen)); |
|
247 spaced = 0; |
|
248 |
|
249 /* Retry interval. */ |
|
250 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
251 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); |
|
252 T(len = ns_format_ttl(t, buf, buflen)); |
|
253 addlen((size_t)len, &buf, &buflen); |
|
254 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); |
|
255 T(addstr("; retry\n", (size_t)8, &buf, &buflen)); |
|
256 spaced = 0; |
|
257 |
|
258 /* Expiry. */ |
|
259 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
260 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); |
|
261 T(len = ns_format_ttl(t, buf, buflen)); |
|
262 addlen((size_t)len, &buf, &buflen); |
|
263 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); |
|
264 T(addstr("; expiry\n", (size_t)9, &buf, &buflen)); |
|
265 spaced = 0; |
|
266 |
|
267 /* Minimum TTL. */ |
|
268 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
269 T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen)); |
|
270 T(len = ns_format_ttl(t, buf, buflen)); |
|
271 addlen((size_t)len, &buf, &buflen); |
|
272 T(addstr(" )", (size_t)2, &buf, &buflen)); |
|
273 T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen)); |
|
274 T(addstr("; minimum\n", (size_t)10, &buf, &buflen)); |
|
275 |
|
276 break; |
|
277 } |
|
278 |
|
279 case ns_t_mx: |
|
280 case ns_t_afsdb: |
|
281 case ns_t_rt: { |
|
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; |
|
290 len = SPRINTF((tmp, "%u ", t)); |
|
291 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
292 |
|
293 /* Target. */ |
|
294 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
295 |
|
296 break; |
|
297 } |
|
298 |
|
299 case ns_t_px: { |
|
300 u_int t; |
|
301 |
|
302 if (rdlen < (size_t)NS_INT16SZ) |
|
303 goto formerr; |
|
304 |
|
305 /* Priority. */ |
|
306 t = ns_get16(rdata); |
|
307 rdata += NS_INT16SZ; |
|
308 len = SPRINTF((tmp, "%u ", t)); |
|
309 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
310 |
|
311 /* Name1. */ |
|
312 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
313 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
314 |
|
315 /* Name2. */ |
|
316 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
317 |
|
318 break; |
|
319 } |
|
320 |
|
321 case ns_t_x25: |
|
322 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
323 if (len == 0) |
|
324 goto formerr; |
|
325 rdata += len; |
|
326 break; |
|
327 |
|
328 case ns_t_txt: |
|
329 while (rdata < edata) { |
|
330 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
331 if (len == 0) |
|
332 goto formerr; |
|
333 rdata += len; |
|
334 if (rdata < edata) |
|
335 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
336 } |
|
337 break; |
|
338 |
|
339 case ns_t_nsap: { |
|
340 char t[2+255*3]; |
|
341 |
|
342 (void) inet_nsap_ntoa((int)rdlen, rdata, t); |
|
343 T(addstr(t, strlen(t), &buf, &buflen)); |
|
344 break; |
|
345 } |
|
346 |
|
347 case ns_t_aaaa: |
|
348 if (rdlen != (size_t)NS_IN6ADDRSZ) |
|
349 goto formerr; |
|
350 (void) inet_ntop(AF_INET6, rdata, buf, buflen); |
|
351 addlen(strlen(buf), &buf, &buflen); |
|
352 break; |
|
353 |
|
354 case ns_t_loc: { |
|
355 char t[255]; |
|
356 |
|
357 /* XXX protocol format checking? */ |
|
358 (void) loc_ntoa(rdata, t); |
|
359 T(addstr(t, strlen(t), &buf, &buflen)); |
|
360 break; |
|
361 } |
|
362 |
|
363 case ns_t_naptr: { |
|
364 u_int order, preference; |
|
365 char t[50]; |
|
366 |
|
367 if (rdlen < 2U*NS_INT16SZ) |
|
368 goto formerr; |
|
369 |
|
370 /* Order, Precedence. */ |
|
371 order = ns_get16(rdata); rdata += NS_INT16SZ; |
|
372 preference = ns_get16(rdata); rdata += NS_INT16SZ; |
|
373 len = SPRINTF((t, "%u %u ", order, preference)); |
|
374 T(addstr(t, (size_t)len, &buf, &buflen)); |
|
375 |
|
376 /* Flags. */ |
|
377 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
378 if (len == 0) |
|
379 goto formerr; |
|
380 rdata += len; |
|
381 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
382 |
|
383 /* Service. */ |
|
384 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
385 if (len == 0) |
|
386 goto formerr; |
|
387 rdata += len; |
|
388 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
389 |
|
390 /* Regexp. */ |
|
391 T(len = charstr(rdata, edata, &buf, &buflen)); |
|
392 if (len < 0) |
|
393 return (-1); |
|
394 if (len == 0) |
|
395 goto formerr; |
|
396 rdata += len; |
|
397 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
398 |
|
399 /* Server. */ |
|
400 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
401 break; |
|
402 } |
|
403 |
|
404 case ns_t_srv: { |
|
405 u_int priority, weight, port; |
|
406 char t[50]; |
|
407 |
|
408 if (rdlen < 3U*NS_INT16SZ) |
|
409 goto formerr; |
|
410 |
|
411 /* Priority, Weight, Port. */ |
|
412 priority = ns_get16(rdata); rdata += NS_INT16SZ; |
|
413 weight = ns_get16(rdata); rdata += NS_INT16SZ; |
|
414 port = ns_get16(rdata); rdata += NS_INT16SZ; |
|
415 len = SPRINTF((t, "%u %u %u ", priority, weight, port)); |
|
416 T(addstr(t, (size_t)len, &buf, &buflen)); |
|
417 |
|
418 /* Server. */ |
|
419 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
420 break; |
|
421 } |
|
422 |
|
423 case ns_t_minfo: |
|
424 case ns_t_rp: |
|
425 /* Name1. */ |
|
426 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
427 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
428 |
|
429 /* Name2. */ |
|
430 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
431 |
|
432 break; |
|
433 |
|
434 case ns_t_wks: { |
|
435 int n, lcnt; |
|
436 |
|
437 if (rdlen < 1U + NS_INT32SZ) |
|
438 goto formerr; |
|
439 |
|
440 /* Address. */ |
|
441 (void) inet_ntop(AF_INET, rdata, buf, buflen); |
|
442 addlen(strlen(buf), &buf, &buflen); |
|
443 rdata += NS_INADDRSZ; |
|
444 |
|
445 /* Protocol. */ |
|
446 len = SPRINTF((tmp, " %u ( ", *rdata)); |
|
447 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
448 rdata += NS_INT8SZ; |
|
449 |
|
450 /* Bit map. */ |
|
451 n = 0; |
|
452 lcnt = 0; |
|
453 while (rdata < edata) { |
|
454 u_int c = *rdata++; |
|
455 do { |
|
456 if (c & 0200) { |
|
457 if (lcnt == 0) { |
|
458 T(addstr("\n\t\t\t\t", (size_t)5, |
|
459 &buf, &buflen)); |
|
460 lcnt = 10; |
|
461 spaced = 0; |
|
462 } |
|
463 len = SPRINTF((tmp, "%d ", n)); |
|
464 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
465 lcnt--; |
|
466 } |
|
467 c <<= 1; |
|
468 } while (++n & 07); |
|
469 } |
|
470 T(addstr(")", (size_t)1, &buf, &buflen)); |
|
471 |
|
472 break; |
|
473 } |
|
474 |
|
475 case ns_t_key: { |
|
476 char base64_key[NS_MD5RSA_MAX_BASE64]; |
|
477 u_int keyflags, protocol, algorithm, key_id; |
|
478 const char *leader; |
|
479 int n; |
|
480 |
|
481 if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) |
|
482 goto formerr; |
|
483 |
|
484 /* Key flags, Protocol, Algorithm. */ |
|
485 #if !defined(MOZILLA_NECKO_EXCLUDE_CODE) && !defined(_LIBC) |
|
486 key_id = dst_s_dns_key_id(rdata, edata-rdata); |
|
487 #else |
|
488 key_id = 0; |
|
489 #endif |
|
490 keyflags = ns_get16(rdata); rdata += NS_INT16SZ; |
|
491 protocol = *rdata++; |
|
492 algorithm = *rdata++; |
|
493 len = SPRINTF((tmp, "0x%04x %u %u", |
|
494 keyflags, protocol, algorithm)); |
|
495 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
496 |
|
497 /* Public key data. */ |
|
498 len = b64_ntop(rdata, (size_t)(edata - rdata), |
|
499 base64_key, sizeof base64_key); |
|
500 if (len < 0) |
|
501 goto formerr; |
|
502 if (len > 15) { |
|
503 T(addstr(" (", (size_t)2, &buf, &buflen)); |
|
504 leader = "\n\t\t"; |
|
505 spaced = 0; |
|
506 } else |
|
507 leader = " "; |
|
508 for (n = 0; n < len; n += 48) { |
|
509 T(addstr(leader, strlen(leader), &buf, &buflen)); |
|
510 T(addstr(base64_key + n, (size_t)MIN(len - n, 48), |
|
511 &buf, &buflen)); |
|
512 } |
|
513 if (len > 15) |
|
514 T(addstr(" )", (size_t)2, &buf, &buflen)); |
|
515 n = SPRINTF((tmp, " ; key_tag= %u", key_id)); |
|
516 T(addstr(tmp, (size_t)n, &buf, &buflen)); |
|
517 |
|
518 break; |
|
519 } |
|
520 |
|
521 case ns_t_sig: { |
|
522 char base64_key[NS_MD5RSA_MAX_BASE64]; |
|
523 u_int typ, algorithm, labels, footprint; |
|
524 const char *leader; |
|
525 u_long t; |
|
526 int n; |
|
527 |
|
528 if (rdlen < 22U) |
|
529 goto formerr; |
|
530 |
|
531 /* Type covered, Algorithm, Label count, Original TTL. */ |
|
532 typ = ns_get16(rdata); rdata += NS_INT16SZ; |
|
533 algorithm = *rdata++; |
|
534 labels = *rdata++; |
|
535 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
536 len = SPRINTF((tmp, "%s %d %d %lu ", |
|
537 p_type((int)typ), algorithm, labels, t)); |
|
538 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
539 if (labels > (u_int)dn_count_labels(name)) |
|
540 goto formerr; |
|
541 |
|
542 /* Signature expiry. */ |
|
543 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
544 len = SPRINTF((tmp, "%s ", p_secstodate(t))); |
|
545 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
546 |
|
547 /* Time signed. */ |
|
548 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
549 len = SPRINTF((tmp, "%s ", p_secstodate(t))); |
|
550 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
551 |
|
552 /* Signature Footprint. */ |
|
553 footprint = ns_get16(rdata); rdata += NS_INT16SZ; |
|
554 len = SPRINTF((tmp, "%u ", footprint)); |
|
555 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
556 |
|
557 /* Signer's name. */ |
|
558 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
559 |
|
560 /* Signature. */ |
|
561 len = b64_ntop(rdata, (size_t)(edata - rdata), |
|
562 base64_key, sizeof base64_key); |
|
563 if (len > 15) { |
|
564 T(addstr(" (", (size_t)2, &buf, &buflen)); |
|
565 leader = "\n\t\t"; |
|
566 spaced = 0; |
|
567 } else |
|
568 leader = " "; |
|
569 if (len < 0) |
|
570 goto formerr; |
|
571 for (n = 0; n < len; n += 48) { |
|
572 T(addstr(leader, strlen(leader), &buf, &buflen)); |
|
573 T(addstr(base64_key + n, (size_t)MIN(len - n, 48), |
|
574 &buf, &buflen)); |
|
575 } |
|
576 if (len > 15) |
|
577 T(addstr(" )", (size_t)2, &buf, &buflen)); |
|
578 break; |
|
579 } |
|
580 |
|
581 case ns_t_nxt: { |
|
582 int n, c; |
|
583 |
|
584 /* Next domain name. */ |
|
585 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
586 |
|
587 /* Type bit map. */ |
|
588 n = edata - rdata; |
|
589 for (c = 0; c < n*8; c++) |
|
590 if (NS_NXT_BIT_ISSET(c, rdata)) { |
|
591 len = SPRINTF((tmp, " %s", p_type(c))); |
|
592 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
593 } |
|
594 break; |
|
595 } |
|
596 |
|
597 case ns_t_cert: { |
|
598 u_int c_type, key_tag, alg; |
|
599 int n; |
|
600 unsigned int siz; |
|
601 char base64_cert[8192], tmp1[40]; |
|
602 const char *leader; |
|
603 |
|
604 c_type = ns_get16(rdata); rdata += NS_INT16SZ; |
|
605 key_tag = ns_get16(rdata); rdata += NS_INT16SZ; |
|
606 alg = (u_int) *rdata++; |
|
607 |
|
608 len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg)); |
|
609 T(addstr(tmp1, (size_t)len, &buf, &buflen)); |
|
610 siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ |
|
611 if (siz > sizeof(base64_cert) * 3/4) { |
|
612 const char *str = "record too long to print"; |
|
613 T(addstr(str, strlen(str), &buf, &buflen)); |
|
614 } |
|
615 else { |
|
616 len = b64_ntop(rdata, (size_t)(edata-rdata), |
|
617 base64_cert, siz); |
|
618 |
|
619 if (len < 0) |
|
620 goto formerr; |
|
621 else if (len > 15) { |
|
622 T(addstr(" (", (size_t)2, &buf, &buflen)); |
|
623 leader = "\n\t\t"; |
|
624 spaced = 0; |
|
625 } |
|
626 else |
|
627 leader = " "; |
|
628 |
|
629 for (n = 0; n < len; n += 48) { |
|
630 T(addstr(leader, strlen(leader), |
|
631 &buf, &buflen)); |
|
632 T(addstr(base64_cert + n, (size_t)MIN(len - n, 48), |
|
633 &buf, &buflen)); |
|
634 } |
|
635 if (len > 15) |
|
636 T(addstr(" )", (size_t)2, &buf, &buflen)); |
|
637 } |
|
638 break; |
|
639 } |
|
640 |
|
641 case ns_t_tkey: { |
|
642 /* KJD - need to complete this */ |
|
643 u_long t; |
|
644 int mode, err, keysize; |
|
645 |
|
646 /* Algorithm name. */ |
|
647 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
648 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
649 |
|
650 /* Inception. */ |
|
651 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
652 len = SPRINTF((tmp, "%s ", p_secstodate(t))); |
|
653 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
654 |
|
655 /* Experation. */ |
|
656 t = ns_get32(rdata); rdata += NS_INT32SZ; |
|
657 len = SPRINTF((tmp, "%s ", p_secstodate(t))); |
|
658 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
659 |
|
660 /* Mode , Error, Key Size. */ |
|
661 /* Priority, Weight, Port. */ |
|
662 mode = ns_get16(rdata); rdata += NS_INT16SZ; |
|
663 err = ns_get16(rdata); rdata += NS_INT16SZ; |
|
664 keysize = ns_get16(rdata); rdata += NS_INT16SZ; |
|
665 len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); |
|
666 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
667 |
|
668 /* XXX need to dump key, print otherdata length & other data */ |
|
669 break; |
|
670 } |
|
671 |
|
672 case ns_t_tsig: { |
|
673 /* BEW - need to complete this */ |
|
674 int n; |
|
675 |
|
676 T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
677 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
678 rdata += 8; /* time */ |
|
679 n = ns_get16(rdata); rdata += INT16SZ; |
|
680 rdata += n; /* sig */ |
|
681 n = ns_get16(rdata); rdata += INT16SZ; /* original id */ |
|
682 sprintf(buf, "%d", ns_get16(rdata)); |
|
683 rdata += INT16SZ; |
|
684 addlen(strlen(buf), &buf, &buflen); |
|
685 break; |
|
686 } |
|
687 |
|
688 case ns_t_a6: { |
|
689 struct in6_addr a; |
|
690 int pbyte, pbit; |
|
691 |
|
692 /* prefix length */ |
|
693 if (rdlen == 0U) goto formerr; |
|
694 len = SPRINTF((tmp, "%d ", *rdata)); |
|
695 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
696 pbit = *rdata; |
|
697 if (pbit > 128) goto formerr; |
|
698 pbyte = (pbit & ~7) / 8; |
|
699 rdata++; |
|
700 |
|
701 /* address suffix: provided only when prefix len != 128 */ |
|
702 if (pbit < 128) { |
|
703 if (rdata + pbyte >= edata) goto formerr; |
|
704 memset(&a, 0, sizeof(a)); |
|
705 memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); |
|
706 (void) inet_ntop(AF_INET6, &a, buf, buflen); |
|
707 addlen(strlen(buf), &buf, &buflen); |
|
708 rdata += sizeof(a) - pbyte; |
|
709 } |
|
710 |
|
711 /* prefix name: provided only when prefix len > 0 */ |
|
712 if (pbit == 0) |
|
713 break; |
|
714 if (rdata >= edata) goto formerr; |
|
715 T(addstr(" ", (size_t)1, &buf, &buflen)); |
|
716 T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); |
|
717 |
|
718 break; |
|
719 } |
|
720 |
|
721 case ns_t_opt: { |
|
722 len = SPRINTF((tmp, "%u bytes", class)); |
|
723 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
724 break; |
|
725 } |
|
726 |
|
727 default: |
|
728 comment = "unknown RR type"; |
|
729 goto hexify; |
|
730 } |
|
731 return (buf - obuf); |
|
732 formerr: |
|
733 comment = "RR format error"; |
|
734 hexify: { |
|
735 int n, m; |
|
736 char *p; |
|
737 |
|
738 len = SPRINTF((tmp, "\\# %tu%s\t; %s", edata - rdata, |
|
739 rdlen != 0 ? " (" : "", comment)); |
|
740 T(addstr(tmp, (size_t)len, &buf, &buflen)); |
|
741 while (rdata < edata) { |
|
742 p = tmp; |
|
743 p += SPRINTF((p, "\n\t")); |
|
744 spaced = 0; |
|
745 n = MIN(16, edata - rdata); |
|
746 for (m = 0; m < n; m++) |
|
747 p += SPRINTF((p, "%02x ", rdata[m])); |
|
748 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); |
|
749 if (n < 16) { |
|
750 T(addstr(")", (size_t)1, &buf, &buflen)); |
|
751 T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen)); |
|
752 } |
|
753 p = tmp; |
|
754 p += SPRINTF((p, "; ")); |
|
755 for (m = 0; m < n; m++) |
|
756 *p++ = (isascii(rdata[m]) && isprint(rdata[m])) |
|
757 ? rdata[m] |
|
758 : '.'; |
|
759 T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen)); |
|
760 rdata += n; |
|
761 } |
|
762 return (buf - obuf); |
|
763 } |
|
764 } |
|
765 |
|
766 /* Private. */ |
|
767 |
|
768 /* |
|
769 * size_t |
|
770 * prune_origin(name, origin) |
|
771 * Find out if the name is at or under the current origin. |
|
772 * return: |
|
773 * Number of characters in name before start of origin, |
|
774 * or length of name if origin does not match. |
|
775 * notes: |
|
776 * This function should share code with samedomain(). |
|
777 */ |
|
778 static size_t |
|
779 prune_origin(const char *name, const char *origin) { |
|
780 const char *oname = name; |
|
781 |
|
782 while (*name != '\0') { |
|
783 if (origin != NULL && ns_samename(name, origin) == 1) |
|
784 return (name - oname - (name > oname)); |
|
785 while (*name != '\0') { |
|
786 if (*name == '\\') { |
|
787 name++; |
|
788 /* XXX need to handle \nnn form. */ |
|
789 if (*name == '\0') |
|
790 break; |
|
791 } else if (*name == '.') { |
|
792 name++; |
|
793 break; |
|
794 } |
|
795 name++; |
|
796 } |
|
797 } |
|
798 return (name - oname); |
|
799 } |
|
800 |
|
801 /* |
|
802 * int |
|
803 * charstr(rdata, edata, buf, buflen) |
|
804 * Format a <character-string> into the presentation buffer. |
|
805 * return: |
|
806 * Number of rdata octets consumed |
|
807 * 0 for protocol format error |
|
808 * -1 for output buffer error |
|
809 * side effects: |
|
810 * buffer is advanced on success. |
|
811 */ |
|
812 static int |
|
813 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { |
|
814 const u_char *odata = rdata; |
|
815 size_t save_buflen = *buflen; |
|
816 char *save_buf = *buf; |
|
817 |
|
818 if (addstr("\"", (size_t)1, buf, buflen) < 0) |
|
819 goto enospc; |
|
820 if (rdata < edata) { |
|
821 int n = *rdata; |
|
822 |
|
823 if (rdata + 1 + n <= edata) { |
|
824 rdata++; |
|
825 while (n-- > 0) { |
|
826 if (strchr("\n\"\\", *rdata) != NULL) |
|
827 if (addstr("\\", (size_t)1, buf, buflen) < 0) |
|
828 goto enospc; |
|
829 if (addstr((const char *)rdata, (size_t)1, |
|
830 buf, buflen) < 0) |
|
831 goto enospc; |
|
832 rdata++; |
|
833 } |
|
834 } |
|
835 } |
|
836 if (addstr("\"", (size_t)1, buf, buflen) < 0) |
|
837 goto enospc; |
|
838 return (rdata - odata); |
|
839 enospc: |
|
840 errno = ENOSPC; |
|
841 *buf = save_buf; |
|
842 *buflen = save_buflen; |
|
843 return (-1); |
|
844 } |
|
845 |
|
846 static int |
|
847 addname(const u_char *msg, size_t msglen, |
|
848 const u_char **pp, const char *origin, |
|
849 char **buf, size_t *buflen) |
|
850 { |
|
851 size_t newlen, save_buflen = *buflen; |
|
852 char *save_buf = *buf; |
|
853 int n; |
|
854 |
|
855 n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen); |
|
856 if (n < 0) |
|
857 goto enospc; /* Guess. */ |
|
858 newlen = prune_origin(*buf, origin); |
|
859 if (**buf == '\0') { |
|
860 goto root; |
|
861 } else if (newlen == 0U) { |
|
862 /* Use "@" instead of name. */ |
|
863 if (newlen + 2 > *buflen) |
|
864 goto enospc; /* No room for "@\0". */ |
|
865 (*buf)[newlen++] = '@'; |
|
866 (*buf)[newlen] = '\0'; |
|
867 } else { |
|
868 if (((origin == NULL || origin[0] == '\0') || |
|
869 (origin[0] != '.' && origin[1] != '\0' && |
|
870 (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { |
|
871 /* No trailing dot. */ |
|
872 root: |
|
873 if (newlen + 2 > *buflen) |
|
874 goto enospc; /* No room for ".\0". */ |
|
875 (*buf)[newlen++] = '.'; |
|
876 (*buf)[newlen] = '\0'; |
|
877 } |
|
878 } |
|
879 *pp += n; |
|
880 addlen(newlen, buf, buflen); |
|
881 **buf = '\0'; |
|
882 return (newlen); |
|
883 enospc: |
|
884 errno = ENOSPC; |
|
885 *buf = save_buf; |
|
886 *buflen = save_buflen; |
|
887 return (-1); |
|
888 } |
|
889 |
|
890 static void |
|
891 addlen(size_t len, char **buf, size_t *buflen) { |
|
892 assert(len <= *buflen); |
|
893 *buf += len; |
|
894 *buflen -= len; |
|
895 } |
|
896 |
|
897 static int |
|
898 addstr(const char *src, size_t len, char **buf, size_t *buflen) { |
|
899 if (len >= *buflen) { |
|
900 errno = ENOSPC; |
|
901 return (-1); |
|
902 } |
|
903 memcpy(*buf, src, len); |
|
904 addlen(len, buf, buflen); |
|
905 **buf = '\0'; |
|
906 return (0); |
|
907 } |
|
908 |
|
909 static int |
|
910 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { |
|
911 size_t save_buflen = *buflen; |
|
912 char *save_buf = *buf; |
|
913 int t; |
|
914 |
|
915 if (spaced || len >= target - 1) { |
|
916 T(addstr(" ", (size_t)2, buf, buflen)); |
|
917 spaced = 1; |
|
918 } else { |
|
919 for (t = (target - len - 1) / 8; t >= 0; t--) |
|
920 if (addstr("\t", (size_t)1, buf, buflen) < 0) { |
|
921 *buflen = save_buflen; |
|
922 *buf = save_buf; |
|
923 return (-1); |
|
924 } |
|
925 spaced = 0; |
|
926 } |
|
927 return (spaced); |
|
928 } |