I plan to commit this soon as part of the mrouting cleanup.
Bring the IPv4 multicast forwarding code more into line with the IPv6
version, by unconditionally building with PIM support enabled, and
allowing it to be built as a loadable module.

Use encap_attach_func() to hookup the IPPROTO_PIM input path.
Keep the reserved identifier _PIM_VT around as some folks use this.

TODO: Make the IPv6 multicast forwarding code dynamically loadable.

Index: sys/conf/NOTES
===================================================================
RCS file: /home/ncvs/src/sys/conf/NOTES,v
retrieving revision 1.1409
diff -u -p -r1.1409 NOTES
--- sys/conf/NOTES	7 Feb 2007 18:55:29 -0000	1.1409
+++ sys/conf/NOTES	9 Feb 2007 01:59:43 -0000
@@ -807,10 +807,7 @@ device		stf			#6to4 IPv6 over IPv4 encap
 # Internet family options:
 #
 # MROUTING enables the kernel multicast packet forwarder, which works
-# with mrouted(8).
-#
-# PIM enables Protocol Independent Multicast in the kernel.
-# Requires MROUTING enabled.
+# with mrouted and XORP.
 #
 # IPFIREWALL enables support for IP firewall construction, in
 # conjunction with the `ipfw' program.  IPFIREWALL_VERBOSE sends
@@ -854,7 +851,6 @@ device		stf			#6to4 IPv6 over IPv4 encap
 # using the trpt(8) utility.
 #
 options 	MROUTING		# Multicast routing
-options 	PIM			# Protocol Independent Multicast
 options 	IPFIREWALL		#firewall
 options 	IPFIREWALL_VERBOSE	#enable logging to syslogd(8)
 options 	IPFIREWALL_VERBOSE_LIMIT=100	#limit verbosity
Index: sys/conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.575
diff -u -p -r1.575 options
--- sys/conf/options	7 Feb 2007 18:55:29 -0000	1.575
+++ sys/conf/options	9 Feb 2007 01:59:43 -0000
@@ -352,7 +352,6 @@ ETHER_8023		opt_ef.h
 ETHER_8022		opt_ef.h
 ETHER_SNAP		opt_ef.h
 MROUTING		opt_mrouting.h
-PIM			opt_mrouting.h
 INET			opt_inet.h
 INET6			opt_inet6.h
 IPSEC			opt_ipsec.h
Index: sys/netinet/in_proto.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.82
diff -u -p -r1.82 in_proto.c
--- sys/netinet/in_proto.c	3 Nov 2006 15:23:14 -0000	1.82
+++ sys/netinet/in_proto.c	9 Feb 2007 01:59:43 -0000
@@ -56,9 +56,6 @@
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/igmp_var.h>
-#ifdef PIM
-#include <netinet/pim_var.h>
-#endif
 #include <netinet/tcp.h>
 #include <netinet/tcp_timer.h>
 #include <netinet/tcp_var.h>
@@ -345,17 +342,6 @@ struct protosw inetsw[] = {
 	.pr_usrreqs =		&rip_usrreqs
 },
 #endif
