.. | .. |
---|
17 | 17 | case CHECKSUM_COMPLETE: |
---|
18 | 18 | if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN) |
---|
19 | 19 | break; |
---|
20 | | - if ((protocol == 0 && !csum_fold(skb->csum)) || |
---|
| 20 | + if ((protocol != IPPROTO_TCP && protocol != IPPROTO_UDP && |
---|
| 21 | + !csum_fold(skb->csum)) || |
---|
21 | 22 | !csum_tcpudp_magic(iph->saddr, iph->daddr, |
---|
22 | 23 | skb->len - dataoff, protocol, |
---|
23 | 24 | skb->csum)) { |
---|
24 | 25 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
---|
25 | 26 | break; |
---|
26 | 27 | } |
---|
27 | | - /* fall through */ |
---|
| 28 | + fallthrough; |
---|
28 | 29 | case CHECKSUM_NONE: |
---|
29 | | - if (protocol == 0) |
---|
| 30 | + if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) |
---|
30 | 31 | skb->csum = 0; |
---|
31 | 32 | else |
---|
32 | 33 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, |
---|
.. | .. |
---|
50 | 51 | case CHECKSUM_COMPLETE: |
---|
51 | 52 | if (len == skb->len - dataoff) |
---|
52 | 53 | return nf_ip_checksum(skb, hook, dataoff, protocol); |
---|
53 | | - /* fall through */ |
---|
| 54 | + fallthrough; |
---|
54 | 55 | case CHECKSUM_NONE: |
---|
55 | 56 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol, |
---|
56 | 57 | skb->len - dataoff, 0); |
---|
.. | .. |
---|
78 | 79 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
---|
79 | 80 | break; |
---|
80 | 81 | } |
---|
81 | | - /* fall through */ |
---|
| 82 | + fallthrough; |
---|
82 | 83 | case CHECKSUM_NONE: |
---|
83 | 84 | skb->csum = ~csum_unfold( |
---|
84 | 85 | csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, |
---|
.. | .. |
---|
105 | 106 | case CHECKSUM_COMPLETE: |
---|
106 | 107 | if (len == skb->len - dataoff) |
---|
107 | 108 | return nf_ip6_checksum(skb, hook, dataoff, protocol); |
---|
108 | | - /* fall through */ |
---|
| 109 | + fallthrough; |
---|
109 | 110 | case CHECKSUM_NONE: |
---|
110 | 111 | hsum = skb_checksum(skb, 0, dataoff, 0); |
---|
111 | 112 | skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr, |
---|
.. | .. |
---|
162 | 163 | int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, |
---|
163 | 164 | bool strict, unsigned short family) |
---|
164 | 165 | { |
---|
165 | | - const struct nf_ipv6_ops *v6ops; |
---|
| 166 | + const struct nf_ipv6_ops *v6ops __maybe_unused; |
---|
166 | 167 | int ret = 0; |
---|
167 | 168 | |
---|
168 | 169 | switch (family) { |
---|
.. | .. |
---|
170 | 171 | ret = nf_ip_route(net, dst, fl, strict); |
---|
171 | 172 | break; |
---|
172 | 173 | case AF_INET6: |
---|
173 | | - v6ops = rcu_dereference(nf_ipv6_ops); |
---|
174 | | - if (v6ops) |
---|
175 | | - ret = v6ops->route(net, dst, fl, strict); |
---|
| 174 | + ret = nf_ip6_route(net, dst, fl, strict); |
---|
176 | 175 | break; |
---|
177 | 176 | } |
---|
178 | 177 | |
---|
.. | .. |
---|
180 | 179 | } |
---|
181 | 180 | EXPORT_SYMBOL_GPL(nf_route); |
---|
182 | 181 | |
---|
| 182 | +static int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry) |
---|
| 183 | +{ |
---|
| 184 | +#ifdef CONFIG_INET |
---|
| 185 | + const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry); |
---|
| 186 | + |
---|
| 187 | + if (entry->state.hook == NF_INET_LOCAL_OUT) { |
---|
| 188 | + const struct iphdr *iph = ip_hdr(skb); |
---|
| 189 | + |
---|
| 190 | + if (!(iph->tos == rt_info->tos && |
---|
| 191 | + skb->mark == rt_info->mark && |
---|
| 192 | + iph->daddr == rt_info->daddr && |
---|
| 193 | + iph->saddr == rt_info->saddr)) |
---|
| 194 | + return ip_route_me_harder(entry->state.net, entry->state.sk, |
---|
| 195 | + skb, RTN_UNSPEC); |
---|
| 196 | + } |
---|
| 197 | +#endif |
---|
| 198 | + return 0; |
---|
| 199 | +} |
---|
| 200 | + |
---|
183 | 201 | int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry) |
---|
184 | 202 | { |
---|
185 | 203 | const struct nf_ipv6_ops *v6ops; |
---|