1 Netfilter SNAP 20040518
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)
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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter.h linux-2.6.6/include/linux/netfilter.h
56 --- linux-2.6.6.org/include/linux/netfilter.h 2004-05-10 04:32:37.000000000 +0200
57 +++ linux-2.6.6/include/linux/netfilter.h 2004-05-18 12:39:23.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_helpers.h linux-2.6.6/include/linux/netfilter_helpers.h
120 --- linux-2.6.6.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
121 +++ linux-2.6.6/include/linux/netfilter_helpers.h 2004-05-18 12:40:21.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack.h
257 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-05-10 04:33:20.000000000 +0200
258 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack.h 2004-05-18 12:40:50.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_h323.h
320 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
321 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-05-18 12:39:18.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_mms.h
355 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
356 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-05-18 12:39:36.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
390 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
391 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-05-18 12:40:06.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
415 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
416 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-05-18 12:40:16.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
454 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
455 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-05-18 12:40:21.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
526 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
527 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-05-18 12:40:23.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_talk.h
555 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
556 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-05-18 12:40:50.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
711 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-05-10 04:32:54.000000000 +0200
712 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-05-18 12:40:23.000000000 +0200
722 /* The manipulable part of the tuple. */
733 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.6/include/linux/netfilter_ipv4/ip_pool.h
734 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
735 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_pool.h 2004-05-18 12:36:48.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6/include/linux/netfilter_ipv4/ip_tables.h
802 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_tables.h 2004-05-10 04:32:37.000000000 +0200
803 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_tables.h 2004-05-18 12:39:16.000000000 +0200
806 /* Values for "flag" field in struct ipt_ip (general ip structure). */
807 #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
808 -#define IPT_F_MASK 0x01 /* All possible flag bits mask. */
809 +#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
810 +#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
812 /* Values for "inv" field in struct ipt_ip. */
813 #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
816 unsigned int comefrom;
818 + /* Name of the chain */
821 + /* Rule number in the chain. */
824 /* Packet and byte counters. */
825 struct ipt_counters counters;
827 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_CONNMARK.h
828 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
829 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-05-18 12:38:02.000000000 +0200
831 +#ifndef _IPT_CONNMARK_H_target
832 +#define _IPT_CONNMARK_H_target
834 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
835 + * by Henrik Nordstrom <hno@marasystems.com>
837 + * This program is free software; you can redistribute it and/or modify
838 + * it under the terms of the GNU General Public License as published by
839 + * the Free Software Foundation; either version 2 of the License, or
840 + * (at your option) any later version.
844 + IPT_CONNMARK_SET = 0,
846 + IPT_CONNMARK_RESTORE
849 +struct ipt_connmark_target_info {
850 + unsigned long mark;
851 + unsigned long mask;
855 +#endif /*_IPT_CONNMARK_H_target*/
856 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_IPMARK.h
857 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
858 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-05-18 12:38:15.000000000 +0200
860 +#ifndef _IPT_IPMARK_H_target
861 +#define _IPT_IPMARK_H_target
863 +struct ipt_ipmark_target_info {
864 + unsigned long andmask;
865 + unsigned long ormask;
869 +#define IPT_IPMARK_SRC 0
870 +#define IPT_IPMARK_DST 1
872 +#endif /*_IPT_IPMARK_H_target*/
873 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_MARK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_MARK.h
874 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_MARK.h 2004-05-10 04:32:26.000000000 +0200
875 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_MARK.h 2004-05-18 12:38:18.000000000 +0200
877 #ifndef _IPT_MARK_H_target
878 #define _IPT_MARK_H_target
886 struct ipt_mark_target_info {
891 #endif /*_IPT_MARK_H_target*/
892 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_NETLINK.h
893 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
894 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-05-18 12:36:02.000000000 +0200
896 +#ifndef _IPT_FWMON_H
897 +#define _IPT_FWMON_H
899 +/* Bitmask macros */
900 +#define MASK(x,y) (x & y)
901 +#define MASK_SET(x,y) x |= y
902 +#define MASK_UNSET(x,y) x &= ~y
904 +#define USE_MARK 0x00000001
905 +#define USE_DROP 0x00000002
906 +#define USE_SIZE 0x00000004
910 + unsigned int flags;
919 + char iface[IFNAMSIZ];
922 +#endif /*_IPT_FWMON_H*/
923 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_ROUTE.h
924 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
925 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_ROUTE.h 2004-05-18 12:38:20.000000000 +0200
927 +/* Header file for iptables ipt_ROUTE target
929 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
931 + * This software is distributed under GNU GPL v2, 1991
933 +#ifndef _IPT_ROUTE_H_target
934 +#define _IPT_ROUTE_H_target
936 +#define IPT_ROUTE_IFNAMSIZ 16
938 +struct ipt_route_target_info {
939 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
940 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
941 + u_int32_t gw; /* IP address of gateway */
945 +/* Values for "flags" field */
946 +#define IPT_ROUTE_CONTINUE 0x01
948 +#endif /*_IPT_ROUTE_H_target*/
949 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_TCPLAG.h
950 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h 1970-01-01 01:00:00.000000000 +0100
951 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_TCPLAG.h 2004-05-18 12:38:29.000000000 +0200
953 +#ifndef _IPT_TCPLAG_H
954 +#define _IPT_TCPLAG_H
958 + unsigned char level;
959 + unsigned char prefix[ 15 ];
963 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_TTL.h
964 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
965 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_TTL.h 2004-05-18 12:36:09.000000000 +0200
967 +/* TTL modification module for IP tables
968 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
979 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
981 +struct ipt_TTL_info {
988 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_XOR.h
989 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
990 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_XOR.h 2004-05-18 12:38:34.000000000 +0200
995 +struct ipt_XOR_info {
997 + u_int8_t block_size;
1000 +#endif /* _IPT_XOR_H */
1001 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_addrtype.h
1002 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
1003 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-05-18 12:38:44.000000000 +0200
1005 +#ifndef _IPT_ADDRTYPE_H
1006 +#define _IPT_ADDRTYPE_H
1008 +struct ipt_addrtype_info {
1009 + u_int16_t source; /* source-type mask */
1010 + u_int16_t dest; /* dest-type mask */
1011 + int invert_source;
1016 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_connlimit.h
1017 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
1018 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-05-18 12:36:13.000000000 +0200
1020 +#ifndef _IPT_CONNLIMIT_H
1021 +#define _IPT_CONNLIMIT_H
1023 +struct ipt_connlimit_data;
1025 +struct ipt_connlimit_info {
1029 + struct ipt_connlimit_data *data;
1031 +#endif /* _IPT_CONNLIMIT_H */
1032 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_connmark.h
1033 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
1034 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_connmark.h 2004-05-18 12:38:02.000000000 +0200
1036 +#ifndef _IPT_CONNMARK_H
1037 +#define _IPT_CONNMARK_H
1039 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
1040 + * by Henrik Nordstrom <hno@marasystems.com>
1042 + * This program is free software; you can redistribute it and/or modify
1043 + * it under the terms of the GNU General Public License as published by
1044 + * the Free Software Foundation; either version 2 of the License, or
1045 + * (at your option) any later version.
1048 +struct ipt_connmark_info {
1049 + unsigned long mark, mask;
1053 +#endif /*_IPT_CONNMARK_H*/
1054 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_dstlimit.h
1055 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
1056 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-05-18 12:36:19.000000000 +0200
1058 +#ifndef _IPT_DSTLIMIT_H
1059 +#define _IPT_DSTLIMIT_H
1061 +/* timings are in milliseconds. */
1062 +#define IPT_DSTLIMIT_SCALE 10000
1063 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
1064 + seconds, or one every 59 hours. */
1066 +/* details of this structure hidden by the implementation */
1067 +struct ipt_dstlimit_htable;
1069 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
1070 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
1071 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
1073 +struct dstlimit_cfg {
1074 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1075 + u_int32_t avg; /* Average secs between packets * scale */
1076 + u_int32_t burst; /* Period multiplier for upper limit. */
1078 + /* user specified */
1079 + u_int32_t size; /* how many buckets */
1080 + u_int32_t max; /* max number of entries */
1081 + u_int32_t gc_interval; /* gc interval */
1082 + u_int32_t expire; /* when do entries expire? */
1085 +struct ipt_dstlimit_info {
1086 + char name [IFNAMSIZ]; /* name */
1087 + struct dstlimit_cfg cfg;
1088 + struct ipt_dstlimit_htable *hinfo;
1090 + /* Used internally by the kernel */
1093 + struct ipt_dstlimit_info *master;
1096 +#endif /*_IPT_DSTLIMIT_H*/
1097 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_fuzzy.h
1098 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1099 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-05-18 12:36:22.000000000 +0200
1101 +#ifndef _IPT_FUZZY_H
1102 +#define _IPT_FUZZY_H
1104 +#include <linux/param.h>
1105 +#include <linux/types.h>
1107 +#define MAXFUZZYRATE 10000000
1108 +#define MINFUZZYRATE 3
1110 +struct ipt_fuzzy_info {
1111 + u_int32_t minimum_rate;
1112 + u_int32_t maximum_rate;
1113 + u_int32_t packets_total;
1114 + u_int32_t bytes_total;
1115 + u_int32_t previous_time;
1116 + u_int32_t present_time;
1117 + u_int32_t mean_rate;
1118 + u_int8_t acceptance_rate;
1121 +#endif /*_IPT_FUZZY_H*/
1122 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_ipv4options.h
1123 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1124 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-05-18 12:36:29.000000000 +0200
1126 +#ifndef __ipt_ipv4options_h_included__
1127 +#define __ipt_ipv4options_h_included__
1129 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1130 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1131 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1132 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1133 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1134 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1135 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1136 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1137 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1138 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1139 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1141 +struct ipt_ipv4options_info {
1142 + u_int16_t options;
1146 +#endif /* __ipt_ipv4options_h_included__ */
1147 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_mport.h
1148 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1149 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_mport.h 2004-05-18 12:36:36.000000000 +0200
1151 +#ifndef _IPT_MPORT_H
1152 +#define _IPT_MPORT_H
1153 +#include <linux/netfilter_ipv4/ip_tables.h>
1155 +#define IPT_MPORT_SOURCE (1<<0)
1156 +#define IPT_MPORT_DESTINATION (1<<1)
1157 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1159 +#define IPT_MULTI_PORTS 15
1161 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1162 +/* every entry in ports[] except for the last one has one bit in pflags
1163 + * associated with it. If this bit is set, the port is the first port of
1164 + * a portrange, with the next entry being the last.
1165 + * End of list is marked with pflags bit set and port=65535.
1166 + * If 14 ports are used (last one does not have a pflag), the last port
1167 + * is repeated to fill the last entry in ports[] */
1170 + u_int8_t flags:2; /* Type of comparison */
1171 + u_int16_t pflags:14; /* Port flags */
1172 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1174 +#endif /*_IPT_MPORT_H*/
1175 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_nth.h
1176 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1177 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_nth.h 2004-05-18 12:36:40.000000000 +0200
1182 +#include <linux/param.h>
1183 +#include <linux/types.h>
1185 +#ifndef IPT_NTH_NUM_COUNTERS
1186 +#define IPT_NTH_NUM_COUNTERS 16
1189 +struct ipt_nth_info {
1197 +#endif /*_IPT_NTH_H*/
1198 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_osf.h
1199 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1200 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_osf.h 2004-05-18 12:36:46.000000000 +0200
1205 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1208 + * This program is free software; you can redistribute it and/or modify
1209 + * it under the terms of the GNU General Public License as published by
1210 + * the Free Software Foundation; either version 2 of the License, or
1211 + * (at your option) any later version.
1213 + * This program is distributed in the hope that it will be useful,
1214 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1215 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1216 + * GNU General Public License for more details.
1218 + * You should have received a copy of the GNU General Public License
1219 + * along with this program; if not, write to the Free Software
1220 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1226 +#define MAXGENRELEN 32
1227 +#define MAXDETLEN 64
1229 +#define IPT_OSF_GENRE 1
1230 +#define IPT_OSF_SMART 2
1231 +#define IPT_OSF_LOG 4
1232 +#define IPT_OSF_NETLINK 8
1234 +#define IPT_OSF_LOGLEVEL_ALL 0
1235 +#define IPT_OSF_LOGLEVEL_FIRST 1
1237 +#include <linux/list.h>
1240 +#include <netinet/ip.h>
1241 +#include <netinet/tcp.h>
1245 + struct list_head *prev, *next;
1249 +struct ipt_osf_info
1251 + char genre[MAXGENRELEN];
1253 + unsigned long flags;
1255 + int invert; /* UNSUPPORTED */
1261 + unsigned long val;
1264 +/* This struct represents IANA options
1265 + * http://www.iana.org/assignments/tcp-parameters
1269 + unsigned char kind;
1270 + unsigned char length;
1276 + struct list_head flist;
1277 + struct osf_wc wss;
1278 + unsigned char ttl;
1281 + unsigned char genre[MAXGENRELEN];
1282 + unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
1284 + /* Not needed, but for consistency with original table from Michal Zalewski */
1285 + unsigned char details[MAXDETLEN];
1288 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1292 +struct ipt_osf_nlmsg
1294 + struct osf_finger f;
1296 + struct tcphdr tcp;
1301 +/* Defines for IANA option kinds */
1303 +#define OSFOPT_EOL 0 /* End of options */
1304 +#define OSFOPT_NOP 1 /* NOP */
1305 +#define OSFOPT_MSS 2 /* Maximum segment size */
1306 +#define OSFOPT_WSO 3 /* Window scale option */
1307 +#define OSFOPT_SACKP 4 /* SACK permitted */
1308 +#define OSFOPT_SACK 5 /* SACK */
1309 +#define OSFOPT_ECHO 6
1310 +#define OSFOPT_ECHOREPLY 7
1311 +#define OSFOPT_TS 8 /* Timestamp option */
1312 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1313 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1314 +/* Others are not used in current OSF */
1316 +static struct osf_opt IANA_opts[] =
1323 + {5, 1 ,}, /* SACK length is not defined */
1329 + {11, 1,}, /* CC: Suppose 1 */
1330 + {12, 1,}, /* the same */
1331 + {13, 1,}, /* and here too */
1333 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1347 +#endif /* __KERNEL__ */
1349 +#endif /* _IPT_OSF_H */
1350 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_policy.h
1351 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
1352 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_policy.h 2004-05-18 12:39:55.000000000 +0200
1354 +#ifndef _IPT_POLICY_H
1355 +#define _IPT_POLICY_H
1357 +#define POLICY_MAX_ELEM 4
1359 +enum ipt_policy_flags
1361 + POLICY_MATCH_IN = 0x1,
1362 + POLICY_MATCH_OUT = 0x2,
1363 + POLICY_MATCH_NONE = 0x4,
1364 + POLICY_MATCH_STRICT = 0x8,
1367 +enum ipt_policy_modes
1369 + POLICY_MODE_TRANSPORT,
1370 + POLICY_MODE_TUNNEL
1373 +struct ipt_policy_spec
1383 +struct ipt_policy_elem
1394 + struct ipt_policy_spec match;
1395 + struct ipt_policy_spec invert;
1398 +struct ipt_policy_info
1400 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1405 +#endif /* _IPT_POLICY_H */
1406 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_pool.h
1407 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1408 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_pool.h 2004-05-18 12:36:48.000000000 +0200
1410 +#ifndef _IPT_POOL_H
1411 +#define _IPT_POOL_H
1413 +#include <linux/netfilter_ipv4/ip_pool.h>
1415 +#define IPT_POOL_INV_SRC 0x00000001
1416 +#define IPT_POOL_INV_DST 0x00000002
1417 +#define IPT_POOL_DEL_SRC 0x00000004
1418 +#define IPT_POOL_DEL_DST 0x00000008
1419 +#define IPT_POOL_INV_MOD_SRC 0x00000010
1420 +#define IPT_POOL_INV_MOD_DST 0x00000020
1421 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1422 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1423 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
1424 +#define IPT_POOL_MOD_DST_DROP 0x00000200
1427 +struct ipt_pool_info
1434 +#endif /*_IPT_POOL_H*/
1435 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_psd.h
1436 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1437 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_psd.h 2004-05-18 12:36:55.000000000 +0200
1442 +#include <linux/param.h>
1443 +#include <linux/types.h>
1446 + * High port numbers have a lower weight to reduce the frequency of false
1447 + * positives, such as from passive mode FTP transfers.
1449 +#define PORT_WEIGHT_PRIV 3
1450 +#define PORT_WEIGHT_HIGH 1
1453 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1454 + * from the same source, with no longer than DELAY ticks between ports.
1456 +#define SCAN_MIN_COUNT 7
1457 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1458 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1459 +#define SCAN_DELAY_THRESHOLD (300) /* old usage of HZ here was erroneously and broke under uml */
1462 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1463 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1464 + * HASH_MAX source addresses per the same hash value.
1466 +#define LIST_SIZE 0x100
1468 +#define HASH_SIZE (1 << HASH_LOG)
1469 +#define HASH_MAX 0x10
1471 +struct ipt_psd_info {
1472 + unsigned int weight_threshold;
1473 + unsigned int delay_threshold;
1474 + unsigned short lo_ports_weight;
1475 + unsigned short hi_ports_weight;
1478 +#endif /*_IPT_PSD_H*/
1479 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_quota.h
1480 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1481 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_quota.h 2004-05-18 12:36:56.000000000 +0200
1483 +#ifndef _IPT_QUOTA_H
1484 +#define _IPT_QUOTA_H
1486 +/* print debug info in both kernel/netfilter module & iptable library */
1487 +//#define DEBUG_IPT_QUOTA
1489 +struct ipt_quota_info {
1493 +#endif /*_IPT_QUOTA_H*/
1494 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_random.h
1495 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1496 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_random.h 2004-05-18 12:36:59.000000000 +0200
1498 +#ifndef _IPT_RAND_H
1499 +#define _IPT_RAND_H
1501 +#include <linux/param.h>
1502 +#include <linux/types.h>
1504 +struct ipt_rand_info {
1508 +#endif /*_IPT_RAND_H*/
1509 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_realm.h
1510 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1511 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_realm.h 2004-05-18 12:37:05.000000000 +0200
1513 +#ifndef _IPT_REALM_H
1514 +#define _IPT_REALM_H
1516 +struct ipt_realm_info {
1521 +#endif /*_IPT_REALM_H*/
1522 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_sctp.h
1523 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1524 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_sctp.h 2004-05-18 12:37:09.000000000 +0200
1526 +#ifndef _IPT_SCTP_H_
1527 +#define _IPT_SCTP_H_
1529 +#define IPT_SCTP_SRC_PORTS 0x01
1530 +#define IPT_SCTP_DEST_PORTS 0x02
1531 +#define IPT_SCTP_CHUNK_TYPES 0x04
1533 +#define IPT_SCTP_VALID_FLAGS 0x07
1535 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1538 +struct ipt_sctp_flag_info {
1539 + u_int8_t chunktype;
1541 + u_int8_t flag_mask;
1544 +#define IPT_NUM_SCTP_FLAGS 4
1546 +struct ipt_sctp_info {
1547 + u_int16_t dpts[2]; /* Min, Max */
1548 + u_int16_t spts[2]; /* Min, Max */
1550 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
1552 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
1553 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
1554 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
1556 + u_int32_t chunk_match_type;
1557 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1561 + u_int32_t invflags;
1564 +#define bytes(type) (sizeof(type) * 8)
1566 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
1568 + chunkmap[type / bytes(u_int32_t)] |= \
1569 + 1 << (type % bytes(u_int32_t)); \
1572 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
1574 + chunkmap[type / bytes(u_int32_t)] &= \
1575 + ~(1 << (type % bytes(u_int32_t))); \
1578 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
1580 + (chunkmap[type / bytes (u_int32_t)] & \
1581 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
1584 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
1587 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1588 + chunkmap[i] = 0; \
1591 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
1594 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1595 + chunkmap[i] = ~0; \
1598 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
1601 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1602 + destmap[i] = srcmap[i]; \
1605 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
1609 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1610 + if (chunkmap[i]) { \
1618 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
1622 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1623 + if (chunkmap[i] != ~0) { \
1631 +#endif /* _IPT_SCTP_H_ */
1633 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_string.h
1634 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1635 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_string.h 2004-05-18 12:40:41.000000000 +0200
1637 +#ifndef _IPT_STRING_H
1638 +#define _IPT_STRING_H
1640 +/* *** PERFORMANCE TWEAK ***
1641 + * Packet size and search string threshold,
1642 + * above which sublinear searches is used. */
1643 +#define IPT_STRING_HAYSTACK_THRESH 100
1644 +#define IPT_STRING_NEEDLE_THRESH 20
1646 +#define BM_MAX_NLEN 256
1647 +#define BM_MAX_HLEN 1024
1649 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1651 +struct ipt_string_info {
1652 + char string[BM_MAX_NLEN];
1657 +#endif /* _IPT_STRING_H */
1658 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_time.h
1659 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1660 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_time.h 2004-05-18 12:37:29.000000000 +0200
1662 +#ifndef __ipt_time_h_included__
1663 +#define __ipt_time_h_included__
1666 +struct ipt_time_info {
1667 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
1668 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
1669 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
1670 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
1671 + time_t date_start;
1676 +#endif /* __ipt_time_h_included__ */
1677 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_u32.h
1678 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
1679 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_u32.h 2004-05-18 12:37:31.000000000 +0200
1683 +#include <linux/netfilter_ipv4/ip_tables.h>
1693 +struct ipt_u32_location_element
1698 +struct ipt_u32_value_element
1703 +/* *** any way to allow for an arbitrary number of elements?
1704 + for now I settle for a limit of 10 of each */
1705 +#define U32MAXSIZE 10
1706 +struct ipt_u32_test
1709 + struct ipt_u32_location_element location[U32MAXSIZE+1];
1711 + struct ipt_u32_value_element value[U32MAXSIZE+1];
1717 + struct ipt_u32_test tests[U32MAXSIZE+1];
1720 +#endif /*_IPT_U32_H*/
1721 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4.h linux-2.6.6/include/linux/netfilter_ipv4.h
1722 --- linux-2.6.6.org/include/linux/netfilter_ipv4.h 2004-05-10 04:33:13.000000000 +0200
1723 +++ linux-2.6.6/include/linux/netfilter_ipv4.h 2004-05-18 12:39:22.000000000 +0200
1726 #include <linux/config.h>
1727 #include <linux/netfilter.h>
1728 +#include <linux/netdevice.h>
1729 +#include <net/protocol.h>
1731 /* IP Cache bits. */
1732 /* Src IP address. */
1734 Returns true or false. */
1735 extern int skb_ip_make_writable(struct sk_buff **pskb,
1736 unsigned int writable_len);
1738 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1739 +#include <net/route.h>
1740 +#include <net/xfrm.h>
1742 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1744 + return !skb->sp || skb->sp->decap_done;
1748 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1750 + return skb->sp && !skb->sp->decap_done
1751 + && (!ipprot || !ipprot->xfrm_prot);
1754 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1756 + return skb->sp && !skb->sp->decap_done
1757 + && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1760 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1761 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1762 +#else /* CONFIG_XFRM */
1763 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1769 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1774 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1779 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1784 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1788 +#endif /* CONFIG_XFRM */
1789 #endif /*__KERNEL__*/
1791 #endif /*__LINUX_IP_NETFILTER_H*/
1792 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6/include/linux/netfilter_ipv6/ip6_tables.h
1793 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-05-10 04:33:20.000000000 +0200
1794 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6_tables.h 2004-05-18 12:38:32.000000000 +0200
1795 @@ -140,6 +140,12 @@
1797 unsigned int comefrom;
1799 + /* Name of the chain */
1802 + /* Rule number in the chain. */
1803 + u_int32_t rulenum;
1805 /* Packet and byte counters. */
1806 struct ip6t_counters counters;
1808 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_HL.h
1809 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
1810 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_HL.h 2004-05-18 12:35:59.000000000 +0200
1812 +/* Hop Limit modification module for ip6tables
1813 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1814 + * Based on HW's TTL module */
1825 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
1827 +struct ip6t_HL_info {
1829 + u_int8_t hop_limit;
1834 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_REJECT.h
1835 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-05-10 04:31:58.000000000 +0200
1836 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-05-18 12:36:05.000000000 +0200
1838 #define _IP6T_REJECT_H
1840 enum ip6t_reject_with {
1841 - IP6T_ICMP_NET_UNREACHABLE,
1842 - IP6T_ICMP_HOST_UNREACHABLE,
1843 - IP6T_ICMP_PROT_UNREACHABLE,
1844 - IP6T_ICMP_PORT_UNREACHABLE,
1845 - IP6T_ICMP_ECHOREPLY
1846 + IP6T_ICMP6_NO_ROUTE,
1847 + IP6T_ICMP6_ADM_PROHIBITED,
1848 + IP6T_ICMP6_NOT_NEIGHBOUR,
1849 + IP6T_ICMP6_ADDR_UNREACH,
1850 + IP6T_ICMP6_PORT_UNREACH,
1851 + IP6T_ICMP6_ECHOREPLY,
1855 struct ip6t_reject_info {
1856 enum ip6t_reject_with with; /* reject type */
1859 -#endif /*_IPT_REJECT_H*/
1860 +#endif /*_IP6T_REJECT_H*/
1861 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h
1862 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
1863 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2004-05-18 12:38:20.000000000 +0200
1865 +/* Header file for iptables ip6t_ROUTE target
1867 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
1869 + * This software is distributed under GNU GPL v2, 1991
1871 +#ifndef _IPT_ROUTE_H_target
1872 +#define _IPT_ROUTE_H_target
1874 +#define IP6T_ROUTE_IFNAMSIZ 16
1876 +struct ip6t_route_target_info {
1877 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
1878 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
1879 + u_int32_t gw[4]; /* IPv6 address of gateway */
1883 +/* Values for "flags" field */
1884 +#define IP6T_ROUTE_CONTINUE 0x01
1886 +#endif /*_IP6T_ROUTE_H_target*/
1887 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1888 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1889 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-05-18 12:36:22.000000000 +0200
1891 +#ifndef _IP6T_FUZZY_H
1892 +#define _IP6T_FUZZY_H
1894 +#include <linux/param.h>
1895 +#include <linux/types.h>
1897 +#define MAXFUZZYRATE 10000000
1898 +#define MINFUZZYRATE 3
1900 +struct ip6t_fuzzy_info {
1901 + u_int32_t minimum_rate;
1902 + u_int32_t maximum_rate;
1903 + u_int32_t packets_total;
1904 + u_int32_t bytes_total;
1905 + u_int32_t previous_time;
1906 + u_int32_t present_time;
1907 + u_int32_t mean_rate;
1908 + u_int8_t acceptance_rate;
1911 +#endif /*_IP6T_FUZZY_H*/
1912 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_nth.h
1913 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1914 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_nth.h 2004-05-18 12:36:40.000000000 +0200
1916 +#ifndef _IP6T_NTH_H
1917 +#define _IP6T_NTH_H
1919 +#include <linux/param.h>
1920 +#include <linux/types.h>
1922 +#ifndef IP6T_NTH_NUM_COUNTERS
1923 +#define IP6T_NTH_NUM_COUNTERS 16
1926 +struct ip6t_nth_info {
1934 +#endif /*_IP6T_NTH_H*/
1935 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_owner.h
1936 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-05-10 04:32:52.000000000 +0200
1937 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_owner.h 2004-05-18 12:39:53.000000000 +0200
1939 #define IP6T_OWNER_GID 0x02
1940 #define IP6T_OWNER_PID 0x04
1941 #define IP6T_OWNER_SID 0x08
1942 +#define IP6T_OWNER_COMM 0x10
1944 struct ip6t_owner_info {
1950 u_int8_t match, invert; /* flags */
1953 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_policy.h
1954 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1955 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_policy.h 2004-05-18 12:39:55.000000000 +0200
1957 +#ifndef _IP6T_POLICY_H
1958 +#define _IP6T_POLICY_H
1960 +#define POLICY_MAX_ELEM 4
1962 +enum ip6t_policy_flags
1964 + POLICY_MATCH_IN = 0x1,
1965 + POLICY_MATCH_OUT = 0x2,
1966 + POLICY_MATCH_NONE = 0x4,
1967 + POLICY_MATCH_STRICT = 0x8,
1970 +enum ip6t_policy_modes
1972 + POLICY_MODE_TRANSPORT,
1973 + POLICY_MODE_TUNNEL
1976 +struct ip6t_policy_spec
1986 +struct ip6t_policy_elem
1988 + struct in6_addr saddr;
1989 + struct in6_addr smask;
1990 + struct in6_addr daddr;
1991 + struct in6_addr dmask;
1997 + struct ip6t_policy_spec match;
1998 + struct ip6t_policy_spec invert;
2001 +struct ip6t_policy_info
2003 + struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
2008 +#endif /* _IP6T_POLICY_H */
2009 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_random.h
2010 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
2011 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_random.h 2004-05-18 12:36:59.000000000 +0200
2013 +#ifndef _IP6T_RAND_H
2014 +#define _IP6T_RAND_H
2016 +#include <linux/param.h>
2017 +#include <linux/types.h>
2019 +struct ip6t_rand_info {
2023 +#endif /*_IP6T_RAND_H*/
2024 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_mime.h linux-2.6.6/include/linux/netfilter_mime.h
2025 --- linux-2.6.6.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
2026 +++ linux-2.6.6/include/linux/netfilter_mime.h 2004-05-18 12:40:21.000000000 +0200
2029 + * MIME functions for netfilter modules. This file provides implementations
2030 + * for basic MIME parsing. MIME headers are used in many protocols, such as
2031 + * HTTP, RTSP, SIP, etc.
2033 + * gcc will warn for defined but unused functions, so we only include the
2034 + * functions requested. The following macros are used:
2035 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
2037 +#ifndef _NETFILTER_MIME_H
2038 +#define _NETFILTER_MIME_H
2040 +/* Only include these functions for kernel code. */
2043 +#include <linux/ctype.h>
2046 + * Given a buffer and length, advance to the next line and mark the current
2047 + * line. If the current line is empty, *plinelen will be set to zero. If
2048 + * not, it will be set to the actual line length (including CRLF).
2050 + * 'line' in this context means logical line (includes LWS continuations).
2051 + * Returns 1 on success, 0 on failure.
2053 +#ifdef NF_NEED_MIME_NEXTLINE
2055 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2059 + int is_first_line = 1;
2068 + while (p[off] != '\n')
2079 + /* if we saw a crlf, physlen needs adjusted */
2080 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2085 + /* advance past the newline */
2088 + /* check for an empty line */
2094 + /* check for colon on the first physical line */
2095 + if (is_first_line)
2097 + is_first_line = 0;
2098 + if (memchr(p+(*poff), ':', physlen) == NULL)
2104 + while (p[off] == ' ' || p[off] == '\t');
2106 + *plineoff = *poff;
2107 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
2112 +#endif /* NF_NEED_MIME_NEXTLINE */
2114 +#endif /* __KERNEL__ */
2116 +#endif /* _NETFILTER_MIME_H */
2117 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/skbuff.h linux-2.6.6/include/linux/skbuff.h
2118 --- linux-2.6.6.org/include/linux/skbuff.h 2004-05-10 04:32:39.000000000 +0200
2119 +++ linux-2.6.6/include/linux/skbuff.h 2004-05-18 12:35:50.000000000 +0200
2120 @@ -1049,6 +1049,14 @@
2122 atomic_inc(&nfct->master->use);
2124 +static inline void nf_reset(struct sk_buff *skb)
2126 + nf_conntrack_put(skb->nfct);
2128 +#ifdef CONFIG_NETFILTER_DEBUG
2129 + skb->nf_debug = 0;
2133 #ifdef CONFIG_BRIDGE_NETFILTER
2134 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2135 @@ -1061,9 +1069,10 @@
2137 atomic_inc(&nf_bridge->use);
2142 +#endif /* CONFIG_BRIDGE_NETFILTER */
2143 +#else /* CONFIG_NETFILTER */
2144 +static inline void nf_reset(struct sk_buff *skb) {}
2145 +#endif /* CONFIG_NETFILTER */
2147 #endif /* __KERNEL__ */
2148 #endif /* _LINUX_SKBUFF_H */
2149 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/ip.h linux-2.6.6/include/net/ip.h
2150 --- linux-2.6.6.org/include/net/ip.h 2004-05-10 04:32:53.000000000 +0200
2151 +++ linux-2.6.6/include/net/ip.h 2004-05-18 12:39:21.000000000 +0200
2153 #include <linux/netdevice.h>
2154 #include <linux/inetdevice.h>
2155 #include <linux/in_route.h>
2156 +#include <linux/netfilter.h>
2157 +#include <linux/netfilter_ipv4.h>
2158 #include <net/route.h>
2159 #include <net/arp.h>
2162 #define IPSKB_TRANSLATED 2
2163 #define IPSKB_FORWARDED 4
2164 #define IPSKB_XFRM_TUNNEL_SIZE 8
2165 +#define IPSKB_XFRM_TRANSFORMED 16
2169 @@ -212,6 +215,12 @@
2170 __ip_select_ident(iph, dst, more);
2173 +extern inline int ip_dst_output(struct sk_buff *skb)
2175 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2176 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2180 * Map a multicast IP onto multicast MAC for type ethernet.
2182 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/protocol.h linux-2.6.6/include/net/protocol.h
2183 --- linux-2.6.6.org/include/net/protocol.h 2004-05-10 04:32:28.000000000 +0200
2184 +++ linux-2.6.6/include/net/protocol.h 2004-05-18 12:39:22.000000000 +0200
2186 int (*handler)(struct sk_buff *skb);
2187 void (*err_handler)(struct sk_buff *skb, u32 info);
2192 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2193 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/tcp.h linux-2.6.6/include/net/tcp.h
2194 --- linux-2.6.6.org/include/net/tcp.h 2004-05-10 04:32:01.000000000 +0200
2195 +++ linux-2.6.6/include/net/tcp.h 2004-05-18 12:39:47.000000000 +0200
2197 extern void tcp_bucket_unlock(struct sock *sk);
2198 extern int tcp_port_rover;
2199 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2200 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2202 /* These are AF independent. */
2203 static __inline__ int tcp_bhashfn(__u16 lport)
2204 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/udp.h linux-2.6.6/include/net/udp.h
2205 --- linux-2.6.6.org/include/net/udp.h 2004-05-10 04:33:13.000000000 +0200
2206 +++ linux-2.6.6/include/net/udp.h 2004-05-18 12:39:47.000000000 +0200
2208 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2209 extern int udp_disconnect(struct sock *sk, int flags);
2211 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2213 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2214 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
2215 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
2216 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/xfrm.h linux-2.6.6/include/net/xfrm.h
2217 --- linux-2.6.6.org/include/net/xfrm.h 2004-05-10 04:33:13.000000000 +0200
2218 +++ linux-2.6.6/include/net/xfrm.h 2004-05-18 12:39:22.000000000 +0200
2223 +#ifdef CONFIG_NETFILTER
2226 struct sec_decap_state x[XFRM_MAX_DEPTH];
2229 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/core/netfilter.c linux-2.6.6/net/core/netfilter.c
2230 --- linux-2.6.6.org/net/core/netfilter.c 2004-05-10 04:32:29.000000000 +0200
2231 +++ linux-2.6.6/net/core/netfilter.c 2004-05-18 12:39:23.000000000 +0200
2233 #include <linux/icmp.h>
2234 #include <net/sock.h>
2235 #include <net/route.h>
2236 +#include <net/xfrm.h>
2237 +#include <net/ip.h>
2238 #include <linux/ip.h>
2240 /* In this code, we can be waiting indefinitely for userspace to
2242 #ifdef CONFIG_IP_ROUTE_FWMARK
2243 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2245 - fl.proto = iph->protocol;
2246 if (ip_route_output_key(&rt, &fl) != 0)
2249 @@ -665,6 +666,20 @@
2250 if ((*pskb)->dst->error)
2254 + if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2255 + struct xfrm_policy_afinfo *afinfo;
2257 + afinfo = xfrm_policy_get_afinfo(AF_INET);
2258 + if (afinfo != NULL) {
2259 + afinfo->decode_session(*pskb, &fl);
2260 + xfrm_policy_put_afinfo(afinfo);
2261 + if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2267 /* Change in oif may mean change in hh_len. */
2268 hh_len = (*pskb)->dst->dev->hard_header_len;
2269 if (skb_headroom(*pskb) < hh_len) {
2270 @@ -682,6 +697,71 @@
2275 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2277 + skb->sp->decap_done = 1;
2278 + dst_release(skb->dst);
2281 + return netif_rx(skb);
2284 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2286 + __skb_push(skb, skb->data - skb->nh.raw);
2287 + /* Fix header len and checksum if last xfrm was transport mode */
2288 + if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2289 + skb->nh.iph->tot_len = htons(skb->len);
2290 + ip_send_check(skb->nh.iph);
2292 + return nf_rcv_postxfrm_nonlocal(skb);
2295 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2296 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2297 +#include <linux/netfilter_ipv4/ip_nat.h>
2299 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2301 + struct ip_conntrack *ct;
2302 + struct ip_conntrack_tuple *t;
2303 + struct ip_nat_info_manip *m;
2306 + if (skb->nfct == NULL)
2308 + ct = (struct ip_conntrack *)skb->nfct->master;
2310 + for (i = 0; i < ct->nat.info.num_manips; i++) {
2311 + m = &ct->nat.info.manips[i];
2312 + t = &ct->tuplehash[m->direction].tuple;
2314 + switch (m->hooknum) {
2315 + case NF_IP_PRE_ROUTING:
2316 + if (m->maniptype != IP_NAT_MANIP_DST)
2318 + fl->fl4_dst = t->dst.ip;
2319 + if (t->dst.protonum == IPPROTO_TCP ||
2320 + t->dst.protonum == IPPROTO_UDP)
2321 + fl->fl_ip_dport = t->dst.u.tcp.port;
2323 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2324 + case NF_IP_LOCAL_IN:
2325 + if (m->maniptype != IP_NAT_MANIP_SRC)
2327 + fl->fl4_src = t->src.ip;
2328 + if (t->dst.protonum == IPPROTO_TCP ||
2329 + t->dst.protonum == IPPROTO_UDP)
2330 + fl->fl_ip_sport = t->src.u.tcp.port;
2336 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2339 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2341 struct sk_buff *nskb;
2343 EXPORT_SYMBOL(nf_unregister_hook);
2344 EXPORT_SYMBOL(nf_unregister_queue_handler);
2345 EXPORT_SYMBOL(nf_unregister_sockopt);
2346 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2347 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ah4.c linux-2.6.6/net/ipv4/ah4.c
2348 --- linux-2.6.6.org/net/ipv4/ah4.c 2004-05-10 04:33:19.000000000 +0200
2349 +++ linux-2.6.6/net/ipv4/ah4.c 2004-05-18 12:39:22.000000000 +0200
2351 err = -EHOSTUNREACH;
2354 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2355 return NET_XMIT_BYPASS;
2359 .handler = xfrm4_rcv,
2360 .err_handler = ah4_err,
2365 static int __init ah4_init(void)
2366 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/esp4.c linux-2.6.6/net/ipv4/esp4.c
2367 --- linux-2.6.6.org/net/ipv4/esp4.c 2004-05-10 04:32:39.000000000 +0200
2368 +++ linux-2.6.6/net/ipv4/esp4.c 2004-05-18 12:39:22.000000000 +0200
2370 err = -EHOSTUNREACH;
2373 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2374 return NET_XMIT_BYPASS;
2378 .handler = xfrm4_rcv,
2379 .err_handler = esp4_err,
2384 static int __init esp4_init(void)
2385 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/igmp.c linux-2.6.6/net/ipv4/igmp.c
2386 --- linux-2.6.6.org/net/ipv4/igmp.c 2004-05-10 04:33:21.000000000 +0200
2387 +++ linux-2.6.6/net/ipv4/igmp.c 2004-05-18 12:39:21.000000000 +0200
2389 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2391 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2396 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2398 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2400 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2405 static void igmp_gq_timer_expire(unsigned long data)
2406 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_forward.c linux-2.6.6/net/ipv4/ip_forward.c
2407 --- linux-2.6.6.org/net/ipv4/ip_forward.c 2004-05-10 04:31:58.000000000 +0200
2408 +++ linux-2.6.6/net/ipv4/ip_forward.c 2004-05-18 12:39:21.000000000 +0200
2410 if (unlikely(opt->optlen))
2411 ip_forward_options(skb);
2413 - return dst_output(skb);
2414 + return ip_dst_output(skb);
2417 int ip_forward(struct sk_buff *skb)
2418 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_gre.c linux-2.6.6/net/ipv4/ip_gre.c
2419 --- linux-2.6.6.org/net/ipv4/ip_gre.c 2004-05-10 04:32:54.000000000 +0200
2420 +++ linux-2.6.6/net/ipv4/ip_gre.c 2004-05-18 12:35:50.000000000 +0200
2421 @@ -643,13 +643,7 @@
2422 skb->dev = tunnel->dev;
2423 dst_release(skb->dst);
2425 -#ifdef CONFIG_NETFILTER
2426 - nf_conntrack_put(skb->nfct);
2428 -#ifdef CONFIG_NETFILTER_DEBUG
2429 - skb->nf_debug = 0;
2433 ipgre_ecn_decapsulate(iph, skb);
2435 read_unlock(&ipgre_lock);
2436 @@ -877,13 +871,7 @@
2440 -#ifdef CONFIG_NETFILTER
2441 - nf_conntrack_put(skb->nfct);
2443 -#ifdef CONFIG_NETFILTER_DEBUG
2444 - skb->nf_debug = 0;
2450 tunnel->recursion--;
2451 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_input.c linux-2.6.6/net/ipv4/ip_input.c
2452 --- linux-2.6.6.org/net/ipv4/ip_input.c 2004-05-10 04:31:59.000000000 +0200
2453 +++ linux-2.6.6/net/ipv4/ip_input.c 2004-05-18 12:39:23.000000000 +0200
2454 @@ -202,18 +202,10 @@
2456 #ifdef CONFIG_NETFILTER_DEBUG
2457 nf_debug_ip_local_deliver(skb);
2458 - skb->nf_debug = 0;
2459 #endif /*CONFIG_NETFILTER_DEBUG*/
2461 __skb_pull(skb, ihl);
2463 -#ifdef CONFIG_NETFILTER
2464 - /* Free reference early: we don't need it any more, and it may
2465 - hold ip_conntrack module loaded indefinitely. */
2466 - nf_conntrack_put(skb->nfct);
2468 -#endif /*CONFIG_NETFILTER*/
2470 /* Point into the IP datagram, just past the header. */
2471 skb->h.raw = skb->data;
2473 @@ -228,6 +220,13 @@
2475 hash = protocol & (MAX_INET_PROTOS - 1);
2476 raw_sk = sk_head(&raw_v4_htable[hash]);
2477 + ipprot = inet_protos[hash];
2478 + smp_read_barrier_depends();
2480 + if (nf_xfrm_local_done(skb, ipprot)) {
2481 + nf_rcv_postxfrm_local(skb);
2485 /* If there maybe a raw socket we must check - if not we
2487 @@ -235,14 +234,15 @@
2489 raw_v4_input(skb, skb->nh.iph, hash);
2491 - if ((ipprot = inet_protos[hash]) != NULL) {
2492 + if (ipprot != NULL) {
2495 - smp_read_barrier_depends();
2496 - if (!ipprot->no_policy &&
2497 - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2500 + if (!ipprot->no_policy) {
2501 + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2507 ret = ipprot->handler(skb);
2513 - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2514 - ip_local_deliver_finish);
2515 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2516 + ip_local_deliver_finish, nf_hook_input_cond(skb));
2519 static inline int ip_rcv_finish(struct sk_buff *skb)
2524 + if (nf_xfrm_nonlocal_done(skb))
2525 + return nf_rcv_postxfrm_nonlocal(skb);
2527 #ifdef CONFIG_NET_CLS_ROUTE
2528 if (skb->dst->tclassid) {
2529 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2534 - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2536 + return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2537 + ip_rcv_finish, nf_hook_input_cond(skb));
2540 IP_INC_STATS_BH(IpInHdrErrors);
2541 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_output.c linux-2.6.6/net/ipv4/ip_output.c
2542 --- linux-2.6.6.org/net/ipv4/ip_output.c 2004-05-10 04:33:21.000000000 +0200
2543 +++ linux-2.6.6/net/ipv4/ip_output.c 2004-05-18 12:39:21.000000000 +0200
2544 @@ -123,6 +123,15 @@
2548 +#ifdef CONFIG_NETFILTER
2549 +/* out-of-line copy is only required with netfilter */
2550 +int ip_dst_output(struct sk_buff *skb)
2552 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2553 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2558 * Add an ip header to a skbuff and send it out.
2563 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2568 static inline int ip_finish_output2(struct sk_buff *skb)
2570 return ip_finish_output(skb);
2573 -int ip_output(struct sk_buff *skb)
2574 +static inline int ip_output2(struct sk_buff *skb)
2576 IP_INC_STATS(IpOutRequests);
2578 @@ -294,6 +303,16 @@
2579 return ip_finish_output(skb);
2582 +int ip_output(struct sk_buff *skb)
2584 + int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2588 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2589 + skb->dst->dev, ip_output2, transformed);
2592 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2594 struct sock *sk = skb->sk;
2596 skb->priority = sk->sk_priority;
2598 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2603 IP_INC_STATS(IpOutNoRoutes);
2604 @@ -1177,7 +1196,7 @@
2606 /* Netfilter gets whole the not fragmented skb. */
2607 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2608 - skb->dst->dev, dst_output);
2609 + skb->dst->dev, ip_dst_output);
2612 err = inet->recverr ? net_xmit_errno(err) : 0;
2613 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ipcomp.c linux-2.6.6/net/ipv4/ipcomp.c
2614 --- linux-2.6.6.org/net/ipv4/ipcomp.c 2004-05-10 04:33:13.000000000 +0200
2615 +++ linux-2.6.6/net/ipv4/ipcomp.c 2004-05-18 12:39:22.000000000 +0200
2617 err = -EHOSTUNREACH;
2620 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2621 err = NET_XMIT_BYPASS;
2625 .handler = xfrm4_rcv,
2626 .err_handler = ipcomp4_err,
2631 static int __init ipcomp4_init(void)
2632 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ipip.c linux-2.6.6/net/ipv4/ipip.c
2633 --- linux-2.6.6.org/net/ipv4/ipip.c 2004-05-10 04:33:22.000000000 +0200
2634 +++ linux-2.6.6/net/ipv4/ipip.c 2004-05-18 12:39:22.000000000 +0200
2635 @@ -478,6 +478,11 @@
2637 read_lock(&ipip_lock);
2638 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2639 + /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2640 + if (nf_xfrm_local_done(skb, NULL)) {
2641 + nf_rcv_postxfrm_local(skb);
2644 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2647 @@ -496,13 +501,7 @@
2648 skb->dev = tunnel->dev;
2649 dst_release(skb->dst);
2651 -#ifdef CONFIG_NETFILTER
2652 - nf_conntrack_put(skb->nfct);
2654 -#ifdef CONFIG_NETFILTER_DEBUG
2655 - skb->nf_debug = 0;
2659 ipip_ecn_decapsulate(iph, skb);
2661 read_unlock(&ipip_lock);
2662 @@ -647,13 +646,7 @@
2663 if ((iph->ttl = tiph->ttl) == 0)
2664 iph->ttl = old_iph->ttl;
2666 -#ifdef CONFIG_NETFILTER
2667 - nf_conntrack_put(skb->nfct);
2669 -#ifdef CONFIG_NETFILTER_DEBUG
2670 - skb->nf_debug = 0;
2676 tunnel->recursion--;
2677 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ipmr.c linux-2.6.6/net/ipv4/ipmr.c
2678 --- linux-2.6.6.org/net/ipv4/ipmr.c 2004-05-10 04:32:30.000000000 +0200
2679 +++ linux-2.6.6/net/ipv4/ipmr.c 2004-05-18 12:39:21.000000000 +0200
2680 @@ -1120,7 +1120,7 @@
2681 if (unlikely(opt->optlen))
2682 ip_forward_options(skb);
2684 - return dst_output(skb);
2685 + return ip_dst_output(skb);
2689 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/Kconfig linux-2.6.6/net/ipv4/netfilter/Kconfig
2690 --- linux-2.6.6.org/net/ipv4/netfilter/Kconfig 2004-05-10 04:33:13.000000000 +0200
2691 +++ linux-2.6.6/net/ipv4/netfilter/Kconfig 2004-05-18 12:40:50.000000000 +0200
2692 @@ -206,6 +206,11 @@
2694 To compile it as a module, choose M here. If unsure, say N.
2696 +config IP_NF_MATCH_UNCLEAN
2697 + tristate 'unclean match support (EXPERIMENTAL)'
2698 + depends on EXPERIMENTAL && IP_NF_IPTABLES
2701 config IP_NF_MATCH_TTL
2702 tristate "TTL match support"
2703 depends on IP_NF_IPTABLES
2704 @@ -603,5 +608,509 @@
2705 <file:Documentation/modules.txt>. If unsure, say `N'.
2708 +config IP_NF_TARGET_IPV4OPTSSTRIP
2709 + tristate 'IPV4OPTSSTRIP target support'
2710 + depends on IP_NF_MANGLE
2712 + This option adds an IPV4OPTSSTRIP target.
2713 + This target allows you to strip all IP options in a packet.
2715 + If you want to compile it as a module, say M here and read
2716 + Documentation/modules.txt. If unsure, say `N'.
2718 +config IP_NF_TARGET_NETLINK
2719 + tristate 'NETLINK target support'
2720 + depends on IP_NF_FILTER
2722 + The NETLINK target allows you to recieve packets in userspace via
2723 + the kernel firewall netlink socket. Apps such as fwmon
2724 + (http://firestorm.geek-ware.co.uk) can then recieve and dislpay
2725 + these packets. This option is basically a re-implementation of the
2726 + ipchains -o option.
2728 +config IP_NF_TARGET_TTL
2729 + tristate 'TTL target support'
2730 + depends on IP_NF_MANGLE
2732 + This option adds a `TTL' target, which enables the user to set
2733 + the TTL value or increment / decrement the TTL value by a given
2736 + If you want to compile it as a module, say M here and read
2737 + Documentation/modules.txt. If unsure, say `N'.
2739 +config IP_NF_MATCH_CONNLIMIT
2740 + tristate 'Connections/IP limit match support'
2741 + depends on IP_NF_IPTABLES
2743 + This match allows you to restrict the number of parallel TCP
2744 + connections to a server per client IP address (or address block).
2746 + If you want to compile it as a module, say M here and read
2747 + Documentation/modules.txt. If unsure, say `N'.
2749 +config IP_NF_MATCH_DSTLIMIT
2750 + tristate 'dstlimit match support'
2751 + depends on IP_NF_IPTABLES
2753 +config IP_NF_MATCH_FUZZY
2754 + tristate 'fuzzy match support'
2755 + depends on IP_NF_IPTABLES
2757 + This option adds a `fuzzy' match, which allows you to match
2758 + packets according to a fuzzy logic based law.
2760 + If you want to compile it as a module, say M here and read
2761 + Documentation/modules.txt. If unsure, say `N'.
2763 +config IP_NF_MATCH_IPV4OPTIONS
2764 + tristate 'IPV4OPTIONS match support'
2765 + depends on IP_NF_IPTABLES
2767 + This option adds a IPV4OPTIONS match.
2768 + It allows you to filter options like source routing,
2769 + record route, timestamp and router-altert.
2771 + If you say Y here, try iptables -m ipv4options --help for more information.
2773 + If you want to compile it as a module, say M here and read
2774 + Documentation/modules.txt. If unsure, say `N'.
2776 +config IP_NF_MATCH_MPORT
2777 + tristate 'Multiple port with ranges match support'
2778 + depends on IP_NF_IPTABLES
2780 + This is an enhanced multiport match which supports port
2781 + ranges as well as single ports.
2783 + If you want to compile it as a module, say M here and read
2784 + Documentation/modules.txt. If unsure, say `N'.
2786 +config IP_NF_MATCH_NTH
2787 + tristate 'Nth match support'
2788 + depends on IP_NF_IPTABLES
2790 + This option adds a `Nth' match, which allow you to make
2791 + rules that match every Nth packet. By default there are
2792 + 16 different counters.
2795 + --every Nth Match every Nth packet
2796 + [--counter] num Use counter 0-15 (default:0)
2797 + [--start] num Initialize the counter at the number 'num'
2798 + instead of 0. Must be between 0 and Nth-1
2799 + [--packet] num Match on 'num' packet. Must be between 0
2802 + If --packet is used for a counter than
2803 + there must be Nth number of --packet
2804 + rules, covering all values between 0 and
2805 + Nth-1 inclusively.
2807 + If you want to compile it as a module, say M here and read
2808 + Documentation/modules.txt. If unsure, say `N'.
2810 +config IP_NF_MATCH_OSF
2811 + tristate 'OSF match support'
2812 + depends on IP_NF_IPTABLES
2815 + The idea of passive OS fingerprint matching exists for quite a long time,
2816 + but was created as extension fo OpenBSD pf only some weeks ago.
2817 + Original idea was lurked in some OpenBSD mailing list (thanks
2818 + grange@open...) and than adopted for Linux netfilter in form of this code.
2820 + Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
2821 + his excellent p0f and than changed a bit for more convenience.
2823 + This module compares some data(WS, MSS, options and it's order, ttl,
2824 + df and others) from first SYN packet (actually from packets with SYN
2825 + bit set) with hardcoded in fingers[] table ones.
2827 + If you say Y here, try iptables -m osf --help for more information.
2829 + If you want to compile it as a module, say M here and read
2830 + Documentation/modules.txt. If unsure, say `N'.
2832 +config IP_POOL_STATISTICS
2833 + bool 'enable statistics on pool usage'
2834 + depends on IP_NF_POOL!=n
2836 + This option controls whether usage gathering code is compiled into the
2837 + ip_pool module. Disabling statistics may be substantially faster.
2840 + tristate 'IP address pool support'
2841 + depends on IP_NF_IPTABLES
2843 + Pool matching lets you use bitmaps with one bit per address from some
2844 + range of IP addresses; the match depends on whether a checked source
2845 + or destination address has its bit set in the pool.
2847 + There is also a POOL netfilter target, which can be used to set or remove
2848 + the addresses of a packet from a pool.
2850 + To define and use pools, you need userlevel utilities: a patched iptables,
2851 + and the program ippool(8), which defines the pools and their bounds.
2852 + The current release of pool matching is ippool-0.0.2, and can be found
2853 + in the archives of the netfilter mailing list at
2854 + http://lists.samba.org/netfilter/.
2856 + If you want to compile it as a module, say M here and read
2857 + Documentation/modules.txt. If unsure, say `N'.
2859 +config IP_NF_MATCH_PSD
2860 + tristate 'psd match support'
2861 + depends on IP_NF_IPTABLES
2863 + This option adds a `psd' match, which allows you to create rules in
2864 + any iptables table wich will detect TCP and UDP port scans.
2866 + If you want to compile it as a module, say M here and read
2867 + Documentation/modules.txt. If unsure, say `N'.
2869 +config IP_NF_MATCH_QUOTA
2870 + tristate 'quota match support'
2871 + depends on IP_NF_IPTABLES
2873 + This match implements network quotas.
2875 + If you want to compile it as a module, say M here and read
2876 + Documentation/modules.txt. If unsure, say `N'.
2879 +config IP_NF_MATCH_RANDOM
2880 + tristate 'random match support'
2881 + depends on IP_NF_IPTABLES
2883 + This option adds a `random' match,
2884 + which allow you to match packets randomly
2885 + following a given probability.
2887 + If you want to compile it as a module, say M here and read
2888 + Documentation/modules.txt. If unsure, say `N'.
2890 +config IP_NF_MATCH_REALM
2891 + tristate 'realm match support'
2892 + depends on IP_NF_IPTABLES && NET_CLS_ROUTE
2894 + This option adds a `realm' match, which allows you to use the realm
2895 + key from the routing subsytem inside iptables.
2897 + This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
2900 + If you want to compile it as a module, say M here and read
2901 + Documentation/modules.txt. If unsure, say `N'.
2903 +config IP_NF_MATCH_SCTP
2904 + tristate 'SCTP protocol match support'
2905 + depends on IP_NF_IPTABLES
2907 +config IP_NF_MATCH_TIME
2908 + tristate 'TIME match support'
2909 + depends on IP_NF_IPTABLES
2911 + This option adds a `time' match, which allows you
2912 + to match based on the packet arrival time/date
2913 + (arrival time/date at the machine which netfilter is running on) or
2914 + departure time/date (for locally generated packets).
2916 + If you say Y here, try iptables -m time --help for more information.
2918 + If you want to compile it as a module, say M here and read
2919 + Documentation/modules.txt. If unsure, say `N'.
2921 +config IP_NF_MATCH_U32
2922 + tristate 'U32 match support'
2923 + depends on IP_NF_IPTABLES
2925 + U32 allows you to extract quantities of up to 4 bytes from a packet,
2926 + AND them with specified masks, shift them by specified amounts and
2927 + test whether the results are in any of a set of specified ranges.
2928 + The specification of what to extract is general enough to skip over
2929 + headers with lengths stored in the packet, as in IP or TCP header
2932 + Details and examples are in the kernel module source.
2934 +config IP_NF_CONNTRACK_MARK
2935 + bool 'Connection mark tracking support'
2937 + This option enables support for connection marks, used by the
2938 + `CONNMARK' target and `connmark' match. Similar to the mark value
2939 + of packets, but this mark value is kept in the conntrack session
2940 + instead of the individual packets.
2942 +config IP_NF_TARGET_CONNMARK
2943 + tristate 'CONNMARK target support'
2944 + depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
2946 + This option adds a `CONNMARK' target, which allows one to manipulate
2947 + the connection mark value. Similar to the MARK target, but
2948 + affects the connection mark value rather than the packet mark value.
2950 + If you want to compile it as a module, say M here and read
2951 + Documentation/modules.txt. The module will be called
2952 + ipt_CONNMARK.o. If unsure, say `N'.
2954 +config IP_NF_MATCH_CONNMARK
2955 + tristate ' Connection mark match support'
2956 + depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
2958 + This option adds a `connmark' match, which allows you to match the
2959 + connection mark value previously set for the session by `CONNMARK'.
2961 + If you want to compile it as a module, say M here and read
2962 + Documentation/modules.txt. The module will be called
2963 + ipt_connmark.o. If unsure, say `N'.
2965 +config IP_NF_TARGET_IPMARK
2966 + tristate 'IPMARK target support'
2967 + depends on IP_NF_MANGLE
2969 + This option adds a `IPMARK' target, which allows you to create rules
2970 + in the `mangle' table which alter the netfilter mark (nfmark) field
2971 + basing on the source or destination ip address of the packet.
2972 + This is very useful for very fast massive mangling and marking.
2974 + If you want to compile it as a module, say M here and read
2975 + <file:Documentation/modules.txt>. If unsure, say `N'.
2977 +config IP_NF_TARGET_ROUTE
2978 + tristate 'ROUTE target support'
2979 + depends on IP_NF_MANGLE
2981 + This option adds a `ROUTE' target, which enables you to setup unusual
2982 + routes. For example, the ROUTE lets you route a received packet through
2983 + an interface or towards a host, even if the regular destination of the
2984 + packet is the router itself. The ROUTE target is also able to change the
2985 + incoming interface of a packet.
2987 + The target can be or not a final target. It has to be used inside the
2990 + If you want to compile it as a module, say M here and read
2991 + Documentation/modules.txt. The module will be called ipt_ROUTE.o.
2992 + If unsure, say `N'.
2994 +config IP_NF_TARGET_TARPIT
2995 + tristate 'TARPIT target support'
2996 + depends on IP_NF_FILTER
2998 + Adds a TARPIT target to iptables, which captures and holds
2999 + incoming TCP connections using no local per-connection resources.
3000 + Connections are accepted, but immediately switched to the persist
3001 + state (0 byte window), in which the remote side stops sending data
3002 + and asks to continue every 60-240 seconds. Attempts to close the
3003 + connection are ignored, forcing the remote side to time out the
3004 + connection in 12-24 minutes.
3006 + This offers similar functionality to LaBrea
3007 + <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
3008 + hardware or IPs. Any TCP port that you would normally DROP or REJECT
3009 + can instead become a tarpit.
3011 +config IP_NF_TARGET_TCPLAG
3012 + tristate 'TCPLAG target support'
3013 + depends on IP_NF_IPTABLES
3015 + This option adds a `TCPLAG' target, intended for INPUT, OUTPUT and
3018 + This target has no effect on packets but will passively monitor TCP/IP
3019 + connections and send lag estimates to syslog. Lag estimates are
3020 + generated by considering the time delay between SEQ and matching ACK,
3021 + which does not map precisely to any particular network property.
3022 + We can say that a fast network will typically give smaller lag values
3023 + than a slow network.
3025 + Safest option is to choose `M' here and compile as a module,
3026 + the module will do nothing until activated using the `iptables' utility.
3028 +config IP_NF_TARGET_TRACE
3029 + tristate 'TRACE target support'
3030 + depends on IP_NF_RAW
3032 + The TRACE target allows packets to be traced as those
3033 + matches any subsequent rule in any table/rule. The matched
3034 + rule and the packet is logged with the prefix
3036 + TRACE: tablename/chainname/rulenum
3038 + If you want to compile it as a module, say M here and read
3039 + <file:Documentation/modules.txt>. If unsure, say `N'.
3041 +config IP_NF_TARGET_XOR
3042 + tristate 'XOR target support'
3043 + depends on IP_NF_MANGLE
3045 + This option adds a `XOR' target, which can encrypt TCP and
3046 + UDP traffic using a simple XOR encryption.
3048 + If you want to compile it as a module, say M here and read
3049 + Documentation/modules.txt. If unsure, say `N'.
3051 +config IP_NF_MATCH_ADDRTYPE
3052 + tristate 'address type match support'
3053 + depends on IP_NF_IPTABLES
3055 + This option allows you to match what routing thinks of an address,
3056 + eg. UNICAST, LOCAL, BROADCAST, ...
3058 + If you want to compile it as a module, say M here and read
3059 + Documentation/modules.txt. If unsure, say `N'.
3062 + tristate 'Eggdrop bot support'
3063 + depends on IP_NF_CONNTRACK
3065 + If you are running an eggdrop hub bot on this machine, then you
3066 + may want to enable this feature. This enables eggdrop bots to share
3067 + their user file to other eggdrop bots.
3069 + If you want to compile it as a module, say M here and read
3070 + Documentation/modules.txt. If unsure, say `N'.
3072 +config IP_NF_NAT_H323
3074 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3075 + default IP_NF_NAT if IP_NF_H323=y
3076 + default m if IP_NF_H323=m
3079 + tristate 'H.323 (netmeeting) support'
3080 + depends on IP_NF_CONNTRACK
3082 + H.323 is a standard signalling protocol used by teleconferencing
3083 + softwares like netmeeting. With the ip_conntrack_h323 and
3084 + the ip_nat_h323 modules you can support the protocol on a connection
3085 + tracking/NATing firewall.
3087 + If you want to compile it as a module, say 'M' here and read
3088 + Documentation/modules.txt. If unsure, say 'N'.
3090 +config IP_NF_NAT_MMS
3092 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3093 + default IP_NF_NAT if IP_NF_MMS=y
3094 + default m if IP_NF_MMS=m
3097 + tristate 'MMS protocol support'
3098 + depends on IP_NF_CONNTRACK
3100 + Tracking MMS (Microsoft Windows Media Services) connections
3101 + could be problematic if random ports are used to send the
3102 + streaming content. This option allows users to track streaming
3103 + connections over random UDP or TCP ports.
3105 + If you want to compile it as a module, say M here and read
3106 + <file:Documentation/modules.txt>. If unsure, say `Y'.
3108 +config IP_NF_MATCH_POLICY
3109 + tristate "IPsec policy match support"
3110 + depends on IP_NF_IPTABLES && XFRM
3112 + Policy matching allows you to match packets based on the
3113 + IPsec policy that was used during decapsulation/will
3114 + be used during encapsulation.
3116 + To compile it as a module, choose M here. If unsure, say N.
3118 +config IP_NF_NAT_QUAKE3
3120 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
3121 + default IP_NF_NAT if IP_NF_QUAKE3=y
3122 + default m if IP_NF_QUAKE3=m
3124 +config IP_NF_QUAKE3
3125 + tristate "Quake3 protocol support"
3126 + depends on IP_NF_CONNTRACK
3128 + Quake III Arena connection tracking helper. This module allows for a
3129 + stricter firewall rulebase if one only allows traffic to a master
3130 + server. Connections to Quake III server IP addresses and ports returned
3131 + by the master server will be tracked automatically.
3133 + If you want to compile it as a module, say M here and read
3134 + <file:Documentation/modules.txt>. If unsure, say `Y'.
3137 + tristate 'RSH protocol support'
3138 + depends on IP_NF_CONNTRACK
3140 + The RSH connection tracker is required if the dynamic
3141 + stderr "Server to Client" connection is to occur during a
3142 + normal RSH session. This typically operates as follows;
3144 + Client 0:1023 --> Server 514 (stream 1 - stdin/stdout)
3145 + Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
3147 + This connection tracker will identify new RSH sessions,
3148 + extract the outbound session details, and notify netfilter
3149 + of pending "related" sessions.
3151 + Warning: This module could be dangerous. It is not "best
3152 + practice" to use RSH, use SSH in all instances.
3153 + (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
3156 + If you want to compile it as a module, say M here and read
3157 + <file:Documentation/modules.txt>. If unsure, say `N'.
3159 +config IP_NF_NAT_RTSP
3161 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3162 + default IP_NF_NAT if IP_NF_RTSP=y
3163 + default m if IP_NF_RTSP=m
3166 + tristate ' RTSP protocol support'
3167 + depends on IP_NF_CONNTRACK
3169 + Support the RTSP protocol. This allows UDP transports to be setup
3170 + properly, including RTP and RDT.
3172 + If you want to compile it as a module, say 'M' here and read
3173 + Documentation/modules.txt. If unsure, say 'Y'.
3175 +config IP_NF_CT_PROTO_SCTP
3176 + tristate 'SCTP protocol connection tracking support'
3177 + depends on IP_NF_CONNTRACK
3179 +config IP_NF_MATCH_STRING
3180 + tristate 'String match support'
3181 + depends on IP_NF_IPTABLES
3183 + String matching alows you to match packets which contain a
3184 + specified string of characters.
3186 + If you want to compile it as a module, say M here and read
3187 + Documentation/modules.txt. If unsure, say `N'.
3189 +config IP_NF_NAT_TALK
3191 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3192 + default IP_NF_NAT if IP_NF_TALK=y
3193 + default m if IP_NF_TALK=m
3196 + tristate 'talk protocol support'
3197 + depends on IP_NF_CONNTRACK
3199 + The talk protocols (both otalk/talk - or talk/ntalk, to confuse
3200 + you by the different namings about which is old or which is new :-)
3201 + use an additional channel to setup the talk session and a separated
3202 + data channel for the actual conversation (like in FTP). Both the
3203 + initiating and the setup channels are over UDP, while the data channel
3204 + is over TCP, on a random port. The conntrack part of this extension
3205 + will enable you to let in/out talk sessions easily by matching these
3206 + connections as RELATED by the state match, while the NAT part helps
3207 + you to let talk sessions trough a NAT machine.
3209 + If you want to compile it as a module, say 'M' here and read
3210 + Documentation/modules.txt. If unsure, say 'N'.
3214 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/Makefile linux-2.6.6/net/ipv4/netfilter/Makefile
3215 --- linux-2.6.6.org/net/ipv4/netfilter/Makefile 2004-05-10 04:32:26.000000000 +0200
3216 +++ linux-2.6.6/net/ipv4/netfilter/Makefile 2004-05-18 12:40:50.000000000 +0200
3218 # connection tracking
3219 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
3221 +# talk protocol support
3222 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
3223 +ifdef CONFIG_IP_NF_TALK
3224 + export-objs += ip_conntrack_talk.o
3226 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
3229 +# SCTP protocol connection tracking
3230 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
3233 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
3234 +ifdef CONFIG_IP_NF_H323
3235 + export-objs += ip_conntrack_h323.o
3237 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
3240 # connection tracking helpers
3242 +# rtsp protocol support
3243 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
3244 +ifdef CONFIG_IP_NF_NAT_RTSP
3245 + export-objs += ip_conntrack_rtsp.o
3247 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
3249 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
3250 +ifdef CONFIG_IP_NF_NAT_QUAKE3
3251 + export-objs += ip_conntrack_quake3.o
3253 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
3254 +ifdef CONFIG_IP_NF_MMS
3255 + export-objs += ip_conntrack_mms.o
3257 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
3258 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
3259 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
3260 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
3262 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
3264 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
3268 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
3269 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
3270 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
3271 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
3272 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
3275 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
3278 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
3279 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
3280 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
3281 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
3282 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
3283 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
3284 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
3285 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
3286 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
3288 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
3289 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
3291 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
3293 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
3294 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
3296 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
3299 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
3301 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
3303 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
3306 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
3308 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
3311 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
3313 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
3315 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
3316 @@ -60,28 +125,48 @@
3318 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
3320 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
3323 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
3324 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
3325 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
3326 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
3327 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
3328 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
3329 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
3330 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
3331 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
3332 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
3334 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
3335 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
3338 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
3339 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
3340 obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
3341 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
3342 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
3343 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
3344 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
3345 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
3346 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
3347 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
3348 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
3349 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
3350 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
3351 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
3352 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
3353 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
3354 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
3355 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
3356 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
3357 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
3358 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
3359 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
3360 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
3361 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
3362 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
3364 # generic ARP tables
3365 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_core.c
3366 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-05-10 04:31:55.000000000 +0200
3367 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_core.c 2004-05-18 12:38:02.000000000 +0200
3369 ip_conntrack_destroyed(ct);
3371 WRITE_LOCK(&ip_conntrack_lock);
3372 - /* Delete us from our own list to prevent corruption later */
3373 - list_del(&ct->sibling_list);
3374 + /* Make sure don't leave any orphaned expectations lying around */
3375 + if (ct->expecting)
3376 + remove_expectations(ct, 1);
3378 /* Delete our master expectation */
3380 @@ -692,25 +693,22 @@
3381 struct ip_conntrack_expect *, tuple);
3382 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3384 - /* If master is not in hash table yet (ie. packet hasn't left
3385 - this machine yet), how can other end know about expected?
3386 - Hence these are not the droids you are looking for (if
3387 - master ct never got confirmed, we'd hold a reference to it
3388 - and weird things would happen to future packets). */
3389 - if (expected && !is_confirmed(expected->expectant))
3392 - /* Look up the conntrack helper for master connections only */
3394 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
3396 + /* If master is not in hash table yet (ie. packet hasn't left
3397 + this machine yet), how can other end know about expected?
3398 + Hence these are not the droids you are looking for (if
3399 + master ct never got confirmed, we'd hold a reference to it
3400 + and weird things would happen to future packets). */
3401 + if (!is_confirmed(expected->expectant)) {
3402 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3406 - /* If the expectation is dying, then this is a loser. */
3408 - && expected->expectant->helper->timeout
3409 - && ! del_timer(&expected->timeout))
3411 + /* Expectation is dying... */
3412 + if (expected->expectant->helper->timeout
3413 + && !del_timer(&expected->timeout))
3417 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3418 conntrack, expected);
3419 /* Welcome, Mr. Bond. We've been expecting you... */
3420 @@ -718,16 +716,28 @@
3421 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3422 conntrack->master = expected;
3423 expected->sibling = conntrack;
3424 +#if CONFIG_IP_NF_CONNTRACK_MARK
3425 + conntrack->mark = expected->expectant->mark;
3427 LIST_DELETE(&ip_conntrack_expect_list, expected);
3428 expected->expectant->expecting--;
3429 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3431 - atomic_inc(&ip_conntrack_count);
3433 + /* this is a braindead... --pablo */
3434 + atomic_inc(&ip_conntrack_count);
3435 + WRITE_UNLOCK(&ip_conntrack_lock);
3437 + if (expected->expectfn)
3438 + expected->expectfn(conntrack);
3442 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3444 +end: atomic_inc(&ip_conntrack_count);
3445 WRITE_UNLOCK(&ip_conntrack_lock);
3447 - if (expected && expected->expectfn)
3448 - expected->expectfn(conntrack);
3449 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3450 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3453 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3455 atomic_set(&new->use, 1);
3457 /* add to expected list for this connection */
3458 - list_add(&new->expected_list, &related_to->sibling_list);
3459 + list_add_tail(&new->expected_list, &related_to->sibling_list);
3460 /* add to global list of expectations */
3462 list_prepend(&ip_conntrack_expect_list, &new->list);
3463 /* add and start timer if required */
3464 if (related_to->helper->timeout) {
3465 @@ -1003,7 +1012,6 @@
3467 } else if (related_to->helper->max_expected &&
3468 related_to->expecting >= related_to->helper->max_expected) {
3469 - struct list_head *cur_item;
3471 if (!(related_to->helper->flags &
3472 IP_CT_HELPER_F_REUSE_EXPECT)) {
3473 @@ -1029,21 +1037,14 @@
3474 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3476 /* choose the the oldest expectation to evict */
3477 - list_for_each(cur_item, &related_to->sibling_list) {
3478 - struct ip_conntrack_expect *cur;
3480 - cur = list_entry(cur_item,
3481 - struct ip_conntrack_expect,
3483 - if (cur->sibling == NULL) {
3485 + list_for_each_entry(old, &related_to->sibling_list,
3487 + if (old->sibling == NULL)
3492 - /* (!old) cannot happen, since related_to->expecting is the
3493 - * number of unconfirmed expects */
3494 - IP_NF_ASSERT(old);
3495 + /* We cannot fail since related_to->expecting is the number
3496 + * of unconfirmed expectations */
3497 + IP_NF_ASSERT(old && old->sibling == NULL);
3499 /* newnat14 does not reuse the real allocated memory
3500 * structures but rather unexpects the old and
3501 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_egg.c
3502 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3503 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_egg.c 2004-05-18 12:39:11.000000000 +0200
3505 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3506 + * based on ip_conntrack_irc.c
3508 + * This module only supports the share userfile-send command,
3509 + * used by eggdrops to share it's userfile.
3511 + * There are no support for NAT at the moment.
3513 + * This program is free software; you can redistribute it and/or
3514 + * modify it under the terms of the GNU General Public License
3515 + * as published by the Free Software Foundation; either version
3516 + * 2 of the License, or (at your option) any later version.
3518 + * Module load syntax:
3520 + * please give the ports of all Eggdrops You have running
3521 + * on your system, the default port is 3333.
3523 + * 2001-04-19: Security update. IP addresses are now compared
3524 + * to prevent unauthorized "related" access.
3526 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3527 + * Port to netfilter 'newnat' API.
3530 +#include <linux/module.h>
3531 +#include <linux/netfilter.h>
3532 +#include <linux/ip.h>
3533 +#include <net/checksum.h>
3534 +#include <net/tcp.h>
3536 +#include <linux/netfilter_ipv4/lockhelp.h>
3537 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3539 +#define MAX_PORTS 8
3540 +static int ports[MAX_PORTS];
3541 +static int ports_c = 0;
3542 +static unsigned int egg_timeout = 300;
3544 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3545 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3546 +MODULE_LICENSE("GPL");
3548 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3549 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3552 +DECLARE_LOCK(ip_egg_lock);
3553 +struct module *ip_conntrack_egg = THIS_MODULE;
3556 +#define DEBUGP printk
3558 +#define DEBUGP(format, args...)
3561 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3562 +/* tries to get the ip_addr and port out of a eggdrop command
3563 + return value: -1 on failure, 0 on success
3564 + data pointer to first byte of DCC command data
3565 + data_end pointer to last byte of dcc command data
3566 + ip returns parsed ip of dcc command
3567 + port returns parsed port of dcc command */
3569 + if (data > data_end)
3572 + *ip = simple_strtoul(data, &data, 10);
3574 + /* skip blanks between ip and port */
3575 + while (*data == ' ' && data < data_end)
3578 + *port = simple_strtoul(data, &data, 10);
3583 +static int help(const struct iphdr *iph, size_t len,
3584 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3586 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3587 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3588 + char *data = (char *) tcph + tcph->doff * 4;
3590 + u_int32_t tcplen = len - iph->ihl * 4;
3591 + u_int32_t datalen = tcplen - tcph->doff * 4;
3592 + int dir = CTINFO2DIR(ctinfo);
3593 + int bytes_scanned = 0;
3594 + struct ip_conntrack_expect exp;
3597 + u_int16_t egg_port;
3599 + DEBUGP("entered\n");
3601 + /* If packet is coming from IRC server */
3602 + if (dir != IP_CT_DIR_REPLY)
3605 + /* Until there's been traffic both ways, don't look in packets. */
3606 + if (ctinfo != IP_CT_ESTABLISHED
3607 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3608 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
3612 + /* Not whole TCP header? */
3613 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3614 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3618 + /* Checksum invalid? Ignore. */
3619 + /* FIXME: Source route IP option packets --RR */
3620 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3621 + csum_partial((char *) tcph, tcplen, 0))) {
3622 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3623 + tcph, tcplen, NIPQUAD(iph->saddr),
3624 + NIPQUAD(iph->daddr));
3628 + data_limit = (char *) data + datalen;
3629 + while (datalen > 5 && bytes_scanned < 128) {
3630 + if (memcmp(data, "s us ", 5)) {
3639 + DEBUGP("Userfile-share found in connection "
3640 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3641 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3643 + if (parse_command((char *) data, data_limit, &egg_ip,
3645 + DEBUGP("no data in userfile-share pkt\n");
3649 + memset(&exp, 0, sizeof(exp));
3651 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3652 + if (net_ratelimit())
3653 + printk("Forged Eggdrop command from "
3654 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3655 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3656 + HIPQUAD(egg_ip), egg_port);
3660 + exp.tuple.src.ip = iph->daddr;
3661 + exp.tuple.src.u.tcp.port = 0;
3662 + exp.tuple.dst.ip = htonl(egg_ip);
3663 + exp.tuple.dst.u.tcp.port = htons(egg_port);
3664 + exp.tuple.dst.protonum = IPPROTO_TCP;
3666 + exp.mask.dst.u.tcp.port = 0xffff;
3667 + exp.mask.dst.protonum = 0xffff;
3669 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3670 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3671 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3673 + ip_conntrack_expect_related(ct, &exp);
3679 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3680 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3682 +static void deregister_helpers(void) {
3685 + for (i = 0; i < ports_c; i++) {
3686 + DEBUGP("unregistering helper for port %d\n", ports[i]);
3687 + ip_conntrack_helper_unregister(&egg_helpers[i]);
3691 +static int __init init(void)
3696 + /* If no port given, default to standard eggdrop port */
3697 + if (ports[0] == 0)
3700 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3701 + memset(&egg_helpers[i], 0,
3702 + sizeof(struct ip_conntrack_helper));
3703 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3704 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3705 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3706 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
3707 + egg_helpers[i].max_expected = 1;
3708 + egg_helpers[i].timeout = egg_timeout;
3709 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3710 + egg_helpers[i].me = THIS_MODULE;
3711 + egg_helpers[i].help = help;
3713 + tmpname = &egg_names[i][0];
3714 + if (ports[i] == 3333)
3715 + sprintf(tmpname, "eggdrop");
3717 + sprintf(tmpname, "eggdrop-%d", ports[i]);
3718 + egg_helpers[i].name = tmpname;
3720 + DEBUGP("port #%d: %d\n", i, ports[i]);
3722 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
3725 + printk("ip_conntrack_egg: ERROR registering helper "
3726 + "for port %d\n", ports[i]);
3727 + deregister_helpers();
3735 +static void __exit fini(void)
3737 + deregister_helpers();
3742 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_h323.c
3743 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3744 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_h323.c 2004-05-18 12:39:18.000000000 +0200
3747 + * H.323 'brute force' extension for H.323 connection tracking.
3748 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3750 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3751 + * (http://www.coritel.it/projects/sofia/nat/)
3752 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3753 + * the unregistered helpers to the conntrack entries.
3757 +#include <linux/module.h>
3758 +#include <linux/netfilter.h>
3759 +#include <linux/ip.h>
3760 +#include <net/checksum.h>
3761 +#include <net/tcp.h>
3763 +#include <linux/netfilter_ipv4/lockhelp.h>
3764 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3765 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3766 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3767 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3768 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3770 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3771 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3772 +MODULE_LICENSE("GPL");
3774 +DECLARE_LOCK(ip_h323_lock);
3775 +struct module *ip_conntrack_h323 = THIS_MODULE;
3778 +#define DEBUGP printk
3780 +#define DEBUGP(format, args...)
3783 +/* FIXME: This should be in userspace. Later. */
3784 +static int h245_help(const struct iphdr *iph, size_t len,
3785 + struct ip_conntrack *ct,
3786 + enum ip_conntrack_info ctinfo)
3788 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3789 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3790 + unsigned char *data_limit;
3791 + u_int32_t tcplen = len - iph->ihl * 4;
3792 + u_int32_t datalen = tcplen - tcph->doff * 4;
3793 + int dir = CTINFO2DIR(ctinfo);
3794 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3795 + struct ip_conntrack_expect expect, *exp = &expect;
3796 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3797 + u_int16_t data_port;
3798 + u_int32_t data_ip;
3801 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3802 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3803 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3805 + /* Can't track connections formed before we registered */
3809 + /* Until there's been traffic both ways, don't look in packets. */
3810 + if (ctinfo != IP_CT_ESTABLISHED
3811 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3812 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3816 + /* Not whole TCP header or too short packet? */
3817 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3818 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3822 + /* Checksum invalid? Ignore. */
3823 + /* FIXME: Source route IP option packets --RR */
3824 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3825 + csum_partial((char *)tcph, tcplen, 0))) {
3826 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3827 + tcph, tcplen, NIPQUAD(iph->saddr),
3828 + NIPQUAD(iph->daddr));
3832 + data_limit = (unsigned char *) data + datalen;
3835 + for (i = 0; data < (data_limit - 5); data++, i++) {
3836 + data_ip = *((u_int32_t *)data);
3837 + if (data_ip == iph->saddr) {
3838 + data_port = *((u_int16_t *)(data + 4));
3839 + memset(&expect, 0, sizeof(expect));
3840 + /* update the H.225 info */
3841 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3842 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3843 + NIPQUAD(iph->saddr), ntohs(data_port));
3844 + LOCK_BH(&ip_h323_lock);
3845 + info->is_h225 = H225_PORT + 1;
3846 + exp_info->port = data_port;
3847 + exp_info->dir = dir;
3848 + exp_info->offset = i;
3850 + exp->seq = ntohl(tcph->seq) + i;
3852 + exp->tuple = ((struct ip_conntrack_tuple)
3853 + { { ct->tuplehash[!dir].tuple.src.ip,
3856 + { .tcp = { data_port } },
3858 + exp->mask = ((struct ip_conntrack_tuple)
3859 + { { 0xFFFFFFFF, { 0 } },
3860 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3862 + exp->expectfn = NULL;
3864 + /* Ignore failure; should only happen with NAT */
3865 + ip_conntrack_expect_related(ct, exp);
3867 + UNLOCK_BH(&ip_h323_lock);
3875 +/* H.245 helper is not registered! */
3876 +static struct ip_conntrack_helper h245 =
3878 + "H.245", /* name */
3879 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3880 + NULL, /* module */
3881 + 8, /* max_ expected */
3882 + 240, /* timeout */
3883 + { { 0, { 0 } }, /* tuple */
3884 + { 0, { 0 }, IPPROTO_TCP } },
3885 + { { 0, { 0xFFFF } }, /* mask */
3886 + { 0, { 0 }, 0xFFFF } },
3887 + h245_help /* helper */
3890 +static int h225_expect(struct ip_conntrack *ct)
3892 + WRITE_LOCK(&ip_conntrack_lock);
3893 + ct->helper = &h245;
3894 + DEBUGP("h225_expect: helper for %p added\n", ct);
3895 + WRITE_UNLOCK(&ip_conntrack_lock);
3897 + return NF_ACCEPT; /* unused */
3900 +/* FIXME: This should be in userspace. Later. */
3901 +static int h225_help(const struct iphdr *iph, size_t len,
3902 + struct ip_conntrack *ct,
3903 + enum ip_conntrack_info ctinfo)
3905 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3906 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3907 + unsigned char *data_limit;
3908 + u_int32_t tcplen = len - iph->ihl * 4;
3909 + u_int32_t datalen = tcplen - tcph->doff * 4;
3910 + int dir = CTINFO2DIR(ctinfo);
3911 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3912 + struct ip_conntrack_expect expect, *exp = &expect;
3913 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3914 + u_int16_t data_port;
3915 + u_int32_t data_ip;
3918 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3919 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3920 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3922 + /* Can't track connections formed before we registered */
3926 + /* Until there's been traffic both ways, don't look in packets. */
3927 + if (ctinfo != IP_CT_ESTABLISHED
3928 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3929 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3933 + /* Not whole TCP header or too short packet? */
3934 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3935 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3939 + /* Checksum invalid? Ignore. */
3940 + /* FIXME: Source route IP option packets --RR */
3941 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3942 + csum_partial((char *)tcph, tcplen, 0))) {
3943 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3944 + tcph, tcplen, NIPQUAD(iph->saddr),
3945 + NIPQUAD(iph->daddr));
3949 + data_limit = (unsigned char *) data + datalen;
3952 + for (i = 0; data < (data_limit - 5); data++, i++) {
3953 + data_ip = *((u_int32_t *)data);
3954 + if (data_ip == iph->saddr) {
3955 + data_port = *((u_int16_t *)(data + 4));
3956 + if (data_port == tcph->source) {
3957 + /* Signal address */
3958 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3959 + NIPQUAD(iph->saddr));
3960 + /* Update the H.225 info so that NAT can mangle the address/port
3961 + even when we have no expected connection! */
3962 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3963 + LOCK_BH(&ip_h323_lock);
3965 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3966 + info->offset[IP_CT_DIR_ORIGINAL] = i;
3967 + UNLOCK_BH(&ip_h323_lock);
3970 + memset(&expect, 0, sizeof(expect));
3972 + /* update the H.225 info */
3973 + LOCK_BH(&ip_h323_lock);
3974 + info->is_h225 = H225_PORT;
3975 + exp_info->port = data_port;
3976 + exp_info->dir = dir;
3977 + exp_info->offset = i;
3979 + exp->seq = ntohl(tcph->seq) + i;
3981 + exp->tuple = ((struct ip_conntrack_tuple)
3982 + { { ct->tuplehash[!dir].tuple.src.ip,
3985 + { .tcp = { data_port } },
3987 + exp->mask = ((struct ip_conntrack_tuple)
3988 + { { 0xFFFFFFFF, { 0 } },
3989 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3991 + exp->expectfn = h225_expect;
3993 + /* Ignore failure */
3994 + ip_conntrack_expect_related(ct, exp);
3996 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3997 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3998 + NIPQUAD(iph->saddr), ntohs(data_port));
4000 + UNLOCK_BH(&ip_h323_lock);
4002 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4003 + } else if (data_ip == iph->daddr) {
4004 + data_port = *((u_int16_t *)(data + 4));
4005 + if (data_port == tcph->dest) {
4006 + /* Signal address */
4007 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
4008 + NIPQUAD(iph->daddr));
4009 + /* Update the H.225 info so that NAT can mangle the address/port
4010 + even when we have no expected connection! */
4011 + LOCK_BH(&ip_h323_lock);
4013 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
4014 + info->offset[IP_CT_DIR_REPLY] = i;
4015 + UNLOCK_BH(&ip_h323_lock);
4025 +static struct ip_conntrack_helper h225 =
4027 + "H.225", /* name */
4028 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
4029 + THIS_MODULE, /* module */
4030 + 2, /* max_expected */
4031 + 240, /* timeout */
4032 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
4033 + { 0, { 0 }, IPPROTO_TCP } },
4034 + { { 0, { 0xFFFF } }, /* mask */
4035 + { 0, { 0 }, 0xFFFF } },
4036 + h225_help /* helper */
4039 +static int __init init(void)
4041 + return ip_conntrack_helper_register(&h225);
4044 +static void __exit fini(void)
4046 + /* Unregister H.225 helper */
4047 + ip_conntrack_helper_unregister(&h225);
4050 +EXPORT_SYMBOL(ip_h323_lock);
4054 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_mms.c
4055 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
4056 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_mms.c 2004-05-18 12:39:36.000000000 +0200
4058 +/* MMS extension for IP connection tracking
4059 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4060 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
4062 + * ip_conntrack_mms.c v0.3 2002-09-22
4064 + * This program is free software; you can redistribute it and/or
4065 + * modify it under the terms of the GNU General Public License
4066 + * as published by the Free Software Foundation; either version
4067 + * 2 of the License, or (at your option) any later version.
4069 + * Module load syntax:
4070 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
4072 + * Please give the ports of all MMS servers You wish to connect to.
4073 + * If you don't specify ports, the default will be TCP port 1755.
4075 + * More info on MMS protocol, firewalls and NAT:
4076 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
4077 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
4079 + * The SDP project people are reverse-engineering MMS:
4080 + * http://get.to/sdp
4083 +#include <linux/config.h>
4084 +#include <linux/module.h>
4085 +#include <linux/netfilter.h>
4086 +#include <linux/ip.h>
4087 +#include <linux/ctype.h>
4088 +#include <net/checksum.h>
4089 +#include <net/tcp.h>
4091 +#include <linux/netfilter_ipv4/lockhelp.h>
4092 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4093 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
4095 +DECLARE_LOCK(ip_mms_lock);
4096 +struct module *ip_conntrack_mms = THIS_MODULE;
4098 +#define MAX_PORTS 8
4099 +static int ports[MAX_PORTS];
4100 +static int ports_c;
4102 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4106 +#define DEBUGP printk
4108 +#define DEBUGP(format, args...)
4111 +EXPORT_SYMBOL(ip_mms_lock);
4113 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4114 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
4115 +MODULE_LICENSE("GPL");
4117 +/* #define isdigit(c) (c >= '0' && c <= '9') */
4119 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
4120 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
4123 + for (i = 0; i < unicode_size; ++i) {
4124 + string[i] = (char)(unicode[i]);
4126 + string[unicode_size] = 0x00;
4129 +__inline static int atoi(char *s)
4132 + while (isdigit(*s)) {
4133 + i = i*10 + *(s++) - '0';
4138 +/* convert ip address string like "192.168.0.10" to unsigned int */
4139 +__inline static u_int32_t asciiiptoi(char *s)
4141 + unsigned int i, j, k;
4143 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
4145 + for(j=0; (*(++s) != '.') && (j<3); ++j)
4152 +int parse_mms(const char *data,
4153 + const unsigned int datalen,
4154 + u_int32_t *mms_ip,
4155 + u_int16_t *mms_proto,
4156 + u_int16_t *mms_port,
4157 + char **mms_string_b,
4158 + char **mms_string_e,
4159 + char **mms_padding_e)
4161 + int unicode_size, i;
4162 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
4163 + char getlengthstring[28];
4165 + for(unicode_size=0;
4166 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
4168 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
4169 + return -1; /* out of bounds - incomplete packet */
4171 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
4172 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
4174 + /* IP address ? */
4175 + *mms_ip = asciiiptoi(tempstring+2);
4177 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
4180 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
4181 + *mms_proto = IPPROTO_TCP;
4182 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
4183 + *mms_proto = IPPROTO_UDP;
4186 + *mms_port = atoi(tempstring+7+i);
4188 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
4189 + unicode string, one to the end of the string, and one to the end
4190 + of the packet, since we must keep track of the number of bytes
4191 + between end of the unicode string and the end of packet (padding) */
4192 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
4193 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
4194 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
4199 +/* FIXME: This should be in userspace. Later. */
4200 +static int help(const struct iphdr *iph, size_t len,
4201 + struct ip_conntrack *ct,
4202 + enum ip_conntrack_info ctinfo)
4204 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
4205 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4206 + const char *data = (const char *)tcph + tcph->doff * 4;
4207 + unsigned int tcplen = len - iph->ihl * 4;
4208 + unsigned int datalen = tcplen - tcph->doff * 4;
4209 + int dir = CTINFO2DIR(ctinfo);
4210 + struct ip_conntrack_expect expect, *exp = &expect;
4211 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
4214 + u_int16_t mms_proto;
4215 + char mms_proto_string[8];
4216 + u_int16_t mms_port;
4217 + char *mms_string_b, *mms_string_e, *mms_padding_e;
4219 + /* Until there's been traffic both ways, don't look in packets. */
4220 + if (ctinfo != IP_CT_ESTABLISHED
4221 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4222 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
4226 + /* Not whole TCP header? */
4227 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
4228 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
4232 + /* Checksum invalid? Ignore. */
4233 + /* FIXME: Source route IP option packets --RR */
4234 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4235 + csum_partial((char *)tcph, tcplen, 0))) {
4236 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4237 + tcph, tcplen, NIPQUAD(iph->saddr),
4238 + NIPQUAD(iph->daddr));
4242 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
4243 + /* FIXME: There is an issue with only looking at this packet: before this packet,
4244 + the client has already sent a packet to the server with the server's hostname
4245 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
4246 + server will break the connection if this doesn't correspond to its own host
4247 + header. The client can also connect to an IP address; if it's the server's IP
4248 + address, it will not break the connection. When doing DNAT on a connection
4249 + where the client uses a server's IP address, the nat module should detect
4250 + this and change this string accordingly to the DNATed address. This should
4251 + probably be done by checking for an IP address, then storing it as a member
4252 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
4254 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
4255 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
4256 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
4257 + (u8)*(data+36), (u8)*(data+37),
4258 + (u8)*(data+38), (u8)*(data+39),
4260 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
4261 + &mms_string_b, &mms_string_e, &mms_padding_e))
4262 + if(net_ratelimit())
4263 + /* FIXME: more verbose debugging ? */
4264 + printk(KERN_WARNING
4265 + "ip_conntrack_mms: Unable to parse data payload\n");
4267 + memset(&expect, 0, sizeof(expect));
4269 + sprintf(mms_proto_string, "(%u)", mms_proto);
4270 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
4271 + mms_proto == IPPROTO_TCP ? "TCP"
4272 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
4273 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4277 + /* it's possible that the client will just ask the server to tunnel
4278 + the stream over the same TCP session (from port 1755): there's
4279 + shouldn't be a need to add an expectation in that case, but it
4280 + makes NAT packet mangling so much easier */
4281 + LOCK_BH(&ip_mms_lock);
4283 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
4285 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
4286 + exp_mms_info->len = (mms_string_e - mms_string_b);
4287 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
4288 + exp_mms_info->port = mms_port;
4290 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
4291 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
4293 + exp->tuple = ((struct ip_conntrack_tuple)
4294 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4296 + { .tcp = { (__u16) ntohs(mms_port) } },
4299 + exp->mask = ((struct ip_conntrack_tuple)
4300 + { { 0xFFFFFFFF, { 0 } },
4301 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4302 + exp->expectfn = NULL;
4303 + ip_conntrack_expect_related(ct, &expect);
4304 + UNLOCK_BH(&ip_mms_lock);
4310 +static struct ip_conntrack_helper mms[MAX_PORTS];
4311 +static char mms_names[MAX_PORTS][10];
4313 +/* Not __exit: called from init() */
4314 +static void fini(void)
4317 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4318 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
4320 + ip_conntrack_helper_unregister(&mms[i]);
4324 +static int __init init(void)
4329 + if (ports[0] == 0)
4330 + ports[0] = MMS_PORT;
4332 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4333 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
4334 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
4335 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
4336 + mms[i].mask.src.u.tcp.port = 0xFFFF;
4337 + mms[i].mask.dst.protonum = 0xFFFF;
4338 + mms[i].max_expected = 1;
4339 + mms[i].timeout = 0;
4340 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4341 + mms[i].me = THIS_MODULE;
4342 + mms[i].help = help;
4344 + tmpname = &mms_names[i][0];
4345 + if (ports[i] == MMS_PORT)
4346 + sprintf(tmpname, "mms");
4348 + sprintf(tmpname, "mms-%d", ports[i]);
4349 + mms[i].name = tmpname;
4351 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
4353 + ret = ip_conntrack_helper_register(&mms[i]);
4366 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
4367 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
4368 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-05-18 12:40:23.000000000 +0200
4371 + * Connection tracking protocol helper module for SCTP.
4373 + * SCTP is defined in RFC 2960. References to various sections in this code
4374 + * are to this RFC.
4376 + * This program is free software; you can redistribute it and/or modify
4377 + * it under the terms of the GNU General Public License version 2 as
4378 + * published by the Free Software Foundation.
4381 +#include <linux/types.h>
4382 +#include <linux/sched.h>
4383 +#include <linux/timer.h>
4384 +#include <linux/netfilter.h>
4385 +#include <linux/module.h>
4386 +#include <linux/in.h>
4387 +#include <linux/ip.h>
4388 +#include <linux/sctp.h>
4389 +#include <linux/string.h>
4391 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4392 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4393 +#include <linux/netfilter_ipv4/lockhelp.h>
4396 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4398 +#define DEBUGP(format, args...)
4401 +/* Protects conntrack->proto.sctp */
4402 +static DECLARE_RWLOCK(sctp_lock);
4404 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4405 + closely. They're more complex. --RR
4407 + And so for me for SCTP :D -Kiran */
4409 +static const char *sctp_conntrack_names[] = {
4417 + "SHUTDOWN_ACK_SENT",
4421 +#define MINS * 60 SECS
4422 +#define HOURS * 60 MINS
4423 +#define DAYS * 24 HOURS
4425 +unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
4426 +unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
4427 +unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
4428 +unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
4429 +unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
4430 +unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
4431 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
4433 +static unsigned long * sctp_timeouts[]
4434 += { 0, /* SCTP_CONNTRACK_NONE */
4435 + &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
4436 + &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
4437 + &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
4438 + &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
4439 + &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4440 + &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4441 + &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4444 +#define sNO SCTP_CONNTRACK_NONE
4445 +#define sCL SCTP_CONNTRACK_CLOSED
4446 +#define sCW SCTP_CONNTRACK_COOKIE_WAIT
4447 +#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
4448 +#define sES SCTP_CONNTRACK_ESTABLISHED
4449 +#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4450 +#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4451 +#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4452 +#define sIV SCTP_CONNTRACK_MAX
4455 + These are the descriptions of the states:
4457 +NOTE: These state names are tantalizingly similar to the states of an
4458 +SCTP endpoint. But the interpretation of the states is a little different,
4459 +considering that these are the states of the connection and not of an end
4460 +point. Please note the subtleties. -Kiran
4462 +NONE - Nothing so far.
4463 +COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
4464 + an INIT_ACK chunk in the reply direction.
4465 +COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
4466 +ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
4467 +SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
4468 +SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
4469 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4470 + to that of the SHUTDOWN chunk.
4471 +CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
4472 + the SHUTDOWN chunk. Connection is closed.
4476 + - I have assumed that the first INIT is in the original direction.
4477 + This messes things when an INIT comes in the reply direction in CLOSED
4479 + - Check the error type in the reply dir before transitioning from
4480 +cookie echoed to closed.
4481 + - Sec 5.2.4 of RFC 2960
4482 + - Multi Homing support.
4485 +/* SCTP conntrack state transitions */
4486 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4489 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4490 +/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4491 +/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4492 +/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4493 +/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4494 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4495 +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4496 +/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4497 +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4498 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4502 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4503 +/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4504 +/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4505 +/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4506 +/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4507 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4508 +/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4509 +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4510 +/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4511 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4515 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4516 + unsigned int dataoff,
4517 + struct ip_conntrack_tuple *tuple)
4519 + sctp_sctphdr_t hdr;
4521 + DEBUGP(__FUNCTION__);
4524 + /* Actually only need first 8 bytes. */
4525 + if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4528 + tuple->src.u.sctp.port = hdr.source;
4529 + tuple->dst.u.sctp.port = hdr.dest;
4534 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4535 + const struct ip_conntrack_tuple *orig)
4537 + DEBUGP(__FUNCTION__);
4540 + tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4541 + tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4545 +/* Print out the per-protocol part of the tuple. */
4546 +static unsigned int sctp_print_tuple(char *buffer,
4547 + const struct ip_conntrack_tuple *tuple)
4549 + DEBUGP(__FUNCTION__);
4552 + return sprintf(buffer, "sport=%hu dport=%hu ",
4553 + ntohs(tuple->src.u.sctp.port),
4554 + ntohs(tuple->dst.u.sctp.port));
4557 +/* Print out the private part of the conntrack. */
4558 +static unsigned int sctp_print_conntrack(char *buffer,
4559 + const struct ip_conntrack *conntrack)
4561 + enum sctp_conntrack state;
4563 + DEBUGP(__FUNCTION__);
4566 + READ_LOCK(&sctp_lock);
4567 + state = conntrack->proto.sctp.state;
4568 + READ_UNLOCK(&sctp_lock);
4570 + return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4573 +#define for_each_sctp_chunk(skb, sch, offset, count) \
4574 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
4575 + offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
4576 + offset += (htons(sch.length) + 3) & ~3, count++)
4578 +/* Some validity checks to make sure the chunks are fine */
4579 +static int do_basic_checks(struct ip_conntrack *conntrack,
4580 + const struct sk_buff *skb,
4583 + u_int32_t offset, count;
4584 + sctp_chunkhdr_t sch;
4587 + DEBUGP(__FUNCTION__);
4592 + for_each_sctp_chunk (skb, sch, offset, count) {
4593 + DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
4595 + if (sch.type == SCTP_CID_INIT
4596 + || sch.type == SCTP_CID_INIT_ACK
4597 + || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4601 + /* Cookie Ack/Echo chunks not the first OR
4602 + Init / Init Ack / Shutdown compl chunks not the only chunks */
4603 + if ((sch.type == SCTP_CID_COOKIE_ACK
4604 + || sch.type == SCTP_CID_COOKIE_ECHO
4607 + DEBUGP("Basic checks failed\n");
4612 + set_bit (sch.type, (void *)map);
4616 + DEBUGP("Basic checks passed\n");
4620 +static int new_state(enum ip_conntrack_dir dir,
4621 + enum sctp_conntrack cur_state,
4626 + DEBUGP(__FUNCTION__);
4629 + DEBUGP("Chunk type: %d\n", chunk_type);
4631 + switch (chunk_type) {
4632 + case SCTP_CID_INIT:
4633 + DEBUGP("SCTP_CID_INIT\n");
4635 + case SCTP_CID_INIT_ACK:
4636 + DEBUGP("SCTP_CID_INIT_ACK\n");
4638 + case SCTP_CID_ABORT:
4639 + DEBUGP("SCTP_CID_ABORT\n");
4641 + case SCTP_CID_SHUTDOWN:
4642 + DEBUGP("SCTP_CID_SHUTDOWN\n");
4644 + case SCTP_CID_SHUTDOWN_ACK:
4645 + DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4647 + case SCTP_CID_ERROR:
4648 + DEBUGP("SCTP_CID_ERROR\n");
4650 + case SCTP_CID_COOKIE_ECHO:
4651 + DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4653 + case SCTP_CID_COOKIE_ACK:
4654 + DEBUGP("SCTP_CID_COOKIE_ACK\n");
4656 + case SCTP_CID_SHUTDOWN_COMPLETE:
4657 + DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4660 + /* Other chunks like DATA, SACK, HEARTBEAT and
4661 + its ACK do not cause a change in state */
4662 + DEBUGP("Unknown chunk type, Will stay in %s\n",
4663 + sctp_conntrack_names[cur_state]);
4667 + DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
4668 + dir, sctp_conntrack_names[cur_state], chunk_type,
4669 + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4671 + return sctp_conntracks[dir][i][cur_state];
4674 +/* Returns verdict for packet, or -1 for invalid. */
4675 +static int sctp_packet(struct ip_conntrack *conntrack,
4676 + const struct sk_buff *skb,
4677 + enum ip_conntrack_info ctinfo)
4679 + enum sctp_conntrack newconntrack, oldsctpstate;
4680 + sctp_sctphdr_t sctph;
4681 + sctp_chunkhdr_t sch;
4682 + u_int32_t offset, count;
4683 + char map[256 / sizeof (char)] = {0};
4685 + DEBUGP(__FUNCTION__);
4688 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4691 + if (do_basic_checks(conntrack, skb, map) != 0)
4694 + /* Check the verification tag (Sec 8.5) */
4695 + if (!test_bit(SCTP_CID_INIT, (void *)map)
4696 + && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4697 + && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4698 + && !test_bit(SCTP_CID_ABORT, (void *)map)
4699 + && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4700 + && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4701 + DEBUGP("Verification tag check failed\n");
4705 + oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4706 + for_each_sctp_chunk (skb, sch, offset, count) {
4707 + WRITE_LOCK(&sctp_lock);
4709 + /* Special cases of Verification tag check (Sec 8.5.1) */
4710 + if (sch.type == SCTP_CID_INIT) {
4711 + /* Sec 8.5.1 (A) */
4712 + if (sctph.vtag != 0) {
4713 + WRITE_UNLOCK(&sctp_lock);
4716 + } else if (sch.type == SCTP_CID_ABORT) {
4717 + /* Sec 8.5.1 (B) */
4718 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4719 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4720 + [1 - CTINFO2DIR(ctinfo)])) {
4721 + WRITE_UNLOCK(&sctp_lock);
4724 + } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4725 + /* Sec 8.5.1 (C) */
4726 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4727 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4728 + [1 - CTINFO2DIR(ctinfo)]
4729 + && (sch.flags & 1))) {
4730 + WRITE_UNLOCK(&sctp_lock);
4733 + } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4734 + /* Sec 8.5.1 (D) */
4735 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4736 + WRITE_UNLOCK(&sctp_lock);
4741 + oldsctpstate = conntrack->proto.sctp.state;
4742 + newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4745 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4746 + DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4747 + CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4748 + WRITE_UNLOCK(&sctp_lock);
4752 + /* If it is an INIT or an INIT ACK note down the vtag */
4753 + if (sch.type == SCTP_CID_INIT
4754 + || sch.type == SCTP_CID_INIT_ACK) {
4755 + sctp_inithdr_t inithdr;
4757 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4758 + &inithdr, sizeof(inithdr)) != 0) {
4759 + WRITE_UNLOCK(&sctp_lock);
4762 + DEBUGP("Setting vtag %x for dir %d\n",
4763 + inithdr.init_tag, CTINFO2DIR(ctinfo));
4764 + conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4767 + conntrack->proto.sctp.state = newconntrack;
4768 + WRITE_UNLOCK(&sctp_lock);
4771 + ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4773 + if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4774 + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4775 + && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4776 + DEBUGP("Setting assured bit\n");
4777 + set_bit(IPS_ASSURED_BIT, &conntrack->status);
4783 +/* Called when a new connection for this protocol found. */
4784 +static int sctp_new(struct ip_conntrack *conntrack,
4785 + const struct sk_buff *skb)
4787 + enum sctp_conntrack newconntrack;
4788 + sctp_sctphdr_t sctph;
4789 + sctp_chunkhdr_t sch;
4790 + u_int32_t offset, count;
4791 + char map[256 / sizeof (char)] = {0};
4793 + DEBUGP(__FUNCTION__);
4796 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4799 + if (do_basic_checks(conntrack, skb, map) != 0)
4802 + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4803 + if ((test_bit (SCTP_CID_ABORT, (void *)map))
4804 + || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4805 + || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4809 + newconntrack = SCTP_CONNTRACK_MAX;
4810 + for_each_sctp_chunk (skb, sch, offset, count) {
4811 + /* Don't need lock here: this conntrack not in circulation yet */
4812 + newconntrack = new_state (IP_CT_DIR_ORIGINAL,
4813 + SCTP_CONNTRACK_NONE, sch.type);
4815 + /* Invalid: delete conntrack */
4816 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4817 + DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4821 + /* Copy the vtag into the state info */
4822 + if (sch.type == SCTP_CID_INIT) {
4823 + if (sctph.vtag == 0) {
4824 + sctp_inithdr_t inithdr;
4826 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4827 + &inithdr, sizeof(inithdr)) != 0) {
4831 + DEBUGP("Setting vtag %x for new conn\n",
4832 + inithdr.init_tag);
4834 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
4837 + /* Sec 8.5.1 (A) */
4841 + /* If it is a shutdown ack OOTB packet, we expect a return
4842 + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4844 + DEBUGP("Setting vtag %x for new conn OOTB\n",
4846 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4849 + conntrack->proto.sctp.state = newconntrack;
4855 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4856 + const struct sk_buff *skb)
4858 + /* To be implemented */
4862 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
4863 + .list = { NULL, NULL },
4864 + .proto = IPPROTO_SCTP,
4866 + .pkt_to_tuple = sctp_pkt_to_tuple,
4867 + .invert_tuple = sctp_invert_tuple,
4868 + .print_tuple = sctp_print_tuple,
4869 + .print_conntrack = sctp_print_conntrack,
4870 + .packet = sctp_packet,
4873 + .exp_matches_pkt = sctp_exp_matches_pkt,
4877 +int __init init(void)
4881 + ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4882 + DEBUGP("SCTP conntrack module loading %s\n",
4883 + ret ? "failed": "succeeded");
4887 +void __exit fini(void)
4889 + ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4890 + DEBUGP("SCTP conntrack module unloaded\n");
4896 +MODULE_LICENSE("GPL");
4897 +MODULE_AUTHOR("Kiran Kumar Immidi");
4898 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
4899 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_quake3.c
4900 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
4901 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-05-18 12:40:06.000000000 +0200
4903 +/* Quake3 extension for IP connection tracking
4904 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4905 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
4907 + * ip_conntrack_quake3.c v0.04 2002-08-31
4909 + * This program is free software; you can redistribute it and/or
4910 + * modify it under the terms of the GNU General Public License
4911 + * as published by the Free Software Foundation; either version
4912 + * 2 of the License, or (at your option) any later version.
4914 + * Module load syntax:
4915 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
4917 + * please give the ports of all Quake3 master servers You wish to
4918 + * connect to. If you don't specify ports, the default will be UDP
4921 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
4924 +#include <linux/module.h>
4925 +#include <linux/ip.h>
4926 +#include <linux/udp.h>
4928 +#include <linux/netfilter.h>
4929 +#include <linux/netfilter_ipv4/ip_tables.h>
4930 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4931 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
4933 +struct module *ip_conntrack_quake3 = THIS_MODULE;
4935 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4936 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
4937 +MODULE_LICENSE("GPL");
4939 +#define MAX_PORTS 8
4940 +static int ports[MAX_PORTS];
4941 +static int ports_c = 0;
4943 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4944 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
4947 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
4948 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
4950 +#define DEBUGP printk
4952 +#define DEBUGP(format, args...)
4955 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
4957 +static int quake3_help(const struct iphdr *iph, size_t len,
4958 + struct ip_conntrack *ct,
4959 + enum ip_conntrack_info ctinfo)
4961 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
4962 + int dir = CTINFO2DIR(ctinfo);
4963 + struct ip_conntrack_expect exp;
4966 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
4967 + if (ctinfo != IP_CT_ESTABLISHED
4968 + && ctinfo != IP_CT_IS_REPLY) {
4969 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
4971 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
4973 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
4974 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
4975 + i+6 < ntohs(udph->len);
4977 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
4978 + i, ntohs(udph->len),
4979 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
4980 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
4982 + memset(&exp, 0, sizeof(exp));
4984 + exp.tuple = ((struct ip_conntrack_tuple)
4985 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4986 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
4987 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
4990 + exp.mask = ((struct ip_conntrack_tuple)
4991 + { { 0xFFFFFFFF, { 0 } },
4992 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
4993 + exp.expectfn = NULL;
4995 + ip_conntrack_expect_related(ct, &exp);
5000 + return(NF_ACCEPT);
5003 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5004 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
5006 +static void fini(void)
5010 + for(i = 0 ; (i < ports_c); i++) {
5011 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5013 + ip_conntrack_helper_unregister(&quake3[i]);
5017 +static int __init init(void)
5023 + ports[0]=QUAKE3_MASTER_PORT;
5025 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5026 + /* Create helper structure */
5027 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5029 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5030 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5031 + quake3[i].mask.dst.protonum = 0xFFFF;
5032 + quake3[i].mask.src.u.udp.port = 0xFFFF;
5033 + quake3[i].help = quake3_help;
5034 + quake3[i].me = THIS_MODULE;
5036 + tmpname = &quake3_names[i][0];
5037 + if (ports[i] == QUAKE3_MASTER_PORT)
5038 + sprintf(tmpname, "quake3");
5040 + sprintf(tmpname, "quake3-%d", i);
5041 + quake3[i].name = tmpname;
5043 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5046 + ret=ip_conntrack_helper_register(&quake3[i]);
5059 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rsh.c
5060 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
5061 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-05-18 12:40:16.000000000 +0200
5063 +/* RSH extension for IP connection tracking, Version 1.0
5064 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5065 + * based on HW's ip_conntrack_irc.c
5067 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
5069 + * This program is free software; you can redistribute it and/or
5070 + * modify it under the terms of the GNU General Public License
5071 + * as published by the Free Software Foundation; either version
5072 + * 2 of the License, or (at your option) any later version.
5074 + * Module load syntax:
5075 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
5077 + * please give the ports of all RSH servers You wish to connect to.
5078 + * If You don't specify ports, the default will be port 514
5081 + * RSH blows ... you should use SSH (openssh.org) to replace it,
5082 + * unfortunately I babysit some sysadmins that won't migrate
5083 + * their legacy crap, in our second tier.
5088 + * Some docco ripped from the net to teach me all there is to know about
5089 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
5092 + * I have no idea what "unix rshd man pages" these guys have .. but that
5093 + * is some pretty detailed docco!
5096 + * 4. Of the rsh protocol.
5097 + * -----------------------
5099 + * The rshd listens on TCP port #514. The following info is from the unix
5100 + * rshd man pages :
5102 + * "Service Request Protocol
5104 + * When the rshd daemon receives a service request, it initiates the
5105 + * following protocol:
5107 + * 1. The rshd daemon checks the source port number for the request.
5108 + * If the port number is not in the range 0 through 1023, the rshd daemon
5109 + * terminates the connection.
5111 + * 2. The rshd daemon reads characters from the socket up to a null byte.
5112 + * The string read is interpreted as an ASCII number (base 10). If this
5113 + * number is nonzero, the rshd daemon interprets it as the port number
5114 + * of a secondary stream to be used as standard error. A second connection
5115 + * is created to the specified port on the client host. The source port
5116 + * on the local host is in the range 0 through 1023.
5118 + * 3. The rshd daemon uses the source address of the initial connection
5119 + * request to determine the name of the client host. If the name cannot
5120 + * be determined, the rshd daemon uses the dotted decimal representation
5121 + * of the client host's address.
5123 + * 4. The rshd daemon retrieves the following information from the initial
5126 + * * A null-terminated string of at most 16 bytes interpreted as
5127 + * the user name of the user on the client host.
5129 + * * A null-terminated string of at most 16 bytes interpreted as
5130 + * the user name to be used on the local server host.
5132 + * * Another null-terminated string interpreted as a command line
5133 + * to be passed to a shell on the local server host.
5135 + * 5. The rshd daemon attempts to validate the user using the following steps:
5137 + * a. The rshd daemon looks up the local user name in the /etc/passwd
5138 + * file and tries to switch to the home directory (using the chdir
5139 + * subroutine). If either the lookup or the directory change fails,
5140 + * the rshd daemon terminates the connection.
5142 + * b. If the local user ID is a nonzero value, the rshd daemon searches
5143 + * the /etc/hosts.equiv file to see if the name of the client
5144 + * workstation is listed. If the client workstation is listed as an
5145 + * equivalent host, the rshd daemon validates the user.
5147 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
5148 + * authenticate the user by checking the .rhosts file.
5150 + * d. If either the $HOME/.rhosts authentication fails or the
5151 + * client host is not an equivalent host, the rshd daemon
5152 + * terminates the connection.
5154 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
5155 + * on the initial connection and passes the command line to the user's
5156 + * local login shell. The shell then inherits the network connections
5157 + * established by the rshd daemon."
5162 +#include <linux/module.h>
5163 +#include <linux/netfilter.h>
5164 +#include <linux/ip.h>
5165 +#include <net/checksum.h>
5166 +#include <net/tcp.h>
5168 +#include <linux/netfilter_ipv4/lockhelp.h>
5169 +#include <linux/netfilter_ipv4/ip_tables.h>
5170 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5171 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
5173 +#define MAX_PORTS 8
5174 +static int ports[MAX_PORTS];
5175 +static int ports_n_c = 0;
5177 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
5178 +MODULE_DESCRIPTION("RSH connection tracking module");
5179 +MODULE_LICENSE("GPL");
5181 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5182 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
5185 +DECLARE_LOCK(ip_rsh_lock);
5186 +struct module *ip_conntrack_rsh = THIS_MODULE;
5189 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
5192 +#define DEBUGP(format, args...)
5197 +/* FIXME: This should be in userspace. Later. */
5198 +static int help(const struct iphdr *iph, size_t len,
5199 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5201 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5202 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5203 + const char *data = (const char *) tcph + tcph->doff * 4;
5204 + u_int32_t tcplen = len - iph->ihl * 4;
5205 + int dir = CTINFO2DIR(ctinfo);
5206 + struct ip_conntrack_expect expect, *exp = &expect;
5207 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
5211 + /* note that "maxoctet" is used to maintain sanity (8 was the
5212 + * original array size used in rshd/glibc) -- is there a
5213 + * vulnerability in rshd.c in the looped port *= 10?
5217 + DEBUGP("entered\n");
5219 + /* bail if packet is not from RSH client */
5220 + if (dir == IP_CT_DIR_REPLY)
5223 + /* Until there's been traffic both ways, don't look in packets. */
5224 + if (ctinfo != IP_CT_ESTABLISHED
5225 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5226 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
5230 + /* Not whole TCP header? */
5231 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5232 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
5236 + /* Checksum invalid? Ignore. */
5237 + /* FIXME: Source route IP option packets --RR */
5238 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5239 + csum_partial((char *) tcph, tcplen, 0))) {
5240 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5241 + tcph, tcplen, NIPQUAD(iph->saddr),
5242 + NIPQUAD(iph->daddr));
5246 + /* find the rsh stderr port */
5249 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
5254 + if (*data < 48 || *data > 57) {
5255 + DEBUGP("these aren't the packets you're looking for ..\n");
5258 + port = port * 10 + ( *data - 48 );
5261 + /* dont relate sessions that try to expose the client */
5262 + DEBUGP("found port %u\n", port);
5263 + if (port > 1023) {
5264 + DEBUGP("skipping, expected port size is greater than 1023!\n");
5269 + LOCK_BH(&ip_rsh_lock);
5271 + /* new(,related) connection is;
5272 + * reply + dst (uint)port + src port (0:1023)
5274 + memset(&expect, 0, sizeof(expect));
5276 + /* save some discovered data, in case someone ever wants to write
5277 + * a NAT module for this bastard ..
5279 + exp_rsh_info->port = port;
5281 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
5284 + /* Watch out, Radioactive-Man! */
5285 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5286 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5287 + exp->tuple.src.u.tcp.port = 0;
5288 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
5289 + exp->tuple.dst.protonum = IPPROTO_TCP;
5291 + exp->mask.src.ip = 0xffffffff;
5292 + exp->mask.dst.ip = 0xffffffff;
5294 + exp->mask.src.u.tcp.port = htons(0xfc00);
5295 + exp->mask.dst.u.tcp.port = htons(0xfc00);
5296 + exp->mask.dst.protonum = 0xffff;
5298 + exp->expectfn = NULL;
5300 + ip_conntrack_expect_related(ct, &expect);
5302 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5303 + NIPQUAD(exp->tuple.src.ip),
5304 + ntohs(exp->tuple.src.u.tcp.port),
5305 + NIPQUAD(exp->tuple.dst.ip),
5306 + ntohs(exp->tuple.dst.u.tcp.port));
5308 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5309 + NIPQUAD(exp->mask.src.ip),
5310 + ntohs(exp->mask.src.u.tcp.port),
5311 + NIPQUAD(exp->mask.dst.ip),
5312 + ntohs(exp->mask.dst.u.tcp.port));
5313 + UNLOCK_BH(&ip_rsh_lock);
5318 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
5320 +static void fini(void);
5322 +static int __init init(void)
5325 + static char name[10];
5328 + /* If no port given, default to standard RSH port */
5329 + if (ports[0] == 0)
5330 + ports[0] = RSH_PORT;
5332 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5333 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5335 + if (ports[port] == RSH_PORT)
5336 + sprintf(name, "rsh");
5338 + sprintf(name, "rsh-%d", port);
5340 + rsh_helpers[port].name = name;
5341 + rsh_helpers[port].me = THIS_MODULE;
5342 + rsh_helpers[port].max_expected = 1;
5343 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5344 + rsh_helpers[port].timeout = 0;
5346 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5347 + rsh_helpers[port].mask.dst.protonum = 0xffff;
5349 + /* RSH must come from ports 0:1023 to ports[port] (514) */
5350 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
5351 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
5352 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
5354 + rsh_helpers[port].help = help;
5356 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5357 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5358 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
5359 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
5360 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
5361 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
5362 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5363 + NIPQUAD(rsh_helpers[port].mask.src.ip),
5364 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
5365 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
5366 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
5368 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
5371 + printk("ERROR registering port %d\n",
5381 +/* This function is intentionally _NOT_ defined as __exit, because
5382 + * it is needed by the init function */
5383 +static void fini(void)
5386 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5387 + DEBUGP("unregistering port %d\n", ports[port]);
5388 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
5394 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rtsp.c
5395 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
5396 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-05-18 12:40:21.000000000 +0200
5399 + * RTSP extension for IP connection tracking
5400 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5401 + * based on ip_conntrack_irc.c
5403 + * This program is free software; you can redistribute it and/or
5404 + * modify it under the terms of the GNU General Public License
5405 + * as published by the Free Software Foundation; either version
5406 + * 2 of the License, or (at your option) any later version.
5408 + * Module load syntax:
5409 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5410 + * max_outstanding=n setup_timeout=secs
5412 + * If no ports are specified, the default will be port 554.
5414 + * With max_outstanding you can define the maximum number of not yet
5415 + * answered SETUP requests per RTSP session (default 8).
5416 + * With setup_timeout you can specify how long the system waits for
5417 + * an expected data channel (default 300 seconds).
5420 +#include <linux/config.h>
5421 +#include <linux/module.h>
5422 +#include <linux/netfilter.h>
5423 +#include <linux/ip.h>
5424 +#include <net/checksum.h>
5425 +#include <net/tcp.h>
5427 +#include <linux/netfilter_ipv4/lockhelp.h>
5428 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5429 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5431 +#include <linux/ctype.h>
5432 +#define NF_NEED_STRNCASECMP
5433 +#define NF_NEED_STRTOU16
5434 +#define NF_NEED_STRTOU32
5435 +#define NF_NEED_NEXTLINE
5436 +#include <linux/netfilter_helpers.h>
5437 +#define NF_NEED_MIME_NEXTLINE
5438 +#include <linux/netfilter_mime.h>
5440 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5442 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5443 +#ifdef IP_NF_RTSP_DEBUG
5444 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5446 +#define DEBUGP(fmt, args...)
5449 +#define MAX_PORTS 8
5450 +static int ports[MAX_PORTS];
5451 +static int num_ports = 0;
5452 +static int max_outstanding = 8;
5453 +static unsigned int setup_timeout = 300;
5455 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5456 +MODULE_DESCRIPTION("RTSP connection tracking module");
5457 +MODULE_LICENSE("GPL");
5459 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5460 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5461 +MODULE_PARM(max_outstanding, "i");
5462 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5463 +MODULE_PARM(setup_timeout, "i");
5464 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5467 +DECLARE_LOCK(ip_rtsp_lock);
5468 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5471 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5472 + * of allocated ports is twice this value). Note that SMIL burns a lot of
5473 + * ports so keep this reasonably high. If this is too low, you will see a
5474 + * lot of "no free client map entries" messages.
5476 +#define MAX_PORT_MAPS 16
5478 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5480 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5483 + * Parse an RTSP packet.
5485 + * Returns zero if parsing failed.
5488 + * IN ptcp tcp data pointer
5489 + * IN tcplen tcp data len
5490 + * IN/OUT ptcpoff points to current tcp offset
5491 + * OUT phdrsoff set to offset of rtsp headers
5492 + * OUT phdrslen set to length of rtsp headers
5493 + * OUT pcseqoff set to offset of CSeq header
5494 + * OUT pcseqlen set to length of CSeq header
5497 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5498 + uint* phdrsoff, uint* phdrslen,
5499 + uint* pcseqoff, uint* pcseqlen)
5501 + uint entitylen = 0;
5505 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5510 + *phdrsoff = *ptcpoff;
5511 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5515 + if (entitylen > 0)
5517 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5521 + if (lineoff+linelen > tcplen)
5523 + INFOP("!! overrun !!\n");
5527 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5529 + *pcseqoff = lineoff;
5530 + *pcseqlen = linelen;
5532 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5534 + uint off = lineoff+15;
5535 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
5536 + nf_strtou32(ptcp+off, &entitylen);
5539 + *phdrslen = (*ptcpoff) - (*phdrsoff);
5545 + * Find lo/hi client ports (if any) in transport header
5547 + * ptcp, tcplen = packet
5548 + * tranoff, tranlen = buffer to search
5551 + * pport_lo, pport_hi = lo/hi ports (host endian)
5553 + * Returns nonzero if any client ports found
5555 + * Note: it is valid (and expected) for the client to request multiple
5556 + * transports, so we need to parse the entire line.
5559 +rtsp_parse_transport(char* ptran, uint tranlen,
5560 + struct ip_ct_rtsp_expect* prtspexp)
5565 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5566 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
5568 + INFOP("sanity check failed\n");
5571 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5573 + SKIP_WSPACE(ptran, tranlen, off);
5575 + /* Transport: tran;field;field=val,tran;field;field=val,... */
5576 + while (off < tranlen)
5578 + const char* pparamend;
5579 + uint nextparamoff;
5581 + pparamend = memchr(ptran+off, ',', tranlen-off);
5582 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5583 + nextparamoff = pparamend-ptran;
5585 + while (off < nextparamoff)
5587 + const char* pfieldend;
5588 + uint nextfieldoff;
5590 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5591 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5593 + if (strncmp(ptran+off, "client_port=", 12) == 0)
5599 + numlen = nf_strtou16(ptran+off, &port);
5601 + if (prtspexp->loport != 0 && prtspexp->loport != port)
5603 + DEBUGP("multiple ports found, port %hu ignored\n", port);
5607 + prtspexp->loport = prtspexp->hiport = port;
5608 + if (ptran[off] == '-')
5611 + numlen = nf_strtou16(ptran+off, &port);
5613 + prtspexp->pbtype = pb_range;
5614 + prtspexp->hiport = port;
5616 + // If we have a range, assume rtp:
5617 + // loport must be even, hiport must be loport+1
5618 + if ((prtspexp->loport & 0x0001) != 0 ||
5619 + prtspexp->hiport != prtspexp->loport+1)
5621 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
5622 + prtspexp->loport, prtspexp->hiport);
5623 + prtspexp->loport &= 0xfffe;
5624 + prtspexp->hiport = prtspexp->loport+1;
5627 + else if (ptran[off] == '/')
5630 + numlen = nf_strtou16(ptran+off, &port);
5632 + prtspexp->pbtype = pb_discon;
5633 + prtspexp->hiport = port;
5640 + * Note we don't look for the destination parameter here.
5641 + * If we are using NAT, the NAT module will handle it. If not,
5642 + * and the client is sending packets elsewhere, the expectation
5643 + * will quietly time out.
5646 + off = nextfieldoff;
5649 + off = nextparamoff;
5655 +/*** conntrack functions ***/
5657 +/* outbound packet: client->server */
5659 +help_out(const struct iphdr* iph, size_t pktlen,
5660 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5662 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5663 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5664 + uint tcplen = pktlen - iph->ihl * 4;
5665 + char* pdata = (char*)tcph + tcph->doff * 4;
5666 + uint datalen = tcplen - tcph->doff * 4;
5669 + struct ip_conntrack_expect exp;
5671 + while (dataoff < datalen)
5673 + uint cmdoff = dataoff;
5683 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
5684 + &hdrsoff, &hdrslen,
5685 + &cseqoff, &cseqlen))
5687 + break; /* not a valid message */
5690 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5692 + continue; /* not a SETUP message */
5694 + DEBUGP("found a setup message\n");
5696 + memset(&exp, 0, sizeof(exp));
5699 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5700 + &lineoff, &linelen))
5706 + if (off > hdrsoff+hdrslen)
5708 + INFOP("!! overrun !!");
5712 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5714 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5715 + &exp.help.exp_rtsp_info);
5719 + if (exp.help.exp_rtsp_info.loport == 0)
5721 + DEBUGP("no udp transports found\n");
5722 + continue; /* no udp transports found */
5725 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5726 + (int)exp.help.exp_rtsp_info.pbtype,
5727 + exp.help.exp_rtsp_info.loport,
5728 + exp.help.exp_rtsp_info.hiport);
5730 + LOCK_BH(&ip_rtsp_lock);
5731 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5732 + exp.help.exp_rtsp_info.len = hdrslen;
5734 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5735 + exp.mask.src.ip = 0xffffffff;
5736 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5737 + exp.mask.dst.ip = 0xffffffff;
5738 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5739 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5740 + exp.tuple.dst.protonum = IPPROTO_UDP;
5741 + exp.mask.dst.protonum = 0xffff;
5743 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5744 + NIPQUAD(exp.tuple.src.ip),
5745 + ntohs(exp.tuple.src.u.tcp.port),
5746 + NIPQUAD(exp.tuple.dst.ip),
5747 + ntohs(exp.tuple.dst.u.tcp.port));
5749 + /* pass the request off to the nat helper */
5750 + rc = ip_conntrack_expect_related(ct, &exp);
5751 + UNLOCK_BH(&ip_rtsp_lock);
5754 + DEBUGP("ip_conntrack_expect_related succeeded\n");
5758 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5765 +/* inbound packet: server->client */
5767 +help_in(const struct iphdr* iph, size_t pktlen,
5768 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5774 +help(const struct iphdr* iph, size_t pktlen,
5775 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5777 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5778 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5779 + u_int32_t tcplen = pktlen - iph->ihl * 4;
5781 + /* Until there's been traffic both ways, don't look in packets. */
5782 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5784 + DEBUGP("conntrackinfo = %u\n", ctinfo);
5788 + /* Not whole TCP header? */
5789 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5791 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5795 + /* Checksum invalid? Ignore. */
5796 + /* FIXME: Source route IP option packets --RR */
5797 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5798 + csum_partial((char*)tcph, tcplen, 0)))
5800 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5801 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5805 + switch (CTINFO2DIR(ctinfo))
5807 + case IP_CT_DIR_ORIGINAL:
5808 + help_out(iph, pktlen, ct, ctinfo);
5810 + case IP_CT_DIR_REPLY:
5811 + help_in(iph, pktlen, ct, ctinfo);
5818 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5819 +static char rtsp_names[MAX_PORTS][10];
5821 +/* This function is intentionally _NOT_ defined as __exit */
5826 + for (i = 0; i < num_ports; i++)
5828 + DEBUGP("unregistering port %d\n", ports[i]);
5829 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5837 + struct ip_conntrack_helper *hlpr;
5840 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5842 + if (max_outstanding < 1)
5844 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5847 + if (setup_timeout < 0)
5849 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5853 + /* If no port given, default to standard rtsp port */
5854 + if (ports[0] == 0)
5856 + ports[0] = RTSP_PORT;
5859 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5861 + hlpr = &rtsp_helpers[i];
5862 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5863 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5864 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
5865 + hlpr->mask.src.u.tcp.port = 0xFFFF;
5866 + hlpr->mask.dst.protonum = 0xFFFF;
5867 + hlpr->max_expected = max_outstanding;
5868 + hlpr->timeout = setup_timeout;
5869 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5870 + hlpr->me = ip_conntrack_rtsp;
5871 + hlpr->help = help;
5873 + tmpname = &rtsp_names[i][0];
5874 + if (ports[i] == RTSP_PORT)
5876 + sprintf(tmpname, "rtsp");
5880 + sprintf(tmpname, "rtsp-%d", i);
5882 + hlpr->name = tmpname;
5884 + DEBUGP("port #%d: %d\n", i, ports[i]);
5886 + ret = ip_conntrack_helper_register(hlpr);
5890 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5899 +#ifdef CONFIG_IP_NF_NAT_NEEDED
5900 +EXPORT_SYMBOL(ip_rtsp_lock);
5905 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_standalone.c
5906 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-05-10 04:32:29.000000000 +0200
5907 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-05-18 12:39:22.000000000 +0200
5909 len += sprintf(buffer + len, "[ASSURED] ");
5910 len += sprintf(buffer + len, "use=%u ",
5911 atomic_read(&conntrack->ct_general.use));
5912 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5913 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5915 len += sprintf(buffer + len, "\n");
5919 EXPORT_SYMBOL(ip_conntrack_alter_reply);
5920 EXPORT_SYMBOL(ip_conntrack_destroyed);
5921 EXPORT_SYMBOL(ip_conntrack_get);
5922 +EXPORT_SYMBOL(__ip_conntrack_confirm);
5923 EXPORT_SYMBOL(need_ip_conntrack);
5924 EXPORT_SYMBOL(ip_conntrack_helper_register);
5925 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5926 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_talk.c
5927 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
5928 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_talk.c 2004-05-18 12:40:50.000000000 +0200
5931 + * talk extension for IP connection tracking.
5932 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5934 + * This program is free software; you can redistribute it and/or
5935 + * modify it under the terms of the GNU General Public License
5936 + * as published by the Free Software Foundation; either version
5937 + * 2 of the License, or (at your option) any later version.
5939 + * Module load syntax:
5940 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5942 + * talk=[0|1] disable|enable old talk support
5943 + * ntalk=[0|1] disable|enable ntalk support
5944 + * ntalk2=[0|1] disable|enable ntalk2 support
5946 + * The default is talk=1 ntalk=1 ntalk2=1
5948 + * The helper does not support simultaneous talk requests.
5951 + * ASCII art on talk protocols
5954 + * caller server callee server
5961 + * caller client ----------- callee client
5964 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
5965 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5966 + * 3. callee client <-> caller server: LOOK_UP invitation
5967 + * 4. callee client <-> caller client: talk data channel
5969 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
5970 + * draft-hunter-talk-00.txt
5971 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
5973 +#include <linux/config.h>
5974 +#include <linux/module.h>
5975 +#include <linux/netfilter.h>
5976 +#include <linux/ip.h>
5977 +#include <net/checksum.h>
5978 +#include <net/udp.h>
5980 +#include <linux/netfilter_ipv4/lockhelp.h>
5981 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5982 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5983 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5984 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5986 +/* Default all talk protocols are supported */
5987 +static int talk = 1;
5988 +static int ntalk = 1;
5989 +static int ntalk2 = 1;
5990 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5991 +MODULE_DESCRIPTION("talk connection tracking module");
5992 +MODULE_LICENSE("GPL");
5994 +MODULE_PARM(talk, "i");
5995 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5996 +MODULE_PARM(ntalk, "i");
5997 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5998 +MODULE_PARM(ntalk2, "i");
5999 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
6002 +DECLARE_LOCK(ip_talk_lock);
6003 +struct module *ip_conntrack_talk = THIS_MODULE;
6006 +#define DEBUGP printk
6008 +#define DEBUGP(format, args...)
6011 +static int talk_expect(struct ip_conntrack *ct);
6012 +static int ntalk_expect(struct ip_conntrack *ct);
6014 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
6016 +static int talk_help_response(const struct iphdr *iph, size_t len,
6017 + struct ip_conntrack *ct,
6018 + enum ip_conntrack_info ctinfo,
6023 + struct talk_addr *addr)
6025 + int dir = CTINFO2DIR(ctinfo);
6026 + struct ip_conntrack_expect expect, *exp = &expect;
6027 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
6029 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
6030 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
6033 + if (!(answer == SUCCESS && type == mode))
6036 + memset(&expect, 0, sizeof(expect));
6038 + if (type == ANNOUNCE) {
6040 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
6042 + /* update the talk info */
6043 + LOCK_BH(&ip_talk_lock);
6044 + exp_talk_info->port = htons(talk_port);
6046 + /* expect callee client -> caller server message */
6047 + exp->tuple = ((struct ip_conntrack_tuple)
6048 + { { ct->tuplehash[dir].tuple.src.ip,
6050 + { ct->tuplehash[dir].tuple.dst.ip,
6051 + { .tcp = { htons(talk_port) } },
6053 + exp->mask = ((struct ip_conntrack_tuple)
6054 + { { 0xFFFFFFFF, { 0 } },
6055 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6057 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
6059 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
6060 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
6061 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
6063 + /* Ignore failure; should only happen with NAT */
6064 + ip_conntrack_expect_related(ct, &expect);
6065 + UNLOCK_BH(&ip_talk_lock);
6067 + if (type == LOOK_UP) {
6069 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
6071 + /* update the talk info */
6072 + LOCK_BH(&ip_talk_lock);
6073 + exp_talk_info->port = addr->ta_port;
6075 + /* expect callee client -> caller client connection */
6076 + exp->tuple = ((struct ip_conntrack_tuple)
6077 + { { ct->tuplehash[!dir].tuple.src.ip,
6080 + { addr->ta_port },
6082 + exp->mask = ((struct ip_conntrack_tuple)
6083 + { { 0xFFFFFFFF, { 0 } },
6084 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6086 + exp->expectfn = NULL;
6088 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
6089 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
6090 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
6092 + /* Ignore failure; should only happen with NAT */
6093 + ip_conntrack_expect_related(ct, &expect);
6094 + UNLOCK_BH(&ip_talk_lock);
6100 +/* FIXME: This should be in userspace. Later. */
6101 +static int talk_help(const struct iphdr *iph, size_t len,
6102 + struct ip_conntrack *ct,
6103 + enum ip_conntrack_info ctinfo,
6107 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6108 + const char *data = (const char *)udph + sizeof(struct udphdr);
6109 + int dir = CTINFO2DIR(ctinfo);
6112 + DEBUGP("ip_ct_talk_help: help entered\n");
6114 + /* Until there's been traffic both ways, don't look in packets. */
6115 + if (ctinfo != IP_CT_ESTABLISHED
6116 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6117 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
6121 + /* Not whole UDP header? */
6122 + udplen = len - iph->ihl * 4;
6123 + if (udplen < sizeof(struct udphdr)) {
6124 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
6128 + /* Checksum invalid? Ignore. */
6129 + /* FIXME: Source route IP option packets --RR */
6130 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6131 + csum_partial((char *)udph, udplen, 0))) {
6132 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6133 + udph, udplen, NIPQUAD(iph->saddr),
6134 + NIPQUAD(iph->daddr));
6138 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6139 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
6141 + if (dir == IP_CT_DIR_ORIGINAL)
6144 + if (talk_port == TALK_PORT
6145 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6146 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6147 + ((struct talk_response *)data)->type,
6148 + ((struct talk_response *)data)->answer,
6149 + &(((struct talk_response *)data)->addr));
6150 + else if (talk_port == NTALK_PORT
6152 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6153 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6154 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6155 + ((struct ntalk_response *)data)->type,
6156 + ((struct ntalk_response *)data)->answer,
6157 + &(((struct ntalk_response *)data)->addr));
6158 + else if (talk_port == NTALK_PORT
6160 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6161 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6162 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6163 + ((struct ntalk2_response *)data)->type,
6164 + ((struct ntalk2_response *)data)->answer,
6165 + &(((struct ntalk2_response *)data)->addr));
6167 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
6168 + (unsigned)udplen - sizeof(struct udphdr),
6169 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6174 +static int lookup_help(const struct iphdr *iph, size_t len,
6175 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6177 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
6180 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
6181 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6183 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
6186 +static struct ip_conntrack_helper lookup_helpers[2] =
6187 + { { { NULL, NULL },
6188 + "talk", /* name */
6190 + NULL, /* module */
6191 + 1, /* max_expected */
6192 + 240, /* timeout */
6193 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
6194 + { 0, { 0 }, IPPROTO_UDP } },
6195 + { { 0, { 0xFFFF } }, /* mask */
6196 + { 0, { 0 }, 0xFFFF } },
6197 + lookup_help }, /* helper */
6199 + "ntalk", /* name */
6201 + NULL, /* module */
6202 + 1, /* max_expected */
6203 + 240, /* timeout */
6204 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
6205 + { 0, { 0 }, IPPROTO_UDP } },
6206 + { { 0, { 0xFFFF } }, /* mask */
6207 + { 0, { 0 }, 0xFFFF } },
6208 + lookup_nhelp } /* helper */
6211 +static int talk_expect(struct ip_conntrack *ct)
6213 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
6214 + WRITE_LOCK(&ip_conntrack_lock);
6215 + ct->helper = &lookup_helpers[0];
6216 + WRITE_UNLOCK(&ip_conntrack_lock);
6218 + return NF_ACCEPT; /* unused */
6221 +static int ntalk_expect(struct ip_conntrack *ct)
6223 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
6224 + WRITE_LOCK(&ip_conntrack_lock);
6225 + ct->helper = &lookup_helpers[1];
6226 + WRITE_UNLOCK(&ip_conntrack_lock);
6228 + return NF_ACCEPT; /* unused */
6231 +static int help(const struct iphdr *iph, size_t len,
6232 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6234 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
6237 +static int nhelp(const struct iphdr *iph, size_t len,
6238 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6240 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
6243 +static struct ip_conntrack_helper talk_helpers[2] =
6244 + { { { NULL, NULL },
6245 + "talk", /* name */
6247 + THIS_MODULE, /* module */
6248 + 1, /* max_expected */
6249 + 240, /* timeout */
6250 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
6251 + { 0, { 0 }, IPPROTO_UDP } },
6252 + { { 0, { 0xFFFF } }, /* mask */
6253 + { 0, { 0 }, 0xFFFF } },
6254 + help }, /* helper */
6256 + "ntalk", /* name */
6258 + THIS_MODULE, /* module */
6259 + 1, /* max_expected */
6260 + 240, /* timeout */
6261 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
6262 + { 0, { 0 }, IPPROTO_UDP } },
6263 + { { 0, { 0xFFFF } }, /* mask */
6264 + { 0, { 0 }, 0xFFFF } },
6265 + nhelp } /* helper */
6268 +static int __init init(void)
6271 + ip_conntrack_helper_register(&talk_helpers[0]);
6272 + if (ntalk > 0 || ntalk2 > 0)
6273 + ip_conntrack_helper_register(&talk_helpers[1]);
6278 +static void __exit fini(void)
6281 + ip_conntrack_helper_unregister(&talk_helpers[0]);
6282 + if (ntalk > 0 || ntalk2 > 0)
6283 + ip_conntrack_helper_unregister(&talk_helpers[1]);
6286 +EXPORT_SYMBOL(ip_talk_lock);
6290 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.6/net/ipv4/netfilter/ip_nat_core.c
6291 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_core.c 2004-05-10 04:32:01.000000000 +0200
6292 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_core.c 2004-05-18 12:35:39.000000000 +0200
6295 /* Have to grab read lock before sibling_list traversal */
6296 READ_LOCK(&ip_conntrack_lock);
6297 - list_for_each(cur_item, &ct->sibling_list) {
6298 + list_for_each_prev(cur_item, &ct->sibling_list) {
6299 exp = list_entry(cur_item, struct ip_conntrack_expect,
6302 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6/net/ipv4/netfilter/ip_nat_h323.c
6303 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
6304 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_h323.c 2004-05-18 12:39:18.000000000 +0200
6307 + * H.323 'brute force' extension for NAT alteration.
6308 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6310 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6311 + * (http://www.coritel.it/projects/sofia/nat.html)
6312 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6313 + * the unregistered helpers to the conntrack entries.
6317 +#include <linux/module.h>
6318 +#include <linux/netfilter.h>
6319 +#include <linux/ip.h>
6320 +#include <net/checksum.h>
6321 +#include <net/tcp.h>
6323 +#include <linux/netfilter_ipv4/lockhelp.h>
6324 +#include <linux/netfilter_ipv4/ip_nat.h>
6325 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6326 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6327 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6328 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6329 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6331 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6332 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6333 +MODULE_LICENSE("GPL");
6335 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6336 +struct module *ip_nat_h323 = THIS_MODULE;
6339 +#define DEBUGP printk
6341 +#define DEBUGP(format, args...)
6344 +/* FIXME: Time out? --RR */
6346 +static unsigned int
6347 +h225_nat_expected(struct sk_buff **pskb,
6348 + unsigned int hooknum,
6349 + struct ip_conntrack *ct,
6350 + struct ip_nat_info *info);
6352 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6353 + struct ip_conntrack_expect *exp,
6354 + struct ip_nat_info *info,
6355 + enum ip_conntrack_info ctinfo,
6356 + unsigned int hooknum,
6357 + struct sk_buff **pskb);
6359 +static struct ip_nat_helper h245 =
6361 + "H.245", /* name */
6363 + NULL, /* module */
6364 + { { 0, { 0 } }, /* tuple */
6365 + { 0, { 0 }, IPPROTO_TCP } },
6366 + { { 0, { 0xFFFF } }, /* mask */
6367 + { 0, { 0 }, 0xFFFF } },
6368 + h225_nat_help, /* helper */
6369 + h225_nat_expected /* expectfn */
6372 +static unsigned int
6373 +h225_nat_expected(struct sk_buff **pskb,
6374 + unsigned int hooknum,
6375 + struct ip_conntrack *ct,
6376 + struct ip_nat_info *info)
6378 + struct ip_nat_multi_range mr;
6379 + u_int32_t newdstip, newsrcip, newip;
6381 + struct ip_ct_h225_expect *exp_info;
6382 + struct ip_ct_h225_master *master_info;
6383 + struct ip_conntrack *master = master_ct(ct);
6384 + unsigned int is_h225, ret;
6386 + IP_NF_ASSERT(info);
6387 + IP_NF_ASSERT(master);
6389 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6391 + DEBUGP("h225_nat_expected: We have a connection!\n");
6392 + master_info = &ct->master->expectant->help.ct_h225_info;
6393 + exp_info = &ct->master->help.exp_h225_info;
6395 + LOCK_BH(&ip_h323_lock);
6397 + DEBUGP("master: ");
6398 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6399 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6400 + DEBUGP("conntrack: ");
6401 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6402 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6403 + /* Make connection go to the client. */
6404 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6405 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6406 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6407 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6409 + /* Make the connection go to the server */
6410 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6411 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6412 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6413 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6415 + port = exp_info->port;
6416 + is_h225 = master_info->is_h225 == H225_PORT;
6417 + UNLOCK_BH(&ip_h323_lock);
6419 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6424 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6427 + /* We don't want to manip the per-protocol, just the IPs... */
6428 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6429 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6431 + /* ... unless we're doing a MANIP_DST, in which case, make
6432 + sure we map to the correct port */
6433 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6434 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6435 + mr.range[0].min = mr.range[0].max
6436 + = ((union ip_conntrack_manip_proto)
6437 + { .tcp = { port } });
6440 + ret = ip_nat_setup_info(ct, &mr, hooknum);
6443 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6444 + /* NAT expectfn called with ip_nat_lock write-locked */
6445 + info->helper = &h245;
6450 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6451 + struct sk_buff **pskb,
6452 + enum ip_conntrack_info ctinfo)
6454 + struct iphdr *iph = (*pskb)->nh.iph;
6455 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6456 + char *data = (char *) tcph + tcph->doff * 4;
6457 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6458 + u_int32_t datalen = tcplen - tcph->doff*4;
6459 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6464 + MUST_BE_LOCKED(&ip_h323_lock);
6466 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6467 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6469 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6471 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6472 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6475 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6476 + info->offset[IP_CT_DIR_ORIGINAL],
6477 + info->offset[IP_CT_DIR_REPLY],
6479 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6480 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6482 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
6483 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6484 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6485 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6486 + if (!between(info->seq[i], ntohl(tcph->seq),
6487 + ntohl(tcph->seq) + datalen))
6489 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6490 + ntohl(tcph->seq) + datalen)) {
6491 + /* Partial retransmisison. It's a cracker being funky. */
6492 + if (net_ratelimit()) {
6493 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6496 + ntohl(tcph->seq) + datalen);
6501 + /* Change address inside packet to match way we're mapping
6502 + this connection. */
6503 + if (i == IP_CT_DIR_ORIGINAL) {
6504 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6505 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6507 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
6508 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6511 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6512 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6513 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6514 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6516 + /* Modify the packet */
6517 + *(u_int32_t *)(data + info->offset[i]) = newip;
6518 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
6520 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6521 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6522 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6523 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6526 + /* fix checksum information */
6528 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6532 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6533 + csum_partial((char *)tcph, tcph->doff*4,
6535 + ip_send_check(iph);
6540 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6541 + struct ip_conntrack *ct,
6542 + struct sk_buff **pskb,
6543 + enum ip_conntrack_info ctinfo,
6544 + struct ip_conntrack_expect *expect)
6548 + struct ip_conntrack_tuple newtuple;
6549 + struct iphdr *iph = (*pskb)->nh.iph;
6550 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6551 + char *data = (char *) tcph + tcph->doff * 4;
6552 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6553 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6556 + MUST_BE_LOCKED(&ip_h323_lock);
6557 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6558 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6559 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6561 + if (!between(expect->seq + 6, ntohl(tcph->seq),
6562 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6563 + /* Partial retransmisison. It's a cracker being funky. */
6564 + if (net_ratelimit()) {
6565 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6568 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6573 + /* Change address inside packet to match way we're mapping
6574 + this connection. */
6575 + if (info->dir == IP_CT_DIR_REPLY) {
6576 + /* Must be where client thinks server is */
6577 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6578 + /* Expect something from client->server */
6579 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6580 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6582 + /* Must be where server thinks client is */
6583 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6584 + /* Expect something from server->client */
6585 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6586 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6589 + is_h225 = (master_info->is_h225 == H225_PORT);
6592 + newtuple.dst.protonum = IPPROTO_TCP;
6593 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6595 + newtuple.dst.protonum = IPPROTO_UDP;
6596 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6599 + /* Try to get same port: if not, try to change it. */
6600 + for (port = ntohs(info->port); port != 0; port++) {
6602 + newtuple.dst.u.tcp.port = htons(port);
6604 + newtuple.dst.u.udp.port = htons(port);
6606 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6610 + DEBUGP("h323_data_fixup: no free port found!\n");
6614 + port = htons(port);
6616 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6617 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6618 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6620 + /* Modify the packet */
6621 + *(u_int32_t *)(data + info->offset) = newip;
6622 + *(u_int16_t *)(data + info->offset + 4) = port;
6624 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6625 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6626 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6628 + /* fix checksum information */
6629 + /* FIXME: usually repeated multiple times in the case of H.245! */
6631 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6632 + tcplen - tcph->doff*4, 0);
6635 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6636 + csum_partial((char *)tcph, tcph->doff*4,
6638 + ip_send_check(iph);
6643 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6644 + struct ip_conntrack_expect *exp,
6645 + struct ip_nat_info *info,
6646 + enum ip_conntrack_info ctinfo,
6647 + unsigned int hooknum,
6648 + struct sk_buff **pskb)
6651 + struct ip_ct_h225_expect *exp_info;
6653 + /* Only mangle things once: original direction in POST_ROUTING
6654 + and reply direction on PRE_ROUTING. */
6655 + dir = CTINFO2DIR(ctinfo);
6656 + DEBUGP("nat_h323: dir %s at hook %s\n",
6657 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6658 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6659 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6660 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6661 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6662 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6663 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6664 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6665 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6666 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6667 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6672 + LOCK_BH(&ip_h323_lock);
6673 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6674 + UNLOCK_BH(&ip_h323_lock);
6677 + UNLOCK_BH(&ip_h323_lock);
6681 + exp_info = &exp->help.exp_h225_info;
6683 + LOCK_BH(&ip_h323_lock);
6684 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6685 + UNLOCK_BH(&ip_h323_lock);
6688 + UNLOCK_BH(&ip_h323_lock);
6693 +static struct ip_nat_helper h225 =
6695 + "H.225", /* name */
6696 + IP_NAT_HELPER_F_ALWAYS, /* flags */
6697 + THIS_MODULE, /* module */
6698 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6699 + { 0, { 0 }, IPPROTO_TCP } },
6700 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6701 + { 0, { 0 }, 0xFFFF } },
6702 + h225_nat_help, /* helper */
6703 + h225_nat_expected /* expectfn */
6706 +static int __init init(void)
6710 + ret = ip_nat_helper_register(&h225);
6713 + printk("ip_nat_h323: cannot initialize the module!\n");
6718 +static void __exit fini(void)
6720 + ip_nat_helper_unregister(&h225);
6725 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6/net/ipv4/netfilter/ip_nat_mms.c
6726 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6727 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_mms.c 2004-05-18 12:39:36.000000000 +0200
6729 +/* MMS extension for TCP NAT alteration.
6730 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6731 + * based on ip_nat_ftp.c and ip_nat_irc.c
6733 + * ip_nat_mms.c v0.3 2002-09-22
6735 + * This program is free software; you can redistribute it and/or
6736 + * modify it under the terms of the GNU General Public License
6737 + * as published by the Free Software Foundation; either version
6738 + * 2 of the License, or (at your option) any later version.
6740 + * Module load syntax:
6741 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6743 + * Please give the ports of all MMS servers You wish to connect to.
6744 + * If you don't specify ports, the default will be TCP port 1755.
6746 + * More info on MMS protocol, firewalls and NAT:
6747 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6748 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6750 + * The SDP project people are reverse-engineering MMS:
6751 + * http://get.to/sdp
6754 +/* FIXME: issue with UDP & fragmentation with this URL:
6755 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6756 + may be related to out-of-order first packets:
6757 + basically the expectation is set up correctly, then the server sends
6758 + a first UDP packet which is fragmented plus arrives out-of-order.
6759 + the MASQUERADING firewall with ip_nat_mms loaded responds with
6760 + an ICMP unreachable back to the server */
6762 +#include <linux/module.h>
6763 +#include <linux/netfilter_ipv4.h>
6764 +#include <linux/ip.h>
6765 +#include <linux/tcp.h>
6766 +#include <net/tcp.h>
6767 +#include <linux/netfilter_ipv4/ip_nat.h>
6768 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6769 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6770 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6771 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6774 +#define DEBUGP printk
6775 +#define DUMP_BYTES(address, counter) \
6777 + int temp_counter; \
6778 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6779 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
6784 +#define DEBUGP(format, args...)
6785 +#define DUMP_BYTES(address, counter)
6788 +#define MAX_PORTS 8
6789 +static int ports[MAX_PORTS];
6790 +static int ports_c = 0;
6793 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6796 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6797 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6798 +MODULE_LICENSE("GPL");
6800 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6802 +/* FIXME: Time out? --RR */
6804 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6805 + struct ip_conntrack *ct,
6806 + struct sk_buff **pskb,
6807 + enum ip_conntrack_info ctinfo,
6808 + struct ip_conntrack_expect *expect)
6811 + struct ip_conntrack_tuple t;
6812 + struct iphdr *iph = (*pskb)->nh.iph;
6813 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6814 + char *data = (char *)tcph + tcph->doff * 4;
6815 + int i, j, k, port;
6816 + u_int16_t mms_proto;
6818 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6819 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6820 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6824 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6825 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6826 + char proto_string[6];
6828 + MUST_BE_LOCKED(&ip_mms_lock);
6830 + /* what was the protocol again ? */
6831 + mms_proto = expect->tuple.dst.protonum;
6832 + sprintf(proto_string, "%u", mms_proto);
6834 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6835 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6836 + mms_proto == IPPROTO_UDP ? "UDP"
6837 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6839 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6841 + /* Alter conntrack's expectations. */
6842 + t = expect->tuple;
6844 + for (port = ct_mms_info->port; port != 0; port++) {
6845 + t.dst.u.tcp.port = htons(port);
6846 + if (ip_conntrack_change_expect(expect, &t) == 0) {
6847 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6855 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6857 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6858 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6860 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6862 + memset(unicode_buffer, 0, sizeof(char)*75);
6864 + for (i=0; i<strlen(buffer); ++i)
6865 + *(unicode_buffer+i*2)=*(buffer+i);
6867 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6868 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6869 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6871 + /* add end of packet to it */
6872 + for (j=0; j<ct_mms_info->padding; ++j) {
6873 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6874 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6875 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6878 + /* pad with zeroes at the end ? see explanation of weird math below */
6879 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6880 + for (k=0; k<zero_padding; ++k)
6881 + *(unicode_buffer+i*2+j+k)= (char)0;
6883 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6884 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6885 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6887 + /* explanation, before I forget what I did:
6888 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6889 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
6890 + but note that things may have to be padded with zeroes to align by 8
6891 + bytes, hence we add 7 and divide by 8 to get the correct length */
6892 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6893 + *mms_chunkLenLV = *mms_chunkLenLM+2;
6894 + *mms_messageLength = *mms_chunkLenLV*8;
6896 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6897 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6899 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6900 + expect->seq - ntohl(tcph->seq),
6901 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6902 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6903 + DUMP_BYTES(unicode_buffer, 60);
6908 +static unsigned int
6909 +mms_nat_expected(struct sk_buff **pskb,
6910 + unsigned int hooknum,
6911 + struct ip_conntrack *ct,
6912 + struct ip_nat_info *info)
6914 + struct ip_nat_multi_range mr;
6915 + u_int32_t newdstip, newsrcip, newip;
6917 + struct ip_conntrack *master = master_ct(ct);
6919 + IP_NF_ASSERT(info);
6920 + IP_NF_ASSERT(master);
6922 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6924 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6926 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6927 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6928 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6929 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6930 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6931 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6932 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6934 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6939 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6942 + /* We don't want to manip the per-protocol, just the IPs. */
6943 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6944 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6946 + return ip_nat_setup_info(ct, &mr, hooknum);
6950 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6951 + struct ip_conntrack_expect *exp,
6952 + struct ip_nat_info *info,
6953 + enum ip_conntrack_info ctinfo,
6954 + unsigned int hooknum,
6955 + struct sk_buff **pskb)
6957 + struct iphdr *iph = (*pskb)->nh.iph;
6958 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6959 + unsigned int datalen;
6961 + struct ip_ct_mms_expect *ct_mms_info;
6964 + DEBUGP("ip_nat_mms: no exp!!");
6966 + ct_mms_info = &exp->help.exp_mms_info;
6968 + /* Only mangle things once: original direction in POST_ROUTING
6969 + and reply direction on PRE_ROUTING. */
6970 + dir = CTINFO2DIR(ctinfo);
6971 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6972 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6973 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6974 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6975 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6976 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6977 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6980 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6981 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6982 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6983 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6984 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6986 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6988 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6989 + exp->seq + ct_mms_info->len,
6991 + ntohl(tcph->seq) + datalen);
6993 + LOCK_BH(&ip_mms_lock);
6994 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
6995 + if (between(exp->seq + ct_mms_info->len,
6997 + ntohl(tcph->seq) + datalen)) {
6998 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6999 + UNLOCK_BH(&ip_mms_lock);
7003 + /* Half a match? This means a partial retransmisison.
7004 + It's a cracker being funky. */
7005 + if (net_ratelimit()) {
7006 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
7007 + exp->seq, ct_mms_info->len,
7009 + ntohl(tcph->seq) + datalen);
7011 + UNLOCK_BH(&ip_mms_lock);
7014 + UNLOCK_BH(&ip_mms_lock);
7019 +static struct ip_nat_helper mms[MAX_PORTS];
7020 +static char mms_names[MAX_PORTS][10];
7022 +/* Not __exit: called from init() */
7023 +static void fini(void)
7027 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7028 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
7029 + ip_nat_helper_unregister(&mms[i]);
7033 +static int __init init(void)
7038 + if (ports[0] == 0)
7039 + ports[0] = MMS_PORT;
7041 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7043 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
7045 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
7046 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
7047 + mms[i].mask.dst.protonum = 0xFFFF;
7048 + mms[i].mask.src.u.tcp.port = 0xFFFF;
7049 + mms[i].help = mms_nat_help;
7050 + mms[i].me = THIS_MODULE;
7052 + mms[i].expect = mms_nat_expected;
7054 + tmpname = &mms_names[i][0];
7055 + if (ports[i] == MMS_PORT)
7056 + sprintf(tmpname, "mms");
7058 + sprintf(tmpname, "mms-%d", i);
7059 + mms[i].name = tmpname;
7061 + DEBUGP("ip_nat_mms: register helper for port %d\n",
7063 + ret = ip_nat_helper_register(&mms[i]);
7066 + printk("ip_nat_mms: error registering "
7067 + "helper for port %d\n", ports[i]);
7079 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6/net/ipv4/netfilter/ip_nat_quake3.c
7080 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
7081 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_quake3.c 2004-05-18 12:40:06.000000000 +0200
7083 +/* Quake3 extension for UDP NAT alteration.
7084 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7085 + * based on ip_nat_ftp.c and ip_nat_tftp.c
7087 + * ip_nat_quake3.c v0.0.3 2002-08-31
7089 + * This program is free software; you can redistribute it and/or
7090 + * modify it under the terms of the GNU General Public License
7091 + * as published by the Free Software Foundation; either version
7092 + * 2 of the License, or (at your option) any later version.
7094 + * Module load syntax:
7095 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
7097 + * please give the ports of all Quake3 master servers You wish to
7098 + * connect to. If you don't specify ports, the default will be UDP
7101 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
7104 + * - If you're one of those people who would try anything to lower
7105 + * latency while playing Quake (and who isn't :-) ), you may want to
7106 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
7107 + * outgoing UDP traffic.
7108 + * This will make ip_conntrack_quake3 add the necessary expectations,
7109 + * but there will be no overhead for client->server UDP streams. If
7110 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
7111 + * hook for every packet in the client->server UDP stream.
7112 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
7113 + * The IP addresses in the master connection payload (=IP addresses
7114 + * of Quake servers) have no relation with the master server so
7115 + * DNAT'ing the master connection to a server should not change the
7116 + * expected connections.
7117 + * - Not tested due to lack of equipment:
7118 + * - multiple Quake3 clients behind one MASQUERADE gateway
7119 + * - what if Quake3 client is running on router too
7122 +#include <linux/module.h>
7123 +#include <linux/netfilter_ipv4.h>
7124 +#include <linux/ip.h>
7125 +#include <linux/udp.h>
7127 +#include <linux/netfilter.h>
7128 +#include <linux/netfilter_ipv4/ip_tables.h>
7129 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7130 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
7131 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7132 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7134 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7135 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
7136 +MODULE_LICENSE("GPL");
7138 +#define MAX_PORTS 8
7140 +static int ports[MAX_PORTS];
7141 +static int ports_c = 0;
7143 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7144 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7147 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7148 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7150 +#define DEBUGP printk
7152 +#define DEBUGP(format, args...)
7155 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7157 +static unsigned int
7158 +quake3_nat_help(struct ip_conntrack *ct,
7159 + struct ip_conntrack_expect *exp,
7160 + struct ip_nat_info *info,
7161 + enum ip_conntrack_info ctinfo,
7162 + unsigned int hooknum,
7163 + struct sk_buff **pskb)
7165 + struct iphdr *iph = (*pskb)->nh.iph;
7166 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7167 + struct ip_conntrack_tuple repl;
7168 + int dir = CTINFO2DIR(ctinfo);
7171 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7172 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7173 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7174 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7175 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7177 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7178 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7180 + /* Only mangle things once: original direction in POST_ROUTING
7181 + and reply direction on PRE_ROUTING. */
7182 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7183 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7184 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7185 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7186 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7187 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7188 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7193 + DEBUGP("no conntrack expectation to modify\n");
7197 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7198 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7199 + i+6 < ntohs(udph->len);
7201 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
7202 + i, ntohs(udph->len),
7203 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7204 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7206 + memset(&repl, 0, sizeof(repl));
7208 + repl.dst.protonum = IPPROTO_UDP;
7209 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7210 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7211 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
7213 + ip_conntrack_change_expect(exp, &repl);
7219 +static unsigned int
7220 +quake3_nat_expected(struct sk_buff **pskb,
7221 + unsigned int hooknum,
7222 + struct ip_conntrack *ct,
7223 + struct ip_nat_info *info)
7225 + const struct ip_conntrack *master = ct->master->expectant;
7226 + struct ip_nat_multi_range mr;
7227 + u_int32_t newsrcip, newdstip, newip;
7229 + const struct ip_conntrack_tuple *repl =
7230 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7231 + struct iphdr *iph = (*pskb)->nh.iph;
7232 + struct udphdr *udph = (void *)iph + iph->ihl*4;
7235 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7236 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7238 + IP_NF_ASSERT(info);
7239 + IP_NF_ASSERT(master);
7240 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7242 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7243 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7245 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7247 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7248 + "newsrc: %u.%u.%u.%u\n",
7249 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7250 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7251 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7252 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7253 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7258 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7259 + "newdst: %u.%u.%u.%u\n",
7260 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7261 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7262 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7263 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7264 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7269 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7270 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7272 + return ip_nat_setup_info(ct,&mr,hooknum);
7275 +static struct ip_nat_helper quake3[MAX_PORTS];
7276 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
7278 +static void fini(void)
7282 + for (i = 0 ; i < ports_c; i++) {
7283 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7284 + ip_nat_helper_unregister(&quake3[i]);
7288 +static int __init init(void)
7294 + ports[0] = QUAKE3_MASTER_PORT;
7296 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7297 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7299 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7300 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7301 + quake3[i].mask.dst.protonum = 0xFFFF;
7302 + quake3[i].mask.src.u.udp.port = 0xFFFF;
7303 + quake3[i].help = quake3_nat_help;
7304 + quake3[i].flags = 0;
7305 + quake3[i].me = THIS_MODULE;
7306 + quake3[i].expect = quake3_nat_expected;
7308 + tmpname = &quake3_names[i][0];
7309 + if (ports[i] == QUAKE3_MASTER_PORT)
7310 + sprintf(tmpname, "quake3");
7312 + sprintf(tmpname, "quake3-%d", i);
7313 + quake3[i].name = tmpname;
7315 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7316 + ports[i], quake3[i].name);
7317 + ret = ip_nat_helper_register(&quake3[i]);
7320 + printk("ip_nat_quake3: unable to register helper for port %d\n",
7332 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6/net/ipv4/netfilter/ip_nat_rtsp.c
7333 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
7334 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_rtsp.c 2004-05-18 12:40:21.000000000 +0200
7337 + * RTSP extension for TCP NAT alteration
7338 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7339 + * based on ip_nat_irc.c
7341 + * This program is free software; you can redistribute it and/or
7342 + * modify it under the terms of the GNU General Public License
7343 + * as published by the Free Software Foundation; either version
7344 + * 2 of the License, or (at your option) any later version.
7346 + * Module load syntax:
7347 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7348 + * stunaddr=<address>
7349 + * destaction=[auto|strip|none]
7351 + * If no ports are specified, the default will be port 554 only.
7353 + * stunaddr specifies the address used to detect that a client is using STUN.
7354 + * If this address is seen in the destination parameter, it is assumed that
7355 + * the client has already punched a UDP hole in the firewall, so we don't
7356 + * mangle the client_port. If none is specified, it is autodetected. It
7357 + * only needs to be set if you have multiple levels of NAT. It should be
7358 + * set to the external address that the STUN clients detect. Note that in
7359 + * this case, it will not be possible for clients to use UDP with servers
7360 + * between the NATs.
7362 + * If no destaction is specified, auto is used.
7363 + * destaction=auto: strip destination parameter if it is not stunaddr.
7364 + * destaction=strip: always strip destination parameter (not recommended).
7365 + * destaction=none: do not touch destination parameter (not recommended).
7368 +#include <linux/module.h>
7369 +#include <linux/netfilter_ipv4.h>
7370 +#include <linux/ip.h>
7371 +#include <linux/tcp.h>
7372 +#include <linux/kernel.h>
7373 +#include <net/tcp.h>
7374 +#include <linux/netfilter_ipv4/ip_nat.h>
7375 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7376 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7377 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7378 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7380 +#include <linux/inet.h>
7381 +#include <linux/ctype.h>
7382 +#define NF_NEED_STRNCASECMP
7383 +#define NF_NEED_STRTOU16
7384 +#include <linux/netfilter_helpers.h>
7385 +#define NF_NEED_MIME_NEXTLINE
7386 +#include <linux/netfilter_mime.h>
7388 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7389 +#ifdef IP_NF_RTSP_DEBUG
7390 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7392 +#define DEBUGP(fmt, args...)
7395 +#define MAX_PORTS 8
7396 +#define DSTACT_AUTO 0
7397 +#define DSTACT_STRIP 1
7398 +#define DSTACT_NONE 2
7400 +static int ports[MAX_PORTS];
7401 +static char* stunaddr = NULL;
7402 +static char* destaction = NULL;
7404 +static int num_ports = 0;
7405 +static u_int32_t extip = 0;
7406 +static int dstact = 0;
7408 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7409 +MODULE_DESCRIPTION("RTSP network address translation module");
7410 +MODULE_LICENSE("GPL");
7412 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7413 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7414 +MODULE_PARM(stunaddr, "s");
7415 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7416 +MODULE_PARM(destaction, "s");
7417 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7420 +/* protects rtsp part of conntracks */
7421 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7423 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7425 +/*** helper functions ***/
7428 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7430 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7431 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7433 + *pptcpdata = (char*)tcph + tcph->doff*4;
7434 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7437 +/*** nat functions ***/
7440 + * Mangle the "Transport:" header:
7441 + * - Replace all occurences of "client_port=<spec>"
7442 + * - Handle destination parameter
7445 + * ct, ctinfo = conntrack context
7447 + * tranoff = Transport header offset from TCP data
7448 + * tranlen = Transport header length (incl. CRLF)
7449 + * rport_lo = replacement low port (host endian)
7450 + * rport_hi = replacement high port (host endian)
7452 + * Returns packet size difference.
7454 + * Assumes that a complete transport header is present, ending with CR or LF
7457 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7458 + struct ip_conntrack_expect* exp,
7459 + struct sk_buff** pskb, uint tranoff, uint tranlen)
7464 + char rbuf1[16]; /* Replacement buffer (one port) */
7465 + uint rbuf1len; /* Replacement len (one port) */
7466 + char rbufa[16]; /* Replacement buffer (all ports) */
7467 + uint rbufalen; /* Replacement len (all ports) */
7469 + u_int16_t loport, hiport;
7471 + uint diff; /* Number of bytes we removed */
7473 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7474 + struct ip_conntrack_tuple t;
7476 + char szextaddr[15+1];
7480 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7481 + ptran = ptcp+tranoff;
7483 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7484 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7485 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
7487 + INFOP("sanity check failed\n");
7491 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7493 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7497 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7498 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7499 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7501 + rbuf1len = rbufalen = 0;
7502 + switch (prtspexp->pbtype)
7505 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7507 + t.dst.u.udp.port = htons(loport);
7508 + if (ip_conntrack_change_expect(exp, &t) == 0)
7510 + DEBUGP("using port %hu\n", loport);
7516 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7517 + rbufalen = sprintf(rbufa, "%hu", loport);
7521 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7523 + t.dst.u.udp.port = htons(loport);
7524 + if (ip_conntrack_change_expect(exp, &t) == 0)
7526 + hiport = loport + ~exp->mask.dst.u.udp.port;
7527 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
7533 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7534 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7538 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7540 + t.dst.u.udp.port = htons(loport);
7541 + if (ip_conntrack_change_expect(exp, &t) == 0)
7543 + DEBUGP("using port %hu (1 of 2)\n", loport);
7547 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7549 + t.dst.u.udp.port = htons(hiport);
7550 + if (ip_conntrack_change_expect(exp, &t) == 0)
7552 + DEBUGP("using port %hu (2 of 2)\n", hiport);
7556 + if (loport != 0 && hiport != 0)
7558 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7559 + if (hiport == loport+1)
7561 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7565 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7571 + if (rbuf1len == 0)
7573 + return 0; /* cannot get replacement port(s) */
7576 + /* Transport: tran;field;field=val,tran;field;field=val,... */
7577 + while (off < tranlen)
7580 + const char* pparamend;
7581 + uint nextparamoff;
7583 + pparamend = memchr(ptran+off, ',', tranlen-off);
7584 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7585 + nextparamoff = pparamend-ptcp;
7588 + * We pass over each param twice. On the first pass, we look for a
7589 + * destination= field. It is handled by the security policy. If it
7590 + * is present, allowed, and equal to our external address, we assume
7591 + * that STUN is being used and we leave the client_port= field alone.
7595 + while (off < nextparamoff)
7597 + const char* pfieldend;
7598 + uint nextfieldoff;
7600 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7601 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7603 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7605 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7609 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7611 + diff = nextfieldoff-off;
7612 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7613 + off, diff, NULL, 0))
7615 + /* mangle failed, all we can do is bail */
7618 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7619 + ptran = ptcp+tranoff;
7621 + nextparamoff -= diff;
7622 + nextfieldoff -= diff;
7626 + off = nextfieldoff;
7633 + while (off < nextparamoff)
7635 + const char* pfieldend;
7636 + uint nextfieldoff;
7638 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7639 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7641 + if (strncmp(ptran+off, "client_port=", 12) == 0)
7647 + char* rbuf = rbuf1;
7648 + uint rbuflen = rbuf1len;
7651 + origoff = (ptran-ptcp)+off;
7653 + numlen = nf_strtou16(ptran+off, &port);
7655 + origlen += numlen;
7656 + if (port != prtspexp->loport)
7658 + DEBUGP("multiple ports found, port %hu ignored\n", port);
7662 + if (ptran[off] == '-' || ptran[off] == '/')
7666 + numlen = nf_strtou16(ptran+off, &port);
7668 + origlen += numlen;
7670 + rbuflen = rbufalen;
7674 + * note we cannot just memcpy() if the sizes are the same.
7675 + * the mangle function does skb resizing, checks for a
7676 + * cloned skb, and updates the checksums.
7678 + * parameter 4 below is offset from start of tcp data.
7680 + diff = origlen-rbuflen;
7681 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7682 + origoff, origlen, rbuf, rbuflen))
7684 + /* mangle failed, all we can do is bail */
7687 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7688 + ptran = ptcp+tranoff;
7690 + nextparamoff -= diff;
7691 + nextfieldoff -= diff;
7695 + off = nextfieldoff;
7698 + off = nextparamoff;
7704 +static unsigned int
7705 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7707 + struct ip_nat_multi_range mr;
7708 + u_int32_t newdstip, newsrcip, newip;
7710 + struct ip_conntrack *master = master_ct(ct);
7712 + IP_NF_ASSERT(info);
7713 + IP_NF_ASSERT(master);
7715 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7717 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7718 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7719 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7721 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7722 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7725 + /* We don't want to manip the per-protocol, just the IPs. */
7726 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7727 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7729 + return ip_nat_setup_info(ct, &mr, hooknum);
7733 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7734 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7744 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7745 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7747 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7749 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7751 + hdrsoff = exp->seq - ntohl(tcph->seq);
7752 + hdrslen = prtspexp->len;
7755 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7761 + if (off > hdrsoff+hdrslen)
7763 + INFOP("!! overrun !!");
7766 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7768 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7770 + uint oldtcplen = tcplen;
7771 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7775 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7776 + hdrslen -= (oldtcplen-tcplen);
7777 + off -= (oldtcplen-tcplen);
7778 + lineoff -= (oldtcplen-tcplen);
7779 + linelen -= (oldtcplen-tcplen);
7780 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7788 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7789 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7791 + /* XXX: unmangle */
7796 +help(struct ip_conntrack* ct,
7797 + struct ip_conntrack_expect* exp,
7798 + struct ip_nat_info* info,
7799 + enum ip_conntrack_info ctinfo,
7800 + unsigned int hooknum,
7801 + struct sk_buff** pskb)
7803 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7804 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7807 + struct ip_ct_rtsp_expect* ct_rtsp_info;
7808 + int rc = NF_ACCEPT;
7810 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7812 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7816 + ct_rtsp_info = &exp->help.exp_rtsp_info;
7819 + * Only mangle things once: original direction in POST_ROUTING
7820 + * and reply direction on PRE_ROUTING.
7822 + dir = CTINFO2DIR(ctinfo);
7823 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7824 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7826 + DEBUGP("Not touching dir %s at hook %s\n",
7827 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7828 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7829 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7830 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7833 + DEBUGP("got beyond not touching\n");
7835 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7837 + LOCK_BH(&ip_rtsp_lock);
7838 + /* Ensure the packet contains all of the marked data */
7839 + if (!between(exp->seq + ct_rtsp_info->len,
7840 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7842 + /* Partial retransmission? Probably a hacker. */
7843 + if (net_ratelimit())
7845 + INFOP("partial packet %u/%u in %u/%u\n",
7846 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7848 + UNLOCK_BH(&ip_rtsp_lock);
7854 + case IP_CT_DIR_ORIGINAL:
7855 + rc = help_out(ct, ctinfo, exp, pskb);
7857 + case IP_CT_DIR_REPLY:
7858 + rc = help_in(ct, ctinfo, exp, pskb);
7861 + UNLOCK_BH(&ip_rtsp_lock);
7866 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7867 +static char rtsp_names[MAX_PORTS][10];
7869 +/* This function is intentionally _NOT_ defined as __exit */
7875 + for (i = 0; i < num_ports; i++)
7877 + DEBUGP("unregistering helper for port %d\n", ports[i]);
7878 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7887 + struct ip_nat_helper* hlpr;
7890 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7892 + if (ports[0] == 0)
7894 + ports[0] = RTSP_PORT;
7897 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7899 + hlpr = &ip_nat_rtsp_helpers[i];
7900 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
7902 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
7903 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7904 + hlpr->mask.src.u.tcp.port = 0xFFFF;
7905 + hlpr->mask.dst.protonum = 0xFFFF;
7906 + hlpr->help = help;
7908 + hlpr->me = THIS_MODULE;
7909 + hlpr->expect = expected;
7911 + tmpname = &rtsp_names[i][0];
7912 + if (ports[i] == RTSP_PORT)
7914 + sprintf(tmpname, "rtsp");
7918 + sprintf(tmpname, "rtsp-%d", i);
7920 + hlpr->name = tmpname;
7922 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7923 + ret = ip_nat_helper_register(hlpr);
7927 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7933 + if (stunaddr != NULL)
7935 + extip = in_aton(stunaddr);
7937 + if (destaction != NULL)
7939 + if (strcmp(destaction, "auto") == 0)
7941 + dstact = DSTACT_AUTO;
7943 + if (strcmp(destaction, "strip") == 0)
7945 + dstact = DSTACT_STRIP;
7947 + if (strcmp(destaction, "none") == 0)
7949 + dstact = DSTACT_NONE;
7957 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6/net/ipv4/netfilter/ip_nat_rule.c
7958 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rule.c 2004-05-10 04:32:28.000000000 +0200
7959 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_rule.c 2004-05-18 12:38:32.000000000 +0200
7962 sizeof(struct ipt_entry),
7963 sizeof(struct ipt_standard),
7964 - 0, { 0, 0 }, { } },
7965 + 0, NULL, 0, { 0, 0 }, { } },
7966 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7971 sizeof(struct ipt_entry),
7972 sizeof(struct ipt_standard),
7973 - 0, { 0, 0 }, { } },
7974 + 0, NULL, 0, { 0, 0 }, { } },
7975 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7980 sizeof(struct ipt_entry),
7981 sizeof(struct ipt_standard),
7982 - 0, { 0, 0 }, { } },
7983 + 0, NULL, 0, { 0, 0 }, { } },
7984 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7989 sizeof(struct ipt_entry),
7990 sizeof(struct ipt_error),
7991 - 0, { 0, 0 }, { } },
7992 + 0, NULL, 0, { 0, 0 }, { } },
7993 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7996 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6/net/ipv4/netfilter/ip_nat_standalone.c
7997 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-05-10 04:33:12.000000000 +0200
7998 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_standalone.c 2004-05-18 12:39:22.000000000 +0200
7999 @@ -175,6 +175,45 @@
8000 return do_bindings(ct, ctinfo, info, hooknum, pskb);
8003 +struct nat_route_key
8012 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
8014 + struct iphdr *iph = skb->nh.iph;
8016 + key->addr = which ? iph->daddr : iph->saddr;
8019 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8020 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8021 + key->port = ports[which];
8027 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
8029 + struct iphdr *iph = skb->nh.iph;
8031 + if (key->addr != (which ? iph->daddr : iph->saddr))
8034 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8035 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8036 + if (key->port != ports[which])
8043 ip_nat_out(unsigned int hooknum,
8044 struct sk_buff **pskb,
8046 const struct net_device *out,
8047 int (*okfn)(struct sk_buff *))
8049 + struct nat_route_key key;
8052 /* root is playing with raw sockets. */
8053 if ((*pskb)->len < sizeof(struct iphdr)
8054 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8055 @@ -204,7 +246,29 @@
8059 - return ip_nat_fn(hooknum, pskb, in, out, okfn);
8060 + nat_route_key_get(*pskb, &key, 0);
8061 + ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8063 + if (ret != NF_DROP && ret != NF_STOLEN
8064 + && nat_route_key_compare(*pskb, &key, 0)) {
8065 + if (ip_route_me_harder(pskb) != 0)
8069 + * POST_ROUTING hook is called with fixed outfn, we need
8070 + * to manually confirm the packet and direct it to the
8071 + * transformers if a policy matches.
8073 + else if ((*pskb)->dst->xfrm != NULL) {
8074 + ret = ip_conntrack_confirm(*pskb);
8075 + if (ret != NF_DROP) {
8076 + dst_output(*pskb);
8085 #ifdef CONFIG_IP_NF_NAT_LOCAL
8087 const struct net_device *out,
8088 int (*okfn)(struct sk_buff *))
8090 - u_int32_t saddr, daddr;
8091 + struct nat_route_key key;
8094 /* root is playing with raw sockets. */
8095 @@ -223,14 +287,14 @@
8096 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8099 - saddr = (*pskb)->nh.iph->saddr;
8100 - daddr = (*pskb)->nh.iph->daddr;
8102 + nat_route_key_get(*pskb, &key, 1);
8103 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8105 if (ret != NF_DROP && ret != NF_STOLEN
8106 - && ((*pskb)->nh.iph->saddr != saddr
8107 - || (*pskb)->nh.iph->daddr != daddr))
8108 - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
8109 + && nat_route_key_compare(*pskb, &key, 1)) {
8110 + if (ip_route_me_harder(pskb) != 0)
8116 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6/net/ipv4/netfilter/ip_nat_talk.c
8117 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
8118 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_talk.c 2004-05-18 12:40:50.000000000 +0200
8121 + * talk extension for UDP NAT alteration.
8122 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8124 + * This program is free software; you can redistribute it and/or
8125 + * modify it under the terms of the GNU General Public License
8126 + * as published by the Free Software Foundation; either version
8127 + * 2 of the License, or (at your option) any later version.
8129 + * Module load syntax:
8130 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
8132 + * talk=[0|1] disable|enable old talk support
8133 + * ntalk=[0|1] disable|enable ntalk support
8134 + * ntalk2=[0|1] disable|enable ntalk2 support
8136 + * The default is talk=1 ntalk=1 ntalk2=1
8140 +#include <linux/module.h>
8141 +#include <linux/netfilter_ipv4.h>
8142 +#include <linux/ip.h>
8143 +#include <linux/udp.h>
8144 +#include <linux/kernel.h>
8145 +#include <net/tcp.h>
8146 +#include <net/udp.h>
8148 +#include <linux/netfilter_ipv4/ip_nat.h>
8149 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8150 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8151 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8152 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8154 +/* Default all talk protocols are supported */
8155 +static int talk = 1;
8156 +static int ntalk = 1;
8157 +static int ntalk2 = 1;
8158 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8159 +MODULE_DESCRIPTION("talk network address translation module");
8161 +MODULE_PARM(talk, "i");
8162 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8163 +MODULE_PARM(ntalk, "i");
8164 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8165 +MODULE_PARM(ntalk2, "i");
8166 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8170 +#define DEBUGP printk
8171 +#define IP_NAT_TALK_DEBUG
8173 +#define DEBUGP(format, args...)
8176 +/* FIXME: Time out? --RR */
8179 +mangle_packet(struct sk_buff **pskb,
8180 + struct ip_conntrack *ct,
8183 + struct talk_addr *addr,
8184 + struct talk_addr *ctl_addr)
8186 + struct iphdr *iph = (*pskb)->nh.iph;
8187 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8188 + size_t udplen = (*pskb)->len - iph->ihl * 4;
8190 + /* Fortunately talk sends a structure with the address and
8191 + port in it. The size of the packet won't change. */
8193 + if (ctl_addr == NULL) {
8195 + if (addr->ta_addr == INADDR_ANY)
8197 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8198 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8199 + NIPQUAD(newip), ntohs(port));
8200 + addr->ta_addr = newip;
8201 + addr->ta_port = port;
8204 + if (addr->ta_addr != INADDR_ANY) {
8205 + /* Change address inside packet to match way we're mapping
8206 + this connection. */
8207 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8208 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8209 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
8210 + ntohs(addr->ta_port));
8211 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8213 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8214 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8215 + NIPQUAD(newip), ntohs(port));
8216 + ctl_addr->ta_addr = newip;
8217 + ctl_addr->ta_port = port;
8220 + /* Fix checksums */
8221 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8223 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8224 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8226 + ip_send_check(iph);
8230 +static int talk_help_msg(struct ip_conntrack *ct,
8231 + struct sk_buff **pskb,
8233 + struct talk_addr *addr,
8234 + struct talk_addr *ctl_addr)
8239 + unsigned int verdict = NF_ACCEPT;
8241 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8242 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8243 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8246 + /* Change address inside packet to match way we're mapping
8247 + this connection. */
8248 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8249 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8250 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8251 + NIPQUAD(newip), ntohs(port));
8253 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8254 + verdict = NF_DROP;
8259 +static int talk_help_response(struct ip_conntrack *ct,
8260 + struct ip_conntrack_expect *exp,
8261 + struct sk_buff **pskb,
8264 + struct talk_addr *addr)
8268 + struct ip_conntrack_tuple t;
8269 + struct ip_ct_talk_expect *ct_talk_info;
8271 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8272 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8275 + LOCK_BH(&ip_talk_lock);
8276 + ct_talk_info = &exp->help.exp_talk_info;
8278 + if (!(answer == SUCCESS
8279 + && (type == LOOK_UP || type == ANNOUNCE)
8280 + && exp != NULL)) {
8281 + UNLOCK_BH(&ip_talk_lock);
8285 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
8286 + ntohs(ct_talk_info->port),
8287 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8289 + /* Change address inside packet to match way we're mapping
8290 + this connection. */
8291 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
8292 + IP_CT_DIR_REPLY].tuple.dst.ip;
8293 + /* We can read expect here without conntrack lock, since it's
8294 + only set in ip_conntrack_talk , with ip_talk_lock held
8299 + /* Try to get same port: if not, try to change it. */
8300 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8301 + if (type == LOOK_UP)
8302 + t.dst.u.tcp.port = htons(port);
8304 + t.dst.u.udp.port = htons(port);
8306 + if (ip_conntrack_change_expect(exp, &t) == 0) {
8307 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8311 + UNLOCK_BH(&ip_talk_lock);
8313 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8319 +static unsigned int talk_help(struct ip_conntrack *ct,
8320 + struct ip_conntrack_expect *exp,
8321 + struct ip_nat_info *info,
8322 + enum ip_conntrack_info ctinfo,
8323 + unsigned int hooknum,
8324 + struct sk_buff **pskb,
8327 + struct iphdr *iph = (*pskb)->nh.iph;
8328 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8329 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8330 + char *data = (char *)udph + sizeof(struct udphdr);
8333 + /* Only mangle things once: original direction in POST_ROUTING
8334 + and reply direction on PRE_ROUTING. */
8335 + dir = CTINFO2DIR(ctinfo);
8336 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8337 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8338 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8339 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8340 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8341 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8342 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8345 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8346 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8347 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8348 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8349 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8350 + NIPQUAD(iph->saddr), ntohs(udph->source),
8351 + NIPQUAD(iph->daddr), ntohs(udph->dest),
8354 + /* Because conntrack does not drop packets, checking must be repeated here... */
8355 + if (talk_port == TALK_PORT) {
8356 + if (dir == IP_CT_DIR_ORIGINAL
8357 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8358 + return talk_help_msg(ct, pskb,
8359 + ((struct talk_msg *)data)->type,
8360 + &(((struct talk_msg *)data)->addr),
8361 + &(((struct talk_msg *)data)->ctl_addr));
8362 + else if (dir == IP_CT_DIR_REPLY
8363 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8364 + return talk_help_response(ct, exp, pskb,
8365 + ((struct talk_response *)data)->type,
8366 + ((struct talk_response *)data)->answer,
8367 + &(((struct talk_response *)data)->addr));
8369 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8370 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
8371 + (unsigned)udplen - sizeof(struct udphdr),
8372 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8376 + if (dir == IP_CT_DIR_ORIGINAL) {
8378 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8379 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8380 + return talk_help_msg(ct, pskb,
8381 + ((struct ntalk_msg *)data)->type,
8382 + &(((struct ntalk_msg *)data)->addr),
8383 + &(((struct ntalk_msg *)data)->ctl_addr));
8385 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8386 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8387 + && udplen == sizeof(struct udphdr)
8388 + + sizeof(struct ntalk2_msg)
8389 + + ((struct ntalk2_msg *)data)->extended)
8390 + return talk_help_msg(ct, pskb,
8391 + ((struct ntalk2_msg *)data)->type,
8392 + &(((struct ntalk2_msg *)data)->addr),
8393 + &(((struct ntalk2_msg *)data)->ctl_addr));
8395 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8396 + (unsigned)udplen - sizeof(struct udphdr),
8397 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8402 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8403 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8404 + return talk_help_response(ct, exp, pskb,
8405 + ((struct ntalk_response *)data)->type,
8406 + ((struct ntalk_response *)data)->answer,
8407 + &(((struct ntalk_response *)data)->addr));
8409 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8410 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8411 + return talk_help_response(ct, exp, pskb,
8412 + ((struct ntalk2_response *)data)->type,
8413 + ((struct ntalk2_response *)data)->answer,
8414 + &(((struct ntalk2_response *)data)->addr));
8416 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8417 + (unsigned)udplen - sizeof(struct udphdr),
8418 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8425 +static unsigned int help(struct ip_conntrack *ct,
8426 + struct ip_conntrack_expect *exp,
8427 + struct ip_nat_info *info,
8428 + enum ip_conntrack_info ctinfo,
8429 + unsigned int hooknum,
8430 + struct sk_buff **pskb)
8432 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8435 +static unsigned int nhelp(struct ip_conntrack *ct,
8436 + struct ip_conntrack_expect *exp,
8437 + struct ip_nat_info *info,
8438 + enum ip_conntrack_info ctinfo,
8439 + unsigned int hooknum,
8440 + struct sk_buff **pskb)
8442 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8445 +static unsigned int
8446 +talk_nat_expected(struct sk_buff **pskb,
8447 + unsigned int hooknum,
8448 + struct ip_conntrack *ct,
8449 + struct ip_nat_info *info);
8451 +static struct ip_nat_helper talk_helpers[2] =
8452 + { { { NULL, NULL },
8453 + "talk", /* name */
8454 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8455 + THIS_MODULE, /* module */
8456 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8457 + { 0, { 0 }, IPPROTO_UDP } },
8458 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8459 + { 0, { 0 }, 0xFFFF } },
8460 + help, /* helper */
8461 + talk_nat_expected }, /* expectfn */
8463 + "ntalk", /* name */
8464 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8465 + THIS_MODULE, /* module */
8466 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8467 + { 0, { 0 }, IPPROTO_UDP } },
8468 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8469 + { 0, { 0 }, 0xFFFF } },
8470 + nhelp, /* helper */
8471 + talk_nat_expected } /* expectfn */
8474 +static unsigned int
8475 +talk_nat_expected(struct sk_buff **pskb,
8476 + unsigned int hooknum,
8477 + struct ip_conntrack *ct,
8478 + struct ip_nat_info *info)
8480 + struct ip_nat_multi_range mr;
8481 + u_int32_t newdstip, newsrcip, newip;
8485 + struct ip_conntrack *master = master_ct(ct);
8487 + IP_NF_ASSERT(info);
8488 + IP_NF_ASSERT(master);
8490 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8492 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8494 + LOCK_BH(&ip_talk_lock);
8495 + port = ct->master->help.exp_talk_info.port;
8496 + UNLOCK_BH(&ip_talk_lock);
8498 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8499 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8500 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8501 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8502 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8505 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8506 + /* Callee client -> caller server */
8507 +#ifdef IP_NAT_TALK_DEBUG
8508 + struct iphdr *iph = (*pskb)->nh.iph;
8509 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8511 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8512 + NIPQUAD(iph->saddr), ntohs(udph->source),
8513 + NIPQUAD(iph->daddr), ntohs(udph->dest));
8515 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8516 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8517 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8518 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8520 + /* Callee client -> caller client */
8521 +#ifdef IP_NAT_TALK_DEBUG
8522 + struct iphdr *iph = (*pskb)->nh.iph;
8523 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8525 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8526 + NIPQUAD(iph->saddr), ntohs(tcph->source),
8527 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
8529 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8530 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8531 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8532 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8534 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8539 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8542 + /* We don't want to manip the per-protocol, just the IPs... */
8543 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8544 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8546 + /* ... unless we're doing a MANIP_DST, in which case, make
8547 + sure we map to the correct port */
8548 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8549 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8550 + mr.range[0].min = mr.range[0].max
8551 + = ((union ip_conntrack_manip_proto)
8552 + { .udp = { port } });
8554 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8556 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8557 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8558 + /* NAT expectfn called with ip_nat_lock write-locked */
8559 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
8564 +static int __init init(void)
8569 + ret = ip_nat_helper_register(&talk_helpers[0]);
8574 + if (ntalk > 0 || ntalk2 > 0) {
8575 + ret = ip_nat_helper_register(&talk_helpers[1]);
8577 + if (ret != 0 && talk > 0)
8578 + ip_nat_helper_unregister(&talk_helpers[0]);
8583 +static void __exit fini(void)
8586 + ip_nat_helper_unregister(&talk_helpers[0]);
8587 + if (ntalk > 0 || ntalk2 > 0)
8588 + ip_nat_helper_unregister(&talk_helpers[1]);
8593 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_pool.c linux-2.6.6/net/ipv4/netfilter/ip_pool.c
8594 --- linux-2.6.6.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
8595 +++ linux-2.6.6/net/ipv4/netfilter/ip_pool.c 2004-05-18 12:36:48.000000000 +0200
8597 +/* Kernel module for IP pool management */
8599 +#include <linux/module.h>
8600 +#include <linux/ip.h>
8601 +#include <linux/skbuff.h>
8602 +#include <linux/netfilter_ipv4/ip_tables.h>
8603 +#include <linux/netfilter_ipv4/ip_pool.h>
8604 +#include <linux/errno.h>
8605 +#include <asm/uaccess.h>
8606 +#include <asm/bitops.h>
8607 +#include <linux/interrupt.h>
8608 +#include <linux/spinlock.h>
8613 +#define DP(format, args...)
8616 +MODULE_LICENSE("GPL");
8619 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8622 + u_int32_t first_ip; /* host byte order, included in range */
8623 + u_int32_t last_ip; /* host byte order, included in range */
8624 + void *members; /* the bitmap proper */
8625 + int nr_use; /* total nr. of tests through this */
8626 + int nr_match; /* total nr. of matches through this */
8630 +static struct ip_pool *POOL;
8632 +static inline struct ip_pool *lookup(ip_pool_t index)
8634 + if (index < 0 || index >= nr_pool) {
8635 + DP("ip_pool:lookup: bad index %d\n", index);
8638 + return POOL+index;
8641 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8643 + struct ip_pool *pool = lookup(index);
8646 + if (!pool || !pool->members)
8648 + read_lock_bh(&pool->lock);
8649 + if (pool->members) {
8650 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
8651 + addr -= pool->first_ip;
8652 + if (test_bit(addr, pool->members)) {
8654 +#ifdef CONFIG_IP_POOL_STATISTICS
8659 +#ifdef CONFIG_IP_POOL_STATISTICS
8663 + read_unlock_bh(&pool->lock);
8666 +EXPORT_SYMBOL(ip_pool_match);
8668 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8670 + struct ip_pool *pool;
8673 + pool = lookup(index);
8674 + if ( !pool || !pool->members
8675 + || addr < pool->first_ip || addr > pool->last_ip)
8677 + read_lock_bh(&pool->lock);
8678 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8679 + addr -= pool->first_ip;
8681 + ? (0 != test_and_clear_bit(addr, pool->members))
8682 + : (0 != test_and_set_bit(addr, pool->members));
8684 + read_unlock_bh(&pool->lock);
8688 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8690 + int res = pool_change(index,addr,isdel);
8692 + if (!isdel) res = !res;
8695 +EXPORT_SYMBOL(ip_pool_mod);
8697 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8699 + return 4*((((b-a+8)/8)+3)/4);
8702 +static inline int poolbytes(ip_pool_t index)
8704 + struct ip_pool *pool = lookup(index);
8706 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8709 +static int setpool(
8715 + struct ip_pool_request req;
8717 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8718 + if (!capable(CAP_NET_ADMIN))
8720 + if (optval != SO_IP_POOL)
8722 + if (len != sizeof(req))
8724 + if (copy_from_user(&req, user, sizeof(req)) != 0)
8726 + printk("obsolete op - upgrade your ippool(8) utility.\n");
8730 +static int getpool(
8736 + struct ip_pool_request req;
8737 + struct ip_pool *pool;
8743 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8744 + if (!capable(CAP_NET_ADMIN))
8746 + if (optval != SO_IP_POOL)
8748 + if (*len != sizeof(req)) {
8751 + if (copy_from_user(&req, user, sizeof(req)) != 0)
8753 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8754 + if (req.op < IP_POOL_BAD001) {
8755 + printk("obsolete op - upgrade your ippool(8) utility.\n");
8759 + case IP_POOL_HIGH_NR:
8760 + DP("ip_pool HIGH_NR\n");
8761 + req.index = IP_POOL_NONE;
8762 + for (i=0; i<nr_pool; i++)
8763 + if (POOL[i].members)
8765 + return copy_to_user(user, &req, sizeof(req));
8766 + case IP_POOL_LOOKUP:
8767 + DP("ip_pool LOOKUP\n");
8768 + pool = lookup(req.index);
8771 + if (!pool->members)
8773 + req.addr = htonl(pool->first_ip);
8774 + req.addr2 = htonl(pool->last_ip);
8775 + return copy_to_user(user, &req, sizeof(req));
8776 + case IP_POOL_USAGE:
8777 + DP("ip_pool USE\n");
8778 + pool = lookup(req.index);
8781 + if (!pool->members)
8783 + req.addr = pool->nr_use;
8784 + req.addr2 = pool->nr_match;
8785 + return copy_to_user(user, &req, sizeof(req));
8786 + case IP_POOL_TEST_ADDR:
8787 + DP("ip_pool TEST 0x%08x\n", req.addr);
8788 + pool = lookup(req.index);
8792 + read_lock_bh(&pool->lock);
8793 + if (!pool->members) {
8794 + DP("ip_pool TEST_ADDR no members in pool\n");
8796 + goto unlock_and_return_res;
8798 + req.addr = ntohl(req.addr);
8799 + if (req.addr < pool->first_ip) {
8800 + DP("ip_pool TEST_ADDR address < pool bounds\n");
8802 + goto unlock_and_return_res;
8804 + if (req.addr > pool->last_ip) {
8805 + DP("ip_pool TEST_ADDR address > pool bounds\n");
8807 + goto unlock_and_return_res;
8809 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
8811 + read_unlock_bh(&pool->lock);
8812 + return copy_to_user(user, &req, sizeof(req));
8813 + case IP_POOL_FLUSH:
8814 + DP("ip_pool FLUSH not yet implemented.\n");
8816 + case IP_POOL_DESTROY:
8817 + DP("ip_pool DESTROY not yet implemented.\n");
8819 + case IP_POOL_INIT:
8820 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8821 + pool = lookup(req.index);
8824 + req.addr = ntohl(req.addr);
8825 + req.addr2 = ntohl(req.addr2);
8826 + if (req.addr > req.addr2) {
8827 + DP("ip_pool INIT bad ip range\n");
8830 + newbytes = bitmap_bytes(req.addr, req.addr2);
8831 + newmembers = kmalloc(newbytes, GFP_KERNEL);
8832 + if (!newmembers) {
8833 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8836 + memset(newmembers, 0, newbytes);
8837 + write_lock_bh(&pool->lock);
8838 + if (pool->members) {
8839 + DP("ip_pool INIT pool %d exists\n", req.index);
8840 + kfree(newmembers);
8842 + goto unlock_and_return_res;
8844 + pool->first_ip = req.addr;
8845 + pool->last_ip = req.addr2;
8847 + pool->nr_match = 0;
8848 + pool->members = newmembers;
8849 + write_unlock_bh(&pool->lock);
8851 + case IP_POOL_ADD_ADDR:
8852 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8853 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
8854 + return copy_to_user(user, &req, sizeof(req));
8855 + case IP_POOL_DEL_ADDR:
8856 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8857 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
8858 + return copy_to_user(user, &req, sizeof(req));
8860 + DP("ip_pool:getpool bad op %d\n", req.op);
8865 +unlock_and_return_res:
8867 + read_unlock_bh(&pool->lock);
8871 +static struct nf_sockopt_ops so_pool
8872 += { { NULL, NULL }, PF_INET,
8873 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
8874 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
8877 +MODULE_PARM(nr_pool, "i");
8879 +static int __init init(void)
8884 + if (nr_pool < 1) {
8885 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8888 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
8890 + printk("ip_pool module init: out of memory for nr_pool %d\n",
8894 + for (i=0; i<nr_pool; i++) {
8895 + POOL[i].first_ip = 0;
8896 + POOL[i].last_ip = 0;
8897 + POOL[i].members = 0;
8898 + POOL[i].nr_use = 0;
8899 + POOL[i].nr_match = 0;
8900 + POOL[i].lock = RW_LOCK_UNLOCKED;
8902 + res = nf_register_sockopt(&so_pool);
8903 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
8911 +static void __exit fini(void)
8915 + DP("ip_pool:fini BYEBYE\n");
8916 + nf_unregister_sockopt(&so_pool);
8917 + for (i=0; i<nr_pool; i++) {
8918 + if (POOL[i].members) {
8919 + kfree(POOL[i].members);
8920 + POOL[i].members = 0;
8925 + DP("ip_pool:fini these are the famous last words\n");
8931 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6/net/ipv4/netfilter/ip_tables.c
8932 --- linux-2.6.6.org/net/ipv4/netfilter/ip_tables.c 2004-05-10 04:32:26.000000000 +0200
8933 +++ linux-2.6.6/net/ipv4/netfilter/ip_tables.c 2004-05-18 12:39:16.000000000 +0200
8936 #include <linux/netfilter_ipv4/ip_tables.h>
8938 +static const char *hooknames[] = {
8939 + [NF_IP_PRE_ROUTING] "PREROUTING",
8940 + [NF_IP_LOCAL_IN] "INPUT",
8941 + [NF_IP_FORWARD] "FORWARD",
8942 + [NF_IP_LOCAL_OUT] "OUTPUT",
8943 + [NF_IP_POST_ROUTING] "POSTROUTING",
8946 MODULE_LICENSE("GPL");
8947 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8948 MODULE_DESCRIPTION("IPv4 packet filter");
8949 @@ -326,6 +334,12 @@
8951 t = ipt_get_target(e);
8952 IP_NF_ASSERT(t->u.kernel.target);
8954 + /* The packet traced and the rule isn't an unconditional return/END. */
8955 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
8956 + nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8957 + table->name, e->chainname, e->rulenum);
8959 /* Standard target? */
8960 if (!t->u.kernel.target->target) {
8966 - != (void *)e + e->next_offset) {
8967 + != (void *)e + e->next_offset && !(e->ip.flags & IPT_F_GOTO)) {
8968 /* Save old back ptr in next entry */
8969 struct ipt_entry *next
8970 = (void *)e + e->next_offset;
8972 /* set back pointer to next entry */
8976 e = get_entry(table_base, v);
8978 /* Targets which reenter must return
8979 @@ -478,6 +491,29 @@
8980 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8984 +find_error_target(struct ipt_entry *s,
8985 + struct ipt_entry *e,
8988 + struct ipt_entry_target *t;
8989 + static struct ipt_entry *found = NULL;
8994 + t = ipt_get_target(found);
8995 + if (strcmp(t->u.user.name,
8996 + IPT_ERROR_TARGET) == 0) {
8997 + *chainname = t->data;
9006 /* All zeroes == unconditional rule. */
9008 unconditional(const struct ipt_ip *ip)
9010 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
9013 + char *chainname = NULL;
9014 + u_int32_t rulenum;
9016 /* No recursion; use packet counter to save back ptrs (reset
9017 to 0 as we leave), and comefrom to save source hook bitmask */
9020 /* Set initial back pointer. */
9021 e->counters.pcnt = pos;
9023 + chainname = (char *) hooknames[hook];
9026 struct ipt_standard_target *t
9030 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
9031 + e->rulenum = rulenum++;
9032 + e->chainname = chainname;
9034 /* Unconditional return/END. */
9035 if (e->target_offset == sizeof(struct ipt_entry)
9036 @@ -531,6 +573,10 @@
9037 && unconditional(&e->ip)) {
9038 unsigned int oldpos, size;
9040 + /* Set unconditional rulenum to zero. */
9042 + e->counters.bcnt = 0;
9044 /* Return: backtrack through the last
9047 @@ -556,6 +602,11 @@
9048 (newinfo->entries + pos);
9049 } while (oldpos == pos + e->next_offset);
9051 + /* Restore chainname, rulenum. */
9052 + chainname = e->chainname;
9053 + rulenum = e->counters.bcnt;
9054 + e->counters.bcnt = 0;
9056 /* Move along one */
9057 size = e->next_offset;
9058 e = (struct ipt_entry *)
9059 @@ -571,6 +622,17 @@
9060 /* This a jump; chase it. */
9061 duprintf("Jump rule %u -> %u\n",
9063 + e->counters.bcnt = rulenum++;
9065 + e = (struct ipt_entry *)
9066 + (newinfo->entries + newpos);
9067 + if (IPT_ENTRY_ITERATE(newinfo->entries,
9069 + find_error_target,
9070 + e, &chainname) == 0) {
9071 + printk("ip_tables: table screwed up!\n");
9075 /* ... this is a fallthru */
9076 newpos = pos + e->next_offset;
9077 @@ -1716,9 +1778,9 @@
9080 #ifdef CONFIG_PROC_FS
9081 -static inline int print_name(const char *i,
9082 - off_t start_offset, char *buffer, int length,
9083 - off_t *pos, unsigned int *count)
9084 +static int print_name(const char *i,
9085 + off_t start_offset, char *buffer, int length,
9086 + off_t *pos, unsigned int *count)
9088 if ((*count)++ >= start_offset) {
9089 unsigned int namelen;
9090 @@ -1752,6 +1814,15 @@
9094 +static inline int print_target(const struct ipt_target *t,
9095 + off_t start_offset, char *buffer, int length,
9096 + off_t *pos, unsigned int *count)
9098 + if (t == &ipt_standard_target || t == &ipt_error_target)
9100 + return print_name((char *)t, start_offset, buffer, length, pos, count);
9103 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
9106 @@ -1760,7 +1831,7 @@
9107 if (down_interruptible(&ipt_mutex) != 0)
9110 - LIST_FIND(&ipt_target, print_name, void *,
9111 + LIST_FIND(&ipt_target, print_target, struct ipt_target *,
9112 offset, buffer, length, &pos, &count);
9115 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6/net/ipv4/netfilter/ipt_CONNMARK.c
9116 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
9117 +++ linux-2.6.6/net/ipv4/netfilter/ipt_CONNMARK.c 2004-05-18 12:38:02.000000000 +0200
9119 +/* This kernel module is used to modify the connection mark values, or
9120 + * to optionally restore the skb nfmark from the connection mark
9122 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9123 + * by Henrik Nordstrom <hno@marasystems.com>
9125 + * This program is free software; you can redistribute it and/or modify
9126 + * it under the terms of the GNU General Public License as published by
9127 + * the Free Software Foundation; either version 2 of the License, or
9128 + * (at your option) any later version.
9130 + * This program is distributed in the hope that it will be useful,
9131 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9132 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9133 + * GNU General Public License for more details.
9135 + * You should have received a copy of the GNU General Public License
9136 + * along with this program; if not, write to the Free Software
9137 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9139 +#include <linux/module.h>
9140 +#include <linux/skbuff.h>
9141 +#include <linux/ip.h>
9142 +#include <net/checksum.h>
9144 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9145 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
9146 +MODULE_LICENSE("GPL");
9148 +#include <linux/netfilter_ipv4/ip_tables.h>
9149 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
9150 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9152 +static unsigned int
9153 +target(struct sk_buff **pskb,
9154 + const struct net_device *in,
9155 + const struct net_device *out,
9156 + unsigned int hooknum,
9157 + const void *targinfo,
9160 + const struct ipt_connmark_target_info *markinfo = targinfo;
9161 + unsigned long diff;
9162 + unsigned long nfmark;
9163 + unsigned long newmark;
9165 + enum ip_conntrack_info ctinfo;
9166 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
9168 + switch(markinfo->mode) {
9169 + case IPT_CONNMARK_SET:
9170 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
9171 + if (newmark != ct->mark)
9172 + ct->mark = newmark;
9174 + case IPT_CONNMARK_SAVE:
9175 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
9176 + if (ct->mark != newmark)
9177 + ct->mark = newmark;
9179 + case IPT_CONNMARK_RESTORE:
9180 + nfmark = (*pskb)->nfmark;
9181 + diff = (ct->mark ^ nfmark & markinfo->mask);
9183 + (*pskb)->nfmark = nfmark ^ diff;
9184 + (*pskb)->nfcache |= NFC_ALTERED;
9190 + return IPT_CONTINUE;
9194 +checkentry(const char *tablename,
9195 + const struct ipt_entry *e,
9197 + unsigned int targinfosize,
9198 + unsigned int hook_mask)
9200 + struct ipt_connmark_target_info *matchinfo = targinfo;
9201 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
9202 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
9204 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
9208 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
9209 + if (strcmp(tablename, "mangle") != 0) {
9210 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9218 +static struct ipt_target ipt_connmark_reg = {
9219 + .name = "CONNMARK",
9220 + .target = &target,
9221 + .checkentry = &checkentry,
9225 +static int __init init(void)
9227 + return ipt_register_target(&ipt_connmark_reg);
9230 +static void __exit fini(void)
9232 + ipt_unregister_target(&ipt_connmark_reg);
9237 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6/net/ipv4/netfilter/ipt_IPMARK.c
9238 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
9239 +++ linux-2.6.6/net/ipv4/netfilter/ipt_IPMARK.c 2004-05-18 12:38:15.000000000 +0200
9241 +/* This is a module which is used for setting the NFMARK field of an skb. */
9242 +#include <linux/module.h>
9243 +#include <linux/skbuff.h>
9244 +#include <linux/ip.h>
9245 +#include <net/checksum.h>
9247 +#include <linux/netfilter_ipv4/ip_tables.h>
9248 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
9250 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
9251 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
9252 +MODULE_LICENSE("GPL");
9254 +static unsigned int
9255 +target(struct sk_buff **pskb,
9256 + const struct net_device *in,
9257 + const struct net_device *out,
9258 + unsigned int hooknum,
9259 + const void *targinfo,
9262 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
9263 + struct iphdr *iph = (*pskb)->nh.iph;
9264 + unsigned long mark;
9266 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
9267 + mark = (unsigned long) ntohl(iph->saddr);
9269 + mark = (unsigned long) ntohl(iph->daddr);
9271 + mark &= ipmarkinfo->andmask;
9272 + mark |= ipmarkinfo->ormask;
9274 + if ((*pskb)->nfmark != mark) {
9275 + (*pskb)->nfmark = mark;
9276 + (*pskb)->nfcache |= NFC_ALTERED;
9278 + return IPT_CONTINUE;
9282 +checkentry(const char *tablename,
9283 + const struct ipt_entry *e,
9285 + unsigned int targinfosize,
9286 + unsigned int hook_mask)
9288 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
9289 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
9291 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
9295 + if (strcmp(tablename, "mangle") != 0) {
9296 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9303 +static struct ipt_target ipt_ipmark_reg = {
9306 + .checkentry = checkentry,
9310 +static int __init init(void)
9312 + return ipt_register_target(&ipt_ipmark_reg);
9315 +static void __exit fini(void)
9317 + ipt_unregister_target(&ipt_ipmark_reg);
9322 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.6/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
9323 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
9324 +++ linux-2.6.6/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-05-18 12:36:01.000000000 +0200
9327 + * Strip all IP options in the IP packet header.
9329 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
9330 + * This software is distributed under GNU GPL v2, 1991
9333 +#include <linux/module.h>
9334 +#include <linux/skbuff.h>
9335 +#include <linux/ip.h>
9336 +#include <net/checksum.h>
9338 +#include <linux/netfilter_ipv4/ip_tables.h>
9340 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
9341 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
9342 +MODULE_LICENSE("GPL");
9344 +static unsigned int
9345 +target(struct sk_buff **pskb,
9346 + const struct net_device *in,
9347 + const struct net_device *out,
9348 + unsigned int hooknum,
9349 + const void *targinfo,
9352 + struct iphdr *iph;
9353 + struct sk_buff *skb;
9354 + struct ip_options *opt;
9355 + unsigned char *optiph;
9358 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9362 + iph = (*pskb)->nh.iph;
9363 + optiph = skb->nh.raw;
9364 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
9366 + /* if no options in packet then nothing to clear. */
9367 + if (iph->ihl * 4 == sizeof(struct iphdr))
9368 + return IPT_CONTINUE;
9370 + /* else clear all options */
9371 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
9372 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
9373 + opt = &(IPCB(skb)->opt);
9377 + skb->nfcache |= NFC_ALTERED;
9379 + return IPT_CONTINUE;
9383 +checkentry(const char *tablename,
9384 + const struct ipt_entry *e,
9386 + unsigned int targinfosize,
9387 + unsigned int hook_mask)
9389 + if (strcmp(tablename, "mangle")) {
9390 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9393 + /* nothing else to check because no parameters */
9397 +static struct ipt_target ipt_ipv4optsstrip_reg = {
9398 + .name = "IPV4OPTSSTRIP",
9400 + .checkentry = checkentry,
9401 + .me = THIS_MODULE };
9403 +static int __init init(void)
9405 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
9408 +static void __exit fini(void)
9410 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9415 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_MARK.c linux-2.6.6/net/ipv4/netfilter/ipt_MARK.c
9416 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_MARK.c 2004-05-10 04:32:37.000000000 +0200
9417 +++ linux-2.6.6/net/ipv4/netfilter/ipt_MARK.c 2004-05-18 12:38:18.000000000 +0200
9420 const struct ipt_mark_target_info *markinfo = targinfo;
9422 - if((*pskb)->nfmark != markinfo->mark) {
9423 + switch (markinfo->mode) {
9424 + case IPT_MARK_SET:
9425 (*pskb)->nfmark = markinfo->mark;
9426 - (*pskb)->nfcache |= NFC_ALTERED;
9429 + case IPT_MARK_AND:
9430 + (*pskb)->nfmark &= markinfo->mark;
9434 + (*pskb)->nfmark |= markinfo->mark;
9437 + (*pskb)->nfcache |= NFC_ALTERED;
9438 return IPT_CONTINUE;
9441 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.6/net/ipv4/netfilter/ipt_NETLINK.c
9442 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
9443 +++ linux-2.6.6/net/ipv4/netfilter/ipt_NETLINK.c 2004-05-18 12:36:02.000000000 +0200
9445 +#include <linux/module.h>
9446 +#include <linux/version.h>
9447 +#include <linux/config.h>
9448 +#include <linux/socket.h>
9449 +#include <linux/skbuff.h>
9450 +#include <linux/kernel.h>
9451 +#include <linux/netlink.h>
9452 +#include <linux/netdevice.h>
9453 +#include <linux/mm.h>
9454 +#include <linux/socket.h>
9455 +#include <linux/netfilter_ipv4/ip_tables.h>
9456 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9457 +#include <net/sock.h>
9459 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9460 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9461 +MODULE_LICENSE("GPL");
9464 +#define DEBUGP printk
9466 +#define DEBUGP(format, args...)
9469 +static struct sock *ipfwsk;
9471 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9472 + unsigned int hooknum,
9473 + const struct net_device *in,
9474 + const struct net_device *out,
9475 + const void *targinfo, void *userinfo)
9477 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9478 + struct iphdr *ip = (*pskb)->nh.iph;
9479 + struct sk_buff *outskb;
9480 + struct netlink_t nlhdr;
9483 + /* Allocate a socket buffer */
9484 + if ( MASK(nld->flags, USE_SIZE) )
9485 + len = nld->size+sizeof(nlhdr);
9487 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
9489 + outskb=alloc_skb(len, GFP_ATOMIC);
9494 + if ( MASK(nld->flags, USE_MARK) )
9495 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
9497 + nlhdr.mark=(*pskb)->nfmark;
9499 + if ( in && in->name ) {
9500 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9501 + }else if ( out && out->name ){
9502 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9505 + skb_put(outskb, len);
9506 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9507 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9508 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9510 + if (net_ratelimit())
9511 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9514 + if ( MASK(nld->flags, USE_DROP) )
9517 + return IPT_CONTINUE;
9520 +static int ipt_netlink_checkentry(const char *tablename,
9521 + const struct ipt_entry *e,
9523 + unsigned int targinfosize,
9524 + unsigned int hookmask)
9526 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9531 +static struct ipt_target ipt_netlink_reg = {
9534 + ipt_netlink_target,
9535 + ipt_netlink_checkentry,
9540 +static int __init init(void)
9542 + DEBUGP("ipt_NETLINK: init module\n");
9544 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
9548 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9555 +static void __exit fini(void)
9557 + DEBUGP("ipt_NETLINK: cleanup_module\n");
9558 + ipt_unregister_target(&ipt_netlink_reg);
9559 + if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9564 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.6/net/ipv4/netfilter/ipt_POOL.c
9565 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
9566 +++ linux-2.6.6/net/ipv4/netfilter/ipt_POOL.c 2004-05-18 12:36:48.000000000 +0200
9568 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9570 + * This target can be used almost everywhere. It acts on some specified
9571 + * IP pool, adding or deleting some IP address in the pool. The address
9572 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9573 + * of the packet under inspection.
9575 + * The target normally returns IPT_CONTINUE.
9578 +#include <linux/types.h>
9579 +#include <linux/ip.h>
9580 +#include <linux/timer.h>
9581 +#include <linux/module.h>
9582 +#include <linux/netfilter.h>
9583 +#include <linux/netdevice.h>
9584 +#include <linux/if.h>
9585 +#include <linux/inetdevice.h>
9586 +#include <net/protocol.h>
9587 +#include <net/checksum.h>
9588 +#include <linux/netfilter_ipv4.h>
9589 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9590 +#include <linux/netfilter_ipv4/ipt_pool.h>
9593 +#define DEBUGP printk
9595 +#define DEBUGP(format, args...)
9598 +/*** NOTE NOTE NOTE NOTE ***
9600 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9601 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9602 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9603 +** is modified for the source IP address of the packet under inspection.
9604 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9606 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9607 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9609 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9610 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9611 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9612 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9616 +do_check(const char *tablename,
9617 + const struct ipt_entry *e,
9619 + unsigned int targinfosize,
9620 + unsigned int hook_mask)
9622 + const struct ipt_pool_info *ipi = targinfo;
9624 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9625 + DEBUGP("POOL_check: size %u.\n", targinfosize);
9628 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9632 +static unsigned int
9633 +do_target(struct sk_buff **pskb,
9634 + unsigned int hooknum,
9635 + const struct net_device *in,
9636 + const struct net_device *out,
9637 + const void *targinfo,
9640 + const struct ipt_pool_info *ipi = targinfo;
9642 + unsigned int verdict = IPT_CONTINUE;
9644 + if (ipi->src != IP_POOL_NONE) {
9645 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9646 + ipi->flags & IPT_POOL_DEL_SRC);
9647 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9648 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9649 + verdict = NF_ACCEPT;
9650 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9651 + verdict = NF_DROP;
9654 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9655 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9656 + ipi->flags & IPT_POOL_DEL_DST);
9657 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9658 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9659 + verdict = NF_ACCEPT;
9660 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9661 + verdict = NF_DROP;
9667 +static struct ipt_target pool_reg
9668 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9670 +static int __init init(void)
9672 + DEBUGP("init ipt_POOL\n");
9673 + return ipt_register_target(&pool_reg);
9676 +static void __exit fini(void)
9678 + DEBUGP("fini ipt_POOL\n");
9679 + ipt_unregister_target(&pool_reg);
9684 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.6/net/ipv4/netfilter/ipt_ROUTE.c
9685 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
9686 +++ linux-2.6.6/net/ipv4/netfilter/ipt_ROUTE.c 2004-05-18 12:38:20.000000000 +0200
9689 + * This implements the ROUTE target, which enables you to setup unusual
9690 + * routes not supported by the standard kernel routing table.
9692 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9694 + * v 1.9 2004/05/14
9696 + * This software is distributed under GNU GPL v2, 1991
9699 +#include <linux/module.h>
9700 +#include <linux/skbuff.h>
9701 +#include <linux/ip.h>
9702 +#include <linux/netfilter_ipv4/ip_tables.h>
9703 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
9704 +#include <linux/netdevice.h>
9705 +#include <linux/route.h>
9706 +#include <net/ip.h>
9707 +#include <net/route.h>
9708 +#include <net/icmp.h>
9709 +#include <net/checksum.h>
9712 +#define DEBUGP printk
9714 +#define DEBUGP(format, args...)
9717 +MODULE_LICENSE("GPL");
9718 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
9719 +MODULE_DESCRIPTION("iptables ROUTE target module");
9721 +/* Try to route the packet according to the routing keys specified in
9722 + * route_info. Keys are :
9724 + * 0 if no oif preferred,
9725 + * otherwise set to the index of the desired oif
9726 + * - route_info->gw :
9727 + * 0 if no gateway specified,
9728 + * otherwise set to the next host to which the pkt must be routed
9729 + * If success, skb->dev is the output device to which the packet must
9730 + * be sent and skb->dst is not NULL
9732 + * RETURN: -1 if an error occured
9733 + * 1 if the packet was succesfully routed to the
9734 + * destination desired
9735 + * 0 if the kernel routing table could not route the packet
9736 + * according to the keys specified
9738 +static int route(struct sk_buff *skb,
9739 + unsigned int ifindex,
9740 + const struct ipt_route_target_info *route_info)
9743 + struct rtable *rt;
9744 + struct iphdr *iph = skb->nh.iph;
9745 + struct flowi fl = {
9749 + .daddr = iph->daddr,
9751 + .tos = RT_TOS(iph->tos),
9752 + .scope = RT_SCOPE_UNIVERSE,
9757 + /* The destination address may be overloaded by the target */
9758 + if (route_info->gw)
9759 + fl.fld_dst = route_info->gw;
9761 + /* Trying to route the packet using the standard routing table. */
9762 + if ((err = ip_route_output_key(&rt, &fl))) {
9763 + if (net_ratelimit())
9764 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
9768 + /* Drop old route. */
9769 + dst_release(skb->dst);
9772 + /* Success if no oif specified or if the oif correspond to the
9774 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
9775 + skb->dst = &rt->u.dst;
9776 + skb->dev = skb->dst->dev;
9780 + /* The interface selected by the routing table is not the one
9781 + * specified by the user. This may happen because the dst address
9782 + * is one of our own addresses.
9784 + if (net_ratelimit())
9785 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
9786 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
9792 +/* Stolen from ip_finish_output2
9793 + * PRE : skb->dev is set to the device we are leaving by
9794 + * skb->dst is not NULL
9795 + * POST: the packet is sent with the link layer header pushed
9796 + * the packet is destroyed
9798 +static void ip_direct_send(struct sk_buff *skb)
9800 + struct dst_entry *dst = skb->dst;
9801 + struct hh_cache *hh = dst->hh;
9804 + read_lock_bh(&hh->hh_lock);
9805 + memcpy(skb->data - 16, hh->hh_data, 16);
9806 + read_unlock_bh(&hh->hh_lock);
9807 + skb_push(skb, hh->hh_len);
9808 + hh->hh_output(skb);
9809 + } else if (dst->neighbour)
9810 + dst->neighbour->output(skb);
9812 + if (net_ratelimit())
9813 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
9819 +/* PRE : skb->dev is set to the device we are leaving by
9820 + * POST: - the packet is directly sent to the skb->dev device, without
9821 + * pushing the link layer header.
9822 + * - the packet is destroyed
9824 +static inline int dev_direct_send(struct sk_buff *skb)
9826 + return dev_queue_xmit(skb);
9830 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
9831 + struct sk_buff *skb)
9833 + unsigned int ifindex = 0;
9834 + struct net_device *dev_out = NULL;
9836 + /* The user set the interface name to use.
9837 + * Getting the current interface index.
9839 + if ((dev_out = dev_get_by_name(route_info->oif))) {
9840 + ifindex = dev_out->ifindex;
9842 + /* Unknown interface name : packet dropped */
9843 + if (net_ratelimit())
9844 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
9848 + /* Trying the standard way of routing packets */
9849 + switch (route(skb, ifindex, route_info)) {
9852 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9853 + return IPT_CONTINUE;
9855 + ip_direct_send(skb);
9859 + /* Failed to send to oif. Trying the hard way */
9860 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9863 + if (net_ratelimit())
9864 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
9867 + /* We have to force the use of an interface.
9868 + * This interface must be a tunnel interface since
9869 + * otherwise we can't guess the hw address for
9870 + * the packet. For a tunnel interface, no hw address
9873 + if ((dev_out->type != ARPHRD_TUNNEL)
9874 + && (dev_out->type != ARPHRD_IPGRE)) {
9875 + if (net_ratelimit())
9876 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
9881 + /* Send the packet. This will also free skb
9882 + * Do not go through the POST_ROUTING hook because
9883 + * skb->dst is not set and because it will probably
9884 + * get confused by the destination IP address.
9886 + skb->dev = dev_out;
9887 + dev_direct_send(skb);
9892 + /* Unexpected error */
9899 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
9900 + struct sk_buff *skb)
9902 + struct net_device *dev_in = NULL;
9904 + /* Getting the current interface index. */
9905 + if (!(dev_in = dev_get_by_name(route_info->iif))) {
9906 + if (net_ratelimit())
9907 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
9911 + skb->dev = dev_in;
9912 + dst_release(skb->dst);
9921 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
9922 + struct sk_buff *skb)
9924 + if (route(skb, 0, route_info)!=1)
9927 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9928 + return IPT_CONTINUE;
9930 + ip_direct_send(skb);
9935 +static unsigned int ipt_route_target(struct sk_buff **pskb,
9936 + const struct net_device *in,
9937 + const struct net_device *out,
9938 + unsigned int hooknum,
9939 + const void *targinfo,
9942 + const struct ipt_route_target_info *route_info = targinfo;
9943 + struct sk_buff *skb = *pskb;
9945 + /* If we are at PREROUTING or INPUT hook
9946 + * the TTL isn't decreased by the IP stack
9948 + if (hooknum == NF_IP_PRE_ROUTING ||
9949 + hooknum == NF_IP_LOCAL_IN) {
9951 + struct iphdr *iph = skb->nh.iph;
9953 + if (iph->ttl <= 1) {
9954 + struct rtable *rt;
9955 + struct flowi fl = {
9959 + .daddr = iph->daddr,
9960 + .saddr = iph->saddr,
9961 + .tos = RT_TOS(iph->tos),
9962 + .scope = ((iph->tos & RTO_ONLINK) ?
9964 + RT_SCOPE_UNIVERSE)
9969 + if (ip_route_output_key(&rt, &fl)) {
9973 + if (skb->dev == rt->u.dst.dev) {
9974 + /* Drop old route. */
9975 + dst_release(skb->dst);
9976 + skb->dst = &rt->u.dst;
9978 + /* this will traverse normal stack, and
9979 + * thus call conntrack on the icmp packet */
9980 + icmp_send(skb, ICMP_TIME_EXCEEDED,
9988 + * If we are at INPUT the checksum must be recalculated since
9989 + * the length could change as the result of a defragmentation.
9991 + if(hooknum == NF_IP_LOCAL_IN) {
9992 + iph->ttl = iph->ttl - 1;
9994 + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
9996 + ip_decrease_ttl(iph);
10000 + /* Tell conntrack to forget this packet since it may get confused
10001 + * when a packet is leaving with dst address == our address.
10002 + * Good idea ? Dunno. Need advice.
10004 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
10005 + nf_conntrack_put(skb->nfct);
10006 + skb->nfct = NULL;
10007 + skb->nfcache = 0;
10008 +#ifdef CONFIG_NETFILTER_DEBUG
10009 + skb->nf_debug = 0;
10013 + if (route_info->oif[0] != '\0')
10014 + return route_oif(route_info, *pskb);
10016 + if (route_info->iif[0] != '\0')
10017 + return route_iif(route_info, *pskb);
10019 + if (route_info->gw)
10020 + return route_gw(route_info, *pskb);
10022 + if (net_ratelimit())
10023 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
10025 + return IPT_CONTINUE;
10029 +static int ipt_route_checkentry(const char *tablename,
10030 + const struct ipt_entry *e,
10032 + unsigned int targinfosize,
10033 + unsigned int hook_mask)
10035 + if (strcmp(tablename, "mangle") != 0) {
10036 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
10041 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
10042 + | (1 << NF_IP_LOCAL_IN)
10043 + | (1 << NF_IP_FORWARD)
10044 + | (1 << NF_IP_LOCAL_OUT)
10045 + | (1 << NF_IP_POST_ROUTING))) {
10046 + printk("ipt_ROUTE: bad hook\n");
10050 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
10051 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
10053 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
10061 +static struct ipt_target ipt_route_reg = {
10063 + .target = ipt_route_target,
10064 + .checkentry = ipt_route_checkentry,
10065 + .me = THIS_MODULE,
10068 +static int __init init(void)
10070 + return ipt_register_target(&ipt_route_reg);
10074 +static void __exit fini(void)
10076 + ipt_unregister_target(&ipt_route_reg);
10079 +module_init(init);
10080 +module_exit(fini);
10081 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6/net/ipv4/netfilter/ipt_TARPIT.c
10082 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
10083 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TARPIT.c 2004-05-18 12:38:28.000000000 +0200
10086 + * Kernel module to capture and hold incoming TCP connections using
10087 + * no local per-connection resources.
10089 + * Based on ipt_REJECT.c and offering functionality similar to
10090 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
10092 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
10094 + * This program is free software; you can redistribute it and/or modify
10095 + * it under the terms of the GNU General Public License as published by
10096 + * the Free Software Foundation; either version 2 of the License, or
10097 + * (at your option) any later version.
10099 + * This program is distributed in the hope that it will be useful,
10100 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10101 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10102 + * GNU General Public License for more details.
10104 + * You should have received a copy of the GNU General Public License
10105 + * along with this program; if not, write to the Free Software
10106 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10109 + * - Allow incoming TCP connections to be established.
10110 + * - Passing data should result in the connection being switched to the
10111 + * persist state (0 byte window), in which the remote side stops sending
10112 + * data and asks to continue every 60 seconds.
10113 + * - Attempts to shut down the connection should be ignored completely, so
10114 + * the remote side ends up having to time it out.
10117 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
10118 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
10119 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
10122 +#include <linux/config.h>
10123 +#include <linux/module.h>
10124 +#include <linux/skbuff.h>
10125 +#include <linux/ip.h>
10126 +#include <net/ip.h>
10127 +#include <net/tcp.h>
10128 +#include <net/icmp.h>
10130 +#include <net/route.h>
10131 +#include <linux/random.h>
10132 +#include <linux/netfilter_ipv4/ip_tables.h>
10135 +#define DEBUGP printk
10137 +#define DEBUGP(format, args...)
10140 +MODULE_LICENSE("GPL");
10141 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
10143 +/* Stolen from ip_finish_output2 */
10144 +static int ip_direct_send(struct sk_buff *skb)
10146 + struct dst_entry *dst = skb->dst;
10147 + struct hh_cache *hh = dst->hh;
10150 + read_lock_bh(&hh->hh_lock);
10151 + memcpy(skb->data - 16, hh->hh_data, 16);
10152 + read_unlock_bh(&hh->hh_lock);
10153 + skb_push(skb, hh->hh_len);
10154 + return hh->hh_output(skb);
10155 + } else if (dst->neighbour)
10156 + return dst->neighbour->output(skb);
10158 + if (net_ratelimit())
10159 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
10166 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
10168 + struct sk_buff *nskb;
10169 + struct rtable *nrt;
10170 + struct tcphdr *otcph, *ntcph;
10171 + struct flowi fl = {};
10172 + unsigned int otcplen;
10175 + /* A truncated TCP header isn't going to be useful */
10176 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
10179 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
10180 + + oskb->nh.iph->ihl);
10181 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
10183 + /* No replies for RST or FIN */
10184 + if (otcph->rst || otcph->fin)
10187 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
10188 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
10191 + /* Check checksum. */
10192 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
10193 + oskb->nh.iph->daddr,
10194 + csum_partial((char *)otcph, otcplen, 0)) != 0)
10197 + /* Copy skb (even if skb is about to be dropped, we can't just
10198 + clone it because there may be other things, such as tcpdump,
10199 + interested in it) */
10200 + nskb = skb_copy(oskb, GFP_ATOMIC);
10204 + /* This packet will not be the same as the other: clear nf fields */
10205 + nf_conntrack_put(nskb->nfct);
10206 + nskb->nfct = NULL;
10207 + nskb->nfcache = 0;
10208 +#ifdef CONFIG_NETFILTER_DEBUG
10209 + nskb->nf_debug = 0;
10212 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
10214 + /* Truncate to length (no data) */
10215 + ntcph->doff = sizeof(struct tcphdr)/4;
10216 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
10217 + nskb->nh.iph->tot_len = htons(nskb->len);
10219 + /* Swap source and dest */
10220 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
10221 + tmp = ntcph->source;
10222 + ntcph->source = ntcph->dest;
10223 + ntcph->dest = tmp;
10225 + /* Use supplied sequence number or make a new one */
10226 + ntcph->seq = otcph->ack ? otcph->ack_seq
10227 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
10228 + nskb->nh.iph->daddr,
10232 + /* Our SYN-ACKs must have a >0 window */
10233 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
10235 + ntcph->urg_ptr = 0;
10237 + /* Reset flags */
10238 + ((u_int8_t *)ntcph)[13] = 0;
10240 + if (otcph->syn && otcph->ack) {
10242 + ntcph->ack_seq = 0;
10244 + ntcph->syn = otcph->syn;
10246 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
10249 + /* Adjust TCP checksum */
10250 + ntcph->check = 0;
10251 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
10252 + nskb->nh.iph->saddr,
10253 + nskb->nh.iph->daddr,
10254 + csum_partial((char *)ntcph,
10255 + sizeof(struct tcphdr), 0));
10257 + /* Adjust IP TTL */
10258 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
10260 + /* Set DF, id = 0 */
10261 + nskb->nh.iph->frag_off = htons(IP_DF);
10262 + nskb->nh.iph->id = 0;
10264 + /* Adjust IP checksum */
10265 + nskb->nh.iph->check = 0;
10266 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
10267 + nskb->nh.iph->ihl);
10269 + fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
10270 + fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
10271 + fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
10274 + if (ip_route_output_key(&nrt, &fl))
10277 + dst_release(nskb->dst);
10278 + nskb->dst = &nrt->u.dst;
10280 + /* "Never happens" */
10281 + if (nskb->len > dst_pmtu(nskb->dst))
10284 + ip_direct_send (nskb);
10293 +static unsigned int tarpit(struct sk_buff **pskb,
10294 + const struct net_device *in,
10295 + const struct net_device *out,
10296 + unsigned int hooknum,
10297 + const void *targinfo,
10300 + struct sk_buff *skb = *pskb;
10301 + struct rtable *rt = (struct rtable*)skb->dst;
10303 + /* Do we have an input route cache entry? */
10307 + /* No replies to physical multicast/broadcast */
10308 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
10311 + /* Now check at the protocol level */
10312 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
10315 + /* Our naive response construction doesn't deal with IP
10316 + options, and probably shouldn't try. */
10317 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
10320 + /* We aren't interested in fragments */
10321 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
10324 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
10330 +static int check(const char *tablename,
10331 + const struct ipt_entry *e,
10333 + unsigned int targinfosize,
10334 + unsigned int hook_mask)
10336 + /* Only allow these for input/forward packet filtering. */
10337 + if (strcmp(tablename, "filter") != 0) {
10338 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
10341 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
10342 + | (1 << NF_IP_FORWARD))) != 0) {
10343 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
10347 + /* Must specify that it's a TCP packet */
10348 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
10349 + DEBUGP("TARPIT: not valid for non-tcp\n");
10356 +static struct ipt_target ipt_tarpit_reg = {
10357 + .name = "TARPIT",
10358 + .target = tarpit,
10359 + .checkentry = check,
10360 + .me = THIS_MODULE
10363 +static int __init init(void)
10365 + return ipt_register_target(&ipt_tarpit_reg);
10368 +static void __exit fini(void)
10370 + ipt_unregister_target(&ipt_tarpit_reg);
10373 +module_init(init);
10374 +module_exit(fini);
10375 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.6/net/ipv4/netfilter/ipt_TCPLAG.c
10376 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
10377 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TCPLAG.c 2004-05-18 12:38:29.000000000 +0200
10379 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
10380 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
10382 + * This program is free software; you can redistribute it and/or modify
10383 + * it under the terms of the GNU General Public License as published by
10384 + * the Free Software Foundation; either version 2 of the License, or
10385 + * (at your option) any later version.
10387 + * This program is distributed in the hope that it will be useful,
10388 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10389 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10390 + * GNU General Public License for more details.
10392 + * You should have received a copy of the GNU General Public License
10393 + * along with this program; if not, write to the Free Software
10394 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10398 + * This collects packets and attempts to make them into pairs
10399 + * based on its own knowledge of how typical network conversations
10400 + * operate. Once it has a pair, it logs the time between them.
10402 +#include <linux/module.h>
10403 +#include <linux/skbuff.h>
10404 +#include <linux/ip.h>
10405 +#include <linux/spinlock.h>
10406 +#include <net/icmp.h>
10407 +#include <net/udp.h>
10408 +#include <net/tcp.h>
10409 +#include <linux/netfilter_ipv4/ip_tables.h>
10411 +#include <net/route.h>
10412 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
10415 +#define DEBUGP printk
10417 +#define DEBUGP(format, args...)
10421 + * We need one spinlock for the hash table.
10423 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
10425 +typedef struct timeval timeval_T;
10428 + * Linked lists of events in the connection,
10429 + * these store the SEQ numbers and the newest is always
10430 + * at the start of the linked list, then they get older
10431 + * down to the end of the linked list (this is not perfect
10432 + * if packets get out of order but we don't worry about fine
10433 + * details like that).
10435 + * Matching any event wipes out that event and also all other
10436 + * events down the chain (i.e. all older events).
10437 + * This keeps the linked list as short as possible.
10439 +typedef struct tcplag_event_S
10441 + struct tcplag_event_S *next;
10444 + u32 expected_ACK;
10445 + struct timeval stamp;
10449 + * This stores the connection statistics
10450 + * We define connections more loosely than TCP/IP does,
10451 + * because we only consider the two hosts, not the ports
10452 + * Also, we list the host-pairs in low,high order which
10453 + * means that we don't care who originated the connection.
10455 +typedef struct tcplag_hash_S
10459 + struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
10460 + struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
10461 + tcplag_event_T *h_ACK_list; /* Try to match ACK packets coming from h in this list */
10462 + tcplag_event_T *l_ACK_list; /* Try to match ACK packets coming from l in this list */
10463 + time_t stamp; /* When this bucket got added to the table */
10464 + u16 count_l_SEQ_h_ACK; /* Increment for each event */
10465 + u16 count_h_SEQ_l_ACK; /* Increment for each event */
10468 +static tcplag_hash_T **hashtab = 0;
10469 +static u32 hashsize = 0;
10470 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
10471 +static u32 reaper_ix = 0;
10473 +static void divide_down( timeval_T *T, int c )
10478 + remainder = T->tv_sec % c; /* Only works properly with positive numbers */
10479 + remainder *= 1000000;
10480 + T->tv_usec == remainder;
10484 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
10488 + x = tv1->tv_sec - tv2->tv_sec;
10489 + if( x ) return( x );
10490 + x = tv1->tv_usec - tv2->tv_usec;
10494 +void sprint_timeval( char *buf, timeval_T *tv )
10497 + sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
10499 + sprintf( buf, "%lu", tv->tv_usec );
10503 + * This generates the log messages through printk()
10505 + * There is really no particular interest in the port numbers at this stage,
10506 + * they are only useful for matching up the request with the reply.
10507 + * The IP numbers are useful because some sites may be slower than others
10508 + * or may travel different routes, etc (OK, in theory changing the port number
10509 + * could also change the route but I don't like that sort of theory).
10513 + * LIP= The IP number of the side with the lowest lag
10514 + * RIP= The IP number of the side with the highest lag
10515 + * LLAG= The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
10516 + * RLAG= The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
10518 +static void output( tcplag_hash_T *H, int level, const char *prefix )
10520 + struct timeval ltm, rtm;
10521 + u32 local_ip, remote_ip;
10522 + char r_buf[ 20 ], l_buf[ 20 ];
10524 + * We can't make sense of a connection that only passes data one way,
10525 + * In principle, at least the SYN and FIN should go both ways so we
10526 + * should get a few hits for every connection.
10528 + if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
10530 + * Calculate average times by dividing down
10532 + divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
10533 + divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
10535 + * Sort these two by the lag so the the local is always the short lag
10537 + if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
10539 + local_ip = H->low_ip;
10540 + remote_ip = H->high_ip;
10541 + rtm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
10542 + rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
10543 + ltm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
10544 + ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
10548 + local_ip = H->high_ip;
10549 + remote_ip = H->low_ip;
10550 + ltm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
10551 + ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
10552 + rtm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
10553 + rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
10556 + * Don't use a spinlock on the output,
10557 + * it is not guaranteed safe because some OTHER printk could
10558 + * split our log message so we want only one single printk.
10560 + * We use sprintf() to partially pre-digest the output
10562 + * Actually, neither this not the main netfilter LOG target is
10563 + * really safe from printk() overlap, basically syslog cannot
10564 + * be regarded as a guaranteed data output channel. It is good
10565 + * enough for most purposes.
10567 + sprint_timeval( l_buf, <m );
10568 + sprint_timeval( r_buf, &rtm );
10569 + printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
10570 + level & 7, prefix,
10571 + NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
10576 + * The reaper rolls through the hash table looking for old.
10577 + * Log entries are only generated at the reaping time
10578 + * (which means all log entries are out-of-date)
10580 +static void reaper( time_t now, int level, const char *prefix )
10584 + now -= max_seconds;
10585 + if( !hashsize ) return;
10586 + if( !hashtab ) return;
10587 + for( i = 0; i < 10; i++ )
10589 + if( ++reaper_ix >= hashsize ) reaper_ix = 0;
10591 +// DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
10593 + if( hashtab[ reaper_ix ])
10595 + tcplag_hash_T *found = 0;
10597 + spin_lock_bh( &hash_lock );
10598 + if( hashtab[ reaper_ix ])
10600 + if( now > hashtab[ reaper_ix ]->stamp )
10602 + DEBUGP( KERN_WARNING "reaper found expired entry\n" );
10603 + found = hashtab[ reaper_ix ];
10604 + hashtab[ reaper_ix ] = 0;
10607 + spin_unlock_bh( &hash_lock );
10611 + output( found, level, prefix );
10619 + * Convert the connection characteristics into a number
10620 + * (not including the timestamp) FIXME: this is a sucky hash function
10622 +static u32 make_hash( tcplag_hash_T *connection )
10626 + r = connection->low_ip;
10627 + r += connection->high_ip;
10631 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
10635 + x = con1->low_ip - con2->low_ip; if( x ) return( x );
10636 + x = con1->high_ip - con2->high_ip;
10640 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
10644 + DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
10645 + x = ev1->expected_ACK - ev2->expected_ACK;
10646 + if( x ) return( x );
10647 + DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
10648 + x = ev1->source_port - ev2->source_port;
10649 + if( x ) return( x );
10650 + DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
10651 + x = ev1->dest_port - ev2->dest_port;
10656 + * Go to the hash table and either find an existing connection that
10657 + * matches correctly or inject a new connection into the table.
10658 + * Once the connection is OK, chain the event onto the linked list.
10660 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
10664 + if( !event ) return; /* Just to be safe */
10665 + if( !hashsize ) return;
10666 + if( !hashtab ) return;
10668 + h = make_hash( connection );
10671 + DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
10673 + spin_lock_bh( &hash_lock );
10674 + for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
10676 + tcplag_hash_T *co_new = 0;
10678 + * Consider existing entry
10680 + if( hashtab[ h ])
10682 + if( compare_connections( hashtab[ h ], connection )) continue;
10683 + co_new = hashtab[ h ];
10684 + DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
10688 + * Use empty slot for new entry
10690 + if( !hashtab[ h ])
10692 + co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
10693 + memset( co_new, 0, sizeof( tcplag_hash_T ));
10694 + co_new->low_ip = connection->low_ip;
10695 + co_new->high_ip = connection->high_ip;
10696 + co_new->stamp = event->stamp.tv_sec;
10697 + hashtab[ h ] = co_new;
10698 + DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
10701 + tcplag_event_T *ev_new;
10703 + ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
10704 + memcpy( ev_new, event, sizeof( tcplag_event_T ));
10707 + ev_new->next = co_new->h_ACK_list;
10708 + co_new->h_ACK_list = ev_new;
10709 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
10713 + ev_new->next = co_new->l_ACK_list;
10714 + co_new->l_ACK_list = ev_new;
10715 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
10722 + spin_unlock_bh( &hash_lock );
10726 + * Search the hash table for a matching connection,
10727 + * if we can't find one of those then we are stuffed.
10729 + * Once a connection has been found, scan along the list for
10730 + * a matching SEQ number and if that is found then calculate
10731 + * the lag, update the counters and cut the chain at the
10732 + * point where the matching SEQ is found.
10734 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
10738 + if( !event ) return( 0 );
10739 + if( !hashsize ) return( 0 );
10740 + if( !hashtab ) return( 0 );
10741 + h = make_hash( connection );
10744 + DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
10746 + for( i = 0; i < hashsize; i++ )
10748 + tcplag_hash_T *found = 0;
10750 + if( !hashtab[ h ]) return( 0 );
10752 + spin_lock_bh( &hash_lock );
10753 + if( hashtab[ h ])
10755 + if( !compare_connections( hashtab[ h ], connection ))
10757 + tcplag_event_T *ev, **evroot;
10761 + found = hashtab[ h ];
10764 + evroot = &found->h_ACK_list;
10765 + tv = &found->lag_l_SEQ_h_ACK;
10766 + cn = &found->count_l_SEQ_h_ACK;
10767 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
10771 + evroot = &found->l_ACK_list;
10772 + tv = &found->lag_h_SEQ_l_ACK;
10773 + cn = &found->count_h_SEQ_l_ACK;
10774 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
10776 + for( ev = *evroot; ev; ev = ev->next )
10778 + if( !compare_events( ev, event ))
10781 + * Calculate the lag (in two parts) and add that to the collection
10783 + event->stamp.tv_sec -= ev->stamp.tv_sec;
10784 + event->stamp.tv_usec -= ev->stamp.tv_usec;
10785 + if( event->stamp.tv_usec < 0 )
10787 + event->stamp.tv_usec += 1000000;
10788 + event->stamp.tv_sec++;
10790 + if( event->stamp.tv_sec < 0 )
10792 + DEBUGP( KERN_WARNING "Negative lag detected\n" );
10796 + tv->tv_sec += event->stamp.tv_sec;
10797 + tv->tv_usec += event->stamp.tv_usec;
10799 + DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
10800 + " (accumulator is up to %lu.%06lu, %u events)\n",
10801 + event->stamp.tv_sec,
10802 + event->stamp.tv_usec,
10803 + tv->tv_sec, tv->tv_usec, *cn );
10806 + * Truncate the linked list.
10808 + * Visit each event in the list and return the memory to the pool.
10810 + * If a host is making multiple connections to the same remote host
10811 + * then this truncation will result in some requests not being
10812 + * monitored. Statistically we will still get some reasonable number
10813 + * of measurements and multiple simultaneous connections between host
10814 + * pairs don't happen all that often.
10819 + tcplag_event_T *ev_next = ev->next;
10820 + DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
10825 + * TODO: overflow limit for *cn, force premature output() if necessary
10826 + * (and drop this connection from the hash table)
10835 + spin_unlock_bh( &hash_lock );
10837 + if( found ) return( 1 );
10838 + if( ++h >= hashsize ) h = 0;
10844 + * Here is our target data:
10846 + * pskb -- The packet itself (see linux/skbuff.h for breakdown)
10850 + * in -- The device that this packet came in on
10851 + * (depending on the chain this may or may not exist)
10853 + * out -- The device that this packet is just about to go
10854 + * out onto (again existance depends on the chain)
10856 + * targinfo -- Our private data (handed through from iptables command util)
10858 + * userinfo -- Some more data
10862 +static unsigned int target( struct sk_buff **pskb,
10863 + unsigned int hooknum,
10864 + const struct net_device *in,
10865 + const struct net_device *out,
10866 + const void *targinfo,
10869 + struct iphdr *iph = ( *pskb )->nh.iph;
10870 + const struct ipt_tcplag *el = targinfo;
10871 + tcplag_hash_T connection;
10872 + tcplag_event_T event;
10875 + * We know we are dealing with IP here
10876 + * Fill in all the obvious fields
10878 + if( iph->saddr > iph->daddr )
10881 + connection.high_ip = iph->saddr;
10882 + connection.low_ip = iph->daddr;
10887 + connection.low_ip = iph->saddr;
10888 + connection.high_ip = iph->daddr;
10890 + do_gettimeofday( &event.stamp );
10892 + * Do a bit of cleaning
10894 + reaper( event.stamp.tv_sec, el->level, el->prefix );
10896 + DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
10897 + event.stamp.tv_sec,
10898 + event.stamp.tv_usec,
10899 + in ? in->name : "none", out ? out->name : "none" );
10901 + * Now start looking at the details
10903 + * First step is to identify this packet to see if it is
10904 + * the sort of packet that we are interested in.
10905 + * Don't hold any locks while we are doing this because often
10906 + * we will just let the packet go without any further consideration.
10908 + switch( iph->protocol )
10910 + case IPPROTO_TCP:
10912 + struct tcphdr *tcp;
10914 + if( ntohs( iph->frag_off ) & IP_OFFSET )
10916 + DEBUGP( KERN_WARNING "ignoring fragment\n" );
10919 + tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
10920 + event.source_port = ntohs( tcp->source );
10921 + event.dest_port = ntohs( tcp->dest );
10923 + * Every packet should have a valid SEQ number so use this to
10924 + * generate an ACK number. This works along the formula:
10925 + * -- Start with the SEQ number
10926 + * -- For SYN or FIN add 1 to that number
10927 + * -- For data packet, add the data length to that number
10931 + * Data length requires a bit of fiddling around
10934 + unsigned int data_len;
10935 + if( tcp->syn || tcp->fin )
10937 + data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
10941 + data_len = ntohs( iph->tot_len );
10942 + data_len -= 4 * iph->ihl; /* Subtract away IP header & options */
10943 + data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
10946 + DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
10948 + if( data_len ) /* Only track events that demand an ACK */
10950 + event.expected_ACK = ntohl( tcp->seq ) + data_len;
10951 + hash_insert( &connection, &event, direction );
10955 + DEBUGP( "Don't bother to insert this, ACK not required\n" );
10962 + * Now we consider the matching of an existing event.
10963 + * Reverse the port numbers and change the ACK number to the actual ACK number
10964 + * Note that the direction is reversed because the reply will be going
10965 + * the opposite way to the request.
10967 + event.expected_ACK = ntohl( tcp->ack_seq );
10968 + event.dest_port = ntohs( tcp->source );
10969 + event.source_port = ntohs( tcp->dest );
10970 + request_complete( &connection, &event, !direction );
10974 + DEBUGP( "Don't bother to check this, ACK not valid\n" );
10978 + return( IPT_CONTINUE );
10982 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
10983 + * return( 1 ) if the entry is suitable
10989 + * targinfo -- Our private data block (handed to us from iptables plug-in)
10991 + * targinfosize -- The size of our private data block
10996 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
10997 + * all possible flag combos make sense. All we check for is correct data size.
10999 +static int checkentry( const char *tablename,
11000 + const struct ipt_entry *e,
11002 + unsigned int targinfosize,
11003 + unsigned int hook_mask )
11005 + const struct ipt_tcplag *el = targinfo;
11007 + if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
11009 + DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
11010 + IPT_ALIGN( sizeof( struct ipt_tcplag )));
11013 + if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
11017 +static struct ipt_target reg =
11027 +static int __init init( void )
11029 + if( ipt_register_target( ® )) return( -EINVAL );
11030 + hashsize = 123; /* should be configurable */
11031 + hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
11032 + memset( hashtab, 0, sizeof( void * ) * hashsize );
11037 + * This should not need locks (in theory)
11038 + * because it can only get punted after it is no longer
11039 + * chained into any of the netfilter lists.
11041 +static void __exit fini( void )
11045 + ipt_unregister_target( ® );
11047 + * Put back kernel memory
11049 + for( i = 0; i < hashsize; i++ )
11051 + tcplag_hash_T *p;
11053 + if(( p = hashtab[ i ]))
11055 + tcplag_event_T *ev, *evn;
11057 + hashtab[ i ] = 0;
11058 + for( ev = p->h_ACK_list; ev; ev = evn )
11063 + for( ev = p->l_ACK_list; ev; ev = evn )
11071 + kfree( hashtab );
11074 +module_init(init);
11075 +module_exit(fini);
11076 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6/net/ipv4/netfilter/ipt_TRACE.c
11077 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
11078 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TRACE.c 2004-05-18 12:38:32.000000000 +0200
11080 +/* This is a module which is used for setting
11081 + * the NFC_TRACE flag in the nfcache field of an skb.
11083 +#include <linux/module.h>
11084 +#include <linux/skbuff.h>
11086 +#include <linux/netfilter_ipv4/ip_tables.h>
11088 +static unsigned int
11089 +target(struct sk_buff **pskb,
11090 + const struct net_device *in,
11091 + const struct net_device *out,
11092 + unsigned int hooknum,
11093 + const void *targinfo,
11096 + (*pskb)->nfcache |= NFC_TRACE;
11097 + return IPT_CONTINUE;
11101 +checkentry(const char *tablename,
11102 + const struct ipt_entry *e,
11104 + unsigned int targinfosize,
11105 + unsigned int hook_mask)
11107 + if (targinfosize != 0) {
11108 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
11113 + if (strcmp(tablename, "raw") != 0) {
11114 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
11121 +static struct ipt_target ipt_trace_reg = {
11123 + .target = target,
11124 + .checkentry = checkentry,
11125 + .me = THIS_MODULE
11128 +static int __init init(void)
11130 + if (ipt_register_target(&ipt_trace_reg))
11136 +static void __exit fini(void)
11138 + ipt_unregister_target(&ipt_trace_reg);
11141 +module_init(init);
11142 +module_exit(fini);
11143 +MODULE_LICENSE("GPL");
11144 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.6/net/ipv4/netfilter/ipt_TTL.c
11145 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
11146 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TTL.c 2004-05-18 12:36:09.000000000 +0200
11148 +/* TTL modification target for IP tables
11149 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
11151 + * Version: $Revision$
11153 + * This software is distributed under the terms of GNU GPL
11156 +#include <linux/module.h>
11157 +#include <linux/skbuff.h>
11158 +#include <linux/ip.h>
11159 +#include <net/checksum.h>
11161 +#include <linux/netfilter_ipv4/ip_tables.h>
11162 +#include <linux/netfilter_ipv4/ipt_TTL.h>
11164 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
11165 +MODULE_DESCRIPTION("IP tables TTL modification module");
11166 +MODULE_LICENSE("GPL");
11168 +static unsigned int
11169 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
11170 + const struct net_device *out, unsigned int hooknum,
11171 + const void *targinfo, void *userinfo)
11173 + struct iphdr *iph;
11174 + const struct ipt_TTL_info *info = targinfo;
11175 + u_int16_t diffs[2];
11178 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
11181 + iph = (*pskb)->nh.iph;
11183 + switch (info->mode) {
11184 + case IPT_TTL_SET:
11185 + new_ttl = info->ttl;
11187 + case IPT_TTL_INC:
11188 + new_ttl = iph->ttl + info->ttl;
11189 + if (new_ttl > 255)
11192 + case IPT_TTL_DEC:
11193 + new_ttl = iph->ttl + info->ttl;
11198 + new_ttl = iph->ttl;
11202 + if (new_ttl != iph->ttl) {
11203 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
11204 + iph->ttl = new_ttl;
11205 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
11206 + iph->check = csum_fold(csum_partial((char *)diffs,
11208 + iph->check^0xFFFF));
11209 + (*pskb)->nfcache |= NFC_ALTERED;
11212 + return IPT_CONTINUE;
11215 +static int ipt_ttl_checkentry(const char *tablename,
11216 + const struct ipt_entry *e,
11218 + unsigned int targinfosize,
11219 + unsigned int hook_mask)
11221 + struct ipt_TTL_info *info = targinfo;
11223 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
11224 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
11226 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
11230 + if (strcmp(tablename, "mangle")) {
11231 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
11235 + if (info->mode > IPT_TTL_MAXMODE) {
11236 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
11241 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
11242 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
11249 +static struct ipt_target ipt_TTL = {
11251 + .target = ipt_ttl_target,
11252 + .checkentry = ipt_ttl_checkentry,
11253 + .me = THIS_MODULE
11256 +static int __init init(void)
11258 + return ipt_register_target(&ipt_TTL);
11261 +static void __exit fini(void)
11263 + ipt_unregister_target(&ipt_TTL);
11266 +module_init(init);
11267 +module_exit(fini);
11268 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6/net/ipv4/netfilter/ipt_XOR.c
11269 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
11270 +++ linux-2.6.6/net/ipv4/netfilter/ipt_XOR.c 2004-05-18 12:38:34.000000000 +0200
11272 +/* XOR target for IP tables
11273 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
11274 + * Based on ipt_TTL.c
11278 + * This software is distributed under the terms of GNU GPL
11281 +#include <linux/module.h>
11282 +#include <linux/skbuff.h>
11283 +#include <linux/ip.h>
11284 +#include <linux/tcp.h>
11285 +#include <linux/udp.h>
11287 +#include <linux/netfilter_ipv4/ip_tables.h>
11288 +#include <linux/netfilter_ipv4/ipt_XOR.h>
11290 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
11291 +MODULE_DESCRIPTION("IP tables XOR module");
11292 +MODULE_LICENSE("GPL");
11294 +static unsigned int
11295 +ipt_xor_target(struct sk_buff **pskb,
11296 + const struct net_device *in, const struct net_device *out,
11297 + unsigned int hooknum, const void *targinfo, void *userinfo)
11299 + struct ipt_XOR_info *info = (void *) targinfo;
11300 + struct iphdr *iph;
11301 + struct tcphdr *tcph;
11302 + struct udphdr *udph;
11305 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
11308 + iph = (*pskb)->nh.iph;
11310 + if (iph->protocol == IPPROTO_TCP) {
11311 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
11312 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
11313 + for (k=0; k<=info->block_size; k++) {
11314 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
11319 + if (info->key[j] == 0x00)
11322 + } else if (iph->protocol == IPPROTO_UDP) {
11323 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
11324 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
11325 + for (k=0; k<=info->block_size; k++) {
11326 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
11331 + if (info->key[j] == 0x00)
11336 + return IPT_CONTINUE;
11339 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
11340 + void *targinfo, unsigned int targinfosize,
11341 + unsigned int hook_mask)
11343 + struct ipt_XOR_info *info = targinfo;
11345 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
11346 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
11347 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
11351 + if (strcmp(tablename, "mangle")) {
11352 + printk(KERN_WARNING "XOR: can only be called from"
11353 + "\"mangle\" table, not \"%s\"\n", tablename);
11357 + if (!strcmp(info->key, "")) {
11358 + printk(KERN_WARNING "XOR: You must specify a key");
11362 + if (info->block_size == 0) {
11363 + printk(KERN_WARNING "XOR: You must specify a block-size");
11370 +static struct ipt_target ipt_XOR = {
11372 + .target = ipt_xor_target,
11373 + .checkentry = ipt_xor_checkentry,
11374 + .me = THIS_MODULE,
11377 +static int __init init(void)
11379 + return ipt_register_target(&ipt_XOR);
11382 +static void __exit fini(void)
11384 + ipt_unregister_target(&ipt_XOR);
11387 +module_init(init);
11388 +module_exit(fini);
11389 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6/net/ipv4/netfilter/ipt_addrtype.c
11390 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
11391 +++ linux-2.6.6/net/ipv4/netfilter/ipt_addrtype.c 2004-05-18 12:38:44.000000000 +0200
11394 + * iptables module to match inet_addr_type() of an ip.
11397 +#include <linux/module.h>
11398 +#include <linux/skbuff.h>
11399 +#include <linux/netdevice.h>
11400 +#include <net/route.h>
11402 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
11403 +#include <linux/netfilter_ipv4/ip_tables.h>
11405 +MODULE_LICENSE("GPL");
11407 +static inline int match_type(u_int32_t addr, u_int16_t mask)
11409 + return !!(mask & (1 << inet_addr_type(addr)));
11412 +static int match(const struct sk_buff *skb, const struct net_device *in,
11413 + const struct net_device *out, const void *matchinfo,
11414 + int offset, int *hotdrop)
11416 + const struct ipt_addrtype_info *info = matchinfo;
11417 + const struct iphdr *iph = skb->nh.iph;
11420 + if (info->source)
11421 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
11423 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
11428 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
11429 + void *matchinfo, unsigned int matchsize,
11430 + unsigned int hook_mask)
11432 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
11433 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
11434 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
11441 +static struct ipt_match addrtype_match = {
11442 + .name = "addrtype",
11444 + .checkentry = checkentry,
11445 + .me = THIS_MODULE
11448 +static int __init init(void)
11450 + return ipt_register_match(&addrtype_match);
11453 +static void __exit fini(void)
11455 + ipt_unregister_match(&addrtype_match);
11459 +module_init(init);
11460 +module_exit(fini);
11461 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.6/net/ipv4/netfilter/ipt_connlimit.c
11462 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
11463 +++ linux-2.6.6/net/ipv4/netfilter/ipt_connlimit.c 2004-05-18 12:36:13.000000000 +0200
11466 + * netfilter module to limit the number of parallel tcp
11467 + * connections per IP address.
11468 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
11469 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
11470 + * only ignore TIME_WAIT or gone connections
11474 + * Kernel module to match connection tracking information.
11475 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
11477 +#include <linux/module.h>
11478 +#include <linux/skbuff.h>
11479 +#include <linux/list.h>
11480 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11481 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
11482 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
11483 +#include <linux/netfilter_ipv4/ip_tables.h>
11484 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
11488 +MODULE_LICENSE("GPL");
11490 +/* we'll save the tuples of all connections we care about */
11491 +struct ipt_connlimit_conn
11493 + struct list_head list;
11494 + struct ip_conntrack_tuple tuple;
11497 +struct ipt_connlimit_data {
11499 + struct list_head iphash[256];
11502 +static int ipt_iphash(u_int32_t addr)
11506 + hash = addr & 0xff;
11507 + hash ^= (addr >> 8) & 0xff;
11508 + hash ^= (addr >> 16) & 0xff;
11509 + hash ^= (addr >> 24) & 0xff;
11513 +static int count_them(struct ipt_connlimit_data *data,
11514 + u_int32_t addr, u_int32_t mask,
11515 + struct ip_conntrack *ct)
11518 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
11519 + "fin_wait", "time_wait", "close", "close_wait",
11520 + "last_ack", "listen" };
11522 + int addit = 1, matches = 0;
11523 + struct ip_conntrack_tuple tuple;
11524 + struct ip_conntrack_tuple_hash *found;
11525 + struct ipt_connlimit_conn *conn;
11526 + struct list_head *hash,*lh;
11528 + spin_lock(&data->lock);
11529 + tuple = ct->tuplehash[0].tuple;
11530 + hash = &data->iphash[ipt_iphash(addr & mask)];
11532 + /* check the saved connections */
11533 + for (lh = hash->next; lh != hash; lh = lh->next) {
11534 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
11535 + found = ip_conntrack_find_get(&conn->tuple,ct);
11536 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
11538 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
11539 + /* Just to be sure we have it only once in the list.
11540 + We should'nt see tuples twice unless someone hooks this
11541 + into a table without "-p tcp --syn" */
11545 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
11546 + ipt_iphash(addr & mask),
11547 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
11548 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
11549 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
11551 + if (NULL == found) {
11552 + /* this one is gone */
11554 + list_del(lh->next);
11558 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
11559 + /* we don't care about connections which are
11560 + closed already -> ditch it */
11562 + list_del(lh->next);
11564 + nf_conntrack_put(&found->ctrack->infos[0]);
11567 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
11568 + /* same source IP address -> be counted! */
11571 + nf_conntrack_put(&found->ctrack->infos[0]);
11574 + /* save the new connection in our list */
11576 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
11577 + ipt_iphash(addr & mask),
11578 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
11579 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
11581 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
11582 + if (NULL == conn)
11584 + memset(conn,0,sizeof(*conn));
11585 + INIT_LIST_HEAD(&conn->list);
11586 + conn->tuple = tuple;
11587 + list_add(&conn->list,hash);
11590 + spin_unlock(&data->lock);
11595 +match(const struct sk_buff *skb,
11596 + const struct net_device *in,
11597 + const struct net_device *out,
11598 + const void *matchinfo,
11602 + const struct ipt_connlimit_info *info = matchinfo;
11603 + int connections, match;
11604 + struct ip_conntrack *ct;
11605 + enum ip_conntrack_info ctinfo;
11607 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11608 + if (NULL == ct) {
11609 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
11613 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
11614 + if (-1 == connections) {
11615 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
11616 + *hotdrop = 1; /* let's free some memory :-) */
11619 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
11621 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
11622 + "connections=%d limit=%d match=%s\n",
11623 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
11624 + connections, info->limit, match ? "yes" : "no");
11630 +static int check(const char *tablename,
11631 + const struct ipt_ip *ip,
11633 + unsigned int matchsize,
11634 + unsigned int hook_mask)
11636 + struct ipt_connlimit_info *info = matchinfo;
11639 + /* verify size */
11640 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
11643 + /* refuse anything but tcp */
11644 + if (ip->proto != IPPROTO_TCP)
11647 + /* init private data */
11648 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
11649 + spin_lock_init(&(info->data->lock));
11650 + for (i = 0; i < 256; i++)
11651 + INIT_LIST_HEAD(&(info->data->iphash[i]));
11656 +static void destroy(void *matchinfo, unsigned int matchinfosize)
11658 + struct ipt_connlimit_info *info = matchinfo;
11659 + struct ipt_connlimit_conn *conn;
11660 + struct list_head *hash;
11664 + for (i = 0; i < 256; i++) {
11665 + hash = &(info->data->iphash[i]);
11666 + while (hash != hash->next) {
11667 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
11668 + list_del(hash->next);
11672 + kfree(info->data);
11675 +static struct ipt_match connlimit_match = {
11676 + .name = "connlimit",
11678 + .checkentry = &check,
11679 + .destroy = &destroy,
11680 + .me = THIS_MODULE
11683 +static int __init init(void)
11685 + return ipt_register_match(&connlimit_match);
11688 +static void __exit fini(void)
11690 + ipt_unregister_match(&connlimit_match);
11693 +module_init(init);
11694 +module_exit(fini);
11695 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6/net/ipv4/netfilter/ipt_connmark.c
11696 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
11697 +++ linux-2.6.6/net/ipv4/netfilter/ipt_connmark.c 2004-05-18 12:38:02.000000000 +0200
11699 +/* This kernel module matches connection mark values set by the
11700 + * CONNMARK target
11702 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
11703 + * by Henrik Nordstrom <hno@marasystems.com>
11705 + * This program is free software; you can redistribute it and/or modify
11706 + * it under the terms of the GNU General Public License as published by
11707 + * the Free Software Foundation; either version 2 of the License, or
11708 + * (at your option) any later version.
11710 + * This program is distributed in the hope that it will be useful,
11711 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11712 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11713 + * GNU General Public License for more details.
11715 + * You should have received a copy of the GNU General Public License
11716 + * along with this program; if not, write to the Free Software
11717 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11720 +#include <linux/module.h>
11721 +#include <linux/skbuff.h>
11723 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
11724 +MODULE_DESCRIPTION("IP tables connmark match module");
11725 +MODULE_LICENSE("GPL");
11727 +#include <linux/netfilter_ipv4/ip_tables.h>
11728 +#include <linux/netfilter_ipv4/ipt_connmark.h>
11729 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11732 +match(const struct sk_buff *skb,
11733 + const struct net_device *in,
11734 + const struct net_device *out,
11735 + const void *matchinfo,
11739 + const struct ipt_connmark_info *info = matchinfo;
11740 + enum ip_conntrack_info ctinfo;
11741 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11745 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
11749 +checkentry(const char *tablename,
11750 + const struct ipt_ip *ip,
11752 + unsigned int matchsize,
11753 + unsigned int hook_mask)
11755 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
11761 +static struct ipt_match connmark_match = {
11762 + .name = "connmark",
11764 + .checkentry = &checkentry,
11765 + .me = THIS_MODULE
11768 +static int __init init(void)
11770 + return ipt_register_match(&connmark_match);
11773 +static void __exit fini(void)
11775 + ipt_unregister_match(&connmark_match);
11778 +module_init(init);
11779 +module_exit(fini);
11780 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.6/net/ipv4/netfilter/ipt_dstlimit.c
11781 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
11782 +++ linux-2.6.6/net/ipv4/netfilter/ipt_dstlimit.c 2004-05-18 12:36:19.000000000 +0200
11784 +/* iptables match extension to limit the number of packets per second
11785 + * seperately for each destination.
11787 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
11791 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
11793 + * based on ipt_limit.c by:
11794 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
11795 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
11796 + * Rusty Russell <rusty@rustcorp.com.au>
11798 + * The general idea is to create a hash table for every dstip and have a
11799 + * seperate limit counter per tuple. This way you can do something like 'limit
11800 + * the number of syn packets for each of my internal addresses.
11802 + * Ideally this would just be implemented as a general 'hash' match, which would
11803 + * allow us to attach any iptables target to it's hash buckets. But this is
11804 + * not possible in the current iptables architecture. As always, pkttables for
11805 + * 2.7.x will help ;)
11807 +#include <linux/module.h>
11808 +#include <linux/skbuff.h>
11809 +#include <linux/spinlock.h>
11810 +#include <linux/random.h>
11811 +#include <linux/jhash.h>
11812 +#include <linux/slab.h>
11813 +#include <linux/vmalloc.h>
11814 +#include <linux/tcp.h>
11815 +#include <linux/udp.h>
11816 +#include <linux/proc_fs.h>
11817 +#include <linux/seq_file.h>
11819 +#define ASSERT_READ_LOCK(x)
11820 +#define ASSERT_WRITE_LOCK(x)
11821 +#include <linux/netfilter_ipv4/lockhelp.h>
11822 +#include <linux/netfilter_ipv4/listhelp.h>
11824 +#include <linux/netfilter_ipv4/ip_tables.h>
11825 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
11827 +/* FIXME: this is just for IP_NF_ASSERRT */
11828 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11830 +#define MS2JIFFIES(x) ((x*HZ)/1000)
11832 +MODULE_LICENSE("GPL");
11833 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
11834 +MODULE_DESCRIPTION("iptables match for limiting per destination");
11836 +/* need to declare this at the top */
11837 +static struct proc_dir_entry *dstlimit_procdir;
11838 +static struct file_operations dl_file_ops;
11840 +/* hash table crap */
11842 +struct dsthash_dst {
11843 + u_int32_t src_ip;
11844 + u_int32_t dst_ip;
11848 +struct dsthash_ent {
11849 + /* static / read-only parts in the beginning */
11850 + struct list_head list;
11851 + struct dsthash_dst dst;
11853 + /* modified structure members in the end */
11854 + unsigned long expires; /* precalculated expiry time */
11856 + unsigned long prev; /* last modification */
11857 + u_int32_t credit;
11858 + u_int32_t credit_cap, cost;
11862 +struct ipt_dstlimit_htable {
11863 + struct list_head list; /* global list of all htables */
11866 + struct dstlimit_cfg cfg; /* config */
11868 + /* used internally */
11869 + spinlock_t lock; /* lock for list_head */
11870 + u_int32_t rnd; /* random seed for hash */
11871 + struct timer_list timer; /* timer for gc */
11872 + atomic_t count; /* number entries in table */
11874 + /* seq_file stuff */
11875 + struct proc_dir_entry *pde;
11877 + struct list_head hash[0]; /* hashtable itself */
11880 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
11881 +static LIST_HEAD(dstlimit_htables);
11882 +static kmem_cache_t *dstlimit_cachep;
11884 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
11886 + return (ent->dst.dst_ip == b->dst_ip
11887 + && ent->dst.port == b->port
11888 + && ent->dst.src_ip == b->src_ip);
11891 +static inline u_int32_t
11892 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
11894 + return (jhash_3words(dst->dst_ip, dst->port,
11895 + dst->src_ip, ht->rnd) % ht->cfg.size);
11898 +static inline struct dsthash_ent *
11899 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11901 + struct dsthash_ent *ent;
11902 + u_int32_t hash = hash_dst(ht, dst);
11903 + MUST_BE_LOCKED(&ht->lock);
11904 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
11908 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
11909 +static struct dsthash_ent *
11910 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11912 + struct dsthash_ent *ent;
11914 + /* initialize hash with random val at the time we allocate
11915 + * the first hashtable entry */
11917 + get_random_bytes(&ht->rnd, 4);
11919 + if (ht->cfg.max &&
11920 + atomic_read(&ht->count) >= ht->cfg.max) {
11921 + /* FIXME: do something. question is what.. */
11922 + if (net_ratelimit())
11923 + printk(KERN_WARNING
11924 + "ipt_dstlimit: max count of %u reached\n",
11929 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
11931 + if (net_ratelimit())
11933 + "ipt_dstlimit: can't allocate dsthash_ent\n");
11937 + atomic_inc(&ht->count);
11939 + ent->dst.dst_ip = dst->dst_ip;
11940 + ent->dst.port = dst->port;
11941 + ent->dst.src_ip = dst->src_ip;
11943 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
11948 +static inline void
11949 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
11951 + MUST_BE_LOCKED(&ht->lock);
11953 + list_del(&ent->list);
11954 + kmem_cache_free(dstlimit_cachep, ent);
11955 + atomic_dec(&ht->count);
11957 +static void htable_gc(unsigned long htlong);
11959 +static int htable_create(struct ipt_dstlimit_info *minfo)
11962 + unsigned int size;
11963 + struct ipt_dstlimit_htable *hinfo;
11965 + if (minfo->cfg.size)
11966 + size = minfo->cfg.size;
11968 + size = (((num_physpages << PAGE_SHIFT) / 16384)
11969 + / sizeof(struct list_head));
11970 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
11975 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
11976 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
11977 + + (sizeof(struct list_head) * size));
11979 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
11982 + minfo->hinfo = hinfo;
11984 + /* copy match config into hashtable config */
11985 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
11986 + hinfo->cfg.size = size;
11987 + if (!hinfo->cfg.max)
11988 + hinfo->cfg.max = 8 * hinfo->cfg.size;
11989 + else if (hinfo->cfg.max < hinfo->cfg.size)
11990 + hinfo->cfg.max = hinfo->cfg.size;
11992 + for (i = 0; i < hinfo->cfg.size; i++)
11993 + INIT_LIST_HEAD(&hinfo->hash[i]);
11995 + atomic_set(&hinfo->count, 0);
11996 + atomic_set(&hinfo->use, 1);
11998 + hinfo->lock = SPIN_LOCK_UNLOCKED;
11999 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
12000 + if (!hinfo->pde) {
12004 + hinfo->pde->proc_fops = &dl_file_ops;
12005 + hinfo->pde->data = hinfo;
12007 + init_timer(&hinfo->timer);
12008 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
12009 + hinfo->timer.data = (unsigned long )hinfo;
12010 + hinfo->timer.function = htable_gc;
12011 + add_timer(&hinfo->timer);
12013 + WRITE_LOCK(&dstlimit_lock);
12014 + list_add(&hinfo->list, &dstlimit_htables);
12015 + WRITE_UNLOCK(&dstlimit_lock);
12020 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12025 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12027 + return (jiffies >= he->expires);
12030 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
12031 + int (*select)(struct ipt_dstlimit_htable *ht,
12032 + struct dsthash_ent *he))
12036 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
12038 + /* lock hash table and iterate over it */
12039 + LOCK_BH(&ht->lock);
12040 + for (i = 0; i < ht->cfg.size; i++) {
12041 + struct dsthash_ent *dh, *n;
12042 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
12043 + if ((*select)(ht, dh))
12044 + __dsthash_free(ht, dh);
12047 + UNLOCK_BH(&ht->lock);
12050 +/* hash table garbage collector, run by timer */
12051 +static void htable_gc(unsigned long htlong)
12053 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
12055 + htable_selective_cleanup(ht, select_gc);
12057 + /* re-add the timer accordingly */
12058 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
12059 + add_timer(&ht->timer);
12062 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
12064 + /* remove timer, if it is pending */
12065 + if (timer_pending(&hinfo->timer))
12066 + del_timer(&hinfo->timer);
12068 + /* remove proc entry */
12069 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
12071 + htable_selective_cleanup(hinfo, select_all);
12075 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
12077 + struct ipt_dstlimit_htable *hinfo;
12079 + READ_LOCK(&dstlimit_lock);
12080 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
12081 + if (!strcmp(name, hinfo->pde->name)) {
12082 + atomic_inc(&hinfo->use);
12083 + READ_UNLOCK(&dstlimit_lock);
12087 + READ_UNLOCK(&dstlimit_lock);
12092 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
12094 + if (atomic_dec_and_test(&hinfo->use)) {
12095 + WRITE_LOCK(&dstlimit_lock);
12096 + list_del(&hinfo->list);
12097 + WRITE_UNLOCK(&dstlimit_lock);
12098 + htable_destroy(hinfo);
12103 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
12104 + * see net/sched/sch_tbf.c in the linux source tree
12107 +/* Rusty: This is my (non-mathematically-inclined) understanding of
12108 + this algorithm. The `average rate' in jiffies becomes your initial
12109 + amount of credit `credit' and the most credit you can ever have
12110 + `credit_cap'. The `peak rate' becomes the cost of passing the
12113 + `prev' tracks the last packet hit: you gain one credit per jiffy.
12114 + If you get credit balance more than this, the extra credit is
12115 + discarded. Every time the match passes, you lose `cost' credits;
12116 + if you don't have that many, the test fails.
12118 + See Alexey's formal explanation in net/sched/sch_tbf.c.
12120 + To get the maximum range, we multiply by this factor (ie. you get N
12121 + credits per jiffy). We want to allow a rate as low as 1 per day
12122 + (slowest userspace tool allows), which means
12123 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
12125 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
12127 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
12128 + * us the power of 2 below the theoretical max, so GCC simply does a
12130 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
12131 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
12132 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
12133 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
12134 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
12135 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
12137 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
12139 +/* Precision saver. */
12140 +static inline u_int32_t
12141 +user2credits(u_int32_t user)
12143 + /* If multiplying would overflow... */
12144 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
12145 + /* Divide first. */
12146 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
12148 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
12151 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
12153 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
12154 + * CREDITS_PER_JIFFY;
12155 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
12156 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
12160 +dstlimit_match(const struct sk_buff *skb,
12161 + const struct net_device *in,
12162 + const struct net_device *out,
12163 + const void *matchinfo,
12167 + struct ipt_dstlimit_info *r =
12168 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
12169 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
12170 + unsigned long now = jiffies;
12171 + struct dsthash_ent *dh;
12172 + struct dsthash_dst dst;
12174 + memset(&dst, 0, sizeof(dst));
12176 + /* dest ip is always in hash */
12177 + dst.dst_ip = skb->nh.iph->daddr;
12179 + /* source ip only if respective hashmode, otherwise set to
12181 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
12182 + dst.src_ip = skb->nh.iph->saddr;
12184 + /* dest port only if respective mode */
12185 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
12188 + /* Must not be a fragment. */
12192 + /* Must be big enough to read ports (both UDP and TCP have
12193 + them at the start). */
12194 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12195 + /* We've been asked to examine this packet, and we
12196 + can't. Hence, no choice but to drop. */
12201 + switch (skb->nh.iph->protocol) {
12202 + struct tcphdr *th;
12203 + struct udphdr *uh;
12204 + case IPPROTO_TCP:
12205 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12206 + dst.port = th->dest;
12208 + case IPPROTO_UDP:
12209 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12210 + dst.port = uh->dest;
12217 + LOCK_BH(&hinfo->lock);
12218 + dh = __dsthash_find(hinfo, &dst);
12220 + dh = __dsthash_alloc_init(hinfo, &dst);
12223 + /* enomem... don't match == DROP */
12224 + if (net_ratelimit())
12225 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
12226 + UNLOCK_BH(&hinfo->lock);
12230 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
12232 + dh->rateinfo.prev = jiffies;
12233 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
12234 + hinfo->cfg.burst);
12235 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
12236 + hinfo->cfg.burst);
12237 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
12239 + UNLOCK_BH(&hinfo->lock);
12243 + /* update expiration timeout */
12244 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
12246 + rateinfo_recalc(dh, now);
12247 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
12248 + /* We're underlimit. */
12249 + dh->rateinfo.credit -= dh->rateinfo.cost;
12250 + UNLOCK_BH(&hinfo->lock);
12254 + UNLOCK_BH(&hinfo->lock);
12256 + /* default case: we're overlimit, thus don't match */
12261 +dstlimit_checkentry(const char *tablename,
12262 + const struct ipt_ip *ip,
12264 + unsigned int matchsize,
12265 + unsigned int hook_mask)
12267 + struct ipt_dstlimit_info *r = matchinfo;
12269 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
12272 + /* Check for overflow. */
12273 + if (r->cfg.burst == 0
12274 + || user2credits(r->cfg.avg * r->cfg.burst) <
12275 + user2credits(r->cfg.avg)) {
12276 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
12277 + r->cfg.avg, r->cfg.burst);
12281 + if (r->cfg.mode == 0
12282 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
12283 + |IPT_DSTLIMIT_HASH_DIP
12284 + |IPT_DSTLIMIT_HASH_SIP))
12287 + if (!r->cfg.gc_interval)
12290 + if (!r->cfg.expire)
12293 + r->hinfo = htable_find_get(r->name);
12294 + if (!r->hinfo && (htable_create(r) != 0)) {
12298 + /* Ugly hack: For SMP, we only want to use one set */
12305 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
12307 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
12309 + htable_put(r->hinfo);
12312 +static struct ipt_match ipt_dstlimit = {
12313 + .list = { .prev = NULL, .next = NULL },
12314 + .name = "dstlimit",
12315 + .match = dstlimit_match,
12316 + .checkentry = dstlimit_checkentry,
12317 + .destroy = dstlimit_destroy,
12318 + .me = THIS_MODULE
12323 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
12325 + struct proc_dir_entry *pde = s->private;
12326 + struct ipt_dstlimit_htable *htable = pde->data;
12327 + unsigned int *bucket;
12329 + LOCK_BH(&htable->lock);
12330 + if (*pos >= htable->cfg.size)
12333 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
12335 + return ERR_PTR(-ENOMEM);
12341 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
12343 + struct proc_dir_entry *pde = s->private;
12344 + struct ipt_dstlimit_htable *htable = pde->data;
12345 + unsigned int *bucket = (unsigned int *)v;
12347 + *pos = ++(*bucket);
12348 + if (*pos >= htable->cfg.size) {
12355 +static void dl_seq_stop(struct seq_file *s, void *v)
12357 + struct proc_dir_entry *pde = s->private;
12358 + struct ipt_dstlimit_htable *htable = pde->data;
12359 + unsigned int *bucket = (unsigned int *)v;
12363 + UNLOCK_BH(&htable->lock);
12366 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
12368 + /* recalculate to show accurate numbers */
12369 + rateinfo_recalc(ent, jiffies);
12371 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
12372 + (ent->expires - jiffies)/HZ,
12373 + NIPQUAD(ent->dst.src_ip),
12374 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
12375 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
12376 + ent->rateinfo.cost);
12379 +static int dl_seq_show(struct seq_file *s, void *v)
12381 + struct proc_dir_entry *pde = s->private;
12382 + struct ipt_dstlimit_htable *htable = pde->data;
12383 + unsigned int *bucket = (unsigned int *)v;
12385 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
12386 + struct dsthash_ent *, s)) {
12387 + /* buffer was filled and unable to print that tuple */
12393 +static struct seq_operations dl_seq_ops = {
12394 + .start = dl_seq_start,
12395 + .next = dl_seq_next,
12396 + .stop = dl_seq_stop,
12397 + .show = dl_seq_show
12400 +static int dl_proc_open(struct inode *inode, struct file *file)
12402 + int ret = seq_open(file, &dl_seq_ops);
12405 + struct seq_file *sf = file->private_data;
12406 + sf->private = PDE(inode);
12411 +static struct file_operations dl_file_ops = {
12412 + .owner = THIS_MODULE,
12413 + .open = dl_proc_open,
12414 + .read = seq_read,
12415 + .llseek = seq_lseek,
12416 + .release = seq_release
12419 +static int init_or_fini(int fini)
12426 + if (ipt_register_match(&ipt_dstlimit)) {
12428 + goto cleanup_nothing;
12431 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
12432 + * quite small ? */
12433 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
12434 + sizeof(struct dsthash_ent), 0,
12435 + SLAB_HWCACHE_ALIGN, NULL, NULL);
12436 + if (!dstlimit_cachep) {
12437 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
12439 + goto cleanup_unreg_match;
12442 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
12443 + if (!dstlimit_procdir) {
12444 + printk(KERN_ERR "Unable to create proc dir entry\n");
12446 + goto cleanup_free_slab;
12452 + remove_proc_entry("ipt_dstlimit", proc_net);
12453 +cleanup_free_slab:
12454 + kmem_cache_destroy(dstlimit_cachep);
12455 +cleanup_unreg_match:
12456 + ipt_unregister_match(&ipt_dstlimit);
12462 +static int __init init(void)
12464 + return init_or_fini(0);
12467 +static void __exit fini(void)
12472 +module_init(init);
12473 +module_exit(fini);
12474 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.6/net/ipv4/netfilter/ipt_fuzzy.c
12475 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
12476 +++ linux-2.6.6/net/ipv4/netfilter/ipt_fuzzy.c 2004-05-18 12:36:22.000000000 +0200
12479 + * This module implements a simple TSK FLC
12480 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
12481 + * to limit , in an adaptive and flexible way , the packet rate crossing
12482 + * a given stream . It serves as an initial and very simple (but effective)
12483 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
12484 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
12485 + * into our code in a precise , adaptive and efficient manner.
12486 + * The goal is very similar to that of "limit" match , but using techniques of
12487 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
12488 + * avoiding over and undershoots - and stuff like that .
12491 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
12492 + * 2002-08-17 : Changed to eliminate floating point operations .
12493 + * 2002-08-23 : Coding style changes .
12496 +#include <linux/module.h>
12497 +#include <linux/skbuff.h>
12498 +#include <linux/ip.h>
12499 +#include <linux/random.h>
12500 +#include <net/tcp.h>
12501 +#include <linux/spinlock.h>
12502 +#include <linux/netfilter_ipv4/ip_tables.h>
12503 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
12506 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
12507 + Expressed in percentage
12510 +#define PAR_LOW 1/100
12511 +#define PAR_HIGH 1
12513 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
12515 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
12516 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
12517 +MODULE_LICENSE("GPL");
12519 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12527 + return ( (100*(tx-mini)) / (maxi-mini) );
12530 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12538 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
12542 +ipt_fuzzy_match(const struct sk_buff *pskb,
12543 + const struct net_device *in,
12544 + const struct net_device *out,
12545 + const void *matchinfo,
12549 + /* From userspace */
12551 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
12553 + u_int8_t random_number;
12554 + unsigned long amount;
12555 + u_int8_t howhigh, howlow;
12558 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
12560 + info->bytes_total += pskb->len;
12561 + info->packets_total++;
12563 + info->present_time = jiffies;
12565 + if (info->present_time >= info->previous_time)
12566 + amount = info->present_time - info->previous_time;
12568 + /* There was a transition : I choose to re-sample
12569 + and keep the old acceptance rate...
12573 + info->previous_time = info->present_time;
12574 + info->bytes_total = info->packets_total = 0;
12577 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
12580 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
12583 + info->previous_time = info->present_time;
12584 + info->bytes_total = info->packets_total = 0;
12586 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
12587 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
12589 + info->acceptance_rate = (u_int8_t) \
12590 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
12592 + /* In fact , the above defuzzification would require a denominator
12593 + proportional to (howhigh+howlow) but , in this particular case ,
12594 + that expression is constant .
12595 + An imediate consequence is that it isn't necessary to call
12596 + both mf_high and mf_low - but to keep things understandable ,
12601 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
12604 + if ( info->acceptance_rate < 100 )
12606 + get_random_bytes((void *)(&random_number), 1);
12608 + /* If within the acceptance , it can pass => don't match */
12609 + if (random_number <= (255 * info->acceptance_rate) / 100)
12612 + return 1; /* It can't pass ( It matches ) */
12615 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
12620 +ipt_fuzzy_checkentry(const char *tablename,
12621 + const struct ipt_ip *e,
12623 + unsigned int matchsize,
12624 + unsigned int hook_mask)
12627 + const struct ipt_fuzzy_info *info = matchinfo;
12629 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
12630 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
12631 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
12635 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
12636 + || (info->minimum_rate >= info->maximum_rate )) {
12637 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
12644 +static struct ipt_match ipt_fuzzy_reg = {
12646 + .match = ipt_fuzzy_match,
12647 + .checkentry = ipt_fuzzy_checkentry,
12648 + .me = THIS_MODULE
12651 +static int __init init(void)
12653 + return ipt_register_match(&ipt_fuzzy_reg);
12656 +static void __exit fini(void)
12658 + ipt_unregister_match(&ipt_fuzzy_reg);
12661 +module_init(init);
12662 +module_exit(fini);
12663 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6/net/ipv4/netfilter/ipt_helper.c
12664 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_helper.c 2004-05-10 04:32:54.000000000 +0200
12665 +++ linux-2.6.6/net/ipv4/netfilter/ipt_helper.c 2004-05-18 12:39:27.000000000 +0200
12666 @@ -41,17 +41,17 @@
12667 struct ip_conntrack_expect *exp;
12668 struct ip_conntrack *ct;
12669 enum ip_conntrack_info ctinfo;
12671 + int ret = info->invert;
12673 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12675 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
12681 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
12688 DEBUGP("master's name = %s , info->name = %s\n",
12689 exp->expectant->helper->name, info->name);
12691 - ret = !strncmp(exp->expectant->helper->name, info->name,
12692 - strlen(exp->expectant->helper->name)) ^ info->invert;
12693 + if (info->name[0] == '\0')
12696 + ret ^= !strncmp(exp->expectant->helper->name, info->name,
12697 + strlen(exp->expectant->helper->name));
12699 READ_UNLOCK(&ip_conntrack_lock);
12702 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
12705 - /* verify that we actually should match anything */
12706 - if ( strlen(info->name) == 0 )
12712 @@ -108,7 +107,6 @@
12714 static int __init init(void)
12716 - need_ip_conntrack();
12717 return ipt_register_match(&helper_match);
12720 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.6/net/ipv4/netfilter/ipt_ipv4options.c
12721 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
12722 +++ linux-2.6.6/net/ipv4/netfilter/ipt_ipv4options.c 2004-05-18 12:36:29.000000000 +0200
12725 + This is a module which is used to match ipv4 options.
12726 + This file is distributed under the terms of the GNU General Public
12727 + License (GPL). Copies of the GPL can be obtained from:
12728 + ftp://prep.ai.mit.edu/pub/gnu/GPL
12730 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
12731 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
12732 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
12733 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
12734 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
12737 +#include <linux/module.h>
12738 +#include <linux/skbuff.h>
12739 +#include <net/ip.h>
12741 +#include <linux/netfilter_ipv4/ip_tables.h>
12742 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
12744 +MODULE_LICENSE("GPL");
12745 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12748 +match(const struct sk_buff *skb,
12749 + const struct net_device *in,
12750 + const struct net_device *out,
12751 + const void *matchinfo,
12755 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
12756 + const struct iphdr *iph = skb->nh.iph;
12757 + const struct ip_options *opt;
12759 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
12760 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
12762 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
12763 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12764 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12765 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12766 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12767 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
12772 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
12773 + /* there are options, and we don't need to care which one */
12776 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
12777 + /* there are options but we don't want any ! */
12782 + opt = &(IPCB(skb)->opt);
12784 + /* source routing */
12785 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
12786 + if (!((opt->srr) & (opt->is_strictroute)))
12789 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
12790 + if (!((opt->srr) & (!opt->is_strictroute)))
12793 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
12797 + /* record route */
12798 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
12802 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
12807 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
12811 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
12815 + /* router-alert option */
12816 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
12817 + if (!opt->router_alert)
12820 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
12821 + if (opt->router_alert)
12830 +checkentry(const char *tablename,
12831 + const struct ipt_ip *ip,
12833 + unsigned int matchsize,
12834 + unsigned int hook_mask)
12836 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
12837 + /* Check the size */
12838 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
12840 + /* Now check the coherence of the data ... */
12841 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
12842 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
12843 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
12844 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
12845 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
12846 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
12847 + return 0; /* opposites */
12848 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
12849 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12850 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12851 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12852 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12853 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
12854 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
12855 + return 0; /* opposites */
12856 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
12857 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
12858 + return 0; /* cannot match in the same time loose and strict source routing */
12859 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12860 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
12861 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
12862 + return 0; /* opposites */
12863 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
12864 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
12865 + return 0; /* opposites */
12866 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
12867 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
12868 + return 0; /* opposites */
12869 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
12870 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
12871 + return 0; /* opposites */
12873 + /* everything looks ok. */
12877 +static struct ipt_match ipv4options_match = {
12878 + .name = "ipv4options",
12880 + .checkentry = checkentry,
12881 + .me = THIS_MODULE
12884 +static int __init init(void)
12886 + return ipt_register_match(&ipv4options_match);
12889 +static void __exit fini(void)
12891 + ipt_unregister_match(&ipv4options_match);
12894 +module_init(init);
12895 +module_exit(fini);
12896 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.6/net/ipv4/netfilter/ipt_mport.c
12897 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
12898 +++ linux-2.6.6/net/ipv4/netfilter/ipt_mport.c 2004-05-18 12:36:36.000000000 +0200
12900 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
12901 + the same place so we can treat them as equal. */
12902 +#include <linux/module.h>
12903 +#include <linux/types.h>
12904 +#include <linux/udp.h>
12905 +#include <linux/skbuff.h>
12907 +#include <linux/netfilter_ipv4/ipt_mport.h>
12908 +#include <linux/netfilter_ipv4/ip_tables.h>
12910 +MODULE_LICENSE("GPL");
12913 +#define duprintf(format, args...) printk(format , ## args)
12915 +#define duprintf(format, args...)
12918 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
12920 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
12924 + u_int16_t pflags = minfo->pflags;
12925 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
12929 + && minfo->ports[i] == 65535)
12932 + s = minfo->ports[i];
12934 + if (pflags & m) {
12935 + e = minfo->ports[++i];
12940 + if (minfo->flags & IPT_MPORT_SOURCE
12941 + && src >= s && src <= e)
12944 + if (minfo->flags & IPT_MPORT_DESTINATION
12945 + && dst >= s && dst <= e)
12953 +match(const struct sk_buff *skb,
12954 + const struct net_device *in,
12955 + const struct net_device *out,
12956 + const void *matchinfo,
12961 + const struct ipt_mport *minfo = matchinfo;
12966 + /* Must be big enough to read ports (both UDP and TCP have
12967 + them at the start). */
12968 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12969 + /* We've been asked to examine this packet, and we
12970 + can't. Hence, no choice but to drop. */
12971 + duprintf("ipt_multiport:"
12972 + " Dropping evil offset=0 tinygram.\n");
12977 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
12980 +/* Called when user tries to insert an entry of this type. */
12982 +checkentry(const char *tablename,
12983 + const struct ipt_ip *ip,
12985 + unsigned int matchsize,
12986 + unsigned int hook_mask)
12988 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
12991 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
12992 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
12993 + && !(ip->invflags & IPT_INV_PROTO)
12994 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
12997 +static struct ipt_match mport_match = {
13000 + .checkentry = &checkentry,
13001 + .me = THIS_MODULE
13004 +static int __init init(void)
13006 + return ipt_register_match(&mport_match);
13009 +static void __exit fini(void)
13011 + ipt_unregister_match(&mport_match);
13014 +module_init(init);
13015 +module_exit(fini);
13016 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.6/net/ipv4/netfilter/ipt_nth.c
13017 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
13018 +++ linux-2.6.6/net/ipv4/netfilter/ipt_nth.c 2004-05-18 12:36:40.000000000 +0200
13021 + This is a module which is used for match support for every Nth packet
13022 + This file is distributed under the terms of the GNU General Public
13023 + License (GPL). Copies of the GPL can be obtained from:
13024 + ftp://prep.ai.mit.edu/pub/gnu/GPL
13026 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
13027 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
13028 + * added support for multiple counters
13029 + * added support for matching on individual packets
13030 + in the counter cycle
13031 + 2004-02-19 Harald Welte <laforge@netfilter.org>
13036 +#include <linux/module.h>
13037 +#include <linux/skbuff.h>
13038 +#include <linux/ip.h>
13039 +#include <net/tcp.h>
13040 +#include <linux/spinlock.h>
13041 +#include <linux/netfilter_ipv4/ip_tables.h>
13042 +#include <linux/netfilter_ipv4/ipt_nth.h>
13044 +MODULE_LICENSE("GPL");
13045 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
13048 + * State information.
13052 + u_int16_t number;
13055 +static struct state states[IPT_NTH_NUM_COUNTERS];
13058 +ipt_nth_match(const struct sk_buff *pskb,
13059 + const struct net_device *in,
13060 + const struct net_device *out,
13061 + const void *matchinfo,
13065 + /* Parameters from userspace */
13066 + const struct ipt_nth_info *info = matchinfo;
13067 + unsigned counter = info->counter;
13068 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
13070 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
13074 + spin_lock(&states[counter].lock);
13076 + /* Are we matching every nth packet?*/
13077 + if (info->packet == 0xFF)
13079 + /* We're matching every nth packet and only every nth packet*/
13080 + /* Do we match or invert match? */
13081 + if (info->not == 0)
13083 + if (states[counter].number == 0)
13085 + ++states[counter].number;
13088 + if (states[counter].number >= info->every)
13089 + states[counter].number = 0; /* reset the counter */
13091 + ++states[counter].number;
13096 + if (states[counter].number == 0)
13098 + ++states[counter].number;
13101 + if (states[counter].number >= info->every)
13102 + states[counter].number = 0;
13104 + ++states[counter].number;
13110 + /* We're using the --packet, so there must be a rule for every value */
13111 + if (states[counter].number == info->packet)
13113 + /* only increment the counter when a match happens */
13114 + if (states[counter].number >= info->every)
13115 + states[counter].number = 0; /* reset the counter */
13117 + ++states[counter].number;
13125 + /* don't match */
13126 + spin_unlock(&states[counter].lock);
13130 + spin_unlock(&states[counter].lock);
13135 +ipt_nth_checkentry(const char *tablename,
13136 + const struct ipt_ip *e,
13138 + unsigned int matchsize,
13139 + unsigned int hook_mask)
13141 + /* Parameters from userspace */
13142 + const struct ipt_nth_info *info = matchinfo;
13143 + unsigned counter = info->counter;
13144 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
13146 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
13150 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
13151 + printk("nth: matchsize %u != %u\n", matchsize,
13152 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
13156 + states[counter].number = info->startat;
13161 +static struct ipt_match ipt_nth_reg = {
13163 + .match = ipt_nth_match,
13164 + .checkentry = ipt_nth_checkentry,
13165 + .me = THIS_MODULE
13168 +static int __init init(void)
13170 + unsigned counter;
13172 + memset(&states, 0, sizeof(states));
13173 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
13174 + spin_lock_init(&(states[counter].lock));
13176 + return ipt_register_match(&ipt_nth_reg);
13179 +static void __exit fini(void)
13181 + ipt_unregister_match(&ipt_nth_reg);
13184 +module_init(init);
13185 +module_exit(fini);
13186 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6/net/ipv4/netfilter/ipt_osf.c
13187 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
13188 +++ linux-2.6.6/net/ipv4/netfilter/ipt_osf.c 2004-05-18 12:36:46.000000000 +0200
13193 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
13196 + * This program is free software; you can redistribute it and/or modify
13197 + * it under the terms of the GNU General Public License as published by
13198 + * the Free Software Foundation; either version 2 of the License, or
13199 + * (at your option) any later version.
13201 + * This program is distributed in the hope that it will be useful,
13202 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13203 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13204 + * GNU General Public License for more details.
13206 + * You should have received a copy of the GNU General Public License
13207 + * along with this program; if not, write to the Free Software
13208 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13212 + * OS fingerprint matching module.
13213 + * It simply compares various parameters from SYN packet with
13214 + * some hardcoded ones.
13216 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
13220 +#include <linux/config.h>
13221 +#include <linux/kernel.h>
13222 +#include <linux/types.h>
13223 +#include <linux/string.h>
13224 +#include <linux/smp.h>
13225 +#include <linux/module.h>
13226 +#include <linux/skbuff.h>
13227 +#include <linux/file.h>
13228 +#include <linux/ip.h>
13229 +#include <linux/proc_fs.h>
13230 +#include <linux/fs.h>
13231 +#include <linux/slab.h>
13232 +#include <linux/spinlock.h>
13233 +#include <linux/ctype.h>
13234 +#include <linux/list.h>
13235 +#include <linux/if.h>
13237 +#include <net/sock.h>
13238 +#include <net/ip.h>
13240 +#include <linux/netfilter_ipv4/ip_tables.h>
13242 +#include <linux/netfilter_ipv4/ipt_osf.h>
13247 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
13248 +#define loga(x...) printk(x)
13250 +#define log(x...) do {} while(0)
13251 +#define loga(x...) do {} while(0)
13254 +#define FMATCH_WRONG 0
13255 +#define FMATCH_OK 1
13256 +#define FMATCH_OPT_WRONG 2
13258 +#define OPTDEL ','
13259 +#define OSFPDEL ':'
13260 +#define MAXOPTSTRLEN 128
13261 +#define OSFFLUSH "FLUSH"
13263 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
13264 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
13265 +static struct list_head finger_list;
13266 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
13267 + const void *, int,
13268 + const void *, u_int16_t,
13270 +static int checkentry(const char *, const struct ipt_ip *, void *,
13271 + unsigned int, unsigned int);
13273 +static unsigned long seq, ipt_osf_groups = 1;
13274 +static struct sock *nts;
13276 +static struct ipt_match osf_match =
13286 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
13288 + unsigned int size;
13289 + struct sk_buff *skb;
13290 + struct ipt_osf_nlmsg *data;
13291 + struct nlmsghdr *nlh;
13293 + size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
13295 + skb = alloc_skb(size, GFP_ATOMIC);
13298 + log("skb_alloc() failed.\n");
13302 + nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
13304 + data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
13306 + memcpy(&data->f, f, sizeof(struct osf_finger));
13307 + memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
13308 + memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
13310 + NETLINK_CB(skb).dst_groups = ipt_osf_groups;
13311 + netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
13317 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
13319 + struct iphdr *ip = skb->nh.iph;
13321 + if (flags & IPT_OSF_SMART)
13323 + struct in_device *in_dev = in_dev_get(skb->dev);
13327 + if (inet_ifa_match(ip->saddr, ifa))
13329 + in_dev_put(in_dev);
13330 + return (ip->ttl == f_ttl);
13333 + endfor_ifa(in_dev);
13335 + in_dev_put(in_dev);
13336 + return (ip->ttl <= f_ttl);
13339 + return (ip->ttl == f_ttl);
13343 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
13344 + const void *matchinfo, int offset,
13345 + const void *hdr, u_int16_t datalen,
13348 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
13349 + struct iphdr *ip = skb->nh.iph;
13350 + struct tcphdr *tcp;
13351 + int fmatch = FMATCH_WRONG, fcount = 0;
13352 + unsigned long totlen, optsize = 0, window;
13353 + unsigned char df, *optp = NULL, *_optp = NULL;
13354 + char check_WSS = 0;
13355 + struct list_head *ent;
13356 + struct osf_finger *f;
13358 + if (!ip || !info)
13361 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
13366 + totlen = ntohs(ip->tot_len);
13367 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
13368 + window = ntohs(tcp->window);
13370 + if (tcp->doff*4 > sizeof(struct tcphdr))
13372 + _optp = optp = (char *)(tcp+1);
13373 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
13377 + /* Actually we can create hash/table of all genres and search
13378 + * only in appropriate part, but here is initial variant,
13379 + * so will use slow path.
13381 + read_lock(&osf_lock);
13382 + list_for_each(ent, &finger_list)
13384 + f = list_entry(ent, struct osf_finger, flist);
13386 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
13390 + fmatch = FMATCH_WRONG;
13392 + if (totlen == f->ss && df == f->df &&
13393 + smart_dec(skb, info->flags, f->ttl))
13395 + unsigned long foptsize;
13397 + unsigned short mss = 0;
13401 + switch (f->wss.wc)
13403 + case 0: check_WSS = 0; break;
13404 + case 'S': check_WSS = 1; break;
13405 + case 'T': check_WSS = 2; break;
13406 + case '%': check_WSS = 3; break;
13407 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
13408 + f->wss.wc, f->genre, f->details);
13412 + if (check_WSS == 4)
13415 + /* Check options */
13418 + for (optnum=0; optnum<f->opt_num; ++optnum)
13419 + foptsize += f->opt[optnum].length;
13422 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
13427 + fmatch = FMATCH_OK;
13428 + loga("\tYEP : matching without options.\n");
13429 + if ((info->flags & IPT_OSF_LOG) &&
13430 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13437 + for (optnum=0; optnum<f->opt_num; ++optnum)
13439 + if (f->opt[optnum].kind == (*optp))
13441 + unsigned char len = f->opt[optnum].length;
13442 + unsigned char *optend = optp + len;
13443 + int loop_cont = 0;
13445 + fmatch = FMATCH_OK;
13451 + mss = ntohs(*(unsigned short *)(optp+2));
13466 + /* Skip kind and length fields*/
13469 + if (f->opt[optnum].wc.val != 0)
13471 + unsigned long tmp = 0;
13473 + /* Hmmm... It looks a bit ugly. :) */
13474 + memcpy(&tmp, optp,
13475 + (len > sizeof(unsigned long)?
13476 + sizeof(unsigned long):len));
13477 + /* 2 + 2: optlen(2 bytes) +
13478 + * kind(1 byte) + length(1 byte) */
13480 + tmp = ntohs(tmp);
13482 + tmp = ntohl(tmp);
13484 + if (f->opt[optnum].wc.wc == '%')
13486 + if ((tmp % f->opt[optnum].wc.val) != 0)
13487 + fmatch = FMATCH_OPT_WRONG;
13489 + else if (tmp != f->opt[optnum].wc.val)
13490 + fmatch = FMATCH_OPT_WRONG;
13497 + fmatch = FMATCH_OPT_WRONG;
13499 + if (fmatch != FMATCH_OK)
13503 + if (fmatch != FMATCH_OPT_WRONG)
13505 + fmatch = FMATCH_WRONG;
13507 + switch (check_WSS)
13510 + if (f->wss.val == 0 || window == f->wss.val)
13511 + fmatch = FMATCH_OK;
13513 + case 1: /* MSS */
13514 +/* Lurked in OpenBSD */
13515 +#define SMART_MSS 1460
13516 + if (window == f->wss.val*mss ||
13517 + window == f->wss.val*SMART_MSS)
13518 + fmatch = FMATCH_OK;
13520 + case 2: /* MTU */
13521 + if (window == f->wss.val*(mss+40) ||
13522 + window == f->wss.val*(SMART_MSS+40))
13523 + fmatch = FMATCH_OK;
13525 + case 3: /* MOD */
13526 + if ((window % f->wss.val) == 0)
13527 + fmatch = FMATCH_OK;
13533 + if (fmatch == FMATCH_OK)
13536 + log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
13537 + f->genre, f->version,
13538 + f->subtype, f->details,
13539 + NIPQUAD(ip->saddr), ntohs(tcp->source),
13540 + NIPQUAD(ip->daddr), ntohs(tcp->dest),
13541 + f->ttl - ip->ttl);
13542 + if (info->flags & IPT_OSF_NETLINK)
13544 + spin_lock_bh(&ipt_osf_netlink_lock);
13545 + ipt_osf_nlsend(f, skb);
13546 + spin_unlock_bh(&ipt_osf_netlink_lock);
13548 + if ((info->flags & IPT_OSF_LOG) &&
13549 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13554 + if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
13556 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
13557 + unsigned int i, optsize;
13558 + struct osf_finger fg;
13560 + memset(&fg, 0, sizeof(fg));
13562 + if ((info->flags & IPT_OSF_LOG))
13563 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
13566 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
13567 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
13568 + opt, optsize) < 0)
13570 + if (info->flags & IPT_OSF_LOG)
13571 + loga("TRUNCATED");
13572 + if (info->flags & IPT_OSF_NETLINK)
13573 + strcpy(fg.details, "TRUNCATED");
13577 + for (i = 0; i < optsize; i++)
13579 + if (info->flags & IPT_OSF_LOG)
13580 + loga("%02X", opt[i]);
13582 + if (info->flags & IPT_OSF_NETLINK)
13583 + memcpy(fg.details, opt, MAXDETLEN);
13586 + if ((info->flags & IPT_OSF_LOG))
13587 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
13588 + NIPQUAD(ip->saddr), ntohs(tcp->source),
13589 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
13591 + if (info->flags & IPT_OSF_NETLINK)
13593 + fg.wss.val = window;
13594 + fg.ttl = ip->ttl;
13597 + strncpy(fg.genre, "Unknown", MAXGENRELEN);
13599 + spin_lock_bh(&ipt_osf_netlink_lock);
13600 + ipt_osf_nlsend(&fg, skb);
13601 + spin_unlock_bh(&ipt_osf_netlink_lock);
13605 + read_unlock(&osf_lock);
13607 + return (fmatch == FMATCH_OK)?1:0;
13611 +checkentry(const char *tablename,
13612 + const struct ipt_ip *ip,
13614 + unsigned int matchsize,
13615 + unsigned int hook_mask)
13617 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
13619 + if (ip->proto != IPPROTO_TCP)
13625 +static char * osf_strchr(char *ptr, char c)
13629 + tmp = strchr(ptr, c);
13631 + while (tmp && tmp+1 && isspace(*(tmp+1)))
13637 +static struct osf_finger * finger_alloc(void)
13639 + struct osf_finger *f;
13641 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
13643 + memset(f, 0, sizeof(struct osf_finger));
13648 +static void finger_free(struct osf_finger *f)
13650 + memset(f, 0, sizeof(struct osf_finger));
13655 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
13659 + unsigned long val;
13663 + while (ptr != NULL && i < olen)
13672 + ptr = osf_strchr(&obuf[i], OPTDEL);
13677 + i += (int)(ptr-&obuf[i]);
13684 + op = OSFOPT_SACKP;
13685 + ptr = osf_strchr(&obuf[i], OPTDEL);
13690 + i += (int)(ptr-&obuf[i]);
13698 + ptr = osf_strchr(&obuf[i], OPTDEL);
13703 + i += (int)(ptr-&obuf[i]);
13711 + ptr = osf_strchr(&obuf[i], OPTDEL);
13714 + switch (obuf[i+1])
13716 + case '%': wc = '%'; break;
13717 + case 'S': wc = 'S'; break;
13718 + case 'T': wc = 'T'; break;
13719 + default: wc = 0; break;
13725 + val = simple_strtoul(&obuf[i+2], NULL, 10);
13727 + val = simple_strtoul(&obuf[i+1], NULL, 10);
13728 + i += (int)(ptr-&obuf[i]);
13736 + ptr = osf_strchr(&obuf[i], OPTDEL);
13739 + if (obuf[i+1] == '%')
13744 + val = simple_strtoul(&obuf[i+2], NULL, 10);
13746 + val = simple_strtoul(&obuf[i+1], NULL, 10);
13747 + i += (int)(ptr-&obuf[i]);
13755 + ptr = osf_strchr(&obuf[i], OPTDEL);
13760 + i += (int)(ptr-&obuf[i]);
13767 + ptr = osf_strchr(&obuf[i], OPTDEL);
13771 + i += (int)(ptr-&obuf[i]);
13779 + opt[*optnum].kind = IANA_opts[op].kind;
13780 + opt[*optnum].length = IANA_opts[op].length;
13781 + opt[*optnum].wc.wc = wc;
13782 + opt[*optnum].wc.val = val;
13788 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
13790 + struct list_head *ent;
13791 + struct osf_finger *f = NULL;
13797 + read_lock_bh(&osf_lock);
13798 + list_for_each(ent, &finger_list)
13800 + f = list_entry(ent, struct osf_finger, flist);
13802 + log("%s [%s]", f->genre, f->details);
13804 + count += sprintf(buf+count, "%s - %s[%s] : %s",
13805 + f->genre, f->version,
13806 + f->subtype, f->details);
13811 + //count += sprintf(buf+count, " OPT: ");
13812 + for (i=0; i<f->opt_num; ++i)
13814 + //count += sprintf(buf+count, "%d.%c%lu; ",
13815 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13816 + loga("%d.%c%lu; ",
13817 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13821 + count += sprintf(buf+count, "\n");
13823 + read_unlock_bh(&osf_lock);
13828 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
13832 + char obuf[MAXOPTSTRLEN];
13833 + struct osf_finger *finger;
13834 + struct list_head *ent, *n;
13836 + char *pbeg, *pend;
13838 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
13841 + write_lock_bh(&osf_lock);
13842 + list_for_each_safe(ent, n, &finger_list)
13845 + finger = list_entry(ent, struct osf_finger, flist);
13846 + list_del(&finger->flist);
13847 + finger_free(finger);
13849 + write_unlock_bh(&osf_lock);
13851 + log("Flushed %d entries.\n", i);
13858 + for (i=0; i<count && buffer[i] != '\0'; ++i)
13859 + if (buffer[i] == ':')
13862 + if (cnt != 8 || i != count)
13864 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
13869 + memset(obuf, 0, sizeof(obuf));
13871 + finger = finger_alloc();
13874 + log("Failed to allocate new fingerprint entry.\n");
13878 + pbeg = (char *)buffer;
13879 + pend = osf_strchr(pbeg, OSFPDEL);
13883 + if (pbeg[0] == 'S')
13885 + finger->wss.wc = 'S';
13886 + if (pbeg[1] == '%')
13887 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13888 + else if (pbeg[1] == '*')
13889 + finger->wss.val = 0;
13891 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13893 + else if (pbeg[0] == 'T')
13895 + finger->wss.wc = 'T';
13896 + if (pbeg[1] == '%')
13897 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13898 + else if (pbeg[1] == '*')
13899 + finger->wss.val = 0;
13901 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13903 + else if (pbeg[0] == '%')
13905 + finger->wss.wc = '%';
13906 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13908 + else if (isdigit(pbeg[0]))
13910 + finger->wss.wc = 0;
13911 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
13916 + pend = osf_strchr(pbeg, OSFPDEL);
13920 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
13923 + pend = osf_strchr(pbeg, OSFPDEL);
13927 + finger->df = simple_strtoul(pbeg, NULL, 10);
13930 + pend = osf_strchr(pbeg, OSFPDEL);
13934 + finger->ss = simple_strtoul(pbeg, NULL, 10);
13938 + pend = osf_strchr(pbeg, OSFPDEL);
13942 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
13946 + pend = osf_strchr(pbeg, OSFPDEL);
13950 + if (pbeg[0] == '@' || pbeg[0] == '*')
13951 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
13953 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
13957 + pend = osf_strchr(pbeg, OSFPDEL);
13961 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
13965 + pend = osf_strchr(pbeg, OSFPDEL);
13969 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
13973 + cnt = snprintf(finger->details,
13974 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
13977 + log("%s - %s[%s] : %s\n",
13978 + finger->genre, finger->version,
13979 + finger->subtype, finger->details);
13981 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
13984 + write_lock_bh(&osf_lock);
13985 + list_add_tail(&finger->flist, &finger_list);
13986 + write_unlock_bh(&osf_lock);
13991 +static int __init osf_init(void)
13994 + struct proc_dir_entry *p;
13996 + log("Startng OS fingerprint matching module.\n");
13998 + INIT_LIST_HEAD(&finger_list);
14000 + err = ipt_register_match(&osf_match);
14003 + log("Failed to register OS fingerprint matching module.\n");
14007 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
14010 + ipt_unregister_match(&osf_match);
14014 + p->write_proc = osf_proc_write;
14015 + p->read_proc = osf_proc_read;
14017 + nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
14020 + log("netlink_kernel_create() failed\n");
14021 + remove_proc_entry("sys/net/ipv4/osf", NULL);
14022 + ipt_unregister_match(&osf_match);
14029 +static void __exit osf_fini(void)
14031 + struct list_head *ent, *n;
14032 + struct osf_finger *f;
14034 + remove_proc_entry("sys/net/ipv4/osf", NULL);
14035 + ipt_unregister_match(&osf_match);
14036 + if (nts && nts->sk_socket)
14037 + sock_release(nts->sk_socket);
14039 + list_for_each_safe(ent, n, &finger_list)
14041 + f = list_entry(ent, struct osf_finger, flist);
14042 + list_del(&f->flist);
14046 + log("OS fingerprint matching module finished.\n");
14049 +module_init(osf_init);
14050 +module_exit(osf_fini);
14052 +MODULE_LICENSE("GPL");
14053 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
14054 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
14055 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6/net/ipv4/netfilter/ipt_owner.c
14056 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_owner.c 2004-05-10 04:33:20.000000000 +0200
14057 +++ linux-2.6.6/net/ipv4/netfilter/ipt_owner.c 2004-05-18 12:39:47.000000000 +0200
14059 * This program is free software; you can redistribute it and/or modify
14060 * it under the terms of the GNU General Public License version 2 as
14061 * published by the Free Software Foundation.
14063 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
14066 #include <linux/module.h>
14067 #include <linux/skbuff.h>
14068 #include <linux/file.h>
14069 +#include <linux/ip.h>
14070 +#include <linux/tcp.h>
14071 +#include <linux/udp.h>
14072 #include <net/sock.h>
14073 +#include <net/tcp.h>
14074 +#include <net/udp.h>
14076 #include <linux/netfilter_ipv4/ipt_owner.h>
14077 #include <linux/netfilter_ipv4/ip_tables.h>
14079 MODULE_DESCRIPTION("iptables owner match");
14082 -match_comm(const struct sk_buff *skb, const char *comm)
14083 +match_comm(const struct sock *sk, const char *comm)
14085 struct task_struct *g, *p;
14086 struct files_struct *files;
14088 spin_lock(&files->file_lock);
14089 for (i=0; i < files->max_fds; i++) {
14090 if (fcheck_files(files, i) ==
14091 - skb->sk->sk_socket->file) {
14092 + sk->sk_socket->file) {
14093 spin_unlock(&files->file_lock);
14095 read_unlock(&tasklist_lock);
14100 -match_pid(const struct sk_buff *skb, pid_t pid)
14101 +match_pid(const struct sock *sk, pid_t pid)
14103 struct task_struct *p;
14104 struct files_struct *files;
14106 spin_lock(&files->file_lock);
14107 for (i=0; i < files->max_fds; i++) {
14108 if (fcheck_files(files, i) ==
14109 - skb->sk->sk_socket->file) {
14110 + sk->sk_socket->file) {
14111 spin_unlock(&files->file_lock);
14113 read_unlock(&tasklist_lock);
14114 @@ -86,10 +93,10 @@
14118 -match_sid(const struct sk_buff *skb, pid_t sid)
14119 +match_sid(const struct sock *sk, pid_t sid)
14121 struct task_struct *g, *p;
14122 - struct file *file = skb->sk->sk_socket->file;
14123 + struct file *file = sk->sk_socket->file;
14126 read_lock(&tasklist_lock);
14127 @@ -129,41 +136,71 @@
14130 const struct ipt_owner_info *info = matchinfo;
14131 + struct iphdr *iph = skb->nh.iph;
14132 + struct sock *sk = NULL;
14138 + if (iph->protocol == IPPROTO_TCP) {
14139 + struct tcphdr *tcph =
14140 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
14141 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
14142 + iph->daddr, tcph->dest,
14143 + skb->dev->ifindex);
14144 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
14145 + tcp_tw_put((struct tcp_tw_bucket *)sk);
14148 + } else if (iph->protocol == IPPROTO_UDP) {
14149 + struct udphdr *udph =
14150 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
14151 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
14152 + udph->dest, skb->dev->ifindex);
14156 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
14158 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
14161 if(info->match & IPT_OWNER_UID) {
14162 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
14163 + if ((sk->sk_socket->file->f_uid != info->uid) ^
14164 !!(info->invert & IPT_OWNER_UID))
14169 if(info->match & IPT_OWNER_GID) {
14170 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
14171 + if ((sk->sk_socket->file->f_gid != info->gid) ^
14172 !!(info->invert & IPT_OWNER_GID))
14177 if(info->match & IPT_OWNER_PID) {
14178 - if (!match_pid(skb, info->pid) ^
14179 + if (!match_pid(sk, info->pid) ^
14180 !!(info->invert & IPT_OWNER_PID))
14185 if(info->match & IPT_OWNER_SID) {
14186 - if (!match_sid(skb, info->sid) ^
14187 + if (!match_sid(sk, info->sid) ^
14188 !!(info->invert & IPT_OWNER_SID))
14193 if(info->match & IPT_OWNER_COMM) {
14194 - if (!match_comm(skb, info->comm) ^
14195 + if (!match_comm(sk, info->comm) ^
14196 !!(info->invert & IPT_OWNER_COMM))
14212 @@ -173,11 +210,19 @@
14213 unsigned int matchsize,
14214 unsigned int hook_mask)
14217 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
14218 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
14222 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
14223 + (1 << NF_IP_LOCAL_IN))) {
14224 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
14225 + "or POST_ROUTING.\n");
14229 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
14230 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
14231 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
14235 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
14236 printk("Matchsize %u != %Zu\n", matchsize,
14237 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6/net/ipv4/netfilter/ipt_policy.c
14238 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
14239 +++ linux-2.6.6/net/ipv4/netfilter/ipt_policy.c 2004-05-18 12:39:55.000000000 +0200
14241 +/* IP tables module for matching IPsec policy
14243 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
14245 + * This program is free software; you can redistribute it and/or modify
14246 + * it under the terms of the GNU General Public License version 2 as
14247 + * published by the Free Software Foundation.
14250 +#include <linux/kernel.h>
14251 +#include <linux/config.h>
14252 +#include <linux/module.h>
14253 +#include <linux/skbuff.h>
14254 +#include <linux/init.h>
14255 +#include <net/xfrm.h>
14257 +#include <linux/netfilter_ipv4.h>
14258 +#include <linux/netfilter_ipv4/ipt_policy.h>
14259 +#include <linux/netfilter_ipv4/ip_tables.h>
14261 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
14262 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
14263 +MODULE_LICENSE("GPL");
14267 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
14269 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
14271 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
14272 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
14273 + MISMATCH(proto, x->id.proto) ||
14274 + MISMATCH(mode, x->props.mode) ||
14275 + MISMATCH(spi, x->id.spi) ||
14276 + MISMATCH(reqid, x->props.reqid))
14282 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
14284 + const struct ipt_policy_elem *e;
14285 + struct sec_path *sp = skb->sp;
14286 + int strict = info->flags & POLICY_MATCH_STRICT;
14291 + if (strict && info->len != sp->len)
14294 + for (i = sp->len - 1; i >= 0; i--) {
14295 + pos = strict ? i - sp->len + 1 : 0;
14296 + if (pos >= info->len)
14298 + e = &info->pol[pos];
14300 + if (match_xfrm_state(sp->x[i].xvec, e)) {
14303 + } else if (strict)
14307 + return strict ? 1 : 0;
14311 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
14313 + const struct ipt_policy_elem *e;
14314 + struct dst_entry *dst = skb->dst;
14315 + int strict = info->flags & POLICY_MATCH_STRICT;
14318 + if (dst->xfrm == NULL)
14321 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
14322 + pos = strict ? i : 0;
14323 + if (pos >= info->len)
14325 + e = &info->pol[pos];
14327 + if (match_xfrm_state(dst->xfrm, e)) {
14330 + } else if (strict)
14334 + return strict ? 1 : 0;
14337 +static int match(const struct sk_buff *skb,
14338 + const struct net_device *in,
14339 + const struct net_device *out,
14340 + const void *matchinfo, int offset, int *hotdrop)
14342 + const struct ipt_policy_info *info = matchinfo;
14345 + if (info->flags & POLICY_MATCH_IN)
14346 + ret = match_policy_in(skb, info);
14348 + ret = match_policy_out(skb, info);
14351 + if (info->flags & POLICY_MATCH_NONE)
14355 + } else if (info->flags & POLICY_MATCH_NONE)
14361 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
14362 + void *matchinfo, unsigned int matchsize,
14363 + unsigned int hook_mask)
14365 + struct ipt_policy_info *info = matchinfo;
14367 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
14368 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
14369 + matchsize, IPT_ALIGN(sizeof(*info)));
14372 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
14373 + printk(KERN_ERR "ipt_policy: neither incoming nor "
14374 + "outgoing policy selected\n");
14377 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
14378 + && info->flags & POLICY_MATCH_OUT) {
14379 + printk(KERN_ERR "ipt_policy: output policy not valid in "
14380 + "PRE_ROUTING and INPUT\n");
14383 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
14384 + && info->flags & POLICY_MATCH_IN) {
14385 + printk(KERN_ERR "ipt_policy: input policy not valid in "
14386 + "POST_ROUTING and OUTPUT\n");
14389 + if (info->len > POLICY_MAX_ELEM) {
14390 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
14397 +static struct ipt_match policy_match =
14399 + .name = "policy",
14401 + .checkentry = checkentry,
14402 + .me = THIS_MODULE,
14405 +static int __init init(void)
14407 + return ipt_register_match(&policy_match);
14410 +static void __exit fini(void)
14412 + ipt_unregister_match(&policy_match);
14415 +module_init(init);
14416 +module_exit(fini);
14417 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.6/net/ipv4/netfilter/ipt_pool.c
14418 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
14419 +++ linux-2.6.6/net/ipv4/netfilter/ipt_pool.c 2004-05-18 12:36:48.000000000 +0200
14421 +/* Kernel module to match an IP address pool. */
14423 +#include <linux/module.h>
14424 +#include <linux/ip.h>
14425 +#include <linux/skbuff.h>
14427 +#include <linux/netfilter_ipv4/ip_tables.h>
14428 +#include <linux/netfilter_ipv4/ip_pool.h>
14429 +#include <linux/netfilter_ipv4/ipt_pool.h>
14431 +static inline int match_pool(
14436 + if (ip_pool_match(index, ntohl(addr)))
14442 + const struct sk_buff *skb,
14443 + const struct net_device *in,
14444 + const struct net_device *out,
14445 + const void *matchinfo,
14448 + u_int16_t datalen,
14451 + const struct ipt_pool_info *info = matchinfo;
14452 + const struct iphdr *iph = skb->nh.iph;
14454 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
14455 + info->flags&IPT_POOL_INV_SRC))
14458 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
14459 + info->flags&IPT_POOL_INV_DST))
14465 +static int checkentry(
14466 + const char *tablename,
14467 + const struct ipt_ip *ip,
14469 + unsigned int matchsize,
14470 + unsigned int hook_mask
14472 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
14477 +static struct ipt_match pool_match
14478 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
14480 +static int __init init(void)
14482 + return ipt_register_match(&pool_match);
14485 +static void __exit fini(void)
14487 + ipt_unregister_match(&pool_match);
14490 +module_init(init);
14491 +module_exit(fini);
14492 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.6/net/ipv4/netfilter/ipt_psd.c
14493 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
14494 +++ linux-2.6.6/net/ipv4/netfilter/ipt_psd.c 2004-05-18 12:36:55.000000000 +0200
14497 + This is a module which is used for PSD (portscan detection)
14498 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
14499 + and LOG target module.
14501 + Copyright (C) 2000,2001 astaro AG
14503 + This file is distributed under the terms of the GNU General Public
14504 + License (GPL). Copies of the GPL can be obtained from:
14505 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14507 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
14508 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
14509 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
14510 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
14511 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
14512 + 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
14515 +#include <linux/module.h>
14516 +#include <linux/skbuff.h>
14517 +#include <linux/ip.h>
14518 +#include <net/tcp.h>
14519 +#include <linux/spinlock.h>
14520 +#include <linux/netfilter_ipv4/ip_tables.h>
14521 +#include <linux/netfilter_ipv4/ipt_psd.h>
14524 +#define DEBUGP printk
14526 +#define DEBUGP(format, args...)
14529 +MODULE_LICENSE("GPL");
14530 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
14532 +#define HF_DADDR_CHANGING 0x01
14533 +#define HF_SPORT_CHANGING 0x02
14534 +#define HF_TOS_CHANGING 0x04
14535 +#define HF_TTL_CHANGING 0x08
14538 + * Information we keep per each target port
14541 + u_int16_t number; /* port number */
14542 + u_int8_t proto; /* protocol number */
14543 + u_int8_t and_flags; /* tcp ANDed flags */
14544 + u_int8_t or_flags; /* tcp ORed flags */
14548 + * Information we keep per each source address.
14551 + struct host *next; /* Next entry with the same hash */
14552 + clock_t timestamp; /* Last update time */
14553 + struct in_addr src_addr; /* Source address */
14554 + struct in_addr dest_addr; /* Destination address */
14555 + unsigned short src_port; /* Source port */
14556 + int count; /* Number of ports in the list */
14557 + int weight; /* Total weight of ports in the list */
14558 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
14559 + unsigned char tos; /* TOS */
14560 + unsigned char ttl; /* TTL */
14561 + unsigned char flags; /* HF_ flags bitmask */
14565 + * State information.
14569 + struct host list[LIST_SIZE]; /* List of source addresses */
14570 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
14571 + int index; /* Oldest entry to be replaced */
14575 + * Convert an IP address into a hash table index.
14577 +static inline int hashfunc(struct in_addr addr)
14579 + unsigned int value;
14582 + value = addr.s_addr;
14586 + } while ((value >>= HASH_LOG));
14588 + return hash & (HASH_SIZE - 1);
14592 +ipt_psd_match(const struct sk_buff *pskb,
14593 + const struct net_device *in,
14594 + const struct net_device *out,
14595 + const void *matchinfo,
14599 + struct iphdr *ip_hdr;
14600 + struct tcphdr *tcp_hdr;
14601 + struct in_addr addr;
14602 + u_int16_t src_port,dest_port;
14603 + u_int8_t tcp_flags, proto;
14605 + struct host *curr, *last, **head;
14606 + int hash, index, count;
14608 + /* Parameters from userspace */
14609 + const struct ipt_psd_info *psdinfo = matchinfo;
14612 + ip_hdr = pskb->nh.iph;
14614 + /* Sanity check */
14615 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
14616 + DEBUGP("PSD: sanity check failed\n");
14620 + /* TCP or UDP ? */
14621 + proto = ip_hdr->protocol;
14623 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
14624 + DEBUGP("PSD: protocol not supported\n");
14628 + /* Get the source address, source & destination ports, and TCP flags */
14630 + addr.s_addr = ip_hdr->saddr;
14632 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
14634 + /* Yep, it´s dirty */
14635 + src_port = tcp_hdr->source;
14636 + dest_port = tcp_hdr->dest;
14638 + if (proto == IPPROTO_TCP) {
14639 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
14642 + tcp_flags = 0x00;
14645 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
14646 + * them spoof us. [DHCP needs this feature - HW] */
14647 + if (!addr.s_addr) {
14648 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
14652 + /* Use jiffies here not to depend on someone setting the time while we're
14653 + * running; we need to be careful with possible return value overflows. */
14656 + spin_lock(&state.lock);
14658 + /* Do we know this source address already? */
14661 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
14663 + if (curr->src_addr.s_addr == addr.s_addr) break;
14665 + if (curr->next) last = curr;
14666 + } while ((curr = curr->next));
14670 + /* We know this address, and the entry isn't too old. Update it. */
14671 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
14672 + time_after_eq(now, curr->timestamp)) {
14674 + /* Just update the appropriate list entry if we've seen this port already */
14675 + for (index = 0; index < curr->count; index++) {
14676 + if (curr->ports[index].number == dest_port) {
14677 + curr->ports[index].proto = proto;
14678 + curr->ports[index].and_flags &= tcp_flags;
14679 + curr->ports[index].or_flags |= tcp_flags;
14680 + goto out_no_match;
14684 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
14685 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
14686 + goto out_no_match;
14688 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
14689 + curr->timestamp = now;
14691 + /* Logged this scan already? Then drop the packet. */
14692 + if (curr->weight >= psdinfo->weight_threshold)
14695 + /* Specify if destination address, source port, TOS or TTL are not fixed */
14696 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
14697 + curr->flags |= HF_DADDR_CHANGING;
14698 + if (curr->src_port != src_port)
14699 + curr->flags |= HF_SPORT_CHANGING;
14700 + if (curr->tos != ip_hdr->tos)
14701 + curr->flags |= HF_TOS_CHANGING;
14702 + if (curr->ttl != ip_hdr->ttl)
14703 + curr->flags |= HF_TTL_CHANGING;
14705 + /* Update the total weight */
14706 + curr->weight += (ntohs(dest_port) < 1024) ?
14707 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14709 + /* Got enough destination ports to decide that this is a scan? */
14710 + /* Then log it and drop the packet. */
14711 + if (curr->weight >= psdinfo->weight_threshold)
14714 + /* Remember the new port */
14715 + if (curr->count < SCAN_MAX_COUNT) {
14716 + curr->ports[curr->count].number = dest_port;
14717 + curr->ports[curr->count].proto = proto;
14718 + curr->ports[curr->count].and_flags = tcp_flags;
14719 + curr->ports[curr->count].or_flags = tcp_flags;
14723 + goto out_no_match;
14726 + /* We know this address, but the entry is outdated. Mark it unused, and
14727 + * remove from the hash table. We'll allocate a new entry instead since
14728 + * this one might get re-used too soon. */
14729 + curr->src_addr.s_addr = 0;
14731 + last->next = last->next->next;
14733 + *head = (*head)->next;
14737 + /* We don't need an ACK from a new source address */
14738 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
14739 + goto out_no_match;
14741 + /* Got too many source addresses with the same hash value? Then remove the
14742 + * oldest one from the hash table, so that they can't take too much of our
14743 + * CPU time even with carefully chosen spoofed IP addresses. */
14744 + if (count >= HASH_MAX && last) last->next = NULL;
14746 + /* We're going to re-use the oldest list entry, so remove it from the hash
14747 + * table first (if it is really already in use, and isn't removed from the
14748 + * hash table already because of the HASH_MAX check above). */
14750 + /* First, find it */
14751 + if (state.list[state.index].src_addr.s_addr)
14752 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
14756 + if ((curr = *head))
14758 + if (curr == &state.list[state.index]) break;
14760 + } while ((curr = curr->next));
14762 + /* Then, remove it */
14765 + last->next = last->next->next;
14767 + *head = (*head)->next;
14770 + /* Get our list entry */
14771 + curr = &state.list[state.index++];
14772 + if (state.index >= LIST_SIZE) state.index = 0;
14774 + /* Link it into the hash table */
14775 + head = &state.hash[hash];
14776 + curr->next = *head;
14779 + /* And fill in the fields */
14780 + curr->timestamp = now;
14781 + curr->src_addr = addr;
14782 + curr->dest_addr.s_addr = ip_hdr->daddr;
14783 + curr->src_port = src_port;
14785 + curr->weight = (ntohs(dest_port) < 1024) ?
14786 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14787 + curr->ports[0].number = dest_port;
14788 + curr->ports[0].proto = proto;
14789 + curr->ports[0].and_flags = tcp_flags;
14790 + curr->ports[0].or_flags = tcp_flags;
14791 + curr->tos = ip_hdr->tos;
14792 + curr->ttl = ip_hdr->ttl;
14795 + spin_unlock(&state.lock);
14799 + spin_unlock(&state.lock);
14803 +static int ipt_psd_checkentry(const char *tablename,
14804 + const struct ipt_ip *e,
14806 + unsigned int matchsize,
14807 + unsigned int hook_mask)
14809 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
14811 + /* we accept TCP only */
14812 +/* if (e->ip.proto != IPPROTO_TCP) { */
14813 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
14817 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
14818 + DEBUGP("PSD: matchsize %u != %u\n",
14820 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
14827 +static struct ipt_match ipt_psd_reg = {
14829 + .match = ipt_psd_match,
14830 + .checkentry = ipt_psd_checkentry,
14831 + .me = THIS_MODULE };
14833 +static int __init init(void)
14835 + if (ipt_register_match(&ipt_psd_reg))
14838 + memset(&state, 0, sizeof(state));
14840 + spin_lock_init(&(state.lock));
14842 + printk("netfilter PSD loaded - (c) astaro AG\n");
14846 +static void __exit fini(void)
14848 + ipt_unregister_match(&ipt_psd_reg);
14849 + printk("netfilter PSD unloaded - (c) astaro AG\n");
14852 +module_init(init);
14853 +module_exit(fini);
14854 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.6/net/ipv4/netfilter/ipt_quota.c
14855 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
14856 +++ linux-2.6.6/net/ipv4/netfilter/ipt_quota.c 2004-05-18 12:36:56.000000000 +0200
14859 + * netfilter module to enforce network quotas
14861 + * Sam Johnston <samj@samj.net>
14863 +#include <linux/module.h>
14864 +#include <linux/skbuff.h>
14865 +#include <linux/spinlock.h>
14866 +#include <linux/interrupt.h>
14868 +#include <linux/netfilter_ipv4/ip_tables.h>
14869 +#include <linux/netfilter_ipv4/ipt_quota.h>
14871 +MODULE_LICENSE("GPL");
14872 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14874 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
14877 +match(const struct sk_buff *skb,
14878 + const struct net_device *in,
14879 + const struct net_device *out,
14880 + const void *matchinfo,
14881 + int offset, int *hotdrop)
14883 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
14884 + unsigned int datalen;
14886 + if (skb->len < sizeof(struct iphdr))
14887 + return NF_ACCEPT;
14889 + datalen = skb->len - skb->nh.iph->ihl*4;
14891 + spin_lock_bh("a_lock);
14893 + if (q->quota >= datalen) {
14894 + /* we can afford this one */
14895 + q->quota -= datalen;
14896 + spin_unlock_bh("a_lock);
14898 +#ifdef DEBUG_IPT_QUOTA
14899 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
14904 + /* so we do not allow even small packets from now on */
14907 +#ifdef DEBUG_IPT_QUOTA
14908 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
14911 + spin_unlock_bh("a_lock);
14916 +checkentry(const char *tablename,
14917 + const struct ipt_ip *ip,
14918 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
14920 + /* TODO: spinlocks? sanity checks? */
14921 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
14927 +static struct ipt_match quota_match = {
14930 + .checkentry = checkentry,
14931 + .me = THIS_MODULE
14937 + return ipt_register_match("a_match);
14940 +static void __exit
14943 + ipt_unregister_match("a_match);
14946 +module_init(init);
14947 +module_exit(fini);
14949 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_random.c linux-2.6.6/net/ipv4/netfilter/ipt_random.c
14950 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
14951 +++ linux-2.6.6/net/ipv4/netfilter/ipt_random.c 2004-05-18 12:36:59.000000000 +0200
14954 + This is a module which is used for a "random" match support.
14955 + This file is distributed under the terms of the GNU General Public
14956 + License (GPL). Copies of the GPL can be obtained from:
14957 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14959 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14962 +#include <linux/module.h>
14963 +#include <linux/skbuff.h>
14964 +#include <linux/ip.h>
14965 +#include <linux/random.h>
14966 +#include <net/tcp.h>
14967 +#include <linux/spinlock.h>
14968 +#include <linux/netfilter_ipv4/ip_tables.h>
14969 +#include <linux/netfilter_ipv4/ipt_random.h>
14971 +MODULE_LICENSE("GPL");
14974 +ipt_rand_match(const struct sk_buff *pskb,
14975 + const struct net_device *in,
14976 + const struct net_device *out,
14977 + const void *matchinfo,
14980 + u_int16_t datalen,
14983 + /* Parameters from userspace */
14984 + const struct ipt_rand_info *info = matchinfo;
14985 + u_int8_t random_number;
14987 + /* get 1 random number from the kernel random number generation routine */
14988 + get_random_bytes((void *)(&random_number), 1);
14990 + /* Do we match ? */
14991 + if (random_number <= info->average)
14998 +ipt_rand_checkentry(const char *tablename,
14999 + const struct ipt_ip *e,
15001 + unsigned int matchsize,
15002 + unsigned int hook_mask)
15004 + /* Parameters from userspace */
15005 + const struct ipt_rand_info *info = matchinfo;
15007 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
15008 + printk("ipt_random: matchsize %u != %u\n", matchsize,
15009 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
15013 + /* must be 1 <= average % <= 99 */
15014 + /* 1 x 2.55 = 2 */
15015 + /* 99 x 2.55 = 252 */
15016 + if ((info->average < 2) || (info->average > 252)) {
15017 + printk("ipt_random: invalid average %u\n", info->average);
15024 +static struct ipt_match ipt_rand_reg = {
15028 + ipt_rand_checkentry,
15032 +static int __init init(void)
15034 + if (ipt_register_match(&ipt_rand_reg))
15037 + printk("ipt_random match loaded\n");
15041 +static void __exit fini(void)
15043 + ipt_unregister_match(&ipt_rand_reg);
15044 + printk("ipt_random match unloaded\n");
15047 +module_init(init);
15048 +module_exit(fini);
15049 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.6/net/ipv4/netfilter/ipt_realm.c
15050 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
15051 +++ linux-2.6.6/net/ipv4/netfilter/ipt_realm.c 2004-05-18 12:37:05.000000000 +0200
15053 +/* IP tables module for matching the routing realm
15057 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
15059 + * This program is free software; you can redistribute it and/or modify
15060 + * it under the terms of the GNU General Public License version 2 as
15061 + * published by the Free Software Foundation.
15064 +#include <linux/module.h>
15065 +#include <linux/skbuff.h>
15066 +#include <linux/netdevice.h>
15067 +#include <net/route.h>
15069 +#include <linux/netfilter_ipv4/ipt_realm.h>
15070 +#include <linux/netfilter_ipv4/ip_tables.h>
15072 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
15073 +MODULE_LICENSE("GPL");
15076 +match(const struct sk_buff *skb,
15077 + const struct net_device *in,
15078 + const struct net_device *out,
15079 + const void *matchinfo,
15083 + const struct ipt_realm_info *info = matchinfo;
15084 + struct dst_entry *dst = skb->dst;
15089 + return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
15092 +static int check(const char *tablename,
15093 + const struct ipt_ip *ip,
15095 + unsigned int matchsize,
15096 + unsigned int hook_mask)
15099 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
15100 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
15101 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
15102 + "LOCAL_IN or FORWARD.\n");
15106 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
15112 +static struct ipt_match realm_match = {
15115 + .checkentry = check,
15116 + .me = THIS_MODULE
15119 +static int __init init(void)
15121 + return ipt_register_match(&realm_match);
15124 +static void __exit fini(void)
15126 + ipt_unregister_match(&realm_match);
15129 +module_init(init);
15130 +module_exit(fini);
15131 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.6/net/ipv4/netfilter/ipt_sctp.c
15132 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
15133 +++ linux-2.6.6/net/ipv4/netfilter/ipt_sctp.c 2004-05-18 12:37:09.000000000 +0200
15135 +#include <linux/module.h>
15136 +#include <linux/skbuff.h>
15137 +#include <net/ip.h>
15138 +#include <linux/sctp.h>
15140 +#include <linux/netfilter_ipv4/ip_tables.h>
15141 +#include <linux/netfilter_ipv4/ipt_sctp.h>
15144 +#define duprintf(format, args...) printk(format , ## args)
15146 +#define duprintf(format, args...)
15149 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
15150 + || (!!((invflag) & (option)) ^ (cond)))
15153 +match_flags(const struct ipt_sctp_flag_info *flag_info,
15154 + const int flag_count,
15155 + u_int8_t chunktype,
15156 + u_int8_t chunkflags)
15160 + for (i = 0; i < flag_count; i++) {
15161 + if (flag_info[i].chunktype == chunktype) {
15162 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
15170 +match_packet(const struct sk_buff *skb,
15171 + const u_int32_t *chunkmap,
15172 + int chunk_match_type,
15173 + const struct ipt_sctp_flag_info *flag_info,
15174 + const int flag_count,
15178 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
15179 + sctp_chunkhdr_t sch;
15183 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
15184 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
15187 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
15189 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
15190 + duprintf("Dropping invalid SCTP packet.\n");
15195 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
15196 + ++i, offset, sch.type, htons(sch.length), sch.flags);
15198 + offset += (htons(sch.length) + 3) & ~3;
15200 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
15202 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
15203 + switch (chunk_match_type) {
15204 + case SCTP_CHUNK_MATCH_ANY:
15205 + if (match_flags(flag_info, flag_count,
15206 + sch.type, sch.flags)) {
15211 + case SCTP_CHUNK_MATCH_ALL:
15212 + if (match_flags(flag_info, flag_count,
15213 + sch.type, sch.flags)) {
15214 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
15218 + case SCTP_CHUNK_MATCH_ONLY:
15219 + if (!match_flags(flag_info, flag_count,
15220 + sch.type, sch.flags)) {
15226 + switch (chunk_match_type) {
15227 + case SCTP_CHUNK_MATCH_ONLY:
15231 + } while (offset < skb->len);
15233 + switch (chunk_match_type) {
15234 + case SCTP_CHUNK_MATCH_ALL:
15235 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
15236 + case SCTP_CHUNK_MATCH_ANY:
15238 + case SCTP_CHUNK_MATCH_ONLY:
15242 + /* This will never be reached, but required to stop compiler whine */
15247 +match(const struct sk_buff *skb,
15248 + const struct net_device *in,
15249 + const struct net_device *out,
15250 + const void *matchinfo,
15254 + const struct ipt_sctp_info *info;
15255 + sctp_sctphdr_t sh;
15257 + info = (const struct ipt_sctp_info *)matchinfo;
15260 + duprintf("Dropping non-first fragment.. FIXME\n");
15264 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
15265 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
15269 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
15271 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
15272 + && (ntohs(sh.source) <= info->spts[1])),
15273 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
15274 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
15275 + && (ntohs(sh.dest) <= info->dpts[1])),
15276 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
15277 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
15278 + info->flag_info, info->flag_count,
15280 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
15284 +checkentry(const char *tablename,
15285 + const struct ipt_ip *ip,
15287 + unsigned int matchsize,
15288 + unsigned int hook_mask)
15290 + const struct ipt_sctp_info *info;
15292 + info = (const struct ipt_sctp_info *)matchinfo;
15294 + return ip->proto == IPPROTO_SCTP
15295 + && !(ip->invflags & IPT_INV_PROTO)
15296 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
15297 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
15298 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
15299 + && !(info->invflags & ~info->flags)
15300 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
15301 + (info->chunk_match_type &
15302 + (SCTP_CHUNK_MATCH_ALL
15303 + | SCTP_CHUNK_MATCH_ANY
15304 + | SCTP_CHUNK_MATCH_ONLY)));
15307 +static struct ipt_match sctp_match =
15309 + .list = { NULL, NULL},
15312 + .checkentry = &checkentry,
15314 + .me = THIS_MODULE
15317 +static int __init init(void)
15319 + return ipt_register_match(&sctp_match);
15322 +static void __exit fini(void)
15324 + ipt_unregister_match(&sctp_match);
15327 +module_init(init);
15328 +module_exit(fini);
15330 +MODULE_LICENSE("GPL");
15331 +MODULE_AUTHOR("Kiran Kumar Immidi");
15332 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
15334 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6/net/ipv4/netfilter/ipt_string.c
15335 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
15336 +++ linux-2.6.6/net/ipv4/netfilter/ipt_string.c 2004-05-18 12:40:41.000000000 +0200
15338 +/* Kernel module to match a string into a packet.
15340 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
15343 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
15344 + * Fixed SMP re-entrancy problem using per-cpu data areas
15345 + * for the skip/shift tables.
15346 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
15347 + * Fixed kernel panic, due to overrunning boyer moore string
15348 + * tables. Also slightly tweaked heuristic for deciding what
15349 + * search algo to use.
15350 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
15351 + * Implemented Boyer Moore Sublinear search algorithm
15352 + * alongside the existing linear search based on memcmp().
15353 + * Also a quick check to decide which method to use on a per
15357 +#include <linux/smp.h>
15358 +#include <linux/module.h>
15359 +#include <linux/skbuff.h>
15360 +#include <linux/file.h>
15361 +#include <net/sock.h>
15363 +#include <linux/netfilter_ipv4/ip_tables.h>
15364 +#include <linux/netfilter_ipv4/ipt_string.h>
15366 +MODULE_LICENSE("GPL");
15368 +struct string_per_cpu {
15374 +struct string_per_cpu *bm_string_data=NULL;
15376 +/* Boyer Moore Sublinear string search - VERY FAST */
15377 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
15379 + int M1, right_end, sk, sh;
15382 + int *skip, *shift, *len;
15384 + /* use data suitable for this CPU */
15385 + shift=bm_string_data[smp_processor_id()].shift;
15386 + skip=bm_string_data[smp_processor_id()].skip;
15387 + len=bm_string_data[smp_processor_id()].len;
15389 + /* Setup skip/shift tables */
15390 + M1 = right_end = needle_len-1;
15391 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
15392 + for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
15394 + for (i = 1; i < needle_len; i++) {
15395 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
15400 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
15401 + for (i = M1; i > 0; i--) shift[len[i]] = i;
15404 + for (i = 0; i < needle_len; i++) {
15405 + if (len[i] == M1 - i) ended = i;
15406 + if (ended) shift[i] = ended;
15409 + /* Do the search*/
15410 + while (right_end < haystack_len)
15412 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
15413 + if (i == needle_len) {
15414 + return haystack+(right_end - M1);
15417 + sk = skip[haystack[right_end - i]];
15419 + right_end = max(right_end - i + sk, right_end + sh);
15425 +/* Linear string search based on memcmp() */
15426 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
15428 + char *k = haystack + (haystack_len-needle_len);
15429 + char *t = haystack;
15431 + while ( t <= k ) {
15432 + if (memcmp(t, needle, needle_len) == 0)
15442 +match(const struct sk_buff *skb,
15443 + const struct net_device *in,
15444 + const struct net_device *out,
15445 + const void *matchinfo,
15448 + u_int16_t datalen,
15451 + const struct ipt_string_info *info = matchinfo;
15452 + struct iphdr *ip = skb->nh.iph;
15454 + char *needle, *haystack;
15455 + proc_ipt_search search=search_linear;
15457 + if ( !ip ) return 0;
15459 + /* get lenghts, and validate them */
15461 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
15462 + if ( nlen > hlen ) return 0;
15464 + needle=(char *)&info->string;
15465 + haystack=(char *)ip+(ip->ihl*4);
15467 + /* The sublinear search comes in to its own
15468 + * on the larger packets */
15469 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
15470 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
15471 + if ( hlen < BM_MAX_HLEN ) {
15472 + search=search_sublinear;
15474 + if (net_ratelimit())
15475 + printk(KERN_INFO "ipt_string: Packet too big "
15476 + "to attempt sublinear string search "
15477 + "(%d bytes)\n", hlen );
15481 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
15485 +checkentry(const char *tablename,
15486 + const struct ipt_ip *ip,
15488 + unsigned int matchsize,
15489 + unsigned int hook_mask)
15492 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
15498 +void string_freeup_data(void)
15502 + if ( bm_string_data ) {
15503 + for(c=0; c<smp_num_cpus; c++) {
15504 + if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
15505 + if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
15506 + if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
15508 + kfree(bm_string_data);
15512 +static struct ipt_match string_match
15513 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
15515 +static int __init init(void)
15521 + tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
15522 + alen=sizeof(int)*BM_MAX_HLEN;
15524 + /* allocate array of structures */
15525 + if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
15529 + memset(bm_string_data, 0, tlen);
15531 + /* allocate our skip/shift tables */
15532 + for(c=0; c<smp_num_cpus; c++) {
15533 + if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
15535 + if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
15537 + if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
15541 + return ipt_register_match(&string_match);
15544 + string_freeup_data();
15548 +static void __exit fini(void)
15550 + ipt_unregister_match(&string_match);
15551 + string_freeup_data();
15554 +module_init(init);
15555 +module_exit(fini);
15556 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_time.c linux-2.6.6/net/ipv4/netfilter/ipt_time.c
15557 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
15558 +++ linux-2.6.6/net/ipv4/netfilter/ipt_time.c 2004-05-18 12:37:29.000000000 +0200
15561 + This is a module which is used for time matching
15562 + It is using some modified code from dietlibc (localtime() function)
15563 + that you can find at http://www.fefe.de/dietlibc/
15564 + This file is distributed under the terms of the GNU General Public
15565 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
15566 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
15567 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
15568 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
15569 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
15570 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
15571 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
15572 + 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
15575 +#include <linux/module.h>
15576 +#include <linux/skbuff.h>
15577 +#include <linux/netfilter_ipv4/ip_tables.h>
15578 +#include <linux/netfilter_ipv4/ipt_time.h>
15579 +#include <linux/time.h>
15581 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
15582 +MODULE_DESCRIPTION("Match arrival timestamp/date");
15583 +MODULE_LICENSE("GPL");
15587 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
15588 + int tm_min; /* Minutes. [0-59] */
15589 + int tm_hour; /* Hours. [0-23] */
15590 + int tm_mday; /* Day. [1-31] */
15591 + int tm_mon; /* Month. [0-11] */
15592 + int tm_year; /* Year - 1900. */
15593 + int tm_wday; /* Day of week. [0-6] */
15594 + int tm_yday; /* Days in year.[0-365] */
15595 + int tm_isdst; /* DST. [-1/0/1]*/
15597 + long int tm_gmtoff; /* we don't care, we count from GMT */
15598 + const char *tm_zone; /* we don't care, we count from GMT */
15602 +localtime(const time_t *timepr, struct tm *r);
15605 +match(const struct sk_buff *skb,
15606 + const struct net_device *in,
15607 + const struct net_device *out,
15608 + const void *matchinfo,
15611 + u_int16_t datalen,
15614 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
15615 + struct tm currenttime; /* time human readable */
15616 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
15617 + u_int16_t packet_time;
15618 + struct timeval kerneltimeval;
15619 + time_t packet_local_time;
15621 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
15622 + if (info->kerneltime)
15624 + do_gettimeofday(&kerneltimeval);
15625 + packet_local_time = kerneltimeval.tv_sec;
15628 + packet_local_time = skb->stamp.tv_sec;
15630 + /* First we make sure we are in the date start-stop boundaries */
15631 + if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
15632 + return 0; /* We are outside the date boundaries */
15634 + /* Transform the timestamp of the packet, in a human readable form */
15635 + localtime(&packet_local_time, ¤ttime);
15637 + /* check if we match this timestamp, we start by the days... */
15638 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
15639 + return 0; /* the day doesn't match */
15641 + /* ... check the time now */
15642 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
15643 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
15646 + /* here we match ! */
15651 +checkentry(const char *tablename,
15652 + const struct ipt_ip *ip,
15654 + unsigned int matchsize,
15655 + unsigned int hook_mask)
15657 + struct ipt_time_info *info = matchinfo; /* match info for rule */
15659 + /* First, check that we are in the correct hooks */
15661 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15663 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
15666 + /* we use the kerneltime if we are in forward or output */
15667 + info->kerneltime = 1;
15668 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15669 + /* we use the skb time */
15670 + info->kerneltime = 0;
15672 + /* Check the size */
15673 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
15675 + /* Now check the coherence of the data ... */
15676 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
15677 + (info->time_stop > 1439))
15679 + printk(KERN_WARNING "ipt_time: invalid argument\n");
15686 +static struct ipt_match time_match
15687 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
15689 +static int __init init(void)
15691 + printk("ipt_time loading\n");
15692 + return ipt_register_match(&time_match);
15695 +static void __exit fini(void)
15697 + ipt_unregister_match(&time_match);
15698 + printk("ipt_time unloaded\n");
15701 +module_init(init);
15702 +module_exit(fini);
15705 +/* The part below is borowed and modified from dietlibc */
15707 +/* seconds per day */
15708 +#define SPD 24*60*60
15711 +localtime(const time_t *timepr, struct tm *r) {
15714 + extern struct timezone sys_tz;
15715 + const unsigned int __spm[12] =
15721 + (31+28+31+30+31),
15722 + (31+28+31+30+31+30),
15723 + (31+28+31+30+31+30+31),
15724 + (31+28+31+30+31+30+31+31),
15725 + (31+28+31+30+31+30+31+31+30),
15726 + (31+28+31+30+31+30+31+31+30+31),
15727 + (31+28+31+30+31+30+31+31+30+31+30),
15729 + register time_t work;
15731 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
15732 + work=timep%(SPD);
15733 + r->tm_sec=work%60; work/=60;
15734 + r->tm_min=work%60; r->tm_hour=work/60;
15735 + work=timep/(SPD);
15736 + r->tm_wday=(4+work)%7;
15737 + for (i=1970; ; ++i) {
15738 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
15744 + r->tm_year=i-1900;
15745 + for (i=11; i && __spm[i]>work; --i) ;
15747 + r->tm_mday=work-__spm[i]+1;
15749 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.6/net/ipv4/netfilter/ipt_u32.c
15750 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
15751 +++ linux-2.6.6/net/ipv4/netfilter/ipt_u32.c 2004-05-18 12:37:31.000000000 +0200
15753 +/* Kernel module to match u32 packet content. */
15756 +U32 tests whether quantities of up to 4 bytes extracted from a packet
15757 +have specified values. The specification of what to extract is general
15758 +enough to find data at given offsets from tcp headers or payloads.
15761 + The argument amounts to a program in a small language described below.
15762 + tests := location = value | tests && location = value
15763 + value := range | value , range
15764 + range := number | number : number
15765 + a single number, n, is interpreted the same as n:n
15766 + n:m is interpreted as the range of numbers >=n and <=m
15767 + location := number | location operator number
15768 + operator := & | << | >> | @
15770 + The operators &, <<, >>, && mean the same as in c. The = is really a set
15771 + membership operator and the value syntax describes a set. The @ operator
15772 + is what allows moving to the next header and is described further below.
15774 + *** Until I can find out how to avoid it, there are some artificial limits
15775 + on the size of the tests:
15776 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
15777 + - no more than 10 ranges (and 9 commas) per value
15778 + - no more than 10 numbers (and 9 operators) per location
15780 + To describe the meaning of location, imagine the following machine that
15781 + interprets it. There are three registers:
15782 + A is of type char*, initially the address of the IP header
15783 + B and C are unsigned 32 bit integers, initially zero
15785 + The instructions are:
15786 + number B = number;
15787 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
15788 + &number C = C&number
15789 + <<number C = C<<number
15790 + >>number C = C>>number
15791 + @number A = A+C; then do the instruction number
15792 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
15793 + Otherwise the result of the computation is the final value of C.
15795 + Whitespace is allowed but not required in the tests.
15796 + However the characters that do occur there are likely to require
15797 + shell quoting, so it's a good idea to enclose the arguments in quotes.
15800 + match IP packets with total length >= 256
15801 + The IP header contains a total length field in bytes 2-3.
15802 + --u32 "0&0xFFFF=0x100:0xFFFF"
15804 + AND that with FFFF (giving bytes 2-3),
15805 + and test whether that's in the range [0x100:0xFFFF]
15807 +Example: (more realistic, hence more complicated)
15808 + match icmp packets with icmp type 0
15809 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
15810 + --u32 "6&0xFF=1 && ...
15811 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
15812 + Next test that it's not a fragment.
15813 + (If so it might be part of such a packet but we can't always tell.)
15814 + n.b. This test is generally needed if you want to match anything
15815 + beyond the IP header.
15816 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
15817 + packet (not a fragment). Alternatively, you can allow first fragments
15818 + by only testing the last 5 bits of byte 6.
15819 + ... 4&0x3FFF=0 && ...
15820 + Last test: the first byte past the IP header (the type) is 0
15821 + This is where we have to use the @syntax. The length of the IP header
15822 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
15823 + IP header itself.
15824 + ... 0>>22&0x3C@0>>24=0"
15825 + The first 0 means read bytes 0-3,
15826 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
15827 + the first byte, so only 22 bits is four times that plus a few more bits.
15828 + &3C then eliminates the two extra bits on the right and the first four
15829 + bits of the first byte.
15830 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
15831 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
15832 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
15833 + @ means to use this number as a new offset into the packet, and read
15834 + four bytes starting from there. This is the first 4 bytes of the icmp
15835 + payload, of which byte 0 is the icmp type. Therefore we simply shift
15836 + the value 24 to the right to throw out all but the first byte and compare
15837 + the result with 0.
15840 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
15841 + First we test that the packet is a tcp packet (similar to icmp).
15842 + --u32 "6&0xFF=6 && ...
15843 + Next, test that it's not a fragment (same as above).
15844 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
15845 + 0>>22&3C as above computes the number of bytes in the IP header.
15846 + @ makes this the new offset into the packet, which is the start of the
15847 + tcp header. The length of the tcp header (again in 32 bit words) is
15848 + the left half of byte 12 of the tcp header. The 12>>26&3C
15849 + computes this length in bytes (similar to the IP header before).
15850 + @ makes this the new offset, which is the start of the tcp payload.
15851 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
15852 + result is any of 1, 2, 5 or 8
15855 +#include <linux/module.h>
15856 +#include <linux/skbuff.h>
15858 +#include <linux/netfilter_ipv4/ipt_u32.h>
15859 +#include <linux/netfilter_ipv4/ip_tables.h>
15861 +/* #include <asm-i386/timex.h> for timing */
15863 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
15864 +MODULE_DESCRIPTION("IP tables u32 matching module");
15865 +MODULE_LICENSE("GPL");
15868 +match(const struct sk_buff *skb,
15869 + const struct net_device *in,
15870 + const struct net_device *out,
15871 + const void *matchinfo,
15874 + u_int16_t datalen,
15877 + const struct ipt_u32 *data = matchinfo;
15879 + unsigned char* origbase = (char*)skb->nh.iph;
15880 + unsigned char* base = origbase;
15881 + unsigned char* head = skb->head;
15882 + unsigned char* end = skb->end;
15883 + int nnums, nvals;
15884 + u_int32_t pos, val;
15885 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
15886 + cycles1 = get_cycles(); */
15888 + for (testind=0; testind < data->ntests; testind++) {
15889 + base = origbase; /* reset for each test */
15890 + pos = data->tests[testind].location[0].number;
15891 + if (base+pos+3 > end || base+pos < head)
15893 + val = (base[pos]<<24) + (base[pos+1]<<16) +
15894 + (base[pos+2]<<8) + base[pos+3];
15895 + nnums = data->tests[testind].nnums;
15896 + for (i=1; i < nnums; i++) {
15897 + u_int32_t number = data->tests[testind].location[i].number;
15898 + switch (data->tests[testind].location[i].nextop) {
15899 + case IPT_U32_AND:
15900 + val = val & number;
15902 + case IPT_U32_LEFTSH:
15903 + val = val << number;
15905 + case IPT_U32_RIGHTSH:
15906 + val = val >> number;
15909 + base = base + val;
15911 + if (base+pos+3 > end || base+pos < head)
15913 + val = (base[pos]<<24) + (base[pos+1]<<16) +
15914 + (base[pos+2]<<8) + base[pos+3];
15918 + nvals = data->tests[testind].nvalues;
15919 + for (i=0; i < nvals; i++) {
15920 + if ((data->tests[testind].value[i].min <= val) &&
15921 + (val <= data->tests[testind].value[i].max)) {
15925 + if (i >= data->tests[testind].nvalues) {
15926 + /* cycles2 = get_cycles();
15927 + printk("failed %d in %d cycles\n", testind,
15928 + cycles2-cycles1); */
15932 + /* cycles2 = get_cycles();
15933 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
15938 +checkentry(const char *tablename,
15939 + const struct ipt_ip *ip,
15941 + unsigned int matchsize,
15942 + unsigned int hook_mask)
15944 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
15949 +static struct ipt_match u32_match
15950 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
15952 +static int __init init(void)
15954 + return ipt_register_match(&u32_match);
15957 +static void __exit fini(void)
15959 + ipt_unregister_match(&u32_match);
15962 +module_init(init);
15963 +module_exit(fini);
15964 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6/net/ipv4/netfilter/ipt_unclean.c
15965 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
15966 +++ linux-2.6.6/net/ipv4/netfilter/ipt_unclean.c 2004-05-18 12:40:37.000000000 +0200
15968 +/* Kernel module to match suspect packets. */
15969 +#include <linux/module.h>
15970 +#include <linux/skbuff.h>
15971 +#include <linux/ip.h>
15972 +#include <linux/udp.h>
15973 +#include <linux/tcp.h>
15974 +#include <linux/icmp.h>
15975 +#include <net/checksum.h>
15977 +#include <linux/netfilter_ipv4/ip_tables.h>
15979 +#define limpk(format, args...) \
15981 + if (net_ratelimit()) \
15982 + printk("ipt_unclean: %s" format, \
15983 + embedded ? "(embedded packet) " : "" , ## args); \
15986 +enum icmp_error_status
15988 + ICMP_MAY_BE_ERROR,
15995 + size_t min_len, max_len;
15996 + enum icmp_error_status err;
15997 + u_int8_t min_code, max_code;
16001 +check_ip(struct iphdr *iph, size_t length, int embedded);
16003 +/* ICMP-specific checks. */
16005 +check_icmp(const struct icmphdr *icmph,
16006 + u_int16_t datalen,
16007 + unsigned int offset,
16011 + static struct icmp_info info[]
16012 + = { [ICMP_ECHOREPLY]
16013 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16014 + [ICMP_DEST_UNREACH]
16015 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
16016 + [ICMP_SOURCE_QUENCH]
16017 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
16019 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
16021 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16022 + /* Router advertisement. */
16024 + = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
16025 + /* Router solicitation. */
16027 + = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
16028 + [ICMP_TIME_EXCEEDED]
16029 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
16030 + [ICMP_PARAMETERPROB]
16031 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
16033 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
16034 + [ICMP_TIMESTAMPREPLY]
16035 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
16036 + [ICMP_INFO_REQUEST]
16037 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16038 + [ICMP_INFO_REPLY]
16039 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16041 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
16042 + [ICMP_ADDRESSREPLY]
16043 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
16045 + /* Can't do anything if it's a fragment. */
16049 + /* Must cover type and code. */
16050 + if (datalen < 2) {
16051 + limpk("ICMP len=%u too short\n", datalen);
16055 + /* If not embedded. */
16057 + /* Bad checksum? Don't print, just ignore. */
16059 + && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
16062 + /* CHECK: Truncated ICMP (even if first fragment). */
16063 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16064 + && info[icmph->type].min_len != 0
16065 + && datalen < info[icmph->type].min_len) {
16066 + limpk("ICMP type %u len %u too short\n",
16067 + icmph->type, datalen);
16071 + /* CHECK: Check within known error ICMPs. */
16072 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16073 + && info[icmph->type].err == ICMP_IS_ERROR) {
16074 + /* CHECK: Embedded packet must be at least
16075 + length of iph + 8 bytes. */
16076 + struct iphdr *inner = (void *)icmph + 8;
16078 + /* datalen > 8 since all ICMP_IS_ERROR types
16079 + have min length > 8 */
16080 + if (datalen - 8 < sizeof(struct iphdr)) {
16081 + limpk("ICMP error internal way too short\n");
16084 + if (datalen - 8 < inner->ihl*4 + 8) {
16085 + limpk("ICMP error internal too short\n");
16088 + if (!check_ip(inner, datalen - 8, 1))
16092 + /* CHECK: Can't embed ICMP unless known non-error. */
16093 + if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
16094 + || info[icmph->type].err != ICMP_NOT_ERROR) {
16095 + limpk("ICMP type %u not embeddable\n",
16101 + /* CHECK: Invalid ICMP codes. */
16102 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16103 + && (icmph->code < info[icmph->type].min_code
16104 + || icmph->code > info[icmph->type].max_code)) {
16105 + limpk("ICMP type=%u code=%u\n",
16106 + icmph->type, icmph->code);
16110 + /* CHECK: Above maximum length. */
16111 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16112 + && info[icmph->type].max_len != 0
16113 + && datalen > info[icmph->type].max_len) {
16114 + limpk("ICMP type=%u too long: %u bytes\n",
16115 + icmph->type, datalen);
16119 + switch (icmph->type) {
16120 + case ICMP_PARAMETERPROB: {
16121 + /* CHECK: Problem param must be within error packet's
16123 + struct iphdr *iph = (void *)icmph + 8;
16124 + u_int32_t arg = ntohl(icmph->un.gateway);
16126 + if (icmph->code == 0) {
16127 + /* Code 0 means that upper 8 bits is pointer
16129 + if ((arg >> 24) >= iph->ihl*4) {
16130 + limpk("ICMP PARAMETERPROB ptr = %u\n",
16131 + ntohl(icmph->un.gateway) >> 24);
16134 + arg &= 0x00FFFFFF;
16137 + /* CHECK: Rest must be zero. */
16139 + limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
16146 + case ICMP_TIME_EXCEEDED:
16147 + case ICMP_SOURCE_QUENCH:
16148 + /* CHECK: Unused must be zero. */
16149 + if (icmph->un.gateway != 0) {
16150 + limpk("ICMP type=%u unused = %u\n",
16151 + icmph->type, ntohl(icmph->un.gateway));
16160 +/* UDP-specific checks. */
16162 +check_udp(const struct iphdr *iph,
16163 + const struct udphdr *udph,
16164 + u_int16_t datalen,
16165 + unsigned int offset,
16169 + /* Can't do anything if it's a fragment. */
16173 + /* CHECK: Must cover UDP header. */
16174 + if (datalen < sizeof(struct udphdr)) {
16175 + limpk("UDP len=%u too short\n", datalen);
16179 + /* Bad checksum? Don't print, just say it's unclean. */
16180 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
16181 + if (!more_frags && !embedded && udph->check
16182 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
16183 + csum_partial((char *)udph, datalen, 0)) != 0)
16186 + /* CHECK: Destination port can't be zero. */
16187 + if (!udph->dest) {
16188 + limpk("UDP zero destination port\n");
16192 + if (!more_frags) {
16194 + /* CHECK: UDP length must match. */
16195 + if (ntohs(udph->len) != datalen) {
16196 + limpk("UDP len too short %u vs %u\n",
16197 + ntohs(udph->len), datalen);
16201 + /* CHECK: UDP length be >= this truncated pkt. */
16202 + if (ntohs(udph->len) < datalen) {
16203 + limpk("UDP len too long %u vs %u\n",
16204 + ntohs(udph->len), datalen);
16209 + /* CHECK: UDP length must be > this frag's length. */
16210 + if (ntohs(udph->len) <= datalen) {
16211 + limpk("UDP fragment len too short %u vs %u\n",
16212 + ntohs(udph->len), datalen);
16220 +#define TH_FIN 0x01
16221 +#define TH_SYN 0x02
16222 +#define TH_RST 0x04
16223 +#define TH_PUSH 0x08
16224 +#define TH_ACK 0x10
16225 +#define TH_URG 0x20
16226 +#define TH_ECE 0x40
16227 +#define TH_CWR 0x80
16229 +/* table of valid flag combinations - ECE and CWR are always valid */
16230 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
16233 + [TH_SYN|TH_ACK] = 1,
16235 + [TH_RST|TH_ACK] = 1,
16236 + [TH_RST|TH_ACK|TH_PUSH] = 1,
16237 + [TH_FIN|TH_ACK] = 1,
16239 + [TH_ACK|TH_PUSH] = 1,
16240 + [TH_ACK|TH_URG] = 1,
16241 + [TH_ACK|TH_URG|TH_PUSH] = 1,
16242 + [TH_FIN|TH_ACK|TH_PUSH] = 1,
16243 + [TH_FIN|TH_ACK|TH_URG] = 1,
16244 + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
16247 +/* TCP-specific checks. */
16249 +check_tcp(const struct iphdr *iph,
16250 + const struct tcphdr *tcph,
16251 + u_int16_t datalen,
16252 + unsigned int offset,
16256 + u_int8_t *opt = (u_int8_t *)tcph;
16257 + u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
16258 + u_int8_t tcpflags;
16259 + int end_of_options = 0;
16262 + /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
16263 + /* In fact, this is caught below (offset < 516). */
16265 + /* Can't do anything if it's a fragment. */
16269 + /* CHECK: Smaller than minimal TCP hdr. */
16270 + if (datalen < sizeof(struct tcphdr)) {
16272 + limpk("Packet length %u < TCP header.\n", datalen);
16275 + /* Must have ports available (datalen >= 8), from
16276 + check_icmp which set embedded = 1 */
16277 + /* CHECK: TCP ports inside ICMP error */
16278 + if (!tcph->source || !tcph->dest) {
16279 + limpk("Zero TCP ports %u/%u.\n",
16280 + htons(tcph->source), htons(tcph->dest));
16286 + /* CHECK: Smaller than actual TCP hdr. */
16287 + if (datalen < tcph->doff * 4) {
16289 + limpk("Packet length %u < actual TCP header.\n",
16296 + /* Bad checksum? Don't print, just say it's unclean. */
16297 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
16298 + if (!more_frags && !embedded
16299 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
16300 + csum_partial((char *)tcph, datalen, 0)) != 0)
16303 + /* CHECK: TCP ports non-zero */
16304 + if (!tcph->source || !tcph->dest) {
16305 + limpk("Zero TCP ports %u/%u.\n",
16306 + htons(tcph->source), htons(tcph->dest));
16310 + /* CHECK: TCP reserved bits zero. */
16311 + if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
16312 + limpk("TCP reserved bits not zero\n");
16316 + /* CHECK: TCP flags. */
16317 + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
16318 + if (!tcp_valid_flags[tcpflags]) {
16319 + limpk("TCP flags bad: %u\n", tcpflags);
16323 + for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
16324 + switch (opt[i]) {
16326 + end_of_options = 1;
16333 + /* CHECK: options after EOO. */
16334 + if (end_of_options) {
16335 + limpk("TCP option %u after end\n",
16339 + /* CHECK: options at tail. */
16340 + else if (i+1 >= tcph->doff * 4) {
16341 + limpk("TCP option %u at tail\n",
16345 + /* CHECK: zero-length options. */
16346 + else if (opt[i+1] == 0) {
16347 + limpk("TCP option %u 0 len\n",
16351 + /* CHECK: oversize options. */
16352 + else if (&opt[i] + opt[i+1] > endhdr) {
16353 + limpk("TCP option %u at %Zu too long\n",
16354 + (unsigned int) opt[i], i);
16357 + /* Move to next option */
16365 +/* Returns 1 if ok */
16366 +/* Standard IP checks. */
16368 +check_ip(struct iphdr *iph, size_t length, int embedded)
16370 + u_int8_t *opt = (u_int8_t *)iph;
16371 + u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
16372 + int end_of_options = 0;
16376 + unsigned int offset;
16378 + /* Should only happen for local outgoing raw-socket packets. */
16379 + /* CHECK: length >= ip header. */
16380 + if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
16381 + limpk("Packet length %Zu < IP header.\n", length);
16385 + offset = ntohs(iph->frag_off) & IP_OFFSET;
16386 + protoh = (void *)iph + iph->ihl * 4;
16387 + datalen = length - iph->ihl * 4;
16389 + /* CHECK: Embedded fragment. */
16390 + if (embedded && offset) {
16391 + limpk("Embedded fragment.\n");
16395 + for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
16396 + switch (opt[i]) {
16398 + end_of_options = 1;
16405 + /* CHECK: options after EOO. */
16406 + if (end_of_options) {
16407 + limpk("IP option %u after end\n",
16411 + /* CHECK: options at tail. */
16412 + else if (i+1 >= iph->ihl * 4) {
16413 + limpk("IP option %u at tail\n",
16417 + /* CHECK: zero-length or one-length options. */
16418 + else if (opt[i+1] < 2) {
16419 + limpk("IP option %u %u len\n",
16420 + opt[i], opt[i+1]);
16423 + /* CHECK: oversize options. */
16424 + else if (&opt[i] + opt[i+1] > endhdr) {
16425 + limpk("IP option %u at %u too long\n",
16429 + /* Move to next option */
16434 + /* Fragment checks. */
16436 + /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
16437 + if ((ntohs(iph->frag_off) & IP_MF)
16438 + && (ntohs(iph->tot_len) % 8) != 0) {
16439 + limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
16443 + /* CHECK: Oversize fragment a-la Ping of Death. */
16444 + if (offset * 8 + datalen > 65535) {
16445 + limpk("Oversize fragment to %u.\n", offset * 8);
16449 + /* CHECK: DF set and offset or MF set. */
16450 + if ((ntohs(iph->frag_off) & IP_DF)
16451 + && (offset || (ntohs(iph->frag_off) & IP_MF))) {
16452 + limpk("DF set and offset=%u, MF=%u.\n",
16453 + offset, ntohs(iph->frag_off) & IP_MF);
16457 + /* CHECK: Zero-sized fragments. */
16458 + if ((offset || (ntohs(iph->frag_off) & IP_MF))
16459 + && datalen == 0) {
16460 + limpk("Zero size fragment offset=%u\n", offset);
16464 + /* Note: we can have even middle fragments smaller than this:
16465 + consider a large packet passing through a 600MTU then
16466 + 576MTU link: this gives a fragment of 24 data bytes. But
16467 + everyone packs fragments largest first, hence a fragment
16468 + can't START before 576 - MAX_IP_HEADER_LEN. */
16470 + /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
16471 + down to 128 (576 taken from RFC 791: All hosts must be
16472 + prepared to accept datagrams of up to 576 octets). Use 128
16474 +#define MIN_LIKELY_MTU 128
16475 + /* CHECK: Min size of first frag = 128. */
16476 + if ((ntohs(iph->frag_off) & IP_MF)
16478 + && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
16479 + limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
16484 + /* CHECK: Min offset of frag = 128 - IP hdr len. */
16485 + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
16486 + limpk("Fragment starts at %u < %u\n", offset * 8,
16487 + MIN_LIKELY_MTU - iph->ihl * 4);
16491 + /* CHECK: Protocol specification non-zero. */
16492 + if (iph->protocol == 0) {
16493 + limpk("Zero protocol\n");
16497 + /* CHECK: Do not use what is unused.
16498 + * First bit of fragmentation flags should be unused.
16499 + * May be used by OS fingerprinting tools.
16500 + * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
16502 + if (ntohs(iph->frag_off)>>15) {
16503 + limpk("IP unused bit set\n");
16507 + /* Per-protocol checks. */
16508 + switch (iph->protocol) {
16509 + case IPPROTO_ICMP:
16510 + return check_icmp(protoh, datalen, offset,
16511 + (ntohs(iph->frag_off) & IP_MF),
16514 + case IPPROTO_UDP:
16515 + return check_udp(iph, protoh, datalen, offset,
16516 + (ntohs(iph->frag_off) & IP_MF),
16519 + case IPPROTO_TCP:
16520 + return check_tcp(iph, protoh, datalen, offset,
16521 + (ntohs(iph->frag_off) & IP_MF),
16524 + /* Ignorance is bliss. */
16530 +match(const struct sk_buff *skb,
16531 + const struct net_device *in,
16532 + const struct net_device *out,
16533 + const void *matchinfo,
16536 + u_int16_t datalen,
16539 + return !check_ip(skb->nh.iph, skb->len, 0);
16542 +/* Called when user tries to insert an entry of this type. */
16544 +checkentry(const char *tablename,
16545 + const struct ipt_ip *ip,
16547 + unsigned int matchsize,
16548 + unsigned int hook_mask)
16550 + if (matchsize != IPT_ALIGN(0))
16556 +static struct ipt_match unclean_match
16557 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
16559 +static int __init init(void)
16561 + return ipt_register_match(&unclean_match);
16564 +static void __exit fini(void)
16566 + ipt_unregister_match(&unclean_match);
16569 +module_init(init);
16570 +module_exit(fini);
16571 +MODULE_LICENSE("GPL");
16572 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6/net/ipv4/netfilter/iptable_filter.c
16573 --- linux-2.6.6.org/net/ipv4/netfilter/iptable_filter.c 2004-05-10 04:32:28.000000000 +0200
16574 +++ linux-2.6.6/net/ipv4/netfilter/iptable_filter.c 2004-05-18 12:38:32.000000000 +0200
16577 sizeof(struct ipt_entry),
16578 sizeof(struct ipt_standard),
16579 - 0, { 0, 0 }, { } },
16580 + 0, NULL, 0, { 0, 0 }, { } },
16581 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16582 -NF_ACCEPT - 1 } },
16586 sizeof(struct ipt_entry),
16587 sizeof(struct ipt_standard),
16588 - 0, { 0, 0 }, { } },
16589 + 0, NULL, 0, { 0, 0 }, { } },
16590 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16591 -NF_ACCEPT - 1 } },
16595 sizeof(struct ipt_entry),
16596 sizeof(struct ipt_standard),
16597 - 0, { 0, 0 }, { } },
16598 + 0, NULL, 0, { 0, 0 }, { } },
16599 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16604 sizeof(struct ipt_entry),
16605 sizeof(struct ipt_error),
16606 - 0, { 0, 0 }, { } },
16607 + 0, NULL, 0, { 0, 0 }, { } },
16608 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16611 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6/net/ipv4/netfilter/iptable_mangle.c
16612 --- linux-2.6.6.org/net/ipv4/netfilter/iptable_mangle.c 2004-05-10 04:33:14.000000000 +0200
16613 +++ linux-2.6.6/net/ipv4/netfilter/iptable_mangle.c 2004-05-18 12:38:32.000000000 +0200
16616 sizeof(struct ipt_entry),
16617 sizeof(struct ipt_standard),
16618 - 0, { 0, 0 }, { } },
16619 + 0, NULL, 0, { 0, 0 }, { } },
16620 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16621 -NF_ACCEPT - 1 } },
16625 sizeof(struct ipt_entry),
16626 sizeof(struct ipt_standard),
16627 - 0, { 0, 0 }, { } },
16628 + 0, NULL, 0, { 0, 0 }, { } },
16629 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16630 -NF_ACCEPT - 1 } },
16634 sizeof(struct ipt_entry),
16635 sizeof(struct ipt_standard),
16636 - 0, { 0, 0 }, { } },
16637 + 0, NULL, 0, { 0, 0 }, { } },
16638 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16639 -NF_ACCEPT - 1 } },
16643 sizeof(struct ipt_entry),
16644 sizeof(struct ipt_standard),
16645 - 0, { 0, 0 }, { } },
16646 + 0, NULL, 0, { 0, 0 }, { } },
16647 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16648 -NF_ACCEPT - 1 } },
16650 @@ -106,7 +106,7 @@
16652 sizeof(struct ipt_entry),
16653 sizeof(struct ipt_standard),
16654 - 0, { 0, 0 }, { } },
16655 + 0, NULL, 0, { 0, 0 }, { } },
16656 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16657 -NF_ACCEPT - 1 } },
16659 @@ -115,7 +115,7 @@
16661 sizeof(struct ipt_entry),
16662 sizeof(struct ipt_error),
16663 - 0, { 0, 0 }, { } },
16664 + 0, NULL, 0, { 0, 0 }, { } },
16665 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16668 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6/net/ipv4/netfilter/iptable_raw.c
16669 --- linux-2.6.6.org/net/ipv4/netfilter/iptable_raw.c 2004-05-10 04:33:19.000000000 +0200
16670 +++ linux-2.6.6/net/ipv4/netfilter/iptable_raw.c 2004-05-18 12:38:32.000000000 +0200
16673 sizeof(struct ipt_entry),
16674 sizeof(struct ipt_standard),
16675 - 0, { 0, 0 }, { } },
16676 + 0, NULL, 0, { 0, 0 }, { } },
16677 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16678 -NF_ACCEPT - 1 } },
16682 sizeof(struct ipt_entry),
16683 sizeof(struct ipt_standard),
16684 - 0, { 0, 0 }, { } },
16685 + 0, NULL, 0, { 0, 0 }, { } },
16686 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16691 sizeof(struct ipt_entry),
16692 sizeof(struct ipt_error),
16693 - 0, { 0, 0 }, { } },
16694 + 0, NULL, 0, { 0, 0 }, { } },
16695 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16698 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/raw.c linux-2.6.6/net/ipv4/raw.c
16699 --- linux-2.6.6.org/net/ipv4/raw.c 2004-05-10 04:32:38.000000000 +0200
16700 +++ linux-2.6.6/net/ipv4/raw.c 2004-05-18 12:39:23.000000000 +0200
16701 @@ -249,6 +249,7 @@
16703 return NET_RX_DROP;
16707 skb_push(skb, skb->data - skb->nh.raw);
16709 @@ -307,7 +308,7 @@
16712 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
16716 err = inet->recverr ? net_xmit_errno(err) : 0;
16718 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/tcp_ipv4.c linux-2.6.6/net/ipv4/tcp_ipv4.c
16719 --- linux-2.6.6.org/net/ipv4/tcp_ipv4.c 2004-05-18 11:20:48.000000000 +0200
16720 +++ linux-2.6.6/net/ipv4/tcp_ipv4.c 2004-05-18 12:39:47.000000000 +0200
16721 @@ -1785,6 +1785,7 @@
16723 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
16724 goto discard_and_relse;
16727 if (sk_filter(sk, skb, 0))
16728 goto discard_and_relse;
16729 @@ -2636,6 +2637,7 @@
16730 EXPORT_SYMBOL(tcp_v4_connect);
16731 EXPORT_SYMBOL(tcp_v4_do_rcv);
16732 EXPORT_SYMBOL(tcp_v4_lookup_listener);
16733 +EXPORT_SYMBOL(tcp_v4_lookup);
16734 EXPORT_SYMBOL(tcp_v4_rebuild_header);
16735 EXPORT_SYMBOL(tcp_v4_remember_stamp);
16736 EXPORT_SYMBOL(tcp_v4_send_check);
16737 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/udp.c linux-2.6.6/net/ipv4/udp.c
16738 --- linux-2.6.6.org/net/ipv4/udp.c 2004-05-10 04:32:01.000000000 +0200
16739 +++ linux-2.6.6/net/ipv4/udp.c 2004-05-18 12:39:47.000000000 +0200
16740 @@ -1045,6 +1045,7 @@
16746 if (up->encap_type) {
16748 @@ -1210,6 +1211,7 @@
16750 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
16754 /* No socket. Drop packet silently, if checksum is wrong */
16755 if (udp_checksum_complete(skb))
16756 @@ -1558,6 +1560,7 @@
16757 EXPORT_SYMBOL(udp_port_rover);
16758 EXPORT_SYMBOL(udp_prot);
16759 EXPORT_SYMBOL(udp_sendmsg);
16760 +EXPORT_SYMBOL(udp_v4_lookup);
16762 #ifdef CONFIG_PROC_FS
16763 EXPORT_SYMBOL(udp_proc_register);
16764 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6/net/ipv4/xfrm4_tunnel.c
16765 --- linux-2.6.6.org/net/ipv4/xfrm4_tunnel.c 2004-05-10 04:32:00.000000000 +0200
16766 +++ linux-2.6.6/net/ipv4/xfrm4_tunnel.c 2004-05-18 12:39:22.000000000 +0200
16768 err = -EHOSTUNREACH;
16771 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
16772 return NET_XMIT_BYPASS;
16775 @@ -170,6 +171,7 @@
16776 .handler = ipip_rcv,
16777 .err_handler = ipip_err,
16782 static int __init ipip_init(void)
16783 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/ip6_tunnel.c linux-2.6.6/net/ipv6/ip6_tunnel.c
16784 --- linux-2.6.6.org/net/ipv6/ip6_tunnel.c 2004-05-10 04:31:59.000000000 +0200
16785 +++ linux-2.6.6/net/ipv6/ip6_tunnel.c 2004-05-18 12:35:50.000000000 +0200
16786 @@ -715,13 +715,7 @@
16787 ipv6h->nexthdr = proto;
16788 ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
16789 ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
16790 -#ifdef CONFIG_NETFILTER
16791 - nf_conntrack_put(skb->nfct);
16792 - skb->nfct = NULL;
16793 -#ifdef CONFIG_NETFILTER_DEBUG
16794 - skb->nf_debug = 0;
16798 pkt_len = skb->len;
16799 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
16800 skb->dst->dev, dst_output);
16801 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/Kconfig linux-2.6.6/net/ipv6/netfilter/Kconfig
16802 --- linux-2.6.6.org/net/ipv6/netfilter/Kconfig 2004-05-10 04:33:13.000000000 +0200
16803 +++ linux-2.6.6/net/ipv6/netfilter/Kconfig 2004-05-18 12:39:55.000000000 +0200
16804 @@ -230,5 +230,107 @@
16805 <file:Documentation/modules.txt>. If unsure, say `N'.
16808 +config IP6_NF_TARGET_HL
16809 + tristate 'HL target support'
16810 + depends on IP6_NF_MANGLE
16812 + This option adds a `HL' target, which allows you to modify the value of
16813 + IPv6 Hop Limit field.
16815 + If you want to compile it as a module, say M here and read
16816 + <file:Documentation/modules.txt>. If unsure, say `N'.
16818 +config IP6_NF_TARGET_REJECT
16819 + tristate 'REJECT target support'
16820 + depends on IP6_NF_FILTER
16822 + The REJECT target allows a filtering rule to specify that an ICMPv6
16823 + error should be issued in response to an incoming packet, rather
16824 + than silently being dropped.
16826 + If you want to compile it as a module, say M here and read
16827 + Documentation/modules.txt. If unsure, say `N'.
16829 +config IP6_NF_MATCH_FUZZY
16830 + tristate 'Fuzzy match support'
16831 + depends on IP6_NF_FILTER
16833 + This option adds a `fuzzy' match, which allows you to match
16834 + packets according to a fuzzy logic based law.
16836 + If you want to compile it as a module, say M here and read
16837 + Documentation/modules.txt. If unsure, say `N'.
16839 +config IP6_NF_MATCH_NTH
16840 + tristate 'Nth match support'
16841 + depends on IP6_NF_IPTABLES
16843 + This option adds a `Nth' match, which allow you to make
16844 + rules that match every Nth packet. By default there are
16845 + 16 different counters.
16848 + --every Nth Match every Nth packet
16849 + [--counter] num Use counter 0-15 (default:0)
16850 + [--start] num Initialize the counter at the number 'num'
16851 + instead of 0. Must be between 0 and Nth-1
16852 + [--packet] num Match on 'num' packet. Must be between 0
16855 + If --packet is used for a counter than
16856 + there must be Nth number of --packet
16857 + rules, covering all values between 0 and
16858 + Nth-1 inclusively.
16860 + If you want to compile it as a module, say M here and read
16861 + Documentation/modules.txt. If unsure, say `N'.
16863 +config IP6_NF_MATCH_RANDOM
16864 + tristate 'Random match support'
16865 + depends on IP6_NF_IPTABLES
16867 + This option adds a `random' match,
16868 + which allow you to match packets randomly
16869 + following a given probability.
16871 + If you want to compile it as a module, say M here and read
16872 + Documentation/modules.txt. If unsure, say `N'.
16874 +config IP6_NF_TARGET_ROUTE
16875 + tristate ' ROUTE target support'
16876 + depends on IP6_NF_MANGLE
16878 + This option adds a `ROUTE' target, which enables you to setup unusual
16879 + routes. The ROUTE target is also able to change the incoming interface
16882 + The target can be or not a final target. It has to be used inside the
16885 + Not working as a module.
16887 +config IP6_NF_TARGET_TRACE
16888 + tristate 'TRACE target support'
16889 + depends on IP6_NF_RAW
16891 + The TRACE target allows packets to be traced as those
16892 + matches any subsequent rule in any table/rule. The matched
16893 + rule and the packet is logged with the prefix
16895 + TRACE: tablename/chainname/rulenum
16897 + If you want to compile it as a module, say M here and read
16898 + <file:Documentation/modules.txt>. If unsure, say `N'.
16900 +config IP6_NF_MATCH_POLICY
16901 + tristate "IPsec policy match support"
16902 + depends on IP6_NF_IPTABLES && XFRM
16904 + Policy matching allows you to match packets based on the
16905 + IPsec policy that was used during decapsulation/will
16906 + be used during encapsulation.
16908 + To compile it as a module, choose M here. If unsure, say N.
16912 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/Makefile linux-2.6.6/net/ipv6/netfilter/Makefile
16913 --- linux-2.6.6.org/net/ipv6/netfilter/Makefile 2004-05-10 04:32:39.000000000 +0200
16914 +++ linux-2.6.6/net/ipv6/netfilter/Makefile 2004-05-18 12:39:55.000000000 +0200
16916 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
16917 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
16918 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
16919 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
16920 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
16921 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
16922 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
16923 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
16924 obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
16925 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
16926 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
16927 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
16928 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
16929 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16930 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
16931 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
16932 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
16933 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
16934 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
16935 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
16937 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
16939 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
16940 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
16941 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
16942 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
16943 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
16944 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6/net/ipv6/netfilter/ip6_tables.c
16945 --- linux-2.6.6.org/net/ipv6/netfilter/ip6_tables.c 2004-05-10 04:33:19.000000000 +0200
16946 +++ linux-2.6.6/net/ipv6/netfilter/ip6_tables.c 2004-05-18 12:38:32.000000000 +0200
16948 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
16949 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
16951 +static const char *hook6names[] = {
16952 + [NF_IP6_PRE_ROUTING] "PREROUTING",
16953 + [NF_IP6_LOCAL_IN] "INPUT",
16954 + [NF_IP6_FORWARD] "FORWARD",
16955 + [NF_IP6_LOCAL_OUT] "OUTPUT",
16956 + [NF_IP6_POST_ROUTING] "POSTROUTING",
16959 /*#define DEBUG_IP_FIREWALL*/
16960 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
16961 /*#define DEBUG_IP_FIREWALL_USER*/
16962 @@ -408,6 +416,12 @@
16964 t = ip6t_get_target(e);
16965 IP_NF_ASSERT(t->u.kernel.target);
16967 + /* The packet traced and the rule isn't an unconditional return/END. */
16968 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
16969 + nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
16970 + table->name, e->chainname, e->rulenum);
16972 /* Standard target? */
16973 if (!t->u.kernel.target->target) {
16975 @@ -561,6 +575,29 @@
16976 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
16980 +find_error_target(struct ip6t_entry *s,
16981 + struct ip6t_entry *e,
16982 + char **chainname)
16984 + struct ip6t_entry_target *t;
16985 + static struct ip6t_entry *found = NULL;
16990 + t = ip6t_get_target(found);
16991 + if (strcmp(t->u.user.name,
16992 + IP6T_ERROR_TARGET) == 0) {
16993 + *chainname = t->data;
17002 /* All zeroes == unconditional rule. */
17004 unconditional(const struct ip6t_ip6 *ipv6)
17005 @@ -580,6 +617,8 @@
17006 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
17009 + char *chainname = NULL;
17010 + u_int32_t rulenum;
17012 /* No recursion; use packet counter to save back ptrs (reset
17013 to 0 as we leave), and comefrom to save source hook bitmask */
17014 @@ -593,6 +632,8 @@
17016 /* Set initial back pointer. */
17017 e->counters.pcnt = pos;
17019 + chainname = (char *) hook6names[hook];
17022 struct ip6t_standard_target *t
17023 @@ -605,6 +646,8 @@
17026 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
17027 + e->rulenum = rulenum++;
17028 + e->chainname = chainname;
17030 /* Unconditional return/END. */
17031 if (e->target_offset == sizeof(struct ip6t_entry)
17032 @@ -614,6 +657,10 @@
17033 && unconditional(&e->ipv6)) {
17034 unsigned int oldpos, size;
17036 + /* Set unconditional rulenum to zero. */
17038 + e->counters.bcnt = 0;
17040 /* Return: backtrack through the last
17043 @@ -639,6 +686,11 @@
17044 (newinfo->entries + pos);
17045 } while (oldpos == pos + e->next_offset);
17047 + /* Restore chainname, rulenum. */
17048 + chainname = e->chainname;
17049 + rulenum = e->counters.bcnt;
17050 + e->counters.bcnt = 0;
17052 /* Move along one */
17053 size = e->next_offset;
17054 e = (struct ip6t_entry *)
17055 @@ -654,6 +706,17 @@
17056 /* This a jump; chase it. */
17057 duprintf("Jump rule %u -> %u\n",
17059 + e->counters.bcnt = rulenum++;
17061 + e = (struct ip6t_entry *)
17062 + (newinfo->entries + newpos);
17063 + if (IP6T_ENTRY_ITERATE(newinfo->entries,
17065 + find_error_target,
17066 + e, &chainname) == 0) {
17067 + printk("ip6_tables: table screwed up!\n");
17071 /* ... this is a fallthru */
17072 newpos = pos + e->next_offset;
17073 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.6/net/ipv6/netfilter/ip6t_HL.c
17074 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
17075 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_HL.c 2004-05-18 12:35:59.000000000 +0200
17078 + * Hop Limit modification target for ip6tables
17079 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
17080 + * Based on HW's TTL module
17082 + * This software is distributed under the terms of GNU GPL
17085 +#include <linux/module.h>
17086 +#include <linux/skbuff.h>
17087 +#include <linux/ip.h>
17089 +#include <linux/netfilter_ipv6/ip6_tables.h>
17090 +#include <linux/netfilter_ipv6/ip6t_HL.h>
17092 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
17093 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
17094 +MODULE_LICENSE("GPL");
17096 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
17097 + const struct net_device *in, const struct net_device *out,
17098 + const void *targinfo, void *userinfo)
17100 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
17101 + const struct ip6t_HL_info *info = targinfo;
17102 + u_int16_t diffs[2];
17105 + switch (info->mode) {
17106 + case IP6T_HL_SET:
17107 + new_hl = info->hop_limit;
17109 + case IP6T_HL_INC:
17110 + new_hl = ip6h->hop_limit + info->hop_limit;
17111 + if (new_hl > 255)
17114 + case IP6T_HL_DEC:
17115 + new_hl = ip6h->hop_limit + info->hop_limit;
17120 + new_hl = ip6h->hop_limit;
17124 + if (new_hl != ip6h->hop_limit) {
17125 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
17126 + ip6h->hop_limit = new_hl;
17127 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
17130 + return IP6T_CONTINUE;
17133 +static int ip6t_hl_checkentry(const char *tablename,
17134 + const struct ip6t_entry *e,
17136 + unsigned int targinfosize,
17137 + unsigned int hook_mask)
17139 + struct ip6t_HL_info *info = targinfo;
17141 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
17142 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
17144 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
17148 + if (strcmp(tablename, "mangle")) {
17149 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
17153 + if (info->mode > IP6T_HL_MAXMODE) {
17154 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
17159 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
17160 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
17167 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
17168 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
17170 +static int __init init(void)
17172 + return ip6t_register_target(&ip6t_HL);
17175 +static void __exit fini(void)
17177 + ip6t_unregister_target(&ip6t_HL);
17180 +module_init(init);
17181 +module_exit(fini);
17182 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.6/net/ipv6/netfilter/ip6t_REJECT.c
17183 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
17184 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_REJECT.c 2004-05-18 12:36:05.000000000 +0200
17187 + * IP6 tables REJECT target module
17188 + * Linux INET6 implementation
17190 + * Copyright (C)2003 USAGI/WIDE Project
17193 + * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
17195 + * Based on net/ipv4/netfilter/ipt_REJECT.c
17197 + * This program is free software; you can redistribute it and/or
17198 + * modify it under the terms of the GNU General Public License
17199 + * as published by the Free Software Foundation; either version
17200 + * 2 of the License, or (at your option) any later version.
17203 +#include <linux/config.h>
17204 +#include <linux/module.h>
17205 +#include <linux/skbuff.h>
17206 +#include <linux/icmpv6.h>
17207 +#include <net/ipv6.h>
17208 +#include <net/tcp.h>
17209 +#include <net/icmp.h>
17210 +#include <net/ip6_fib.h>
17211 +#include <net/ip6_route.h>
17212 +#include <net/flow.h>
17213 +#include <linux/netfilter_ipv6/ip6_tables.h>
17214 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
17216 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
17217 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
17218 +MODULE_LICENSE("GPL");
17221 +#define DEBUGP printk
17223 +#define DEBUGP(format, args...)
17227 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
17229 + void (*attach)(struct sk_buff *, struct nf_ct_info *);
17230 + if (nfct && (attach = ip6_ct_attach) != NULL) {
17232 + attach(new_skb, nfct);
17237 +static int maybe_reroute(struct sk_buff *skb)
17239 + if (skb->nfcache & NFC_ALTERED){
17240 + if (ip6_route_me_harder(skb) != 0){
17246 + return dst_output(skb);
17249 +/* Send RST reply */
17250 +static void send_reset(struct sk_buff *oldskb)
17252 + struct sk_buff *nskb;
17253 + struct tcphdr otcph, *tcph;
17254 + unsigned int otcplen, tcphoff, hh_len;
17256 + struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
17257 + struct dst_entry *dst = NULL;
17260 + proto = oip6h->nexthdr;
17263 + if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
17264 + (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
17265 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17269 + tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
17270 + &proto, oldskb->len - ((u8*)(oip6h+1)
17271 + - oldskb->data));
17273 + if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
17274 + DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
17278 + otcplen = oldskb->len - tcphoff;
17280 + /* IP header checks: fragment, too short. */
17281 + if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
17282 + DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
17287 + if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
17288 + if (net_ratelimit())
17289 + printk("ip6t_REJECT: Can't copy tcp header\n");
17293 + /* No RST for RST. */
17295 + DEBUGP("ip6t_REJECT: RST is set\n");
17299 + /* Check checksum. */
17300 + if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
17301 + skb_checksum(oldskb, tcphoff, otcplen, 0))) {
17302 + DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
17306 + memset(&fl, 0, sizeof(fl));
17307 + fl.proto = IPPROTO_TCP;
17308 + ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
17309 + ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
17310 + fl.fl_ip_sport = otcph.dest;
17311 + fl.fl_ip_dport = otcph.source;
17312 + err = ip6_dst_lookup(NULL, &dst, &fl);
17314 + if (net_ratelimit())
17315 + printk("ip6t_REJECT: can't find dst. err = %d\n", err);
17319 + hh_len = (dst->dev->hard_header_len + 15)&~15;
17320 + nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
17321 + + sizeof(struct tcphdr) + dst->trailer_len,
17325 + if (net_ratelimit())
17326 + printk("ip6t_REJECT: Can't alloc skb\n");
17327 + dst_release(dst);
17334 + skb_reserve(nskb, hh_len + dst->header_len);
17336 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17337 + skb_put(nskb, sizeof(struct ipv6hdr));
17338 + ip6h->version = 6;
17339 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17340 + ip6h->nexthdr = IPPROTO_TCP;
17341 + ip6h->payload_len = htons(sizeof(struct tcphdr));
17342 + ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
17343 + ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
17345 + tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
17346 + /* Truncate to length (no data) */
17347 + tcph->doff = sizeof(struct tcphdr)/4;
17348 + tcph->source = otcph.dest;
17349 + tcph->dest = otcph.source;
17353 + tcph->seq = otcph.ack_seq;
17354 + tcph->ack_seq = 0;
17357 + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
17358 + + otcplen - (otcph.doff<<2));
17362 + /* Reset flags */
17363 + ((u_int8_t *)tcph)[13] = 0;
17365 + tcph->ack = needs_ack;
17366 + tcph->window = 0;
17367 + tcph->urg_ptr = 0;
17370 + /* Adjust TCP checksum */
17371 + tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
17372 + &nskb->nh.ipv6h->daddr,
17373 + sizeof(struct tcphdr), IPPROTO_TCP,
17374 + csum_partial((char *)tcph,
17375 + sizeof(struct tcphdr), 0));
17378 + connection_attach(nskb, oldskb->nfct);
17381 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17384 + dst_release(dst);
17387 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
17389 + struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
17390 + struct icmp6hdr *icmp6h;
17391 + struct dst_entry *dst = NULL;
17392 + struct rt6_info *rt;
17395 + unsigned int len, datalen, hh_len;
17396 + int saddr_type, daddr_type;
17397 + unsigned int ptr, ip6off;
17400 + struct sk_buff *nskb;
17403 + saddr_type = ipv6_addr_type(&hdr->saddr);
17404 + daddr_type = ipv6_addr_type(&hdr->daddr);
17406 + if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
17407 + (!(daddr_type & IPV6_ADDR_UNICAST))) {
17408 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17412 + ip6off = skb_in->nh.raw - skb_in->data;
17413 + proto = hdr->nexthdr;
17414 + ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
17415 + skb_in->len - ip6off);
17417 + if ((ptr < 0) || (ptr > skb_in->len)) {
17418 + ptr = ip6off + sizeof(struct ipv6hdr);
17419 + proto = hdr->nexthdr;
17420 + } else if (proto == IPPROTO_ICMPV6) {
17423 + if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
17424 + icmp6_type), &type, 1)) {
17425 + DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
17429 + if (!(type & ICMPV6_INFOMSG_MASK)) {
17430 + DEBUGP("ip6t_REJECT: no reply to icmp error\n");
17433 + } else if (proto == IPPROTO_UDP) {
17434 + int plen = skb_in->len - (ptr - ip6off);
17437 + if (plen < sizeof(struct udphdr)) {
17438 + DEBUGP("ip6t_REJECT: too short\n");
17442 + if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
17444 + if (net_ratelimit())
17445 + printk("ip6t_REJECT: can't get copy from skb");
17450 + csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
17452 + skb_checksum(skb_in, ptr, plen, 0))) {
17453 + DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
17458 + memset(&fl, 0, sizeof(fl));
17459 + fl.proto = IPPROTO_ICMPV6;
17460 + ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
17461 + ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
17462 + fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
17463 + fl.fl_icmp_code = code;
17465 + if (ip6_dst_lookup(NULL, &dst, &fl)) {
17469 + rt = (struct rt6_info *)dst;
17472 + if (rt->rt6i_dst.plen < 128)
17473 + tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
17475 + if (!xrlim_allow(dst, tmo)) {
17476 + if (net_ratelimit())
17477 + printk("ip6t_REJECT: rate limitted\n");
17478 + goto dst_release_out;
17481 + len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
17483 + if (len > dst_pmtu(dst))
17484 + len = dst_pmtu(dst);
17485 + if (len > IPV6_MIN_MTU)
17486 + len = IPV6_MIN_MTU;
17488 + datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
17489 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
17491 + nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
17495 + if (net_ratelimit())
17496 + printk("ip6t_REJECT: can't alloc skb\n");
17497 + goto dst_release_out;
17500 + nskb->priority = 0;
17504 + skb_reserve(nskb, hh_len + dst->header_len);
17506 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17507 + skb_put(nskb, sizeof(struct ipv6hdr));
17508 + ip6h->version = 6;
17509 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17510 + ip6h->nexthdr = IPPROTO_ICMPV6;
17511 + ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
17512 + ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
17513 + ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
17515 + icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
17516 + icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
17517 + icmp6h->icmp6_code = code;
17518 + icmp6h->icmp6_cksum = 0;
17520 + data = skb_put(nskb, datalen);
17522 + csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
17523 + csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
17524 + icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
17525 + datalen + sizeof(struct icmp6hdr),
17526 + IPPROTO_ICMPV6, csum);
17529 + connection_attach(nskb, skb_in->nfct);
17531 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17535 + dst_release(dst);
17538 +static unsigned int reject6_target(struct sk_buff **pskb,
17539 + unsigned int hooknum,
17540 + const struct net_device *in,
17541 + const struct net_device *out,
17542 + const void *targinfo,
17545 + const struct ip6t_reject_info *reject = targinfo;
17547 + DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
17548 + /* WARNING: This code causes reentry within ip6tables.
17549 + This means that the ip6tables jump stack is now crap. We
17550 + must return an absolute verdict. --RR */
17551 + switch (reject->with) {
17552 + case IP6T_ICMP6_NO_ROUTE:
17553 + send_unreach(*pskb, ICMPV6_NOROUTE);
17555 + case IP6T_ICMP6_ADM_PROHIBITED:
17556 + send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
17558 + case IP6T_ICMP6_NOT_NEIGHBOUR:
17559 + send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
17561 + case IP6T_ICMP6_ADDR_UNREACH:
17562 + send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
17564 + case IP6T_ICMP6_PORT_UNREACH:
17565 + send_unreach(*pskb, ICMPV6_PORT_UNREACH);
17567 + case IP6T_ICMP6_ECHOREPLY:
17570 + case IP6T_TCP_RESET:
17571 + send_reset(*pskb);
17574 + if (net_ratelimit())
17575 + printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
17582 +static int check(const char *tablename,
17583 + const struct ip6t_entry *e,
17585 + unsigned int targinfosize,
17586 + unsigned int hook_mask)
17588 + const struct ip6t_reject_info *rejinfo = targinfo;
17590 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
17591 + DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
17595 + /* Only allow these for packet filtering. */
17596 + if (strcmp(tablename, "filter") != 0) {
17597 + DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
17601 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
17602 + | (1 << NF_IP6_FORWARD)
17603 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
17604 + DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
17608 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
17609 + printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
17611 + } else if (rejinfo->with == IP6T_TCP_RESET) {
17612 + /* Must specify that it's a TCP packet */
17613 + if (e->ipv6.proto != IPPROTO_TCP
17614 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
17615 + DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
17623 +static struct ip6t_target ip6t_reject_reg = {
17624 + .name = "REJECT",
17625 + .target = reject6_target,
17626 + .checkentry = check,
17627 + .me = THIS_MODULE
17630 +static int __init init(void)
17632 + if (ip6t_register_target(&ip6t_reject_reg))
17637 +static void __exit fini(void)
17639 + ip6t_unregister_target(&ip6t_reject_reg);
17642 +module_init(init);
17643 +module_exit(fini);
17644 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.6/net/ipv6/netfilter/ip6t_ROUTE.c
17645 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
17646 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_ROUTE.c 2004-05-18 12:38:20.000000000 +0200
17649 + * This implements the ROUTE v6 target, which enables you to setup unusual
17650 + * routes not supported by the standard kernel routing table.
17652 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
17654 + * v 1.0 2003/08/05
17656 + * This software is distributed under GNU GPL v2, 1991
17659 +#include <linux/module.h>
17660 +#include <linux/skbuff.h>
17661 +#include <linux/ipv6.h>
17662 +#include <linux/netfilter_ipv6/ip6_tables.h>
17663 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17664 +#include <linux/netdevice.h>
17665 +#include <net/ipv6.h>
17666 +#include <net/ndisc.h>
17667 +#include <net/ip6_route.h>
17668 +#include <linux/icmpv6.h>
17671 +#define DEBUGP printk
17673 +#define DEBUGP(format, args...)
17676 +#define NIP6(addr) \
17677 + ntohs((addr).s6_addr16[0]), \
17678 + ntohs((addr).s6_addr16[1]), \
17679 + ntohs((addr).s6_addr16[2]), \
17680 + ntohs((addr).s6_addr16[3]), \
17681 + ntohs((addr).s6_addr16[4]), \
17682 + ntohs((addr).s6_addr16[5]), \
17683 + ntohs((addr).s6_addr16[6]), \
17684 + ntohs((addr).s6_addr16[7])
17686 +/* Route the packet according to the routing keys specified in
17687 + * route_info. Keys are :
17689 + * 0 if no oif preferred,
17690 + * otherwise set to the index of the desired oif
17691 + * - route_info->gw :
17692 + * 0 if no gateway specified,
17693 + * otherwise set to the next host to which the pkt must be routed
17694 + * If success, skb->dev is the output device to which the packet must
17695 + * be sent and skb->dst is not NULL
17697 + * RETURN: 1 if the packet was succesfully routed to the
17698 + * destination desired
17699 + * 0 if the kernel routing table could not route the packet
17700 + * according to the keys specified
17703 +route6(struct sk_buff *skb,
17704 + unsigned int ifindex,
17705 + const struct ip6t_route_target_info *route_info)
17707 + struct rt6_info *rt = NULL;
17708 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17709 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17711 + DEBUGP("ip6t_ROUTE: called with: ");
17712 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
17713 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
17714 + DEBUGP("OUT=%s\n", route_info->oif);
17716 + if (ipv6_addr_any(gw))
17717 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
17719 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
17724 + DEBUGP("ip6t_ROUTE: routing gives: ");
17725 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
17726 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
17727 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
17729 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
17730 + goto wrong_route;
17732 + if (!rt->rt6i_nexthop) {
17733 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
17734 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
17737 + /* Drop old route. */
17738 + dst_release(skb->dst);
17739 + skb->dst = &rt->u.dst;
17740 + skb->dev = rt->rt6i_dev;
17744 + dst_release(&rt->u.dst);
17746 + if (!net_ratelimit())
17749 + printk("ip6t_ROUTE: no explicit route found ");
17751 + printk("via interface %s ", route_info->oif);
17752 + if (!ipv6_addr_any(gw))
17753 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
17759 +/* Stolen from ip6_output_finish
17760 + * PRE : skb->dev is set to the device we are leaving by
17761 + * skb->dst is not NULL
17762 + * POST: the packet is sent with the link layer header pushed
17763 + * the packet is destroyed
17765 +static void ip_direct_send(struct sk_buff *skb)
17767 + struct dst_entry *dst = skb->dst;
17768 + struct hh_cache *hh = dst->hh;
17771 + read_lock_bh(&hh->hh_lock);
17772 + memcpy(skb->data - 16, hh->hh_data, 16);
17773 + read_unlock_bh(&hh->hh_lock);
17774 + skb_push(skb, hh->hh_len);
17775 + hh->hh_output(skb);
17776 + } else if (dst->neighbour)
17777 + dst->neighbour->output(skb);
17779 + if (net_ratelimit())
17780 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
17786 +static unsigned int
17787 +route6_oif(const struct ip6t_route_target_info *route_info,
17788 + struct sk_buff *skb)
17790 + unsigned int ifindex = 0;
17791 + struct net_device *dev_out = NULL;
17793 + /* The user set the interface name to use.
17794 + * Getting the current interface index.
17796 + if ((dev_out = dev_get_by_name(route_info->oif))) {
17797 + ifindex = dev_out->ifindex;
17799 + /* Unknown interface name : packet dropped */
17800 + if (net_ratelimit())
17801 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
17803 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17804 + return IP6T_CONTINUE;
17809 + /* Trying the standard way of routing packets */
17810 + if (route6(skb, ifindex, route_info)) {
17811 + dev_put(dev_out);
17812 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17813 + return IP6T_CONTINUE;
17815 + ip_direct_send(skb);
17816 + return NF_STOLEN;
17822 +static unsigned int
17823 +route6_gw(const struct ip6t_route_target_info *route_info,
17824 + struct sk_buff *skb)
17826 + if (route6(skb, 0, route_info)) {
17827 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17828 + return IP6T_CONTINUE;
17830 + ip_direct_send(skb);
17831 + return NF_STOLEN;
17837 +static unsigned int
17838 +ip6t_route_target(struct sk_buff **pskb,
17839 + unsigned int hooknum,
17840 + const struct net_device *in,
17841 + const struct net_device *out,
17842 + const void *targinfo,
17845 + const struct ip6t_route_target_info *route_info = targinfo;
17846 + struct sk_buff *skb = *pskb;
17847 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17849 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17852 + /* If we are at PREROUTING or INPUT hook
17853 + * the TTL isn't decreased by the IP stack
17855 + if (hooknum == NF_IP6_PRE_ROUTING ||
17856 + hooknum == NF_IP6_LOCAL_IN) {
17858 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17860 + if (ipv6h->hop_limit <= 1) {
17861 + /* Force OUTPUT device used as source address */
17862 + skb->dev = skb->dst->dev;
17864 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
17865 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
17870 + ipv6h->hop_limit--;
17875 + if (route_info->oif[0])
17876 + return route6_oif(route_info, *pskb);
17878 + if (!ipv6_addr_any(gw))
17879 + return route6_gw(route_info, *pskb);
17881 + if (net_ratelimit())
17882 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
17884 + return IP6T_CONTINUE;
17889 +ip6t_route_checkentry(const char *tablename,
17890 + const struct ip6t_entry *e,
17892 + unsigned int targinfosize,
17893 + unsigned int hook_mask)
17895 + if (strcmp(tablename, "mangle") != 0) {
17896 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
17900 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
17901 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
17903 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
17911 +static struct ip6t_target ip6t_route_reg = {
17913 + .target = ip6t_route_target,
17914 + .checkentry = ip6t_route_checkentry,
17915 + .me = THIS_MODULE
17919 +static int __init init(void)
17921 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
17922 + if (ip6t_register_target(&ip6t_route_reg))
17929 +static void __exit fini(void)
17931 + ip6t_unregister_target(&ip6t_route_reg);
17934 +module_init(init);
17935 +module_exit(fini);
17936 +MODULE_LICENSE("GPL");
17937 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6/net/ipv6/netfilter/ip6t_TRACE.c
17938 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
17939 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_TRACE.c 2004-05-18 12:38:32.000000000 +0200
17941 +/* This is a module which is used for setting
17942 + * the NFC_TRACE flag in the nfcache field of an skb.
17944 +#include <linux/module.h>
17945 +#include <linux/skbuff.h>
17947 +#include <linux/netfilter_ipv6/ip6_tables.h>
17949 +MODULE_LICENSE("GPL");
17951 +static unsigned int
17952 +target(struct sk_buff **pskb,
17953 + unsigned int hooknum,
17954 + const struct net_device *in,
17955 + const struct net_device *out,
17956 + const void *targinfo,
17959 + (*pskb)->nfcache |= NFC_TRACE;
17960 + return IP6T_CONTINUE;
17964 +checkentry(const char *tablename,
17965 + const struct ip6t_entry *e,
17967 + unsigned int targinfosize,
17968 + unsigned int hook_mask)
17970 + if (targinfosize != 0) {
17971 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17976 + if (strcmp(tablename, "raw") != 0) {
17977 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17984 +static struct ip6t_target ip6t_trace_reg = {
17986 + .target = target,
17987 + .checkentry = checkentry,
17988 + .me = THIS_MODULE
17991 +static int __init init(void)
17993 + if (ip6t_register_target(&ip6t_trace_reg))
17999 +static void __exit fini(void)
18001 + ip6t_unregister_target(&ip6t_trace_reg);
18004 +module_init(init);
18005 +module_exit(fini);
18006 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.6/net/ipv6/netfilter/ip6t_fuzzy.c
18007 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
18008 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_fuzzy.c 2004-05-18 12:36:22.000000000 +0200
18011 + * This module implements a simple TSK FLC
18012 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
18013 + * to limit , in an adaptive and flexible way , the packet rate crossing
18014 + * a given stream . It serves as an initial and very simple (but effective)
18015 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
18016 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
18017 + * into our code in a precise , adaptive and efficient manner.
18018 + * The goal is very similar to that of "limit" match , but using techniques of
18019 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
18020 + * avoiding over and undershoots - and stuff like that .
18023 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
18024 + * 2002-08-17 : Changed to eliminate floating point operations .
18025 + * 2002-08-23 : Coding style changes .
18026 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
18029 +#include <linux/module.h>
18030 +#include <linux/skbuff.h>
18031 +#include <linux/ipv6.h>
18032 +#include <linux/random.h>
18033 +#include <net/tcp.h>
18034 +#include <linux/spinlock.h>
18035 +#include <linux/netfilter_ipv6/ip6_tables.h>
18036 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
18039 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
18040 + Expressed in percentage
18043 +#define PAR_LOW 1/100
18044 +#define PAR_HIGH 1
18046 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
18048 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
18049 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
18050 +MODULE_LICENSE("GPL");
18052 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
18054 + if (tx >= maxi) return 100;
18056 + if (tx <= mini) return 0;
18058 + return ((100 * (tx-mini)) / (maxi-mini));
18061 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
18063 + if (tx <= mini) return 100;
18065 + if (tx >= maxi) return 0;
18067 + return ((100 * (maxi - tx)) / (maxi - mini));
18072 +ip6t_fuzzy_match(const struct sk_buff *pskb,
18073 + const struct net_device *in,
18074 + const struct net_device *out,
18075 + const void *matchinfo,
18078 + u_int16_t datalen,
18081 + /* From userspace */
18083 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
18085 + u_int8_t random_number;
18086 + unsigned long amount;
18087 + u_int8_t howhigh, howlow;
18090 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
18092 + info->bytes_total += pskb->len;
18093 + info->packets_total++;
18095 + info->present_time = jiffies;
18097 + if (info->present_time >= info->previous_time)
18098 + amount = info->present_time - info->previous_time;
18100 + /* There was a transition : I choose to re-sample
18101 + and keep the old acceptance rate...
18105 + info->previous_time = info->present_time;
18106 + info->bytes_total = info->packets_total = 0;
18109 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
18111 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
18114 + info->previous_time = info->present_time;
18115 + info->bytes_total = info->packets_total = 0;
18117 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
18118 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
18120 + info->acceptance_rate = (u_int8_t) \
18121 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
18123 + /* In fact, the above defuzzification would require a denominator
18124 + * proportional to (howhigh+howlow) but, in this particular case,
18125 + * that expression is constant.
18126 + * An imediate consequence is that it is not necessary to call
18127 + * both mf_high and mf_low - but to keep things understandable,
18133 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
18136 + if (info->acceptance_rate < 100)
18138 + get_random_bytes((void *)(&random_number), 1);
18140 + /* If within the acceptance , it can pass => don't match */
18141 + if (random_number <= (255 * info->acceptance_rate) / 100)
18144 + return 1; /* It can't pass (It matches) */
18147 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
18152 +ip6t_fuzzy_checkentry(const char *tablename,
18153 + const struct ip6t_ip6 *ip,
18155 + unsigned int matchsize,
18156 + unsigned int hook_mask)
18159 + const struct ip6t_fuzzy_info *info = matchinfo;
18161 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
18162 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
18163 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
18167 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
18168 + || (info->minimum_rate >= info->maximum_rate)) {
18169 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
18176 +static struct ip6t_match ip6t_fuzzy_reg = {
18179 + ip6t_fuzzy_match,
18180 + ip6t_fuzzy_checkentry,
18184 +static int __init init(void)
18186 + if (ip6t_register_match(&ip6t_fuzzy_reg))
18192 +static void __exit fini(void)
18194 + ip6t_unregister_match(&ip6t_fuzzy_reg);
18197 +module_init(init);
18198 +module_exit(fini);
18199 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.6/net/ipv6/netfilter/ip6t_nth.c
18200 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
18201 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_nth.c 2004-05-18 12:36:40.000000000 +0200
18204 + This is a module which is used for match support for every Nth packet
18205 + This file is distributed under the terms of the GNU General Public
18206 + License (GPL). Copies of the GPL can be obtained from:
18207 + ftp://prep.ai.mit.edu/pub/gnu/GPL
18209 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18210 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
18211 + * added support for multiple counters
18212 + * added support for matching on individual packets
18213 + in the counter cycle
18214 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18218 +#include <linux/module.h>
18219 +#include <linux/skbuff.h>
18220 +#include <linux/ip.h>
18221 +#include <net/tcp.h>
18222 +#include <linux/spinlock.h>
18223 +#include <linux/netfilter_ipv6/ip6_tables.h>
18224 +#include <linux/netfilter_ipv6/ip6t_nth.h>
18226 +MODULE_LICENSE("GPL");
18229 + * State information.
18233 + u_int16_t number;
18236 +static struct state states[IP6T_NTH_NUM_COUNTERS];
18239 +ip6t_nth_match(const struct sk_buff *pskb,
18240 + const struct net_device *in,
18241 + const struct net_device *out,
18242 + const void *matchinfo,
18245 + u_int16_t datalen,
18248 + /* Parameters from userspace */
18249 + const struct ip6t_nth_info *info = matchinfo;
18250 + unsigned counter = info->counter;
18251 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
18253 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
18257 + spin_lock(&states[counter].lock);
18259 + /* Are we matching every nth packet?*/
18260 + if (info->packet == 0xFF)
18262 + /* We're matching every nth packet and only every nth packet*/
18263 + /* Do we match or invert match? */
18264 + if (info->not == 0)
18266 + if (states[counter].number == 0)
18268 + ++states[counter].number;
18271 + if (states[counter].number >= info->every)
18272 + states[counter].number = 0; /* reset the counter */
18274 + ++states[counter].number;
18279 + if (states[counter].number == 0)
18281 + ++states[counter].number;
18284 + if (states[counter].number >= info->every)
18285 + states[counter].number = 0;
18287 + ++states[counter].number;
18293 + /* We're using the --packet, so there must be a rule for every value */
18294 + if (states[counter].number == info->packet)
18296 + /* only increment the counter when a match happens */
18297 + if (states[counter].number >= info->every)
18298 + states[counter].number = 0; /* reset the counter */
18300 + ++states[counter].number;
18308 + /* don't match */
18309 + spin_unlock(&states[counter].lock);
18313 + spin_unlock(&states[counter].lock);
18318 +ip6t_nth_checkentry(const char *tablename,
18319 + const struct ip6t_ip6 *e,
18321 + unsigned int matchsize,
18322 + unsigned int hook_mask)
18324 + /* Parameters from userspace */
18325 + const struct ip6t_nth_info *info = matchinfo;
18326 + unsigned counter = info->counter;
18327 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
18329 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
18333 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
18334 + printk("nth: matchsize %u != %u\n", matchsize,
18335 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
18339 + states[counter].number = info->startat;
18344 +static struct ip6t_match ip6t_nth_reg = {
18348 + ip6t_nth_checkentry,
18352 +static int __init init(void)
18354 + unsigned counter;
18355 + memset(&states, 0, sizeof(states));
18356 + if (ip6t_register_match(&ip6t_nth_reg))
18359 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
18361 + spin_lock_init(&(states[counter].lock));
18364 + printk("ip6t_nth match loaded\n");
18368 +static void __exit fini(void)
18370 + ip6t_unregister_match(&ip6t_nth_reg);
18371 + printk("ip6t_nth match unloaded\n");
18374 +module_init(init);
18375 +module_exit(fini);
18376 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6/net/ipv6/netfilter/ip6t_owner.c
18377 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_owner.c 2004-05-10 04:33:13.000000000 +0200
18378 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_owner.c 2004-05-18 12:39:53.000000000 +0200
18380 MODULE_LICENSE("GPL");
18383 +match_comm(const struct sk_buff *skb, const char *comm)
18385 + struct task_struct *p, *g;
18386 + struct files_struct *files;
18389 + read_lock(&tasklist_lock);
18390 + do_each_thread(g, p) {
18391 + if(strncmp(p->comm, comm, sizeof(p->comm)))
18395 + files = p->files;
18397 + read_lock(&files->file_lock);
18398 + for (i=0; i < files->max_fds; i++) {
18399 + if (fcheck_files(files, i) ==
18400 + skb->sk->sk_socket->file) {
18401 + read_unlock(&files->file_lock);
18403 + read_unlock(&tasklist_lock);
18407 + read_unlock(&files->file_lock);
18410 + } while_each_thread(g, p);
18411 + read_unlock(&tasklist_lock);
18416 match_pid(const struct sk_buff *skb, pid_t pid)
18418 struct task_struct *p;
18419 @@ -125,6 +158,12 @@
18423 + if(info->match & IP6T_OWNER_COMM) {
18424 + if (!match_comm(skb, info->comm) ^
18425 + !!(info->invert & IP6T_OWNER_COMM))
18432 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6/net/ipv6/netfilter/ip6t_policy.c
18433 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
18434 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_policy.c 2004-05-18 12:39:55.000000000 +0200
18436 +/* IP tables module for matching IPsec policy
18438 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
18440 + * This program is free software; you can redistribute it and/or modify
18441 + * it under the terms of the GNU General Public License version 2 as
18442 + * published by the Free Software Foundation.
18445 +#include <linux/kernel.h>
18446 +#include <linux/config.h>
18447 +#include <linux/module.h>
18448 +#include <linux/skbuff.h>
18449 +#include <linux/init.h>
18450 +#include <net/xfrm.h>
18452 +#include <linux/netfilter_ipv6.h>
18453 +#include <linux/netfilter_ipv6/ip6t_policy.h>
18454 +#include <linux/netfilter_ipv6/ip6_tables.h>
18456 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
18457 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
18458 +MODULE_LICENSE("GPL");
18461 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
18462 + struct in6_addr mask,
18463 + struct in6_addr addr2)
18467 + for (i = 0; i < 16; i++) {
18468 + if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
18469 + (addr2.s6_addr[i] & mask.s6_addr[i]))
18477 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
18479 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
18481 + struct in6_addr xfrm_saddr, xfrm_daddr;
18483 + if ((e->match.saddr
18484 + && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
18485 + ^ e->invert.saddr ) ||
18487 + && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
18488 + ^ e->invert.daddr ) ||
18489 + MISMATCH(proto, x->id.proto) ||
18490 + MISMATCH(mode, x->props.mode) ||
18491 + MISMATCH(spi, x->id.spi) ||
18492 + MISMATCH(reqid, x->props.reqid))
18498 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18500 + const struct ip6t_policy_elem *e;
18501 + struct sec_path *sp = skb->sp;
18502 + int strict = info->flags & POLICY_MATCH_STRICT;
18507 + if (strict && info->len != sp->len)
18510 + for (i = sp->len - 1; i >= 0; i--) {
18511 + pos = strict ? i - sp->len + 1 : 0;
18512 + if (pos >= info->len)
18514 + e = &info->pol[pos];
18516 + if (match_xfrm_state(sp->x[i].xvec, e)) {
18519 + } else if (strict)
18523 + return strict ? 1 : 0;
18527 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18529 + const struct ip6t_policy_elem *e;
18530 + struct dst_entry *dst = skb->dst;
18531 + int strict = info->flags & POLICY_MATCH_STRICT;
18534 + if (dst->xfrm == NULL)
18537 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
18538 + pos = strict ? i : 0;
18539 + if (pos >= info->len)
18541 + e = &info->pol[pos];
18543 + if (match_xfrm_state(dst->xfrm, e)) {
18546 + } else if (strict)
18550 + return strict ? 1 : 0;
18553 +static int match(const struct sk_buff *skb,
18554 + const struct net_device *in,
18555 + const struct net_device *out,
18556 + const void *matchinfo,
18559 + u_int16_t datalen,
18562 + const struct ip6t_policy_info *info = matchinfo;
18565 + if (info->flags & POLICY_MATCH_IN)
18566 + ret = match_policy_in(skb, info);
18568 + ret = match_policy_out(skb, info);
18571 + if (info->flags & POLICY_MATCH_NONE)
18575 + } else if (info->flags & POLICY_MATCH_NONE)
18581 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
18582 + void *matchinfo, unsigned int matchsize,
18583 + unsigned int hook_mask)
18585 + struct ip6t_policy_info *info = matchinfo;
18587 + if (matchsize != IP6T_ALIGN(sizeof(*info))) {
18588 + printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
18589 + matchsize, IP6T_ALIGN(sizeof(*info)));
18592 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
18593 + printk(KERN_ERR "ip6t_policy: neither incoming nor "
18594 + "outgoing policy selected\n");
18597 + if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
18598 + && info->flags & POLICY_MATCH_OUT) {
18599 + printk(KERN_ERR "ip6t_policy: output policy not valid in "
18600 + "PRE_ROUTING and INPUT\n");
18603 + if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
18604 + && info->flags & POLICY_MATCH_IN) {
18605 + printk(KERN_ERR "ip6t_policy: input policy not valid in "
18606 + "POST_ROUTING and OUTPUT\n");
18609 + if (info->len > POLICY_MAX_ELEM) {
18610 + printk(KERN_ERR "ip6t_policy: too many policy elements\n");
18617 +static struct ip6t_match policy_match =
18619 + .name = "policy",
18621 + .checkentry = checkentry,
18622 + .me = THIS_MODULE,
18625 +static int __init init(void)
18627 + return ip6t_register_match(&policy_match);
18630 +static void __exit fini(void)
18632 + ip6t_unregister_match(&policy_match);
18635 +module_init(init);
18636 +module_exit(fini);
18637 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.6/net/ipv6/netfilter/ip6t_random.c
18638 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
18639 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_random.c 2004-05-18 12:36:59.000000000 +0200
18642 + This is a module which is used for a "random" match support.
18643 + This file is distributed under the terms of the GNU General Public
18644 + License (GPL). Copies of the GPL can be obtained from:
18645 + ftp://prep.ai.mit.edu/pub/gnu/GPL
18647 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18648 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18651 +#include <linux/module.h>
18652 +#include <linux/skbuff.h>
18653 +#include <linux/ip.h>
18654 +#include <linux/random.h>
18655 +#include <net/tcp.h>
18656 +#include <linux/spinlock.h>
18657 +#include <linux/netfilter_ipv6/ip6_tables.h>
18658 +#include <linux/netfilter_ipv6/ip6t_random.h>
18660 +MODULE_LICENSE("GPL");
18663 +ip6t_rand_match(const struct sk_buff *pskb,
18664 + const struct net_device *in,
18665 + const struct net_device *out,
18666 + const void *matchinfo,
18669 + u_int16_t datalen,
18672 + /* Parameters from userspace */
18673 + const struct ip6t_rand_info *info = matchinfo;
18674 + u_int8_t random_number;
18676 + /* get 1 random number from the kernel random number generation routine */
18677 + get_random_bytes((void *)(&random_number), 1);
18679 + /* Do we match ? */
18680 + if (random_number <= info->average)
18687 +ip6t_rand_checkentry(const char *tablename,
18688 + const struct ip6t_ip6 *e,
18690 + unsigned int matchsize,
18691 + unsigned int hook_mask)
18693 + /* Parameters from userspace */
18694 + const struct ip6t_rand_info *info = matchinfo;
18696 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
18697 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
18698 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
18702 + /* must be 1 <= average % <= 99 */
18703 + /* 1 x 2.55 = 2 */
18704 + /* 99 x 2.55 = 252 */
18705 + if ((info->average < 2) || (info->average > 252)) {
18706 + printk("ip6t_random: invalid average %u\n", info->average);
18713 +static struct ip6t_match ip6t_rand_reg = {
18717 + ip6t_rand_checkentry,
18721 +static int __init init(void)
18723 + if (ip6t_register_match(&ip6t_rand_reg))
18726 + printk("ip6t_random match loaded\n");
18730 +static void __exit fini(void)
18732 + ip6t_unregister_match(&ip6t_rand_reg);
18733 + printk("ip6t_random match unloaded\n");
18736 +module_init(init);
18737 +module_exit(fini);
18738 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6/net/ipv6/netfilter/ip6table_filter.c
18739 --- linux-2.6.6.org/net/ipv6/netfilter/ip6table_filter.c 2004-05-10 04:32:00.000000000 +0200
18740 +++ linux-2.6.6/net/ipv6/netfilter/ip6table_filter.c 2004-05-18 12:38:32.000000000 +0200
18743 sizeof(struct ip6t_entry),
18744 sizeof(struct ip6t_standard),
18745 - 0, { 0, 0 }, { } },
18746 + 0, NULL, 0, { 0, 0 }, { } },
18747 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18748 -NF_ACCEPT - 1 } },
18752 sizeof(struct ip6t_entry),
18753 sizeof(struct ip6t_standard),
18754 - 0, { 0, 0 }, { } },
18755 + 0, NULL, 0, { 0, 0 }, { } },
18756 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18757 -NF_ACCEPT - 1 } },
18761 sizeof(struct ip6t_entry),
18762 sizeof(struct ip6t_standard),
18763 - 0, { 0, 0 }, { } },
18764 + 0, NULL, 0, { 0, 0 }, { } },
18765 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18770 sizeof(struct ip6t_entry),
18771 sizeof(struct ip6t_error),
18772 - 0, { 0, 0 }, { } },
18773 + 0, NULL, 0, { 0, 0 }, { } },
18774 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18777 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6/net/ipv6/netfilter/ip6table_mangle.c
18778 --- linux-2.6.6.org/net/ipv6/netfilter/ip6table_mangle.c 2004-05-10 04:32:28.000000000 +0200
18779 +++ linux-2.6.6/net/ipv6/netfilter/ip6table_mangle.c 2004-05-18 12:38:32.000000000 +0200
18782 sizeof(struct ip6t_entry),
18783 sizeof(struct ip6t_standard),
18784 - 0, { 0, 0 }, { } },
18785 + 0, NULL, 0, { 0, 0 }, { } },
18786 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18787 -NF_ACCEPT - 1 } },
18791 sizeof(struct ip6t_entry),
18792 sizeof(struct ip6t_standard),
18793 - 0, { 0, 0 }, { } },
18794 + 0, NULL, 0, { 0, 0 }, { } },
18795 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18796 -NF_ACCEPT - 1 } },
18800 sizeof(struct ip6t_entry),
18801 sizeof(struct ip6t_standard),
18802 - 0, { 0, 0 }, { } },
18803 + 0, NULL, 0, { 0, 0 }, { } },
18804 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18805 -NF_ACCEPT - 1 } },
18809 sizeof(struct ip6t_entry),
18810 sizeof(struct ip6t_standard),
18811 - 0, { 0, 0 }, { } },
18812 + 0, NULL, 0, { 0, 0 }, { } },
18813 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18814 -NF_ACCEPT - 1 } },
18816 @@ -105,7 +105,7 @@
18818 sizeof(struct ip6t_entry),
18819 sizeof(struct ip6t_standard),
18820 - 0, { 0, 0 }, { } },
18821 + 0, NULL, 0, { 0, 0 }, { } },
18822 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18825 @@ -114,7 +114,7 @@
18827 sizeof(struct ip6t_entry),
18828 sizeof(struct ip6t_error),
18829 - 0, { 0, 0 }, { } },
18830 + 0, NULL, 0, { 0, 0 }, { } },
18831 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18834 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6/net/ipv6/netfilter/ip6table_raw.c
18835 --- linux-2.6.6.org/net/ipv6/netfilter/ip6table_raw.c 2004-05-10 04:32:53.000000000 +0200
18836 +++ linux-2.6.6/net/ipv6/netfilter/ip6table_raw.c 2004-05-18 12:38:32.000000000 +0200
18839 sizeof(struct ip6t_entry),
18840 sizeof(struct ip6t_standard),
18841 - 0, { 0, 0 }, { } },
18842 + 0, NULL, 0, { 0, 0 }, { } },
18843 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18844 -NF_ACCEPT - 1 } },
18848 sizeof(struct ip6t_entry),
18849 sizeof(struct ip6t_standard),
18850 - 0, { 0, 0 }, { } },
18851 + 0, NULL, 0, { 0, 0 }, { } },
18852 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18853 -NF_ACCEPT - 1 } },
18857 sizeof(struct ip6t_entry),
18858 sizeof(struct ip6t_error),
18859 - 0, { 0, 0 }, { } },
18860 + 0, NULL, 0, { 0, 0 }, { } },
18861 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18864 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/sit.c linux-2.6.6/net/ipv6/sit.c
18865 --- linux-2.6.6.org/net/ipv6/sit.c 2004-05-10 04:33:20.000000000 +0200
18866 +++ linux-2.6.6/net/ipv6/sit.c 2004-05-18 12:35:50.000000000 +0200
18867 @@ -388,13 +388,7 @@
18868 skb->dev = tunnel->dev;
18869 dst_release(skb->dst);
18871 -#ifdef CONFIG_NETFILTER
18872 - nf_conntrack_put(skb->nfct);
18873 - skb->nfct = NULL;
18874 -#ifdef CONFIG_NETFILTER_DEBUG
18875 - skb->nf_debug = 0;
18879 ipip6_ecn_decapsulate(iph, skb);
18881 read_unlock(&ipip6_lock);
18882 @@ -580,13 +574,7 @@
18883 if ((iph->ttl = tiph->ttl) == 0)
18884 iph->ttl = iph6->hop_limit;
18886 -#ifdef CONFIG_NETFILTER
18887 - nf_conntrack_put(skb->nfct);
18888 - skb->nfct = NULL;
18889 -#ifdef CONFIG_NETFILTER_DEBUG
18890 - skb->nf_debug = 0;
18896 tunnel->recursion--;
18897 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/xfrm/xfrm_input.c linux-2.6.6/net/xfrm/xfrm_input.c
18898 --- linux-2.6.6.org/net/xfrm/xfrm_input.c 2004-05-10 04:31:59.000000000 +0200
18899 +++ linux-2.6.6/net/xfrm/xfrm_input.c 2004-05-18 12:39:22.000000000 +0200
18904 +#ifdef CONFIG_NETFILTER
18905 + sp->decap_done = 0;
18910 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/xfrm/xfrm_policy.c linux-2.6.6/net/xfrm/xfrm_policy.c
18911 --- linux-2.6.6.org/net/xfrm/xfrm_policy.c 2004-05-10 04:32:37.000000000 +0200
18912 +++ linux-2.6.6/net/xfrm/xfrm_policy.c 2004-05-18 12:39:23.000000000 +0200
18914 #include <linux/workqueue.h>
18915 #include <linux/notifier.h>
18916 #include <linux/netdevice.h>
18917 +#include <linux/netfilter.h>
18918 #include <net/xfrm.h>
18919 #include <net/ip.h>
18921 @@ -908,6 +909,7 @@
18923 if (_decode_session(skb, &fl, family) < 0)
18925 + nf_nat_decode_session(skb, &fl, family);
18927 /* First, check used SA against their selectors. */
18929 --- linux-2.6.6/net/ipv6/ip6_output.c.org 2004-05-10 04:31:59.000000000 +0200
18930 +++ linux-2.6.6/net/ipv6/ip6_output.c 2004-05-11 18:35:06.402777016 +0200
18931 @@ -805,6 +805,7 @@
18935 +EXPORT_SYMBOL(ip6_dst_lookup);
18937 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
18938 void *from, int length, int transhdrlen,