[master] allow different time formats: local, iso8601, iso8601-utc

4518.	[func]		The "print-time" option in the logging configuration
			can now take arguments "local", "iso8601" or
			"iso8601-utc" to indicate the format in which the
			date and time should be logged. For backward
			compatibility, "yes" is a synonym for "local".
			[RT #42585]
This commit is contained in:
Evan Hunt 2016-11-22 23:34:47 -08:00
parent f26fab1103
commit 62c85a4a52
18 changed files with 526 additions and 44 deletions

View file

@ -1,3 +1,10 @@
4518. [func] The "print-time" option in the logging configuration
can now take arguments "local", "iso8601" or
"iso8601-utc" to indicate the format in which the
date and time should be logged. For backward
compatibility, "yes" is a synonym for "local".
[RT #42585]
4517. [placeholder]
4516. [bug] isc_socketmgr_renderjson was missing from the

View file

@ -87,8 +87,7 @@ category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *logconfig) {
* in 'cchan' and add it to 'logconfig'.
*/
static isc_result_t
channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig)
{
channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig) {
isc_result_t result;
isc_logdestination_t dest;
unsigned int type;
@ -202,12 +201,21 @@ channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig)
if (printcat != NULL && cfg_obj_asboolean(printcat))
flags |= ISC_LOG_PRINTCATEGORY;
if (printtime != NULL && cfg_obj_asboolean(printtime))
flags |= ISC_LOG_PRINTTIME;
if (printsev != NULL && cfg_obj_asboolean(printsev))
flags |= ISC_LOG_PRINTLEVEL;
if (buffered != NULL && cfg_obj_asboolean(buffered))
flags |= ISC_LOG_BUFFERED;
if (printtime != NULL && cfg_obj_isboolean(printtime)) {
if (cfg_obj_asboolean(printtime))
flags |= ISC_LOG_PRINTTIME;
} else if (printtime != NULL) { /* local/iso8601/iso8601-utc */
const char *s = cfg_obj_asstring(printtime);
flags |= ISC_LOG_PRINTTIME;
if (strcasecmp(s, "iso8601") == 0)
flags |= ISC_LOG_ISO8601;
else if (strcasecmp(s, "iso8601-utc") == 0)
flags |= ISC_LOG_ISO8601 | ISC_LOG_UTC;
}
}
level = ISC_LOG_INFO;

View file

@ -0,0 +1,14 @@
/*
* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
logging {
channel one {
file "one.out";
print-time bogus;
};
};

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
logging {
channel one {
file "one.out";
print-time no;
};
channel two {
file "two.out";
print-time yes;
};
channel three {
file "three.out";
print-time local;
};
channel four {
file "four.out";
print-time iso8601;
};
channel five {
file "five.out";
print-time iso8601-utc;
};
};

View file

@ -6,8 +6,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# $Id: clean.sh,v 1.4 2011/03/22 16:51:50 smann Exp $
#
# Clean up after log file tests
#
@ -19,4 +17,6 @@ rm -rf ns1/named_dir
rm -f ns1/named_deflog
rm -f ns*/named.lock
rm -f ns1/query_log
rm -f ns1/named_iso8601
rm -f ns1/named_iso8601_utc
rm -f ns1/rndc.out.test*

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on port 5300 {
10.53.0.1;
};
listen-on-v6 { none; };
recursion no;
notify yes;
};
logging {
channel default_log {
file "named_iso8601";
print-time iso8601;
severity debug 9;
};
category default { default_log; default_debug; };
};
controls {
inet 127.0.0.1 port 9593
allow { 127.0.0.1/32; ::1/128; }
keys { "rndc-key"; };
};
key "rndc-key" {
algorithm hmac-sha256;
secret "Am9vCg==";
};
zone "." {
type master;
file "root.db";
};

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on port 5300 {
10.53.0.1;
};
listen-on-v6 { none; };
recursion no;
notify yes;
};
logging {
channel default_log {
file "named_iso8601_utc";
print-time iso8601-utc;
severity debug 9;
};
category default { default_log; default_debug; };
};
controls {
inet 127.0.0.1 port 9593
allow { 127.0.0.1/32; ::1/128; }
keys { "rndc-key"; };
};
key "rndc-key" {
algorithm hmac-sha256;
secret "Am9vCg==";
};
zone "." {
type master;
file "root.db";
};

