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
This commit is contained in:
parent
f4d39872ad
commit
45e30f880b
@ -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_attach_p)(struct ifnet *ifp);
|
||||||
void (*ng_gif_detach_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 *,
|
static int gif_set_tunnel(struct ifnet *, struct sockaddr *,
|
||||||
struct sockaddr *);
|
struct sockaddr *);
|
||||||
static void gif_delete_tunnel(struct ifnet *);
|
static void gif_delete_tunnel(struct ifnet *);
|
||||||
@ -352,18 +353,32 @@ gif_transmit(struct ifnet *ifp, struct mbuf *m)
|
|||||||
uint8_t proto, ecn;
|
uint8_t proto, ecn;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
#ifdef MAC
|
||||||
|
error = mac_ifnet_check_transmit(ifp, m);
|
||||||
|
if (error) {
|
||||||
|
m_freem(m);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
error = ENETDOWN;
|
error = ENETDOWN;
|
||||||
sc = ifp->if_softc;
|
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);
|
m_freem(m);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
/* Now pull back the af that we stashed in the csum_data. */
|
/* 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);
|
BPF_MTAP2(ifp, &af, sizeof(af), m);
|
||||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||||
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
|
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
|
||||||
M_SETFIB(m, sc->gif_fibnum);
|
|
||||||
/* inner AF-specific encapsulation */
|
/* inner AF-specific encapsulation */
|
||||||
ecn = 0;
|
ecn = 0;
|
||||||
switch (af) {
|
switch (af) {
|
||||||
@ -447,24 +462,12 @@ gif_qflush(struct ifnet *ifp __unused)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
#define MTAG_GIF 1080679712
|
||||||
gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
static int
|
||||||
struct route *ro)
|
gif_check_nesting(struct ifnet *ifp, struct mbuf *m)
|
||||||
{
|
{
|
||||||
struct m_tag *mtag;
|
struct m_tag *mtag;
|
||||||
uint32_t af;
|
int count;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gif may cause infinite recursion calls when misconfigured.
|
* 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.
|
* High nesting level may cause stack exhaustion.
|
||||||
* We'll prevent this by introducing upper limit.
|
* We'll prevent this by introducing upper limit.
|
||||||
*/
|
*/
|
||||||
gif_called = 1;
|
count = 1;
|
||||||
mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL);
|
mtag = NULL;
|
||||||
while (mtag != NULL) {
|
while ((mtag = m_tag_locate(m, MTAG_GIF, 0, mtag)) != NULL) {
|
||||||
if (*(struct ifnet **)(mtag + 1) == ifp) {
|
if (*(struct ifnet **)(mtag + 1) == ifp) {
|
||||||
log(LOG_NOTICE,
|
log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname);
|
||||||
"gif_output: loop detected on %s\n",
|
return (EIO);
|
||||||
(*(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);
|
count++;
|
||||||
gif_called++;
|
|
||||||
}
|
}
|
||||||
if (gif_called > V_max_gif_nesting) {
|
if (count > V_max_gif_nesting) {
|
||||||
log(LOG_NOTICE,
|
log(LOG_NOTICE,
|
||||||
"gif_output: recursively called too many times(%d)\n",
|
"%s: if_output recursively called too many times(%d)\n",
|
||||||
gif_called);
|
if_name(ifp), count);
|
||||||
error = EIO; /* is there better errno? */
|
return (EIO);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *),
|
|
||||||
M_NOWAIT);
|
|
||||||
if (mtag == NULL) {
|
|
||||||
error = ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
mtag = m_tag_alloc(MTAG_GIF, 0, sizeof(struct ifnet *), M_NOWAIT);
|
||||||
|
if (mtag == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
*(struct ifnet **)(mtag + 1) = ifp;
|
*(struct ifnet **)(mtag + 1) = ifp;
|
||||||
m_tag_prepend(m, mtag);
|
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)
|
if (dst->sa_family == AF_UNSPEC)
|
||||||
bcopy(dst->sa_data, &af, sizeof(af));
|
bcopy(dst->sa_data, &af, sizeof(af));
|
||||||
else
|
else
|
||||||
af = dst->sa_family;
|
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
|
* 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
|
* 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;
|
m->m_pkthdr.csum_data = af;
|
||||||
return (ifp->if_transmit(ifp, m));
|
return (ifp->if_transmit(ifp, m));
|
||||||
err:
|
|
||||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
|
||||||
m_freem(m);
|
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -90,9 +90,6 @@ struct gif_softc {
|
|||||||
#define GIF_MTU_MIN (1280) /* Minimum MTU */
|
#define GIF_MTU_MIN (1280) /* Minimum MTU */
|
||||||
#define GIF_MTU_MAX (8192) /* Maximum MTU */
|
#define GIF_MTU_MAX (8192) /* Maximum MTU */
|
||||||
|
|
||||||
#define MTAG_GIF 1080679712
|
|
||||||
#define MTAG_GIF_CALLED 0
|
|
||||||
|
|
||||||
struct etherip_header {
|
struct etherip_header {
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
u_int eip_resvl:4, /* reserved */
|
u_int eip_resvl:4, /* reserved */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user