- bcopy(&ia->ia_addr, &ifra.ifra_addr,
- ia->ia_addr.sin6_len);
- if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
- bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
- ia->ia_dstaddr.sin6_len);
- } else {
- bzero(&ifra.ifra_dstaddr,
- sizeof(ifra.ifra_dstaddr));
- }
- bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
- ia->ia_prefixmask.sin6_len);
-
- ifra.ifra_flags = ia->ia6_flags;
-#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) && !defined (__APPLE__)
- return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
- ifp, p);
-#else
- return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
- ifp);
-#endif
- }
- }
- }
-
- return EOPNOTSUPP; /*just for safety*/
-}
-
-/*
- * Delete any existing route for an interface.
- */
-void
-in6_ifscrub(ifp, ia)
- register struct ifnet *ifp;
- register struct in6_ifaddr *ia;
-{
- if ((ia->ia_flags & IFA_ROUTE) == 0)
- return;
- if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
- rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
- else
- rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
- ia->ia_flags &= ~IFA_ROUTE;
-
- /* Remove ownaddr's loopback rtentry, if it exists. */
- in6_ifremloop(&(ia->ia_ifa));
-}
-
-/*
- * Initialize an interface's intetnet6 address
- * and routing table entry.
- */
-int
-in6_ifinit(ifp, ia, sin6, scrub)
- struct ifnet *ifp;
- struct in6_ifaddr *ia;
- struct sockaddr_in6 *sin6;
- int scrub;
-{
- struct sockaddr_in6 oldaddr;
- int error, flags = RTF_UP;
- u_long dl_tag;
- int s = splimp();
-
- oldaddr = ia->ia_addr;
- ia->ia_addr = *sin6;
- /*
- * Give the interface a chance to initialize
- * if this is its first address,
- * and to validate the address if necessary.
- */
-#ifdef __APPLE__
- error = dlil_ioctl(0, ifp, SIOCSIFADDR, (caddr_t)ia) ;
- if (error == EOPNOTSUPP)
- error = 0;
- if (error) {
-
-#else
- if (ifp->if_ioctl &&
- (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
-#endif
- printf("in6_ifinit SIOCSIFADDR for if=%s returns error=%x\n", if_name(ifp), error);
- splx(s);
- ia->ia_addr = oldaddr;
- return(error);
- }
-
- switch (ifp->if_type) {
- case IFT_ARCNET:
- case IFT_ETHER:
- case IFT_FDDI:
- ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
- ia->ia_ifa.ifa_flags |= RTF_CLONING;
- break;
- case IFT_PPP:
- ia->ia_ifa.ifa_rtrequest = nd6_p2p_rtrequest;
- ia->ia_ifa.ifa_flags |= RTF_CLONING;
- break;
- }
-
- splx(s);
- if (scrub) {
- ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
- in6_ifscrub(ifp, ia);
- ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
- }
- /* xxx
- * in_socktrim
- */
- /*
- * Add route for the network.
- */
- ia->ia_ifa.ifa_metric = ifp->if_metric;
- if (ifp->if_flags & IFF_LOOPBACK) {
- ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
- flags |= RTF_HOST;
- } else if (ifp->if_flags & IFF_POINTOPOINT) {
- if (ia->ia_dstaddr.sin6_family != AF_INET6)
- return(0);
- flags |= RTF_HOST;
- }
- if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
- ia->ia_flags |= IFA_ROUTE;
-
- /* Add ownaddr as loopback rtentry, if necessary(ex. on p2p link). */
- in6_ifaddloop(&(ia->ia_ifa));
-
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
- if (ifp->if_flags & IFF_MULTICAST)
- in6_restoremkludge(ia, ifp);
-#endif
-
-#ifdef __APPLE__
- printf("in6_ifinit: Attach dl_tag for if=%s%n\n", ifp->if_name, ifp->if_unit);
-
- if (strcmp(ifp->if_name, "en") == 0)
- dl_tag = ether_attach_inet6(ifp);
-
- if (strcmp(ifp->if_name, "lo") == 0)
- dl_tag = lo_attach_inet(ifp);
-#if NGIF > 0
- if (strcmp(ifp->if_name, "gif") == 0)
- dl_tag = gif_attach_inet(ifp);
-#endif
-/* End of temp code */
- ia->ia_ifa.ifa_dlt = dl_tag;
-#endif
-
- return(error);
-}
-
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
-/*
- * Multicast address kludge:
- * If there were any multicast addresses attached to this interface address,
- * either move them to another address on this interface, or save them until
- * such time as this interface is reconfigured for IPv6.
- */
-void
-in6_savemkludge(oia)
- struct in6_ifaddr *oia;
-{
- struct in6_ifaddr *ia;
- struct in6_multi *in6m, *next;
-
- IFP_TO_IA6(oia->ia_ifp, ia);
- if (ia) { /* there is another address */
- for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
- next = in6m->in6m_entry.le_next;
- IFAFREE(&in6m->in6m_ia->ia_ifa);
- ia->ia_ifa.ifa_refcnt++;
- in6m->in6m_ia = ia;
- LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
- }
- } else { /* last address on this if deleted, save */
- struct multi6_kludge *mk;
-
- mk = _MALLOC(sizeof(*mk), M_IPMADDR, M_WAITOK);
-
- LIST_INIT(&mk->mk_head);
- mk->mk_ifp = oia->ia_ifp;
-
- for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
- next = in6m->in6m_entry.le_next;
- IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */
- in6m->in6m_ia = NULL;
- LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
- }
-
- if (mk->mk_head.lh_first != NULL) {
- LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
- } else {
- FREE(mk, M_IPMADDR);
- }
- }
-}
-
-/*
- * Continuation of multicast address hack:
- * If there was a multicast group list previously saved for this interface,
- * then we re-attach it to the first address configured on the i/f.
- */
-void
-in6_restoremkludge(ia, ifp)
- struct in6_ifaddr *ia;
- struct ifnet *ifp;
-{
- struct multi6_kludge *mk;
-
- for (mk = in6_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
- if (mk->mk_ifp == ifp) {
- struct in6_multi *in6m, *next;
-
- for (in6m = mk->mk_head.lh_first; in6m; in6m = next){
- next = in6m->in6m_entry.le_next;
- in6m->in6m_ia = ia;
- ia->ia_ifa.ifa_refcnt++;
- LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
- in6m, in6m_entry);