View file

@ -12,16 +12,19 @@ SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
THISDIR=`pwd`
CONFDIR="ns1"
PLAINCONF="${THISDIR}/${CONFDIR}/named.plain"
DIRCONF="${THISDIR}/${CONFDIR}/named.dirconf"
PIPECONF="${THISDIR}/${CONFDIR}/named.pipeconf"
SYMCONF="${THISDIR}/${CONFDIR}/named.symconf"
PLAINCONF="${THISDIR}/${CONFDIR}/named.plainconf"
ISOCONF="${THISDIR}/${CONFDIR}/named.iso8601"
ISOCONFUTC="${THISDIR}/${CONFDIR}/named.iso8601-utc"
PLAINFILE="named_log"
DIRFILE="named_dir"
PIPEFILE="named_pipe"
SYMFILE="named_sym"
DLFILE="named_deflog"
ISOFILE="named_iso8601"
ISOUTCFILE="named_iso8601_utc"
PIDFILE="${THISDIR}/${CONFDIR}/named.pid"
myRNDC="$RNDC -c ${THISDIR}/${CONFDIR}/rndc.conf"
myNAMED="$NAMED -c ${THISDIR}/${CONFDIR}/named.conf -m record,size,mctx -T clienttest -T nosyslog -d 99 -X named.lock -U 4"
@ -238,10 +241,8 @@ else
echo "I: skipping symlink test (unable to create symlink)"
fi
status=0
n=`expr $n + 1`
echo "I:testing default logfile using named -L file ($n)"
echo "I: testing default logfile using named -L file ($n)"
# Now stop the server again and test the -L option
rm -f $DLFILE
$PERL ../../stop.pl .. ns1
@ -270,5 +271,29 @@ else
exit 1
fi
echo "I:testing logging functionality"
n=`expr $n + 1`
echo "I: testing iso8601 timestamp ($n)"
cp $ISOCONF named.conf
$myRNDC reconfig > rndc.out.test$n 2>&1
if grep '^....-..-..T..:..:..\.... ' $ISOFILE > /dev/null; then
echo "I: testing iso8601 timestamp succeeded"
else
echo "I: testing iso8601 timestamp failed"
status=`expr $status + 1`
fi
n=`expr $n + 1`
echo "I: testing iso8601-utc timestamp ($n)"
cp $ISOCONFUTC named.conf
$myRNDC reconfig > rndc.out.test$n 2>&1
if grep '^....-..-..T..:..:..\....Z' $ISOUTCFILE > /dev/null; then
echo "I: testing iso8601-utc timestamp succeeded"
else
echo "I: testing iso8601-utc timestamp failed"
status=`expr $status + 1`
fi
echo "I:exit status: $status"
[ $status -eq 0 ] || exit 1

View file

