diff options
author | chuck <chuck@cvs.openbsd.org> | 1996-07-11 00:17:11 +0000 |
---|---|---|
committer | chuck <chuck@cvs.openbsd.org> | 1996-07-11 00:17:11 +0000 |
commit | bb6f532983a1c44bbc031d6010a1ca82bb18db8b (patch) | |
tree | 8e4cd271bafdcad9460c8ec8527b470455ba10da /sys/dev/ic | |
parent | dbfec0039f7098c627cd5e35e63c85b384316ce2 (diff) |
fixes:
- don't try and add a PDU trailer (or TBD for that matter) to an M_EXT
mbuf. when M_EXT is set, the data area of the mbuf can be shared
with other mbufs (see m_copym()), and writing to one M_EXT mbuf may
invalidate another M_EXT mbuf (saw this with PDU trailers).
- be sure to validate the length value from the PDU trailer so that it
doesn't throw us out of sync with the chip (fixes yet another source
of the dread "en_service: id mismatch" panic).
- on recv, don't bother allocating an mbuf if mlen is zero since we are
only going to toss the data anyway.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/midway.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/sys/dev/ic/midway.c b/sys/dev/ic/midway.c index 95b052eb1f2..e50d73d48d1 100644 --- a/sys/dev/ic/midway.c +++ b/sys/dev/ic/midway.c @@ -1,5 +1,5 @@ -/* $OpenBSD: midway.c,v 1.8 1996/07/03 17:21:19 chuck Exp $ */ -/* (sync'd to midway.c 1.57) */ +/* $OpenBSD: midway.c,v 1.9 1996/07/11 00:17:10 chuck Exp $ */ +/* (sync'd to midway.c 1.58) */ /* * @@ -1360,7 +1360,15 @@ struct ifnet *ifp; #endif #ifdef EN_MBUF_OPT - if (M_LEADINGSPACE(m) >= MID_TBD_SIZE) { + + /* + * note: external storage (M_EXT) can be shared between mbufs + * to avoid copying (see m_copym()). this means that the same + * data buffer could be shared by several mbufs, and thus it isn't + * a good idea to try and write TBDs or PDUs to M_EXT data areas. + */ + + if (M_LEADINGSPACE(m) >= MID_TBD_SIZE && (m->m_flags & M_EXT) == 0) { m->m_data -= MID_TBD_SIZE; m->m_len += MID_TBD_SIZE; mlen += MID_TBD_SIZE; @@ -1374,7 +1382,8 @@ struct ifnet *ifp; atm_flags |= EN_OBHDR; } - if (toadd && M_TRAILINGSPACE(lastm) >= toadd) { + if (toadd && (lastm->m_flags & M_EXT) == 0 && + M_TRAILINGSPACE(lastm) >= toadd) { cp = mtod(lastm, u_int8_t *) + lastm->m_len; lastm->m_len += toadd; mlen += toadd; @@ -2280,6 +2289,14 @@ defer: /* defer processing */ pdu -= (EN_RXSZ*1024); pdu = EN_READ(sc, pdu); /* READ swaps to proper byte order */ fill = tlen - MID_RBD_SIZE - MID_PDU_LEN(pdu); + if (fill < 0) { + printf("%s: invalid AAL5 PDU length detected, dropping frame\n", + sc->sc_dev.dv_xname); + printf("%s: got %d cells (%d bytes), AAL5 len is %d bytes (pdu=0x%x)\n", + sc->sc_dev.dv_xname, MID_RBD_CNT(rbd), tlen - MID_RBD_SIZE, + MID_PDU_LEN(pdu), pdu); + fill = tlen; + } mlen = tlen - fill; } @@ -2299,6 +2316,7 @@ defer: /* defer processing */ */ m = sc->rxslot[slot].q.ifq_head; + drqneed = 1; if (m) { sav = mtod(m, u_int32_t *); if (sav[0] != cur) { @@ -2319,7 +2337,7 @@ defer: /* defer processing */ } } - if (m == NULL) { + if (mlen != 0 && m == NULL) { m = en_mget(sc, mlen, &drqneed); /* allocate! */ if (m == NULL) { fill += mlen; |