Commit 43bc0ca7 authored by Al Viro's avatar Al Viro Committed by David S. Miller

[NET]: netfilter checksum annotations

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f9214b26
...@@ -282,11 +282,27 @@ extern void nf_invalidate_cache(int pf); ...@@ -282,11 +282,27 @@ extern void nf_invalidate_cache(int pf);
Returns true or false. */ Returns true or false. */
extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, static inline void nf_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
u_int32_t csum); {
extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, __be32 diff[] = { ~from, to };
u_int32_t oldval, u_int32_t newval,
u_int16_t csum, int pseudohdr); *sum = csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum_unfold(*sum)));
}
static inline void nf_csum_replace2(__sum16 *sum, __be16 from, __be16 to)
{
nf_csum_replace4(sum, (__force __be32)from, (__force __be32)to);
}
extern void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
__be32 from, __be32 to, int pseudohdr);
static inline void nf_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
__be16 from, __be16 to, int pseudohdr)
{
nf_proto_csum_replace4(sum, skb, (__force __be32)from,
(__force __be32)to, pseudohdr);
}
struct nf_afinfo { struct nf_afinfo {
unsigned short family; unsigned short family;
......
...@@ -102,11 +102,11 @@ static inline __be32 *gre_key(struct gre_hdr *greh) ...@@ -102,11 +102,11 @@ static inline __be32 *gre_key(struct gre_hdr *greh)
} }
/* get pointer ot gre csum, if present */ /* get pointer ot gre csum, if present */
static inline u_int16_t *gre_csum(struct gre_hdr *greh) static inline __sum16 *gre_csum(struct gre_hdr *greh)
{ {
if (!greh->csum) if (!greh->csum)
return NULL; return NULL;
return (u_int16_t *) (greh+sizeof(*greh)); return (__sum16 *) (greh+sizeof(*greh));
} }
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -362,12 +362,10 @@ manip_pkt(u_int16_t proto, ...@@ -362,12 +362,10 @@ manip_pkt(u_int16_t proto,
iph = (void *)(*pskb)->data + iphdroff; iph = (void *)(*pskb)->data + iphdroff;
if (maniptype == IP_NAT_MANIP_SRC) { if (maniptype == IP_NAT_MANIP_SRC) {
iph->check = nf_csum_update(~iph->saddr, target->src.ip, nf_csum_replace4(&iph->check, iph->saddr, target->src.ip);
iph->check);
iph->saddr = target->src.ip; iph->saddr = target->src.ip;
} else { } else {
iph->check = nf_csum_update(~iph->daddr, target->dst.ip, nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip);
iph->check);
iph->daddr = target->dst.ip; iph->daddr = target->dst.ip;
} }
return 1; return 1;
......
...@@ -188,10 +188,8 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, ...@@ -188,10 +188,8 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
csum_partial((char *)tcph, csum_partial((char *)tcph,
datalen, 0)); datalen, 0));
} else } else
tcph->check = nf_proto_csum_update(*pskb, nf_proto_csum_replace2(&tcph->check, *pskb,
htons(oldlen) ^ htons(0xFFFF), htons(oldlen), htons(datalen), 1);
htons(datalen),
tcph->check, 1);
if (rep_len != match_len) { if (rep_len != match_len) {
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
...@@ -266,10 +264,8 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, ...@@ -266,10 +264,8 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
if (!udph->check) if (!udph->check)
udph->check = CSUM_MANGLED_0; udph->check = CSUM_MANGLED_0;
} else } else
udph->check = nf_proto_csum_update(*pskb, nf_proto_csum_replace2(&udph->check, *pskb,
htons(oldlen) ^ htons(0xFFFF), htons(oldlen), htons(datalen), 1);
htons(datalen),
udph->check, 1);
return 1; return 1;
} }
EXPORT_SYMBOL(ip_nat_mangle_udp_packet); EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
...@@ -307,14 +303,10 @@ sack_adjust(struct sk_buff *skb, ...@@ -307,14 +303,10 @@ sack_adjust(struct sk_buff *skb,
ntohl(sack->start_seq), new_start_seq, ntohl(sack->start_seq), new_start_seq,
ntohl(sack->end_seq), new_end_seq); ntohl(sack->end_seq), new_end_seq);
tcph->check = nf_proto_csum_update(skb, nf_proto_csum_replace4(&tcph->check, skb,
~sack->start_seq, sack->start_seq, new_start_seq, 0);
new_start_seq, nf_proto_csum_replace4(&tcph->check, skb,
tcph->check, 0); sack->end_seq, new_end_seq, 0);
tcph->check = nf_proto_csum_update(skb,
~sack->end_seq,
new_end_seq,
tcph->check, 0);
sack->start_seq = new_start_seq; sack->start_seq = new_start_seq;
sack->end_seq = new_end_seq; sack->end_seq = new_end_seq;
sackoff += sizeof(*sack); sackoff += sizeof(*sack);
...@@ -397,10 +389,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb, ...@@ -397,10 +389,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
else else
newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq, nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
tcph->check, 0); nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack,
tcph->check, 0);
DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
......
...@@ -129,11 +129,9 @@ gre_manip_pkt(struct sk_buff **pskb, ...@@ -129,11 +129,9 @@ gre_manip_pkt(struct sk_buff **pskb,
} }
if (greh->csum) { if (greh->csum) {
/* FIXME: Never tested this code... */ /* FIXME: Never tested this code... */
*(gre_csum(greh)) = nf_proto_csum_replace4(gre_csum(greh), *pskb,
nf_proto_csum_update(*pskb, *(gre_key(greh)),
~*(gre_key(greh)), tuple->dst.u.gre.key, 0);
tuple->dst.u.gre.key,
*(gre_csum(greh)), 0);
} }
*(gre_key(greh)) = tuple->dst.u.gre.key; *(gre_key(greh)) = tuple->dst.u.gre.key;
break; break;
......
...@@ -66,10 +66,8 @@ icmp_manip_pkt(struct sk_buff **pskb, ...@@ -66,10 +66,8 @@ icmp_manip_pkt(struct sk_buff **pskb,
return 0; return 0;
hdr = (struct icmphdr *)((*pskb)->data + hdroff); hdr = (struct icmphdr *)((*pskb)->data + hdroff);
hdr->checksum = nf_proto_csum_update(*pskb, nf_proto_csum_replace2(&hdr->checksum, *pskb,
hdr->un.echo.id ^ htons(0xFFFF), hdr->un.echo.id, tuple->src.u.icmp.id, 0);
tuple->src.u.icmp.id,
hdr->checksum, 0);
hdr->un.echo.id = tuple->src.u.icmp.id; hdr->un.echo.id = tuple->src.u.icmp.id;
return 1; return 1;
} }
......
...@@ -129,9 +129,8 @@ tcp_manip_pkt(struct sk_buff **pskb, ...@@ -129,9 +129,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (hdrsize < sizeof(*hdr)) if (hdrsize < sizeof(*hdr))
return 1; return 1;
hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1); nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport, nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
hdr->check, 0);
return 1; return 1;
} }
......
...@@ -115,11 +115,8 @@ udp_manip_pkt(struct sk_buff **pskb, ...@@ -115,11 +115,8 @@ udp_manip_pkt(struct sk_buff **pskb,
} }
if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
hdr->check, 1); nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0);
hdr->check = nf_proto_csum_update(*pskb,
*portptr ^ htons(0xFFFF), newport,
hdr->check, 0);
if (!hdr->check) if (!hdr->check)
hdr->check = CSUM_MANGLED_0; hdr->check = CSUM_MANGLED_0;
} }
......
...@@ -28,17 +28,16 @@ static inline int ...@@ -28,17 +28,16 @@ static inline int
set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
{ {
struct iphdr *iph = (*pskb)->nh.iph; struct iphdr *iph = (*pskb)->nh.iph;
u_int16_t oldtos;
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
__u8 oldtos;
if (!skb_make_writable(pskb, sizeof(struct iphdr))) if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return 0; return 0;
iph = (*pskb)->nh.iph; iph = (*pskb)->nh.iph;
oldtos = iph->tos; oldtos = iph->tos;
iph->tos &= ~IPT_ECN_IP_MASK; iph->tos &= ~IPT_ECN_IP_MASK;
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
htons(iph->tos), iph->check);
} }
return 1; return 1;
} }
...@@ -72,10 +71,8 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) ...@@ -72,10 +71,8 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
if (einfo->operation & IPT_ECN_OP_SET_CWR) if (einfo->operation & IPT_ECN_OP_SET_CWR)
tcph->cwr = einfo->proto.tcp.cwr; tcph->cwr = einfo->proto.tcp.cwr;
tcph->check = nf_proto_csum_update((*pskb), nf_proto_csum_replace2(&tcph->check, *pskb,
oldval ^ htons(0xFFFF), oldval, ((__be16 *)tcph)[6], 0);
((__be16 *)tcph)[6],
tcph->check, 0);
return 1; return 1;
} }
......
...@@ -97,10 +97,8 @@ ipt_tcpmss_target(struct sk_buff **pskb, ...@@ -97,10 +97,8 @@ ipt_tcpmss_target(struct sk_buff **pskb,
opt[i+2] = (newmss & 0xff00) >> 8; opt[i+2] = (newmss & 0xff00) >> 8;
opt[i+3] = (newmss & 0x00ff); opt[i+3] = (newmss & 0x00ff);
tcph->check = nf_proto_csum_update(*pskb, nf_proto_csum_replace2(&tcph->check, *pskb,
htons(oldmss)^htons(0xFFFF), htons(oldmss), htons(newmss), 0);
htons(newmss),
tcph->check, 0);
return IPT_CONTINUE; return IPT_CONTINUE;
} }
} }
...@@ -126,28 +124,22 @@ ipt_tcpmss_target(struct sk_buff **pskb, ...@@ -126,28 +124,22 @@ ipt_tcpmss_target(struct sk_buff **pskb,
opt = (u_int8_t *)tcph + sizeof(struct tcphdr); opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
tcph->check = nf_proto_csum_update(*pskb, nf_proto_csum_replace2(&tcph->check, *pskb,
htons(tcplen) ^ htons(0xFFFF), htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
htons(tcplen + TCPOLEN_MSS),
tcph->check, 1);
opt[0] = TCPOPT_MSS; opt[0] = TCPOPT_MSS;
opt[1] = TCPOLEN_MSS; opt[1] = TCPOLEN_MSS;
opt[2] = (newmss & 0xff00) >> 8; opt[2] = (newmss & 0xff00) >> 8;
opt[3] = (newmss & 0x00ff); opt[3] = (newmss & 0x00ff);
tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt), nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
tcph->check, 0);
oldval = ((__be16 *)tcph)[6]; oldval = ((__be16 *)tcph)[6];
tcph->doff += TCPOLEN_MSS/4; tcph->doff += TCPOLEN_MSS/4;
tcph->check = nf_proto_csum_update(*pskb, nf_proto_csum_replace2(&tcph->check, *pskb,
oldval ^ htons(0xFFFF), oldval, ((__be16 *)tcph)[6], 0);
((__be16 *)tcph)[6],
tcph->check, 0);
newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF), nf_csum_replace2(&iph->check, iph->tot_len, newtotlen);
newtotlen, iph->check);
iph->tot_len = newtotlen; iph->tot_len = newtotlen;
return IPT_CONTINUE; return IPT_CONTINUE;
} }
......
...@@ -30,16 +30,15 @@ target(struct sk_buff **pskb, ...@@ -30,16 +30,15 @@ target(struct sk_buff **pskb,
{ {
const struct ipt_tos_target_info *tosinfo = targinfo; const struct ipt_tos_target_info *tosinfo = targinfo;
struct iphdr *iph = (*pskb)->nh.iph; struct iphdr *iph = (*pskb)->nh.iph;
u_int16_t oldtos;
if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
__u8 oldtos;
if (!skb_make_writable(pskb, sizeof(struct iphdr))) if (!skb_make_writable(pskb, sizeof(struct iphdr)))
return NF_DROP; return NF_DROP;
iph = (*pskb)->nh.iph; iph = (*pskb)->nh.iph;
oldtos = iph->tos; oldtos = iph->tos;
iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
htons(iph->tos), iph->check);
} }
return IPT_CONTINUE; return IPT_CONTINUE;
} }
......
...@@ -54,9 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb, ...@@ -54,9 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb,
} }
if (new_ttl != iph->ttl) { if (new_ttl != iph->ttl) {
iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF), nf_csum_replace2(&iph->check, htons(iph->ttl << 8),
htons(new_ttl << 8), htons(new_ttl << 8));
iph->check);
iph->ttl = new_ttl; iph->ttl = new_ttl;
} }
......
...@@ -222,28 +222,21 @@ copy_skb: ...@@ -222,28 +222,21 @@ copy_skb:
} }
EXPORT_SYMBOL(skb_make_writable); EXPORT_SYMBOL(skb_make_writable);
u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum) void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
{ __be32 from, __be32 to, int pseudohdr)
u_int32_t diff[] = { oldval, newval };
return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum));
}
EXPORT_SYMBOL(nf_csum_update);
u_int16_t nf_proto_csum_update(struct sk_buff *skb,
u_int32_t oldval, u_int32_t newval,
u_int16_t csum, int pseudohdr)
{ {
__be32 diff[] = { ~from, to };
if (skb->ip_summed != CHECKSUM_PARTIAL) { if (skb->ip_summed != CHECKSUM_PARTIAL) {
csum = nf_csum_update(oldval, newval, csum); *sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
~csum_unfold(*sum)));
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
skb->csum = nf_csum_update(oldval, newval, skb->csum); skb->csum = ~csum_partial((char *)diff, sizeof(diff),
~skb->csum);
} else if (pseudohdr) } else if (pseudohdr)
csum = ~nf_csum_update(oldval, newval, ~csum); *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
csum_unfold(*sum)));
return csum;
} }
EXPORT_SYMBOL(nf_proto_csum_update); EXPORT_SYMBOL(nf_proto_csum_replace4);
/* This does not belong here, but locally generated errors need it if connection /* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, and hence tracking in use: without this, connection may not be in hash table, and hence
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment