summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/drivers/net/undinet.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c
index 03515fd5e..2a097ff2c 100644
--- a/src/arch/i386/drivers/net/undinet.c
+++ b/src/arch/i386/drivers/net/undinet.c
@@ -418,6 +418,7 @@ static void undinet_poll ( struct net_device *netdev ) {
struct io_buffer *iobuf = NULL;
size_t len;
size_t frag_len;
+ size_t max_frag_len;
int rc;
if ( ! undinic->isr_processing ) {
@@ -446,6 +447,14 @@ static void undinet_poll ( struct net_device *netdev ) {
/* Packet fragment received */
len = undi_isr.FrameLength;
frag_len = undi_isr.BufferLength;
+ if ( ( len == 0 ) || ( len < frag_len ) ) {
+ /* Don't laugh. VMWare does it. */
+ DBGC ( undinic, "UNDINIC %p reported insane "
+ "fragment (%zd of %zd bytes)\n",
+ undinic, frag_len, len );
+ netdev_rx_err ( netdev, NULL, -EINVAL );
+ break;
+ }
if ( ! iobuf )
iobuf = alloc_iob ( len );
if ( ! iobuf ) {
@@ -456,10 +465,13 @@ static void undinet_poll ( struct net_device *netdev ) {
netdev_rx_err ( netdev, NULL, -ENOMEM );
goto done;
}
- if ( frag_len > iob_tailroom ( iobuf ) ) {
- DBGC ( undinic, "UNDINIC %p fragment too "
- "large\n", undinic );
- frag_len = iob_tailroom ( iobuf );
+ max_frag_len = iob_tailroom ( iobuf );
+ if ( frag_len > max_frag_len ) {
+ DBGC ( undinic, "UNDINIC %p fragment too big "
+ "(%zd+%zd does not fit into %zd)\n",
+ undinic, iob_len ( iobuf ), frag_len,
+ ( iob_len ( iobuf ) + max_frag_len ) );
+ frag_len = max_frag_len;
}
copy_from_real ( iob_put ( iobuf, frag_len ),
undi_isr.Frame.segment,
@@ -473,6 +485,8 @@ static void undinet_poll ( struct net_device *netdev ) {
*/
if ( undinic->hacks & UNDI_HACK_EB54 )
--last_trigger_count;
+ /** HACK: effective RX quota of 1 */
+ goto done;
}
break;
case PXENV_UNDI_ISR_OUT_DONE:
@@ -491,8 +505,9 @@ static void undinet_poll ( struct net_device *netdev ) {
done:
if ( iobuf ) {
- DBGC ( undinic, "UNDINIC %p returned incomplete packet\n",
- undinic );
+ DBGC ( undinic, "UNDINIC %p returned incomplete packet "
+ "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
+ ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
netdev_rx_err ( netdev, iobuf, -EINVAL );
}
}