- Disable hardware checksumming until it is properly tested.

- Don't discard frames if the dropped or error flag is set.
- Don't remove the last 4-bytes of every packet.
- Add extra range check for data position offset when receiving data.

MFC after:	1 day
PR:		191432
This commit is contained in:
hselasky 2014-07-03 10:49:46 +00:00
parent 9f9f2874f6
commit da0fdeefee

View File

@ -123,8 +123,8 @@ static int axge_attach_post_sub(struct usb_ether *);
static int axge_ifmedia_upd(struct ifnet *);
static void axge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
static int axge_ioctl(struct ifnet *, u_long, caddr_t);
static int axge_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
static int axge_rxeof(struct usb_ether *, struct usb_page_cache *,
static void axge_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
static void axge_rxeof(struct usb_ether *, struct usb_page_cache *,
unsigned int, unsigned int, uint32_t);
static void axge_csum_cfg(struct usb_ether *);
@ -605,8 +605,7 @@ axge_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
pc = usbd_xfer_get_frame(xfer, 0);
if (axge_rx_frame(ue, pc, actlen) != 0)
goto tr_setup;
axge_rx_frame(ue, pc, actlen);
/* FALLTHROUGH */
case USB_ST_SETUP:
@ -926,12 +925,11 @@ axge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (error);
}
static int
static void
axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
{
int error;
int pos;
int pkt_cnt;
uint32_t pos;
uint32_t pkt_cnt;
uint32_t rxhdr;
uint32_t pkt_hdr;
uint32_t hdr_off;
@ -939,10 +937,9 @@ axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
/* verify we have enough data */
if (actlen < (int)sizeof(rxhdr))
return (EINVAL);
return;
pos = 0;
error = 0;
usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr));
rxhdr = le32toh(rxhdr);
@ -950,35 +947,36 @@ axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
pkt_cnt = (uint16_t)rxhdr;
hdr_off = (uint16_t)(rxhdr >> 16);
while (pkt_cnt > 0) {
while (pkt_cnt--) {
/* verify the header offset */
if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) {
error = EINVAL;
DPRINTF("End of packet headers\n");
break;
}
if ((int)pos >= actlen) {
DPRINTF("Data position reached end\n");
break;
}
usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
pkt_hdr = le32toh(pkt_hdr);
pktlen = (pkt_hdr >> 16) & 0x1fff;
if ((pkt_hdr & AXGE_RXHDR_CRC_ERR) ||
(pkt_hdr & AXGE_RXHDR_DROP_ERR))
if (pkt_hdr & (AXGE_RXHDR_CRC_ERR | AXGE_RXHDR_DROP_ERR)) {
DPRINTF("Dropped a packet\n");
ue->ue_ifp->if_ierrors++;
/* verify the data payload */
if (pktlen < 6 || (int)(pos + 2 + pktlen - 6) > actlen) {
error = EINVAL;
break;
}
axge_rxeof(ue, pc, pos + 2, pktlen - 6, pkt_hdr);
if (pktlen >= 2 && (int)(pos + pktlen) <= actlen) {
axge_rxeof(ue, pc, pos + 2, pktlen - 2, pkt_hdr);
} else {
DPRINTF("Invalid packet pos=%d len=%d\n",
(int)pos, (int)pktlen);
}
pos += (pktlen + 7) & ~7;
hdr_off += sizeof(pkt_hdr);
pkt_cnt--;
}
if (error != 0)
ue->ue_ifp->if_ierrors++;
return (error);
}
static int
static void
axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc,
unsigned int offset, unsigned int len, uint32_t pkt_hdr)
{
@ -988,37 +986,34 @@ axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc,
ifp = ue->ue_ifp;
if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) {
ifp->if_ierrors++;
return (EINVAL);
return;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
ifp->if_iqdrops++;
return (ENOMEM);
return;
}
m->m_len = m->m_pkthdr.len = MCLBYTES;
m->m_pkthdr.rcvif = ifp;
m->m_len = m->m_pkthdr.len = len + ETHER_ALIGN;
m_adj(m, ETHER_ALIGN);
usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
ifp->if_ipackets++;
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = len;
#if 0
if ((pkt_hdr & (AXGE_RXHDR_L4CSUM_ERR | AXGE_RXHDR_L3CSUM_ERR)) == 0) {
m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | CSUM_IP_VALID;
if ((pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
AXGE_RXHDR_L4_TYPE_TCP ||
(pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
AXGE_RXHDR_L4_TYPE_UDP) {
m->m_pkthdr.csum_flags |= CSUM_DATA_VALID |
CSUM_PSEUDO_HDR;
CSUM_PSEUDO_HDR | CSUM_IP_CHECKED | CSUM_IP_VALID;
m->m_pkthdr.csum_data = 0xffff;
}
}
#endif
_IF_ENQUEUE(&ue->ue_rxq, m);
return (0);
}
static void