Hi David, I think you got lost in the callbacks.
The multiple send calls are not for multiple actions. This is all for one action. That code was contributed as part of the IPv6 port. I verified the implementation with what I could find as references to sending on IPv6 and think the implementation uses proper procedures for that environment. In essence, on an IPv6-enabled system, you will receive multiple sockets that you potentially can use to send the message. What the code does is iterate over these sockets and see which one really works. There is also an option (not checked but pretty sure) that permits sending to all receivers. I think that was the other situation you have seen. The listen socket is NOT being reused for sending. RFC3164 actually recommends that port 514 is used as the source port, and we had a lengthy discussion at the IETF about this recommendation. The bottom line is that you cannot reuse the receive socket on a highly parallel syslogd because each thread needs its own (or you have even more sync). Rsyslog creates a new (set of) send sockets *per action*. I guess part of the confusion stems back from your understanding of sysklogd code. Sysklogd works totally different here. I hope this clarifies a bit. I will try to have a look at the code provided asap and see what I can do. Its unfortunately still very busy, so I can not commit when I will finally start. HTH Rainer > -----Original Message----- > From: [email protected] [mailto:rsyslog- > [email protected]] On Behalf Of [email protected] > Sent: Wednesday, February 25, 2009 9:47 PM > To: rsyslog-users > Subject: Re: [rsyslog] UDP source forging. > > figuring out how to do this is navigating a twisty maze of helper > functions, all different ;-) > > there are a few things that look odd here if I am reading the code > properly. > > rsyslog makes one call to the UDPSend routine for all forwarded > messages, > this means that they must all send the same format. > > the UDPSend routine then walks through all destinations attempting to > send > the message to them. and considers the message successfully sent if any > of > them can be sent. I would have expected that it would only be > considered > successful if all of them succeded. > > UDPSend attempts to use the sockets that were created to listening for > messages to send it's message out. in a multi-homed machine the local > IP > address of those sockets may not be appropriate for the relay. also, > what > would happen if a system recieves via TCP and forwards via UDP and so > doesn't have any UDP listener sockets. > > > so now, my suggestion > > On Linux in /etc/sysctl.conf add the line > > net.ipv4.ip_nonlocal_bind=1 > > this tells the kernel not to fail bind requests to IP addresses that > don't > exist on the box > > then in omfwd.c > > in the routine that calls UDPSend, modify it to pass the source IP > address > of the message to UDPSend > > create a new filehandle array to use for outbound messages (one > filehandle > for each destination since they may end up with different source IPs) > > > in UDPSend > > three options. > > > 1. default > > use the appropriate filehandle for each destination and send the > message. this is similar to what currently takes place, but instead of > walking through each open socket for each destination, there should > only > be one sendto per destination. when opening the socket it should not be > nessasary to do a bind, just issue the socket call. > > if there is anything in the syslog standard specifying the source > port > (I don't think there is, although many implementations use port 514 > becouse they do the same thing that rsyslog is doing and re-use > listening > sockets to send messages) > > > 2. randomize source ports to support external load balancers > > same as default, except that every X (configurable) messages close > and > re-open the sockets. > > the reason for this is that each time a message is first sent the OS > picks a random source port that will be used for all messages sent > through > that socket. by closing the socket once in a while, load balancers that > balance based on source IP + source port + destination IP + destination > port will be able to function (a similar feature for TCP based > transports > would be useful for the same reason) > > > 3. forge the source IP/port > > for each message that is sent, open a new socket, then issue a > 'bind' > command for that socket (filehandle) that sets the local IP address to > the > IP address that the message initially came from, then issue the sendto, > then close the filehandle. > > there is no need for an array of sockets in this case as the socket > needs to be re-opened for each message/destination. in theory there is > a > possibility of a performance gain by keeping sockets open and re-using > them, but since each socket is unique to the sender + destination there > would be a large number of sockets and a low probability of re-using a > socket for the next message. > > in sysklogd I implemented #2 with the simple code below (once I created > a > different filehandle to use for outbound connections) > > this closed and re-opened the socket for each message, doing it every X > messages would save on the overhead and be just as good in practice. > > the bind command that's commented out is basicly what would be needed > for > #3, but with real values for the source.sin_addr.s_addr (and > source.sin_port if you wanted to forge the port as well, leaving it > zero > lets the OS pick a port number) > > if (finet >0) { > /* close and re-open the outbound socket after each message so > that the source port is randomized and load balancers can distribute > the messages */ > close(finet); > finet = create_inet_socket(); > /* if we want to forge the source IP for the outbound packets, > this is the place to do it by seeting the IP address to the address we > received the message from > struct sockaddr_in source; > source.sin_addr.s_addr = 0x00000000; > source.sin_port = 0x0000; > bind(finet,(struct sockaddr *) > &source,sizeof(source));*/ > } > > > the create_inet_socket() routine is: > > static int create_inet_socket() > { > int fd, on = 1; > int sockflags; > > fd = socket(AF_INET, SOCK_DGRAM, 0); > if (fd < 0) { > logerror("syslog: Unknown protocol, suspending inet > service."); > return fd; > } > > if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \ > (char *) &on, sizeof(on)) < 0 ) { > logerror("setsockopt(REUSEADDR), suspending inet"); > close(fd); > return -1; > } > /* We must not block on the network socket, in case a packet > * gets lost between select and recv, otherise the process > * will stall until the timeout, and other processes trying to > * log will also stall. > */ > if ((sockflags = fcntl(fd, F_GETFL)) != -1) { > sockflags |= O_NONBLOCK; > /* > * SETFL could fail too, so get it caught by the > subsequent > * error check. > */ > sockflags = fcntl(fd, F_SETFL, sockflags); > } > if (sockflags == -1) { > logerror("fcntl(O_NONBLOCK), suspending inet"); > close(fd); > return -1; > } > return fd; > } > > > this isn't a patch like you asked for and I offered to put togeather, > but > is it enough to clearly explain this? if not I can continue to work on > the > patch. > > David Lang > > On Tue, 24 Feb 2009, Rainer Gerhards wrote: > > > David, > > > > Excellent, please do as you have time. I'll make sure it fits. > > Thread-safety, btw., is not a big issue at this level as the output > > modules are guaranteed to be never called by multiple threads > > concurrently. That was a trade-off to enable other folks to easily > write > > them (but I have an option in the back of my head that a module can > tell > > the engine it *is* capable to run on multiple threads > concurrently...). > > > > Rainer > > > >> -----Original Message----- > >> From: [email protected] [mailto:rsyslog- > >> [email protected]] On Behalf Of [email protected] > >> Sent: Tuesday, February 24, 2009 9:43 AM > >> To: rsyslog-users > >> Subject: Re: [rsyslog] UDP source forging. > >> > >> On Tue, 24 Feb 2009, Rainer Gerhards wrote: > >> > >>> Hi David et all, > >>> > >>> Currently rsyslog does not support this and I have to admit I was > >> always > >>> very hesitant to add it (I see potential for misuse). Co- > >> incidentally, I > >>> received a similar request and was about to relay it to the mailing > >> list > >>> to gather feedback. As it looks, this no longer is necessary ;) > >>> > >>> When I thought about implementation, I originally thought about raw > >>> sockets (which indeed require root access), but if there is any > > other > >>> way, I would be most interested. If you can provide some code, I > > will > >>> happily integrate it. I think an addition to the omfwd module, in > > udp > >>> forwarding, together with a new directive ($SpoofOriginalUDPAddress > >> or > >>> so...) would be the right way to go. > >> > >> I'll see about hacking in some example code (probably without any > >> config > >> option and not thread-safe) and send it to you. > >> > >> there's another similar change in the same area that I was looking > at, > >> I'll mock it up as well. > >> > >> David Lang > >> > >>> Rainer > >>> > >>>> -----Original Message----- > >>>> From: [email protected] > >>>> [mailto:[email protected]] On Behalf Of > >> [email protected] > >>>> Sent: Tuesday, February 24, 2009 4:40 AM > >>>> To: rsyslog-users > >>>> Subject: Re: [rsyslog] UDP source forging. > >>>> > >>>> On Mon, 23 Feb 2009, RB wrote: > >>>> > >>>>> On Mon, Feb 23, 2009 at 18:11, <[email protected]> wrote: > >>>>>> I have a need to use some products that are stupid enough > >>>> to ignore the > >>>>>> host field in the syslog message and instead base > >>>> everything on the IP > >>>>>> address the message originates from. > >>>>>> > >>>>>> some other syslog servers can handle this by forging the > >>>> source of the UDP > >>>>>> packet, can rsyslog do this? > >>>>> > >>>>> So is rsyslog originating the messages, or are you using it to > >>>>> aggregate them and then feed them on to the other [bad] > >>>> acceptors? I > >>>>> am unaware of a way to get rsyslog to forge packets (short > >>>> of writing > >>>>> an output module), but unless you must get another syslog > >>>> daemon into > >>>>> the mix, you may be better off just feeding your messages > >>>> directly to > >>>>> the other collector. > >>>> > >>>> rsyslog would be the relay from one non-routed network to another > >>>> non-routed network. > >>>> > >>>> this could be a fairly simple change to the UDP output module > >>>> (adding a > >>>> couple commands around the sending of a message), but before > >>>> I dove in to > >>>> do that I wanted to see if I had missed this feature anywhere. > >>>> > >>>> David Lang > >>>> _______________________________________________ > >>>> rsyslog mailing list > >>>> http://lists.adiscon.net/mailman/listinfo/rsyslog > >>>> http://www.rsyslog.com > >>>> > >>> _______________________________________________ > >>> rsyslog mailing list > >>> http://lists.adiscon.net/mailman/listinfo/rsyslog > >>> http://www.rsyslog.com > >>> > >> _______________________________________________ > >> rsyslog mailing list > >> http://lists.adiscon.net/mailman/listinfo/rsyslog > >> http://www.rsyslog.com > > _______________________________________________ > > rsyslog mailing list > > http://lists.adiscon.net/mailman/listinfo/rsyslog > > http://www.rsyslog.com > > > _______________________________________________ > rsyslog mailing list > http://lists.adiscon.net/mailman/listinfo/rsyslog > http://www.rsyslog.com _______________________________________________ rsyslog mailing list http://lists.adiscon.net/mailman/listinfo/rsyslog http://www.rsyslog.com

