Root/target/linux/generic-2.4/patches/624-netfilter_ip6t_reject.patch

1--- /dev/null
2+++ b/net/ipv6/netfilter/ip6t_REJECT.c
3@@ -0,0 +1,301 @@
4+/*
5+ * This is a module which is used for rejecting packets.
6+ * Added support for customized reject packets (Jozsef Kadlecsik).
7+ * Sun 12 Nov 2000
8+ * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
9+ */
10+#include <linux/config.h>
11+#include <linux/module.h>
12+#include <linux/skbuff.h>
13+#include <linux/icmpv6.h>
14+#include <net/tcp.h>
15+#include <net/ipv6.h>
16+#include <net/ip6_fib.h>
17+#include <net/ip6_route.h>
18+#include <linux/netfilter_ipv6/ip6_tables.h>
19+#include <linux/netfilter_ipv6/ip6t_REJECT.h>
20+
21+#if 1
22+#define DEBUGP printk
23+#else
24+#define DEBUGP(format, args...)
25+#endif
26+
27+#if 0
28+/* Send RST reply */
29+static void send_reset(struct sk_buff *oldskb)
30+{
31+ struct sk_buff *nskb;
32+ struct tcphdr *otcph, *tcph;
33+ struct rtable *rt;
34+ unsigned int otcplen;
35+ int needs_ack;
36+
37+ /* IP header checks: fragment, too short. */
38+ if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
39+ || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
40+ return;
41+
42+ otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
43+ otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
44+
45+ /* No RST for RST. */
46+ if (otcph->rst)
47+ return;
48+
49+ /* Check checksum. */
50+ if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
51+ oldskb->nh.iph->daddr,
52+ csum_partial((char *)otcph, otcplen, 0)) != 0)
53+ return;
54+
55+ /* Copy skb (even if skb is about to be dropped, we can't just
56+ clone it because there may be other things, such as tcpdump,
57+ interested in it) */
58+ nskb = skb_copy(oldskb, GFP_ATOMIC);
59+ if (!nskb)
60+ return;
61+
62+ /* This packet will not be the same as the other: clear nf fields */
63+ nf_conntrack_put(nskb->nfct);
64+ nskb->nfct = NULL;
65+ nskb->nfcache = 0;
66+#ifdef CONFIG_NETFILTER_DEBUG
67+ nskb->nf_debug = 0;
68+#endif
69+
70+ tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
71+
72+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
73+ tcph->source = xchg(&tcph->dest, tcph->source);
74+
75+ /* Truncate to length (no data) */
76+ tcph->doff = sizeof(struct tcphdr)/4;
77+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
78+ nskb->nh.iph->tot_len = htons(nskb->len);
79+
80+ if (tcph->ack) {
81+ needs_ack = 0;
82+ tcph->seq = otcph->ack_seq;
83+ tcph->ack_seq = 0;
84+ } else {
85+ needs_ack = 1;
86+ tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
87+ + otcplen - (otcph->doff<<2));
88+ tcph->seq = 0;
89+ }
90+
91+ /* Reset flags */
92+ ((u_int8_t *)tcph)[13] = 0;
93+ tcph->rst = 1;
94+ tcph->ack = needs_ack;
95+
96+ tcph->window = 0;
97+ tcph->urg_ptr = 0;
98+
99+ /* Adjust TCP checksum */
100+ tcph->check = 0;
101+ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
102+ nskb->nh.iph->saddr,
103+ nskb->nh.iph->daddr,
104+ csum_partial((char *)tcph,
105+ sizeof(struct tcphdr), 0));
106+
107+ /* Adjust IP TTL, DF */
108+ nskb->nh.iph->ttl = MAXTTL;
109+ /* Set DF, id = 0 */
110+ nskb->nh.iph->frag_off = htons(IP_DF);
111+ nskb->nh.iph->id = 0;
112+
113+ /* Adjust IP checksum */
114+ nskb->nh.iph->check = 0;
115+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
116+ nskb->nh.iph->ihl);
117+
118+ /* Routing */
119+ if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
120+ RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
121+ 0) != 0)
122+ goto free_nskb;
123+
124+ dst_release(nskb->dst);
125+ nskb->dst = &rt->u.dst;
126+
127+ /* "Never happens" */
128+ if (nskb->len > nskb->dst->pmtu)
129+ goto free_nskb;
130+
131+ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
132+ ip_finish_output);
133+ return;
134+
135+ free_nskb:
136+ kfree_skb(nskb);
137+}
138+#endif
139+
140+static unsigned int reject6_target(struct sk_buff **pskb,
141+ unsigned int hooknum,
142+ const struct net_device *in,
143+ const struct net_device *out,
144+ const void *targinfo,
145+ void *userinfo)
146+{
147+ const struct ip6t_reject_info *reject = targinfo;
148+ struct sk_buff *skb2 = NULL;
149+ struct rt6_info *rt6i;
150+ struct net_device odev;
151+
152+ if (!out) {
153+ skb2 = skb_clone(*pskb, GFP_ATOMIC);
154+ if (skb2 == NULL) {
155+ return NF_DROP;
156+ }
157+ dst_release(skb2->dst);
158+ skb2->dst = NULL;
159+
160+ rt6i = rt6_lookup(&skb2->nh.ipv6h->saddr, NULL, 0, 0);
161+ if (rt6i && rt6i->rt6i_dev) {
162+ skb2->dev = rt6i->rt6i_dev;
163+ rt6i = rt6_lookup(&skb2->nh.ipv6h->daddr, &skb2->nh.ipv6h->saddr, 0, 0);
164+ }
165+ memcpy(&odev, skb2->dev, sizeof(odev)); /* XXX 'out' has 'const' qualifier... */
166+ } else {
167+ memcpy(&odev, out, sizeof(odev));
168+ }
169+
170+ printk(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
171+ /* WARNING: This code causes reentry within ip6tables.
172+ This means that the ip6tables jump stack is now crap. We
173+ must return an absolute verdict. --RR */
174+ DEBUGP("REJECTv6: calling icmpv6_send\n");
175+ switch (reject->with) {
176+ case IP6T_ICMP6_NO_ROUTE:
177+ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, &odev);
178+ break;
179+ case IP6T_ICMP6_ADM_PROHIBITED:
180+ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, &odev);
181+ break;
182+ case IP6T_ICMP6_NOT_NEIGHBOUR:
183+ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, &odev);
184+ break;
185+ case IP6T_ICMP6_ADDR_UNREACH:
186+ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, &odev);
187+ break;
188+ case IP6T_ICMP6_PORT_UNREACH:
189+ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, &odev);
190+ break;
191+#if 0
192+ case IPT_ICMP_ECHOREPLY: {
193+ struct icmp6hdr *icmph = (struct icmphdr *)
194+ ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
195+ unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
196+
197+ /* Not non-head frags, or truncated */
198+ if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
199+ && datalen >= 4) {
200+ /* Usually I don't like cut & pasting code,
201+ but dammit, my party is starting in 45
202+ mins! --RR */
203+ struct icmp_bxm icmp_param;
204+
205+ icmp_param.icmph=*icmph;
206+ icmp_param.icmph.type=ICMP_ECHOREPLY;
207+ icmp_param.data_ptr=(icmph+1);
208+ icmp_param.data_len=datalen;
209+ icmp_reply(&icmp_param, *pskb);
210+ }
211+ }
212+ break;
213+ case IPT_TCP_RESET:
214+ send_reset(*pskb);
215+ break;
216+#endif
217+ default:
218+ printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
219+ break;
220+ }
221+
222+ if (skb2) kfree_skb(skb2);
223+
224+ return NF_DROP;
225+}
226+
227+static inline int find_ping_match(const struct ip6t_entry_match *m)
228+{
229+ const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
230+
231+ if (strcmp(m->u.kernel.match->name, "icmp6") == 0
232+ && icmpinfo->type == ICMPV6_ECHO_REQUEST
233+ && !(icmpinfo->invflags & IP6T_ICMP_INV))
234+ return 1;
235+
236+ return 0;
237+}
238+
239+static int check(const char *tablename,
240+ const struct ip6t_entry *e,
241+ void *targinfo,
242+ unsigned int targinfosize,
243+ unsigned int hook_mask)
244+{
245+ const struct ip6t_reject_info *rejinfo = targinfo;
246+
247+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
248+ DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
249+ return 0;
250+ }
251+
252+ /* Only allow these for packet filtering. */
253+ if (strcmp(tablename, "filter") != 0) {
254+ DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
255+ return 0;
256+ }
257+ if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
258+ | (1 << NF_IP6_FORWARD)
259+ | (1 << NF_IP6_LOCAL_OUT))) != 0) {
260+ DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
261+ return 0;
262+ }
263+
264+ if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
265+ /* Must specify that it's an ICMP ping packet. */
266+ if (e->ipv6.proto != IPPROTO_ICMPV6
267+ || (e->ipv6.invflags & IP6T_INV_PROTO)) {
268+ DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
269+ return 0;
270+ }
271+ /* Must contain ICMP match. */
272+ if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
273+ DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
274+ return 0;
275+ }
276+ } else if (rejinfo->with == IP6T_TCP_RESET) {
277+ /* Must specify that it's a TCP packet */
278+ if (e->ipv6.proto != IPPROTO_TCP
279+ || (e->ipv6.invflags & IP6T_INV_PROTO)) {
280+ DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
281+ return 0;
282+ }
283+ }
284+
285+ return 1;
286+}
287+
288+static struct ip6t_target ip6t_reject_reg
289+= { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
290+
291+static int __init init(void)
292+{
293+ if (ip6t_register_target(&ip6t_reject_reg))
294+ return -EINVAL;
295+ return 0;
296+}
297+
298+static void __exit fini(void)
299+{
300+ ip6t_unregister_target(&ip6t_reject_reg);
301+}
302+
303+module_init(init);
304+module_exit(fini);
305--- a/include/linux/netfilter_ipv6/ip6t_REJECT.h
306+++ b/include/linux/netfilter_ipv6/ip6t_REJECT.h
307@@ -2,15 +2,17 @@
308 #define _IP6T_REJECT_H
309 
310 enum ip6t_reject_with {
311- IP6T_ICMP_NET_UNREACHABLE,
312- IP6T_ICMP_HOST_UNREACHABLE,
313- IP6T_ICMP_PROT_UNREACHABLE,
314- IP6T_ICMP_PORT_UNREACHABLE,
315- IP6T_ICMP_ECHOREPLY
316+ IP6T_ICMP6_NO_ROUTE,
317+ IP6T_ICMP6_ADM_PROHIBITED,
318+ IP6T_ICMP6_NOT_NEIGHBOUR,
319+ IP6T_ICMP6_ADDR_UNREACH,
320+ IP6T_ICMP6_PORT_UNREACH,
321+ IP6T_ICMP6_ECHOREPLY,
322+ IP6T_TCP_RESET
323 };
324 
325 struct ip6t_reject_info {
326     enum ip6t_reject_with with; /* reject type */
327 };
328 
329-#endif /*_IPT_REJECT_H*/
330+#endif /*_IP6T_REJECT_H*/
331--- a/net/ipv6/netfilter/Makefile
332+++ b/net/ipv6/netfilter/Makefile
333@@ -34,5 +34,7 @@ obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.
334 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
335 obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
336 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
337+obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
338+
339 
340 include $(TOPDIR)/Rules.make
341--- a/net/ipv6/netfilter/Config.in
342+++ b/net/ipv6/netfilter/Config.in
343@@ -61,6 +61,9 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ];
344   if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
345     dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_FILTER
346   fi
347+ if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
348+ dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
349+ fi
350 
351 # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
352 # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
353

Archive Download this file



interactive