Hi, Whilst rolling out our new FreeRADIUS infrastructure I stumbled on a Linux bug where for IPv6 clients the reply source IP address from the server does not necessary match the request's destination address; as a result the client ignores the reply packet. I use OSPF to anycast our RADIUS servers and so have to bind to '::', the box as a result is obviously multi-homed too. I am guessing this is why I am seeing the bug whilst most other (in)?sane sysadmin's bind to the EUI64 address and so do not see this problem. Turns out 'struct in6_pktinfo' is a GNU extension[1] and so you need to define _GNU_SOURCE when ./configure is running otherwise you get HAVE_IN6_PKTINFO is undefined. I just gave it a whirl, config.cache shows 'yes' now for the presence of ipi6_pktinfo: ---- ac56@domokun:/usr/src/deb-src/freeradius/freeradius-2.1.10+dfsg$ grep pktinfo config.cache ac_cv_type_struct_in6_pktinfo_has_ipi6_addr=${ac_cv_type_struct_in6_pktinfo_has_ipi6_addr=yes} ac_cv_type_struct_in_pktinfo_has_ipi_addr=${ac_cv_type_struct_in_pktinfo_has_ipi_addr=yes} ---- Until I forced _GNU_SOURCE into CFLAGS I was seeing '${ac_cv_type_struct_in6_pktinfo_has_ipi6_addr=}', note the lack of a 'yes' on the end there, which would explain why things were not behaving. Once this was enabled, I noticed that someone thinks IPv6 addresses are integers, so I have provided a patch to fix that. I noticed someone has disabled udpfromto.c being used for IPv6 sockets altogether...this is also fixed in the patch :) I would provide a patch for the autoconf bit but I have no idea how to persuade autoconf to do what I want...from what I have heard I do not want to either :) Anyway, with the following, my IPv6 client support works once again, although someone with Clue(tm) probably should look over it to make sure all is well with it :) Cheers [1] http://linux.derkeiler.com/Mailing-Lists/Fedora/2009-02/msg00318.html --- freeradius-2.1.10+dfsg.orig/src/lib/udpfromto.c 2010-09-28 11:03:56.000000000 +0000 +++ freeradius-2.1.10+dfsg/src/lib/udpfromto.c 2010-12-13 19:12:40.000000000 +0000 @@ -87,7 +87,7 @@ * This should actually be standard IPv6 */ proto = IPPROTO_IPV6; - flag = IPV6_PKTINFO; + flag = IPV6_RECVPKTINFO; #endif #endif } else { @@ -172,7 +172,7 @@ return -1; } *tolen = sizeof(*dst); - *dst = *src; + memcpy(dst, src, sizeof(*dst)); #if !defined(HAVE_IN6_PKTINFO) /* @@ -240,7 +240,7 @@ (cmsg->cmsg_type == IPV6_PKTINFO)) { struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg); - ((struct sockaddr_in6 *)to)->sin6_addr = i->ipi6_addr; + memcpy(&((struct sockaddr_in6 *) to)->sin6_addr, &i->ipi6_addr, sizeof(struct in6_addr)); *tolen = sizeof(struct sockaddr_in6); break; } @@ -335,7 +335,7 @@ pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg); memset(pkt, 0, sizeof(*pkt)); - pkt->ipi6_addr = s6->sin6_addr; + memcpy(&pkt->ipi6_addr, &s6->sin6_addr, sizeof(struct in6_addr)); #endif } #endif --- freeradius-2.1.10+dfsg.orig/src/lib/radius.c 2010-09-28 11:03:56.000000000 +0000 +++ freeradius-2.1.10+dfsg/src/lib/radius.c 2010-12-13 19:11:34.000000000 +0000 @@ -228,13 +228,11 @@ #ifdef WITH_UDPFROMTO /* - * Only IPv4 is supported for udpfromto. - * * And if they don't specify a source IP address, don't * use udpfromto. */ - if ((dst_ipaddr->af == AF_INET) && - (src_ipaddr->af != AF_UNSPEC)) { + if ((dst_ipaddr->af == AF_INET || dst_ipaddr->af == AF_INET6) + && (src_ipaddr->af != AF_UNSPEC)) { return sendfromto(sockfd, data, data_len, flags, (struct sockaddr *)&src, sizeof_src, (struct sockaddr *)&dst, sizeof_dst); @@ -244,7 +242,7 @@ #endif /* - * No udpfromto, OR an IPv6 socket, fail gracefully. + * No udpfromto so fail gracefully. */ return sendto(sockfd, data, data_len, flags, (struct sockaddr *) &dst, sizeof_dst); @@ -415,14 +413,14 @@ * packet after "len" bytes. */ #ifdef WITH_UDPFROMTO - if (dst.ss_family == AF_INET) { + if (dst.ss_family == AF_INET || dst.ss_family == AF_INET6) { data_len = recvfromto(sockfd, buf, len, flags, (struct sockaddr *)&src, &sizeof_src, (struct sockaddr *)&dst, &sizeof_dst); } else #endif /* - * No udpfromto, OR an IPv6 socket. Fail gracefully. + * No udpfromto so fail gracefully. */ data_len = recvfrom(sockfd, buf, len, flags, (struct sockaddr *)&src, &sizeof_src);