-#ifdef PIM
-{
-	.pr_type =		SOCK_RAW,
-	.pr_domain =		&inetdomain,
-	.pr_protocol =		IPPROTO_PIM,
-	.pr_flags =		PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-	.pr_input =		pim_input,
-	.pr_ctloutput =		rip_ctloutput,
-	.pr_usrreqs =		&rip_usrreqs
-},
-#endif	/* PIM */
 #ifdef DEV_PFSYNC
 {
 	.pr_type =		SOCK_RAW,
@@ -438,9 +424,6 @@ SYSCTL_NODE(_net_inet, IPPROTO_AH,	ipsec
 #endif /* IPSEC */
 #endif /* !FAST_IPSEC */
 SYSCTL_NODE(_net_inet, IPPROTO_RAW,	raw,	CTLFLAG_RW, 0,	"RAW");
-#ifdef PIM
-SYSCTL_NODE(_net_inet, IPPROTO_PIM,	pim,	CTLFLAG_RW, 0,	"PIM");
-#endif
 #ifdef DEV_PFSYNC
 SYSCTL_NODE(_net_inet, IPPROTO_PFSYNC,	pfsync,	CTLFLAG_RW, 0,	"PFSYNC");
 #endif
Index: sys/netinet/ip_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.126
diff -u -p -r1.126 ip_mroute.c
--- sys/netinet/ip_mroute.c	8 Feb 2007 23:05:08 -0000	1.126
+++ sys/netinet/ip_mroute.c	9 Feb 2007 01:59:45 -0000
@@ -58,9 +58,7 @@
 #include "opt_mac.h"
 #include "opt_mrouting.h"
 
-#ifdef PIM
 #define _PIM_VT 1
-#endif
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -91,10 +89,8 @@
 #include <netinet/ip_mroute.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_options.h>
-#ifdef PIM
 #include <netinet/pim.h>
 #include <netinet/pim_var.h>
-#endif
 #include <netinet/udp.h>
 #include <machine/in_cksum.h>
 
@@ -197,12 +193,27 @@ static u_int	bw_upcalls_n; /* # of pendi
 static struct callout bw_upcalls_ch;
 #define BW_UPCALLS_PERIOD (hz)		/* periodical flush of bw upcalls */
 
-#ifdef PIM
 static struct pimstat pimstat;
+
+SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
 SYSCTL_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD,
     &pimstat, pimstat,
     "PIM Statistics (struct pimstat, netinet/pim_var.h)");
 
+extern  struct domain inetdomain;
+struct protosw in_pim_protosw = {
+	.pr_type =		SOCK_RAW,
+	.pr_domain =		&inetdomain,
+	.pr_protocol =		IPPROTO_PIM,
+	.pr_flags =		PR_ATOMIC|PR_ADDR|PR_LASTHDR,
+	.pr_input =		pim_input,
+	.pr_output =		(pr_output_t*)rip_output,
+	.pr_ctloutput =		rip_ctloutput,
+	.pr_usrreqs =		&rip_usrreqs
+};
+static const struct encaptab *pim_encap_cookie;
+static int pim_encapcheck(const struct mbuf *, int, int, void *);
+
 /*
  * Note: the PIM Register encapsulation adds the following in front of a
  * data packet:
@@ -247,7 +258,6 @@ static struct pim_encap_pimhdr pim_encap
 
 static struct ifnet multicast_register_if;
 static vifi_t reg_vif_num = VIFI_INVALID;
-#endif /* PIM */
 
 /*
  * Private variables.
@@ -296,7 +306,6 @@ static void bw_meter_process(void);
 static void expire_bw_upcalls_send(void *);
 static void expire_bw_meter_process(void *);
 
-#ifdef PIM
 static int pim_register_send(struct ip *, struct vif *,
 		struct mbuf *, struct mfc *);
 static int pim_register_send_rp(struct ip *, struct vif *,
@@ -304,7 +313,6 @@ static int pim_register_send_rp(struct i
 static int pim_register_send_upcall(struct ip *, struct vif *,
 		struct mbuf *, struct mfc *);
 static struct mbuf *pim_register_prepare(struct ip *, struct mbuf *);
-#endif
 
 /*
  * whether or not special PIM assert processing is enabled.
@@ -603,7 +611,7 @@ ip_mrouter_reset(void)
     callout_init(&bw_meter_ch, NET_CALLOUT_MPSAFE);
 }
 
-static struct mtx mrouter_mtx;		/* used to synch init/done work */
+static struct mtx mrouter_mtx;
 
 static void
 if_detached_event(void *arg __unused, struct ifnet *ifp)
@@ -788,9 +796,7 @@ X_ip_mrouter_done(void)
     bzero(bw_meter_timers, sizeof(bw_meter_timers));
     MFC_UNLOCK();
 
-#ifdef PIM
     reg_vif_num = VIFI_INVALID;
-#endif
 
     mtx_unlock(&mrouter_mtx);
 
@@ -883,7 +889,6 @@ add_vif(struct vifctl *vifcp)
     }
 
     /* Find the interface with an address in AF_INET family */
-#ifdef PIM
     if (vifcp->vifc_flags & VIFF_REGISTER) {
 	/*
 	 * XXX: Because VIFF_REGISTER does not really need a valid
@@ -891,9 +896,7 @@ add_vif(struct vifctl *vifcp)
 	 * check its address.
 	 */
 	ifp = NULL;
-    } else
-#endif
-    {
+    } else {
 	sin.sin_addr = vifcp->vifc_lcl_addr;
 	ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
 	if (ifa == NULL) {
@@ -907,7 +910,6 @@ add_vif(struct vifctl *vifcp)
 	log(LOG_ERR, "tunnels are no longer supported\n");
 	VIF_UNLOCK();
 	return EOPNOTSUPP;
-#ifdef PIM
     } else if (vifcp->vifc_flags & VIFF_REGISTER) {
 	ifp = &multicast_register_if;
 	if (mrtdebug)
@@ -918,7 +920,6 @@ add_vif(struct vifctl *vifcp)
 	    multicast_register_if.if_flags = IFF_LOOPBACK;
 	    reg_vif_num = vifcp->vifc_vifi;
 	}
-#endif
     } else {		/* Make sure the interface supports multicast */
 	if ((ifp->if_flags & IFF_MULTICAST) == 0) {
 	    VIF_UNLOCK();
@@ -984,10 +985,8 @@ del_vif_locked(vifi_t vifi)
     if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER)))
 	if_allmulti(vifp->v_ifp, 0);
 
