-/* $KAME: ip6_mroute.c,v 1.15 2000/02/22 14:04:21 itojun Exp $ */
+/*
+ * Copyright (c) 2003-2011 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+/* $FreeBSD: src/sys/netinet6/ip6_mroute.c,v 1.16.2.1 2002/12/18 21:39:40 suz Exp $ */
+/* $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+/*
+ * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
+ * support for mandatory and extensible security protections. This notice
+ * is included in support of clause 2.2 (b) of the Apple Public License,
+ * Version 2.0.
+ */
/* BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp */
* MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
*/
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
-#include "opt_inet.h"
-#endif
-
-#ifndef _KERNEL
-# ifdef KERNEL
-# define _KERNEL
-# endif
-#endif
#include <sys/param.h>
#include <sys/systm.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
#include <sys/malloc.h>
-#endif
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
-#include <sys/ioctl.h>
-#endif
#include <sys/syslog.h>
+#include <kern/locks.h>
#include <net/if.h>
#include <net/route.h>
#include <net/raw_cb.h>
+#include <net/dlil.h>
+#include <net/net_osdep.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/scope6_var.h>
#include <netinet6/ip6_mroute.h>
+#include <netinet/icmp6.h>
#include <netinet6/pim6.h>
#include <netinet6/pim6_var.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#if CONFIG_MACF_NET
+#include <security/mac.h>
+#endif /* MAC_NET */
+
+#ifndef __APPLE__
static MALLOC_DEFINE(M_MRTABLE, "mf6c", "multicast forwarding cache entry");
#endif
#define M_HASCL(m) ((m)->m_flags & M_EXT)
-static int ip6_mdq __P((struct mbuf *, struct ifnet *, struct mf6c *));
-static void phyint_send __P((struct ip6_hdr *, struct mif6 *, struct mbuf *));
+static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
+static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
-static int set_pim6 __P((int *));
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
-static int get_pim6 __P((struct mbuf *));
-#endif
-static int socket_send __P((struct socket *, struct mbuf *,
- struct sockaddr_in6 *));
-static int register_send __P((struct ip6_hdr *, struct mif6 *,
- struct mbuf *));
+static int set_pim6(int *);
+static int socket_send(struct socket *, struct mbuf *,
+ struct sockaddr_in6 *);
+static int register_send(struct ip6_hdr *, struct mif6 *,
+ struct mbuf *);
/*
* Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static,
* except for netstat or debugging purposes.
*/
struct socket *ip6_mrouter = NULL;
+int ip6_mrouter_ver = 0;
int ip6_mrtproto = IPPROTO_PIM; /* for netstat only */
+
+#if MROUTING
+
struct mrt6stat mrt6stat;
#define NO_RTE_FOUND 0x1
#define RTE_FOUND 0x2
struct mf6c *mf6ctable[MF6CTBLSIZ];
-u_char nexpire[MF6CTBLSIZ];
+u_char n6expire[MF6CTBLSIZ];
static struct mif6 mif6table[MAXMIFS];
#if MRT6DEBUG
u_int mrt6debug = 0; /* debug level */
#define DEBUG_PIM 0x40
#endif
-static void expire_upcalls __P((void *));
+static void expire_upcalls(void *);
+
#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
#define UPCALL_EXPIRE 6 /* number of timeouts */
#endif
#endif
-static u_long lo_dl_tag = 0;
/*
* 'Interfaces' associated with decapsulator (so we can tell
* packets that went through it from ones that get reflected
static mifi_t reg_mif_num = (mifi_t)-1;
static struct pim6stat pim6stat;
-
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-static struct callout_handle expire_upcalls_ch;
-#endif
-
-/*
- * one-back cache used by ipip_input to locate a tunnel's mif
- * given a datagram's src ip address.
- */
static int pim6;
/*
* Quality of service parameter to be added in the future!!!
*/
-#define MF6CFIND(o, g, rt) { \
- register struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
+#define MF6CFIND(o, g, rt) do { \
+ struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
rt = NULL; \
mrt6stat.mrt6s_mfc_lookups++; \
while (_rt) { \
if (rt == NULL) { \
mrt6stat.mrt6s_mfc_misses++; \
} \
-}
+} while (0)
/*
* Macros to compute elapsed time efficiently
* Borrowed from Van Jacobson's scheduling code
*/
-#define TV_DELTA(a, b, delta) { \
- register int xxs; \
+#define TV_DELTA(a, b, delta) do { \
+ int xxs; \
\
delta = (a).tv_usec - (b).tv_usec; \
if ((xxs = (a).tv_sec - (b).tv_sec)) { \
delta += (1000000 * xxs); \
} \
} \
-}
+} while (0)
#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
(a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
#if UPCALL_TIMING
#define UPCALL_MAX 50
-u_long upcall_data[UPCALL_MAX + 1];
+u_int32_t upcall_data[UPCALL_MAX + 1];
static void collate();
#endif /* UPCALL_TIMING */
-static int get_sg_cnt __P((struct sioc_sg_req6 *));
-static int get_mif6_cnt __P((struct sioc_mif_req6 *));
-static int ip6_mrouter_init __P((struct socket *, struct mbuf *));
-static int add_m6if __P((struct mif6ctl *));
-static int del_m6if __P((mifi_t *));
-static int add_m6fc __P((struct mf6cctl *));
-static int del_m6fc __P((struct mf6cctl *));
+static int get_sg_cnt(struct sioc_sg_req6 *);
+static int get_mif6_cnt(void *, int);
+static int ip6_mrouter_init(struct socket *, int, int);
+static int add_m6if(struct mif6ctl *);
+static int del_m6if(mifi_t *);
+static int add_m6fc(struct mf6cctl *);
+static int del_m6fc(struct mf6cctl *);
/*
* Handle MRT setsockopt commands to modify the multicast routing tables.
*/
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
int
ip6_mrouter_set(so, sopt)
struct socket *so;
struct sockopt *sopt;
{
- int error = 0;
- struct mbuf *m;
+ int error = 0;
+ int optval;
+ struct mif6ctl mifc;
+ struct mf6cctl mfcc;
+ mifi_t mifi;
if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT)
return (EACCES);
- if (error = sooptgetm(sopt, &m)) /* XXX */
- return (error);
- if (error = sooptmcopyin(sopt, m)) /* XXX */
- return (error);
-
switch (sopt->sopt_name) {
- case MRT6_INIT:
- error = ip6_mrouter_init(so, m);
- break;
- case MRT6_DONE:
- error = ip6_mrouter_done();
- break;
- case MRT6_ADD_MIF:
- error = add_m6if(mtod(m, struct mif6ctl *));
- break;
- case MRT6_DEL_MIF:
- error = del_m6if(mtod(m, mifi_t *));
- break;
- case MRT6_ADD_MFC:
- error = add_m6fc(mtod(m, struct mf6cctl *));
- break;
- case MRT6_DEL_MFC:
- error = del_m6fc(mtod(m, struct mf6cctl *));
- break;
- case MRT6_PIM:
- error = set_pim6(mtod(m, int *));
- break;
- default:
- error = EOPNOTSUPP;
- break;
+ case MRT6_INIT:
+#if MRT6_OINIT
+ case MRT6_OINIT:
+#endif
+ error = sooptcopyin(sopt, &optval, sizeof(optval),
+ sizeof(optval));
+ if (error)
+ break;
+ error = ip6_mrouter_init(so, optval, sopt->sopt_name);
+ break;
+ case MRT6_DONE:
+ error = ip6_mrouter_done();
+ break;
+ case MRT6_ADD_MIF:
+ error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc));
+ if (error)
+ break;
+ error = add_m6if(&mifc);
+ break;
+ case MRT6_ADD_MFC:
+ error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
+ if (error)
+ break;
+ error = add_m6fc(&mfcc);
+ break;
+ case MRT6_DEL_MFC:
+ error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
+ if (error)
+ break;
+ error = del_m6fc(&mfcc);
+ break;
+ case MRT6_DEL_MIF:
+ error = sooptcopyin(sopt, &mifi, sizeof(mifi), sizeof(mifi));
+ if (error)
+ break;
+ error = del_m6if(&mifi);
+ break;
+ case MRT6_PIM:
+ error = sooptcopyin(sopt, &optval, sizeof(optval),
+ sizeof(optval));
+ if (error)
+ break;
+ error = set_pim6(&optval);
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
}
- (void)m_freem(m);
- return(error);
-}
-#else
-int
-ip6_mrouter_set(cmd, so, m)
- int cmd;
- struct socket *so;
- struct mbuf *m;
-{
- if (cmd != MRT6_INIT && so != ip6_mrouter)
- return EACCES;
-
- switch (cmd) {
- case MRT6_INIT: return ip6_mrouter_init(so, m);
- case MRT6_DONE: return ip6_mrouter_done();
- case MRT6_ADD_MIF: return add_m6if(mtod(m, struct mif6ctl *));
- case MRT6_DEL_MIF: return del_m6if(mtod(m, mifi_t *));
- case MRT6_ADD_MFC: return add_m6fc(mtod(m, struct mf6cctl *));
- case MRT6_DEL_MFC: return del_m6fc(mtod(m, struct mf6cctl *));
- case MRT6_PIM: return set_pim6(mtod(m, int *));
- default: return EOPNOTSUPP;
- }
+ return (error);
}
-#endif
/*
* Handle MRT getsockopt commands
*/
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3 || defined (__APPLE__)
int
ip6_mrouter_get(so, sopt)
struct socket *so;
}
return (error);
}
-#else
-int
-ip6_mrouter_get(cmd, so, m)
- int cmd;
- struct socket *so;
- struct mbuf **m;
-{
- struct mbuf *mb;
-
- if (so != ip6_mrouter) return EACCES;
-
- *m = mb = m_get(M_WAIT, MT_SOOPTS);
-
- switch (cmd) {
- case MRT6_PIM: return get_pim6(mb);
- default:
- m_free(mb);
- return EOPNOTSUPP;
- }
-}
-#endif
/*
* Handle ioctl commands to obtain information from the cache
*/
int
-mrt6_ioctl(cmd, data)
- int cmd;
- caddr_t data;
+mrt6_ioctl(u_long cmd, caddr_t data)
{
- int error = 0;
-
- switch (cmd) {
- case SIOCGETSGCNT_IN6:
- return(get_sg_cnt((struct sioc_sg_req6 *)data));
- break; /* for safety */
- case SIOCGETMIFCNT_IN6:
- return(get_mif6_cnt((struct sioc_mif_req6 *)data));
- break; /* for safety */
- default:
- return (EINVAL);
- break;
- }
- return error;
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCGETSGCNT_IN6:
+ return (get_sg_cnt((struct sioc_sg_req6 *)data));
+ /* NOTREACHED */
+
+ case SIOCGETMIFCNT_IN6_32:
+ case SIOCGETMIFCNT_IN6_64:
+ return (get_mif6_cnt(data, cmd == SIOCGETMIFCNT_IN6_64));
+ /* NOTREACHED */
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return (error);
}
/*
*/
static int
get_sg_cnt(req)
- register struct sioc_sg_req6 *req;
+ struct sioc_sg_req6 *req;
{
- register struct mf6c *rt;
- int s;
+ struct mf6c *rt;
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
- splx(s);
if (rt != NULL) {
req->pktcnt = rt->mf6c_pkt_cnt;
req->bytecnt = rt->mf6c_byte_cnt;
* returns the input and output packet and byte counts on the mif provided
*/
static int
-get_mif6_cnt(req)
- register struct sioc_mif_req6 *req;
+get_mif6_cnt(void *data, int p64)
{
- register mifi_t mifi = req->mifi;
+ if (p64) {
+ struct sioc_mif_req6_64 *req = data;
- if (mifi >= nummifs)
- return EINVAL;
+ mifi_t mifi = req->mifi;
- req->icount = mif6table[mifi].m6_pkt_in;
- req->ocount = mif6table[mifi].m6_pkt_out;
- req->ibytes = mif6table[mifi].m6_bytes_in;
- req->obytes = mif6table[mifi].m6_bytes_out;
+ if (mifi >= nummifs)
+ return (EINVAL);
- return 0;
-}
-
-#if !(defined(__FreeBSD__) && __FreeBSD__ >=3) || !defined(__APPLE__)
-/*
- * Get PIM processiong global
- */
-static int
-get_pim6(m)
- struct mbuf *m;
-{
- int *i;
+ req->icount = mif6table[mifi].m6_pkt_in;
+ req->ocount = mif6table[mifi].m6_pkt_out;
+ req->ibytes = mif6table[mifi].m6_bytes_in;
+ req->obytes = mif6table[mifi].m6_bytes_out;
+ } else {
+ struct sioc_mif_req6_32 *req = data;
- i = mtod(m, int *);
+ mifi_t mifi = req->mifi;
- *i = pim6;
+ if (mifi >= nummifs)
+ return (EINVAL);
- return 0;
+ req->icount = mif6table[mifi].m6_pkt_in;
+ req->ocount = mif6table[mifi].m6_pkt_out;
+ req->ibytes = mif6table[mifi].m6_bytes_in;
+ req->obytes = mif6table[mifi].m6_bytes_out;
+ }
+ return (0);
}
-#endif
static int
set_pim6(i)
* Enable multicast routing
*/
static int
-ip6_mrouter_init(so, m)
+ip6_mrouter_init(so, v, cmd)
struct socket *so;
- struct mbuf *m;
+ int v;
+ int cmd;
{
- int *v;
-
#if MRT6DEBUG
if (mrt6debug)
log(LOG_DEBUG,
so->so_proto->pr_protocol != IPPROTO_ICMPV6)
return EOPNOTSUPP;
- if (!m || (m->m_len != sizeof(int *)))
- return ENOPROTOOPT;
-
- v = mtod(m, int *);
- if (*v != 1)
- return ENOPROTOOPT;
+ if (v != 1)
+ return (ENOPROTOOPT);
if (ip6_mrouter != NULL) return EADDRINUSE;
ip6_mrouter = so;
+ ip6_mrouter_ver = cmd;
bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
- bzero((caddr_t)nexpire, sizeof(nexpire));
+ bzero((caddr_t)n6expire, sizeof(n6expire));
pim6 = 0;/* used for stubbing out/in pim stuff */
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- expire_upcalls_ch =
-#endif
timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
#if MRT6DEBUG
{
mifi_t mifi;
int i;
- struct ifnet *ifp;
- struct in6_ifreq ifr;
struct mf6c *rt;
struct rtdetq *rte;
- int s;
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
/*
* For each phyint in use, disable promiscuous reception of all IPv6
for (mifi = 0; mifi < nummifs; mifi++) {
if (mif6table[mifi].m6_ifp &&
!(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
- ifr.ifr_addr.sin6_family = AF_INET6;
- ifr.ifr_addr.sin6_addr= in6addr_any;
- ifp = mif6table[mifi].m6_ifp;
#ifdef __APPLE__
- dlil_ioctl(0, ifp, SIOCDELMULTI,
- (caddr_t)&ifr);
+ if_allmulti(mif6table[mifi].m6_ifp, 0);
#else
- (*ifp->if_ioctl)(ifp, SIOCDELMULTI,
- (caddr_t)&ifr);
+ {
+ struct ifnet *ifp;
+ struct in6_ifreq ifr;
+
+ ifr.ifr_addr.sin6_family = AF_INET6;
+ ifr.ifr_addr.sin6_addr= in6addr_any;
+ ifp = mif6table[mifi].m6_ifp;
+ ifnet_ioctl(ifp, 0, SIOCDELMULTI, &ifr);
+ }
#endif
}
}
}
-#if notyet
- bzero((caddr_t)qtable, sizeof(qtable));
- bzero((caddr_t)tbftable, sizeof(tbftable));
-#endif
bzero((caddr_t)mif6table, sizeof(mif6table));
nummifs = 0;
pim6 = 0; /* used to stub out/in pim specific code */
- untimeout(expire_upcalls, (caddr_t)NULL
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- , expire_upcalls_ch
-#endif
- );
+ untimeout(expire_upcalls, (caddr_t)NULL);
/*
* Free all multicast forwarding cache entries.
+ *###LD 5/27 needs locking
*/
for (i = 0; i < MF6CTBLSIZ; i++) {
rt = mf6ctable[i];
struct rtdetq *n = rte->next;
m_free(rte->m);
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
rte = n;
}
frt = rt;
rt = rt->mf6c_next;
- _FREE(frt, M_MRTABLE);
+ FREE(frt, M_MRTABLE);
}
}
reg_mif_num = -1;
ip6_mrouter = NULL;
+ ip6_mrouter_ver = 0;
- splx(s);
#if MRT6DEBUG
if (mrt6debug)
return 0;
}
-static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
+static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 ,
+ 0, 0, IN6ADDR_ANY_INIT, 0};
/*
* Add a mif to the mif table
*/
static int
add_m6if(mifcp)
- register struct mif6ctl *mifcp;
+ struct mif6ctl *mifcp;
{
- register struct mif6 *mifp;
+ struct mif6 *mifp;
struct ifnet *ifp;
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
- struct in6_ifreq ifr;
-#endif
- int error, s;
+ int error;
#if notyet
struct tbf *m_tbf = tbftable + mifcp->mif6c_mifi;
#endif
return EINVAL;
mifp = mif6table + mifcp->mif6c_mifi;
if (mifp->m6_ifp)
- return EADDRINUSE; /* XXX: is it appropriate? */
+ return (EADDRINUSE); /* XXX: is it appropriate? */
if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index)
+ return (ENXIO);
+
+ ifnet_head_lock_shared();
+ if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > if_index) {
+ ifnet_head_done();
return ENXIO;
+ }
ifp = ifindex2ifnet[mifcp->mif6c_pifi];
+ ifnet_head_done();
+ if (ifp == NULL) {
+ return ENXIO;
+ }
if (mifcp->mif6c_flags & MIFF_REGISTER) {
if (reg_mif_num == (mifi_t)-1) {
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- strcpy(multicast_register_if.if_xname,
- "register_mif"); /* XXX */
-#else
multicast_register_if.if_name = "register_mif";
-#endif
multicast_register_if.if_flags |= IFF_LOOPBACK;
multicast_register_if.if_index = mifcp->mif6c_mifi;
reg_mif_num = mifcp->mif6c_mifi;
if ((ifp->if_flags & IFF_MULTICAST) == 0)
return EOPNOTSUPP;
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
error = if_allmulti(ifp, 1);
-#else
- /*
- * Enable promiscuous reception of all IPv6 multicasts
- * from the interface.
- */
- ifr.ifr_addr.sin6_family = AF_INET6;
- ifr.ifr_addr.sin6_addr = in6addr_any;
- error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
-#endif
- splx(s);
if (error)
return error;
}
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
mifp->m6_flags = mifcp->mif6c_flags;
mifp->m6_ifp = ifp;
-#if notyet
- /* scaling up here allows division by 1024 in critical code */
- mifp->m6_rate_limit = mifcp->mif6c_rate_limit * 1024 / 1000;
-#endif
+
/* initialize per mif pkt counters */
mifp->m6_pkt_in = 0;
mifp->m6_pkt_out = 0;
mifp->m6_bytes_in = 0;
mifp->m6_bytes_out = 0;
- splx(s);
/* Adjust nummifs up if the mifi is higher than nummifs */
if (nummifs <= mifcp->mif6c_mifi)
del_m6if(mifip)
mifi_t *mifip;
{
- register struct mif6 *mifp = mif6table + *mifip;
- register mifi_t mifi;
+ struct mif6 *mifp = mif6table + *mifip;
+ mifi_t mifi;
struct ifnet *ifp;
-#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__)
- struct in6_ifreq ifr;
-#endif
- int s;
if (*mifip >= nummifs)
return EINVAL;
if (mifp->m6_ifp == NULL)
return EINVAL;
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
if (!(mifp->m6_flags & MIFF_REGISTER)) {
/*
*/
ifp = mifp->m6_ifp;
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined (__APPLE__)
if_allmulti(ifp, 0);
-#else
- ifr.ifr_addr.sin6_family = AF_INET6;
- ifr.ifr_addr.sin6_addr = in6addr_any;
- (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
-#endif
}
-#if notyet
- bzero((caddr_t)qtable[*mifip], sizeof(qtable[*mifip]));
- bzero((caddr_t)mifp->m6_tbf, sizeof(*(mifp->m6_tbf)));
-#endif
- bzero((caddr_t)mifp, sizeof (*mifp));
+ bzero((caddr_t)mifp, sizeof(*mifp));
/* Adjust nummifs down */
for (mifi = nummifs; mifi > 0; mifi--)
break;
nummifs = mifi;
- splx(s);
#if MRT6DEBUG
if (mrt6debug)
struct mf6cctl *mfccp;
{
struct mf6c *rt;
- u_long hash;
+ u_int32_t hash;
struct rtdetq *rte;
- register u_short nstl;
- int s;
+ u_short nstl;
MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
mfccp->mf6cc_mcastgrp.sin6_addr, rt);
if (rt) {
#if MRT6DEBUG
if (mrt6debug & DEBUG_MFC)
- log(LOG_DEBUG,"add_m6fc update o %s g %s p %x\n",
+ log(LOG_DEBUG,
+ "add_m6fc no upcall h %d o %s g %s p %x\n",
ip6_sprintf(&mfccp->mf6cc_origin.sin6_addr),
ip6_sprintf(&mfccp->mf6cc_mcastgrp.sin6_addr),
mfccp->mf6cc_parent);
#endif
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
rt->mf6c_parent = mfccp->mf6cc_parent;
rt->mf6c_ifset = mfccp->mf6cc_ifset;
- splx(s);
return 0;
}
/*
* Find the entry for which the upcall was made and update
*/
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
mfccp->mf6cc_mcastgrp.sin6_addr);
for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
rt->mf6c_wrong_if = 0;
rt->mf6c_expire = 0; /* Don't clean this guy up */
- nexpire[hash]--;
+ n6expire[hash]--;
/* free packets Qed at the end of this entry */
for (rte = rt->mf6c_stall; rte != NULL; ) {
#if UPCALL_TIMING
collate(&(rte->t));
#endif /* UPCALL_TIMING */
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
rte = n;
}
rt->mf6c_stall = NULL;
rt->mf6c_origin = mfccp->mf6cc_origin;
rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
rt->mf6c_parent = mfccp->mf6cc_parent;
+ rt->mf6c_ifset = mfccp->mf6cc_ifset;
/* initialize pkt counters per src-grp */
rt->mf6c_pkt_cnt = 0;
rt->mf6c_byte_cnt = 0;
rt->mf6c_wrong_if = 0;
if (rt->mf6c_expire)
- nexpire[hash]--;
+ n6expire[hash]--;
rt->mf6c_expire = 0;
}
}
rt = (struct mf6c *)_MALLOC(sizeof(*rt), M_MRTABLE,
M_NOWAIT);
if (rt == NULL) {
- splx(s);
return ENOBUFS;
}
rt->mf6c_origin = mfccp->mf6cc_origin;
rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
rt->mf6c_parent = mfccp->mf6cc_parent;
+ rt->mf6c_ifset = mfccp->mf6cc_ifset;
/* initialize pkt counters per src-grp */
rt->mf6c_pkt_cnt = 0;
rt->mf6c_byte_cnt = 0;
mf6ctable[hash] = rt;
}
}
- splx(s);
return 0;
}
*/
static void
collate(t)
- register struct timeval *t;
+ struct timeval *t;
{
- register u_long d;
- register struct timeval tp;
- register u_long delta;
+ u_int32_t d;
+ struct timeval tp;
+ u_int32_t delta;
GET_TIME(tp);
struct sockaddr_in6 mcastgrp;
struct mf6c *rt;
struct mf6c **nptr;
- u_long hash;
- int s;
+ u_int32_t hash;
origin = mfccp->mf6cc_origin;
mcastgrp = mfccp->mf6cc_mcastgrp;
ip6_sprintf(&mcastgrp.sin6_addr));
#endif
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
nptr = &mf6ctable[hash];
while ((rt = *nptr) != NULL) {
nptr = &rt->mf6c_next;
}
if (rt == NULL) {
- splx(s);
return EADDRNOTAVAIL;
}
*nptr = rt->mf6c_next;
- _FREE(rt, M_MRTABLE);
+ FREE(rt, M_MRTABLE);
- splx(s);
return 0;
}
struct mbuf *mm;
struct sockaddr_in6 *src;
{
+//### LD 5/27/04 needs locking!
+//
if (s) {
if (sbappendaddr(&s->so_rcv,
(struct sockaddr *)src,
- mm, (struct mbuf *)0) != 0) {
+ mm, (struct mbuf *)0, NULL) != 0) {
sorwakeup(s);
return 0;
}
}
- m_freem(mm);
return -1;
}
int
ip6_mforward(ip6, ifp, m)
- register struct ip6_hdr *ip6;
+ struct ip6_hdr *ip6;
struct ifnet *ifp;
struct mbuf *m;
{
- register struct mf6c *rt;
- register struct mif6 *mifp;
- register struct mbuf *mm;
- int s;
+ struct mf6c *rt;
+ struct mif6 *mifp;
+ struct mbuf *mm;
mifi_t mifi;
+ struct timeval timenow;
#if MRT6DEBUG
if (mrt6debug & DEBUG_FORWARD)
return 0;
ip6->ip6_hlim--;
+ /*
+ * Source address check: do not forward packets with unspecified
+ * source. It was discussed in July 2000, on ipngwg mailing list.
+ * This is rather more serious than unicast cases, because some
+ * MLD packets can be sent with the unspecified source address
+ * (although such packets must normally set 1 to the hop limit field).
+ */
+ getmicrotime(&timenow);
+ if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
+ ip6stat.ip6s_cantforward++;
+ if (ip6_log_time + ip6_log_interval < timenow.tv_sec) {
+ ip6_log_time = timenow.tv_sec;
+ log(LOG_DEBUG,
+ "cannot forward "
+ "from %s to %s nxt %d received on %s\n",
+ ip6_sprintf(&ip6->ip6_src),
+ ip6_sprintf(&ip6->ip6_dst),
+ ip6->ip6_nxt,
+ if_name(m->m_pkthdr.rcvif));
+ }
+ return 0;
+ }
+
/*
* Determine forwarding mifs from the forwarding cache table
*/
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
/* Entry exists, so forward if necessary */
if (rt) {
- splx(s);
return (ip6_mdq(m, ifp, rt));
} else {
/*
* send message to routing daemon
*/
- register struct mbuf *mb0;
- register struct rtdetq *rte;
- register u_long hash;
-/* register int i, npkts;*/
+ struct mbuf *mb0;
+ struct rtdetq *rte;
+ u_int32_t hash;
+/* int i, npkts;*/
#if UPCALL_TIMING
struct timeval tp;
rte = (struct rtdetq *)_MALLOC(sizeof(*rte), M_MRTABLE,
M_NOWAIT);
if (rte == NULL) {
- splx(s);
return ENOBUFS;
}
mb0 = m_copy(m, 0, M_COPYALL);
(M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
if (mb0 == NULL) {
- _FREE(rte, M_MRTABLE);
- splx(s);
+ FREE(rte, M_MRTABLE);
return ENOBUFS;
}
if (rt == NULL) {
struct mrt6msg *im;
+#if MRT6_OINIT
+ struct omrt6msg *oim;
+#endif
/* no upcall, so make a new entry */
rt = (struct mf6c *)_MALLOC(sizeof(*rt), M_MRTABLE,
M_NOWAIT);
if (rt == NULL) {
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
m_freem(mb0);
- splx(s);
return ENOBUFS;
}
/*
mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
if (mm == NULL) {
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
m_freem(mb0);
- _FREE(rt, M_MRTABLE);
- splx(s);
+ FREE(rt, M_MRTABLE);
return ENOBUFS;
}
*/
sin6.sin6_addr = ip6->ip6_src;
- im = mtod(mm, struct mrt6msg *);
- im->im6_msgtype = MRT6MSG_NOCACHE;
- im->im6_mbz = 0;
+ im = NULL;
+#if MRT6_OINIT
+ oim = NULL;
+#endif
+ switch (ip6_mrouter_ver) {
+#if MRT6_OINIT
+ case MRT6_OINIT:
+ oim = mtod(mm, struct omrt6msg *);
+ oim->im6_msgtype = MRT6MSG_NOCACHE;
+ oim->im6_mbz = 0;
+ break;
+#endif
+ case MRT6_INIT:
+ im = mtod(mm, struct mrt6msg *);
+ im->im6_msgtype = MRT6MSG_NOCACHE;
+ im->im6_mbz = 0;
+ break;
+ default:
+ FREE(rte, M_MRTABLE);
+ m_freem(mb0);
+ FREE(rt, M_MRTABLE);
+ return EINVAL;
+ }
#if MRT6DEBUG
if (mrt6debug & DEBUG_FORWARD)
mifp++, mifi++)
;
- im->im6_mif = mifi;
+ switch (ip6_mrouter_ver) {
+#if MRT6_OINIT
+ case MRT6_OINIT:
+ oim->im6_mif = mifi;
+ break;
+#endif
+ case MRT6_INIT:
+ im->im6_mif = mifi;
+ break;
+ }
if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
"socket queue full\n");
mrt6stat.mrt6s_upq_sockfull++;
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
m_freem(mb0);
- _FREE(rt, M_MRTABLE);
- splx(s);
+ FREE(rt, M_MRTABLE);
return ENOBUFS;
}
rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
rt->mf6c_expire = UPCALL_EXPIRE;
- nexpire[hash]++;
+ n6expire[hash]++;
rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
/* link into table */
} else {
/* determine if q has overflowed */
struct rtdetq **p;
- register int npkts = 0;
+ int npkts = 0;
for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
if (++npkts > MAX_UPQ6) {
mrt6stat.mrt6s_upq_ovflw++;
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
m_freem(mb0);
- splx(s);
return 0;
}
rte->t = tp;
#endif /* UPCALL_TIMING */
- splx(s);
return 0;
}
* Call from the Slow Timeout mechanism, every half second.
*/
static void
-expire_upcalls_funneled(unused)
- void *unused;
-{
-#ifdef __APPLE__
- boolean_t funnel_state;
- funnel_state = thread_funnel_set(network_flock, TRUE);
-#endif
- expire_upcalls(unused);
-#ifdef __APPLE__
- (void) thread_funnel_set(network_flock, FALSE);
-#endif
-}
-
-static void
-expire_upcalls(unused)
- void *unused;
+expire_upcalls(
+ __unused void *unused)
{
struct rtdetq *rte;
struct mf6c *mfc, **nptr;
int i;
- int s;
-#if __NetBSD__
- s = splsoftnet();
-#else
- s = splnet();
-#endif
for (i = 0; i < MF6CTBLSIZ; i++) {
- if (nexpire[i] == 0)
+ if (n6expire[i] == 0)
continue;
nptr = &mf6ctable[i];
while ((mfc = *nptr) != NULL) {
do {
struct rtdetq *n = rte->next;
m_freem(rte->m);
- _FREE(rte, M_MRTABLE);
+ FREE(rte, M_MRTABLE);
rte = n;
} while (rte != NULL);
mrt6stat.mrt6s_cache_cleanups++;
- nexpire[i]--;
+ n6expire[i]--;
*nptr = mfc->mf6c_next;
- _FREE(mfc, M_MRTABLE);
+ FREE(mfc, M_MRTABLE);
} else {
nptr = &mfc->mf6c_next;
}
}
}
- splx(s);
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- expire_upcalls_ch =
-#endif
- timeout(expire_upcalls_funneled, (caddr_t)NULL, EXPIRE_TIMEOUT);
+
+ timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
}
/*
*/
static int
ip6_mdq(m, ifp, rt)
- register struct mbuf *m;
- register struct ifnet *ifp;
- register struct mf6c *rt;
+ struct mbuf *m;
+ struct ifnet *ifp;
+ struct mf6c *rt;
{
- register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- register mifi_t mifi, iif;
- register struct mif6 *mifp;
- register int plen = m->m_pkthdr.len;
+ struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
+ mifi_t mifi, iif;
+ struct mif6 *mifp;
+ int plen = m->m_pkthdr.len;
+ struct in6_addr src0, dst0; /* copies for local work */
+ u_int32_t iszone, idzone, oszone, odzone;
+ int error = 0;
/*
* Macro to send packet on mif. Since RSVP packets don't get counted on
* input, they shouldn't get counted on output, so statistics keeping is
- * seperate.
+ * separate.
*/
-#define MC6_SEND(ip6,mifp,m) { \
- if ((mifp)->m6_flags & MIFF_REGISTER) \
- register_send((ip6), (mifp), (m)); \
- else \
- phyint_send((ip6), (mifp), (m)); \
-}
+#define MC6_SEND(ip6, mifp, m) do { \
+ if ((mifp)->m6_flags & MIFF_REGISTER) \
+ register_send((ip6), (mifp), (m)); \
+ else \
+ phyint_send((ip6), (mifp), (m)); \
+} while (0)
/*
* Don't forward if it didn't arrive from the parent mif
* packets on this interface, send a message to the
* routing daemon.
*/
- if(mifi < nummifs) /* have to make sure this is a valid mif */
- if(mif6table[mifi].m6_ifp)
-
- if (pim6 && (m->m_flags & M_LOOP) == 0) {
- /*
- * Check the M_LOOP flag to avoid an
- * unnecessary PIM assert.
- * XXX: M_LOOP is an ad-hoc hack...
- */
- static struct sockaddr_in6 sin6 =
- { sizeof(sin6), AF_INET6 };
-
- register struct mbuf *mm;
- struct mrt6msg *im;
-
- mm = m_copy(m, 0,
- sizeof(struct ip6_hdr));
- if (mm &&
- (M_HASCL(mm) ||
- mm->m_len < sizeof(struct ip6_hdr)))
- mm = m_pullup(mm, sizeof(struct ip6_hdr));
- if (mm == NULL)
- return ENOBUFS;
-
+ /* have to make sure this is a valid mif */
+ if (mifi < nummifs && mif6table[mifi].m6_ifp)
+ if (pim6 && (m->m_flags & M_LOOP) == 0) {
+ /*
+ * Check the M_LOOP flag to avoid an
+ * unnecessary PIM assert.
+ * XXX: M_LOOP is an ad-hoc hack...
+ */
+ static struct sockaddr_in6 addr =
+ { sizeof(addr), AF_INET6 , 0, 0, IN6ADDR_ANY_INIT, 0};
+
+ struct mbuf *mm;
+ struct mrt6msg *im;
+#if MRT6_OINIT
+ struct omrt6msg *oim;
+#endif
+
+ mm = m_copy(m, 0, sizeof(struct ip6_hdr));
+ if (mm &&
+ (M_HASCL(mm) ||
+ mm->m_len < sizeof(struct ip6_hdr)))
+ mm = m_pullup(mm, sizeof(struct ip6_hdr));
+ if (mm == NULL)
+ return ENOBUFS;
+
+#if MRT6_OINIT
+ oim = NULL;
+#endif
+ im = NULL;
+ switch (ip6_mrouter_ver) {
+#if MRT6_OINIT
+ case MRT6_OINIT:
+ oim = mtod(mm, struct omrt6msg *);
+ oim->im6_msgtype = MRT6MSG_WRONGMIF;
+ oim->im6_mbz = 0;
+ break;
+#endif
+ case MRT6_INIT:
im = mtod(mm, struct mrt6msg *);
- im->im6_msgtype = MRT6MSG_WRONGMIF;
- im->im6_mbz = 0;
-
- for (mifp = mif6table, iif = 0;
- iif < nummifs && mifp &&
- mifp->m6_ifp != ifp;
- mifp++, iif++);
-
- im->im6_mif = iif;
+ im->im6_msgtype = MRT6MSG_WRONGMIF;
+ im->im6_mbz = 0;
+ break;
+ default:
+ m_freem(mm);
+ return EINVAL;
+ }
- sin6.sin6_addr = im->im6_src;
+ for (mifp = mif6table, iif = 0;
+ iif < nummifs && mifp &&
+ mifp->m6_ifp != ifp;
+ mifp++, iif++)
+ ;
+
+ switch (ip6_mrouter_ver) {
+#if MRT6_OINIT
+ case MRT6_OINIT:
+ oim->im6_mif = iif;
+ addr.sin6_addr = oim->im6_src;
+ break;
+#endif
+ case MRT6_INIT:
+ im->im6_mif = iif;
+ addr.sin6_addr = im->im6_src;
+ break;
+ }
- mrt6stat.mrt6s_upcalls++;
+ mrt6stat.mrt6s_upcalls++;
- if (socket_send(ip6_mrouter, mm,
- &sin6) < 0) {
+ if (socket_send(ip6_mrouter, mm, &addr) < 0) {
#if MRT6DEBUG
- if (mrt6debug)
- log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
+ if (mrt6debug)
+ log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
#endif
- ++mrt6stat.mrt6s_upq_sockfull;
- return ENOBUFS;
- } /* if socket Q full */
- } /* if PIM */
+ ++mrt6stat.mrt6s_upq_sockfull;
+ return ENOBUFS;
+ } /* if socket Q full */
+ } /* if PIM */
return 0;
} /* if wrong iif */
* For each mif, forward a copy of the packet if there are group
* members downstream on the interface.
*/
- for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++)
+ src0 = ip6->ip6_src;
+ dst0 = ip6->ip6_dst;
+ if ((error = in6_setscope(&src0, ifp, &iszone)) != 0 ||
+ (error = in6_setscope(&dst0, ifp, &idzone)) != 0) {
+ ip6stat.ip6s_badscope++;
+ return (error);
+ }
+ for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
+ /*
+ * check if the outgoing packet is going to break
+ * a scope boundary.
+ * XXX For packets through PIM register tunnel
+ * interface, we believe a routing daemon.
+ */
+ if (!(mif6table[rt->mf6c_parent].m6_flags &
+ MIFF_REGISTER) &&
+ !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
+ if (in6_setscope(&src0, mif6table[mifi].m6_ifp,
+ &oszone) ||
+ in6_setscope(&dst0, mif6table[mifi].m6_ifp,
+ &odzone) ||
+ iszone != oszone ||
+ idzone != odzone) {
+ ip6stat.ip6s_badscope++;
+ continue;
+ }
+ }
+
mifp->m6_pkt_out++;
mifp->m6_bytes_out += plen;
MC6_SEND(ip6, mifp, m);
}
+ }
return 0;
}
struct mif6 *mifp;
struct mbuf *m;
{
- register struct mbuf *mb_copy;
+ struct mbuf *mb_copy;
struct ifnet *ifp = mifp->m6_ifp;
int error = 0;
-#if __NetBSD__
- int s = splsoftnet();
-#else
- int s = splnet();
-#endif
- static struct route_in6 ro6;
+ static struct route_in6 ro;
struct in6_multi *in6m;
+ struct sockaddr_in6 *dst6;
/*
* Make a new reference to the packet; make sure that
if (mb_copy &&
(M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
- if (mb_copy == NULL)
+ if (mb_copy == NULL) {
return;
+ }
/* set MCAST flag to the outgoing packet */
mb_copy->m_flags |= M_MCAST;
* sending queue.
*/
if (m->m_pkthdr.rcvif == NULL) {
- struct ip6_moptions im6o;
+ struct ip6_moptions *im6o;
+
+ im6o = ip6_allocmoptions(M_DONTWAIT);
+ if (im6o == NULL) {
+ m_freem(mb_copy);
+ return;
+ }
- im6o.im6o_multicast_ifp = ifp;
+ im6o->im6o_multicast_ifp = ifp;
/* XXX: ip6_output will override ip6->ip6_hlim */
- im6o.im6o_multicast_hlim = ip6->ip6_hlim;
- im6o.im6o_multicast_loop = 1;
- error = ip6_output(mb_copy, NULL, &ro6,
- IPV6_FORWARDING, &im6o, NULL);
+ im6o->im6o_multicast_hlim = ip6->ip6_hlim;
+ im6o->im6o_multicast_loop = 1;
+ error = ip6_output(mb_copy, NULL, &ro, IPV6_FORWARDING,
+ im6o, NULL, NULL);
+ IM6O_REMREF(im6o);
#if MRT6DEBUG
if (mrt6debug & DEBUG_XMIT)
log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
mifp - mif6table, error);
#endif
- splx(s);
return;
}
* If we belong to the destination multicast group
* on the outgoing interface, loop back a copy.
*/
+ dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
+ in6_multihead_lock_shared();
IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
+ in6_multihead_lock_done();
if (in6m != NULL) {
- ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
- ro6.ro_dst.sin6_family = AF_INET6;
- ro6.ro_dst.sin6_addr = ip6->ip6_dst;
- ip6_mloopback(ifp, m, &ro6.ro_dst);
+ IN6M_REMREF(in6m);
+ dst6->sin6_len = sizeof(struct sockaddr_in6);
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_addr = ip6->ip6_dst;
+ ip6_mloopback(ifp, m, (struct sockaddr_in6 *)&ro.ro_dst);
}
/*
* Put the packet into the sending queue of the outgoing interface
* if it would fit in the MTU of the interface.
*/
- if (mb_copy->m_pkthdr.len < ifp->if_mtu || ifp->if_mtu < IPV6_MMTU) {
- ro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
- ro6.ro_dst.sin6_family = AF_INET6;
- ro6.ro_dst.sin6_addr = ip6->ip6_dst;
+ if (mb_copy->m_pkthdr.len <= ifp->if_mtu || ifp->if_mtu < IPV6_MMTU) {
+ dst6->sin6_len = sizeof(struct sockaddr_in6);
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_addr = ip6->ip6_dst;
/*
* We just call if_output instead of nd6_output here, since
* we need no ND for a multicast forwarded packet...right?
*/
#ifdef __APPLE__
- error = dlil_output(ifptodlt(ifp, PF_INET6), mb_copy,
- NULL, (struct sockaddr *)&ro6.ro_dst, 0);
+ /* Make sure the HW checksum flags are cleaned before sending the packet */
+
+ mb_copy->m_pkthdr.rcvif = 0;
+ mb_copy->m_pkthdr.csum_data = 0;
+ mb_copy->m_pkthdr.csum_flags = 0;
+
+ error = dlil_output(ifp, PF_INET6, mb_copy,
+ NULL, (struct sockaddr *)&ro.ro_dst, 0);
#else
error = (*ifp->if_output)(ifp, mb_copy,
- (struct sockaddr *)&ro6.ro_dst,
+ (struct sockaddr *)&ro.ro_dst,
NULL);
#endif
#if MRT6DEBUG
log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
mifp - mif6table, error);
#endif
- }
- else {
-#if MULTICAST_PMTUD
- icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
- return;
-#else
+ } else {
+ /*
+ * pMTU discovery is intentionally disabled by default, since
+ * various router may notify pMTU in multicast, which can be
+ * a DDoS to a router
+ */
+ if (ip6_mcast_pmtu)
+ icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
#if MRT6DEBUG
-#if __NetBSD__
- if (mrt6debug & DEBUG_DEBUG_XMIT)
- log(LOG_DEBUG,
- "phyint_send: packet too big on %s o %s g %s"
- " size %d(discarded)\n",
- ifp->if_xname,
- ip6_sprintf(&ip6->ip6_src),
- ip6_sprintf(&ip6->ip6_dst),
- mb_copy->m_pkthdr.len);
-#else
- if (mrt6debug & DEBUG_XMIT)
- log(LOG_DEBUG,
- "phyint_send: packet too big on %s%u o %s g %s"
- " size %d(discarded)\n",
- ifp->if_name, ifp->if_unit,
- ip6_sprintf(&ip6->ip6_src),
- ip6_sprintf(&ip6->ip6_dst),
- mb_copy->m_pkthdr.len);
-#endif /* __NetBSD__ */
+ else {
+ if (mrt6debug & DEBUG_XMIT) {
+ log(LOG_DEBUG,
+ "phyint_send: packet too big on %s o %s "
+ "g %s size %d(discarded)\n",
+ if_name(ifp),
+ ip6_sprintf(&ip6->ip6_src),
+ ip6_sprintf(&ip6->ip6_dst),
+ mb_copy->m_pkthdr.len);
+ }
+ }
#endif /* MRT6DEBUG */
m_freem(mb_copy); /* simply discard the packet */
- return;
-#endif
+
}
}
static int
register_send(ip6, mif, m)
- register struct ip6_hdr *ip6;
+ struct ip6_hdr *ip6;
struct mif6 *mif;
- register struct mbuf *m;
+ struct mbuf *m;
{
- register struct mbuf *mm;
- register int i, len = m->m_pkthdr.len;
- static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
+ struct mbuf *mm;
+ int i, len = m->m_pkthdr.len;
+ static struct sockaddr_in6 addr = { sizeof(addr), AF_INET6 ,
+ 0, 0, IN6ADDR_ANY_INIT, 0};
struct mrt6msg *im6;
#if MRT6DEBUG
MGETHDR(mm, M_DONTWAIT, MT_HEADER);
if (mm == NULL)
return ENOBUFS;
+#ifdef __darwin8_notyet
+#if CONFIG_MACF_NET
+ mac_create_mbuf_multicast_encap(m, mif->m6_ifp, mm);
+#endif
+#endif
+ mm->m_pkthdr.rcvif = NULL;
mm->m_data += max_linkhdr;
mm->m_len = sizeof(struct ip6_hdr);
/*
* Send message to routing daemon
*/
- sin6.sin6_addr = ip6->ip6_src;
+ addr.sin6_addr = ip6->ip6_src;
im6 = mtod(mm, struct mrt6msg *);
im6->im6_msgtype = MRT6MSG_WHOLEPKT;
/* iif info is not given for reg. encap.n */
mrt6stat.mrt6s_upcalls++;
- if (socket_send(ip6_mrouter, mm, &sin6) < 0) {
+ if (socket_send(ip6_mrouter, mm, &addr) < 0) {
#if MRT6DEBUG
if (mrt6debug)
log(LOG_WARNING,
- "register_send: ip_mrouter socket queue full\n");
+ "register_send: ip6_mrouter socket queue full\n");
#endif
- ++mrt6stat.mrt6s_upq_sockfull;
- return ENOBUFS;
+ ++mrt6stat.mrt6s_upq_sockfull;
+ return ENOBUFS;
}
return 0;
}
* is stripped off, and the inner packet is passed to register_mforward.
*/
int
-pim6_input(mp, offp, proto)
- struct mbuf **mp;
- int *offp, proto;
+pim6_input(struct mbuf **mp, int *offp, int proto)
{
- register struct pim *pim; /* pointer to a pim struct */
- register struct ip6_hdr *ip6;
- register int pimlen;
+ struct pim *pim; /* pointer to a pim struct */
+ struct ip6_hdr *ip6;
+ int pimlen;
struct mbuf *m = *mp;
- int minlen;
+ int minlen;
int off = *offp;
++pim6stat.pim6s_rcv_total;
- ip6 = mtod(m, struct ip6_hdr *);
- pimlen = m->m_pkthdr.len - *offp;
+ ip6 = mtod(m, struct ip6_hdr *);
+ pimlen = m->m_pkthdr.len - *offp;
- /*
- * Validate lengths
- */
+ /*
+ * Validate lengths
+ */
if (pimlen < PIM_MINLEN) {
++pim6stat.pim6s_rcv_tooshort;
#if MRT6DEBUG
* possibly the PIM REGISTER header
*/
#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE);
+ IP6_EXTHDR_CHECK(m, off, minlen, return IPPROTO_DONE);
/* adjust pointer */
ip6 = mtod(m, struct ip6_hdr *);
}
#endif
-
-#define PIM6_CHECKSUM 1
-#if PIM6_CHECKSUM
+#define PIM6_CHECKSUM
+#ifdef PIM6_CHECKSUM
{
int cksumlen;
* headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
* routing daemon.
*/
- static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
+ static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 ,
+ 0, 0, IN6ADDR_ANY_INIT, 0 };
struct mbuf *mcp;
struct ip6_hdr *eip6;
u_int32_t *reghdr;
- int rc;
++pim6stat.pim6s_rcv_registers;
ip6_sprintf(&eip6->ip6_dst),
ntohs(eip6->ip6_plen));
#endif
+
+ /* verify the version number of the inner packet */
+ if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+ ++pim6stat.pim6s_rcv_badregisters;
+#if MRT6DEBUG
+ log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
+ "of the inner packet\n",
+ (eip6->ip6_vfc & IPV6_VERSION));
+#endif
+ m_freem(m);
+ return(IPPROTO_NONE);
+ }
/* verify the inner packet is destined to a mcast group */
if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
}
#endif
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
- (struct sockaddr *) &dst, NULL);
-#else
-#if defined (__APPLE__)
- if (lo_dl_tag == 0)
- dlil_find_dltag(APPLE_IF_FAM_LOOPBACK, 0, PF_INET6, &lo_dl_tag);
-
- if (lo_dl_tag)
- dlil_output(lo_dl_tag, m, 0, (struct sockaddr *) &dst, 0);
+#ifdef __APPLE__
+
+ if (lo_ifp) {
+ dlil_output(lo_ifp, PF_INET6, m, 0, (struct sockaddr *)&dst, 0);
+ }
else {
printf("Warning: pim6_input call to dlil_find_dltag failed!\n");
m_freem(m);
}
#else
- rc = looutput(mif6table[reg_mif_num].m6_ifp, m,
- (struct sockaddr *) &dst,
- (struct rtentry *) NULL);
-#endif
+ (void) if_simloop(mif6table[reg_mif_num].m6_ifp, m,
+ dst.sin6_family, NULL);
#endif
/* prepare the register head to send to the mrouting daemon */
* encapsulated ip6 header.
*/
pim6_input_to_daemon:
- rip6_input(&m, offp, proto);
+ rip6_input(&m, offp);
return(IPPROTO_DONE);
}
+#endif