Skip to content
Merged

Tcp #29

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
1 change: 1 addition & 0 deletions conf/systemd-netlogd.conf.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[Network]
#Address=239.0.0.1:6000
#Protocol=udp
30 changes: 30 additions & 0 deletions src/netlog/netlog-conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -33,6 +34,35 @@ int config_parse_netlog_remote_address(const char *unit,
return 0;
}

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) {
Manager *m = userdata;
int r;

assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);

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;
}

int manager_parse_config_file(Manager *m) {
assert(m);

Expand Down
10 changes: 10 additions & 0 deletions src/netlog/netlog-conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,14 @@ int config_parse_netlog_remote_address(const char *unit,
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);
1 change: 1 addition & 0 deletions src/netlog/netlog-gperf.gperf
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ struct ConfigPerfItem;
%includes
%%
Network.Address, config_parse_netlog_remote_address, 0, 0
Network.Protocol, config_parse_protocol, 0, offsetof(Manager, protocol)
Network.StructuredData, config_parse_string, 0, offsetof(Manager, structured_data)
8 changes: 8 additions & 0 deletions src/netlog/netlog-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions src/netlog/netlog-manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -33,6 +40,7 @@ struct Manager {

char *last_cursor, *current_cursor;
char *structured_data;
SysLogTransmissionProtocol protocol;
};

int manager_new(Manager **ret, const char *state_file, const char *cursor);
Expand All @@ -50,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_;
77 changes: 75 additions & 2 deletions src/netlog/netlog-network.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <unistd.h>
#include <stddef.h>
#include <poll.h>
#include <netinet/tcp.h>

#include "netlog-manager.h"
#include "io-util.h"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -152,12 +153,36 @@ int manager_push_to_network(Manager *m,
/* Ninth: message */
IOVEC_SET_STRING(iov[n++], message);

/* 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);
}

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);
}

Expand All @@ -170,7 +195,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, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 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 -EPROTONOSUPPORT;
}
if (m->socket < 0)
return -errno;

Expand All @@ -180,6 +214,45 @@ int manager_open_network_socket(Manager *m) {
goto fail;
}

if (SYSLOG_TRANSMISSION_PROTOCOL_TCP == m->protocol) {
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_nonblock(m->socket, 1);
if (r < 0)
goto fail;

return m->socket;

fail:
Expand Down
16 changes: 16 additions & 0 deletions src/share/fd-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,22 @@ int fd_cloexec(int fd, bool cloexec) {
return 0;
}

int fd_nonblock(int fd, bool nonblock) {
int flags, nflags;

assert(fd >= 0);

flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
return -errno;

nflags = UPDATE_FLAG(flags, O_NONBLOCK, nonblock);
if (nflags == flags)
return 0;

return RET_NERRNO(fcntl(fd, F_SETFL, nflags));
}

void stdio_unset_cloexec(void) {
fd_cloexec(STDIN_FILENO, false);
fd_cloexec(STDOUT_FILENO, false);
Expand Down
1 change: 1 addition & 0 deletions src/share/fd-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_nonblock(int fd, bool nonblock);
void stdio_unset_cloexec(void);


Expand Down
6 changes: 5 additions & 1 deletion src/share/macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
23 changes: 23 additions & 0 deletions src/share/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down