From d99c7a23fa74a4f765d73ee343104fc6a31c5b8d Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Thu, 16 Mar 1995 16:25:55 +0000 Subject: [PATCH] This set of patches enables IP multicasting to work under FreeBSD. I am submitting them as context diffs for the following files: sys/netinet/ip_mroute.c sys/netinet/ip_var.h sys/netinet/raw_ip.c usr.sbin/mrouted/igmp.c usr.sbin/mrouted/prune.c The routine rip_ip_input in raw_ip.c is suggested by Mark Tinguely (tinguely@plains.nodak.edu). I have been running mrouted with these patches for over a week and nothing has seemed seriously wrong. It is being run in two places on our network as a tunnel on one and a subnet querier on the other. The only problem I have run into is that mrouted on the tunnel must start up last or the pruning isn't done correctly and multicast packets flood your subnets. Submitted by: Soochon Radee --- sys/netinet/ip_mroute.c | 46 +++++++++++++++++++++++----------------- sys/netinet/ip_var.h | 6 +++++- sys/netinet/raw_ip.c | 27 ++++++++++++++++++++--- usr.sbin/mrouted/igmp.c | 6 +++--- usr.sbin/mrouted/prune.c | 14 ++++++++++-- 5 files changed, 71 insertions(+), 28 deletions(-) diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 5afffbb903c2..40b39da73600 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -104,7 +103,7 @@ void multiencap_decap(struct mbuf *m) { /* XXX must fixup manually */ int (*legal_vif_num)(int) = 0; -#else +#else /* MROUTING */ #define INSIZ sizeof(struct in_addr) #define same(a1, a2) \ @@ -121,7 +120,7 @@ struct socket *ip_mrouter = NULL; struct mrtstat mrtstat; int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ -#else +#else /* MROUTE_LKM */ extern struct mrtstat mrtstat; extern int ip_mrtproto; #endif @@ -177,6 +176,7 @@ struct ip multicast_encap_iphdr = { * Private variables. */ static vifi_t numvifs = 0; +static void (*encap_oldrawip)() = 0; /* * one-back cache used by multiencap_decap to locate a tunnel's vif @@ -212,6 +212,7 @@ void tbf_send_packet(struct vif *, struct mbuf *, struct ip_moptions *); void tbf_update_tokens(struct vif *); static int priority(struct vif *, struct ip *); static int ip_mrouter_init(struct socket *); +void multiencap_decap(struct mbuf *m); /* * A simple hash function: returns MFCHASHMOD of the low-order octet of @@ -580,13 +581,17 @@ add_vif(vifcp) if (vifcp->vifc_flags & VIFF_TUNNEL) { if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) { - static int inited = 0; - if(!inited) { + if (encap_oldrawip == 0) { + extern struct protosw inetsw[]; + extern u_char ip_protox[]; + register u_char pr = ip_protox[ENCAP_PROTO]; + + encap_oldrawip = inetsw[pr].pr_input; + inetsw[pr].pr_input = multiencap_decap; for (s = 0; s < MAXVIFS; ++s) { multicast_decap_if[s].if_name = "mdecap"; multicast_decap_if[s].if_unit = s; } - inited = 1; } ifp = &multicast_decap_if[vifcp->vifc_vifi]; } else { @@ -931,8 +936,9 @@ X_ip_mforward(ip, ifp, m, imo) int s; if (mrtdebug > 1) - log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %x\n", - ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp); + log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %x (%s%d)\n", + ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp, + ifp->if_name, ifp->if_unit); if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) { @@ -1119,9 +1125,7 @@ X_ip_mforward(ip, ifp, m, imo) mrtstat.mrts_upcalls++; - raw_input(mm, &k_igmpproto, - (struct sockaddr *)&k_igmpsrc, - (struct sockaddr *)&k_igmpdst); + rip_ip_input(mm, ip_mrouter, (struct sockaddr *)&k_igmpsrc); /* set timer to cleanup entry if upcall is lost */ timeout(cleanup_cache, (caddr_t)mb_rt, 100); @@ -1519,15 +1523,19 @@ multiencap_decap(m) mrtstat.mrts_cant_tunnel++; /*XXX*/ m_freem(m); if (mrtdebug) - log(LOG_DEBUG, "ip_mforward: no tunnel with %u\n", + log(LOG_DEBUG, "ip_mforward: no tunnel with %x\n", ntohl(ip->ip_src.s_addr)); return; } ifp = vifp->v_ifp; - hlen -= sizeof(struct ifnet *); - m->m_data += hlen; - m->m_len -= hlen; - *(mtod(m, struct ifnet **)) = ifp; + + if (hlen > IP_HDR_LEN) + ip_stripoptions(m, (struct mbuf *) 0); + m->m_data += IP_HDR_LEN; + m->m_len -= IP_HDR_LEN; + m->m_pkthdr.len -= IP_HDR_LEN; + m->m_pkthdr.rcvif = ifp; + ifq = &ipintrq; s = splimp(); if (IF_QFULL(ifq)) { @@ -1879,8 +1887,8 @@ ip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd) ip_mforward = X_ip_mforward; old_mrt_ioctl = mrt_ioctl; mrt_ioctl = X_mrt_ioctl; - old_proto4_input = inetsw[ip_protox[IPPROTO_ENCAP]].pr_input; - inetsw[ip_protox[IPPROTO_ENCAP]].pr_input = X_multiencap_decap; + old_proto4_input = inetsw[ip_protox[ENCAP_PROTO]].pr_input; + inetsw[ip_protox[ENCAP_PROTO]].pr_input = X_multiencap_decap; old_legal_vif_num = legal_vif_num; legal_vif_num = X_legal_vif_num; ip_mrtproto = IGMP_DVMRP; @@ -1896,7 +1904,7 @@ ip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd) ip_mrouter_done = old_ip_mrouter_done; ip_mforward = old_ip_mforward; mrt_ioctl = old_mrt_ioctl; - inetsw[ip_protox[IPPROTO_ENCAP]].pr_input = old_proto4_input; + inetsw[ip_protox[ENCAP_PROTO]].pr_input = old_proto4_input; legal_vif_num = old_legal_vif_num; ip_mrtproto = 0; break; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 08e0c57b31dd..5ac0e8060292 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_var.h 8.1 (Berkeley) 6/10/93 - * $Id: ip_var.h,v 1.6 1994/09/14 03:10:14 wollman Exp $ + * $Id: ip_var.h,v 1.7 1995/02/14 06:25:17 phk Exp $ */ #ifndef _NETINET_IP_VAR_H_ @@ -194,6 +194,10 @@ int rip_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *)); int ip_rsvp_init __P((struct socket *)); int ip_rsvp_done __P((void)); + +void rip_ip_input __P((struct mbuf *mm, + register struct socket *ip_mrouter, struct sockaddr *src)); + #endif #endif diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 4fcc900cff5f..95fe7a65dde3 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94 - * $Id: raw_ip.c,v 1.14 1995/02/07 02:53:14 wollman Exp $ + * $Id: raw_ip.c,v 1.15 1995/02/14 06:24:40 phk Exp $ */ #include @@ -96,10 +96,10 @@ rip_input(m) if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) continue; if (inp->inp_laddr.s_addr && - inp->inp_laddr.s_addr == ip->ip_dst.s_addr) + inp->inp_laddr.s_addr != ip->ip_dst.s_addr) continue; if (inp->inp_faddr.s_addr && - inp->inp_faddr.s_addr == ip->ip_src.s_addr) + inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; if (last) { struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); @@ -123,6 +123,27 @@ rip_input(m) sorwakeup(last); } else { m_freem(m); + ipstat.ips_noproto++; + ipstat.ips_delivered--; + } +} + +void rip_ip_input(mm, ip_mrouter, src) + struct mbuf *mm; + register struct socket *ip_mrouter; + struct sockaddr *src; +{ + if (ip_mrouter) + { + if (sbappendaddr(&ip_mrouter->so_rcv, src, + mm, (struct mbuf *) 0) == 0) + m_freem(mm); + else + sorwakeup(ip_mrouter); + } + else + { + m_freem(mm); ipstat.ips_noproto++; ipstat.ips_delivered--; } diff --git a/usr.sbin/mrouted/igmp.c b/usr.sbin/mrouted/igmp.c index 7ddf3bc115a7..ce5c1cebf28c 100644 --- a/usr.sbin/mrouted/igmp.c +++ b/usr.sbin/mrouted/igmp.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: igmp.c,v 1.8 1994/08/24 23:53:32 thyagara Exp $ + * igmp.c,v 1.2 1994/09/08 02:51:15 wollman Exp */ @@ -181,12 +181,12 @@ void accept_igmp(recvlen) case DVMRP_PROBE: accept_probe(src, dst, - (char *)(igmp+1), igmpdatalen, group); + (char *)(igmp+1), igmpdatalen, ntohl(group)); return; case DVMRP_REPORT: accept_report(src, dst, - (char *)(igmp+1), igmpdatalen, group); + (char *)(igmp+1), igmpdatalen, ntohl(group)); return; case DVMRP_ASK_NEIGHBORS: diff --git a/usr.sbin/mrouted/prune.c b/usr.sbin/mrouted/prune.c index 04387a1cfe71..dfab604fece0 100644 --- a/usr.sbin/mrouted/prune.c +++ b/usr.sbin/mrouted/prune.c @@ -7,7 +7,7 @@ * Leland Stanford Junior University. * * - * $Id: prune.c,v 1.4 1994/08/24 23:54:33 thyagara Exp $ + * $Id: prune.c,v 1.2 1994/09/08 02:51:23 wollman Exp $ */ @@ -530,7 +530,12 @@ void send_prune(kt) *p++ = ((char *)&(kt->kt_origin))[i]; for (i = 0; i < 4; i++) *p++ = ((char *)&(kt->kt_mcastgrp))[i]; +#if BYTE_ORDER == BIG_ENDIAN for (i = 0; i < 4; i++) +#endif +#if BYTE_ORDER == LITTLE_ENDIAN + for (i = 3; i >= 0; i--) +#endif *p++ = ((char *)&(kt->kt_prsent_timer))[i]; datalen += 12; @@ -589,7 +594,12 @@ void accept_prune(src, dst, p, datalen) ((char *)&prun_src)[i] = *p++; for (i = 0; i< 4; i++) ((char *)&prun_dst)[i] = *p++; +#if BYTE_ORDER == BIG_ENDIAN for (i = 0; i< 4; i++) +#endif +#if BYTE_ORDER == LITTLE_ENDIAN + for (i = 3; i >= 0; i--) +#endif ((char *)&prun_tmr)[i] = *p++; kt = find_src_grp(prun_src, prun_dst); @@ -1051,7 +1061,7 @@ void age_table_entry() krl; prev_krl = krl, krl = krl->rl_next) { if ((krl->rl_timer -= ROUTE_MAX_REPORT_DELAY) <= 0) { - log(LOG_DEBUG, 0, "forw again s %x g%x on vif %d", + log(LOG_DEBUG, 0, "forw again s %x g %x on vif %d", kt->kt_origin, kt->kt_mcastgrp, krl->rl_vifi); if (!VIFM_ISSET(krl->rl_vifi, kt->kt_grpmems)) {