Index: net/if.c =================================================================== RCS file: /home/naklab/tanimura/rina2/CVS/FreeBSD/sys/net/if.c,v retrieving revision 1.1.1.4.6.3 diff -u -r1.1.1.4.6.3 if.c --- net/if.c 2000/07/23 03:27:44 1.1.1.4.6.3 +++ net/if.c 2000/08/16 02:08:59 @@ -87,6 +87,8 @@ int ifqmaxlen = IFQ_MAXLEN; struct ifnethead ifnet; /* depend on static init XXX */ +struct ifmultihead ifmultiaddrs; + #ifdef INET6 /* * XXX: declare here to avoid to include many inet6 related files.. @@ -116,6 +118,7 @@ ifp->if_name, ifp->if_unit); ifp->if_snd.ifq_maxlen = ifqmaxlen; } + LIST_INIT(&ifmultiaddrs); splx(s); if_slowtimo(0); } @@ -1235,6 +1238,7 @@ */ s = splimp(); LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); + LIST_INSERT_HEAD(&ifmultiaddrs, ifma, ifma_linkg); splx(s); *retifma = ifma; @@ -1257,6 +1261,7 @@ ifma->ifma_refcount = 1; s = splimp(); LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); + LIST_INSERT_HEAD(&ifmultiaddrs, ifma, ifma_linkg); splx(s); } } @@ -1281,12 +1286,21 @@ struct sockaddr *sa; { struct ifmultiaddr *ifma; - int s; + int s, ifactive; - for (ifma = ifp->if_multiaddrs.lh_first; ifma; - ifma = ifma->ifma_link.le_next) - if (equal(sa, ifma->ifma_addr)) - break; + ifactive = if_isactive(ifp); + if (ifactive) { + for (ifma = ifp->if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) + if (equal(sa, ifma->ifma_addr)) + break; + } else { + for (ifma = ifmultiaddrs.lh_first; ifma; + ifma = ifma->ifma_linkg.le_next) + if (ifma->ifma_ifp == ifp && equal(sa, ifma->ifma_addr)) + break; + } + if (ifma == 0) return ENOENT; @@ -1299,6 +1313,7 @@ sa = ifma->ifma_lladdr; s = splimp(); LIST_REMOVE(ifma, ifma_link); + LIST_REMOVE(ifma, ifma_linkg); splx(s); free(ifma->ifma_addr, M_IFMADDR); free(ifma, M_IFMADDR); @@ -1316,10 +1331,17 @@ * in the record for the link-layer address. (So we don't complain * in that case.) */ - for (ifma = ifp->if_multiaddrs.lh_first; ifma; - ifma = ifma->ifma_link.le_next) - if (equal(sa, ifma->ifma_addr)) - break; + if (ifactive) { + for (ifma = ifp->if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) + if (equal(sa, ifma->ifma_addr)) + break; + } else { + for (ifma = ifmultiaddrs.lh_first; ifma; + ifma = ifma->ifma_linkg.le_next) + if (ifma->ifma_ifp == ifp && equal(sa, ifma->ifma_addr)) + break; + } if (ifma == 0) return 0; @@ -1330,7 +1352,9 @@ s = splimp(); LIST_REMOVE(ifma, ifma_link); - ifp->if_ioctl(ifp, SIOCDELMULTI, 0); + LIST_REMOVE(ifma, ifma_linkg); + if (ifactive) + ifp->if_ioctl(ifp, SIOCDELMULTI, 0); splx(s); free(ifma->ifma_addr, M_IFMADDR); free(sa, M_IFMADDR); @@ -1352,6 +1376,26 @@ break; return ifma; +} + +/* Confirm if an interface exists in the list of the active interfaces. */ +int +if_isactive(ifp) + struct ifnet *ifp; +{ + struct ifnet *myifp; + + myifp = TAILQ_FIRST(&ifnet); + while (myifp != NULL) { + if (myifp == ifp) + break; + myifp = TAILQ_NEXT(myifp, if_link); + } + + if (myifp != NULL) + return 1; + else + return 0; } SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); Index: net/if_var.h =================================================================== RCS file: /home/naklab/tanimura/rina2/CVS/FreeBSD/sys/net/if_var.h,v retrieving revision 1.1.1.4.6.3 diff -u -r1.1.1.4.6.3 if_var.h --- net/if_var.h 2000/07/16 04:05:04 1.1.1.4.6.3 +++ net/if_var.h 2000/08/16 02:09:00 @@ -300,6 +300,7 @@ */ struct ifmultiaddr { LIST_ENTRY(ifmultiaddr) ifma_link; /* queue macro glue */ + LIST_ENTRY(ifmultiaddr) ifma_linkg; /* queue macro glue */ struct sockaddr *ifma_addr; /* address this membership is for */ struct sockaddr *ifma_lladdr; /* link-layer translation, if any */ struct ifnet *ifma_ifp; /* back-pointer to interface */ @@ -339,6 +340,7 @@ int if_delmulti __P((struct ifnet *, struct sockaddr *)); void if_detach __P((struct ifnet *)); void if_down __P((struct ifnet *)); +int if_isactive __P((struct ifnet *)); void if_route __P((struct ifnet *, int flag, int fam)); void if_unroute __P((struct ifnet *, int flag, int fam)); void if_up __P((struct ifnet *)); Index: netinet/ip_output.c =================================================================== RCS file: /home/naklab/tanimura/rina2/CVS/FreeBSD/sys/netinet/ip_output.c,v retrieving revision 1.1.1.4.6.4 diff -u -r1.1.1.4.6.4 ip_output.c --- netinet/ip_output.c 2000/08/11 10:44:32 1.1.1.4.6.4 +++ netinet/ip_output.c 2000/08/16 02:09:01 @@ -323,6 +323,11 @@ } } + /* Make sure that we have the interface to send out this packet. */ + if (!if_isactive(ifp)) { + error = ENXIO; + goto bad; + } IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm); if (inm != NULL && (imo == NULL || imo->imo_multicast_loop)) {