in6_len2mask(&mask, prefixlen);
in6_prefixlen2mask(&mask, prefixlen);
in6_ifadd(ifp, in6, addr, prefixlen)	struct ifnet *ifp;	struct in6_addr *in6;	struct in6_addr *addr;	int prefixlen;	/* prefix len of the new prefix in "in6" */{	struct ifaddr *ifa;	struct in6_ifaddr *ia, *ib, *oia;	int s, error;	struct in6_addr mask;	in6_len2mask(&mask, prefixlen);	/* find link-local address (will be interface ID) */	ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);/* 0 is OK? */	if (ifa)		ib = (struct in6_ifaddr *)ifa;	else		return NULL;#if 0 /* don't care link local addr state, and always do DAD */	/* if link-local address is not eligible, do not autoconfigure. */	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {		printf("in6_ifadd: link-local address not ready\n");		return NULL;	}#endif	/* prefixlen + ifidlen must be equal to 128 */	if (prefixlen != in6_mask2len(&ib->ia_prefixmask.sin6_addr)) {		nd6log((LOG_ERR, "in6_ifadd: wrong prefixlen for %s"			"(prefix=%d ifid=%d)\n", ifp->if_xname,			prefixlen,			128 - in6_mask2len(&ib->ia_prefixmask.sin6_addr)));		return NULL;	}	/* make ifaddr */	ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_DONTWAIT);	if (ia == NULL) {		printf("ENOBUFS in in6_ifadd %d\n", __LINE__);		return NULL;	}	bzero((caddr_t)ia, sizeof(*ia));	ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;	if (ifp->if_flags & IFF_POINTOPOINT)		ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;	else		ia->ia_ifa.ifa_dstaddr = NULL;	ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;	ia->ia_ifp = ifp;	/* link to in6_ifaddr */	if ((oia = in6_ifaddr) != NULL) {		for( ; oia->ia_next; oia = oia->ia_next)			continue;		oia->ia_next = ia;	} else {		/*		 * This should be impossible, since we have at least one		 * link-local address (see the beginning of this function).		 * XXX: should we rather panic here?		 */		printf("in6_ifadd: in6_ifaddr is NULL (impossible!)\n");		in6_ifaddr = ia;	}	/* gain a refcnt for the link from in6_ifaddr */	ia->ia_ifa.ifa_refcnt++;	/* link to if_addrlist */	TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);	/* gain another refcnt for the link from if_addrlist */	ia->ia_ifa.ifa_refcnt++;	/* new address */	ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);	ia->ia_addr.sin6_family = AF_INET6;	/* prefix */	bcopy(in6, &ia->ia_addr.sin6_addr, sizeof(ia->ia_addr.sin6_addr));	ia->ia_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];	ia->ia_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];	ia->ia_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];	ia->ia_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];	/* interface ID */	ia->ia_addr.sin6_addr.s6_addr32[0]		|= (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);	ia->ia_addr.sin6_addr.s6_addr32[1]		|= (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);	ia->ia_addr.sin6_addr.s6_addr32[2]		|= (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);	ia->ia_addr.sin6_addr.s6_addr32[3]		|= (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);	/* new prefix */	ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);	ia->ia_prefixmask.sin6_family = AF_INET6;	bcopy(&mask, &ia->ia_prefixmask.sin6_addr,		sizeof(ia->ia_prefixmask.sin6_addr));	/* same routine */	ia->ia_ifa.ifa_rtrequest =		(ifp->if_type == IFT_PPP) ? nd6_p2p_rtrequest : nd6_rtrequest;	ia->ia_ifa.ifa_flags |= RTF_CLONING;	ia->ia_ifa.ifa_metric = ifp->if_metric;	/* add interface route */	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP|RTF_CLONING))) {		nd6log((LOG_NOTICE,		    "in6_ifadd: failed to add an interface route "		    "for %s/%d on %s, errno = %d\n",		    ip6_sprintf(&ia->ia_addr.sin6_addr), prefixlen,		    ifp->if_xname, error));	}	else		ia->ia_flags |= IFA_ROUTE;	*addr = ia->ia_addr.sin6_addr;	if (ifp->if_flags & IFF_MULTICAST) {		int error;	/* not used */		struct in6_addr sol6;		/* Restore saved multicast addresses(if any). */		in6_restoremkludge(ia, ifp);		/* join solicited node multicast address */		bzero(&sol6, sizeof(sol6));		sol6.s6_addr16[0] = htons(0xff02);		sol6.s6_addr16[1] = htons(ifp->if_index);		sol6.s6_addr32[1] = 0;		sol6.s6_addr32[2] = htonl(1);		sol6.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];		sol6.s6_addr8[12] = 0xff;		(void)in6_addmulti(&sol6, ifp, &error);	}	ia->ia6_flags |= IN6_IFF_TENTATIVE;	/*	 * To make the interface up. Only AF_INET6 in ia is used...	 */	s = splimp();	if (ifp->if_ioctl && (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) {		splx(s);		return NULL;	}	splx(s);	/* Perform DAD, if needed. */	nd6_dad_start((struct ifaddr *)ia, NULL);	return ia;}