svn commit: r195623 - in user/kmacy/head_ppacket/sys: net netinet
Kip Macy
kmacy at FreeBSD.org
Sat Jul 11 21:46:21 UTC 2009
Author: kmacy
Date: Sat Jul 11 21:46:20 2009
New Revision: 195623
URL: http://svn.freebsd.org/changeset/base/195623
Log:
- provide reference counting for gre_softc
- serialize access to gre_softc
- take first pass at decoupling ip_gre from if_gre
Modified:
user/kmacy/head_ppacket/sys/net/if_gre.c
user/kmacy/head_ppacket/sys/net/if_gre.h
user/kmacy/head_ppacket/sys/netinet/ip_gre.c
Modified: user/kmacy/head_ppacket/sys/net/if_gre.c
==============================================================================
--- user/kmacy/head_ppacket/sys/net/if_gre.c Sat Jul 11 17:36:59 2009 (r195622)
+++ user/kmacy/head_ppacket/sys/net/if_gre.c Sat Jul 11 21:46:20 2009 (r195623)
@@ -86,9 +86,44 @@
#endif
#include <net/bpf.h>
-
#include <net/if_gre.h>
+struct gre_softc {
+ struct mtx gre_mtx;
+ int gre_unit;
+ /*
+ * refcount counts total references, not list external
+ * like rtentry as that has proven to be error-prone
+ */
+ int gre_refcnt;
+ u_int gre_fibnum; /* use this fib for envelopes */
+ struct route route; /* routing entry that determines, where a
+ encapsulated packet should go */
+ const struct encaptab *encap; /* encapsulation cookie */
+
+ int called; /* infinite recursion preventer */
+
+ uint32_t key; /* key included in outgoing GRE packets */
+ /* zero means none */
+
+#define MTX_BUF_SIZE 32
+ char sc_mtx_buf[MTX_BUF_SIZE];
+ LIST_ENTRY(gre_softc) sc_list;
+ struct gre_softc_external gre_ext;
+};
+#define gre_src gre_ext.g_src
+#define gre_dst gre_ext.g_dst
+#define gre_proto gre_ext.g_proto
+#define gre_wccp_ver gre_ext.g_wccp_ver
+LIST_HEAD(gre_softc_head, gre_softc);
+
+#define GRE_LOCK(sc) mtx_lock(&(sc)->gre_mtx);
+#define GRE_UNLOCK(sc) mtx_unlock(&(sc)->gre_mtx);
+#define GRE_ADDREF(sc) do { \
+ GRE_LOCK(sc); \
+ (sc)->gre_refcnt++; \
+ GRE_UNLOCK(sc); \
+ } while (0)
/*
* It is not easy to calculate the right value for a GRE MTU.
* We leave this task to the admin and use the same default that
@@ -188,6 +223,9 @@ gre_clone_create(ifc, unit, params)
free(sc, M_GRE);
return (ENOSPC);
}
+ snprintf(sc->sc_mtx_buf, MTX_BUF_SIZE, "%s%d_mtx", ifc->ifc_name, unit);
+ mtx_init(&sc->gre_mtx, sc->sc_mtx_buf, NULL, MTX_DEF);
+ sc->gre_refcnt = 1;
GRE2IFP(sc)->if_softc = sc;
if_initname(GRE2IFP(sc), ifc->ifc_name, unit);
@@ -199,13 +237,13 @@ gre_clone_create(ifc, unit, params)
GRE2IFP(sc)->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
GRE2IFP(sc)->if_output = gre_output;
GRE2IFP(sc)->if_ioctl = gre_ioctl;
- sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
- sc->g_proto = IPPROTO_GRE;
+ sc->gre_dst.s_addr = sc->gre_src.s_addr = INADDR_ANY;
+ sc->gre_proto = IPPROTO_GRE;
GRE2IFP(sc)->if_flags |= IFF_LINK0;
sc->encap = NULL;
sc->called = 0;
sc->gre_fibnum = curthread->td_proc->p_fibnum;
- sc->wccp_ver = WCCP_V1;
+ sc->gre_wccp_ver = WCCP_V1;
sc->key = 0;
if_attach(GRE2IFP(sc));
bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
@@ -215,29 +253,43 @@ gre_clone_create(ifc, unit, params)
return (0);
}
-static void
-gre_clone_destroy(ifp)
- struct ifnet *ifp;
+void
+gre_free(struct gre_softc *sc)
{
- struct gre_softc *sc = ifp->if_softc;
+ struct ifnet *ifp;
- mtx_lock(&gre_mtx);
- LIST_REMOVE(sc, sc_list);
- mtx_unlock(&gre_mtx);
+ GRE_LOCK(sc);
+ (sc)->gre_refcnt--;
+ if ((sc)->gre_refcnt > 0) {
+ GRE_UNLOCK((sc));
+ return;
+ }
#ifdef INET
if (sc->encap != NULL)
encap_detach(sc->encap);
#endif
+ ifp = GRE2IFP(sc);
bpfdetach(ifp);
if_detach(ifp);
if_free(ifp);
free(sc, M_GRE);
}
+static void
+gre_clone_destroy(struct ifnet *ifp)
+{
+ struct gre_softc *sc = ifp->if_softc;
+
+ mtx_lock(&gre_mtx);
+ LIST_REMOVE(sc, sc_list);
+ mtx_unlock(&gre_mtx);
+ gre_free(sc);
+}
+
/*
* The output routine. Takes a packet and encapsulates it in the protocol
- * given by sc->g_proto. See also RFC 1701 and RFC 2004
+ * given by sc->gre_proto. See also RFC 1701 and RFC 2004
*/
static int
gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
@@ -256,7 +308,8 @@ gre_output(struct ifnet *ifp, struct mbu
struct mobile_h mob_h;
u_int32_t af;
int extra = 0;
-
+
+ GRE_LOCK(sc);
/*
* gre may cause infinite recursion calls when misconfigured.
* We'll prevent this by introducing upper limit.
@@ -271,7 +324,7 @@ gre_output(struct ifnet *ifp, struct mbu
if (!((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)) ||
- sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
+ sc->gre_src.s_addr == INADDR_ANY || sc->gre_dst.s_addr == INADDR_ANY) {
m_freem(m);
error = ENETDOWN;
goto end;
@@ -293,7 +346,7 @@ gre_output(struct ifnet *ifp, struct mbu
m->m_flags &= ~(M_BCAST|M_MCAST);
- if (sc->g_proto == IPPROTO_MOBILE) {
+ if (sc->gre_proto == IPPROTO_MOBILE) {
if (dst->sa_family == AF_INET) {
struct mbuf *m0;
int msiz;
@@ -313,19 +366,19 @@ gre_output(struct ifnet *ifp, struct mbu
memset(&mob_h, 0, MOB_H_SIZ_L);
mob_h.proto = (ip->ip_p) << 8;
mob_h.odst = ip->ip_dst.s_addr;
- ip->ip_dst.s_addr = sc->g_dst.s_addr;
+ ip->ip_dst.s_addr = sc->gre_dst.s_addr;
/*
* If the packet comes from our host, we only change
* the destination address in the IP header.
* Else we also need to save and change the source
*/
- if (in_hosteq(ip->ip_src, sc->g_src)) {
+ if (in_hosteq(ip->ip_src, sc->gre_src)) {
msiz = MOB_H_SIZ_S;
} else {
mob_h.proto |= MOB_H_SBIT;
mob_h.osrc = ip->ip_src.s_addr;
- ip->ip_src.s_addr = sc->g_src.s_addr;
+ ip->ip_src.s_addr = sc->gre_src.s_addr;
msiz = MOB_H_SIZ_L;
}
mob_h.proto = htons(mob_h.proto);
@@ -365,13 +418,13 @@ gre_output(struct ifnet *ifp, struct mbu
error = EINVAL;
goto end;
}
- } else if (sc->g_proto == IPPROTO_GRE) {
+ } else if (sc->gre_proto == IPPROTO_GRE) {
switch (dst->sa_family) {
case AF_INET:
ip = mtod(m, struct ip *);
gre_ip_tos = ip->ip_tos;
gre_ip_id = ip->ip_id;
- if (sc->wccp_ver == WCCP_V2) {
+ if (sc->gre_wccp_ver == WCCP_V2) {
extra = sizeof(uint32_t);
etype = WCCP_PROTOCOL_TYPE;
} else {
@@ -417,7 +470,7 @@ gre_output(struct ifnet *ifp, struct mbu
M_SETFIB(m, sc->gre_fibnum); /* The envelope may use a different FIB */
gh = mtod(m, struct greip *);
- if (sc->g_proto == IPPROTO_GRE) {
+ if (sc->gre_proto == IPPROTO_GRE) {
uint32_t *options = gh->gi_options;
memset((void *)gh, 0, sizeof(struct greip) + extra);
@@ -432,10 +485,10 @@ gre_output(struct ifnet *ifp, struct mbu
}
}
- gh->gi_pr = sc->g_proto;
- if (sc->g_proto != IPPROTO_MOBILE) {
- gh->gi_src = sc->g_src;
- gh->gi_dst = sc->g_dst;
+ gh->gi_pr = sc->gre_proto;
+ if (sc->gre_proto != IPPROTO_MOBILE) {
+ gh->gi_src = sc->gre_src;
+ gh->gi_dst = sc->gre_dst;
((struct ip*)gh)->ip_v = IPPROTO_IPV4;
((struct ip*)gh)->ip_hl = (sizeof(struct ip)) >> 2;
((struct ip*)gh)->ip_ttl = GRE_TTL;
@@ -454,6 +507,7 @@ gre_output(struct ifnet *ifp, struct mbu
error = ip_output(m, NULL, &sc->route, IP_FORWARDING,
(struct ip_moptions *)NULL, (struct inpcb *)NULL);
end:
+ GRE_UNLOCK(sc);
sc->called = 0;
if (error)
ifp->if_oerrors++;
@@ -467,7 +521,6 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
struct if_laddrreq *lifr = (struct if_laddrreq *)data;
struct in_aliasreq *aifr = (struct in_aliasreq *)data;
struct gre_softc *sc = ifp->if_softc;
- int s;
struct sockaddr_in si;
struct sockaddr *sa = NULL;
int error, adj;
@@ -477,7 +530,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
error = 0;
adj = 0;
- s = splnet();
+ GRE_LOCK(sc);
switch (cmd) {
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
@@ -492,13 +545,13 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
if ((error = priv_check(curthread, PRIV_NET_SETIFFLAGS)) != 0)
break;
if ((ifr->ifr_flags & IFF_LINK0) != 0)
- sc->g_proto = IPPROTO_GRE;
+ sc->gre_proto = IPPROTO_GRE;
else
- sc->g_proto = IPPROTO_MOBILE;
+ sc->gre_proto = IPPROTO_MOBILE;
if ((ifr->ifr_flags & IFF_LINK2) != 0)
- sc->wccp_ver = WCCP_V2;
+ sc->gre_wccp_ver = WCCP_V2;
else
- sc->wccp_ver = WCCP_V1;
+ sc->gre_wccp_ver = WCCP_V1;
goto recompute;
case SIOCSIFMTU:
/*
@@ -573,8 +626,8 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
*/
if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0)
break;
- sc->g_proto = ifr->ifr_flags;
- switch (sc->g_proto) {
+ sc->gre_proto = ifr->ifr_flags;
+ switch (sc->gre_proto) {
case IPPROTO_GRE:
ifp->if_flags |= IFF_LINK0;
break;
@@ -587,7 +640,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
}
goto recompute;
case GREGPROTO:
- ifr->ifr_flags = sc->g_proto;
+ ifr->ifr_flags = sc->gre_proto;
break;
case GRESADDRS:
case GRESADDRD:
@@ -600,9 +653,9 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
*/
sa = &ifr->ifr_addr;
if (cmd == GRESADDRS)
- sc->g_src = (satosin(sa))->sin_addr;
+ sc->gre_src = (satosin(sa))->sin_addr;
if (cmd == GRESADDRD)
- sc->g_dst = (satosin(sa))->sin_addr;
+ sc->gre_dst = (satosin(sa))->sin_addr;
recompute:
#ifdef INET
if (sc->encap != NULL) {
@@ -610,8 +663,8 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
sc->encap = NULL;
}
#endif
- if ((sc->g_src.s_addr != INADDR_ANY) &&
- (sc->g_dst.s_addr != INADDR_ANY)) {
+ if ((sc->gre_src.s_addr != INADDR_ANY) &&
+ (sc->gre_dst.s_addr != INADDR_ANY)) {
bzero(&sp, sizeof(sp));
bzero(&sm, sizeof(sm));
bzero(&dp, sizeof(dp));
@@ -620,14 +673,14 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
sizeof(struct sockaddr_in);
sp.sin_family = sm.sin_family = dp.sin_family =
dm.sin_family = AF_INET;
- sp.sin_addr = sc->g_src;
- dp.sin_addr = sc->g_dst;
+ sp.sin_addr = sc->gre_src;
+ dp.sin_addr = sc->gre_dst;
sm.sin_addr.s_addr = dm.sin_addr.s_addr =
INADDR_BROADCAST;
#ifdef INET
- sc->encap = encap_attach(AF_INET, sc->g_proto,
+ sc->encap = encap_attach(AF_INET, sc->gre_proto,
sintosa(&sp), sintosa(&sm), sintosa(&dp),
- sintosa(&dm), (sc->g_proto == IPPROTO_GRE) ?
+ sintosa(&dm), (sc->gre_proto == IPPROTO_GRE) ?
&in_gre_protosw : &in_mobile_protosw, sc);
if (sc->encap == NULL)
printf("%s: unable to attach encap\n",
@@ -645,7 +698,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
- si.sin_addr.s_addr = sc->g_src.s_addr;
+ si.sin_addr.s_addr = sc->gre_src.s_addr;
sa = sintosa(&si);
ifr->ifr_addr = *sa;
break;
@@ -653,7 +706,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
- si.sin_addr.s_addr = sc->g_dst.s_addr;
+ si.sin_addr.s_addr = sc->gre_dst.s_addr;
sa = sintosa(&si);
ifr->ifr_addr = *sa;
break;
@@ -674,8 +727,8 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
error = EINVAL;
break;
}
- sc->g_src = aifr->ifra_addr.sin_addr;
- sc->g_dst = aifr->ifra_dstaddr.sin_addr;
+ sc->gre_src = aifr->ifra_addr.sin_addr;
+ sc->gre_dst = aifr->ifra_dstaddr.sin_addr;
goto recompute;
case SIOCSLIFPHYADDR:
/*
@@ -694,8 +747,8 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
error = EINVAL;
break;
}
- sc->g_src = (satosin(&lifr->addr))->sin_addr;
- sc->g_dst =
+ sc->gre_src = (satosin(&lifr->addr))->sin_addr;
+ sc->gre_dst =
(satosin(&lifr->dstaddr))->sin_addr;
goto recompute;
case SIOCDIFPHYADDR:
@@ -705,49 +758,49 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
*/
if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0)
break;
- sc->g_src.s_addr = INADDR_ANY;
- sc->g_dst.s_addr = INADDR_ANY;
+ sc->gre_src.s_addr = INADDR_ANY;
+ sc->gre_dst.s_addr = INADDR_ANY;
goto recompute;
case SIOCGLIFPHYADDR:
- if (sc->g_src.s_addr == INADDR_ANY ||
- sc->g_dst.s_addr == INADDR_ANY) {
+ if (sc->gre_src.s_addr == INADDR_ANY ||
+ sc->gre_dst.s_addr == INADDR_ANY) {
error = EADDRNOTAVAIL;
break;
}
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
- si.sin_addr.s_addr = sc->g_src.s_addr;
+ si.sin_addr.s_addr = sc->gre_src.s_addr;
memcpy(&lifr->addr, &si, sizeof(si));
- si.sin_addr.s_addr = sc->g_dst.s_addr;
+ si.sin_addr.s_addr = sc->gre_dst.s_addr;
memcpy(&lifr->dstaddr, &si, sizeof(si));
break;
case SIOCGIFPSRCADDR:
#ifdef INET6
case SIOCGIFPSRCADDR_IN6:
#endif
- if (sc->g_src.s_addr == INADDR_ANY) {
+ if (sc->gre_src.s_addr == INADDR_ANY) {
error = EADDRNOTAVAIL;
break;
}
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
- si.sin_addr.s_addr = sc->g_src.s_addr;
+ si.sin_addr.s_addr = sc->gre_src.s_addr;
bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
break;
case SIOCGIFPDSTADDR:
#ifdef INET6
case SIOCGIFPDSTADDR_IN6:
#endif
- if (sc->g_dst.s_addr == INADDR_ANY) {
+ if (sc->gre_dst.s_addr == INADDR_ANY) {
error = EADDRNOTAVAIL;
break;
}
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_len = sizeof(struct sockaddr_in);
- si.sin_addr.s_addr = sc->g_dst.s_addr;
+ si.sin_addr.s_addr = sc->gre_dst.s_addr;
bcopy(&si, &ifr->ifr_addr, sizeof(ifr->ifr_addr));
break;
case GRESKEY:
@@ -779,7 +832,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd,
break;
}
- splx(s);
+ GRE_UNLOCK(sc);
return (error);
}
@@ -802,7 +855,7 @@ gre_compute_route(struct gre_softc *sc)
ro = &sc->route;
memset(ro, 0, sizeof(struct route));
- ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
+ ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->gre_dst;
ro->ro_dst.sa_family = AF_INET;
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
@@ -843,7 +896,7 @@ gre_compute_route(struct gre_softc *sc)
* the route and search one to this interface ...
*/
if ((GRE2IFP(sc)->if_flags & IFF_LINK1) == 0)
- ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->g_dst;
+ ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = sc->gre_dst;
#ifdef DIAGNOSTIC
printf(", choosing %s with gateway %s", if_name(ro->ro_rt->rt_ifp),
@@ -883,6 +936,31 @@ gre_in_cksum(u_int16_t *p, u_int len)
return (~sum);
}
+/*
+ * Find the gre interface associated with our src/dst/proto set.
+ *
+ */
+struct gre_softc *
+gre_lookup(struct mbuf *m, u_char proto,
+ int (*func)(struct gre_softc_external *, struct mbuf *, u_char))
+{
+ struct gre_softc *sc;
+
+ mtx_lock(&gre_mtx);
+ for (sc = LIST_FIRST(&gre_softc_list); sc != NULL;
+ sc = LIST_NEXT(sc, sc_list)) {
+ if (func(&sc->gre_ext, m, proto) &&
+ ((GRE2IFP(sc)->if_flags & IFF_UP) != 0)) {
+ GRE_ADDREF(sc);
+ mtx_unlock(&gre_mtx);
+ return (sc);
+ }
+ }
+ mtx_unlock(&gre_mtx);
+
+ return (NULL);
+}
+
static int
gremodevent(module_t mod, int type, void *data)
{
Modified: user/kmacy/head_ppacket/sys/net/if_gre.h
==============================================================================
--- user/kmacy/head_ppacket/sys/net/if_gre.h Sat Jul 11 17:36:59 2009 (r195622)
+++ user/kmacy/head_ppacket/sys/net/if_gre.h Sat Jul 11 21:46:20 2009 (r195623)
@@ -54,30 +54,19 @@ typedef enum {
WCCP_V2
} wccp_ver_t;
-struct gre_softc {
- struct ifnet *sc_ifp;
- LIST_ENTRY(gre_softc) sc_list;
- int gre_unit;
- int gre_flags;
- u_int gre_fibnum; /* use this fib for envelopes */
+/*
+ * The binary contract is to have the ifp at the front of the softc
+ *
+ */
+#define GRE2IFP(sc) (*(struct ifnet **)(&sc))
+struct gre_softc_external {
+ struct ifnet *gre_ifp;
struct in_addr g_src; /* source address of gre packets */
struct in_addr g_dst; /* destination address of gre packets */
- struct route route; /* routing entry that determines, where a
- encapsulated packet should go */
u_char g_proto; /* protocol of encapsulator */
-
- const struct encaptab *encap; /* encapsulation cookie */
-
- int called; /* infinite recursion preventer */
-
- uint32_t key; /* key included in outgoing GRE packets */
- /* zero means none */
-
- wccp_ver_t wccp_ver; /* version of the WCCP */
+ wccp_ver_t g_wccp_ver; /* version of the WCCP */
};
-#define GRE2IFP(sc) ((sc)->sc_ifp)
-
-
+
struct gre_h {
u_int16_t flags; /* GRE flags */
u_int16_t ptype; /* protocol type of payload typically
@@ -184,11 +173,11 @@ struct mobip_h {
#define GRESKEY _IOW('i', 108, struct ifreq)
#ifdef _KERNEL
-LIST_HEAD(gre_softc_head, gre_softc);
-extern struct mtx gre_mtx;
-extern struct gre_softc_head gre_softc_list;
-
+struct gre_softc;
u_int16_t gre_in_cksum(u_int16_t *, u_int);
+struct gre_softc *gre_lookup(struct mbuf *m, u_char proto,
+ int (*func)(struct gre_softc_external *, struct mbuf *, u_char));
+void gre_free(struct gre_softc *sc);
#endif /* _KERNEL */
#endif
Modified: user/kmacy/head_ppacket/sys/netinet/ip_gre.c
==============================================================================
--- user/kmacy/head_ppacket/sys/netinet/ip_gre.c Sat Jul 11 17:36:59 2009 (r195622)
+++ user/kmacy/head_ppacket/sys/netinet/ip_gre.c Sat Jul 11 21:46:20 2009 (r195623)
@@ -91,35 +91,14 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
-#if 1
-void gre_inet_ntoa(struct in_addr in); /* XXX */
-#endif
-
-static struct gre_softc *gre_lookup(struct mbuf *, u_int8_t);
-
-static struct mbuf *gre_input2(struct mbuf *, int, u_char);
-
-/*
- * De-encapsulate a packet and feed it back through ip input (this
- * routine is called whenever IP gets a packet with proto type
- * IPPROTO_GRE and a local destination address).
- * This really is simple
- */
-void
-gre_input(struct mbuf *m, int off)
+static int
+gre_input_lookup_func(struct gre_softc_external *sc, struct mbuf *m, u_char proto)
{
- int proto;
-
- proto = (mtod(m, struct ip *))->ip_p;
-
- m = gre_input2(m, off, proto);
+ struct ip *ip = mtod(m, struct ip *);
- /*
- * If no matching tunnel that is up is found. We inject
- * the mbuf to raw ip socket to see if anyone picks it up.
- */
- if (m != NULL)
- rip_input(m, off);
+ return ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
+ (sc->g_src.s_addr == ip->ip_dst.s_addr) &&
+ (sc->g_proto == proto));
}
/*
@@ -137,15 +116,15 @@ gre_input2(struct mbuf *m ,int hlen, u_c
u_int16_t flags;
u_int32_t af;
- if ((sc = gre_lookup(m, proto)) == NULL) {
+ if ((sc = gre_lookup(m, proto, gre_input_lookup_func)) == NULL) {
/* No matching tunnel or tunnel is down. */
return (m);
}
if (m->m_len < sizeof(*gip)) {
m = m_pullup(m, sizeof(*gip));
- if (m == NULL)
- return (NULL);
+ if (m == NULL)
+ goto done;
}
gip = mtod(m, struct greip *);
@@ -164,7 +143,7 @@ gre_input2(struct mbuf *m ,int hlen, u_c
hlen += 4;
/* We don't support routing fields (variable length) */
if (flags & GRE_RP)
- return (m);
+ goto done;
if (flags & GRE_KP)
hlen += 4;
if (flags & GRE_SP)
@@ -172,7 +151,7 @@ gre_input2(struct mbuf *m ,int hlen, u_c
switch (ntohs(gip->gi_ptype)) { /* ethertypes */
case WCCP_PROTOCOL_TYPE:
- if (sc->wccp_ver == WCCP_V2)
+ if (((struct gre_softc_external *)sc)->g_wccp_ver == WCCP_V2)
hlen += 4;
/* FALLTHROUGH */
case ETHERTYPE_IP: /* shouldn't need a schednetisr(), */
@@ -193,17 +172,18 @@ gre_input2(struct mbuf *m ,int hlen, u_c
#endif
default:
/* Others not yet supported. */
- return (m);
+ goto done;
}
break;
default:
/* Others not yet supported. */
- return (m);
+ goto done;
}
if (hlen > m->m_pkthdr.len) {
m_freem(m);
- return (NULL);
+ m = NULL;
+ goto done;
}
/* Unlike NetBSD, in FreeBSD m_adj() adjusts m->m_pkthdr.len as well */
m_adj(m, hlen);
@@ -213,11 +193,37 @@ gre_input2(struct mbuf *m ,int hlen, u_c
}
m->m_pkthdr.rcvif = GRE2IFP(sc);
-
+ gre_free(sc);
netisr_queue(isr, m);
/* Packet is done, no further processing needed. */
return (NULL);
+done:
+ gre_free(sc);
+ return (m);
+}
+
+/*
+ * De-encapsulate a packet and feed it back through ip input (this
+ * routine is called whenever IP gets a packet with proto type
+ * IPPROTO_GRE and a local destination address).
+ * This really is simple
+ */
+void
+gre_input(struct mbuf *m, int off)
+{
+ int proto;
+
+ proto = (mtod(m, struct ip *))->ip_p;
+
+ m = gre_input2(m, off, proto);
+
+ /*
+ * If no matching tunnel that is up is found. We inject
+ * the mbuf to raw ip socket to see if anyone picks it up.
+ */
+ if (m != NULL)
+ rip_input(m, off);
}
/*
@@ -226,7 +232,6 @@ gre_input2(struct mbuf *m ,int hlen, u_c
* encapsulating header was not prepended, but instead inserted
* between IP header and payload
*/
-
void
gre_mobile_input(struct mbuf *m, int hlen)
{
@@ -235,7 +240,7 @@ gre_mobile_input(struct mbuf *m, int hle
struct gre_softc *sc;
int msiz;
- if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) {
+ if ((sc = gre_lookup(m, IPPROTO_MOBILE, gre_input_lookup_func)) == NULL) {
/* No matching tunnel or tunnel is down. */
m_freem(m);
return;
@@ -244,7 +249,7 @@ gre_mobile_input(struct mbuf *m, int hle
if (m->m_len < sizeof(*mip)) {
m = m_pullup(m, sizeof(*mip));
if (m == NULL)
- return;
+ goto done;
}
ip = mtod(m, struct ip *);
mip = mtod(m, struct mobip_h *);
@@ -261,7 +266,7 @@ gre_mobile_input(struct mbuf *m, int hle
if (m->m_len < (ip->ip_hl << 2) + msiz) {
m = m_pullup(m, (ip->ip_hl << 2) + msiz);
if (m == NULL)
- return;
+ goto done;
ip = mtod(m, struct ip *);
mip = mtod(m, struct mobip_h *);
}
@@ -271,7 +276,7 @@ gre_mobile_input(struct mbuf *m, int hle
if (gre_in_cksum((u_int16_t *)&mip->mh, msiz) != 0) {
m_freem(m);
- return;
+ goto done;
}
bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) +
@@ -297,38 +302,8 @@ gre_mobile_input(struct mbuf *m, int hle
}
m->m_pkthdr.rcvif = GRE2IFP(sc);
-
netisr_queue(NETISR_IP, m);
-}
-
-/*
- * Find the gre interface associated with our src/dst/proto set.
- *
- * XXXRW: Need some sort of drain/refcount mechanism so that the softc
- * reference remains valid after it's returned from gre_lookup(). Right
- * now, I'm thinking it should be reference-counted with a gre_dropref()
- * when the caller is done with the softc. This is complicated by how
- * to handle destroying the gre softc; probably using a gre_drain() in
- * in_gre.c during destroy.
- */
-static struct gre_softc *
-gre_lookup(struct mbuf *m, u_int8_t proto)
-{
- struct ip *ip = mtod(m, struct ip *);
- struct gre_softc *sc;
- mtx_lock(&gre_mtx);
- for (sc = LIST_FIRST(&gre_softc_list); sc != NULL;
- sc = LIST_NEXT(sc, sc_list)) {
- if ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
- (sc->g_src.s_addr == ip->ip_dst.s_addr) &&
- (sc->g_proto == proto) &&
- ((GRE2IFP(sc)->if_flags & IFF_UP) != 0)) {
- mtx_unlock(&gre_mtx);
- return (sc);
- }
- }
- mtx_unlock(&gre_mtx);
-
- return (NULL);
+done:
+ gre_free(sc);
}
More information about the svn-src-user
mailing list