diff -u syslog-ng-1.9.9.orig/src/afinet.c syslog-ng-1.9.9/src/afinet.c --- syslog-ng-1.9.9.orig/src/afinet.c 2006-02-12 12:03:15.000000000 +0000 +++ syslog-ng-1.9.9/src/afinet.c 2006-03-30 13:53:46.868514000 +0100 @@ -56,6 +56,24 @@ } static void +afinet_set_ttl(GSockAddr *addr, gint ttl) +{ + if (addr) + { + if (ttl>=0 && ttl<=255) + { + addr->ttl = (char) ttl; + } + else + { + msg_error("Error ttl must be higher than zero and less than 255", + NULL); + return; + } + } +} + +static void afinet_set_ip(GSockAddr *addr, gchar *ip) { if (addr && !inet_aton(ip, &((struct sockaddr_in *) &addr->sa)->sin_addr)) @@ -120,6 +138,14 @@ } void +afinet_dd_set_ttl(LogDriver *s, gint ttl) +{ + AFInetDestDriver *self = (AFInetDestDriver *) s; + + afinet_set_ttl(self->super.dest_addr, ttl); +} + +void afinet_dd_set_localip(LogDriver *s, gchar *ip) { AFInetDestDriver *self = (AFInetDestDriver *) s; diff -u syslog-ng-1.9.9.orig/src/afinet.h syslog-ng-1.9.9/src/afinet.h --- syslog-ng-1.9.9.orig/src/afinet.h 2006-02-11 07:37:58.000000000 +0000 +++ syslog-ng-1.9.9/src/afinet.h 2006-03-30 14:30:20.328514000 +0100 @@ -47,6 +47,7 @@ LogDriver *afinet_dd_new(gchar *host, gint port, guint flags); void afinet_dd_set_localport(LogDriver *self, gint port, gchar *service, gchar *proto); void afinet_dd_set_destport(LogDriver *self, gint port, gchar *service, gchar *proto); +void afinet_dd_set_ttl(LogDriver *self, gint ttl); void afinet_dd_set_localip(LogDriver *self, gchar *ip); void afinet_dd_set_sync_freq(LogDriver *self, gint sync_freq); diff -u syslog-ng-1.9.9.orig/src/cfg-grammar.y syslog-ng-1.9.9/src/cfg-grammar.y --- syslog-ng-1.9.9.orig/src/cfg-grammar.y 2006-02-26 08:31:44.000000000 +0000 +++ syslog-ng-1.9.9/src/cfg-grammar.y 2006-03-30 14:30:43.368514000 +0100 @@ -88,7 +88,7 @@ /* socket related options */ %token KW_KEEP_ALIVE KW_MAX_CONNECTIONS -%token KW_LOCALIP KW_IP KW_LOCALPORT KW_PORT KW_DESTPORT +%token KW_LOCALIP KW_IP KW_LOCALPORT KW_PORT KW_DESTPORT KW_TTL /* misc options */ %token KW_USE_TIME_RECVD @@ -559,6 +559,7 @@ dest_afinet_option : KW_LOCALIP '(' string ')' { afinet_dd_set_localip(last_driver, $3); free($3); } | KW_PORT '(' NUMBER ')' { afinet_dd_set_destport(last_driver, $3, NULL, NULL); } + | KW_TTL '(' NUMBER ')' { afinet_dd_set_ttl(last_driver, $3); } | dest_writer_option ; diff -u syslog-ng-1.9.9.orig/src/cfg-lex.l syslog-ng-1.9.9/src/cfg-lex.l --- syslog-ng-1.9.9.orig/src/cfg-lex.l 2006-02-26 08:31:35.000000000 +0000 +++ syslog-ng-1.9.9/src/cfg-lex.l 2006-03-30 13:39:40.568514000 +0100 @@ -113,6 +113,7 @@ { "ip", KW_IP }, { "localport", KW_LOCALPORT }, { "port", KW_PORT }, + { "ttl", KW_TTL }, { "destport", KW_DESTPORT }, { "owner", KW_OWNER }, { "group", KW_GROUP }, diff -u syslog-ng-1.9.9.orig/src/gsockaddr.c syslog-ng-1.9.9/src/gsockaddr.c --- syslog-ng-1.9.9.orig/src/gsockaddr.c 2006-03-30 14:32:54.008514000 +0100 +++ syslog-ng-1.9.9/src/gsockaddr.c 2006-03-30 13:52:14.488514000 +0100 @@ -158,6 +158,10 @@ } else { + if (g_ttl(fd, remote)) + { + return G_IO_STATUS_ERROR; + } return G_IO_STATUS_NORMAL; } } @@ -287,6 +291,7 @@ GSockAddrFuncs *sa_funcs; int salen; struct sockaddr_in sin; + char ttl; } GSockAddrInet; /*+ private function to prepare an IPv4 style bind, e.g. set @@ -361,6 +366,7 @@ addr->sin.sin_family = AF_INET; addr->sin.sin_port = htons(port); addr->sin.sin_addr = ina; + addr->ttl = 0; addr->sa_funcs = &inet_sockaddr_funcs; } return (GSockAddr *) addr; @@ -396,6 +402,9 @@ } } } + + addr->ttl = 0; + return (GSockAddr *) addr; } @@ -421,6 +430,7 @@ addr->flags = 0; addr->salen = sizeof(struct sockaddr_in); addr->sin = *sin; + addr->ttl = 0; addr->sa_funcs = &inet_sockaddr_funcs; return (GSockAddr *) addr; @@ -439,6 +449,7 @@ GSockAddrFuncs *sa_funcs; int salen; struct sockaddr_in sin; + char ttl; gpointer options; guint options_length; guint16 min_port, max_port, last_port; @@ -459,6 +470,9 @@ g_error("SockAddrInetRange, invalid range given; min_port='%d', max_port='%d'", addr->min_port, addr->max_port); return G_IO_STATUS_ERROR; } + + addr->ttl = 0; + for (port = addr->last_port; port <= addr->max_port; port++) { /* attempt to bind */ @@ -502,6 +516,7 @@ addr->sin.sin_family = AF_INET; inet_aton(ip, &addr->sin.sin_addr); addr->sin.sin_port = 0; + addr->ttl = 0; addr->sa_funcs = &inet_range_sockaddr_funcs; if (max_port > min_port) { @@ -529,6 +544,7 @@ GSockAddrFuncs *sa_funcs; int salen; struct sockaddr_in6 sin6; + char ttl; } GSockAddrInet6; /*+ format an IPv6 address into human readable form */ @@ -582,6 +598,7 @@ addr->sin6.sin6_family = AF_INET6; inet_pton(AF_INET6, ip, &addr->sin6.sin6_addr); addr->sin6.sin6_port = htons(port); + addr->ttl = 0; addr->sa_funcs = &inet6_sockaddr_funcs; return (GSockAddr *) addr; @@ -609,6 +626,7 @@ addr->flags = 0; addr->salen = sizeof(struct sockaddr_in6); addr->sin6 = *sin6; + addr->ttl = 0; addr->sa_funcs = &inet6_sockaddr_funcs; return (GSockAddr *) addr; @@ -651,6 +669,47 @@ return 0; } +int +g_ttl(int fd, GSockAddr *addr) +{ + if (addr->ttl == 0) + { + return 0; + } + + switch (addr->sa.sa_family) + { +#if ENABLE_IPV6 + case AF_INET6: + if (IN6_IS_ADDR_MULTICAST(&(((GSockAddrInet6 *) addr)->sin6.sin6_addr))) + { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &addr->ttl, sizeof(addr->ttl)) < 0) + return 1; + } + else + { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &addr->ttl, sizeof(addr->ttl)) < 0) + return 1; + } + break; +#endif + case AF_INET: + if (IN_MULTICAST(ntohl(((GSockAddrInet *) addr)->sin.sin_addr.s_addr))) + { + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &addr->ttl, sizeof(addr->ttl)) < 0) + return 1; + } + else + { + if (setsockopt(fd, IPPROTO_IP, IP_TTL, &addr->ttl, sizeof(addr->ttl)) < 0) + return 1; + } + break; + } + + return 0; +} + /* AF_UNIX socket address */ /*+ diff -u syslog-ng-1.9.9.orig/src/gsockaddr.h syslog-ng-1.9.9/src/gsockaddr.h --- syslog-ng-1.9.9.orig/src/gsockaddr.h 2006-03-30 14:32:54.008514000 +0100 +++ syslog-ng-1.9.9/src/gsockaddr.h 2006-03-30 14:31:24.218514000 +0100 @@ -44,6 +44,7 @@ GSockAddrFuncs *sa_funcs; int salen; struct sockaddr sa; + char ttl; } GSockAddr; struct _GSockAddrFuncs @@ -74,6 +75,7 @@ #endif int g_in_multicast(int fd, GSockAddr *addr); +int g_ttl(int fd, GSockAddr *addr); GSockAddr *g_sockaddr_unix_new(gchar *name); GSockAddr *g_sockaddr_unix_new2(struct sockaddr_un *s_un, int sunlen);