pull encapsulated packet for vif* via ip_encap framework.

This commit is contained in:
itojun 2001-05-08 10:07:15 +00:00
parent c8f1f39d19
commit 02077e028f
3 changed files with 103 additions and 65 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_encap.c,v 1.4 2000/10/02 03:55:42 itojun Exp $ */
/* $NetBSD: ip_encap.c,v 1.5 2001/05/08 10:07:15 itojun Exp $ */
/* $KAME: ip_encap.c,v 1.39 2000/10/01 12:37:18 itojun Exp $ */
/*
@ -211,17 +211,6 @@ encap4_input(m, va_alist)
return;
}
/* for backward compatibility */
#ifdef MROUTING
if (proto == IPPROTO_IPV4 && mrt_ipip_input(m, off)) {
/*
* Multicast routing code claimed this one. No
* more processing at this level.
*/
return;
}
#endif
/* last resort: inject to raw socket */
rip_input(m, off, proto);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_mroute.c,v 1.53 2001/04/13 23:30:23 thorpej Exp $ */
/* $NetBSD: ip_mroute.c,v 1.54 2001/05/08 10:07:15 itojun Exp $ */
/*
* IP multicast forwarding procedures
@ -41,6 +41,7 @@
#include <netinet/igmp.h>
#include <netinet/igmp_var.h>
#include <netinet/ip_mroute.h>
#include <netinet/ip_encap.h>
#include <machine/stdarg.h>
@ -82,6 +83,17 @@ extern struct socket *ip_rsvpd;
extern int rsvp_on;
#endif /* RSVP_ISI */
/* vif attachment using sys/netinet/ip_encap.c */
extern struct domain inetdomain;
static void vif_input __P((struct mbuf *, ...));
static int vif_encapcheck __P((const struct mbuf *, int, int, void *));
static struct protosw vif_protosw =
{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
vif_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0,
};
#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
#define UPCALL_EXPIRE 6 /* number of timeouts */
@ -564,6 +576,12 @@ add_vif(m)
return (EOPNOTSUPP);
}
/* attach this vif to decapsulator dispatch table */
vifp->v_encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV4,
vif_encapcheck, &vif_protosw, vifp);
if (!vifp->v_encap_cookie)
return (EINVAL);
/* Create a fake encapsulation interface. */
ifp = (struct ifnet *)malloc(sizeof(*ifp), M_MRTABLE, M_WAITOK);
bzero(ifp, sizeof(*ifp));
@ -572,7 +590,10 @@ add_vif(m)
/* Prepare cached route entry. */
bzero(&vifp->v_route, sizeof(vifp->v_route));
/* Tell mrt_ipip_input() to start looking at encapsulated packets. */
/*
* Tell mrt_ipip_input() to start looking at encapsulated
* packets.
*/
have_encap_tunnel = 1;
} else {
/* Use the physical interface associated with the address. */
@ -649,6 +670,10 @@ reset_vif(vifp)
callout_stop(&vifp->v_repq_ch);
/* detach this vif from decapsulator dispatch table */
encap_detach(vifp->v_encap_cookie);
vifp->v_encap_cookie = NULL;
for (m = vifp->tbf_q; m != 0; m = n) {
n = m->m_nextpkt;
m_freem(m);
@ -1446,64 +1471,39 @@ encap_send(ip, vifp, m)
}
/*
* 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.
* De-encapsulate a packet and feed it back through ip input.
*/
int
mrt_ipip_input(m, hlen)
static void
#if __STDC__
vif_input(struct mbuf *m, ...)
#else
vif_input(m, va_alist)
struct mbuf *m;
int hlen;
va_dcl
#endif
{
struct ip *ip = mtod(m, struct ip *);
int off, proto;
va_list ap;
struct ip *ip;
struct vif *vifp;
int s;
struct ifqueue *ifq;
struct vif *vifp;
if (!have_encap_tunnel)
return (0);
va_start(ap, m);
off = va_arg(ap, int);
proto = va_arg(ap, int);
va_end(ap);
/*
* 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);
vifp = (struct vif *)encap_getarg(m);
if (!vifp || proto != AF_INET) {
m_freem(m);
mrtstat.mrts_bad_tunnel++;
return;
}
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;
ip = mtod(m, struct ip *);
m->m_data += hlen;
m->m_len -= hlen;
m->m_pkthdr.len -= hlen;
m_adj(m, off);
m->m_pkthdr.rcvif = vifp->v_ifp;
ifq = &ipintrq;
s = splnet();
@ -1521,7 +1521,55 @@ mrt_ipip_input(m, hlen)
*/
}
splx(s);
return (1);
}
/*
* Check if the packet should be grabbed by us.
*/
static int
vif_encapcheck(m, off, proto, arg)
const struct mbuf *m;
int off;
int proto;
void *arg;
{
struct vif *vifp;
struct ip ip;
#ifdef DIAGNOSTIC
if (!arg || proto != IPPROTO_IPV4)
panic("unexpected arg in vif_encapcheck");
#endif
/*
* do not grab 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).
*/
/* LINTED const cast */
m_copydata((struct mbuf *)m, off, sizeof(ip), (caddr_t)&ip);
if (!IN_MULTICAST(ip.ip_dst.s_addr))
return 0;
/* LINTED const cast */
m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
if (!in_hosteq(ip.ip_src, last_encap_src)) {
vifp = (struct vif *)arg;
if (vifp->v_flags & VIFF_TUNNEL &&
in_hosteq(vifp->v_rmt_addr, ip.ip_src))
;
else
return 0;
last_encap_vif = vifp;
last_encap_src = ip.ip_src;
} else
vifp = last_encap_vif;
/* 32bit match, since we have checked ip_src only */
return 32;
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_mroute.h,v 1.18 2000/03/23 07:03:29 thorpej Exp $ */
/* $NetBSD: ip_mroute.h,v 1.19 2001/05/08 10:07:15 itojun Exp $ */
/*
* Definitions for IP multicast forwarding.
@ -120,6 +120,7 @@ struct mrtstat {
/*
* The kernel's virtual-interface structure.
*/
struct encaptab;
struct vif {
struct mbuf *tbf_q, **tbf_t; /* packet queue */
struct timeval tbf_last_pkt_t; /* arr. time of last pkt */
@ -143,6 +144,7 @@ struct vif {
int v_rsvp_on; /* # RSVP listening on this vif */
struct socket *v_rsvpd; /* # RSVPD daemon */
#endif /* RSVP_ISI */
const struct encaptab *v_encap_cookie;
};
/*
@ -218,7 +220,6 @@ void rsvp_input __P((struct mbuf *, int, int));
#else
int ip_mforward __P((struct mbuf *, struct ifnet *));
#endif
int mrt_ipip_input __P((struct mbuf *, int));
#endif /* _KERNEL */