On Thu, 26 Feb 2009, Rainer Gerhards wrote:

> Just one quick answer (on the leave)
>
>>> 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*.
>>
>> if you don't do a bind on the socket you can't specify the source
> port.
>> if
>> you do bind on the socket and set the source port to 514 aren't you
>> generating a conflict between the multiple send sockets?
>
> I am ignoring the RFC recommendation. It is also removed from the
> soon-to-appear RFC5424. I should have mentioned this...

good, that clarifies things a lot.

I think I see a significant simplification here.

getaddrinfo can return a bunch of different addrinfo structures, which you 
walk through and try to send to each one until you find one that works. 
based on the man page for this I see the following reasons for multiple 
sockets

1. number of IP stacks (IPv4 vs IPv6 vs both)

2. multiple interfaces (and potentially multiple IPs if hostname resolves 
to more than one)

the number of structures that you get back is #1 * #2.


however, I don't think that you need to go through this.

since you maintain a instance of omfwd for each action (i.e. destination), 
you should be able to figure out what will work and not waste any time 
dealing with the others.

when you lookup the destination address to send to, you should be able to 
find out if it's an IPv4 or an IPv6 address.

If you have both pick one to use (arguments can be made as to which is the 
best to use, pick one to default to and have a config option to override 
it)

If you get multiple addresses, use the first one.

at this point you have one socket of the correct type to send to that 
destination.

attempting to send to each one until you get sucess works, and may be more 
robust, but it's a significant amount of complication and overhead that 
you shouldn't need to go through.


I think the basic changes needed to support forging the address are 
something like this (whitespace munged by cut-n-paste)

diff --git a/tools/omfwd.c b/tools/omfwd.c
index 1dd184e..1112db6 100644
--- a/tools/omfwd.c
+++ b/tools/omfwd.c
@@ -193,6 +193,15 @@ static rsRetVal UDPSend(instanceData *pData, char *msg, 
size_t len)
         int bSendSuccess;

         if(pData->pSockArray != NULL) {
+               /* close and re-open sockets for two possilbe reasons
+                * so that the source port is randomized again (to support load 
balancers
+                * so that we can bind to them to forge the from address on the 
packet
+                * this should be conditional on config options (including how 
frequently to do this)
+                * David Lang 2009-02-25
+                */
+               net.closeUDPListenSockets(pData->pSockArray);
+               pData->pSockArray = 
net.create_udp_socket((uchar*)pData->f_hname, NULL, 0);
+
                 /* we need to track if we have success sending to the remote
                  * peer. Success is indicated by at least one sendto() call
                  * succeeding. We track this be bSendSuccess. We can not simply
@@ -203,6 +212,15 @@ static rsRetVal UDPSend(instanceData *pData, char *msg, 
size_t len)
                 bSendSuccess = FALSE;
                 for (r = pData->f_addr; r; r = r->ai_next) {
                         for (i = 0; i < *pData->pSockArray; i++) {
+                               /* if we are forging the source IP of the 
packet, issue the bind to do so
+                                * this should be made conditional on a config 
option -- David Lang 2009-02-25
+                                * since I don't know how to get the correct 
source IP, I'll set it to look
+                                * like it comes from 10.201.1.1 IPv4
+                                */
+
+
+                                struct sockaddr_in source;
+                               memset(&source,0,sizeof(source));
+                                source.sin_family =  AF_INET;
+                                source.sin_addr.s_addr = 0x0101c90a;
+                                source.sin_port = 0x0000;
+
+/*                             bind(pData->pSockArray[i+1],(struct sockaddr *) 
&source,sizeof(source));
+*/
+
                                lsent = sendto(pData->pSockArray[i+1], msg, 
len, 0, r->ai_addr, r->ai_addrlen);
                                 if (lsent == len) {
                                         bSendSuccess = TRUE;


this works for reopening the socket each time, but if I uncomment the bind 
the sendto fails  (error 22, invalid input)

I haven't yet figured out what I'm missing on the bind that's causing this

David Lang

_______________________________________________
rsyslog mailing list
http://lists.adiscon.net/mailman/listinfo/rsyslog
http://www.rsyslog.com

Reply via email to