Push RFC 5424 message format from logmsg() into fprintlog().
Now that all of parsemsg() parses both RFC 3164 and 5424 messages and hands them to logmsg(), alter the latter to properly forward all RFC 5424 message attributes to fprintlog(). While there, make some minor cleanups to this code: - Instead of extending the existing code that compares hostnames and message bodies for deduplication, print all of the relevant message fields into a single string that we can compare ('saved'). - No longer let the behaviour of fprintflog() depend on whether 'msg == NULL' to print repetition messages, Simply decompose this function into fprintlog_first() and fprintlog_successive(). This makes the interpretation of function arguments less magical and also allows us to get consistent behaviour across RFC 3164 and 5424 when adding support for the RFC 5424 output format. - As RFC 5424 syslog messages have a dedicated application name field, alter the repetition messages to be printed on behalf of syslogd on the current system. Change these messages to use the local hostname, so that it's obvious which syslogd instance detected the repetition. Remove f_prevhost, as it has now become unnecessary. - Remove a useless strdup(). Deconsting the message string is safe in this specific case.
This commit is contained in:
parent
6a740d0bcf
commit
b484e3fee4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=332118
@ -252,7 +252,6 @@ struct filed {
|
|||||||
#define fu_pipe_pid f_un.f_pipe.f_pid
|
#define fu_pipe_pid f_un.f_pipe.f_pid
|
||||||
char f_prevline[MAXSVLINE]; /* last message logged */
|
char f_prevline[MAXSVLINE]; /* last message logged */
|
||||||
struct logtime f_lasttime; /* time of last occurrence */
|
struct logtime f_lasttime; /* time of last occurrence */
|
||||||
char f_prevhost[MAXHOSTNAMELEN]; /* host from which recd. */
|
|
||||||
int f_prevpri; /* pri of f_prevline */
|
int f_prevpri; /* pri of f_prevline */
|
||||||
size_t f_prevlen; /* length of f_prevline */
|
size_t f_prevlen; /* length of f_prevline */
|
||||||
int f_prevcount; /* repetition cnt of prevline */
|
int f_prevcount; /* repetition cnt of prevline */
|
||||||
@ -385,7 +384,9 @@ static void die(int) __dead2;
|
|||||||
static void dodie(int);
|
static void dodie(int);
|
||||||
static void dofsync(void);
|
static void dofsync(void);
|
||||||
static void domark(int);
|
static void domark(int);
|
||||||
static void fprintlog(struct filed *, int, const char *);
|
static void fprintlog_first(struct filed *, const char *, const char *,
|
||||||
|
const char *, const char *, const char *, const char *, int);
|
||||||
|
static void fprintlog_successive(struct filed *, int);
|
||||||
static void init(int);
|
static void init(int);
|
||||||
static void logerror(const char *);
|
static void logerror(const char *);
|
||||||
static void logmsg(int, const struct logtime *, const char *, const char *,
|
static void logmsg(int, const struct logtime *, const char *, const char *,
|
||||||
@ -1411,19 +1412,19 @@ skip_message(const char *name, const char *spec, int checkcase)
|
|||||||
* STRUCTURED-DATA fields are thus discarded for the time being.
|
* STRUCTURED-DATA fields are thus discarded for the time being.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
logmsg(int pri, const struct logtime *timestamp, const char *from,
|
logmsg(int pri, const struct logtime *timestamp, const char *hostname,
|
||||||
const char *app_name, const char *procid, const char *msgid __unused,
|
const char *app_name, const char *procid, const char *msgid,
|
||||||
const char *structured_data __unused, const char *msg, int flags)
|
const char *structured_data, const char *msg, int flags)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct logtime timestamp_now;
|
struct logtime timestamp_now;
|
||||||
struct filed *f;
|
struct filed *f;
|
||||||
size_t msglen;
|
size_t savedlen;
|
||||||
int fac, prilev;
|
int fac, prilev;
|
||||||
char buf[MAXLINE+1];
|
char saved[MAXSVLINE];
|
||||||
|
|
||||||
dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
|
dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
|
||||||
pri, flags, from, msg);
|
pri, flags, hostname, msg);
|
||||||
|
|
||||||
(void)gettimeofday(&tv, NULL);
|
(void)gettimeofday(&tv, NULL);
|
||||||
now = tv.tv_sec;
|
now = tv.tv_sec;
|
||||||
@ -1445,18 +1446,6 @@ logmsg(int pri, const struct logtime *timestamp, const char *from,
|
|||||||
|
|
||||||
prilev = LOG_PRI(pri);
|
prilev = LOG_PRI(pri);
|
||||||
|
|
||||||
/* Prepend the application name to the message if provided. */
|
|
||||||
if (app_name != NULL) {
|
|
||||||
if (procid != NULL)
|
|
||||||
msglen = snprintf(buf, sizeof(buf), "%s[%s]: %s",
|
|
||||||
app_name, procid, msg);
|
|
||||||
else
|
|
||||||
msglen = snprintf(buf, sizeof(buf), "%s: %s",
|
|
||||||
app_name, msg);
|
|
||||||
msg = buf;
|
|
||||||
} else
|
|
||||||
msglen = strlen(msg);
|
|
||||||
|
|
||||||
/* log the message to the particular outputs */
|
/* log the message to the particular outputs */
|
||||||
if (!Initialized) {
|
if (!Initialized) {
|
||||||
f = &consfile;
|
f = &consfile;
|
||||||
@ -1468,12 +1457,27 @@ logmsg(int pri, const struct logtime *timestamp, const char *from,
|
|||||||
|
|
||||||
if (f->f_file >= 0) {
|
if (f->f_file >= 0) {
|
||||||
f->f_lasttime = *timestamp;
|
f->f_lasttime = *timestamp;
|
||||||
fprintlog(f, flags, msg);
|
fprintlog_first(f, hostname, app_name, procid, msgid,
|
||||||
|
structured_data, msg, flags);
|
||||||
close(f->f_file);
|
close(f->f_file);
|
||||||
f->f_file = -1;
|
f->f_file = -1;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store all of the fields of the message, except the timestamp,
|
||||||
|
* in a single string. This string is used to detect duplicate
|
||||||
|
* messages.
|
||||||
|
*/
|
||||||
|
assert(hostname != NULL);
|
||||||
|
assert(msg != NULL);
|
||||||
|
savedlen = snprintf(saved, sizeof(saved),
|
||||||
|
"%d %s %s %s %s %s %s", pri, hostname,
|
||||||
|
app_name == NULL ? "-" : app_name, procid == NULL ? "-" : procid,
|
||||||
|
msgid == NULL ? "-" : msgid,
|
||||||
|
structured_data == NULL ? "-" : structured_data, msg);
|
||||||
|
|
||||||
STAILQ_FOREACH(f, &fhead, next) {
|
STAILQ_FOREACH(f, &fhead, next) {
|
||||||
/* skip messages that are incorrect priority */
|
/* skip messages that are incorrect priority */
|
||||||
if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev))
|
if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev))
|
||||||
@ -1484,7 +1488,7 @@ logmsg(int pri, const struct logtime *timestamp, const char *from,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip messages with the incorrect hostname */
|
/* skip messages with the incorrect hostname */
|
||||||
if (skip_message(from, f->f_host, 0))
|
if (skip_message(hostname, f->f_host, 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* skip messages with the incorrect program name */
|
/* skip messages with the incorrect program name */
|
||||||
@ -1504,9 +1508,8 @@ logmsg(int pri, const struct logtime *timestamp, const char *from,
|
|||||||
* suppress duplicate lines to this file
|
* suppress duplicate lines to this file
|
||||||
*/
|
*/
|
||||||
if (no_compress - (f->f_type != F_PIPE) < 1 &&
|
if (no_compress - (f->f_type != F_PIPE) < 1 &&
|
||||||
(flags & MARK) == 0 && msglen == f->f_prevlen &&
|
(flags & MARK) == 0 && savedlen == f->f_prevlen &&
|
||||||
!strcmp(msg, f->f_prevline) &&
|
strcmp(saved, f->f_prevline) == 0) {
|
||||||
!strcasecmp(from, f->f_prevhost)) {
|
|
||||||
f->f_lasttime = *timestamp;
|
f->f_lasttime = *timestamp;
|
||||||
f->f_prevcount++;
|
f->f_prevcount++;
|
||||||
dprintf("msg repeated %d times, %ld sec of %d\n",
|
dprintf("msg repeated %d times, %ld sec of %d\n",
|
||||||
@ -1519,27 +1522,22 @@ logmsg(int pri, const struct logtime *timestamp, const char *from,
|
|||||||
* in the future.
|
* in the future.
|
||||||
*/
|
*/
|
||||||
if (now > REPEATTIME(f)) {
|
if (now > REPEATTIME(f)) {
|
||||||
fprintlog(f, flags, (char *)NULL);
|
fprintlog_successive(f, flags);
|
||||||
BACKOFF(f);
|
BACKOFF(f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* new line, save it */
|
/* new line, save it */
|
||||||
if (f->f_prevcount)
|
if (f->f_prevcount)
|
||||||
fprintlog(f, 0, (char *)NULL);
|
fprintlog_successive(f, 0);
|
||||||
f->f_repeatcount = 0;
|
f->f_repeatcount = 0;
|
||||||
f->f_prevpri = pri;
|
f->f_prevpri = pri;
|
||||||
f->f_lasttime = *timestamp;
|
f->f_lasttime = *timestamp;
|
||||||
(void)strlcpy(f->f_prevhost, from,
|
static_assert(sizeof(f->f_prevline) == sizeof(saved),
|
||||||
sizeof(f->f_prevhost));
|
"Space to store saved line incorrect");
|
||||||
if (msglen < MAXSVLINE) {
|
(void)strcpy(f->f_prevline, saved);
|
||||||
f->f_prevlen = msglen;
|
f->f_prevlen = savedlen;
|
||||||
(void)strlcpy(f->f_prevline, msg, sizeof(f->f_prevline));
|
fprintlog_first(f, hostname, app_name, procid, msgid,
|
||||||
fprintlog(f, flags, (char *)NULL);
|
structured_data, msg, flags);
|
||||||
} else {
|
|
||||||
f->f_prevline[0] = 0;
|
|
||||||
f->f_prevlen = 0;
|
|
||||||
fprintlog(f, flags, msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1560,12 +1558,14 @@ dofsync(void)
|
|||||||
|
|
||||||
#define IOV_SIZE 7
|
#define IOV_SIZE 7
|
||||||
static void
|
static void
|
||||||
fprintlog(struct filed *f, int flags, const char *msg)
|
fprintlog_first(struct filed *f, const char *hostname, const char *app_name,
|
||||||
|
const char *procid, const char *msgid __unused,
|
||||||
|
const char *structured_data __unused, const char *msg, int flags)
|
||||||
{
|
{
|
||||||
struct iovec iov[IOV_SIZE];
|
struct iovec iov[IOV_SIZE];
|
||||||
struct addrinfo *r;
|
struct addrinfo *r;
|
||||||
int l, lsent = 0;
|
int l, lsent = 0;
|
||||||
char line[MAXLINE + 1], repbuf[80], greetings[200], *wmsg = NULL;
|
char tagged_msg[MAXLINE + 1], line[MAXLINE + 1], greetings[200];
|
||||||
char nul[] = "", space[] = " ", lf[] = "\n", crlf[] = "\r\n";
|
char nul[] = "", space[] = " ", lf[] = "\n", crlf[] = "\r\n";
|
||||||
char timebuf[RFC3164_DATELEN + 1];
|
char timebuf[RFC3164_DATELEN + 1];
|
||||||
const char *msgret;
|
const char *msgret;
|
||||||
@ -1583,8 +1583,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
|
|||||||
.iov_base = greetings,
|
.iov_base = greetings,
|
||||||
.iov_len = snprintf(greetings, sizeof(greetings),
|
.iov_len = snprintf(greetings, sizeof(greetings),
|
||||||
"\r\n\7Message from syslogd@%s "
|
"\r\n\7Message from syslogd@%s "
|
||||||
"at %.24s ...\r\n",
|
"at %.24s ...\r\n", hostname, timebuf)
|
||||||
f->f_prevhost, timebuf)
|
|
||||||
};
|
};
|
||||||
if (iov[0].iov_len >= sizeof(greetings))
|
if (iov[0].iov_len >= sizeof(greetings))
|
||||||
iov[0].iov_len = sizeof(greetings) - 1;
|
iov[0].iov_len = sizeof(greetings) - 1;
|
||||||
@ -1647,36 +1646,28 @@ fprintlog(struct filed *f, int flags, const char *msg)
|
|||||||
.iov_len = 0
|
.iov_len = 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/* Prepend the application name to the message if provided. */
|
||||||
|
if (app_name != NULL) {
|
||||||
|
if (procid != NULL)
|
||||||
|
snprintf(tagged_msg, sizeof(tagged_msg),
|
||||||
|
"%s[%s]: %s", app_name, procid, msg);
|
||||||
|
else
|
||||||
|
snprintf(tagged_msg, sizeof(tagged_msg),
|
||||||
|
"%s: %s", app_name, msg);
|
||||||
|
msg = tagged_msg;
|
||||||
|
}
|
||||||
iov[3] = (struct iovec){
|
iov[3] = (struct iovec){
|
||||||
.iov_base = f->f_prevhost,
|
.iov_base = __DECONST(char *, hostname),
|
||||||
.iov_len = strlen(f->f_prevhost)
|
.iov_len = strlen(hostname)
|
||||||
};
|
};
|
||||||
iov[4] = (struct iovec){
|
iov[4] = (struct iovec){
|
||||||
.iov_base = space,
|
.iov_base = space,
|
||||||
.iov_len = 1
|
.iov_len = 1
|
||||||
};
|
};
|
||||||
if (msg) {
|
iov[5] = (struct iovec){
|
||||||
wmsg = strdup(msg); /* XXX iov_base needs a `const' sibling. */
|
.iov_base = __DECONST(char *, msg),
|
||||||
if (wmsg == NULL) {
|
.iov_len = strlen(msg)
|
||||||
logerror("strdup");
|
};
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
iov[5] = (struct iovec){
|
|
||||||
.iov_base = wmsg,
|
|
||||||
.iov_len = strlen(msg)
|
|
||||||
};
|
|
||||||
} else if (f->f_prevcount > 1) {
|
|
||||||
iov[5] = (struct iovec){
|
|
||||||
.iov_base = repbuf,
|
|
||||||
.iov_len = snprintf(repbuf, sizeof(repbuf),
|
|
||||||
"last message repeated %d times", f->f_prevcount)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
iov[5] = (struct iovec){
|
|
||||||
.iov_base = f->f_prevline,
|
|
||||||
.iov_len = f->f_prevlen
|
|
||||||
};
|
|
||||||
}
|
|
||||||
dprintf("Logging to %s", TypeNames[f->f_type]);
|
dprintf("Logging to %s", TypeNames[f->f_type]);
|
||||||
f->f_time = now;
|
f->f_time = now;
|
||||||
|
|
||||||
@ -1704,11 +1695,11 @@ fprintlog(struct filed *f, int flags, const char *msg)
|
|||||||
dprintf("\n");
|
dprintf("\n");
|
||||||
}
|
}
|
||||||
/* check for local vs remote messages */
|
/* check for local vs remote messages */
|
||||||
if (strcasecmp(f->f_prevhost, LocalHostName))
|
if (strcasecmp(hostname, LocalHostName))
|
||||||
l = snprintf(line, sizeof line - 1,
|
l = snprintf(line, sizeof line - 1,
|
||||||
"<%d>%.15s Forwarded from %s: %s",
|
"<%d>%.15s Forwarded from %s: %s",
|
||||||
f->f_prevpri, (char *)iov[0].iov_base,
|
f->f_prevpri, (char *)iov[0].iov_base,
|
||||||
f->f_prevhost, (char *)iov[5].iov_base);
|
hostname, (char *)iov[5].iov_base);
|
||||||
else
|
else
|
||||||
l = snprintf(line, sizeof line - 1, "<%d>%.15s %s",
|
l = snprintf(line, sizeof line - 1, "<%d>%.15s %s",
|
||||||
f->f_prevpri, (char *)iov[0].iov_base,
|
f->f_prevpri, (char *)iov[0].iov_base,
|
||||||
@ -1841,7 +1832,22 @@ fprintlog(struct filed *f, int flags, const char *msg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
f->f_prevcount = 0;
|
f->f_prevcount = 0;
|
||||||
free(wmsg);
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints a message to a log file that the previously logged message was
|
||||||
|
* received multiple times.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fprintlog_successive(struct filed *f, int flags)
|
||||||
|
{
|
||||||
|
char msg[100];
|
||||||
|
|
||||||
|
assert(f->f_prevcount > 0);
|
||||||
|
snprintf(msg, sizeof(msg), "last message repeated %d times",
|
||||||
|
f->f_prevcount);
|
||||||
|
fprintlog_first(f, LocalHostName, "syslogd", NULL, NULL, NULL, msg,
|
||||||
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2022,7 +2028,7 @@ die(int signo)
|
|||||||
STAILQ_FOREACH(f, &fhead, next) {
|
STAILQ_FOREACH(f, &fhead, next) {
|
||||||
/* flush any pending output */
|
/* flush any pending output */
|
||||||
if (f->f_prevcount)
|
if (f->f_prevcount)
|
||||||
fprintlog(f, 0, (char *)NULL);
|
fprintlog_successive(f, 0);
|
||||||
if (f->f_type == F_PIPE && f->fu_pipe_pid > 0)
|
if (f->f_type == F_PIPE && f->fu_pipe_pid > 0)
|
||||||
close_filed(f);
|
close_filed(f);
|
||||||
}
|
}
|
||||||
@ -2252,7 +2258,7 @@ init(int signo)
|
|||||||
STAILQ_FOREACH(f, &fhead, next) {
|
STAILQ_FOREACH(f, &fhead, next) {
|
||||||
/* flush any pending output */
|
/* flush any pending output */
|
||||||
if (f->f_prevcount)
|
if (f->f_prevcount)
|
||||||
fprintlog(f, 0, (char *)NULL);
|
fprintlog_successive(f, 0);
|
||||||
|
|
||||||
switch (f->f_type) {
|
switch (f->f_type) {
|
||||||
case F_FILE:
|
case F_FILE:
|
||||||
@ -2696,7 +2702,7 @@ markit(void)
|
|||||||
dprintf("flush %s: repeated %d times, %d sec.\n",
|
dprintf("flush %s: repeated %d times, %d sec.\n",
|
||||||
TypeNames[f->f_type], f->f_prevcount,
|
TypeNames[f->f_type], f->f_prevcount,
|
||||||
repeatinterval[f->f_repeatcount]);
|
repeatinterval[f->f_repeatcount]);
|
||||||
fprintlog(f, 0, (char *)NULL);
|
fprintlog_successive(f, 0);
|
||||||
BACKOFF(f);
|
BACKOFF(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user