blob: a2c679ee2b0c2f519621fbada6c295fe091fd0b4 [file] [log] [blame]
Rusty Russell3f6d08c2000-07-14 07:45:08 +00001diff -urN -X /tmp/fileVB9oIz --minimal tmp/include/linux/netfilter_ipv4/ipt_REJECT.h working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h
2--- tmp/include/linux/netfilter_ipv4/ipt_REJECT.h Tue Mar 28 04:35:56 2000
3+++ working-2.4.0-test3-9/include/linux/netfilter_ipv4/ipt_REJECT.h Tue Jul 11 17:36:54 2000
4@@ -6,7 +6,10 @@
5 IPT_ICMP_HOST_UNREACHABLE,
6 IPT_ICMP_PROT_UNREACHABLE,
7 IPT_ICMP_PORT_UNREACHABLE,
8- IPT_ICMP_ECHOREPLY
9+ IPT_ICMP_ECHOREPLY,
10+ IPT_ICMP_NET_PROHIBITED,
11+ IPT_ICMP_HOST_PROHIBITED,
12+ IPT_TCP_RESET
13 };
14
15 struct ipt_reject_info {
16diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/core/netfilter.c working-2.4.0-test3-9/net/core/netfilter.c
17--- tmp/net/core/netfilter.c Fri Apr 14 10:19:57 2000
18+++ working-2.4.0-test3-9/net/core/netfilter.c Wed Jul 12 12:18:42 2000
19@@ -261,11 +261,11 @@
20 if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING)
21 | (1 << NF_IP_FORWARD)
22 | (1 << NF_IP_POST_ROUTING))) {
23- /* Fragments will have no owners, but still
24- may be local */
25- if (!(skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET))
26- || skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
27- | (1 << NF_IP_POST_ROUTING))){
28+ /* Fragments, entunnelled packets, TCP RSTs
29+ generated by ipt_REJECT will have no
30+ owners, but still may be local */
31+ if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
32+ | (1 << NF_IP_POST_ROUTING))){
33 printk("ip_finish_output:"
34 " bad unowned skb = %p: ",skb);
35 debug_print_hooks_ip(skb->nf_debug);
36diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_conntrack_core.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c
37--- tmp/net/ipv4/netfilter/ip_conntrack_core.c Tue Jul 11 12:08:17 2000
38+++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_core.c Tue Jul 11 17:12:08 2000
39@@ -551,6 +551,7 @@
40 resolve_normal_ct(struct sk_buff *skb,
41 struct ip_conntrack_protocol *proto,
42 int *set_reply,
43+ unsigned int hooknum,
44 enum ip_conntrack_info *ctinfo)
45 {
46 struct ip_conntrack_tuple tuple;
47@@ -573,6 +574,21 @@
48 if (DIRECTION(h) == IP_CT_DIR_REPLY) {
49 /* Reply on unconfirmed connection => unclassifiable */
50 if (!(h->ctrack->status & IPS_CONFIRMED)) {
51+ /* Exception: local TCP RSTs (generated by
52+ REJECT target). */
53+ if (hooknum == NF_IP_LOCAL_OUT
54+ && h->tuple.dst.protonum == IPPROTO_TCP) {
55+ const struct tcphdr *tcph
56+ = (const struct tcphdr *)
57+ ((u_int32_t *)skb->nh.iph
58+ + skb->nh.iph->ihl);
59+ if (tcph->rst) {
60+ *ctinfo = IP_CT_ESTABLISHED
61+ + IP_CT_IS_REPLY;
62+ *set_reply = 0;
63+ goto set_skb;
64+ }
65+ }
66 DEBUGP("Reply on unconfirmed connection\n");
67 ip_conntrack_put(h->ctrack);
68 return NULL;
69@@ -598,6 +614,7 @@
70 }
71 *set_reply = 0;
72 }
73+ set_skb:
74 skb->nfct = &h->ctrack->infos[*ctinfo];
75 return h->ctrack;
76 }
77@@ -669,7 +686,7 @@
78 && icmp_error_track(*pskb, &ctinfo, hooknum))
79 return NF_ACCEPT;
80
81- if (!(ct = resolve_normal_ct(*pskb, proto, &set_reply, &ctinfo)))
82+ if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
83 /* Not valid part of a connection */
84 return NF_ACCEPT;
85
86diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_conntrack_standalone.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c
87--- tmp/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Apr 28 08:43:15 2000
88+++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_conntrack_standalone.c Tue Jul 11 17:12:08 2000
89@@ -169,11 +169,15 @@
90 const struct net_device *out,
91 int (*okfn)(struct sk_buff *))
92 {
93- /* We've seen it coming out the other side: confirm */
94+ /* We've seen it coming out the other side: confirm (only if
95+ new packet: REJECT can generate TCP RESET response, or ICMP
96+ errors) */
97 if ((*pskb)->nfct) {
98 struct ip_conntrack *ct
99 = (struct ip_conntrack *)(*pskb)->nfct->master;
100- if (!(ct->status & IPS_CONFIRMED))
101+ /* ctinfo is the index of the nfct inside the conntrack */
102+ if ((*pskb)->nfct - ct->infos == IP_CT_NEW
103+ && !(ct->status & IPS_CONFIRMED))
104 ip_conntrack_confirm(ct);
105 }
106 return NF_ACCEPT;
107@@ -191,7 +195,8 @@
108 if ((*pskb)->nfct) {
109 struct ip_conntrack *ct
110 = (struct ip_conntrack *)(*pskb)->nfct->master;
111- if (!(ct->status & IPS_CONFIRMED))
112+ if ((*pskb)->nfct - ct->infos == IP_CT_NEW
113+ && !(ct->status & IPS_CONFIRMED))
114 ip_conntrack_confirm(ct);
115 }
116
117diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ip_fw_compat.c working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c
118--- tmp/net/ipv4/netfilter/ip_fw_compat.c Tue Jul 11 12:08:17 2000
119+++ working-2.4.0-test3-9/net/ipv4/netfilter/ip_fw_compat.c Tue Jul 11 17:12:08 2000
120@@ -71,7 +71,8 @@
121 struct ip_conntrack *ct
122 = (struct ip_conntrack *)skb->nfct->master;
123
124- if (!(ct->status & IPS_CONFIRMED))
125+ if (skb->nfct - ct->infos == IP_CT_NEW
126+ && !(ct->status & IPS_CONFIRMED))
127 ip_conntrack_confirm(ct);
128 }
129 }
130diff -urN -X /tmp/fileVB9oIz --minimal tmp/net/ipv4/netfilter/ipt_REJECT.c working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c
131--- tmp/net/ipv4/netfilter/ipt_REJECT.c Tue Jun 27 14:52:47 2000
132+++ working-2.4.0-test3-9/net/ipv4/netfilter/ipt_REJECT.c Wed Jul 12 17:46:26 2000
133@@ -7,6 +7,7 @@
134 #include <linux/ip.h>
135 #include <net/icmp.h>
136 #include <net/ip.h>
137+#include <net/tcp.h>
138 struct in_device;
139 #include <net/route.h>
140 #include <linux/netfilter_ipv4/ip_tables.h>
141@@ -18,6 +19,113 @@
142 #define DEBUGP(format, args...)
143 #endif
144
145+/* Send RST reply */
146+static void send_reset(struct sk_buff *oldskb)
147+{
148+ struct sk_buff *nskb;
149+ struct tcphdr *tcph;
150+ struct rtable *rt;
151+ unsigned int tcplen;
152+ int needs_ack;
153+
154+ /* Clone skb (skb is about to be dropped, so we don't care) */
155+ nskb = skb_clone(oldskb, GFP_ATOMIC);
156+ if (!nskb)
157+ return;
158+
159+ /* This packet will not be the same as the other: clear nf fields */
160+ nf_conntrack_put(nskb->nfct);
161+ nskb->nfct = NULL;
162+ nskb->nfcache = 0;
163+#ifdef CONFIG_NETFILTER_DEBUG
164+ nskb->nf_debug = 0;
165+#endif
166+
167+ /* IP header checks: fragment, too short. */
168+ if (nskb->nh.iph->frag_off & htons(IP_OFFSET)
169+ || nskb->len < (nskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
170+ goto free_nskb;
171+
172+ tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
173+ tcplen = nskb->len - nskb->nh.iph->ihl*4;
174+
175+ /* Check checksum. */
176+ if (tcp_v4_check(tcph, tcplen, nskb->nh.iph->saddr,
177+ nskb->nh.iph->daddr,
178+ csum_partial((char *)tcph, tcplen, 0)) != 0)
179+ goto free_nskb;
180+
181+ /* No RST for RST. */
182+ if (tcph->rst)
183+ goto free_nskb;
184+
185+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
186+ tcph->source = xchg(&tcph->dest, tcph->source);
187+
188+ /* Truncate to length (no data) */
189+ tcph->doff = sizeof(struct tcphdr)/4;
190+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
191+
192+ if (tcph->ack) {
193+ needs_ack = 0;
194+ tcph->seq = tcph->ack_seq;
195+ tcph->ack_seq = 0;
196+ } else {
197+ needs_ack = 1;
198+ tcph->seq = 0;
199+ tcph->ack_seq = htonl(ntohl(tcph->seq) + tcph->syn + tcph->fin
200+ + tcplen - (tcph->doff<<2));
201+ }
202+
203+ /* Reset flags */
204+ ((u_int8_t *)tcph)[13] = 0;
205+ tcph->rst = 1;
206+ if (needs_ack)
207+ tcph->ack = 1;
208+
209+ tcph->window = 0;
210+ tcph->urg_ptr = 0;
211+
212+ /* Adjust TCP checksum */
213+ tcph->check = 0;
214+ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
215+ nskb->nh.iph->saddr,
216+ nskb->nh.iph->daddr,
217+ csum_partial((char *)tcph,
218+ sizeof(struct tcphdr), 0));
219+
220+ /* Adjust IP TTL, DF */
221+ nskb->nh.iph->ttl = MAXTTL;
222+ /* Set DF, id = 0 */
223+ nskb->nh.iph->frag_off = htons(IP_DF);
224+ nskb->nh.iph->id = 0;
225+
226+ /* Adjust IP checksum */
227+ nskb->nh.iph->check = 0;
228+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
229+ nskb->nh.iph->ihl);
230+
231+ /* Routing */
232+ if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
233+ RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
234+ 0) != 0)
235+ goto free_nskb;
236+
237+ dst_release(nskb->dst);
238+ nskb->dst = &rt->u.dst;
239+
240+ /* "Never happens" */
241+ if (nskb->len > nskb->dst->pmtu)
242+ goto free_nskb;
243+
244+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
245+ ip_finish_output);
246+ return;
247+
248+ free_nskb:
249+ kfree_skb(nskb);
250+}
251+
252 static unsigned int reject(struct sk_buff **pskb,
253 unsigned int hooknum,
254 const struct net_device *in,
255@@ -43,6 +151,12 @@
256 case IPT_ICMP_PORT_UNREACHABLE:
257 icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
258 break;
259+ case IPT_ICMP_NET_PROHIBITED:
260+ icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
261+ break;
262+ case IPT_ICMP_HOST_PROHIBITED:
263+ icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
264+ break;
265 case IPT_ICMP_ECHOREPLY: {
266 struct icmphdr *icmph = (struct icmphdr *)
267 ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
268@@ -64,6 +178,9 @@
269 }
270 }
271 break;
272+ case IPT_TCP_RESET:
273+ send_reset(*pskb);
274+ break;
275 }
276
277 return NF_DROP;
278@@ -96,7 +213,7 @@
279
280 /* Only allow these for packet filtering. */
281 if (strcmp(tablename, "filter") != 0) {
282- DEBUGP("REJECT: bad table `%s'.\n", table);
283+ DEBUGP("REJECT: bad table `%s'.\n", tablename);
284 return 0;
285 }
286 if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
287@@ -116,6 +233,18 @@
288 /* Must contain ICMP match. */
289 if (IPT_MATCH_ITERATE(e, find_ping_match) == 0) {
290 DEBUGP("REJECT: ECHOREPLY illegal for non-ping\n");
291+ return 0;
292+ }
293+ } else if (rejinfo->with == IPT_TCP_RESET) {
294+ /* Must specify that it's a TCP packet */
295+ if (e->ip.proto != IPPROTO_TCP
296+ || (e->ip.invflags & IPT_INV_PROTO)) {
297+ DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n");
298+ return 0;
299+ }
300+ /* Only for local input. Rest is too dangerous. */
301+ if ((hook_mask & ~(1 << NF_IP_LOCAL_IN)) != 0) {
302+ DEBUGP("REJECT: TCP_RESET only from INPUT\n");
303 return 0;
304 }
305 }