Subject: SIOCALIFADDR + IPv6 = surprise
To: None <tech-net@netbsd.org>
From: David Young <dyoung@pobox.com>
List: tech-net
Date: 09/20/2006 20:12:17
--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Last night I was trying to add addresses to a point-to-point IPv6
interface with SIOCALIFADDR, and I was astonished when the ioctl returned
0, indicating success, but no addresses had been added!  I consider this
a serious bug.

Reading the code, it looks like the call path is this,

ifioctl(,SIOCALIFADDR,) ->
in6_control(,SIOCALIFADDR,) ->
in6_lifaddr_ioctl(,SIOCALIFADDR,) ->
in6_control(,SIOCAIFADDR_IN6,) ->
in6_update_ifa()

in6_lifaddr_ioctl converts its if_laddrreq argument into an in6_aliasreq,
however, it does not initialize the ifra_lifetime members ia6t_vltime
and ia6t_pltime.  It calls in6_control(,SIOCAIFADDR_IN6,) to add an
IPv6 address with 0 lifetime; in6_control() obliges by adding *no*
address at all.

Seems to me that in6_lifaddr_ioctl ought to initialize
both the ifra_lifetime members ia6t_vltime and ia6t_pltime to
ND6_INFINITE_LIFETIME.  I am testing a patch that does just that, and
now the point-to-point addresses "take".  I'm going to check my patch
in the next day or two, if nobody squeals.

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933

--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="in6_lifaddr_ioctl.patch"

Index: sys/netinet6/in6.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6.c,v
retrieving revision 1.110
diff -p -u -u -p -r1.110 in6.c
--- sys/netinet6/in6.c	25 Aug 2006 18:29:17 -0000	1.110
+++ sys/netinet6/in6.c	21 Sep 2006 01:11:14 -0000
@@ -1559,7 +1556,8 @@ in6_lifaddr_ioctl(so, cmd, data, ifp, l)
 
 		ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
 		in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
-
+		ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+		ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 		ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
 		return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, l);
 	    }

--WIyZ46R2i8wDzkSu--