diff options
| -rw-r--r-- | net/ipv4/netfilter.c | 60 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 14 |
2 files changed, 26 insertions, 48 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 4614babdc45f..2e97e3ec1eb7 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
| @@ -17,51 +17,35 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
| 17 | const struct iphdr *iph = ip_hdr(skb); | 17 | const struct iphdr *iph = ip_hdr(skb); |
| 18 | struct rtable *rt; | 18 | struct rtable *rt; |
| 19 | struct flowi4 fl4 = {}; | 19 | struct flowi4 fl4 = {}; |
| 20 | unsigned long orefdst; | 20 | __be32 saddr = iph->saddr; |
| 21 | __u8 flags = 0; | ||
| 21 | unsigned int hh_len; | 22 | unsigned int hh_len; |
| 22 | unsigned int type; | ||
| 23 | 23 | ||
| 24 | type = inet_addr_type(net, iph->saddr); | 24 | if (!skb->sk && addr_type != RTN_LOCAL) { |
| 25 | if (skb->sk && inet_sk(skb->sk)->transparent) | 25 | if (addr_type == RTN_UNSPEC) |
| 26 | type = RTN_LOCAL; | 26 | addr_type = inet_addr_type(net, saddr); |
| 27 | if (addr_type == RTN_UNSPEC) | 27 | if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST) |
| 28 | addr_type = type; | 28 | flags |= FLOWI_FLAG_ANYSRC; |
| 29 | else | ||
| 30 | saddr = 0; | ||
| 31 | } | ||
| 29 | 32 | ||
| 30 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause | 33 | /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause |
| 31 | * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook. | 34 | * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook. |
| 32 | */ | 35 | */ |
| 33 | if (addr_type == RTN_LOCAL) { | 36 | fl4.daddr = iph->daddr; |
| 34 | fl4.daddr = iph->daddr; | 37 | fl4.saddr = saddr; |
| 35 | if (type == RTN_LOCAL) | 38 | fl4.flowi4_tos = RT_TOS(iph->tos); |
| 36 | fl4.saddr = iph->saddr; | 39 | fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; |
| 37 | fl4.flowi4_tos = RT_TOS(iph->tos); | 40 | fl4.flowi4_mark = skb->mark; |
| 38 | fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; | 41 | fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : flags; |
| 39 | fl4.flowi4_mark = skb->mark; | 42 | rt = ip_route_output_key(net, &fl4); |
| 40 | fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; | 43 | if (IS_ERR(rt)) |
| 41 | rt = ip_route_output_key(net, &fl4); | 44 | return -1; |
| 42 | if (IS_ERR(rt)) | ||
| 43 | return -1; | ||
| 44 | |||
| 45 | /* Drop old route. */ | ||
| 46 | skb_dst_drop(skb); | ||
| 47 | skb_dst_set(skb, &rt->dst); | ||
| 48 | } else { | ||
| 49 | /* non-local src, find valid iif to satisfy | ||
| 50 | * rp-filter when calling ip_route_input. */ | ||
| 51 | fl4.daddr = iph->saddr; | ||
| 52 | rt = ip_route_output_key(net, &fl4); | ||
| 53 | if (IS_ERR(rt)) | ||
| 54 | return -1; | ||
| 55 | 45 | ||
| 56 | orefdst = skb->_skb_refdst; | 46 | /* Drop old route. */ |
| 57 | if (ip_route_input(skb, iph->daddr, iph->saddr, | 47 | skb_dst_drop(skb); |
| 58 | RT_TOS(iph->tos), rt->dst.dev) != 0) { | 48 | skb_dst_set(skb, &rt->dst); |
| 59 | dst_release(&rt->dst); | ||
| 60 | return -1; | ||
| 61 | } | ||
| 62 | dst_release(&rt->dst); | ||
| 63 | refdst_drop(orefdst); | ||
| 64 | } | ||
| 65 | 49 | ||
| 66 | if (skb_dst(skb)->error) | 50 | if (skb_dst(skb)->error) |
| 67 | return -1; | 51 | return -1; |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 1ff79e557f96..51f13f8ec724 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
| @@ -40,7 +40,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 40 | struct iphdr *niph; | 40 | struct iphdr *niph; |
| 41 | const struct tcphdr *oth; | 41 | const struct tcphdr *oth; |
| 42 | struct tcphdr _otcph, *tcph; | 42 | struct tcphdr _otcph, *tcph; |
| 43 | unsigned int addr_type; | ||
| 44 | 43 | ||
| 45 | /* IP header checks: fragment. */ | 44 | /* IP header checks: fragment. */ |
| 46 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) | 45 | if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET)) |
| @@ -55,6 +54,9 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 55 | if (oth->rst) | 54 | if (oth->rst) |
| 56 | return; | 55 | return; |
| 57 | 56 | ||
| 57 | if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | ||
| 58 | return; | ||
| 59 | |||
| 58 | /* Check checksum */ | 60 | /* Check checksum */ |
| 59 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) | 61 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP)) |
| 60 | return; | 62 | return; |
| @@ -101,19 +103,11 @@ static void send_reset(struct sk_buff *oldskb, int hook) | |||
| 101 | nskb->csum_start = (unsigned char *)tcph - nskb->head; | 103 | nskb->csum_start = (unsigned char *)tcph - nskb->head; |
| 102 | nskb->csum_offset = offsetof(struct tcphdr, check); | 104 | nskb->csum_offset = offsetof(struct tcphdr, check); |
| 103 | 105 | ||
| 104 | addr_type = RTN_UNSPEC; | ||
| 105 | if (hook != NF_INET_FORWARD | ||
| 106 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
| 107 | || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED) | ||
| 108 | #endif | ||
| 109 | ) | ||
| 110 | addr_type = RTN_LOCAL; | ||
| 111 | |||
| 112 | /* ip_route_me_harder expects skb->dst to be set */ | 106 | /* ip_route_me_harder expects skb->dst to be set */ |
| 113 | skb_dst_set_noref(nskb, skb_dst(oldskb)); | 107 | skb_dst_set_noref(nskb, skb_dst(oldskb)); |
| 114 | 108 | ||
| 115 | nskb->protocol = htons(ETH_P_IP); | 109 | nskb->protocol = htons(ETH_P_IP); |
| 116 | if (ip_route_me_harder(nskb, addr_type)) | 110 | if (ip_route_me_harder(nskb, RTN_UNSPEC)) |
| 117 | goto free_nskb; | 111 | goto free_nskb; |
| 118 | 112 | ||
| 119 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); | 113 | niph->ttl = ip4_dst_hoplimit(skb_dst(nskb)); |
