@@ -153,6 +153,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
153153 const char * rep_buffer ,
154154 unsigned int rep_len )
155155{
156+ struct rtable * rt = (struct rtable * )(* pskb )-> dst ;
156157 struct iphdr * iph ;
157158 struct tcphdr * tcph ;
158159 int oldlen , datalen ;
@@ -176,11 +177,22 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
176177
177178 datalen = (* pskb )-> len - iph -> ihl * 4 ;
178179 if ((* pskb )-> ip_summed != CHECKSUM_PARTIAL ) {
179- tcph -> check = 0 ;
180- tcph -> check = tcp_v4_check (datalen ,
181- iph -> saddr , iph -> daddr ,
182- csum_partial ((char * )tcph ,
183- datalen , 0 ));
180+ if (!(rt -> rt_flags & RTCF_LOCAL ) &&
181+ (* pskb )-> dev -> features & NETIF_F_ALL_CSUM ) {
182+ (* pskb )-> ip_summed = CHECKSUM_PARTIAL ;
183+ (* pskb )-> csum_start = skb_headroom (* pskb ) +
184+ skb_network_offset (* pskb ) +
185+ iph -> ihl * 4 ;
186+ (* pskb )-> csum_offset = offsetof(struct tcphdr , check );
187+ tcph -> check = ~tcp_v4_check (datalen ,
188+ iph -> saddr , iph -> daddr , 0 );
189+ } else {
190+ tcph -> check = 0 ;
191+ tcph -> check = tcp_v4_check (datalen ,
192+ iph -> saddr , iph -> daddr ,
193+ csum_partial ((char * )tcph ,
194+ datalen , 0 ));
195+ }
184196 } else
185197 nf_proto_csum_replace2 (& tcph -> check , * pskb ,
186198 htons (oldlen ), htons (datalen ), 1 );
@@ -217,6 +229,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
217229 const char * rep_buffer ,
218230 unsigned int rep_len )
219231{
232+ struct rtable * rt = (struct rtable * )(* pskb )-> dst ;
220233 struct iphdr * iph ;
221234 struct udphdr * udph ;
222235 int datalen , oldlen ;
@@ -251,13 +264,25 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
251264 return 1 ;
252265
253266 if ((* pskb )-> ip_summed != CHECKSUM_PARTIAL ) {
254- udph -> check = 0 ;
255- udph -> check = csum_tcpudp_magic (iph -> saddr , iph -> daddr ,
256- datalen , IPPROTO_UDP ,
257- csum_partial ((char * )udph ,
258- datalen , 0 ));
259- if (!udph -> check )
260- udph -> check = CSUM_MANGLED_0 ;
267+ if (!(rt -> rt_flags & RTCF_LOCAL ) &&
268+ (* pskb )-> dev -> features & NETIF_F_ALL_CSUM ) {
269+ (* pskb )-> ip_summed = CHECKSUM_PARTIAL ;
270+ (* pskb )-> csum_start = skb_headroom (* pskb ) +
271+ skb_network_offset (* pskb ) +
272+ iph -> ihl * 4 ;
273+ (* pskb )-> csum_offset = offsetof(struct udphdr , check );
274+ udph -> check = ~csum_tcpudp_magic (iph -> saddr , iph -> daddr ,
275+ datalen , IPPROTO_UDP ,
276+ 0 );
277+ } else {
278+ udph -> check = 0 ;
279+ udph -> check = csum_tcpudp_magic (iph -> saddr , iph -> daddr ,
280+ datalen , IPPROTO_UDP ,
281+ csum_partial ((char * )udph ,
282+ datalen , 0 ));
283+ if (!udph -> check )
284+ udph -> check = CSUM_MANGLED_0 ;
285+ }
261286 } else
262287 nf_proto_csum_replace2 (& udph -> check , * pskb ,
263288 htons (oldlen ), htons (datalen ), 1 );
0 commit comments