With input from mk, we improved the diff.
Testing is very much appreciated.
mk@ suggests checking total_len right after xfer_status to make
sure the header is safe to use.
There's a mistake in the DPRINTF() fo RX status, one parameter is missing.
This caused another crash when debug mode is enabled.
it discards packets that are more than UDAV_BUFSZ even if the status
is correct (This is from mk@).
The datasheet mentions that a normal packet is 1522 bytes.
It works with no regression on my udav(4).
Index: src/sys/dev/usb/if_udav.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_udav.c,v
retrieving revision 1.54
diff -u -p -r1.54 if_udav.c
--- src/sys/dev/usb/if_udav.c 20 Mar 2011 17:58:26 -0000 1.54
+++ src/sys/dev/usb/if_udav.c 20 Mar 2011 19:58:51 -0000
@@ -1128,18 +1128,25 @@ udav_rxeof(usbd_xfer_handle xfer, usbd_p
usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
+ if (total_len < UDAV_RX_HDRLEN) {
+ ifp->if_ierrors++;
+ goto done;
+ }
+
h = (struct udav_rx_hdr *)c->udav_buf;
total_len = UGETW(h->length) - ETHER_CRC_LEN;
- DPRINTF(("%s: RX Status: 0x%02x\n", h->pktstat));
+ DPRINTF(("%s: RX Status: 0x%02x\n", sc->sc_dev.dv_xname, h->pktstat));
if (h->pktstat & UDAV_RSR_LCS) {
ifp->if_collisions++;
goto done;
}
+ /* RX status may still be correct but total_len is bogus */
if (total_len < sizeof(struct ether_header) ||
- h->pktstat & UDAV_RSR_ERR) {
+ h->pktstat & UDAV_RSR_ERR ||
+ total_len > UDAV_BUFSZ ) {
ifp->if_ierrors++;
goto done;
}
Index: src/sys/dev/usb/if_udavreg.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_udavreg.h,v
retrieving revision 1.11
diff -u -p -r1.11 if_udavreg.h
--- src/sys/dev/usb/if_udavreg.h 6 Dec 2010 04:41:39 -0000 1.11
+++ src/sys/dev/usb/if_udavreg.h 20 Mar 2011 19:58:51 -0000
@@ -200,6 +200,6 @@ struct udav_rx_hdr {
#define UDAV_RX_HDRLEN sizeof(struct udav_rx_hdr)
/* Packet length */
-#define UDAV_MAX_MTU 1536 /* XXX: max frame size is unknown
*/
+#define UDAV_MAX_MTU 1522 /* According to datasheet */
#define UDAV_MIN_FRAME_LEN 60
#define UDAV_BUFSZ UDAV_MAX_MTU + UDAV_RX_HDRLEN