Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split out syslog protocol #108

Merged
merged 1 commit into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ systemd_netlogd_sources = files('''
netlog/netlog-manager.h
netlog/netlog-network.c
netlog/netlog-network.h
netlog/netlog-protocol.c
netlog/netlog-protocol.h
netlog/netlog-dtls.c
netlog/netlog-dtls.h
netlog/netlog-tls.c
Expand Down
224 changes: 3 additions & 221 deletions src/netlog/netlog-network.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "fd-util.h"
#include "io-util.h"
#include "netlog-manager.h"
#include "netlog-network.h"
#include "netlog-protocol.h"

#define RFC_5424_NILVALUE "-"
#define RFC_5424_PROTOCOL 1
Expand Down Expand Up @@ -46,7 +48,7 @@ static int sendmsg_loop(Manager *m, struct msghdr *mh) {
return 0;
}

static int network_send(Manager *m, struct iovec *iovec, unsigned n_iovec) {
int network_send(Manager *m, struct iovec *iovec, unsigned n_iovec) {
struct msghdr mh = {
.msg_iov = iovec,
.msg_iovlen = n_iovec,
Expand All @@ -67,226 +69,6 @@ static int network_send(Manager *m, struct iovec *iovec, unsigned n_iovec) {

return sendmsg_loop(m, &mh);
}

static int protocol_send(Manager *m, struct iovec *iovec, unsigned n_iovec) {
int r;

switch (m->protocol) {
case SYSLOG_TRANSMISSION_PROTOCOL_DTLS:
r = dtls_datagram_writev(m->dtls, iovec, n_iovec);
if (r < 0 && r != -EAGAIN) {
manager_connect(m);
return r;
}
break;
case SYSLOG_TRANSMISSION_PROTOCOL_TLS:
r = tls_stream_writev(m->tls, iovec, n_iovec);
if (r < 0 && r != -EAGAIN) {
manager_connect(m);
return r;
}
break;
default:
r = network_send(m, iovec, n_iovec);
if (r < 0 && r != -EAGAIN) {
manager_connect(m);
return r;
}
break;
}

return 0;
}

/* rfc3339 timestamp format: yyyy-mm-ddthh:mm:ss[.frac]<+/->zz:zz */
static void format_rfc3339_timestamp(const struct timeval *tv, char *header_time, size_t header_size) {
char gm_buf[sizeof("+0530") + 1];
struct tm tm;
time_t t;
size_t written;
int r;

assert(header_time);

t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
localtime_r(&t, &tm);

written = strftime(header_time, header_size, "%Y-%m-%dT%T", &tm);
assert(written != 0);
header_time += written;
header_size -= written;

/* add fractional part */
if (tv) {
r = snprintf(header_time, header_size, ".%06ld", tv->tv_usec);
assert(r > 0 && (size_t)r < header_size);
header_time += r;
header_size -= r;
}

/* format the timezone according to RFC */
xstrftime(gm_buf, "%z", &tm);
r = snprintf(header_time, header_size, "%.3s:%.2s ", gm_buf, gm_buf + 3);
assert(r > 0 && (size_t)r < header_size);
}

/* The Syslog Protocol RFC5424 format :
* <pri>version sp timestamp sp hostname sp app-name sp procid sp msgid sp [sd-id]s sp msg
*/
static int format_rfc5424(Manager *m,
int severity,
int facility,
const char *identifier,
const char *message,
const char *hostname,
const char *pid,
const struct timeval *tv,
const char *syslog_structured_data,
const char *syslog_msgid) {

char header_time[FORMAT_TIMESTAMP_MAX];
char header_priority[sizeof("< >1 ")];
struct iovec iov[14];
uint8_t makepri;
int n = 0, r;

assert(m);
assert(message);

makepri = (facility << 3) + severity;

/* First: priority field Second: Version '<pri>version' */
r = snprintf(header_priority, sizeof(header_priority), "<%i>%i ", makepri, RFC_5424_PROTOCOL);
assert(r > 0 && (size_t)r < sizeof(header_priority));
IOVEC_SET_STRING(iov[n++], header_priority);

/* Third: timestamp */
format_rfc3339_timestamp(tv, header_time, sizeof(header_time));
IOVEC_SET_STRING(iov[n++], header_time);

/* Fourth: hostname */
if (hostname)
IOVEC_SET_STRING(iov[n++], hostname);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], " ");

/* Fifth: identifier */
if (identifier)
IOVEC_SET_STRING(iov[n++], identifier);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], " ");

/* Sixth: procid */
if (pid)
IOVEC_SET_STRING(iov[n++], pid);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], " ");

/* Seventh: msgid */
if (syslog_msgid)
IOVEC_SET_STRING(iov[n++], syslog_msgid);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], " ");

/* Eighth: [structured-data] */
if (m->structured_data)
IOVEC_SET_STRING(iov[n++], m->structured_data);
else if (syslog_structured_data)
IOVEC_SET_STRING(iov[n++], syslog_structured_data);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], " ");

/* Ninth: message */
IOVEC_SET_STRING(iov[n++], message);

/* Last Optional newline message separator, if not implicitly terminated by end of UDP frame
* De facto standard: separate messages by a newline
*/
if (m->protocol == SYSLOG_TRANSMISSION_PROTOCOL_TCP)
IOVEC_SET_STRING(iov[n++], "\n");

return protocol_send(m, iov, n);
}

static int format_rfc3339(Manager *m,
int severity,
int facility,
const char *identifier,
const char *message,
const char *hostname,
const char *pid,
const struct timeval *tv) {

char header_priority[sizeof("< >1 ")];
char header_time[FORMAT_TIMESTAMP_MAX];
struct iovec iov[14];
uint8_t makepri;
int n = 0, r;

assert(m);
assert(message);

makepri = (facility << 3) + severity;

/* rfc3339
* <35>Oct 12 22:14:15 client_machine su: 'su root' failed for joe on /dev/pts/2
*/

/* First: priority field '<pri>' */
r = snprintf(header_priority, sizeof(header_priority), "<%i>", makepri);
assert(r > 0 && (size_t)r < sizeof(header_priority));
IOVEC_SET_STRING(iov[n++], header_priority);

/* Third: timestamp */
format_rfc3339_timestamp(tv, header_time, sizeof(header_time));
IOVEC_SET_STRING(iov[n++], header_time);

/* Fourth: hostname */
if (hostname)
IOVEC_SET_STRING(iov[n++], hostname);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], " ");

/* Fifth: identifier */
if (identifier)
IOVEC_SET_STRING(iov[n++], identifier);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], "[");

/* Sixth: procid */
if (pid)
IOVEC_SET_STRING(iov[n++], pid);
else
IOVEC_SET_STRING(iov[n++], RFC_5424_NILVALUE);

IOVEC_SET_STRING(iov[n++], "]: ");

/* Ninth: message */
IOVEC_SET_STRING(iov[n++], message);

/* Last Optional newline message separator, if not implicitly terminated by end of UDP frame
* De facto standard: separate messages by a newline
*/
if (m->protocol == SYSLOG_TRANSMISSION_PROTOCOL_TCP)
IOVEC_SET_STRING(iov[n++], "\n");

return protocol_send(m, iov, n);
}

int manager_push_to_network(Manager *m,
int severity,
int facility,
Expand Down
2 changes: 2 additions & 0 deletions src/netlog/netlog-network.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
#pragma once

#include "netlog-manager.h"

int network_send(Manager *m, struct iovec *iovec, unsigned n_iovec);
Loading