]> git.pld-linux.org Git - packages/kernel.git/blame - pom-ng-unclean-20060504.patch
- converted to utf8
[packages/kernel.git] / pom-ng-unclean-20060504.patch
CommitLineData
c6410bf7 1 Kconfig | 14 +
2 Makefile | 1
3 ipt_unclean.c | 612 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 3 files changed, 627 insertions(+)
5
6diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
7--- linux.org/net/ipv4/netfilter/Kconfig 2006-05-02 23:38:44.000000000 +0200
8+++ linux/net/ipv4/netfilter/Kconfig 2006-05-04 14:49:54.000000000 +0200
9@@ -606,5 +606,19 @@
10 Allows altering the ARP packet payload: source and destination
11 hardware and network addresses.
12
13+config IP_NF_MATCH_UNCLEAN
14+ tristate 'Unclean match support (DANGEROUS)'
15+ depends on EXPERIMENTAL && IP_NF_IPTABLES
16+ help
17+ Unclean packet matching matches any strange or invalid packets, by
18+ looking at a series of fields in the IP, TCP, UDP and ICMP headers.
19+
20+ Please note that this kind of matching is considered dangerous and
21+ might harm the future compatibility of your packet filter.
22+
23+ It has happened before, search on the net for ECN blackholes :(
24+
25+
26+
27 endmenu
28
29diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
30--- linux.org/net/ipv4/netfilter/Makefile 2006-05-02 23:38:44.000000000 +0200
31+++ linux/net/ipv4/netfilter/Makefile 2006-05-04 14:49:54.000000000 +0200
32@@ -0,0 +0,1 @@
33+obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
34diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_unclean.c linux/net/ipv4/netfilter/ipt_unclean.c
35--- linux.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
36+++ linux/net/ipv4/netfilter/ipt_unclean.c 2006-05-04 14:49:54.000000000 +0200
37@@ -0,0 +1,612 @@
38+/* Kernel module to match suspect packets. */
39+#include <linux/module.h>
40+#include <linux/skbuff.h>
41+#include <linux/ip.h>
42+#include <linux/udp.h>
43+#include <linux/tcp.h>
44+#include <linux/icmp.h>
45+#include <net/checksum.h>
46+#include <net/ip.h>
47+
48+#include <linux/netfilter_ipv4/ip_tables.h>
49+
50+#define limpk(format, args...) \
51+do { \
52+ if (net_ratelimit()) \
53+ printk("ipt_unclean: %s" format, \
54+ embedded ? "(embedded packet) " : "" , ## args); \
55+} while(0)
56+
57+enum icmp_error_status
58+{
59+ ICMP_MAY_BE_ERROR,
60+ ICMP_IS_ERROR,
61+ ICMP_NOT_ERROR
62+};
63+
64+struct icmp_info
65+{
66+ size_t min_len, max_len;
67+ enum icmp_error_status err;
68+ u_int8_t min_code, max_code;
69+};
70+
71+static int
72+check_ip(const struct sk_buff *skb, unsigned int offset);
73+
74+/* ICMP-specific checks. */
75+static int
76+check_icmp(const struct sk_buff *skb,
77+ unsigned int offset,
78+ unsigned int fragoff,
79+ int more_frags,
80+ int embedded)
81+{
82+ struct icmphdr icmph;
83+ static struct icmp_info info[]
84+ = { [ICMP_ECHOREPLY]
85+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
86+ [ICMP_DEST_UNREACH]
87+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
88+ [ICMP_SOURCE_QUENCH]
89+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
90+ [ICMP_REDIRECT]
91+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
92+ [ICMP_ECHO]
93+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
94+ /* Router advertisement. */
95+ [9]
96+ = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
97+ /* Router solicitation. */
98+ [10]
99+ = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
100+ [ICMP_TIME_EXCEEDED]
101+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
102+ [ICMP_PARAMETERPROB]
103+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
104+ [ICMP_TIMESTAMP]
105+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
106+ [ICMP_TIMESTAMPREPLY]
107+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
108+ [ICMP_INFO_REQUEST]
109+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
110+ [ICMP_INFO_REPLY]
111+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
112+ [ICMP_ADDRESS]
113+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
114+ [ICMP_ADDRESSREPLY]
115+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
116+
117+ /* Can't do anything if it's a fragment. */
118+ if (fragoff)
119+ return 1;
120+
121+ /* CHECK: Must have whole header.. */
122+ if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0) {
123+ limpk("ICMP len=%u too short\n", skb->len - offset);
124+ return 0;
125+ }
126+
127+ /* If not embedded in an ICMP error already. */
128+ if (!embedded) {
129+ /* CHECK: Truncated ICMP (even if first fragment). */
130+ if (icmph.type < sizeof(info)/sizeof(struct icmp_info)
131+ && info[icmph.type].min_len != 0
132+ && skb->len - offset < info[icmph.type].min_len) {
133+ limpk("ICMP type %u len %u too short\n",
134+ icmph.type, skb->len - offset);
135+ return 0;
136+ }
137+
138+ /* CHECK: Check within known error ICMPs. */
139+ if (icmph.type < sizeof(info)/sizeof(struct icmp_info)
140+ && info[icmph.type].err == ICMP_IS_ERROR) {
141+ /* Max IP header size = 60 */
142+ char inner[60 + 8];
143+ struct iphdr *inner_ip = (struct iphdr *)inner;
144+
145+ /* CHECK: Embedded packet must be at least
146+ length of iph + 8 bytes. */
147+ if (skb_copy_bits(skb, offset + sizeof(icmph),
148+ inner, sizeof(struct iphdr)+8) < 0) {
149+ limpk("ICMP error internal way too short\n");
150+ return 0;
151+ }
152+
153+ /* iphhdr may actually be longer: still need 8
154+ actual protocol bytes. */
155+ if (offset + sizeof(icmph) + inner_ip->ihl*4 + 8
156+ > skb->len) {
157+ limpk("ICMP error internal too short\n");
158+ return 0;
159+ }
160+ if (!check_ip(skb, offset + sizeof(icmph)))
161+ return 0;
162+ }
163+ } else {
164+ /* CHECK: Can't embed ICMP unless known non-error. */
165+ if (icmph.type >= sizeof(info)/sizeof(struct icmp_info)
166+ || info[icmph.type].err != ICMP_NOT_ERROR) {
167+ limpk("ICMP type %u not embeddable\n",
168+ icmph.type);
169+ return 0;
170+ }
171+ }
172+
173+ /* CHECK: Invalid ICMP codes. */
174+ if (icmph.type < sizeof(info)/sizeof(struct icmp_info)
175+ && (icmph.code < info[icmph.type].min_code
176+ || icmph.code > info[icmph.type].max_code)) {
177+ limpk("ICMP type=%u code=%u\n",
178+ icmph.type, icmph.code);
179+ return 0;
180+ }
181+
182+ /* CHECK: Above maximum length. */
183+ if (icmph.type < sizeof(info)/sizeof(struct icmp_info)
184+ && info[icmph.type].max_len != 0
185+ && skb->len - offset > info[icmph.type].max_len) {
186+ limpk("ICMP type=%u too long: %u bytes\n",
187+ icmph.type, skb->len - offset);
188+ return 0;
189+ }
190+
191+ switch (icmph.type) {
192+ case ICMP_PARAMETERPROB: {
193+ /* CHECK: Problem param must be within error packet's
194+ * IP header. */
195+ u_int32_t arg = ntohl(icmph.un.gateway);
196+
197+ if (icmph.code == 0) {
198+ /* We've already made sure it's long enough. */
199+ struct iphdr iph;
200+ skb_copy_bits(skb, offset + sizeof(icmph), &iph,
201+ sizeof(iph));
202+ /* Code 0 means that upper 8 bits is pointer
203+ to problem. */
204+ if ((arg >> 24) >= iph.ihl*4) {
205+ limpk("ICMP PARAMETERPROB ptr = %u\n",
206+ ntohl(icmph.un.gateway) >> 24);
207+ return 0;
208+ }
209+ arg &= 0x00FFFFFF;
210+ }
211+
212+ /* CHECK: Rest must be zero. */
213+ if (arg) {
214+ limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
215+ arg);
216+ return 0;
217+ }
218+ break;
219+ }
220+
221+ case ICMP_TIME_EXCEEDED:
222+ case ICMP_SOURCE_QUENCH:
223+ /* CHECK: Unused must be zero. */
224+ if (icmph.un.gateway != 0) {
225+ limpk("ICMP type=%u unused = %u\n",
226+ icmph.type, ntohl(icmph.un.gateway));
227+ return 0;
228+ }
229+ break;
230+ }
231+
232+ return 1;
233+}
234+
235+/* UDP-specific checks. */
236+static int
237+check_udp(const struct sk_buff *skb,
238+ unsigned int offset,
239+ unsigned int fragoff,
240+ int more_frags,
241+ int embedded)
242+{
243+ struct udphdr udph;
244+
245+ /* Can't do anything if it's a fragment. */
246+ if (fragoff)
247+ return 1;
248+
249+ /* CHECK: Must cover UDP header. */
250+ if (skb_copy_bits(skb, offset, &udph, sizeof(udph)) < 0) {
251+ limpk("UDP len=%u too short\n", skb->len - offset);
252+ return 0;
253+ }
254+
255+ /* CHECK: Destination port can't be zero. */
256+ if (!udph.dest) {
257+ limpk("UDP zero destination port\n");
258+ return 0;
259+ }
260+
261+ if (!more_frags) {
262+ if (!embedded) {
263+ /* CHECK: UDP length must match. */
264+ if (ntohs(udph.len) != skb->len - offset) {
265+ limpk("UDP len too short %u vs %u\n",
266+ ntohs(udph.len), skb->len - offset);
267+ return 0;
268+ }
269+ } else {
270+ /* CHECK: UDP length be >= this truncated pkt. */
271+ if (ntohs(udph.len) < skb->len - offset) {
272+ limpk("UDP len too long %u vs %u\n",
273+ ntohs(udph.len), skb->len - offset);
274+ return 0;
275+ }
276+ }
277+ } else {
278+ /* CHECK: UDP length must be > this frag's length. */
279+ if (ntohs(udph.len) <= skb->len - offset) {
280+ limpk("UDP fragment len too short %u vs %u\n",
281+ ntohs(udph.len), skb->len - offset);
282+ return 0;
283+ }
284+ }
285+
286+ return 1;
287+}
288+
289+/* TCP-specific checks. */
290+static int
291+check_tcp(const struct sk_buff *skb,
292+ unsigned int offset,
293+ unsigned int fragoff,
294+ int more_frags,
295+ int embedded)
296+{
297+ struct tcphdr tcph;
298+ unsigned char opt[15 * 4 - sizeof(struct tcphdr)];
299+ u32 tcpflags;
300+ int end_of_options = 0;
301+ unsigned int i, optlen;
302+
303+ /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
304+ /* In fact, this is caught below (offset < 516). */
305+
306+ /* Can't do anything if it's a fragment. */
307+ if (fragoff)
308+ return 1;
309+
310+ /* CHECK: Smaller than minimal TCP hdr. */
311+ if (skb_copy_bits(skb, offset, &tcph, sizeof(tcph)) < 0) {
312+ u16 ports[2];
313+
314+ if (!embedded) {
315+ limpk("Packet length %u < TCP header.\n",
316+ skb->len - offset);
317+ return 0;
318+ }
319+
320+ /* Must have ports available (datalen >= 8), from
321+ check_icmp which set embedded = 1 */
322+ /* CHECK: TCP ports inside ICMP error */
323+ skb_copy_bits(skb, offset, ports, sizeof(ports));
324+ if (!ports[0] || !ports[1]) {
325+ limpk("Zero TCP ports %u/%u.\n",
326+ htons(ports[0]), htons(ports[1]));
327+ return 0;
328+ }
329+ return 1;
330+ }
331+
332+ /* CHECK: TCP header claims tiny size. */
333+ if (tcph.doff * 4 < sizeof(tcph)) {
334+ limpk("TCP header claims tiny size %u\n", tcph.doff * 4);
335+ return 0;
336+ }
337+
338+ /* CHECK: Packet smaller than actual TCP hdr. */
339+ optlen = tcph.doff*4 - sizeof(tcph);
340+ if (skb_copy_bits(skb, offset + sizeof(tcph), opt, optlen) < 0) {
341+ if (!embedded) {
342+ limpk("Packet length %u < actual TCP header.\n",
343+ skb->len - offset);
344+ return 0;
345+ } else
346+ return 1;
347+ }
348+
349+ /* CHECK: TCP ports non-zero */
350+ if (!tcph.source || !tcph.dest) {
351+ limpk("Zero TCP ports %u/%u.\n",
352+ htons(tcph.source), htons(tcph.dest));
353+ return 0;
354+ }
355+
356+ tcpflags = tcp_flag_word(&tcph);
357+
358+ /* CHECK: TCP reserved bits zero. */
359+ if (tcpflags & TCP_RESERVED_BITS) {
360+ limpk("TCP reserved bits not zero\n");
361+ return 0;
362+ }
363+
364+ tcpflags &= ~(TCP_DATA_OFFSET | TCP_FLAG_CWR | TCP_FLAG_ECE
365+ | __constant_htonl(0x0000FFFF));
366+
367+ /* CHECK: TCP flags. */
368+ if (tcpflags != TCP_FLAG_SYN
369+ && tcpflags != (TCP_FLAG_SYN|TCP_FLAG_ACK)
370+ && tcpflags != TCP_FLAG_RST
371+ && tcpflags != (TCP_FLAG_RST|TCP_FLAG_ACK)
372+ && tcpflags != (TCP_FLAG_RST|TCP_FLAG_ACK|TCP_FLAG_PSH)
373+ && tcpflags != (TCP_FLAG_FIN|TCP_FLAG_ACK)
374+ && tcpflags != TCP_FLAG_ACK
375+ && tcpflags != (TCP_FLAG_ACK|TCP_FLAG_PSH)
376+ && tcpflags != (TCP_FLAG_ACK|TCP_FLAG_URG)
377+ && tcpflags != (TCP_FLAG_ACK|TCP_FLAG_URG|TCP_FLAG_PSH)
378+ && tcpflags != (TCP_FLAG_FIN|TCP_FLAG_ACK|TCP_FLAG_PSH)
379+ && tcpflags != (TCP_FLAG_FIN|TCP_FLAG_ACK|TCP_FLAG_URG)
380+ && tcpflags != (TCP_FLAG_FIN|TCP_FLAG_ACK|TCP_FLAG_URG
381+ |TCP_FLAG_PSH)) {
382+ limpk("TCP flags bad: 0x%04X\n", ntohl(tcpflags) >> 16);
383+ return 0;
384+ }
385+
386+ for (i = 0; i < optlen; ) {
387+ switch (opt[i]) {
388+ case 0:
389+ end_of_options = 1;
390+ i++;
391+ break;
392+ case 1:
393+ i++;
394+ break;
395+ default:
396+ /* CHECK: options after EOO. */
397+ if (end_of_options) {
398+ limpk("TCP option %u after end\n",
399+ opt[i]);
400+ return 0;
401+ }
402+ /* CHECK: options at tail. */
403+ else if (i+1 >= optlen) {
404+ limpk("TCP option %u at tail\n",
405+ opt[i]);
406+ return 0;
407+ }
408+ /* CHECK: zero-length options. */
409+ else if (opt[i+1] == 0) {
410+ limpk("TCP option %u 0 len\n",
411+ opt[i]);
412+ return 0;
413+ }
414+ /* CHECK: oversize options. */
415+ else if (i + opt[i+1] > optlen) {
416+ limpk("TCP option %u at %u too long\n",
417+ (unsigned int) opt[i], i);
418+ return 0;
419+ }
420+ /* Move to next option */
421+ i += opt[i+1];
422+ }
423+ }
424+
425+ return 1;
426+}
427+
428+/* Returns 1 if ok */
429+/* Standard IP checks. */
430+static int
431+check_ip(const struct sk_buff *skb, unsigned int offset)
432+{
433+ int end_of_options = 0;
434+ unsigned int datalen, optlen;
435+ unsigned int i;
436+ unsigned int fragoff;
437+ struct iphdr iph;
438+ unsigned char opt[15 * 4 - sizeof(struct iphdr)];
439+ int embedded = offset;
440+
441+ /* Should only happen for local outgoing raw-socket packets. */
442+ /* CHECK: length >= ip header. */
443+ if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0) {
444+ limpk("Packet length %u < IP header.\n", skb->len - offset);
445+ return 0;
446+ }
447+ if (iph.ihl * 4 < sizeof(iph)) {
448+ limpk("IP len %u < minimum IP header.\n", iph.ihl*4);
449+ return 0;
450+ }
451+
452+ optlen = iph.ihl * 4 - sizeof(iph);
453+ if (skb_copy_bits(skb, offset+sizeof(struct iphdr), opt, optlen)<0) {
454+ limpk("Packet length %u < IP header %u.\n",
455+ skb->len - offset, iph.ihl * 4);
456+ return 0;
457+ }
458+
459+ fragoff = (ntohs(iph.frag_off) & IP_OFFSET);
460+ datalen = skb->len - (offset + sizeof(struct iphdr) + optlen);
461+
462+ /* CHECK: Embedded fragment. */
463+ if (offset && fragoff) {
464+ limpk("Embedded fragment.\n");
465+ return 0;
466+ }
467+
468+ for (i = 0; i < optlen; ) {
469+ switch (opt[i]) {
470+ case 0:
471+ end_of_options = 1;
472+ i++;
473+ break;
474+ case 1:
475+ i++;
476+ break;
477+ default:
478+ /* CHECK: options after EOO. */
479+ if (end_of_options) {
480+ limpk("IP option %u after end\n",
481+ opt[i]);
482+ return 0;
483+ }
484+ /* CHECK: options at tail. */
485+ else if (i+1 >= optlen) {
486+ limpk("IP option %u at tail\n",
487+ opt[i]);
488+ return 0;
489+ }
490+ /* CHECK: zero-length or one-length options. */
491+ else if (opt[i+1] < 2) {
492+ limpk("IP option %u %u len\n",
493+ opt[i], opt[i+1]);
494+ return 0;
495+ }
496+ /* CHECK: oversize options. */
497+ else if (i + opt[i+1] > optlen) {
498+ limpk("IP option %u at %u too long\n",
499+ opt[i], i);
500+ return 0;
501+ }
502+ /* Move to next option */
503+ i += opt[i+1];
504+ }
505+ }
506+
507+ /* Fragment checks. */
508+
509+ /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
510+ if ((ntohs(iph.frag_off) & IP_MF)
511+ && (ntohs(iph.tot_len) % 8) != 0) {
512+ limpk("Truncated fragment %u long.\n", ntohs(iph.tot_len));
513+ return 0;
514+ }
515+
516+ /* CHECK: Oversize fragment a-la Ping of Death. */
517+ if (fragoff * 8 + datalen > 65535) {
518+ limpk("Oversize fragment to %u.\n", fragoff * 8);
519+ return 0;
520+ }
521+
522+ /* CHECK: DF set and fragoff or MF set. */
523+ if ((ntohs(iph.frag_off) & IP_DF)
524+ && (fragoff || (ntohs(iph.frag_off) & IP_MF))) {
525+ limpk("DF set and offset=%u, MF=%u.\n",
526+ fragoff, ntohs(iph.frag_off) & IP_MF);
527+ return 0;
528+ }
529+
530+ /* CHECK: Zero-sized fragments. */
531+ if ((fragoff || (ntohs(iph.frag_off) & IP_MF))
532+ && datalen == 0) {
533+ limpk("Zero size fragment offset=%u\n", fragoff);
534+ return 0;
535+ }
536+
537+ /* Note: we can have even middle fragments smaller than this:
538+ consider a large packet passing through a 600MTU then
539+ 576MTU link: this gives a fragment of 24 data bytes. But
540+ everyone packs fragments largest first, hence a fragment
541+ can't START before 576 - MAX_IP_HEADER_LEN. */
542+
543+ /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
544+ down to 128 (576 taken from RFC 791: All hosts must be
545+ prepared to accept datagrams of up to 576 octets). Use 128
546+ here. */
547+#define MIN_LIKELY_MTU 128
548+ /* CHECK: Min size of first frag = 128. */
549+ if ((ntohs(iph.frag_off) & IP_MF)
550+ && fragoff == 0
551+ && ntohs(iph.tot_len) < MIN_LIKELY_MTU) {
552+ limpk("First fragment size %u < %u\n", ntohs(iph.tot_len),
553+ MIN_LIKELY_MTU);
554+ return 0;
555+ }
556+
557+ /* CHECK: Min offset of frag = 128 - IP hdr len. */
558+ if (fragoff && fragoff * 8 < MIN_LIKELY_MTU - iph.ihl * 4) {
559+ limpk("Fragment starts at %u < %u\n", fragoff * 8,
560+ MIN_LIKELY_MTU - iph.ihl * 4);
561+ return 0;
562+ }
563+
564+ /* CHECK: Protocol specification non-zero. */
565+ if (iph.protocol == 0) {
566+ limpk("Zero protocol\n");
567+ return 0;
568+ }
569+
570+ /* FIXME: This is already checked for in "Oversize fragment"
571+ above --RR */
572+ /* CHECK: Do not use what is unused.
573+ * First bit of fragmentation flags should be unused.
574+ * May be used by OS fingerprinting tools.
575+ * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
576+ */
577+ if (ntohs(iph.frag_off)>>15) {
578+ limpk("IP unused bit set\n");
579+ return 0;
580+ }
581+
582+ /* Per-protocol checks. */
583+ switch (iph.protocol) {
584+ case IPPROTO_ICMP:
585+ return check_icmp(skb, offset + iph.ihl*4, fragoff,
586+ (ntohs(iph.frag_off) & IP_MF),
587+ embedded);
588+
589+ case IPPROTO_UDP:
590+ return check_udp(skb, offset + iph.ihl*4, fragoff,
591+ (ntohs(iph.frag_off) & IP_MF),
592+ embedded);
593+
594+ case IPPROTO_TCP:
595+ return check_tcp(skb, offset + iph.ihl*4, fragoff,
596+ (ntohs(iph.frag_off) & IP_MF),
597+ embedded);
598+ default:
599+ /* Ignorance is bliss. */
600+ return 1;
601+ }
602+}
603+
604+static int
605+match(const struct sk_buff *skb,
606+ const struct net_device *in,
607+ const struct net_device *out,
608+ const void *matchinfo,
609+ int offset,
610+ unsigned int protoff,
611+ int *hotdrop)
612+{
613+ return !check_ip(skb, 0);
614+}
615+
616+/* Called when user tries to insert an entry of this type. */
617+static int
618+checkentry(const char *tablename,
619+ const void *ip,
620+ void *matchinfo,
621+ unsigned int matchsize,
622+ unsigned int hook_mask)
623+{
624+ if (matchsize != IPT_ALIGN(0))
625+ return 0;
626+
627+ return 1;
628+}
629+
630+static struct ipt_match unclean_match = {
631+ .name = "unclean",
632+ .match = &match,
633+ .checkentry = &checkentry,
634+ .me = THIS_MODULE,
635+};
636+
637+static int __init init(void)
638+{
639+ return ipt_register_match(&unclean_match);
640+}
641+
642+static void __exit fini(void)
643+{
644+ ipt_unregister_match(&unclean_match);
645+}
646+
647+module_init(init);
648+module_exit(fini);
649+MODULE_LICENSE("GPL");
This page took 0.14406 seconds and 4 git commands to generate.