| .. | .. |
|---|
| 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; |
|---|