2
* Copyright (c) 2002-2010 BalaBit IT Ltd, Budapest, Hungary
3
* Copyright (c) 1998-2010 Balázs Scheidler
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 as published
7
* by the Free Software Foundation, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
* As an additional exemption you are allowed to compile & link against the
19
* OpenSSL libraries as published by the OpenSSL project. See the file
20
* COPYING for details.
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <arpa/inet.h>
33
#include <netinet/in.h>
38
#define SOL_IP IPPROTO_IP
42
#define SOL_IPV6 IPPROTO_IPV6
47
afinet_set_port(GSockAddr *addr, gchar *service, const gchar *proto)
54
/* check if service is numeric */
55
port = strtol(service, &end, 10);
60
/* service is not numeric, check if it's a service in /etc/services */
61
se = getservbyname(service, proto);
64
port = ntohs(se->s_port);
68
msg_error("Error finding port number, falling back to default",
69
evt_tag_printf("service", "%s/%s", proto, service),
75
switch (addr->sa.sa_family)
78
g_sockaddr_inet_set_port(addr, port);
82
g_sockaddr_inet6_set_port(addr, port);
86
g_assert_not_reached();
94
afinet_setup_socket(gint fd, GSockAddr *addr, InetSocketOptions *sock_options, AFSocketDirection dir)
98
if (!afsocket_setup_socket(fd, &sock_options->super, dir))
101
switch (addr->sa.sa_family)
107
if (IN_MULTICAST(ntohl(g_sockaddr_inet_get_address(addr).s_addr)))
109
if (dir & AFSOCKET_DIR_RECV)
111
memset(&mreq, 0, sizeof(mreq));
112
mreq.imr_multiaddr = g_sockaddr_inet_get_address(addr);
113
mreq.imr_interface.s_addr = INADDR_ANY;
114
setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
115
setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &off, sizeof(off));
117
if (dir & AFSOCKET_DIR_SEND)
119
if (sock_options->ttl)
120
setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &sock_options->ttl, sizeof(sock_options->ttl));
126
if (sock_options->ttl && (dir & AFSOCKET_DIR_SEND))
127
setsockopt(fd, SOL_IP, IP_TTL, &sock_options->ttl, sizeof(sock_options->ttl));
129
if (sock_options->tos && (dir & AFSOCKET_DIR_SEND))
130
setsockopt(fd, SOL_IP, IP_TOS, &sock_options->tos, sizeof(sock_options->tos));
137
struct ipv6_mreq mreq6;
139
if (IN6_IS_ADDR_MULTICAST(&g_sockaddr_inet6_get_sa(addr)->sin6_addr))
141
if (dir & AFSOCKET_DIR_RECV)
143
memset(&mreq6, 0, sizeof(mreq6));
144
mreq6.ipv6mr_multiaddr = *g_sockaddr_inet6_get_address(addr);
145
mreq6.ipv6mr_interface = 0;
146
setsockopt(fd, SOL_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6));
147
setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
149
if (dir & AFSOCKET_DIR_SEND)
151
if (sock_options->ttl)
152
setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &sock_options->ttl, sizeof(sock_options->ttl));
157
if (sock_options->ttl && (dir & AFSOCKET_DIR_SEND))
158
setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &sock_options->ttl, sizeof(sock_options->ttl));
168
afinet_sd_set_localport(LogDriver *s, gchar *service, const gchar *proto)
170
AFSocketSourceDriver *self = (AFSocketSourceDriver *) s;
172
afinet_set_port(self->bind_addr, service, proto);
176
afinet_sd_set_localip(LogDriver *s, gchar *ip)
178
AFSocketSourceDriver *self = (AFSocketSourceDriver *) s;
180
resolve_hostname(&self->bind_addr, ip);
184
afinet_sd_setup_socket(AFSocketSourceDriver *s, gint fd)
186
return afinet_setup_socket(fd, s->bind_addr, (InetSocketOptions *) s->sock_options_ptr, AFSOCKET_DIR_RECV);
190
afinet_sd_set_transport(LogDriver *s, const gchar *transport)
192
AFInetSourceDriver *self = (AFInetSourceDriver *) s;
194
if (self->super.transport)
195
g_free(self->super.transport);
196
self->super.transport = g_strdup(transport);
197
if (strcasecmp(transport, "udp") == 0)
199
self->super.flags = (self->super.flags & ~0x0003) | AFSOCKET_DGRAM;
201
else if (strcasecmp(transport, "tcp") == 0)
203
self->super.flags = (self->super.flags & ~0x0003) | AFSOCKET_STREAM;
205
else if (strcasecmp(transport, "tls") == 0)
207
self->super.flags = (self->super.flags & ~0x0003) | AFSOCKET_STREAM | AFSOCKET_REQUIRE_TLS;
211
msg_error("Unknown syslog transport specified, please use one of udp, tcp, or tls",
212
evt_tag_str("transport", transport),
218
afinet_sd_new(gint af, gchar *host, gint port, guint flags)
220
AFInetSourceDriver *self = g_new0(AFInetSourceDriver, 1);
222
afsocket_sd_init_instance(&self->super, &self->sock_options.super, flags);
223
if (self->super.flags & AFSOCKET_DGRAM)
224
self->super.transport = g_strdup("udp");
225
else if (self->super.flags & AFSOCKET_STREAM)
226
self->super.transport = g_strdup("tcp");
229
self->super.bind_addr = g_sockaddr_inet_new("0.0.0.0", port);
236
self->super.bind_addr = g_sockaddr_inet6_new("::", port);
240
g_assert_not_reached();
243
resolve_hostname(&self->super.bind_addr, host);
244
self->super.setup_socket = afinet_sd_setup_socket;
246
return &self->super.super;
249
/* afinet destination */
252
afinet_dd_set_localport(LogDriver *s, gchar *service, const gchar *proto)
254
AFInetDestDriver *self = (AFInetDestDriver *) s;
256
afinet_set_port(self->super.bind_addr, service, proto);
260
afinet_dd_set_destport(LogDriver *s, gchar *service, const gchar *proto)
262
AFInetDestDriver *self = (AFInetDestDriver *) s;
264
afinet_set_port(self->super.dest_addr, service, proto);
266
g_free(self->super.dest_name);
267
self->super.dest_name = g_strdup_printf("%s:%d", self->super.hostname,
268
g_sockaddr_inet_check(self->super.dest_addr) ? g_sockaddr_inet_get_port(self->super.dest_addr)
270
: g_sockaddr_inet6_get_port(self->super.dest_addr)
278
afinet_dd_set_localip(LogDriver *s, gchar *ip)
280
AFInetDestDriver *self = (AFInetDestDriver *) s;
282
resolve_hostname(&self->super.bind_addr, ip);
286
afinet_dd_set_spoof_source(LogDriver *s, gboolean enable)
288
#if ENABLE_SPOOF_SOURCE
289
AFInetDestDriver *self = (AFInetDestDriver *) s;
291
self->spoof_source = (self->super.flags & AFSOCKET_DGRAM) && enable;
293
msg_error("Error enabling spoof-source, you need to compile syslog-ng with --enable-spoof-source", NULL);
298
afinet_dd_set_transport(LogDriver *s, const gchar *transport)
300
AFInetDestDriver *self = (AFInetDestDriver *) s;
302
if (self->super.transport)
303
g_free(self->super.transport);
304
self->super.transport = g_strdup(transport);
305
if (strcasecmp(transport, "udp") == 0)
307
self->super.flags = (self->super.flags & ~0x0003) | AFSOCKET_DGRAM;
309
else if (strcasecmp(transport, "tcp") == 0)
311
self->super.flags = (self->super.flags & ~0x0003) | AFSOCKET_STREAM;
313
else if (strcasecmp(transport, "tls") == 0)
315
self->super.flags = (self->super.flags & ~0x0003) | AFSOCKET_STREAM | AFSOCKET_REQUIRE_TLS;
319
msg_error("Unknown syslog transport specified, please use one of udp, tcp, or tls",
320
evt_tag_str("transport", transport),
326
afinet_dd_setup_socket(AFSocketDestDriver *s, gint fd)
328
AFInetDestDriver *self = (AFInetDestDriver *) s;
330
if (!resolve_hostname(&self->super.dest_addr, self->super.hostname))
333
return afinet_setup_socket(fd, self->super.dest_addr, (InetSocketOptions *) s->sock_options_ptr, AFSOCKET_DIR_SEND);
337
afinet_dd_init(LogPipe *s)
339
AFInetDestDriver *self G_GNUC_UNUSED = (AFInetDestDriver *) s;
342
success = afsocket_dd_init(s);
343
#if ENABLE_SPOOF_SOURCE
346
if (self->spoof_source && !self->lnet_ctx)
348
gchar error[LIBNET_ERRBUF_SIZE];
351
saved_caps = g_process_cap_save();
352
g_process_cap_modify(CAP_NET_RAW, TRUE);
353
self->lnet_ctx = libnet_init(self->super.dest_addr->sa.sa_family == AF_INET ? LIBNET_RAW4 : LIBNET_RAW6, NULL, error);
354
g_process_cap_restore(saved_caps);
357
msg_error("Error initializing raw socket, spoof-source support disabled",
358
evt_tag_str("error", NULL),
368
#if ENABLE_SPOOF_SOURCE
370
afinet_dd_construct_ipv4_packet(AFInetDestDriver *self, LogMessage *msg, GString *msg_line)
372
libnet_ptag_t ip, udp;
373
struct sockaddr_in *src, *dst;
375
if (msg->saddr->sa.sa_family != AF_INET)
378
src = (struct sockaddr_in *) &msg->saddr->sa;
379
dst = (struct sockaddr_in *) &self->super.dest_addr->sa;
381
libnet_clear_packet(self->lnet_ctx);
383
udp = libnet_build_udp(ntohs(src->sin_port),
384
ntohs(dst->sin_port),
385
LIBNET_UDP_H + msg_line->len,
387
(guchar *) msg_line->str,
394
ip = libnet_build_ipv4(LIBNET_IPV4_H + msg_line->len + LIBNET_UDP_H,
395
IPTOS_LOWDELAY, /* IP tos */
399
IPPROTO_UDP, /* transport protocol */
401
src->sin_addr.s_addr, /* source IP */
402
dst->sin_addr.s_addr, /* destination IP */
403
NULL, /* payload (none) */
404
0, /* payload length */
415
afinet_dd_construct_ipv6_packet(AFInetDestDriver *self, LogMessage *msg, GString *msg_line)
417
libnet_ptag_t ip, udp;
418
struct sockaddr_in *src4;
419
struct sockaddr_in6 src, *dst;
420
struct libnet_in6_addr ln_src, ln_dst;
422
switch (msg->saddr->sa.sa_family)
425
src4 = (struct sockaddr_in *) &msg->saddr->sa;
426
memset(&src, 0, sizeof(src));
427
src.sin6_family = AF_INET6;
428
src.sin6_port = src4->sin_port;
429
((guint32 *) &src.sin6_addr)[0] = 0;
430
((guint32 *) &src.sin6_addr)[1] = 0;
431
((guint32 *) &src.sin6_addr)[2] = htonl(0xffff);
432
((guint32 *) &src.sin6_addr)[3] = src4->sin_addr.s_addr;
435
src = *((struct sockaddr_in6 *) &msg->saddr->sa);
438
g_assert_not_reached();
442
dst = (struct sockaddr_in6 *) &self->super.dest_addr->sa;
444
libnet_clear_packet(self->lnet_ctx);
446
udp = libnet_build_udp(ntohs(src.sin6_port),
447
ntohs(dst->sin6_port),
448
LIBNET_UDP_H + msg_line->len,
450
(guchar *) msg_line->str,
457
/* There seems to be a bug in libnet 1.1.2 that is triggered when
458
* checksumming UDP6 packets. This is a workaround below. */
460
libnet_toggle_checksum(self->lnet_ctx, udp, LIBNET_OFF);
462
memcpy(&ln_src, &src.sin6_addr, sizeof(ln_src));
463
memcpy(&ln_dst, &dst->sin6_addr, sizeof(ln_dst));
464
ip = libnet_build_ipv6(0, 0,
465
LIBNET_UDP_H + msg_line->len,
466
IPPROTO_UDP, /* IPv6 next header */
469
NULL, 0, /* payload and its length */
483
afinet_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options)
485
#if ENABLE_SPOOF_SOURCE
486
AFInetDestDriver *self = (AFInetDestDriver *) s;
488
if (self->spoof_source && self->lnet_ctx && msg->saddr && (msg->saddr->sa.sa_family == AF_INET || msg->saddr->sa.sa_family == AF_INET6))
490
gboolean success = FALSE;
491
GString *msg_line = g_string_sized_new(256);
493
g_assert((self->super.flags & AFSOCKET_DGRAM) != 0);
495
log_writer_format_log((LogWriter *) self->super.writer, msg, msg_line);
497
switch (self->super.dest_addr->sa.sa_family)
500
success = afinet_dd_construct_ipv4_packet(self, msg, msg_line);
504
success = afinet_dd_construct_ipv6_packet(self, msg, msg_line);
508
g_assert_not_reached();
512
if (libnet_write(self->lnet_ctx) >= 0)
514
/* we have finished processing msg */
515
log_msg_ack(msg, path_options);
517
g_string_free(msg_line, TRUE);
523
msg_error("Error sending raw frame",
524
evt_tag_str("error", libnet_geterror(self->lnet_ctx)),
528
g_string_free(msg_line, TRUE);
531
log_pipe_forward_msg(s, msg, path_options);
535
afinet_dd_free(LogPipe *s)
542
afinet_dd_new(gint af, gchar *host, gint port, guint flags)
544
AFInetDestDriver *self = g_new0(AFInetDestDriver, 1);
546
afsocket_dd_init_instance(&self->super, &self->sock_options.super, flags, g_strdup(host), g_strdup_printf("%s:%d", host, port));
547
if (self->super.flags & AFSOCKET_DGRAM)
548
self->super.transport = g_strdup("udp");
549
else if (self->super.flags & AFSOCKET_STREAM)
550
self->super.transport = g_strdup("tcp");
551
self->super.super.super.init = afinet_dd_init;
552
self->super.super.super.queue = afinet_dd_queue;
553
self->super.super.super.free_fn = afinet_dd_free;
556
self->super.bind_addr = g_sockaddr_inet_new("0.0.0.0", 0);
557
self->super.dest_addr = g_sockaddr_inet_new("0.0.0.0", port);
562
self->super.bind_addr = g_sockaddr_inet6_new("::", 0);
563
self->super.dest_addr = g_sockaddr_inet6_new("::", port);
565
g_assert_not_reached();
568
self->super.setup_socket = afinet_dd_setup_socket;
569
return &self->super.super;