]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/BsdSocketLib/ns_print.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / BsdSocketLib / ns_print.c
CommitLineData
d7ce7006 1/*\r
2 * Copyright (c) 1996, 1998 by Internet Software Consortium.\r
3 *\r
4 * Permission to use, copy, modify, and distribute this software for any\r
5 * purpose with or without fee is hereby granted, provided that the above\r
6 * copyright notice and this permission notice appear in all copies.\r
7 *\r
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS\r
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\r
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE\r
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\r
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\r
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\r
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
15 * SOFTWARE.\r
16 */\r
17\r
18/*\r
19 * Portions copyright (c) 1999, 2000\r
20 * Intel Corporation.\r
21 * All rights reserved.\r
22 * \r
23 * Redistribution and use in source and binary forms, with or without\r
24 * modification, are permitted provided that the following conditions\r
25 * are met:\r
26 * \r
27 * 1. Redistributions of source code must retain the above copyright\r
28 * notice, this list of conditions and the following disclaimer.\r
29 * \r
30 * 2. Redistributions in binary form must reproduce the above copyright\r
31 * notice, this list of conditions and the following disclaimer in the\r
32 * documentation and/or other materials provided with the distribution.\r
33 * \r
34 * 3. All advertising materials mentioning features or use of this software\r
35 * must display the following acknowledgement:\r
36 * \r
37 * This product includes software developed by Intel Corporation and\r
38 * its contributors.\r
39 * \r
40 * 4. Neither the name of Intel Corporation or its contributors may be\r
41 * used to endorse or promote products derived from this software\r
42 * without specific prior written permission.\r
43 * \r
44 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''\r
45 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
47 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE\r
48 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r
54 * THE POSSIBILITY OF SUCH DAMAGE.\r
55 * \r
56 */\r
57\r
58#ifndef lint\r
59static char rcsid[] = "$Id: ns_print.c,v 1.1.1.1 2003/11/19 01:51:34 kyu3 Exp $";\r
60#endif\r
61\r
62/* Import. */\r
63\r
64#include <sys/types.h>\r
65#include <sys/socket.h>\r
66\r
67#include <netinet/in.h>\r
68#include <arpa/nameser.h>\r
69#include <arpa/inet.h>\r
70\r
71#include <assert.h>\r
72#include <errno.h>\r
73#include <resolv.h>\r
74#include <string.h>\r
75#include <ctype.h>\r
76\r
77#define SPRINTF(x) (sprintf x)\r
78\r
79/* Forward. */\r
80\r
81static size_t prune_origin(const char *name, const char *origin);\r
82static int charstr(const u_char *rdata, const u_char *edata,\r
83 char **buf, size_t *buflen);\r
84static int addname(const u_char *msg, size_t msglen,\r
85 const u_char **p, const char *origin,\r
86 char **buf, size_t *buflen);\r
87static void addlen(size_t len, char **buf, size_t *buflen);\r
88static int addstr(const char *src, size_t len,\r
89 char **buf, size_t *buflen);\r
90static int addtab(size_t len, size_t target, int spaced,\r
91 char **buf, size_t *buflen);\r
92\r
93/* Macros. */\r
94\r
95#define T(x) \\r
96 do { \\r
97 if ((ssize_t)(x) < 0) \\r
98 return (-1); \\r
99 } while (0)\r
100\r
101/* Public. */\r
102\r
103/*\r
104 * int\r
105 * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)\r
106 * Convert an RR to presentation format.\r
107 * return:\r
108 * Number of characters written to buf, or -1 (check errno).\r
109 */\r
110int\r
111ns_sprintrr(const ns_msg *handle, const ns_rr *rr,\r
112 const char *name_ctx, const char *origin,\r
113 char *buf, size_t buflen)\r
114{\r
115 int n;\r
116\r
117 n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),\r
118 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),\r
119 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),\r
120 name_ctx, origin, buf, buflen);\r
121 return (n);\r
122}\r
123\r
124/*\r
125 * int\r
126 * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,\r
127 * name_ctx, origin, buf, buflen)\r
128 * Convert the fields of an RR into presentation format.\r
129 * return:\r
130 * Number of characters written to buf, or -1 (check errno).\r
131 */\r
132int\r
133ns_sprintrrf(const u_char *msg, size_t msglen,\r
134 const char *name, ns_class class, ns_type type,\r
135 u_long ttl, const u_char *rdata, size_t rdlen,\r
136 const char *name_ctx, const char *origin,\r
137 char *buf, size_t buflen)\r
138{\r
139 const char *obuf = buf;\r
140 const u_char *edata = rdata + rdlen;\r
141 int spaced = 0;\r
142\r
143 const char *comment;\r
144 char tmp[100];\r
145 int x;\r
146 size_t len;\r
147\r
148 static char base64_key[NS_MD5RSA_MAX_BASE64];\r
149 static char t[255*3];\r
150\r
151 /*\r
152 * Owner.\r
153 */\r
154 if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) {\r
155 T(addstr("\t\t\t", 3, &buf, &buflen));\r
156 } else {\r
157 len = prune_origin(name, origin);\r
158 if (len == 0) {\r
159 T(addstr("@\t\t\t", 4, &buf, &buflen));\r
160 } else {\r
161 T(addstr(name, len, &buf, &buflen));\r
162 /* Origin not used and no trailing dot? */\r
163 if ((!origin || !origin[0] || name[len] == '\0') &&\r
164 name[len - 1] != '.') {\r
165 T(addstr(".", 1, &buf, &buflen));\r
166 len++;\r
167 }\r
168 T(spaced = addtab(len, 24, spaced, &buf, &buflen));\r
169 }\r
170 }\r
171\r
172 /*\r
173 * TTL, Class, Type.\r
174 */\r
175 T(x = ns_format_ttl(ttl, buf, buflen));\r
176 addlen(x, &buf, &buflen);\r
177 len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));\r
178 T(addstr(tmp, len, &buf, &buflen));\r
179 T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));\r
180\r
181 /*\r
182 * RData.\r
183 */\r
184 switch (type) {\r
185 case ns_t_a:\r
186 if (rdlen != NS_INADDRSZ)\r
187 goto formerr;\r
188 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);\r
189 addlen(strlen(buf), &buf, &buflen);\r
190 break;\r
191\r
192 case ns_t_cname:\r
193 case ns_t_mb:\r
194 case ns_t_mg:\r
195 case ns_t_mr:\r
196 case ns_t_ns:\r
197 case ns_t_ptr:\r
198 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
199 break;\r
200\r
201 case ns_t_hinfo:\r
202 case ns_t_isdn:\r
203 /* First word. */\r
204 T(len = charstr(rdata, edata, &buf, &buflen));\r
205 if (len == 0)\r
206 goto formerr;\r
207 rdata += len;\r
208 T(addstr(" ", 1, &buf, &buflen));\r
209\r
210 /* Second word. */\r
211 T(len = charstr(rdata, edata, &buf, &buflen));\r
212 if (len == 0)\r
213 goto formerr;\r
214 rdata += len;\r
215 break;\r
216\r
217 case ns_t_soa: {\r
218 u_long t;\r
219\r
220 /* Server name. */\r
221 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
222 T(addstr(" ", 1, &buf, &buflen));\r
223\r
224 /* Administrator name. */\r
225 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
226 T(addstr(" (\n", 3, &buf, &buflen));\r
227 spaced = 0;\r
228\r
229 if ((edata - rdata) != 5*NS_INT32SZ)\r
230 goto formerr;\r
231\r
232 /* Serial number. */\r
233 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
234 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));\r
235 len = SPRINTF((tmp, "%lu", t));\r
236 T(addstr(tmp, len, &buf, &buflen));\r
237 T(spaced = addtab(len, 16, spaced, &buf, &buflen));\r
238 T(addstr("; serial\n", 9, &buf, &buflen));\r
239 spaced = 0;\r
240\r
241 /* Refresh interval. */\r
242 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
243 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));\r
244 T(len = ns_format_ttl(t, buf, buflen));\r
245 addlen(len, &buf, &buflen);\r
246 T(spaced = addtab(len, 16, spaced, &buf, &buflen));\r
247 T(addstr("; refresh\n", 10, &buf, &buflen));\r
248 spaced = 0;\r
249\r
250 /* Retry interval. */\r
251 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
252 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));\r
253 T(len = ns_format_ttl(t, buf, buflen));\r
254 addlen(len, &buf, &buflen);\r
255 T(spaced = addtab(len, 16, spaced, &buf, &buflen));\r
256 T(addstr("; retry\n", 8, &buf, &buflen));\r
257 spaced = 0;\r
258\r
259 /* Expiry. */\r
260 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
261 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));\r
262 T(len = ns_format_ttl(t, buf, buflen));\r
263 addlen(len, &buf, &buflen);\r
264 T(spaced = addtab(len, 16, spaced, &buf, &buflen));\r
265 T(addstr("; expiry\n", 9, &buf, &buflen));\r
266 spaced = 0;\r
267\r
268 /* Minimum TTL. */\r
269 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
270 T(addstr("\t\t\t\t\t", 5, &buf, &buflen));\r
271 T(len = ns_format_ttl(t, buf, buflen));\r
272 addlen(len, &buf, &buflen);\r
273 T(addstr(" )", 2, &buf, &buflen));\r
274 T(spaced = addtab(len, 16, spaced, &buf, &buflen));\r
275 T(addstr("; minimum\n", 10, &buf, &buflen));\r
276\r
277 break;\r
278 }\r
279\r
280 case ns_t_mx:\r
281 case ns_t_afsdb:\r
282 case ns_t_rt: {\r
283 u_int t;\r
284\r
285 if (rdlen < NS_INT16SZ)\r
286 goto formerr;\r
287\r
288 /* Priority. */\r
289 t = ns_get16(rdata);\r
290 rdata += NS_INT16SZ;\r
291 len = SPRINTF((tmp, "%u ", t));\r
292 T(addstr(tmp, len, &buf, &buflen));\r
293\r
294 /* Target. */\r
295 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
296\r
297 break;\r
298 }\r
299\r
300 case ns_t_px: {\r
301 u_int t;\r
302\r
303 if (rdlen < NS_INT16SZ)\r
304 goto formerr;\r
305\r
306 /* Priority. */\r
307 t = ns_get16(rdata);\r
308 rdata += NS_INT16SZ;\r
309 len = SPRINTF((tmp, "%u ", t));\r
310 T(addstr(tmp, len, &buf, &buflen));\r
311\r
312 /* Name1. */\r
313 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
314 T(addstr(" ", 1, &buf, &buflen));\r
315\r
316 /* Name2. */\r
317 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
318\r
319 break;\r
320 }\r
321\r
322 case ns_t_x25:\r
323 T(len = charstr(rdata, edata, &buf, &buflen));\r
324 if (len == 0)\r
325 goto formerr;\r
326 rdata += len;\r
327 break;\r
328\r
329 case ns_t_txt:\r
330 while (rdata < edata) {\r
331 T(len = charstr(rdata, edata, &buf, &buflen));\r
332 if (len == 0)\r
333 goto formerr;\r
334 rdata += len;\r
335 if (rdata < edata)\r
336 T(addstr(" ", 1, &buf, &buflen));\r
337 }\r
338 break;\r
339\r
340 case ns_t_nsap: {\r
341\r
342 (void) inet_nsap_ntoa((int)rdlen, rdata, t);\r
343 T(addstr(t, strlen(t), &buf, &buflen));\r
344 break;\r
345 }\r
346\r
347 case ns_t_aaaa:\r
348 if (rdlen != NS_IN6ADDRSZ)\r
349 goto formerr;\r
350 (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen);\r
351 addlen(strlen(buf), &buf, &buflen);\r
352 break;\r
353\r
354 case ns_t_loc: {\r
355 /* XXX protocol format checking? */\r
356 (void) loc_ntoa(rdata, t);\r
357 T(addstr(t, strlen(t), &buf, &buflen));\r
358 break;\r
359 }\r
360\r
361 case ns_t_naptr: {\r
362 u_int order, preference;\r
363\r
364 if (rdlen < 2*NS_INT16SZ)\r
365 goto formerr;\r
366\r
367 /* Order, Precedence. */\r
368 order = ns_get16(rdata); rdata += NS_INT16SZ;\r
369 preference = ns_get16(rdata); rdata += NS_INT16SZ;\r
370 len = SPRINTF((t, "%u %u ", order, preference));\r
371 T(addstr(t, len, &buf, &buflen));\r
372\r
373 /* Flags. */\r
374 T(len = charstr(rdata, edata, &buf, &buflen));\r
375 if (len == 0)\r
376 goto formerr;\r
377 rdata += len;\r
378 T(addstr(" ", 1, &buf, &buflen));\r
379\r
380 /* Service. */\r
381 T(len = charstr(rdata, edata, &buf, &buflen));\r
382 if (len == 0)\r
383 goto formerr;\r
384 rdata += len;\r
385 T(addstr(" ", 1, &buf, &buflen));\r
386\r
387 /* Regexp. */\r
388 T(len = charstr(rdata, edata, &buf, &buflen));\r
389 if ((ssize_t)len < 0)\r
390 return (-1);\r
391 if (len == 0)\r
392 goto formerr;\r
393 rdata += len;\r
394 T(addstr(" ", 1, &buf, &buflen));\r
395\r
396 /* Server. */\r
397 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
398 break;\r
399 }\r
400\r
401 case ns_t_srv: {\r
402 u_int priority, weight, port;\r
403\r
404 if (rdlen < NS_INT16SZ*3)\r
405 goto formerr;\r
406\r
407 /* Priority, Weight, Port. */\r
408 priority = ns_get16(rdata); rdata += NS_INT16SZ;\r
409 weight = ns_get16(rdata); rdata += NS_INT16SZ;\r
410 port = ns_get16(rdata); rdata += NS_INT16SZ;\r
411 len = SPRINTF((t, "%u %u %u ", priority, weight, port));\r
412 T(addstr(t, len, &buf, &buflen));\r
413\r
414 /* Server. */\r
415 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
416 break;\r
417 }\r
418\r
419 case ns_t_minfo:\r
420 case ns_t_rp:\r
421 /* Name1. */\r
422 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
423 T(addstr(" ", 1, &buf, &buflen));\r
424\r
425 /* Name2. */\r
426 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
427\r
428 break;\r
429\r
430 case ns_t_wks: {\r
431 int n, lcnt;\r
432\r
433 if (rdlen < NS_INT32SZ + 1)\r
434 goto formerr;\r
435\r
436 /* Address. */\r
437 (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);\r
438 addlen(strlen(buf), &buf, &buflen);\r
439 rdata += NS_INADDRSZ;\r
440\r
441 /* Protocol. */\r
442 len = SPRINTF((tmp, " %u ( ", *rdata));\r
443 T(addstr(tmp, len, &buf, &buflen));\r
444 rdata += NS_INT8SZ;\r
445\r
446 /* Bit map. */\r
447 n = 0;\r
448 lcnt = 0;\r
449 while (rdata < edata) {\r
450 u_int c = *rdata++;\r
451 do {\r
452 if (c & 0200) {\r
453 if (lcnt == 0) {\r
454 T(addstr("\n\t\t\t\t", 5,\r
455 &buf, &buflen));\r
456 lcnt = 10;\r
457 spaced = 0;\r
458 }\r
459 len = SPRINTF((tmp, "%d ", n));\r
460 T(addstr(tmp, len, &buf, &buflen));\r
461 lcnt--;\r
462 }\r
463 c <<= 1;\r
464 } while (++n & 07);\r
465 }\r
466 T(addstr(")", 1, &buf, &buflen));\r
467\r
468 break;\r
469 }\r
470\r
471 case ns_t_key: {\r
472 u_int keyflags, protocol, algorithm;\r
473 const char *leader;\r
474 int n;\r
475\r
476 if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)\r
477 goto formerr;\r
478\r
479 /* Key flags, Protocol, Algorithm. */\r
480 keyflags = ns_get16(rdata); rdata += NS_INT16SZ;\r
481 protocol = *rdata++;\r
482 algorithm = *rdata++;\r
483 len = SPRINTF((tmp, "0x%04x %u %u",\r
484 keyflags, protocol, algorithm));\r
485 T(addstr(tmp, len, &buf, &buflen));\r
486\r
487 /* Public key data. */\r
488 len = b64_ntop(rdata, edata - rdata,\r
489 base64_key, sizeof base64_key);\r
490 if ((ssize_t)len < 0)\r
491 goto formerr;\r
492 if (len > 15) {\r
493 T(addstr(" (", 2, &buf, &buflen));\r
494 leader = "\n\t\t";\r
495 spaced = 0;\r
496 } else\r
497 leader = " ";\r
498 for (n = 0; n < (int)len; n += 48) {\r
499 T(addstr(leader, strlen(leader), &buf, &buflen));\r
500 T(addstr(base64_key + n, MIN(len - n, 48),\r
501 &buf, &buflen));\r
502 }\r
503 if (len > 15)\r
504 T(addstr(" )", 2, &buf, &buflen));\r
505\r
506 break;\r
507 }\r
508\r
509 case ns_t_sig: {\r
510 u_int type, algorithm, labels, footprint;\r
511 const char *leader;\r
512 u_long t;\r
513 int n;\r
514\r
515 if (rdlen < 22)\r
516 goto formerr;\r
517\r
518 /* Type covered, Algorithm, Label count, Original TTL. */\r
519 type = ns_get16(rdata); rdata += NS_INT16SZ;\r
520 algorithm = *rdata++;\r
521 labels = *rdata++;\r
522 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
523 len = SPRINTF((tmp, " %s %d %lu ",\r
524 p_type((int)type), algorithm, t));\r
525 T(addstr(tmp, len, &buf, &buflen));\r
526 if (labels != (u_int)dn_count_labels(name))\r
527 goto formerr;\r
528\r
529 /* Signature expiry. */\r
530 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
531 len = SPRINTF((tmp, "%s ", p_secstodate(t)));\r
532 T(addstr(tmp, len, &buf, &buflen));\r
533\r
534 /* Time signed. */\r
535 t = ns_get32(rdata); rdata += NS_INT32SZ;\r
536 len = SPRINTF((tmp, "%s ", p_secstodate(t)));\r
537 T(addstr(tmp, len, &buf, &buflen));\r
538\r
539 /* Signature Footprint. */\r
540 footprint = ns_get16(rdata); rdata += NS_INT16SZ;\r
541 len = SPRINTF((tmp, "%u ", footprint));\r
542 T(addstr(tmp, len, &buf, &buflen));\r
543\r
544 /* Signer's name. */\r
545 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
546\r
547 /* Signature. */\r
548 len = b64_ntop(rdata, edata - rdata,\r
549 base64_key, sizeof base64_key);\r
550 if (len > 15) {\r
551 T(addstr(" (", 2, &buf, &buflen));\r
552 leader = "\n\t\t";\r
553 spaced = 0;\r
554 } else\r
555 leader = " ";\r
556 if ((ssize_t)len < 0)\r
557 goto formerr;\r
558 for (n = 0; n < (int)len; n += 48) {\r
559 T(addstr(leader, strlen(leader), &buf, &buflen));\r
560 T(addstr(base64_key + n, MIN(len - n, 48),\r
561 &buf, &buflen));\r
562 }\r
563 if (len > 15)\r
564 T(addstr(" )", 2, &buf, &buflen));\r
565\r
566 break;\r
567 }\r
568\r
569 case ns_t_nxt: {\r
570 int n, c;\r
571\r
572 /* Next domain name. */\r
573 T(addname(msg, msglen, &rdata, origin, &buf, &buflen));\r
574\r
575 /* Type bit map. */\r
576 n = (int)(edata - rdata);\r
577 for (c = 0; c < n*8; c++)\r
578 if (NS_NXT_BIT_ISSET(c, rdata)) {\r
579 len = SPRINTF((tmp, " %s", p_type(c)));\r
580 T(addstr(tmp, len, &buf, &buflen));\r
581 }\r
582 break;\r
583 }\r
584\r
585 default:\r
586 comment = "unknown RR type";\r
587 goto hexify;\r
588 }\r
589 return ((int)(buf - obuf));\r
590 formerr:\r
591 comment = "RR format error";\r
592 hexify: {\r
593 int n, m;\r
594 char *p;\r
595\r
596 len = SPRINTF((tmp, "\\#(\t\t; %s", comment));\r
597 T(addstr(tmp, len, &buf, &buflen));\r
598 while (rdata < edata) {\r
599 p = tmp;\r
600 p += SPRINTF((p, "\n\t"));\r
601 spaced = 0;\r
602 n = MIN(16, (int)(edata - rdata));\r
603 for (m = 0; m < n; m++)\r
604 p += SPRINTF((p, "%02x ", rdata[m]));\r
605 T(addstr(tmp, (u_int)(p - tmp), &buf, &buflen));\r
606 if (n < 16) {\r
607 T(addstr(")", 1, &buf, &buflen));\r
608 T(addtab((u_int)(p - tmp) + 1, 48, spaced, &buf, &buflen));\r
609 }\r
610 p = tmp;\r
611 p += SPRINTF((p, "; "));\r
612 for (m = 0; m < n; m++)\r
613 *p++ = (isascii(rdata[m]) && isprint(rdata[m]))\r
614 ? rdata[m]\r
615 : '.';\r
616 T(addstr(tmp, (u_int)(p - tmp), &buf, &buflen));\r
617 rdata += n;\r
618 }\r
619 return ((int)(buf - obuf));\r
620 }\r
621}\r
622\r
623/* Private. */\r
624\r
625/*\r
626 * size_t\r
627 * prune_origin(name, origin)\r
628 * Find out if the name is at or under the current origin.\r
629 * return:\r
630 * Number of characters in name before start of origin,\r
631 * or length of name if origin does not match.\r
632 * notes:\r
633 * This function should share code with samedomain().\r
634 */\r
635static size_t\r
636prune_origin(const char *name, const char *origin) {\r
637 const char *oname = name;\r
638\r
639 while (*name != '\0') {\r
640 if (origin != NULL && strcasecmp(name, origin) == 0)\r
641 return ((size_t)(name - oname) - (name > oname));\r
642 while (*name != '\0') {\r
643 if (*name == '\\') {\r
644 name++;\r
645 /* XXX need to handle \nnn form. */\r
646 if (*name == '\0')\r
647 break;\r
648 } else if (*name == '.') {\r
649 name++;\r
650 break;\r
651 }\r
652 name++;\r
653 }\r
654 }\r
655 return ((size_t)(name - oname));\r
656}\r
657\r
658/*\r
659 * int\r
660 * charstr(rdata, edata, buf, buflen)\r
661 * Format a <character-string> into the presentation buffer.\r
662 * return:\r
663 * Number of rdata octets consumed\r
664 * 0 for protocol format error\r
665 * -1 for output buffer error\r
666 * side effects:\r
667 * buffer is advanced on success.\r
668 */\r
669static int\r
670charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {\r
671 const u_char *odata = rdata;\r
672 size_t save_buflen = *buflen;\r
673 char *save_buf = *buf;\r
674\r
675 if (addstr("\"", 1, buf, buflen) < 0)\r
676 goto enospc;\r
677 if (rdata < edata) {\r
678 int n = *rdata;\r
679\r
680 if (rdata + 1 + n <= edata) {\r
681 rdata++;\r
682 while (n-- > 0) {\r
683 if (strchr("\n\"\\", *rdata) != NULL)\r
684 if (addstr("\\", 1, buf, buflen) < 0)\r
685 goto enospc;\r
686 if (addstr((const char *)rdata, 1,\r
687 buf, buflen) < 0)\r
688 goto enospc;\r
689 rdata++;\r
690 }\r
691 }\r
692 }\r
693 if (addstr("\"", 1, buf, buflen) < 0)\r
694 goto enospc;\r
695 return ((int)(rdata - odata));\r
696 enospc:\r
697 errno = ENOSPC;\r
698 *buf = save_buf;\r
699 *buflen = save_buflen;\r
700 return (-1);\r
701}\r
702\r
703static int\r
704addname(const u_char *msg, size_t msglen,\r
705 const u_char **pp, const char *origin,\r
706 char **buf, size_t *buflen)\r
707{\r
708 size_t newlen, save_buflen = *buflen;\r
709 char *save_buf = *buf;\r
710 int n;\r
711\r
712 n = dn_expand(msg, msg + msglen, *pp, *buf, (int)(*buflen));\r
713 if (n < 0)\r
714 goto enospc; /* Guess. */\r
715 newlen = prune_origin(*buf, origin);\r
716 if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') &&\r
717 (newlen == 0 || (*buf)[newlen - 1] != '.')) {\r
718 /* No trailing dot. */\r
719 if (newlen + 2 > *buflen)\r
720 goto enospc; /* No room for ".\0". */\r
721 (*buf)[newlen++] = '.';\r
722 (*buf)[newlen] = '\0';\r
723 }\r
724 if (newlen == 0) {\r
725 /* Use "@" instead of name. */\r
726 if (newlen + 2 > *buflen)\r
727 goto enospc; /* No room for "@\0". */\r
728 (*buf)[newlen++] = '@';\r
729 (*buf)[newlen] = '\0';\r
730 }\r
731 *pp += n;\r
732 addlen(newlen, buf, buflen);\r
733 **buf = '\0';\r
734 return ((int)newlen);\r
735 enospc:\r
736 errno = ENOSPC;\r
737 *buf = save_buf;\r
738 *buflen = save_buflen;\r
739 return (-1);\r
740}\r
741\r
742static void\r
743addlen(size_t len, char **buf, size_t *buflen) {\r
744 assert(len <= *buflen);\r
745 *buf += len;\r
746 *buflen -= len;\r
747}\r
748\r
749static int\r
750addstr(const char *src, size_t len, char **buf, size_t *buflen) {\r
751 if (len > *buflen) {\r
752 errno = ENOSPC;\r
753 return (-1);\r
754 }\r
755 memcpy(*buf, src, len);\r
756 addlen(len, buf, buflen);\r
757 **buf = '\0';\r
758 return (0);\r
759}\r
760\r
761static int\r
762addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {\r
763 size_t save_buflen = *buflen;\r
764 char *save_buf = *buf;\r
765 int t;\r
766\r
767 if (spaced || len >= target - 1) {\r
768 T(addstr(" ", 2, buf, buflen));\r
769 spaced = 1;\r
770 } else {\r
771 for (t = (int)(target - len - 1) / 8; t >= 0; t--)\r
772 if (addstr("\t", 1, buf, buflen) < 0) {\r
773 *buflen = save_buflen;\r
774 *buf = save_buf;\r
775 return (-1);\r
776 }\r
777 spaced = 0;\r
778 }\r
779 return (spaced);\r
780}\r