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
158168void 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 :
0 commit comments