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

Reply via email to