Project Home
Project Home
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - inetd UDP app after an IP address change: (7 Items)
   
inetd UDP app after an IP address change  
I have a UDP application that is started by inetd when a request on a specific socket it received.  I was testing 
various network occurrences and came across a problem when the Ip address was changed.  If the application is up and the
 IP address was changed I received UDP requests, but I could no longer transmit the replies.  Are you aware of this 
problem?  Do you know of any fixes?

I have found a work around that gets things working and I will describe it below.  I don't know why it works, and don't 
think it should be the final solution.

I am running QNX 6.4.1 on a PC VM.
To simulate the loss of a DHCP assigned IP address an acquisition of another I have turned off dhcp.client and am 
changing the IP address using ifconfig (ifconfig en0 inet <new IP> netmask 255.255.255.0).

Here are the steps of my test.
1) Get the system running (network up, assigned iP address, etc).
2) Send a UDP request to my device and I get a response.
3) Change the Ip address using ifconfig command line.
4) Send the UDP request and sendto() fails the first time in the for loop returning a -1 with errno = 249.
4a) If I send the request from the local network sendto() succeeds the second time.
4b) If I send the request from a different subnet then sendto() fails the second time with errno = 251 and then succeeds
 the third time sendto() is called.
NOTE: If I don't add the loop and set of the flag, then I continuously get a sendto() error with errno = 249 on this 
socket until I change the IP address back to the previously assigned one.

size_t UdpListenerConnection::Write(uint8_t const* dataBuffer, const size_t dataBufferSize, size_t writeTimeoutMs) //
lint --e{715}
{
   size_t numWritten = 0;

   if (true == isOpen && NULL != dataBuffer && dataBufferSize > 0) {
      socklen_t tolen = sizeof(fromAddress);
      int errNum = 0;
      struct sockaddr_in   broadcastAddress;
      int flags = 0, i;

      for (i=0;i < 3; i++) {
         flags = 0;

         memcpy(&broadcastAddress, &fromAddress, tolen);
         if (249 == errNum) {
            flags = MSG_DONTROUTE;
         }

         zError("Write: to=0x%x numBytes=%d", fromAddress.sin_addr.s_addr, dataBufferSize);
         ssize_t writeReturn = sendto(mySocketHandle, dataBuffer, dataBufferSize, flags, (struct sockaddr*)&
broadcastAddress,  tolen);
         if (writeReturn != -1) {
            numWritten = (size_t)writeReturn;
            break;
         } else {
            zError("Write2: broadcast error retval=%d errno=%d", writeReturn, errno);
            errNum = errno;
         }
      }
   } else {
      zError("Write: Port not open or other error");
   }

   return numWritten;
}
Re: inetd UDP app after an IP address change  
Hi Jared, please see inline...

On 10-05-26 06:52 PM, Jared Roundy wrote:
> I have a UDP application that is started by inetd when a request on a
> specific socket it received.  I was testing various network
> occurrences and came across a problem when the Ip address was
> changed.  If the application is up and the IP address was changed I
> received UDP requests, but I could no longer transmit the replies.
> Are you aware of this problem?  Do you know of any fixes?

I'm not aware, but I'm probably not understanding your question 
correctly, please read on...

> I have found a work around that gets things working and I will
> describe it below.  I don't know why it works, and don't think it
> should be the final solution.
>
> I am running QNX 6.4.1 on a PC VM. To simulate the loss of a DHCP
> assigned IP address an acquisition of another I have turned off
> dhcp.client and am changing the IP address using ifconfig (ifconfig
> en0 inet<new IP>  netmask 255.255.255.0).

My first thought is that perhaps your app should be listening for 
address changes on a routing socket, but maybe that's unnecessarily 
complex, I don't know enough about your app...

> Here are the steps of my test.
> 1) Get the system running (network up, assigned iP address, etc).
> 2) Send a UDP request to my device and I get a response.

What kind of UDP request is this? To the stack, UDP is just UDP, there 
is no concept of requests. Is there anything special about it?

