Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Dec 2002 17:16:57 -0700
From:      "Jeff W. Boote" <boote@internet2.edu>
To:        JINMEI@internet2.edu, Tatuya@internet2.edu, /@internet2.edu, "$B?\"@L@C#:Hnet2.edu?fetch>UID>|INBOX>9535"@internet2.edu
Cc:        freebsd-net@FreeBSD.ORG
Subject:   Re: IPv6 udp socket bind: EADDRNOTAVAIL?
Message-ID:  <3DFBC9F9.9BEAA413@internet2.edu>
References:  <3DFA268D.A073F0F3@internet2.edu> <y7vadj9gn19.wl@ocean.jinmei.org>

next in thread | previous in thread | raw e-mail | index | archive | help


JINMEI Tatuya / $B?@L@C#:H(B wrote:
> > 2. This system is auto configuring this address... Is it possible that
> > I'm just having this problem because the system is reconfiguring the
> > address at this time? (I must admit that I have not looked at the auto
> > configuration stuff.)
> 
> I don't think so.  Even if the system is reconfiguring global
> addresses, it should have other stable addresses, such as link-local
> and loopback ones.  So the address list starting at in6_ifaddr should
> rarely be empty.
>
> I suspect the EADDRNOTAVAIL error comes from a different part of the
> kernel (or the kernel has a serious bug).

