Completely removed trailer support. The only reason I wrote that code in

the first place was so that BPF could grok trailer packets. I've since
decided that this is a job for tcpdump to decipher (if at all). Also
fixed up checks for received packet length to better cope with ancient
starlan boards.
This commit is contained in:
David Greenman 1994-10-08 09:24:20 +00:00
parent 0f954e5d09
commit 329726aa91
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=3428
2 changed files with 104 additions and 302 deletions

View File

@ -13,7 +13,7 @@
* the SMC Elite Ultra (8216), the 3Com 3c503, the NE1000 and NE2000,
* and a variety of similar clones.
*
* $Id: if_ed.c,v 1.47 1994/09/07 06:11:29 davidg Exp $
* $Id: if_ed.c,v 1.48 1994/09/16 13:33:40 davidg Exp $
*/
#include "ed.h"
@ -125,11 +125,6 @@ u_short ed_pio_write_mbufs();
void ed_setrcr(struct ifnet *, struct ed_softc *);
struct trailer_header {
u_short ether_type;
u_short ether_residual;
};
struct isa_driver eddriver = {
ed_probe,
ed_attach,
@ -1473,11 +1468,7 @@ ed_start(ifp)
/*
* Enable 16bit access to shared memory on
* WD/SMC boards Don't update wd_laar_proto
* because we want to restore the previous
* state (because an arp reply in the input
* code may cause a call-back to ed_start) XXX
* - the call-back to 'start' is a bug, IMHO.
* WD/SMC boards.
*/
case ED_VENDOR_WD_SMC:{
outb(sc->asic_addr + ED_WD_LAAR,
@ -1532,67 +1523,11 @@ ed_start(ifp)
ed_xmit(ifp);
/*
* If there is BPF support in the configuration, tap off here. The
* following has support for converting trailer packets back to
* normal. XXX - support for trailer packets in BPF should be moved
* into the bpf code proper to avoid code duplication in all of the
* drivers.
* Tap off here if there is a bpf listener.
*/
#if NBPFILTER > 0
if (sc->bpf) {
u_short etype;
int off, datasize, resid;
struct ether_header *eh;
struct trailer_header trailer_header;
char ether_packet[ETHER_MAX_LEN];
char *ep;
ep = ether_packet;
/*
* We handle trailers below: Copy ether header first, then
* residual data, then data. Put all this in a temporary
* buffer 'ether_packet' and send off to bpf. Since the system
* has generated this packet, we assume that all of the
* offsets in the packet are correct; if they're not, the
* system will almost certainly crash in m_copydata. We make
* no assumptions about how the data is arranged in the mbuf
* chain (i.e. how much data is in each mbuf, if mbuf clusters
* are used, etc.), which is why we use m_copydata to get the
* ether header rather than assume that this is located in the
* first mbuf.
*/
/* copy ether header */
m_copydata(m0, 0, sizeof(struct ether_header), ep);
eh = (struct ether_header *) ep;
ep += sizeof(struct ether_header);
etype = ntohs(eh->ether_type);
if (etype >= ETHERTYPE_TRAIL &&
etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
datasize = ((etype - ETHERTYPE_TRAIL) << 9);
off = datasize + sizeof(struct ether_header);
/* copy trailer_header into a data structure */
m_copydata(m0, off, sizeof(struct trailer_header),
(caddr_t) & trailer_header.ether_type);
/* copy residual data */
m_copydata(m0, off + sizeof(struct trailer_header),
resid = ntohs(trailer_header.ether_residual) -
sizeof(struct trailer_header), ep);
ep += resid;
/* copy data */
m_copydata(m0, sizeof(struct ether_header),
datasize, ep);
ep += datasize;
/* restore original ether packet type */
eh->ether_type = trailer_header.ether_type;
bpf_tap(sc->bpf, ether_packet, ep - ether_packet);
} else
bpf_mtap(sc->bpf, m0);
bpf_mtap(sc->bpf, m0);
}
#endif
@ -1646,8 +1581,36 @@ ed_rint(unit)
ed_pio_readmem(sc, packet_ptr, (char *) &packet_hdr,
sizeof(packet_hdr));
len = packet_hdr.count;
if ((len >= ETHER_MIN_LEN) && (len <= ETHER_MAX_LEN)) {
if (len > ETHER_MAX_LEN) {
/*
* Length is a wild value. There's a good chance that
* this was caused by the NIC being old and buggy.
* The bug is that the length low byte is duplicated in
* the high byte. Try to recalculate the length based on
* the pointer to the next packet.
*/
/*
* NOTE: sc->next_packet is pointing at the current packet.
*/
len &= ED_PAGE_SIZE - 1; /* preserve offset into page */
if (packet_hdr.next_packet >= sc->next_packet) {
len += (packet_hdr.next_packet - sc->next_packet) * ED_PAGE_SIZE;
} else {
len += ((packet_hdr.next_packet - sc->rec_page_start) +
(sc->rec_page_stop - sc->next_packet)) * ED_PAGE_SIZE;
}
}
/*
* Be fairly liberal about what we allow as a "reasonable" length
* so that a [crufty] packet will make it to BPF (and can thus
* be analyzed). Note that all that is really important is that
* we have a length that will fit into one mbuf cluster or less;
* the upper layer protocols can then figure out the length from
* their own length field(s).
*/
if ((len <= MCLBYTES) &&
(packet_hdr.next_packet >= sc->rec_page_start) &&
(packet_hdr.next_packet < sc->rec_page_stop)) {
/*
* Go get packet.
*/
@ -1655,12 +1618,8 @@ ed_rint(unit)
len - sizeof(struct ed_ring), packet_hdr.rsr & ED_RSR_PHY);
++sc->arpcom.ac_if.if_ipackets;
} else {
/*
* Really BAD...probably indicates that the ring
* pointers are corrupted. Also seen on early rev
* chips under high load - the byte order of the
* length gets switched.
* Really BAD. The ring pointers are corrupted.
*/
log(LOG_ERR,
"ed%d: NIC memory corrupt - invalid packet length %d\n",
@ -2087,20 +2046,15 @@ ed_get_packet(sc, buf, len, multicast)
int multicast;
{
struct ether_header *eh;
struct mbuf *m, *head = 0, *ed_ring_to_mbuf();
u_short off;
int resid;
u_short etype;
struct trailer_header trailer_header;
struct mbuf *m, *ed_ring_to_mbuf();
/* Allocate a header mbuf */
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == 0)
goto bad;
if (m == NULL)
return;
m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
m->m_pkthdr.len = len;
m->m_len = 0;
head = m;
/* The following sillines is to make NFS happy */
#define EROUND ((sizeof(struct ether_header) + 3) & ~3)
@ -2110,75 +2064,26 @@ ed_get_packet(sc, buf, len, multicast)
* The following assumes there is room for the ether header in the
* header mbuf
*/
head->m_data += EOFF;
eh = mtod(head, struct ether_header *);
m->m_data += EOFF;
eh = mtod(m, struct ether_header *);
if (sc->mem_shared)
bcopy(buf, mtod(head, caddr_t), sizeof(struct ether_header));
bcopy(buf, mtod(m, caddr_t), sizeof(struct ether_header));
else
ed_pio_readmem(sc, buf, mtod(head, caddr_t),
ed_pio_readmem(sc, buf, mtod(m, caddr_t),
sizeof(struct ether_header));
buf += sizeof(struct ether_header);
head->m_len += sizeof(struct ether_header);
m->m_len += sizeof(struct ether_header);
len -= sizeof(struct ether_header);
etype = ntohs((u_short) eh->ether_type);
/*
* Deal with trailer protocol: If trailer protocol, calculate the
* datasize as 'off', which is also the offset to the trailer header.
* Set resid to the amount of packet data following the trailer
* header. Finally, copy residual data into mbuf chain.
*/
if (etype >= ETHERTYPE_TRAIL &&
etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
off = (etype - ETHERTYPE_TRAIL) << 9;
if ((off + sizeof(struct trailer_header)) > len)
goto bad; /* insanity */
/*
* If we have shared memory, we can get info directly from the
* stored packet, otherwise we must get a local copy of the
* trailer header using PIO.
*/
if (sc->mem_shared) {
eh->ether_type = *ringoffset(sc, buf, off, u_short *);
resid = ntohs(*ringoffset(sc, buf, off + 2, u_short *));
} else {
struct trailer_header trailer_header;
ed_pio_readmem(sc,
ringoffset(sc, buf, off, caddr_t),
(char *) &trailer_header,
sizeof(trailer_header));
eh->ether_type = trailer_header.ether_type;
resid = trailer_header.ether_residual;
}
if ((off + resid) > len)
goto bad; /* insanity */
resid -= sizeof(struct trailer_header);
if (resid < 0)
goto bad; /* insanity */
m = ed_ring_to_mbuf(sc, ringoffset(sc, buf, off + 4, char *),
head, resid);
if (m == 0)
goto bad;
len = off;
head->m_pkthdr.len -= 4; /* subtract trailer header */
}
/*
* Pull packet off interface. Or if this was a trailer packet, the
* data portion is appended.
*/
m = ed_ring_to_mbuf(sc, buf, m, len);
if (m == 0)
goto bad;
if (ed_ring_to_mbuf(sc, buf, m, len) == NULL) {
m_freem(m);
return;
}
#if NBPFILTER > 0
@ -2187,7 +2092,7 @@ ed_get_packet(sc, buf, len, multicast)
* the raw packet to bpf.
*/
if (sc->bpf) {
bpf_mtap(sc->bpf, head);
bpf_mtap(sc->bpf, m);
/*
* Note that the interface cannot be in promiscuous mode if
@ -2196,8 +2101,8 @@ ed_get_packet(sc, buf, len, multicast)
*/
if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
sizeof(eh->ether_dhost)) != 0 && multicast == 0) {
m_freem(head);
sizeof(eh->ether_dhost)) != 0 && multicast == 0) {
m_freem(m);
return;
}
}
@ -2206,18 +2111,14 @@ ed_get_packet(sc, buf, len, multicast)
/*
* Fix up data start offset in mbuf to point past ether header
*/
m_adj(head, sizeof(struct ether_header));
m_adj(m, sizeof(struct ether_header));
/*
* silly ether_input routine needs 'type' in host byte order
*/
eh->ether_type = ntohs(eh->ether_type);
ether_input(&sc->arpcom.ac_if, eh, head);
return;
bad: if (head)
m_freem(head);
ether_input(&sc->arpcom.ac_if, eh, m);
return;
}

View File

@ -13,7 +13,7 @@
* the SMC Elite Ultra (8216), the 3Com 3c503, the NE1000 and NE2000,
* and a variety of similar clones.
*
* $Id: if_ed.c,v 1.47 1994/09/07 06:11:29 davidg Exp $
* $Id: if_ed.c,v 1.48 1994/09/16 13:33:40 davidg Exp $
*/
#include "ed.h"
@ -125,11 +125,6 @@ u_short ed_pio_write_mbufs();
void ed_setrcr(struct ifnet *, struct ed_softc *);
struct trailer_header {
u_short ether_type;
u_short ether_residual;
};
struct isa_driver eddriver = {
ed_probe,
ed_attach,
@ -1473,11 +1468,7 @@ ed_start(ifp)
/*
* Enable 16bit access to shared memory on
* WD/SMC boards Don't update wd_laar_proto
* because we want to restore the previous
* state (because an arp reply in the input
* code may cause a call-back to ed_start) XXX
* - the call-back to 'start' is a bug, IMHO.
* WD/SMC boards.
*/
case ED_VENDOR_WD_SMC:{
outb(sc->asic_addr + ED_WD_LAAR,
@ -1532,67 +1523,11 @@ ed_start(ifp)
ed_xmit(ifp);
/*
* If there is BPF support in the configuration, tap off here. The
* following has support for converting trailer packets back to
* normal. XXX - support for trailer packets in BPF should be moved
* into the bpf code proper to avoid code duplication in all of the
* drivers.
* Tap off here if there is a bpf listener.
*/
#if NBPFILTER > 0
if (sc->bpf) {
u_short etype;
int off, datasize, resid;
struct ether_header *eh;
struct trailer_header trailer_header;
char ether_packet[ETHER_MAX_LEN];
char *ep;
ep = ether_packet;
/*
* We handle trailers below: Copy ether header first, then
* residual data, then data. Put all this in a temporary
* buffer 'ether_packet' and send off to bpf. Since the system
* has generated this packet, we assume that all of the
* offsets in the packet are correct; if they're not, the
* system will almost certainly crash in m_copydata. We make
* no assumptions about how the data is arranged in the mbuf
* chain (i.e. how much data is in each mbuf, if mbuf clusters
* are used, etc.), which is why we use m_copydata to get the
* ether header rather than assume that this is located in the
* first mbuf.
*/
/* copy ether header */
m_copydata(m0, 0, sizeof(struct ether_header), ep);
eh = (struct ether_header *) ep;
ep += sizeof(struct ether_header);
etype = ntohs(eh->ether_type);
if (etype >= ETHERTYPE_TRAIL &&
etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
datasize = ((etype - ETHERTYPE_TRAIL) << 9);
off = datasize + sizeof(struct ether_header);
/* copy trailer_header into a data structure */
m_copydata(m0, off, sizeof(struct trailer_header),
(caddr_t) & trailer_header.ether_type);
/* copy residual data */
m_copydata(m0, off + sizeof(struct trailer_header),
resid = ntohs(trailer_header.ether_residual) -
sizeof(struct trailer_header), ep);
ep += resid;
/* copy data */
m_copydata(m0, sizeof(struct ether_header),
datasize, ep);
ep += datasize;
/* restore original ether packet type */
eh->ether_type = trailer_header.ether_type;
bpf_tap(sc->bpf, ether_packet, ep - ether_packet);
} else
bpf_mtap(sc->bpf, m0);
bpf_mtap(sc->bpf, m0);
}
#endif
@ -1646,8 +1581,36 @@ ed_rint(unit)
ed_pio_readmem(sc, packet_ptr, (char *) &packet_hdr,
sizeof(packet_hdr));
len = packet_hdr.count;
if ((len >= ETHER_MIN_LEN) && (len <= ETHER_MAX_LEN)) {
if (len > ETHER_MAX_LEN) {
/*
* Length is a wild value. There's a good chance that
* this was caused by the NIC being old and buggy.
* The bug is that the length low byte is duplicated in
* the high byte. Try to recalculate the length based on
* the pointer to the next packet.
*/
/*
* NOTE: sc->next_packet is pointing at the current packet.
*/
len &= ED_PAGE_SIZE - 1; /* preserve offset into page */
if (packet_hdr.next_packet >= sc->next_packet) {
len += (packet_hdr.next_packet - sc->next_packet) * ED_PAGE_SIZE;
} else {
len += ((packet_hdr.next_packet - sc->rec_page_start) +
(sc->rec_page_stop - sc->next_packet)) * ED_PAGE_SIZE;
}
}
/*
* Be fairly liberal about what we allow as a "reasonable" length
* so that a [crufty] packet will make it to BPF (and can thus
* be analyzed). Note that all that is really important is that
* we have a length that will fit into one mbuf cluster or less;
* the upper layer protocols can then figure out the length from
* their own length field(s).
*/
if ((len <= MCLBYTES) &&
(packet_hdr.next_packet >= sc->rec_page_start) &&
(packet_hdr.next_packet < sc->rec_page_stop)) {
/*
* Go get packet.
*/
@ -1655,12 +1618,8 @@ ed_rint(unit)
len - sizeof(struct ed_ring), packet_hdr.rsr & ED_RSR_PHY);
++sc->arpcom.ac_if.if_ipackets;
} else {
/*
* Really BAD...probably indicates that the ring
* pointers are corrupted. Also seen on early rev
* chips under high load - the byte order of the
* length gets switched.
* Really BAD. The ring pointers are corrupted.
*/
log(LOG_ERR,
"ed%d: NIC memory corrupt - invalid packet length %d\n",
@ -2087,20 +2046,15 @@ ed_get_packet(sc, buf, len, multicast)
int multicast;
{
struct ether_header *eh;
struct mbuf *m, *head = 0, *ed_ring_to_mbuf();
u_short off;
int resid;
u_short etype;
struct trailer_header trailer_header;
struct mbuf *m, *ed_ring_to_mbuf();
/* Allocate a header mbuf */
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == 0)
goto bad;
if (m == NULL)
return;
m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
m->m_pkthdr.len = len;
m->m_len = 0;
head = m;
/* The following sillines is to make NFS happy */
#define EROUND ((sizeof(struct ether_header) + 3) & ~3)
@ -2110,75 +2064,26 @@ ed_get_packet(sc, buf, len, multicast)
* The following assumes there is room for the ether header in the
* header mbuf
*/
head->m_data += EOFF;
eh = mtod(head, struct ether_header *);
m->m_data += EOFF;
eh = mtod(m, struct ether_header *);
if (sc->mem_shared)
bcopy(buf, mtod(head, caddr_t), sizeof(struct ether_header));
bcopy(buf, mtod(m, caddr_t), sizeof(struct ether_header));
else
ed_pio_readmem(sc, buf, mtod(head, caddr_t),
ed_pio_readmem(sc, buf, mtod(m, caddr_t),
sizeof(struct ether_header));
buf += sizeof(struct ether_header);
head->m_len += sizeof(struct ether_header);
m->m_len += sizeof(struct ether_header);
len -= sizeof(struct ether_header);
etype = ntohs((u_short) eh->ether_type);
/*
* Deal with trailer protocol: If trailer protocol, calculate the
* datasize as 'off', which is also the offset to the trailer header.
* Set resid to the amount of packet data following the trailer
* header. Finally, copy residual data into mbuf chain.
*/
if (etype >= ETHERTYPE_TRAIL &&
etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
off = (etype - ETHERTYPE_TRAIL) << 9;
if ((off + sizeof(struct trailer_header)) > len)
goto bad; /* insanity */
/*
* If we have shared memory, we can get info directly from the
* stored packet, otherwise we must get a local copy of the
* trailer header using PIO.
*/
if (sc->mem_shared) {
eh->ether_type = *ringoffset(sc, buf, off, u_short *);
resid = ntohs(*ringoffset(sc, buf, off + 2, u_short *));
} else {
struct trailer_header trailer_header;
ed_pio_readmem(sc,
ringoffset(sc, buf, off, caddr_t),
(char *) &trailer_header,
sizeof(trailer_header));
eh->ether_type = trailer_header.ether_type;
resid = trailer_header.ether_residual;
}
if ((off + resid) > len)
goto bad; /* insanity */
resid -= sizeof(struct trailer_header);
if (resid < 0)
goto bad; /* insanity */
m = ed_ring_to_mbuf(sc, ringoffset(sc, buf, off + 4, char *),
head, resid);
if (m == 0)
goto bad;
len = off;
head->m_pkthdr.len -= 4; /* subtract trailer header */
}
/*
* Pull packet off interface. Or if this was a trailer packet, the
* data portion is appended.
*/
m = ed_ring_to_mbuf(sc, buf, m, len);
if (m == 0)
goto bad;
if (ed_ring_to_mbuf(sc, buf, m, len) == NULL) {
m_freem(m);
return;
}
#if NBPFILTER > 0
@ -2187,7 +2092,7 @@ ed_get_packet(sc, buf, len, multicast)
* the raw packet to bpf.
*/
if (sc->bpf) {
bpf_mtap(sc->bpf, head);
bpf_mtap(sc->bpf, m);
/*
* Note that the interface cannot be in promiscuous mode if
@ -2196,8 +2101,8 @@ ed_get_packet(sc, buf, len, multicast)
*/
if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
sizeof(eh->ether_dhost)) != 0 && multicast == 0) {
m_freem(head);
sizeof(eh->ether_dhost)) != 0 && multicast == 0) {
m_freem(m);
return;
}
}
@ -2206,18 +2111,14 @@ ed_get_packet(sc, buf, len, multicast)
/*
* Fix up data start offset in mbuf to point past ether header
*/
m_adj(head, sizeof(struct ether_header));
m_adj(m, sizeof(struct ether_header));
/*
* silly ether_input routine needs 'type' in host byte order
*/
eh->ether_type = ntohs(eh->ether_type);
ether_input(&sc->arpcom.ac_if, eh, head);
return;
bad: if (head)
m_freem(head);
ether_input(&sc->arpcom.ac_if, eh, m);
return;
}