Re: splnet() and SIOCSIFADDR
On Thu, Sep 11, 2014 at 10:49:33AM +0200, Martin Pieuchot wrote: --- netinet6/in6.c26 Aug 2014 21:44:29 - 1.140 +++ netinet6/in6.c11 Sep 2014 08:45:29 - @@ -561,8 +560,10 @@ in6_control(struct socket *so, u_long cm } case SIOCDIFADDR_IN6: + s = splsoftnet(); in6_purgeaddr(ia6-ia_ifa); dohooks(ifp-if_addrhooks, 0); + splx(s); break; default: In IPv4 all dohooks(if_addrhooks) are protected by a large splsoftnet(). A few lines above in SIOCAIFADDR_IN6 this is not the case. The hook carp_addr_updated() looks like it would need an splsoftnet() as it is looping over if_addrlist. But this is not part of this diff. OK bluhm@
Re: splnet() and SIOCSIFADDR
On 11/09/14(Thu) 10:49, Martin Pieuchot wrote: On 03/09/14(Wed) 20:59, Alexander Bluhm wrote: On Wed, Sep 03, 2014 at 03:53:34PM +0200, Martin Pieuchot wrote: @@ -1078,7 +1079,7 @@ in6_purgeaddr(struct ifaddr *ifa) void in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp) { - int s = splnet(); + splsoftassert(IPL_SOFTNET); ifa_del(ifp, ia6-ia_ifa); I think there are code paths that can trigger this assertion netinet6/in6.c: in6_unlink_ifa() netinet6/in6.c: in6_purgeaddr() netinet6/nd6_rtr.c: purge_detached() netinet6/nd6_rtr.c: nd6_prelist_add() netinet6/in6.c: in6_control() netinet/tcp_usrreq.c: tcp_usrreq() kern/sys_socket.c: soo_ioctl() netinet6/in6.c: in6_unlink_ifa() netinet6/in6.c: in6_purgeaddr() netinet6/nd6_rtr.c: purge_detached() netinet6/nd6_rtr.c: nd6_prelist_add() netinet6/in6_ifattach.c:in6_ifattach_linklocal() netinet/ip_carp.c carp_set_enaddr() netinet/ip_carp.c carp_ioctl() ... nd6_prelist_add() does some splsoftnet() already. I think you should put one around purge_detached() there. Nice catch, updated diff below. Any comment or ok? Index: net/if_loop.c === RCS file: /home/ncvs/src/sys/net/if_loop.c,v retrieving revision 1.57 diff -u -p -r1.57 if_loop.c --- net/if_loop.c 22 Jul 2014 11:06:09 - 1.57 +++ net/if_loop.c 11 Sep 2014 08:45:29 - @@ -288,15 +288,13 @@ loioctl(struct ifnet *ifp, u_long cmd, c { struct ifaddr *ifa; struct ifreq *ifr; - int s, error = 0; + int error = 0; switch (cmd) { case SIOCSIFADDR: - s = splnet(); ifp-if_flags |= IFF_RUNNING; if_up(ifp); /* send up RTM_IFINFO */ - splx(s); ifa = (struct ifaddr *)data; if (ifa != 0) Index: netinet/in.c === RCS file: /home/ncvs/src/sys/netinet/in.c,v retrieving revision 1.103 diff -u -p -r1.103 in.c --- netinet/in.c 3 Sep 2014 08:59:06 - 1.103 +++ netinet/in.c 11 Sep 2014 08:45:29 - @@ -612,7 +612,7 @@ in_ifinit(struct ifnet *ifp, struct in_i { u_int32_t i = sin-sin_addr.s_addr; struct sockaddr_in oldaddr; - int s, error = 0; + int error = 0; splsoftassert(IPL_SOFTNET); @@ -627,7 +627,6 @@ in_ifinit(struct ifnet *ifp, struct in_i rt_ifa_delloop(ia-ia_ifa); ifa_del(ifp, ia-ia_ifa); } - s = splnet(); oldaddr = ia-ia_addr; ia-ia_addr = *sin; @@ -639,10 +638,8 @@ in_ifinit(struct ifnet *ifp, struct in_i if (ifp-if_ioctl (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ia-ia_addr = oldaddr; - splx(s); goto out; } - splx(s); if (ia-ia_netmask == 0) { if (IN_CLASSA(i)) Index: netinet/ip_carp.c === RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.234 diff -u -p -r1.234 ip_carp.c --- netinet/ip_carp.c 8 Sep 2014 06:24:13 - 1.234 +++ netinet/ip_carp.c 11 Sep 2014 08:45:29 - @@ -2059,10 +2059,11 @@ carp_ioctl(struct ifnet *ifp, u_long cmd struct ifaddr *ifa = (struct ifaddr *)addr; struct ifreq *ifr = (struct ifreq *)addr; struct ifnet *cdev = NULL; - int i, error = 0; + int s, i, error = 0; switch (cmd) { case SIOCSIFADDR: + s = splnet(); switch (ifa-ifa_addr-sa_family) { #ifdef INET case AF_INET: @@ -2087,6 +2088,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd break; } break; + splx(s); case SIOCSIFFLAGS: vhe = LIST_FIRST(sc-carp_vhosts); Index: netinet6/in6.c === RCS file: /home/ncvs/src/sys/netinet6/in6.c,v retrieving revision 1.140 diff -u -p -r1.140 in6.c --- netinet6/in6.c26 Aug 2014 21:44:29 - 1.140 +++ netinet6/in6.c11 Sep 2014 08:45:29 - @@ -172,7 +172,7 @@ in6_control(struct socket *so, u_long cm struct in6_ifaddr *ia6 = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr_in6 *sa6; - int privileged; + int s, privileged; privileged = 0; if ((so-so_state SS_PRIV) != 0) @@ -463,7 +463,6 @@ in6_control(struct socket *so, u_long cm { int i, error = 0; struct nd_prefix pr0, *pr; - int s; /* reject
Re: splnet() and SIOCSIFADDR
On 03/09/14(Wed) 20:59, Alexander Bluhm wrote: On Wed, Sep 03, 2014 at 03:53:34PM +0200, Martin Pieuchot wrote: @@ -1078,7 +1079,7 @@ in6_purgeaddr(struct ifaddr *ifa) void in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp) { - int s = splnet(); + splsoftassert(IPL_SOFTNET); ifa_del(ifp, ia6-ia_ifa); I think there are code paths that can trigger this assertion netinet6/in6.c: in6_unlink_ifa() netinet6/in6.c: in6_purgeaddr() netinet6/nd6_rtr.c: purge_detached() netinet6/nd6_rtr.c: nd6_prelist_add() netinet6/in6.c: in6_control() netinet/tcp_usrreq.c: tcp_usrreq() kern/sys_socket.c:soo_ioctl() netinet6/in6.c: in6_unlink_ifa() netinet6/in6.c: in6_purgeaddr() netinet6/nd6_rtr.c: purge_detached() netinet6/nd6_rtr.c: nd6_prelist_add() netinet6/in6_ifattach.c: in6_ifattach_linklocal() netinet/ip_carp.c carp_set_enaddr() netinet/ip_carp.c carp_ioctl() ... nd6_prelist_add() does some splsoftnet() already. I think you should put one around purge_detached() there. Nice catch, updated diff below. Index: net/if_loop.c === RCS file: /home/ncvs/src/sys/net/if_loop.c,v retrieving revision 1.57 diff -u -p -r1.57 if_loop.c --- net/if_loop.c 22 Jul 2014 11:06:09 - 1.57 +++ net/if_loop.c 11 Sep 2014 08:45:29 - @@ -288,15 +288,13 @@ loioctl(struct ifnet *ifp, u_long cmd, c { struct ifaddr *ifa; struct ifreq *ifr; - int s, error = 0; + int error = 0; switch (cmd) { case SIOCSIFADDR: - s = splnet(); ifp-if_flags |= IFF_RUNNING; if_up(ifp); /* send up RTM_IFINFO */ - splx(s); ifa = (struct ifaddr *)data; if (ifa != 0) Index: netinet/in.c === RCS file: /home/ncvs/src/sys/netinet/in.c,v retrieving revision 1.103 diff -u -p -r1.103 in.c --- netinet/in.c3 Sep 2014 08:59:06 - 1.103 +++ netinet/in.c11 Sep 2014 08:45:29 - @@ -612,7 +612,7 @@ in_ifinit(struct ifnet *ifp, struct in_i { u_int32_t i = sin-sin_addr.s_addr; struct sockaddr_in oldaddr; - int s, error = 0; + int error = 0; splsoftassert(IPL_SOFTNET); @@ -627,7 +627,6 @@ in_ifinit(struct ifnet *ifp, struct in_i rt_ifa_delloop(ia-ia_ifa); ifa_del(ifp, ia-ia_ifa); } - s = splnet(); oldaddr = ia-ia_addr; ia-ia_addr = *sin; @@ -639,10 +638,8 @@ in_ifinit(struct ifnet *ifp, struct in_i if (ifp-if_ioctl (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ia-ia_addr = oldaddr; - splx(s); goto out; } - splx(s); if (ia-ia_netmask == 0) { if (IN_CLASSA(i)) Index: netinet/ip_carp.c === RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.234 diff -u -p -r1.234 ip_carp.c --- netinet/ip_carp.c 8 Sep 2014 06:24:13 - 1.234 +++ netinet/ip_carp.c 11 Sep 2014 08:45:29 - @@ -2059,10 +2059,11 @@ carp_ioctl(struct ifnet *ifp, u_long cmd struct ifaddr *ifa = (struct ifaddr *)addr; struct ifreq *ifr = (struct ifreq *)addr; struct ifnet *cdev = NULL; - int i, error = 0; + int s, i, error = 0; switch (cmd) { case SIOCSIFADDR: + s = splnet(); switch (ifa-ifa_addr-sa_family) { #ifdef INET case AF_INET: @@ -2087,6 +2088,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd break; } break; + splx(s); case SIOCSIFFLAGS: vhe = LIST_FIRST(sc-carp_vhosts); Index: netinet6/in6.c === RCS file: /home/ncvs/src/sys/netinet6/in6.c,v retrieving revision 1.140 diff -u -p -r1.140 in6.c --- netinet6/in6.c 26 Aug 2014 21:44:29 - 1.140 +++ netinet6/in6.c 11 Sep 2014 08:45:29 - @@ -172,7 +172,7 @@ in6_control(struct socket *so, u_long cm struct in6_ifaddr *ia6 = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr_in6 *sa6; - int privileged; + int s, privileged; privileged = 0; if ((so-so_state SS_PRIV) != 0) @@ -463,7 +463,6 @@ in6_control(struct socket *so, u_long cm { int i, error = 0; struct nd_prefix pr0, *pr; - int s; /* reject read-only flags */ if ((ifra-ifra_flags
Re: splnet() and SIOCSIFADDR
On 03/09/14(Wed) 23:59, Claudio Jeker wrote: On Wed, Sep 03, 2014 at 03:25:34PM +0200, Martin Pieuchot wrote: Drivers that need a splnet() protection inside their SIOCSIFADDR generally raise the spl level themselves, so we should not need to do that in in{6,}_ifinit(). One exception to this rule is, as always, carp(4)... So the diff below moves the spl dance inside carp's SIOCSIFADDR handler, it's a baby step, so we can take care of carp_set_addr{6,} later. Hmm. My gut feeling is that this is scary. Calling ifp functions at non-splnet is always a cause for troubles (e.g. the watchdog callbacks miss often the needed splnet calls). I think the ioctl code pathes in the various places may suffer from similar problems with missing splnet() calls. Guess a bit of an audit is needed in that area. And the audit revealed that only lo(4) has an unneeded splnet() call. Something else I wonder is if splsoftnet() is good enough when dealing with ifp in general (aren't we detaching interfaces at splnet())? Removable interfaces opened for sure a bucket sized can of worms. I believe it is, or at least it should be. splnet() should only be necessary inside drivers to protect the code that might interfere with configuring the hardware or messing with the rings. The rational is quite simple: packets are processed in softnet, so the pieces of code modifying the global lists and tables should make sure code run at softnet cannot be executed in parallel. The fact that some of the operations are still done under splnet(), like detatching interfaces, seems related to history. I'm trying to carefully remove the unneeded splnet()s. One of the biggest problem was the routing table update triggered by a link state change that *was* executed during a IPL_NET interrupt. But that's no longer the case.
Re: splnet() and SIOCSIFADDR
On 03/09/14(Wed) 15:25, Martin Pieuchot wrote: Drivers that need a splnet() protection inside their SIOCSIFADDR generally raise the spl level themselves, so we should not need to do that in in{6,}_ifinit(). One exception to this rule is, as always, carp(4)... So the diff below moves the spl dance inside carp's SIOCSIFADDR handler, it's a baby step, so we can take care of carp_set_addr{6,} later. mikeb@ pointed out that a spl dance was missing from the SIOCDIFADDR_IN6 ioctl, updated diff below also fixes that. Index: netinet/in.c === RCS file: /home/ncvs/src/sys/netinet/in.c,v retrieving revision 1.103 diff -u -p -r1.103 in.c --- netinet/in.c3 Sep 2014 08:59:06 - 1.103 +++ netinet/in.c3 Sep 2014 13:52:41 - @@ -612,7 +612,7 @@ in_ifinit(struct ifnet *ifp, struct in_i { u_int32_t i = sin-sin_addr.s_addr; struct sockaddr_in oldaddr; - int s, error = 0; + int error = 0; splsoftassert(IPL_SOFTNET); @@ -627,7 +627,6 @@ in_ifinit(struct ifnet *ifp, struct in_i rt_ifa_delloop(ia-ia_ifa); ifa_del(ifp, ia-ia_ifa); } - s = splnet(); oldaddr = ia-ia_addr; ia-ia_addr = *sin; @@ -639,10 +638,8 @@ in_ifinit(struct ifnet *ifp, struct in_i if (ifp-if_ioctl (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ia-ia_addr = oldaddr; - splx(s); goto out; } - splx(s); if (ia-ia_netmask == 0) { if (IN_CLASSA(i)) Index: netinet/ip_carp.c === RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.233 diff -u -p -r1.233 ip_carp.c --- netinet/ip_carp.c 22 Jul 2014 11:06:10 - 1.233 +++ netinet/ip_carp.c 3 Sep 2014 13:52:41 - @@ -2060,10 +2060,11 @@ carp_ioctl(struct ifnet *ifp, u_long cmd struct ifaddr *ifa = (struct ifaddr *)addr; struct ifreq *ifr = (struct ifreq *)addr; struct ifnet *cdev = NULL; - int i, error = 0; + int s, i, error = 0; switch (cmd) { case SIOCSIFADDR: + s = splnet(); switch (ifa-ifa_addr-sa_family) { #ifdef INET case AF_INET: @@ -2088,6 +2089,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd break; } break; + splx(s); case SIOCSIFFLAGS: vhe = LIST_FIRST(sc-carp_vhosts); Index: netinet6/in6.c === RCS file: /home/ncvs/src/sys/netinet6/in6.c,v retrieving revision 1.140 diff -u -p -r1.140 in6.c --- netinet6/in6.c 26 Aug 2014 21:44:29 - 1.140 +++ netinet6/in6.c 3 Sep 2014 13:52:41 - @@ -172,7 +172,7 @@ in6_control(struct socket *so, u_long cm struct in6_ifaddr *ia6 = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; struct sockaddr_in6 *sa6; - int privileged; + int s, privileged; privileged = 0; if ((so-so_state SS_PRIV) != 0) @@ -463,7 +463,6 @@ in6_control(struct socket *so, u_long cm { int i, error = 0; struct nd_prefix pr0, *pr; - int s; /* reject read-only flags */ if ((ifra-ifra_flags IN6_IFF_DUPLICATED) != 0 || @@ -561,8 +560,10 @@ in6_control(struct socket *so, u_long cm } case SIOCDIFADDR_IN6: + s = splsoftnet(); in6_purgeaddr(ia6-ia_ifa); dohooks(ifp-if_addrhooks, 0); + splx(s); break; default: @@ -1078,7 +1079,7 @@ in6_purgeaddr(struct ifaddr *ifa) void in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp) { - int s = splnet(); + splsoftassert(IPL_SOFTNET); ifa_del(ifp, ia6-ia_ifa); @@ -1107,8 +1108,6 @@ in6_unlink_ifa(struct in6_ifaddr *ia6, s * Note that we should decrement the refcnt at least once for all *BSD. */ ifafree(ia6-ia_ifa); - - splx(s); } /* @@ -1355,9 +1354,10 @@ int in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost) { int error = 0, plen, ifacount = 0; - int s = splnet(); struct ifaddr *ifa; + splsoftassert(IPL_SOFTNET); + /* * Give the interface a chance to initialize * if this is its first address (or it is a CARP interface) @@ -1374,10 +1374,8 @@ in6_ifinit(struct ifnet *ifp, struct in6 if ((ifacount = 1 || ifp-if_type == IFT_CARP || (ifp-if_flags IFF_POINTOPOINT)) ifp-if_ioctl (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) { - splx(s); return (error); } - splx(s); ia6-ia_ifa.ifa_metric =
Re: splnet() and SIOCSIFADDR
On 3 September 2014 15:53, Martin Pieuchot mpieuc...@nolizard.org wrote: On 03/09/14(Wed) 15:25, Martin Pieuchot wrote: Drivers that need a splnet() protection inside their SIOCSIFADDR generally raise the spl level themselves, so we should not need to do that in in{6,}_ifinit(). One exception to this rule is, as always, carp(4)... So the diff below moves the spl dance inside carp's SIOCSIFADDR handler, it's a baby step, so we can take care of carp_set_addr{6,} later. mikeb@ pointed out that a spl dance was missing from the SIOCDIFADDR_IN6 ioctl, updated diff below also fixes that. i think we're ready to step on a carefully placed landmine. OK mikeb
Re: splnet() and SIOCSIFADDR
On Wed, Sep 03, 2014 at 03:53:34PM +0200, Martin Pieuchot wrote: @@ -1078,7 +1079,7 @@ in6_purgeaddr(struct ifaddr *ifa) void in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp) { - int s = splnet(); + splsoftassert(IPL_SOFTNET); ifa_del(ifp, ia6-ia_ifa); I think there are code paths that can trigger this assertion netinet6/in6.c: in6_unlink_ifa() netinet6/in6.c: in6_purgeaddr() netinet6/nd6_rtr.c: purge_detached() netinet6/nd6_rtr.c: nd6_prelist_add() netinet6/in6.c: in6_control() netinet/tcp_usrreq.c: tcp_usrreq() kern/sys_socket.c: soo_ioctl() netinet6/in6.c: in6_unlink_ifa() netinet6/in6.c: in6_purgeaddr() netinet6/nd6_rtr.c: purge_detached() netinet6/nd6_rtr.c: nd6_prelist_add() netinet6/in6_ifattach.c:in6_ifattach_linklocal() netinet/ip_carp.c carp_set_enaddr() netinet/ip_carp.c carp_ioctl() ... nd6_prelist_add() does some splsoftnet() already. I think you should put one around purge_detached() there. bluhm
Re: splnet() and SIOCSIFADDR
On Wed, Sep 03, 2014 at 03:25:34PM +0200, Martin Pieuchot wrote: Drivers that need a splnet() protection inside their SIOCSIFADDR generally raise the spl level themselves, so we should not need to do that in in{6,}_ifinit(). One exception to this rule is, as always, carp(4)... So the diff below moves the spl dance inside carp's SIOCSIFADDR handler, it's a baby step, so we can take care of carp_set_addr{6,} later. Hmm. My gut feeling is that this is scary. Calling ifp functions at non-splnet is always a cause for troubles (e.g. the watchdog callbacks miss often the needed splnet calls). I think the ioctl code pathes in the various places may suffer from similar problems with missing splnet() calls. Guess a bit of an audit is needed in that area. Something else I wonder is if splsoftnet() is good enough when dealing with ifp in general (aren't we detaching interfaces at splnet())? Removable interfaces opened for sure a bucket sized can of worms. ok? Index: netinet/in.c === RCS file: /home/ncvs/src/sys/netinet/in.c,v retrieving revision 1.103 diff -u -p -r1.103 in.c --- netinet/in.c 3 Sep 2014 08:59:06 - 1.103 +++ netinet/in.c 3 Sep 2014 13:08:43 - @@ -612,7 +612,7 @@ in_ifinit(struct ifnet *ifp, struct in_i { u_int32_t i = sin-sin_addr.s_addr; struct sockaddr_in oldaddr; - int s, error = 0; + int error = 0; splsoftassert(IPL_SOFTNET); @@ -627,7 +627,6 @@ in_ifinit(struct ifnet *ifp, struct in_i rt_ifa_delloop(ia-ia_ifa); ifa_del(ifp, ia-ia_ifa); } - s = splnet(); oldaddr = ia-ia_addr; ia-ia_addr = *sin; @@ -639,10 +638,8 @@ in_ifinit(struct ifnet *ifp, struct in_i if (ifp-if_ioctl (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ia-ia_addr = oldaddr; - splx(s); goto out; } - splx(s); if (ia-ia_netmask == 0) { if (IN_CLASSA(i)) Index: netinet/ip_carp.c === RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.233 diff -u -p -r1.233 ip_carp.c --- netinet/ip_carp.c 22 Jul 2014 11:06:10 - 1.233 +++ netinet/ip_carp.c 3 Sep 2014 13:08:43 - @@ -2060,10 +2060,11 @@ carp_ioctl(struct ifnet *ifp, u_long cmd struct ifaddr *ifa = (struct ifaddr *)addr; struct ifreq *ifr = (struct ifreq *)addr; struct ifnet *cdev = NULL; - int i, error = 0; + int s, i, error = 0; switch (cmd) { case SIOCSIFADDR: + s = splnet(); switch (ifa-ifa_addr-sa_family) { #ifdef INET case AF_INET: @@ -2088,6 +2089,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd break; } break; + splx(s); case SIOCSIFFLAGS: vhe = LIST_FIRST(sc-carp_vhosts); Index: netinet6/in6.c === RCS file: /home/ncvs/src/sys/netinet6/in6.c,v retrieving revision 1.140 diff -u -p -r1.140 in6.c --- netinet6/in6.c26 Aug 2014 21:44:29 - 1.140 +++ netinet6/in6.c3 Sep 2014 13:08:43 - @@ -1078,7 +1078,7 @@ in6_purgeaddr(struct ifaddr *ifa) void in6_unlink_ifa(struct in6_ifaddr *ia6, struct ifnet *ifp) { - int s = splnet(); + splsoftassert(IPL_SOFTNET); ifa_del(ifp, ia6-ia_ifa); @@ -1107,8 +1107,6 @@ in6_unlink_ifa(struct in6_ifaddr *ia6, s * Note that we should decrement the refcnt at least once for all *BSD. */ ifafree(ia6-ia_ifa); - - splx(s); } /* @@ -1355,9 +1353,10 @@ int in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost) { int error = 0, plen, ifacount = 0; - int s = splnet(); struct ifaddr *ifa; + splsoftassert(IPL_SOFTNET); + /* * Give the interface a chance to initialize * if this is its first address (or it is a CARP interface) @@ -1374,10 +1373,8 @@ in6_ifinit(struct ifnet *ifp, struct in6 if ((ifacount = 1 || ifp-if_type == IFT_CARP || (ifp-if_flags IFF_POINTOPOINT)) ifp-if_ioctl (error = (*ifp-if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) { - splx(s); return (error); } - splx(s); ia6-ia_ifa.ifa_metric = ifp-if_metric; -- :wq Claudio