diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 0a4139ffa787..91ab6181ae35 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -446,13 +446,48 @@ gif_qflush(struct ifnet *ifp __unused) } +#define MTAG_GIF 1080679712 +static int +gif_check_nesting(struct ifnet *ifp, struct mbuf *m) +{ + struct m_tag *mtag; + int count; + + /* + * gif may cause infinite recursion calls when misconfigured. + * We'll prevent this by detecting loops. + * + * High nesting level may cause stack exhaustion. + * We'll prevent this by introducing upper limit. + */ + count = 1; + mtag = NULL; + while ((mtag = m_tag_locate(m, MTAG_GIF, 0, mtag)) != NULL) { + if (*(struct ifnet **)(mtag + 1) == ifp) { + log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname); + return (EIO); + } + count++; + } + if (count > V_max_gif_nesting) { + log(LOG_NOTICE, + "%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) { - struct m_tag *mtag; uint32_t af; - int gif_called; int error = 0; #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -465,42 +500,9 @@ gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, goto err; } - /* - * gif may cause infinite recursion calls when misconfigured. - * We'll prevent this by detecting loops. - * - * 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) { - 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; - } - mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag); - gif_called++; - } - if (gif_called > V_max_gif_nesting) { - log(LOG_NOTICE, - "gif_output: recursively called too many times(%d)\n", - gif_called); - error = EIO; /* is there better errno? */ + error = gif_check_nesting(ifp, m); + if (error != 0) goto err; - } - mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *), - M_NOWAIT); - if (mtag == NULL) { - error = ENOMEM; - goto err; - } - *(struct ifnet **)(mtag + 1) = ifp; - m_tag_prepend(m, mtag); - 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 b263850ef47c..c1fe83b800d4 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 */