-#ifdef PIM
     if (vifp->v_flags & VIFF_REGISTER)
 	reg_vif_num = VIFI_INVALID;
-#endif
 
     bzero((caddr_t)vifp, sizeof (*vifp));
 
@@ -1571,12 +1570,10 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
      * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
      */
     if (xmt_vif < numvifs) {
-#ifdef PIM
 	if (viftable[xmt_vif].v_flags & VIFF_REGISTER)
-	    pim_register_send(ip, viftable + xmt_vif, m, rt);
+		pim_register_send(ip, viftable + xmt_vif, m, rt);
 	else
-#endif
-	phyint_send(ip, viftable + xmt_vif, m);
+		phyint_send(ip, viftable + xmt_vif, m);
 	return 1;
     }
 
@@ -1603,10 +1600,8 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
 	    struct timeval now;
 	    u_long delta;
 
-#ifdef PIM
 	    if (ifp == &multicast_register_if)
 		pimstat.pims_rcv_registers_wrongiif++;
-#endif
 
 	    /* Get vifi for the incoming packet */
 	    for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++)
@@ -1674,12 +1669,10 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
 	if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) {
 	    viftable[vifi].v_pkt_out++;
 	    viftable[vifi].v_bytes_out += plen;
-#ifdef PIM
 	    if (viftable[vifi].v_flags & VIFF_REGISTER)
 		pim_register_send(ip, viftable + vifi, m, rt);
 	    else
-#endif
-	    phyint_send(ip, viftable + vifi, m);
+		phyint_send(ip, viftable + vifi, m);
 	}
 
     /*
@@ -2516,7 +2509,6 @@ expire_bw_meter_process(void *unused)
  * End of bandwidth monitoring code
  */
 
-#ifdef PIM
 /*
  * Send the packet up to the user daemon, or eventually do kernel encapsulation
  *
@@ -2739,6 +2731,21 @@ pim_register_send_rp(struct ip *ip, stru
  * (used by PIM-SM): the PIM header is stripped off, and the inner packet
  * is passed to if_simloop().
  */
+static int
+pim_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+{
+    struct ip *ip = mtod(m, struct ip *);
+    int hlen = ip->ip_hl << 2;
+
+#ifdef DIAGNOSTIC
+    KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
+#endif
+    if (!IN_MULTICAST(ntohl(((struct ip *)((char *)ip+hlen))->ip_dst.s_addr)))
+	return 0;
+
+    return 64;
+}
+
 void
 pim_input(struct mbuf *m, int off)
 {
@@ -2971,7 +2978,6 @@ pim_input_to_daemon:
 
     return;
 }
-#endif /* PIM */
 
 static int
 ip_mroute_modevent(module_t mod, int type, void *unused)
@@ -2982,6 +2988,15 @@ ip_mroute_modevent(module_t mod, int typ
 	MFC_LOCK_INIT();
 	VIF_LOCK_INIT();
 	ip_mrouter_reset();
+	pim_encap_cookie = encap_attach_func(AF_INET, IPPROTO_PIM,
+	    pim_encapcheck, &in_pim_protosw, NULL);
+	if (pim_encap_cookie == NULL) {
+		printf("ip_mroute: unable to attach pim encap\n");
+		VIF_LOCK_DESTROY();
+		MFC_LOCK_DESTROY();
+		mtx_destroy(&mrouter_mtx);
+		return (EINVAL);
+	}
 	ip_mcast_src = X_ip_mcast_src;
 	ip_mforward = X_ip_mforward;
 	ip_mrouter_done = X_ip_mrouter_done;
@@ -3006,6 +3021,11 @@ ip_mroute_modevent(module_t mod, int typ
 	if (ip_mrouter)
 	    return EINVAL;
 
+	if (pim_encap_cookie) {
+	    encap_detach(pim_encap_cookie);
+	    pim_encap_cookie = NULL;
+	}
+
 	X_ip_mrouter_done();
 	ip_mcast_src = NULL;
 	ip_mforward = NULL;
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to