|
@@ -119,6 +119,7 @@ error:
|
|
static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
|
|
static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
|
|
{
|
|
{
|
|
int ah_hlen;
|
|
int ah_hlen;
|
|
|
|
+ int ihl;
|
|
struct iphdr *iph;
|
|
struct iphdr *iph;
|
|
struct ip_auth_hdr *ah;
|
|
struct ip_auth_hdr *ah;
|
|
struct ah_data *ahp;
|
|
struct ah_data *ahp;
|
|
@@ -149,13 +150,14 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
|
|
ah = (struct ip_auth_hdr*)skb->data;
|
|
ah = (struct ip_auth_hdr*)skb->data;
|
|
iph = skb->nh.iph;
|
|
iph = skb->nh.iph;
|
|
|
|
|
|
- memcpy(work_buf, iph, iph->ihl*4);
|
|
|
|
|
|
+ ihl = skb->data - skb->nh.raw;
|
|
|
|
+ memcpy(work_buf, iph, ihl);
|
|
|
|
|
|
iph->ttl = 0;
|
|
iph->ttl = 0;
|
|
iph->tos = 0;
|
|
iph->tos = 0;
|
|
iph->frag_off = 0;
|
|
iph->frag_off = 0;
|
|
iph->check = 0;
|
|
iph->check = 0;
|
|
- if (iph->ihl != 5) {
|
|
|
|
|
|
+ if (ihl > sizeof(*iph)) {
|
|
u32 dummy;
|
|
u32 dummy;
|
|
if (ip_clear_mutable_options(iph, &dummy))
|
|
if (ip_clear_mutable_options(iph, &dummy))
|
|
goto out;
|
|
goto out;
|
|
@@ -164,7 +166,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
|
|
u8 auth_data[MAX_AH_AUTH_LEN];
|
|
u8 auth_data[MAX_AH_AUTH_LEN];
|
|
|
|
|
|
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
|
|
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
|
|
- skb_push(skb, skb->data - skb->nh.raw);
|
|
|
|
|
|
+ skb_push(skb, ihl);
|
|
ahp->icv(ahp, skb, ah->auth_data);
|
|
ahp->icv(ahp, skb, ah->auth_data);
|
|
if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
|
|
if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
|
|
x->stats.integrity_failed++;
|
|
x->stats.integrity_failed++;
|
|
@@ -172,11 +174,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
((struct iphdr*)work_buf)->protocol = ah->nexthdr;
|
|
((struct iphdr*)work_buf)->protocol = ah->nexthdr;
|
|
- skb->nh.raw = skb_pull(skb, ah_hlen);
|
|
|
|
- memcpy(skb->nh.raw, work_buf, iph->ihl*4);
|
|
|
|
- skb->nh.iph->tot_len = htons(skb->len);
|
|
|
|
- skb_pull(skb, skb->nh.iph->ihl*4);
|
|
|
|
- skb->h.raw = skb->data;
|
|
|
|
|
|
+ skb->h.raw = memcpy(skb->nh.raw += ah_hlen, work_buf, ihl);
|
|
|
|
+ __skb_pull(skb, ah_hlen + ihl);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|