X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=net%2Fipv4%2Fnetfilter%2Fipt_ECN.c;h=120109cd294db678e9e47014075d9e69fe8cc1ae;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=8ca402564f5e0b662b76ce708a1f31f25d572c29;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index 8ca402564..120109cd2 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c @@ -52,34 +52,39 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) static inline int set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward) { - struct tcphdr tcph; + struct tcphdr _tcph, *th; u_int16_t diffs[2]; /* Not enought header? */ - if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, &tcph, sizeof(tcph)) - < 0) + th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4, + sizeof(_tcph), &_tcph); + if (th == NULL) return 0; - diffs[0] = ((u_int16_t *)&tcph)[6]; + diffs[0] = ((u_int16_t *)th)[6]; if (einfo->operation & IPT_ECN_OP_SET_ECE) - tcph.ece = einfo->proto.tcp.ece; + th->ece = einfo->proto.tcp.ece; if (einfo->operation & IPT_ECN_OP_SET_CWR) - tcph.cwr = einfo->proto.tcp.cwr; - diffs[1] = ((u_int16_t *)&tcph)[6]; + th->cwr = einfo->proto.tcp.cwr; + diffs[1] = ((u_int16_t *)&th)[6]; /* Only mangle if it's changed. */ if (diffs[0] != diffs[1]) { diffs[0] = diffs[0] ^ 0xFFFF; if (!skb_ip_make_writable(pskb, - (*pskb)->nh.iph->ihl*4+sizeof(tcph))) + (*pskb)->nh.iph->ihl*4+sizeof(_tcph))) return 0; + + if (th != &_tcph) + memcpy(&_tcph, th, sizeof(_tcph)); + if ((*pskb)->ip_summed != CHECKSUM_HW) - tcph.check = csum_fold(csum_partial((char *)diffs, - sizeof(diffs), - tcph.check^0xFFFF)); + _tcph.check = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + _tcph.check^0xFFFF)); memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4, - &tcph, sizeof(tcph)); + &_tcph, sizeof(_tcph)); if ((*pskb)->ip_summed == CHECKSUM_HW) if (skb_checksum_help(pskb, inward)) return 0;