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>
