diff options
| -rw-r--r-- | drivers/net/ppp_generic.c | 4 | ||||
| -rw-r--r-- | drivers/net/pppoe.c | 3 | ||||
| -rw-r--r-- | include/linux/skbuff.h | 4 | ||||
| -rw-r--r-- | net/802/psnap.c | 3 | ||||
| -rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
| -rw-r--r-- | net/bridge/br_netfilter.c | 6 | ||||
| -rw-r--r-- | net/core/skbuff.c | 21 |
7 files changed, 32 insertions, 15 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 0245e40b51a1..f608c12e3e8b 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
| @@ -1691,8 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) | |||
| 1691 | || ppp->npmode[npi] != NPMODE_PASS) { | 1691 | || ppp->npmode[npi] != NPMODE_PASS) { |
| 1692 | kfree_skb(skb); | 1692 | kfree_skb(skb); |
| 1693 | } else { | 1693 | } else { |
| 1694 | skb_pull(skb, 2); /* chop off protocol */ | 1694 | /* chop off protocol */ |
| 1695 | skb_postpull_rcsum(skb, skb->data - 2, 2); | 1695 | skb_pull_rcsum(skb, 2); |
| 1696 | skb->dev = ppp->dev; | 1696 | skb->dev = ppp->dev; |
| 1697 | skb->protocol = htons(npindex_to_ethertype[npi]); | 1697 | skb->protocol = htons(npindex_to_ethertype[npi]); |
| 1698 | skb->mac.raw = skb->data; | 1698 | skb->mac.raw = skb->data; |
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 9369f811075d..475dc930380f 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
| @@ -337,8 +337,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) | |||
| 337 | if (sk->sk_state & PPPOX_BOUND) { | 337 | if (sk->sk_state & PPPOX_BOUND) { |
| 338 | struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; | 338 | struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; |
| 339 | int len = ntohs(ph->length); | 339 | int len = ntohs(ph->length); |
| 340 | skb_pull(skb, sizeof(struct pppoe_hdr)); | 340 | skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); |
| 341 | skb_postpull_rcsum(skb, ph, sizeof(*ph)); | ||
| 342 | if (pskb_trim_rcsum(skb, len)) | 341 | if (pskb_trim_rcsum(skb, len)) |
| 343 | goto abort_kfree; | 342 | goto abort_kfree; |
| 344 | 343 | ||
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 75c963103b9f..613b9513f8b9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -1159,12 +1159,14 @@ static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp) | |||
| 1159 | */ | 1159 | */ |
| 1160 | 1160 | ||
| 1161 | static inline void skb_postpull_rcsum(struct sk_buff *skb, | 1161 | static inline void skb_postpull_rcsum(struct sk_buff *skb, |
| 1162 | const void *start, int len) | 1162 | const void *start, unsigned int len) |
| 1163 | { | 1163 | { |
| 1164 | if (skb->ip_summed == CHECKSUM_HW) | 1164 | if (skb->ip_summed == CHECKSUM_HW) |
| 1165 | skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); | 1165 | skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); |
| 1166 | } | 1166 | } |
| 1167 | 1167 | ||
| 1168 | unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); | ||
| 1169 | |||
| 1168 | /** | 1170 | /** |
| 1169 | * pskb_trim_rcsum - trim received skb and update checksum | 1171 | * pskb_trim_rcsum - trim received skb and update checksum |
| 1170 | * @skb: buffer to trim | 1172 | * @skb: buffer to trim |
diff --git a/net/802/psnap.c b/net/802/psnap.c index 34e42968b477..97c95eec79ed 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c | |||
| @@ -61,8 +61,7 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 61 | /* Pass the frame on. */ | 61 | /* Pass the frame on. */ |
| 62 | u8 *hdr = skb->data; | 62 | u8 *hdr = skb->data; |
| 63 | skb->h.raw += 5; | 63 | skb->h.raw += 5; |
| 64 | skb_pull(skb, 5); | 64 | skb_pull_rcsum(skb, 5); |
| 65 | skb_postpull_rcsum(skb, hdr, 5); | ||
| 66 | rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); | 65 | rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); |
| 67 | } else { | 66 | } else { |
| 68 | skb->sk = NULL; | 67 | skb->sk = NULL; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 0f604d227da2..da9cfe927158 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -163,10 +163,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
| 163 | stats->rx_packets++; | 163 | stats->rx_packets++; |
| 164 | stats->rx_bytes += skb->len; | 164 | stats->rx_bytes += skb->len; |
| 165 | 165 | ||
| 166 | skb_pull(skb, VLAN_HLEN); /* take off the VLAN header (4 bytes currently) */ | 166 | /* Take off the VLAN header (4 bytes currently) */ |
| 167 | 167 | skb_pull_rcsum(skb, VLAN_HLEN); | |
| 168 | /* Need to correct hardware checksum */ | ||
| 169 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
| 170 | 168 | ||
| 171 | /* Ok, lets check to make sure the device (dev) we | 169 | /* Ok, lets check to make sure the device (dev) we |
| 172 | * came in on is what this VLAN is attached to. | 170 | * came in on is what this VLAN is attached to. |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e060aad8624d..6787bc5197f7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -425,8 +425,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 425 | 425 | ||
| 426 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 426 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { |
| 427 | u8 *vhdr = skb->data; | 427 | u8 *vhdr = skb->data; |
| 428 | skb_pull(skb, VLAN_HLEN); | 428 | skb_pull_rcsum(skb, VLAN_HLEN); |
| 429 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
| 430 | skb->nh.raw += VLAN_HLEN; | 429 | skb->nh.raw += VLAN_HLEN; |
| 431 | } | 430 | } |
| 432 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); | 431 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); |
| @@ -444,8 +443,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 444 | 443 | ||
| 445 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 444 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { |
| 446 | u8 *vhdr = skb->data; | 445 | u8 *vhdr = skb->data; |
| 447 | skb_pull(skb, VLAN_HLEN); | 446 | skb_pull_rcsum(skb, VLAN_HLEN); |
| 448 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
| 449 | skb->nh.raw += VLAN_HLEN; | 447 | skb->nh.raw += VLAN_HLEN; |
| 450 | } | 448 | } |
| 451 | 449 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 01abf1e8990b..2960c8b82b23 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -1795,6 +1795,27 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, | |||
| 1795 | return 0; | 1795 | return 0; |
| 1796 | } | 1796 | } |
| 1797 | 1797 | ||
| 1798 | /** | ||
| 1799 | * skb_pull_rcsum - pull skb and update receive checksum | ||
| 1800 | * @skb: buffer to update | ||
| 1801 | * @start: start of data before pull | ||
| 1802 | * @len: length of data pulled | ||
| 1803 | * | ||
| 1804 | * This function performs an skb_pull on the packet and updates | ||
| 1805 | * update the CHECKSUM_HW checksum. It should be used on receive | ||
| 1806 | * path processing instead of skb_pull unless you know that the | ||
| 1807 | * checksum difference is zero (e.g., a valid IP header) or you | ||
| 1808 | * are setting ip_summed to CHECKSUM_NONE. | ||
| 1809 | */ | ||
| 1810 | unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) | ||
| 1811 | { | ||
| 1812 | BUG_ON(len > skb->len); | ||
| 1813 | skb->len -= len; | ||
| 1814 | BUG_ON(skb->len < skb->data_len); | ||
| 1815 | skb_postpull_rcsum(skb, skb->data, len); | ||
| 1816 | return skb->data += len; | ||
| 1817 | } | ||
| 1818 | |||
| 1798 | void __init skb_init(void) | 1819 | void __init skb_init(void) |
| 1799 | { | 1820 | { |
| 1800 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", | 1821 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", |
