diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/if_ether.h | 74 | ||||
-rw-r--r-- | sys/netinet/in.c | 206 | ||||
-rw-r--r-- | sys/netinet/in_var.h | 56 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.c | 10 |
4 files changed, 78 insertions, 268 deletions
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index c4f56c8..155cb3f 100644 --- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 - * $Id: if_ether.h,v 1.16 1996/12/11 17:46:33 wollman Exp $ + * $Id: if_ether.h,v 1.17 1997/01/03 19:51:54 wollman Exp $ */ #ifndef _NETINET_IF_ETHER_H_ @@ -40,7 +40,6 @@ #include <net/ethernet.h> #include <net/if_arp.h> -#ifdef KERNEL /* * Macro to map an IP multicast address to an Ethernet multicast address. * The high-order 25 bits of the Ethernet address are statically assigned, @@ -57,7 +56,6 @@ (enaddr)[4] = ((u_char *)ipaddr)[2]; \ (enaddr)[5] = ((u_char *)ipaddr)[3]; \ } -#endif /* * Ethernet Address Resolution Protocol. @@ -91,7 +89,6 @@ struct arpcom { */ struct ifnet ac_if; /* network-visible interface */ u_char ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */ - struct ether_multi *ac_multiaddrs; /* list of ether multicast addrs */ int ac_multicnt; /* length of ac_multiaddrs list */ }; @@ -120,75 +117,6 @@ extern struct ifqueue arpintrq; int arpresolve __P((struct arpcom *, struct rtentry *, struct mbuf *, struct sockaddr *, u_char *, struct rtentry *)); void arp_ifinit __P((struct arpcom *, struct ifaddr *)); -int ether_addmulti __P((struct ifreq *, struct arpcom *)); -int ether_delmulti __P((struct ifreq *, struct arpcom *)); - -/* - * Ethernet multicast address structure. There is one of these for each - * multicast address or range of multicast addresses that we are supposed - * to listen to on a particular interface. They are kept in a linked list, - * rooted in the interface's arpcom structure. (This really has nothing to - * do with ARP, or with the Internet address family, but this appears to be - * the minimally-disrupting place to put it.) - */ -struct ether_multi { - u_char enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */ - u_char enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */ - struct arpcom *enm_ac; /* back pointer to arpcom */ - u_int enm_refcount; /* no. claims to this addr/range */ - struct ether_multi *enm_next; /* ptr to next ether_multi */ -}; - -/* - * Structure used by macros below to remember position when stepping through - * all of the ether_multi records. - */ -struct ether_multistep { - struct ether_multi *e_enm; -}; - -/* - * Macro for looking up the ether_multi record for a given range of Ethernet - * multicast addresses connected to a given arpcom structure. If no matching - * record is found, "enm" returns NULL. - */ -#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \ - /* u_char addrlo[ETHER_ADDR_LEN]; */ \ - /* u_char addrhi[ETHER_ADDR_LEN]; */ \ - /* struct arpcom *ac; */ \ - /* struct ether_multi *enm; */ \ -{ \ - for ((enm) = (ac)->ac_multiaddrs; \ - (enm) != NULL && \ - (bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \ - bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \ - (enm) = (enm)->enm_next); \ -} - -/* - * Macro to step through all of the ether_multi records, one at a time. - * The current position is remembered in "step", which the caller must - * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step" - * and get the first record. Both macros return a NULL "enm" when there - * are no remaining records. - */ -#define ETHER_NEXT_MULTI(step, enm) \ - /* struct ether_multistep step; */ \ - /* struct ether_multi *enm; */ \ -{ \ - if (((enm) = (step).e_enm) != NULL) \ - (step).e_enm = (enm)->enm_next; \ -} - -#define ETHER_FIRST_MULTI(step, ac, enm) \ - /* struct ether_multistep step; */ \ - /* struct arpcom *ac; */ \ - /* struct ether_multi *enm; */ \ -{ \ - (step).e_enm = (ac)->ac_multiaddrs; \ - ETHER_NEXT_MULTI((step), (enm)); \ -} - #endif #endif diff --git a/sys/netinet/in.c b/sys/netinet/in.c index f200860..015783e 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in.c 8.4 (Berkeley) 1/9/95 - * $Id: in.c,v 1.26 1996/12/13 21:28:52 wollman Exp $ + * $Id: in.c,v 1.27 1996/12/15 22:44:00 wollman Exp $ */ #include <sys/param.h> @@ -55,18 +55,6 @@ #include <netinet/igmp_var.h> -/* - * This structure is used to keep track of in_multi chains which belong to - * deleted interface addresses. - */ -static LIST_HEAD(, multi_kludge) in_mk; /* XXX BSS initialization */ - -struct multi_kludge { - LIST_ENTRY(multi_kludge) mk_entry; - struct ifnet *mk_ifp; - struct in_multihead mk_head; -}; - static void in_socktrim __P((struct sockaddr_in *)); static int in_ifinit __P((struct ifnet *, struct in_ifaddr *, struct sockaddr_in *, int)); @@ -75,6 +63,9 @@ static void in_ifscrub __P((struct ifnet *, struct in_ifaddr *)); static int subnetsarelocal = 0; SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, &subnetsarelocal, 0, ""); + +struct in_multihead in_multihead; /* XXX BSS initialization */ + /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). If subnetsarelocal @@ -164,7 +155,6 @@ in_control(so, cmd, data, ifp) struct sockaddr_in oldaddr; int error, hostIsNew, maskIsNew, s; u_long i; - struct multi_kludge *mk; /* * Find address for this interface, if it exists. @@ -350,10 +340,6 @@ in_control(so, cmd, data, ifp) return (error); case SIOCDIFADDR: - mk = malloc(sizeof *mk, M_IPMADDR, M_WAITOK); - if (!mk) - return ENOBUFS; - in_ifscrub(ifp, ia); /* * Protect from ipintr() traversing address list @@ -365,51 +351,7 @@ in_control(so, cmd, data, ifp) TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); oia = ia; TAILQ_REMOVE(&in_ifaddrhead, oia, ia_link); - if (!oia->ia_multiaddrs.lh_first) { - IFAFREE(&oia->ia_ifa); - FREE(mk, M_IPMADDR); - splx(s); - break; - } - - /* - * 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 IP. - */ - IFP_TO_IA(oia->ia_ifp, ia); - if (ia) { /* there is another address */ - struct in_multi *inm; - for(inm = oia->ia_multiaddrs.lh_first; inm; - inm = inm->inm_entry.le_next) { - IFAFREE(&inm->inm_ia->ia_ifa); - ia->ia_ifa.ifa_refcnt++; - inm->inm_ia = ia; - LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, - inm_entry); - } - FREE(mk, M_IPMADDR); - } else { /* last address on this if deleted, save */ - struct in_multi *inm; - - LIST_INIT(&mk->mk_head); - mk->mk_ifp = ifp; - - for(inm = oia->ia_multiaddrs.lh_first; inm; - inm = inm->inm_entry.le_next) { - LIST_INSERT_HEAD(&mk->mk_head, inm, inm_entry); - } - - if (mk->mk_head.lh_first) { - LIST_INSERT_HEAD(&in_mk, mk, mk_entry); - } else { - FREE(mk, M_IPMADDR); - } - } - - IFAFREE((&oia->ia_ifa)); + IFAFREE(&oia->ia_ifa); splx(s); break; @@ -453,7 +395,6 @@ in_ifinit(ifp, ia, sin, scrub) register u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr_in oldaddr; int s = splimp(), flags = RTF_UP, error; - struct multi_kludge *mk; oldaddr = ia->ia_addr; ia->ia_addr = *sin; @@ -513,7 +454,6 @@ in_ifinit(ifp, ia, sin, scrub) if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) ia->ia_flags |= IFA_ROUTE; - LIST_INIT(&ia->ia_multiaddrs); /* * If the interface supports multicast, join the "all hosts" * multicast group on that interface. @@ -521,30 +461,6 @@ in_ifinit(ifp, ia, sin, scrub) if (ifp->if_flags & IFF_MULTICAST) { struct in_addr addr; - /* - * 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. - */ - for(mk = in_mk.lh_first; mk; mk = mk->mk_entry.le_next) { - if(mk->mk_ifp == ifp) { - struct in_multi *inm; - - for(inm = mk->mk_head.lh_first; inm; - inm = inm->inm_entry.le_next) { - IFAFREE(&inm->inm_ia->ia_ifa); - ia->ia_ifa.ifa_refcnt++; - inm->inm_ia = ia; - LIST_INSERT_HEAD(&ia->ia_multiaddrs, - inm, inm_entry); - } - LIST_REMOVE(mk, mk_entry); - free(mk, M_IPMADDR); - break; - } - } - addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); in_addmulti(&addr, ifp); } @@ -602,63 +518,52 @@ in_addmulti(ap, ifp) register struct ifnet *ifp; { register struct in_multi *inm; - struct ifreq ifr; - struct in_ifaddr *ia; + int error; + struct sockaddr_in sin; + struct ifmultiaddr *ifma; int s = splnet(); /* - * See if address already in list. + * Call generic routine to add membership or increment + * refcount. It wants addresses in the form of a sockaddr, + * so we build one here (being careful to zero the unused bytes). */ - IN_LOOKUP_MULTI(*ap, ifp, inm); - if (inm != NULL) { - /* - * Found it; just increment the reference count. - */ - ++inm->inm_refcount; + bzero(&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_len = sizeof sin; + sin.sin_addr = *ap; + error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma); + if (error) { + splx(s); + return 0; } - else { - /* - * New address; allocate a new multicast record - * and link it into the interface's multicast list. - */ - inm = (struct in_multi *)malloc(sizeof(*inm), - M_IPMADDR, M_NOWAIT); - if (inm == NULL) { - splx(s); - return (NULL); - } - inm->inm_addr = *ap; - inm->inm_ifp = ifp; - inm->inm_refcount = 1; - IFP_TO_IA(ifp, ia); - if (ia == NULL) { - free(inm, M_IPMADDR); - splx(s); - return (NULL); - } - inm->inm_ia = ia; - ia->ia_ifa.ifa_refcnt++; /* gain a reference */ - LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_entry); - /* - * Ask the network driver to update its multicast reception - * filter appropriately for the new address. - */ - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; - if ((ifp->if_ioctl == NULL) || - (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { - LIST_REMOVE(inm, inm_entry); - IFAFREE(&ia->ia_ifa); /* release reference */ - free(inm, M_IPMADDR); - splx(s); - return (NULL); - } - /* - * Let IGMP know that we have joined a new IP multicast group. - */ - igmp_joingroup(inm); + /* + * If ifma->ifma_protospec is null, then if_addmulti() created + * a new record. Otherwise, we are done. + */ + if (ifma->ifma_protospec != 0) + return ifma->ifma_protospec; + + /* XXX - if_addmulti uses M_WAITOK. Can this really be called + at interrupt time? If so, need to fix if_addmulti. XXX */ + inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT); + if (inm == NULL) { + splx(s); + return (NULL); } + + bzero(inm, sizeof *inm); + inm->inm_addr = *ap; + inm->inm_ifp = ifp; + inm->inm_ifma = ifma; + ifma->ifma_protospec = inm; + LIST_INSERT_HEAD(&in_multihead, inm, inm_link); + + /* + * Let IGMP know that we have joined a new IP multicast group. + */ + igmp_joingroup(inm); splx(s); return (inm); } @@ -670,31 +575,20 @@ void in_delmulti(inm) register struct in_multi *inm; { - struct ifreq ifr; + struct ifmultiaddr *ifma = inm->inm_ifma; int s = splnet(); - if (--inm->inm_refcount == 0) { + if (ifma->ifma_refcount == 1) { /* * No remaining claims to this record; let IGMP know that * we are leaving the multicast group. */ igmp_leavegroup(inm); - /* - * Unlink from list. - */ - LIST_REMOVE(inm, inm_entry); - IFAFREE(&inm->inm_ia->ia_ifa); /* release reference */ - - /* - * Notify the network driver to update its multicast reception - * filter. - */ - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = - inm->inm_addr; - (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, - (caddr_t)&ifr); + ifma->ifma_protospec = 0; + LIST_REMOVE(inm, inm_link); free(inm, M_IPMADDR); } + /* XXX - should be separate API for when we have an ifma? */ + if_delmulti(ifma->ifma_ifp, ifma->ifma_addr); splx(s); } diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 03aa446..af7e54c 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in_var.h 8.2 (Berkeley) 1/9/95 - * $Id: in_var.h,v 1.18 1996/12/13 21:28:54 wollman Exp $ + * $Id: in_var.h,v 1.19 1996/12/15 20:46:39 wollman Exp $ */ #ifndef _NETINET_IN_VAR_H_ @@ -41,7 +41,7 @@ /* * Interface address, Internet version. One of these structures - * is allocated for each interface with an Internet address. + * is allocated for each Internet address on an interface. * The ifaddr structure contains the protocol-independent part * of the structure and is assumed to be first. */ @@ -60,8 +60,6 @@ struct in_ifaddr { struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ - LIST_HEAD(in_multihead, in_multi) ia_multiaddrs; - /* list of multicast addresses */ }; struct in_aliasreq { @@ -146,49 +144,51 @@ struct router_info { /* * Internet multicast address structure. There is one of these for each IP * multicast group to which this host belongs on a given network interface. - * They are kept in a linked list, rooted in the interface's in_ifaddr - * structure. + * For every entry on the interface's if_multiaddrs list which represents + * an IP multicast group, there is one of these structures. They are also + * kept on a system-wide list to make it easier to keep our legacy IGMP code + * compatible with the rest of the world (see IN_FIRST_MULTI et al, below). */ struct in_multi { - LIST_ENTRY(in_multi) inm_entry; /* list glue */ - struct in_addr inm_addr; /* IP multicast address */ + LIST_ENTRY(in_multi) inm_link; /* queue macro glue */ + struct in_addr inm_addr; /* IP multicast address, convenience */ struct ifnet *inm_ifp; /* back pointer to ifnet */ - struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */ - u_int inm_refcount; /* no. membership claims by sockets */ + struct ifmultiaddr *inm_ifma; /* back pointer to ifmultiaddr */ u_int inm_timer; /* IGMP membership report timer */ u_int inm_state; /* state of the membership */ struct router_info *inm_rti; /* router info*/ }; #ifdef KERNEL +extern LIST_HEAD(in_multihead, in_multi) in_multihead; + /* * Structure used by macros below to remember position when stepping through * all of the in_multi records. */ struct in_multistep { - struct in_ifaddr *i_ia; struct in_multi *i_inm; }; /* * Macro for looking up the in_multi record for a given IP multicast address - * on a given interface. If no matching record is found, "inm" returns NULL. + * on a given interface. If no matching record is found, "inm" is set null. */ #define IN_LOOKUP_MULTI(addr, ifp, inm) \ /* struct in_addr addr; */ \ /* struct ifnet *ifp; */ \ /* struct in_multi *inm; */ \ do { \ - register struct in_ifaddr *ia; \ + register struct ifmultiaddr *ifma; \ \ - IFP_TO_IA((ifp), ia); \ - if (ia == NULL) \ - (inm) = NULL; \ - else \ - for ((inm) = ia->ia_multiaddrs.lh_first; \ - (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ - (inm) = inm->inm_entry.le_next) \ - continue; \ + for (ifma = (ifp)->if_multiaddrs.lh_first; ifma; \ + ifma = ifma->ifma_link.le_next) { \ + if (ifma->ifma_addr->sa_family == AF_INET \ + && ((struct sockaddr_in *)ifma)->sin_addr.s_addr == \ + (addr).s_addr) \ + break; \ + } \ + (inm) = ifma ? ifma->ifma_protospec : 0; \ } while(0) /* @@ -203,24 +203,14 @@ do { \ /* struct in_multi *inm; */ \ do { \ if (((inm) = (step).i_inm) != NULL) \ - (step).i_inm = (inm)->inm_entry.le_next; \ - else \ - while ((step).i_ia != NULL) { \ - (inm) = (step).i_ia->ia_multiaddrs.lh_first; \ - (step).i_ia = (step).i_ia->ia_link.tqe_next; \ - if ((inm) != NULL) { \ - (step).i_inm = (inm)->inm_entry.le_next; \ - break; \ - } \ - } \ + (step).i_inm = (step).i_inm->inm_link.le_next; \ } while(0) #define IN_FIRST_MULTI(step, inm) \ /* struct in_multistep step; */ \ /* struct in_multi *inm; */ \ do { \ - (step).i_ia = in_ifaddrhead.tqh_first; \ - (step).i_inm = NULL; \ + (step).i_inm = in_multihead.lh_first; \ IN_NEXT_MULTI((step), (inm)); \ } while(0) diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index bc5b3cc..44566ab 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -9,7 +9,7 @@ * Modified by Bill Fenner, PARC, April 1995 * * MROUTING Revision: 3.5 - * $Id: ip_mroute.c,v 1.34 1996/07/12 17:22:32 fenner Exp $ + * $Id: ip_mroute.c,v 1.35 1996/11/23 19:07:02 fenner Exp $ */ #include "opt_mrouting.h" @@ -576,7 +576,7 @@ X_ip_mrouter_done() ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; ifp = viftable[vifi].v_ifp; - (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); + if_allmulti(ifp, 0); } } bzero((caddr_t)tbftable, sizeof(tbftable)); @@ -728,10 +728,8 @@ add_vif(vifcp) return EOPNOTSUPP; /* Enable promiscuous reception of all IP multicasts from the if */ - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; - ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; s = splnet(); - error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); + if_allmulti(ifp, 1); splx(s); if (error) return error; @@ -800,7 +798,7 @@ del_vif(vifip) ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY; ifp = vifp->v_ifp; - (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); + if_allmulti(ifp, 0); } if (vifp == last_encap_vif) { |