summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/if_ether.h74
-rw-r--r--sys/netinet/in.c206
-rw-r--r--sys/netinet/in_var.h56
-rw-r--r--sys/netinet/ip_mroute.c10
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) {
OpenPOWER on IntegriCloud