[task #15393] Support scoped literal IPv6 addresses in getaddrinfo

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[task #15393] Support scoped literal IPv6 addresses in getaddrinfo

David GIRAULT-2
URL:
  <https://savannah.nongnu.org/task/?15393>

                 Summary: Support scoped literal IPv6 addresses in getaddrinfo
                 Project: lwIP - A Lightweight TCP/IP stack
            Submitted by: ashesman
            Submitted on: Thu 19 Sep 2019 04:20:16 AM UTC
                Category: socket/netconn
         Should Start On: Thu 19 Sep 2019 12:00:00 AM UTC
   Should be Finished on: Thu 19 Sep 2019 12:00:00 AM UTC
                Priority: 5 - Normal
                  Status: None
                 Privacy: Public
        Percent Complete: 0%
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
         Planned Release: None
                  Effort: 0.00

    _______________________________________________________

Details:

It would be great if you could bind to a linklocal ip address used a scoped
literal type address through the APIs that just take a URI string.  E.g.
fe80::1ff:fe23:4567:890a%en1 or fe80::1ff:fe23:4567:890a%2.

mbedtls net abstraction layer only offers a bind that takes a char *.  Passing
a scoped link local IP address in causes the socket to be incorrectly bound to
zone 0 and hence cannot accept incoming packets.

Currently I cannot see a way to do this in a portable manner using the
existing APIs.

Of course, you can achieve this functionality through lower layer calls...

Please excuse if I have missed something...




    _______________________________________________________

Reply to this item at:

  <https://savannah.nongnu.org/task/?15393>

_______________________________________________
  Message sent via Savannah
  https://savannah.nongnu.org/


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

[task #15393] Support scoped literal IPv6 addresses in getaddrinfo

David GIRAULT-2
Follow-up Comment #1, task #15393 (project lwip):

I thought that should work. Could you help us by telling us which lwIP
function mbedTLS calls to bind and with which parameters? Maybe you just got
the netif name wrong?

    _______________________________________________________

Reply to this item at:

  <https://savannah.nongnu.org/task/?15393>

_______________________________________________
  Message sent via Savannah
  https://savannah.nongnu.org/


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

[task #15393] Support scoped literal IPv6 addresses in getaddrinfo

David GIRAULT-2
Follow-up Comment #2, task #15393 (project lwip):

Thanks for your reply.

The code used by mbedtls is below.  I know the interface name is correct as I
made the interface myself and it returns the correct index when queried by
name.  It gets as deep down as ip6addr_aton with the scoped address which
returns a correctly decoded IPV6 address but the zone is always set to 0 by
line 187 of ip6_addr.c.  There is no test in this function for the existence
of a % in the address.  

I can bind to a link local address on my interface using the socket bind
function as expected but need to call an lwip function to get the interface id
which is not available through a portable API.

I pass "FE80::2B0:52FF:FEFF:FF05%pl1" as bind_ip and it always results in a
zone (scope_id) of 0.  It should set the correct zone I think if there was
only one interface present (there is a test for this somewhere down the
stack).  But I have two interfaces.

int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const
char *port, int proto )
{
    int ret;
    struct addrinfo hints, *addr_list, *cur;

    if ( ( ret = net_prepare() ) != 0 ) {
        return ( ret );
    }

    /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
    memset( &hints, 0, sizeof( hints ) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM :
SOCK_STREAM;
    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP :
IPPROTO_TCP;

    if ( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) {
        return ( MBEDTLS_ERR_NET_UNKNOWN_HOST );
    }

    /* Try the sockaddrs until a binding succeeds */
    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
    for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
        int fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol
);
        if ( fd < 0 ) {
            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
            continue;
        }

        /*SO_REUSEADDR option dafault is disable in source code(lwip)*/
#if SO_REUSE
        int n = 1;
        if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
                         (const char *) &n, sizeof( n ) ) != 0 ) {
            close( fd );
            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
            continue;
        }
#endif
        /*bind interface default don't process the addr is 0xffffffff for TCP
Protocol*/
        struct sockaddr_in *serv_addr = NULL;
        serv_addr = (struct sockaddr_in *)cur->ai_addr;
        serv_addr->sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming
interface */
        if ( bind( fd, (struct sockaddr *)serv_addr, cur->ai_addrlen ) != 0 )
{
            close( fd );
            ret = MBEDTLS_ERR_NET_BIND_FAILED;
            continue;
        }
...


I use this function I wrote instead to bind to the link local address on my
interface which works perfectly:

#include "lwip/netifapi.h"
int mbedtls_net_bind_ip6_interface(mbedtls_net_context *ctx, const char *
bind_ip, const char * interface, unsigned port, int proto )
{
    int ret;
    struct sockaddr_in6 sa6;
    if ( ( ret = net_prepare() ) != 0 ) {
        return ( ret );
    }
    inet_pton(AF_INET6, bind_ip, &(sa6.sin6_addr));
    sa6.sin6_port = htons(port);
    sa6.sin6_len = sizeof(sa6);
    sa6.sin6_flowinfo = 0;
    sa6.sin6_family = AF_INET6;
    u8_t idx = 0;
    netifapi_netif_name_to_index(interface, &idx);
    sa6.sin6_scope_id = idx;
   
    int fd = socket( sa6.sin6_family, proto == MBEDTLS_NET_PROTO_UDP ?
SOCK_DGRAM : SOCK_STREAM, proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP :
IPPROTO_TCP);
    if ( fd < 0 ) {
        return MBEDTLS_ERR_NET_SOCKET_FAILED;
    }

    /*SO_REUSEADDR option dafault is disable in source code(lwip)*/
#if SO_REUSE
    int n = 1;
    if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(
n ) ) != 0 ) {
        close( fd );
        return MBEDTLS_ERR_NET_SOCKET_FAILED;
    }
#endif
    if ( bind( fd, (struct sockaddr *)&sa6, sizeof(sa6) ) != 0 ) {
        close( fd );
        return MBEDTLS_ERR_NET_BIND_FAILED;
    }

...

    _______________________________________________________

Reply to this item at:

  <https://savannah.nongnu.org/task/?15393>

_______________________________________________
  Message sent via Savannah
  https://savannah.nongnu.org/


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

[task #15393] Support scoped literal IPv6 addresses in getaddrinfo

David GIRAULT-2
Follow-up Comment #3, task #15393 (project lwip):

Ok, so it's getaddrinfo("FE80::2B0:52FF:FEFF:FF05%pl1" , ...) that doesn't
work as expected...

    _______________________________________________________

Reply to this item at:

  <https://savannah.nongnu.org/task/?15393>

_______________________________________________
  Message sent via Savannah
  https://savannah.nongnu.org/


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel
Reply | Threaded
Open this post in threaded view
|

[task #15393] Support scoped literal IPv6 addresses in getaddrinfo

David GIRAULT-2
Follow-up Comment #4, task #15393 (project lwip):

Yes, correct.  getaddrinfo works as expected under linux.  For example:

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
    struct addrinfo hints = {0};
    struct addrinfo * res = NULL;
    if (getaddrinfo("fe80::8831:ba34:ba2e:667f%wlp5s0", "1234", &hints, &res)
== 0)
    {
        struct addrinfo * info = res;
        while (info)
        {
            if (info->ai_family == AF_INET6)
            {
                struct sockaddr_in6 * pI6 = (struct sockaddr_in6
*)info->ai_addr;
                                if (IN6_IS_ADDR_LINKLOCAL(&(pI6->sin6_addr)))
                                {
                    char buf[64];
                                        printf("IP6 Addr: %s%%%d\n", inet_ntop(AF_INET6, &pI6->sin6_addr, buf,
sizeof(buf)), pI6->sin6_scope_id);
                                }
            }
            info = info->ai_next;
        }
    }
    freeaddrinfo(res);
    return 0;
}

Gives the following result for "fe80::8831:ba34:ba2e:667f%wlp5s0" :

IP6 Addr: fe80::8831:ba34:ba2e:667f%3
IP6 Addr: fe80::8831:ba34:ba2e:667f%3
IP6 Addr: fe80::8831:ba34:ba2e:667f%3

Or for "fe80::a8e0:d579:be00:72ab%enp4s0" :
IP6 Addr: fe80::a8e0:d579:be00:72ab%2
IP6 Addr: fe80::a8e0:d579:be00:72ab%2
IP6 Addr: fe80::a8e0:d579:be00:72ab%2

    _______________________________________________________

Reply to this item at:

  <https://savannah.nongnu.org/task/?15393>

_______________________________________________
  Message sent via Savannah
  https://savannah.nongnu.org/


_______________________________________________
lwip-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/lwip-devel