Subject: Multicast routing and unnumbered point-to-point interfaces
To: None <tech-net@netbsd.org>
From: Jason R Thorpe <thorpej@zembu.com>
List: tech-net
Date: 10/05/2000 15:24:34
--BOKacYhQ+x31HxR3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Folks...
I have routers with a large number of unnumbered point-to-point
interfaces (`gif' tunnels), and I need to do multicast routing
on them.
This required some hacking in mrouted and the kernel in order to
decouple the notion of "IP address" from "interface identifier".
I did this in two stages:
- Rip out support for mrouted-created v4-in-v4 tunnels.
They are wire-compatible with gif(4), which is more
generic, so we should just use the generic mechanism.
- Changed the MRT_ADD_VIF socket option to pass an
interface name rather than an IP address. I left
the old version in there as OMRT_ADD_VIF so that
old mrouted(8) versions would continue to work, so
long as they did not use VIFF_TUNNEL (which could
not work, since I ripped out all the kernel support
for it :-).
I still have some changes to mrouted(8) to make, and some debugging
and more hacking to do, but I wanted to present this idea here in the
hopes of folding it back into NetBSD, rather than maintaining this
local change forever.
Kernel diff attached. Please comment.
--
-- Jason R. Thorpe <thorpej@zembu.com>
--BOKacYhQ+x31HxR3
Content-Type: text/plain; charset=us-ascii
Content-Description: ip_mroute.diff
Content-Disposition: attachment; filename=foo
Index: ip_mroute.c
===================================================================
RCS file: /home/cvsfiles/netbsd/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.1.1.2
retrieving revision 1.6
diff -c -r1.1.1.2 -r1.6
*** ip_mroute.c 2000/04/25 00:37:11 1.1.1.2
--- ip_mroute.c 2000/10/05 21:19:52 1.6
***************
*** 10,15 ****
--- 10,16 ----
* Modified by Ajit Thyagarajan, PARC, August 1993
* Modified by Bill Fenner, PARC, April 1994
* Modified by Charles M. Hannum, NetBSD, May 1995.
+ * Modified by Jason R. Thorpe, Zembu Labs, October 2000.
*
* MROUTING Revision: 1.2
*/
***************
*** 97,103 ****
--- 98,106 ----
static int get_version __P((struct mbuf *));
static int set_assert __P((struct mbuf *));
static int get_assert __P((struct mbuf *));
+ static int oadd_vif __P((struct mbuf *));
static int add_vif __P((struct mbuf *));
+ static int add_vif_common __P((struct vifctl *, struct ifnet *));
static int del_vif __P((struct mbuf *));
static void update_mfc __P((struct mfcctl *, struct mfc *));
static void expire_mfc __P((struct mfc *));
***************
*** 115,121 ****
static int ip_mdq __P((struct mbuf *, struct ifnet *, struct mfc *));
#endif
static void phyint_send __P((struct ip *, struct vif *, struct mbuf *));
- static void encap_send __P((struct ip *, struct vif *, struct mbuf *));
static void tbf_control __P((struct vif *, struct mbuf *, struct ip *,
u_int32_t));
static void tbf_queue __P((struct vif *, struct mbuf *));
--- 118,123 ----
***************
*** 138,177 ****
struct ifnet multicast_decap_if[MAXVIFS];
#endif
- #define ENCAP_TTL 64
- #define ENCAP_PROTO IPPROTO_IPIP /* 4 */
-
- /* prototype IP hdr for encapsulated packets */
- struct ip multicast_encap_iphdr = {
- #if BYTE_ORDER == LITTLE_ENDIAN
- sizeof(struct ip) >> 2, IPVERSION,
- #else
- IPVERSION, sizeof(struct ip) >> 2,
- #endif
- 0, /* tos */
- sizeof(struct ip), /* total length */
- 0, /* id */
- 0, /* frag offset */
- ENCAP_TTL, ENCAP_PROTO,
- 0, /* checksum */
- };
-
/*
* Private variables.
*/
static vifi_t numvifs = 0;
- static int have_encap_tunnel = 0;
static struct callout expire_upcalls_ch;
/*
- * one-back cache used by mrt_ipip_input to locate a tunnel's vif
- * given a datagram's src ip address.
- */
- static struct in_addr last_encap_src;
- static struct vif *last_encap_vif;
-
- /*
* whether or not special PIM assert processing is enabled.
*/
static int pim_assert;
--- 140,153 ----
***************
*** 250,255 ****
--- 226,234 ----
case MRT_DONE:
error = ip_mrouter_done();
break;
+ case OMRT_ADD_VIF:
+ error = oadd_vif(*m);
+ break;
case MRT_ADD_VIF:
error = add_vif(*m);
break;
***************
*** 444,450 ****
/* Clear out all the vifs currently in use. */
for (vifi = 0; vifi < numvifs; vifi++) {
vifp = &viftable[vifi];
! if (!in_nullhost(vifp->v_lcl_addr))
reset_vif(vifp);
}
--- 423,429 ----
/* Clear out all the vifs currently in use. */
for (vifi = 0; vifi < numvifs; vifi++) {
vifp = &viftable[vifi];
! if (vifp->v_ifp != NULL)
reset_vif(vifp);
}
***************
*** 469,477 ****
free(mfchashtbl, M_MRTABLE);
mfchashtbl = 0;
- /* Reset de-encapsulation cache. */
- have_encap_tunnel = 0;
-
ip_mrouter = 0;
splx(s);
--- 448,453 ----
***************
*** 527,554 ****
static struct sockaddr_in sin = { sizeof(sin), AF_INET };
/*
! * Add a vif to the vif table
*/
static int
! add_vif(m)
struct mbuf *m;
{
! struct vifctl *vifcp;
! struct vif *vifp;
struct ifaddr *ifa;
struct ifnet *ifp;
! struct ifreq ifr;
! int error, s;
!
! if (m == 0 || m->m_len < sizeof(struct vifctl))
return (EINVAL);
! vifcp = mtod(m, struct vifctl *);
if (vifcp->vifc_vifi >= MAXVIFS)
return (EINVAL);
! vifp = &viftable[vifcp->vifc_vifi];
! if (!in_nullhost(vifp->v_lcl_addr))
return (EADDRINUSE);
/* Find the interface with an address in AF_INET family. */
--- 503,534 ----
static struct sockaddr_in sin = { sizeof(sin), AF_INET };
/*
! * Add a vif to the vif table. This supports the older,
! * IP address-based ioctl.
*/
static int
! oadd_vif(m)
struct mbuf *m;
{
! struct ovifctl *vifcp;
struct ifaddr *ifa;
struct ifnet *ifp;
!
! if (m == 0 || m->m_len < sizeof(struct ovifctl))
return (EINVAL);
! vifcp = mtod(m, struct ovifctl *);
if (vifcp->vifc_vifi >= MAXVIFS)
return (EINVAL);
! /*
! * Tunnel vifs are deprecated. Do not allow them
! * to be added.
! */
! if (vifcp->vifc_flags & (OVIFF_TUNNEL|OVIFF_SRCRT))
! return (EINVAL);
!
! if (viftable[vifcp->vifc_vifi].v_ifp != NULL)
return (EADDRINUSE);
/* Find the interface with an address in AF_INET family. */
***************
*** 556,595 ****
ifa = ifa_ifwithaddr(sintosa(&sin));
if (ifa == 0)
return (EADDRNOTAVAIL);
-
- if (vifcp->vifc_flags & VIFF_TUNNEL) {
- if (vifcp->vifc_flags & VIFF_SRCRT) {
- log(LOG_ERR, "Source routed tunnels not supported\n");
- return (EOPNOTSUPP);
- }
! /* Create a fake encapsulation interface. */
! ifp = (struct ifnet *)malloc(sizeof(*ifp), M_MRTABLE, M_WAITOK);
! bzero(ifp, sizeof(*ifp));
! sprintf(ifp->if_xname, "mdecap%d", vifcp->vifc_vifi);
! /* Prepare cached route entry. */
! bzero(&vifp->v_route, sizeof(vifp->v_route));
! /* Tell mrt_ipip_input() to start looking at encapsulated packets. */
! have_encap_tunnel = 1;
! } else {
! /* Use the physical interface associated with the address. */
! ifp = ifa->ifa_ifp;
! /* Make sure the interface supports multicast. */
! if ((ifp->if_flags & IFF_MULTICAST) == 0)
! return (EOPNOTSUPP);
!
! /* Enable promiscuous reception of all IP multicasts. */
! satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
! satosin(&ifr.ifr_addr)->sin_family = AF_INET;
! satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
! error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
! if (error)
! return (error);
}
s = splsoftnet();
/* Define parameters for the tbf structure. */
--- 536,625 ----
ifa = ifa_ifwithaddr(sintosa(&sin));
if (ifa == 0)
return (EADDRNOTAVAIL);
! /* Use the physical interface associated with the address. */
! ifp = ifa->ifa_ifp;
! /* Make sure the interface supports multicast. */
! if ((ifp->if_flags & IFF_MULTICAST) == 0)
! return (EOPNOTSUPP);
! /*
! * The portion of the vifctl structre that we are interested in
! * is the same between the old and new versions of the strucutre,
! * so we just access it as if it were the new one.
! */
! return (add_vif_common((struct vifctl *)vifcp, ifp));
! }
! /*
! * Add a vif to the vif table. This is the new,
! * interface-name based version.
! */
! static int
! add_vif(m)
! struct mbuf *m;
! {
! struct vifctl *vifcp;
! struct ifnet *ifp;
! struct ifaddr *ifa;
!
! if (m == 0 || m->m_len < sizeof(struct vifctl))
! return (EINVAL);
!
! vifcp = mtod(m, struct vifctl *);
! if (vifcp->vifc_vifi >= MAXVIFS)
! return (EINVAL);
!
! if (viftable[vifcp->vifc_vifi].v_ifp != NULL)
! return (EADDRINUSE);
!
! /* Find the interface. */
! vifcp->vifc_ifname[sizeof(vifcp->vifc_ifname) - 1] = '\0';
! ifp = ifunit(vifcp->vifc_ifname);
! if (ifp == NULL)
! return (ENXIO);
!
! /* Make sure the interface has at least one AF_INET address. */
! for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
! ifa = TAILQ_NEXT(ifa, ifa_list)) {
! if (ifa->ifa_addr->sa_family == AF_INET)
! break;
}
+ if (ifa == NULL)
+ return (EADDRNOTAVAIL);
+
+ /* Make sure the interface supports multicast. */
+ if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ return (EOPNOTSUPP);
+ /*
+ * The portion of the vifctl structre that we are interested in
+ * is the same between the old and new versions of the strucutre,
+ * so we just access it as if it were the new one.
+ */
+ return (add_vif_common(vifcp, ifp));
+ }
+
+ int
+ add_vif_common(vifcp, ifp)
+ struct vifctl *vifcp;
+ struct ifnet *ifp;
+ {
+ struct ifreq ifr;
+ struct vif *vifp;
+ int error, s;
+
+ vifp = &viftable[vifcp->vifc_vifi];
+
+ /* Enable promiscuous reception of all IP multicasts. */
+ satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
+ satosin(&ifr.ifr_addr)->sin_family = AF_INET;
+ satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
+ error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
+ if (error)
+ return (error);
+
s = splsoftnet();
/* Define parameters for the tbf structure. */
***************
*** 604,611 ****
vifp->v_threshold = vifcp->vifc_threshold;
/* scaling up here allows division by 1024 in critical code */
vifp->v_rate_limit = vifcp->vifc_rate_limit * 1024 / 1000;
- vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
- vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
vifp->v_ifp = ifp;
/* Initialize per vif pkt counters. */
vifp->v_pkt_in = 0;
--- 634,639 ----
***************
*** 621,637 ****
#endif /* RSVP_ISI */
splx(s);
!
/* Adjust numvifs up if the vifi is higher than numvifs. */
if (numvifs <= vifcp->vifc_vifi)
numvifs = vifcp->vifc_vifi + 1;
!
if (mrtdebug)
! log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n",
vifcp->vifc_vifi,
! ntohl(vifcp->vifc_lcl_addr.s_addr),
! (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
! ntohl(vifcp->vifc_rmt_addr.s_addr),
vifcp->vifc_threshold,
vifcp->vifc_rate_limit);
--- 649,664 ----
#endif /* RSVP_ISI */
splx(s);
!
/* Adjust numvifs up if the vifi is higher than numvifs. */
if (numvifs <= vifcp->vifc_vifi)
numvifs = vifcp->vifc_vifi + 1;
!
if (mrtdebug)
! log(LOG_DEBUG,
! "add_vif #%d, interface %s, thresh %x, rate %d\n",
vifcp->vifc_vifi,
! ifp->if_xname,
vifcp->vifc_threshold,
vifcp->vifc_rate_limit);
***************
*** 653,671 ****
m_freem(m);
}
! if (vifp->v_flags & VIFF_TUNNEL) {
! free(vifp->v_ifp, M_MRTABLE);
! if (vifp == last_encap_vif) {
! last_encap_vif = 0;
! last_encap_src = zeroin_addr;
! }
! } else {
! satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
! satosin(&ifr.ifr_addr)->sin_family = AF_INET;
! satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
! ifp = vifp->v_ifp;
! (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
! }
bzero((caddr_t)vifp, sizeof(*vifp));
}
--- 680,691 ----
m_freem(m);
}
! satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
! satosin(&ifr.ifr_addr)->sin_family = AF_INET;
! satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
! ifp = vifp->v_ifp;
! (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
!
bzero((caddr_t)vifp, sizeof(*vifp));
}
***************
*** 689,695 ****
return (EINVAL);
vifp = &viftable[*vifip];
! if (in_nullhost(vifp->v_lcl_addr))
return (EADDRNOTAVAIL);
s = splsoftnet();
--- 709,715 ----
return (EINVAL);
vifp = &viftable[*vifip];
! if (vifp->v_ifp == NULL)
return (EADDRNOTAVAIL);
s = splsoftnet();
***************
*** 698,704 ****
/* Adjust numvifs down */
for (vifi = numvifs; vifi > 0; vifi--)
! if (!in_nullhost(viftable[vifi-1].v_lcl_addr))
break;
numvifs = vifi;
--- 718,724 ----
/* Adjust numvifs down */
for (vifi = numvifs; vifi > 0; vifi--)
! if (viftable[vifi - 1].v_ifp != NULL)
break;
numvifs = vifi;
***************
*** 999,1007 ****
ip->ip_ttl++; /* compensate for -1 in *_send routines */
if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
vifp = viftable + vifi;
! printf("Sending IPPROTO_RSVP from %x to %x on vif %d (%s%s)\n",
ntohl(ip->ip_src), ntohl(ip->ip_dst), vifi,
- (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",
vifp->v_ifp->if_xname);
}
return (ip_mdq(m, ifp, (struct mfc *)0, vifi));
--- 1019,1026 ----
ip->ip_ttl++; /* compensate for -1 in *_send routines */
if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
vifp = viftable + vifi;
! printf("Sending IPPROTO_RSVP from %x to %x on vif %d (%s)\n",
ntohl(ip->ip_src), ntohl(ip->ip_dst), vifi,
vifp->v_ifp->if_xname);
}
return (ip_mdq(m, ifp, (struct mfc *)0, vifi));
***************
*** 1234,1239 ****
--- 1253,1259 ----
vifi_t xmt_vif;
#endif /* RSVP_ISI */
{
+ struct in_ifaddr *ia;
struct ip *ip = mtod(m, struct ip *);
vifi_t vifi;
struct vif *vifp;
***************
*** 1244,1255 ****
* input, they shouldn't get counted on output, so statistics keeping is
* seperate.
*/
! #define MC_SEND(ip,vifp,m) { \
! if ((vifp)->v_flags & VIFF_TUNNEL) \
! encap_send((ip), (vifp), (m)); \
! else \
! phyint_send((ip), (vifp), (m)); \
! }
#ifdef RSVP_ISI
/*
--- 1264,1270 ----
* input, they shouldn't get counted on output, so statistics keeping is
* seperate.
*/
! #define MC_SEND(ip,vifp,m) phyint_send((ip), (vifp), (m))
#ifdef RSVP_ISI
/*
***************
*** 1280,1287 ****
* interface (and not a tunnel), send a message to the routing daemon.
*/
if (pim_assert && rt->mfc_ttls[vifi] &&
! (ifp->if_flags & IFF_BROADCAST) &&
! !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
struct mbuf *mm;
struct igmpmsg *im;
int hlen = ip->ip_hl << 2;
--- 1295,1301 ----
* interface (and not a tunnel), send a message to the routing daemon.
*/
if (pim_assert && rt->mfc_ttls[vifi] &&
! (ifp->if_flags & IFF_BROADCAST)) {
struct mbuf *mm;
struct igmpmsg *im;
int hlen = ip->ip_hl << 2;
***************
*** 1315,1321 ****
}
/* If I sourced this packet, it counts as output, else it was input. */
! if (in_hosteq(ip->ip_src, viftable[vifi].v_lcl_addr)) {
viftable[vifi].v_pkt_out++;
viftable[vifi].v_bytes_out += plen;
} else {
--- 1329,1336 ----
}
/* If I sourced this packet, it counts as output, else it was input. */
! INADDR_TO_IA(ip->ip_src, ia);
! if (ia != NULL) {
viftable[vifi].v_pkt_out++;
viftable[vifi].v_bytes_out += plen;
} else {
***************
*** 1383,1529 ****
tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len);
}
- static void
- encap_send(ip, vifp, m)
- struct ip *ip;
- struct vif *vifp;
- struct mbuf *m;
- {
- struct mbuf *mb_copy;
- struct ip *ip_copy;
- int i, len = ip->ip_len + sizeof(multicast_encap_iphdr);
-
- /*
- * copy the old packet & pullup it's IP header into the
- * new mbuf so we can modify it. Try to fill the new
- * mbuf since if we don't the ethernet driver will.
- */
- MGETHDR(mb_copy, M_DONTWAIT, MT_DATA);
- if (mb_copy == 0)
- return;
- mb_copy->m_data += max_linkhdr;
- mb_copy->m_pkthdr.len = len;
- mb_copy->m_len = sizeof(multicast_encap_iphdr);
-
- if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == 0) {
- m_freem(mb_copy);
- return;
- }
- i = MHLEN - max_linkhdr;
- if (i > len)
- i = len;
- mb_copy = m_pullup(mb_copy, i);
- if (mb_copy == 0)
- return;
-
- /*
- * fill in the encapsulating IP header.
- */
- ip_copy = mtod(mb_copy, struct ip *);
- *ip_copy = multicast_encap_iphdr;
- ip_copy->ip_id = htons(ip_id++);
- ip_copy->ip_len = len;
- ip_copy->ip_src = vifp->v_lcl_addr;
- ip_copy->ip_dst = vifp->v_rmt_addr;
-
- /*
- * turn the encapsulated IP header back into a valid one.
- */
- ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr));
- --ip->ip_ttl;
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
- ip->ip_sum = 0;
- mb_copy->m_data += sizeof(multicast_encap_iphdr);
- ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
- mb_copy->m_data -= sizeof(multicast_encap_iphdr);
-
- if (vifp->v_rate_limit <= 0)
- tbf_send_packet(vifp, mb_copy);
- else
- tbf_control(vifp, mb_copy, ip, ip_copy->ip_len);
- }
-
/*
- * De-encapsulate a packet and feed it back through ip input (this
- * routine is called whenever IP gets a packet with proto type
- * ENCAP_PROTO and a local destination address).
- *
- * Return 1 if we handled the packet, 0 if we did not.
- *
- * Called from encap4_input() in sys/netinet/ip_encap.c.
- */
- int
- mrt_ipip_input(m, hlen)
- struct mbuf *m;
- int hlen;
- {
- struct ip *ip = mtod(m, struct ip *);
- int s;
- struct ifqueue *ifq;
- struct vif *vifp;
-
- if (!have_encap_tunnel)
- return (0);
-
- /*
- * dump the packet if it's not to a multicast destination or if
- * we don't have an encapsulating tunnel with the source.
- * Note: This code assumes that the remote site IP address
- * uniquely identifies the tunnel (i.e., that this site has
- * at most one tunnel with the remote site).
- */
- if (!IN_MULTICAST(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr)) {
- ++mrtstat.mrts_bad_tunnel;
- return (0);
- }
-
- if (!in_hosteq(ip->ip_src, last_encap_src)) {
- struct vif *vife;
-
- vifp = viftable;
- vife = vifp + numvifs;
- for (; vifp < vife; vifp++)
- if (vifp->v_flags & VIFF_TUNNEL &&
- in_hosteq(vifp->v_rmt_addr, ip->ip_src))
- break;
- if (vifp == vife) {
- mrtstat.mrts_cant_tunnel++; /*XXX*/
- if (mrtdebug)
- log(LOG_DEBUG,
- "ip_mforward: no tunnel with %x\n",
- ntohl(ip->ip_src.s_addr));
- return (0);
- }
- last_encap_vif = vifp;
- last_encap_src = ip->ip_src;
- } else
- vifp = last_encap_vif;
-
- m->m_data += hlen;
- m->m_len -= hlen;
- m->m_pkthdr.len -= hlen;
- m->m_pkthdr.rcvif = vifp->v_ifp;
- ifq = &ipintrq;
- s = splimp();
- if (IF_QFULL(ifq)) {
- IF_DROP(ifq);
- m_freem(m);
- } else {
- IF_ENQUEUE(ifq, m);
- /*
- * normally we would need a "schednetisr(NETISR_IP)"
- * here but we were called by ip_input and it is going
- * to loop back & try to dequeue the packet we just
- * queued as soon as we return so we avoid the
- * unnecessary software interrrupt.
- */
- }
- splx(s);
- return (1);
- }
-
- /*
* Token bucket filter module
*/
static void
--- 1398,1404 ----
***************
*** 1683,1721 ****
struct vif *vifp;
struct mbuf *m;
{
int error;
int s = splsoftnet();
-
- if (vifp->v_flags & VIFF_TUNNEL) {
- /* If tunnel options */
- #ifdef IPSEC
- /* Don't lookup socket in forwading case */
- ipsec_setsocket(m, NULL);
- #endif
- ip_output(m, (struct mbuf *)0, &vifp->v_route,
- IP_FORWARDING, (struct ip_moptions *)0);
- } else {
- /* if physical interface option, extract the options and then send */
- struct ip_moptions imo;
! imo.imo_multicast_ifp = vifp->v_ifp;
! imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
! imo.imo_multicast_loop = 1;
#ifdef RSVP_ISI
! imo.imo_multicast_vif = -1;
#endif
#ifdef IPSEC
! /* Don't lookup socket in forwading case */
! ipsec_setsocket(m, NULL);
#endif
! error = ip_output(m, (struct mbuf *)0, (struct route *)0,
! IP_FORWARDING|IP_MULTICASTOPTS, &imo);
! if (mrtdebug & DEBUG_XMIT)
! log(LOG_DEBUG, "phyint_send on vif %ld err %d\n",
! (long)(vifp-viftable), error);
! }
splx(s);
}
--- 1558,1584 ----
struct vif *vifp;
struct mbuf *m;
{
+ struct ip_moptions imo;
int error;
int s = splsoftnet();
! imo.imo_multicast_ifp = vifp->v_ifp;
! imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
! imo.imo_multicast_loop = 1;
#ifdef RSVP_ISI
! imo.imo_multicast_vif = -1;
#endif
#ifdef IPSEC
! /* Don't lookup socket in forwading case */
! ipsec_setsocket(m, NULL);
#endif
! error = ip_output(m, (struct mbuf *)0, (struct route *)0,
! IP_FORWARDING|IP_MULTICASTOPTS, &imo);
! if (mrtdebug & DEBUG_XMIT)
! log(LOG_DEBUG, "phyint_send on vif %ld err %d\n",
! (long)(vifp-viftable), error);
splx(s);
}
Index: ip_mroute.h
===================================================================
RCS file: /home/cvsfiles/netbsd/src/sys/netinet/ip_mroute.h,v
retrieving revision 1.1.1.1
retrieving revision 1.6
diff -c -r1.1.1.1 -r1.6
*** ip_mroute.h 2000/03/31 20:00:36 1.1.1.1
--- ip_mroute.h 2000/10/05 21:19:52 1.6
***************
*** 7,12 ****
--- 7,13 ----
* Modified by Steve Deering, Stanford, February 1989.
* Modified by Ajit Thyagarajan, PARC, August 1993.
* Modified by Ajit Thyagarajan, PARC, August 1994.
+ * Modified by Jason R. Thorpe, Zembu Labs, October 2000.
*
* MROUTING Revision: 1.2
*/
***************
*** 17,33 ****
#include <sys/queue.h>
#include <sys/callout.h>
/*
* Multicast Routing set/getsockopt commands.
*/
#define MRT_INIT 100 /* initialize forwarder */
#define MRT_DONE 101 /* shut down forwarder */
! #define MRT_ADD_VIF 102 /* create virtual interface */
#define MRT_DEL_VIF 103 /* delete virtual interface */
#define MRT_ADD_MFC 104 /* insert forwarding cache entry */
#define MRT_DEL_MFC 105 /* delete forwarding cache entry */
#define MRT_VERSION 106 /* get kernel version number */
#define MRT_ASSERT 107 /* enable PIM assert processing */
/*
--- 18,37 ----
#include <sys/queue.h>
#include <sys/callout.h>
+ #include <net/if.h>
+
/*
* Multicast Routing set/getsockopt commands.
*/
#define MRT_INIT 100 /* initialize forwarder */
#define MRT_DONE 101 /* shut down forwarder */
! #define OMRT_ADD_VIF 102 /* old create virtual interface */
#define MRT_DEL_VIF 103 /* delete virtual interface */
#define MRT_ADD_MFC 104 /* insert forwarding cache entry */
#define MRT_DEL_MFC 105 /* delete forwarding cache entry */
#define MRT_VERSION 106 /* get kernel version number */
#define MRT_ASSERT 107 /* enable PIM assert processing */
+ #define MRT_ADD_VIF 108 /* create virtual interface */
/*
***************
*** 45,58 ****
#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom))
#define VIFM_SAME(m1, m2) ((m1) == (m2))
! #define VIFF_TUNNEL 0x1 /* vif represents a tunnel end-point */
! #define VIFF_SRCRT 0x2 /* tunnel uses IP src routing */
/*
! * Argument structure for MRT_ADD_VIF.
* (MRT_DEL_VIF takes a single vifi_t argument.)
*/
! struct vifctl {
vifi_t vifc_vifi; /* the index of the vif to be added */
u_int8_t vifc_flags; /* VIFF_ flags defined below */
u_int8_t vifc_threshold; /* min ttl required to forward on vif */
--- 49,68 ----
#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom))
#define VIFM_SAME(m1, m2) ((m1) == (m2))
! #ifdef _KERNEL
! /*
! * These flags were used for "tunnel" vifs, and are deprecated. We
! * rename them to break old source, but keep them around in order
! * to return sane errors to userland routing daemons.
! */
! #define OVIFF_TUNNEL 0x01
! #define OVIFF_SRCRT 0x02
/*
! * Argument structure for OMRT_ADD_VIF.
* (MRT_DEL_VIF takes a single vifi_t argument.)
*/
! struct ovifctl {
vifi_t vifc_vifi; /* the index of the vif to be added */
u_int8_t vifc_flags; /* VIFF_ flags defined below */
u_int8_t vifc_threshold; /* min ttl required to forward on vif */
***************
*** 60,65 ****
--- 70,88 ----
struct in_addr vifc_lcl_addr;/* local interface address */
struct in_addr vifc_rmt_addr;/* remote address (tunnels only) */
};
+ #endif /* _KERNEL */
+
+ /*
+ * Argument structure for MRT_ADD_VIF.
+ * (MRT_DEL_VIF takes a single vifi_t argument.)
+ */
+ struct vifctl {
+ vifi_t vifc_vifi; /* the index of the vif to be added */
+ u_int8_t vifc_flags; /* VIFF_ flags */
+ u_int8_t vifc_threshold; /* min ttl required to forward on vif */
+ u_int32_t vifc_rate_limit; /* max rate */
+ char vifc_ifname[IFNAMSIZ];/* interface name */
+ };
/*
* Argument structure for MRT_ADD_MFC and MRT_DEL_MFC.
***************
*** 130,143 ****
u_int8_t v_flags; /* VIFF_ flags defined above */
u_int8_t v_threshold; /* min ttl required to forward on vif */
u_int32_t v_rate_limit; /* max rate */
- struct in_addr v_lcl_addr; /* local interface address */
- struct in_addr v_rmt_addr; /* remote address (tunnels only) */
struct ifnet *v_ifp; /* pointer to interface */
u_long v_pkt_in; /* # pkts in on interface */
u_long v_pkt_out; /* # pkts out on interface */
u_long v_bytes_in; /* # bytes in on interface */
u_long v_bytes_out; /* # bytes out on interface */
- struct route v_route; /* cached route if this is a tunnel */
struct callout v_repq_ch; /* for tbf_reprocess_q() */
#ifdef RSVP_ISI
int v_rsvp_on; /* # RSVP listening on this vif */
--- 153,163 ----
***************
*** 218,224 ****
#else
int ip_mforward __P((struct mbuf *, struct ifnet *));
#endif
- int mrt_ipip_input __P((struct mbuf *, int));
#endif /* _KERNEL */
--- 238,243 ----
--BOKacYhQ+x31HxR3--