summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c31
-rw-r--r--sys/net/if.h15
-rw-r--r--sys/net/if_ethersubr.c184
-rw-r--r--sys/net/route.h8
-rw-r--r--sys/net/rtsock.c41
5 files changed, 86 insertions, 193 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index b382d48..29e7aca 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -576,12 +576,24 @@ ifioctl(so, cmd, data, p)
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- if (ifp->if_ioctl == NULL)
- return (EOPNOTSUPP);
- error = (*ifp->if_ioctl)(ifp, cmd, data);
- if (error == 0 )
- microtime(&ifp->if_lastchange);
- return(error);
+
+ /* Don't allow group membership on non-multicast interfaces. */
+ if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ return EOPNOTSUPP;
+
+ /* Don't let users screw up protocols' entries. */
+ if (ifr->ifr_addr.sa_family != AF_LINK)
+ return EINVAL;
+
+ if (cmd == SIOCADDMULTI) {
+ struct ifmultiaddr *ifma;
+ error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
+ } else {
+ error = if_delmulti(ifp, &ifr->ifr_addr);
+ }
+ if (error == 0)
+ microtime(&ifp->if_lastchange);
+ return error;
default:
if (so->so_proto == 0)
@@ -835,6 +847,7 @@ if_addmulti(ifp, sa, retifma)
ifma->ifma_ifp = ifp;
ifma->ifma_refcount = 1;
ifma->ifma_protospec = 0;
+ rt_newmaddrmsg(RTM_NEWMADDR, ifma);
/*
* Some network interfaces can scan the address list at
@@ -856,7 +869,10 @@ if_addmulti(ifp, sa, retifma)
} else {
MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
M_IFMADDR, M_WAITOK);
- ifma->ifma_addr = llsa;
+ MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
+ M_IFMADDR, M_WAITOK);
+ bcopy(llsa, dupsa, llsa->sa_len);
+ ifma->ifma_addr = dupsa;
ifma->ifma_ifp = ifp;
ifma->ifma_refcount = 1;
}
@@ -899,6 +915,7 @@ if_delmulti(ifp, sa)
return 0;
}
+ rt_newmaddrmsg(RTM_DELMADDR, ifma);
sa = ifma->ifma_lladdr;
s = splimp();
LIST_REMOVE(ifma, ifma_link);
diff --git a/sys/net/if.h b/sys/net/if.h
index 86e4384..4160868 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)if.h 8.1 (Berkeley) 6/10/93
- * $Id: if.h,v 1.41 1996/12/13 21:28:37 wollman Exp $
+ * $Id: if.h,v 1.42 1997/01/03 19:50:25 wollman Exp $
*/
#ifndef _NET_IF_H_
@@ -124,6 +124,19 @@ struct ifa_msghdr {
};
/*
+ * Message format for use in obtaining information about multicast addresses
+ * from the routing socket
+ */
+struct ifma_msghdr {
+ u_short ifmam_msglen; /* to skip over non-understood messages */
+ u_char ifmam_version; /* future binary compatability */
+ u_char ifmam_type; /* message type */
+ int ifmam_addrs; /* like rtm_addrs */
+ int ifmam_flags; /* value of ifa_flags */
+ u_short ifmam_index; /* index for associated ifp */
+};
+
+/*
* Interface request structure used for socket
* ioctl's. All interface ioctl's must have parameter
* definitions which begin with ifr_name. The
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 38d4911..2dcfde4 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
- * $Id: if_ethersubr.c,v 1.29 1996/12/13 21:28:38 wollman Exp $
+ * $Id: if_ethersubr.c,v 1.30 1997/01/07 19:15:30 wollman Exp $
*/
#include <sys/param.h>
@@ -667,188 +667,6 @@ ether_ifattach(ifp)
bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
}
-static u_char ether_ipmulticast_min[6] =
- { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
-static u_char ether_ipmulticast_max[6] =
- { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
-/*
- * Add an Ethernet multicast address or range of addresses to the list for a
- * given interface.
- */
-int
-ether_addmulti(ifr, ac)
- struct ifreq *ifr;
- register struct arpcom *ac;
-{
- register struct ether_multi *enm;
- struct sockaddr_in *sin;
- u_char addrlo[6];
- u_char addrhi[6];
- int set_allmulti = 0;
- int s = splimp();
-
- switch (ifr->ifr_addr.sa_family) {
-
- case AF_UNSPEC:
- bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
- bcopy(addrlo, addrhi, 6);
- break;
-
-#ifdef INET
- case AF_INET:
- sin = (struct sockaddr_in *)&(ifr->ifr_addr);
- if (sin->sin_addr.s_addr == INADDR_ANY) {
- /*
- * An IP address of INADDR_ANY means listen to all
- * of the Ethernet multicast addresses used for IP.
- * (This is for the sake of IP multicast routers.)
- */
- bcopy(ether_ipmulticast_min, addrlo, 6);
- bcopy(ether_ipmulticast_max, addrhi, 6);
- set_allmulti = 1;
- }
- else {
- ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
- bcopy(addrlo, addrhi, 6);
- }
- break;
-#endif
-
- default:
- splx(s);
- return (EAFNOSUPPORT);
- }
-
- /*
- * Verify that we have valid Ethernet multicast addresses.
- */
- if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
- splx(s);
- return (EINVAL);
- }
- /*
- * See if the address range is already in the list.
- */
- ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
- if (enm != NULL) {
- /*
- * Found it; just increment the reference count.
- */
- ++enm->enm_refcount;
- splx(s);
- return (0);
- }
- /*
- * New address or range; malloc a new multicast record
- * and link it into the interface's multicast list.
- */
- enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
- if (enm == NULL) {
- splx(s);
- return (ENOBUFS);
- }
- bcopy(addrlo, enm->enm_addrlo, 6);
- bcopy(addrhi, enm->enm_addrhi, 6);
- enm->enm_ac = ac;
- enm->enm_refcount = 1;
- enm->enm_next = ac->ac_multiaddrs;
- ac->ac_multiaddrs = enm;
- ac->ac_multicnt++;
- splx(s);
- if (set_allmulti)
- ac->ac_if.if_flags |= IFF_ALLMULTI;
-
- /*
- * Return ENETRESET to inform the driver that the list has changed
- * and its reception filter should be adjusted accordingly.
- */
- return (ENETRESET);
-}
-
-/*
- * Delete a multicast address record.
- */
-int
-ether_delmulti(ifr, ac)
- struct ifreq *ifr;
- register struct arpcom *ac;
-{
- register struct ether_multi *enm;
- register struct ether_multi **p;
- struct sockaddr_in *sin;
- u_char addrlo[6];
- u_char addrhi[6];
- int unset_allmulti = 0;
- int s = splimp();
-
- switch (ifr->ifr_addr.sa_family) {
-
- case AF_UNSPEC:
- bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
- bcopy(addrlo, addrhi, 6);
- break;
-
-#ifdef INET
- case AF_INET:
- sin = (struct sockaddr_in *)&(ifr->ifr_addr);
- if (sin->sin_addr.s_addr == INADDR_ANY) {
- /*
- * An IP address of INADDR_ANY means stop listening
- * to the range of Ethernet multicast addresses used
- * for IP.
- */
- bcopy(ether_ipmulticast_min, addrlo, 6);
- bcopy(ether_ipmulticast_max, addrhi, 6);
- unset_allmulti = 1;
- }
- else {
- ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
- bcopy(addrlo, addrhi, 6);
- }
- break;
-#endif
-
- default:
- splx(s);
- return (EAFNOSUPPORT);
- }
-
- /*
- * Look up the address in our list.
- */
- ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
- if (enm == NULL) {
- splx(s);
- return (ENXIO);
- }
- if (--enm->enm_refcount != 0) {
- /*
- * Still some claims to this record.
- */
- splx(s);
- return (0);
- }
- /*
- * No remaining claims to this record; unlink and free it.
- */
- for (p = &enm->enm_ac->ac_multiaddrs;
- *p != enm;
- p = &(*p)->enm_next)
- continue;
- *p = (*p)->enm_next;
- free(enm, M_IFMADDR);
- ac->ac_multicnt--;
- splx(s);
- if (unset_allmulti)
- ac->ac_if.if_flags &= ~IFF_ALLMULTI;
-
- /*
- * Return ENETRESET to inform the driver that the list has changed
- * and its reception filter should be adjusted accordingly.
- */
- return (ENETRESET);
-}
-
SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
int
diff --git a/sys/net/route.h b/sys/net/route.h
index 0b518df..31fbcae 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)route.h 8.3 (Berkeley) 4/19/94
- * $Id: route.h,v 1.22 1996/08/26 22:04:47 julian Exp $
+ * $Id: route.h,v 1.23 1996/10/09 18:35:10 wollman Exp $
*/
#ifndef _NET_ROUTE_H_
@@ -203,6 +203,8 @@ struct rt_msghdr {
#define RTM_NEWADDR 0xc /* address being added to iface */
#define RTM_DELADDR 0xd /* address being removed from iface */
#define RTM_IFINFO 0xe /* iface going up/down etc. */
+#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
+#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
#define RTV_MTU 0x1 /* init or lock _mtu */
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
@@ -262,10 +264,14 @@ extern struct route_cb route_cb;
extern struct rtstat rtstat;
extern struct radix_node_head *rt_tables[AF_MAX+1];
+/* forward declaration for rt_newmaddrmsg() */
+struct ifmultiaddr;
+
void route_init __P((void));
void rt_ifmsg __P((struct ifnet *));
void rt_missmsg __P((int, struct rt_addrinfo *, int, int));
void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *));
+void rt_newmaddrmsg __P((int, struct ifmultiaddr *));
int rt_setgate __P((struct rtentry *,
struct sockaddr *, struct sockaddr *));
void rtalloc __P((struct route *));
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index eb786fa..e831d67 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)rtsock.c 8.5 (Berkeley) 11/2/94
- * $Id: rtsock.c,v 1.21 1996/12/11 20:38:16 wollman Exp $
+ * $Id: rtsock.c,v 1.22 1996/12/13 21:28:41 wollman Exp $
*/
#include <sys/param.h>
@@ -416,6 +416,11 @@ rt_msg1(type, rtinfo)
len = sizeof(struct ifa_msghdr);
break;
+ case RTM_DELMADDR:
+ case RTM_NEWMADDR:
+ len = sizeof(struct ifma_msghdr);
+ break;
+
case RTM_IFINFO:
len = sizeof(struct if_msghdr);
break;
@@ -637,6 +642,40 @@ rt_newaddrmsg(cmd, ifa, error, rt)
}
}
+/*
+ * This is the analogue to the rt_newaddrmsg which performs the same
+ * function but for multicast group memberhips. This is easier since
+ * there is no route state to worry about.
+ */
+void
+rt_newmaddrmsg(cmd, ifma)
+ int cmd;
+ struct ifmultiaddr *ifma;
+{
+ struct rt_addrinfo info;
+ struct mbuf *m = 0;
+ struct ifnet *ifp = ifma->ifma_ifp;
+ struct ifma_msghdr *ifmam;
+
+ if (route_cb.any_count == 0)
+ return;
+
+ bzero((caddr_t)&info, sizeof(info));
+ ifaaddr = ifma->ifma_addr;
+ ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
+ /*
+ * If a link-layer address is present, present it as a ``gateway''
+ * (similarly to how ARP entries, e.g., are presented).
+ */
+ gate = ifma->ifma_lladdr;
+ if ((m = rt_msg1(cmd, &info)) == NULL)
+ return;
+ ifmam = mtod(m, struct ifma_msghdr *);
+ ifmam->ifmam_index = ifp->if_index;
+ ifmam->ifmam_addrs = info.rti_addrs;
+ route_proto.sp_protocol = ifma->ifma_addr->sa_family;
+ raw_input(m, &route_proto, &route_src, &route_dst);
+}
/*
* This is used in dumping the kernel table via sysctl().
OpenPOWER on IntegriCloud