Failure to bind socket when custom ip is set for ethernet adapter
Asked Answered
B

1

6

The problem

On our system running RTEMS 4.9.2 we are experiencing a very odd issue with socket communications. We are setting up a socket and using the following command to bind:

// Bind the socket to set the local port
sockaddr_in localSocketAddress = {0};
localSocketAddress.sin_family = AF_INET;
localSocketAddress.sin_port = (u_short)localPort;
localSocketAddress.sin_addr.s_addr = localAddress;

if (bind( mSocket, (sockaddr *)&localSocketAddress, sizeof(sockaddr_in)) == SOCKET_ERROR)
{
    int errorOut = errno;
    ...

And this works for UDP communications except in a strange specific scenario which is explained below. The problem that we experience is a failure of this bind call even though the setup is correct. We get the error 125 which for RTEMS is EADDRNOTAVAIL:

A nonexistent interface was requested or the requested address was not local.

The Apparent Cause

At boot of the device we can set up our network in 1 of 2 ways:

  1. The Network IP and SUBNET is autoconfigured based on what is in the default bootloader (UBOOT), and is set up through the RTEMS OS.

  2. The RTEMS function rtems_bsdnet_ifconfig is called to change the ip address of the sole ethernet interface after boot time.

For clarification, option 2 is called like this:

rtems_bsdnet_ifconfig(eth_interface, SIOCSIFADDR, &ipaddr);

If the network is set up as indicated by option 1, everything works as expected, but if option 2 is used (even in the case where the setup matches the network options defined by option 1) then the socket bind fails.

Is there a known reason or bug for RTEMS that indicates that this bind would fail if you reconfigure your IP?

Additional Information

  • We are setting up a new IP address (option 2) using a method that essentially uses ioctl("eht1", SIOCSIFADDR, ...).

  • If we bind our socket without specifying a local ADDRESS (ie use INADDR_ANY) then it works in any case.

  • The rtems_bsdnet_ifconfig is a simple interface for the ioctl function. It is from rtems_glue.c and has the function signiture int rtems_bsdnet_ifconfig(const char *ifname, uint32_t cmd, void *param)

  • All normal network functions seem to work except for this bind.

  • After looking at this i thought maybe I needed to do more in resetting my IP address. But this doesn't work , using the first answer or even doing anything with SIOCSIFFLAGS causes all network functionality to cease.

Bael answered 8/6, 2016 at 16:46 Comment(15)
is it possible your bind is happening before the interface has completed setting up? does it continue to fail if you continue to retry the bind?Bitthia
@Bitthia The bind is well after the setup, both setup options occur at boot before the socket setup can be attempted.Bael
Probably something change since my rtems version (4.6.1) but rtems_bsdnet_ifconfig it is a struct not a function...Gun
@Gun It is both, a struct exists and so does a function, the function doesnt seem to have any documentation otherwise i would link it, it can be found in rtems_glue.c.Bael
Disclaimer: No expert here, just went through the code a bit. Do you explicitly set sa_family to AF_INET? Seems as if this isn't required, but should be set as it is used in the comparision. Another hint, as the sockaddr structs are byte-compared: do you memset your sockaddr struct to 0 before configuring it's values and passing to bind?Divaricate
Have you tried to step through the bind() call with a debugger and look where the return EADDRNOTAVAIL exactly happens?Clearly
@Clearly Unfortunately we have no active debugger, this only occurs on the actual embedded hardware, all i can use is print statements.Bael
Do you compile the library yourself?Clearly
@Clearly We compile the entire OS ourselves. But there is no interface to the embedded hardware that could use a debugger even if RTEMS implemented one.Bael
@Divaricate We do both those things, i have edited the question to reflect this. sockaddr_in localSocketAddress = {0};Bael
That is not why I am asking. Is there any chance that you include some debug output at the relevant places and debug it that way? We will have to put some thoughts and effort into figuring out this "relevant" places, but that might be worth trying.Clearly
@Clearly Yes, i can put debug prints into the operating system, it uses BSDNet libs for everything networking. I would then be able to recompile the operating system and see the prints, but i usually have to be very careful, printing too much can screw up the timing. I hate doing that ...Bael
I hate that, too. But as long nobody answers I think you have not much choice.Clearly
@Ben alright, I see. Another thing to check, though I don't think that it's the core of the issue here: There's a sin_len member of sockaddr_in which you should initialize to sizeof struct sockaddr_in.Divaricate
@Divaricate So i gave this a go, doesn't make any difference unfortunately.Bael
C
1

You didn't mention the architecture you are running on, but you are setting the port and address in local byte order, which may not be the same as network byte order. The very first thing I would try is:

localSocketAddress.sin_port = htons (localPort); localSocketAddress.sin_addr.s_addr = htonl (localAddress);

This will also make your code more portable, in case that is NOT your problem (i.e. you are running on a big-endian host) and you one day try to compile on a different system that is little endian.

Christiachristian answered 11/7, 2016 at 17:37 Comment(5)
Why should it be a comment? Just asking for future clarity's sake. Also did you even TRY my suggestion? Those fields are supposed to be in network byte order and using htons() and htonl() is "correct".Christiachristian
@Ben A solution is an answer, not a comment. You are mistaken and Kean is not.Primordium
@Kean, my apologies about the comment thing, i will try your solution. However, do we expect it to work? If you read the question the socket bind works just fine in every case unless i run rtems_bsdnet_ifconfig( to reconfigure my network address. Why would it ever work if the network address was in the wrong order?Bael
@Ben I think I assumed that the actual address you were connecting to changed after that rtems call. I should not have assumed such, but since I did my reasoning was that in the first case it could have been some constant you had assigned to localAddress, whereas after making the change you set it to something else. Assumption is the mother of all failures. Sorry about that.Christiachristian
Just so we are clear about this, unfortunately this solution didn't work.Bael

© 2022 - 2024 — McMap. All rights reserved.