summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/mld6.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2004-03-04 15:07:42 +0000
committerume <ume@FreeBSD.org>2004-03-04 15:07:42 +0000
commit996df05b7818a9d71c34cee0968322c76d8a0ff2 (patch)
treee540107dbc3411b806495184a13a60b0c99c203d /sys/netinet6/mld6.c
parent425e7490f53525c7fe6e54be9a780267b77dfe90 (diff)
downloadFreeBSD-src-996df05b7818a9d71c34cee0968322c76d8a0ff2.zip
FreeBSD-src-996df05b7818a9d71c34cee0968322c76d8a0ff2.tar.gz
move in6_addmulti()/in6_delmulti() into mld6.c
Obtained from: KAME
Diffstat (limited to 'sys/netinet6/mld6.c')
-rw-r--r--sys/netinet6/mld6.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 3714ef7..8f8c326 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -78,6 +78,7 @@
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/syslog.h>
+#include <sys/malloc.h>
#include <net/if.h>
@@ -475,3 +476,95 @@ mld6_sendpkt(in6m, type, dst)
}
}
}
+
+/*
+ * Add an address to the list of IP6 multicast addresses for a given interface.
+ * Add source addresses to the list also, if upstream router is MLDv2 capable
+ * and the number of source is not 0.
+ */
+struct in6_multi *
+in6_addmulti(maddr6, ifp, errorp)
+ struct in6_addr *maddr6;
+ struct ifnet *ifp;
+ int *errorp;
+{
+ struct in6_multi *in6m;
+ struct ifmultiaddr *ifma;
+ struct sockaddr_in6 sa6;
+ int s = splnet();
+
+ *errorp = 0;
+
+ /*
+ * 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).
+ */
+ bzero(&sa6, sizeof(sa6));
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_len = sizeof(struct sockaddr_in6);
+ sa6.sin6_addr = *maddr6;
+ *errorp = if_addmulti(ifp, (struct sockaddr *)&sa6, &ifma);
+ if (*errorp) {
+ splx(s);
+ return 0;
+ }
+
+ /*
+ * If ifma->ifma_protospec is null, then if_addmulti() created
+ * a new record. Otherwise, we are done.
+ */
+ if (ifma->ifma_protospec != 0) {
+ splx(s);
+ 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 */
+ in6m = (struct in6_multi *)malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
+ if (in6m == NULL) {
+ splx(s);
+ return (NULL);
+ }
+
+ bzero(in6m, sizeof *in6m);
+ in6m->in6m_addr = *maddr6;
+ in6m->in6m_ifp = ifp;
+ in6m->in6m_refcount = 1;
+ in6m->in6m_ifma = ifma;
+ ifma->ifma_protospec = in6m;
+ LIST_INSERT_HEAD(&in6_multihead, in6m, in6m_entry);
+
+ /*
+ * Let MLD6 know that we have joined a new IPv6 multicast
+ * group.
+ */
+ mld6_start_listening(in6m);
+ splx(s);
+ return (in6m);
+}
+
+/*
+ * Delete a multicast address record.
+ */
+void
+in6_delmulti(in6m)
+ struct in6_multi *in6m;
+{
+ struct ifmultiaddr *ifma = in6m->in6m_ifma;
+ int s = splnet();
+
+ if (ifma->ifma_refcount == 1) {
+ /*
+ * No remaining claims to this record; let MLD6 know
+ * that we are leaving the multicast group.
+ */
+ mld6_stop_listening(in6m);
+ ifma->ifma_protospec = 0;
+ LIST_REMOVE(in6m, in6m_entry);
+ free(in6m, M_IPMADDR);
+ }
+ /* XXX - should be separate API for when we have an ifma? */
+ if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
+ splx(s);
+}
OpenPOWER on IntegriCloud