summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2015-01-17 11:43:13 +0000
committerae <ae@FreeBSD.org>2015-01-17 11:43:13 +0000
commit45e30f880b8686433b53d2e730f51a485c88afb3 (patch)
tree9d0ae1675064eea1cf7d949af44121f4ac5b7839
parentf4d39872ad741a7a9d6aa20cd195c0106c0c3f1b (diff)
downloadFreeBSD-src-45e30f880b8686433b53d2e730f51a485c88afb3.zip
FreeBSD-src-45e30f880b8686433b53d2e730f51a485c88afb3.tar.gz
MFC r276901:
Move the recursion detection code into separate function gif_check_nesting(). Also make MTAG_GIF definition private to if_gif.c. MFC r276907: Restore Ethernet-within-IP Encapsulation support that was broken after r273087. Move all checks from gif_output() into gif_transmit(). Previously they were checked always, because if_start always called gif_output. Now gif_transmit() can be called directly from if_bridge() code and we need do checks here. PR: 196646
-rw-r--r--sys/net/if_gif.c90
-rw-r--r--sys/net/if_gif.h3
2 files changed, 43 insertions, 50 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index a98fb19..6d7145b 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -120,6 +120,7 @@ void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
void (*ng_gif_attach_p)(struct ifnet *ifp);
void (*ng_gif_detach_p)(struct ifnet *ifp);
+static int gif_check_nesting(struct ifnet *, struct mbuf *);
static int gif_set_tunnel(struct ifnet *, struct sockaddr *,
struct sockaddr *);
static void gif_delete_tunnel(struct ifnet *);
@@ -352,18 +353,32 @@ gif_transmit(struct ifnet *ifp, struct mbuf *m)
uint8_t proto, ecn;
int error;
+#ifdef MAC
+ error = mac_ifnet_check_transmit(ifp, m);
+ if (error) {
+ m_freem(m);
+ goto err;
+ }
+#endif
error = ENETDOWN;
sc = ifp->if_softc;
- if (sc->gif_family == 0) {
+ if ((ifp->if_flags & IFF_MONITOR) != 0 ||
+ (ifp->if_flags & IFF_UP) == 0 ||
+ sc->gif_family == 0 ||
+ (error = gif_check_nesting(ifp, m)) != 0) {
m_freem(m);
goto err;
}
/* Now pull back the af that we stashed in the csum_data. */
- af = m->m_pkthdr.csum_data;
+ if (ifp->if_bridge)
+ af = AF_LINK;
+ else
+ af = m->m_pkthdr.csum_data;
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+ M_SETFIB(m, sc->gif_fibnum);
BPF_MTAP2(ifp, &af, sizeof(af), m);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
- M_SETFIB(m, sc->gif_fibnum);
/* inner AF-specific encapsulation */
ecn = 0;
switch (af) {
@@ -447,24 +462,12 @@ gif_qflush(struct ifnet *ifp __unused)
}
-int
-gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
- struct route *ro)
+#define MTAG_GIF 1080679712
+static int
+gif_check_nesting(struct ifnet *ifp, struct mbuf *m)
{
struct m_tag *mtag;
- uint32_t af;
- int gif_called;
- int error = 0;
-#ifdef MAC
- error = mac_ifnet_check_transmit(ifp, m);
- if (error)
- goto err;
-#endif
- if ((ifp->if_flags & IFF_MONITOR) != 0 ||
- (ifp->if_flags & IFF_UP) == 0) {
- error = ENETDOWN;
- goto err;
- }
+ int count;
/*
* gif may cause infinite recursion calls when misconfigured.
@@ -473,42 +476,39 @@ gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
* High nesting level may cause stack exhaustion.
* We'll prevent this by introducing upper limit.
*/
- gif_called = 1;
- mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL);
- while (mtag != NULL) {
+ count = 1;
+ mtag = NULL;
+ while ((mtag = m_tag_locate(m, MTAG_GIF, 0, mtag)) != NULL) {
if (*(struct ifnet **)(mtag + 1) == ifp) {
- log(LOG_NOTICE,
- "gif_output: loop detected on %s\n",
- (*(struct ifnet **)(mtag + 1))->if_xname);
- error = EIO; /* is there better errno? */
- goto err;
+ log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname);
+ return (EIO);
}
- mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag);
- gif_called++;
+ count++;
}
- if (gif_called > V_max_gif_nesting) {
+ if (count > V_max_gif_nesting) {
log(LOG_NOTICE,
- "gif_output: recursively called too many times(%d)\n",
- gif_called);
- error = EIO; /* is there better errno? */
- goto err;
- }
- mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *),
- M_NOWAIT);
- if (mtag == NULL) {
- error = ENOMEM;
- goto err;
+ "%s: if_output recursively called too many times(%d)\n",
+ if_name(ifp), count);
+ return (EIO);
}
+ mtag = m_tag_alloc(MTAG_GIF, 0, sizeof(struct ifnet *), M_NOWAIT);
+ if (mtag == NULL)
+ return (ENOMEM);
*(struct ifnet **)(mtag + 1) = ifp;
m_tag_prepend(m, mtag);
+ return (0);
+}
+
+int
+gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
+ struct route *ro)
+{
+ uint32_t af;
- m->m_flags &= ~(M_BCAST|M_MCAST);
if (dst->sa_family == AF_UNSPEC)
bcopy(dst->sa_data, &af, sizeof(af));
else
af = dst->sa_family;
- if (ifp->if_bridge)
- af = AF_LINK;
/*
* Now save the af in the inbound pkt csum data, this is a cheat since
* we are using the inbound csum_data field to carry the af over to
@@ -516,10 +516,6 @@ gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
*/
m->m_pkthdr.csum_data = af;
return (ifp->if_transmit(ifp, m));
-err:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- m_freem(m);
- return (error);
}
void
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
index b5ebf15..8986a20 100644
--- a/sys/net/if_gif.h
+++ b/sys/net/if_gif.h
@@ -90,9 +90,6 @@ struct gif_softc {
#define GIF_MTU_MIN (1280) /* Minimum MTU */
#define GIF_MTU_MAX (8192) /* Maximum MTU */
-#define MTAG_GIF 1080679712
-#define MTAG_GIF_CALLED 0
-
struct etherip_header {
#if BYTE_ORDER == LITTLE_ENDIAN
u_int eip_resvl:4, /* reserved */
OpenPOWER on IntegriCloud