@ -3644,7 +3644,7 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
<option>info</option> | <option>debug</option> [ <replaceable>level</replaceable> ] | <option>dynamic</option> ); ]
[ <command>print-category</command> <option>yes</option> or <option>no</option>; ]
[ <command>print-severity</command> <option>yes</option> or <option>no</option>; ]
[ <command>print-time</command> <option>yes</option> or <option>no</option>; ]
[ <command>print-time</command> ( <option>>yes</option> | <option>no</option> | <option>local</option> | <option>iso8601</option> | <option>iso8601-utc</option> ) ;
[ <command>buffered</command> <option>yes</option> or <option>no</option>; ]
}; ]
[ <command>category</command> <replaceable>category_name</replaceable> {
@ -3877,14 +3877,30 @@ notrace</command>. All debugging messages in the server have a debug
server's global debug level to determine what messages to print.
</para>
<para>
If <command>print-time</command> has been turned on,
then
the date and time will be logged. <command>print-time</command> may
<command>print-time</command> can be set to
<userinput>yes</userinput>, <userinput>no</userinput>,
or a time format specifier, which may be one of
<option>local</option>, <option>iso8601</option> or
<option>iso8601-utc</option>. If set to
<userinput>no</userinput>, then the date and time will
not be logged. If set to <userinput>yes</userinput>
or <option>local</option>, the date and time are logged
in a human readable format, using the local time zone.
If set to <option>iso8601</option> the local time is
logged in ISO8601 format. If set to
<option>iso8601-utc</option>, then the date and time
are logged in ISO8601 format, with time zone set to
UTC. The default is <option>local</option>.
</para>
<para>
<command>print-time</command> may
be specified for a <command>syslog</command> channel,
but is usually
but it is usually
pointless since <command>syslog</command> also logs
the date and
time. If <command>print-category</command> is
the date and time.
</para>
<para>
If <command>print-category</command> is
requested, then the
category of the message will be logged as well. Finally, if <command>print-severity</command> is
on, then the severity level of the message will be logged. The <command>print-</command> options may

View file

@ -39,9 +39,10 @@
<listitem>
<para>
Added the ability to specify the maximum number of records
permitted in a zone (max-records #;). This provides a mechanism
to block overly large zone transfers, which is a potential risk
with slave zones from other parties, as described in CVE-2016-6170.
permitted in a zone (<option>max-records #;</option>).
This provides a mechanism to block overly large zone
transfers, which is a potential risk with slave zones from
other parties, as described in CVE-2016-6170.
[RT #42143]
</para>
</listitem>
@ -52,7 +53,13 @@
<itemizedlist>
<listitem>
<para>
None.
The <option>print-time</option> option in the
<option>logging</option> configuration can now take arguments
<userinput>local</userinput>, <userinput>iso8601</userinput> or
<userinput>iso8601-utc</userinput> to indicate the format in
which the date and time should be logged. For backward
compatibility, <userinput>yes</userinput> is a synonym for
<userinput>local</userinput>. [RT #42585]
</para>
</listitem>
</itemizedlist>

View file

@ -54,16 +54,18 @@
/*%
* Channel flags.
*/
#define ISC_LOG_PRINTTIME 0x0001
#define ISC_LOG_PRINTLEVEL 0x0002
#define ISC_LOG_PRINTCATEGORY 0x0004
#define ISC_LOG_PRINTMODULE 0x0008
#define ISC_LOG_PRINTTAG 0x0010 /* tag and ":" */
#define ISC_LOG_PRINTPREFIX 0x0020 /* tag only, no colon */
#define ISC_LOG_PRINTALL 0x003F
#define ISC_LOG_BUFFERED 0x0040
#define ISC_LOG_DEBUGONLY 0x1000
#define ISC_LOG_OPENERR 0x8000 /* internal */
#define ISC_LOG_PRINTTIME 0x00001
#define ISC_LOG_PRINTLEVEL 0x00002
#define ISC_LOG_PRINTCATEGORY 0x00004
#define ISC_LOG_PRINTMODULE 0x00008
#define ISC_LOG_PRINTTAG 0x00010 /* tag and ":" */
#define ISC_LOG_PRINTPREFIX 0x00020 /* tag only, no colon */
#define ISC_LOG_PRINTALL 0x0003F
#define ISC_LOG_BUFFERED 0x00040
#define ISC_LOG_DEBUGONLY 0x01000
#define ISC_LOG_OPENERR 0x08000 /* internal */
#define ISC_LOG_ISO8601 0x10000 /* if PRINTTIME, use ISO8601 */
#define ISC_LOG_UTC 0x20000 /* if PRINTTIME, use UTC */
/*@}*/
/*@{*/

View file

@ -697,7 +697,8 @@ isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
isc_logchannel_t *channel;
isc_mem_t *mctx;
unsigned int permitted = ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY |
ISC_LOG_BUFFERED;
ISC_LOG_BUFFERED | ISC_LOG_ISO8601 |
ISC_LOG_UTC;
REQUIRE(VALID_CONFIG(lcfg));
REQUIRE(name != NULL);
@ -1396,12 +1397,15 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
const char *format, va_list args)
{
int syslog_level;
char time_string[64];
const char *time_string;
char local_time[64];
char iso8601z_string[64];
char iso8601l_string[64];
char level_string[24];
const char *iformat;
struct stat statbuf;
isc_boolean_t matched = ISC_FALSE;
isc_boolean_t printtime, printtag, printcolon;
isc_boolean_t printtime, iso8601, utc, printtag, printcolon;
isc_boolean_t printcategory, printmodule, printlevel, buffered;
isc_logconfig_t *lcfg;
isc_logchannel_t *channel;
@ -1433,7 +1437,9 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
else
iformat = format;
time_string[0] = '\0';
local_time[0] = '\0';
iso8601l_string[0] = '\0';
iso8601z_string[0] = '\0';
level_string[0] = '\0';
LOCK(&lctx->lock);
@ -1496,12 +1502,21 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
continue;
if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
time_string[0] == '\0') {
local_time[0] == '\0')
{
isc_time_t isctime;
TIME_NOW(&isctime);
isc_time_formattimestamp(&isctime, time_string,
sizeof(time_string));
isc_time_formattimestamp(&isctime,
local_time,
sizeof(local_time));
isc_time_formatISO8601ms(&isctime,
iso8601z_string,
sizeof(iso8601z_string));
isc_time_formatISO8601Lms(&isctime,
iso8601l_string,
sizeof(iso8601l_string));
}
if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
@ -1628,6 +1643,8 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
}
}
utc = ISC_TF((channel->flags & ISC_LOG_UTC) != 0);
iso8601 = ISC_TF((channel->flags & ISC_LOG_ISO8601) != 0);
printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME)
!= 0);
printtag = ISC_TF((channel->flags &
@ -1644,6 +1661,19 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
buffered = ISC_TF((channel->flags & ISC_LOG_BUFFERED)
!= 0);
if (printtime) {
if (iso8601) {
if (utc) {
time_string = iso8601z_string;
} else {
time_string = iso8601l_string;
}
} else {
time_string = local_time;
}
} else
time_string = "";
switch (channel->type) {
case ISC_LOG_TOFILE:
if (FILE_MAXREACHED(channel)) {
@ -1691,7 +1721,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
case ISC_LOG_TOFILEDESC:
fprintf(FILE_STREAM(channel),
"%s%s%s%s%s%s%s%s%s%s\n",
printtime ? time_string : "",
printtime ? time_string : "",
printtime ? " " : "",
printtag ? lcfg->tag : "",
printcolon ? ": " : "",

View file

@ -8,6 +8,7 @@
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <atf-c.h>
@ -33,11 +34,118 @@ ATF_TC_BODY(isc_time_parsehttptimestamp, tc) {
ATF_REQUIRE_EQ(isc_time_seconds(&t), isc_time_seconds(&x));
}
ATF_TC(isc_time_formatISO8601);
ATF_TC_HEAD(isc_time_formatISO8601, tc) {
atf_tc_set_md_var(tc, "descr", "print UTC in ISO8601");
}
ATF_TC_BODY(isc_time_formatISO8601, tc) {
isc_result_t result;
isc_time_t t;
char buf[64];
setenv("TZ", "PST8PDT", 1);
result = isc_time_now(&t);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
/* yyyy-mm-ddThh:mm:ssZ */
memset(buf, 'X', sizeof(buf));
isc_time_formatISO8601(&t, buf, sizeof(buf));
ATF_CHECK_EQ(strlen(buf), 20);
ATF_CHECK_EQ(buf[4], '-');
ATF_CHECK_EQ(buf[7], '-');
ATF_CHECK_EQ(buf[10], 'T');
ATF_CHECK_EQ(buf[13], ':');
ATF_CHECK_EQ(buf[16], ':');
ATF_CHECK_EQ(buf[19], 'Z');
}
ATF_TC(isc_time_formatISO8601ms);
ATF_TC_HEAD(isc_time_formatISO8601ms, tc) {
atf_tc_set_md_var(tc, "descr",
"print UTC in ISO8601 with milliseconds");
}
ATF_TC_BODY(isc_time_formatISO8601ms, tc) {
isc_result_t result;
isc_time_t t;
char buf[64];
setenv("TZ", "PST8PDT", 1);
result = isc_time_now(&t);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
/* yyyy-mm-ddThh:mm:ss.sssZ */
memset(buf, 'X', sizeof(buf));
isc_time_formatISO8601ms(&t, buf, sizeof(buf));
ATF_CHECK_EQ(strlen(buf), 24);
ATF_CHECK_EQ(buf[4], '-');
ATF_CHECK_EQ(buf[7], '-');
ATF_CHECK_EQ(buf[10], 'T');
ATF_CHECK_EQ(buf[13], ':');
ATF_CHECK_EQ(buf[16], ':');
ATF_CHECK_EQ(buf[19], '.');
ATF_CHECK_EQ(buf[23], 'Z');
}
ATF_TC(isc_time_formatISO8601L);
ATF_TC_HEAD(isc_time_formatISO8601L, tc) {
atf_tc_set_md_var(tc, "descr",
"print local time in ISO8601");
}
ATF_TC_BODY(isc_time_formatISO8601L, tc) {
isc_result_t result;
isc_time_t t;
char buf[64];
setenv("TZ", "PST8PDT", 1);
result = isc_time_now(&t);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
/* yyyy-mm-ddThh:mm:ss */
memset(buf, 'X', sizeof(buf));
isc_time_formatISO8601L(&t, buf, sizeof(buf));
ATF_CHECK_EQ(strlen(buf), 19);
ATF_CHECK_EQ(buf[4], '-');
ATF_CHECK_EQ(buf[7], '-');
ATF_CHECK_EQ(buf[10], 'T');
ATF_CHECK_EQ(buf[13], ':');
ATF_CHECK_EQ(buf[16], ':');
}
ATF_TC(isc_time_formatISO8601Lms);
ATF_TC_HEAD(isc_time_formatISO8601Lms, tc) {
atf_tc_set_md_var(tc, "descr",
"print local time in ISO8601 with milliseconds");
}
ATF_TC_BODY(isc_time_formatISO8601Lms, tc) {
isc_result_t result;
isc_time_t t;
char buf[64];
setenv("TZ", "PST8PDT", 1);
result = isc_time_now(&t);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
/* yyyy-mm-ddThh:mm:ss.sss */
memset(buf, 'X', sizeof(buf));
isc_time_formatISO8601Lms(&t, buf, sizeof(buf));
ATF_CHECK_EQ(strlen(buf), 23);
ATF_CHECK_EQ(buf[4], '-');
ATF_CHECK_EQ(buf[7], '-');
ATF_CHECK_EQ(buf[10], 'T');
ATF_CHECK_EQ(buf[13], ':');
ATF_CHECK_EQ(buf[16], ':');
ATF_CHECK_EQ(buf[19], '.');
}
/*
* Main
*/
ATF_TP_ADD_TCS(tp) {
ATF_TP_ADD_TC(tp, isc_time_parsehttptimestamp);
ATF_TP_ADD_TC(tp, isc_time_formatISO8601);
ATF_TP_ADD_TC(tp, isc_time_formatISO8601ms);
ATF_TP_ADD_TC(tp, isc_time_formatISO8601L);
ATF_TP_ADD_TC(tp, isc_time_formatISO8601Lms);
return (atf_no_error());
}

View file

@ -323,6 +323,34 @@ isc_time_parsehttptimestamp(char *input, isc_time_t *t);
*\li 'buf' and 't' are not NULL.
*/
void
isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sss"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<

View file

@ -424,6 +424,34 @@ isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
return (ISC_R_SUCCESS);
}
void
isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;
unsigned int flen;
REQUIRE(len > 0);
now = (time_t)t->seconds;
flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime(&now));
INSIST(flen < len);
}
void
isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;
unsigned int flen;
REQUIRE(len > 0);
now = (time_t)t->seconds;
flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime(&now));
INSIST(flen < len);
if (flen > 0U && len - flen >= 6) {
snprintf(buf + flen, len - flen, ".%03u",
t->nanoseconds / NS_PER_MS);
}
}
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
time_t now;
@ -446,8 +474,8 @@ isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
now = (time_t)t->seconds;
flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
INSIST(flen < len);
if (flen == len - 5) {
flen -= 1; /* rewind one character */
if (flen > 0U && len - flen >= 5) {
flen -= 1; /* rewind one character (Z) */
snprintf(buf + flen, len - flen, ".%03uZ",
t->nanoseconds / NS_PER_MS);
}

View file

@ -287,6 +287,34 @@ isc_time_parsehttptimestamp(char *input, isc_time_t *t);
*\li 'buf' and 't' are not NULL.
*/
void
isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len);
/*%<
* Format the time 't' into the buffer 'buf' of length 'len',
* using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sss"
* If the text does not fit in the buffer, the result is indeterminate,
* but is always guaranteed to be null terminated.
*
* Requires:
*\li 'len' > 0
*\li 'buf' points to an array of at least len chars
*
*/
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
/*%<

View file

@ -328,6 +328,49 @@ isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
return (ISC_R_SUCCESS);
}
void
isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len) {
SYSTEMTIME st;
char DateBuf[50];
char TimeBuf[50];
/* strtime() format: "%Y-%m-%dT%H:%M:%S" */
REQUIRE(len > 0);
if (FileTimeToSystemTime(&t->absolute, &st)) {
GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "yyyy-MM-dd",
DateBuf, 50);
GetTimeFormat(LOCALE_USER_DEFAULT,
TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
&st, "hh':'mm':'ss", TimeBuf, 50);
snprintf(buf, len, "%sT%s", DateBuf, TimeBuf);
} else {
buf[0] = 0;
}
}
void
isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) {
SYSTEMTIME st;
char DateBuf[50];
char TimeBuf[50];
/* strtime() format: "%Y-%m-%dT%H:%M:%S.SSS" */
REQUIRE(len > 0);
if (FileTimeToSystemTime(&t->absolute, &st)) {
GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "yyyy-MM-dd",
DateBuf, 50);
GetTimeFormat(LOCALE_USER_DEFAULT,
TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
&st, "hh':'mm':'ss", TimeBuf, 50);
snprintf(buf, len, "%sT%s.%03u", DateBuf, TimeBuf,
st.wMilliseconds);
} else {
buf[0] = 0;
}
}
void
isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
SYSTEMTIME st;

