diff options
author | ae <ae@FreeBSD.org> | 2015-01-17 11:43:13 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2015-01-17 11:43:13 +0000 |
commit | 45e30f880b8686433b53d2e730f51a485c88afb3 (patch) | |
tree | 9d0ae1675064eea1cf7d949af44121f4ac5b7839 | |
parent | f4d39872ad741a7a9d6aa20cd195c0106c0c3f1b (diff) | |
download | FreeBSD-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.c | 90 | ||||
-rw-r--r-- | sys/net/if_gif.h | 3 |
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 */ |