diff options
Diffstat (limited to 'net/ipv4/ipcomp.c')
-rw-r--r-- | net/ipv4/ipcomp.c | 34 |
1 files changed, 8 insertions, 26 deletions
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 95278b22b669..3ed8b57a1002 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -45,7 +45,6 @@ static LIST_HEAD(ipcomp_tfms_list); | |||
45 | static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) | 45 | static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) |
46 | { | 46 | { |
47 | int err, plen, dlen; | 47 | int err, plen, dlen; |
48 | struct iphdr *iph; | ||
49 | struct ipcomp_data *ipcd = x->data; | 48 | struct ipcomp_data *ipcd = x->data; |
50 | u8 *start, *scratch; | 49 | u8 *start, *scratch; |
51 | struct crypto_tfm *tfm; | 50 | struct crypto_tfm *tfm; |
@@ -74,8 +73,6 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) | |||
74 | 73 | ||
75 | skb_put(skb, dlen - plen); | 74 | skb_put(skb, dlen - plen); |
76 | memcpy(skb->data, scratch, dlen); | 75 | memcpy(skb->data, scratch, dlen); |
77 | iph = skb->nh.iph; | ||
78 | iph->tot_len = htons(dlen + iph->ihl * 4); | ||
79 | out: | 76 | out: |
80 | put_cpu(); | 77 | put_cpu(); |
81 | return err; | 78 | return err; |
@@ -83,34 +80,21 @@ out: | |||
83 | 80 | ||
84 | static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) | 81 | static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) |
85 | { | 82 | { |
86 | u8 nexthdr; | 83 | int err = -ENOMEM; |
87 | int err = 0; | ||
88 | struct iphdr *iph; | 84 | struct iphdr *iph; |
89 | union { | 85 | struct ip_comp_hdr *ipch; |
90 | struct iphdr iph; | ||
91 | char buf[60]; | ||
92 | } tmp_iph; | ||
93 | |||
94 | 86 | ||
95 | if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && | 87 | if (skb_linearize_cow(skb)) |
96 | skb_linearize(skb, GFP_ATOMIC) != 0) { | ||
97 | err = -ENOMEM; | ||
98 | goto out; | 88 | goto out; |
99 | } | ||
100 | 89 | ||
101 | skb->ip_summed = CHECKSUM_NONE; | 90 | skb->ip_summed = CHECKSUM_NONE; |
102 | 91 | ||
103 | /* Remove ipcomp header and decompress original payload */ | 92 | /* Remove ipcomp header and decompress original payload */ |
104 | iph = skb->nh.iph; | 93 | iph = skb->nh.iph; |
105 | memcpy(&tmp_iph, iph, iph->ihl * 4); | 94 | ipch = (void *)skb->data; |
106 | nexthdr = *(u8 *)skb->data; | 95 | iph->protocol = ipch->nexthdr; |
107 | skb_pull(skb, sizeof(struct ip_comp_hdr)); | 96 | skb->h.raw = skb->nh.raw + sizeof(*ipch); |
108 | skb->nh.raw += sizeof(struct ip_comp_hdr); | 97 | __skb_pull(skb, sizeof(*ipch)); |
109 | memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4); | ||
110 | iph = skb->nh.iph; | ||
111 | iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr)); | ||
112 | iph->protocol = nexthdr; | ||
113 | skb->h.raw = skb->data; | ||
114 | err = ipcomp_decompress(x, skb); | 98 | err = ipcomp_decompress(x, skb); |
115 | 99 | ||
116 | out: | 100 | out: |
@@ -171,10 +155,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
171 | goto out_ok; | 155 | goto out_ok; |
172 | } | 156 | } |
173 | 157 | ||
174 | if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && | 158 | if (skb_linearize_cow(skb)) |
175 | skb_linearize(skb, GFP_ATOMIC) != 0) { | ||
176 | goto out_ok; | 159 | goto out_ok; |
177 | } | ||
178 | 160 | ||
179 | err = ipcomp_compress(x, skb); | 161 | err = ipcomp_compress(x, skb); |
180 | iph = skb->nh.iph; | 162 | iph = skb->nh.iph; |