View file

@ -123,6 +123,7 @@ static cfg_type_t cfg_type_optional_port;
static cfg_type_t cfg_type_optional_uint32;
static cfg_type_t cfg_type_options;
static cfg_type_t cfg_type_portiplist;
static cfg_type_t cfg_type_printtime;
static cfg_type_t cfg_type_querysource4;
static cfg_type_t cfg_type_querysource6;
static cfg_type_t cfg_type_querysource;
@ -2070,7 +2071,6 @@ static cfg_type_t cfg_type_server = {
server_clausesets
};
/*%
* Clauses that can be found in a 'channel' clause in the
* 'logging' statement.
@ -2078,8 +2078,24 @@ static cfg_type_t cfg_type_server = {
* These have some additional constraints that need to be
* checked after parsing:
* - There must exactly one of file/syslog/null/stderr
*
*/
static const char *printtime_enums[] = {
"local", "iso8601", "iso8601-utc", NULL
};
static isc_result_t
parse_printtime(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
}
static void
doc_printtime(cfg_printer_t *pctx, const cfg_type_t *type) {
doc_enum_or_other(pctx, type, &cfg_type_boolean);
}
static cfg_type_t cfg_type_printtime = {
"printtime", parse_printtime, cfg_print_ustring, doc_printtime,
&cfg_rep_string, printtime_enums
};
static cfg_clausedef_t
channel_clauses[] = {
/* Destinations. We no longer require these to be first. */
@ -2089,7 +2105,7 @@ channel_clauses[] = {
{ "stderr", &cfg_type_void, 0 },
/* Options. We now accept these for the null channel, too. */
{ "severity", &cfg_type_logseverity, 0 },
{ "print-time", &cfg_type_boolean, 0 },
{ "print-time", &cfg_type_printtime, 0 },
{ "print-severity", &cfg_type_boolean, 0 },
{ "print-category", &cfg_type_boolean, 0 },
{ "buffered", &cfg_type_boolean, 0 },