diff options
author | Michael Brown | 2006-08-09 03:24:32 +0200 |
---|---|---|
committer | Michael Brown | 2006-08-09 03:24:32 +0200 |
commit | a3d508b648906fb742e5205bcd4b97fbf88ea653 (patch) | |
tree | f5783a075a4d73d014949412a2323637bace4a09 /src/net/ipv4.c | |
parent | Note to self: learn to count. (diff) | |
download | ipxe-a3d508b648906fb742e5205bcd4b97fbf88ea653.tar.gz ipxe-a3d508b648906fb742e5205bcd4b97fbf88ea653.tar.xz ipxe-a3d508b648906fb742e5205bcd4b97fbf88ea653.zip |
Clarified packet ownership transfer between a few functions.
Added a large number of missing calls to free_pkb(). In the case of UDP,
no received packets were ever freed, which lead to memory exhaustion
remarkably quickly once pxelinux started up.
In general, any function with _rx() in its name which accepts a pk_buff
*must* either call free_pkb() or pass the pkb to another _rx() function
(e.g. the next layer up the stack). Since the UDP (and TCP) layers don't
pass packet buffers up to the higher-layer protocols (the
"applications"), they must free the packet buffer after calling the
application's newdata() method.
Diffstat (limited to 'src/net/ipv4.c')
-rw-r--r-- | src/net/ipv4.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/src/net/ipv4.c b/src/net/ipv4.c index 59fa9f82..da16452f 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -389,9 +389,8 @@ static int ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused, /* Sanity check */ if ( pkb_len ( pkb ) < sizeof ( *iphdr ) ) { - DBG ( "IP datagram too short (%d bytes)\n", - pkb_len ( pkb ) ); - return -EINVAL; + DBG ( "IP datagram too short (%d bytes)\n", pkb_len ( pkb ) ); + goto err; } /* Print IP4 header for debugging */ @@ -400,14 +399,14 @@ static int ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused, /* Validate version and header length */ if ( iphdr->verhdrlen != 0x45 ) { DBG ( "Bad version and header length %x\n", iphdr->verhdrlen ); - return -EINVAL; + goto err; } /* Validate length of IP packet */ if ( ntohs ( iphdr->len ) > pkb_len ( pkb ) ) { DBG ( "Inconsistent packet length %d\n", ntohs ( iphdr->len ) ); - return -EINVAL; + goto err; } /* Verify the checksum */ @@ -447,6 +446,10 @@ static int ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused, /* Send it to the transport layer */ return tcpip_rx ( pkb, iphdr->protocol, &src.st, &dest.st ); + + err: + free_pkb ( pkb ); + return -EINVAL; } /** |