aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c97
1 files changed, 19 insertions, 78 deletions
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index fd0c05efed8a..ad0312d0e4fd 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -38,76 +38,16 @@ MODULE_DESCRIPTION("iptables REJECT target module");
38#define DEBUGP(format, args...) 38#define DEBUGP(format, args...)
39#endif 39#endif
40 40
41static inline struct rtable *route_reverse(struct sk_buff *skb,
42 struct tcphdr *tcph, int hook)
43{
44 struct iphdr *iph = skb->nh.iph;
45 struct dst_entry *odst;
46 struct flowi fl = {};
47 struct rtable *rt;
48
49 /* We don't require ip forwarding to be enabled to be able to
50 * send a RST reply for bridged traffic. */
51 if (hook != NF_IP_FORWARD
52#ifdef CONFIG_BRIDGE_NETFILTER
53 || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED)
54#endif
55 ) {
56 fl.nl_u.ip4_u.daddr = iph->saddr;
57 if (hook == NF_IP_LOCAL_IN)
58 fl.nl_u.ip4_u.saddr = iph->daddr;
59 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
60
61 if (ip_route_output_key(&rt, &fl) != 0)
62 return NULL;
63 } else {
64 /* non-local src, find valid iif to satisfy
65 * rp-filter when calling ip_route_input. */
66 fl.nl_u.ip4_u.daddr = iph->daddr;
67 if (ip_route_output_key(&rt, &fl) != 0)
68 return NULL;
69
70 odst = skb->dst;
71 if (ip_route_input(skb, iph->saddr, iph->daddr,
72 RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
73 dst_release(&rt->u.dst);
74 return NULL;
75 }
76 dst_release(&rt->u.dst);
77 rt = (struct rtable *)skb->dst;
78 skb->dst = odst;
79
80 fl.nl_u.ip4_u.daddr = iph->saddr;
81 fl.nl_u.ip4_u.saddr = iph->daddr;
82 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
83 }
84
85 if (rt->u.dst.error) {
86 dst_release(&rt->u.dst);
87 return NULL;
88 }
89
90 fl.proto = IPPROTO_TCP;
91 fl.fl_ip_sport = tcph->dest;
92 fl.fl_ip_dport = tcph->source;
93 security_skb_classify_flow(skb, &fl);
94
95 xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
96
97 return rt;
98}
99
100/* Send RST reply */ 41/* Send RST reply */
101static void send_reset(struct sk_buff *oldskb, int hook) 42static void send_reset(struct sk_buff *oldskb, int hook)
102{ 43{
103 struct sk_buff *nskb; 44 struct sk_buff *nskb;
104 struct iphdr *iph = oldskb->nh.iph; 45 struct iphdr *iph = oldskb->nh.iph;
105 struct tcphdr _otcph, *oth, *tcph; 46 struct tcphdr _otcph, *oth, *tcph;
106 struct rtable *rt;
107 __be16 tmp_port; 47 __be16 tmp_port;
108 __be32 tmp_addr; 48 __be32 tmp_addr;
109 int needs_ack; 49 int needs_ack;
110 int hh_len; 50 unsigned int addr_type;
111 51
112 /* IP header checks: fragment. */ 52 /* IP header checks: fragment. */
113 if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) 53 if (oldskb->nh.iph->frag_off & htons(IP_OFFSET))
@@ -126,23 +66,13 @@ static void send_reset(struct sk_buff *oldskb, int hook)
126 if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP)) 66 if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
127 return; 67 return;
128 68
129 if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
130 return;
131
132 hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
133
134 /* We need a linear, writeable skb. We also need to expand 69 /* We need a linear, writeable skb. We also need to expand
135 headroom in case hh_len of incoming interface < hh_len of 70 headroom in case hh_len of incoming interface < hh_len of
136 outgoing interface */ 71 outgoing interface */
137 nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb), 72 nskb = skb_copy_expand(oldskb, LL_MAX_HEADER, skb_tailroom(oldskb),
138 GFP_ATOMIC); 73 GFP_ATOMIC);
139 if (!nskb) { 74 if (!nskb)
140 dst_release(&rt->u.dst);
141 return; 75 return;
142 }
143
144 dst_release(nskb->dst);
145 nskb->dst = &rt->u.dst;
146 76
147 /* This packet will not be the same as the other: clear nf fields */ 77 /* This packet will not be the same as the other: clear nf fields */
148 nf_reset(nskb); 78 nf_reset(nskb);
@@ -184,6 +114,21 @@ static void send_reset(struct sk_buff *oldskb, int hook)
184 tcph->window = 0; 114 tcph->window = 0;
185 tcph->urg_ptr = 0; 115 tcph->urg_ptr = 0;
186 116
117 /* Set DF, id = 0 */
118 nskb->nh.iph->frag_off = htons(IP_DF);
119 nskb->nh.iph->id = 0;
120
121 addr_type = RTN_UNSPEC;
122 if (hook != NF_IP_FORWARD
123#ifdef CONFIG_BRIDGE_NETFILTER
124 || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED)
125#endif
126 )
127 addr_type = RTN_LOCAL;
128
129 if (ip_route_me_harder(&nskb, addr_type))
130 goto free_nskb;
131
187 /* Adjust TCP checksum */ 132 /* Adjust TCP checksum */
188 nskb->ip_summed = CHECKSUM_NONE; 133 nskb->ip_summed = CHECKSUM_NONE;
189 tcph->check = 0; 134 tcph->check = 0;
@@ -192,12 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook)
192 nskb->nh.iph->daddr, 137 nskb->nh.iph->daddr,
193 csum_partial((char *)tcph, 138 csum_partial((char *)tcph,
194 sizeof(struct tcphdr), 0)); 139 sizeof(struct tcphdr), 0));
195 140 /* Adjust IP TTL */
196 /* Adjust IP TTL, DF */
197 nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); 141 nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
198 /* Set DF, id = 0 */
199 nskb->nh.iph->frag_off = htons(IP_DF);
200 nskb->nh.iph->id = 0;
201 142
202 /* Adjust IP checksum */ 143 /* Adjust IP checksum */
203 nskb->nh.iph->check = 0; 144 nskb->nh.iph->check = 0;