]> git.pld-linux.org Git - packages/kernel.git/blob - pom-ng-unclean-20060504.patch
- addedd Linux-ABI support. Bcond, default disabled.
[packages/kernel.git] / pom-ng-unclean-20060504.patch
1  Kconfig       |   14 +
2  Makefile      |    1 
3  ipt_unclean.c |  612 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4  3 files changed, 627 insertions(+)
5
6 diff -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  
29 diff -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
34 diff -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.087246 seconds and 3 git commands to generate.