Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Jul 2014 16:13:44 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r268219 - stable/10/sys/dev/usb/net
Message-ID:  <201407031613.s63GDiCW038423@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407031613.s63GDiCW038423>