buglwIP - A Lightweight TCP/IP stack - Bugs: bug #61230, Improve Dual-Stack support for...

 
 

You are not allowed to post comments on this tracker with your current authentication level.

bug #61230: Improve Dual-Stack support for getaddrinfo, return both IPv4 and IPv6 results

Submitter:  Simon Kueppers <skuep2>
Submitted:  Mon 27 Sep 2021 07:37:20 AM UTC
   
 
Category:  sockets/netconn Severity:  3 - Normal
Item Group:  Change Request Status:  None
Privacy:  Public Assigned to:  None
Open/Closed:  Open Planned Release:  None
lwIP version:  git head

Wed 06 Oct 2021 07:53:40 PM UTC, comment #2: 

Some further notes regarding my first post:
getaddrinfo in server applications (AI_PASSIVE) now works exactly as it should. The order of AF_INET/AF_INET6 in dual-stack applications can be set with LWIP_DNS_API_FAMILIES_LOCAL (netdb.h).

In client applications, I now implemented the version where two successive DNS calls to the DNS server are done, when no family is specified in the hints and lwIP is compiled as dual-stack.
This is wasteful, yes, but I think this is only an edge case. Additionally, this is something that a more-aware version of the DNS api could work around by caching both IPv4 and IPv6 addresses when a request to the DNS server is made.
The order of returned IP addresses can be set with LWIP_DNS_API_FAMILIES (netdb.h)

In the attachment is now the Python script that I used to create the reference file. I also added the C-code I used to print the results from lwIP.

(file #52061, file #52062)

Simon Kueppers <skuep2>
Wed 06 Oct 2021 07:43:09 PM UTC, comment #1: 

I have been busy and I think I have a good solution.
I have created a python script to generate reference output of some test cases for getaddrinfo. I then wrote a C function, that I compiled with lwIP using the same getaddrinfo calls and then I compared the output to the reference output of the python script.

See attached the patch to lwIP and the test outputs (can be compared using diff).

(file #52057, file #52058, file #52059, file #52060)

Simon Kueppers <skuep2>
Mon 27 Sep 2021 07:37:20 AM UTC, original submission:  

Currently getaddrinfo only returns a single struct addrinfo with either an IPv4 or IPv6 address (with IPv4 being preferred if AF_UNSPEC is given). This is true for either server application usage (i.e. getaddrinfo(NULL, 1234, IPPROTO_TCP, AI_PASSIVE)) or client application usage (i.e. getaddrinfo("hostname.domain", 1234, IPPROTO_TCP, 0)).

This behaviour is not entirely correct and prevents some server applications (such as open62541) from being able to listen on IPv6 addresses, when they use dedicated sockets for IPv4 and IPv6 connections (using IPV6_V6ONLY on IPv6 sockets). Note that server applications that do not set IPV6_V6ONLY on the socket and listen on the IPv6 address only already work perfectly in a dual-stack configuration with LWIP.
When running the getaddrinfo function on a Ubuntu based system, the results are as followed:

python3 -c "import socket; print(socket.getaddrinfo(None, 1234, proto=socket.IPPROTO_TCP, flags=socket.AI_PASSIVE))"
[
  (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('0.0.0.0', 1234)),
  (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('::', 1234, 0, 0))
]

This is the intended behaviour and it would be best if LWIP's implementation of getaddrinfo could be closer to this behaviour.

I propose a two-step approach regarding this bug/feature:

  • When using getaddrinfo in server applications (AI_PASSIVE):

getaddrinfo should return both IPv4 and IPv6 listen addresses (e.g. "0.0.0.0" and "::") to support dual-stack server applications that listen on each of the returned sockets separately and use IPV6_V6ONLY on the IPv6 socket.
This should be relatively straight forward to implement. We could add an LWIP configuration option to explicitly enable this behaviour in order to not break things for existing applications and stay compatible to the current behaviour by default.

  • When using getaddrinfo as client:

This is probably a bit harder to solve, since we rely on netconn_gethostbyname_addrtype calling dns_gethostbyname which is only able to return a single address at once. It may be possible, but wasteful to run two successive calls to netconn_gethostbyname_addrtype to retrieve both IPv4 and IPv6 addresses.
This issue would need to be tackled first, before continuing to implement this feature in getaddrinfo.



In addtion, when returning multiple struct addrinfo entries, the question of their order arises. I.e. whether the IPv4 or IPv6 address should be returned first. Since netconn_gethostbyname_addrtype already uses a prioritization scheme (e.g. NETCONN_DNS_IPV4_IPV6) when looking up hostnames via DNS, we could implement a similar behaviour in case getaddrinfo being called with AF_UNSPEC.
On desktop OSes such as Ubuntu, there is a system-wide gai.conf file that controls the order of entries returned by getaddrinfo.
I am suggesting adding another LWIP configuration option to explicitly set the priority/order of IPv4/IPv6 addresses returned by the getaddrinfo function to "emulate" the functionality of gai.conf.

Simon Kueppers <skuep2>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attached Files
file #52061:  getaddrinfo.py added by skuep2 (2KiB - text/x-python)
file #52062:  getaddrinfo.c added by skuep2 (5KiB - text/x-csrc)
file #52057:  lwip_getaddrinfo.patch added by skuep2 (17KiB - text/x-patch)
file #52058:  getaddrinfo.pc.txt added by skuep2 (4KiB - text/plain)
file #52059:  getaddrinfo.lwip-old.txt added by skuep2 (2KiB - text/plain)
file #52060:  getaddrinfo.lwip-new.txt added by skuep2 (4KiB - text/plain)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by skuep2 (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

     

    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2021-10-06 skuep2 Attached File- Added getaddrinfo.py, #52061
        Attached File- Added getaddrinfo.c, #52062
    2021-10-06 skuep2 Attached File- Added lwip_getaddrinfo.patch, #52057
        Attached File- Added getaddrinfo.pc.txt, #52058
        Attached File- Added getaddrinfo.lwip-old.txt, #52059
        Attached File- Added getaddrinfo.lwip-new.txt, #52060

    Back to the top

    Powered by Savane 3.13-758e.
    Corresponding source code