The code below hints at broadcasts are used, is that right? If so, what 
broadcast? Is the request and/or response broadcast? Is it using the 
limited broadcast (255.255.255.255) or the subnet directed broadcast 
(address | ~subnetmask)? Any other information I should know about it?

> 3) Change the Ip address using ifconfig command line.
> 4) Send the UDP request and sendto() fails the first time in the for loop returning a -1 with errno = 249.

This address indicates that the source address wasn't available. Did you 
bind the socket? To a unicast or broadcast address? If unicast, to the 
old interface address or the new? Or is your intent that you can send 
from and/or to a different address each time?

> 4a) If I send the request from the local network sendto() succeeds the second time.

What do you mean by "from the local network" here?

> 4b) If I send the request from a different subnet then sendto() fails the second time with errno = 251 and then 
succeeds the third time sendto() is called.
> NOTE: If I don't add the loop and set of the flag, then I
> continuously  get a sendto() error with errno = 249 on this socket until I change the
 > IP address back to the previously assigned one.

Depending on the situation the socket API requires you to 
SO_BINDTODEVICE in order for broadcasts to work.

> size_t UdpListenerConnection::Write(uint8_t const* dataBuffer, const size_t dataBufferSize, size_t writeTimeoutMs) //
lint --e{715}
> {
>     size_t numWritten = 0;
>
>     if (true == isOpen&&  NULL != dataBuffer&&  dataBufferSize>  0) {
>        socklen_t tolen = sizeof(fromAddress);
>        int errNum = 0;
>        struct sockaddr_in   broadcastAddress;
>        int flags = 0, i;
>
>        for (i=0;i<  3; i++) {
>           flags = 0;
>
>           memcpy(&broadcastAddress,&fromAddress, tolen);
>           if (249 == errNum) {
>              flags = MSG_DONTROUTE;
>           }
>
>           zError("Write: to=0x%x numBytes=%d", fromAddress.sin_addr.s_addr, dataBufferSize);
>           ssize_t writeReturn = sendto(mySocketHandle, dataBuffer, dataBufferSize, flags, (struct sockaddr*)&
broadcastAddress,  tolen);

This is a little confusing, zError() prints (or logs, I assume) the 
message that indicates you're writing to fromAddress, but then sendto() 
sends to...
View Full Message
Re: inetd UDP app after an IP address change  
please see inline...
> 
> My first thought is that perhaps your app should be listening for 
> address changes on a routing socket, but maybe that's unnecessarily 
> complex, I don't know enough about your app...

Our app listens on a UDP socket for a packet that effectively says "send me your info".  We then send a packet back to 
the sender with "our info". Then it waits for another request from someone.  I hoped I didn't have to worry about the IP
 address.

> 
> > Here are the steps of my test.
> > 1) Get the system running (network up, assigned iP address, etc).
> > 2) Send a UDP request to my device and I get a response.
> 
> What kind of UDP request is this? To the stack, UDP is just UDP, there 
> is no concept of requests. Is there anything special about it?

To UDP it is just a packet that gets delivered to our app.  We then want to send a UDP packet back to the sender.  The 
stack doesn't need to worry about anything special.  It just has to give us the packets, and send the responses back to 
the sender [the sender's IP address is passed into the sendto()].  We don't keep track of what our IP address is.

> 
> The code below hints at broadcasts are used, is that right? If so, what 
> broadcast? Is the request and/or response broadcast? Is it using the 
> limited broadcast (255.255.255.255) or the subnet directed broadcast 
> (address | ~subnetmask)? Any other information I should know about it?

Sorry for the confusion about broadcasts.  We do not send packets to any type of broadcast address, subnet directed or 
any other.  We send our responses to the PC that requests the information.  The name wasn't cleaned up from hacking the 
code to try to get it to work and some other code I pulled it from.

> 
> > 3) Change the Ip address using ifconfig command line.
> > 4) Send the UDP request and sendto() fails the first time in the for loop 
> returning a -1 with errno = 249.
> 
> This address indicates that the source address wasn't available. Did you 
> bind the socket? To a unicast or broadcast address? If unicast, to the 
> old interface address or the new? Or is your intent that you can send 
> from and/or to a different address each time?

