summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2014-07-03 10:49:46 +0000
committerhselasky <hselasky@FreeBSD.org>2014-07-03 10:49:46 +0000
commitda0fdeefee4419578b08e9bd94dc1b02617d5ca3 (patch)
treef7de0cc86d83c18c0a601332e7cde6c2457a6398
parent9f9f2874f668cfc964a2d62f908e115c4c9b6211 (diff)
downloadFreeBSD-src-da0fdeefee4419578b08e9bd94dc1b02617d5ca3.zip
FreeBSD-src-da0fdeefee4419578b08e9bd94dc1b02617d5ca3.tar.gz
- 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
-rw-r--r--sys/dev/usb/net/if_axge.c63
1 files changed, 29 insertions, 34 deletions
diff --git a/sys/dev/usb/net/if_axge.c b/sys/dev/usb/net/if_axge.c
index 15a60f2..351e0aa 100644
--- a/sys/dev/usb/net/if_axge.c
+++ b/sys/dev/usb/net/if_axge.c
@@ -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
OpenPOWER on IntegriCloud