On 12/21/15 11:36, Martin Pieuchot wrote:
> Currently if you try to configure the same IPv6 address twice via the
> SIOCAIFADDR_IN6 ioctl(2) the kernel will return EEXIST and the address
> will be unset:
>
> # ifconfig vether0 inet6 2001::1
> # ifconfig vether0 inet6 2001::1
> ifconfig: SIOCAIFADDR: File exists
>
> Diff below fixes that by not inserting the local route if we're "just"
> updating an existing address. sebastia@ confirmed it fixes his use
> case, so I'm looking for oks.
>
> Index: netinet6/in6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/in6.c,v
> retrieving revision 1.181
> diff -u -p -r1.181 in6.c
> --- netinet6/in6.c 3 Dec 2015 13:13:42 -0000 1.181
> +++ netinet6/in6.c 18 Dec 2015 09:27:18 -0000
[...]
> @@ -454,12 +454,15 @@ in6_control(struct socket *so, u_long cm
> return (EINVAL);
> }
>
> + if (ia6 == NULL)
> + newifaddr = 1;
> +
> /*
> * Make the address tentative before joining multicast
> * addresses, so that corresponding MLD responses would
> * not have a tentative source address.
> */
> - if ((ia6 == NULL) && in6if_do_dad(ifp))
> + if (newifaddr && in6if_do_dad(ifp))
> ifra->ifra_flags |= IN6_IFF_TENTATIVE;
>
> /*
[...]
> @@ -489,6 +493,9 @@ in6_control(struct socket *so, u_long cm
> /* Perform DAD, if needed. */
> if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
> nd6_dad_start(&ia6->ia_ifa);
> +
> + if (!newifaddr)
> + break;
>
> plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
> if ((ifp->if_flags & IFF_LOOPBACK) || plen == 128) {
>
The "if (!newaddr)" should be moved above the "if (IN6_IFF_TENTATIVE)" ;
this way the skipping of DAD when !newaddr is more explicit.