We have previously used the getsockname() function on a UDP socket to get our local ip address. When we upgraded to NuttX 7.23 (from 7.21) this stopped working. I traced this down to a change in net/socket/getsockname.c, where the function ipv4_getsockname() was moved to net/inet/ipv4_getsockname.c. The function was also changed such that if the local address (upd_conn.u.ipv4.laddr) is set to 0 (i.e. INADDR_ANY) the returned IP-address is also 0. In the previous version, a local address of zero (for the socket) returned the IP address of the first ethernet device. I was wondering if this is intentional? ...
Yes, this is correct in the newer versions of NuttX. The old versions of NuttX had an option to support only a single network device. It did not matter if the packet was routable or not, it always responding with information about that single network device or, more correctly, the single network supported by the device.
That logic was wrong in previous versions of NuttX!
The current version of NuttX is correct. If asked about anything that requires knowledge of the routing, the query will either fail or will depend on some entry in the routing to table to determine what to do with the packet. In ipv4_getsockname() there it this:
dev = netdev_findby_ipv4addr(lipaddr, ripaddr);
And that will (1) try to find a network device serving the network of the remote address and, if none is found, it will (2) look in the routing table to determine which network device to use. If you only have one network device and you want the similar behavior to the older, incorrect code, you will need to add a default route like:
0.0.0.0/0 -> aa.bb.cc.dd
That will send everything tthat requires routing to network device that serves the network of aa.bb.cc.dd (If you wanted other routing, it should appear BEFORE this one in the routing table).
"If the socket has not been bound to a local name, the value stored in the object pointed to by address is unspecified."
I believe that if you wanted things behave the way you want on any Unix-like platform, you would need a default route in your routing table. I believe that NuttX is compatible with the rest of the world in this way.
We do not bind the socket specifically, but send on it using sendto() which eventually calls udp_connect() which binds the socket to a local port. Not sure if this counts as binding it to a local name or not?
udp_connect() is misnamed since there are no connections with datagrams. This is really just the internal implementation of sendto: When you sendto a remote peer, it will again do the lookup to find the device that serves the network of the remote peer. That device is then simply remembered in by udp_connect() in order to perform the send.
So I don't think this has any relevance (other than it might leave the socket in a bound state after the sendto... that would be wrong).