Skip to content

Commit 28497d2

Browse files
authored
Merge pull request #29 from balnbibarbi/tcp
Tcp
2 parents 0b5a39d + eee1031 commit 28497d2

File tree

11 files changed

+181
-3
lines changed

11 files changed

+181
-3
lines changed

conf/systemd-netlogd.conf.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
[Network]
22
#Address=239.0.0.1:6000
3+
#Protocol=udp

src/netlog/netlog-conf.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "in-addr-util.h"
55
#include "netlog-conf.h"
66
#include "conf-parser.h"
7+
#include "string-util.h"
78

89
int config_parse_netlog_remote_address(const char *unit,
910
const char *filename,
@@ -33,6 +34,35 @@ int config_parse_netlog_remote_address(const char *unit,
3334
return 0;
3435
}
3536

37+
int config_parse_protocol(const char *unit,
38+
const char *filename,
39+
unsigned line,
40+
const char *section,
41+
unsigned section_line,
42+
const char *lvalue,
43+
int ltype,
44+
const char *rvalue,
45+
void *data,
46+
void *userdata) {
47+
Manager *m = userdata;
48+
int r;
49+
50+
assert(filename);
51+
assert(lvalue);
52+
assert(rvalue);
53+
assert(data);
54+
55+
r = protocol_from_string(rvalue);
56+
if (r < 0) {
57+
log_syntax(unit, LOG_ERR, filename, line, -r,
58+
"Unrecognised Protocol '%s'", rvalue);
59+
return -EPROTONOSUPPORT;
60+
}
61+
62+
m->protocol = r;
63+
return 0;
64+
}
65+
3666
int manager_parse_config_file(Manager *m) {
3767
assert(m);
3868

src/netlog/netlog-conf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,14 @@ int config_parse_netlog_remote_address(const char *unit,
1717
const char *rvalue,
1818
void *data,
1919
void *userdata);
20+
int config_parse_protocol(const char *unit,
21+
const char *filename,
22+
unsigned line,
23+
const char *section,
24+
unsigned section_line,
25+
const char *lvalue,
26+
int ltype,
27+
const char *rvalue,
28+
void *data,
29+
void *userdata);
2030
int manager_parse_config_file(Manager *m);

src/netlog/netlog-gperf.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ struct ConfigPerfItem;
1616
%includes
1717
%%
1818
Network.Address, config_parse_netlog_remote_address, 0, 0
19+
Network.Protocol, config_parse_protocol, 0, offsetof(Manager, protocol)
1920
Network.StructuredData, config_parse_string, 0, offsetof(Manager, structured_data)

src/netlog/netlog-manager.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "fd-util.h"
1313
#include "fileio.h"
1414
#include "string-util.h"
15+
#include "string-table.h"
1516
#include "parse-util.h"
1617
#include "netlog-manager.h"
1718

@@ -26,6 +27,13 @@
2627
#define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \
2728
for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; )
2829

30+
static const char *const protocol_table[_SYSLOG_TRANSMISSION_PROTOCOL_MAX] = {
31+
[SYSLOG_TRANSMISSION_PROTOCOL_UDP] = "udp",
32+
[SYSLOG_TRANSMISSION_PROTOCOL_TCP] = "tcp",
33+
};
34+
35+
DEFINE_STRING_TABLE_LOOKUP(protocol, int);
36+
2937
static int parse_field(const void *data, size_t length, const char *field, char **target) {
3038
size_t fl, nl;
3139
void *buf;

src/netlog/netlog-manager.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
#include "sd-network.h"
88
#include "socket-util.h"
99

10+
typedef enum SysLogTransmissionProtocol {
11+
SYSLOG_TRANSMISSION_PROTOCOL_UDP = 1 << 0,
12+
SYSLOG_TRANSMISSION_PROTOCOL_TCP = 1 << 1,
13+
_SYSLOG_TRANSMISSION_PROTOCOL_MAX,
14+
_SYSLOG_TRANSMISSION_PROTOCOL_INVALID = -EINVAL,
15+
} SysLogTransmissionProtocol;
16+
1017
typedef struct Manager Manager;
1118

1219
struct Manager {
@@ -33,6 +40,7 @@ struct Manager {
3340

3441
char *last_cursor, *current_cursor;
3542
char *structured_data;
43+
SysLogTransmissionProtocol protocol;
3644
};
3745

3846
int manager_new(Manager **ret, const char *state_file, const char *cursor);
@@ -50,3 +58,6 @@ int manager_push_to_network(Manager *m, int severity, int facility,
5058
const char *identifier, const char *message,
5159
const char *hostname, const char *pid,
5260
const struct timeval *tv);
61+
62+
const char *protocol_to_string(int v) _const_;
63+
int protocol_from_string(const char *s) _pure_;

src/netlog/netlog-network.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <unistd.h>
44
#include <stddef.h>
55
#include <poll.h>
6+
#include <netinet/tcp.h>
67

78
#include "netlog-manager.h"
89
#include "io-util.h"
@@ -97,7 +98,7 @@ int manager_push_to_network(Manager *m,
9798
char header_priority[sizeof("< >1 ")];
9899
char header_time[FORMAT_TIMESTAMP_MAX];
99100
uint8_t makepri;
100-
struct iovec iov[13];
101+
struct iovec iov[14];
101102
int n = 0;
102103

103104
assert(m);
@@ -152,12 +153,36 @@ int manager_push_to_network(Manager *m,
152153
/* Ninth: message */
153154
IOVEC_SET_STRING(iov[n++], message);
154155

156+
/* Tenth: Optional newline message separator, if not implicitly terminated by end of UDP frame */
157+
if (SYSLOG_TRANSMISSION_PROTOCOL_TCP == m->protocol)
158+
/* De facto standard: separate messages by a newline */
159+
IOVEC_SET_STRING(iov[n++], "\n");
160+
else if (SYSLOG_TRANSMISSION_PROTOCOL_UDP == m->protocol) {
161+
/* Message is implicitly terminated by end of UDP packet */
162+
} else
163+
return -EPROTONOSUPPORT;
164+
155165
return network_send(m, iov, n);
156166
}
157167

158168
void manager_close_network_socket(Manager *m) {
159169
assert(m);
160170

171+
switch (m->protocol) {
172+
case SYSLOG_TRANSMISSION_PROTOCOL_UDP:
173+
/* shutdown not required */
174+
break;
175+
case SYSLOG_TRANSMISSION_PROTOCOL_TCP:
176+
{
177+
int r = shutdown(m->socket, SHUT_RDWR);
178+
if (r < 0)
179+
log_error_errno(r, "Failed to shutdown netlog socket: %m");
180+
}
181+
break;
182+
default:
183+
break;
184+
}
185+
161186
m->socket = safe_close(m->socket);
162187
}
163188

@@ -170,7 +195,16 @@ int manager_open_network_socket(Manager *m) {
170195
if (!IN_SET(m->address.sockaddr.sa.sa_family, AF_INET, AF_INET6))
171196
return -EAFNOSUPPORT;
172197

173-
m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
198+
switch (m->protocol) {
199+
case SYSLOG_TRANSMISSION_PROTOCOL_UDP:
200+
m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
201+
break;
202+
case SYSLOG_TRANSMISSION_PROTOCOL_TCP:
203+
m->socket = socket(m->address.sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
204+
break;
205+
default:
206+
return -EPROTONOSUPPORT;
207+
}
174208
if (m->socket < 0)
175209
return -errno;
176210

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

217+
if (SYSLOG_TRANSMISSION_PROTOCOL_TCP == m->protocol) {
218+
union sockaddr_union sa;
219+
socklen_t salen;
220+
switch (m->address.sockaddr.sa.sa_family) {
221+
case AF_INET:
222+
sa = (union sockaddr_union) {
223+
.in.sin_family = m->address.sockaddr.sa.sa_family,
224+
.in.sin_port = m->address.sockaddr.in.sin_port,
225+
.in.sin_addr = m->address.sockaddr.in.sin_addr,
226+
};
227+
salen = sizeof(sa.in);
228+
break;
229+
case AF_INET6:
230+
sa = (union sockaddr_union) {
231+
.in6.sin6_family = m->address.sockaddr.sa.sa_family,
232+
.in6.sin6_port = m->address.sockaddr.in6.sin6_port,
233+
.in6.sin6_addr = m->address.sockaddr.in6.sin6_addr,
234+
};
235+
salen = sizeof(sa.in6);
236+
break;
237+
default:
238+
r = -EAFNOSUPPORT;
239+
goto fail;
240+
}
241+
r = connect(m->socket, &m->address.sockaddr.sa, salen);
242+
if (r < 0) {
243+
r = -errno;
244+
goto fail;
245+
}
246+
247+
r = setsockopt(m->socket, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
248+
if (r < 0)
249+
return r;
250+
}
251+
252+
r = fd_nonblock(m->socket, 1);
253+
if (r < 0)
254+
goto fail;
255+
183256
return m->socket;
184257

185258
fail:

src/share/fd-util.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,22 @@ int fd_cloexec(int fd, bool cloexec) {
121121
return 0;
122122
}
123123

124+
int fd_nonblock(int fd, bool nonblock) {
125+
int flags, nflags;
126+
127+
assert(fd >= 0);
128+
129+
flags = fcntl(fd, F_GETFL, 0);
130+
if (flags < 0)
131+
return -errno;
132+
133+
nflags = UPDATE_FLAG(flags, O_NONBLOCK, nonblock);
134+
if (nflags == flags)
135+
return 0;
136+
137+
return RET_NERRNO(fcntl(fd, F_SETFL, nflags));
138+
}
139+
124140
void stdio_unset_cloexec(void) {
125141
fd_cloexec(STDIN_FILENO, false);
126142
fd_cloexec(STDOUT_FILENO, false);

src/share/fd-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
3838
#define _cleanup_close_pair_ _cleanup_(close_pairp)
3939

4040
int fd_cloexec(int fd, bool cloexec);
41+
int fd_nonblock(int fd, bool nonblock);
4142
void stdio_unset_cloexec(void);
4243

4344

src/share/macro.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
312312
ans; \
313313
})
314314

315+
#define UPDATE_FLAG(orig, flag, b) \
316+
((b) ? ((orig) | (flag)) : ((orig) & ~(flag)))
315317
#define SET_FLAG(v, flag, b) \
316-
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
318+
(v) = UPDATE_FLAG(v, flag, b)
319+
#define FLAGS_SET(v, flags) \
320+
((~(v) & (flags)) == 0)
317321

318322
#define CASE_F(X) case X:
319323
#define CASE_F_1(CASE, X) CASE_F(X)

0 commit comments

Comments
 (0)