1 Netfilter SNAP 20040429
3 PENDING/expect-evict-order
4 PENDING/init_conntrack-optimize
5 PENDING/ipt_helper-invert-fix
8 PENDING/orphaned-expect-fix
9 PENDING/proc-no-internal-targets
12 BASE/NETLINK // fix socket -> sk_socket
21 BASE/osf // fix socket -> sk_socket
22 BASE/pool // added EXPORT_SYMBOL(ip_pool_mod, ip_pool_match)
30 EXTRA/CONNMARK // main linux.patch needs fix
33 EXTRA/TARPIT // fix Makefile.ladd and req patch for 2.6
37 EXTRA/eggdrop-conntrack
38 EXTRA/h323-conntrack-nat
39 EXTRA/ipsec-01-output-hooks
40 EXTRA/ipsec-02-input-hooks
41 EXTRA/ipsec-03-policy-lookup
42 EXTRA/ipsec-04-policy-check
44 EXTRA/mms-conntrack-nat
45 EXTRA/owner-socketlookup
48 EXTRA/quake3-conntrack-nat
51 EXTRA/sctp-conntrack-nat
52 EXTRA/string // required unclean module - included
53 EXTRA/talk-conntrack-nat
55 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter.h linux-2.6.6-rc3/include/linux/netfilter.h
56 --- linux-2.6.6-rc3.org/include/linux/netfilter.h 2004-04-28 03:35:48.000000000 +0200
57 +++ linux-2.6.6-rc3/include/linux/netfilter.h 2004-04-30 09:12:42.000000000 +0200
59 <= 0x2000 is used for protocol-flags. */
60 #define NFC_UNKNOWN 0x4000
61 #define NFC_ALTERED 0x8000
62 +#define NFC_TRACE 0x10000
65 #include <linux/config.h>
67 /* This is gross, but inline doesn't cut it for avoiding the function
68 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
69 #ifdef CONFIG_NETFILTER_DEBUG
70 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
71 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
72 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
75 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
76 #define NF_HOOK_THRESH nf_hook_slow
78 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
79 -(list_empty(&nf_hooks[(pf)][(hook)]) \
80 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
81 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
83 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
84 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
87 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
89 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
90 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
92 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
93 struct net_device *indev, struct net_device *outdev,
96 #else /* !CONFIG_NETFILTER */
97 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
98 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
99 #endif /*CONFIG_NETFILTER*/
102 +#ifdef CONFIG_IP_NF_NAT_NEEDED
104 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
107 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
109 + if (family == AF_INET)
110 + nf_nat_decode_session4(skb, fl);
112 +#else /* CONFIG_IP_NF_NAT_NEEDED */
113 +#define nf_nat_decode_session(skb,fl,family)
114 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
115 +#endif /* CONFIG_XFRM */
117 #endif /*__KERNEL__*/
118 #endif /*__LINUX_NETFILTER_H*/
119 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h linux-2.6.6-rc3/include/linux/netfilter_helpers.h
120 --- linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
121 +++ linux-2.6.6-rc3/include/linux/netfilter_helpers.h 2004-04-30 09:14:05.000000000 +0200
124 + * Helpers for netfiler modules. This file provides implementations for basic
125 + * functions such as strncasecmp(), etc.
127 + * gcc will warn for defined but unused functions, so we only include the
128 + * functions requested. The following macros are used:
129 + * NF_NEED_STRNCASECMP nf_strncasecmp()
130 + * NF_NEED_STRTOU16 nf_strtou16()
131 + * NF_NEED_STRTOU32 nf_strtou32()
133 +#ifndef _NETFILTER_HELPERS_H
134 +#define _NETFILTER_HELPERS_H
136 +/* Only include these functions for kernel code. */
139 +#include <linux/ctype.h>
140 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
143 + * The standard strncasecmp()
145 +#ifdef NF_NEED_STRNCASECMP
147 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
149 + if (s1 == NULL || s2 == NULL)
151 + if (s1 == NULL && s2 == NULL)
155 + return (s1 == NULL) ? -1 : 1;
157 + while (len > 0 && tolower(*s1) == tolower(*s2))
163 + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
165 +#endif /* NF_NEED_STRNCASECMP */
168 + * Parse a string containing a 16-bit unsigned integer.
169 + * Returns the number of chars used, or zero if no number is found.
171 +#ifdef NF_NEED_STRTOU16
173 +nf_strtou16(const char* pbuf, u_int16_t* pval)
178 + while (isdigit(pbuf[n]))
180 + *pval = (*pval * 10) + (pbuf[n] - '0');
186 +#endif /* NF_NEED_STRTOU16 */
189 + * Parse a string containing a 32-bit unsigned integer.
190 + * Returns the number of chars used, or zero if no number is found.
192 +#ifdef NF_NEED_STRTOU32
194 +nf_strtou32(const char* pbuf, u_int32_t* pval)
199 + while (pbuf[n] >= '0' && pbuf[n] <= '9')
201 + *pval = (*pval * 10) + (pbuf[n] - '0');
207 +#endif /* NF_NEED_STRTOU32 */
210 + * Given a buffer and length, advance to the next line and mark the current
213 +#ifdef NF_NEED_NEXTLINE
215 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
225 + while (p[off] != '\n')
236 + /* if we saw a crlf, physlen needs adjusted */
237 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
242 + /* advance past the newline */
246 + *plinelen = physlen;
251 +#endif /* NF_NEED_NEXTLINE */
253 +#endif /* __KERNEL__ */
255 +#endif /* _NETFILTER_HELPERS_H */
256 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
257 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-28 03:36:37.000000000 +0200
258 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-30 09:14:39.000000000 +0200
261 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
262 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
263 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
265 /* per conntrack: protocol private data */
266 union ip_conntrack_proto {
267 /* insert conntrack proto private data here */
268 + struct ip_ct_sctp sctp;
269 struct ip_ct_tcp tcp;
270 struct ip_ct_icmp icmp;
275 /* Add protocol helper include file here */
276 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
277 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
278 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
279 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
280 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
281 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
282 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
283 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
285 /* per expectation: application helper private data */
286 union ip_conntrack_expect_help {
287 /* insert conntrack helper private data (expect) here */
288 + struct ip_ct_talk_expect exp_talk_info;
289 + struct ip_ct_rtsp_expect exp_rtsp_info;
290 + struct ip_ct_rsh_expect exp_rsh_info;
291 + struct ip_ct_mms_expect exp_mms_info;
292 + struct ip_ct_h225_expect exp_h225_info;
293 struct ip_ct_amanda_expect exp_amanda_info;
294 struct ip_ct_ftp_expect exp_ftp_info;
295 struct ip_ct_irc_expect exp_irc_info;
297 /* per conntrack: application helper private data */
298 union ip_conntrack_help {
299 /* insert conntrack helper private data (master) here */
300 + struct ip_ct_talk_master ct_talk_info;
301 + struct ip_ct_rtsp_master ct_rtsp_info;
302 + struct ip_ct_rsh_master ct_rsh_info;
303 + struct ip_ct_mms_master ct_mms_info;
304 + struct ip_ct_h225_master ct_h225_info;
305 struct ip_ct_ftp_master ct_ftp_info;
306 struct ip_ct_irc_master ct_irc_info;
310 #endif /* CONFIG_IP_NF_NAT_NEEDED */
312 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
313 + unsigned long mark;
318 /* get master conntrack via master expectation */
319 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
320 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
321 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-04-30 09:12:34.000000000 +0200
323 +#ifndef _IP_CONNTRACK_H323_H
324 +#define _IP_CONNTRACK_H323_H
325 +/* H.323 connection tracking. */
328 +/* Protects H.323 related data */
329 +#include <linux/netfilter_ipv4/lockhelp.h>
330 +DECLARE_LOCK_EXTERN(ip_h323_lock);
333 +/* Default H.225 port */
334 +#define H225_PORT 1720
336 +/* This structure is per expected connection */
337 +struct ip_ct_h225_expect {
338 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
339 + enum ip_conntrack_dir dir; /* Direction of the original connection */
340 + unsigned int offset; /* offset of the address in the payload */
343 +/* This structure exists only once per master */
344 +struct ip_ct_h225_master {
345 + int is_h225; /* H.225 or H.245 connection */
346 +#ifdef CONFIG_IP_NF_NAT_NEEDED
347 + enum ip_conntrack_dir dir; /* Direction of the original connection */
348 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
349 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
353 +#endif /* _IP_CONNTRACK_H323_H */
354 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
355 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
356 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-04-30 09:12:58.000000000 +0200
358 +#ifndef _IP_CONNTRACK_MMS_H
359 +#define _IP_CONNTRACK_MMS_H
363 +#include <linux/netfilter_ipv4/lockhelp.h>
365 +DECLARE_LOCK_EXTERN(ip_mms_lock);
367 +#define MMS_PORT 1755
368 +#define MMS_SRV_MSG_ID 196610
370 +#define MMS_SRV_MSG_OFFSET 36
371 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
372 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
373 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
374 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
377 +/* This structure is per expected connection */
378 +struct ip_ct_mms_expect {
384 +/* This structure exists only once per master */
385 +struct ip_ct_mms_master {
388 +#endif /* _IP_CONNTRACK_MMS_H */
389 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
390 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
391 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-04-30 09:13:29.000000000 +0200
393 +#ifndef _IP_CT_QUAKE3
394 +#define _IP_CT_QUAKE3
396 +/* Don't confuse with 27960, often used as the Server Port */
397 +#define QUAKE3_MASTER_PORT 27950
399 +struct quake3_search {
400 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
401 + const char *pattern;
405 +/* This structure is per expected connection */
406 +struct ip_ct_quake3_expect {
409 +/* This structure exists only once per master */
410 +struct ip_ct_quake3_master {
413 +#endif /* _IP_CT_QUAKE3 */
414 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
415 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
416 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-04-30 09:13:59.000000000 +0200
418 +/* RSH extension for IP connection tracking, Version 1.0
419 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
420 + * based on HW's ip_conntrack_irc.c
422 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
424 + * This program is free software; you can redistribute it and/or
425 + * modify it under the terms of the GNU General Public License
426 + * as published by the Free Software Foundation; either version
427 + * 2 of the License, or (at your option) any later version.
429 +#ifndef _IP_CONNTRACK_RSH_H
430 +#define _IP_CONNTRACK_RSH_H
433 +#include <linux/netfilter_ipv4/lockhelp.h>
435 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
439 +#define RSH_PORT 514
441 +/* This structure is per expected connection */
442 +struct ip_ct_rsh_expect
447 +/* This structure exists only once per master */
448 +struct ip_ct_rsh_master {
451 +#endif /* _IP_CONNTRACK_RSH_H */
453 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
454 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
455 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-04-30 09:14:05.000000000 +0200
458 + * RTSP extension for IP connection tracking.
459 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
460 + * based on ip_conntrack_irc.h
462 + * This program is free software; you can redistribute it and/or
463 + * modify it under the terms of the GNU General Public License
464 + * as published by the Free Software Foundation; either version
465 + * 2 of the License, or (at your option) any later version.
467 +#ifndef _IP_CONNTRACK_RTSP_H
468 +#define _IP_CONNTRACK_RTSP_H
470 +/* #define IP_NF_RTSP_DEBUG */
471 +#define IP_NF_RTSP_VERSION "0.01"
473 +/* port block types */
475 + pb_single, /* client_port=x */
476 + pb_range, /* client_port=x-y */
477 + pb_discon /* client_port=x/y (rtspbis) */
480 +/* We record seq number and length of rtsp headers here, all in host order. */
483 + * This structure is per expected connection. It is a member of struct
484 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
485 + * there and we are expected to only store the length of the data which
486 + * needs replaced. If a packet contains multiple RTSP messages, we create
487 + * one expected connection per message.
489 + * We use these variables to mark the entire header block. This may seem
490 + * like overkill, but the nature of RTSP requires it. A header may appear
491 + * multiple times in a message. We must treat two Transport headers the
492 + * same as one Transport header with two entries.
494 +struct ip_ct_rtsp_expect
496 + u_int32_t len; /* length of header block */
497 + portblock_t pbtype; /* Type of port block that was requested */
498 + u_int16_t loport; /* Port that was requested, low or first */
499 + u_int16_t hiport; /* Port that was requested, high or second */
501 + uint method; /* RTSP method */
502 + uint cseq; /* CSeq from request */
506 +/* This structure exists only once per master */
507 +struct ip_ct_rtsp_master
515 +#include <linux/netfilter_ipv4/lockhelp.h>
517 +#define RTSP_PORT 554
519 +/* Protects rtsp part of conntracks */
520 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
522 +#endif /* __KERNEL__ */
524 +#endif /* _IP_CONNTRACK_RTSP_H */
525 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
526 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
527 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-04-30 09:14:08.000000000 +0200
529 +#ifndef _IP_CONNTRACK_SCTP_H
530 +#define _IP_CONNTRACK_SCTP_H
531 +/* SCTP tracking. */
533 +enum sctp_conntrack {
534 + SCTP_CONNTRACK_NONE,
535 + SCTP_CONNTRACK_CLOSED,
536 + SCTP_CONNTRACK_COOKIE_WAIT,
537 + SCTP_CONNTRACK_COOKIE_ECHOED,
538 + SCTP_CONNTRACK_ESTABLISHED,
539 + SCTP_CONNTRACK_SHUTDOWN_SENT,
540 + SCTP_CONNTRACK_SHUTDOWN_RECD,
541 + SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
547 + enum sctp_conntrack state;
549 + u_int32_t vtag[IP_CT_DIR_MAX];
550 + u_int32_t ttag[IP_CT_DIR_MAX];
553 +#endif /* _IP_CONNTRACK_SCTP_H */
554 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
555 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
556 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-04-30 09:14:39.000000000 +0200
558 +#ifndef _IP_CONNTRACK_TALK_H
559 +#define _IP_CONNTRACK_TALK_H
560 +/* TALK tracking. */
563 +#include <linux/in.h>
564 +#include <linux/netfilter_ipv4/lockhelp.h>
566 +/* Protects talk part of conntracks */
567 +DECLARE_LOCK_EXTERN(ip_talk_lock);
571 +#define TALK_PORT 517
572 +#define NTALK_PORT 518
574 +/* talk structures and constants from <protocols/talkd.h> */
577 + * 4.3BSD struct sockaddr
580 + u_int16_t ta_family;
583 + u_int32_t ta_junk1;
584 + u_int32_t ta_junk2;
587 +#define TALK_OLD_NSIZE 9
588 +#define TALK_NSIZE 12
589 +#define TALK_TTY_NSIZE 16
592 + * Client->server request message formats.
595 + u_char type; /* request type, see below */
596 + char l_name[TALK_OLD_NSIZE];/* caller's name */
597 + char r_name[TALK_OLD_NSIZE];/* callee's name */
599 + u_int32_t id_num; /* message id */
600 + int32_t pid; /* caller's process id */
601 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
602 + struct talk_addr addr; /* old (4.3) style */
603 + struct talk_addr ctl_addr; /* old (4.3) style */
607 + u_char vers; /* protocol version */
608 + u_char type; /* request type, see below */
609 + u_char answer; /* not used */
611 + u_int32_t id_num; /* message id */
612 + struct talk_addr addr; /* old (4.3) style */
613 + struct talk_addr ctl_addr; /* old (4.3) style */
614 + int32_t pid; /* caller's process id */
615 + char l_name[TALK_NSIZE];/* caller's name */
616 + char r_name[TALK_NSIZE];/* callee's name */
617 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
621 + u_char vers; /* talk protocol version */
622 + u_char type; /* request type */
623 + u_char answer; /* */
624 + u_char extended; /* !0 if additional parts */
625 + u_int32_t id_num; /* message id number (dels) */
626 + struct talk_addr addr; /* target address */
627 + struct talk_addr ctl_addr; /* reply to address */
628 + int32_t pid; /* caller's process id */
629 + char l_name[TALK_NSIZE]; /* caller's name */
630 + char r_name[TALK_NSIZE]; /* callee's name */
631 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
635 + * Server->client response message formats.
637 +struct talk_response {
638 + u_char type; /* type of request message, see below */
639 + u_char answer; /* response to request message, see below */
641 + u_int32_t id_num; /* message id */
642 + struct talk_addr addr; /* address for establishing conversation */
645 +struct ntalk_response {
646 + u_char vers; /* protocol version */
647 + u_char type; /* type of request message, see below */
648 + u_char answer; /* response to request message, see below */
650 + u_int32_t id_num; /* message id */
651 + struct talk_addr addr; /* address for establishing conversation */
654 +struct ntalk2_response {
655 + u_char vers; /* protocol version */
656 + u_char type; /* type of request message */
657 + u_char answer; /* response to request */
658 + u_char rvers; /* Version of answering vers*/
659 + u_int32_t id_num; /* message id number */
660 + struct talk_addr addr; /* address for connection */
661 + /* This is at the end to compatiblize this with NTALK version. */
662 + char r_name[TALK_NSIZE]; /* callee's name */
665 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
666 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
667 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
669 +#define TALK_VERSION 0 /* protocol versions */
670 +#define NTALK_VERSION 1
671 +#define NTALK2_VERSION 2
673 +/* message type values */
674 +#define LEAVE_INVITE 0 /* leave invitation with server */
675 +#define LOOK_UP 1 /* check for invitation by callee */
676 +#define DELETE 2 /* delete invitation by caller */
677 +#define ANNOUNCE 3 /* announce invitation by caller */
679 +#define REPLY_QUERY 4 /* request reply data from local daemon */
682 +#define SUCCESS 0 /* operation completed properly */
683 +#define NOT_HERE 1 /* callee not logged in */
684 +#define FAILED 2 /* operation failed for unexplained reason */
685 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
686 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
687 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
688 +#define BADVERSION 6 /* request has invalid protocol version */
689 +#define BADADDR 7 /* request has invalid addr value */
690 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
692 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
693 +#define TRY_HERE 10 /* Not on this machine, try this */
694 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
695 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
697 +/* We don't really need much for talk */
698 +struct ip_ct_talk_expect
700 + /* Port that was to be used */
704 +/* This structure exists only once per master */
705 +struct ip_ct_talk_master
709 +#endif /* _IP_CONNTRACK_TALK_H */
710 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
711 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-28 03:36:22.000000000 +0200
712 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-30 09:14:08.000000000 +0200
722 /* The manipulable part of the tuple. */
733 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h
734 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
735 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h 2004-04-30 09:10:40.000000000 +0200
740 +/***************************************************************************/
741 +/* This program is free software; you can redistribute it and/or modify */
742 +/* it under the terms of the GNU General Public License as published by */
743 +/* the Free Software Foundation; either version 2 of the License, or */
744 +/* (at your option) any later version. */
746 +/* This program is distributed in the hope that it will be useful, */
747 +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
748 +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
749 +/* GNU General Public License for more details. */
751 +/* You should have received a copy of the GNU General Public License */
752 +/* along with this program; if not, write to the Free Software */
753 +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
754 +/***************************************************************************/
756 +/* A sockopt of such quality has hardly ever been seen before on the open
757 + * market! This little beauty, hardly ever used: above 64, so it's
758 + * traditionally used for firewalling, not touched (even once!) by the
759 + * 2.0, 2.2 and 2.4 kernels!
761 + * Comes with its own certificate of authenticity, valid anywhere in the
766 +#define SO_IP_POOL 81
768 +typedef int ip_pool_t; /* pool index */
769 +#define IP_POOL_NONE ((ip_pool_t)-1)
771 +struct ip_pool_request {
778 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
780 +#define IP_POOL_BAD001 0x00000010
782 +#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
783 +#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
784 +#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
785 +#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
786 +#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
787 +#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
788 +#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
789 +#define IP_POOL_USAGE 0x00000018 /* result in addr */
790 +#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
794 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
795 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
796 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
800 +#endif /*_IP_POOL_H*/
801 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h
802 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h 2004-04-28 03:35:48.000000000 +0200
803 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h 2004-04-30 09:11:53.000000000 +0200
806 unsigned int comefrom;
808 + /* Name of the chain */
811 + /* Rule number in the chain. */
814 /* Packet and byte counters. */
815 struct ipt_counters counters;
817 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
818 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
819 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-30 09:11:35.000000000 +0200
821 +#ifndef _IPT_CONNMARK_H_target
822 +#define _IPT_CONNMARK_H_target
824 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
825 + * by Henrik Nordstrom <hno@marasystems.com>
827 + * This program is free software; you can redistribute it and/or modify
828 + * it under the terms of the GNU General Public License as published by
829 + * the Free Software Foundation; either version 2 of the License, or
830 + * (at your option) any later version.
834 + IPT_CONNMARK_SET = 0,
836 + IPT_CONNMARK_RESTORE
839 +struct ipt_connmark_target_info {
840 + unsigned long mark;
841 + unsigned long mask;
845 +#endif /*_IPT_CONNMARK_H_target*/
846 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
847 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
848 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-30 09:11:38.000000000 +0200
850 +#ifndef _IPT_IPMARK_H_target
851 +#define _IPT_IPMARK_H_target
853 +struct ipt_ipmark_target_info {
854 + unsigned long andmask;
855 + unsigned long ormask;
859 +#define IPT_IPMARK_SRC 0
860 +#define IPT_IPMARK_DST 1
862 +#endif /*_IPT_IPMARK_H_target*/
863 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
864 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
865 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-04-30 09:10:09.000000000 +0200
867 +#ifndef _IPT_FWMON_H
868 +#define _IPT_FWMON_H
870 +/* Bitmask macros */
871 +#define MASK(x,y) (x & y)
872 +#define MASK_SET(x,y) x |= y
873 +#define MASK_UNSET(x,y) x &= ~y
875 +#define USE_MARK 0x00000001
876 +#define USE_DROP 0x00000002
877 +#define USE_SIZE 0x00000004
881 + unsigned int flags;
890 + char iface[IFNAMSIZ];
893 +#endif /*_IPT_FWMON_H*/
894 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
895 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
896 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h 2004-04-30 09:10:15.000000000 +0200
898 +/* TTL modification module for IP tables
899 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
910 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
912 +struct ipt_TTL_info {
919 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
920 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
921 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-30 09:11:56.000000000 +0200
926 +struct ipt_XOR_info {
928 + u_int8_t block_size;
931 +#endif /* _IPT_XOR_H */
932 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
933 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
934 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-30 09:11:57.000000000 +0200
936 +#ifndef _IPT_ADDRTYPE_H
937 +#define _IPT_ADDRTYPE_H
939 +struct ipt_addrtype_info {
940 + u_int16_t source; /* source-type mask */
941 + u_int16_t dest; /* dest-type mask */
947 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
948 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
949 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-04-30 09:10:17.000000000 +0200
951 +#ifndef _IPT_CONNLIMIT_H
952 +#define _IPT_CONNLIMIT_H
954 +struct ipt_connlimit_data;
956 +struct ipt_connlimit_info {
960 + struct ipt_connlimit_data *data;
962 +#endif /* _IPT_CONNLIMIT_H */
963 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
964 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
965 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-30 09:11:35.000000000 +0200
967 +#ifndef _IPT_CONNMARK_H
968 +#define _IPT_CONNMARK_H
970 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
971 + * by Henrik Nordstrom <hno@marasystems.com>
973 + * This program is free software; you can redistribute it and/or modify
974 + * it under the terms of the GNU General Public License as published by
975 + * the Free Software Foundation; either version 2 of the License, or
976 + * (at your option) any later version.
979 +struct ipt_connmark_info {
980 + unsigned long mark, mask;
984 +#endif /*_IPT_CONNMARK_H*/
985 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
986 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
987 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-04-30 09:10:21.000000000 +0200
989 +#ifndef _IPT_DSTLIMIT_H
990 +#define _IPT_DSTLIMIT_H
992 +/* timings are in milliseconds. */
993 +#define IPT_DSTLIMIT_SCALE 10000
994 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
995 + seconds, or one every 59 hours. */
997 +/* details of this structure hidden by the implementation */
998 +struct ipt_dstlimit_htable;
1000 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
1001 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
1002 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
1004 +struct dstlimit_cfg {
1005 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1006 + u_int32_t avg; /* Average secs between packets * scale */
1007 + u_int32_t burst; /* Period multiplier for upper limit. */
1009 + /* user specified */
1010 + u_int32_t size; /* how many buckets */
1011 + u_int32_t max; /* max number of entries */
1012 + u_int32_t gc_interval; /* gc interval */
1013 + u_int32_t expire; /* when do entries expire? */
1016 +struct ipt_dstlimit_info {
1017 + char name [IFNAMSIZ]; /* name */
1018 + struct dstlimit_cfg cfg;
1019 + struct ipt_dstlimit_htable *hinfo;
1021 + /* Used internally by the kernel */
1024 + struct ipt_dstlimit_info *master;
1027 +#endif /*_IPT_DSTLIMIT_H*/
1028 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
1029 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1030 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-04-30 09:10:22.000000000 +0200
1032 +#ifndef _IPT_FUZZY_H
1033 +#define _IPT_FUZZY_H
1035 +#include <linux/param.h>
1036 +#include <linux/types.h>
1038 +#define MAXFUZZYRATE 10000000
1039 +#define MINFUZZYRATE 3
1041 +struct ipt_fuzzy_info {
1042 + u_int32_t minimum_rate;
1043 + u_int32_t maximum_rate;
1044 + u_int32_t packets_total;
1045 + u_int32_t bytes_total;
1046 + u_int32_t previous_time;
1047 + u_int32_t present_time;
1048 + u_int32_t mean_rate;
1049 + u_int8_t acceptance_rate;
1052 +#endif /*_IPT_FUZZY_H*/
1053 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
1054 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1055 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-04-30 09:10:27.000000000 +0200
1057 +#ifndef __ipt_ipv4options_h_included__
1058 +#define __ipt_ipv4options_h_included__
1060 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1061 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1062 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1063 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1064 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1065 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1066 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1067 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1068 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1069 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1070 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1072 +struct ipt_ipv4options_info {
1073 + u_int16_t options;
1077 +#endif /* __ipt_ipv4options_h_included__ */
1078 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h
1079 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1080 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h 2004-04-30 09:10:30.000000000 +0200
1082 +#ifndef _IPT_MPORT_H
1083 +#define _IPT_MPORT_H
1084 +#include <linux/netfilter_ipv4/ip_tables.h>
1086 +#define IPT_MPORT_SOURCE (1<<0)
1087 +#define IPT_MPORT_DESTINATION (1<<1)
1088 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1090 +#define IPT_MULTI_PORTS 15
1092 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1093 +/* every entry in ports[] except for the last one has one bit in pflags
1094 + * associated with it. If this bit is set, the port is the first port of
1095 + * a portrange, with the next entry being the last.
1096 + * End of list is marked with pflags bit set and port=65535.
1097 + * If 14 ports are used (last one does not have a pflag), the last port
1098 + * is repeated to fill the last entry in ports[] */
1101 + u_int8_t flags:2; /* Type of comparison */
1102 + u_int16_t pflags:14; /* Port flags */
1103 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1105 +#endif /*_IPT_MPORT_H*/
1106 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h
1107 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1108 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h 2004-04-30 09:10:36.000000000 +0200
1113 +#include <linux/param.h>
1114 +#include <linux/types.h>
1116 +#ifndef IPT_NTH_NUM_COUNTERS
1117 +#define IPT_NTH_NUM_COUNTERS 16
1120 +struct ipt_nth_info {
1128 +#endif /*_IPT_NTH_H*/
1129 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h
1130 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1131 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h 2004-04-30 09:10:38.000000000 +0200
1136 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1139 + * This program is free software; you can redistribute it and/or modify
1140 + * it under the terms of the GNU General Public License as published by
1141 + * the Free Software Foundation; either version 2 of the License, or
1142 + * (at your option) any later version.
1144 + * This program is distributed in the hope that it will be useful,
1145 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1146 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1147 + * GNU General Public License for more details.
1149 + * You should have received a copy of the GNU General Public License
1150 + * along with this program; if not, write to the Free Software
1151 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1157 +#define MAXGENRELEN 32
1158 +#define MAXDETLEN 64
1160 +#define IPT_OSF_GENRE 1
1161 +#define IPT_OSF_SMART 2
1162 +#define IPT_OSF_LOG 4
1163 +#define IPT_OSF_NETLINK 8
1165 +#define IPT_OSF_LOGLEVEL_ALL 0
1166 +#define IPT_OSF_LOGLEVEL_FIRST 1
1168 +#include <linux/list.h>
1171 +#include <netinet/ip.h>
1172 +#include <netinet/tcp.h>
1176 + struct list_head *prev, *next;
1180 +struct ipt_osf_info
1182 + char genre[MAXGENRELEN];
1184 + unsigned long flags;
1186 + int invert; /* UNSUPPORTED */
1192 + unsigned long val;
1195 +/* This struct represents IANA options
1196 + * http://www.iana.org/assignments/tcp-parameters
1200 + unsigned char kind;
1201 + unsigned char length;
1207 + struct list_head flist;
1208 + struct osf_wc wss;
1209 + unsigned char ttl;
1212 + unsigned char genre[MAXGENRELEN];
1213 + unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
1215 + /* Not needed, but for consistency with original table from Michal Zalewski */
1216 + unsigned char details[MAXDETLEN];
1219 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1223 +struct ipt_osf_nlmsg
1225 + struct osf_finger f;
1227 + struct tcphdr tcp;
1232 +/* Defines for IANA option kinds */
1234 +#define OSFOPT_EOL 0 /* End of options */
1235 +#define OSFOPT_NOP 1 /* NOP */
1236 +#define OSFOPT_MSS 2 /* Maximum segment size */
1237 +#define OSFOPT_WSO 3 /* Window scale option */
1238 +#define OSFOPT_SACKP 4 /* SACK permitted */
1239 +#define OSFOPT_SACK 5 /* SACK */
1240 +#define OSFOPT_ECHO 6
1241 +#define OSFOPT_ECHOREPLY 7
1242 +#define OSFOPT_TS 8 /* Timestamp option */
1243 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1244 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1245 +/* Others are not used in current OSF */
1247 +static struct osf_opt IANA_opts[] =
1254 + {5, 1 ,}, /* SACK length is not defined */
1260 + {11, 1,}, /* CC: Suppose 1 */
1261 + {12, 1,}, /* the same */
1262 + {13, 1,}, /* and here too */
1264 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1278 +#endif /* __KERNEL__ */
1280 +#endif /* _IPT_OSF_H */
1281 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h
1282 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
1283 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-30 09:13:22.000000000 +0200
1285 +#ifndef _IPT_POLICY_H
1286 +#define _IPT_POLICY_H
1288 +#define POLICY_MAX_ELEM 4
1290 +enum ipt_policy_flags
1292 + POLICY_MATCH_IN = 0x1,
1293 + POLICY_MATCH_OUT = 0x2,
1294 + POLICY_MATCH_NONE = 0x4,
1295 + POLICY_MATCH_STRICT = 0x8,
1298 +enum ipt_policy_modes
1300 + POLICY_MODE_TRANSPORT,
1301 + POLICY_MODE_TUNNEL
1304 +struct ipt_policy_spec
1314 +struct ipt_policy_elem
1325 + struct ipt_policy_spec match;
1326 + struct ipt_policy_spec invert;
1329 +struct ipt_policy_info
1331 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1336 +#endif /* _IPT_POLICY_H */
1337 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h
1338 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1339 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h 2004-04-30 09:10:40.000000000 +0200
1341 +#ifndef _IPT_POOL_H
1342 +#define _IPT_POOL_H
1344 +#include <linux/netfilter_ipv4/ip_pool.h>
1346 +#define IPT_POOL_INV_SRC 0x00000001
1347 +#define IPT_POOL_INV_DST 0x00000002
1348 +#define IPT_POOL_DEL_SRC 0x00000004
1349 +#define IPT_POOL_DEL_DST 0x00000008
1350 +#define IPT_POOL_INV_MOD_SRC 0x00000010
1351 +#define IPT_POOL_INV_MOD_DST 0x00000020
1352 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1353 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1354 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
1355 +#define IPT_POOL_MOD_DST_DROP 0x00000200
1358 +struct ipt_pool_info
1365 +#endif /*_IPT_POOL_H*/
1366 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h
1367 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1368 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h 2004-04-30 09:10:44.000000000 +0200
1373 +#include <linux/param.h>
1374 +#include <linux/types.h>
1377 + * High port numbers have a lower weight to reduce the frequency of false
1378 + * positives, such as from passive mode FTP transfers.
1380 +#define PORT_WEIGHT_PRIV 3
1381 +#define PORT_WEIGHT_HIGH 1
1384 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1385 + * from the same source, with no longer than DELAY ticks between ports.
1387 +#define SCAN_MIN_COUNT 7
1388 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1389 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1390 +#define SCAN_DELAY_THRESHOLD (HZ * 3)
1393 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1394 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1395 + * HASH_MAX source addresses per the same hash value.
1397 +#define LIST_SIZE 0x100
1399 +#define HASH_SIZE (1 << HASH_LOG)
1400 +#define HASH_MAX 0x10
1402 +struct ipt_psd_info {
1403 + unsigned int weight_threshold;
1404 + unsigned int delay_threshold;
1405 + unsigned short lo_ports_weight;
1406 + unsigned short hi_ports_weight;
1409 +#endif /*_IPT_PSD_H*/
1410 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h
1411 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1412 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h 2004-04-30 09:10:45.000000000 +0200
1414 +#ifndef _IPT_QUOTA_H
1415 +#define _IPT_QUOTA_H
1417 +/* print debug info in both kernel/netfilter module & iptable library */
1418 +//#define DEBUG_IPT_QUOTA
1420 +struct ipt_quota_info {
1424 +#endif /*_IPT_QUOTA_H*/
1425 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h
1426 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1427 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h 2004-04-30 09:10:46.000000000 +0200
1429 +#ifndef _IPT_RAND_H
1430 +#define _IPT_RAND_H
1432 +#include <linux/param.h>
1433 +#include <linux/types.h>
1435 +struct ipt_rand_info {
1439 +#endif /*_IPT_RAND_H*/
1440 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h
1441 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1442 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h 2004-04-30 09:10:50.000000000 +0200
1444 +#ifndef _IPT_REALM_H
1445 +#define _IPT_REALM_H
1447 +struct ipt_realm_info {
1452 +#endif /*_IPT_REALM_H*/
1453 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h
1454 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1455 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h 2004-04-30 09:10:52.000000000 +0200
1457 +#ifndef _IPT_SCTP_H_
1458 +#define _IPT_SCTP_H_
1460 +#define IPT_SCTP_SRC_PORTS 0x01
1461 +#define IPT_SCTP_DEST_PORTS 0x02
1462 +#define IPT_SCTP_CHUNK_TYPES 0x04
1464 +#define IPT_SCTP_VALID_FLAGS 0x07
1466 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1469 +struct ipt_sctp_flag_info {
1470 + u_int8_t chunktype;
1472 + u_int8_t flag_mask;
1475 +#define IPT_NUM_SCTP_FLAGS 4
1477 +struct ipt_sctp_info {
1478 + u_int16_t dpts[2]; /* Min, Max */
1479 + u_int16_t spts[2]; /* Min, Max */
1481 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
1483 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
1484 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
1485 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
1487 + u_int32_t chunk_match_type;
1488 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1492 + u_int32_t invflags;
1495 +#define bytes(type) (sizeof(type) * 8)
1497 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
1499 + chunkmap[type / bytes(u_int32_t)] |= \
1500 + 1 << (type % bytes(u_int32_t)); \
1503 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
1505 + chunkmap[type / bytes(u_int32_t)] &= \
1506 + ~(1 << (type % bytes(u_int32_t))); \
1509 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
1511 + (chunkmap[type / bytes (u_int32_t)] & \
1512 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
1515 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
1518 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1519 + chunkmap[i] = 0; \
1522 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
1525 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1526 + chunkmap[i] = ~0; \
1529 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
1532 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1533 + destmap[i] = srcmap[i]; \
1536 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
1540 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1541 + if (chunkmap[i]) { \
1549 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
1553 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1554 + if (chunkmap[i] != ~0) { \
1562 +#endif /* _IPT_SCTP_H_ */
1564 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h
1565 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1566 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-04-30 09:14:35.000000000 +0200
1568 +#ifndef _IPT_STRING_H
1569 +#define _IPT_STRING_H
1571 +/* *** PERFORMANCE TWEAK ***
1572 + * Packet size and search string threshold,
1573 + * above which sublinear searches is used. */
1574 +#define IPT_STRING_HAYSTACK_THRESH 100
1575 +#define IPT_STRING_NEEDLE_THRESH 20
1577 +#define BM_MAX_NLEN 256
1578 +#define BM_MAX_HLEN 1024
1580 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1582 +struct ipt_string_info {
1583 + char string[BM_MAX_NLEN];
1588 +#endif /* _IPT_STRING_H */
1589 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h
1590 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1591 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h 2004-04-30 09:10:54.000000000 +0200
1593 +#ifndef __ipt_time_h_included__
1594 +#define __ipt_time_h_included__
1597 +struct ipt_time_info {
1598 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
1599 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
1600 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
1601 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
1605 +#endif /* __ipt_time_h_included__ */
1606 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h
1607 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
1608 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h 2004-04-30 09:10:55.000000000 +0200
1612 +#include <linux/netfilter_ipv4/ip_tables.h>
1622 +struct ipt_u32_location_element
1627 +struct ipt_u32_value_element
1632 +/* *** any way to allow for an arbitrary number of elements?
1633 + for now I settle for a limit of 10 of each */
1634 +#define U32MAXSIZE 10
1635 +struct ipt_u32_test
1638 + struct ipt_u32_location_element location[U32MAXSIZE+1];
1640 + struct ipt_u32_value_element value[U32MAXSIZE+1];
1646 + struct ipt_u32_test tests[U32MAXSIZE+1];
1649 +#endif /*_IPT_U32_H*/
1650 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
1651 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h 2004-04-28 03:36:31.000000000 +0200
1652 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h 2004-04-30 09:12:40.000000000 +0200
1655 #include <linux/config.h>
1656 #include <linux/netfilter.h>
1657 +#include <linux/netdevice.h>
1658 +#include <net/protocol.h>
1660 /* IP Cache bits. */
1661 /* Src IP address. */
1663 Returns true or false. */
1664 extern int skb_ip_make_writable(struct sk_buff **pskb,
1665 unsigned int writable_len);
1667 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1668 +#include <net/route.h>
1669 +#include <net/xfrm.h>
1671 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1673 + return !skb->sp || skb->sp->decap_done;
1677 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1679 + return skb->sp && !skb->sp->decap_done
1680 + && (!ipprot || !ipprot->xfrm_prot);
1683 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1685 + return skb->sp && !skb->sp->decap_done
1686 + && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1689 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1690 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1691 +#else /* CONFIG_XFRM */
1692 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1698 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1703 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1708 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1713 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1717 +#endif /* CONFIG_XFRM */
1718 #endif /*__KERNEL__*/
1720 #endif /*__LINUX_IP_NETFILTER_H*/
1721 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1722 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-28 03:36:37.000000000 +0200
1723 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-30 09:11:53.000000000 +0200
1724 @@ -140,6 +140,12 @@
1726 unsigned int comefrom;
1728 + /* Name of the chain */
1731 + /* Rule number in the chain. */
1732 + u_int32_t rulenum;
1734 /* Packet and byte counters. */
1735 struct ip6t_counters counters;
1737 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
1738 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
1739 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h 2004-04-30 09:10:04.000000000 +0200
1741 +/* Hop Limit modification module for ip6tables
1742 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1743 + * Based on HW's TTL module */
1754 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
1756 +struct ip6t_HL_info {
1758 + u_int8_t hop_limit;
1763 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1764 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-04-28 03:34:59.000000000 +0200
1765 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-04-30 09:10:13.000000000 +0200
1767 #define _IP6T_REJECT_H
1769 enum ip6t_reject_with {
1770 - IP6T_ICMP_NET_UNREACHABLE,
1771 - IP6T_ICMP_HOST_UNREACHABLE,
1772 - IP6T_ICMP_PROT_UNREACHABLE,
1773 - IP6T_ICMP_PORT_UNREACHABLE,
1774 - IP6T_ICMP_ECHOREPLY
1775 + IP6T_ICMP6_NO_ROUTE,
1776 + IP6T_ICMP6_ADM_PROHIBITED,
1777 + IP6T_ICMP6_NOT_NEIGHBOUR,
1778 + IP6T_ICMP6_ADDR_UNREACH,
1779 + IP6T_ICMP6_PORT_UNREACH,
1780 + IP6T_ICMP6_ECHOREPLY,
1784 struct ip6t_reject_info {
1785 enum ip6t_reject_with with; /* reject type */
1788 -#endif /*_IPT_REJECT_H*/
1789 +#endif /*_IP6T_REJECT_H*/
1790 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1791 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1792 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-04-30 09:10:22.000000000 +0200
1794 +#ifndef _IP6T_FUZZY_H
1795 +#define _IP6T_FUZZY_H
1797 +#include <linux/param.h>
1798 +#include <linux/types.h>
1800 +#define MAXFUZZYRATE 10000000
1801 +#define MINFUZZYRATE 3
1803 +struct ip6t_fuzzy_info {
1804 + u_int32_t minimum_rate;
1805 + u_int32_t maximum_rate;
1806 + u_int32_t packets_total;
1807 + u_int32_t bytes_total;
1808 + u_int32_t previous_time;
1809 + u_int32_t present_time;
1810 + u_int32_t mean_rate;
1811 + u_int8_t acceptance_rate;
1814 +#endif /*_IP6T_FUZZY_H*/
1815 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
1816 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1817 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h 2004-04-30 09:10:36.000000000 +0200
1819 +#ifndef _IP6T_NTH_H
1820 +#define _IP6T_NTH_H
1822 +#include <linux/param.h>
1823 +#include <linux/types.h>
1825 +#ifndef IP6T_NTH_NUM_COUNTERS
1826 +#define IP6T_NTH_NUM_COUNTERS 16
1829 +struct ip6t_nth_info {
1837 +#endif /*_IP6T_NTH_H*/
1838 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1839 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-28 03:36:03.000000000 +0200
1840 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-30 09:13:19.000000000 +0200
1842 #define IP6T_OWNER_GID 0x02
1843 #define IP6T_OWNER_PID 0x04
1844 #define IP6T_OWNER_SID 0x08
1845 +#define IP6T_OWNER_COMM 0x10
1847 struct ip6t_owner_info {
1853 u_int8_t match, invert; /* flags */
1856 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1857 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1858 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h 2004-04-30 09:13:22.000000000 +0200
1860 +#ifndef _IP6T_POLICY_H
\r
1861 +#define _IP6T_POLICY_H
\r
1863 +#define POLICY_MAX_ELEM 4
\r
1865 +enum ip6t_policy_flags
\r
1867 + POLICY_MATCH_IN = 0x1,
\r
1868 + POLICY_MATCH_OUT = 0x2,
\r
1869 + POLICY_MATCH_NONE = 0x4,
\r
1870 + POLICY_MATCH_STRICT = 0x8,
\r
1873 +enum ip6t_policy_modes
\r
1875 + POLICY_MODE_TRANSPORT,
\r
1876 + POLICY_MODE_TUNNEL
\r
1879 +struct ip6t_policy_spec
\r
1881 + u_int8_t saddr:1,
\r
1889 +struct ip6t_policy_elem
\r
1891 + struct in6_addr saddr;
\r
1892 + struct in6_addr smask;
\r
1893 + struct in6_addr daddr;
\r
1894 + struct in6_addr dmask;
\r
1896 + u_int32_t reqid;
\r
1900 + struct ip6t_policy_spec match;
\r
1901 + struct ip6t_policy_spec invert;
\r
1904 +struct ip6t_policy_info
\r
1906 + struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
\r
1907 + u_int16_t flags;
\r
1911 +#endif /* _IP6T_POLICY_H */
\r
1912 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h
1913 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
1914 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h 2004-04-30 09:10:46.000000000 +0200
1916 +#ifndef _IP6T_RAND_H
1917 +#define _IP6T_RAND_H
1919 +#include <linux/param.h>
1920 +#include <linux/types.h>
1922 +struct ip6t_rand_info {
1926 +#endif /*_IP6T_RAND_H*/
1927 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1928 --- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1929 +++ linux-2.6.6-rc3/include/linux/netfilter_mime.h 2004-04-30 09:14:05.000000000 +0200
1932 + * MIME functions for netfilter modules. This file provides implementations
1933 + * for basic MIME parsing. MIME headers are used in many protocols, such as
1934 + * HTTP, RTSP, SIP, etc.
1936 + * gcc will warn for defined but unused functions, so we only include the
1937 + * functions requested. The following macros are used:
1938 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1940 +#ifndef _NETFILTER_MIME_H
1941 +#define _NETFILTER_MIME_H
1943 +/* Only include these functions for kernel code. */
1946 +#include <linux/ctype.h>
1949 + * Given a buffer and length, advance to the next line and mark the current
1950 + * line. If the current line is empty, *plinelen will be set to zero. If
1951 + * not, it will be set to the actual line length (including CRLF).
1953 + * 'line' in this context means logical line (includes LWS continuations).
1954 + * Returns 1 on success, 0 on failure.
1956 +#ifdef NF_NEED_MIME_NEXTLINE
1958 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1962 + int is_first_line = 1;
1971 + while (p[off] != '\n')
1982 + /* if we saw a crlf, physlen needs adjusted */
1983 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1988 + /* advance past the newline */
1991 + /* check for an empty line */
1997 + /* check for colon on the first physical line */
1998 + if (is_first_line)
2000 + is_first_line = 0;
2001 + if (memchr(p+(*poff), ':', physlen) == NULL)
2007 + while (p[off] == ' ' || p[off] == '\t');
2009 + *plineoff = *poff;
2010 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
2015 +#endif /* NF_NEED_MIME_NEXTLINE */
2017 +#endif /* __KERNEL__ */
2019 +#endif /* _NETFILTER_MIME_H */
2020 diff -Nur linux-2.6.6-rc3.org/include/linux/skbuff.h linux-2.6.6-rc3/include/linux/skbuff.h
2021 --- linux-2.6.6-rc3.org/include/linux/skbuff.h 2004-04-30 08:34:16.000000000 +0200
2022 +++ linux-2.6.6-rc3/include/linux/skbuff.h 2004-04-30 09:09:38.000000000 +0200
2023 @@ -1049,6 +1049,14 @@
2025 atomic_inc(&nfct->master->use);
2027 +static inline void nf_reset(struct sk_buff *skb)
2029 + nf_conntrack_put(skb->nfct);
2031 +#ifdef CONFIG_NETFILTER_DEBUG
2032 + skb->nf_debug = 0;
2036 #ifdef CONFIG_BRIDGE_NETFILTER
2037 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2038 @@ -1061,9 +1069,10 @@
2040 atomic_inc(&nf_bridge->use);
2045 +#endif /* CONFIG_BRIDGE_NETFILTER */
2046 +#else /* CONFIG_NETFILTER */
2047 +static inline void nf_reset(struct sk_buff *skb) {}
2048 +#endif /* CONFIG_NETFILTER */
2050 #endif /* __KERNEL__ */
2051 #endif /* _LINUX_SKBUFF_H */
2052 diff -Nur linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
2053 --- linux-2.6.6-rc3.org/include/net/ip.h 2004-04-28 03:36:16.000000000 +0200
2054 +++ linux-2.6.6-rc3/include/net/ip.h 2004-04-30 09:12:39.000000000 +0200
2056 #include <linux/netdevice.h>
2057 #include <linux/inetdevice.h>
2058 #include <linux/in_route.h>
2059 +#include <linux/netfilter.h>
2060 +#include <linux/netfilter_ipv4.h>
2061 #include <net/route.h>
2062 #include <net/arp.h>
2065 #define IPSKB_TRANSLATED 2
2066 #define IPSKB_FORWARDED 4
2067 #define IPSKB_XFRM_TUNNEL_SIZE 8
2068 +#define IPSKB_XFRM_TRANSFORMED 16
2072 @@ -212,6 +215,12 @@
2073 __ip_select_ident(iph, dst, more);
2076 +extern inline int ip_dst_output(struct sk_buff *skb)
2078 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2079 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2083 * Map a multicast IP onto multicast MAC for type ethernet.
2085 diff -Nur linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
2086 --- linux-2.6.6-rc3.org/include/net/protocol.h 2004-04-28 03:35:44.000000000 +0200
2087 +++ linux-2.6.6-rc3/include/net/protocol.h 2004-04-30 09:12:40.000000000 +0200
2089 int (*handler)(struct sk_buff *skb);
2090 void (*err_handler)(struct sk_buff *skb, u32 info);
2095 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2096 diff -Nur linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
2097 --- linux-2.6.6-rc3.org/include/net/tcp.h 2004-04-30 08:34:16.000000000 +0200
2098 +++ linux-2.6.6-rc3/include/net/tcp.h 2004-04-30 09:13:14.000000000 +0200
2100 extern void tcp_bucket_unlock(struct sock *sk);
2101 extern int tcp_port_rover;
2102 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2103 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2105 /* These are AF independent. */
2106 static __inline__ int tcp_bhashfn(__u16 lport)
2107 diff -Nur linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
2108 --- linux-2.6.6-rc3.org/include/net/udp.h 2004-04-28 03:36:29.000000000 +0200
2109 +++ linux-2.6.6-rc3/include/net/udp.h 2004-04-30 09:13:14.000000000 +0200
2111 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2112 extern int udp_disconnect(struct sock *sk, int flags);
2114 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2116 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2117 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
2118 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
2119 diff -Nur linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
2120 --- linux-2.6.6-rc3.org/include/net/xfrm.h 2004-04-28 03:36:31.000000000 +0200
2121 +++ linux-2.6.6-rc3/include/net/xfrm.h 2004-04-30 09:12:40.000000000 +0200
2126 +#ifdef CONFIG_NETFILTER
2129 struct sec_decap_state x[XFRM_MAX_DEPTH];
2132 diff -Nur linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
2133 --- linux-2.6.6-rc3.org/net/core/netfilter.c 2004-04-28 03:35:46.000000000 +0200
2134 +++ linux-2.6.6-rc3/net/core/netfilter.c 2004-04-30 09:12:42.000000000 +0200
2136 #include <linux/icmp.h>
2137 #include <net/sock.h>
2138 #include <net/route.h>
2139 +#include <net/xfrm.h>
2140 +#include <net/ip.h>
2141 #include <linux/ip.h>
2143 /* In this code, we can be waiting indefinitely for userspace to
2145 #ifdef CONFIG_IP_ROUTE_FWMARK
2146 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2148 - fl.proto = iph->protocol;
2149 if (ip_route_output_key(&rt, &fl) != 0)
2152 @@ -665,6 +666,20 @@
2153 if ((*pskb)->dst->error)
2157 + if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2158 + struct xfrm_policy_afinfo *afinfo;
2160 + afinfo = xfrm_policy_get_afinfo(AF_INET);
2161 + if (afinfo != NULL) {
2162 + afinfo->decode_session(*pskb, &fl);
2163 + xfrm_policy_put_afinfo(afinfo);
2164 + if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2170 /* Change in oif may mean change in hh_len. */
2171 hh_len = (*pskb)->dst->dev->hard_header_len;
2172 if (skb_headroom(*pskb) < hh_len) {
2173 @@ -682,6 +697,71 @@
2178 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2180 + skb->sp->decap_done = 1;
2181 + dst_release(skb->dst);
2184 + return netif_rx(skb);
2187 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2189 + __skb_push(skb, skb->data - skb->nh.raw);
2190 + /* Fix header len and checksum if last xfrm was transport mode */
2191 + if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2192 + skb->nh.iph->tot_len = htons(skb->len);
2193 + ip_send_check(skb->nh.iph);
2195 + return nf_rcv_postxfrm_nonlocal(skb);
2198 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2199 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2200 +#include <linux/netfilter_ipv4/ip_nat.h>
2202 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2204 + struct ip_conntrack *ct;
2205 + struct ip_conntrack_tuple *t;
2206 + struct ip_nat_info_manip *m;
2209 + if (skb->nfct == NULL)
2211 + ct = (struct ip_conntrack *)skb->nfct->master;
2213 + for (i = 0; i < ct->nat.info.num_manips; i++) {
2214 + m = &ct->nat.info.manips[i];
2215 + t = &ct->tuplehash[m->direction].tuple;
2217 + switch (m->hooknum) {
2218 + case NF_IP_PRE_ROUTING:
2219 + if (m->maniptype != IP_NAT_MANIP_DST)
2221 + fl->fl4_dst = t->dst.ip;
2222 + if (t->dst.protonum == IPPROTO_TCP ||
2223 + t->dst.protonum == IPPROTO_UDP)
2224 + fl->fl_ip_dport = t->dst.u.tcp.port;
2226 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2227 + case NF_IP_LOCAL_IN:
2228 + if (m->maniptype != IP_NAT_MANIP_SRC)
2230 + fl->fl4_src = t->src.ip;
2231 + if (t->dst.protonum == IPPROTO_TCP ||
2232 + t->dst.protonum == IPPROTO_UDP)
2233 + fl->fl_ip_sport = t->src.u.tcp.port;
2239 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2242 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2244 struct sk_buff *nskb;
2246 EXPORT_SYMBOL(nf_unregister_hook);
2247 EXPORT_SYMBOL(nf_unregister_queue_handler);
2248 EXPORT_SYMBOL(nf_unregister_sockopt);
2249 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2250 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
2251 --- linux-2.6.6-rc3.org/net/ipv4/ah4.c 2004-04-28 03:36:34.000000000 +0200
2252 +++ linux-2.6.6-rc3/net/ipv4/ah4.c 2004-04-30 09:12:40.000000000 +0200
2254 err = -EHOSTUNREACH;
2257 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2258 return NET_XMIT_BYPASS;
2262 .handler = xfrm4_rcv,
2263 .err_handler = ah4_err,
2268 static int __init ah4_init(void)
2269 diff -Nur linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
2270 --- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
2271 +++ linux-2.6.6-rc3/net/ipv4/esp4.c 2004-04-30 09:12:40.000000000 +0200
2273 err = -EHOSTUNREACH;
2276 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2277 return NET_XMIT_BYPASS;
2281 .handler = xfrm4_rcv,
2282 .err_handler = esp4_err,
2287 static int __init esp4_init(void)
2288 diff -Nur linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
2289 --- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
2290 +++ linux-2.6.6-rc3/net/ipv4/igmp.c 2004-04-30 09:12:39.000000000 +0200
2292 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2294 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2299 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2301 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2303 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2308 static void igmp_gq_timer_expire(unsigned long data)
2309 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
2310 --- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c 2004-04-28 03:34:59.000000000 +0200
2311 +++ linux-2.6.6-rc3/net/ipv4/ip_forward.c 2004-04-30 09:12:39.000000000 +0200
2313 if (unlikely(opt->optlen))
2314 ip_forward_options(skb);
2316 - return dst_output(skb);
2317 + return ip_dst_output(skb);
2320 int ip_forward(struct sk_buff *skb)
2321 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_gre.c linux-2.6.6-rc3/net/ipv4/ip_gre.c
2322 --- linux-2.6.6-rc3.org/net/ipv4/ip_gre.c 2004-04-28 03:36:22.000000000 +0200
2323 +++ linux-2.6.6-rc3/net/ipv4/ip_gre.c 2004-04-30 09:09:38.000000000 +0200
2324 @@ -643,13 +643,7 @@
2325 skb->dev = tunnel->dev;
2326 dst_release(skb->dst);
2328 -#ifdef CONFIG_NETFILTER
2329 - nf_conntrack_put(skb->nfct);
2331 -#ifdef CONFIG_NETFILTER_DEBUG
2332 - skb->nf_debug = 0;
2336 ipgre_ecn_decapsulate(iph, skb);
2338 read_unlock(&ipgre_lock);
2339 @@ -877,13 +871,7 @@
2343 -#ifdef CONFIG_NETFILTER
2344 - nf_conntrack_put(skb->nfct);
2346 -#ifdef CONFIG_NETFILTER_DEBUG
2347 - skb->nf_debug = 0;
2353 tunnel->recursion--;
2354 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
2355 --- linux-2.6.6-rc3.org/net/ipv4/ip_input.c 2004-04-28 03:35:06.000000000 +0200
2356 +++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-30 09:12:42.000000000 +0200
2357 @@ -202,18 +202,10 @@
2359 #ifdef CONFIG_NETFILTER_DEBUG
2360 nf_debug_ip_local_deliver(skb);
2361 - skb->nf_debug = 0;
2362 #endif /*CONFIG_NETFILTER_DEBUG*/
2364 __skb_pull(skb, ihl);
2366 -#ifdef CONFIG_NETFILTER
2367 - /* Free reference early: we don't need it any more, and it may
2368 - hold ip_conntrack module loaded indefinitely. */
2369 - nf_conntrack_put(skb->nfct);
2371 -#endif /*CONFIG_NETFILTER*/
2373 /* Point into the IP datagram, just past the header. */
2374 skb->h.raw = skb->data;
2376 @@ -228,6 +220,13 @@
2378 hash = protocol & (MAX_INET_PROTOS - 1);
2379 raw_sk = sk_head(&raw_v4_htable[hash]);
2380 + ipprot = inet_protos[hash];
2381 + smp_read_barrier_depends();
2383 + if (nf_xfrm_local_done(skb, ipprot)) {
2384 + nf_rcv_postxfrm_local(skb);
2388 /* If there maybe a raw socket we must check - if not we
2390 @@ -235,14 +234,15 @@
2392 raw_v4_input(skb, skb->nh.iph, hash);
2394 - if ((ipprot = inet_protos[hash]) != NULL) {
2395 + if (ipprot != NULL) {
2398 - smp_read_barrier_depends();
2399 - if (!ipprot->no_policy &&
2400 - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2403 + if (!ipprot->no_policy) {
2404 + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2410 ret = ipprot->handler(skb);
2416 - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2417 - ip_local_deliver_finish);
2418 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2419 + ip_local_deliver_finish, nf_hook_input_cond(skb));
2422 static inline int ip_rcv_finish(struct sk_buff *skb)
2427 + if (nf_xfrm_nonlocal_done(skb))
2428 + return nf_rcv_postxfrm_nonlocal(skb);
2430 #ifdef CONFIG_NET_CLS_ROUTE
2431 if (skb->dst->tclassid) {
2432 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2437 - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2439 + return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2440 + ip_rcv_finish, nf_hook_input_cond(skb));
2443 IP_INC_STATS_BH(IpInHdrErrors);
2444 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
2445 --- linux-2.6.6-rc3.org/net/ipv4/ip_output.c 2004-04-28 03:36:55.000000000 +0200
2446 +++ linux-2.6.6-rc3/net/ipv4/ip_output.c 2004-04-30 09:12:39.000000000 +0200
2447 @@ -123,6 +123,15 @@
2451 +#ifdef CONFIG_NETFILTER
2452 +/* out-of-line copy is only required with netfilter */
2453 +int ip_dst_output(struct sk_buff *skb)
2455 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2456 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2461 * Add an ip header to a skbuff and send it out.
2466 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2471 static inline int ip_finish_output2(struct sk_buff *skb)
2473 return ip_finish_output(skb);
2476 -int ip_output(struct sk_buff *skb)
2477 +static inline int ip_output2(struct sk_buff *skb)
2479 IP_INC_STATS(IpOutRequests);
2481 @@ -294,6 +303,16 @@
2482 return ip_finish_output(skb);
2485 +int ip_output(struct sk_buff *skb)
2487 + int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2491 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2492 + skb->dst->dev, ip_output2, transformed);
2495 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2497 struct sock *sk = skb->sk;
2499 skb->priority = sk->sk_priority;
2501 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2506 IP_INC_STATS(IpOutNoRoutes);
2507 @@ -1177,7 +1196,7 @@
2509 /* Netfilter gets whole the not fragmented skb. */
2510 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2511 - skb->dst->dev, dst_output);
2512 + skb->dst->dev, ip_dst_output);
2515 err = inet->recverr ? net_xmit_errno(err) : 0;
2516 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
2517 --- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c 2004-04-28 03:36:33.000000000 +0200
2518 +++ linux-2.6.6-rc3/net/ipv4/ipcomp.c 2004-04-30 09:12:40.000000000 +0200
2520 err = -EHOSTUNREACH;
2523 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2524 err = NET_XMIT_BYPASS;
2528 .handler = xfrm4_rcv,
2529 .err_handler = ipcomp4_err,
2534 static int __init ipcomp4_init(void)
2535 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
2536 --- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-28 03:37:06.000000000 +0200
2537 +++ linux-2.6.6-rc3/net/ipv4/ipip.c 2004-04-30 09:12:40.000000000 +0200
2538 @@ -478,6 +478,11 @@
2540 read_lock(&ipip_lock);
2541 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2542 + /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2543 + if (nf_xfrm_local_done(skb, NULL)) {
2544 + nf_rcv_postxfrm_local(skb);
2547 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2550 @@ -496,13 +501,7 @@
2551 skb->dev = tunnel->dev;
2552 dst_release(skb->dst);
2554 -#ifdef CONFIG_NETFILTER
2555 - nf_conntrack_put(skb->nfct);
2557 -#ifdef CONFIG_NETFILTER_DEBUG
2558 - skb->nf_debug = 0;
2562 ipip_ecn_decapsulate(iph, skb);
2564 read_unlock(&ipip_lock);
2565 @@ -647,13 +646,7 @@
2566 if ((iph->ttl = tiph->ttl) == 0)
2567 iph->ttl = old_iph->ttl;
2569 -#ifdef CONFIG_NETFILTER
2570 - nf_conntrack_put(skb->nfct);
2572 -#ifdef CONFIG_NETFILTER_DEBUG
2573 - skb->nf_debug = 0;
2579 tunnel->recursion--;
2580 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
2581 --- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
2582 +++ linux-2.6.6-rc3/net/ipv4/ipmr.c 2004-04-30 09:12:39.000000000 +0200
2583 @@ -1120,7 +1120,7 @@
2584 if (unlikely(opt->optlen))
2585 ip_forward_options(skb);
2587 - return dst_output(skb);
2588 + return ip_dst_output(skb);
2592 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
2593 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig 2004-04-28 03:36:31.000000000 +0200
2594 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig 2004-04-30 09:14:39.000000000 +0200
2595 @@ -206,6 +206,11 @@
2597 To compile it as a module, choose M here. If unsure, say N.
2599 +config IP_NF_MATCH_UNCLEAN
2600 + tristate 'unclean match support (EXPERIMENTAL)'
2601 + depends on EXPERIMENTAL && IP_NF_IPTABLES
2604 config IP_NF_MATCH_TTL
2605 tristate "TTL match support"
2606 depends on IP_NF_IPTABLES
2607 @@ -603,5 +608,227 @@
2608 <file:Documentation/modules.txt>. If unsure, say `N'.
2611 +config IP_NF_TARGET_IPV4OPTSSTRIP
2612 + tristate 'IPV4OPTSSTRIP target support'
2613 + depends on IP_NF_MANGLE
2616 +config IP_NF_TARGET_NETLINK
2617 + tristate 'NETLINK target support'
2618 + depends on IP_NF_FILTER
2621 +config IP_NF_TARGET_TTL
2622 + tristate 'TTL target support'
2623 + depends on IP_NF_MANGLE
2626 +config IP_NF_MATCH_CONNLIMIT
2627 + tristate 'Connections/IP limit match support'
2628 + depends on IP_NF_IPTABLES
2631 +config IP_NF_MATCH_DSTLIMIT
2632 + tristate 'dstlimit match support'
2633 + depends on IP_NF_IPTABLES
2636 +config IP_NF_MATCH_FUZZY
2637 + tristate 'fuzzy match support'
2638 + depends on IP_NF_IPTABLES
2641 +config IP_NF_MATCH_IPV4OPTIONS
2642 + tristate 'IPV4OPTIONS match support'
2643 + depends on IP_NF_IPTABLES
2646 +config IP_NF_MATCH_MPORT
2647 + tristate 'Multiple port with ranges match support'
2648 + depends on IP_NF_IPTABLES
2651 +config IP_NF_MATCH_NTH
2652 + tristate 'Nth match support'
2653 + depends on IP_NF_IPTABLES
2656 +config IP_NF_MATCH_OSF
2657 + tristate 'OSF match support'
2658 + depends on IP_NF_IPTABLES
2661 +config IP_POOL_STATISTICS
2662 + bool 'enable statistics on pool usage'
2663 + depends on IP_NF_POOL!=n
2666 + tristate 'IP address pool support'
2667 + depends on IP_NF_IPTABLES
2670 +config IP_NF_MATCH_PSD
2671 + tristate 'psd match support'
2672 + depends on IP_NF_IPTABLES
2675 +config IP_NF_MATCH_QUOTA
2676 + tristate 'quota match support'
2677 + depends on IP_NF_IPTABLES
2680 +config IP_NF_MATCH_RANDOM
2681 + tristate 'random match support'
2682 + depends on IP_NF_IPTABLES
2685 +config IP_NF_MATCH_REALM
2686 + tristate 'realm match support'
2687 + depends on IP_NF_IPTABLES && NET_CLS_ROUTE
2690 +config IP_NF_MATCH_SCTP
2691 + tristate 'SCTP protocol match support'
2692 + depends on IP_NF_IPTABLES
2695 +config IP_NF_MATCH_TIME
2696 + tristate 'TIME match support'
2697 + depends on IP_NF_IPTABLES
2700 +config IP_NF_MATCH_U32
2701 + tristate 'U32 match support'
2702 + depends on IP_NF_IPTABLES
2705 +config IP_NF_CONNTRACK_MARK
2706 + bool 'Connection mark tracking support'
2707 +config IP_NF_TARGET_CONNMARK
2708 + tristate 'CONNMARK target support'
2709 + depends on IP_NF_MANGLE
2710 +config IP_NF_MATCH_CONNMARK
2711 + tristate ' Connection mark match support'
2712 + depends on IP_NF_IPTABLES
2715 +config IP_NF_TARGET_IPMARK
2716 + tristate 'IPMARK target support'
2717 + depends on IP_NF_MANGLE
2720 +config IP_NF_TARGET_TARPIT
2721 + tristate 'TARPIT target support'
2722 + depends on IP_NF_FILTER
2725 +config IP_NF_TARGET_TRACE
2726 + tristate 'TRACE target support'
2727 + depends on IP_NF_RAW
2729 + The TRACE target allows packets to be traced as those
2730 + matches any subsequent rule in any table/rule. The matched
2731 + rule and the packet is logged with the prefix
2733 + TRACE: tablename/chainname/rulenum
2735 + If you want to compile it as a module, say M here and read
2736 + <file:Documentation/modules.txt>. If unsure, say `N'.
2739 +config IP_NF_TARGET_XOR
2740 + tristate 'XOR target support'
2741 + depends on IP_NF_MANGLE
2744 +config IP_NF_MATCH_ADDRTYPE
2745 + tristate 'address type match support'
2746 + depends on IP_NF_IPTABLES
2750 + tristate 'Eggdrop bot support'
2751 + depends on IP_NF_CONNTRACK
2754 +config IP_NF_NAT_H323
2756 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2757 + default IP_NF_NAT if IP_NF_H323=y
2758 + default m if IP_NF_H323=m
2761 + tristate 'H.323 (netmeeting) support'
2762 + depends on IP_NF_CONNTRACK
2765 +config IP_NF_NAT_MMS
2767 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2768 + default IP_NF_NAT if IP_NF_MMS=y
2769 + default m if IP_NF_MMS=m
2772 + tristate 'MMS protocol support'
2773 + depends on IP_NF_CONNTRACK
2776 +config IP_NF_MATCH_POLICY
2777 + tristate "IPsec policy match support"
2778 + depends on IP_NF_IPTABLES && XFRM
2780 + Policy matching allows you to match packets based on the
2781 + IPsec policy that was used during decapsulation/will
2782 + be used during encapsulation.
2784 + To compile it as a module, choose M here. If unsure, say N.
2787 +config IP_NF_NAT_QUAKE3
2789 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
2790 + default IP_NF_NAT if IP_NF_QUAKE3=y
2791 + default m if IP_NF_QUAKE3=m
2793 +config IP_NF_QUAKE3
2794 + tristate "Quake3 protocol support"
2795 + depends on IP_NF_CONNTRACK
2799 + tristate 'RSH protocol support'
2800 + depends on IP_NF_CONNTRACK
2803 +config IP_NF_NAT_RTSP
2805 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2806 + default IP_NF_NAT if IP_NF_RTSP=y
2807 + default m if IP_NF_RTSP=m
2809 + tristate ' RTSP protocol support'
2810 + depends on IP_NF_CONNTRACK
2813 +config IP_NF_CT_PROTO_SCTP
2814 + tristate 'SCTP protocol connection tracking support'
2815 + depends on IP_NF_CONNTRACK
2818 +config IP_NF_MATCH_STRING
2819 + tristate 'String match support'
2820 + depends on IP_NF_IPTABLES
2823 +config IP_NF_NAT_TALK
2825 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2826 + default IP_NF_NAT if IP_NF_TALK=y
2827 + default m if IP_NF_TALK=m
2829 + tristate 'talk protocol support'
2830 + depends on IP_NF_CONNTRACK
2835 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
2836 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile 2004-04-28 03:35:21.000000000 +0200
2837 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-30 09:14:39.000000000 +0200
2839 # connection tracking
2840 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
2842 +# talk protocol support
2843 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
2844 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
2847 +# SCTP protocol connection tracking
2848 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
2851 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
2852 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
2855 # connection tracking helpers
2857 +# rtsp protocol support
2858 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
2859 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
2861 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
2862 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
2863 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
2864 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
2865 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
2866 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
2868 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
2870 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
2874 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
2875 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
2876 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
2877 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
2878 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
2881 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
2884 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2885 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2886 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2887 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
2888 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
2889 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
2890 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
2891 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
2892 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
2894 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
2895 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
2897 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
2899 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
2900 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
2902 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
2905 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
2907 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
2909 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
2912 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
2914 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
2917 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
2919 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
2921 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
2922 @@ -60,12 +125,22 @@
2924 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
2926 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
2929 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
2930 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
2931 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
2932 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
2933 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
2934 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
2935 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
2936 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
2937 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
2938 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
2940 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
2941 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
2944 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
2946 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
2947 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
2948 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
2949 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
2950 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
2951 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
2952 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
2953 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
2955 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
2956 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
2957 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2958 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
2959 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
2960 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
2961 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
2962 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
2963 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2964 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2965 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2966 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2968 # generic ARP tables
2969 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c
2970 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-28 03:34:58.000000000 +0200
2971 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-30 09:11:35.000000000 +0200
2973 ip_conntrack_destroyed(ct);
2975 WRITE_LOCK(&ip_conntrack_lock);
2976 - /* Delete us from our own list to prevent corruption later */
2977 - list_del(&ct->sibling_list);
2978 + /* Make sure don't leave any orphaned expectations lying around */
2979 + if (ct->expecting)
2980 + remove_expectations(ct, 1);
2982 /* Delete our master expectation */
2984 @@ -692,42 +693,53 @@
2985 struct ip_conntrack_expect *, tuple);
2986 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
2988 - /* If master is not in hash table yet (ie. packet hasn't left
2989 - this machine yet), how can other end know about expected?
2990 - Hence these are not the droids you are looking for (if
2991 - master ct never got confirmed, we'd hold a reference to it
2992 - and weird things would happen to future packets). */
2993 - if (expected && !is_confirmed(expected->expectant))
2996 - /* Look up the conntrack helper for master connections only */
2998 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
3000 - /* If the expectation is dying, then this is a loser. */
3002 - && expected->expectant->helper->timeout
3003 - && ! del_timer(&expected->timeout))
3007 - DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3008 - conntrack, expected);
3009 - /* Welcome, Mr. Bond. We've been expecting you... */
3010 - IP_NF_ASSERT(master_ct(conntrack));
3011 - __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3012 - conntrack->master = expected;
3013 - expected->sibling = conntrack;
3014 - LIST_DELETE(&ip_conntrack_expect_list, expected);
3015 - expected->expectant->expecting--;
3016 - nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3018 - atomic_inc(&ip_conntrack_count);
3019 + /* If master is not in hash table yet (ie. packet hasn't left
3020 + this machine yet), how can other end know about expected?
3021 + Hence these are not the droids you are looking for (if
3022 + master ct never got confirmed, we'd hold a reference to it
3023 + and weird things would happen to future packets). */
3024 + if (!is_confirmed(expected->expectant)) {
3026 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3030 + /* Expectation is dying... */
3031 + if (expected->expectant->helper->timeout
3032 + && ! del_timer(&expected->timeout)) {
3036 + DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3037 + conntrack, expected);
3038 + /* Welcome, Mr. Bond. We've been expecting you... */
3039 + IP_NF_ASSERT(master_ct(conntrack));
3040 + __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3041 + conntrack->master = expected;
3042 + expected->sibling = conntrack;
3043 +#if CONFIG_IP_NF_CONNTRACK_MARK
3044 + conntrack->mark = expected->expectant->mark;
3046 + LIST_DELETE(&ip_conntrack_expect_list, expected);
3047 + expected->expectant->expecting--;
3048 + nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3050 + /* this is a braindead... --pablo */
3051 + atomic_inc(&ip_conntrack_count);
3052 + WRITE_UNLOCK(&ip_conntrack_lock);
3054 + if (expected->expectfn)
3055 + expected->expectfn(conntrack);
3059 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3061 +end: atomic_inc(&ip_conntrack_count);
3062 WRITE_UNLOCK(&ip_conntrack_lock);
3064 - if (expected && expected->expectfn)
3065 - expected->expectfn(conntrack);
3066 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3067 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3070 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3072 atomic_set(&new->use, 1);
3074 /* add to expected list for this connection */
3075 - list_add(&new->expected_list, &related_to->sibling_list);
3076 + list_add_tail(&new->expected_list, &related_to->sibling_list);
3077 /* add to global list of expectations */
3079 list_prepend(&ip_conntrack_expect_list, &new->list);
3080 /* add and start timer if required */
3081 if (related_to->helper->timeout) {
3082 @@ -1003,7 +1014,6 @@
3084 } else if (related_to->helper->max_expected &&
3085 related_to->expecting >= related_to->helper->max_expected) {
3086 - struct list_head *cur_item;
3088 if (!(related_to->helper->flags &
3089 IP_CT_HELPER_F_REUSE_EXPECT)) {
3090 @@ -1029,21 +1039,14 @@
3091 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3093 /* choose the the oldest expectation to evict */
3094 - list_for_each(cur_item, &related_to->sibling_list) {
3095 - struct ip_conntrack_expect *cur;
3097 - cur = list_entry(cur_item,
3098 - struct ip_conntrack_expect,
3100 - if (cur->sibling == NULL) {
3102 + list_for_each_entry(old, &related_to->sibling_list,
3104 + if (old->sibling == NULL)
3109 - /* (!old) cannot happen, since related_to->expecting is the
3110 - * number of unconfirmed expects */
3111 - IP_NF_ASSERT(old);
3112 + /* We cannot fail since related_to->expecting is the number
3113 + * of unconfirmed expectations */
3114 + IP_NF_ASSERT(old && old->sibling == NULL);
3116 /* newnat14 does not reuse the real allocated memory
3117 * structures but rather unexpects the old and
3118 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
3119 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3120 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-04-30 09:12:26.000000000 +0200
3122 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3123 + * based on ip_conntrack_irc.c
3125 + * This module only supports the share userfile-send command,
3126 + * used by eggdrops to share it's userfile.
3128 + * There are no support for NAT at the moment.
3130 + * This program is free software; you can redistribute it and/or
3131 + * modify it under the terms of the GNU General Public License
3132 + * as published by the Free Software Foundation; either version
3133 + * 2 of the License, or (at your option) any later version.
3135 + * Module load syntax:
3137 + * please give the ports of all Eggdrops You have running
3138 + * on your system, the default port is 3333.
3140 + * 2001-04-19: Security update. IP addresses are now compared
3141 + * to prevent unauthorized "related" access.
3143 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3144 + * Port to netfilter 'newnat' API.
3147 +#include <linux/module.h>
3148 +#include <linux/netfilter.h>
3149 +#include <linux/ip.h>
3150 +#include <net/checksum.h>
3151 +#include <net/tcp.h>
3153 +#include <linux/netfilter_ipv4/lockhelp.h>
3154 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3156 +#define MAX_PORTS 8
3157 +static int ports[MAX_PORTS];
3158 +static int ports_c = 0;
3159 +static unsigned int egg_timeout = 300;
3161 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3162 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3163 +MODULE_LICENSE("GPL");
3165 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3166 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3169 +DECLARE_LOCK(ip_egg_lock);
3170 +struct module *ip_conntrack_egg = THIS_MODULE;
3173 +#define DEBUGP printk
3175 +#define DEBUGP(format, args...)
3178 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3179 +/* tries to get the ip_addr and port out of a eggdrop command
3180 + return value: -1 on failure, 0 on success
3181 + data pointer to first byte of DCC command data
3182 + data_end pointer to last byte of dcc command data
3183 + ip returns parsed ip of dcc command
3184 + port returns parsed port of dcc command */
3186 + if (data > data_end)
3189 + *ip = simple_strtoul(data, &data, 10);
3191 + /* skip blanks between ip and port */
3192 + while (*data == ' ' && data < data_end)
3195 + *port = simple_strtoul(data, &data, 10);
3200 +static int help(const struct iphdr *iph, size_t len,
3201 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3203 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3204 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3205 + char *data = (char *) tcph + tcph->doff * 4;
3207 + u_int32_t tcplen = len - iph->ihl * 4;
3208 + u_int32_t datalen = tcplen - tcph->doff * 4;
3209 + int dir = CTINFO2DIR(ctinfo);
3210 + int bytes_scanned = 0;
3211 + struct ip_conntrack_expect exp;
3214 + u_int16_t egg_port;
3216 + DEBUGP("entered\n");
3218 + /* If packet is coming from IRC server */
3219 + if (dir != IP_CT_DIR_REPLY)
3222 + /* Until there's been traffic both ways, don't look in packets. */
3223 + if (ctinfo != IP_CT_ESTABLISHED
3224 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3225 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
3229 + /* Not whole TCP header? */
3230 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3231 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3235 + /* Checksum invalid? Ignore. */
3236 + /* FIXME: Source route IP option packets --RR */
3237 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3238 + csum_partial((char *) tcph, tcplen, 0))) {
3239 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3240 + tcph, tcplen, NIPQUAD(iph->saddr),
3241 + NIPQUAD(iph->daddr));
3245 + data_limit = (char *) data + datalen;
3246 + while (datalen > 5 && bytes_scanned < 128) {
3247 + if (memcmp(data, "s us ", 5)) {
3256 + DEBUGP("Userfile-share found in connection "
3257 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3258 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3260 + if (parse_command((char *) data, data_limit, &egg_ip,
3262 + DEBUGP("no data in userfile-share pkt\n");
3266 + memset(&exp, 0, sizeof(exp));
3268 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3269 + if (net_ratelimit())
3270 + printk("Forged Eggdrop command from "
3271 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3272 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3273 + HIPQUAD(egg_ip), egg_port);
3277 + exp.tuple.src.ip = iph->daddr;
3278 + exp.tuple.src.u.tcp.port = 0;
3279 + exp.tuple.dst.ip = htonl(egg_ip);
3280 + exp.tuple.dst.u.tcp.port = htons(egg_port);
3281 + exp.tuple.dst.protonum = IPPROTO_TCP;
3283 + exp.mask.dst.u.tcp.port = 0xffff;
3284 + exp.mask.dst.protonum = 0xffff;
3286 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3287 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3288 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3290 + ip_conntrack_expect_related(ct, &exp);
3296 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3297 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3299 +static void deregister_helpers(void) {
3302 + for (i = 0; i < ports_c; i++) {
3303 + DEBUGP("unregistering helper for port %d\n", ports[i]);
3304 + ip_conntrack_helper_unregister(&egg_helpers[i]);
3308 +static int __init init(void)
3313 + /* If no port given, default to standard eggdrop port */
3314 + if (ports[0] == 0)
3317 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3318 + memset(&egg_helpers[i], 0,
3319 + sizeof(struct ip_conntrack_helper));
3320 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3321 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3322 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3323 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
3324 + egg_helpers[i].max_expected = 1;
3325 + egg_helpers[i].timeout = egg_timeout;
3326 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3327 + egg_helpers[i].me = THIS_MODULE;
3328 + egg_helpers[i].help = help;
3330 + tmpname = &egg_names[i][0];
3331 + if (ports[i] == 3333)
3332 + sprintf(tmpname, "eggdrop");
3334 + sprintf(tmpname, "eggdrop-%d", ports[i]);
3335 + egg_helpers[i].name = tmpname;
3337 + DEBUGP("port #%d: %d\n", i, ports[i]);
3339 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
3342 + printk("ip_conntrack_egg: ERROR registering helper "
3343 + "for port %d\n", ports[i]);
3344 + deregister_helpers();
3352 +static void __exit fini(void)
3354 + deregister_helpers();
3359 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
3360 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3361 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-04-30 09:12:34.000000000 +0200
3364 + * H.323 'brute force' extension for H.323 connection tracking.
3365 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3367 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3368 + * (http://www.coritel.it/projects/sofia/nat/)
3369 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3370 + * the unregistered helpers to the conntrack entries.
3374 +#include <linux/module.h>
3375 +#include <linux/netfilter.h>
3376 +#include <linux/ip.h>
3377 +#include <net/checksum.h>
3378 +#include <net/tcp.h>
3380 +#include <linux/netfilter_ipv4/lockhelp.h>
3381 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3382 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3383 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3384 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3385 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3387 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3388 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3389 +MODULE_LICENSE("GPL");
3391 +DECLARE_LOCK(ip_h323_lock);
3392 +struct module *ip_conntrack_h323 = THIS_MODULE;
3395 +#define DEBUGP printk
3397 +#define DEBUGP(format, args...)
3400 +/* FIXME: This should be in userspace. Later. */
3401 +static int h245_help(const struct iphdr *iph, size_t len,
3402 + struct ip_conntrack *ct,
3403 + enum ip_conntrack_info ctinfo)
3405 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3406 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3407 + unsigned char *data_limit;
3408 + u_int32_t tcplen = len - iph->ihl * 4;
3409 + u_int32_t datalen = tcplen - tcph->doff * 4;
3410 + int dir = CTINFO2DIR(ctinfo);
3411 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3412 + struct ip_conntrack_expect expect, *exp = &expect;
3413 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3414 + u_int16_t data_port;
3415 + u_int32_t data_ip;
3418 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3419 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3420 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3422 + /* Can't track connections formed before we registered */
3426 + /* Until there's been traffic both ways, don't look in packets. */
3427 + if (ctinfo != IP_CT_ESTABLISHED
3428 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3429 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3433 + /* Not whole TCP header or too short packet? */
3434 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3435 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3439 + /* Checksum invalid? Ignore. */
3440 + /* FIXME: Source route IP option packets --RR */
3441 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3442 + csum_partial((char *)tcph, tcplen, 0))) {
3443 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3444 + tcph, tcplen, NIPQUAD(iph->saddr),
3445 + NIPQUAD(iph->daddr));
3449 + data_limit = (unsigned char *) data + datalen;
3452 + for (i = 0; data < (data_limit - 5); data++, i++) {
3453 + data_ip = *((u_int32_t *)data);
3454 + if (data_ip == iph->saddr) {
3455 + data_port = *((u_int16_t *)(data + 4));
3456 + memset(&expect, 0, sizeof(expect));
3457 + /* update the H.225 info */
3458 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3459 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3460 + NIPQUAD(iph->saddr), ntohs(data_port));
3461 + LOCK_BH(&ip_h323_lock);
3462 + info->is_h225 = H225_PORT + 1;
3463 + exp_info->port = data_port;
3464 + exp_info->dir = dir;
3465 + exp_info->offset = i;
3467 + exp->seq = ntohl(tcph->seq) + i;
3469 + exp->tuple = ((struct ip_conntrack_tuple)
3470 + { { ct->tuplehash[!dir].tuple.src.ip,
3473 + { .tcp = { data_port } },
3475 + exp->mask = ((struct ip_conntrack_tuple)
3476 + { { 0xFFFFFFFF, { 0 } },
3477 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3479 + exp->expectfn = NULL;
3481 + /* Ignore failure; should only happen with NAT */
3482 + ip_conntrack_expect_related(ct, exp);
3484 + UNLOCK_BH(&ip_h323_lock);
3492 +/* H.245 helper is not registered! */
3493 +static struct ip_conntrack_helper h245 =
3495 + "H.245", /* name */
3496 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3497 + NULL, /* module */
3498 + 8, /* max_ expected */
3499 + 240, /* timeout */
3500 + { { 0, { 0 } }, /* tuple */
3501 + { 0, { 0 }, IPPROTO_TCP } },
3502 + { { 0, { 0xFFFF } }, /* mask */
3503 + { 0, { 0 }, 0xFFFF } },
3504 + h245_help /* helper */
3507 +static int h225_expect(struct ip_conntrack *ct)
3509 + WRITE_LOCK(&ip_conntrack_lock);
3510 + ct->helper = &h245;
3511 + DEBUGP("h225_expect: helper for %p added\n", ct);
3512 + WRITE_UNLOCK(&ip_conntrack_lock);
3514 + return NF_ACCEPT; /* unused */
3517 +/* FIXME: This should be in userspace. Later. */
3518 +static int h225_help(const struct iphdr *iph, size_t len,
3519 + struct ip_conntrack *ct,
3520 + enum ip_conntrack_info ctinfo)
3522 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3523 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3524 + unsigned char *data_limit;
3525 + u_int32_t tcplen = len - iph->ihl * 4;
3526 + u_int32_t datalen = tcplen - tcph->doff * 4;
3527 + int dir = CTINFO2DIR(ctinfo);
3528 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3529 + struct ip_conntrack_expect expect, *exp = &expect;
3530 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3531 + u_int16_t data_port;
3532 + u_int32_t data_ip;
3535 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3536 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3537 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3539 + /* Can't track connections formed before we registered */
3543 + /* Until there's been traffic both ways, don't look in packets. */
3544 + if (ctinfo != IP_CT_ESTABLISHED
3545 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3546 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3550 + /* Not whole TCP header or too short packet? */
3551 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3552 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3556 + /* Checksum invalid? Ignore. */
3557 + /* FIXME: Source route IP option packets --RR */
3558 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3559 + csum_partial((char *)tcph, tcplen, 0))) {
3560 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3561 + tcph, tcplen, NIPQUAD(iph->saddr),
3562 + NIPQUAD(iph->daddr));
3566 + data_limit = (unsigned char *) data + datalen;
3569 + for (i = 0; data < (data_limit - 5); data++, i++) {
3570 + data_ip = *((u_int32_t *)data);
3571 + if (data_ip == iph->saddr) {
3572 + data_port = *((u_int16_t *)(data + 4));
3573 + if (data_port == tcph->source) {
3574 + /* Signal address */
3575 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3576 + NIPQUAD(iph->saddr));
3577 + /* Update the H.225 info so that NAT can mangle the address/port
3578 + even when we have no expected connection! */
3579 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3580 + LOCK_BH(&ip_h323_lock);
3582 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3583 + info->offset[IP_CT_DIR_ORIGINAL] = i;
3584 + UNLOCK_BH(&ip_h323_lock);
3587 + memset(&expect, 0, sizeof(expect));
3589 + /* update the H.225 info */
3590 + LOCK_BH(&ip_h323_lock);
3591 + info->is_h225 = H225_PORT;
3592 + exp_info->port = data_port;
3593 + exp_info->dir = dir;
3594 + exp_info->offset = i;
3596 + exp->seq = ntohl(tcph->seq) + i;
3598 + exp->tuple = ((struct ip_conntrack_tuple)
3599 + { { ct->tuplehash[!dir].tuple.src.ip,
3602 + { .tcp = { data_port } },
3604 + exp->mask = ((struct ip_conntrack_tuple)
3605 + { { 0xFFFFFFFF, { 0 } },
3606 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3608 + exp->expectfn = h225_expect;
3610 + /* Ignore failure */
3611 + ip_conntrack_expect_related(ct, exp);
3613 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3614 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3615 + NIPQUAD(iph->saddr), ntohs(data_port));
3617 + UNLOCK_BH(&ip_h323_lock);
3619 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3620 + } else if (data_ip == iph->daddr) {
3621 + data_port = *((u_int16_t *)(data + 4));
3622 + if (data_port == tcph->dest) {
3623 + /* Signal address */
3624 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3625 + NIPQUAD(iph->daddr));
3626 + /* Update the H.225 info so that NAT can mangle the address/port
3627 + even when we have no expected connection! */
3628 + LOCK_BH(&ip_h323_lock);
3630 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3631 + info->offset[IP_CT_DIR_REPLY] = i;
3632 + UNLOCK_BH(&ip_h323_lock);
3642 +static struct ip_conntrack_helper h225 =
3644 + "H.225", /* name */
3645 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3646 + THIS_MODULE, /* module */
3647 + 2, /* max_expected */
3648 + 240, /* timeout */
3649 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
3650 + { 0, { 0 }, IPPROTO_TCP } },
3651 + { { 0, { 0xFFFF } }, /* mask */
3652 + { 0, { 0 }, 0xFFFF } },
3653 + h225_help /* helper */
3656 +static int __init init(void)
3658 + return ip_conntrack_helper_register(&h225);
3661 +static void __exit fini(void)
3663 + /* Unregister H.225 helper */
3664 + ip_conntrack_helper_unregister(&h225);
3667 +EXPORT_SYMBOL(ip_h323_lock);
3671 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
3672 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
3673 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-04-30 09:12:58.000000000 +0200
3675 +/* MMS extension for IP connection tracking
3676 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3677 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3679 + * ip_conntrack_mms.c v0.3 2002-09-22
3681 + * This program is free software; you can redistribute it and/or
3682 + * modify it under the terms of the GNU General Public License
3683 + * as published by the Free Software Foundation; either version
3684 + * 2 of the License, or (at your option) any later version.
3686 + * Module load syntax:
3687 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3689 + * Please give the ports of all MMS servers You wish to connect to.
3690 + * If you don't specify ports, the default will be TCP port 1755.
3692 + * More info on MMS protocol, firewalls and NAT:
3693 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3694 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3696 + * The SDP project people are reverse-engineering MMS:
3697 + * http://get.to/sdp
3700 +#include <linux/config.h>
3701 +#include <linux/module.h>
3702 +#include <linux/netfilter.h>
3703 +#include <linux/ip.h>
3704 +#include <linux/ctype.h>
3705 +#include <net/checksum.h>
3706 +#include <net/tcp.h>
3708 +#include <linux/netfilter_ipv4/lockhelp.h>
3709 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3710 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3712 +DECLARE_LOCK(ip_mms_lock);
3713 +struct module *ip_conntrack_mms = THIS_MODULE;
3715 +#define MAX_PORTS 8
3716 +static int ports[MAX_PORTS];
3717 +static int ports_c;
3719 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3723 +#define DEBUGP printk
3725 +#define DEBUGP(format, args...)
3728 +EXPORT_SYMBOL(ip_mms_lock);
3730 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3731 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3732 +MODULE_LICENSE("GPL");
3734 +/* #define isdigit(c) (c >= '0' && c <= '9') */
3736 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3737 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3740 + for (i = 0; i < unicode_size; ++i) {
3741 + string[i] = (char)(unicode[i]);
3743 + string[unicode_size] = 0x00;
3746 +__inline static int atoi(char *s)
3749 + while (isdigit(*s)) {
3750 + i = i*10 + *(s++) - '0';
3755 +/* convert ip address string like "192.168.0.10" to unsigned int */
3756 +__inline static u_int32_t asciiiptoi(char *s)
3758 + unsigned int i, j, k;
3760 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
3762 + for(j=0; (*(++s) != '.') && (j<3); ++j)
3769 +int parse_mms(const char *data,
3770 + const unsigned int datalen,
3771 + u_int32_t *mms_ip,
3772 + u_int16_t *mms_proto,
3773 + u_int16_t *mms_port,
3774 + char **mms_string_b,
3775 + char **mms_string_e,
3776 + char **mms_padding_e)
3778 + int unicode_size, i;
3779 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
3780 + char getlengthstring[28];
3782 + for(unicode_size=0;
3783 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3785 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
3786 + return -1; /* out of bounds - incomplete packet */
3788 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3789 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3791 + /* IP address ? */
3792 + *mms_ip = asciiiptoi(tempstring+2);
3794 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3797 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
3798 + *mms_proto = IPPROTO_TCP;
3799 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3800 + *mms_proto = IPPROTO_UDP;
3803 + *mms_port = atoi(tempstring+7+i);
3805 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
3806 + unicode string, one to the end of the string, and one to the end
3807 + of the packet, since we must keep track of the number of bytes
3808 + between end of the unicode string and the end of packet (padding) */
3809 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3810 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3811 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3816 +/* FIXME: This should be in userspace. Later. */
3817 +static int help(const struct iphdr *iph, size_t len,
3818 + struct ip_conntrack *ct,
3819 + enum ip_conntrack_info ctinfo)
3821 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3822 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3823 + const char *data = (const char *)tcph + tcph->doff * 4;
3824 + unsigned int tcplen = len - iph->ihl * 4;
3825 + unsigned int datalen = tcplen - tcph->doff * 4;
3826 + int dir = CTINFO2DIR(ctinfo);
3827 + struct ip_conntrack_expect expect, *exp = &expect;
3828 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3831 + u_int16_t mms_proto;
3832 + char mms_proto_string[8];
3833 + u_int16_t mms_port;
3834 + char *mms_string_b, *mms_string_e, *mms_padding_e;
3836 + /* Until there's been traffic both ways, don't look in packets. */
3837 + if (ctinfo != IP_CT_ESTABLISHED
3838 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3839 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3843 + /* Not whole TCP header? */
3844 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3845 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3849 + /* Checksum invalid? Ignore. */
3850 + /* FIXME: Source route IP option packets --RR */
3851 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3852 + csum_partial((char *)tcph, tcplen, 0))) {
3853 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3854 + tcph, tcplen, NIPQUAD(iph->saddr),
3855 + NIPQUAD(iph->daddr));
3859 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3860 + /* FIXME: There is an issue with only looking at this packet: before this packet,
3861 + the client has already sent a packet to the server with the server's hostname
3862 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
3863 + server will break the connection if this doesn't correspond to its own host
3864 + header. The client can also connect to an IP address; if it's the server's IP
3865 + address, it will not break the connection. When doing DNAT on a connection
3866 + where the client uses a server's IP address, the nat module should detect
3867 + this and change this string accordingly to the DNATed address. This should
3868 + probably be done by checking for an IP address, then storing it as a member
3869 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3871 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
3872 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3873 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
3874 + (u8)*(data+36), (u8)*(data+37),
3875 + (u8)*(data+38), (u8)*(data+39),
3877 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3878 + &mms_string_b, &mms_string_e, &mms_padding_e))
3879 + if(net_ratelimit())
3880 + /* FIXME: more verbose debugging ? */
3881 + printk(KERN_WARNING
3882 + "ip_conntrack_mms: Unable to parse data payload\n");
3884 + memset(&expect, 0, sizeof(expect));
3886 + sprintf(mms_proto_string, "(%u)", mms_proto);
3887 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3888 + mms_proto == IPPROTO_TCP ? "TCP"
3889 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3890 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3894 + /* it's possible that the client will just ask the server to tunnel
3895 + the stream over the same TCP session (from port 1755): there's
3896 + shouldn't be a need to add an expectation in that case, but it
3897 + makes NAT packet mangling so much easier */
3898 + LOCK_BH(&ip_mms_lock);
3900 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3902 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3903 + exp_mms_info->len = (mms_string_e - mms_string_b);
3904 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
3905 + exp_mms_info->port = mms_port;
3907 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3908 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3910 + exp->tuple = ((struct ip_conntrack_tuple)
3911 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3913 + { .tcp = { (__u16) ntohs(mms_port) } },
3916 + exp->mask = ((struct ip_conntrack_tuple)
3917 + { { 0xFFFFFFFF, { 0 } },
3918 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3919 + exp->expectfn = NULL;
3920 + ip_conntrack_expect_related(ct, &expect);
3921 + UNLOCK_BH(&ip_mms_lock);
3927 +static struct ip_conntrack_helper mms[MAX_PORTS];
3928 +static char mms_names[MAX_PORTS][10];
3930 +/* Not __exit: called from init() */
3931 +static void fini(void)
3934 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3935 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3937 + ip_conntrack_helper_unregister(&mms[i]);
3941 +static int __init init(void)
3946 + if (ports[0] == 0)
3947 + ports[0] = MMS_PORT;
3949 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3950 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3951 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3952 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
3953 + mms[i].mask.src.u.tcp.port = 0xFFFF;
3954 + mms[i].mask.dst.protonum = 0xFFFF;
3955 + mms[i].max_expected = 1;
3956 + mms[i].timeout = 0;
3957 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3958 + mms[i].me = THIS_MODULE;
3959 + mms[i].help = help;
3961 + tmpname = &mms_names[i][0];
3962 + if (ports[i] == MMS_PORT)
3963 + sprintf(tmpname, "mms");
3965 + sprintf(tmpname, "mms-%d", ports[i]);
3966 + mms[i].name = tmpname;
3968 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
3970 + ret = ip_conntrack_helper_register(&mms[i]);
3983 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
3984 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
3985 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-30 09:14:08.000000000 +0200
3988 + * Connection tracking protocol helper module for SCTP.
3990 + * SCTP is defined in RFC 2960. References to various sections in this code
3991 + * are to this RFC.
3993 + * This program is free software; you can redistribute it and/or modify
3994 + * it under the terms of the GNU General Public License version 2 as
3995 + * published by the Free Software Foundation.
3998 +#include <linux/types.h>
3999 +#include <linux/sched.h>
4000 +#include <linux/timer.h>
4001 +#include <linux/netfilter.h>
4002 +#include <linux/module.h>
4003 +#include <linux/in.h>
4004 +#include <linux/ip.h>
4005 +#include <linux/sctp.h>
4006 +#include <linux/string.h>
4008 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4009 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4010 +#include <linux/netfilter_ipv4/lockhelp.h>
4013 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4015 +#define DEBUGP(format, args...)
4018 +/* Protects conntrack->proto.sctp */
4019 +static DECLARE_RWLOCK(sctp_lock);
4021 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4022 + closely. They're more complex. --RR
4024 + And so for me for SCTP :D -Kiran */
4026 +static const char *sctp_conntrack_names[] = {
4034 + "SHUTDOWN_ACK_SENT",
4038 +#define MINS * 60 SECS
4039 +#define HOURS * 60 MINS
4040 +#define DAYS * 24 HOURS
4042 +unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
4043 +unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
4044 +unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
4045 +unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
4046 +unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
4047 +unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
4048 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
4050 +static unsigned long * sctp_timeouts[]
4051 += { 0, /* SCTP_CONNTRACK_NONE */
4052 + &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
4053 + &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
4054 + &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
4055 + &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
4056 + &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4057 + &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4058 + &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4061 +#define sNO SCTP_CONNTRACK_NONE
4062 +#define sCL SCTP_CONNTRACK_CLOSED
4063 +#define sCW SCTP_CONNTRACK_COOKIE_WAIT
4064 +#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
4065 +#define sES SCTP_CONNTRACK_ESTABLISHED
4066 +#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4067 +#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4068 +#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4069 +#define sIV SCTP_CONNTRACK_MAX
4072 + These are the descriptions of the states:
4074 +NOTE: These state names are tantalizingly similar to the states of an
4075 +SCTP endpoint. But the interpretation of the states is a little different,
4076 +considering that these are the states of the connection and not of an end
4077 +point. Please note the subtleties. -Kiran
4079 +NONE - Nothing so far.
4080 +COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
4081 + an INIT_ACK chunk in the reply direction.
4082 +COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
4083 +ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
4084 +SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
4085 +SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
4086 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4087 + to that of the SHUTDOWN chunk.
4088 +CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
4089 + the SHUTDOWN chunk. Connection is closed.
4093 + - I have assumed that the first INIT is in the original direction.
4094 + This messes things when an INIT comes in the reply direction in CLOSED
4096 + - Check the error type in the reply dir before transitioning from
4097 +cookie echoed to closed.
4098 + - Sec 5.2.4 of RFC 2960
4099 + - Multi Homing support.
4102 +/* SCTP conntrack state transitions */
4103 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4106 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4107 +/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4108 +/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4109 +/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4110 +/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4111 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4112 +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4113 +/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4114 +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4115 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4119 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4120 +/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4121 +/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4122 +/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4123 +/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4124 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4125 +/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4126 +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4127 +/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4128 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4132 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4133 + unsigned int dataoff,
4134 + struct ip_conntrack_tuple *tuple)
4136 + sctp_sctphdr_t hdr;
4138 + DEBUGP(__FUNCTION__);
4141 + /* Actually only need first 8 bytes. */
4142 + if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4145 + tuple->src.u.sctp.port = hdr.source;
4146 + tuple->dst.u.sctp.port = hdr.dest;
4151 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4152 + const struct ip_conntrack_tuple *orig)
4154 + DEBUGP(__FUNCTION__);
4157 + tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4158 + tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4162 +/* Print out the per-protocol part of the tuple. */
4163 +static unsigned int sctp_print_tuple(char *buffer,
4164 + const struct ip_conntrack_tuple *tuple)
4166 + DEBUGP(__FUNCTION__);
4169 + return sprintf(buffer, "sport=%hu dport=%hu ",
4170 + ntohs(tuple->src.u.sctp.port),
4171 + ntohs(tuple->dst.u.sctp.port));
4174 +/* Print out the private part of the conntrack. */
4175 +static unsigned int sctp_print_conntrack(char *buffer,
4176 + const struct ip_conntrack *conntrack)
4178 + enum sctp_conntrack state;
4180 + DEBUGP(__FUNCTION__);
4183 + READ_LOCK(&sctp_lock);
4184 + state = conntrack->proto.sctp.state;
4185 + READ_UNLOCK(&sctp_lock);
4187 + return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4190 +#define for_each_sctp_chunk(skb, sch, offset, count) \
4191 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
4192 + offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
4193 + offset += (htons(sch.length) + 3) & ~3, count++)
4195 +/* Some validity checks to make sure the chunks are fine */
4196 +static int do_basic_checks(struct ip_conntrack *conntrack,
4197 + const struct sk_buff *skb,
4200 + u_int32_t offset, count;
4201 + sctp_chunkhdr_t sch;
4204 + DEBUGP(__FUNCTION__);
4209 + for_each_sctp_chunk (skb, sch, offset, count) {
4210 + DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
4212 + if (sch.type == SCTP_CID_INIT
4213 + || sch.type == SCTP_CID_INIT_ACK
4214 + || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4218 + /* Cookie Ack/Echo chunks not the first OR
4219 + Init / Init Ack / Shutdown compl chunks not the only chunks */
4220 + if ((sch.type == SCTP_CID_COOKIE_ACK
4221 + || sch.type == SCTP_CID_COOKIE_ECHO
4224 + DEBUGP("Basic checks failed\n");
4229 + set_bit (sch.type, (void *)map);
4233 + DEBUGP("Basic checks passed\n");
4237 +static int new_state(enum ip_conntrack_dir dir,
4238 + enum sctp_conntrack cur_state,
4243 + DEBUGP(__FUNCTION__);
4246 + DEBUGP("Chunk type: %d\n", chunk_type);
4248 + switch (chunk_type) {
4249 + case SCTP_CID_INIT:
4250 + DEBUGP("SCTP_CID_INIT\n");
4252 + case SCTP_CID_INIT_ACK:
4253 + DEBUGP("SCTP_CID_INIT_ACK\n");
4255 + case SCTP_CID_ABORT:
4256 + DEBUGP("SCTP_CID_ABORT\n");
4258 + case SCTP_CID_SHUTDOWN:
4259 + DEBUGP("SCTP_CID_SHUTDOWN\n");
4261 + case SCTP_CID_SHUTDOWN_ACK:
4262 + DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4264 + case SCTP_CID_ERROR:
4265 + DEBUGP("SCTP_CID_ERROR\n");
4267 + case SCTP_CID_COOKIE_ECHO:
4268 + DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4270 + case SCTP_CID_COOKIE_ACK:
4271 + DEBUGP("SCTP_CID_COOKIE_ACK\n");
4273 + case SCTP_CID_SHUTDOWN_COMPLETE:
4274 + DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4277 + /* Other chunks like DATA, SACK, HEARTBEAT and
4278 + its ACK do not cause a change in state */
4279 + DEBUGP("Unknown chunk type, Will stay in %s\n",
4280 + sctp_conntrack_names[cur_state]);
4284 + DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
4285 + dir, sctp_conntrack_names[cur_state], chunk_type,
4286 + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4288 + return sctp_conntracks[dir][i][cur_state];
4291 +/* Returns verdict for packet, or -1 for invalid. */
4292 +static int sctp_packet(struct ip_conntrack *conntrack,
4293 + const struct sk_buff *skb,
4294 + enum ip_conntrack_info ctinfo)
4296 + enum sctp_conntrack newconntrack, oldsctpstate;
4297 + sctp_sctphdr_t sctph;
4298 + sctp_chunkhdr_t sch;
4299 + u_int32_t offset, count;
4300 + char map[256 / sizeof (char)] = {0};
4302 + DEBUGP(__FUNCTION__);
4305 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4308 + if (do_basic_checks(conntrack, skb, map) != 0)
4311 + /* Check the verification tag (Sec 8.5) */
4312 + if (!test_bit(SCTP_CID_INIT, (void *)map)
4313 + && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4314 + && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4315 + && !test_bit(SCTP_CID_ABORT, (void *)map)
4316 + && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4317 + && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4318 + DEBUGP("Verification tag check failed\n");
4322 + oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4323 + for_each_sctp_chunk (skb, sch, offset, count) {
4324 + WRITE_LOCK(&sctp_lock);
4326 + /* Special cases of Verification tag check (Sec 8.5.1) */
4327 + if (sch.type == SCTP_CID_INIT) {
4328 + /* Sec 8.5.1 (A) */
4329 + if (sctph.vtag != 0) {
4330 + WRITE_UNLOCK(&sctp_lock);
4333 + } else if (sch.type == SCTP_CID_ABORT) {
4334 + /* Sec 8.5.1 (B) */
4335 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4336 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4337 + [1 - CTINFO2DIR(ctinfo)])) {
4338 + WRITE_UNLOCK(&sctp_lock);
4341 + } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4342 + /* Sec 8.5.1 (C) */
4343 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4344 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4345 + [1 - CTINFO2DIR(ctinfo)]
4346 + && (sch.flags & 1))) {
4347 + WRITE_UNLOCK(&sctp_lock);
4350 + } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4351 + /* Sec 8.5.1 (D) */
4352 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4353 + WRITE_UNLOCK(&sctp_lock);
4358 + oldsctpstate = conntrack->proto.sctp.state;
4359 + newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4362 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4363 + DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4364 + CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4365 + WRITE_UNLOCK(&sctp_lock);
4369 + /* If it is an INIT or an INIT ACK note down the vtag */
4370 + if (sch.type == SCTP_CID_INIT
4371 + || sch.type == SCTP_CID_INIT_ACK) {
4372 + sctp_inithdr_t inithdr;
4374 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4375 + &inithdr, sizeof(inithdr)) != 0) {
4376 + WRITE_UNLOCK(&sctp_lock);
4379 + DEBUGP("Setting vtag %x for dir %d\n",
4380 + inithdr.init_tag, CTINFO2DIR(ctinfo));
4381 + conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4384 + conntrack->proto.sctp.state = newconntrack;
4385 + WRITE_UNLOCK(&sctp_lock);
4388 + ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4390 + if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4391 + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4392 + && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4393 + DEBUGP("Setting assured bit\n");
4394 + set_bit(IPS_ASSURED_BIT, &conntrack->status);
4400 +/* Called when a new connection for this protocol found. */
4401 +static int sctp_new(struct ip_conntrack *conntrack,
4402 + const struct sk_buff *skb)
4404 + enum sctp_conntrack newconntrack;
4405 + sctp_sctphdr_t sctph;
4406 + sctp_chunkhdr_t sch;
4407 + u_int32_t offset, count;
4408 + char map[256 / sizeof (char)] = {0};
4410 + DEBUGP(__FUNCTION__);
4413 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4416 + if (do_basic_checks(conntrack, skb, map) != 0)
4419 + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4420 + if ((test_bit (SCTP_CID_ABORT, (void *)map))
4421 + || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4422 + || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4426 + newconntrack = SCTP_CONNTRACK_MAX;
4427 + for_each_sctp_chunk (skb, sch, offset, count) {
4428 + /* Don't need lock here: this conntrack not in circulation yet */
4429 + newconntrack = new_state (IP_CT_DIR_ORIGINAL,
4430 + SCTP_CONNTRACK_NONE, sch.type);
4432 + /* Invalid: delete conntrack */
4433 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4434 + DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4438 + /* Copy the vtag into the state info */
4439 + if (sch.type == SCTP_CID_INIT) {
4440 + if (sctph.vtag == 0) {
4441 + sctp_inithdr_t inithdr;
4443 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4444 + &inithdr, sizeof(inithdr)) != 0) {
4448 + DEBUGP("Setting vtag %x for new conn\n",
4449 + inithdr.init_tag);
4451 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
4454 + /* Sec 8.5.1 (A) */
4458 + /* If it is a shutdown ack OOTB packet, we expect a return
4459 + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4461 + DEBUGP("Setting vtag %x for new conn OOTB\n",
4463 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4466 + conntrack->proto.sctp.state = newconntrack;
4472 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4473 + const struct sk_buff *skb)
4475 + /* To be implemented */
4479 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
4480 + .list = { NULL, NULL },
4481 + .proto = IPPROTO_SCTP,
4483 + .pkt_to_tuple = sctp_pkt_to_tuple,
4484 + .invert_tuple = sctp_invert_tuple,
4485 + .print_tuple = sctp_print_tuple,
4486 + .print_conntrack = sctp_print_conntrack,
4487 + .packet = sctp_packet,
4490 + .exp_matches_pkt = sctp_exp_matches_pkt,
4494 +int __init init(void)
4498 + ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4499 + DEBUGP("SCTP conntrack module loading %s\n",
4500 + ret ? "failed": "succeeded");
4504 +void __exit fini(void)
4506 + ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4507 + DEBUGP("SCTP conntrack module unloaded\n");
4513 +MODULE_LICENSE("GPL");
4514 +MODULE_AUTHOR("Kiran Kumar Immidi");
4515 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
4516 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
4517 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
4518 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-04-30 09:13:29.000000000 +0200
4520 +/* Quake3 extension for IP connection tracking
4521 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4522 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
4524 + * ip_conntrack_quake3.c v0.04 2002-08-31
4526 + * This program is free software; you can redistribute it and/or
4527 + * modify it under the terms of the GNU General Public License
4528 + * as published by the Free Software Foundation; either version
4529 + * 2 of the License, or (at your option) any later version.
4531 + * Module load syntax:
4532 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
4534 + * please give the ports of all Quake3 master servers You wish to
4535 + * connect to. If you don't specify ports, the default will be UDP
4538 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
4541 +#include <linux/module.h>
4542 +#include <linux/ip.h>
4543 +#include <linux/udp.h>
4545 +#include <linux/netfilter.h>
4546 +#include <linux/netfilter_ipv4/ip_tables.h>
4547 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4548 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
4550 +struct module *ip_conntrack_quake3 = THIS_MODULE;
4552 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4553 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
4554 +MODULE_LICENSE("GPL");
4556 +#define MAX_PORTS 8
4557 +static int ports[MAX_PORTS];
4558 +static int ports_c = 0;
4560 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4561 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
4564 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
4565 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
4567 +#define DEBUGP printk
4569 +#define DEBUGP(format, args...)
4572 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
4574 +static int quake3_help(const struct iphdr *iph, size_t len,
4575 + struct ip_conntrack *ct,
4576 + enum ip_conntrack_info ctinfo)
4578 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
4579 + int dir = CTINFO2DIR(ctinfo);
4580 + struct ip_conntrack_expect exp;
4583 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
4584 + if (ctinfo != IP_CT_ESTABLISHED
4585 + && ctinfo != IP_CT_IS_REPLY) {
4586 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
4588 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
4590 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
4591 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
4592 + i+6 < ntohs(udph->len);
4594 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
4595 + i, ntohs(udph->len),
4596 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
4597 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
4599 + memset(&exp, 0, sizeof(exp));
4601 + exp.tuple = ((struct ip_conntrack_tuple)
4602 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4603 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
4604 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
4607 + exp.mask = ((struct ip_conntrack_tuple)
4608 + { { 0xFFFFFFFF, { 0 } },
4609 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
4610 + exp.expectfn = NULL;
4612 + ip_conntrack_expect_related(ct, &exp);
4617 + return(NF_ACCEPT);
4620 +static struct ip_conntrack_helper quake3[MAX_PORTS];
4621 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
4623 +static void fini(void)
4627 + for(i = 0 ; (i < ports_c); i++) {
4628 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
4630 + ip_conntrack_helper_unregister(&quake3[i]);
4634 +static int __init init(void)
4640 + ports[0]=QUAKE3_MASTER_PORT;
4642 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
4643 + /* Create helper structure */
4644 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
4646 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
4647 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
4648 + quake3[i].mask.dst.protonum = 0xFFFF;
4649 + quake3[i].mask.src.u.udp.port = 0xFFFF;
4650 + quake3[i].help = quake3_help;
4651 + quake3[i].me = THIS_MODULE;
4653 + tmpname = &quake3_names[i][0];
4654 + if (ports[i] == QUAKE3_MASTER_PORT)
4655 + sprintf(tmpname, "quake3");
4657 + sprintf(tmpname, "quake3-%d", i);
4658 + quake3[i].name = tmpname;
4660 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
4663 + ret=ip_conntrack_helper_register(&quake3[i]);
4676 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
4677 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
4678 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-04-30 09:13:59.000000000 +0200
4680 +/* RSH extension for IP connection tracking, Version 1.0
4681 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4682 + * based on HW's ip_conntrack_irc.c
4684 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4686 + * This program is free software; you can redistribute it and/or
4687 + * modify it under the terms of the GNU General Public License
4688 + * as published by the Free Software Foundation; either version
4689 + * 2 of the License, or (at your option) any later version.
4691 + * Module load syntax:
4692 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4694 + * please give the ports of all RSH servers You wish to connect to.
4695 + * If You don't specify ports, the default will be port 514
4698 + * RSH blows ... you should use SSH (openssh.org) to replace it,
4699 + * unfortunately I babysit some sysadmins that won't migrate
4700 + * their legacy crap, in our second tier.
4705 + * Some docco ripped from the net to teach me all there is to know about
4706 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4709 + * I have no idea what "unix rshd man pages" these guys have .. but that
4710 + * is some pretty detailed docco!
4713 + * 4. Of the rsh protocol.
4714 + * -----------------------
4716 + * The rshd listens on TCP port #514. The following info is from the unix
4717 + * rshd man pages :
4719 + * "Service Request Protocol
4721 + * When the rshd daemon receives a service request, it initiates the
4722 + * following protocol:
4724 + * 1. The rshd daemon checks the source port number for the request.
4725 + * If the port number is not in the range 0 through 1023, the rshd daemon
4726 + * terminates the connection.
4728 + * 2. The rshd daemon reads characters from the socket up to a null byte.
4729 + * The string read is interpreted as an ASCII number (base 10). If this
4730 + * number is nonzero, the rshd daemon interprets it as the port number
4731 + * of a secondary stream to be used as standard error. A second connection
4732 + * is created to the specified port on the client host. The source port
4733 + * on the local host is in the range 0 through 1023.
4735 + * 3. The rshd daemon uses the source address of the initial connection
4736 + * request to determine the name of the client host. If the name cannot
4737 + * be determined, the rshd daemon uses the dotted decimal representation
4738 + * of the client host's address.
4740 + * 4. The rshd daemon retrieves the following information from the initial
4743 + * * A null-terminated string of at most 16 bytes interpreted as
4744 + * the user name of the user on the client host.
4746 + * * A null-terminated string of at most 16 bytes interpreted as
4747 + * the user name to be used on the local server host.
4749 + * * Another null-terminated string interpreted as a command line
4750 + * to be passed to a shell on the local server host.
4752 + * 5. The rshd daemon attempts to validate the user using the following steps:
4754 + * a. The rshd daemon looks up the local user name in the /etc/passwd
4755 + * file and tries to switch to the home directory (using the chdir
4756 + * subroutine). If either the lookup or the directory change fails,
4757 + * the rshd daemon terminates the connection.
4759 + * b. If the local user ID is a nonzero value, the rshd daemon searches
4760 + * the /etc/hosts.equiv file to see if the name of the client
4761 + * workstation is listed. If the client workstation is listed as an
4762 + * equivalent host, the rshd daemon validates the user.
4764 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4765 + * authenticate the user by checking the .rhosts file.
4767 + * d. If either the $HOME/.rhosts authentication fails or the
4768 + * client host is not an equivalent host, the rshd daemon
4769 + * terminates the connection.
4771 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
4772 + * on the initial connection and passes the command line to the user's
4773 + * local login shell. The shell then inherits the network connections
4774 + * established by the rshd daemon."
4779 +#include <linux/module.h>
4780 +#include <linux/netfilter.h>
4781 +#include <linux/ip.h>
4782 +#include <net/checksum.h>
4783 +#include <net/tcp.h>
4785 +#include <linux/netfilter_ipv4/lockhelp.h>
4786 +#include <linux/netfilter_ipv4/ip_tables.h>
4787 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4788 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4790 +#define MAX_PORTS 8
4791 +static int ports[MAX_PORTS];
4792 +static int ports_n_c = 0;
4794 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4795 +MODULE_DESCRIPTION("RSH connection tracking module");
4796 +MODULE_LICENSE("GPL");
4798 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4799 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4802 +DECLARE_LOCK(ip_rsh_lock);
4803 +struct module *ip_conntrack_rsh = THIS_MODULE;
4806 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4809 +#define DEBUGP(format, args...)
4814 +/* FIXME: This should be in userspace. Later. */
4815 +static int help(const struct iphdr *iph, size_t len,
4816 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4818 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4819 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4820 + const char *data = (const char *) tcph + tcph->doff * 4;
4821 + u_int32_t tcplen = len - iph->ihl * 4;
4822 + int dir = CTINFO2DIR(ctinfo);
4823 + struct ip_conntrack_expect expect, *exp = &expect;
4824 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4828 + /* note that "maxoctet" is used to maintain sanity (8 was the
4829 + * original array size used in rshd/glibc) -- is there a
4830 + * vulnerability in rshd.c in the looped port *= 10?
4834 + DEBUGP("entered\n");
4836 + /* bail if packet is not from RSH client */
4837 + if (dir == IP_CT_DIR_REPLY)
4840 + /* Until there's been traffic both ways, don't look in packets. */
4841 + if (ctinfo != IP_CT_ESTABLISHED
4842 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4843 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
4847 + /* Not whole TCP header? */
4848 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4849 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4853 + /* Checksum invalid? Ignore. */
4854 + /* FIXME: Source route IP option packets --RR */
4855 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4856 + csum_partial((char *) tcph, tcplen, 0))) {
4857 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4858 + tcph, tcplen, NIPQUAD(iph->saddr),
4859 + NIPQUAD(iph->daddr));
4863 + /* find the rsh stderr port */
4866 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4871 + if (*data < 48 || *data > 57) {
4872 + DEBUGP("these aren't the packets you're looking for ..\n");
4875 + port = port * 10 + ( *data - 48 );
4878 + /* dont relate sessions that try to expose the client */
4879 + DEBUGP("found port %u\n", port);
4880 + if (port > 1023) {
4881 + DEBUGP("skipping, expected port size is greater than 1023!\n");
4886 + LOCK_BH(&ip_rsh_lock);
4888 + /* new(,related) connection is;
4889 + * reply + dst (uint)port + src port (0:1023)
4891 + memset(&expect, 0, sizeof(expect));
4893 + /* save some discovered data, in case someone ever wants to write
4894 + * a NAT module for this bastard ..
4896 + exp_rsh_info->port = port;
4898 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4901 + /* Watch out, Radioactive-Man! */
4902 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4903 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4904 + exp->tuple.src.u.tcp.port = 0;
4905 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4906 + exp->tuple.dst.protonum = IPPROTO_TCP;
4908 + exp->mask.src.ip = 0xffffffff;
4909 + exp->mask.dst.ip = 0xffffffff;
4911 + exp->mask.src.u.tcp.port = htons(0xfc00);
4912 + exp->mask.dst.u.tcp.port = htons(0xfc00);
4913 + exp->mask.dst.protonum = 0xffff;
4915 + exp->expectfn = NULL;
4917 + ip_conntrack_expect_related(ct, &expect);
4919 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4920 + NIPQUAD(exp->tuple.src.ip),
4921 + ntohs(exp->tuple.src.u.tcp.port),
4922 + NIPQUAD(exp->tuple.dst.ip),
4923 + ntohs(exp->tuple.dst.u.tcp.port));
4925 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4926 + NIPQUAD(exp->mask.src.ip),
4927 + ntohs(exp->mask.src.u.tcp.port),
4928 + NIPQUAD(exp->mask.dst.ip),
4929 + ntohs(exp->mask.dst.u.tcp.port));
4930 + UNLOCK_BH(&ip_rsh_lock);
4935 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4937 +static void fini(void);
4939 +static int __init init(void)
4942 + static char name[10];
4945 + /* If no port given, default to standard RSH port */
4946 + if (ports[0] == 0)
4947 + ports[0] = RSH_PORT;
4949 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4950 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4952 + if (ports[port] == RSH_PORT)
4953 + sprintf(name, "rsh");
4955 + sprintf(name, "rsh-%d", port);
4957 + rsh_helpers[port].name = name;
4958 + rsh_helpers[port].me = THIS_MODULE;
4959 + rsh_helpers[port].max_expected = 1;
4960 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4961 + rsh_helpers[port].timeout = 0;
4963 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4964 + rsh_helpers[port].mask.dst.protonum = 0xffff;
4966 + /* RSH must come from ports 0:1023 to ports[port] (514) */
4967 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4968 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4969 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4971 + rsh_helpers[port].help = help;
4973 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4974 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4975 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
4976 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4977 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4978 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4979 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4980 + NIPQUAD(rsh_helpers[port].mask.src.ip),
4981 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4982 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
4983 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4985 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4988 + printk("ERROR registering port %d\n",
4998 +/* This function is intentionally _NOT_ defined as __exit, because
4999 + * it is needed by the init function */
5000 +static void fini(void)
5003 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5004 + DEBUGP("unregistering port %d\n", ports[port]);
5005 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
5011 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
5012 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
5013 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-04-30 09:14:05.000000000 +0200
5016 + * RTSP extension for IP connection tracking
5017 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5018 + * based on ip_conntrack_irc.c
5020 + * This program is free software; you can redistribute it and/or
5021 + * modify it under the terms of the GNU General Public License
5022 + * as published by the Free Software Foundation; either version
5023 + * 2 of the License, or (at your option) any later version.
5025 + * Module load syntax:
5026 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5027 + * max_outstanding=n setup_timeout=secs
5029 + * If no ports are specified, the default will be port 554.
5031 + * With max_outstanding you can define the maximum number of not yet
5032 + * answered SETUP requests per RTSP session (default 8).
5033 + * With setup_timeout you can specify how long the system waits for
5034 + * an expected data channel (default 300 seconds).
5037 +#include <linux/config.h>
5038 +#include <linux/module.h>
5039 +#include <linux/netfilter.h>
5040 +#include <linux/ip.h>
5041 +#include <net/checksum.h>
5042 +#include <net/tcp.h>
5044 +#include <linux/netfilter_ipv4/lockhelp.h>
5045 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5046 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5048 +#include <linux/ctype.h>
5049 +#define NF_NEED_STRNCASECMP
5050 +#define NF_NEED_STRTOU16
5051 +#define NF_NEED_STRTOU32
5052 +#define NF_NEED_NEXTLINE
5053 +#include <linux/netfilter_helpers.h>
5054 +#define NF_NEED_MIME_NEXTLINE
5055 +#include <linux/netfilter_mime.h>
5057 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5059 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5060 +#ifdef IP_NF_RTSP_DEBUG
5061 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5063 +#define DEBUGP(fmt, args...)
5066 +#define MAX_PORTS 8
5067 +static int ports[MAX_PORTS];
5068 +static int num_ports = 0;
5069 +static int max_outstanding = 8;
5070 +static unsigned int setup_timeout = 300;
5072 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5073 +MODULE_DESCRIPTION("RTSP connection tracking module");
5074 +MODULE_LICENSE("GPL");
5076 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5077 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5078 +MODULE_PARM(max_outstanding, "i");
5079 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5080 +MODULE_PARM(setup_timeout, "i");
5081 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5084 +DECLARE_LOCK(ip_rtsp_lock);
5085 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5088 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5089 + * of allocated ports is twice this value). Note that SMIL burns a lot of
5090 + * ports so keep this reasonably high. If this is too low, you will see a
5091 + * lot of "no free client map entries" messages.
5093 +#define MAX_PORT_MAPS 16
5095 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5097 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5100 + * Parse an RTSP packet.
5102 + * Returns zero if parsing failed.
5105 + * IN ptcp tcp data pointer
5106 + * IN tcplen tcp data len
5107 + * IN/OUT ptcpoff points to current tcp offset
5108 + * OUT phdrsoff set to offset of rtsp headers
5109 + * OUT phdrslen set to length of rtsp headers
5110 + * OUT pcseqoff set to offset of CSeq header
5111 + * OUT pcseqlen set to length of CSeq header
5114 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5115 + uint* phdrsoff, uint* phdrslen,
5116 + uint* pcseqoff, uint* pcseqlen)
5118 + uint entitylen = 0;
5122 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5127 + *phdrsoff = *ptcpoff;
5128 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5132 + if (entitylen > 0)
5134 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5138 + if (lineoff+linelen > tcplen)
5140 + INFOP("!! overrun !!\n");
5144 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5146 + *pcseqoff = lineoff;
5147 + *pcseqlen = linelen;
5149 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5151 + uint off = lineoff+15;
5152 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
5153 + nf_strtou32(ptcp+off, &entitylen);
5156 + *phdrslen = (*ptcpoff) - (*phdrsoff);
5162 + * Find lo/hi client ports (if any) in transport header
5164 + * ptcp, tcplen = packet
5165 + * tranoff, tranlen = buffer to search
5168 + * pport_lo, pport_hi = lo/hi ports (host endian)
5170 + * Returns nonzero if any client ports found
5172 + * Note: it is valid (and expected) for the client to request multiple
5173 + * transports, so we need to parse the entire line.
5176 +rtsp_parse_transport(char* ptran, uint tranlen,
5177 + struct ip_ct_rtsp_expect* prtspexp)
5182 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5183 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
5185 + INFOP("sanity check failed\n");
5188 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5190 + SKIP_WSPACE(ptran, tranlen, off);
5192 + /* Transport: tran;field;field=val,tran;field;field=val,... */
5193 + while (off < tranlen)
5195 + const char* pparamend;
5196 + uint nextparamoff;
5198 + pparamend = memchr(ptran+off, ',', tranlen-off);
5199 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5200 + nextparamoff = pparamend-ptran;
5202 + while (off < nextparamoff)
5204 + const char* pfieldend;
5205 + uint nextfieldoff;
5207 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5208 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5210 + if (strncmp(ptran+off, "client_port=", 12) == 0)
5216 + numlen = nf_strtou16(ptran+off, &port);
5218 + if (prtspexp->loport != 0 && prtspexp->loport != port)
5220 + DEBUGP("multiple ports found, port %hu ignored\n", port);
5224 + prtspexp->loport = prtspexp->hiport = port;
5225 + if (ptran[off] == '-')
5228 + numlen = nf_strtou16(ptran+off, &port);
5230 + prtspexp->pbtype = pb_range;
5231 + prtspexp->hiport = port;
5233 + // If we have a range, assume rtp:
5234 + // loport must be even, hiport must be loport+1
5235 + if ((prtspexp->loport & 0x0001) != 0 ||
5236 + prtspexp->hiport != prtspexp->loport+1)
5238 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
5239 + prtspexp->loport, prtspexp->hiport);
5240 + prtspexp->loport &= 0xfffe;
5241 + prtspexp->hiport = prtspexp->loport+1;
5244 + else if (ptran[off] == '/')
5247 + numlen = nf_strtou16(ptran+off, &port);
5249 + prtspexp->pbtype = pb_discon;
5250 + prtspexp->hiport = port;
5257 + * Note we don't look for the destination parameter here.
5258 + * If we are using NAT, the NAT module will handle it. If not,
5259 + * and the client is sending packets elsewhere, the expectation
5260 + * will quietly time out.
5263 + off = nextfieldoff;
5266 + off = nextparamoff;
5272 +/*** conntrack functions ***/
5274 +/* outbound packet: client->server */
5276 +help_out(const struct iphdr* iph, size_t pktlen,
5277 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5279 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5280 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5281 + uint tcplen = pktlen - iph->ihl * 4;
5282 + char* pdata = (char*)tcph + tcph->doff * 4;
5283 + uint datalen = tcplen - tcph->doff * 4;
5286 + struct ip_conntrack_expect exp;
5288 + while (dataoff < datalen)
5290 + uint cmdoff = dataoff;
5300 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
5301 + &hdrsoff, &hdrslen,
5302 + &cseqoff, &cseqlen))
5304 + break; /* not a valid message */
5307 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5309 + continue; /* not a SETUP message */
5311 + DEBUGP("found a setup message\n");
5313 + memset(&exp, 0, sizeof(exp));
5316 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5317 + &lineoff, &linelen))
5323 + if (off > hdrsoff+hdrslen)
5325 + INFOP("!! overrun !!");
5329 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5331 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5332 + &exp.help.exp_rtsp_info);
5336 + if (exp.help.exp_rtsp_info.loport == 0)
5338 + DEBUGP("no udp transports found\n");
5339 + continue; /* no udp transports found */
5342 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5343 + (int)exp.help.exp_rtsp_info.pbtype,
5344 + exp.help.exp_rtsp_info.loport,
5345 + exp.help.exp_rtsp_info.hiport);
5347 + LOCK_BH(&ip_rtsp_lock);
5348 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5349 + exp.help.exp_rtsp_info.len = hdrslen;
5351 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5352 + exp.mask.src.ip = 0xffffffff;
5353 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5354 + exp.mask.dst.ip = 0xffffffff;
5355 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5356 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5357 + exp.tuple.dst.protonum = IPPROTO_UDP;
5358 + exp.mask.dst.protonum = 0xffff;
5360 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5361 + NIPQUAD(exp.tuple.src.ip),
5362 + ntohs(exp.tuple.src.u.tcp.port),
5363 + NIPQUAD(exp.tuple.dst.ip),
5364 + ntohs(exp.tuple.dst.u.tcp.port));
5366 + /* pass the request off to the nat helper */
5367 + rc = ip_conntrack_expect_related(ct, &exp);
5368 + UNLOCK_BH(&ip_rtsp_lock);
5371 + DEBUGP("ip_conntrack_expect_related succeeded\n");
5375 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5382 +/* inbound packet: server->client */
5384 +help_in(const struct iphdr* iph, size_t pktlen,
5385 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5391 +help(const struct iphdr* iph, size_t pktlen,
5392 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5394 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5395 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5396 + u_int32_t tcplen = pktlen - iph->ihl * 4;
5398 + /* Until there's been traffic both ways, don't look in packets. */
5399 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5401 + DEBUGP("conntrackinfo = %u\n", ctinfo);
5405 + /* Not whole TCP header? */
5406 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5408 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5412 + /* Checksum invalid? Ignore. */
5413 + /* FIXME: Source route IP option packets --RR */
5414 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5415 + csum_partial((char*)tcph, tcplen, 0)))
5417 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5418 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5422 + switch (CTINFO2DIR(ctinfo))
5424 + case IP_CT_DIR_ORIGINAL:
5425 + help_out(iph, pktlen, ct, ctinfo);
5427 + case IP_CT_DIR_REPLY:
5428 + help_in(iph, pktlen, ct, ctinfo);
5435 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5436 +static char rtsp_names[MAX_PORTS][10];
5438 +/* This function is intentionally _NOT_ defined as __exit */
5443 + for (i = 0; i < num_ports; i++)
5445 + DEBUGP("unregistering port %d\n", ports[i]);
5446 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5454 + struct ip_conntrack_helper *hlpr;
5457 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5459 + if (max_outstanding < 1)
5461 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5464 + if (setup_timeout < 0)
5466 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5470 + /* If no port given, default to standard rtsp port */
5471 + if (ports[0] == 0)
5473 + ports[0] = RTSP_PORT;
5476 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5478 + hlpr = &rtsp_helpers[i];
5479 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5480 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5481 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
5482 + hlpr->mask.src.u.tcp.port = 0xFFFF;
5483 + hlpr->mask.dst.protonum = 0xFFFF;
5484 + hlpr->max_expected = max_outstanding;
5485 + hlpr->timeout = setup_timeout;
5486 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5487 + hlpr->me = ip_conntrack_rtsp;
5488 + hlpr->help = help;
5490 + tmpname = &rtsp_names[i][0];
5491 + if (ports[i] == RTSP_PORT)
5493 + sprintf(tmpname, "rtsp");
5497 + sprintf(tmpname, "rtsp-%d", i);
5499 + hlpr->name = tmpname;
5501 + DEBUGP("port #%d: %d\n", i, ports[i]);
5503 + ret = ip_conntrack_helper_register(hlpr);
5507 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5516 +#ifdef CONFIG_IP_NF_NAT_NEEDED
5517 +EXPORT_SYMBOL(ip_rtsp_lock);
5522 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
5523 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-28 03:35:45.000000000 +0200
5524 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-30 09:12:41.000000000 +0200
5526 len += sprintf(buffer + len, "[ASSURED] ");
5527 len += sprintf(buffer + len, "use=%u ",
5528 atomic_read(&conntrack->ct_general.use));
5529 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5530 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5532 len += sprintf(buffer + len, "\n");
5536 EXPORT_SYMBOL(ip_conntrack_alter_reply);
5537 EXPORT_SYMBOL(ip_conntrack_destroyed);
5538 EXPORT_SYMBOL(ip_conntrack_get);
5539 +EXPORT_SYMBOL(__ip_conntrack_confirm);
5540 EXPORT_SYMBOL(need_ip_conntrack);
5541 EXPORT_SYMBOL(ip_conntrack_helper_register);
5542 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5543 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
5544 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
5545 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-04-30 09:14:39.000000000 +0200
5548 + * talk extension for IP connection tracking.
5549 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5551 + * This program is free software; you can redistribute it and/or
5552 + * modify it under the terms of the GNU General Public License
5553 + * as published by the Free Software Foundation; either version
5554 + * 2 of the License, or (at your option) any later version.
5556 + * Module load syntax:
5557 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5559 + * talk=[0|1] disable|enable old talk support
5560 + * ntalk=[0|1] disable|enable ntalk support
5561 + * ntalk2=[0|1] disable|enable ntalk2 support
5563 + * The default is talk=1 ntalk=1 ntalk2=1
5565 + * The helper does not support simultaneous talk requests.
5568 + * ASCII art on talk protocols
5571 + * caller server callee server
5578 + * caller client ----------- callee client
5581 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
5582 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5583 + * 3. callee client <-> caller server: LOOK_UP invitation
5584 + * 4. callee client <-> caller client: talk data channel
5586 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
5587 + * draft-hunter-talk-00.txt
5588 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
5590 +#include <linux/config.h>
5591 +#include <linux/module.h>
5592 +#include <linux/netfilter.h>
5593 +#include <linux/ip.h>
5594 +#include <net/checksum.h>
5595 +#include <net/udp.h>
5597 +#include <linux/netfilter_ipv4/lockhelp.h>
5598 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5599 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5600 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5601 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5603 +/* Default all talk protocols are supported */
5604 +static int talk = 1;
5605 +static int ntalk = 1;
5606 +static int ntalk2 = 1;
5607 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5608 +MODULE_DESCRIPTION("talk connection tracking module");
5609 +MODULE_LICENSE("GPL");
5611 +MODULE_PARM(talk, "i");
5612 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5613 +MODULE_PARM(ntalk, "i");
5614 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5615 +MODULE_PARM(ntalk2, "i");
5616 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5619 +DECLARE_LOCK(ip_talk_lock);
5620 +struct module *ip_conntrack_talk = THIS_MODULE;
5623 +#define DEBUGP printk
5625 +#define DEBUGP(format, args...)
5628 +static int talk_expect(struct ip_conntrack *ct);
5629 +static int ntalk_expect(struct ip_conntrack *ct);
5631 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5633 +static int talk_help_response(const struct iphdr *iph, size_t len,
5634 + struct ip_conntrack *ct,
5635 + enum ip_conntrack_info ctinfo,
5640 + struct talk_addr *addr)
5642 + int dir = CTINFO2DIR(ctinfo);
5643 + struct ip_conntrack_expect expect, *exp = &expect;
5644 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5646 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5647 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5650 + if (!(answer == SUCCESS && type == mode))
5653 + memset(&expect, 0, sizeof(expect));
5655 + if (type == ANNOUNCE) {
5657 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5659 + /* update the talk info */
5660 + LOCK_BH(&ip_talk_lock);
5661 + exp_talk_info->port = htons(talk_port);
5663 + /* expect callee client -> caller server message */
5664 + exp->tuple = ((struct ip_conntrack_tuple)
5665 + { { ct->tuplehash[dir].tuple.src.ip,
5667 + { ct->tuplehash[dir].tuple.dst.ip,
5668 + { .tcp = { htons(talk_port) } },
5670 + exp->mask = ((struct ip_conntrack_tuple)
5671 + { { 0xFFFFFFFF, { 0 } },
5672 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5674 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5676 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5677 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5678 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5680 + /* Ignore failure; should only happen with NAT */
5681 + ip_conntrack_expect_related(ct, &expect);
5682 + UNLOCK_BH(&ip_talk_lock);
5684 + if (type == LOOK_UP) {
5686 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5688 + /* update the talk info */
5689 + LOCK_BH(&ip_talk_lock);
5690 + exp_talk_info->port = addr->ta_port;
5692 + /* expect callee client -> caller client connection */
5693 + exp->tuple = ((struct ip_conntrack_tuple)
5694 + { { ct->tuplehash[!dir].tuple.src.ip,
5697 + { addr->ta_port },
5699 + exp->mask = ((struct ip_conntrack_tuple)
5700 + { { 0xFFFFFFFF, { 0 } },
5701 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5703 + exp->expectfn = NULL;
5705 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5706 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5707 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5709 + /* Ignore failure; should only happen with NAT */
5710 + ip_conntrack_expect_related(ct, &expect);
5711 + UNLOCK_BH(&ip_talk_lock);
5717 +/* FIXME: This should be in userspace. Later. */
5718 +static int talk_help(const struct iphdr *iph, size_t len,
5719 + struct ip_conntrack *ct,
5720 + enum ip_conntrack_info ctinfo,
5724 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5725 + const char *data = (const char *)udph + sizeof(struct udphdr);
5726 + int dir = CTINFO2DIR(ctinfo);
5729 + DEBUGP("ip_ct_talk_help: help entered\n");
5731 + /* Until there's been traffic both ways, don't look in packets. */
5732 + if (ctinfo != IP_CT_ESTABLISHED
5733 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5734 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5738 + /* Not whole UDP header? */
5739 + udplen = len - iph->ihl * 4;
5740 + if (udplen < sizeof(struct udphdr)) {
5741 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5745 + /* Checksum invalid? Ignore. */
5746 + /* FIXME: Source route IP option packets --RR */
5747 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5748 + csum_partial((char *)udph, udplen, 0))) {
5749 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5750 + udph, udplen, NIPQUAD(iph->saddr),
5751 + NIPQUAD(iph->daddr));
5755 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5756 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5758 + if (dir == IP_CT_DIR_ORIGINAL)
5761 + if (talk_port == TALK_PORT
5762 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5763 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5764 + ((struct talk_response *)data)->type,
5765 + ((struct talk_response *)data)->answer,
5766 + &(((struct talk_response *)data)->addr));
5767 + else if (talk_port == NTALK_PORT
5769 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5770 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5771 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5772 + ((struct ntalk_response *)data)->type,
5773 + ((struct ntalk_response *)data)->answer,
5774 + &(((struct ntalk_response *)data)->addr));
5775 + else if (talk_port == NTALK_PORT
5777 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5778 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5779 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5780 + ((struct ntalk2_response *)data)->type,
5781 + ((struct ntalk2_response *)data)->answer,
5782 + &(((struct ntalk2_response *)data)->addr));
5784 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
5785 + (unsigned)udplen - sizeof(struct udphdr),
5786 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5791 +static int lookup_help(const struct iphdr *iph, size_t len,
5792 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5794 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5797 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
5798 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5800 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5803 +static struct ip_conntrack_helper lookup_helpers[2] =
5804 + { { { NULL, NULL },
5805 + "talk", /* name */
5807 + NULL, /* module */
5808 + 1, /* max_expected */
5809 + 240, /* timeout */
5810 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5811 + { 0, { 0 }, IPPROTO_UDP } },
5812 + { { 0, { 0xFFFF } }, /* mask */
5813 + { 0, { 0 }, 0xFFFF } },
5814 + lookup_help }, /* helper */
5816 + "ntalk", /* name */
5818 + NULL, /* module */
5819 + 1, /* max_expected */
5820 + 240, /* timeout */
5821 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5822 + { 0, { 0 }, IPPROTO_UDP } },
5823 + { { 0, { 0xFFFF } }, /* mask */
5824 + { 0, { 0 }, 0xFFFF } },
5825 + lookup_nhelp } /* helper */
5828 +static int talk_expect(struct ip_conntrack *ct)
5830 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5831 + WRITE_LOCK(&ip_conntrack_lock);
5832 + ct->helper = &lookup_helpers[0];
5833 + WRITE_UNLOCK(&ip_conntrack_lock);
5835 + return NF_ACCEPT; /* unused */
5838 +static int ntalk_expect(struct ip_conntrack *ct)
5840 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5841 + WRITE_LOCK(&ip_conntrack_lock);
5842 + ct->helper = &lookup_helpers[1];
5843 + WRITE_UNLOCK(&ip_conntrack_lock);
5845 + return NF_ACCEPT; /* unused */
5848 +static int help(const struct iphdr *iph, size_t len,
5849 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5851 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5854 +static int nhelp(const struct iphdr *iph, size_t len,
5855 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5857 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5860 +static struct ip_conntrack_helper talk_helpers[2] =
5861 + { { { NULL, NULL },
5862 + "talk", /* name */
5864 + THIS_MODULE, /* module */
5865 + 1, /* max_expected */
5866 + 240, /* timeout */
5867 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5868 + { 0, { 0 }, IPPROTO_UDP } },
5869 + { { 0, { 0xFFFF } }, /* mask */
5870 + { 0, { 0 }, 0xFFFF } },
5871 + help }, /* helper */
5873 + "ntalk", /* name */
5875 + THIS_MODULE, /* module */
5876 + 1, /* max_expected */
5877 + 240, /* timeout */
5878 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5879 + { 0, { 0 }, IPPROTO_UDP } },
5880 + { { 0, { 0xFFFF } }, /* mask */
5881 + { 0, { 0 }, 0xFFFF } },
5882 + nhelp } /* helper */
5885 +static int __init init(void)
5888 + ip_conntrack_helper_register(&talk_helpers[0]);
5889 + if (ntalk > 0 || ntalk2 > 0)
5890 + ip_conntrack_helper_register(&talk_helpers[1]);
5895 +static void __exit fini(void)
5898 + ip_conntrack_helper_unregister(&talk_helpers[0]);
5899 + if (ntalk > 0 || ntalk2 > 0)
5900 + ip_conntrack_helper_unregister(&talk_helpers[1]);
5903 +EXPORT_SYMBOL(ip_talk_lock);
5907 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c
5908 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c 2004-04-28 03:35:10.000000000 +0200
5909 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c 2004-04-30 09:09:25.000000000 +0200
5912 /* Have to grab read lock before sibling_list traversal */
5913 READ_LOCK(&ip_conntrack_lock);
5914 - list_for_each(cur_item, &ct->sibling_list) {
5915 + list_for_each_prev(cur_item, &ct->sibling_list) {
5916 exp = list_entry(cur_item, struct ip_conntrack_expect,
5919 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c
5920 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
5921 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-04-30 09:12:34.000000000 +0200
5924 + * H.323 'brute force' extension for NAT alteration.
5925 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5927 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
5928 + * (http://www.coritel.it/projects/sofia/nat.html)
5929 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
5930 + * the unregistered helpers to the conntrack entries.
5934 +#include <linux/module.h>
5935 +#include <linux/netfilter.h>
5936 +#include <linux/ip.h>
5937 +#include <net/checksum.h>
5938 +#include <net/tcp.h>
5940 +#include <linux/netfilter_ipv4/lockhelp.h>
5941 +#include <linux/netfilter_ipv4/ip_nat.h>
5942 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5943 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5944 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5945 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5946 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
5948 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5949 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
5950 +MODULE_LICENSE("GPL");
5952 +DECLARE_LOCK_EXTERN(ip_h323_lock);
5953 +struct module *ip_nat_h323 = THIS_MODULE;
5956 +#define DEBUGP printk
5958 +#define DEBUGP(format, args...)
5961 +/* FIXME: Time out? --RR */
5963 +static unsigned int
5964 +h225_nat_expected(struct sk_buff **pskb,
5965 + unsigned int hooknum,
5966 + struct ip_conntrack *ct,
5967 + struct ip_nat_info *info);
5969 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5970 + struct ip_conntrack_expect *exp,
5971 + struct ip_nat_info *info,
5972 + enum ip_conntrack_info ctinfo,
5973 + unsigned int hooknum,
5974 + struct sk_buff **pskb);
5976 +static struct ip_nat_helper h245 =
5978 + "H.245", /* name */
5980 + NULL, /* module */
5981 + { { 0, { 0 } }, /* tuple */
5982 + { 0, { 0 }, IPPROTO_TCP } },
5983 + { { 0, { 0xFFFF } }, /* mask */
5984 + { 0, { 0 }, 0xFFFF } },
5985 + h225_nat_help, /* helper */
5986 + h225_nat_expected /* expectfn */
5989 +static unsigned int
5990 +h225_nat_expected(struct sk_buff **pskb,
5991 + unsigned int hooknum,
5992 + struct ip_conntrack *ct,
5993 + struct ip_nat_info *info)
5995 + struct ip_nat_multi_range mr;
5996 + u_int32_t newdstip, newsrcip, newip;
5998 + struct ip_ct_h225_expect *exp_info;
5999 + struct ip_ct_h225_master *master_info;
6000 + struct ip_conntrack *master = master_ct(ct);
6001 + unsigned int is_h225, ret;
6003 + IP_NF_ASSERT(info);
6004 + IP_NF_ASSERT(master);
6006 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6008 + DEBUGP("h225_nat_expected: We have a connection!\n");
6009 + master_info = &ct->master->expectant->help.ct_h225_info;
6010 + exp_info = &ct->master->help.exp_h225_info;
6012 + LOCK_BH(&ip_h323_lock);
6014 + DEBUGP("master: ");
6015 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6016 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6017 + DEBUGP("conntrack: ");
6018 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6019 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6020 + /* Make connection go to the client. */
6021 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6022 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6023 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6024 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6026 + /* Make the connection go to the server */
6027 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6028 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6029 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6030 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6032 + port = exp_info->port;
6033 + is_h225 = master_info->is_h225 == H225_PORT;
6034 + UNLOCK_BH(&ip_h323_lock);
6036 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6041 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6044 + /* We don't want to manip the per-protocol, just the IPs... */
6045 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6046 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6048 + /* ... unless we're doing a MANIP_DST, in which case, make
6049 + sure we map to the correct port */
6050 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6051 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6052 + mr.range[0].min = mr.range[0].max
6053 + = ((union ip_conntrack_manip_proto)
6054 + { .tcp = { port } });
6057 + ret = ip_nat_setup_info(ct, &mr, hooknum);
6060 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6061 + /* NAT expectfn called with ip_nat_lock write-locked */
6062 + info->helper = &h245;
6067 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6068 + struct sk_buff **pskb,
6069 + enum ip_conntrack_info ctinfo)
6071 + struct iphdr *iph = (*pskb)->nh.iph;
6072 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6073 + char *data = (char *) tcph + tcph->doff * 4;
6074 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6075 + u_int32_t datalen = tcplen - tcph->doff*4;
6076 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6081 + MUST_BE_LOCKED(&ip_h323_lock);
6083 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6084 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6086 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6088 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6089 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6092 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6093 + info->offset[IP_CT_DIR_ORIGINAL],
6094 + info->offset[IP_CT_DIR_REPLY],
6096 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6097 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6099 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
6100 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6101 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6102 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6103 + if (!between(info->seq[i], ntohl(tcph->seq),
6104 + ntohl(tcph->seq) + datalen))
6106 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6107 + ntohl(tcph->seq) + datalen)) {
6108 + /* Partial retransmisison. It's a cracker being funky. */
6109 + if (net_ratelimit()) {
6110 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6113 + ntohl(tcph->seq) + datalen);
6118 + /* Change address inside packet to match way we're mapping
6119 + this connection. */
6120 + if (i == IP_CT_DIR_ORIGINAL) {
6121 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6122 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6124 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
6125 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6128 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6129 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6130 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6131 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6133 + /* Modify the packet */
6134 + *(u_int32_t *)(data + info->offset[i]) = newip;
6135 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
6137 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6138 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6139 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6140 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6143 + /* fix checksum information */
6145 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6149 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6150 + csum_partial((char *)tcph, tcph->doff*4,
6152 + ip_send_check(iph);
6157 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6158 + struct ip_conntrack *ct,
6159 + struct sk_buff **pskb,
6160 + enum ip_conntrack_info ctinfo,
6161 + struct ip_conntrack_expect *expect)
6165 + struct ip_conntrack_tuple newtuple;
6166 + struct iphdr *iph = (*pskb)->nh.iph;
6167 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6168 + char *data = (char *) tcph + tcph->doff * 4;
6169 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6170 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6173 + MUST_BE_LOCKED(&ip_h323_lock);
6174 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6175 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6176 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6178 + if (!between(expect->seq + 6, ntohl(tcph->seq),
6179 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6180 + /* Partial retransmisison. It's a cracker being funky. */
6181 + if (net_ratelimit()) {
6182 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6185 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6190 + /* Change address inside packet to match way we're mapping
6191 + this connection. */
6192 + if (info->dir == IP_CT_DIR_REPLY) {
6193 + /* Must be where client thinks server is */
6194 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6195 + /* Expect something from client->server */
6196 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6197 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6199 + /* Must be where server thinks client is */
6200 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6201 + /* Expect something from server->client */
6202 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6203 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6206 + is_h225 = (master_info->is_h225 == H225_PORT);
6209 + newtuple.dst.protonum = IPPROTO_TCP;
6210 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6212 + newtuple.dst.protonum = IPPROTO_UDP;
6213 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6216 + /* Try to get same port: if not, try to change it. */
6217 + for (port = ntohs(info->port); port != 0; port++) {
6219 + newtuple.dst.u.tcp.port = htons(port);
6221 + newtuple.dst.u.udp.port = htons(port);
6223 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6227 + DEBUGP("h323_data_fixup: no free port found!\n");
6231 + port = htons(port);
6233 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6234 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6235 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6237 + /* Modify the packet */
6238 + *(u_int32_t *)(data + info->offset) = newip;
6239 + *(u_int16_t *)(data + info->offset + 4) = port;
6241 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6242 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6243 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6245 + /* fix checksum information */
6246 + /* FIXME: usually repeated multiple times in the case of H.245! */
6248 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6249 + tcplen - tcph->doff*4, 0);
6252 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6253 + csum_partial((char *)tcph, tcph->doff*4,
6255 + ip_send_check(iph);
6260 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6261 + struct ip_conntrack_expect *exp,
6262 + struct ip_nat_info *info,
6263 + enum ip_conntrack_info ctinfo,
6264 + unsigned int hooknum,
6265 + struct sk_buff **pskb)
6268 + struct ip_ct_h225_expect *exp_info;
6270 + /* Only mangle things once: original direction in POST_ROUTING
6271 + and reply direction on PRE_ROUTING. */
6272 + dir = CTINFO2DIR(ctinfo);
6273 + DEBUGP("nat_h323: dir %s at hook %s\n",
6274 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6275 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6276 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6277 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6278 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6279 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6280 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6281 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6282 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6283 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6284 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6289 + LOCK_BH(&ip_h323_lock);
6290 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6291 + UNLOCK_BH(&ip_h323_lock);
6294 + UNLOCK_BH(&ip_h323_lock);
6298 + exp_info = &exp->help.exp_h225_info;
6300 + LOCK_BH(&ip_h323_lock);
6301 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6302 + UNLOCK_BH(&ip_h323_lock);
6305 + UNLOCK_BH(&ip_h323_lock);
6310 +static struct ip_nat_helper h225 =
6312 + "H.225", /* name */
6313 + IP_NAT_HELPER_F_ALWAYS, /* flags */
6314 + THIS_MODULE, /* module */
6315 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6316 + { 0, { 0 }, IPPROTO_TCP } },
6317 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6318 + { 0, { 0 }, 0xFFFF } },
6319 + h225_nat_help, /* helper */
6320 + h225_nat_expected /* expectfn */
6323 +static int __init init(void)
6327 + ret = ip_nat_helper_register(&h225);
6330 + printk("ip_nat_h323: cannot initialize the module!\n");
6335 +static void __exit fini(void)
6337 + ip_nat_helper_unregister(&h225);
6342 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c
6343 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6344 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-04-30 09:12:58.000000000 +0200
6346 +/* MMS extension for TCP NAT alteration.
6347 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6348 + * based on ip_nat_ftp.c and ip_nat_irc.c
6350 + * ip_nat_mms.c v0.3 2002-09-22
6352 + * This program is free software; you can redistribute it and/or
6353 + * modify it under the terms of the GNU General Public License
6354 + * as published by the Free Software Foundation; either version
6355 + * 2 of the License, or (at your option) any later version.
6357 + * Module load syntax:
6358 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6360 + * Please give the ports of all MMS servers You wish to connect to.
6361 + * If you don't specify ports, the default will be TCP port 1755.
6363 + * More info on MMS protocol, firewalls and NAT:
6364 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6365 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6367 + * The SDP project people are reverse-engineering MMS:
6368 + * http://get.to/sdp
6371 +/* FIXME: issue with UDP & fragmentation with this URL:
6372 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6373 + may be related to out-of-order first packets:
6374 + basically the expectation is set up correctly, then the server sends
6375 + a first UDP packet which is fragmented plus arrives out-of-order.
6376 + the MASQUERADING firewall with ip_nat_mms loaded responds with
6377 + an ICMP unreachable back to the server */
6379 +#include <linux/module.h>
6380 +#include <linux/netfilter_ipv4.h>
6381 +#include <linux/ip.h>
6382 +#include <linux/tcp.h>
6383 +#include <net/tcp.h>
6384 +#include <linux/netfilter_ipv4/ip_nat.h>
6385 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6386 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6387 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6388 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6391 +#define DEBUGP printk
6392 +#define DUMP_BYTES(address, counter) \
6394 + int temp_counter; \
6395 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6396 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
6401 +#define DEBUGP(format, args...)
6402 +#define DUMP_BYTES(address, counter)
6405 +#define MAX_PORTS 8
6406 +static int ports[MAX_PORTS];
6407 +static int ports_c = 0;
6410 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6413 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6414 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6415 +MODULE_LICENSE("GPL");
6417 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6419 +/* FIXME: Time out? --RR */
6421 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6422 + struct ip_conntrack *ct,
6423 + struct sk_buff **pskb,
6424 + enum ip_conntrack_info ctinfo,
6425 + struct ip_conntrack_expect *expect)
6428 + struct ip_conntrack_tuple t;
6429 + struct iphdr *iph = (*pskb)->nh.iph;
6430 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6431 + char *data = (char *)tcph + tcph->doff * 4;
6432 + int i, j, k, port;
6433 + u_int16_t mms_proto;
6435 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6436 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6437 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6441 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6442 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6443 + char proto_string[6];
6445 + MUST_BE_LOCKED(&ip_mms_lock);
6447 + /* what was the protocol again ? */
6448 + mms_proto = expect->tuple.dst.protonum;
6449 + sprintf(proto_string, "%u", mms_proto);
6451 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6452 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6453 + mms_proto == IPPROTO_UDP ? "UDP"
6454 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6456 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6458 + /* Alter conntrack's expectations. */
6459 + t = expect->tuple;
6461 + for (port = ct_mms_info->port; port != 0; port++) {
6462 + t.dst.u.tcp.port = htons(port);
6463 + if (ip_conntrack_change_expect(expect, &t) == 0) {
6464 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6472 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6474 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6475 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6477 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6479 + memset(unicode_buffer, 0, sizeof(char)*75);
6481 + for (i=0; i<strlen(buffer); ++i)
6482 + *(unicode_buffer+i*2)=*(buffer+i);
6484 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6485 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6486 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6488 + /* add end of packet to it */
6489 + for (j=0; j<ct_mms_info->padding; ++j) {
6490 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6491 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6492 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6495 + /* pad with zeroes at the end ? see explanation of weird math below */
6496 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6497 + for (k=0; k<zero_padding; ++k)
6498 + *(unicode_buffer+i*2+j+k)= (char)0;
6500 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6501 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6502 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6504 + /* explanation, before I forget what I did:
6505 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6506 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
6507 + but note that things may have to be padded with zeroes to align by 8
6508 + bytes, hence we add 7 and divide by 8 to get the correct length */
6509 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6510 + *mms_chunkLenLV = *mms_chunkLenLM+2;
6511 + *mms_messageLength = *mms_chunkLenLV*8;
6513 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6514 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6516 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6517 + expect->seq - ntohl(tcph->seq),
6518 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6519 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6520 + DUMP_BYTES(unicode_buffer, 60);
6525 +static unsigned int
6526 +mms_nat_expected(struct sk_buff **pskb,
6527 + unsigned int hooknum,
6528 + struct ip_conntrack *ct,
6529 + struct ip_nat_info *info)
6531 + struct ip_nat_multi_range mr;
6532 + u_int32_t newdstip, newsrcip, newip;
6534 + struct ip_conntrack *master = master_ct(ct);
6536 + IP_NF_ASSERT(info);
6537 + IP_NF_ASSERT(master);
6539 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6541 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6543 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6544 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6545 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6546 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6547 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6548 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6549 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6551 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6556 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6559 + /* We don't want to manip the per-protocol, just the IPs. */
6560 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6561 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6563 + return ip_nat_setup_info(ct, &mr, hooknum);
6567 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6568 + struct ip_conntrack_expect *exp,
6569 + struct ip_nat_info *info,
6570 + enum ip_conntrack_info ctinfo,
6571 + unsigned int hooknum,
6572 + struct sk_buff **pskb)
6574 + struct iphdr *iph = (*pskb)->nh.iph;
6575 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6576 + unsigned int datalen;
6578 + struct ip_ct_mms_expect *ct_mms_info;
6581 + DEBUGP("ip_nat_mms: no exp!!");
6583 + ct_mms_info = &exp->help.exp_mms_info;
6585 + /* Only mangle things once: original direction in POST_ROUTING
6586 + and reply direction on PRE_ROUTING. */
6587 + dir = CTINFO2DIR(ctinfo);
6588 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6589 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6590 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6591 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6592 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6593 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6594 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6597 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6598 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6599 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6600 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6601 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6603 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6605 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6606 + exp->seq + ct_mms_info->len,
6608 + ntohl(tcph->seq) + datalen);
6610 + LOCK_BH(&ip_mms_lock);
6611 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
6612 + if (between(exp->seq + ct_mms_info->len,
6614 + ntohl(tcph->seq) + datalen)) {
6615 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6616 + UNLOCK_BH(&ip_mms_lock);
6620 + /* Half a match? This means a partial retransmisison.
6621 + It's a cracker being funky. */
6622 + if (net_ratelimit()) {
6623 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6624 + exp->seq, ct_mms_info->len,
6626 + ntohl(tcph->seq) + datalen);
6628 + UNLOCK_BH(&ip_mms_lock);
6631 + UNLOCK_BH(&ip_mms_lock);
6636 +static struct ip_nat_helper mms[MAX_PORTS];
6637 +static char mms_names[MAX_PORTS][10];
6639 +/* Not __exit: called from init() */
6640 +static void fini(void)
6644 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6645 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6646 + ip_nat_helper_unregister(&mms[i]);
6650 +static int __init init(void)
6655 + if (ports[0] == 0)
6656 + ports[0] = MMS_PORT;
6658 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6660 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6662 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
6663 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6664 + mms[i].mask.dst.protonum = 0xFFFF;
6665 + mms[i].mask.src.u.tcp.port = 0xFFFF;
6666 + mms[i].help = mms_nat_help;
6667 + mms[i].me = THIS_MODULE;
6669 + mms[i].expect = mms_nat_expected;
6671 + tmpname = &mms_names[i][0];
6672 + if (ports[i] == MMS_PORT)
6673 + sprintf(tmpname, "mms");
6675 + sprintf(tmpname, "mms-%d", i);
6676 + mms[i].name = tmpname;
6678 + DEBUGP("ip_nat_mms: register helper for port %d\n",
6680 + ret = ip_nat_helper_register(&mms[i]);
6683 + printk("ip_nat_mms: error registering "
6684 + "helper for port %d\n", ports[i]);
6696 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6697 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
6698 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-04-30 09:13:29.000000000 +0200
6700 +/* Quake3 extension for UDP NAT alteration.
6701 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6702 + * based on ip_nat_ftp.c and ip_nat_tftp.c
6704 + * ip_nat_quake3.c v0.0.3 2002-08-31
6706 + * This program is free software; you can redistribute it and/or
6707 + * modify it under the terms of the GNU General Public License
6708 + * as published by the Free Software Foundation; either version
6709 + * 2 of the License, or (at your option) any later version.
6711 + * Module load syntax:
6712 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6714 + * please give the ports of all Quake3 master servers You wish to
6715 + * connect to. If you don't specify ports, the default will be UDP
6718 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6721 + * - If you're one of those people who would try anything to lower
6722 + * latency while playing Quake (and who isn't :-) ), you may want to
6723 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
6724 + * outgoing UDP traffic.
6725 + * This will make ip_conntrack_quake3 add the necessary expectations,
6726 + * but there will be no overhead for client->server UDP streams. If
6727 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6728 + * hook for every packet in the client->server UDP stream.
6729 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6730 + * The IP addresses in the master connection payload (=IP addresses
6731 + * of Quake servers) have no relation with the master server so
6732 + * DNAT'ing the master connection to a server should not change the
6733 + * expected connections.
6734 + * - Not tested due to lack of equipment:
6735 + * - multiple Quake3 clients behind one MASQUERADE gateway
6736 + * - what if Quake3 client is running on router too
6739 +#include <linux/module.h>
6740 +#include <linux/netfilter_ipv4.h>
6741 +#include <linux/ip.h>
6742 +#include <linux/udp.h>
6744 +#include <linux/netfilter.h>
6745 +#include <linux/netfilter_ipv4/ip_tables.h>
6746 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6747 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6748 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6749 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6751 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6752 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6753 +MODULE_LICENSE("GPL");
6755 +#define MAX_PORTS 8
6757 +static int ports[MAX_PORTS];
6758 +static int ports_c = 0;
6760 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
6761 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
6764 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
6765 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
6767 +#define DEBUGP printk
6769 +#define DEBUGP(format, args...)
6772 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
6774 +static unsigned int
6775 +quake3_nat_help(struct ip_conntrack *ct,
6776 + struct ip_conntrack_expect *exp,
6777 + struct ip_nat_info *info,
6778 + enum ip_conntrack_info ctinfo,
6779 + unsigned int hooknum,
6780 + struct sk_buff **pskb)
6782 + struct iphdr *iph = (*pskb)->nh.iph;
6783 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6784 + struct ip_conntrack_tuple repl;
6785 + int dir = CTINFO2DIR(ctinfo);
6788 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
6789 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6790 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6791 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6792 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6794 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6795 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6797 + /* Only mangle things once: original direction in POST_ROUTING
6798 + and reply direction on PRE_ROUTING. */
6799 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6800 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6801 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
6802 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6803 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6804 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6805 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6810 + DEBUGP("no conntrack expectation to modify\n");
6814 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
6815 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
6816 + i+6 < ntohs(udph->len);
6818 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
6819 + i, ntohs(udph->len),
6820 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
6821 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
6823 + memset(&repl, 0, sizeof(repl));
6825 + repl.dst.protonum = IPPROTO_UDP;
6826 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6827 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
6828 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
6830 + ip_conntrack_change_expect(exp, &repl);
6836 +static unsigned int
6837 +quake3_nat_expected(struct sk_buff **pskb,
6838 + unsigned int hooknum,
6839 + struct ip_conntrack *ct,
6840 + struct ip_nat_info *info)
6842 + const struct ip_conntrack *master = ct->master->expectant;
6843 + struct ip_nat_multi_range mr;
6844 + u_int32_t newsrcip, newdstip, newip;
6846 + const struct ip_conntrack_tuple *repl =
6847 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
6848 + struct iphdr *iph = (*pskb)->nh.iph;
6849 + struct udphdr *udph = (void *)iph + iph->ihl*4;
6852 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
6853 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6855 + IP_NF_ASSERT(info);
6856 + IP_NF_ASSERT(master);
6857 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6859 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6860 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6862 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
6864 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6865 + "newsrc: %u.%u.%u.%u\n",
6866 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6867 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6868 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6869 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6870 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6875 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6876 + "newdst: %u.%u.%u.%u\n",
6877 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6878 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6879 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6880 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6881 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6886 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6887 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6889 + return ip_nat_setup_info(ct,&mr,hooknum);
6892 +static struct ip_nat_helper quake3[MAX_PORTS];
6893 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
6895 +static void fini(void)
6899 + for (i = 0 ; i < ports_c; i++) {
6900 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
6901 + ip_nat_helper_unregister(&quake3[i]);
6905 +static int __init init(void)
6911 + ports[0] = QUAKE3_MASTER_PORT;
6913 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6914 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
6916 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
6917 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
6918 + quake3[i].mask.dst.protonum = 0xFFFF;
6919 + quake3[i].mask.src.u.udp.port = 0xFFFF;
6920 + quake3[i].help = quake3_nat_help;
6921 + quake3[i].flags = 0;
6922 + quake3[i].me = THIS_MODULE;
6923 + quake3[i].expect = quake3_nat_expected;
6925 + tmpname = &quake3_names[i][0];
6926 + if (ports[i] == QUAKE3_MASTER_PORT)
6927 + sprintf(tmpname, "quake3");
6929 + sprintf(tmpname, "quake3-%d", i);
6930 + quake3[i].name = tmpname;
6932 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
6933 + ports[i], quake3[i].name);
6934 + ret = ip_nat_helper_register(&quake3[i]);
6937 + printk("ip_nat_quake3: unable to register helper for port %d\n",
6949 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
6950 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
6951 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-04-30 09:14:05.000000000 +0200
6954 + * RTSP extension for TCP NAT alteration
6955 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6956 + * based on ip_nat_irc.c
6958 + * This program is free software; you can redistribute it and/or
6959 + * modify it under the terms of the GNU General Public License
6960 + * as published by the Free Software Foundation; either version
6961 + * 2 of the License, or (at your option) any later version.
6963 + * Module load syntax:
6964 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6965 + * stunaddr=<address>
6966 + * destaction=[auto|strip|none]
6968 + * If no ports are specified, the default will be port 554 only.
6970 + * stunaddr specifies the address used to detect that a client is using STUN.
6971 + * If this address is seen in the destination parameter, it is assumed that
6972 + * the client has already punched a UDP hole in the firewall, so we don't
6973 + * mangle the client_port. If none is specified, it is autodetected. It
6974 + * only needs to be set if you have multiple levels of NAT. It should be
6975 + * set to the external address that the STUN clients detect. Note that in
6976 + * this case, it will not be possible for clients to use UDP with servers
6977 + * between the NATs.
6979 + * If no destaction is specified, auto is used.
6980 + * destaction=auto: strip destination parameter if it is not stunaddr.
6981 + * destaction=strip: always strip destination parameter (not recommended).
6982 + * destaction=none: do not touch destination parameter (not recommended).
6985 +#include <linux/module.h>
6986 +#include <linux/netfilter_ipv4.h>
6987 +#include <linux/ip.h>
6988 +#include <linux/tcp.h>
6989 +#include <linux/kernel.h>
6990 +#include <net/tcp.h>
6991 +#include <linux/netfilter_ipv4/ip_nat.h>
6992 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6993 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6994 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6995 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6997 +#include <linux/inet.h>
6998 +#include <linux/ctype.h>
6999 +#define NF_NEED_STRNCASECMP
7000 +#define NF_NEED_STRTOU16
7001 +#include <linux/netfilter_helpers.h>
7002 +#define NF_NEED_MIME_NEXTLINE
7003 +#include <linux/netfilter_mime.h>
7005 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7006 +#ifdef IP_NF_RTSP_DEBUG
7007 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7009 +#define DEBUGP(fmt, args...)
7012 +#define MAX_PORTS 8
7013 +#define DSTACT_AUTO 0
7014 +#define DSTACT_STRIP 1
7015 +#define DSTACT_NONE 2
7017 +static int ports[MAX_PORTS];
7018 +static char* stunaddr = NULL;
7019 +static char* destaction = NULL;
7021 +static int num_ports = 0;
7022 +static u_int32_t extip = 0;
7023 +static int dstact = 0;
7025 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7026 +MODULE_DESCRIPTION("RTSP network address translation module");
7027 +MODULE_LICENSE("GPL");
7029 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7030 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7031 +MODULE_PARM(stunaddr, "s");
7032 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7033 +MODULE_PARM(destaction, "s");
7034 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7037 +/* protects rtsp part of conntracks */
7038 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7040 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7042 +/*** helper functions ***/
7045 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7047 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7048 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7050 + *pptcpdata = (char*)tcph + tcph->doff*4;
7051 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7054 +/*** nat functions ***/
7057 + * Mangle the "Transport:" header:
7058 + * - Replace all occurences of "client_port=<spec>"
7059 + * - Handle destination parameter
7062 + * ct, ctinfo = conntrack context
7064 + * tranoff = Transport header offset from TCP data
7065 + * tranlen = Transport header length (incl. CRLF)
7066 + * rport_lo = replacement low port (host endian)
7067 + * rport_hi = replacement high port (host endian)
7069 + * Returns packet size difference.
7071 + * Assumes that a complete transport header is present, ending with CR or LF
7074 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7075 + struct ip_conntrack_expect* exp,
7076 + struct sk_buff** pskb, uint tranoff, uint tranlen)
7081 + char rbuf1[16]; /* Replacement buffer (one port) */
7082 + uint rbuf1len; /* Replacement len (one port) */
7083 + char rbufa[16]; /* Replacement buffer (all ports) */
7084 + uint rbufalen; /* Replacement len (all ports) */
7086 + u_int16_t loport, hiport;
7088 + uint diff; /* Number of bytes we removed */
7090 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7091 + struct ip_conntrack_tuple t;
7093 + char szextaddr[15+1];
7097 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7098 + ptran = ptcp+tranoff;
7100 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7101 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7102 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
7104 + INFOP("sanity check failed\n");
7108 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7110 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7114 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7115 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7116 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7118 + rbuf1len = rbufalen = 0;
7119 + switch (prtspexp->pbtype)
7122 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7124 + t.dst.u.udp.port = htons(loport);
7125 + if (ip_conntrack_change_expect(exp, &t) == 0)
7127 + DEBUGP("using port %hu\n", loport);
7133 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7134 + rbufalen = sprintf(rbufa, "%hu", loport);
7138 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7140 + t.dst.u.udp.port = htons(loport);
7141 + if (ip_conntrack_change_expect(exp, &t) == 0)
7143 + hiport = loport + ~exp->mask.dst.u.udp.port;
7144 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
7150 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7151 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7155 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7157 + t.dst.u.udp.port = htons(loport);
7158 + if (ip_conntrack_change_expect(exp, &t) == 0)
7160 + DEBUGP("using port %hu (1 of 2)\n", loport);
7164 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7166 + t.dst.u.udp.port = htons(hiport);
7167 + if (ip_conntrack_change_expect(exp, &t) == 0)
7169 + DEBUGP("using port %hu (2 of 2)\n", hiport);
7173 + if (loport != 0 && hiport != 0)
7175 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7176 + if (hiport == loport+1)
7178 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7182 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7188 + if (rbuf1len == 0)
7190 + return 0; /* cannot get replacement port(s) */
7193 + /* Transport: tran;field;field=val,tran;field;field=val,... */
7194 + while (off < tranlen)
7197 + const char* pparamend;
7198 + uint nextparamoff;
7200 + pparamend = memchr(ptran+off, ',', tranlen-off);
7201 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7202 + nextparamoff = pparamend-ptcp;
7205 + * We pass over each param twice. On the first pass, we look for a
7206 + * destination= field. It is handled by the security policy. If it
7207 + * is present, allowed, and equal to our external address, we assume
7208 + * that STUN is being used and we leave the client_port= field alone.
7212 + while (off < nextparamoff)
7214 + const char* pfieldend;
7215 + uint nextfieldoff;
7217 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7218 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7220 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7222 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7226 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7228 + diff = nextfieldoff-off;
7229 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7230 + off, diff, NULL, 0))
7232 + /* mangle failed, all we can do is bail */
7235 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7236 + ptran = ptcp+tranoff;
7238 + nextparamoff -= diff;
7239 + nextfieldoff -= diff;
7243 + off = nextfieldoff;
7250 + while (off < nextparamoff)
7252 + const char* pfieldend;
7253 + uint nextfieldoff;
7255 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7256 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7258 + if (strncmp(ptran+off, "client_port=", 12) == 0)
7264 + char* rbuf = rbuf1;
7265 + uint rbuflen = rbuf1len;
7268 + origoff = (ptran-ptcp)+off;
7270 + numlen = nf_strtou16(ptran+off, &port);
7272 + origlen += numlen;
7273 + if (port != prtspexp->loport)
7275 + DEBUGP("multiple ports found, port %hu ignored\n", port);
7279 + if (ptran[off] == '-' || ptran[off] == '/')
7283 + numlen = nf_strtou16(ptran+off, &port);
7285 + origlen += numlen;
7287 + rbuflen = rbufalen;
7291 + * note we cannot just memcpy() if the sizes are the same.
7292 + * the mangle function does skb resizing, checks for a
7293 + * cloned skb, and updates the checksums.
7295 + * parameter 4 below is offset from start of tcp data.
7297 + diff = origlen-rbuflen;
7298 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7299 + origoff, origlen, rbuf, rbuflen))
7301 + /* mangle failed, all we can do is bail */
7304 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7305 + ptran = ptcp+tranoff;
7307 + nextparamoff -= diff;
7308 + nextfieldoff -= diff;
7312 + off = nextfieldoff;
7315 + off = nextparamoff;
7321 +static unsigned int
7322 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7324 + struct ip_nat_multi_range mr;
7325 + u_int32_t newdstip, newsrcip, newip;
7327 + struct ip_conntrack *master = master_ct(ct);
7329 + IP_NF_ASSERT(info);
7330 + IP_NF_ASSERT(master);
7332 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7334 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7335 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7336 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7338 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7339 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7342 + /* We don't want to manip the per-protocol, just the IPs. */
7343 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7344 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7346 + return ip_nat_setup_info(ct, &mr, hooknum);
7350 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7351 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7361 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7362 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7364 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7366 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7368 + hdrsoff = exp->seq - ntohl(tcph->seq);
7369 + hdrslen = prtspexp->len;
7372 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7378 + if (off > hdrsoff+hdrslen)
7380 + INFOP("!! overrun !!");
7383 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7385 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7387 + uint oldtcplen = tcplen;
7388 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7392 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7393 + hdrslen -= (oldtcplen-tcplen);
7394 + off -= (oldtcplen-tcplen);
7395 + lineoff -= (oldtcplen-tcplen);
7396 + linelen -= (oldtcplen-tcplen);
7397 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7405 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7406 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7408 + /* XXX: unmangle */
7413 +help(struct ip_conntrack* ct,
7414 + struct ip_conntrack_expect* exp,
7415 + struct ip_nat_info* info,
7416 + enum ip_conntrack_info ctinfo,
7417 + unsigned int hooknum,
7418 + struct sk_buff** pskb)
7420 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7421 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7424 + struct ip_ct_rtsp_expect* ct_rtsp_info;
7425 + int rc = NF_ACCEPT;
7427 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7429 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7433 + ct_rtsp_info = &exp->help.exp_rtsp_info;
7436 + * Only mangle things once: original direction in POST_ROUTING
7437 + * and reply direction on PRE_ROUTING.
7439 + dir = CTINFO2DIR(ctinfo);
7440 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7441 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7443 + DEBUGP("Not touching dir %s at hook %s\n",
7444 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7445 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7446 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7447 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7450 + DEBUGP("got beyond not touching\n");
7452 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7454 + LOCK_BH(&ip_rtsp_lock);
7455 + /* Ensure the packet contains all of the marked data */
7456 + if (!between(exp->seq + ct_rtsp_info->len,
7457 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7459 + /* Partial retransmission? Probably a hacker. */
7460 + if (net_ratelimit())
7462 + INFOP("partial packet %u/%u in %u/%u\n",
7463 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7465 + UNLOCK_BH(&ip_rtsp_lock);
7471 + case IP_CT_DIR_ORIGINAL:
7472 + rc = help_out(ct, ctinfo, exp, pskb);
7474 + case IP_CT_DIR_REPLY:
7475 + rc = help_in(ct, ctinfo, exp, pskb);
7478 + UNLOCK_BH(&ip_rtsp_lock);
7483 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7484 +static char rtsp_names[MAX_PORTS][10];
7486 +/* This function is intentionally _NOT_ defined as __exit */
7492 + for (i = 0; i < num_ports; i++)
7494 + DEBUGP("unregistering helper for port %d\n", ports[i]);
7495 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7504 + struct ip_nat_helper* hlpr;
7507 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7509 + if (ports[0] == 0)
7511 + ports[0] = RTSP_PORT;
7514 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7516 + hlpr = &ip_nat_rtsp_helpers[i];
7517 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
7519 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
7520 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7521 + hlpr->mask.src.u.tcp.port = 0xFFFF;
7522 + hlpr->mask.dst.protonum = 0xFFFF;
7523 + hlpr->help = help;
7525 + hlpr->me = THIS_MODULE;
7526 + hlpr->expect = expected;
7528 + tmpname = &rtsp_names[i][0];
7529 + if (ports[i] == RTSP_PORT)
7531 + sprintf(tmpname, "rtsp");
7535 + sprintf(tmpname, "rtsp-%d", i);
7537 + hlpr->name = tmpname;
7539 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7540 + ret = ip_nat_helper_register(hlpr);
7544 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7550 + if (stunaddr != NULL)
7552 + extip = in_aton(stunaddr);
7554 + if (destaction != NULL)
7556 + if (strcmp(destaction, "auto") == 0)
7558 + dstact = DSTACT_AUTO;
7560 + if (strcmp(destaction, "strip") == 0)
7562 + dstact = DSTACT_STRIP;
7564 + if (strcmp(destaction, "none") == 0)
7566 + dstact = DSTACT_NONE;
7574 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c
7575 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c 2004-04-28 03:35:44.000000000 +0200
7576 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c 2004-04-30 09:11:53.000000000 +0200
7579 sizeof(struct ipt_entry),
7580 sizeof(struct ipt_standard),
7581 - 0, { 0, 0 }, { } },
7582 + 0, NULL, 0, { 0, 0 }, { } },
7583 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7588 sizeof(struct ipt_entry),
7589 sizeof(struct ipt_standard),
7590 - 0, { 0, 0 }, { } },
7591 + 0, NULL, 0, { 0, 0 }, { } },
7592 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7597 sizeof(struct ipt_entry),
7598 sizeof(struct ipt_standard),
7599 - 0, { 0, 0 }, { } },
7600 + 0, NULL, 0, { 0, 0 }, { } },
7601 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7606 sizeof(struct ipt_entry),
7607 sizeof(struct ipt_error),
7608 - 0, { 0, 0 }, { } },
7609 + 0, NULL, 0, { 0, 0 }, { } },
7610 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7613 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7614 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-28 03:36:29.000000000 +0200
7615 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-30 09:12:41.000000000 +0200
7616 @@ -175,6 +175,45 @@
7617 return do_bindings(ct, ctinfo, info, hooknum, pskb);
7620 +struct nat_route_key
7629 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7631 + struct iphdr *iph = skb->nh.iph;
7633 + key->addr = which ? iph->daddr : iph->saddr;
7636 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7637 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7638 + key->port = ports[which];
7644 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7646 + struct iphdr *iph = skb->nh.iph;
7648 + if (key->addr != (which ? iph->daddr : iph->saddr))
7651 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7652 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7653 + if (key->port != ports[which])
7660 ip_nat_out(unsigned int hooknum,
7661 struct sk_buff **pskb,
7663 const struct net_device *out,
7664 int (*okfn)(struct sk_buff *))
7666 + struct nat_route_key key;
7669 /* root is playing with raw sockets. */
7670 if ((*pskb)->len < sizeof(struct iphdr)
7671 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7672 @@ -204,7 +246,29 @@
7676 - return ip_nat_fn(hooknum, pskb, in, out, okfn);
7677 + nat_route_key_get(*pskb, &key, 0);
7678 + ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7680 + if (ret != NF_DROP && ret != NF_STOLEN
7681 + && nat_route_key_compare(*pskb, &key, 0)) {
7682 + if (ip_route_me_harder(pskb) != 0)
7686 + * POST_ROUTING hook is called with fixed outfn, we need
7687 + * to manually confirm the packet and direct it to the
7688 + * transformers if a policy matches.
7690 + else if ((*pskb)->dst->xfrm != NULL) {
7691 + ret = ip_conntrack_confirm(*pskb);
7692 + if (ret != NF_DROP) {
7693 + dst_output(*pskb);
7702 #ifdef CONFIG_IP_NF_NAT_LOCAL
7704 const struct net_device *out,
7705 int (*okfn)(struct sk_buff *))
7707 - u_int32_t saddr, daddr;
7708 + struct nat_route_key key;
7711 /* root is playing with raw sockets. */
7712 @@ -223,14 +287,14 @@
7713 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7716 - saddr = (*pskb)->nh.iph->saddr;
7717 - daddr = (*pskb)->nh.iph->daddr;
7719 + nat_route_key_get(*pskb, &key, 1);
7720 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7722 if (ret != NF_DROP && ret != NF_STOLEN
7723 - && ((*pskb)->nh.iph->saddr != saddr
7724 - || (*pskb)->nh.iph->daddr != daddr))
7725 - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7726 + && nat_route_key_compare(*pskb, &key, 1)) {
7727 + if (ip_route_me_harder(pskb) != 0)
7733 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c
7734 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
7735 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-04-30 09:14:39.000000000 +0200
7738 + * talk extension for UDP NAT alteration.
7739 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7741 + * This program is free software; you can redistribute it and/or
7742 + * modify it under the terms of the GNU General Public License
7743 + * as published by the Free Software Foundation; either version
7744 + * 2 of the License, or (at your option) any later version.
7746 + * Module load syntax:
7747 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7749 + * talk=[0|1] disable|enable old talk support
7750 + * ntalk=[0|1] disable|enable ntalk support
7751 + * ntalk2=[0|1] disable|enable ntalk2 support
7753 + * The default is talk=1 ntalk=1 ntalk2=1
7757 +#include <linux/module.h>
7758 +#include <linux/netfilter_ipv4.h>
7759 +#include <linux/ip.h>
7760 +#include <linux/udp.h>
7761 +#include <linux/kernel.h>
7762 +#include <net/tcp.h>
7763 +#include <net/udp.h>
7765 +#include <linux/netfilter_ipv4/ip_nat.h>
7766 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7767 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7768 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7769 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7771 +/* Default all talk protocols are supported */
7772 +static int talk = 1;
7773 +static int ntalk = 1;
7774 +static int ntalk2 = 1;
7775 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7776 +MODULE_DESCRIPTION("talk network address translation module");
7778 +MODULE_PARM(talk, "i");
7779 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7780 +MODULE_PARM(ntalk, "i");
7781 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7782 +MODULE_PARM(ntalk2, "i");
7783 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7787 +#define DEBUGP printk
7788 +#define IP_NAT_TALK_DEBUG
7790 +#define DEBUGP(format, args...)
7793 +/* FIXME: Time out? --RR */
7796 +mangle_packet(struct sk_buff **pskb,
7797 + struct ip_conntrack *ct,
7800 + struct talk_addr *addr,
7801 + struct talk_addr *ctl_addr)
7803 + struct iphdr *iph = (*pskb)->nh.iph;
7804 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7805 + size_t udplen = (*pskb)->len - iph->ihl * 4;
7807 + /* Fortunately talk sends a structure with the address and
7808 + port in it. The size of the packet won't change. */
7810 + if (ctl_addr == NULL) {
7812 + if (addr->ta_addr == INADDR_ANY)
7814 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7815 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7816 + NIPQUAD(newip), ntohs(port));
7817 + addr->ta_addr = newip;
7818 + addr->ta_port = port;
7821 + if (addr->ta_addr != INADDR_ANY) {
7822 + /* Change address inside packet to match way we're mapping
7823 + this connection. */
7824 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7825 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7826 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7827 + ntohs(addr->ta_port));
7828 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7830 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7831 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7832 + NIPQUAD(newip), ntohs(port));
7833 + ctl_addr->ta_addr = newip;
7834 + ctl_addr->ta_port = port;
7837 + /* Fix checksums */
7838 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
7840 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7841 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
7843 + ip_send_check(iph);
7847 +static int talk_help_msg(struct ip_conntrack *ct,
7848 + struct sk_buff **pskb,
7850 + struct talk_addr *addr,
7851 + struct talk_addr *ctl_addr)
7856 + unsigned int verdict = NF_ACCEPT;
7858 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
7859 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7860 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7863 + /* Change address inside packet to match way we're mapping
7864 + this connection. */
7865 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7866 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7867 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
7868 + NIPQUAD(newip), ntohs(port));
7870 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
7871 + verdict = NF_DROP;
7876 +static int talk_help_response(struct ip_conntrack *ct,
7877 + struct ip_conntrack_expect *exp,
7878 + struct sk_buff **pskb,
7881 + struct talk_addr *addr)
7885 + struct ip_conntrack_tuple t;
7886 + struct ip_ct_talk_expect *ct_talk_info;
7888 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
7889 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7892 + LOCK_BH(&ip_talk_lock);
7893 + ct_talk_info = &exp->help.exp_talk_info;
7895 + if (!(answer == SUCCESS
7896 + && (type == LOOK_UP || type == ANNOUNCE)
7897 + && exp != NULL)) {
7898 + UNLOCK_BH(&ip_talk_lock);
7902 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
7903 + ntohs(ct_talk_info->port),
7904 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
7906 + /* Change address inside packet to match way we're mapping
7907 + this connection. */
7908 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
7909 + IP_CT_DIR_REPLY].tuple.dst.ip;
7910 + /* We can read expect here without conntrack lock, since it's
7911 + only set in ip_conntrack_talk , with ip_talk_lock held
7916 + /* Try to get same port: if not, try to change it. */
7917 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
7918 + if (type == LOOK_UP)
7919 + t.dst.u.tcp.port = htons(port);
7921 + t.dst.u.udp.port = htons(port);
7923 + if (ip_conntrack_change_expect(exp, &t) == 0) {
7924 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
7928 + UNLOCK_BH(&ip_talk_lock);
7930 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
7936 +static unsigned int talk_help(struct ip_conntrack *ct,
7937 + struct ip_conntrack_expect *exp,
7938 + struct ip_nat_info *info,
7939 + enum ip_conntrack_info ctinfo,
7940 + unsigned int hooknum,
7941 + struct sk_buff **pskb,
7944 + struct iphdr *iph = (*pskb)->nh.iph;
7945 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7946 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
7947 + char *data = (char *)udph + sizeof(struct udphdr);
7950 + /* Only mangle things once: original direction in POST_ROUTING
7951 + and reply direction on PRE_ROUTING. */
7952 + dir = CTINFO2DIR(ctinfo);
7953 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7954 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7955 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
7956 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7957 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7958 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7959 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7962 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
7963 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7964 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7965 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7966 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7967 + NIPQUAD(iph->saddr), ntohs(udph->source),
7968 + NIPQUAD(iph->daddr), ntohs(udph->dest),
7971 + /* Because conntrack does not drop packets, checking must be repeated here... */
7972 + if (talk_port == TALK_PORT) {
7973 + if (dir == IP_CT_DIR_ORIGINAL
7974 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
7975 + return talk_help_msg(ct, pskb,
7976 + ((struct talk_msg *)data)->type,
7977 + &(((struct talk_msg *)data)->addr),
7978 + &(((struct talk_msg *)data)->ctl_addr));
7979 + else if (dir == IP_CT_DIR_REPLY
7980 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7981 + return talk_help_response(ct, exp, pskb,
7982 + ((struct talk_response *)data)->type,
7983 + ((struct talk_response *)data)->answer,
7984 + &(((struct talk_response *)data)->addr));
7986 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
7987 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
7988 + (unsigned)udplen - sizeof(struct udphdr),
7989 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
7993 + if (dir == IP_CT_DIR_ORIGINAL) {
7995 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
7996 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
7997 + return talk_help_msg(ct, pskb,
7998 + ((struct ntalk_msg *)data)->type,
7999 + &(((struct ntalk_msg *)data)->addr),
8000 + &(((struct ntalk_msg *)data)->ctl_addr));
8002 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8003 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8004 + && udplen == sizeof(struct udphdr)
8005 + + sizeof(struct ntalk2_msg)
8006 + + ((struct ntalk2_msg *)data)->extended)
8007 + return talk_help_msg(ct, pskb,
8008 + ((struct ntalk2_msg *)data)->type,
8009 + &(((struct ntalk2_msg *)data)->addr),
8010 + &(((struct ntalk2_msg *)data)->ctl_addr));
8012 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8013 + (unsigned)udplen - sizeof(struct udphdr),
8014 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8019 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8020 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8021 + return talk_help_response(ct, exp, pskb,
8022 + ((struct ntalk_response *)data)->type,
8023 + ((struct ntalk_response *)data)->answer,
8024 + &(((struct ntalk_response *)data)->addr));
8026 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8027 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8028 + return talk_help_response(ct, exp, pskb,
8029 + ((struct ntalk2_response *)data)->type,
8030 + ((struct ntalk2_response *)data)->answer,
8031 + &(((struct ntalk2_response *)data)->addr));
8033 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8034 + (unsigned)udplen - sizeof(struct udphdr),
8035 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8042 +static unsigned int help(struct ip_conntrack *ct,
8043 + struct ip_conntrack_expect *exp,
8044 + struct ip_nat_info *info,
8045 + enum ip_conntrack_info ctinfo,
8046 + unsigned int hooknum,
8047 + struct sk_buff **pskb)
8049 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8052 +static unsigned int nhelp(struct ip_conntrack *ct,
8053 + struct ip_conntrack_expect *exp,
8054 + struct ip_nat_info *info,
8055 + enum ip_conntrack_info ctinfo,
8056 + unsigned int hooknum,
8057 + struct sk_buff **pskb)
8059 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8062 +static unsigned int
8063 +talk_nat_expected(struct sk_buff **pskb,
8064 + unsigned int hooknum,
8065 + struct ip_conntrack *ct,
8066 + struct ip_nat_info *info);
8068 +static struct ip_nat_helper talk_helpers[2] =
8069 + { { { NULL, NULL },
8070 + "talk", /* name */
8071 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8072 + THIS_MODULE, /* module */
8073 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8074 + { 0, { 0 }, IPPROTO_UDP } },
8075 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8076 + { 0, { 0 }, 0xFFFF } },
8077 + help, /* helper */
8078 + talk_nat_expected }, /* expectfn */
8080 + "ntalk", /* name */
8081 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8082 + THIS_MODULE, /* module */
8083 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8084 + { 0, { 0 }, IPPROTO_UDP } },
8085 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8086 + { 0, { 0 }, 0xFFFF } },
8087 + nhelp, /* helper */
8088 + talk_nat_expected } /* expectfn */
8091 +static unsigned int
8092 +talk_nat_expected(struct sk_buff **pskb,
8093 + unsigned int hooknum,
8094 + struct ip_conntrack *ct,
8095 + struct ip_nat_info *info)
8097 + struct ip_nat_multi_range mr;
8098 + u_int32_t newdstip, newsrcip, newip;
8102 + struct ip_conntrack *master = master_ct(ct);
8104 + IP_NF_ASSERT(info);
8105 + IP_NF_ASSERT(master);
8107 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8109 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8111 + LOCK_BH(&ip_talk_lock);
8112 + port = ct->master->help.exp_talk_info.port;
8113 + UNLOCK_BH(&ip_talk_lock);
8115 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8116 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8117 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8118 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8119 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8122 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8123 + /* Callee client -> caller server */
8124 +#ifdef IP_NAT_TALK_DEBUG
8125 + struct iphdr *iph = (*pskb)->nh.iph;
8126 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8128 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8129 + NIPQUAD(iph->saddr), ntohs(udph->source),
8130 + NIPQUAD(iph->daddr), ntohs(udph->dest));
8132 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8133 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8134 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8135 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8137 + /* Callee client -> caller client */
8138 +#ifdef IP_NAT_TALK_DEBUG
8139 + struct iphdr *iph = (*pskb)->nh.iph;
8140 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8142 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8143 + NIPQUAD(iph->saddr), ntohs(tcph->source),
8144 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
8146 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8147 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8148 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8149 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8151 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8156 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8159 + /* We don't want to manip the per-protocol, just the IPs... */
8160 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8161 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8163 + /* ... unless we're doing a MANIP_DST, in which case, make
8164 + sure we map to the correct port */
8165 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8166 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8167 + mr.range[0].min = mr.range[0].max
8168 + = ((union ip_conntrack_manip_proto)
8169 + { .udp = { port } });
8171 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8173 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8174 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8175 + /* NAT expectfn called with ip_nat_lock write-locked */
8176 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
8181 +static int __init init(void)
8186 + ret = ip_nat_helper_register(&talk_helpers[0]);
8191 + if (ntalk > 0 || ntalk2 > 0) {
8192 + ret = ip_nat_helper_register(&talk_helpers[1]);
8194 + if (ret != 0 && talk > 0)
8195 + ip_nat_helper_unregister(&talk_helpers[0]);
8200 +static void __exit fini(void)
8203 + ip_nat_helper_unregister(&talk_helpers[0]);
8204 + if (ntalk > 0 || ntalk2 > 0)
8205 + ip_nat_helper_unregister(&talk_helpers[1]);
8210 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c
8211 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
8212 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c 2004-04-30 09:10:40.000000000 +0200
8214 +/* Kernel module for IP pool management */
8216 +#include <linux/module.h>
8217 +#include <linux/ip.h>
8218 +#include <linux/skbuff.h>
8219 +#include <linux/netfilter_ipv4/ip_tables.h>
8220 +#include <linux/netfilter_ipv4/ip_pool.h>
8221 +#include <linux/errno.h>
8222 +#include <asm/uaccess.h>
8223 +#include <asm/bitops.h>
8224 +#include <linux/interrupt.h>
8225 +#include <linux/spinlock.h>
8230 +#define DP(format, args...)
8233 +MODULE_LICENSE("GPL");
8236 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8239 + u_int32_t first_ip; /* host byte order, included in range */
8240 + u_int32_t last_ip; /* host byte order, included in range */
8241 + void *members; /* the bitmap proper */
8242 + int nr_use; /* total nr. of tests through this */
8243 + int nr_match; /* total nr. of matches through this */
8247 +static struct ip_pool *POOL;
8249 +static inline struct ip_pool *lookup(ip_pool_t index)
8251 + if (index < 0 || index >= nr_pool) {
8252 + DP("ip_pool:lookup: bad index %d\n", index);
8255 + return POOL+index;
8258 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8260 + struct ip_pool *pool = lookup(index);
8263 + if (!pool || !pool->members)
8265 + read_lock_bh(&pool->lock);
8266 + if (pool->members) {
8267 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
8268 + addr -= pool->first_ip;
8269 + if (test_bit(addr, pool->members)) {
8271 +#ifdef CONFIG_IP_POOL_STATISTICS
8276 +#ifdef CONFIG_IP_POOL_STATISTICS
8280 + read_unlock_bh(&pool->lock);
8283 +EXPORT_SYMBOL(ip_pool_match);
8285 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8287 + struct ip_pool *pool;
8290 + pool = lookup(index);
8291 + if ( !pool || !pool->members
8292 + || addr < pool->first_ip || addr > pool->last_ip)
8294 + read_lock_bh(&pool->lock);
8295 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8296 + addr -= pool->first_ip;
8298 + ? (0 != test_and_clear_bit(addr, pool->members))
8299 + : (0 != test_and_set_bit(addr, pool->members));
8301 + read_unlock_bh(&pool->lock);
8305 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8307 + int res = pool_change(index,addr,isdel);
8309 + if (!isdel) res = !res;
8312 +EXPORT_SYMBOL(ip_pool_mod);
8314 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8316 + return 4*((((b-a+8)/8)+3)/4);
8319 +static inline int poolbytes(ip_pool_t index)
8321 + struct ip_pool *pool = lookup(index);
8323 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8326 +static int setpool(
8332 + struct ip_pool_request req;
8334 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8335 + if (!capable(CAP_NET_ADMIN))
8337 + if (optval != SO_IP_POOL)
8339 + if (len != sizeof(req))
8341 + if (copy_from_user(&req, user, sizeof(req)) != 0)
8343 + printk("obsolete op - upgrade your ippool(8) utility.\n");
8347 +static int getpool(
8353 + struct ip_pool_request req;
8354 + struct ip_pool *pool;
8360 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8361 + if (!capable(CAP_NET_ADMIN))
8363 + if (optval != SO_IP_POOL)
8365 + if (*len != sizeof(req)) {
8368 + if (copy_from_user(&req, user, sizeof(req)) != 0)
8370 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8371 + if (req.op < IP_POOL_BAD001) {
8372 + printk("obsolete op - upgrade your ippool(8) utility.\n");
8376 + case IP_POOL_HIGH_NR:
8377 + DP("ip_pool HIGH_NR\n");
8378 + req.index = IP_POOL_NONE;
8379 + for (i=0; i<nr_pool; i++)
8380 + if (POOL[i].members)
8382 + return copy_to_user(user, &req, sizeof(req));
8383 + case IP_POOL_LOOKUP:
8384 + DP("ip_pool LOOKUP\n");
8385 + pool = lookup(req.index);
8388 + if (!pool->members)
8390 + req.addr = htonl(pool->first_ip);
8391 + req.addr2 = htonl(pool->last_ip);
8392 + return copy_to_user(user, &req, sizeof(req));
8393 + case IP_POOL_USAGE:
8394 + DP("ip_pool USE\n");
8395 + pool = lookup(req.index);
8398 + if (!pool->members)
8400 + req.addr = pool->nr_use;
8401 + req.addr2 = pool->nr_match;
8402 + return copy_to_user(user, &req, sizeof(req));
8403 + case IP_POOL_TEST_ADDR:
8404 + DP("ip_pool TEST 0x%08x\n", req.addr);
8405 + pool = lookup(req.index);
8409 + read_lock_bh(&pool->lock);
8410 + if (!pool->members) {
8411 + DP("ip_pool TEST_ADDR no members in pool\n");
8413 + goto unlock_and_return_res;
8415 + req.addr = ntohl(req.addr);
8416 + if (req.addr < pool->first_ip) {
8417 + DP("ip_pool TEST_ADDR address < pool bounds\n");
8419 + goto unlock_and_return_res;
8421 + if (req.addr > pool->last_ip) {
8422 + DP("ip_pool TEST_ADDR address > pool bounds\n");
8424 + goto unlock_and_return_res;
8426 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
8428 + read_unlock_bh(&pool->lock);
8429 + return copy_to_user(user, &req, sizeof(req));
8430 + case IP_POOL_FLUSH:
8431 + DP("ip_pool FLUSH not yet implemented.\n");
8433 + case IP_POOL_DESTROY:
8434 + DP("ip_pool DESTROY not yet implemented.\n");
8436 + case IP_POOL_INIT:
8437 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8438 + pool = lookup(req.index);
8441 + req.addr = ntohl(req.addr);
8442 + req.addr2 = ntohl(req.addr2);
8443 + if (req.addr > req.addr2) {
8444 + DP("ip_pool INIT bad ip range\n");
8447 + newbytes = bitmap_bytes(req.addr, req.addr2);
8448 + newmembers = kmalloc(newbytes, GFP_KERNEL);
8449 + if (!newmembers) {
8450 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8453 + memset(newmembers, 0, newbytes);
8454 + write_lock_bh(&pool->lock);
8455 + if (pool->members) {
8456 + DP("ip_pool INIT pool %d exists\n", req.index);
8457 + kfree(newmembers);
8459 + goto unlock_and_return_res;
8461 + pool->first_ip = req.addr;
8462 + pool->last_ip = req.addr2;
8464 + pool->nr_match = 0;
8465 + pool->members = newmembers;
8466 + write_unlock_bh(&pool->lock);
8468 + case IP_POOL_ADD_ADDR:
8469 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8470 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
8471 + return copy_to_user(user, &req, sizeof(req));
8472 + case IP_POOL_DEL_ADDR:
8473 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8474 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
8475 + return copy_to_user(user, &req, sizeof(req));
8477 + DP("ip_pool:getpool bad op %d\n", req.op);
8482 +unlock_and_return_res:
8484 + read_unlock_bh(&pool->lock);
8488 +static struct nf_sockopt_ops so_pool
8489 += { { NULL, NULL }, PF_INET,
8490 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
8491 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
8494 +MODULE_PARM(nr_pool, "i");
8496 +static int __init init(void)
8501 + if (nr_pool < 1) {
8502 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8505 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
8507 + printk("ip_pool module init: out of memory for nr_pool %d\n",
8511 + for (i=0; i<nr_pool; i++) {
8512 + POOL[i].first_ip = 0;
8513 + POOL[i].last_ip = 0;
8514 + POOL[i].members = 0;
8515 + POOL[i].nr_use = 0;
8516 + POOL[i].nr_match = 0;
8517 + POOL[i].lock = RW_LOCK_UNLOCKED;
8519 + res = nf_register_sockopt(&so_pool);
8520 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
8528 +static void __exit fini(void)
8532 + DP("ip_pool:fini BYEBYE\n");
8533 + nf_unregister_sockopt(&so_pool);
8534 + for (i=0; i<nr_pool; i++) {
8535 + if (POOL[i].members) {
8536 + kfree(POOL[i].members);
8537 + POOL[i].members = 0;
8542 + DP("ip_pool:fini these are the famous last words\n");
8548 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
8549 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-04-28 03:35:21.000000000 +0200
8550 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c 2004-04-30 09:11:53.000000000 +0200
8553 #include <linux/netfilter_ipv4/ip_tables.h>
8555 +static const char *hooknames[] = {
8556 + [NF_IP_PRE_ROUTING] "PREROUTING",
8557 + [NF_IP_LOCAL_IN] "INPUT",
8558 + [NF_IP_FORWARD] "FORWARD",
8559 + [NF_IP_LOCAL_OUT] "OUTPUT",
8560 + [NF_IP_POST_ROUTING] "POSTROUTING",
8563 MODULE_LICENSE("GPL");
8564 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8565 MODULE_DESCRIPTION("IPv4 packet filter");
8566 @@ -326,6 +334,12 @@
8568 t = ipt_get_target(e);
8569 IP_NF_ASSERT(t->u.kernel.target);
8571 + /* The packet traced and the rule isn't an unconditional return/END. */
8572 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
8573 + nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8574 + table->name, e->chainname, e->rulenum);
8576 /* Standard target? */
8577 if (!t->u.kernel.target->target) {
8580 /* set back pointer to next entry */
8584 e = get_entry(table_base, v);
8586 /* Targets which reenter must return
8587 @@ -478,6 +491,29 @@
8588 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8592 +find_error_target(struct ipt_entry *s,
8593 + struct ipt_entry *e,
8596 + struct ipt_entry_target *t;
8597 + static struct ipt_entry *found = NULL;
8602 + t = ipt_get_target(found);
8603 + if (strcmp(t->u.user.name,
8604 + IPT_ERROR_TARGET) == 0) {
8605 + *chainname = t->data;
8614 /* All zeroes == unconditional rule. */
8616 unconditional(const struct ipt_ip *ip)
8618 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8621 + char *chainname = NULL;
8622 + u_int32_t rulenum;
8624 /* No recursion; use packet counter to save back ptrs (reset
8625 to 0 as we leave), and comefrom to save source hook bitmask */
8628 /* Set initial back pointer. */
8629 e->counters.pcnt = pos;
8631 + chainname = (char *) hooknames[hook];
8634 struct ipt_standard_target *t
8638 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8639 + e->rulenum = rulenum++;
8640 + e->chainname = chainname;
8642 /* Unconditional return/END. */
8643 if (e->target_offset == sizeof(struct ipt_entry)
8644 @@ -531,6 +573,10 @@
8645 && unconditional(&e->ip)) {
8646 unsigned int oldpos, size;
8648 + /* Set unconditional rulenum to zero. */
8650 + e->counters.bcnt = 0;
8652 /* Return: backtrack through the last
8655 @@ -556,6 +602,11 @@
8656 (newinfo->entries + pos);
8657 } while (oldpos == pos + e->next_offset);
8659 + /* Restore chainname, rulenum. */
8660 + chainname = e->chainname;
8661 + rulenum = e->counters.bcnt;
8662 + e->counters.bcnt = 0;
8664 /* Move along one */
8665 size = e->next_offset;
8666 e = (struct ipt_entry *)
8667 @@ -571,6 +622,17 @@
8668 /* This a jump; chase it. */
8669 duprintf("Jump rule %u -> %u\n",
8671 + e->counters.bcnt = rulenum++;
8673 + e = (struct ipt_entry *)
8674 + (newinfo->entries + newpos);
8675 + if (IPT_ENTRY_ITERATE(newinfo->entries,
8677 + find_error_target,
8678 + e, &chainname) == 0) {
8679 + printk("ip_tables: table screwed up!\n");
8683 /* ... this is a fallthru */
8684 newpos = pos + e->next_offset;
8685 @@ -1716,9 +1778,9 @@
8688 #ifdef CONFIG_PROC_FS
8689 -static inline int print_name(const char *i,
8690 - off_t start_offset, char *buffer, int length,
8691 - off_t *pos, unsigned int *count)
8692 +static int print_name(const char *i,
8693 + off_t start_offset, char *buffer, int length,
8694 + off_t *pos, unsigned int *count)
8696 if ((*count)++ >= start_offset) {
8697 unsigned int namelen;
8698 @@ -1752,6 +1814,15 @@
8702 +static inline int print_target(const struct ipt_target *t,
8703 + off_t start_offset, char *buffer, int length,
8704 + off_t *pos, unsigned int *count)
8706 + if (t != &ipt_standard_target && t != &ipt_error_target)
8708 + return print_name((char *)t, start_offset, buffer, length, pos, count);
8711 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
8714 @@ -1760,7 +1831,7 @@
8715 if (down_interruptible(&ipt_mutex) != 0)
8718 - LIST_FIND(&ipt_target, print_name, void *,
8719 + LIST_FIND(&ipt_target, print_target, struct ipt_target *,
8720 offset, buffer, length, &pos, &count);
8723 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
8724 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
8725 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-30 09:11:35.000000000 +0200
8727 +/* This kernel module is used to modify the connection mark values, or
8728 + * to optionally restore the skb nfmark from the connection mark
8730 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8731 + * by Henrik Nordstrom <hno@marasystems.com>
8733 + * This program is free software; you can redistribute it and/or modify
8734 + * it under the terms of the GNU General Public License as published by
8735 + * the Free Software Foundation; either version 2 of the License, or
8736 + * (at your option) any later version.
8738 + * This program is distributed in the hope that it will be useful,
8739 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8740 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8741 + * GNU General Public License for more details.
8743 + * You should have received a copy of the GNU General Public License
8744 + * along with this program; if not, write to the Free Software
8745 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8747 +#include <linux/module.h>
8748 +#include <linux/skbuff.h>
8749 +#include <linux/ip.h>
8750 +#include <net/checksum.h>
8752 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8753 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8754 +MODULE_LICENSE("GPL");
8756 +#include <linux/netfilter_ipv4/ip_tables.h>
8757 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8758 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8760 +static unsigned int
8761 +target(struct sk_buff **pskb,
8762 + const struct net_device *in,
8763 + const struct net_device *out,
8764 + unsigned int hooknum,
8765 + const void *targinfo,
8768 + const struct ipt_connmark_target_info *markinfo = targinfo;
8769 + unsigned long diff;
8770 + unsigned long nfmark;
8771 + unsigned long newmark;
8773 + enum ip_conntrack_info ctinfo;
8774 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8776 + switch(markinfo->mode) {
8777 + case IPT_CONNMARK_SET:
8778 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8779 + if (newmark != ct->mark)
8780 + ct->mark = newmark;
8782 + case IPT_CONNMARK_SAVE:
8783 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8784 + if (ct->mark != newmark)
8785 + ct->mark = newmark;
8787 + case IPT_CONNMARK_RESTORE:
8788 + nfmark = (*pskb)->nfmark;
8789 + diff = (ct->mark ^ nfmark & markinfo->mask);
8791 + (*pskb)->nfmark = nfmark ^ diff;
8792 + (*pskb)->nfcache |= NFC_ALTERED;
8798 + return IPT_CONTINUE;
8802 +checkentry(const char *tablename,
8803 + const struct ipt_entry *e,
8805 + unsigned int targinfosize,
8806 + unsigned int hook_mask)
8808 + struct ipt_connmark_target_info *matchinfo = targinfo;
8809 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8810 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8812 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8816 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8817 + if (strcmp(tablename, "mangle") != 0) {
8818 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8826 +static struct ipt_target ipt_connmark_reg = {
8827 + .name = "CONNMARK",
8828 + .target = &target,
8829 + .checkentry = &checkentry,
8833 +static int __init init(void)
8835 + return ipt_register_target(&ipt_connmark_reg);
8838 +static void __exit fini(void)
8840 + ipt_unregister_target(&ipt_connmark_reg);
8845 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c
8846 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8847 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-30 09:11:38.000000000 +0200
8849 +/* This is a module which is used for setting the NFMARK field of an skb. */
8850 +#include <linux/module.h>
8851 +#include <linux/skbuff.h>
8852 +#include <linux/ip.h>
8853 +#include <net/checksum.h>
8855 +#include <linux/netfilter_ipv4/ip_tables.h>
8856 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8858 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8859 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8860 +MODULE_LICENSE("GPL");
8862 +static unsigned int
8863 +target(struct sk_buff **pskb,
8864 + const struct net_device *in,
8865 + const struct net_device *out,
8866 + unsigned int hooknum,
8867 + const void *targinfo,
8870 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8871 + struct iphdr *iph = (*pskb)->nh.iph;
8872 + unsigned long mark;
8874 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8875 + mark = (unsigned long) ntohl(iph->saddr);
8877 + mark = (unsigned long) ntohl(iph->daddr);
8879 + mark &= ipmarkinfo->andmask;
8880 + mark |= ipmarkinfo->ormask;
8882 + if ((*pskb)->nfmark != mark) {
8883 + (*pskb)->nfmark = mark;
8884 + (*pskb)->nfcache |= NFC_ALTERED;
8886 + return IPT_CONTINUE;
8890 +checkentry(const char *tablename,
8891 + const struct ipt_entry *e,
8893 + unsigned int targinfosize,
8894 + unsigned int hook_mask)
8896 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8897 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8899 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8903 + if (strcmp(tablename, "mangle") != 0) {
8904 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8911 +static struct ipt_target ipt_ipmark_reg = {
8914 + .checkentry = checkentry,
8918 +static int __init init(void)
8920 + return ipt_register_target(&ipt_ipmark_reg);
8923 +static void __exit fini(void)
8925 + ipt_unregister_target(&ipt_ipmark_reg);
8930 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
8931 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
8932 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-04-30 09:10:05.000000000 +0200
8935 + * Strip all IP options in the IP packet header.
8937 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
8938 + * This software is distributed under GNU GPL v2, 1991
8941 +#include <linux/module.h>
8942 +#include <linux/skbuff.h>
8943 +#include <linux/ip.h>
8944 +#include <net/checksum.h>
8946 +#include <linux/netfilter_ipv4/ip_tables.h>
8948 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
8949 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
8950 +MODULE_LICENSE("GPL");
8952 +static unsigned int
8953 +target(struct sk_buff **pskb,
8954 + const struct net_device *in,
8955 + const struct net_device *out,
8956 + unsigned int hooknum,
8957 + const void *targinfo,
8960 + struct iphdr *iph;
8961 + struct sk_buff *skb;
8962 + struct ip_options *opt;
8963 + unsigned char *optiph;
8966 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
8970 + iph = (*pskb)->nh.iph;
8971 + optiph = skb->nh.raw;
8972 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
8974 + /* if no options in packet then nothing to clear. */
8975 + if (iph->ihl * 4 == sizeof(struct iphdr))
8976 + return IPT_CONTINUE;
8978 + /* else clear all options */
8979 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
8980 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
8981 + opt = &(IPCB(skb)->opt);
8985 + skb->nfcache |= NFC_ALTERED;
8987 + return IPT_CONTINUE;
8991 +checkentry(const char *tablename,
8992 + const struct ipt_entry *e,
8994 + unsigned int targinfosize,
8995 + unsigned int hook_mask)
8997 + if (strcmp(tablename, "mangle")) {
8998 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9001 + /* nothing else to check because no parameters */
9005 +static struct ipt_target ipt_ipv4optsstrip_reg = {
9006 + .name = "IPV4OPTSSTRIP",
9008 + .checkentry = checkentry,
9009 + .me = THIS_MODULE };
9011 +static int __init init(void)
9013 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
9016 +static void __exit fini(void)
9018 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9023 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c
9024 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
9025 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c 2004-04-30 09:10:09.000000000 +0200
9027 +#include <linux/module.h>
9028 +#include <linux/version.h>
9029 +#include <linux/config.h>
9030 +#include <linux/socket.h>
9031 +#include <linux/skbuff.h>
9032 +#include <linux/kernel.h>
9033 +#include <linux/netlink.h>
9034 +#include <linux/netdevice.h>
9035 +#include <linux/mm.h>
9036 +#include <linux/socket.h>
9037 +#include <linux/netfilter_ipv4/ip_tables.h>
9038 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9039 +#include <net/sock.h>
9041 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9042 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9043 +MODULE_LICENSE("GPL");
9046 +#define DEBUGP printk
9048 +#define DEBUGP(format, args...)
9051 +static struct sock *ipfwsk;
9053 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9054 + unsigned int hooknum,
9055 + const struct net_device *in,
9056 + const struct net_device *out,
9057 + const void *targinfo, void *userinfo)
9059 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9060 + struct iphdr *ip = (*pskb)->nh.iph;
9061 + struct sk_buff *outskb;
9062 + struct netlink_t nlhdr;
9065 + /* Allocate a socket buffer */
9066 + if ( MASK(nld->flags, USE_SIZE) )
9067 + len = nld->size+sizeof(nlhdr);
9069 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
9071 + outskb=alloc_skb(len, GFP_ATOMIC);
9076 + if ( MASK(nld->flags, USE_MARK) )
9077 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
9079 + nlhdr.mark=(*pskb)->nfmark;
9081 + if ( in && in->name ) {
9082 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9083 + }else if ( out && out->name ){
9084 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9087 + skb_put(outskb, len);
9088 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9089 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9090 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9092 + if (net_ratelimit())
9093 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9096 + if ( MASK(nld->flags, USE_DROP) )
9099 + return IPT_CONTINUE;
9102 +static int ipt_netlink_checkentry(const char *tablename,
9103 + const struct ipt_entry *e,
9105 + unsigned int targinfosize,
9106 + unsigned int hookmask)
9108 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9113 +static struct ipt_target ipt_netlink_reg = {
9116 + ipt_netlink_target,
9117 + ipt_netlink_checkentry,
9122 +static int __init init(void)
9124 + DEBUGP("ipt_NETLINK: init module\n");
9126 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
9130 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9137 +static void __exit fini(void)
9139 + DEBUGP("ipt_NETLINK: cleanup_module\n");
9140 + ipt_unregister_target(&ipt_netlink_reg);
9141 + if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9146 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c
9147 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
9148 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c 2004-04-30 09:10:40.000000000 +0200
9150 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9152 + * This target can be used almost everywhere. It acts on some specified
9153 + * IP pool, adding or deleting some IP address in the pool. The address
9154 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9155 + * of the packet under inspection.
9157 + * The target normally returns IPT_CONTINUE.
9160 +#include <linux/types.h>
9161 +#include <linux/ip.h>
9162 +#include <linux/timer.h>
9163 +#include <linux/module.h>
9164 +#include <linux/netfilter.h>
9165 +#include <linux/netdevice.h>
9166 +#include <linux/if.h>
9167 +#include <linux/inetdevice.h>
9168 +#include <net/protocol.h>
9169 +#include <net/checksum.h>
9170 +#include <linux/netfilter_ipv4.h>
9171 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9172 +#include <linux/netfilter_ipv4/ipt_pool.h>
9175 +#define DEBUGP printk
9177 +#define DEBUGP(format, args...)
9180 +/*** NOTE NOTE NOTE NOTE ***
9182 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9183 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9184 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9185 +** is modified for the source IP address of the packet under inspection.
9186 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9188 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9189 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9191 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9192 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9193 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9194 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9198 +do_check(const char *tablename,
9199 + const struct ipt_entry *e,
9201 + unsigned int targinfosize,
9202 + unsigned int hook_mask)
9204 + const struct ipt_pool_info *ipi = targinfo;
9206 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9207 + DEBUGP("POOL_check: size %u.\n", targinfosize);
9210 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9214 +static unsigned int
9215 +do_target(struct sk_buff **pskb,
9216 + unsigned int hooknum,
9217 + const struct net_device *in,
9218 + const struct net_device *out,
9219 + const void *targinfo,
9222 + const struct ipt_pool_info *ipi = targinfo;
9224 + unsigned int verdict = IPT_CONTINUE;
9226 + if (ipi->src != IP_POOL_NONE) {
9227 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9228 + ipi->flags & IPT_POOL_DEL_SRC);
9229 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9230 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9231 + verdict = NF_ACCEPT;
9232 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9233 + verdict = NF_DROP;
9236 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9237 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9238 + ipi->flags & IPT_POOL_DEL_DST);
9239 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9240 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9241 + verdict = NF_ACCEPT;
9242 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9243 + verdict = NF_DROP;
9249 +static struct ipt_target pool_reg
9250 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9252 +static int __init init(void)
9254 + DEBUGP("init ipt_POOL\n");
9255 + return ipt_register_target(&pool_reg);
9258 +static void __exit fini(void)
9260 + DEBUGP("fini ipt_POOL\n");
9261 + ipt_unregister_target(&pool_reg);
9266 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c
9267 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
9268 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-30 09:11:46.000000000 +0200
9271 + * Kernel module to capture and hold incoming TCP connections using
9272 + * no local per-connection resources.
9274 + * Based on ipt_REJECT.c and offering functionality similar to
9275 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
9277 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
9279 + * This program is free software; you can redistribute it and/or modify
9280 + * it under the terms of the GNU General Public License as published by
9281 + * the Free Software Foundation; either version 2 of the License, or
9282 + * (at your option) any later version.
9284 + * This program is distributed in the hope that it will be useful,
9285 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9286 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9287 + * GNU General Public License for more details.
9289 + * You should have received a copy of the GNU General Public License
9290 + * along with this program; if not, write to the Free Software
9291 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
9294 + * - Allow incoming TCP connections to be established.
9295 + * - Passing data should result in the connection being switched to the
9296 + * persist state (0 byte window), in which the remote side stops sending
9297 + * data and asks to continue every 60 seconds.
9298 + * - Attempts to shut down the connection should be ignored completely, so
9299 + * the remote side ends up having to time it out.
9302 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
9303 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
9304 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
9307 +#include <linux/config.h>
9308 +#include <linux/module.h>
9309 +#include <linux/skbuff.h>
9310 +#include <linux/ip.h>
9311 +#include <net/ip.h>
9312 +#include <net/tcp.h>
9313 +#include <net/icmp.h>
9315 +#include <net/route.h>
9316 +#include <linux/random.h>
9317 +#include <linux/netfilter_ipv4/ip_tables.h>
9320 +#define DEBUGP printk
9322 +#define DEBUGP(format, args...)
9325 +MODULE_LICENSE("GPL");
9326 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
9328 +/* Stolen from ip_finish_output2 */
9329 +static int ip_direct_send(struct sk_buff *skb)
9331 + struct dst_entry *dst = skb->dst;
9332 + struct hh_cache *hh = dst->hh;
9335 + read_lock_bh(&hh->hh_lock);
9336 + memcpy(skb->data - 16, hh->hh_data, 16);
9337 + read_unlock_bh(&hh->hh_lock);
9338 + skb_push(skb, hh->hh_len);
9339 + return hh->hh_output(skb);
9340 + } else if (dst->neighbour)
9341 + return dst->neighbour->output(skb);
9343 + if (net_ratelimit())
9344 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
9351 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
9353 + struct sk_buff *nskb;
9354 + struct rtable *nrt;
9355 + struct tcphdr *otcph, *ntcph;
9356 + unsigned int otcplen;
9358 + struct flowi fl = {};
9360 + /* A truncated TCP header isn't going to be useful */
9361 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
9364 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
9365 + + oskb->nh.iph->ihl);
9366 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
9368 + /* No replies for RST or FIN */
9369 + if (otcph->rst || otcph->fin)
9372 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
9373 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
9376 + /* Check checksum. */
9377 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
9378 + oskb->nh.iph->daddr,
9379 + csum_partial((char *)otcph, otcplen, 0)) != 0)
9382 + /* Copy skb (even if skb is about to be dropped, we can't just
9383 + clone it because there may be other things, such as tcpdump,
9384 + interested in it) */
9385 + nskb = skb_copy(oskb, GFP_ATOMIC);
9389 + /* This packet will not be the same as the other: clear nf fields */
9390 + nf_conntrack_put(nskb->nfct);
9391 + nskb->nfct = NULL;
9392 + nskb->nfcache = 0;
9393 +#ifdef CONFIG_NETFILTER_DEBUG
9394 + nskb->nf_debug = 0;
9397 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
9399 + /* Truncate to length (no data) */
9400 + ntcph->doff = sizeof(struct tcphdr)/4;
9401 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
9402 + nskb->nh.iph->tot_len = htons(nskb->len);
9404 + /* Swap source and dest */
9405 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
9406 + tmp = ntcph->source;
9407 + ntcph->source = ntcph->dest;
9408 + ntcph->dest = tmp;
9410 + /* Use supplied sequence number or make a new one */
9411 + ntcph->seq = otcph->ack ? otcph->ack_seq
9412 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
9413 + nskb->nh.iph->daddr,
9417 + /* Our SYN-ACKs must have a >0 window */
9418 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
9420 + ntcph->urg_ptr = 0;
9423 + ((u_int8_t *)ntcph)[13] = 0;
9425 + if (otcph->syn && otcph->ack) {
9427 + ntcph->ack_seq = 0;
9429 + ntcph->syn = otcph->syn;
9431 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
9434 + /* Adjust TCP checksum */
9436 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
9437 + nskb->nh.iph->saddr,
9438 + nskb->nh.iph->daddr,
9439 + csum_partial((char *)ntcph,
9440 + sizeof(struct tcphdr), 0));
9442 + /* Adjust IP TTL */
9443 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
9445 + /* Set DF, id = 0 */
9446 + nskb->nh.iph->frag_off = htons(IP_DF);
9447 + nskb->nh.iph->id = 0;
9449 + /* Adjust IP checksum */
9450 + nskb->nh.iph->check = 0;
9451 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
9452 + nskb->nh.iph->ihl);
9454 + fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
9455 + fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
9456 + fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
9458 + if (ip_route_output_key(&nrt, &fl) != 0)
9461 + dst_release(nskb->dst);
9462 + nskb->dst = &nrt->u.dst;
9464 + /* "Never happens" */
9465 + if (nskb->len > dst_pmtu(nskb->dst))
9468 + ip_direct_send (nskb);
9477 +static unsigned int tarpit(struct sk_buff **pskb,
9478 + const struct net_device *in,
9479 + const struct net_device *out,
9480 + unsigned int hooknum,
9481 + const void *targinfo,
9484 + struct sk_buff *skb = *pskb;
9485 + struct rtable *rt = (struct rtable*)skb->dst;
9487 + /* Do we have an input route cache entry? */
9491 + /* No replies to physical multicast/broadcast */
9492 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
9495 + /* Now check at the protocol level */
9496 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
9499 + /* Our naive response construction doesn't deal with IP
9500 + options, and probably shouldn't try. */
9501 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
9504 + /* We aren't interested in fragments */
9505 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
9508 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
9514 +static int check(const char *tablename,
9515 + const struct ipt_entry *e,
9517 + unsigned int targinfosize,
9518 + unsigned int hook_mask)
9520 + /* Only allow these for input/forward packet filtering. */
9521 + if (strcmp(tablename, "filter") != 0) {
9522 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
9525 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
9526 + | (1 << NF_IP_FORWARD))) != 0) {
9527 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
9531 + /* Must specify that it's a TCP packet */
9532 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
9533 + DEBUGP("TARPIT: not valid for non-tcp\n");
9540 +static struct ipt_target ipt_tarpit_reg = {
9543 + .checkentry = check,
9547 +static int __init init(void)
9549 + return ipt_register_target(&ipt_tarpit_reg);
9552 +static void __exit fini(void)
9554 + ipt_unregister_target(&ipt_tarpit_reg);
9559 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c
9560 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
9561 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c 2004-04-30 09:11:53.000000000 +0200
9563 +/* This is a module which is used for setting
9564 + * the NFC_TRACE flag in the nfcache field of an skb.
9566 +#include <linux/module.h>
9567 +#include <linux/skbuff.h>
9569 +#include <linux/netfilter_ipv4/ip_tables.h>
9571 +static unsigned int
9572 +target(struct sk_buff **pskb,
9573 + const struct net_device *in,
9574 + const struct net_device *out,
9575 + unsigned int hooknum,
9576 + const void *targinfo,
9579 + (*pskb)->nfcache |= NFC_TRACE;
9580 + return IPT_CONTINUE;
9584 +checkentry(const char *tablename,
9585 + const struct ipt_entry *e,
9587 + unsigned int targinfosize,
9588 + unsigned int hook_mask)
9590 + if (targinfosize != 0) {
9591 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
9596 + if (strcmp(tablename, "raw") != 0) {
9597 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
9604 +static struct ipt_target ipt_trace_reg = {
9607 + .checkentry = checkentry,
9611 +static int __init init(void)
9613 + if (ipt_register_target(&ipt_trace_reg))
9619 +static void __exit fini(void)
9621 + ipt_unregister_target(&ipt_trace_reg);
9626 +MODULE_LICENSE("GPL");
9627 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c
9628 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
9629 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c 2004-04-30 09:10:15.000000000 +0200
9631 +/* TTL modification target for IP tables
9632 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
9634 + * Version: $Revision$
9636 + * This software is distributed under the terms of GNU GPL
9639 +#include <linux/module.h>
9640 +#include <linux/skbuff.h>
9641 +#include <linux/ip.h>
9642 +#include <net/checksum.h>
9644 +#include <linux/netfilter_ipv4/ip_tables.h>
9645 +#include <linux/netfilter_ipv4/ipt_TTL.h>
9647 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9648 +MODULE_DESCRIPTION("IP tables TTL modification module");
9649 +MODULE_LICENSE("GPL");
9651 +static unsigned int
9652 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
9653 + const struct net_device *out, unsigned int hooknum,
9654 + const void *targinfo, void *userinfo)
9656 + struct iphdr *iph;
9657 + const struct ipt_TTL_info *info = targinfo;
9658 + u_int16_t diffs[2];
9661 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9664 + iph = (*pskb)->nh.iph;
9666 + switch (info->mode) {
9668 + new_ttl = info->ttl;
9671 + new_ttl = iph->ttl + info->ttl;
9672 + if (new_ttl > 255)
9676 + new_ttl = iph->ttl + info->ttl;
9681 + new_ttl = iph->ttl;
9685 + if (new_ttl != iph->ttl) {
9686 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
9687 + iph->ttl = new_ttl;
9688 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
9689 + iph->check = csum_fold(csum_partial((char *)diffs,
9691 + iph->check^0xFFFF));
9692 + (*pskb)->nfcache |= NFC_ALTERED;
9695 + return IPT_CONTINUE;
9698 +static int ipt_ttl_checkentry(const char *tablename,
9699 + const struct ipt_entry *e,
9701 + unsigned int targinfosize,
9702 + unsigned int hook_mask)
9704 + struct ipt_TTL_info *info = targinfo;
9706 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
9707 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
9709 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
9713 + if (strcmp(tablename, "mangle")) {
9714 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9718 + if (info->mode > IPT_TTL_MAXMODE) {
9719 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
9724 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
9725 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
9732 +static struct ipt_target ipt_TTL = {
9734 + .target = ipt_ttl_target,
9735 + .checkentry = ipt_ttl_checkentry,
9739 +static int __init init(void)
9741 + return ipt_register_target(&ipt_TTL);
9744 +static void __exit fini(void)
9746 + ipt_unregister_target(&ipt_TTL);
9751 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c
9752 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
9753 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-04-30 09:11:56.000000000 +0200
9755 +/* XOR target for IP tables
9756 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9757 + * Based on ipt_TTL.c
9761 + * This software is distributed under the terms of GNU GPL
9764 +#include <linux/module.h>
9765 +#include <linux/skbuff.h>
9766 +#include <linux/ip.h>
9767 +#include <linux/tcp.h>
9768 +#include <linux/udp.h>
9770 +#include <linux/netfilter_ipv4/ip_tables.h>
9771 +#include <linux/netfilter_ipv4/ipt_XOR.h>
9773 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9774 +MODULE_DESCRIPTION("IP tables XOR module");
9775 +MODULE_LICENSE("GPL");
9777 +static unsigned int
9778 +ipt_xor_target(struct sk_buff **pskb,
9779 + const struct net_device *in, const struct net_device *out,
9780 + unsigned int hooknum, const void *targinfo, void *userinfo)
9782 + struct ipt_XOR_info *info = (void *) targinfo;
9783 + struct iphdr *iph;
9784 + struct tcphdr *tcph;
9785 + struct udphdr *udph;
9788 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9791 + iph = (*pskb)->nh.iph;
9793 + if (iph->protocol == IPPROTO_TCP) {
9794 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9795 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9796 + for (k=0; k<=info->block_size; k++) {
9797 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
9802 + if (info->key[j] == 0x00)
9805 + } else if (iph->protocol == IPPROTO_UDP) {
9806 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9807 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9808 + for (k=0; k<=info->block_size; k++) {
9809 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
9814 + if (info->key[j] == 0x00)
9819 + return IPT_CONTINUE;
9822 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9823 + void *targinfo, unsigned int targinfosize,
9824 + unsigned int hook_mask)
9826 + struct ipt_XOR_info *info = targinfo;
9828 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9829 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
9830 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9834 + if (strcmp(tablename, "mangle")) {
9835 + printk(KERN_WARNING "XOR: can only be called from"
9836 + "\"mangle\" table, not \"%s\"\n", tablename);
9840 + if (!strcmp(info->key, "")) {
9841 + printk(KERN_WARNING "XOR: You must specify a key");
9845 + if (info->block_size == 0) {
9846 + printk(KERN_WARNING "XOR: You must specify a block-size");
9853 +static struct ipt_target ipt_XOR = {
9855 + .target = ipt_xor_target,
9856 + .checkentry = ipt_xor_checkentry,
9857 + .me = THIS_MODULE,
9860 +static int __init init(void)
9862 + return ipt_register_target(&ipt_XOR);
9865 +static void __exit fini(void)
9867 + ipt_unregister_target(&ipt_XOR);
9872 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c
9873 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
9874 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-04-30 09:11:57.000000000 +0200
9877 + * iptables module to match inet_addr_type() of an ip.
9880 +#include <linux/module.h>
9881 +#include <linux/skbuff.h>
9882 +#include <linux/netdevice.h>
9883 +#include <net/route.h>
9885 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
9886 +#include <linux/netfilter_ipv4/ip_tables.h>
9888 +MODULE_LICENSE("GPL");
9890 +static inline int match_type(u_int32_t addr, u_int16_t mask)
9892 + return !!(mask & (1 << inet_addr_type(addr)));
9895 +static int match(const struct sk_buff *skb, const struct net_device *in,
9896 + const struct net_device *out, const void *matchinfo,
9897 + int offset, int *hotdrop)
9899 + const struct ipt_addrtype_info *info = matchinfo;
9900 + const struct iphdr *iph = skb->nh.iph;
9904 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
9906 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9911 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9912 + void *matchinfo, unsigned int matchsize,
9913 + unsigned int hook_mask)
9915 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9916 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9917 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9924 +static struct ipt_match addrtype_match = {
9925 + .name = "addrtype",
9927 + .checkentry = checkentry,
9931 +static int __init init(void)
9933 + return ipt_register_match(&addrtype_match);
9936 +static void __exit fini(void)
9938 + ipt_unregister_match(&addrtype_match);
9944 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c
9945 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
9946 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c 2004-04-30 09:10:17.000000000 +0200
9949 + * netfilter module to limit the number of parallel tcp
9950 + * connections per IP address.
9951 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
9952 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
9953 + * only ignore TIME_WAIT or gone connections
9957 + * Kernel module to match connection tracking information.
9958 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
9960 +#include <linux/module.h>
9961 +#include <linux/skbuff.h>
9962 +#include <linux/list.h>
9963 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9964 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
9965 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
9966 +#include <linux/netfilter_ipv4/ip_tables.h>
9967 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
9971 +MODULE_LICENSE("GPL");
9973 +/* we'll save the tuples of all connections we care about */
9974 +struct ipt_connlimit_conn
9976 + struct list_head list;
9977 + struct ip_conntrack_tuple tuple;
9980 +struct ipt_connlimit_data {
9982 + struct list_head iphash[256];
9985 +static int ipt_iphash(u_int32_t addr)
9989 + hash = addr & 0xff;
9990 + hash ^= (addr >> 8) & 0xff;
9991 + hash ^= (addr >> 16) & 0xff;
9992 + hash ^= (addr >> 24) & 0xff;
9996 +static int count_them(struct ipt_connlimit_data *data,
9997 + u_int32_t addr, u_int32_t mask,
9998 + struct ip_conntrack *ct)
10001 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
10002 + "fin_wait", "time_wait", "close", "close_wait",
10003 + "last_ack", "listen" };
10005 + int addit = 1, matches = 0;
10006 + struct ip_conntrack_tuple tuple;
10007 + struct ip_conntrack_tuple_hash *found;
10008 + struct ipt_connlimit_conn *conn;
10009 + struct list_head *hash,*lh;
10011 + spin_lock(&data->lock);
10012 + tuple = ct->tuplehash[0].tuple;
10013 + hash = &data->iphash[ipt_iphash(addr & mask)];
10015 + /* check the saved connections */
10016 + for (lh = hash->next; lh != hash; lh = lh->next) {
10017 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
10018 + found = ip_conntrack_find_get(&conn->tuple,ct);
10019 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
10021 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
10022 + /* Just to be sure we have it only once in the list.
10023 + We should'nt see tuples twice unless someone hooks this
10024 + into a table without "-p tcp --syn" */
10028 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
10029 + ipt_iphash(addr & mask),
10030 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
10031 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
10032 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
10034 + if (NULL == found) {
10035 + /* this one is gone */
10037 + list_del(lh->next);
10041 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
10042 + /* we don't care about connections which are
10043 + closed already -> ditch it */
10045 + list_del(lh->next);
10047 + nf_conntrack_put(&found->ctrack->infos[0]);
10050 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
10051 + /* same source IP address -> be counted! */
10054 + nf_conntrack_put(&found->ctrack->infos[0]);
10057 + /* save the new connection in our list */
10059 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
10060 + ipt_iphash(addr & mask),
10061 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
10062 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
10064 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
10065 + if (NULL == conn)
10067 + memset(conn,0,sizeof(*conn));
10068 + INIT_LIST_HEAD(&conn->list);
10069 + conn->tuple = tuple;
10070 + list_add(&conn->list,hash);
10073 + spin_unlock(&data->lock);
10078 +match(const struct sk_buff *skb,
10079 + const struct net_device *in,
10080 + const struct net_device *out,
10081 + const void *matchinfo,
10085 + const struct ipt_connlimit_info *info = matchinfo;
10086 + int connections, match;
10087 + struct ip_conntrack *ct;
10088 + enum ip_conntrack_info ctinfo;
10090 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10091 + if (NULL == ct) {
10092 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
10096 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
10097 + if (-1 == connections) {
10098 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
10099 + *hotdrop = 1; /* let's free some memory :-) */
10102 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
10104 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
10105 + "connections=%d limit=%d match=%s\n",
10106 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
10107 + connections, info->limit, match ? "yes" : "no");
10113 +static int check(const char *tablename,
10114 + const struct ipt_ip *ip,
10116 + unsigned int matchsize,
10117 + unsigned int hook_mask)
10119 + struct ipt_connlimit_info *info = matchinfo;
10122 + /* verify size */
10123 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
10126 + /* refuse anything but tcp */
10127 + if (ip->proto != IPPROTO_TCP)
10130 + /* init private data */
10131 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
10132 + spin_lock_init(&(info->data->lock));
10133 + for (i = 0; i < 256; i++)
10134 + INIT_LIST_HEAD(&(info->data->iphash[i]));
10139 +static void destroy(void *matchinfo, unsigned int matchinfosize)
10141 + struct ipt_connlimit_info *info = matchinfo;
10142 + struct ipt_connlimit_conn *conn;
10143 + struct list_head *hash;
10147 + for (i = 0; i < 256; i++) {
10148 + hash = &(info->data->iphash[i]);
10149 + while (hash != hash->next) {
10150 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
10151 + list_del(hash->next);
10155 + kfree(info->data);
10158 +static struct ipt_match connlimit_match = {
10159 + .name = "connlimit",
10161 + .checkentry = &check,
10162 + .destroy = &destroy,
10163 + .me = THIS_MODULE
10166 +static int __init init(void)
10168 + return ipt_register_match(&connlimit_match);
10171 +static void __exit fini(void)
10173 + ipt_unregister_match(&connlimit_match);
10176 +module_init(init);
10177 +module_exit(fini);
10178 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c
10179 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
10180 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-04-30 09:11:35.000000000 +0200
10182 +/* This kernel module matches connection mark values set by the
10183 + * CONNMARK target
10185 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
10186 + * by Henrik Nordstrom <hno@marasystems.com>
10188 + * This program is free software; you can redistribute it and/or modify
10189 + * it under the terms of the GNU General Public License as published by
10190 + * the Free Software Foundation; either version 2 of the License, or
10191 + * (at your option) any later version.
10193 + * This program is distributed in the hope that it will be useful,
10194 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10195 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10196 + * GNU General Public License for more details.
10198 + * You should have received a copy of the GNU General Public License
10199 + * along with this program; if not, write to the Free Software
10200 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10203 +#include <linux/module.h>
10204 +#include <linux/skbuff.h>
10206 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
10207 +MODULE_DESCRIPTION("IP tables connmark match module");
10208 +MODULE_LICENSE("GPL");
10210 +#include <linux/netfilter_ipv4/ip_tables.h>
10211 +#include <linux/netfilter_ipv4/ipt_connmark.h>
10212 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10215 +match(const struct sk_buff *skb,
10216 + const struct net_device *in,
10217 + const struct net_device *out,
10218 + const void *matchinfo,
10222 + const struct ipt_connmark_info *info = matchinfo;
10223 + enum ip_conntrack_info ctinfo;
10224 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10228 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
10232 +checkentry(const char *tablename,
10233 + const struct ipt_ip *ip,
10235 + unsigned int matchsize,
10236 + unsigned int hook_mask)
10238 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
10244 +static struct ipt_match connmark_match = {
10245 + .name = "connmark",
10247 + .checkentry = &checkentry,
10248 + .me = THIS_MODULE
10251 +static int __init init(void)
10253 + return ipt_register_match(&connmark_match);
10256 +static void __exit fini(void)
10258 + ipt_unregister_match(&connmark_match);
10261 +module_init(init);
10262 +module_exit(fini);
10263 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c
10264 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
10265 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c 2004-04-30 09:10:21.000000000 +0200
10267 +/* iptables match extension to limit the number of packets per second
10268 + * seperately for each destination.
10270 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
10274 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
10276 + * based on ipt_limit.c by:
10277 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
10278 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
10279 + * Rusty Russell <rusty@rustcorp.com.au>
10281 + * The general idea is to create a hash table for every dstip and have a
10282 + * seperate limit counter per tuple. This way you can do something like 'limit
10283 + * the number of syn packets for each of my internal addresses.
10285 + * Ideally this would just be implemented as a general 'hash' match, which would
10286 + * allow us to attach any iptables target to it's hash buckets. But this is
10287 + * not possible in the current iptables architecture. As always, pkttables for
10288 + * 2.7.x will help ;)
10290 +#include <linux/module.h>
10291 +#include <linux/skbuff.h>
10292 +#include <linux/spinlock.h>
10293 +#include <linux/random.h>
10294 +#include <linux/jhash.h>
10295 +#include <linux/slab.h>
10296 +#include <linux/vmalloc.h>
10297 +#include <linux/tcp.h>
10298 +#include <linux/udp.h>
10299 +#include <linux/proc_fs.h>
10300 +#include <linux/seq_file.h>
10302 +#define ASSERT_READ_LOCK(x)
10303 +#define ASSERT_WRITE_LOCK(x)
10304 +#include <linux/netfilter_ipv4/lockhelp.h>
10305 +#include <linux/netfilter_ipv4/listhelp.h>
10307 +#include <linux/netfilter_ipv4/ip_tables.h>
10308 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
10310 +/* FIXME: this is just for IP_NF_ASSERRT */
10311 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10313 +#define MS2JIFFIES(x) ((x*HZ)/1000)
10315 +MODULE_LICENSE("GPL");
10316 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
10317 +MODULE_DESCRIPTION("iptables match for limiting per destination");
10319 +/* need to declare this at the top */
10320 +static struct proc_dir_entry *dstlimit_procdir;
10321 +static struct file_operations dl_file_ops;
10323 +/* hash table crap */
10325 +struct dsthash_dst {
10326 + u_int32_t src_ip;
10327 + u_int32_t dst_ip;
10331 +struct dsthash_ent {
10332 + /* static / read-only parts in the beginning */
10333 + struct list_head list;
10334 + struct dsthash_dst dst;
10336 + /* modified structure members in the end */
10337 + unsigned long expires; /* precalculated expiry time */
10339 + unsigned long prev; /* last modification */
10340 + u_int32_t credit;
10341 + u_int32_t credit_cap, cost;
10345 +struct ipt_dstlimit_htable {
10346 + struct list_head list; /* global list of all htables */
10349 + struct dstlimit_cfg cfg; /* config */
10351 + /* used internally */
10352 + spinlock_t lock; /* lock for list_head */
10353 + u_int32_t rnd; /* random seed for hash */
10354 + struct timer_list timer; /* timer for gc */
10355 + atomic_t count; /* number entries in table */
10357 + /* seq_file stuff */
10358 + struct proc_dir_entry *pde;
10360 + struct list_head hash[0]; /* hashtable itself */
10363 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
10364 +static LIST_HEAD(dstlimit_htables);
10365 +static kmem_cache_t *dstlimit_cachep;
10367 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
10369 + return (ent->dst.dst_ip == b->dst_ip
10370 + && ent->dst.port == b->port
10371 + && ent->dst.src_ip == b->src_ip);
10374 +static inline u_int32_t
10375 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
10377 + return (jhash_3words(dst->dst_ip, dst->port,
10378 + dst->src_ip, ht->rnd) % ht->cfg.size);
10381 +static inline struct dsthash_ent *
10382 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
10384 + struct dsthash_ent *ent;
10385 + u_int32_t hash = hash_dst(ht, dst);
10386 + MUST_BE_LOCKED(&ht->lock);
10387 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
10391 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
10392 +static struct dsthash_ent *
10393 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
10395 + struct dsthash_ent *ent;
10397 + /* initialize hash with random val at the time we allocate
10398 + * the first hashtable entry */
10400 + get_random_bytes(&ht->rnd, 4);
10402 + if (ht->cfg.max &&
10403 + atomic_read(&ht->count) >= ht->cfg.max) {
10404 + /* FIXME: do something. question is what.. */
10405 + if (net_ratelimit())
10406 + printk(KERN_WARNING
10407 + "ipt_dstlimit: max count of %u reached\n",
10412 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
10414 + if (net_ratelimit())
10416 + "ipt_dstlimit: can't allocate dsthash_ent\n");
10420 + atomic_inc(&ht->count);
10422 + ent->dst.dst_ip = dst->dst_ip;
10423 + ent->dst.port = dst->port;
10424 + ent->dst.src_ip = dst->src_ip;
10426 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
10431 +static inline void
10432 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
10434 + MUST_BE_LOCKED(&ht->lock);
10436 + list_del(&ent->list);
10437 + kmem_cache_free(dstlimit_cachep, ent);
10438 + atomic_dec(&ht->count);
10440 +static void htable_gc(unsigned long htlong);
10442 +static int htable_create(struct ipt_dstlimit_info *minfo)
10445 + unsigned int size;
10446 + struct ipt_dstlimit_htable *hinfo;
10448 + if (minfo->cfg.size)
10449 + size = minfo->cfg.size;
10451 + size = (((num_physpages << PAGE_SHIFT) / 16384)
10452 + / sizeof(struct list_head));
10453 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
10458 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
10459 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
10460 + + (sizeof(struct list_head) * size));
10462 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
10465 + minfo->hinfo = hinfo;
10467 + /* copy match config into hashtable config */
10468 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
10469 + hinfo->cfg.size = size;
10470 + if (!hinfo->cfg.max)
10471 + hinfo->cfg.max = 8 * hinfo->cfg.size;
10472 + else if (hinfo->cfg.max < hinfo->cfg.size)
10473 + hinfo->cfg.max = hinfo->cfg.size;
10475 + for (i = 0; i < hinfo->cfg.size; i++)
10476 + INIT_LIST_HEAD(&hinfo->hash[i]);
10478 + atomic_set(&hinfo->count, 0);
10479 + atomic_set(&hinfo->use, 1);
10481 + hinfo->lock = SPIN_LOCK_UNLOCKED;
10482 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
10483 + if (!hinfo->pde) {
10487 + hinfo->pde->proc_fops = &dl_file_ops;
10488 + hinfo->pde->data = hinfo;
10490 + init_timer(&hinfo->timer);
10491 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
10492 + hinfo->timer.data = (unsigned long )hinfo;
10493 + hinfo->timer.function = htable_gc;
10494 + add_timer(&hinfo->timer);
10496 + WRITE_LOCK(&dstlimit_lock);
10497 + list_add(&hinfo->list, &dstlimit_htables);
10498 + WRITE_UNLOCK(&dstlimit_lock);
10503 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
10508 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
10510 + return (jiffies >= he->expires);
10513 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
10514 + int (*select)(struct ipt_dstlimit_htable *ht,
10515 + struct dsthash_ent *he))
10519 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
10521 + /* lock hash table and iterate over it */
10522 + LOCK_BH(&ht->lock);
10523 + for (i = 0; i < ht->cfg.size; i++) {
10524 + struct dsthash_ent *dh, *n;
10525 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
10526 + if ((*select)(ht, dh))
10527 + __dsthash_free(ht, dh);
10530 + UNLOCK_BH(&ht->lock);
10533 +/* hash table garbage collector, run by timer */
10534 +static void htable_gc(unsigned long htlong)
10536 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
10538 + htable_selective_cleanup(ht, select_gc);
10540 + /* re-add the timer accordingly */
10541 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
10542 + add_timer(&ht->timer);
10545 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
10547 + /* remove timer, if it is pending */
10548 + if (timer_pending(&hinfo->timer))
10549 + del_timer(&hinfo->timer);
10551 + /* remove proc entry */
10552 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
10554 + htable_selective_cleanup(hinfo, select_all);
10558 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
10560 + struct ipt_dstlimit_htable *hinfo;
10562 + READ_LOCK(&dstlimit_lock);
10563 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
10564 + if (!strcmp(name, hinfo->pde->name)) {
10565 + atomic_inc(&hinfo->use);
10566 + READ_UNLOCK(&dstlimit_lock);
10570 + READ_UNLOCK(&dstlimit_lock);
10575 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
10577 + if (atomic_dec_and_test(&hinfo->use)) {
10578 + WRITE_LOCK(&dstlimit_lock);
10579 + list_del(&hinfo->list);
10580 + WRITE_UNLOCK(&dstlimit_lock);
10581 + htable_destroy(hinfo);
10586 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
10587 + * see net/sched/sch_tbf.c in the linux source tree
10590 +/* Rusty: This is my (non-mathematically-inclined) understanding of
10591 + this algorithm. The `average rate' in jiffies becomes your initial
10592 + amount of credit `credit' and the most credit you can ever have
10593 + `credit_cap'. The `peak rate' becomes the cost of passing the
10596 + `prev' tracks the last packet hit: you gain one credit per jiffy.
10597 + If you get credit balance more than this, the extra credit is
10598 + discarded. Every time the match passes, you lose `cost' credits;
10599 + if you don't have that many, the test fails.
10601 + See Alexey's formal explanation in net/sched/sch_tbf.c.
10603 + To get the maximum range, we multiply by this factor (ie. you get N
10604 + credits per jiffy). We want to allow a rate as low as 1 per day
10605 + (slowest userspace tool allows), which means
10606 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
10608 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
10610 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
10611 + * us the power of 2 below the theoretical max, so GCC simply does a
10613 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
10614 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
10615 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
10616 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
10617 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
10618 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
10620 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
10622 +/* Precision saver. */
10623 +static inline u_int32_t
10624 +user2credits(u_int32_t user)
10626 + /* If multiplying would overflow... */
10627 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
10628 + /* Divide first. */
10629 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
10631 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
10634 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
10636 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
10637 + * CREDITS_PER_JIFFY;
10638 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
10639 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
10643 +dstlimit_match(const struct sk_buff *skb,
10644 + const struct net_device *in,
10645 + const struct net_device *out,
10646 + const void *matchinfo,
10650 + struct ipt_dstlimit_info *r =
10651 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
10652 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
10653 + unsigned long now = jiffies;
10654 + struct dsthash_ent *dh;
10655 + struct dsthash_dst dst;
10657 + memset(&dst, 0, sizeof(dst));
10659 + /* dest ip is always in hash */
10660 + dst.dst_ip = skb->nh.iph->daddr;
10662 + /* source ip only if respective hashmode, otherwise set to
10664 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
10665 + dst.src_ip = skb->nh.iph->saddr;
10667 + /* dest port only if respective mode */
10668 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
10671 + /* Must not be a fragment. */
10675 + /* Must be big enough to read ports (both UDP and TCP have
10676 + them at the start). */
10677 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
10678 + /* We've been asked to examine this packet, and we
10679 + can't. Hence, no choice but to drop. */
10684 + switch (skb->nh.iph->protocol) {
10685 + struct tcphdr *th;
10686 + struct udphdr *uh;
10687 + case IPPROTO_TCP:
10688 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
10689 + dst.port = th->dest;
10691 + case IPPROTO_UDP:
10692 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
10693 + dst.port = uh->dest;
10700 + LOCK_BH(&hinfo->lock);
10701 + dh = __dsthash_find(hinfo, &dst);
10703 + dh = __dsthash_alloc_init(hinfo, &dst);
10706 + /* enomem... don't match == DROP */
10707 + if (net_ratelimit())
10708 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
10709 + UNLOCK_BH(&hinfo->lock);
10713 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
10715 + dh->rateinfo.prev = jiffies;
10716 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
10717 + hinfo->cfg.burst);
10718 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
10719 + hinfo->cfg.burst);
10720 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
10722 + UNLOCK_BH(&hinfo->lock);
10726 + /* update expiration timeout */
10727 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
10729 + rateinfo_recalc(dh, now);
10730 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
10731 + /* We're underlimit. */
10732 + dh->rateinfo.credit -= dh->rateinfo.cost;
10733 + UNLOCK_BH(&hinfo->lock);
10737 + UNLOCK_BH(&hinfo->lock);
10739 + /* default case: we're overlimit, thus don't match */
10744 +dstlimit_checkentry(const char *tablename,
10745 + const struct ipt_ip *ip,
10747 + unsigned int matchsize,
10748 + unsigned int hook_mask)
10750 + struct ipt_dstlimit_info *r = matchinfo;
10752 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
10755 + /* Check for overflow. */
10756 + if (r->cfg.burst == 0
10757 + || user2credits(r->cfg.avg * r->cfg.burst) <
10758 + user2credits(r->cfg.avg)) {
10759 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
10760 + r->cfg.avg, r->cfg.burst);
10764 + if (r->cfg.mode == 0
10765 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
10766 + |IPT_DSTLIMIT_HASH_DIP
10767 + |IPT_DSTLIMIT_HASH_SIP))
10770 + if (!r->cfg.gc_interval)
10773 + if (!r->cfg.expire)
10776 + r->hinfo = htable_find_get(r->name);
10777 + if (!r->hinfo && (htable_create(r) != 0)) {
10781 + /* Ugly hack: For SMP, we only want to use one set */
10788 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
10790 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
10792 + htable_put(r->hinfo);
10795 +static struct ipt_match ipt_dstlimit = {
10796 + .list = { .prev = NULL, .next = NULL },
10797 + .name = "dstlimit",
10798 + .match = dstlimit_match,
10799 + .checkentry = dstlimit_checkentry,
10800 + .destroy = dstlimit_destroy,
10801 + .me = THIS_MODULE
10806 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
10808 + struct proc_dir_entry *pde = s->private;
10809 + struct ipt_dstlimit_htable *htable = pde->data;
10810 + unsigned int *bucket;
10812 + LOCK_BH(&htable->lock);
10813 + if (*pos >= htable->cfg.size)
10816 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
10818 + return ERR_PTR(-ENOMEM);
10824 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
10826 + struct proc_dir_entry *pde = s->private;
10827 + struct ipt_dstlimit_htable *htable = pde->data;
10828 + unsigned int *bucket = (unsigned int *)v;
10830 + *pos = ++(*bucket);
10831 + if (*pos >= htable->cfg.size) {
10838 +static void dl_seq_stop(struct seq_file *s, void *v)
10840 + struct proc_dir_entry *pde = s->private;
10841 + struct ipt_dstlimit_htable *htable = pde->data;
10842 + unsigned int *bucket = (unsigned int *)v;
10846 + UNLOCK_BH(&htable->lock);
10849 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
10851 + /* recalculate to show accurate numbers */
10852 + rateinfo_recalc(ent, jiffies);
10854 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
10855 + (ent->expires - jiffies)/HZ,
10856 + NIPQUAD(ent->dst.src_ip),
10857 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
10858 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
10859 + ent->rateinfo.cost);
10862 +static int dl_seq_show(struct seq_file *s, void *v)
10864 + struct proc_dir_entry *pde = s->private;
10865 + struct ipt_dstlimit_htable *htable = pde->data;
10866 + unsigned int *bucket = (unsigned int *)v;
10868 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
10869 + struct dsthash_ent *, s)) {
10870 + /* buffer was filled and unable to print that tuple */
10876 +static struct seq_operations dl_seq_ops = {
10877 + .start = dl_seq_start,
10878 + .next = dl_seq_next,
10879 + .stop = dl_seq_stop,
10880 + .show = dl_seq_show
10883 +static int dl_proc_open(struct inode *inode, struct file *file)
10885 + int ret = seq_open(file, &dl_seq_ops);
10888 + struct seq_file *sf = file->private_data;
10889 + sf->private = PDE(inode);
10894 +static struct file_operations dl_file_ops = {
10895 + .owner = THIS_MODULE,
10896 + .open = dl_proc_open,
10897 + .read = seq_read,
10898 + .llseek = seq_lseek,
10899 + .release = seq_release
10902 +static int init_or_fini(int fini)
10909 + if (ipt_register_match(&ipt_dstlimit)) {
10911 + goto cleanup_nothing;
10914 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
10915 + * quite small ? */
10916 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
10917 + sizeof(struct dsthash_ent), 0,
10918 + SLAB_HWCACHE_ALIGN, NULL, NULL);
10919 + if (!dstlimit_cachep) {
10920 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
10922 + goto cleanup_unreg_match;
10925 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
10926 + if (!dstlimit_procdir) {
10927 + printk(KERN_ERR "Unable to create proc dir entry\n");
10929 + goto cleanup_free_slab;
10935 + remove_proc_entry("ipt_dstlimit", proc_net);
10936 +cleanup_free_slab:
10937 + kmem_cache_destroy(dstlimit_cachep);
10938 +cleanup_unreg_match:
10939 + ipt_unregister_match(&ipt_dstlimit);
10945 +static int __init init(void)
10947 + return init_or_fini(0);
10950 +static void __exit fini(void)
10955 +module_init(init);
10956 +module_exit(fini);
10957 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_fuzzy.c
10958 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
10959 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_fuzzy.c 2004-04-30 09:10:22.000000000 +0200
10962 + * This module implements a simple TSK FLC
10963 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
10964 + * to limit , in an adaptive and flexible way , the packet rate crossing
10965 + * a given stream . It serves as an initial and very simple (but effective)
10966 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
10967 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
10968 + * into our code in a precise , adaptive and efficient manner.
10969 + * The goal is very similar to that of "limit" match , but using techniques of
10970 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
10971 + * avoiding over and undershoots - and stuff like that .
10974 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
10975 + * 2002-08-17 : Changed to eliminate floating point operations .
10976 + * 2002-08-23 : Coding style changes .
10979 +#include <linux/module.h>
10980 +#include <linux/skbuff.h>
10981 +#include <linux/ip.h>
10982 +#include <linux/random.h>
10983 +#include <net/tcp.h>
10984 +#include <linux/spinlock.h>
10985 +#include <linux/netfilter_ipv4/ip_tables.h>
10986 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
10989 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
10990 + Expressed in percentage
10993 +#define PAR_LOW 1/100
10994 +#define PAR_HIGH 1
10996 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
10998 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
10999 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
11000 +MODULE_LICENSE("GPL");
11002 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11010 + return ( (100*(tx-mini)) / (maxi-mini) );
11013 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11021 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
11025 +ipt_fuzzy_match(const struct sk_buff *pskb,
11026 + const struct net_device *in,
11027 + const struct net_device *out,
11028 + const void *matchinfo,
11032 + /* From userspace */
11034 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
11036 + u_int8_t random_number;
11037 + unsigned long amount;
11038 + u_int8_t howhigh, howlow;
11041 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
11043 + info->bytes_total += pskb->len;
11044 + info->packets_total++;
11046 + info->present_time = jiffies;
11048 + if (info->present_time >= info->previous_time)
11049 + amount = info->present_time - info->previous_time;
11051 + /* There was a transition : I choose to re-sample
11052 + and keep the old acceptance rate...
11056 + info->previous_time = info->present_time;
11057 + info->bytes_total = info->packets_total = 0;
11060 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
11063 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
11066 + info->previous_time = info->present_time;
11067 + info->bytes_total = info->packets_total = 0;
11069 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
11070 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
11072 + info->acceptance_rate = (u_int8_t) \
11073 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
11075 + /* In fact , the above defuzzification would require a denominator
11076 + proportional to (howhigh+howlow) but , in this particular case ,
11077 + that expression is constant .
11078 + An imediate consequence is that it isn't necessary to call
11079 + both mf_high and mf_low - but to keep things understandable ,
11084 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
11087 + if ( info->acceptance_rate < 100 )
11089 + get_random_bytes((void *)(&random_number), 1);
11091 + /* If within the acceptance , it can pass => don't match */
11092 + if (random_number <= (255 * info->acceptance_rate) / 100)
11095 + return 1; /* It can't pass ( It matches ) */
11098 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
11103 +ipt_fuzzy_checkentry(const char *tablename,
11104 + const struct ipt_ip *e,
11106 + unsigned int matchsize,
11107 + unsigned int hook_mask)
11110 + const struct ipt_fuzzy_info *info = matchinfo;
11112 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
11113 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
11114 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
11118 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
11119 + || (info->minimum_rate >= info->maximum_rate )) {
11120 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
11127 +static struct ipt_match ipt_fuzzy_reg = {
11129 + .match = ipt_fuzzy_match,
11130 + .checkentry = ipt_fuzzy_checkentry,
11131 + .me = THIS_MODULE
11134 +static int __init init(void)
11136 + return ipt_register_match(&ipt_fuzzy_reg);
11139 +static void __exit fini(void)
11141 + ipt_unregister_match(&ipt_fuzzy_reg);
11144 +module_init(init);
11145 +module_exit(fini);
11146 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c
11147 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-28 03:36:22.000000000 +0200
11148 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c 2004-04-30 09:12:49.000000000 +0200
11149 @@ -41,17 +41,17 @@
11150 struct ip_conntrack_expect *exp;
11151 struct ip_conntrack *ct;
11152 enum ip_conntrack_info ctinfo;
11154 + int ret = info->invert;
11156 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11158 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
11164 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
11171 DEBUGP("master's name = %s , info->name = %s\n",
11172 exp->expectant->helper->name, info->name);
11174 - ret = !strncmp(exp->expectant->helper->name, info->name,
11175 - strlen(exp->expectant->helper->name)) ^ info->invert;
11176 + if (info->name[0] == '\0')
11179 + ret ^= !strncmp(exp->expectant->helper->name, info->name,
11180 + strlen(exp->expectant->helper->name));
11182 READ_UNLOCK(&ip_conntrack_lock);
11185 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
11188 - /* verify that we actually should match anything */
11189 - if ( strlen(info->name) == 0 )
11195 @@ -108,7 +107,6 @@
11197 static int __init init(void)
11199 - need_ip_conntrack();
11200 return ipt_register_match(&helper_match);
11203 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_ipv4options.c
11204 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
11205 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_ipv4options.c 2004-04-30 09:10:27.000000000 +0200
11208 + This is a module which is used to match ipv4 options.
11209 + This file is distributed under the terms of the GNU General Public
11210 + License (GPL). Copies of the GPL can be obtained from:
11211 + ftp://prep.ai.mit.edu/pub/gnu/GPL
11213 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
11214 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
11215 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
11216 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
11217 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
11220 +#include <linux/module.h>
11221 +#include <linux/skbuff.h>
11222 +#include <net/ip.h>
11224 +#include <linux/netfilter_ipv4/ip_tables.h>
11225 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
11227 +MODULE_LICENSE("GPL");
11228 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
11231 +match(const struct sk_buff *skb,
11232 + const struct net_device *in,
11233 + const struct net_device *out,
11234 + const void *matchinfo,
11238 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
11239 + const struct iphdr *iph = skb->nh.iph;
11240 + const struct ip_options *opt;
11242 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
11243 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
11245 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
11246 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
11247 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
11248 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
11249 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
11250 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
11255 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
11256 + /* there are options, and we don't need to care which one */
11259 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
11260 + /* there are options but we don't want any ! */
11265 + opt = &(IPCB(skb)->opt);
11267 + /* source routing */
11268 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
11269 + if (!((opt->srr) & (opt->is_strictroute)))
11272 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
11273 + if (!((opt->srr) & (!opt->is_strictroute)))
11276 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
11280 + /* record route */
11281 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
11285 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
11290 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
11294 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
11298 + /* router-alert option */
11299 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
11300 + if (!opt->router_alert)
11303 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
11304 + if (opt->router_alert)
11313 +checkentry(const char *tablename,
11314 + const struct ipt_ip *ip,
11316 + unsigned int matchsize,
11317 + unsigned int hook_mask)
11319 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
11320 + /* Check the size */
11321 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
11323 + /* Now check the coherence of the data ... */
11324 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
11325 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
11326 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
11327 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
11328 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
11329 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
11330 + return 0; /* opposites */
11331 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
11332 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
11333 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
11334 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
11335 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
11336 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
11337 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
11338 + return 0; /* opposites */
11339 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
11340 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
11341 + return 0; /* cannot match in the same time loose and strict source routing */
11342 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
11343 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
11344 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
11345 + return 0; /* opposites */
11346 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
11347 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
11348 + return 0; /* opposites */
11349 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
11350 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
11351 + return 0; /* opposites */
11352 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
11353 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
11354 + return 0; /* opposites */
11356 + /* everything looks ok. */
11360 +static struct ipt_match ipv4options_match = {
11361 + .name = "ipv4options",
11363 + .checkentry = checkentry,
11364 + .me = THIS_MODULE
11367 +static int __init init(void)
11369 + return ipt_register_match(&ipv4options_match);
11372 +static void __exit fini(void)
11374 + ipt_unregister_match(&ipv4options_match);
11377 +module_init(init);
11378 +module_exit(fini);
11379 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_mport.c
11380 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
11381 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_mport.c 2004-04-30 09:10:30.000000000 +0200
11383 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
11384 + the same place so we can treat them as equal. */
11385 +#include <linux/module.h>
11386 +#include <linux/types.h>
11387 +#include <linux/udp.h>
11388 +#include <linux/skbuff.h>
11390 +#include <linux/netfilter_ipv4/ipt_mport.h>
11391 +#include <linux/netfilter_ipv4/ip_tables.h>
11393 +MODULE_LICENSE("GPL");
11396 +#define duprintf(format, args...) printk(format , ## args)
11398 +#define duprintf(format, args...)
11401 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
11403 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
11407 + u_int16_t pflags = minfo->pflags;
11408 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
11412 + && minfo->ports[i] == 65535)
11415 + s = minfo->ports[i];
11417 + if (pflags & m) {
11418 + e = minfo->ports[++i];
11423 + if (minfo->flags & IPT_MPORT_SOURCE
11424 + && src >= s && src <= e)
11427 + if (minfo->flags & IPT_MPORT_DESTINATION
11428 + && dst >= s && dst <= e)
11436 +match(const struct sk_buff *skb,
11437 + const struct net_device *in,
11438 + const struct net_device *out,
11439 + const void *matchinfo,
11444 + const struct ipt_mport *minfo = matchinfo;
11449 + /* Must be big enough to read ports (both UDP and TCP have
11450 + them at the start). */
11451 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
11452 + /* We've been asked to examine this packet, and we
11453 + can't. Hence, no choice but to drop. */
11454 + duprintf("ipt_multiport:"
11455 + " Dropping evil offset=0 tinygram.\n");
11460 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
11463 +/* Called when user tries to insert an entry of this type. */
11465 +checkentry(const char *tablename,
11466 + const struct ipt_ip *ip,
11468 + unsigned int matchsize,
11469 + unsigned int hook_mask)
11471 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
11474 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
11475 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
11476 + && !(ip->invflags & IPT_INV_PROTO)
11477 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
11480 +static struct ipt_match mport_match = {
11483 + .checkentry = &checkentry,
11484 + .me = THIS_MODULE
11487 +static int __init init(void)
11489 + return ipt_register_match(&mport_match);
11492 +static void __exit fini(void)
11494 + ipt_unregister_match(&mport_match);
11497 +module_init(init);
11498 +module_exit(fini);
11499 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_nth.c
11500 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
11501 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_nth.c 2004-04-30 09:10:36.000000000 +0200
11504 + This is a module which is used for match support for every Nth packet
11505 + This file is distributed under the terms of the GNU General Public
11506 + License (GPL). Copies of the GPL can be obtained from:
11507 + ftp://prep.ai.mit.edu/pub/gnu/GPL
11509 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
11510 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
11511 + * added support for multiple counters
11512 + * added support for matching on individual packets
11513 + in the counter cycle
11514 + 2004-02-19 Harald Welte <laforge@netfilter.org>
11519 +#include <linux/module.h>
11520 +#include <linux/skbuff.h>
11521 +#include <linux/ip.h>
11522 +#include <net/tcp.h>
11523 +#include <linux/spinlock.h>
11524 +#include <linux/netfilter_ipv4/ip_tables.h>
11525 +#include <linux/netfilter_ipv4/ipt_nth.h>
11527 +MODULE_LICENSE("GPL");
11528 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
11531 + * State information.
11535 + u_int16_t number;
11538 +static struct state states[IPT_NTH_NUM_COUNTERS];
11541 +ipt_nth_match(const struct sk_buff *pskb,
11542 + const struct net_device *in,
11543 + const struct net_device *out,
11544 + const void *matchinfo,
11548 + /* Parameters from userspace */
11549 + const struct ipt_nth_info *info = matchinfo;
11550 + unsigned counter = info->counter;
11551 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
11553 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
11557 + spin_lock(&states[counter].lock);
11559 + /* Are we matching every nth packet?*/
11560 + if (info->packet == 0xFF)
11562 + /* We're matching every nth packet and only every nth packet*/
11563 + /* Do we match or invert match? */
11564 + if (info->not == 0)
11566 + if (states[counter].number == 0)
11568 + ++states[counter].number;
11571 + if (states[counter].number >= info->every)
11572 + states[counter].number = 0; /* reset the counter */
11574 + ++states[counter].number;
11579 + if (states[counter].number == 0)
11581 + ++states[counter].number;
11584 + if (states[counter].number >= info->every)
11585 + states[counter].number = 0;
11587 + ++states[counter].number;
11593 + /* We're using the --packet, so there must be a rule for every value */
11594 + if (states[counter].number == info->packet)
11596 + /* only increment the counter when a match happens */
11597 + if (states[counter].number >= info->every)
11598 + states[counter].number = 0; /* reset the counter */
11600 + ++states[counter].number;
11608 + /* don't match */
11609 + spin_unlock(&states[counter].lock);
11613 + spin_unlock(&states[counter].lock);
11618 +ipt_nth_checkentry(const char *tablename,
11619 + const struct ipt_ip *e,
11621 + unsigned int matchsize,
11622 + unsigned int hook_mask)
11624 + /* Parameters from userspace */
11625 + const struct ipt_nth_info *info = matchinfo;
11626 + unsigned counter = info->counter;
11627 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
11629 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
11633 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
11634 + printk("nth: matchsize %u != %u\n", matchsize,
11635 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
11639 + states[counter].number = info->startat;
11644 +static struct ipt_match ipt_nth_reg = {
11646 + .match = ipt_nth_match,
11647 + .checkentry = ipt_nth_checkentry,
11648 + .me = THIS_MODULE
11651 +static int __init init(void)
11653 + unsigned counter;
11655 + memset(&states, 0, sizeof(states));
11656 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
11657 + spin_lock_init(&(states[counter].lock));
11659 + return ipt_register_match(&ipt_nth_reg);
11662 +static void __exit fini(void)
11664 + ipt_unregister_match(&ipt_nth_reg);
11667 +module_init(init);
11668 +module_exit(fini);
11669 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_osf.c
11670 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
11671 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_osf.c 2004-04-30 09:10:38.000000000 +0200
11676 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
11679 + * This program is free software; you can redistribute it and/or modify
11680 + * it under the terms of the GNU General Public License as published by
11681 + * the Free Software Foundation; either version 2 of the License, or
11682 + * (at your option) any later version.
11684 + * This program is distributed in the hope that it will be useful,
11685 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11686 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11687 + * GNU General Public License for more details.
11689 + * You should have received a copy of the GNU General Public License
11690 + * along with this program; if not, write to the Free Software
11691 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11695 + * OS fingerprint matching module.
11696 + * It simply compares various parameters from SYN packet with
11697 + * some hardcoded ones.
11699 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
11703 +#include <linux/config.h>
11704 +#include <linux/kernel.h>
11705 +#include <linux/types.h>
11706 +#include <linux/string.h>
11707 +#include <linux/smp.h>
11708 +#include <linux/module.h>
11709 +#include <linux/skbuff.h>
11710 +#include <linux/file.h>
11711 +#include <linux/ip.h>
11712 +#include <linux/proc_fs.h>
11713 +#include <linux/fs.h>
11714 +#include <linux/slab.h>
11715 +#include <linux/spinlock.h>
11716 +#include <linux/ctype.h>
11717 +#include <linux/list.h>
11718 +#include <linux/if.h>
11720 +#include <net/sock.h>
11721 +#include <net/ip.h>
11723 +#include <linux/netfilter_ipv4/ip_tables.h>
11725 +#include <linux/netfilter_ipv4/ipt_osf.h>
11730 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
11731 +#define loga(x...) printk(x)
11733 +#define log(x...) do {} while(0)
11734 +#define loga(x...) do {} while(0)
11737 +#define FMATCH_WRONG 0
11738 +#define FMATCH_OK 1
11739 +#define FMATCH_OPT_WRONG 2
11741 +#define OPTDEL ','
11742 +#define OSFPDEL ':'
11743 +#define MAXOPTSTRLEN 128
11744 +#define OSFFLUSH "FLUSH"
11746 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
11747 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
11748 +static struct list_head finger_list;
11749 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
11750 + const void *, int,
11751 + const void *, u_int16_t,
11753 +static int checkentry(const char *, const struct ipt_ip *, void *,
11754 + unsigned int, unsigned int);
11756 +static unsigned long seq, ipt_osf_groups = 1;
11757 +static struct sock *nts;
11759 +static struct ipt_match osf_match =
11769 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
11771 + unsigned int size;
11772 + struct sk_buff *skb;
11773 + struct ipt_osf_nlmsg *data;
11774 + struct nlmsghdr *nlh;
11776 + size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
11778 + skb = alloc_skb(size, GFP_ATOMIC);
11781 + log("skb_alloc() failed.\n");
11785 + nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
11787 + data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
11789 + memcpy(&data->f, f, sizeof(struct osf_finger));
11790 + memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
11791 + memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
11793 + NETLINK_CB(skb).dst_groups = ipt_osf_groups;
11794 + netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
11800 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
11802 + struct iphdr *ip = skb->nh.iph;
11804 + if (flags & IPT_OSF_SMART)
11806 + struct in_device *in_dev = in_dev_get(skb->dev);
11810 + if (inet_ifa_match(ip->saddr, ifa))
11812 + in_dev_put(in_dev);
11813 + return (ip->ttl == f_ttl);
11816 + endfor_ifa(in_dev);
11818 + in_dev_put(in_dev);
11819 + return (ip->ttl <= f_ttl);
11822 + return (ip->ttl == f_ttl);
11826 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
11827 + const void *matchinfo, int offset,
11828 + const void *hdr, u_int16_t datalen,
11831 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
11832 + struct iphdr *ip = skb->nh.iph;
11833 + struct tcphdr *tcp;
11834 + int fmatch = FMATCH_WRONG, fcount = 0;
11835 + unsigned long totlen, optsize = 0, window;
11836 + unsigned char df, *optp = NULL, *_optp = NULL;
11837 + char check_WSS = 0;
11838 + struct list_head *ent;
11839 + struct osf_finger *f;
11841 + if (!ip || !info)
11844 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
11849 + totlen = ntohs(ip->tot_len);
11850 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
11851 + window = ntohs(tcp->window);
11853 + if (tcp->doff*4 > sizeof(struct tcphdr))
11855 + _optp = optp = (char *)(tcp+1);
11856 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
11860 + /* Actually we can create hash/table of all genres and search
11861 + * only in appropriate part, but here is initial variant,
11862 + * so will use slow path.
11864 + read_lock(&osf_lock);
11865 + list_for_each(ent, &finger_list)
11867 + f = list_entry(ent, struct osf_finger, flist);
11869 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
11873 + fmatch = FMATCH_WRONG;
11875 + if (totlen == f->ss && df == f->df &&
11876 + smart_dec(skb, info->flags, f->ttl))
11878 + unsigned long foptsize;
11880 + unsigned short mss = 0;
11884 + switch (f->wss.wc)
11886 + case 0: check_WSS = 0; break;
11887 + case 'S': check_WSS = 1; break;
11888 + case 'T': check_WSS = 2; break;
11889 + case '%': check_WSS = 3; break;
11890 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
11891 + f->wss.wc, f->genre, f->details);
11895 + if (check_WSS == 4)
11898 + /* Check options */
11901 + for (optnum=0; optnum<f->opt_num; ++optnum)
11902 + foptsize += f->opt[optnum].length;
11905 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
11910 + fmatch = FMATCH_OK;
11911 + loga("\tYEP : matching without options.\n");
11912 + if ((info->flags & IPT_OSF_LOG) &&
11913 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
11920 + for (optnum=0; optnum<f->opt_num; ++optnum)
11922 + if (f->opt[optnum].kind == (*optp))
11924 + unsigned char len = f->opt[optnum].length;
11925 + unsigned char *optend = optp + len;
11926 + int loop_cont = 0;
11928 + fmatch = FMATCH_OK;
11934 + mss = ntohs(*(unsigned short *)(optp+2));
11949 + /* Skip kind and length fields*/
11952 + if (f->opt[optnum].wc.val != 0)
11954 + unsigned long tmp = 0;
11956 + /* Hmmm... It looks a bit ugly. :) */
11957 + memcpy(&tmp, optp,
11958 + (len > sizeof(unsigned long)?
11959 + sizeof(unsigned long):len));
11960 + /* 2 + 2: optlen(2 bytes) +
11961 + * kind(1 byte) + length(1 byte) */
11963 + tmp = ntohs(tmp);
11965 + tmp = ntohl(tmp);
11967 + if (f->opt[optnum].wc.wc == '%')
11969 + if ((tmp % f->opt[optnum].wc.val) != 0)
11970 + fmatch = FMATCH_OPT_WRONG;
11972 + else if (tmp != f->opt[optnum].wc.val)
11973 + fmatch = FMATCH_OPT_WRONG;
11980 + fmatch = FMATCH_OPT_WRONG;
11982 + if (fmatch != FMATCH_OK)
11986 + if (fmatch != FMATCH_OPT_WRONG)
11988 + fmatch = FMATCH_WRONG;
11990 + switch (check_WSS)
11993 + if (f->wss.val == 0 || window == f->wss.val)
11994 + fmatch = FMATCH_OK;
11996 + case 1: /* MSS */
11997 +/* Lurked in OpenBSD */
11998 +#define SMART_MSS 1460
11999 + if (window == f->wss.val*mss ||
12000 + window == f->wss.val*SMART_MSS)
12001 + fmatch = FMATCH_OK;
12003 + case 2: /* MTU */
12004 + if (window == f->wss.val*(mss+40) ||
12005 + window == f->wss.val*(SMART_MSS+40))
12006 + fmatch = FMATCH_OK;
12008 + case 3: /* MOD */
12009 + if ((window % f->wss.val) == 0)
12010 + fmatch = FMATCH_OK;
12016 + if (fmatch == FMATCH_OK)
12019 + log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
12020 + f->genre, f->version,
12021 + f->subtype, f->details,
12022 + NIPQUAD(ip->saddr), ntohs(tcp->source),
12023 + NIPQUAD(ip->daddr), ntohs(tcp->dest),
12024 + f->ttl - ip->ttl);
12025 + if (info->flags & IPT_OSF_NETLINK)
12027 + spin_lock_bh(&ipt_osf_netlink_lock);
12028 + ipt_osf_nlsend(f, skb);
12029 + spin_unlock_bh(&ipt_osf_netlink_lock);
12031 + if ((info->flags & IPT_OSF_LOG) &&
12032 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
12037 + if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
12039 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
12040 + unsigned int i, optsize;
12041 + struct osf_finger fg;
12043 + memset(&fg, 0, sizeof(fg));
12045 + if ((info->flags & IPT_OSF_LOG))
12046 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
12049 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
12050 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
12051 + opt, optsize) < 0)
12053 + if (info->flags & IPT_OSF_LOG)
12054 + loga("TRUNCATED");
12055 + if (info->flags & IPT_OSF_NETLINK)
12056 + strcpy(fg.details, "TRUNCATED");
12060 + for (i = 0; i < optsize; i++)
12062 + if (info->flags & IPT_OSF_LOG)
12063 + loga("%02X", opt[i]);
12065 + if (info->flags & IPT_OSF_NETLINK)
12066 + memcpy(fg.details, opt, MAXDETLEN);
12069 + if ((info->flags & IPT_OSF_LOG))
12070 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
12071 + NIPQUAD(ip->saddr), ntohs(tcp->source),
12072 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
12074 + if (info->flags & IPT_OSF_NETLINK)
12076 + fg.wss.val = window;
12077 + fg.ttl = ip->ttl;
12080 + strncpy(fg.genre, "Unknown", MAXGENRELEN);
12082 + spin_lock_bh(&ipt_osf_netlink_lock);
12083 + ipt_osf_nlsend(&fg, skb);
12084 + spin_unlock_bh(&ipt_osf_netlink_lock);
12088 + read_unlock(&osf_lock);
12090 + return (fmatch == FMATCH_OK)?1:0;
12094 +checkentry(const char *tablename,
12095 + const struct ipt_ip *ip,
12097 + unsigned int matchsize,
12098 + unsigned int hook_mask)
12100 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
12102 + if (ip->proto != IPPROTO_TCP)
12108 +static char * osf_strchr(char *ptr, char c)
12112 + tmp = strchr(ptr, c);
12114 + while (tmp && tmp+1 && isspace(*(tmp+1)))
12120 +static struct osf_finger * finger_alloc(void)
12122 + struct osf_finger *f;
12124 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
12126 + memset(f, 0, sizeof(struct osf_finger));
12131 +static void finger_free(struct osf_finger *f)
12133 + memset(f, 0, sizeof(struct osf_finger));
12138 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
12142 + unsigned long val;
12146 + while (ptr != NULL && i < olen)
12155 + ptr = osf_strchr(&obuf[i], OPTDEL);
12160 + i += (int)(ptr-&obuf[i]);
12167 + op = OSFOPT_SACKP;
12168 + ptr = osf_strchr(&obuf[i], OPTDEL);
12173 + i += (int)(ptr-&obuf[i]);
12181 + ptr = osf_strchr(&obuf[i], OPTDEL);
12186 + i += (int)(ptr-&obuf[i]);
12194 + ptr = osf_strchr(&obuf[i], OPTDEL);
12197 + switch (obuf[i+1])
12199 + case '%': wc = '%'; break;
12200 + case 'S': wc = 'S'; break;
12201 + case 'T': wc = 'T'; break;
12202 + default: wc = 0; break;
12208 + val = simple_strtoul(&obuf[i+2], NULL, 10);
12210 + val = simple_strtoul(&obuf[i+1], NULL, 10);
12211 + i += (int)(ptr-&obuf[i]);
12219 + ptr = osf_strchr(&obuf[i], OPTDEL);
12222 + if (obuf[i+1] == '%')
12227 + val = simple_strtoul(&obuf[i+2], NULL, 10);
12229 + val = simple_strtoul(&obuf[i+1], NULL, 10);
12230 + i += (int)(ptr-&obuf[i]);
12238 + ptr = osf_strchr(&obuf[i], OPTDEL);
12243 + i += (int)(ptr-&obuf[i]);
12250 + ptr = osf_strchr(&obuf[i], OPTDEL);
12254 + i += (int)(ptr-&obuf[i]);
12262 + opt[*optnum].kind = IANA_opts[op].kind;
12263 + opt[*optnum].length = IANA_opts[op].length;
12264 + opt[*optnum].wc.wc = wc;
12265 + opt[*optnum].wc.val = val;
12271 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
12273 + struct list_head *ent;
12274 + struct osf_finger *f = NULL;
12280 + read_lock_bh(&osf_lock);
12281 + list_for_each(ent, &finger_list)
12283 + f = list_entry(ent, struct osf_finger, flist);
12285 + log("%s [%s]", f->genre, f->details);
12287 + count += sprintf(buf+count, "%s - %s[%s] : %s",
12288 + f->genre, f->version,
12289 + f->subtype, f->details);
12294 + //count += sprintf(buf+count, " OPT: ");
12295 + for (i=0; i<f->opt_num; ++i)
12297 + //count += sprintf(buf+count, "%d.%c%lu; ",
12298 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
12299 + loga("%d.%c%lu; ",
12300 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
12304 + count += sprintf(buf+count, "\n");
12306 + read_unlock_bh(&osf_lock);
12311 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
12315 + char obuf[MAXOPTSTRLEN];
12316 + struct osf_finger *finger;
12317 + struct list_head *ent, *n;
12319 + char *pbeg, *pend;
12321 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
12324 + write_lock_bh(&osf_lock);
12325 + list_for_each_safe(ent, n, &finger_list)
12328 + finger = list_entry(ent, struct osf_finger, flist);
12329 + list_del(&finger->flist);
12330 + finger_free(finger);
12332 + write_unlock_bh(&osf_lock);
12334 + log("Flushed %d entries.\n", i);
12341 + for (i=0; i<count && buffer[i] != '\0'; ++i)
12342 + if (buffer[i] == ':')
12345 + if (cnt != 8 || i != count)
12347 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
12352 + memset(obuf, 0, sizeof(obuf));
12354 + finger = finger_alloc();
12357 + log("Failed to allocate new fingerprint entry.\n");
12361 + pbeg = (char *)buffer;
12362 + pend = osf_strchr(pbeg, OSFPDEL);
12366 + if (pbeg[0] == 'S')
12368 + finger->wss.wc = 'S';
12369 + if (pbeg[1] == '%')
12370 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
12371 + else if (pbeg[1] == '*')
12372 + finger->wss.val = 0;
12374 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
12376 + else if (pbeg[0] == 'T')
12378 + finger->wss.wc = 'T';
12379 + if (pbeg[1] == '%')
12380 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
12381 + else if (pbeg[1] == '*')
12382 + finger->wss.val = 0;
12384 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
12386 + else if (pbeg[0] == '%')
12388 + finger->wss.wc = '%';
12389 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
12391 + else if (isdigit(pbeg[0]))
12393 + finger->wss.wc = 0;
12394 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
12399 + pend = osf_strchr(pbeg, OSFPDEL);
12403 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
12406 + pend = osf_strchr(pbeg, OSFPDEL);
12410 + finger->df = simple_strtoul(pbeg, NULL, 10);
12413 + pend = osf_strchr(pbeg, OSFPDEL);
12417 + finger->ss = simple_strtoul(pbeg, NULL, 10);
12421 + pend = osf_strchr(pbeg, OSFPDEL);
12425 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
12429 + pend = osf_strchr(pbeg, OSFPDEL);
12433 + if (pbeg[0] == '@' || pbeg[0] == '*')
12434 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
12436 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
12440 + pend = osf_strchr(pbeg, OSFPDEL);
12444 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
12448 + pend = osf_strchr(pbeg, OSFPDEL);
12452 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
12456 + cnt = snprintf(finger->details,
12457 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
12460 + log("%s - %s[%s] : %s\n",
12461 + finger->genre, finger->version,
12462 + finger->subtype, finger->details);
12464 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
12467 + write_lock_bh(&osf_lock);
12468 + list_add_tail(&finger->flist, &finger_list);
12469 + write_unlock_bh(&osf_lock);
12474 +static int __init osf_init(void)
12477 + struct proc_dir_entry *p;
12479 + log("Startng OS fingerprint matching module.\n");
12481 + INIT_LIST_HEAD(&finger_list);
12483 + err = ipt_register_match(&osf_match);
12486 + log("Failed to register OS fingerprint matching module.\n");
12490 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
12493 + ipt_unregister_match(&osf_match);
12497 + p->write_proc = osf_proc_write;
12498 + p->read_proc = osf_proc_read;
12500 + nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
12503 + log("netlink_kernel_create() failed\n");
12504 + remove_proc_entry("sys/net/ipv4/osf", NULL);
12505 + ipt_unregister_match(&osf_match);
12512 +static void __exit osf_fini(void)
12514 + struct list_head *ent, *n;
12515 + struct osf_finger *f;
12517 + remove_proc_entry("sys/net/ipv4/osf", NULL);
12518 + ipt_unregister_match(&osf_match);
12519 + if (nts && nts->sk_socket)
12520 + sock_release(nts->sk_socket);
12522 + list_for_each_safe(ent, n, &finger_list)
12524 + f = list_entry(ent, struct osf_finger, flist);
12525 + list_del(&f->flist);
12529 + log("OS fingerprint matching module finished.\n");
12532 +module_init(osf_init);
12533 +module_exit(osf_fini);
12535 +MODULE_LICENSE("GPL");
12536 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
12537 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
12538 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c
12539 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c 2004-04-28 03:36:37.000000000 +0200
12540 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c 2004-04-30 09:13:14.000000000 +0200
12542 * This program is free software; you can redistribute it and/or modify
12543 * it under the terms of the GNU General Public License version 2 as
12544 * published by the Free Software Foundation.
12546 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
12549 #include <linux/module.h>
12550 #include <linux/skbuff.h>
12551 #include <linux/file.h>
12552 +#include <linux/ip.h>
12553 +#include <linux/tcp.h>
12554 +#include <linux/udp.h>
12555 #include <net/sock.h>
12556 +#include <net/tcp.h>
12557 +#include <net/udp.h>
12559 #include <linux/netfilter_ipv4/ipt_owner.h>
12560 #include <linux/netfilter_ipv4/ip_tables.h>
12562 MODULE_DESCRIPTION("iptables owner match");
12565 -match_comm(const struct sk_buff *skb, const char *comm)
12566 +match_comm(const struct sock *sk, const char *comm)
12568 struct task_struct *g, *p;
12569 struct files_struct *files;
12571 spin_lock(&files->file_lock);
12572 for (i=0; i < files->max_fds; i++) {
12573 if (fcheck_files(files, i) ==
12574 - skb->sk->sk_socket->file) {
12575 + sk->sk_socket->file) {
12576 spin_unlock(&files->file_lock);
12578 read_unlock(&tasklist_lock);
12583 -match_pid(const struct sk_buff *skb, pid_t pid)
12584 +match_pid(const struct sock *sk, pid_t pid)
12586 struct task_struct *p;
12587 struct files_struct *files;
12589 spin_lock(&files->file_lock);
12590 for (i=0; i < files->max_fds; i++) {
12591 if (fcheck_files(files, i) ==
12592 - skb->sk->sk_socket->file) {
12593 + sk->sk_socket->file) {
12594 spin_unlock(&files->file_lock);
12596 read_unlock(&tasklist_lock);
12597 @@ -86,10 +93,10 @@
12601 -match_sid(const struct sk_buff *skb, pid_t sid)
12602 +match_sid(const struct sock *sk, pid_t sid)
12604 struct task_struct *g, *p;
12605 - struct file *file = skb->sk->sk_socket->file;
12606 + struct file *file = sk->sk_socket->file;
12609 read_lock(&tasklist_lock);
12610 @@ -129,41 +136,71 @@
12613 const struct ipt_owner_info *info = matchinfo;
12614 + struct iphdr *iph = skb->nh.iph;
12615 + struct sock *sk = NULL;
12621 + if (iph->protocol == IPPROTO_TCP) {
12622 + struct tcphdr *tcph =
12623 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
12624 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
12625 + iph->daddr, tcph->dest,
12626 + skb->dev->ifindex);
12627 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
12628 + tcp_tw_put((struct tcp_tw_bucket *)sk);
12631 + } else if (iph->protocol == IPPROTO_UDP) {
12632 + struct udphdr *udph =
12633 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
12634 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
12635 + udph->dest, skb->dev->ifindex);
12639 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
12641 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
12644 if(info->match & IPT_OWNER_UID) {
12645 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
12646 + if ((sk->sk_socket->file->f_uid != info->uid) ^
12647 !!(info->invert & IPT_OWNER_UID))
12652 if(info->match & IPT_OWNER_GID) {
12653 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
12654 + if ((sk->sk_socket->file->f_gid != info->gid) ^
12655 !!(info->invert & IPT_OWNER_GID))
12660 if(info->match & IPT_OWNER_PID) {
12661 - if (!match_pid(skb, info->pid) ^
12662 + if (!match_pid(sk, info->pid) ^
12663 !!(info->invert & IPT_OWNER_PID))
12668 if(info->match & IPT_OWNER_SID) {
12669 - if (!match_sid(skb, info->sid) ^
12670 + if (!match_sid(sk, info->sid) ^
12671 !!(info->invert & IPT_OWNER_SID))
12676 if(info->match & IPT_OWNER_COMM) {
12677 - if (!match_comm(skb, info->comm) ^
12678 + if (!match_comm(sk, info->comm) ^
12679 !!(info->invert & IPT_OWNER_COMM))
12695 @@ -173,11 +210,19 @@
12696 unsigned int matchsize,
12697 unsigned int hook_mask)
12700 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
12701 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
12705 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
12706 + (1 << NF_IP_LOCAL_IN))) {
12707 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
12708 + "or POST_ROUTING.\n");
12712 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
12713 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
12714 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
12718 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
12719 printk("Matchsize %u != %Zu\n", matchsize,
12720 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c
12721 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
12722 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c 2004-04-30 09:13:22.000000000 +0200
12724 +/* IP tables module for matching IPsec policy
12726 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
12728 + * This program is free software; you can redistribute it and/or modify
12729 + * it under the terms of the GNU General Public License version 2 as
12730 + * published by the Free Software Foundation.
12733 +#include <linux/kernel.h>
12734 +#include <linux/config.h>
12735 +#include <linux/module.h>
12736 +#include <linux/skbuff.h>
12737 +#include <linux/init.h>
12738 +#include <net/xfrm.h>
12740 +#include <linux/netfilter_ipv4.h>
12741 +#include <linux/netfilter_ipv4/ipt_policy.h>
12742 +#include <linux/netfilter_ipv4/ip_tables.h>
12744 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
12745 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
12746 +MODULE_LICENSE("GPL");
12750 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
12752 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
12754 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
12755 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
12756 + MISMATCH(proto, x->id.proto) ||
12757 + MISMATCH(mode, x->props.mode) ||
12758 + MISMATCH(spi, x->id.spi) ||
12759 + MISMATCH(reqid, x->props.reqid))
12765 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
12767 + const struct ipt_policy_elem *e;
12768 + struct sec_path *sp = skb->sp;
12769 + int strict = info->flags & POLICY_MATCH_STRICT;
12774 + if (strict && info->len != sp->len)
12777 + for (i = sp->len - 1; i >= 0; i--) {
12778 + pos = strict ? i - sp->len + 1 : 0;
12779 + if (pos >= info->len)
12781 + e = &info->pol[pos];
12783 + if (match_xfrm_state(sp->x[i].xvec, e)) {
12786 + } else if (strict)
12790 + return strict ? 1 : 0;
12794 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
12796 + const struct ipt_policy_elem *e;
12797 + struct dst_entry *dst = skb->dst;
12798 + int strict = info->flags & POLICY_MATCH_STRICT;
12801 + if (dst->xfrm == NULL)
12804 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
12805 + pos = strict ? i : 0;
12806 + if (pos >= info->len)
12808 + e = &info->pol[pos];
12810 + if (match_xfrm_state(dst->xfrm, e)) {
12813 + } else if (strict)
12817 + return strict ? 1 : 0;
12820 +static int match(const struct sk_buff *skb,
12821 + const struct net_device *in,
12822 + const struct net_device *out,
12823 + const void *matchinfo, int offset, int *hotdrop)
12825 + const struct ipt_policy_info *info = matchinfo;
12828 + if (info->flags & POLICY_MATCH_IN)
12829 + ret = match_policy_in(skb, info);
12831 + ret = match_policy_out(skb, info);
12834 + if (info->flags & POLICY_MATCH_NONE)
12838 + } else if (info->flags & POLICY_MATCH_NONE)
12844 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
12845 + void *matchinfo, unsigned int matchsize,
12846 + unsigned int hook_mask)
12848 + struct ipt_policy_info *info = matchinfo;
12850 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
12851 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
12852 + matchsize, IPT_ALIGN(sizeof(*info)));
12855 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
12856 + printk(KERN_ERR "ipt_policy: neither incoming nor "
12857 + "outgoing policy selected\n");
12860 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
12861 + && info->flags & POLICY_MATCH_OUT) {
12862 + printk(KERN_ERR "ipt_policy: output policy not valid in "
12863 + "PRE_ROUTING and INPUT\n");
12866 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
12867 + && info->flags & POLICY_MATCH_IN) {
12868 + printk(KERN_ERR "ipt_policy: input policy not valid in "
12869 + "POST_ROUTING and OUTPUT\n");
12872 + if (info->len > POLICY_MAX_ELEM) {
12873 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
12880 +static struct ipt_match policy_match =
12882 + .name = "policy",
12884 + .checkentry = checkentry,
12885 + .me = THIS_MODULE,
12888 +static int __init init(void)
12890 + return ipt_register_match(&policy_match);
12893 +static void __exit fini(void)
12895 + ipt_unregister_match(&policy_match);
12898 +module_init(init);
12899 +module_exit(fini);
12900 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_pool.c
12901 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
12902 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_pool.c 2004-04-30 09:10:40.000000000 +0200
12904 +/* Kernel module to match an IP address pool. */
12906 +#include <linux/module.h>
12907 +#include <linux/ip.h>
12908 +#include <linux/skbuff.h>
12910 +#include <linux/netfilter_ipv4/ip_tables.h>
12911 +#include <linux/netfilter_ipv4/ip_pool.h>
12912 +#include <linux/netfilter_ipv4/ipt_pool.h>
12914 +static inline int match_pool(
12919 + if (ip_pool_match(index, ntohl(addr)))
12925 + const struct sk_buff *skb,
12926 + const struct net_device *in,
12927 + const struct net_device *out,
12928 + const void *matchinfo,
12931 + u_int16_t datalen,
12934 + const struct ipt_pool_info *info = matchinfo;
12935 + const struct iphdr *iph = skb->nh.iph;
12937 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
12938 + info->flags&IPT_POOL_INV_SRC))
12941 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
12942 + info->flags&IPT_POOL_INV_DST))
12948 +static int checkentry(
12949 + const char *tablename,
12950 + const struct ipt_ip *ip,
12952 + unsigned int matchsize,
12953 + unsigned int hook_mask
12955 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
12960 +static struct ipt_match pool_match
12961 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
12963 +static int __init init(void)
12965 + return ipt_register_match(&pool_match);
12968 +static void __exit fini(void)
12970 + ipt_unregister_match(&pool_match);
12973 +module_init(init);
12974 +module_exit(fini);
12975 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_psd.c
12976 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
12977 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_psd.c 2004-04-30 09:10:44.000000000 +0200
12980 + This is a module which is used for PSD (portscan detection)
12981 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
12982 + and LOG target module.
12984 + Copyright (C) 2000,2001 astaro AG
12986 + This file is distributed under the terms of the GNU General Public
12987 + License (GPL). Copies of the GPL can be obtained from:
12988 + ftp://prep.ai.mit.edu/pub/gnu/GPL
12990 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
12991 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
12992 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
12993 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
12994 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
12997 +#include <linux/module.h>
12998 +#include <linux/skbuff.h>
12999 +#include <linux/ip.h>
13000 +#include <net/tcp.h>
13001 +#include <linux/spinlock.h>
13002 +#include <linux/netfilter_ipv4/ip_tables.h>
13003 +#include <linux/netfilter_ipv4/ipt_psd.h>
13006 +#define DEBUGP printk
13008 +#define DEBUGP(format, args...)
13011 +MODULE_LICENSE("GPL");
13012 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
13014 +#define HF_DADDR_CHANGING 0x01
13015 +#define HF_SPORT_CHANGING 0x02
13016 +#define HF_TOS_CHANGING 0x04
13017 +#define HF_TTL_CHANGING 0x08
13020 + * Information we keep per each target port
13023 + u_int16_t number; /* port number */
13024 + u_int8_t proto; /* protocol number */
13025 + u_int8_t and_flags; /* tcp ANDed flags */
13026 + u_int8_t or_flags; /* tcp ORed flags */
13030 + * Information we keep per each source address.
13033 + struct host *next; /* Next entry with the same hash */
13034 + clock_t timestamp; /* Last update time */
13035 + struct in_addr src_addr; /* Source address */
13036 + struct in_addr dest_addr; /* Destination address */
13037 + unsigned short src_port; /* Source port */
13038 + int count; /* Number of ports in the list */
13039 + int weight; /* Total weight of ports in the list */
13040 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
13041 + unsigned char tos; /* TOS */
13042 + unsigned char ttl; /* TTL */
13043 + unsigned char flags; /* HF_ flags bitmask */
13047 + * State information.
13051 + struct host list[LIST_SIZE]; /* List of source addresses */
13052 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
13053 + int index; /* Oldest entry to be replaced */
13057 + * Convert an IP address into a hash table index.
13059 +static inline int hashfunc(struct in_addr addr)
13061 + unsigned int value;
13064 + value = addr.s_addr;
13068 + } while ((value >>= HASH_LOG));
13070 + return hash & (HASH_SIZE - 1);
13074 +ipt_psd_match(const struct sk_buff *pskb,
13075 + const struct net_device *in,
13076 + const struct net_device *out,
13077 + const void *matchinfo,
13080 + u_int16_t datalen,
13083 + struct iphdr *ip_hdr;
13084 + struct tcphdr *tcp_hdr;
13085 + struct in_addr addr;
13086 + u_int16_t src_port,dest_port;
13087 + u_int8_t tcp_flags, proto;
13089 + struct host *curr, *last, **head;
13090 + int hash, index, count;
13092 + /* Parameters from userspace */
13093 + const struct ipt_psd_info *psdinfo = matchinfo;
13096 + ip_hdr = pskb->nh.iph;
13098 + /* Sanity check */
13099 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
13100 + DEBUGP("PSD: sanity check failed\n");
13104 + /* TCP or UDP ? */
13105 + proto = ip_hdr->protocol;
13107 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
13108 + DEBUGP("PSD: protocol not supported\n");
13112 + /* Get the source address, source & destination ports, and TCP flags */
13114 + addr.s_addr = ip_hdr->saddr;
13116 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
13118 + /* Yep, it´s dirty */
13119 + src_port = tcp_hdr->source;
13120 + dest_port = tcp_hdr->dest;
13122 + if (proto == IPPROTO_TCP) {
13123 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
13126 + tcp_flags = 0x00;
13129 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
13130 + * them spoof us. [DHCP needs this feature - HW] */
13131 + if (!addr.s_addr) {
13132 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
13136 + /* Use jiffies here not to depend on someone setting the time while we're
13137 + * running; we need to be careful with possible return value overflows. */
13140 + spin_lock(&state.lock);
13142 + /* Do we know this source address already? */
13145 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
13147 + if (curr->src_addr.s_addr == addr.s_addr) break;
13149 + if (curr->next) last = curr;
13150 + } while ((curr = curr->next));
13154 + /* We know this address, and the entry isn't too old. Update it. */
13155 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
13156 + time_after_eq(now, curr->timestamp)) {
13158 + /* Just update the appropriate list entry if we've seen this port already */
13159 + for (index = 0; index < curr->count; index++) {
13160 + if (curr->ports[index].number == dest_port) {
13161 + curr->ports[index].proto = proto;
13162 + curr->ports[index].and_flags &= tcp_flags;
13163 + curr->ports[index].or_flags |= tcp_flags;
13164 + goto out_no_match;
13168 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
13169 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
13170 + goto out_no_match;
13172 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
13173 + curr->timestamp = now;
13175 + /* Logged this scan already? Then drop the packet. */
13176 + if (curr->weight >= psdinfo->weight_threshold)
13179 + /* Specify if destination address, source port, TOS or TTL are not fixed */
13180 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
13181 + curr->flags |= HF_DADDR_CHANGING;
13182 + if (curr->src_port != src_port)
13183 + curr->flags |= HF_SPORT_CHANGING;
13184 + if (curr->tos != ip_hdr->tos)
13185 + curr->flags |= HF_TOS_CHANGING;
13186 + if (curr->ttl != ip_hdr->ttl)
13187 + curr->flags |= HF_TTL_CHANGING;
13189 + /* Update the total weight */
13190 + curr->weight += (ntohs(dest_port) < 1024) ?
13191 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
13193 + /* Got enough destination ports to decide that this is a scan? */
13194 + /* Then log it and drop the packet. */
13195 + if (curr->weight >= psdinfo->weight_threshold)
13198 + /* Remember the new port */
13199 + if (curr->count < SCAN_MAX_COUNT) {
13200 + curr->ports[curr->count].number = dest_port;
13201 + curr->ports[curr->count].proto = proto;
13202 + curr->ports[curr->count].and_flags = tcp_flags;
13203 + curr->ports[curr->count].or_flags = tcp_flags;
13207 + goto out_no_match;
13210 + /* We know this address, but the entry is outdated. Mark it unused, and
13211 + * remove from the hash table. We'll allocate a new entry instead since
13212 + * this one might get re-used too soon. */
13213 + curr->src_addr.s_addr = 0;
13215 + last->next = last->next->next;
13217 + *head = (*head)->next;
13221 + /* We don't need an ACK from a new source address */
13222 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
13223 + goto out_no_match;
13225 + /* Got too many source addresses with the same hash value? Then remove the
13226 + * oldest one from the hash table, so that they can't take too much of our
13227 + * CPU time even with carefully chosen spoofed IP addresses. */
13228 + if (count >= HASH_MAX && last) last->next = NULL;
13230 + /* We're going to re-use the oldest list entry, so remove it from the hash
13231 + * table first (if it is really already in use, and isn't removed from the
13232 + * hash table already because of the HASH_MAX check above). */
13234 + /* First, find it */
13235 + if (state.list[state.index].src_addr.s_addr)
13236 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
13240 + if ((curr = *head))
13242 + if (curr == &state.list[state.index]) break;
13244 + } while ((curr = curr->next));
13246 + /* Then, remove it */
13249 + last->next = last->next->next;
13251 + *head = (*head)->next;
13254 + /* Get our list entry */
13255 + curr = &state.list[state.index++];
13256 + if (state.index >= LIST_SIZE) state.index = 0;
13258 + /* Link it into the hash table */
13259 + head = &state.hash[hash];
13260 + curr->next = *head;
13263 + /* And fill in the fields */
13264 + curr->timestamp = now;
13265 + curr->src_addr = addr;
13266 + curr->dest_addr.s_addr = ip_hdr->daddr;
13267 + curr->src_port = src_port;
13269 + curr->weight = (ntohs(dest_port) < 1024) ?
13270 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
13271 + curr->ports[0].number = dest_port;
13272 + curr->ports[0].proto = proto;
13273 + curr->ports[0].and_flags = tcp_flags;
13274 + curr->ports[0].or_flags = tcp_flags;
13275 + curr->tos = ip_hdr->tos;
13276 + curr->ttl = ip_hdr->ttl;
13279 + spin_unlock(&state.lock);
13283 + spin_unlock(&state.lock);
13287 +static int ipt_psd_checkentry(const char *tablename,
13288 + const struct ipt_ip *e,
13290 + unsigned int matchsize,
13291 + unsigned int hook_mask)
13293 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
13295 + /* we accept TCP only */
13296 +/* if (e->ip.proto != IPPROTO_TCP) { */
13297 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
13301 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
13302 + DEBUGP("PSD: matchsize %u != %u\n",
13304 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
13311 +static struct ipt_match ipt_psd_reg = {
13315 + ipt_psd_checkentry,
13319 +static int __init init(void)
13321 + if (ipt_register_match(&ipt_psd_reg))
13324 + memset(&state, 0, sizeof(state));
13326 + spin_lock_init(&(state.lock));
13328 + printk("netfilter PSD loaded - (c) astaro AG\n");
13332 +static void __exit fini(void)
13334 + ipt_unregister_match(&ipt_psd_reg);
13335 + printk("netfilter PSD unloaded - (c) astaro AG\n");
13338 +module_init(init);
13339 +module_exit(fini);
13340 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_quota.c
13341 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
13342 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_quota.c 2004-04-30 09:10:45.000000000 +0200
13345 + * netfilter module to enforce network quotas
13347 + * Sam Johnston <samj@samj.net>
13349 +#include <linux/module.h>
13350 +#include <linux/skbuff.h>
13351 +#include <linux/spinlock.h>
13352 +#include <linux/interrupt.h>
13354 +#include <linux/netfilter_ipv4/ip_tables.h>
13355 +#include <linux/netfilter_ipv4/ipt_quota.h>
13357 +MODULE_LICENSE("GPL");
13358 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
13360 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
13363 +match(const struct sk_buff *skb,
13364 + const struct net_device *in,
13365 + const struct net_device *out,
13366 + const void *matchinfo,
13367 + int offset, int *hotdrop)
13369 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
13370 + unsigned int datalen;
13372 + if (skb->len < sizeof(struct iphdr))
13373 + return NF_ACCEPT;
13375 + datalen = skb->len - skb->nh.iph->ihl*4;
13377 + spin_lock_bh("a_lock);
13379 + if (q->quota >= datalen) {
13380 + /* we can afford this one */
13381 + q->quota -= datalen;
13382 + spin_unlock_bh("a_lock);
13384 +#ifdef DEBUG_IPT_QUOTA
13385 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
13390 + /* so we do not allow even small packets from now on */
13393 +#ifdef DEBUG_IPT_QUOTA
13394 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
13397 + spin_unlock_bh("a_lock);
13402 +checkentry(const char *tablename,
13403 + const struct ipt_ip *ip,
13404 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
13406 + /* TODO: spinlocks? sanity checks? */
13407 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
13413 +static struct ipt_match quota_match = {
13416 + .checkentry = checkentry,
13417 + .me = THIS_MODULE
13423 + return ipt_register_match("a_match);
13426 +static void __exit
13429 + ipt_unregister_match("a_match);
13432 +module_init(init);
13433 +module_exit(fini);
13435 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_random.c
13436 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
13437 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_random.c 2004-04-30 09:10:46.000000000 +0200
13440 + This is a module which is used for a "random" match support.
13441 + This file is distributed under the terms of the GNU General Public
13442 + License (GPL). Copies of the GPL can be obtained from:
13443 + ftp://prep.ai.mit.edu/pub/gnu/GPL
13445 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
13448 +#include <linux/module.h>
13449 +#include <linux/skbuff.h>
13450 +#include <linux/ip.h>
13451 +#include <linux/random.h>
13452 +#include <net/tcp.h>
13453 +#include <linux/spinlock.h>
13454 +#include <linux/netfilter_ipv4/ip_tables.h>
13455 +#include <linux/netfilter_ipv4/ipt_random.h>
13457 +MODULE_LICENSE("GPL");
13460 +ipt_rand_match(const struct sk_buff *pskb,
13461 + const struct net_device *in,
13462 + const struct net_device *out,
13463 + const void *matchinfo,
13466 + u_int16_t datalen,
13469 + /* Parameters from userspace */
13470 + const struct ipt_rand_info *info = matchinfo;
13471 + u_int8_t random_number;
13473 + /* get 1 random number from the kernel random number generation routine */
13474 + get_random_bytes((void *)(&random_number), 1);
13476 + /* Do we match ? */
13477 + if (random_number <= info->average)
13484 +ipt_rand_checkentry(const char *tablename,
13485 + const struct ipt_ip *e,
13487 + unsigned int matchsize,
13488 + unsigned int hook_mask)
13490 + /* Parameters from userspace */
13491 + const struct ipt_rand_info *info = matchinfo;
13493 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
13494 + printk("ipt_random: matchsize %u != %u\n", matchsize,
13495 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
13499 + /* must be 1 <= average % <= 99 */
13500 + /* 1 x 2.55 = 2 */
13501 + /* 99 x 2.55 = 252 */
13502 + if ((info->average < 2) || (info->average > 252)) {
13503 + printk("ipt_random: invalid average %u\n", info->average);
13510 +static struct ipt_match ipt_rand_reg = {
13514 + ipt_rand_checkentry,
13518 +static int __init init(void)
13520 + if (ipt_register_match(&ipt_rand_reg))
13523 + printk("ipt_random match loaded\n");
13527 +static void __exit fini(void)
13529 + ipt_unregister_match(&ipt_rand_reg);
13530 + printk("ipt_random match unloaded\n");
13533 +module_init(init);
13534 +module_exit(fini);
13535 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_realm.c
13536 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
13537 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_realm.c 2004-04-30 09:10:50.000000000 +0200
13539 +/* IP tables module for matching the routing realm
13543 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
13545 + * This program is free software; you can redistribute it and/or modify
13546 + * it under the terms of the GNU General Public License version 2 as
13547 + * published by the Free Software Foundation.
13550 +#include <linux/module.h>
13551 +#include <linux/skbuff.h>
13552 +#include <linux/netdevice.h>
13553 +#include <net/route.h>
13555 +#include <linux/netfilter_ipv4/ipt_realm.h>
13556 +#include <linux/netfilter_ipv4/ip_tables.h>
13558 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
13559 +MODULE_LICENSE("GPL");
13562 +match(const struct sk_buff *skb,
13563 + const struct net_device *in,
13564 + const struct net_device *out,
13565 + const void *matchinfo,
13569 + const struct ipt_realm_info *info = matchinfo;
13570 + struct dst_entry *dst = skb->dst;
13575 + return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
13578 +static int check(const char *tablename,
13579 + const struct ipt_ip *ip,
13581 + unsigned int matchsize,
13582 + unsigned int hook_mask)
13585 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
13586 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
13587 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
13588 + "LOCAL_IN or FORWARD.\n");
13592 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
13598 +static struct ipt_match realm_match = {
13601 + .checkentry = check,
13602 + .me = THIS_MODULE
13605 +static int __init init(void)
13607 + return ipt_register_match(&realm_match);
13610 +static void __exit fini(void)
13612 + ipt_unregister_match(&realm_match);
13615 +module_init(init);
13616 +module_exit(fini);
13617 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_sctp.c
13618 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
13619 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_sctp.c 2004-04-30 09:10:52.000000000 +0200
13621 +#include <linux/module.h>
13622 +#include <linux/skbuff.h>
13623 +#include <net/ip.h>
13624 +#include <linux/sctp.h>
13626 +#include <linux/netfilter_ipv4/ip_tables.h>
13627 +#include <linux/netfilter_ipv4/ipt_sctp.h>
13630 +#define duprintf(format, args...) printk(format , ## args)
13632 +#define duprintf(format, args...)
13635 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
13636 + || (!!((invflag) & (option)) ^ (cond)))
13639 +match_flags(const struct ipt_sctp_flag_info *flag_info,
13640 + const int flag_count,
13641 + u_int8_t chunktype,
13642 + u_int8_t chunkflags)
13646 + for (i = 0; i < flag_count; i++) {
13647 + if (flag_info[i].chunktype == chunktype) {
13648 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
13656 +match_packet(const struct sk_buff *skb,
13657 + const u_int32_t *chunkmap,
13658 + int chunk_match_type,
13659 + const struct ipt_sctp_flag_info *flag_info,
13660 + const int flag_count,
13664 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
13665 + sctp_chunkhdr_t sch;
13669 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
13670 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
13673 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
13675 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
13676 + duprintf("Dropping invalid SCTP packet.\n");
13681 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
13682 + ++i, offset, sch.type, htons(sch.length), sch.flags);
13684 + offset += (htons(sch.length) + 3) & ~3;
13686 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
13688 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
13689 + switch (chunk_match_type) {
13690 + case SCTP_CHUNK_MATCH_ANY:
13691 + if (match_flags(flag_info, flag_count,
13692 + sch.type, sch.flags)) {
13697 + case SCTP_CHUNK_MATCH_ALL:
13698 + if (match_flags(flag_info, flag_count,
13699 + sch.type, sch.flags)) {
13700 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
13704 + case SCTP_CHUNK_MATCH_ONLY:
13705 + if (!match_flags(flag_info, flag_count,
13706 + sch.type, sch.flags)) {
13712 + switch (chunk_match_type) {
13713 + case SCTP_CHUNK_MATCH_ONLY:
13717 + } while (offset < skb->len);
13719 + switch (chunk_match_type) {
13720 + case SCTP_CHUNK_MATCH_ALL:
13721 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
13722 + case SCTP_CHUNK_MATCH_ANY:
13724 + case SCTP_CHUNK_MATCH_ONLY:
13728 + /* This will never be reached, but required to stop compiler whine */
13733 +match(const struct sk_buff *skb,
13734 + const struct net_device *in,
13735 + const struct net_device *out,
13736 + const void *matchinfo,
13740 + const struct ipt_sctp_info *info;
13741 + sctp_sctphdr_t sh;
13743 + info = (const struct ipt_sctp_info *)matchinfo;
13746 + duprintf("Dropping non-first fragment.. FIXME\n");
13750 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
13751 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
13755 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
13757 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
13758 + && (ntohs(sh.source) <= info->spts[1])),
13759 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
13760 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
13761 + && (ntohs(sh.dest) <= info->dpts[1])),
13762 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
13763 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
13764 + info->flag_info, info->flag_count,
13766 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
13770 +checkentry(const char *tablename,
13771 + const struct ipt_ip *ip,
13773 + unsigned int matchsize,
13774 + unsigned int hook_mask)
13776 + const struct ipt_sctp_info *info;
13778 + info = (const struct ipt_sctp_info *)matchinfo;
13780 + return ip->proto == IPPROTO_SCTP
13781 + && !(ip->invflags & IPT_INV_PROTO)
13782 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
13783 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
13784 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
13785 + && !(info->invflags & ~info->flags)
13786 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
13787 + (info->chunk_match_type &
13788 + (SCTP_CHUNK_MATCH_ALL
13789 + | SCTP_CHUNK_MATCH_ANY
13790 + | SCTP_CHUNK_MATCH_ONLY)));
13793 +static struct ipt_match sctp_match =
13795 + .list = { NULL, NULL},
13798 + .checkentry = &checkentry,
13800 + .me = THIS_MODULE
13803 +static int __init init(void)
13805 + return ipt_register_match(&sctp_match);
13808 +static void __exit fini(void)
13810 + ipt_unregister_match(&sctp_match);
13813 +module_init(init);
13814 +module_exit(fini);
13816 +MODULE_LICENSE("GPL");
13817 +MODULE_AUTHOR("Kiran Kumar Immidi");
13818 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
13820 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c
13821 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
13822 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c 2004-04-30 09:14:35.000000000 +0200
13824 +/* Kernel module to match a string into a packet.
13826 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
13829 + * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
13830 + * Initial 2.6 port
13831 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
13832 + * Fixed SMP re-entrancy problem using per-cpu data areas
13833 + * for the skip/shift tables.
13834 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
13835 + * Fixed kernel panic, due to overrunning boyer moore string
13836 + * tables. Also slightly tweaked heuristic for deciding what
13837 + * search algo to use.
13838 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
13839 + * Implemented Boyer Moore Sublinear search algorithm
13840 + * alongside the existing linear search based on memcmp().
13841 + * Also a quick check to decide which method to use on a per
13845 +#include <linux/smp.h>
13846 +#include <linux/percpu.h>
13847 +#include <linux/module.h>
13848 +#include <linux/skbuff.h>
13849 +#include <linux/file.h>
13850 +#include <net/sock.h>
13852 +#include <linux/netfilter_ipv4/ip_tables.h>
13853 +#include <linux/netfilter_ipv4/ipt_string.h>
13855 +MODULE_LICENSE("GPL");
13857 +struct string_per_cpu {
13858 + int skip[BM_MAX_HLEN];
13859 + int shift[BM_MAX_HLEN];
13860 + int len[BM_MAX_HLEN];
13863 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
13866 +/* Boyer Moore Sublinear string search - VERY FAST */
13867 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
13869 + int M1, right_end, sk, sh;
13872 + int *skip, *shift, *len;
13874 + /* use data suitable for this CPU */
13875 + shift=__get_cpu_var(bm_string_data).shift;
13876 + skip=__get_cpu_var(bm_string_data).skip;
13877 + len=__get_cpu_var(bm_string_data).len;
13879 + /* Setup skip/shift tables */
13880 + M1 = right_end = needle_len-1;
13881 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
13882 + for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
13884 + for (i = 1; i < needle_len; i++) {
13885 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
13890 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
13891 + for (i = M1; i > 0; i--) shift[len[i]] = i;
13894 + for (i = 0; i < needle_len; i++) {
13895 + if (len[i] == M1 - i) ended = i;
13896 + if (ended) shift[i] = ended;
13899 + /* Do the search*/
13900 + while (right_end < haystack_len)
13902 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
13903 + if (i == needle_len) {
13904 + return haystack+(right_end - M1);
13907 + sk = skip[(int)haystack[right_end - i]];
13909 + right_end = max(right_end - i + sk, right_end + sh);
13915 +/* Linear string search based on memcmp() */
13916 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
13918 + char *k = haystack + (haystack_len-needle_len);
13919 + char *t = haystack;
13921 + while ( t <= k ) {
13922 + if (memcmp(t, needle, needle_len) == 0)
13931 +match(const struct sk_buff *skb,
13932 + const struct net_device *in,
13933 + const struct net_device *out,
13934 + const void *matchinfo,
13938 + const struct ipt_string_info *info = matchinfo;
13939 + struct iphdr *ip = skb->nh.iph;
13941 + char *needle, *haystack;
13942 + proc_ipt_search search=search_linear;
13944 + if ( !ip ) return 0;
13946 + /* get lenghts, and validate them */
13948 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
13949 + if ( nlen > hlen ) return 0;
13951 + needle=(char *)&info->string;
13952 + haystack=(char *)ip+(ip->ihl*4);
13954 + /* The sublinear search comes in to its own
13955 + * on the larger packets */
13956 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
13957 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
13958 + if ( hlen < BM_MAX_HLEN ) {
13959 + search=search_sublinear;
13961 + if (net_ratelimit())
13962 + printk(KERN_INFO "ipt_string: Packet too big "
13963 + "to attempt sublinear string search "
13964 + "(%d bytes)\n", hlen );
13968 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
13972 +checkentry(const char *tablename,
13973 + const struct ipt_ip *ip,
13975 + unsigned int matchsize,
13976 + unsigned int hook_mask)
13979 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
13985 +static struct ipt_match string_match = {
13986 + .name = "string",
13988 + .checkentry = &checkentry,
13989 + .me = THIS_MODULE
13993 +static int __init init(void)
13995 + return ipt_register_match(&string_match);
13998 +static void __exit fini(void)
14000 + ipt_unregister_match(&string_match);
14003 +module_init(init);
14004 +module_exit(fini);
14007 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_time.c
14008 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
14009 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_time.c 2004-04-30 09:10:54.000000000 +0200
14012 + This is a module which is used for time matching
14013 + It is using some modified code from dietlibc (localtime() function)
14014 + that you can find at http://www.fefe.de/dietlibc/
14015 + This file is distributed under the terms of the GNU General Public
14016 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
14017 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
14018 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
14019 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
14020 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
14021 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
14022 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
14025 +#include <linux/module.h>
14026 +#include <linux/skbuff.h>
14027 +#include <linux/netfilter_ipv4/ip_tables.h>
14028 +#include <linux/netfilter_ipv4/ipt_time.h>
14029 +#include <linux/time.h>
14031 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
14032 +MODULE_DESCRIPTION("Match arrival timestamp");
14033 +MODULE_LICENSE("GPL");
14037 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
14038 + int tm_min; /* Minutes. [0-59] */
14039 + int tm_hour; /* Hours. [0-23] */
14040 + int tm_mday; /* Day. [1-31] */
14041 + int tm_mon; /* Month. [0-11] */
14042 + int tm_year; /* Year - 1900. */
14043 + int tm_wday; /* Day of week. [0-6] */
14044 + int tm_yday; /* Days in year.[0-365] */
14045 + int tm_isdst; /* DST. [-1/0/1]*/
14047 + long int tm_gmtoff; /* we don't care, we count from GMT */
14048 + const char *tm_zone; /* we don't care, we count from GMT */
14052 +localtime(const time_t *timepr, struct tm *r);
14055 +match(const struct sk_buff *skb,
14056 + const struct net_device *in,
14057 + const struct net_device *out,
14058 + const void *matchinfo,
14061 + u_int16_t datalen,
14064 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
14065 + struct tm currenttime; /* time human readable */
14066 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
14067 + u_int16_t packet_time;
14068 + struct timeval kerneltimeval;
14069 + time_t packet_local_time;
14071 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
14072 + if (info->kerneltime)
14074 + do_gettimeofday(&kerneltimeval);
14075 + packet_local_time = kerneltimeval.tv_sec;
14078 + packet_local_time = skb->stamp.tv_sec;
14080 + /* Transform the timestamp of the packet, in a human readable form */
14081 + localtime(&packet_local_time, ¤ttime);
14083 + /* check if we match this timestamp, we start by the days... */
14084 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
14085 + return 0; /* the day doesn't match */
14087 + /* ... check the time now */
14088 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
14089 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
14092 + /* here we match ! */
14097 +checkentry(const char *tablename,
14098 + const struct ipt_ip *ip,
14100 + unsigned int matchsize,
14101 + unsigned int hook_mask)
14103 + struct ipt_time_info *info = matchinfo; /* match info for rule */
14105 + /* First, check that we are in the correct hook */
14106 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
14108 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
14110 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
14113 + /* we use the kerneltime if we are in forward or output */
14114 + info->kerneltime = 1;
14115 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
14116 + /* if not, we use the skb time */
14117 + info->kerneltime = 0;
14119 + /* Check the size */
14120 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
14122 + /* Now check the coherence of the data ... */
14123 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
14124 + (info->time_stop > 1439))
14126 + printk(KERN_WARNING "ipt_time: invalid argument\n");
14133 +static struct ipt_match time_match
14134 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
14136 +static int __init init(void)
14138 + printk("ipt_time loading\n");
14139 + return ipt_register_match(&time_match);
14142 +static void __exit fini(void)
14144 + ipt_unregister_match(&time_match);
14145 + printk("ipt_time unloaded\n");
14148 +module_init(init);
14149 +module_exit(fini);
14152 +/* The part below is borowed and modified from dietlibc */
14154 +/* seconds per day */
14155 +#define SPD 24*60*60
14158 +localtime(const time_t *timepr, struct tm *r) {
14161 + extern struct timezone sys_tz;
14162 + const unsigned int __spm[12] =
14168 + (31+28+31+30+31),
14169 + (31+28+31+30+31+30),
14170 + (31+28+31+30+31+30+31),
14171 + (31+28+31+30+31+30+31+31),
14172 + (31+28+31+30+31+30+31+31+30),
14173 + (31+28+31+30+31+30+31+31+30+31),
14174 + (31+28+31+30+31+30+31+31+30+31+30),
14176 + register time_t work;
14178 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
14179 + work=timep%(SPD);
14180 + r->tm_sec=work%60; work/=60;
14181 + r->tm_min=work%60; r->tm_hour=work/60;
14182 + work=timep/(SPD);
14183 + r->tm_wday=(4+work)%7;
14184 + for (i=1970; ; ++i) {
14185 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
14191 + r->tm_year=i-1900;
14192 + for (i=11; i && __spm[i]>work; --i) ;
14194 + r->tm_mday=work-__spm[i]+1;
14196 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_u32.c
14197 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
14198 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_u32.c 2004-04-30 09:10:55.000000000 +0200
14200 +/* Kernel module to match u32 packet content. */
14203 +U32 tests whether quantities of up to 4 bytes extracted from a packet
14204 +have specified values. The specification of what to extract is general
14205 +enough to find data at given offsets from tcp headers or payloads.
14208 + The argument amounts to a program in a small language described below.
14209 + tests := location = value | tests && location = value
14210 + value := range | value , range
14211 + range := number | number : number
14212 + a single number, n, is interpreted the same as n:n
14213 + n:m is interpreted as the range of numbers >=n and <=m
14214 + location := number | location operator number
14215 + operator := & | << | >> | @
14217 + The operators &, <<, >>, && mean the same as in c. The = is really a set
14218 + membership operator and the value syntax describes a set. The @ operator
14219 + is what allows moving to the next header and is described further below.
14221 + *** Until I can find out how to avoid it, there are some artificial limits
14222 + on the size of the tests:
14223 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
14224 + - no more than 10 ranges (and 9 commas) per value
14225 + - no more than 10 numbers (and 9 operators) per location
14227 + To describe the meaning of location, imagine the following machine that
14228 + interprets it. There are three registers:
14229 + A is of type char*, initially the address of the IP header
14230 + B and C are unsigned 32 bit integers, initially zero
14232 + The instructions are:
14233 + number B = number;
14234 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
14235 + &number C = C&number
14236 + <<number C = C<<number
14237 + >>number C = C>>number
14238 + @number A = A+C; then do the instruction number
14239 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
14240 + Otherwise the result of the computation is the final value of C.
14242 + Whitespace is allowed but not required in the tests.
14243 + However the characters that do occur there are likely to require
14244 + shell quoting, so it's a good idea to enclose the arguments in quotes.
14247 + match IP packets with total length >= 256
14248 + The IP header contains a total length field in bytes 2-3.
14249 + --u32 "0&0xFFFF=0x100:0xFFFF"
14251 + AND that with FFFF (giving bytes 2-3),
14252 + and test whether that's in the range [0x100:0xFFFF]
14254 +Example: (more realistic, hence more complicated)
14255 + match icmp packets with icmp type 0
14256 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
14257 + --u32 "6&0xFF=1 && ...
14258 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
14259 + Next test that it's not a fragment.
14260 + (If so it might be part of such a packet but we can't always tell.)
14261 + n.b. This test is generally needed if you want to match anything
14262 + beyond the IP header.
14263 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
14264 + packet (not a fragment). Alternatively, you can allow first fragments
14265 + by only testing the last 5 bits of byte 6.
14266 + ... 4&0x3FFF=0 && ...
14267 + Last test: the first byte past the IP header (the type) is 0
14268 + This is where we have to use the @syntax. The length of the IP header
14269 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
14270 + IP header itself.
14271 + ... 0>>22&0x3C@0>>24=0"
14272 + The first 0 means read bytes 0-3,
14273 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
14274 + the first byte, so only 22 bits is four times that plus a few more bits.
14275 + &3C then eliminates the two extra bits on the right and the first four
14276 + bits of the first byte.
14277 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
14278 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
14279 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
14280 + @ means to use this number as a new offset into the packet, and read
14281 + four bytes starting from there. This is the first 4 bytes of the icmp
14282 + payload, of which byte 0 is the icmp type. Therefore we simply shift
14283 + the value 24 to the right to throw out all but the first byte and compare
14284 + the result with 0.
14287 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
14288 + First we test that the packet is a tcp packet (similar to icmp).
14289 + --u32 "6&0xFF=6 && ...
14290 + Next, test that it's not a fragment (same as above).
14291 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
14292 + 0>>22&3C as above computes the number of bytes in the IP header.
14293 + @ makes this the new offset into the packet, which is the start of the
14294 + tcp header. The length of the tcp header (again in 32 bit words) is
14295 + the left half of byte 12 of the tcp header. The 12>>26&3C
14296 + computes this length in bytes (similar to the IP header before).
14297 + @ makes this the new offset, which is the start of the tcp payload.
14298 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
14299 + result is any of 1, 2, 5 or 8
14302 +#include <linux/module.h>
14303 +#include <linux/skbuff.h>
14305 +#include <linux/netfilter_ipv4/ipt_u32.h>
14306 +#include <linux/netfilter_ipv4/ip_tables.h>
14308 +/* #include <asm-i386/timex.h> for timing */
14310 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
14311 +MODULE_DESCRIPTION("IP tables u32 matching module");
14312 +MODULE_LICENSE("GPL");
14315 +match(const struct sk_buff *skb,
14316 + const struct net_device *in,
14317 + const struct net_device *out,
14318 + const void *matchinfo,
14321 + u_int16_t datalen,
14324 + const struct ipt_u32 *data = matchinfo;
14326 + unsigned char* origbase = (char*)skb->nh.iph;
14327 + unsigned char* base = origbase;
14328 + unsigned char* head = skb->head;
14329 + unsigned char* end = skb->end;
14330 + int nnums, nvals;
14331 + u_int32_t pos, val;
14332 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
14333 + cycles1 = get_cycles(); */
14335 + for (testind=0; testind < data->ntests; testind++) {
14336 + base = origbase; /* reset for each test */
14337 + pos = data->tests[testind].location[0].number;
14338 + if (base+pos+3 > end || base+pos < head)
14340 + val = (base[pos]<<24) + (base[pos+1]<<16) +
14341 + (base[pos+2]<<8) + base[pos+3];
14342 + nnums = data->tests[testind].nnums;
14343 + for (i=1; i < nnums; i++) {
14344 + u_int32_t number = data->tests[testind].location[i].number;
14345 + switch (data->tests[testind].location[i].nextop) {
14346 + case IPT_U32_AND:
14347 + val = val & number;
14349 + case IPT_U32_LEFTSH:
14350 + val = val << number;
14352 + case IPT_U32_RIGHTSH:
14353 + val = val >> number;
14356 + base = base + val;
14358 + if (base+pos+3 > end || base+pos < head)
14360 + val = (base[pos]<<24) + (base[pos+1]<<16) +
14361 + (base[pos+2]<<8) + base[pos+3];
14365 + nvals = data->tests[testind].nvalues;
14366 + for (i=0; i < nvals; i++) {
14367 + if ((data->tests[testind].value[i].min <= val) &&
14368 + (val <= data->tests[testind].value[i].max)) {
14372 + if (i >= data->tests[testind].nvalues) {
14373 + /* cycles2 = get_cycles();
14374 + printk("failed %d in %d cycles\n", testind,
14375 + cycles2-cycles1); */
14379 + /* cycles2 = get_cycles();
14380 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
14385 +checkentry(const char *tablename,
14386 + const struct ipt_ip *ip,
14388 + unsigned int matchsize,
14389 + unsigned int hook_mask)
14391 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
14396 +static struct ipt_match u32_match
14397 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
14399 +static int __init init(void)
14401 + return ipt_register_match(&u32_match);
14404 +static void __exit fini(void)
14406 + ipt_unregister_match(&u32_match);
14409 +module_init(init);
14410 +module_exit(fini);
14411 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c
14412 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
14413 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c 2004-04-30 09:14:28.000000000 +0200
14415 +/* Kernel module to match suspect packets. */
14416 +#include <linux/module.h>
14417 +#include <linux/skbuff.h>
14418 +#include <linux/ip.h>
14419 +#include <linux/udp.h>
14420 +#include <linux/tcp.h>
14421 +#include <linux/icmp.h>
14422 +#include <net/checksum.h>
14424 +#include <linux/netfilter_ipv4/ip_tables.h>
14426 +#define limpk(format, args...) \
14428 + if (net_ratelimit()) \
14429 + printk("ipt_unclean: %s" format, \
14430 + embedded ? "(embedded packet) " : "" , ## args); \
14433 +enum icmp_error_status
14435 + ICMP_MAY_BE_ERROR,
14442 + size_t min_len, max_len;
14443 + enum icmp_error_status err;
14444 + u_int8_t min_code, max_code;
14448 +check_ip(struct iphdr *iph, size_t length, int embedded);
14450 +/* ICMP-specific checks. */
14452 +check_icmp(const struct icmphdr *icmph,
14453 + u_int16_t datalen,
14454 + unsigned int offset,
14458 + static struct icmp_info info[]
14459 + = { [ICMP_ECHOREPLY]
14460 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14461 + [ICMP_DEST_UNREACH]
14462 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
14463 + [ICMP_SOURCE_QUENCH]
14464 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
14466 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
14468 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14469 + /* Router advertisement. */
14471 + = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
14472 + /* Router solicitation. */
14474 + = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
14475 + [ICMP_TIME_EXCEEDED]
14476 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
14477 + [ICMP_PARAMETERPROB]
14478 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
14480 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
14481 + [ICMP_TIMESTAMPREPLY]
14482 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
14483 + [ICMP_INFO_REQUEST]
14484 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14485 + [ICMP_INFO_REPLY]
14486 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14488 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
14489 + [ICMP_ADDRESSREPLY]
14490 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
14492 + /* Can't do anything if it's a fragment. */
14496 + /* Must cover type and code. */
14497 + if (datalen < 2) {
14498 + limpk("ICMP len=%u too short\n", datalen);
14502 + /* If not embedded. */
14504 + /* Bad checksum? Don't print, just ignore. */
14506 + && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
14509 + /* CHECK: Truncated ICMP (even if first fragment). */
14510 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14511 + && info[icmph->type].min_len != 0
14512 + && datalen < info[icmph->type].min_len) {
14513 + limpk("ICMP type %u len %u too short\n",
14514 + icmph->type, datalen);
14518 + /* CHECK: Check within known error ICMPs. */
14519 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14520 + && info[icmph->type].err == ICMP_IS_ERROR) {
14521 + /* CHECK: Embedded packet must be at least
14522 + length of iph + 8 bytes. */
14523 + struct iphdr *inner = (void *)icmph + 8;
14525 + /* datalen > 8 since all ICMP_IS_ERROR types
14526 + have min length > 8 */
14527 + if (datalen - 8 < sizeof(struct iphdr)) {
14528 + limpk("ICMP error internal way too short\n");
14531 + if (datalen - 8 < inner->ihl*4 + 8) {
14532 + limpk("ICMP error internal too short\n");
14535 + if (!check_ip(inner, datalen - 8, 1))
14539 + /* CHECK: Can't embed ICMP unless known non-error. */
14540 + if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
14541 + || info[icmph->type].err != ICMP_NOT_ERROR) {
14542 + limpk("ICMP type %u not embeddable\n",
14548 + /* CHECK: Invalid ICMP codes. */
14549 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14550 + && (icmph->code < info[icmph->type].min_code
14551 + || icmph->code > info[icmph->type].max_code)) {
14552 + limpk("ICMP type=%u code=%u\n",
14553 + icmph->type, icmph->code);
14557 + /* CHECK: Above maximum length. */
14558 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14559 + && info[icmph->type].max_len != 0
14560 + && datalen > info[icmph->type].max_len) {
14561 + limpk("ICMP type=%u too long: %u bytes\n",
14562 + icmph->type, datalen);
14566 + switch (icmph->type) {
14567 + case ICMP_PARAMETERPROB: {
14568 + /* CHECK: Problem param must be within error packet's
14570 + struct iphdr *iph = (void *)icmph + 8;
14571 + u_int32_t arg = ntohl(icmph->un.gateway);
14573 + if (icmph->code == 0) {
14574 + /* Code 0 means that upper 8 bits is pointer
14576 + if ((arg >> 24) >= iph->ihl*4) {
14577 + limpk("ICMP PARAMETERPROB ptr = %u\n",
14578 + ntohl(icmph->un.gateway) >> 24);
14581 + arg &= 0x00FFFFFF;
14584 + /* CHECK: Rest must be zero. */
14586 + limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
14593 + case ICMP_TIME_EXCEEDED:
14594 + case ICMP_SOURCE_QUENCH:
14595 + /* CHECK: Unused must be zero. */
14596 + if (icmph->un.gateway != 0) {
14597 + limpk("ICMP type=%u unused = %u\n",
14598 + icmph->type, ntohl(icmph->un.gateway));
14607 +/* UDP-specific checks. */
14609 +check_udp(const struct iphdr *iph,
14610 + const struct udphdr *udph,
14611 + u_int16_t datalen,
14612 + unsigned int offset,
14616 + /* Can't do anything if it's a fragment. */
14620 + /* CHECK: Must cover UDP header. */
14621 + if (datalen < sizeof(struct udphdr)) {
14622 + limpk("UDP len=%u too short\n", datalen);
14626 + /* Bad checksum? Don't print, just say it's unclean. */
14627 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
14628 + if (!more_frags && !embedded && udph->check
14629 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
14630 + csum_partial((char *)udph, datalen, 0)) != 0)
14633 + /* CHECK: Destination port can't be zero. */
14634 + if (!udph->dest) {
14635 + limpk("UDP zero destination port\n");
14639 + if (!more_frags) {
14641 + /* CHECK: UDP length must match. */
14642 + if (ntohs(udph->len) != datalen) {
14643 + limpk("UDP len too short %u vs %u\n",
14644 + ntohs(udph->len), datalen);
14648 + /* CHECK: UDP length be >= this truncated pkt. */
14649 + if (ntohs(udph->len) < datalen) {
14650 + limpk("UDP len too long %u vs %u\n",
14651 + ntohs(udph->len), datalen);
14656 + /* CHECK: UDP length must be > this frag's length. */
14657 + if (ntohs(udph->len) <= datalen) {
14658 + limpk("UDP fragment len too short %u vs %u\n",
14659 + ntohs(udph->len), datalen);
14667 +#define TH_FIN 0x01
14668 +#define TH_SYN 0x02
14669 +#define TH_RST 0x04
14670 +#define TH_PUSH 0x08
14671 +#define TH_ACK 0x10
14672 +#define TH_URG 0x20
14673 +#define TH_ECE 0x40
14674 +#define TH_CWR 0x80
14676 +/* table of valid flag combinations - ECE and CWR are always valid */
14677 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
14680 + [TH_SYN|TH_ACK] = 1,
14682 + [TH_RST|TH_ACK] = 1,
14683 + [TH_RST|TH_ACK|TH_PUSH] = 1,
14684 + [TH_FIN|TH_ACK] = 1,
14686 + [TH_ACK|TH_PUSH] = 1,
14687 + [TH_ACK|TH_URG] = 1,
14688 + [TH_ACK|TH_URG|TH_PUSH] = 1,
14689 + [TH_FIN|TH_ACK|TH_PUSH] = 1,
14690 + [TH_FIN|TH_ACK|TH_URG] = 1,
14691 + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
14694 +/* TCP-specific checks. */
14696 +check_tcp(const struct iphdr *iph,
14697 + const struct tcphdr *tcph,
14698 + u_int16_t datalen,
14699 + unsigned int offset,
14703 + u_int8_t *opt = (u_int8_t *)tcph;
14704 + u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
14705 + u_int8_t tcpflags;
14706 + int end_of_options = 0;
14709 + /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
14710 + /* In fact, this is caught below (offset < 516). */
14712 + /* Can't do anything if it's a fragment. */
14716 + /* CHECK: Smaller than minimal TCP hdr. */
14717 + if (datalen < sizeof(struct tcphdr)) {
14719 + limpk("Packet length %u < TCP header.\n", datalen);
14722 + /* Must have ports available (datalen >= 8), from
14723 + check_icmp which set embedded = 1 */
14724 + /* CHECK: TCP ports inside ICMP error */
14725 + if (!tcph->source || !tcph->dest) {
14726 + limpk("Zero TCP ports %u/%u.\n",
14727 + htons(tcph->source), htons(tcph->dest));
14733 + /* CHECK: Smaller than actual TCP hdr. */
14734 + if (datalen < tcph->doff * 4) {
14736 + limpk("Packet length %u < actual TCP header.\n",
14743 + /* Bad checksum? Don't print, just say it's unclean. */
14744 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
14745 + if (!more_frags && !embedded
14746 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
14747 + csum_partial((char *)tcph, datalen, 0)) != 0)
14750 + /* CHECK: TCP ports non-zero */
14751 + if (!tcph->source || !tcph->dest) {
14752 + limpk("Zero TCP ports %u/%u.\n",
14753 + htons(tcph->source), htons(tcph->dest));
14757 + /* CHECK: TCP reserved bits zero. */
14758 + if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
14759 + limpk("TCP reserved bits not zero\n");
14763 + /* CHECK: TCP flags. */
14764 + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
14765 + if (!tcp_valid_flags[tcpflags]) {
14766 + limpk("TCP flags bad: %u\n", tcpflags);
14770 + for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
14771 + switch (opt[i]) {
14773 + end_of_options = 1;
14780 + /* CHECK: options after EOO. */
14781 + if (end_of_options) {
14782 + limpk("TCP option %u after end\n",
14786 + /* CHECK: options at tail. */
14787 + else if (i+1 >= tcph->doff * 4) {
14788 + limpk("TCP option %u at tail\n",
14792 + /* CHECK: zero-length options. */
14793 + else if (opt[i+1] == 0) {
14794 + limpk("TCP option %u 0 len\n",
14798 + /* CHECK: oversize options. */
14799 + else if (&opt[i] + opt[i+1] > endhdr) {
14800 + limpk("TCP option %u at %Zu too long\n",
14801 + (unsigned int) opt[i], i);
14804 + /* Move to next option */
14812 +/* Returns 1 if ok */
14813 +/* Standard IP checks. */
14815 +check_ip(struct iphdr *iph, size_t length, int embedded)
14817 + u_int8_t *opt = (u_int8_t *)iph;
14818 + u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
14819 + int end_of_options = 0;
14823 + unsigned int offset;
14825 + /* Should only happen for local outgoing raw-socket packets. */
14826 + /* CHECK: length >= ip header. */
14827 + if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
14828 + limpk("Packet length %Zu < IP header.\n", length);
14832 + offset = ntohs(iph->frag_off) & IP_OFFSET;
14833 + protoh = (void *)iph + iph->ihl * 4;
14834 + datalen = length - iph->ihl * 4;
14836 + /* CHECK: Embedded fragment. */
14837 + if (embedded && offset) {
14838 + limpk("Embedded fragment.\n");
14842 + for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
14843 + switch (opt[i]) {
14845 + end_of_options = 1;
14852 + /* CHECK: options after EOO. */
14853 + if (end_of_options) {
14854 + limpk("IP option %u after end\n",
14858 + /* CHECK: options at tail. */
14859 + else if (i+1 >= iph->ihl * 4) {
14860 + limpk("IP option %u at tail\n",
14864 + /* CHECK: zero-length or one-length options. */
14865 + else if (opt[i+1] < 2) {
14866 + limpk("IP option %u %u len\n",
14867 + opt[i], opt[i+1]);
14870 + /* CHECK: oversize options. */
14871 + else if (&opt[i] + opt[i+1] > endhdr) {
14872 + limpk("IP option %u at %u too long\n",
14876 + /* Move to next option */
14881 + /* Fragment checks. */
14883 + /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
14884 + if ((ntohs(iph->frag_off) & IP_MF)
14885 + && (ntohs(iph->tot_len) % 8) != 0) {
14886 + limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
14890 + /* CHECK: Oversize fragment a-la Ping of Death. */
14891 + if (offset * 8 + datalen > 65535) {
14892 + limpk("Oversize fragment to %u.\n", offset * 8);
14896 + /* CHECK: DF set and offset or MF set. */
14897 + if ((ntohs(iph->frag_off) & IP_DF)
14898 + && (offset || (ntohs(iph->frag_off) & IP_MF))) {
14899 + limpk("DF set and offset=%u, MF=%u.\n",
14900 + offset, ntohs(iph->frag_off) & IP_MF);
14904 + /* CHECK: Zero-sized fragments. */
14905 + if ((offset || (ntohs(iph->frag_off) & IP_MF))
14906 + && datalen == 0) {
14907 + limpk("Zero size fragment offset=%u\n", offset);
14911 + /* Note: we can have even middle fragments smaller than this:
14912 + consider a large packet passing through a 600MTU then
14913 + 576MTU link: this gives a fragment of 24 data bytes. But
14914 + everyone packs fragments largest first, hence a fragment
14915 + can't START before 576 - MAX_IP_HEADER_LEN. */
14917 + /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
14918 + down to 128 (576 taken from RFC 791: All hosts must be
14919 + prepared to accept datagrams of up to 576 octets). Use 128
14921 +#define MIN_LIKELY_MTU 128
14922 + /* CHECK: Min size of first frag = 128. */
14923 + if ((ntohs(iph->frag_off) & IP_MF)
14925 + && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
14926 + limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
14931 + /* CHECK: Min offset of frag = 128 - IP hdr len. */
14932 + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
14933 + limpk("Fragment starts at %u < %u\n", offset * 8,
14934 + MIN_LIKELY_MTU - iph->ihl * 4);
14938 + /* CHECK: Protocol specification non-zero. */
14939 + if (iph->protocol == 0) {
14940 + limpk("Zero protocol\n");
14944 + /* CHECK: Do not use what is unused.
14945 + * First bit of fragmentation flags should be unused.
14946 + * May be used by OS fingerprinting tools.
14947 + * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
14949 + if (ntohs(iph->frag_off)>>15) {
14950 + limpk("IP unused bit set\n");
14954 + /* Per-protocol checks. */
14955 + switch (iph->protocol) {
14956 + case IPPROTO_ICMP:
14957 + return check_icmp(protoh, datalen, offset,
14958 + (ntohs(iph->frag_off) & IP_MF),
14961 + case IPPROTO_UDP:
14962 + return check_udp(iph, protoh, datalen, offset,
14963 + (ntohs(iph->frag_off) & IP_MF),
14966 + case IPPROTO_TCP:
14967 + return check_tcp(iph, protoh, datalen, offset,
14968 + (ntohs(iph->frag_off) & IP_MF),
14971 + /* Ignorance is bliss. */
14977 +match(const struct sk_buff *skb,
14978 + const struct net_device *in,
14979 + const struct net_device *out,
14980 + const void *matchinfo,
14983 + u_int16_t datalen,
14986 + return !check_ip(skb->nh.iph, skb->len, 0);
14989 +/* Called when user tries to insert an entry of this type. */
14991 +checkentry(const char *tablename,
14992 + const struct ipt_ip *ip,
14994 + unsigned int matchsize,
14995 + unsigned int hook_mask)
14997 + if (matchsize != IPT_ALIGN(0))
15003 +static struct ipt_match unclean_match
15004 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
15006 +static int __init init(void)
15008 + return ipt_register_match(&unclean_match);
15011 +static void __exit fini(void)
15013 + ipt_unregister_match(&unclean_match);
15016 +module_init(init);
15017 +module_exit(fini);
15018 +MODULE_LICENSE("GPL");
15019 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c
15020 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c 2004-04-28 03:35:43.000000000 +0200
15021 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c 2004-04-30 09:11:53.000000000 +0200
15024 sizeof(struct ipt_entry),
15025 sizeof(struct ipt_standard),
15026 - 0, { 0, 0 }, { } },
15027 + 0, NULL, 0, { 0, 0 }, { } },
15028 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15029 -NF_ACCEPT - 1 } },
15033 sizeof(struct ipt_entry),
15034 sizeof(struct ipt_standard),
15035 - 0, { 0, 0 }, { } },
15036 + 0, NULL, 0, { 0, 0 }, { } },
15037 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15038 -NF_ACCEPT - 1 } },
15042 sizeof(struct ipt_entry),
15043 sizeof(struct ipt_standard),
15044 - 0, { 0, 0 }, { } },
15045 + 0, NULL, 0, { 0, 0 }, { } },
15046 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15051 sizeof(struct ipt_entry),
15052 sizeof(struct ipt_error),
15053 - 0, { 0, 0 }, { } },
15054 + 0, NULL, 0, { 0, 0 }, { } },
15055 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15058 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c
15059 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c 2004-04-28 03:36:34.000000000 +0200
15060 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-04-30 09:11:53.000000000 +0200
15063 sizeof(struct ipt_entry),
15064 sizeof(struct ipt_standard),
15065 - 0, { 0, 0 }, { } },
15066 + 0, NULL, 0, { 0, 0 }, { } },
15067 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15068 -NF_ACCEPT - 1 } },
15072 sizeof(struct ipt_entry),
15073 sizeof(struct ipt_standard),
15074 - 0, { 0, 0 }, { } },
15075 + 0, NULL, 0, { 0, 0 }, { } },
15076 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15077 -NF_ACCEPT - 1 } },
15081 sizeof(struct ipt_entry),
15082 sizeof(struct ipt_standard),
15083 - 0, { 0, 0 }, { } },
15084 + 0, NULL, 0, { 0, 0 }, { } },
15085 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15086 -NF_ACCEPT - 1 } },
15090 sizeof(struct ipt_entry),
15091 sizeof(struct ipt_standard),
15092 - 0, { 0, 0 }, { } },
15093 + 0, NULL, 0, { 0, 0 }, { } },
15094 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15095 -NF_ACCEPT - 1 } },
15097 @@ -106,7 +106,7 @@
15099 sizeof(struct ipt_entry),
15100 sizeof(struct ipt_standard),
15101 - 0, { 0, 0 }, { } },
15102 + 0, NULL, 0, { 0, 0 }, { } },
15103 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15104 -NF_ACCEPT - 1 } },
15106 @@ -115,7 +115,7 @@
15108 sizeof(struct ipt_entry),
15109 sizeof(struct ipt_error),
15110 - 0, { 0, 0 }, { } },
15111 + 0, NULL, 0, { 0, 0 }, { } },
15112 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15115 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c
15116 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c 2004-04-28 03:36:36.000000000 +0200
15117 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c 2004-04-30 09:11:53.000000000 +0200
15120 sizeof(struct ipt_entry),
15121 sizeof(struct ipt_standard),
15122 - 0, { 0, 0 }, { } },
15123 + 0, NULL, 0, { 0, 0 }, { } },
15124 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15125 -NF_ACCEPT - 1 } },
15129 sizeof(struct ipt_entry),
15130 sizeof(struct ipt_standard),
15131 - 0, { 0, 0 }, { } },
15132 + 0, NULL, 0, { 0, 0 }, { } },
15133 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15138 sizeof(struct ipt_entry),
15139 sizeof(struct ipt_error),
15140 - 0, { 0, 0 }, { } },
15141 + 0, NULL, 0, { 0, 0 }, { } },
15142 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15145 diff -Nur linux-2.6.6-rc3.org/net/ipv4/raw.c linux-2.6.6-rc3/net/ipv4/raw.c
15146 --- linux-2.6.6-rc3.org/net/ipv4/raw.c 2004-04-28 03:35:49.000000000 +0200
15147 +++ linux-2.6.6-rc3/net/ipv4/raw.c 2004-04-30 09:12:42.000000000 +0200
15148 @@ -249,6 +249,7 @@
15150 return NET_RX_DROP;
15154 skb_push(skb, skb->data - skb->nh.raw);
15156 @@ -307,7 +308,7 @@
15159 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
15163 err = inet->recverr ? net_xmit_errno(err) : 0;
15165 diff -Nur linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c
15166 --- linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c 2004-04-28 03:35:40.000000000 +0200
15167 +++ linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c 2004-04-30 09:13:14.000000000 +0200
15168 @@ -1785,6 +1785,7 @@
15170 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
15171 goto discard_and_relse;
15174 if (sk_filter(sk, skb, 0))
15175 goto discard_and_relse;
15176 @@ -2670,6 +2671,7 @@
15177 EXPORT_SYMBOL(tcp_v4_connect);
15178 EXPORT_SYMBOL(tcp_v4_do_rcv);
15179 EXPORT_SYMBOL(tcp_v4_lookup_listener);
15180 +EXPORT_SYMBOL(tcp_v4_lookup);
15181 EXPORT_SYMBOL(tcp_v4_rebuild_header);
15182 EXPORT_SYMBOL(tcp_v4_remember_stamp);
15183 EXPORT_SYMBOL(tcp_v4_send_check);
15184 diff -Nur linux-2.6.6-rc3.org/net/ipv4/udp.c linux-2.6.6-rc3/net/ipv4/udp.c
15185 --- linux-2.6.6-rc3.org/net/ipv4/udp.c 2004-04-28 03:35:19.000000000 +0200
15186 +++ linux-2.6.6-rc3/net/ipv4/udp.c 2004-04-30 09:13:14.000000000 +0200
15187 @@ -1045,6 +1045,7 @@
15193 if (up->encap_type) {
15195 @@ -1210,6 +1211,7 @@
15197 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
15201 /* No socket. Drop packet silently, if checksum is wrong */
15202 if (udp_checksum_complete(skb))
15203 @@ -1558,6 +1560,7 @@
15204 EXPORT_SYMBOL(udp_port_rover);
15205 EXPORT_SYMBOL(udp_prot);
15206 EXPORT_SYMBOL(udp_sendmsg);
15207 +EXPORT_SYMBOL(udp_v4_lookup);
15209 #ifdef CONFIG_PROC_FS
15210 EXPORT_SYMBOL(udp_proc_register);
15211 diff -Nur linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c
15212 --- linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-04-28 03:35:08.000000000 +0200
15213 +++ linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c 2004-04-30 09:12:40.000000000 +0200
15215 err = -EHOSTUNREACH;
15218 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
15219 return NET_XMIT_BYPASS;
15222 @@ -170,6 +171,7 @@
15223 .handler = ipip_rcv,
15224 .err_handler = ipip_err,
15229 static int __init ipip_init(void)
15230 diff -Nur linux-2.6.6-rc3.org/net/ipv6/ip6_tunnel.c linux-2.6.6-rc3/net/ipv6/ip6_tunnel.c
15231 --- linux-2.6.6-rc3.org/net/ipv6/ip6_tunnel.c 2004-04-28 03:35:06.000000000 +0200
15232 +++ linux-2.6.6-rc3/net/ipv6/ip6_tunnel.c 2004-04-30 09:09:38.000000000 +0200
15233 @@ -715,13 +715,7 @@
15234 ipv6h->nexthdr = proto;
15235 ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
15236 ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
15237 -#ifdef CONFIG_NETFILTER
15238 - nf_conntrack_put(skb->nfct);
15239 - skb->nfct = NULL;
15240 -#ifdef CONFIG_NETFILTER_DEBUG
15241 - skb->nf_debug = 0;
15245 pkt_len = skb->len;
15246 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
15247 skb->dst->dev, dst_output);
15248 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
15249 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig 2004-04-28 03:36:33.000000000 +0200
15250 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig 2004-04-30 09:15:25.000000000 +0200
15251 @@ -230,5 +230,53 @@
15252 <file:Documentation/modules.txt>. If unsure, say `N'.
15255 +config IP6_NF_TARGET_HL
15256 + tristate 'HL target support'
15257 + depends on IP6_NF_MANGLE
15260 +config IP6_NF_TARGET_REJECT
15261 + tristate 'REJECT target support'
15262 + depends on IP6_NF_FILTER
15265 +config IP6_NF_MATCH_FUZZY
15266 + tristate 'Fuzzy match support'
15267 + depends on IP6_NF_FILTER
15270 +config IP6_NF_MATCH_NTH
15271 + tristate 'Nth match support'
15272 + depends on IP6_NF_IPTABLES
15275 +config IP6_NF_MATCH_RANDOM
15276 + tristate 'Random match support'
15277 + depends on IP6_NF_IPTABLES
15280 +config IP6_NF_TARGET_TRACE
15281 + tristate 'TRACE target support'
15282 + depends on IP6_NF_RAW
15284 + The TRACE target allows packets to be traced as those
15285 + matches any subsequent rule in any table/rule. The matched
15286 + rule and the packet is logged with the prefix
15288 + TRACE: tablename/chainname/rulenum
15290 + If you want to compile it as a module, say M here and read
15291 + <file:Documentation/modules.txt>. If unsure, say `N'.
15294 +config IP6_NF_MATCH_POLICY
15295 + tristate "IPsec policy match support"
15296 + depends on IP6_NF_IPTABLES && XFRM
15298 + Policy matching allows you to match packets based on the
15299 + IPsec policy that was used during decapsulation/will
15300 + be used during encapsulation.
15302 + To compile it as a module, choose M here. If unsure, say N.
15305 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
15306 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile 2004-04-28 03:36:01.000000000 +0200
15307 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-30 09:13:22.000000000 +0200
15309 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
15310 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
15311 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
15312 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
15313 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
15314 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
15315 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
15317 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
15318 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
15319 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
15320 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
15321 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
15322 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
15324 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
15326 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
15327 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
15328 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
15329 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
15330 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
15331 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
15332 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c
15333 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-04-28 03:36:34.000000000 +0200
15334 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c 2004-04-30 09:11:53.000000000 +0200
15336 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
15337 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
15339 +static const char *hook6names[] = {
15340 + [NF_IP6_PRE_ROUTING] "PREROUTING",
15341 + [NF_IP6_LOCAL_IN] "INPUT",
15342 + [NF_IP6_FORWARD] "FORWARD",
15343 + [NF_IP6_LOCAL_OUT] "OUTPUT",
15344 + [NF_IP6_POST_ROUTING] "POSTROUTING",
15347 /*#define DEBUG_IP_FIREWALL*/
15348 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
15349 /*#define DEBUG_IP_FIREWALL_USER*/
15350 @@ -408,6 +416,12 @@
15352 t = ip6t_get_target(e);
15353 IP_NF_ASSERT(t->u.kernel.target);
15355 + /* The packet traced and the rule isn't an unconditional return/END. */
15356 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
15357 + nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
15358 + table->name, e->chainname, e->rulenum);
15360 /* Standard target? */
15361 if (!t->u.kernel.target->target) {
15363 @@ -561,6 +575,29 @@
15364 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
15368 +find_error_target(struct ip6t_entry *s,
15369 + struct ip6t_entry *e,
15370 + char **chainname)
15372 + struct ip6t_entry_target *t;
15373 + static struct ip6t_entry *found = NULL;
15378 + t = ip6t_get_target(found);
15379 + if (strcmp(t->u.user.name,
15380 + IP6T_ERROR_TARGET) == 0) {
15381 + *chainname = t->data;
15390 /* All zeroes == unconditional rule. */
15392 unconditional(const struct ip6t_ip6 *ipv6)
15393 @@ -580,6 +617,8 @@
15394 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
15397 + char *chainname = NULL;
15398 + u_int32_t rulenum;
15400 /* No recursion; use packet counter to save back ptrs (reset
15401 to 0 as we leave), and comefrom to save source hook bitmask */
15402 @@ -593,6 +632,8 @@
15404 /* Set initial back pointer. */
15405 e->counters.pcnt = pos;
15407 + chainname = (char *) hook6names[hook];
15410 struct ip6t_standard_target *t
15411 @@ -605,6 +646,8 @@
15414 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
15415 + e->rulenum = rulenum++;
15416 + e->chainname = chainname;
15418 /* Unconditional return/END. */
15419 if (e->target_offset == sizeof(struct ip6t_entry)
15420 @@ -614,6 +657,10 @@
15421 && unconditional(&e->ipv6)) {
15422 unsigned int oldpos, size;
15424 + /* Set unconditional rulenum to zero. */
15426 + e->counters.bcnt = 0;
15428 /* Return: backtrack through the last
15431 @@ -639,6 +686,11 @@
15432 (newinfo->entries + pos);
15433 } while (oldpos == pos + e->next_offset);
15435 + /* Restore chainname, rulenum. */
15436 + chainname = e->chainname;
15437 + rulenum = e->counters.bcnt;
15438 + e->counters.bcnt = 0;
15440 /* Move along one */
15441 size = e->next_offset;
15442 e = (struct ip6t_entry *)
15443 @@ -654,6 +706,17 @@
15444 /* This a jump; chase it. */
15445 duprintf("Jump rule %u -> %u\n",
15447 + e->counters.bcnt = rulenum++;
15449 + e = (struct ip6t_entry *)
15450 + (newinfo->entries + newpos);
15451 + if (IP6T_ENTRY_ITERATE(newinfo->entries,
15453 + find_error_target,
15454 + e, &chainname) == 0) {
15455 + printk("ip6_tables: table screwed up!\n");
15459 /* ... this is a fallthru */
15460 newpos = pos + e->next_offset;
15461 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_HL.c
15462 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
15463 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_HL.c 2004-04-30 09:10:04.000000000 +0200
15466 + * Hop Limit modification target for ip6tables
15467 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
15468 + * Based on HW's TTL module
15470 + * This software is distributed under the terms of GNU GPL
15473 +#include <linux/module.h>
15474 +#include <linux/skbuff.h>
15475 +#include <linux/ip.h>
15477 +#include <linux/netfilter_ipv6/ip6_tables.h>
15478 +#include <linux/netfilter_ipv6/ip6t_HL.h>
15480 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
15481 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
15482 +MODULE_LICENSE("GPL");
15484 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
15485 + const struct net_device *in, const struct net_device *out,
15486 + const void *targinfo, void *userinfo)
15488 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
15489 + const struct ip6t_HL_info *info = targinfo;
15490 + u_int16_t diffs[2];
15493 + switch (info->mode) {
15494 + case IP6T_HL_SET:
15495 + new_hl = info->hop_limit;
15497 + case IP6T_HL_INC:
15498 + new_hl = ip6h->hop_limit + info->hop_limit;
15499 + if (new_hl > 255)
15502 + case IP6T_HL_DEC:
15503 + new_hl = ip6h->hop_limit + info->hop_limit;
15508 + new_hl = ip6h->hop_limit;
15512 + if (new_hl != ip6h->hop_limit) {
15513 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
15514 + ip6h->hop_limit = new_hl;
15515 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
15518 + return IP6T_CONTINUE;
15521 +static int ip6t_hl_checkentry(const char *tablename,
15522 + const struct ip6t_entry *e,
15524 + unsigned int targinfosize,
15525 + unsigned int hook_mask)
15527 + struct ip6t_HL_info *info = targinfo;
15529 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
15530 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
15532 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
15536 + if (strcmp(tablename, "mangle")) {
15537 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15541 + if (info->mode > IP6T_HL_MAXMODE) {
15542 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
15547 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
15548 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
15555 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
15556 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
15558 +static int __init init(void)
15560 + return ip6t_register_target(&ip6t_HL);
15563 +static void __exit fini(void)
15565 + ip6t_unregister_target(&ip6t_HL);
15568 +module_init(init);
15569 +module_exit(fini);
15570 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_REJECT.c
15571 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
15572 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_REJECT.c 2004-04-30 09:10:13.000000000 +0200
15575 + * IP6 tables REJECT target module
15576 + * Linux INET6 implementation
15578 + * Copyright (C)2003 USAGI/WIDE Project
15581 + * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
15583 + * Based on net/ipv4/netfilter/ipt_REJECT.c
15585 + * This program is free software; you can redistribute it and/or
15586 + * modify it under the terms of the GNU General Public License
15587 + * as published by the Free Software Foundation; either version
15588 + * 2 of the License, or (at your option) any later version.
15591 +#include <linux/config.h>
15592 +#include <linux/module.h>
15593 +#include <linux/skbuff.h>
15594 +#include <linux/icmpv6.h>
15595 +#include <net/ipv6.h>
15596 +#include <net/tcp.h>
15597 +#include <net/icmp.h>
15598 +#include <net/ip6_fib.h>
15599 +#include <net/ip6_route.h>
15600 +#include <net/flow.h>
15601 +#include <linux/netfilter_ipv6/ip6_tables.h>
15602 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
15604 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
15605 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
15606 +MODULE_LICENSE("GPL");
15609 +#define DEBUGP printk
15611 +#define DEBUGP(format, args...)
15615 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
15617 + void (*attach)(struct sk_buff *, struct nf_ct_info *);
15618 + if (nfct && (attach = ip6_ct_attach) != NULL) {
15620 + attach(new_skb, nfct);
15625 +static int maybe_reroute(struct sk_buff *skb)
15627 + if (skb->nfcache & NFC_ALTERED){
15628 + if (ip6_route_me_harder(skb) != 0){
15634 + return dst_output(skb);
15637 +/* Send RST reply */
15638 +static void send_reset(struct sk_buff *oldskb)
15640 + struct sk_buff *nskb;
15641 + struct tcphdr otcph, *tcph;
15642 + unsigned int otcplen, tcphoff, hh_len;
15644 + struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
15645 + struct dst_entry *dst = NULL;
15648 + proto = oip6h->nexthdr;
15651 + if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
15652 + (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
15653 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
15657 + tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
15658 + &proto, oldskb->len - ((u8*)(oip6h+1)
15659 + - oldskb->data));
15661 + if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
15662 + DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
15666 + otcplen = oldskb->len - tcphoff;
15668 + /* IP header checks: fragment, too short. */
15669 + if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
15670 + DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
15675 + if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
15676 + if (net_ratelimit())
15677 + printk("ip6t_REJECT: Can't copy tcp header\n");
15681 + /* No RST for RST. */
15683 + DEBUGP("ip6t_REJECT: RST is set\n");
15687 + /* Check checksum. */
15688 + if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
15689 + skb_checksum(oldskb, tcphoff, otcplen, 0))) {
15690 + DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
15694 + memset(&fl, 0, sizeof(fl));
15695 + fl.proto = IPPROTO_TCP;
15696 + ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
15697 + ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
15698 + fl.fl_ip_sport = otcph.dest;
15699 + fl.fl_ip_dport = otcph.source;
15700 + err = ip6_dst_lookup(NULL, &dst, &fl);
15702 + if (net_ratelimit())
15703 + printk("ip6t_REJECT: can't find dst. err = %d\n", err);
15707 + hh_len = (dst->dev->hard_header_len + 15)&~15;
15708 + nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
15709 + + sizeof(struct tcphdr) + dst->trailer_len,
15713 + if (net_ratelimit())
15714 + printk("ip6t_REJECT: Can't alloc skb\n");
15715 + dst_release(dst);
15722 + skb_reserve(nskb, hh_len + dst->header_len);
15724 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
15725 + skb_put(nskb, sizeof(struct ipv6hdr));
15726 + ip6h->version = 6;
15727 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
15728 + ip6h->nexthdr = IPPROTO_TCP;
15729 + ip6h->payload_len = htons(sizeof(struct tcphdr));
15730 + ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
15731 + ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
15733 + tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
15734 + /* Truncate to length (no data) */
15735 + tcph->doff = sizeof(struct tcphdr)/4;
15736 + tcph->source = otcph.dest;
15737 + tcph->dest = otcph.source;
15741 + tcph->seq = otcph.ack_seq;
15742 + tcph->ack_seq = 0;
15745 + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
15746 + + otcplen - (otcph.doff<<2));
15750 + /* Reset flags */
15751 + ((u_int8_t *)tcph)[13] = 0;
15753 + tcph->ack = needs_ack;
15754 + tcph->window = 0;
15755 + tcph->urg_ptr = 0;
15758 + /* Adjust TCP checksum */
15759 + tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
15760 + &nskb->nh.ipv6h->daddr,
15761 + sizeof(struct tcphdr), IPPROTO_TCP,
15762 + csum_partial((char *)tcph,
15763 + sizeof(struct tcphdr), 0));
15766 + connection_attach(nskb, oldskb->nfct);
15769 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
15772 + dst_release(dst);
15775 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
15777 + struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
15778 + struct icmp6hdr *icmp6h;
15779 + struct dst_entry *dst = NULL;
15780 + struct rt6_info *rt;
15783 + unsigned int len, datalen, hh_len;
15784 + int saddr_type, daddr_type;
15785 + unsigned int ptr, ip6off;
15788 + struct sk_buff *nskb;
15791 + saddr_type = ipv6_addr_type(&hdr->saddr);
15792 + daddr_type = ipv6_addr_type(&hdr->daddr);
15794 + if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
15795 + (!(daddr_type & IPV6_ADDR_UNICAST))) {
15796 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
15800 + ip6off = skb_in->nh.raw - skb_in->data;
15801 + proto = hdr->nexthdr;
15802 + ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
15803 + skb_in->len - ip6off);
15805 + if ((ptr < 0) || (ptr > skb_in->len)) {
15806 + ptr = ip6off + sizeof(struct ipv6hdr);
15807 + proto = hdr->nexthdr;
15808 + } else if (proto == IPPROTO_ICMPV6) {
15811 + if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
15812 + icmp6_type), &type, 1)) {
15813 + DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
15817 + if (!(type & ICMPV6_INFOMSG_MASK)) {
15818 + DEBUGP("ip6t_REJECT: no reply to icmp error\n");
15821 + } else if (proto == IPPROTO_UDP) {
15822 + int plen = skb_in->len - (ptr - ip6off);
15825 + if (plen < sizeof(struct udphdr)) {
15826 + DEBUGP("ip6t_REJECT: too short\n");
15830 + if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
15832 + if (net_ratelimit())
15833 + printk("ip6t_REJECT: can't get copy from skb");
15838 + csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
15840 + skb_checksum(skb_in, ptr, plen, 0))) {
15841 + DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
15846 + memset(&fl, 0, sizeof(fl));
15847 + fl.proto = IPPROTO_ICMPV6;
15848 + ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
15849 + ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
15850 + fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
15851 + fl.fl_icmp_code = code;
15853 + if (ip6_dst_lookup(NULL, &dst, &fl)) {
15857 + rt = (struct rt6_info *)dst;
15860 + if (rt->rt6i_dst.plen < 128)
15861 + tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
15863 + if (!xrlim_allow(dst, tmo)) {
15864 + if (net_ratelimit())
15865 + printk("ip6t_REJECT: rate limitted\n");
15866 + goto dst_release_out;
15869 + len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
15871 + if (len > dst_pmtu(dst))
15872 + len = dst_pmtu(dst);
15873 + if (len > IPV6_MIN_MTU)
15874 + len = IPV6_MIN_MTU;
15876 + datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
15877 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
15879 + nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
15883 + if (net_ratelimit())
15884 + printk("ip6t_REJECT: can't alloc skb\n");
15885 + goto dst_release_out;
15888 + nskb->priority = 0;
15892 + skb_reserve(nskb, hh_len + dst->header_len);
15894 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
15895 + skb_put(nskb, sizeof(struct ipv6hdr));
15896 + ip6h->version = 6;
15897 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
15898 + ip6h->nexthdr = IPPROTO_ICMPV6;
15899 + ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
15900 + ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
15901 + ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
15903 + icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
15904 + icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
15905 + icmp6h->icmp6_code = code;
15906 + icmp6h->icmp6_cksum = 0;
15908 + data = skb_put(nskb, datalen);
15910 + csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
15911 + csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
15912 + icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
15913 + datalen + sizeof(struct icmp6hdr),
15914 + IPPROTO_ICMPV6, csum);
15917 + connection_attach(nskb, skb_in->nfct);
15919 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
15923 + dst_release(dst);
15926 +static unsigned int reject6_target(struct sk_buff **pskb,
15927 + unsigned int hooknum,
15928 + const struct net_device *in,
15929 + const struct net_device *out,
15930 + const void *targinfo,
15933 + const struct ip6t_reject_info *reject = targinfo;
15935 + DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
15936 + /* WARNING: This code causes reentry within ip6tables.
15937 + This means that the ip6tables jump stack is now crap. We
15938 + must return an absolute verdict. --RR */
15939 + switch (reject->with) {
15940 + case IP6T_ICMP6_NO_ROUTE:
15941 + send_unreach(*pskb, ICMPV6_NOROUTE);
15943 + case IP6T_ICMP6_ADM_PROHIBITED:
15944 + send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
15946 + case IP6T_ICMP6_NOT_NEIGHBOUR:
15947 + send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
15949 + case IP6T_ICMP6_ADDR_UNREACH:
15950 + send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
15952 + case IP6T_ICMP6_PORT_UNREACH:
15953 + send_unreach(*pskb, ICMPV6_PORT_UNREACH);
15955 + case IP6T_ICMP6_ECHOREPLY:
15958 + case IP6T_TCP_RESET:
15959 + send_reset(*pskb);
15962 + if (net_ratelimit())
15963 + printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
15970 +static int check(const char *tablename,
15971 + const struct ip6t_entry *e,
15973 + unsigned int targinfosize,
15974 + unsigned int hook_mask)
15976 + const struct ip6t_reject_info *rejinfo = targinfo;
15978 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
15979 + DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
15983 + /* Only allow these for packet filtering. */
15984 + if (strcmp(tablename, "filter") != 0) {
15985 + DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
15989 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
15990 + | (1 << NF_IP6_FORWARD)
15991 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
15992 + DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
15996 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
15997 + printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
15999 + } else if (rejinfo->with == IP6T_TCP_RESET) {
16000 + /* Must specify that it's a TCP packet */
16001 + if (e->ipv6.proto != IPPROTO_TCP
16002 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
16003 + DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
16011 +static struct ip6t_target ip6t_reject_reg = {
16012 + .name = "REJECT",
16013 + .target = reject6_target,
16014 + .checkentry = check,
16015 + .me = THIS_MODULE
16018 +static int __init init(void)
16020 + if (ip6t_register_target(&ip6t_reject_reg))
16025 +static void __exit fini(void)
16027 + ip6t_unregister_target(&ip6t_reject_reg);
16030 +module_init(init);
16031 +module_exit(fini);
16032 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c
16033 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
16034 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c 2004-04-30 09:11:53.000000000 +0200
16036 +/* This is a module which is used for setting
16037 + * the NFC_TRACE flag in the nfcache field of an skb.
16039 +#include <linux/module.h>
16040 +#include <linux/skbuff.h>
16042 +#include <linux/netfilter_ipv6/ip6_tables.h>
16044 +MODULE_LICENSE("GPL");
16046 +static unsigned int
16047 +target(struct sk_buff **pskb,
16048 + unsigned int hooknum,
16049 + const struct net_device *in,
16050 + const struct net_device *out,
16051 + const void *targinfo,
16054 + (*pskb)->nfcache |= NFC_TRACE;
16055 + return IP6T_CONTINUE;
16059 +checkentry(const char *tablename,
16060 + const struct ip6t_entry *e,
16062 + unsigned int targinfosize,
16063 + unsigned int hook_mask)
16065 + if (targinfosize != 0) {
16066 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
16071 + if (strcmp(tablename, "raw") != 0) {
16072 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
16079 +static struct ip6t_target ip6t_trace_reg = {
16081 + .target = target,
16082 + .checkentry = checkentry,
16083 + .me = THIS_MODULE
16086 +static int __init init(void)
16088 + if (ip6t_register_target(&ip6t_trace_reg))
16094 +static void __exit fini(void)
16096 + ip6t_unregister_target(&ip6t_trace_reg);
16099 +module_init(init);
16100 +module_exit(fini);
16101 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_fuzzy.c
16102 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
16103 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_fuzzy.c 2004-04-30 09:10:22.000000000 +0200
16106 + * This module implements a simple TSK FLC
16107 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
16108 + * to limit , in an adaptive and flexible way , the packet rate crossing
16109 + * a given stream . It serves as an initial and very simple (but effective)
16110 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
16111 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
16112 + * into our code in a precise , adaptive and efficient manner.
16113 + * The goal is very similar to that of "limit" match , but using techniques of
16114 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
16115 + * avoiding over and undershoots - and stuff like that .
16118 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
16119 + * 2002-08-17 : Changed to eliminate floating point operations .
16120 + * 2002-08-23 : Coding style changes .
16121 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
16124 +#include <linux/module.h>
16125 +#include <linux/skbuff.h>
16126 +#include <linux/ipv6.h>
16127 +#include <linux/random.h>
16128 +#include <net/tcp.h>
16129 +#include <linux/spinlock.h>
16130 +#include <linux/netfilter_ipv6/ip6_tables.h>
16131 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
16134 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
16135 + Expressed in percentage
16138 +#define PAR_LOW 1/100
16139 +#define PAR_HIGH 1
16141 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
16143 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
16144 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
16145 +MODULE_LICENSE("GPL");
16147 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
16149 + if (tx >= maxi) return 100;
16151 + if (tx <= mini) return 0;
16153 + return ((100 * (tx-mini)) / (maxi-mini));
16156 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
16158 + if (tx <= mini) return 100;
16160 + if (tx >= maxi) return 0;
16162 + return ((100 * (maxi - tx)) / (maxi - mini));
16167 +ip6t_fuzzy_match(const struct sk_buff *pskb,
16168 + const struct net_device *in,
16169 + const struct net_device *out,
16170 + const void *matchinfo,
16173 + u_int16_t datalen,
16176 + /* From userspace */
16178 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
16180 + u_int8_t random_number;
16181 + unsigned long amount;
16182 + u_int8_t howhigh, howlow;
16185 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
16187 + info->bytes_total += pskb->len;
16188 + info->packets_total++;
16190 + info->present_time = jiffies;
16192 + if (info->present_time >= info->previous_time)
16193 + amount = info->present_time - info->previous_time;
16195 + /* There was a transition : I choose to re-sample
16196 + and keep the old acceptance rate...
16200 + info->previous_time = info->present_time;
16201 + info->bytes_total = info->packets_total = 0;
16204 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
16206 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
16209 + info->previous_time = info->present_time;
16210 + info->bytes_total = info->packets_total = 0;
16212 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
16213 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
16215 + info->acceptance_rate = (u_int8_t) \
16216 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
16218 + /* In fact, the above defuzzification would require a denominator
16219 + * proportional to (howhigh+howlow) but, in this particular case,
16220 + * that expression is constant.
16221 + * An imediate consequence is that it is not necessary to call
16222 + * both mf_high and mf_low - but to keep things understandable,
16228 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
16231 + if (info->acceptance_rate < 100)
16233 + get_random_bytes((void *)(&random_number), 1);
16235 + /* If within the acceptance , it can pass => don't match */
16236 + if (random_number <= (255 * info->acceptance_rate) / 100)
16239 + return 1; /* It can't pass (It matches) */
16242 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
16247 +ip6t_fuzzy_checkentry(const char *tablename,
16248 + const struct ip6t_ip6 *ip,
16250 + unsigned int matchsize,
16251 + unsigned int hook_mask)
16254 + const struct ip6t_fuzzy_info *info = matchinfo;
16256 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
16257 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
16258 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
16262 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
16263 + || (info->minimum_rate >= info->maximum_rate)) {
16264 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
16271 +static struct ip6t_match ip6t_fuzzy_reg = {
16274 + ip6t_fuzzy_match,
16275 + ip6t_fuzzy_checkentry,
16279 +static int __init init(void)
16281 + if (ip6t_register_match(&ip6t_fuzzy_reg))
16287 +static void __exit fini(void)
16289 + ip6t_unregister_match(&ip6t_fuzzy_reg);
16292 +module_init(init);
16293 +module_exit(fini);
16294 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_nth.c
16295 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
16296 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_nth.c 2004-04-30 09:10:36.000000000 +0200
16299 + This is a module which is used for match support for every Nth packet
16300 + This file is distributed under the terms of the GNU General Public
16301 + License (GPL). Copies of the GPL can be obtained from:
16302 + ftp://prep.ai.mit.edu/pub/gnu/GPL
16304 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
16305 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
16306 + * added support for multiple counters
16307 + * added support for matching on individual packets
16308 + in the counter cycle
16309 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
16313 +#include <linux/module.h>
16314 +#include <linux/skbuff.h>
16315 +#include <linux/ip.h>
16316 +#include <net/tcp.h>
16317 +#include <linux/spinlock.h>
16318 +#include <linux/netfilter_ipv6/ip6_tables.h>
16319 +#include <linux/netfilter_ipv6/ip6t_nth.h>
16321 +MODULE_LICENSE("GPL");
16324 + * State information.
16328 + u_int16_t number;
16331 +static struct state states[IP6T_NTH_NUM_COUNTERS];
16334 +ip6t_nth_match(const struct sk_buff *pskb,
16335 + const struct net_device *in,
16336 + const struct net_device *out,
16337 + const void *matchinfo,
16340 + u_int16_t datalen,
16343 + /* Parameters from userspace */
16344 + const struct ip6t_nth_info *info = matchinfo;
16345 + unsigned counter = info->counter;
16346 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
16348 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
16352 + spin_lock(&states[counter].lock);
16354 + /* Are we matching every nth packet?*/
16355 + if (info->packet == 0xFF)
16357 + /* We're matching every nth packet and only every nth packet*/
16358 + /* Do we match or invert match? */
16359 + if (info->not == 0)
16361 + if (states[counter].number == 0)
16363 + ++states[counter].number;
16366 + if (states[counter].number >= info->every)
16367 + states[counter].number = 0; /* reset the counter */
16369 + ++states[counter].number;
16374 + if (states[counter].number == 0)
16376 + ++states[counter].number;
16379 + if (states[counter].number >= info->every)
16380 + states[counter].number = 0;
16382 + ++states[counter].number;
16388 + /* We're using the --packet, so there must be a rule for every value */
16389 + if (states[counter].number == info->packet)
16391 + /* only increment the counter when a match happens */
16392 + if (states[counter].number >= info->every)
16393 + states[counter].number = 0; /* reset the counter */
16395 + ++states[counter].number;
16403 + /* don't match */
16404 + spin_unlock(&states[counter].lock);
16408 + spin_unlock(&states[counter].lock);
16413 +ip6t_nth_checkentry(const char *tablename,
16414 + const struct ip6t_ip6 *e,
16416 + unsigned int matchsize,
16417 + unsigned int hook_mask)
16419 + /* Parameters from userspace */
16420 + const struct ip6t_nth_info *info = matchinfo;
16421 + unsigned counter = info->counter;
16422 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
16424 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
16428 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
16429 + printk("nth: matchsize %u != %u\n", matchsize,
16430 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
16434 + states[counter].number = info->startat;
16439 +static struct ip6t_match ip6t_nth_reg = {
16443 + ip6t_nth_checkentry,
16447 +static int __init init(void)
16449 + unsigned counter;
16450 + memset(&states, 0, sizeof(states));
16451 + if (ip6t_register_match(&ip6t_nth_reg))
16454 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
16456 + spin_lock_init(&(states[counter].lock));
16459 + printk("ip6t_nth match loaded\n");
16463 +static void __exit fini(void)
16465 + ip6t_unregister_match(&ip6t_nth_reg);
16466 + printk("ip6t_nth match unloaded\n");
16469 +module_init(init);
16470 +module_exit(fini);
16471 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c
16472 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-28 03:36:30.000000000 +0200
16473 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c 2004-04-30 09:13:19.000000000 +0200
16475 MODULE_LICENSE("GPL");
16478 +match_comm(const struct sk_buff *skb, const char *comm)
16480 + struct task_struct *p, *g;
16481 + struct files_struct *files;
16484 + read_lock(&tasklist_lock);
16485 + do_each_thread(g, p) {
16486 + if(strncmp(p->comm, comm, sizeof(p->comm)))
16490 + files = p->files;
16492 + read_lock(&files->file_lock);
16493 + for (i=0; i < files->max_fds; i++) {
16494 + if (fcheck_files(files, i) ==
16495 + skb->sk->sk_socket->file) {
16496 + read_unlock(&files->file_lock);
16498 + read_unlock(&tasklist_lock);
16502 + read_unlock(&files->file_lock);
16505 + } while_each_thread(g, p);
16506 + read_unlock(&tasklist_lock);
16511 match_pid(const struct sk_buff *skb, pid_t pid)
16513 struct task_struct *p;
16514 @@ -125,6 +158,12 @@
16518 + if(info->match & IP6T_OWNER_COMM) {
16519 + if (!match_comm(skb, info->comm) ^
16520 + !!(info->invert & IP6T_OWNER_COMM))
16527 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c
16528 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
16529 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c 2004-04-30 09:13:22.000000000 +0200
16531 +/* IP tables module for matching IPsec policy
\r
16533 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
\r
16535 + * This program is free software; you can redistribute it and/or modify
\r
16536 + * it under the terms of the GNU General Public License version 2 as
\r
16537 + * published by the Free Software Foundation.
\r
16540 +#include <linux/kernel.h>
\r
16541 +#include <linux/config.h>
\r
16542 +#include <linux/module.h>
\r
16543 +#include <linux/skbuff.h>
\r
16544 +#include <linux/init.h>
\r
16545 +#include <net/xfrm.h>
\r
16547 +#include <linux/netfilter_ipv6.h>
\r
16548 +#include <linux/netfilter_ipv6/ip6t_policy.h>
\r
16549 +#include <linux/netfilter_ipv6/ip6_tables.h>
\r
16551 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
\r
16552 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
\r
16553 +MODULE_LICENSE("GPL");
\r
16556 +static inline int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,
\r
16557 + struct in6_addr addr2)
\r
16561 + for (i = 0; i < 16; i++) {
\r
16562 + if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
\r
16563 + (addr2.s6_addr[i] & mask.s6_addr[i]))
\r
16570 +static inline int
\r
16571 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
\r
16573 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
\r
16575 + struct in6_addr xfrm_saddr, xfrm_daddr;
\r
16577 + if ((e->match.saddr
\r
16578 + && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
\r
16579 + ^ e->invert.saddr ) ||
\r
16580 + (e->match.daddr
\r
16581 + && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
\r
16582 + ^ e->invert.daddr ) ||
\r
16583 + MISMATCH(proto, x->id.proto) ||
\r
16584 + MISMATCH(mode, x->props.mode) ||
\r
16585 + MISMATCH(spi, x->id.spi) ||
\r
16586 + MISMATCH(reqid, x->props.reqid))
\r
16592 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
\r
16594 + const struct ip6t_policy_elem *e;
\r
16595 + struct sec_path *sp = skb->sp;
\r
16596 + int strict = info->flags & POLICY_MATCH_STRICT;
\r
16599 + if (sp == NULL)
\r
16601 + if (strict && info->len != sp->len)
\r
16604 + for (i = sp->len - 1; i >= 0; i--) {
\r
16605 + pos = strict ? i - sp->len + 1 : 0;
\r
16606 + if (pos >= info->len)
\r
16608 + e = &info->pol[pos];
\r
16610 + if (match_xfrm_state(sp->x[i].xvec, e)) {
\r
16613 + } else if (strict)
\r
16617 + return strict ? 1 : 0;
\r
16621 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
\r
16623 + const struct ip6t_policy_elem *e;
\r
16624 + struct dst_entry *dst = skb->dst;
\r
16625 + int strict = info->flags & POLICY_MATCH_STRICT;
\r
16628 + if (dst->xfrm == NULL)
\r
16631 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
\r
16632 + pos = strict ? i : 0;
\r
16633 + if (pos >= info->len)
\r
16635 + e = &info->pol[pos];
\r
16637 + if (match_xfrm_state(dst->xfrm, e)) {
\r
16640 + } else if (strict)
\r
16644 + return strict ? 1 : 0;
\r
16647 +static int match(const struct sk_buff *skb,
\r
16648 + const struct net_device *in,
\r
16649 + const struct net_device *out,
\r
16650 + const void *matchinfo,
\r
16652 + const void *hdr,
\r
16653 + u_int16_t datalen,
\r
16656 + const struct ip6t_policy_info *info = matchinfo;
\r
16659 + if (info->flags & POLICY_MATCH_IN)
\r
16660 + ret = match_policy_in(skb, info);
\r
16662 + ret = match_policy_out(skb, info);
\r
16665 + if (info->flags & POLICY_MATCH_NONE)
\r
16669 + } else if (info->flags & POLICY_MATCH_NONE)
\r
16675 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
\r
16676 + void *matchinfo, unsigned int matchsize,
\r
16677 + unsigned int hook_mask)
\r
16679 + struct ip6t_policy_info *info = matchinfo;
\r
16681 + if (matchsize != IP6T_ALIGN(sizeof(*info))) {
\r
16682 + printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
\r
16683 + matchsize, IP6T_ALIGN(sizeof(*info)));
\r
16686 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
\r
16687 + printk(KERN_ERR "ip6t_policy: neither incoming nor "
\r
16688 + "outgoing policy selected\n");
\r
16691 + if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
\r
16692 + && info->flags & POLICY_MATCH_OUT) {
\r
16693 + printk(KERN_ERR "ip6t_policy: output policy not valid in "
\r
16694 + "PRE_ROUTING and INPUT\n");
\r
16697 + if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
\r
16698 + && info->flags & POLICY_MATCH_IN) {
\r
16699 + printk(KERN_ERR "ip6t_policy: input policy not valid in "
\r
16700 + "POST_ROUTING and OUTPUT\n");
\r
16703 + if (info->len > POLICY_MAX_ELEM) {
\r
16704 + printk(KERN_ERR "ip6t_policy: too many policy elements\n");
\r
16711 +static struct ip6t_match policy_match =
\r
16713 + .name = "policy",
\r
16714 + .match = match,
\r
16715 + .checkentry = checkentry,
\r
16716 + .me = THIS_MODULE,
\r
16719 +static int __init init(void)
\r
16721 + return ip6t_register_match(&policy_match);
\r
16724 +static void __exit fini(void)
\r
16726 + ip6t_unregister_match(&policy_match);
\r
16729 +module_init(init);
\r
16730 +module_exit(fini);
\r
16731 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_random.c
16732 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
16733 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_random.c 2004-04-30 09:10:46.000000000 +0200
16736 + This is a module which is used for a "random" match support.
16737 + This file is distributed under the terms of the GNU General Public
16738 + License (GPL). Copies of the GPL can be obtained from:
16739 + ftp://prep.ai.mit.edu/pub/gnu/GPL
16741 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
16742 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
16745 +#include <linux/module.h>
16746 +#include <linux/skbuff.h>
16747 +#include <linux/ip.h>
16748 +#include <linux/random.h>
16749 +#include <net/tcp.h>
16750 +#include <linux/spinlock.h>
16751 +#include <linux/netfilter_ipv6/ip6_tables.h>
16752 +#include <linux/netfilter_ipv6/ip6t_random.h>
16754 +MODULE_LICENSE("GPL");
16757 +ip6t_rand_match(const struct sk_buff *pskb,
16758 + const struct net_device *in,
16759 + const struct net_device *out,
16760 + const void *matchinfo,
16763 + u_int16_t datalen,
16766 + /* Parameters from userspace */
16767 + const struct ip6t_rand_info *info = matchinfo;
16768 + u_int8_t random_number;
16770 + /* get 1 random number from the kernel random number generation routine */
16771 + get_random_bytes((void *)(&random_number), 1);
16773 + /* Do we match ? */
16774 + if (random_number <= info->average)
16781 +ip6t_rand_checkentry(const char *tablename,
16782 + const struct ip6t_ip6 *e,
16784 + unsigned int matchsize,
16785 + unsigned int hook_mask)
16787 + /* Parameters from userspace */
16788 + const struct ip6t_rand_info *info = matchinfo;
16790 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
16791 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
16792 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
16796 + /* must be 1 <= average % <= 99 */
16797 + /* 1 x 2.55 = 2 */
16798 + /* 99 x 2.55 = 252 */
16799 + if ((info->average < 2) || (info->average > 252)) {
16800 + printk("ip6t_random: invalid average %u\n", info->average);
16807 +static struct ip6t_match ip6t_rand_reg = {
16811 + ip6t_rand_checkentry,
16815 +static int __init init(void)
16817 + if (ip6t_register_match(&ip6t_rand_reg))
16820 + printk("ip6t_random match loaded\n");
16824 +static void __exit fini(void)
16826 + ip6t_unregister_match(&ip6t_rand_reg);
16827 + printk("ip6t_random match unloaded\n");
16830 +module_init(init);
16831 +module_exit(fini);
16832 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c
16833 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c 2004-04-28 03:35:07.000000000 +0200
16834 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c 2004-04-30 09:11:53.000000000 +0200
16837 sizeof(struct ip6t_entry),
16838 sizeof(struct ip6t_standard),
16839 - 0, { 0, 0 }, { } },
16840 + 0, NULL, 0, { 0, 0 }, { } },
16841 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16842 -NF_ACCEPT - 1 } },
16846 sizeof(struct ip6t_entry),
16847 sizeof(struct ip6t_standard),
16848 - 0, { 0, 0 }, { } },
16849 + 0, NULL, 0, { 0, 0 }, { } },
16850 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16851 -NF_ACCEPT - 1 } },
16855 sizeof(struct ip6t_entry),
16856 sizeof(struct ip6t_standard),
16857 - 0, { 0, 0 }, { } },
16858 + 0, NULL, 0, { 0, 0 }, { } },
16859 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16864 sizeof(struct ip6t_entry),
16865 sizeof(struct ip6t_error),
16866 - 0, { 0, 0 }, { } },
16867 + 0, NULL, 0, { 0, 0 }, { } },
16868 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
16871 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c
16872 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c 2004-04-28 03:35:43.000000000 +0200
16873 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c 2004-04-30 09:11:53.000000000 +0200
16876 sizeof(struct ip6t_entry),
16877 sizeof(struct ip6t_standard),
16878 - 0, { 0, 0 }, { } },
16879 + 0, NULL, 0, { 0, 0 }, { } },
16880 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16881 -NF_ACCEPT - 1 } },
16885 sizeof(struct ip6t_entry),
16886 sizeof(struct ip6t_standard),
16887 - 0, { 0, 0 }, { } },
16888 + 0, NULL, 0, { 0, 0 }, { } },
16889 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16890 -NF_ACCEPT - 1 } },
16894 sizeof(struct ip6t_entry),
16895 sizeof(struct ip6t_standard),
16896 - 0, { 0, 0 }, { } },
16897 + 0, NULL, 0, { 0, 0 }, { } },
16898 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16899 -NF_ACCEPT - 1 } },
16903 sizeof(struct ip6t_entry),
16904 sizeof(struct ip6t_standard),
16905 - 0, { 0, 0 }, { } },
16906 + 0, NULL, 0, { 0, 0 }, { } },
16907 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16908 -NF_ACCEPT - 1 } },
16910 @@ -105,7 +105,7 @@
16912 sizeof(struct ip6t_entry),
16913 sizeof(struct ip6t_standard),
16914 - 0, { 0, 0 }, { } },
16915 + 0, NULL, 0, { 0, 0 }, { } },
16916 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16919 @@ -114,7 +114,7 @@
16921 sizeof(struct ip6t_entry),
16922 sizeof(struct ip6t_error),
16923 - 0, { 0, 0 }, { } },
16924 + 0, NULL, 0, { 0, 0 }, { } },
16925 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
16928 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c
16929 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c 2004-04-28 03:36:19.000000000 +0200
16930 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c 2004-04-30 09:11:53.000000000 +0200
16933 sizeof(struct ip6t_entry),
16934 sizeof(struct ip6t_standard),
16935 - 0, { 0, 0 }, { } },
16936 + 0, NULL, 0, { 0, 0 }, { } },
16937 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16938 -NF_ACCEPT - 1 } },
16942 sizeof(struct ip6t_entry),
16943 sizeof(struct ip6t_standard),
16944 - 0, { 0, 0 }, { } },
16945 + 0, NULL, 0, { 0, 0 }, { } },
16946 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16947 -NF_ACCEPT - 1 } },
16951 sizeof(struct ip6t_entry),
16952 sizeof(struct ip6t_error),
16953 - 0, { 0, 0 }, { } },
16954 + 0, NULL, 0, { 0, 0 }, { } },
16955 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
16958 diff -Nur linux-2.6.6-rc3.org/net/ipv6/sit.c linux-2.6.6-rc3/net/ipv6/sit.c
16959 --- linux-2.6.6-rc3.org/net/ipv6/sit.c 2004-04-28 03:36:36.000000000 +0200
16960 +++ linux-2.6.6-rc3/net/ipv6/sit.c 2004-04-30 09:09:38.000000000 +0200
16961 @@ -388,13 +388,7 @@
16962 skb->dev = tunnel->dev;
16963 dst_release(skb->dst);
16965 -#ifdef CONFIG_NETFILTER
16966 - nf_conntrack_put(skb->nfct);
16967 - skb->nfct = NULL;
16968 -#ifdef CONFIG_NETFILTER_DEBUG
16969 - skb->nf_debug = 0;
16973 ipip6_ecn_decapsulate(iph, skb);
16975 read_unlock(&ipip6_lock);
16976 @@ -580,13 +574,7 @@
16977 if ((iph->ttl = tiph->ttl) == 0)
16978 iph->ttl = iph6->hop_limit;
16980 -#ifdef CONFIG_NETFILTER
16981 - nf_conntrack_put(skb->nfct);
16982 - skb->nfct = NULL;
16983 -#ifdef CONFIG_NETFILTER_DEBUG
16984 - skb->nf_debug = 0;
16990 tunnel->recursion--;
16991 diff -Nur linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c linux-2.6.6-rc3/net/xfrm/xfrm_input.c
16992 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c 2004-04-28 03:35:05.000000000 +0200
16993 +++ linux-2.6.6-rc3/net/xfrm/xfrm_input.c 2004-04-30 09:12:40.000000000 +0200
16998 +#ifdef CONFIG_NETFILTER
16999 + sp->decap_done = 0;
17004 diff -Nur linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc3/net/xfrm/xfrm_policy.c
17005 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c 2004-04-28 03:35:48.000000000 +0200
17006 +++ linux-2.6.6-rc3/net/xfrm/xfrm_policy.c 2004-04-30 09:12:42.000000000 +0200
17008 #include <linux/workqueue.h>
17009 #include <linux/notifier.h>
17010 #include <linux/netdevice.h>
17011 +#include <linux/netfilter.h>
17012 #include <net/xfrm.h>
17013 #include <net/ip.h>
17015 @@ -908,6 +909,7 @@
17017 if (_decode_session(skb, &fl, family) < 0)
17019 + nf_nat_decode_session(skb, &fl, family);
17021 /* First, check used SA against their selectors. */