3 Turn data structures into printable text. */
6 * Copyright (c) 1995-2003 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
43 * $Id: print.c,v 1.53.2.9 2003/03/31 03:06:56 dhankins Exp $ Copyright (c) 1995-2003 The Internet Software Consortium. All rights reserved.
44 * $DragonFly: src/contrib/isc-dhcp/common/Attic/print.c,v 1.2 2003/10/11 21:14:17 dillon Exp $
50 char *quotify_string (const char *s, const char *file, int line)
56 for (sp = s; sp && *sp; sp++) {
59 else if (!isascii (*sp) || !isprint (*sp))
61 else if (*sp == '"' || *sp == '\\')
67 buf = dmalloc (len + 1, file, line);
70 for (sp = s; sp && *sp; sp++) {
73 else if (!isascii (*sp) || !isprint (*sp)) {
74 sprintf (nsp, "\\%03o",
75 *(const unsigned char *)sp);
77 } else if (*sp == '"' || *sp == '\\') {
88 char *quotify_buf (const unsigned char *s, unsigned len,
89 const char *file, int line)
95 for (i = 0; i < len; i++) {
98 else if (!isascii (s [i]) || !isprint (s [i]))
100 else if (s [i] == '"' || s [i] == '\\')
106 buf = dmalloc (nulen + 1, MDL);
109 for (i = 0; i < len; i++) {
112 else if (!isascii (s [i]) || !isprint (s [i])) {
113 sprintf (nsp, "\\%03o", s [i]);
115 } else if (s [i] == '"' || s [i] == '\\') {
126 char *print_base64 (const unsigned char *buf, unsigned len,
127 const char *file, int line)
133 static char to64 [] =
134 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
136 bl = ((len * 4 + 2) / 3) + 1;
137 b = dmalloc (bl + 1, file, line);
149 *s++ = to64 [extra << 4];
153 val = (extra << 8) + buf [i++];
158 *s++ = to64 [extra << 2];
162 val = (extra << 8) + buf [i++];
176 char *print_hw_addr (htype, hlen, data)
181 static char habuf [49];
189 for (i = 0; i < hlen; i++) {
190 sprintf (s, "%02x", data [i]);
199 void print_lease (lease)
205 log_debug (" Lease %s",
206 piaddr (lease -> ip_addr));
208 t = gmtime (&lease -> starts);
209 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
210 log_debug (" start %s", tbuf);
212 t = gmtime (&lease -> ends);
213 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
214 log_debug (" end %s", tbuf);
216 if (lease -> hardware_addr.hlen)
217 log_debug (" hardware addr = %s",
218 print_hw_addr (lease -> hardware_addr.hbuf [0],
219 lease -> hardware_addr.hlen - 1,
220 &lease -> hardware_addr.hbuf [1]));
221 log_debug (" host %s ",
222 lease -> host ? lease -> host -> name : "<none>");
225 #if defined (DEBUG_PACKET)
226 void dump_packet_option (struct option_cache *oc,
227 struct packet *packet,
229 struct client_state *client,
230 struct option_state *in_options,
231 struct option_state *cfg_options,
232 struct binding_scope **scope,
233 struct universe *u, void *foo)
235 const char *name, *dot;
236 struct data_string ds;
237 memset (&ds, 0, sizeof ds);
239 if (u != &dhcp_universe) {
246 if (evaluate_option_cache (&ds, packet, lease, client,
247 in_options, cfg_options, scope, oc, MDL)) {
248 log_debug (" option %s%s%s %s;\n",
249 name, dot, oc -> option -> name,
250 pretty_print_option (oc -> option,
251 ds.data, ds.len, 1, 1));
252 data_string_forget (&ds, MDL);
256 void dump_packet (tp)
259 struct dhcp_packet *tdp = tp -> raw;
261 log_debug ("packet length %d", tp -> packet_length);
262 log_debug ("op = %d htype = %d hlen = %d hops = %d",
263 tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
264 log_debug ("xid = %x secs = %ld flags = %x",
265 tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
266 log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
267 log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
268 log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
269 log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
270 log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
271 ((unsigned char *)(tdp -> chaddr)) [0],
272 ((unsigned char *)(tdp -> chaddr)) [1],
273 ((unsigned char *)(tdp -> chaddr)) [2],
274 ((unsigned char *)(tdp -> chaddr)) [3],
275 ((unsigned char *)(tdp -> chaddr)) [4],
276 ((unsigned char *)(tdp -> chaddr)) [5]);
277 log_debug ("filename = %s", tdp -> file);
278 log_debug ("server_name = %s", tdp -> sname);
279 if (tp -> options_valid) {
282 for (i = 0; i < tp -> options -> universe_count; i++) {
283 if (tp -> options -> universes [i]) {
284 option_space_foreach (tp, (struct lease *)0,
285 (struct client_state *)0,
286 (struct option_state *)0,
294 log_debug ("%s", "");
298 void dump_raw (buf, len)
299 const unsigned char *buf;
308 01234567890123456789012345678901234567890123456789012345678901234567890123
309 280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .................
312 memset(lbuf, ' ', 79);
315 for (i = 0; i < len; i++) {
324 memset(lbuf, ' ', 79);
326 sprintf (lbuf, "%03x:", i);
328 } else if ((i & 7) == 0)
331 if(isprint(buf[i])) {
332 lbuf[56+(i%16)]=buf[i];
337 sprintf (&lbuf [lbix], " %02x", buf [i]);
349 void hash_dump (table)
350 struct hash_table *table;
353 struct hash_bucket *bp;
358 for (i = 0; i < table -> hash_count; i++) {
359 if (!table -> buckets [i])
361 log_info ("hash bucket %d:", i);
362 for (bp = table -> buckets [i]; bp; bp = bp -> next) {
364 dump_raw (bp -> name, bp -> len);
366 log_info ("%s", (const char *)bp -> name);
373 #define DECLARE_HEX_PRINTER(x) \
374 char *print_hex##x (len, data, limit) \
376 const u_int8_t *data; \
380 static char hex_buf##x [HBLEN + 1]; \
386 for (i = 0; i < (limit - 2) && i < len; i++) { \
387 if (!isascii (data [i]) || !isprint (data [i])) { \
388 for (i = 0; i < limit / 3 && i < len; i++) { \
389 sprintf (&hex_buf##x [i * 3], \
390 "%02x:", data [i]); \
392 hex_buf##x [i * 3 - 1] = 0; \
396 hex_buf##x [0] = '"'; \
400 memcpy (&hex_buf##x [1], data, i); \
401 hex_buf##x [i + 1] = '"'; \
402 hex_buf##x [i + 2] = 0; \
406 DECLARE_HEX_PRINTER (_1)
407 DECLARE_HEX_PRINTER (_2)
408 DECLARE_HEX_PRINTER (_3)
412 char *print_dotted_quads (len, data)
414 const u_int8_t *data;
416 static char dq_buf [DQLEN + 1];
426 sprintf (s, "%d.%d.%d.%d, ",
427 data [i], data [i + 1], data [i + 2], data [i + 3]);
430 } while ((s - &dq_buf [0] > DQLEN - 21) &&
439 char *print_dec_1 (val)
442 static char vbuf [32];
443 sprintf (vbuf, "%lu", val);
447 char *print_dec_2 (val)
450 static char vbuf [32];
451 sprintf (vbuf, "%lu", val);
455 static unsigned print_subexpression PROTO ((struct expression *,
458 static unsigned print_subexpression (expr, buf, len)
459 struct expression *expr;
466 switch (expr -> op) {
476 strcpy (buf, "(match)");
482 rv = 10 + strlen (expr -> data.check -> name);
484 sprintf (buf, "(check %s)",
485 expr -> data.check -> name);
493 strcpy (buf, "(eq ");
494 rv += print_subexpression (expr -> data.equal [0],
495 buf + rv, len - rv - 2);
497 rv += print_subexpression (expr -> data.equal [1],
498 buf + rv, len - rv - 1);
508 strcpy (buf, "(neq ");
509 rv += print_subexpression (expr -> data.equal [0],
510 buf + rv, len - rv - 2);
512 rv += print_subexpression (expr -> data.equal [1],
513 buf + rv, len - rv - 1);
523 strcpy (buf, "(substr ");
524 rv += print_subexpression (expr -> data.substring.expr,
525 buf + rv, len - rv - 3);
527 rv += print_subexpression
528 (expr -> data.substring.offset,
529 buf + rv, len - rv - 2);
531 rv += print_subexpression (expr -> data.substring.len,
532 buf + rv, len - rv - 1);
542 strcpy (buf, "(suffix ");
543 rv += print_subexpression (expr -> data.suffix.expr,
544 buf + rv, len - rv - 2);
547 rv += print_subexpression (expr -> data.suffix.len,
548 buf + rv, len - rv - 1);
559 strcpy (buf, "(concat ");
560 rv += print_subexpression (expr -> data.concat [0],
561 buf + rv, len - rv - 2);
563 rv += print_subexpression (expr -> data.concat [1],
564 buf + rv, len - rv - 1);
571 case expr_pick_first_value:
574 strcpy (buf, "(pick1st ");
575 rv += print_subexpression
576 (expr -> data.pick_first_value.car,
577 buf + rv, len - rv - 2);
579 rv += print_subexpression
580 (expr -> data.pick_first_value.cdr,
581 buf + rv, len - rv - 1);
588 case expr_host_lookup:
589 rv = 15 + strlen (expr -> data.host_lookup -> hostname);
591 sprintf (buf, "(dns-lookup %s)",
592 expr -> data.host_lookup -> hostname);
603 strcpy (&buf [1], s);
606 rv += print_subexpression (expr -> data.and [0],
607 buf + rv, len - rv - 2);
609 rv += print_subexpression (expr -> data.and [1],
610 buf + rv, len - rv - 1);
641 case expr_binary_and:
649 case expr_binary_xor:
656 strcpy (buf, "(not ");
657 rv += print_subexpression (expr -> data.not,
658 buf + rv, len - rv - 1);
665 case expr_config_option:
672 rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
673 strlen (expr -> data.option -> universe -> name));
675 sprintf (buf, "(option %s.%s)",
676 expr -> data.option -> universe -> name,
677 expr -> data.option -> name);
684 strcpy (buf, "(hardware)");
692 strcpy (buf, "(substr ");
693 rv += print_subexpression (expr -> data.packet.offset,
694 buf + rv, len - rv - 2);
696 rv += print_subexpression (expr -> data.packet.len,
697 buf + rv, len - rv - 1);
704 case expr_const_data:
705 s = print_hex_1 (expr -> data.const_data.len,
706 expr -> data.const_data.data, len);
710 strncpy (buf, s, rv);
714 case expr_encapsulate:
716 strcpy (buf, "(encapsulate ");
717 rv += expr -> data.encapsulate.len;
721 (const char *)expr -> data.encapsulate.data, rv - 13);
726 case expr_extract_int8:
729 strcpy (buf, "(int8 ");
730 rv += print_subexpression (expr -> data.extract_int,
731 buf + rv, len - rv - 1);
738 case expr_extract_int16:
741 strcpy (buf, "(int16 ");
742 rv += print_subexpression (expr -> data.extract_int,
743 buf + rv, len - rv - 1);
750 case expr_extract_int32:
753 strcpy (buf, "(int32 ");
754 rv += print_subexpression (expr -> data.extract_int,
755 buf + rv, len - rv - 1);
762 case expr_encode_int8:
765 strcpy (buf, "(to-int8 ");
766 rv += print_subexpression (expr -> data.encode_int,
767 buf + rv, len - rv - 1);
774 case expr_encode_int16:
777 strcpy (buf, "(to-int16 ");
778 rv += print_subexpression (expr -> data.encode_int,
779 buf + rv, len - rv - 1);
786 case expr_encode_int32:
789 strcpy (buf, "(to-int32 ");
790 rv += print_subexpression (expr -> data.encode_int,
791 buf + rv, len - rv - 1);
799 s = print_dec_1 (expr -> data.const_int);
808 rv = 10 + (strlen (expr -> data.option -> name) +
809 strlen (expr -> data.option -> universe -> name));
811 sprintf (buf, "(exists %s.%s)",
812 expr -> data.option -> universe -> name,
813 expr -> data.option -> name);
818 case expr_variable_exists:
819 rv = 10 + strlen (expr -> data.variable);
821 sprintf (buf, "(defined %s)", expr -> data.variable);
826 case expr_variable_reference:
827 rv = strlen (expr -> data.variable);
829 sprintf (buf, "%s", expr -> data.variable);
844 case expr_leased_address:
845 s = "leased-address";
848 case expr_client_state:
852 case expr_host_decl_name:
853 s = "host-decl-name";
856 case expr_lease_time:
875 strcpy (buf, "(reverse ");
876 rv += print_subexpression (expr -> data.reverse.width,
877 buf + rv, len - rv - 2);
879 rv += print_subexpression (expr -> data.reverse.buffer,
880 buf + rv, len - rv - 1);
887 case expr_binary_to_ascii:
890 strcpy (buf, "(b2a ");
891 rv += print_subexpression (expr -> data.b2a.base,
892 buf + rv, len - rv - 4);
894 rv += print_subexpression (expr -> data.b2a.width,
895 buf + rv, len - rv - 3);
897 rv += print_subexpression (expr -> data.b2a.seperator,
898 buf + rv, len - rv - 2);
900 rv += print_subexpression (expr -> data.b2a.buffer,
901 buf + rv, len - rv - 1);
908 case expr_dns_transaction:
912 strcpy (&buf [1], "ns-update ");
913 while (len < rv + 2) {
914 rv += print_subexpression
915 (expr -> data.dns_transaction.car,
916 buf + rv, len - rv - 2);
918 expr = expr -> data.dns_transaction.cdr;
934 case expr_ns_not_exists:
943 if (len > strlen (s) + 1) {
948 s = print_dec_1 (expr -> data.ns_add.rrclass);
949 if (len > rv + strlen (s) + left) {
950 strcpy (&buf [rv], s);
951 rv += strlen (&buf [rv]);
955 s = print_dec_1 (expr -> data.ns_add.rrtype);
956 if (len > rv + strlen (s) + left) {
957 strcpy (&buf [rv], s);
958 rv += strlen (&buf [rv]);
962 rv += print_subexpression
963 (expr -> data.ns_add.rrname,
964 buf + rv, len - rv - left);
967 rv += print_subexpression
968 (expr -> data.ns_add.rrdata,
969 buf + rv, len - rv - left);
972 rv += print_subexpression
973 (expr -> data.ns_add.ttl,
974 buf + rv, len - rv - left);
983 strcpy (buf, "(null)");
988 rv = 12 + strlen (expr -> data.funcall.name);
990 strcpy (buf, "(funcall ");
991 strcpy (buf + 9, expr -> data.funcall.name);
993 rv += print_subexpression
994 (expr -> data.funcall.arglist, buf + rv,
1003 rv = print_subexpression (expr -> data.arg.val, buf, len);
1004 if (expr -> data.arg.next && rv + 2 < len) {
1006 rv += print_subexpression (expr -> data.arg.next,
1016 struct string_list *foo;
1017 strcpy (buf, "(function");
1018 for (foo = expr -> data.func -> args;
1019 foo; foo = foo -> next) {
1020 if (len > rv + 2 + strlen (foo -> string)) {
1022 strcpy (&buf [rv], foo -> string);
1023 rv += strlen (foo -> string);
1034 void print_expression (name, expr)
1036 struct expression *expr;
1040 print_subexpression (expr, buf, sizeof buf);
1041 log_info ("%s: %s", name, buf);
1044 int token_print_indent_concat (FILE *file, int col, int indent,
1046 const char *suffix, ...)
1053 va_start (list, suffix);
1054 s = va_arg (list, char *);
1058 s = va_arg (list, char *);
1062 t = dmalloc (len + 1, MDL);
1064 log_fatal ("token_print_indent: no memory for copy buffer");
1066 va_start (list, suffix);
1067 s = va_arg (list, char *);
1076 len = token_print_indent (file, col, indent,
1082 int token_indent_data_string (FILE *file, int col, int indent,
1083 const char *prefix, const char *suffix,
1084 struct data_string *data)
1090 /* See if this is just ASCII. */
1091 for (i = 0; i < data -> len; i++)
1092 if (!isascii (data -> data [i]) ||
1093 !isprint (data -> data [i]))
1096 /* If we have a purely ASCII string, output it as text. */
1097 if (i == data -> len) {
1098 char *buf = dmalloc (data -> len + 3, MDL);
1101 memcpy (buf + 1, data -> data, data -> len);
1102 buf [data -> len + 1] = '"';
1103 buf [data -> len + 2] = 0;
1104 i = token_print_indent (file, col, indent,
1105 prefix, suffix, buf);
1111 for (i = 0; i < data -> len; i++) {
1112 sprintf (obuf, "%2.2x", data -> data [i]);
1113 col = token_print_indent (file, col, indent,
1114 i == 0 ? prefix : "",
1115 (i + 1 == data -> len
1118 if (i + 1 != data -> len)
1119 col = token_print_indent (file, col, indent,
1120 prefix, suffix, ":");
1125 int token_print_indent (FILE *file, int col, int indent,
1127 const char *suffix, const char *buf)
1129 int len = strlen (buf) + strlen (prefix);
1130 if (col + len > 79) {
1131 if (indent + len < 79) {
1132 indent_spaces (file, indent);
1135 indent_spaces (file, col);
1136 col = len > 79 ? 0 : 79 - len - 1;
1138 } else if (prefix && *prefix) {
1139 fputs (prefix, file);
1140 col += strlen (prefix);
1144 if (suffix && *suffix) {
1145 if (col + strlen (suffix) > 79) {
1146 indent_spaces (file, indent);
1149 fputs (suffix, file);
1150 col += strlen (suffix);
1156 void indent_spaces (FILE *file, int indent)
1160 for (i = 0; i < indent; i++)
1164 #if defined (NSUPDATE)
1165 void print_dns_status (int status, ns_updque *uq)
1168 char *s = &obuf [0], *end = &obuf [1022];
1172 const char *predicate = "if", *en, *op;
1175 for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
1178 switch (u -> r_opcode)
1181 op = "rrset doesn't exist";
1185 op = "rrset exists";
1189 op = "domain doesn't exist";
1193 op = "domain exists";
1211 if (s != &obuf [0] && s + 1 < end)
1213 if (s + strlen (op) < end) {
1218 if (s != &obuf [0] && s + 1 < end)
1220 if (s + strlen (predicate) < end) {
1221 strcpy (s, predicate);
1229 if (s + strlen (u -> r_dname) < end) {
1230 strcpy (s, u -> r_dname);
1237 /* 27 is as big as a ttl can get. */
1240 (unsigned long)(u -> r_ttl));
1244 switch (u -> r_class) {
1258 if (s + strlen (en) < end) {
1264 switch (u -> r_type) {
1287 if (s + strlen (en) < end) {
1296 if (u -> r_type == T_TXT) {
1300 if(u->r_type == T_KEY) {
1301 strcat(s, "<keydata>");
1302 s+=strlen("<keydata>");
1305 if (s + u -> r_size < end) {
1306 memcpy (s, u -> r_data, u -> r_size);
1308 if (u -> r_type == T_TXT) {
1318 if (s + strlen (op) < end) {
1323 if (u == ISC_LIST_TAIL (*uq))
1326 if (s == &obuf [0]) {
1327 strcpy (s, "empty update");
1330 if (status == NOERROR)
1334 en = isc_result_totext (status);
1338 en = "resolver failed";
1342 en = "format error";
1351 en = "not authorized";
1355 en = "not implemented";
1359 en = "not a single valid zone";
1363 en = "no such domain";
1367 en = "no such record";
1375 en = "server failed";
1379 en = "domain exists";
1383 en = "record exists";
1387 en = "unknown error";
1396 if (s + strlen (en) < end) {
1404 log_error ("%s", obuf);
1406 log_info ("%s", obuf);
1408 #endif /* NSUPDATE */