I *may* have found my problem. (Since this has been intermittent I will
need to let my fix run for a while longer before I'm convinced.)

In my code, I am creating the struct sockaddr directly. (not using
getaddrinfo or anything like that.) This is because the "control"
connection was requesting a specific numeric address for the udp
"test". I believe my problem may have been that I had the sa_len
value set to 0. (It was zero because I memset the entire structure
before starting, and I was attempting to write portable code - and
that member is not portable. In any case, I have determined that
getnameinfo on FreeBSD doesn't work unless it is set. So it wouldn't
surprise me if bind failed in this case as well.) I have modified
my code to set the sa_len field.

Incidentally - I'm setting the flowinfo and scope_id fields to 0 as
well. I believe that is the correct thing to do. At least it looked
like that was correct the last time I checked, but I admit I have not
looked at the latest version of 2553bis to see if this has changed.

> If you give us more
> information, we may be able to diagnose the problem.  The information
> can include:

Oops. Sorry - I definitely should have done that in the first message.
This gets kind of long, but I don't know of any way to make it shorter:

I'm running a 4.6 kernel on that system.

> - the result of ifconfig -a inet6

owamp@nms2-ipls:~[510]$ ifconfig -a inet6
sk0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet6 fe80::200:5aff:fe9a:6a3c%sk0 prefixlen 64 scopeid 0x1 
        inet6 2001:468:12:3:200:5aff:fe9a:6a3c prefixlen 64 autoconf 
fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet6 fe80::203:47ff:fef1:5071%fxp0 prefixlen 64 scopeid 0x2 
        inet6 2001:468:12:2:203:47ff:fef1:5071 prefixlen 64 autoconf 
fxp1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
ifconfig: fxp1 has no inet6 interface address!
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
        inet6 ::1 prefixlen 128 
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4 
ppp0: flags=8010<POINTOPOINT,MULTICAST> mtu 1500
ifconfig: ppp0 has no inet6 interface address!
sl0: flags=c010<POINTOPOINT,LINK2,MULTICAST> mtu 552
ifconfig: sl0 has no inet6 interface address!
faith0: flags=8002<BROADCAST,MULTICAST> mtu 1500
ifconfig: faith0 has no inet6 interface address!


> - the result of netstat -anl -f inet6

(Of course, I'm not currently having the problem... Hmm - perhaps I should
set something up to run netstat automatically if/when this happens again.)

owamp@nms2-ipls:~[512]$ netstat -anl -f inet6
Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.4822         2001:468:f:2:203:47ff:fef1:4daf.1782          ESTABLISHED
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.4822         2001:468:15:2:203:47ff:fef1:505d.2790         ESTABLISHED
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.4822         2001:468:f:2:203:47ff:fef1:4daf.1780          ESTABLISHED
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.4822         2001:468:15:2:203:47ff:fef1:505d.2788         ESTABLISHED
tcp46      0      0  *.4822                 *.*                    LISTEN
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.2971         2001:468:f:2:203:47ff:fef1:4daf.4822          ESTABLISHED
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.2970         2001:468:f:2:203:47ff:fef1:4daf.4822          ESTABLISHED
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.2920         2001:468:15:2:203:47ff:fef1:505d.4822         ESTABLISHED
tcp6       0      0  2001:468:12:2:203:47ff:fef1:5071.2917         2001:468:15:2:203:47ff:fef1:505d.4822         ESTABLISHED
tcp46      0      0  *.22                   *.*                    LISTEN
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.1366         2001:468:f:2:203:47ff:fef1:4daf.1297          
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.3754         *.*                                           
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.3752         *.*                                           
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.3750         *.*                                           
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.3747         *.*                                           
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.3162         2001:468:15:2:203:47ff:fef1:505d.2156         
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.2888         2001:468:f:2:203:47ff:fef1:4daf.1283          
udp6       0      0  2001:468:12:2:203:47ff:fef1:5071.4675         2001:468:15:2:203:47ff:fef1:505d.2137         
udp6       0      0  *.514                                         *.*                                           

> - the IPv6 address (and port) being bound in the error case

(udp)
Addr: 2001:468:12:2:203:47ff:fef1:5071
Port: 0 (I'm trying to allocate a port.)

> - the (related part of the) source code of the daemon

Ok... to make it just related will take some annotating:

# This is the part of the daemon where I initialize the
# sockaddr structures.
# sender and receiver are pointers to sockaddr_storage variables
# that have been initialized with 0 values.
# (This function reads a request off the network and is decoding
# the message. I'm only including the part that decodes the
# address.)
# The last part with the HAVE_STRUCT_SOCKADDR_SA_LEN I just added,
# and have not seen errors since.
#
        switch(*ipvn){
        struct sockaddr_in      *saddr4;
#ifdef  AF_INET6
        struct sockaddr_in6     *saddr6;
                case 6:
                        if(*socklen < sizeof(struct sockaddr_in6)){
                                OWPError(ctx,OWPErrFATAL,OWPErrINVALID,
                "_OWPDecodeV3TestRequest:socklen not big enough (%d < %d)",
                                        *socklen,sizeof(struct sockaddr_in6));
                                *socklen = 0;
                                return OWPErrFATAL;
                        }
                        *socklen = sizeof(struct sockaddr_in6);

                        /* sender address  and port */
                        saddr6 = (struct sockaddr_in6*)sender;
                        saddr6->sin6_family = AF_INET6;
                        memcpy(saddr6->sin6_addr.s6_addr,&buf[4],16);
                        if(*server_conf_sender)
                                saddr6->sin6_port = 0;
                        else
                                saddr6->sin6_port = *(u_int16_t*)&buf[36];

                        /* receiver address and port  */
                        saddr6 = (struct sockaddr_in6*)receiver;
                        saddr6->sin6_family = AF_INET6;
                        memcpy(saddr6->sin6_addr.s6_addr,&buf[20],16);
                        if(*server_conf_receiver)
                                saddr6->sin6_port = 0;
                        else
                                saddr6->sin6_port = *(u_int16_t*)&buf[38];

                        break;
#endif
                case 4:
                        if(*socklen < sizeof(struct sockaddr_in)){
                                *socklen = 0;
                                OWPError(ctx,OWPErrFATAL,OWPErrINVALID,
                "_OWPDecodeV3TestRequest:socklen not big enough (%d < %d)",
                                        *socklen,sizeof(struct sockaddr_in));
                                return OWPErrFATAL;
                        }
                        *socklen = sizeof(struct sockaddr_in);

                        /* sender address and port  */
                        saddr4 = (struct sockaddr_in*)sender;
                        saddr4->sin_family = AF_INET;
                        saddr4->sin_addr.s_addr = *(u_int32_t*)&buf[4];
                        if(*server_conf_sender)
                                saddr4->sin_port = 0;
                        else
                                saddr4->sin_port = *(u_int16_t*)&buf[36];

                        /* receiver address and port  */
                        saddr4 = (struct sockaddr_in*)receiver;
                        saddr4->sin_family = AF_INET;
                        saddr4->sin_addr.s_addr = *(u_int32_t*)&buf[20];
                        if(*server_conf_receiver)
                                saddr4->sin_port = 0;
                        else
                                saddr4->sin_port = *(u_int16_t*)&buf[38];

                        break;
                default:
                        OWPError(ctx,OWPErrFATAL,OWPErrINVALID,
                        "_OWPDecodeV3TestRequest:Unsupported IP version (%d)",
                                                                        *ipvn);
                        return OWPErrFATAL;
        }

#ifdef  HAVE_STRUCT_SOCKADDR_SA_LEN
        sender->sa_len = receiver->sa_len = *socklen;
#endif

#
# Ok - a bunch of things happen between the allocation
# and the creation of the udp socket. (Policy checks and
# the like.) localaddr is a wrapper structure that encodes
# all the addr information that is needed to create the
# socket in a non-addr specific way. (almost an addrinfo
# structure.)
# Now this is the part where I actually use that sockaddr.
# localaddr->saddr is either sender or receiver from the
# initialization function depending upon the context of
# the actual request. (In the error case it is the sender,
# but that is only because that is the case I've been
# testing - there is no difference in the two cases until
# after the socket is bound.)
        /*
         * Create the socket.
         */
        ep->sockfd = socket(localaddr->saddr->sa_family,localaddr->so_type,
                                                localaddr->so_protocol);
        if(ep->sockfd<0){
                OWPError(ctx,OWPErrFATAL,OWPErrUNKNOWN,"socket(): %M");
                goto error;
        }

        /*
         * bind it to the local address getting an ephemeral port number.
         */
        if(bind(ep->sockfd,localaddr->saddr,localaddr->saddrlen) != 0){
                OWPError(ctx,OWPErrFATAL,OWPErrUNKNOWN,
                        "bind([%s]:%s): %M",localaddr->node,localaddr->port);
                goto error;
        }

#
# And this is an example of the error messages I have been seeing:
Nov 26 16:30:10 nms2-ipls owampd[87121]: FILE=endpoint.c, LINE=437, bind([2001:468:12:2:203:47ff:fef1:5071]:0): Can't assign requested address
Nov 26 16:30:12 nms2-ipls owampd[87134]: FILE=endpoint.c, LINE=437, bind([2001:468:12:2:203:47ff:fef1:5071]:0): Can't assign requested address
Nov 26 16:30:13 nms2-ipls owampd[87121]: FILE=endpoint.c, LINE=437, bind([2001:468:12:2:203:47ff:fef1:5071]:0): Can't assign requested address


Now, when this happens, it happens for about 10 seconds - and then things
start working again. So, how likely is it that not initializing sa_len
was causing this? (My ipv4 tests never had problems, and I would think
they would behave the same in this particular regard.)

(If anyone has actually read down this far, I truely thank you.)

Thanks,
jeff

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3DFBC9F9.9BEAA413>