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;