We don't bind() on the socket or anything else.  We use socketHandle = 0, because we are getting started by inetd.  
After we are started by inetd we call Read(), the code is shown below.  Then we check that it is a proper "request for 
information".  If it is, we send back information.  Finally we do a blocking read until we get another packet.  Our 
intent is to send the response packet back from whatever IP address we currently have.

> 
> > 4a) If I send the request from the local network sendto() succeeds the 
> second time.
> 
> What do you mean by "from the local network" here?

I mean the local subnet.  (from 172.30.16.51 to 172.30.16.25 with netmask 255.255.255.0)

> 
> > 4b) If I send the request from a different subnet then sendto() fails the 
> second time with errno = 251 and then succeeds the third time sendto() is 
> called.
> > NOTE: If I don't add the loop and set of the flag, then I
> > continuously  get a sendto() error with errno = 249 on this socket until I 
> change the
>  > IP address back to the previously assigned one.
> 
> Depending on the situation the socket API requires you to 
> SO_BINDTODEVICE in order for broadcasts to work.

We don't want to broadcast, so I assume this isn't needed.  We just want to send back to the address that requested the 
information.

> 
> > size_t UdpListenerConnection::Write(uint8_t const* dataBuffer, const size_t 
> dataBufferSize, size_t writeTimeoutMs) //lint --e{715}
> > {
> >     size_t numWritten = 0;
> >
> >     if (true == isOpen&&  NULL != dataBuffer&&  dataBufferSize> ...
View Full Message
Re: inetd UDP app after an IP address change  
Hello,

what is the output of "pidin -P your_prog_name fd" before and after the IP change?

Regrads, PKY
Re: inetd UDP app after an IP address change  
Here is the requested info.  The first one is before the IP address change.  Then you see the IP address change.  Then I
 requested the information again, it is unchanged.  Then I sent my UDP packet request from my PC.  I finished off by 
getting the infromation again.  I don't see any of the information changing.

# pidin -P EsiIpDiscovery_ln fd
     pid name
59670547 /EsiIpDiscovery_ln
           0  102414 rw        0 I4UDP  *.4201                *.*

           1  102414 rw        0 I4UDP  *.4201                *.*

           2  102414 rw        0 I4UDP  *.4201                *.*

           3    4100 -w        0 /dev/slog
           0s      1
           2s      1
           3s 59269168
           4s 59232291
           5s 59232291
# ifconfig en0 inet 172.30.16.52 netmask 255.255.255.0
# pidin -P EsiIpDiscovery_ln fd
     pid name
59670547 /EsiIpDiscovery_ln
           0  102414 rw        0 I4UDP  *.4201                *.*

           1  102414 rw        0 I4UDP  *.4201                *.*

           2  102414 rw        0 I4UDP  *.4201                *.*

           3    4100 -w        0 /dev/slog
           0s      1
           2s      1
           3s 59269168
           4s 59232291
           5s 59232291
# pidin -P EsiIpDiscovery_ln fd
     pid name
59670547 /EsiIpDiscovery_ln
           0  102414 rw        0 I4UDP  *.4201                *.*

           1  102414 rw        0 I4UDP  *.4201                *.*

           2  102414 rw        0 I4UDP  *.4201                *.*

           3    4100 -w        0 /dev/slog
           0s      1
           2s      1
           3s 59269168
           4s 59232291
           5s 59232291
#
Re: inetd UDP app after an IP address change  
Hi Jared

Did you finally get this to work? Can  you please let us know the problem or the solution?

Regards
Vineet 

Re: inetd UDP app after an IP address change  
The problem seems to lie with the fact that the socket keeps information in itself.  When the IP address changes it has 
problems.  The work around above worked fine (just need to clean it up and fix the variable names).

Due to system design we decided to slay all connections\apps when our IP address changes.

Jared