Index: usr.sbin/newsyslog/extern.h =================================================================== --- usr.sbin/newsyslog/extern.h +++ usr.sbin/newsyslog/extern.h @@ -60,6 +60,8 @@ int ptime_relparse(struct ptime_data *_ptime, int _parseopts, time_t _basetime, const char *_str); const char *ptimeget_ctime(const struct ptime_data *_ptime); +char *ptimeget_ctime_rfc5424(const struct ptime_data *_ptime, + char *timebuf, size_t bufsize); double ptimeget_diff(const struct ptime_data *_minuend, const struct ptime_data *_subtrahend); time_t ptimeget_secs(const struct ptime_data *_ptime); Index: usr.sbin/newsyslog/newsyslog.c =================================================================== --- usr.sbin/newsyslog/newsyslog.c +++ usr.sbin/newsyslog/newsyslog.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include @@ -127,6 +128,8 @@ #define CE_NODUMP 0x0200 /* Set 'nodump' on newly created log file. */ #define CE_PID2CMD 0x0400 /* Replace PID file with a shell command.*/ +#define CE_RFC5424 0x0800 /* Use RFC5424 format rotation message */ + #define MIN_PID 5 /* Don't touch pids lower than this */ #define MAX_PID 99999 /* was lower, see /usr/include/sys/proc.h */ @@ -241,6 +244,15 @@ #define DAYTIME_LEN 16 static char daytime[DAYTIME_LEN];/* The current time in human readable form, * used for rotation-tracking messages. */ + +/* Another buffer to hold the current time in RFC5424 format. Fractional + * seconds are allowed by the RFC, but are not included in the + * rotation-tracking messages written by newsyslog and so are not accounted for + * in the length below. + */ +#define DAYTIME_RFC5424_LEN sizeof("YYYY-MM-DDTHH:MM:SS+00:00") +static char daytime_rfc5424[DAYTIME_RFC5424_LEN]; + static char hostname[MAXHOSTNAMELEN]; /* hostname */ static const char *path_syslogpid = _PATH_SYSLOGPID; @@ -624,6 +636,7 @@ timenow = ptime_init(NULL); ptimeset_time(timenow, time(NULL)); strlcpy(daytime, ptimeget_ctime(timenow) + 4, DAYTIME_LEN); + ptimeget_ctime_rfc5424(timenow, daytime_rfc5424, DAYTIME_RFC5424_LEN); /* Let's get our hostname */ (void)gethostname(hostname, sizeof(hostname)); @@ -1290,6 +1303,9 @@ case 'r': working->flags |= CE_PID2CMD; break; + case 't': + working->flags |= CE_RFC5424; + break; case 'u': working->flags |= CE_SIGNALGROUP; break; @@ -2248,15 +2264,34 @@ xtra = ""; if (log_ent->def_cfg) xtra = " using rule"; - if (log_ent->firstcreate) - fprintf(f, "%s %s newsyslog[%d]: logfile first created%s\n", - daytime, hostname, (int) getpid(), xtra); - else if (log_ent->r_reason != NULL) - fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s%s\n", - daytime, hostname, (int) getpid(), log_ent->r_reason, xtra); - else - fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s\n", - daytime, hostname, (int) getpid(), xtra); + if (log_ent->flags & CE_RFC5424) { + if (log_ent->firstcreate) { + fprintf(f, "<%d>1 %s %s newsyslog %d - - %s%s\n", + LOG_MAKEPRI(LOG_USER, LOG_INFO), + daytime_rfc5424, hostname, (int)getpid(), + "logfile first created", xtra); + } else if (log_ent->r_reason != NULL) { + fprintf(f, "<%d>1 %s %s newsyslog %d - - %s%s%s\n", + LOG_MAKEPRI(LOG_USER, LOG_INFO), + daytime_rfc5424, hostname, (int)getpid(), + "logfile turned over", log_ent->r_reason, xtra); + } else { + fprintf(f, "<%d>1 %s %s newsyslog %d - - %s%s\n", + LOG_MAKEPRI(LOG_USER, LOG_INFO), + daytime_rfc5424, hostname, (int)getpid(), + "logfile turned over", xtra); + } + } else { + if (log_ent->firstcreate) + fprintf(f, "%s %s newsyslog[%d]: logfile first created%s\n", + daytime, hostname, (int)getpid(), xtra); + else if (log_ent->r_reason != NULL) + fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s%s\n", + daytime, hostname, (int)getpid(), log_ent->r_reason, xtra); + else + fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s\n", + daytime, hostname, (int)getpid(), xtra); + } if (fclose(f) == EOF) err(1, "log_trim: fclose"); return (0); Index: usr.sbin/newsyslog/newsyslog.conf.5 =================================================================== --- usr.sbin/newsyslog/newsyslog.conf.5 +++ usr.sbin/newsyslog/newsyslog.conf.5 @@ -21,7 +21,7 @@ .\" the suitability of this software for any purpose. It is .\" provided "as is" without express or implied warranty. .\" -.Dd October 24, 2015 +.Dd March 25, 2017 .Dt NEWSYSLOG.CONF 5 .Os .Sh NAME @@ -313,6 +313,11 @@ .Ar path_to_pid_cmd_file after rotation instead of trying to send signal to a process id stored in the file. +.It Cm T +if this flag is set the informational rotation message written to +the log file will be in the format specified by RFC5424. +Normally, the rotation message is written in the traditional (RFC3164) +syslog format. .It Cm U indicates that the file specified by .Ar path_to_pid_cmd_file @@ -389,6 +394,17 @@ .Xr chown 8 , .Xr newsyslog 8 , .Xr syslogd 8 +.Pp +.Rs +.%A C. Lonvick +.%T The BSD syslog Protocol +.%O RFC3164 +.Re +.Rs +.%A R. Gerhards +.%T The Syslog Protocol +.%O RFC5424 +.Re .Sh HISTORY This manual page first appeared in .Fx 4.10 . Index: usr.sbin/newsyslog/ptimes.c =================================================================== --- usr.sbin/newsyslog/ptimes.c +++ usr.sbin/newsyslog/ptimes.c @@ -478,6 +478,75 @@ return (ctime(&ptime->tsecs)); } +/* + * Generate a time of day string in an RFC5424 compatible format. Return a + * pointer to the buffer with the timestamp string or NULL if an error. If the + * time is not supplied, cannot be converted to local time, or the resulting + * string would overflow the buffer, the returned string will be the RFC5424 + * NILVALUE. + */ +char * +ptimeget_ctime_rfc5424(const struct ptime_data *ptime, + char *timebuf, size_t bufsize) +{ + static const char nilvalue[] = {"-"}; /* RFC5424 specified NILVALUE */ + int chars; + struct tm tm; + int tz_hours; + int tz_mins; + long tz_offset; + char tz_sign; + + if (timebuf == NULL) { + return (NULL); + } + + if (bufsize < sizeof(nilvalue)) { + return (NULL); + } + + /* + * Convert to localtime. RFC5424 mandates the use of the NILVALUE if + * the time cannot be obtained, so use that if there is an error in the + * conversion. + */ + if (ptime == NULL || localtime_r(&(ptime->tsecs), &tm) == NULL) { + strlcpy(timebuf, nilvalue, bufsize); + return (timebuf); + } + + /* + * Convert the time to a string in RFC5424 format. The conversion + * cannot be done with strftime() because it cannot produce the correct + * timezone offset format. + */ + if (tm.tm_gmtoff < 0) { + tz_sign = '-'; + tz_offset = -tm.tm_gmtoff; + } else { + tz_sign = '+'; + tz_offset = tm.tm_gmtoff; + } + + tz_hours = tz_offset / 3600; + tz_mins = (tz_offset % 3600) / 60; + + chars = snprintf(timebuf, bufsize, + "%04d-%02d-%02d" /* date */ + "T%02d:%02d:%02d" /* time */ + "%c%02d:%02d", /* time zone offset */ + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + tz_sign, tz_hours, tz_mins); + + /* If the timestamp is too big for timebuf, return the NILVALUE. */ + if (chars >= (int)bufsize) { + strlcpy(timebuf, nilvalue, bufsize); + } + + return (timebuf); +} + double ptimeget_diff(const struct ptime_data *minuend, const struct ptime_data *subtrahend)