IPv6 bind fails with 49 (#define EADDRNOTAVAIL 49 /* Can't assign requested address */)

Sreenivasa Honnur shonnur at chelsio.com
Thu Apr 18 12:03:10 UTC 2013


I have a ipv6 interface(ping6 to a remove ipv6 works) when I try to bind to this address through a socket program "sobind" fails with "49" as return value. If I give "saddr6.sin6_addr =  in6addr_any;" sobind works.



Any idea what could be going wrong here?



roundhay# ifconfig cxgbe1

cxgbe1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500

        options=6c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>

        ether 00:07:43:11:89:88

        inet6 2010::102 prefixlen 64

        inet6 fe80::207:43ff:fe11:8988%cxgbe1 prefixlen 64 scopeid 0xd

        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

        media: Ethernet 10Gbase-SR <full-duplex>

        status: active

roundhay# ping6 2010::101

PING6(56=40+8+8 bytes) 2010::102 --> 2010::101

16 bytes from 2010::101, icmp_seq=0 hlim=64 time=0.950 ms

16 bytes from 2010::101, icmp_seq=1 hlim=64 time=0.158 ms ^C

--- 2010::101 ping6 statistics ---

2 packets transmitted, 2 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 0.158/0.554/0.950/0.396 ms







Code:

=====

{

            rv = socreate(AF_INET6, &sock, SOCK_STREAM, IPPROTO_TCP,

                                td->td_ucred, td);



                if (rv != 0) {

                        os_log_error("sock create ipv6 %s failed %d.\n",

                                        tbuf, rv);

                        return NULL;

                }



                family = saddr6.sin6_family = AF_INET6;

    inet_pton(AF_INET6, "2010::102", &saddr6.sin6_addr);

                saddr6.sin6_port = htons(ep->port);

                saddr6.sin6_len = sizeof(struct sockaddr_in6);



                rv = sobind(sock, (struct sockaddr *)&saddr6, td); }





Here is the code snippet from where EADDRNOTAVAIL  is returned.



File : netinet6/in6_pcb.c



in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,

    struct ucred *cred)

{

........

........



} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {

                        struct ifaddr *ifa;



                        sin6->sin6_port = 0;            /* yech... */

                        if ((ifa = ifa_ifwithaddr((struct sockaddr *)sin6)) ==

                            NULL &&

                            (inp->inp_flags & INP_BINDANY) == 0) {

                                return (EADDRNOTAVAIL); è it fails here since ifa_ifwithaddr() returns NULL

                        }

........

........



}



File: net/if.c

struct ifaddr *

ifa_ifwithaddr(struct sockaddr *addr)

{



        return (ifa_ifwithaddr_internal(addr, 1)); }



ifa_ifwithaddr_internal(struct sockaddr *addr, int getref) { ........

........



TAILQ_FOREACH(ifp, &V_ifnet, if_link) {

                IF_ADDR_RLOCK(ifp);

                printf("ifp->xname:%s ifp->dname:%s\n",ifp->if_xname, ifp->if_dname);

                TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {

                        if (ifa->ifa_addr->sa_family != addr->sa_family) è  ifa->ifa_addr->sa_family=18 & addr->sa_family=28. Even though the interface is in IPV6 mode its sa_family is not  set properly,

                                                        continue; } Ifa = NULL; ........

........



}



More information about the freebsd-hackers mailing list