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