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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user