diff options
author | ae <ae@FreeBSD.org> | 2015-01-10 03:13:16 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2015-01-10 03:13:16 +0000 |
commit | 075ac8bd5409d35046cc6ab751d36519893b8ca5 (patch) | |
tree | 01a060374e95761d2687690fc49f81284dc6a4c0 /sys/net | |
parent | cc3e2f37122061a6dd34d6b165f2877d554f593b (diff) | |
download | FreeBSD-src-075ac8bd5409d35046cc6ab751d36519893b8ca5.zip FreeBSD-src-075ac8bd5409d35046cc6ab751d36519893b8ca5.tar.gz |
Move the recursion detection code into separate function gif_check_nesting().
Also make MTAG_GIF definition private to if_gif.c.
MFC after: 1 week
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_gif.c | 76 | ||||
-rw-r--r-- | sys/net/if_gif.h | 3 |
2 files changed, 39 insertions, 40 deletions
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 0a4139f..91ab618 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -446,24 +446,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. @@ -472,35 +460,49 @@ 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; + 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; + } + error = gif_check_nesting(ifp, m); + if (error != 0) + goto err; m->m_flags &= ~(M_BCAST|M_MCAST); if (dst->sa_family == AF_UNSPEC) bcopy(dst->sa_data, &af, sizeof(af)); diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h index b263850..c1fe83b 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 */ |