svn commit: r268219 - stable/10/sys/dev/usb/net
Hans Petter Selasky
hselasky at FreeBSD.org
Thu Jul 3 16:13:44 UTC 2014
Author: hselasky
Date: Thu Jul 3 16:13:44 2014
New Revision: 268219
URL: http://svnweb.freebsd.org/changeset/base/268219
Log:
MFC r267955 and r268209:
- Add proper rangechecks in "axge_rx_frame()" function and
fix receive loop header parsing.
- Disable hardware checksumming until it is properly tested.
PR: 191432
Modified:
stable/10/sys/dev/usb/net/if_axge.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/usb/net/if_axge.c
==============================================================================
--- stable/10/sys/dev/usb/net/if_axge.c Thu Jul 3 16:01:30 2014 (r268218)
+++ stable/10/sys/dev/usb/net/if_axge.c Thu Jul 3 16:13:44 2014 (r268219)
@@ -123,8 +123,8 @@ static int axge_attach_post_sub(struct u
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
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,18 +925,21 @@ axge_ioctl(struct ifnet *ifp, u_long cmd
return (error);
}
-static int
+static void
axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
{
- int error, pos;
- int pkt_cnt;
- uint32_t rxhdr, pkt_hdr;
- uint16_t hdr_off;
- uint16_t len, pktlen;
+ uint32_t pos;
+ uint32_t pkt_cnt;
+ uint32_t rxhdr;
+ uint32_t pkt_hdr;
+ uint32_t hdr_off;
+ uint32_t pktlen;
+
+ /* verify we have enough data */
+ if (actlen < (int)sizeof(rxhdr))
+ return;
pos = 0;
- len = 0;
- error = 0;
usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr));
rxhdr = le32toh(rxhdr);
@@ -945,31 +947,36 @@ axge_rx_frame(struct usb_ether *ue, stru
pkt_cnt = (uint16_t)rxhdr;
hdr_off = (uint16_t)(rxhdr >> 16);
- usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
-
- while (pkt_cnt > 0) {
- if ((int)(sizeof(pkt_hdr)) > actlen) {
- error = EINVAL;
+ while (pkt_cnt--) {
+ /* verify the header offset */
+ if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) {
+ 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++;
- axge_rxeof(ue, pc, pos + 2, pktlen - 6, pkt_hdr);
- len = (pktlen + 7) & ~7;
- pos += len;
- pkt_hdr++;
- pkt_cnt--;
+ }
+ 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);
}
-
- 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)
{
@@ -979,37 +986,34 @@ axge_rxeof(struct usb_ether *ue, struct
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
More information about the svn-src-all
mailing list