3 Turn data structures into printable text. */
6 * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1995-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
28 * This software has been written for Internet Systems Consortium
29 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
30 * To learn more about Internet Systems Consortium, see
31 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
32 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
33 * ``http://www.nominum.com''.
38 int db_time_format = DEFAULT_TIME_FORMAT;
40 char *quotify_string (const char *s, const char *file, int line)
46 for (sp = s; sp && *sp; sp++) {
49 else if (!isascii ((int)*sp) || !isprint ((int)*sp))
51 else if (*sp == '"' || *sp == '\\')
57 buf = dmalloc (len + 1, file, line);
60 for (sp = s; sp && *sp; sp++) {
63 else if (!isascii ((int)*sp) || !isprint ((int)*sp)) {
64 sprintf (nsp, "\\%03o",
65 *(const unsigned char *)sp);
67 } else if (*sp == '"' || *sp == '\\') {
78 char *quotify_buf (const unsigned char *s, unsigned len,
79 const char *file, int line)
85 for (i = 0; i < len; i++) {
88 else if (!isascii (s [i]) || !isprint (s [i]))
90 else if (s [i] == '"' || s [i] == '\\')
96 buf = dmalloc (nulen + 1, MDL);
99 for (i = 0; i < len; i++) {
102 else if (!isascii (s [i]) || !isprint (s [i])) {
103 sprintf (nsp, "\\%03o", s [i]);
105 } else if (s [i] == '"' || s [i] == '\\') {
116 char *print_base64 (const unsigned char *buf, unsigned len,
117 const char *file, int line)
123 static char to64 [] =
124 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
126 bl = ((len * 4 + 2) / 3) + 1;
127 b = dmalloc (bl + 1, file, line);
139 *s++ = to64 [extra << 4];
143 val = (extra << 8) + buf [i++];
148 *s++ = to64 [extra << 2];
152 val = (extra << 8) + buf [i++];
166 char *print_hw_addr (htype, hlen, data)
169 const unsigned char *data;
171 static char habuf [49];
179 for (i = 0; i < hlen; i++) {
180 sprintf (s, "%02x", data [i]);
189 void print_lease (lease)
195 log_debug (" Lease %s",
196 piaddr (lease -> ip_addr));
198 t = gmtime (&lease -> starts);
199 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
200 log_debug (" start %s", tbuf);
202 t = gmtime (&lease -> ends);
203 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
204 log_debug (" end %s", tbuf);
206 if (lease -> hardware_addr.hlen)
207 log_debug (" hardware addr = %s",
208 print_hw_addr (lease -> hardware_addr.hbuf [0],
209 lease -> hardware_addr.hlen - 1,
210 &lease -> hardware_addr.hbuf [1]));
211 log_debug (" host %s ",
212 lease -> host ? lease -> host -> name : "<none>");
215 #if defined (DEBUG_PACKET)
216 void dump_packet_option (struct option_cache *oc,
217 struct packet *packet,
219 struct client_state *client,
220 struct option_state *in_options,
221 struct option_state *cfg_options,
222 struct binding_scope **scope,
223 struct universe *u, void *foo)
225 const char *name, *dot;
226 struct data_string ds;
227 memset (&ds, 0, sizeof ds);
229 if (u != &dhcp_universe) {
236 if (evaluate_option_cache (&ds, packet, lease, client,
237 in_options, cfg_options, scope, oc, MDL)) {
238 log_debug (" option %s%s%s %s;\n",
239 name, dot, oc -> option -> name,
240 pretty_print_option (oc -> option,
241 ds.data, ds.len, 1, 1));
242 data_string_forget (&ds, MDL);
246 void dump_packet (tp)
249 struct dhcp_packet *tdp = tp -> raw;
251 log_debug ("packet length %d", tp -> packet_length);
252 log_debug ("op = %d htype = %d hlen = %d hops = %d",
253 tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
254 log_debug ("xid = %x secs = %ld flags = %x",
255 tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
256 log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
257 log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
258 log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
259 log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
260 log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
261 ((unsigned char *)(tdp -> chaddr)) [0],
262 ((unsigned char *)(tdp -> chaddr)) [1],
263 ((unsigned char *)(tdp -> chaddr)) [2],
264 ((unsigned char *)(tdp -> chaddr)) [3],
265 ((unsigned char *)(tdp -> chaddr)) [4],
266 ((unsigned char *)(tdp -> chaddr)) [5]);
267 log_debug ("filename = %s", tdp -> file);
268 log_debug ("server_name = %s", tdp -> sname);
269 if (tp -> options_valid) {
272 for (i = 0; i < tp -> options -> universe_count; i++) {
273 if (tp -> options -> universes [i]) {
274 option_space_foreach (tp, (struct lease *)0,
275 (struct client_state *)0,
276 (struct option_state *)0,
284 log_debug ("%s", "");
288 void dump_raw (buf, len)
289 const unsigned char *buf;
298 01234567890123456789012345678901234567890123456789012345678901234567890123
299 280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .................
302 memset(lbuf, ' ', 79);
305 for (i = 0; i < len; i++) {
312 log_info ("%s", lbuf);
314 memset(lbuf, ' ', 79);
316 sprintf (lbuf, "%03x:", i);
318 } else if ((i & 7) == 0)
321 if(isprint(buf[i])) {
322 lbuf[56+(i%16)]=buf[i];
327 sprintf (&lbuf [lbix], " %02x", buf [i]);
336 log_info ("%s", lbuf);
339 void hash_dump (table)
340 struct hash_table *table;
343 struct hash_bucket *bp;
348 for (i = 0; i < table -> hash_count; i++) {
349 if (!table -> buckets [i])
351 log_info ("hash bucket %d:", i);
352 for (bp = table -> buckets [i]; bp; bp = bp -> next) {
354 dump_raw (bp -> name, bp -> len);
356 log_info ("%s", (const char *)bp -> name);
362 * print a string as hex. This only outputs
363 * colon separated hex list no matter what
364 * the input looks like. See print_hex
365 * for a function that prints either cshl
366 * or a string if all bytes are printible
367 * It only uses limit characters from buf
368 * and doesn't do anything if buf == NULL
370 * len - length of data
372 * limit - length of buf to use
373 * buf - output buffer
375 void print_hex_only (len, data, limit, buf)
377 const u_int8_t *data;
383 if ((buf == NULL) || (limit < 3))
386 for (i = 0; (i < limit / 3) && (i < len); i++) {
387 sprintf(&buf[i*3], "%02x:", data[i]);
389 buf[(i * 3) - 1] = 0;
394 * print a string as either text if all the characters
395 * are printable or colon separated hex if they aren't
397 * len - length of data
399 * limit - length of buf to use
400 * buf - output buffer
402 void print_hex_or_string (len, data, limit, buf)
404 const u_int8_t *data;
409 if ((buf == NULL) || (limit < 3))
412 for (i = 0; (i < (limit - 3)) && (i < len); i++) {
413 if (!isascii(data[i]) || !isprint(data[i])) {
414 print_hex_only(len, data, limit, buf);
423 memcpy(&buf[1], data, i);
430 * print a string as either hex or text
431 * using static buffers to hold the output
433 * len - length of data
435 * limit - length of buf
436 * buf_num - the output buffer to use
439 char *print_hex(len, data, limit, buf_num)
441 const u_int8_t *data;
445 static char hex_buf_1[HBLEN + 1];
446 static char hex_buf_2[HBLEN + 1];
447 static char hex_buf_3[HBLEN + 1];
453 if (limit >= sizeof(hex_buf_1))
454 limit = sizeof(hex_buf_1);
458 if (limit >= sizeof(hex_buf_2))
459 limit = sizeof(hex_buf_2);
463 if (limit >= sizeof(hex_buf_3))
464 limit = sizeof(hex_buf_3);
470 print_hex_or_string(len, data, limit, hex_buf);
476 char *print_dotted_quads (len, data)
478 const u_int8_t *data;
480 static char dq_buf [DQLEN + 1];
489 /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
490 * The sprintf can't exceed 18 bytes, and since the loop enforces
491 * 21 bytes of space per iteration at no time can we exit the
492 * loop without at least 3 bytes spare.
495 sprintf (s, "%u.%u.%u.%u, ",
496 data [i], data [i + 1], data [i + 2], data [i + 3]);
499 } while ((s - &dq_buf [0] > DQLEN - 21) &&
508 char *print_dec_1 (val)
511 static char vbuf [32];
512 sprintf (vbuf, "%lu", val);
516 char *print_dec_2 (val)
519 static char vbuf [32];
520 sprintf (vbuf, "%lu", val);
524 static unsigned print_subexpression (struct expression *, char *, unsigned);
526 static unsigned print_subexpression (expr, buf, len)
527 struct expression *expr;
534 switch (expr -> op) {
544 strcpy (buf, "(match)");
550 rv = 10 + strlen (expr -> data.check -> name);
552 sprintf (buf, "(check %s)",
553 expr -> data.check -> name);
561 strcpy (buf, "(eq ");
562 rv += print_subexpression (expr -> data.equal [0],
563 buf + rv, len - rv - 2);
565 rv += print_subexpression (expr -> data.equal [1],
566 buf + rv, len - rv - 1);
576 strcpy (buf, "(neq ");
577 rv += print_subexpression (expr -> data.equal [0],
578 buf + rv, len - rv - 2);
580 rv += print_subexpression (expr -> data.equal [1],
581 buf + rv, len - rv - 1);
588 case expr_regex_match:
591 strcpy(buf, "(regex ");
592 rv += print_subexpression(expr->data.equal[0],
593 buf + rv, len - rv - 2);
595 rv += print_subexpression(expr->data.equal[1],
596 buf + rv, len - rv - 1);
606 strcpy (buf, "(substr ");
607 rv += print_subexpression (expr -> data.substring.expr,
608 buf + rv, len - rv - 3);
610 rv += print_subexpression
611 (expr -> data.substring.offset,
612 buf + rv, len - rv - 2);
614 rv += print_subexpression (expr -> data.substring.len,
615 buf + rv, len - rv - 1);
625 strcpy (buf, "(suffix ");
626 rv += print_subexpression (expr -> data.suffix.expr,
627 buf + rv, len - rv - 2);
630 rv += print_subexpression (expr -> data.suffix.len,
631 buf + rv, len - rv - 1);
642 strcpy(buf, "(lcase ");
643 rv += print_subexpression(expr->data.lcase,
644 buf + rv, len - rv - 1);
654 strcpy(buf, "(ucase ");
655 rv += print_subexpression(expr->data.ucase,
656 buf + rv, len - rv - 1);
666 strcpy (buf, "(concat ");
667 rv += print_subexpression (expr -> data.concat [0],
668 buf + rv, len - rv - 2);
670 rv += print_subexpression (expr -> data.concat [1],
671 buf + rv, len - rv - 1);
678 case expr_pick_first_value:
681 strcpy (buf, "(pick1st ");
682 rv += print_subexpression
683 (expr -> data.pick_first_value.car,
684 buf + rv, len - rv - 2);
686 rv += print_subexpression
687 (expr -> data.pick_first_value.cdr,
688 buf + rv, len - rv - 1);
695 case expr_host_lookup:
696 rv = 15 + strlen (expr -> data.host_lookup -> hostname);
698 sprintf (buf, "(dns-lookup %s)",
699 expr -> data.host_lookup -> hostname);
710 strcpy (&buf [1], s);
713 rv += print_subexpression (expr -> data.and [0],
714 buf + rv, len - rv - 2);
716 rv += print_subexpression (expr -> data.and [1],
717 buf + rv, len - rv - 1);
748 case expr_binary_and:
756 case expr_binary_xor:
763 strcpy (buf, "(not ");
764 rv += print_subexpression (expr -> data.not,
765 buf + rv, len - rv - 1);
772 case expr_config_option:
779 rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
780 strlen (expr -> data.option -> universe -> name));
782 sprintf (buf, "(option %s.%s)",
783 expr -> data.option -> universe -> name,
784 expr -> data.option -> name);
791 strcpy (buf, "(hardware)");
799 strcpy (buf, "(substr ");
800 rv += print_subexpression (expr -> data.packet.offset,
801 buf + rv, len - rv - 2);
803 rv += print_subexpression (expr -> data.packet.len,
804 buf + rv, len - rv - 1);
811 case expr_const_data:
812 s = print_hex_1 (expr -> data.const_data.len,
813 expr -> data.const_data.data, len);
817 strncpy (buf, s, rv);
821 case expr_encapsulate:
823 strcpy (buf, "(encapsulate ");
824 rv += expr -> data.encapsulate.len;
828 (const char *)expr -> data.encapsulate.data, rv - 13);
833 case expr_extract_int8:
836 strcpy (buf, "(int8 ");
837 rv += print_subexpression (expr -> data.extract_int,
838 buf + rv, len - rv - 1);
845 case expr_extract_int16:
848 strcpy (buf, "(int16 ");
849 rv += print_subexpression (expr -> data.extract_int,
850 buf + rv, len - rv - 1);
857 case expr_extract_int32:
860 strcpy (buf, "(int32 ");
861 rv += print_subexpression (expr -> data.extract_int,
862 buf + rv, len - rv - 1);
869 case expr_encode_int8:
872 strcpy (buf, "(to-int8 ");
873 rv += print_subexpression (expr -> data.encode_int,
874 buf + rv, len - rv - 1);
881 case expr_encode_int16:
884 strcpy (buf, "(to-int16 ");
885 rv += print_subexpression (expr -> data.encode_int,
886 buf + rv, len - rv - 1);
893 case expr_encode_int32:
896 strcpy (buf, "(to-int32 ");
897 rv += print_subexpression (expr -> data.encode_int,
898 buf + rv, len - rv - 1);
906 s = print_dec_1 (expr -> data.const_int);
915 rv = 10 + (strlen (expr -> data.option -> name) +
916 strlen (expr -> data.option -> universe -> name));
918 sprintf (buf, "(exists %s.%s)",
919 expr -> data.option -> universe -> name,
920 expr -> data.option -> name);
925 case expr_variable_exists:
926 rv = 10 + strlen (expr -> data.variable);
928 sprintf (buf, "(defined %s)", expr -> data.variable);
933 case expr_variable_reference:
934 rv = strlen (expr -> data.variable);
936 sprintf (buf, "%s", expr -> data.variable);
951 case expr_leased_address:
952 s = "leased-address";
955 case expr_client_state:
959 case expr_host_decl_name:
960 s = "host-decl-name";
963 case expr_lease_time:
982 strcpy (buf, "(reverse ");
983 rv += print_subexpression (expr -> data.reverse.width,
984 buf + rv, len - rv - 2);
986 rv += print_subexpression (expr -> data.reverse.buffer,
987 buf + rv, len - rv - 1);
994 case expr_binary_to_ascii:
997 strcpy (buf, "(b2a ");
998 rv += print_subexpression (expr -> data.b2a.base,
999 buf + rv, len - rv - 4);
1001 rv += print_subexpression (expr -> data.b2a.width,
1002 buf + rv, len - rv - 3);
1004 rv += print_subexpression (expr -> data.b2a.separator,
1005 buf + rv, len - rv - 2);
1007 rv += print_subexpression (expr -> data.b2a.buffer,
1008 buf + rv, len - rv - 1);
1015 case expr_dns_transaction:
1019 strcpy (&buf [1], "ns-update ");
1020 while (len < rv + 2) {
1021 rv += print_subexpression
1022 (expr -> data.dns_transaction.car,
1023 buf + rv, len - rv - 2);
1025 expr = expr -> data.dns_transaction.cdr;
1033 case expr_ns_delete:
1037 case expr_ns_exists:
1041 case expr_ns_not_exists:
1050 if (len > strlen (s) + 1) {
1052 strcpy (buf + 1, s);
1055 s = print_dec_1 (expr -> data.ns_add.rrclass);
1056 if (len > rv + strlen (s) + left) {
1057 strcpy (&buf [rv], s);
1058 rv += strlen (&buf [rv]);
1062 s = print_dec_1 (expr -> data.ns_add.rrtype);
1063 if (len > rv + strlen (s) + left) {
1064 strcpy (&buf [rv], s);
1065 rv += strlen (&buf [rv]);
1069 rv += print_subexpression
1070 (expr -> data.ns_add.rrname,
1071 buf + rv, len - rv - left);
1074 rv += print_subexpression
1075 (expr -> data.ns_add.rrdata,
1076 buf + rv, len - rv - left);
1079 rv += print_subexpression
1080 (expr -> data.ns_add.ttl,
1081 buf + rv, len - rv - left);
1090 strcpy (buf, "(null)");
1095 rv = 12 + strlen (expr -> data.funcall.name);
1097 strcpy (buf, "(funcall ");
1098 strcpy (buf + 9, expr -> data.funcall.name);
1100 rv += print_subexpression
1101 (expr -> data.funcall.arglist, buf + rv,
1110 rv = print_subexpression (expr -> data.arg.val, buf, len);
1111 if (expr -> data.arg.next && rv + 2 < len) {
1113 rv += print_subexpression (expr -> data.arg.next,
1124 struct string_list *foo;
1125 strcpy (buf, "(function");
1126 for (foo = expr -> data.func -> args;
1127 foo; foo = foo -> next) {
1128 if (len > rv + 2 + strlen (foo -> string)) {
1130 strcpy (&buf [rv], foo -> string);
1131 rv += strlen (foo -> string);
1139 case expr_gethostname:
1141 strcpy(buf, "(gethostname)");
1147 log_fatal("Impossible case at %s:%d (undefined expression "
1148 "%d).", MDL, expr->op);
1154 void print_expression (name, expr)
1156 struct expression *expr;
1160 print_subexpression (expr, buf, sizeof buf);
1161 log_info ("%s: %s", name, buf);
1164 int token_print_indent_concat (FILE *file, int col, int indent,
1166 const char *suffix, ...)
1172 va_start (list, suffix);
1173 s = va_arg (list, char *);
1177 s = va_arg (list, char *);
1181 t = dmalloc (len + 1, MDL);
1183 log_fatal ("token_print_indent: no memory for copy buffer");
1185 va_start (list, suffix);
1186 s = va_arg (list, char *);
1192 s = va_arg (list, char *);
1196 len = token_print_indent (file, col, indent,
1202 int token_indent_data_string (FILE *file, int col, int indent,
1203 const char *prefix, const char *suffix,
1204 struct data_string *data)
1210 /* See if this is just ASCII. */
1211 for (i = 0; i < data -> len; i++)
1212 if (!isascii (data -> data [i]) ||
1213 !isprint (data -> data [i]))
1216 /* If we have a purely ASCII string, output it as text. */
1217 if (i == data -> len) {
1218 buf = dmalloc (data -> len + 3, MDL);
1221 memcpy (buf + 1, data -> data, data -> len);
1222 buf [data -> len + 1] = '"';
1223 buf [data -> len + 2] = 0;
1224 i = token_print_indent (file, col, indent,
1225 prefix, suffix, buf);
1231 for (i = 0; i < data -> len; i++) {
1232 sprintf (obuf, "%2.2x", data -> data [i]);
1233 col = token_print_indent (file, col, indent,
1234 i == 0 ? prefix : "",
1235 (i + 1 == data -> len
1238 if (i + 1 != data -> len)
1239 col = token_print_indent (file, col, indent,
1240 prefix, suffix, ":");
1245 int token_print_indent (FILE *file, int col, int indent,
1247 const char *suffix, const char *buf)
1249 int len = strlen (buf) + strlen (prefix);
1250 if (col + len > 79) {
1251 if (indent + len < 79) {
1252 indent_spaces (file, indent);
1255 indent_spaces (file, col);
1256 col = len > 79 ? 0 : 79 - len - 1;
1258 } else if (prefix && *prefix) {
1259 fputs (prefix, file);
1260 col += strlen (prefix);
1264 if (suffix && *suffix) {
1265 if (col + strlen (suffix) > 79) {
1266 indent_spaces (file, indent);
1269 fputs (suffix, file);
1270 col += strlen (suffix);
1276 void indent_spaces (FILE *file, int indent)
1280 for (i = 0; i < indent; i++)
1284 #if defined (NSUPDATE)
1285 #if defined (DEBUG_DNS_UPDATES)
1287 * direction outbound (messages to the dns server)
1288 * inbound (messages from the dns server)
1289 * ddns_cb is the control block associated with the message
1290 * result is the result from the dns code. For outbound calls
1291 * it is from the call to pass the message to the dns library.
1292 * For inbound calls it is from the event returned by the library.
1294 * For outbound messages we print whatever we think is interesting
1295 * from the control block.
1296 * For inbound messages we only print the transaction id pointer
1297 * and the result and expect that the user will match them up as
1298 * necessary. Note well: the transaction information is opaque to
1299 * us so we simply print the pointer to it. This should be sufficient
1300 * to match requests and replys in a short sequence but is awkward
1301 * when trying to use it for longer sequences.
1304 print_dns_status (int direction,
1305 struct dhcp_ddns_cb *ddns_cb,
1306 isc_result_t result)
1309 char *s = obuf, *end = &obuf[sizeof(obuf)-2];
1311 const char *result_str;
1313 sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
1315 if (direction == DDNS_PRINT_INBOUND) {
1316 log_info("DDNS reply: id ptr %p, result: %s",
1317 ddns_cb->transaction, isc_result_totext(result));
1322 * To avoid having to figure out if any of the strings
1323 * aren't NULL terminated, just 0 the whole string
1325 memset(obuf, 0, 1024);
1327 en = "DDNS request: id ptr ";
1328 if (s + strlen(en) + 16 < end) {
1329 sprintf(s, "%s%p", en, ddns_cb->transaction);
1335 switch (ddns_cb->state) {
1336 case DDNS_STATE_ADD_FW_NXDOMAIN:
1337 en = " add forward ";
1339 case DDNS_STATE_ADD_FW_YXDHCID:
1340 en = " modify forward ";
1343 case DDNS_STATE_ADD_PTR:
1344 en = " add reverse ";
1347 case DDNS_STATE_REM_FW_YXDHCID:
1348 en = " remove forward ";
1351 case DDNS_STATE_REM_FW_NXRR:
1352 en = " remove rrset ";
1355 case DDNS_STATE_REM_PTR:
1356 en = " remove reverse ";
1359 case DDNS_STATE_CLEANUP:
1364 en = " unknown state ";
1368 switch (ddns_cb->state) {
1369 case DDNS_STATE_ADD_FW_NXDOMAIN:
1370 case DDNS_STATE_ADD_FW_YXDHCID:
1371 case DDNS_STATE_REM_FW_YXDHCID:
1372 case DDNS_STATE_REM_FW_NXRR:
1373 strcpy(ddns_address, piaddr(ddns_cb->address));
1374 if (s + strlen(en) + strlen(ddns_address) +
1375 ddns_cb->fwd_name.len + 5 < end) {
1376 sprintf(s, "%s%s for %.*s", en, ddns_address,
1377 ddns_cb->fwd_name.len,
1378 ddns_cb->fwd_name.data);
1385 case DDNS_STATE_ADD_PTR:
1386 case DDNS_STATE_REM_PTR:
1387 if (s + strlen(en) + ddns_cb->fwd_name.len +
1388 ddns_cb->rev_name.len + 5 < end) {
1389 sprintf(s, "%s%.*s for %.*s", en,
1390 ddns_cb->fwd_name.len,
1391 ddns_cb->fwd_name.data,
1392 ddns_cb->rev_name.len,
1393 ddns_cb->rev_name.data);
1400 case DDNS_STATE_CLEANUP:
1402 if (s + strlen(en) < end) {
1403 sprintf(s, "%s", en);
1412 if (s + strlen(en) + strlen((char *)ddns_cb->zone_name) < end) {
1413 sprintf(s, "%s%s", en, ddns_cb->zone_name);
1420 if (ddns_cb->dhcid.len > 0) {
1421 if (s + strlen(en) + ddns_cb->dhcid.len-1 < end) {
1424 strncpy(s, (char *)ddns_cb->dhcid.data+1,
1425 ddns_cb->dhcid.len-1);
1431 en = " dhcid: <empty>";
1432 if (s + strlen(en) < end) {
1441 if (s + strlen(en) + 10 < end) {
1442 sprintf(s, "%s%ld", en, ddns_cb->ttl);
1449 result_str = isc_result_totext(result);
1450 if (s + strlen(en) + strlen(result_str) < end) {
1451 sprintf(s, "%s%s", en, result_str);
1459 * We either finished building the string or ran out
1460 * of space, print whatever we have in case it is useful
1462 log_info("%s", obuf);
1467 #endif /* NSUPDATE */
1469 /* Format the given time as "A; # B", where A is the format
1470 * used by the parser, and B is the local time, for humans.
1475 static char buf[sizeof("epoch 9223372036854775807; "
1476 "# Wed Jun 30 21:49:08 2147483647")];
1477 static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
1479 /* The string: "6 2147483647/12/31 23:59:60;"
1480 * is smaller than the other, used to declare the buffer size, so
1481 * we can use one buffer for both.
1490 /* For those lucky enough to have a 128-bit time_t, ensure that
1491 * whatever (corrupt) value we're given doesn't exceed the static
1494 #if (MAX_TIME > 0x7fffffffffffffff)
1495 if (t > 0x7fffffffffffffff)
1499 if (db_time_format == LOCAL_TIME_FORMAT) {
1500 since_epoch = mktime(localtime(&t));
1501 if ((strftime(buf1, sizeof(buf1),
1502 "# %a %b %d %H:%M:%S %Y",
1503 localtime(&t)) == 0) ||
1504 (snprintf(buf, sizeof(buf), "epoch %lu; %s",
1505 (unsigned long)since_epoch, buf1) >= sizeof(buf)))
1509 /* No bounds check for the year is necessary - in this case,
1510 * strftime() will run out of space and assert an error.
1512 if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",