From a893462adf01e762e2d6155f874e190e93a950bb Mon Sep 17 00:00:00 2001 From: someguy Date: Fri, 29 Apr 2022 03:39:23 -0700 Subject: [PATCH 1/7] Add support for syslog over TCP. --- conf/systemd-netlogd.conf.in | 1 + src/netlog/netlog-conf.c | 31 ++++++++++++++++++++++ src/netlog/netlog-conf.h | 10 ++++++++ src/netlog/netlog-gperf.gperf | 1 + src/netlog/netlog-manager.h | 1 + src/netlog/netlog-network.c | 48 +++++++++++++++++++++++++++++++++-- src/share/fd-util.c | 23 +++++++++++++++++ src/share/fd-util.h | 1 + 8 files changed, 114 insertions(+), 2 deletions(-) diff --git a/conf/systemd-netlogd.conf.in b/conf/systemd-netlogd.conf.in index b567a46..2a468bf 100644 --- a/conf/systemd-netlogd.conf.in +++ b/conf/systemd-netlogd.conf.in @@ -1,2 +1,3 @@ [Network] #Address=239.0.0.1:6000 +#SocketType=udp diff --git a/src/netlog/netlog-conf.c b/src/netlog/netlog-conf.c index cac093e..e550731 100644 --- a/src/netlog/netlog-conf.c +++ b/src/netlog/netlog-conf.c @@ -4,6 +4,7 @@ #include "in-addr-util.h" #include "netlog-conf.h" #include "conf-parser.h" +#include "string-util.h" int config_parse_netlog_remote_address(const char *unit, const char *filename, @@ -33,6 +34,36 @@ int config_parse_netlog_remote_address(const char *unit, return 0; } +int config_parse_socket_type(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Manager *m = userdata; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (strcaseeq(rvalue, "tcp")) + m->socket_type = SOCK_STREAM; + else if (strcaseeq(rvalue, "udp")) + m->socket_type = SOCK_DGRAM; + else { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Unrecognised socket type '%s'; should be either 'tcp' or 'udp'", rvalue); + return -EINVAL; + } + + return 0; +} + int manager_parse_config_file(Manager *m) { assert(m); diff --git a/src/netlog/netlog-conf.h b/src/netlog/netlog-conf.h index ff9e2aa..bbc8271 100644 --- a/src/netlog/netlog-conf.h +++ b/src/netlog/netlog-conf.h @@ -17,4 +17,14 @@ int config_parse_netlog_remote_address(const char *unit, const char *rvalue, void *data, void *userdata); +int config_parse_socket_type(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata); int manager_parse_config_file(Manager *m); diff --git a/src/netlog/netlog-gperf.gperf b/src/netlog/netlog-gperf.gperf index 221771c..ed48574 100644 --- a/src/netlog/netlog-gperf.gperf +++ b/src/netlog/netlog-gperf.gperf @@ -16,4 +16,5 @@ struct ConfigPerfItem; %includes %% Network.Address, config_parse_netlog_remote_address, 0, 0 +Network.SocketType, config_parse_socket_type, 0, offsetof(Manager, socket_type) Network.StructuredData, config_parse_string, 0, offsetof(Manager, structured_data) diff --git a/src/netlog/netlog-manager.h b/src/netlog/netlog-manager.h index 7aeb552..5280b69 100644 --- a/src/netlog/netlog-manager.h +++ b/src/netlog/netlog-manager.h @@ -33,6 +33,7 @@ struct Manager { char *last_cursor, *current_cursor; char *structured_data; + int socket_type; }; int manager_new(Manager **ret, const char *state_file, const char *cursor); diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index 97e9701..11a595d 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "netlog-manager.h" #include "io-util.h" @@ -97,7 +98,7 @@ int manager_push_to_network(Manager *m, char header_priority[sizeof("< >1 ")]; char header_time[FORMAT_TIMESTAMP_MAX]; uint8_t makepri; - struct iovec iov[13]; + struct iovec iov[14]; int n = 0; assert(m); @@ -152,6 +153,10 @@ int manager_push_to_network(Manager *m, /* Ninth: message */ IOVEC_SET_STRING(iov[n++], message); + /* Tenth: Newline message separator, if not implicitly terminated by end of UDP frame */ + if (m->socket_type == SOCK_DGRAM) + IOVEC_SET_STRING(iov[n++], "\n"); + return network_send(m, iov, n); } @@ -170,7 +175,7 @@ int manager_open_network_socket(Manager *m) { if (!IN_SET(m->address.sockaddr.sa.sa_family, AF_INET, AF_INET6)) return -EAFNOSUPPORT; - m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + m->socket = socket(m->address.sockaddr.sa.sa_family, m->socket_type|SOCK_CLOEXEC, 0); if (m->socket < 0) return -errno; @@ -180,6 +185,45 @@ int manager_open_network_socket(Manager *m) { goto fail; } + if (SOCK_STREAM == m->socket_type) { + union sockaddr_union sa; + socklen_t salen; + switch (m->address.sockaddr.sa.sa_family) { + case AF_INET: + sa = (union sockaddr_union) { + .in.sin_family = m->address.sockaddr.sa.sa_family, + .in.sin_port = m->address.sockaddr.in.sin_port, + .in.sin_addr = m->address.sockaddr.in.sin_addr, + }; + salen = sizeof(sa.in); + break; + case AF_INET6: + sa = (union sockaddr_union) { + .in6.sin6_family = m->address.sockaddr.sa.sa_family, + .in6.sin6_port = m->address.sockaddr.in6.sin6_port, + .in6.sin6_addr = m->address.sockaddr.in6.sin6_addr, + }; + salen = sizeof(sa.in6); + break; + default: + r = -EAFNOSUPPORT; + goto fail; + } + r = connect(m->socket, &m->address.sockaddr.sa, salen); + if (r < 0) { + r = -errno; + goto fail; + } + + r = setsockopt(m->socket, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); + if (r < 0) + return r; + } + + r = fd_status_flag(m->socket, O_NONBLOCK, 1); + if (r < 0) + goto fail; + return m->socket; fail: diff --git a/src/share/fd-util.c b/src/share/fd-util.c index dc9c27b..10616c0 100644 --- a/src/share/fd-util.c +++ b/src/share/fd-util.c @@ -121,6 +121,29 @@ int fd_cloexec(int fd, bool cloexec) { return 0; } +int fd_status_flag(int fd, int flag, bool new_value) { + int flags, nflags; + + assert(fd >= 0); + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) + return -errno; + + if (new_value) + nflags = flags | flag; + else + nflags = flags & ~flag; + + if (nflags == flags) + return 0; + + if (fcntl(fd, F_SETFL, nflags) < 0) + return -errno; + + return 0; +} + void stdio_unset_cloexec(void) { fd_cloexec(STDIN_FILENO, false); fd_cloexec(STDOUT_FILENO, false); diff --git a/src/share/fd-util.h b/src/share/fd-util.h index ebb88ce..5c79bb3 100644 --- a/src/share/fd-util.h +++ b/src/share/fd-util.h @@ -38,6 +38,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir); #define _cleanup_close_pair_ _cleanup_(close_pairp) int fd_cloexec(int fd, bool cloexec); +int fd_status_flag(int fd, int flag, bool new_value); void stdio_unset_cloexec(void); From 69c38ec4e9577106b0959ab087b6c00f22781898 Mon Sep 17 00:00:00 2001 From: someguy Date: Sun, 1 May 2022 23:07:41 -0700 Subject: [PATCH 2/7] Copy and use fd_nonblock and RET_NERRNO from systemd source. --- src/netlog/netlog-network.c | 2 +- src/share/fd-util.c | 13 +++---------- src/share/fd-util.h | 2 +- src/share/macro.h | 6 +++++- src/share/util.h | 23 +++++++++++++++++++++++ 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index 11a595d..dd2bd9f 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -220,7 +220,7 @@ int manager_open_network_socket(Manager *m) { return r; } - r = fd_status_flag(m->socket, O_NONBLOCK, 1); + r = fd_nonblock(m->socket, 1); if (r < 0) goto fail; diff --git a/src/share/fd-util.c b/src/share/fd-util.c index 10616c0..317e492 100644 --- a/src/share/fd-util.c +++ b/src/share/fd-util.c @@ -121,7 +121,7 @@ int fd_cloexec(int fd, bool cloexec) { return 0; } -int fd_status_flag(int fd, int flag, bool new_value) { +int fd_nonblock(int fd, bool nonblock) { int flags, nflags; assert(fd >= 0); @@ -130,18 +130,11 @@ int fd_status_flag(int fd, int flag, bool new_value) { if (flags < 0) return -errno; - if (new_value) - nflags = flags | flag; - else - nflags = flags & ~flag; - + nflags = UPDATE_FLAG(flags, O_NONBLOCK, nonblock); if (nflags == flags) return 0; - if (fcntl(fd, F_SETFL, nflags) < 0) - return -errno; - - return 0; + return RET_NERRNO(fcntl(fd, F_SETFL, nflags)); } void stdio_unset_cloexec(void) { diff --git a/src/share/fd-util.h b/src/share/fd-util.h index 5c79bb3..cfe5089 100644 --- a/src/share/fd-util.h +++ b/src/share/fd-util.h @@ -38,7 +38,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir); #define _cleanup_close_pair_ _cleanup_(close_pairp) int fd_cloexec(int fd, bool cloexec); -int fd_status_flag(int fd, int flag, bool new_value); +int fd_nonblock(int fd, bool nonblock); void stdio_unset_cloexec(void); diff --git a/src/share/macro.h b/src/share/macro.h index b8b526b..0423390 100644 --- a/src/share/macro.h +++ b/src/share/macro.h @@ -312,8 +312,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { ans; \ }) +#define UPDATE_FLAG(orig, flag, b) \ + ((b) ? ((orig) | (flag)) : ((orig) & ~(flag))) #define SET_FLAG(v, flag, b) \ - (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) + (v) = UPDATE_FLAG(v, flag, b) +#define FLAGS_SET(v, flags) \ + ((~(v) & (flags)) == 0) #define CASE_F(X) case X: #define CASE_F_1(CASE, X) CASE_F(X) diff --git a/src/share/util.h b/src/share/util.h index 1e74330..18a7be4 100644 --- a/src/share/util.h +++ b/src/share/util.h @@ -103,6 +103,29 @@ static inline int negative_errno(void) { return -errno; } +static inline int RET_NERRNO(int ret) { + + /* Helper to wrap system calls in to make them return negative errno errors. This brings system call + * error handling in sync with how we usually handle errors in our own code, i.e. with immediate + * returning of negative errno. Usage is like this: + * + * … + * r = RET_NERRNO(unlink(t)); + * … + * + * or + * + * … + * fd = RET_NERRNO(open("/etc/fstab", O_RDONLY|O_CLOEXEC)); + * … + */ + + if (ret < 0) + return negative_errno(); + + return ret; +} + static inline unsigned u64log2(uint64_t n) { #if __SIZEOF_LONG_LONG__ == 8 return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0; From 0b5c1d7183a95ffacb56a8db909533d7e4b722f6 Mon Sep 17 00:00:00 2001 From: someguy Date: Mon, 2 May 2022 18:06:02 -0700 Subject: [PATCH 3/7] Use the term 'Protocol' instead of 'SocketType' to distinguish between UDP and TCP. --- conf/systemd-netlogd.conf.in | 2 +- src/netlog/netlog-gperf.gperf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/systemd-netlogd.conf.in b/conf/systemd-netlogd.conf.in index 2a468bf..4dca9cc 100644 --- a/conf/systemd-netlogd.conf.in +++ b/conf/systemd-netlogd.conf.in @@ -1,3 +1,3 @@ [Network] #Address=239.0.0.1:6000 -#SocketType=udp +#Protocol=udp diff --git a/src/netlog/netlog-gperf.gperf b/src/netlog/netlog-gperf.gperf index ed48574..17508f1 100644 --- a/src/netlog/netlog-gperf.gperf +++ b/src/netlog/netlog-gperf.gperf @@ -16,5 +16,5 @@ struct ConfigPerfItem; %includes %% Network.Address, config_parse_netlog_remote_address, 0, 0 -Network.SocketType, config_parse_socket_type, 0, offsetof(Manager, socket_type) +Network.Protocol, config_parse_socket_type, 0, offsetof(Manager, socket_type) Network.StructuredData, config_parse_string, 0, offsetof(Manager, structured_data) From 0368271534283f6f73dbc56e83c404b993282f18 Mon Sep 17 00:00:00 2001 From: someguy Date: Mon, 2 May 2022 18:13:00 -0700 Subject: [PATCH 4/7] Use the term 'protocol' everywhere, instad of socket_type. --- src/netlog/netlog-conf.c | 8 ++++---- src/netlog/netlog-conf.h | 20 ++++++++++---------- src/netlog/netlog-gperf.gperf | 2 +- src/netlog/netlog-manager.h | 2 +- src/netlog/netlog-network.c | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/netlog/netlog-conf.c b/src/netlog/netlog-conf.c index e550731..ed88296 100644 --- a/src/netlog/netlog-conf.c +++ b/src/netlog/netlog-conf.c @@ -34,7 +34,7 @@ int config_parse_netlog_remote_address(const char *unit, return 0; } -int config_parse_socket_type(const char *unit, +int config_parse_protocol(const char *unit, const char *filename, unsigned line, const char *section, @@ -52,12 +52,12 @@ int config_parse_socket_type(const char *unit, assert(data); if (strcaseeq(rvalue, "tcp")) - m->socket_type = SOCK_STREAM; + m->protocol = SOCK_STREAM; else if (strcaseeq(rvalue, "udp")) - m->socket_type = SOCK_DGRAM; + m->protocol = SOCK_DGRAM; else { log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Unrecognised socket type '%s'; should be either 'tcp' or 'udp'", rvalue); + "Unrecognised protocol '%s'; should be either 'tcp' or 'udp'", rvalue); return -EINVAL; } diff --git a/src/netlog/netlog-conf.h b/src/netlog/netlog-conf.h index bbc8271..421a37e 100644 --- a/src/netlog/netlog-conf.h +++ b/src/netlog/netlog-conf.h @@ -17,14 +17,14 @@ int config_parse_netlog_remote_address(const char *unit, const char *rvalue, void *data, void *userdata); -int config_parse_socket_type(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata); +int config_parse_protocol(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata); int manager_parse_config_file(Manager *m); diff --git a/src/netlog/netlog-gperf.gperf b/src/netlog/netlog-gperf.gperf index 17508f1..8f92b23 100644 --- a/src/netlog/netlog-gperf.gperf +++ b/src/netlog/netlog-gperf.gperf @@ -16,5 +16,5 @@ struct ConfigPerfItem; %includes %% Network.Address, config_parse_netlog_remote_address, 0, 0 -Network.Protocol, config_parse_socket_type, 0, offsetof(Manager, socket_type) +Network.Protocol, config_parse_protocol, 0, offsetof(Manager, protocol) Network.StructuredData, config_parse_string, 0, offsetof(Manager, structured_data) diff --git a/src/netlog/netlog-manager.h b/src/netlog/netlog-manager.h index 5280b69..1c1a4c1 100644 --- a/src/netlog/netlog-manager.h +++ b/src/netlog/netlog-manager.h @@ -33,7 +33,7 @@ struct Manager { char *last_cursor, *current_cursor; char *structured_data; - int socket_type; + int protocol; }; int manager_new(Manager **ret, const char *state_file, const char *cursor); diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index dd2bd9f..6298589 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -154,7 +154,7 @@ int manager_push_to_network(Manager *m, IOVEC_SET_STRING(iov[n++], message); /* Tenth: Newline message separator, if not implicitly terminated by end of UDP frame */ - if (m->socket_type == SOCK_DGRAM) + if (m->protocol == SOCK_DGRAM) IOVEC_SET_STRING(iov[n++], "\n"); return network_send(m, iov, n); @@ -175,7 +175,7 @@ int manager_open_network_socket(Manager *m) { if (!IN_SET(m->address.sockaddr.sa.sa_family, AF_INET, AF_INET6)) return -EAFNOSUPPORT; - m->socket = socket(m->address.sockaddr.sa.sa_family, m->socket_type|SOCK_CLOEXEC, 0); + m->socket = socket(m->address.sockaddr.sa.sa_family, m->protocol|SOCK_CLOEXEC, 0); if (m->socket < 0) return -errno; @@ -185,7 +185,7 @@ int manager_open_network_socket(Manager *m) { goto fail; } - if (SOCK_STREAM == m->socket_type) { + if (SOCK_STREAM == m->protocol) { union sockaddr_union sa; socklen_t salen; switch (m->address.sockaddr.sa.sa_family) { From 65e961c5c8d59918065793c54e29534dd6824519 Mon Sep 17 00:00:00 2001 From: someguy Date: Mon, 2 May 2022 20:51:36 -0700 Subject: [PATCH 5/7] Use an enumeration for TCP/UDP protocol instead of SOCK_STREAM/SOCK_DGRAM directly. Use a string table instead of direct string comparisons. --- src/netlog/netlog-manager.c | 8 ++++++++ src/netlog/netlog-manager.h | 12 +++++++++++- src/netlog/netlog-network.c | 22 ++++++++++++++++++---- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/netlog/netlog-manager.c b/src/netlog/netlog-manager.c index cc204cc..f3b541f 100644 --- a/src/netlog/netlog-manager.c +++ b/src/netlog/netlog-manager.c @@ -12,6 +12,7 @@ #include "fd-util.h" #include "fileio.h" #include "string-util.h" +#include "string-table.h" #include "parse-util.h" #include "netlog-manager.h" @@ -26,6 +27,13 @@ #define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \ for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; ) +static const char *const protocol_table[_SYSLOG_TRANSMISSION_PROTOCOL_MAX] = { + [SYSLOG_TRANSMISSION_PROTOCOL_UDP] = "udp", + [SYSLOG_TRANSMISSION_PROTOCOL_TCP] = "tcp", +}; + +DEFINE_STRING_TABLE_LOOKUP(protocol, int); + static int parse_field(const void *data, size_t length, const char *field, char **target) { size_t fl, nl; void *buf; diff --git a/src/netlog/netlog-manager.h b/src/netlog/netlog-manager.h index 1c1a4c1..14d92ae 100644 --- a/src/netlog/netlog-manager.h +++ b/src/netlog/netlog-manager.h @@ -7,6 +7,13 @@ #include "sd-network.h" #include "socket-util.h" +typedef enum SysLogTransmissionProtocol { + SYSLOG_TRANSMISSION_PROTOCOL_UDP = 1 << 0, + SYSLOG_TRANSMISSION_PROTOCOL_TCP = 1 << 1, + _SYSLOG_TRANSMISSION_PROTOCOL_MAX, + _SYSLOG_TRANSMISSION_PROTOCOL_INVALID = -EINVAL, +} SysLogTransmissionProtocol; + typedef struct Manager Manager; struct Manager { @@ -33,7 +40,7 @@ struct Manager { char *last_cursor, *current_cursor; char *structured_data; - int protocol; + SysLogTransmissionProtocol protocol; }; int manager_new(Manager **ret, const char *state_file, const char *cursor); @@ -51,3 +58,6 @@ int manager_push_to_network(Manager *m, int severity, int facility, const char *identifier, const char *message, const char *hostname, const char *pid, const struct timeval *tv); + +const char *protocol_to_string(int v) _const_; +int protocol_from_string(const char *s) _pure_; diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index 6298589..ac7a80b 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -153,9 +153,14 @@ int manager_push_to_network(Manager *m, /* Ninth: message */ IOVEC_SET_STRING(iov[n++], message); - /* Tenth: Newline message separator, if not implicitly terminated by end of UDP frame */ - if (m->protocol == SOCK_DGRAM) + /* Tenth: Optional newline message separator, if not implicitly terminated by end of UDP frame */ + if (SYSLOG_TRANSMISSION_PROTOCOL_TCP == m->protocol) + /* De facto standard: separate messages by a newline */ IOVEC_SET_STRING(iov[n++], "\n"); + else if (SYSLOG_TRANSMISSION_PROTOCOL_UDP == m->protocol) { + /* Message is implicitly terminated by end of UDP packet */ + } else + return -EPROTONOSUPPORT; return network_send(m, iov, n); } @@ -175,7 +180,16 @@ int manager_open_network_socket(Manager *m) { if (!IN_SET(m->address.sockaddr.sa.sa_family, AF_INET, AF_INET6)) return -EAFNOSUPPORT; - m->socket = socket(m->address.sockaddr.sa.sa_family, m->protocol|SOCK_CLOEXEC, 0); + switch (m->protocol) { + case SYSLOG_TRANSMISSION_PROTOCOL_UDP: + m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + break; + case SYSLOG_TRANSMISSION_PROTOCOL_TCP: + m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + break; + default: + return -EINVAL; + } if (m->socket < 0) return -errno; @@ -185,7 +199,7 @@ int manager_open_network_socket(Manager *m) { goto fail; } - if (SOCK_STREAM == m->protocol) { + if (SYSLOG_TRANSMISSION_PROTOCOL_TCP == m->protocol) { union sockaddr_union sa; socklen_t salen; switch (m->address.sockaddr.sa.sa_family) { From d5c5e4d5dcf3673b8fbf36385b9fbaaa03d2b9fa Mon Sep 17 00:00:00 2001 From: someguy Date: Mon, 2 May 2022 21:39:05 -0700 Subject: [PATCH 6/7] Use the string table. Correct an error code. --- src/netlog/netlog-conf.c | 15 +++++++-------- src/netlog/netlog-network.c | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/netlog/netlog-conf.c b/src/netlog/netlog-conf.c index ed88296..3f78c52 100644 --- a/src/netlog/netlog-conf.c +++ b/src/netlog/netlog-conf.c @@ -45,22 +45,21 @@ int config_parse_protocol(const char *unit, void *data, void *userdata) { Manager *m = userdata; + int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (strcaseeq(rvalue, "tcp")) - m->protocol = SOCK_STREAM; - else if (strcaseeq(rvalue, "udp")) - m->protocol = SOCK_DGRAM; - else { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Unrecognised protocol '%s'; should be either 'tcp' or 'udp'", rvalue); - return -EINVAL; + r = protocol_from_string(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, -r, + "Unrecognised Protocol '%s'", rvalue); + return -EPROTONOSUPPORT; } + m->protocol = r; return 0; } diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index ac7a80b..def922b 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -188,7 +188,7 @@ int manager_open_network_socket(Manager *m) { m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); break; default: - return -EINVAL; + return -EPROTONOSUPPORT; } if (m->socket < 0) return -errno; From eee1031a24a827ef17bd4efa4d834d460a3ecedd Mon Sep 17 00:00:00 2001 From: someguy Date: Mon, 2 May 2022 21:39:50 -0700 Subject: [PATCH 7/7] Shut down TCP sockets gracefully. --- src/netlog/netlog-network.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index def922b..4b10f89 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -168,6 +168,21 @@ int manager_push_to_network(Manager *m, void manager_close_network_socket(Manager *m) { assert(m); + switch (m->protocol) { + case SYSLOG_TRANSMISSION_PROTOCOL_UDP: + /* shutdown not required */ + break; + case SYSLOG_TRANSMISSION_PROTOCOL_TCP: + { + int r = shutdown(m->socket, SHUT_RDWR); + if (r < 0) + log_error_errno(r, "Failed to shutdown netlog socket: %m"); + } + break; + default: + break; + } + m->socket = safe_close(m->socket); }