Jared Roundy
|
inetd UDP app after an IP address change
|
Jared Roundy
05/26/2010 6:52 PM
post55641
|
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;
}
|
|
|
Patrik Lahti
|
Re: inetd UDP app after an IP address change
|
Patrik Lahti
06/06/2010 8:51 AM
post56113
|
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
|
|
|
Jared Roundy
|
Re: inetd UDP app after an IP address change
|
Jared Roundy
06/07/2010 1:13 PM
post56192
|
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
|
|
|
Pavol Kycina
|
Re: inetd UDP app after an IP address change
|
Pavol Kycina
06/08/2010 3:44 AM
post56238
|
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
|
|
|
Jared Roundy
|
Re: inetd UDP app after an IP address change
|
Jared Roundy
06/08/2010 8:00 AM
post56255
|
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
#
|
|
|
Vineet Garg
|
Re: inetd UDP app after an IP address change
|
Vineet Garg
07/02/2010 7:32 AM
post58316
|
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
|
|
|
Jared Roundy
|
Re: inetd UDP app after an IP address change
|
Jared Roundy
07/02/2010 8:30 AM
post58323
|
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
|
|
|
|