1 Netfilter SNAP 20040608
3 updates/01_iptables-1.2.10
5 updates/04_linux-2.6.6-helper_reassign
6 updates/05_linux-2.6.6-orphaned_expect
7 PENDING/expect-evict-order
8 PENDING/expect-slab-cache
9 PENDING/init_conntrack-optimize
10 PENDING/ipt_helper-invert-fix
11 PENDING/mangle-reroute
14 PENDING/proc-no-internal-targets
15 PENDING/proc_net_conntrack-permissions
18 BASE/NETLINK // fix socket -> sk_socket
27 BASE/osf // fix socket -> sk_socket
28 BASE/pool // added EXPORT_SYMBOL(ip_pool_mod, ip_pool_match)
32 BASE/raw // removed linux-2.6.patch - included in kernel
41 EXTRA/TRACE // ip_output.c fix
44 EXTRA/eggdrop-conntrack
45 EXTRA/h323-conntrack-nat
46 EXTRA/ipsec-01-output-hooks // fixed
47 EXTRA/ipsec-02-input-hooks
48 EXTRA/ipsec-03-policy-lookup
49 EXTRA/ipsec-04-policy-check
51 EXTRA/mms-conntrack-nat
52 EXTRA/owner-socketlookup
55 EXTRA/quake3-conntrack-nat
58 EXTRA/sctp-conntrack-nat
59 EXTRA/string // required unclean module - included - req fix
60 EXTRA/talk-conntrack-nat
62 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter.h linux-2.6.7-rc3/include/linux/netfilter.h
63 --- linux-2.6.7-rc3.org/include/linux/netfilter.h 2004-06-07 21:14:24.000000000 +0200
64 +++ linux-2.6.7-rc3/include/linux/netfilter.h 2004-06-08 10:38:46.000000000 +0200
66 <= 0x2000 is used for protocol-flags. */
67 #define NFC_UNKNOWN 0x4000
68 #define NFC_ALTERED 0x8000
69 +#define NFC_TRACE 0x10000
72 #include <linux/config.h>
74 /* This is gross, but inline doesn't cut it for avoiding the function
75 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
76 #ifdef CONFIG_NETFILTER_DEBUG
77 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
78 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
79 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
82 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
83 #define NF_HOOK_THRESH nf_hook_slow
85 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
86 -(list_empty(&nf_hooks[(pf)][(hook)]) \
87 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
88 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
90 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
91 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
94 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
96 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
97 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
99 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
100 struct net_device *indev, struct net_device *outdev,
103 #else /* !CONFIG_NETFILTER */
104 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
105 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
106 #endif /*CONFIG_NETFILTER*/
109 +#ifdef CONFIG_IP_NF_NAT_NEEDED
111 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
114 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
116 + if (family == AF_INET)
117 + nf_nat_decode_session4(skb, fl);
119 +#else /* CONFIG_IP_NF_NAT_NEEDED */
120 +#define nf_nat_decode_session(skb,fl,family)
121 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
122 +#endif /* CONFIG_XFRM */
124 #endif /*__KERNEL__*/
125 #endif /*__LINUX_NETFILTER_H*/
126 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_helpers.h linux-2.6.7-rc3/include/linux/netfilter_helpers.h
127 --- linux-2.6.7-rc3.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
128 +++ linux-2.6.7-rc3/include/linux/netfilter_helpers.h 2004-06-08 10:40:46.000000000 +0200
131 + * Helpers for netfiler modules. This file provides implementations for basic
132 + * functions such as strncasecmp(), etc.
134 + * gcc will warn for defined but unused functions, so we only include the
135 + * functions requested. The following macros are used:
136 + * NF_NEED_STRNCASECMP nf_strncasecmp()
137 + * NF_NEED_STRTOU16 nf_strtou16()
138 + * NF_NEED_STRTOU32 nf_strtou32()
140 +#ifndef _NETFILTER_HELPERS_H
141 +#define _NETFILTER_HELPERS_H
143 +/* Only include these functions for kernel code. */
146 +#include <linux/ctype.h>
147 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
150 + * The standard strncasecmp()
152 +#ifdef NF_NEED_STRNCASECMP
154 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
156 + if (s1 == NULL || s2 == NULL)
158 + if (s1 == NULL && s2 == NULL)
162 + return (s1 == NULL) ? -1 : 1;
164 + while (len > 0 && tolower(*s1) == tolower(*s2))
170 + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
172 +#endif /* NF_NEED_STRNCASECMP */
175 + * Parse a string containing a 16-bit unsigned integer.
176 + * Returns the number of chars used, or zero if no number is found.
178 +#ifdef NF_NEED_STRTOU16
180 +nf_strtou16(const char* pbuf, u_int16_t* pval)
185 + while (isdigit(pbuf[n]))
187 + *pval = (*pval * 10) + (pbuf[n] - '0');
193 +#endif /* NF_NEED_STRTOU16 */
196 + * Parse a string containing a 32-bit unsigned integer.
197 + * Returns the number of chars used, or zero if no number is found.
199 +#ifdef NF_NEED_STRTOU32
201 +nf_strtou32(const char* pbuf, u_int32_t* pval)
206 + while (pbuf[n] >= '0' && pbuf[n] <= '9')
208 + *pval = (*pval * 10) + (pbuf[n] - '0');
214 +#endif /* NF_NEED_STRTOU32 */
217 + * Given a buffer and length, advance to the next line and mark the current
220 +#ifdef NF_NEED_NEXTLINE
222 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
232 + while (p[off] != '\n')
243 + /* if we saw a crlf, physlen needs adjusted */
244 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
249 + /* advance past the newline */
253 + *plinelen = physlen;
258 +#endif /* NF_NEED_NEXTLINE */
260 +#endif /* __KERNEL__ */
262 +#endif /* _NETFILTER_HELPERS_H */
263 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
264 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-07 21:14:59.000000000 +0200
265 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-08 10:41:27.000000000 +0200
268 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
269 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
270 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
272 /* per conntrack: protocol private data */
273 union ip_conntrack_proto {
274 /* insert conntrack proto private data here */
275 + struct ip_ct_sctp sctp;
276 struct ip_ct_tcp tcp;
277 struct ip_ct_icmp icmp;
282 /* Add protocol helper include file here */
283 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
284 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
285 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
286 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
287 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
288 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
289 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
290 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
292 /* per expectation: application helper private data */
293 union ip_conntrack_expect_help {
294 /* insert conntrack helper private data (expect) here */
295 + struct ip_ct_talk_expect exp_talk_info;
296 + struct ip_ct_rtsp_expect exp_rtsp_info;
297 + struct ip_ct_rsh_expect exp_rsh_info;
298 + struct ip_ct_mms_expect exp_mms_info;
299 + struct ip_ct_h225_expect exp_h225_info;
300 struct ip_ct_amanda_expect exp_amanda_info;
301 struct ip_ct_ftp_expect exp_ftp_info;
302 struct ip_ct_irc_expect exp_irc_info;
304 /* per conntrack: application helper private data */
305 union ip_conntrack_help {
306 /* insert conntrack helper private data (master) here */
307 + struct ip_ct_talk_master ct_talk_info;
308 + struct ip_ct_rtsp_master ct_rtsp_info;
309 + struct ip_ct_rsh_master ct_rsh_info;
310 + struct ip_ct_mms_master ct_mms_info;
311 + struct ip_ct_h225_master ct_h225_info;
312 struct ip_ct_ftp_master ct_ftp_info;
313 struct ip_ct_irc_master ct_irc_info;
317 #endif /* CONFIG_IP_NF_NAT_NEEDED */
319 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
320 + unsigned long mark;
325 /* get master conntrack via master expectation */
326 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
327 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
328 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-06-08 10:38:40.000000000 +0200
330 +#ifndef _IP_CONNTRACK_H323_H
331 +#define _IP_CONNTRACK_H323_H
332 +/* H.323 connection tracking. */
335 +/* Protects H.323 related data */
336 +#include <linux/netfilter_ipv4/lockhelp.h>
337 +DECLARE_LOCK_EXTERN(ip_h323_lock);
340 +/* Default H.225 port */
341 +#define H225_PORT 1720
343 +/* This structure is per expected connection */
344 +struct ip_ct_h225_expect {
345 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
346 + enum ip_conntrack_dir dir; /* Direction of the original connection */
347 + unsigned int offset; /* offset of the address in the payload */
350 +/* This structure exists only once per master */
351 +struct ip_ct_h225_master {
352 + int is_h225; /* H.225 or H.245 connection */
353 +#ifdef CONFIG_IP_NF_NAT_NEEDED
354 + enum ip_conntrack_dir dir; /* Direction of the original connection */
355 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
356 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
360 +#endif /* _IP_CONNTRACK_H323_H */
361 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
362 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
363 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-06-08 10:39:44.000000000 +0200
365 +#ifndef _IP_CONNTRACK_MMS_H
366 +#define _IP_CONNTRACK_MMS_H
370 +#include <linux/netfilter_ipv4/lockhelp.h>
372 +DECLARE_LOCK_EXTERN(ip_mms_lock);
374 +#define MMS_PORT 1755
375 +#define MMS_SRV_MSG_ID 196610
377 +#define MMS_SRV_MSG_OFFSET 36
378 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
379 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
380 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
381 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
384 +/* This structure is per expected connection */
385 +struct ip_ct_mms_expect {
391 +/* This structure exists only once per master */
392 +struct ip_ct_mms_master {
395 +#endif /* _IP_CONNTRACK_MMS_H */
396 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
397 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
398 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-06-08 10:40:36.000000000 +0200
400 +#ifndef _IP_CT_QUAKE3
401 +#define _IP_CT_QUAKE3
403 +/* Don't confuse with 27960, often used as the Server Port */
404 +#define QUAKE3_MASTER_PORT 27950
406 +struct quake3_search {
407 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
408 + const char *pattern;
412 +/* This structure is per expected connection */
413 +struct ip_ct_quake3_expect {
416 +/* This structure exists only once per master */
417 +struct ip_ct_quake3_master {
420 +#endif /* _IP_CT_QUAKE3 */
421 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
422 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
423 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-06-08 10:40:43.000000000 +0200
425 +/* RSH extension for IP connection tracking, Version 1.0
426 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
427 + * based on HW's ip_conntrack_irc.c
429 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
431 + * This program is free software; you can redistribute it and/or
432 + * modify it under the terms of the GNU General Public License
433 + * as published by the Free Software Foundation; either version
434 + * 2 of the License, or (at your option) any later version.
436 +#ifndef _IP_CONNTRACK_RSH_H
437 +#define _IP_CONNTRACK_RSH_H
440 +#include <linux/netfilter_ipv4/lockhelp.h>
442 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
446 +#define RSH_PORT 514
448 +/* This structure is per expected connection */
449 +struct ip_ct_rsh_expect
454 +/* This structure exists only once per master */
455 +struct ip_ct_rsh_master {
458 +#endif /* _IP_CONNTRACK_RSH_H */
460 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
461 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
462 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-06-08 10:40:46.000000000 +0200
465 + * RTSP extension for IP connection tracking.
466 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
467 + * based on ip_conntrack_irc.h
469 + * This program is free software; you can redistribute it and/or
470 + * modify it under the terms of the GNU General Public License
471 + * as published by the Free Software Foundation; either version
472 + * 2 of the License, or (at your option) any later version.
474 +#ifndef _IP_CONNTRACK_RTSP_H
475 +#define _IP_CONNTRACK_RTSP_H
477 +/* #define IP_NF_RTSP_DEBUG */
478 +#define IP_NF_RTSP_VERSION "0.01"
480 +/* port block types */
482 + pb_single, /* client_port=x */
483 + pb_range, /* client_port=x-y */
484 + pb_discon /* client_port=x/y (rtspbis) */
487 +/* We record seq number and length of rtsp headers here, all in host order. */
490 + * This structure is per expected connection. It is a member of struct
491 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
492 + * there and we are expected to only store the length of the data which
493 + * needs replaced. If a packet contains multiple RTSP messages, we create
494 + * one expected connection per message.
496 + * We use these variables to mark the entire header block. This may seem
497 + * like overkill, but the nature of RTSP requires it. A header may appear
498 + * multiple times in a message. We must treat two Transport headers the
499 + * same as one Transport header with two entries.
501 +struct ip_ct_rtsp_expect
503 + u_int32_t len; /* length of header block */
504 + portblock_t pbtype; /* Type of port block that was requested */
505 + u_int16_t loport; /* Port that was requested, low or first */
506 + u_int16_t hiport; /* Port that was requested, high or second */
508 + uint method; /* RTSP method */
509 + uint cseq; /* CSeq from request */
513 +/* This structure exists only once per master */
514 +struct ip_ct_rtsp_master
522 +#include <linux/netfilter_ipv4/lockhelp.h>
524 +#define RTSP_PORT 554
526 +/* Protects rtsp part of conntracks */
527 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
529 +#endif /* __KERNEL__ */
531 +#endif /* _IP_CONNTRACK_RTSP_H */
532 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
533 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
534 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-06-08 10:40:55.000000000 +0200
536 +#ifndef _IP_CONNTRACK_SCTP_H
537 +#define _IP_CONNTRACK_SCTP_H
538 +/* SCTP tracking. */
540 +enum sctp_conntrack {
541 + SCTP_CONNTRACK_NONE,
542 + SCTP_CONNTRACK_CLOSED,
543 + SCTP_CONNTRACK_COOKIE_WAIT,
544 + SCTP_CONNTRACK_COOKIE_ECHOED,
545 + SCTP_CONNTRACK_ESTABLISHED,
546 + SCTP_CONNTRACK_SHUTDOWN_SENT,
547 + SCTP_CONNTRACK_SHUTDOWN_RECD,
548 + SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
554 + enum sctp_conntrack state;
556 + u_int32_t vtag[IP_CT_DIR_MAX];
557 + u_int32_t ttag[IP_CT_DIR_MAX];
560 +#endif /* _IP_CONNTRACK_SCTP_H */
561 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
562 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
563 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-06-08 10:41:27.000000000 +0200
565 +#ifndef _IP_CONNTRACK_TALK_H
566 +#define _IP_CONNTRACK_TALK_H
567 +/* TALK tracking. */
570 +#include <linux/in.h>
571 +#include <linux/netfilter_ipv4/lockhelp.h>
573 +/* Protects talk part of conntracks */
574 +DECLARE_LOCK_EXTERN(ip_talk_lock);
578 +#define TALK_PORT 517
579 +#define NTALK_PORT 518
581 +/* talk structures and constants from <protocols/talkd.h> */
584 + * 4.3BSD struct sockaddr
587 + u_int16_t ta_family;
590 + u_int32_t ta_junk1;
591 + u_int32_t ta_junk2;
594 +#define TALK_OLD_NSIZE 9
595 +#define TALK_NSIZE 12
596 +#define TALK_TTY_NSIZE 16
599 + * Client->server request message formats.
602 + u_char type; /* request type, see below */
603 + char l_name[TALK_OLD_NSIZE];/* caller's name */
604 + char r_name[TALK_OLD_NSIZE];/* callee's name */
606 + u_int32_t id_num; /* message id */
607 + int32_t pid; /* caller's process id */
608 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
609 + struct talk_addr addr; /* old (4.3) style */
610 + struct talk_addr ctl_addr; /* old (4.3) style */
614 + u_char vers; /* protocol version */
615 + u_char type; /* request type, see below */
616 + u_char answer; /* not used */
618 + u_int32_t id_num; /* message id */
619 + struct talk_addr addr; /* old (4.3) style */
620 + struct talk_addr ctl_addr; /* old (4.3) style */
621 + int32_t pid; /* caller's process id */
622 + char l_name[TALK_NSIZE];/* caller's name */
623 + char r_name[TALK_NSIZE];/* callee's name */
624 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
628 + u_char vers; /* talk protocol version */
629 + u_char type; /* request type */
630 + u_char answer; /* */
631 + u_char extended; /* !0 if additional parts */
632 + u_int32_t id_num; /* message id number (dels) */
633 + struct talk_addr addr; /* target address */
634 + struct talk_addr ctl_addr; /* reply to address */
635 + int32_t pid; /* caller's process id */
636 + char l_name[TALK_NSIZE]; /* caller's name */
637 + char r_name[TALK_NSIZE]; /* callee's name */
638 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
642 + * Server->client response message formats.
644 +struct talk_response {
645 + u_char type; /* type of request message, see below */
646 + u_char answer; /* response to request message, see below */
648 + u_int32_t id_num; /* message id */
649 + struct talk_addr addr; /* address for establishing conversation */
652 +struct ntalk_response {
653 + u_char vers; /* protocol version */
654 + u_char type; /* type of request message, see below */
655 + u_char answer; /* response to request message, see below */
657 + u_int32_t id_num; /* message id */
658 + struct talk_addr addr; /* address for establishing conversation */
661 +struct ntalk2_response {
662 + u_char vers; /* protocol version */
663 + u_char type; /* type of request message */
664 + u_char answer; /* response to request */
665 + u_char rvers; /* Version of answering vers*/
666 + u_int32_t id_num; /* message id number */
667 + struct talk_addr addr; /* address for connection */
668 + /* This is at the end to compatiblize this with NTALK version. */
669 + char r_name[TALK_NSIZE]; /* callee's name */
672 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
673 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
674 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
676 +#define TALK_VERSION 0 /* protocol versions */
677 +#define NTALK_VERSION 1
678 +#define NTALK2_VERSION 2
680 +/* message type values */
681 +#define LEAVE_INVITE 0 /* leave invitation with server */
682 +#define LOOK_UP 1 /* check for invitation by callee */
683 +#define DELETE 2 /* delete invitation by caller */
684 +#define ANNOUNCE 3 /* announce invitation by caller */
686 +#define REPLY_QUERY 4 /* request reply data from local daemon */
689 +#define SUCCESS 0 /* operation completed properly */
690 +#define NOT_HERE 1 /* callee not logged in */
691 +#define FAILED 2 /* operation failed for unexplained reason */
692 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
693 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
694 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
695 +#define BADVERSION 6 /* request has invalid protocol version */
696 +#define BADADDR 7 /* request has invalid addr value */
697 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
699 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
700 +#define TRY_HERE 10 /* Not on this machine, try this */
701 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
702 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
704 +/* We don't really need much for talk */
705 +struct ip_ct_talk_expect
707 + /* Port that was to be used */
711 +/* This structure exists only once per master */
712 +struct ip_ct_talk_master
716 +#endif /* _IP_CONNTRACK_TALK_H */
717 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
718 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-06-07 21:14:55.000000000 +0200
719 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-06-08 10:40:55.000000000 +0200
729 /* The manipulable part of the tuple. */
740 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_pool.h
741 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
742 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_pool.h 2004-06-08 10:31:45.000000000 +0200
747 +/***************************************************************************/
748 +/* This program is free software; you can redistribute it and/or modify */
749 +/* it under the terms of the GNU General Public License as published by */
750 +/* the Free Software Foundation; either version 2 of the License, or */
751 +/* (at your option) any later version. */
753 +/* This program is distributed in the hope that it will be useful, */
754 +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
755 +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
756 +/* GNU General Public License for more details. */
758 +/* You should have received a copy of the GNU General Public License */
759 +/* along with this program; if not, write to the Free Software */
760 +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
761 +/***************************************************************************/
763 +/* A sockopt of such quality has hardly ever been seen before on the open
764 + * market! This little beauty, hardly ever used: above 64, so it's
765 + * traditionally used for firewalling, not touched (even once!) by the
766 + * 2.0, 2.2 and 2.4 kernels!
768 + * Comes with its own certificate of authenticity, valid anywhere in the
773 +#define SO_IP_POOL 81
775 +typedef int ip_pool_t; /* pool index */
776 +#define IP_POOL_NONE ((ip_pool_t)-1)
778 +struct ip_pool_request {
785 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
787 +#define IP_POOL_BAD001 0x00000010
789 +#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
790 +#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
791 +#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
792 +#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
793 +#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
794 +#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
795 +#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
796 +#define IP_POOL_USAGE 0x00000018 /* result in addr */
797 +#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
801 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
802 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
803 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
807 +#endif /*_IP_POOL_H*/
808 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_tables.h
809 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_tables.h 2004-06-07 21:14:25.000000000 +0200
810 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_tables.h 2004-06-08 10:37:30.000000000 +0200
813 unsigned int comefrom;
815 + /* Name of the chain */
818 + /* Rule number in the chain. */
821 /* Packet and byte counters. */
822 struct ipt_counters counters;
824 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
825 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
826 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-06-08 10:36:58.000000000 +0200
828 +#ifndef _IPT_CONNMARK_H_target
829 +#define _IPT_CONNMARK_H_target
831 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
832 + * by Henrik Nordstrom <hno@marasystems.com>
834 + * This program is free software; you can redistribute it and/or modify
835 + * it under the terms of the GNU General Public License as published by
836 + * the Free Software Foundation; either version 2 of the License, or
837 + * (at your option) any later version.
841 + IPT_CONNMARK_SET = 0,
843 + IPT_CONNMARK_RESTORE
846 +struct ipt_connmark_target_info {
847 + unsigned long mark;
848 + unsigned long mask;
852 +#endif /*_IPT_CONNMARK_H_target*/
853 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
854 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
855 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-06-08 10:37:02.000000000 +0200
857 +#ifndef _IPT_IPMARK_H_target
858 +#define _IPT_IPMARK_H_target
860 +struct ipt_ipmark_target_info {
861 + unsigned long andmask;
862 + unsigned long ormask;
866 +#define IPT_IPMARK_SRC 0
867 +#define IPT_IPMARK_DST 1
869 +#endif /*_IPT_IPMARK_H_target*/
870 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
871 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
872 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-06-08 10:31:09.000000000 +0200
874 +#ifndef _IPT_FWMON_H
875 +#define _IPT_FWMON_H
877 +/* Bitmask macros */
878 +#define MASK(x,y) (x & y)
879 +#define MASK_SET(x,y) x |= y
880 +#define MASK_UNSET(x,y) x &= ~y
882 +#define USE_MARK 0x00000001
883 +#define USE_DROP 0x00000002
884 +#define USE_SIZE 0x00000004
888 + unsigned int flags;
897 + char iface[IFNAMSIZ];
900 +#endif /*_IPT_FWMON_H*/
901 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h
902 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
903 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h 2004-06-08 10:37:08.000000000 +0200
905 +/* Header file for iptables ipt_ROUTE target
907 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
909 + * This software is distributed under GNU GPL v2, 1991
911 +#ifndef _IPT_ROUTE_H_target
912 +#define _IPT_ROUTE_H_target
914 +#define IPT_ROUTE_IFNAMSIZ 16
916 +struct ipt_route_target_info {
917 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
918 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
919 + u_int32_t gw; /* IP address of gateway */
923 +/* Values for "flags" field */
924 +#define IPT_ROUTE_CONTINUE 0x01
926 +#endif /*_IPT_ROUTE_H_target*/
927 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
928 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
929 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_TTL.h 2004-06-08 10:31:21.000000000 +0200
931 +/* TTL modification module for IP tables
932 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
943 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
945 +struct ipt_TTL_info {
952 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
953 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
954 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-06-08 10:37:54.000000000 +0200
959 +struct ipt_XOR_info {
961 + u_int8_t block_size;
964 +#endif /* _IPT_XOR_H */
965 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
966 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
967 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-06-08 10:38:04.000000000 +0200
969 +#ifndef _IPT_ADDRTYPE_H
970 +#define _IPT_ADDRTYPE_H
972 +struct ipt_addrtype_info {
973 + u_int16_t source; /* source-type mask */
974 + u_int16_t dest; /* dest-type mask */
980 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
981 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
982 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-06-08 10:31:23.000000000 +0200
984 +#ifndef _IPT_CONNLIMIT_H
985 +#define _IPT_CONNLIMIT_H
987 +struct ipt_connlimit_data;
989 +struct ipt_connlimit_info {
993 + struct ipt_connlimit_data *data;
995 +#endif /* _IPT_CONNLIMIT_H */
996 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
997 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
998 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-06-08 10:36:58.000000000 +0200
1000 +#ifndef _IPT_CONNMARK_H
1001 +#define _IPT_CONNMARK_H
1003 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
1004 + * by Henrik Nordstrom <hno@marasystems.com>
1006 + * This program is free software; you can redistribute it and/or modify
1007 + * it under the terms of the GNU General Public License as published by
1008 + * the Free Software Foundation; either version 2 of the License, or
1009 + * (at your option) any later version.
1012 +struct ipt_connmark_info {
1013 + unsigned long mark, mask;
1017 +#endif /*_IPT_CONNMARK_H*/
1018 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
1019 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
1020 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-06-08 10:31:34.000000000 +0200
1022 +#ifndef _IPT_DSTLIMIT_H
1023 +#define _IPT_DSTLIMIT_H
1025 +/* timings are in milliseconds. */
1026 +#define IPT_DSTLIMIT_SCALE 10000
1027 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
1028 + seconds, or one every 59 hours. */
1030 +/* details of this structure hidden by the implementation */
1031 +struct ipt_dstlimit_htable;
1033 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
1034 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
1035 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
1037 +struct dstlimit_cfg {
1038 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1039 + u_int32_t avg; /* Average secs between packets * scale */
1040 + u_int32_t burst; /* Period multiplier for upper limit. */
1042 + /* user specified */
1043 + u_int32_t size; /* how many buckets */
1044 + u_int32_t max; /* max number of entries */
1045 + u_int32_t gc_interval; /* gc interval */
1046 + u_int32_t expire; /* when do entries expire? */
1049 +struct ipt_dstlimit_info {
1050 + char name [IFNAMSIZ]; /* name */
1051 + struct dstlimit_cfg cfg;
1052 + struct ipt_dstlimit_htable *hinfo;
1054 + /* Used internally by the kernel */
1057 + struct ipt_dstlimit_info *master;
1060 +#endif /*_IPT_DSTLIMIT_H*/
1061 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
1062 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1063 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-06-08 10:31:37.000000000 +0200
1065 +#ifndef _IPT_FUZZY_H
1066 +#define _IPT_FUZZY_H
1068 +#include <linux/param.h>
1069 +#include <linux/types.h>
1071 +#define MAXFUZZYRATE 10000000
1072 +#define MINFUZZYRATE 3
1074 +struct ipt_fuzzy_info {
1075 + u_int32_t minimum_rate;
1076 + u_int32_t maximum_rate;
1077 + u_int32_t packets_total;
1078 + u_int32_t bytes_total;
1079 + u_int32_t previous_time;
1080 + u_int32_t present_time;
1081 + u_int32_t mean_rate;
1082 + u_int8_t acceptance_rate;
1085 +#endif /*_IPT_FUZZY_H*/
1086 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
1087 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1088 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-06-08 10:31:39.000000000 +0200
1090 +#ifndef __ipt_ipv4options_h_included__
1091 +#define __ipt_ipv4options_h_included__
1093 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1094 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1095 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1096 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1097 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1098 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1099 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1100 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1101 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1102 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1103 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1105 +struct ipt_ipv4options_info {
1106 + u_int16_t options;
1110 +#endif /* __ipt_ipv4options_h_included__ */
1111 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_mport.h
1112 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1113 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_mport.h 2004-06-08 10:31:40.000000000 +0200
1115 +#ifndef _IPT_MPORT_H
1116 +#define _IPT_MPORT_H
1117 +#include <linux/netfilter_ipv4/ip_tables.h>
1119 +#define IPT_MPORT_SOURCE (1<<0)
1120 +#define IPT_MPORT_DESTINATION (1<<1)
1121 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1123 +#define IPT_MULTI_PORTS 15
1125 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1126 +/* every entry in ports[] except for the last one has one bit in pflags
1127 + * associated with it. If this bit is set, the port is the first port of
1128 + * a portrange, with the next entry being the last.
1129 + * End of list is marked with pflags bit set and port=65535.
1130 + * If 14 ports are used (last one does not have a pflag), the last port
1131 + * is repeated to fill the last entry in ports[] */
1134 + u_int8_t flags:2; /* Type of comparison */
1135 + u_int16_t pflags:14; /* Port flags */
1136 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1138 +#endif /*_IPT_MPORT_H*/
1139 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_nth.h
1140 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1141 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_nth.h 2004-06-08 10:31:42.000000000 +0200
1146 +#include <linux/param.h>
1147 +#include <linux/types.h>
1149 +#ifndef IPT_NTH_NUM_COUNTERS
1150 +#define IPT_NTH_NUM_COUNTERS 16
1153 +struct ipt_nth_info {
1161 +#endif /*_IPT_NTH_H*/
1162 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_osf.h
1163 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1164 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_osf.h 2004-06-08 10:31:44.000000000 +0200
1169 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1172 + * This program is free software; you can redistribute it and/or modify
1173 + * it under the terms of the GNU General Public License as published by
1174 + * the Free Software Foundation; either version 2 of the License, or
1175 + * (at your option) any later version.
1177 + * This program is distributed in the hope that it will be useful,
1178 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1179 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1180 + * GNU General Public License for more details.
1182 + * You should have received a copy of the GNU General Public License
1183 + * along with this program; if not, write to the Free Software
1184 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1190 +#define MAXGENRELEN 32
1191 +#define MAXDETLEN 64
1193 +#define IPT_OSF_GENRE 1
1194 +#define IPT_OSF_SMART 2
1195 +#define IPT_OSF_LOG 4
1196 +#define IPT_OSF_NETLINK 8
1198 +#define IPT_OSF_LOGLEVEL_ALL 0
1199 +#define IPT_OSF_LOGLEVEL_FIRST 1
1201 +#include <linux/list.h>
1204 +#include <netinet/ip.h>
1205 +#include <netinet/tcp.h>
1209 + struct list_head *prev, *next;
1213 +struct ipt_osf_info
1215 + char genre[MAXGENRELEN];
1217 + unsigned long flags;
1219 + int invert; /* UNSUPPORTED */
1225 + unsigned long val;
1228 +/* This struct represents IANA options
1229 + * http://www.iana.org/assignments/tcp-parameters
1233 + unsigned char kind;
1234 + unsigned char length;
1240 + struct list_head flist;
1241 + struct osf_wc wss;
1242 + unsigned char ttl;
1245 + unsigned char genre[MAXGENRELEN];
1246 + unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
1248 + /* Not needed, but for consistency with original table from Michal Zalewski */
1249 + unsigned char details[MAXDETLEN];
1252 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1256 +struct ipt_osf_nlmsg
1258 + struct osf_finger f;
1260 + struct tcphdr tcp;
1265 +/* Defines for IANA option kinds */
1267 +#define OSFOPT_EOL 0 /* End of options */
1268 +#define OSFOPT_NOP 1 /* NOP */
1269 +#define OSFOPT_MSS 2 /* Maximum segment size */
1270 +#define OSFOPT_WSO 3 /* Window scale option */
1271 +#define OSFOPT_SACKP 4 /* SACK permitted */
1272 +#define OSFOPT_SACK 5 /* SACK */
1273 +#define OSFOPT_ECHO 6
1274 +#define OSFOPT_ECHOREPLY 7
1275 +#define OSFOPT_TS 8 /* Timestamp option */
1276 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1277 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1278 +/* Others are not used in current OSF */
1280 +static struct osf_opt IANA_opts[] =
1287 + {5, 1 ,}, /* SACK length is not defined */
1293 + {11, 1,}, /* CC: Suppose 1 */
1294 + {12, 1,}, /* the same */
1295 + {13, 1,}, /* and here too */
1297 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1311 +#endif /* __KERNEL__ */
1313 +#endif /* _IPT_OSF_H */
1314 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_policy.h
1315 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
1316 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-06-08 10:42:36.000000000 +0200
1318 +#ifndef _IPT_POLICY_H
1319 +#define _IPT_POLICY_H
1321 +#define POLICY_MAX_ELEM 4
1323 +enum ipt_policy_flags
1325 + POLICY_MATCH_IN = 0x1,
1326 + POLICY_MATCH_OUT = 0x2,
1327 + POLICY_MATCH_NONE = 0x4,
1328 + POLICY_MATCH_STRICT = 0x8,
1331 +enum ipt_policy_modes
1333 + POLICY_MODE_TRANSPORT,
1334 + POLICY_MODE_TUNNEL
1337 +struct ipt_policy_spec
1347 +struct ipt_policy_elem
1358 + struct ipt_policy_spec match;
1359 + struct ipt_policy_spec invert;
1362 +struct ipt_policy_info
1364 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1369 +#endif /* _IPT_POLICY_H */
1370 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_pool.h
1371 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1372 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_pool.h 2004-06-08 10:31:45.000000000 +0200
1374 +#ifndef _IPT_POOL_H
1375 +#define _IPT_POOL_H
1377 +#include <linux/netfilter_ipv4/ip_pool.h>
1379 +#define IPT_POOL_INV_SRC 0x00000001
1380 +#define IPT_POOL_INV_DST 0x00000002
1381 +#define IPT_POOL_DEL_SRC 0x00000004
1382 +#define IPT_POOL_DEL_DST 0x00000008
1383 +#define IPT_POOL_INV_MOD_SRC 0x00000010
1384 +#define IPT_POOL_INV_MOD_DST 0x00000020
1385 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1386 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1387 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
1388 +#define IPT_POOL_MOD_DST_DROP 0x00000200
1391 +struct ipt_pool_info
1398 +#endif /*_IPT_POOL_H*/
1399 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_psd.h
1400 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1401 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_psd.h 2004-06-08 10:31:53.000000000 +0200
1406 +#include <linux/param.h>
1407 +#include <linux/types.h>
1410 + * High port numbers have a lower weight to reduce the frequency of false
1411 + * positives, such as from passive mode FTP transfers.
1413 +#define PORT_WEIGHT_PRIV 3
1414 +#define PORT_WEIGHT_HIGH 1
1417 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1418 + * from the same source, with no longer than DELAY ticks between ports.
1420 +#define SCAN_MIN_COUNT 7
1421 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1422 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1423 +#define SCAN_DELAY_THRESHOLD (300) /* old usage of HZ here was erroneously and broke under uml */
1426 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1427 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1428 + * HASH_MAX source addresses per the same hash value.
1430 +#define LIST_SIZE 0x100
1432 +#define HASH_SIZE (1 << HASH_LOG)
1433 +#define HASH_MAX 0x10
1435 +struct ipt_psd_info {
1436 + unsigned int weight_threshold;
1437 + unsigned int delay_threshold;
1438 + unsigned short lo_ports_weight;
1439 + unsigned short hi_ports_weight;
1442 +#endif /*_IPT_PSD_H*/
1443 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_quota.h
1444 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1445 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_quota.h 2004-06-08 10:31:54.000000000 +0200
1447 +#ifndef _IPT_QUOTA_H
1448 +#define _IPT_QUOTA_H
1450 +/* print debug info in both kernel/netfilter module & iptable library */
1451 +//#define DEBUG_IPT_QUOTA
1453 +struct ipt_quota_info {
1457 +#endif /*_IPT_QUOTA_H*/
1458 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_random.h
1459 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1460 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_random.h 2004-06-08 10:31:56.000000000 +0200
1462 +#ifndef _IPT_RAND_H
1463 +#define _IPT_RAND_H
1465 +#include <linux/param.h>
1466 +#include <linux/types.h>
1468 +struct ipt_rand_info {
1472 +#endif /*_IPT_RAND_H*/
1473 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_realm.h
1474 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1475 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_realm.h 2004-06-08 10:32:20.000000000 +0200
1477 +#ifndef _IPT_REALM_H
1478 +#define _IPT_REALM_H
1480 +struct ipt_realm_info {
1485 +#endif /*_IPT_REALM_H*/
1486 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_sctp.h
1487 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1488 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_sctp.h 2004-06-08 10:32:21.000000000 +0200
1490 +#ifndef _IPT_SCTP_H_
1491 +#define _IPT_SCTP_H_
1493 +#define IPT_SCTP_SRC_PORTS 0x01
1494 +#define IPT_SCTP_DEST_PORTS 0x02
1495 +#define IPT_SCTP_CHUNK_TYPES 0x04
1497 +#define IPT_SCTP_VALID_FLAGS 0x07
1499 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1502 +struct ipt_sctp_flag_info {
1503 + u_int8_t chunktype;
1505 + u_int8_t flag_mask;
1508 +#define IPT_NUM_SCTP_FLAGS 4
1510 +struct ipt_sctp_info {
1511 + u_int16_t dpts[2]; /* Min, Max */
1512 + u_int16_t spts[2]; /* Min, Max */
1514 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
1516 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
1517 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
1518 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
1520 + u_int32_t chunk_match_type;
1521 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1525 + u_int32_t invflags;
1528 +#define bytes(type) (sizeof(type) * 8)
1530 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
1532 + chunkmap[type / bytes(u_int32_t)] |= \
1533 + 1 << (type % bytes(u_int32_t)); \
1536 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
1538 + chunkmap[type / bytes(u_int32_t)] &= \
1539 + ~(1 << (type % bytes(u_int32_t))); \
1542 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
1544 + (chunkmap[type / bytes (u_int32_t)] & \
1545 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
1548 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
1551 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1552 + chunkmap[i] = 0; \
1555 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
1558 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1559 + chunkmap[i] = ~0; \
1562 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
1565 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1566 + destmap[i] = srcmap[i]; \
1569 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
1573 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1574 + if (chunkmap[i]) { \
1582 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
1586 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1587 + if (chunkmap[i] != ~0) { \
1595 +#endif /* _IPT_SCTP_H_ */
1597 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_string.h
1598 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1599 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-06-08 10:41:24.000000000 +0200
1601 +#ifndef _IPT_STRING_H
1602 +#define _IPT_STRING_H
1604 +/* *** PERFORMANCE TWEAK ***
1605 + * Packet size and search string threshold,
1606 + * above which sublinear searches is used. */
1607 +#define IPT_STRING_HAYSTACK_THRESH 100
1608 +#define IPT_STRING_NEEDLE_THRESH 20
1610 +#define BM_MAX_NLEN 256
1611 +#define BM_MAX_HLEN 1024
1613 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1615 +struct ipt_string_info {
1616 + char string[BM_MAX_NLEN];
1621 +#endif /* _IPT_STRING_H */
1622 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_time.h
1623 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1624 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_time.h 2004-06-08 10:32:31.000000000 +0200
1626 +#ifndef __ipt_time_h_included__
1627 +#define __ipt_time_h_included__
1630 +struct ipt_time_info {
1631 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
1632 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
1633 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
1634 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
1635 + time_t date_start;
1640 +#endif /* __ipt_time_h_included__ */
1641 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_u32.h
1642 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
1643 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_u32.h 2004-06-08 10:32:32.000000000 +0200
1647 +#include <linux/netfilter_ipv4/ip_tables.h>
1657 +struct ipt_u32_location_element
1662 +struct ipt_u32_value_element
1667 +/* *** any way to allow for an arbitrary number of elements?
1668 + for now I settle for a limit of 10 of each */
1669 +#define U32MAXSIZE 10
1670 +struct ipt_u32_test
1673 + struct ipt_u32_location_element location[U32MAXSIZE+1];
1675 + struct ipt_u32_value_element value[U32MAXSIZE+1];
1681 + struct ipt_u32_test tests[U32MAXSIZE+1];
1684 +#endif /*_IPT_U32_H*/
1685 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.7-rc3/include/linux/netfilter_ipv4.h
1686 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4.h 2004-06-07 21:14:57.000000000 +0200
1687 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4.h 2004-06-08 10:38:44.000000000 +0200
1690 #include <linux/config.h>
1691 #include <linux/netfilter.h>
1692 +#include <linux/netdevice.h>
1693 +#include <net/protocol.h>
1695 /* IP Cache bits. */
1696 /* Src IP address. */
1698 Returns true or false. */
1699 extern int skb_ip_make_writable(struct sk_buff **pskb,
1700 unsigned int writable_len);
1702 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1703 +#include <net/route.h>
1704 +#include <net/xfrm.h>
1706 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1708 + return !skb->sp || skb->sp->decap_done;
1712 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1714 + return skb->sp && !skb->sp->decap_done
1715 + && (!ipprot || !ipprot->xfrm_prot);
1718 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1720 + return skb->sp && !skb->sp->decap_done
1721 + && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1724 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1725 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1726 +#else /* CONFIG_XFRM */
1727 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1733 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1738 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1743 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1748 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1752 +#endif /* CONFIG_XFRM */
1753 #endif /*__KERNEL__*/
1755 #endif /*__LINUX_IP_NETFILTER_H*/
1756 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1757 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-06-07 21:15:11.000000000 +0200
1758 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6_tables.h 2004-06-08 10:37:30.000000000 +0200
1759 @@ -142,6 +142,12 @@
1761 unsigned int comefrom;
1763 + /* Name of the chain */
1766 + /* Rule number in the chain. */
1767 + u_int32_t rulenum;
1769 /* Packet and byte counters. */
1770 struct ip6t_counters counters;
1772 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
1773 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
1774 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_HL.h 2004-06-08 10:31:03.000000000 +0200
1776 +/* Hop Limit modification module for ip6tables
1777 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1778 + * Based on HW's TTL module */
1789 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
1791 +struct ip6t_HL_info {
1793 + u_int8_t hop_limit;
1798 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1799 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-06-07 21:13:34.000000000 +0200
1800 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-06-08 10:31:20.000000000 +0200
1802 #define _IP6T_REJECT_H
1804 enum ip6t_reject_with {
1805 - IP6T_ICMP_NET_UNREACHABLE,
1806 - IP6T_ICMP_HOST_UNREACHABLE,
1807 - IP6T_ICMP_PROT_UNREACHABLE,
1808 - IP6T_ICMP_PORT_UNREACHABLE,
1809 - IP6T_ICMP_ECHOREPLY
1810 + IP6T_ICMP6_NO_ROUTE,
1811 + IP6T_ICMP6_ADM_PROHIBITED,
1812 + IP6T_ICMP6_NOT_NEIGHBOUR,
1813 + IP6T_ICMP6_ADDR_UNREACH,
1814 + IP6T_ICMP6_PORT_UNREACH,
1815 + IP6T_ICMP6_ECHOREPLY,
1819 struct ip6t_reject_info {
1820 enum ip6t_reject_with with; /* reject type */
1823 -#endif /*_IPT_REJECT_H*/
1824 +#endif /*_IP6T_REJECT_H*/
1825 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h
1826 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
1827 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2004-06-08 10:37:08.000000000 +0200
1829 +/* Header file for iptables ip6t_ROUTE target
1831 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
1833 + * This software is distributed under GNU GPL v2, 1991
1835 +#ifndef _IPT_ROUTE_H_target
1836 +#define _IPT_ROUTE_H_target
1838 +#define IP6T_ROUTE_IFNAMSIZ 16
1840 +struct ip6t_route_target_info {
1841 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
1842 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
1843 + u_int32_t gw[4]; /* IPv6 address of gateway */
1847 +/* Values for "flags" field */
1848 +#define IP6T_ROUTE_CONTINUE 0x01
1850 +#endif /*_IP6T_ROUTE_H_target*/
1851 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1852 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1853 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-06-08 10:31:37.000000000 +0200
1855 +#ifndef _IP6T_FUZZY_H
1856 +#define _IP6T_FUZZY_H
1858 +#include <linux/param.h>
1859 +#include <linux/types.h>
1861 +#define MAXFUZZYRATE 10000000
1862 +#define MINFUZZYRATE 3
1864 +struct ip6t_fuzzy_info {
1865 + u_int32_t minimum_rate;
1866 + u_int32_t maximum_rate;
1867 + u_int32_t packets_total;
1868 + u_int32_t bytes_total;
1869 + u_int32_t previous_time;
1870 + u_int32_t present_time;
1871 + u_int32_t mean_rate;
1872 + u_int8_t acceptance_rate;
1875 +#endif /*_IP6T_FUZZY_H*/
1876 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
1877 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1878 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_nth.h 2004-06-08 10:31:42.000000000 +0200
1880 +#ifndef _IP6T_NTH_H
1881 +#define _IP6T_NTH_H
1883 +#include <linux/param.h>
1884 +#include <linux/types.h>
1886 +#ifndef IP6T_NTH_NUM_COUNTERS
1887 +#define IP6T_NTH_NUM_COUNTERS 16
1890 +struct ip6t_nth_info {
1898 +#endif /*_IP6T_NTH_H*/
1899 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1900 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-06-07 21:14:41.000000000 +0200
1901 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_owner.h 2004-06-08 10:40:01.000000000 +0200
1903 #define IP6T_OWNER_GID 0x02
1904 #define IP6T_OWNER_PID 0x04
1905 #define IP6T_OWNER_SID 0x08
1906 +#define IP6T_OWNER_COMM 0x10
1908 struct ip6t_owner_info {
1914 u_int8_t match, invert; /* flags */
1917 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1918 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1919 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_policy.h 2004-06-08 10:42:36.000000000 +0200
1921 +#ifndef _IP6T_POLICY_H
1922 +#define _IP6T_POLICY_H
1924 +#define POLICY_MAX_ELEM 4
1926 +enum ip6t_policy_flags
1928 + POLICY_MATCH_IN = 0x1,
1929 + POLICY_MATCH_OUT = 0x2,
1930 + POLICY_MATCH_NONE = 0x4,
1931 + POLICY_MATCH_STRICT = 0x8,
1934 +enum ip6t_policy_modes
1936 + POLICY_MODE_TRANSPORT,
1937 + POLICY_MODE_TUNNEL
1940 +struct ip6t_policy_spec
1950 +struct ip6t_policy_elem
1952 + struct in6_addr saddr;
1953 + struct in6_addr smask;
1954 + struct in6_addr daddr;
1955 + struct in6_addr dmask;
1961 + struct ip6t_policy_spec match;
1962 + struct ip6t_policy_spec invert;
1965 +struct ip6t_policy_info
1967 + struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
1972 +#endif /* _IP6T_POLICY_H */
1973 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_random.h
1974 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
1975 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_random.h 2004-06-08 10:31:56.000000000 +0200
1977 +#ifndef _IP6T_RAND_H
1978 +#define _IP6T_RAND_H
1980 +#include <linux/param.h>
1981 +#include <linux/types.h>
1983 +struct ip6t_rand_info {
1987 +#endif /*_IP6T_RAND_H*/
1988 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_mime.h linux-2.6.7-rc3/include/linux/netfilter_mime.h
1989 --- linux-2.6.7-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1990 +++ linux-2.6.7-rc3/include/linux/netfilter_mime.h 2004-06-08 10:40:46.000000000 +0200
1993 + * MIME functions for netfilter modules. This file provides implementations
1994 + * for basic MIME parsing. MIME headers are used in many protocols, such as
1995 + * HTTP, RTSP, SIP, etc.
1997 + * gcc will warn for defined but unused functions, so we only include the
1998 + * functions requested. The following macros are used:
1999 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
2001 +#ifndef _NETFILTER_MIME_H
2002 +#define _NETFILTER_MIME_H
2004 +/* Only include these functions for kernel code. */
2007 +#include <linux/ctype.h>
2010 + * Given a buffer and length, advance to the next line and mark the current
2011 + * line. If the current line is empty, *plinelen will be set to zero. If
2012 + * not, it will be set to the actual line length (including CRLF).
2014 + * 'line' in this context means logical line (includes LWS continuations).
2015 + * Returns 1 on success, 0 on failure.
2017 +#ifdef NF_NEED_MIME_NEXTLINE
2019 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2023 + int is_first_line = 1;
2032 + while (p[off] != '\n')
2043 + /* if we saw a crlf, physlen needs adjusted */
2044 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2049 + /* advance past the newline */
2052 + /* check for an empty line */
2058 + /* check for colon on the first physical line */
2059 + if (is_first_line)
2061 + is_first_line = 0;
2062 + if (memchr(p+(*poff), ':', physlen) == NULL)
2068 + while (p[off] == ' ' || p[off] == '\t');
2070 + *plineoff = *poff;
2071 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
2076 +#endif /* NF_NEED_MIME_NEXTLINE */
2078 +#endif /* __KERNEL__ */
2080 +#endif /* _NETFILTER_MIME_H */
2081 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/skbuff.h linux-2.6.7-rc3/include/linux/skbuff.h
2082 --- linux-2.6.7-rc3.org/include/linux/skbuff.h 2004-06-07 21:14:33.000000000 +0200
2083 +++ linux-2.6.7-rc3/include/linux/skbuff.h 2004-06-08 10:30:55.000000000 +0200
2084 @@ -1049,6 +1049,14 @@
2086 atomic_inc(&nfct->master->use);
2088 +static inline void nf_reset(struct sk_buff *skb)
2090 + nf_conntrack_put(skb->nfct);
2092 +#ifdef CONFIG_NETFILTER_DEBUG
2093 + skb->nf_debug = 0;
2097 #ifdef CONFIG_BRIDGE_NETFILTER
2098 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2099 @@ -1061,9 +1069,10 @@
2101 atomic_inc(&nf_bridge->use);
2106 +#endif /* CONFIG_BRIDGE_NETFILTER */
2107 +#else /* CONFIG_NETFILTER */
2108 +static inline void nf_reset(struct sk_buff *skb) {}
2109 +#endif /* CONFIG_NETFILTER */
2111 #endif /* __KERNEL__ */
2112 #endif /* _LINUX_SKBUFF_H */
2113 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/ip.h linux-2.6.7-rc3/include/net/ip.h
2114 --- linux-2.6.7-rc3.org/include/net/ip.h 2004-06-07 21:14:42.000000000 +0200
2115 +++ linux-2.6.7-rc3/include/net/ip.h 2004-06-08 10:38:43.000000000 +0200
2117 #include <linux/netdevice.h>
2118 #include <linux/inetdevice.h>
2119 #include <linux/in_route.h>
2120 +#include <linux/netfilter.h>
2121 +#include <linux/netfilter_ipv4.h>
2122 #include <net/route.h>
2123 #include <net/arp.h>
2126 #define IPSKB_TRANSLATED 2
2127 #define IPSKB_FORWARDED 4
2128 #define IPSKB_XFRM_TUNNEL_SIZE 8
2129 +#define IPSKB_XFRM_TRANSFORMED 16
2133 @@ -212,6 +215,12 @@
2134 __ip_select_ident(iph, dst, more);
2137 +extern inline int ip_dst_output(struct sk_buff *skb)
2139 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2140 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2144 * Map a multicast IP onto multicast MAC for type ethernet.
2146 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/protocol.h linux-2.6.7-rc3/include/net/protocol.h
2147 --- linux-2.6.7-rc3.org/include/net/protocol.h 2004-06-07 21:14:10.000000000 +0200
2148 +++ linux-2.6.7-rc3/include/net/protocol.h 2004-06-08 10:38:44.000000000 +0200
2150 int (*handler)(struct sk_buff *skb);
2151 void (*err_handler)(struct sk_buff *skb, u32 info);
2156 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2157 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/tcp.h linux-2.6.7-rc3/include/net/tcp.h
2158 --- linux-2.6.7-rc3.org/include/net/tcp.h 2004-06-07 21:13:39.000000000 +0200
2159 +++ linux-2.6.7-rc3/include/net/tcp.h 2004-06-08 10:39:56.000000000 +0200
2161 extern void tcp_bucket_unlock(struct sock *sk);
2162 extern int tcp_port_rover;
2163 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2164 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2166 /* These are AF independent. */
2167 static __inline__ int tcp_bhashfn(__u16 lport)
2168 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/udp.h linux-2.6.7-rc3/include/net/udp.h
2169 --- linux-2.6.7-rc3.org/include/net/udp.h 2004-06-07 21:14:56.000000000 +0200
2170 +++ linux-2.6.7-rc3/include/net/udp.h 2004-06-08 10:39:56.000000000 +0200
2172 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2173 extern int udp_disconnect(struct sock *sk, int flags);
2175 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2177 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2178 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
2179 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
2180 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/xfrm.h linux-2.6.7-rc3/include/net/xfrm.h
2181 --- linux-2.6.7-rc3.org/include/net/xfrm.h 2004-06-07 21:14:56.000000000 +0200
2182 +++ linux-2.6.7-rc3/include/net/xfrm.h 2004-06-08 10:38:44.000000000 +0200
2187 +#ifdef CONFIG_NETFILTER
2190 struct sec_decap_state x[XFRM_MAX_DEPTH];
2193 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/core/netfilter.c linux-2.6.7-rc3/net/core/netfilter.c
2194 --- linux-2.6.7-rc3.org/net/core/netfilter.c 2004-06-07 21:14:11.000000000 +0200
2195 +++ linux-2.6.7-rc3/net/core/netfilter.c 2004-06-08 10:38:46.000000000 +0200
2197 #include <linux/icmp.h>
2198 #include <net/sock.h>
2199 #include <net/route.h>
2200 +#include <net/xfrm.h>
2201 +#include <net/ip.h>
2202 #include <linux/ip.h>
2204 /* In this code, we can be waiting indefinitely for userspace to
2206 #ifdef CONFIG_IP_ROUTE_FWMARK
2207 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2209 - fl.proto = iph->protocol;
2210 if (ip_route_output_key(&rt, &fl) != 0)
2213 @@ -657,6 +658,20 @@
2214 if ((*pskb)->dst->error)
2218 + if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2219 + struct xfrm_policy_afinfo *afinfo;
2221 + afinfo = xfrm_policy_get_afinfo(AF_INET);
2222 + if (afinfo != NULL) {
2223 + afinfo->decode_session(*pskb, &fl);
2224 + xfrm_policy_put_afinfo(afinfo);
2225 + if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2231 /* Change in oif may mean change in hh_len. */
2232 hh_len = (*pskb)->dst->dev->hard_header_len;
2233 if (skb_headroom(*pskb) < hh_len) {
2234 @@ -674,6 +689,71 @@
2239 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2241 + skb->sp->decap_done = 1;
2242 + dst_release(skb->dst);
2245 + return netif_rx(skb);
2248 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2250 + __skb_push(skb, skb->data - skb->nh.raw);
2251 + /* Fix header len and checksum if last xfrm was transport mode */
2252 + if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2253 + skb->nh.iph->tot_len = htons(skb->len);
2254 + ip_send_check(skb->nh.iph);
2256 + return nf_rcv_postxfrm_nonlocal(skb);
2259 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2260 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2261 +#include <linux/netfilter_ipv4/ip_nat.h>
2263 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2265 + struct ip_conntrack *ct;
2266 + struct ip_conntrack_tuple *t;
2267 + struct ip_nat_info_manip *m;
2270 + if (skb->nfct == NULL)
2272 + ct = (struct ip_conntrack *)skb->nfct->master;
2274 + for (i = 0; i < ct->nat.info.num_manips; i++) {
2275 + m = &ct->nat.info.manips[i];
2276 + t = &ct->tuplehash[m->direction].tuple;
2278 + switch (m->hooknum) {
2279 + case NF_IP_PRE_ROUTING:
2280 + if (m->maniptype != IP_NAT_MANIP_DST)
2282 + fl->fl4_dst = t->dst.ip;
2283 + if (t->dst.protonum == IPPROTO_TCP ||
2284 + t->dst.protonum == IPPROTO_UDP)
2285 + fl->fl_ip_dport = t->dst.u.tcp.port;
2287 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2288 + case NF_IP_LOCAL_IN:
2289 + if (m->maniptype != IP_NAT_MANIP_SRC)
2291 + fl->fl4_src = t->src.ip;
2292 + if (t->dst.protonum == IPPROTO_TCP ||
2293 + t->dst.protonum == IPPROTO_UDP)
2294 + fl->fl_ip_sport = t->src.u.tcp.port;
2300 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2303 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2305 struct sk_buff *nskb;
2307 EXPORT_SYMBOL(nf_unregister_hook);
2308 EXPORT_SYMBOL(nf_unregister_queue_handler);
2309 EXPORT_SYMBOL(nf_unregister_sockopt);
2310 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2311 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ah4.c linux-2.6.7-rc3/net/ipv4/ah4.c
2312 --- linux-2.6.7-rc3.org/net/ipv4/ah4.c 2004-06-07 21:14:58.000000000 +0200
2313 +++ linux-2.6.7-rc3/net/ipv4/ah4.c 2004-06-08 10:38:44.000000000 +0200
2315 err = -EHOSTUNREACH;
2318 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2319 return NET_XMIT_BYPASS;
2323 .handler = xfrm4_rcv,
2324 .err_handler = ah4_err,
2329 static int __init ah4_init(void)
2330 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/esp4.c linux-2.6.7-rc3/net/ipv4/esp4.c
2331 --- linux-2.6.7-rc3.org/net/ipv4/esp4.c 2004-06-07 21:14:33.000000000 +0200
2332 +++ linux-2.6.7-rc3/net/ipv4/esp4.c 2004-06-08 10:38:44.000000000 +0200
2334 err = -EHOSTUNREACH;
2337 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2338 return NET_XMIT_BYPASS;
2342 .handler = xfrm4_rcv,
2343 .err_handler = esp4_err,
2348 static int __init esp4_init(void)
2349 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/igmp.c linux-2.6.7-rc3/net/ipv4/igmp.c
2350 --- linux-2.6.7-rc3.org/net/ipv4/igmp.c 2004-06-07 21:15:12.000000000 +0200
2351 +++ linux-2.6.7-rc3/net/ipv4/igmp.c 2004-06-08 10:38:43.000000000 +0200
2353 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2355 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2360 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2362 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2364 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2369 static void igmp_gq_timer_expire(unsigned long data)
2370 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_forward.c linux-2.6.7-rc3/net/ipv4/ip_forward.c
2371 --- linux-2.6.7-rc3.org/net/ipv4/ip_forward.c 2004-06-07 21:13:35.000000000 +0200
2372 +++ linux-2.6.7-rc3/net/ipv4/ip_forward.c 2004-06-08 10:38:43.000000000 +0200
2374 if (unlikely(opt->optlen))
2375 ip_forward_options(skb);
2377 - return dst_output(skb);
2378 + return ip_dst_output(skb);
2381 int ip_forward(struct sk_buff *skb)
2382 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_gre.c linux-2.6.7-rc3/net/ipv4/ip_gre.c
2383 --- linux-2.6.7-rc3.org/net/ipv4/ip_gre.c 2004-06-07 21:14:55.000000000 +0200
2384 +++ linux-2.6.7-rc3/net/ipv4/ip_gre.c 2004-06-08 10:30:55.000000000 +0200
2385 @@ -643,13 +643,7 @@
2386 skb->dev = tunnel->dev;
2387 dst_release(skb->dst);
2389 -#ifdef CONFIG_NETFILTER
2390 - nf_conntrack_put(skb->nfct);
2392 -#ifdef CONFIG_NETFILTER_DEBUG
2393 - skb->nf_debug = 0;
2397 ipgre_ecn_decapsulate(iph, skb);
2399 read_unlock(&ipgre_lock);
2400 @@ -877,13 +871,7 @@
2404 -#ifdef CONFIG_NETFILTER
2405 - nf_conntrack_put(skb->nfct);
2407 -#ifdef CONFIG_NETFILTER_DEBUG
2408 - skb->nf_debug = 0;
2414 tunnel->recursion--;
2415 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_input.c linux-2.6.7-rc3/net/ipv4/ip_input.c
2416 --- linux-2.6.7-rc3.org/net/ipv4/ip_input.c 2004-06-07 21:13:37.000000000 +0200
2417 +++ linux-2.6.7-rc3/net/ipv4/ip_input.c 2004-06-08 10:38:46.000000000 +0200
2418 @@ -202,18 +202,10 @@
2420 #ifdef CONFIG_NETFILTER_DEBUG
2421 nf_debug_ip_local_deliver(skb);
2422 - skb->nf_debug = 0;
2423 #endif /*CONFIG_NETFILTER_DEBUG*/
2425 __skb_pull(skb, ihl);
2427 -#ifdef CONFIG_NETFILTER
2428 - /* Free reference early: we don't need it any more, and it may
2429 - hold ip_conntrack module loaded indefinitely. */
2430 - nf_conntrack_put(skb->nfct);
2432 -#endif /*CONFIG_NETFILTER*/
2434 /* Point into the IP datagram, just past the header. */
2435 skb->h.raw = skb->data;
2437 @@ -228,6 +220,13 @@
2439 hash = protocol & (MAX_INET_PROTOS - 1);
2440 raw_sk = sk_head(&raw_v4_htable[hash]);
2441 + ipprot = inet_protos[hash];
2442 + smp_read_barrier_depends();
2444 + if (nf_xfrm_local_done(skb, ipprot)) {
2445 + nf_rcv_postxfrm_local(skb);
2449 /* If there maybe a raw socket we must check - if not we
2451 @@ -235,14 +234,15 @@
2453 raw_v4_input(skb, skb->nh.iph, hash);
2455 - if ((ipprot = inet_protos[hash]) != NULL) {
2456 + if (ipprot != NULL) {
2459 - smp_read_barrier_depends();
2460 - if (!ipprot->no_policy &&
2461 - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2464 + if (!ipprot->no_policy) {
2465 + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2471 ret = ipprot->handler(skb);
2477 - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2478 - ip_local_deliver_finish);
2479 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2480 + ip_local_deliver_finish, nf_hook_input_cond(skb));
2483 static inline int ip_rcv_finish(struct sk_buff *skb)
2488 + if (nf_xfrm_nonlocal_done(skb))
2489 + return nf_rcv_postxfrm_nonlocal(skb);
2491 #ifdef CONFIG_NET_CLS_ROUTE
2492 if (skb->dst->tclassid) {
2493 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2498 - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2500 + return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2501 + ip_rcv_finish, nf_hook_input_cond(skb));
2504 IP_INC_STATS_BH(InHdrErrors);
2505 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_output.c linux-2.6.7-rc3/net/ipv4/ip_output.c
2506 --- linux-2.6.7-rc3.org/net/ipv4/ip_output.c 2004-06-07 21:15:12.000000000 +0200
2507 +++ linux-2.6.7-rc3/net/ipv4/ip_output.c 2004-06-08 10:38:43.000000000 +0200
2508 @@ -123,6 +123,15 @@
2512 +#ifdef CONFIG_NETFILTER
2513 +/* out-of-line copy is only required with netfilter */
2514 +int ip_dst_output(struct sk_buff *skb)
2516 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2517 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2522 * Add an ip header to a skbuff and send it out.
2527 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2532 static inline int ip_finish_output2(struct sk_buff *skb)
2534 return ip_finish_output(skb);
2537 -int ip_output(struct sk_buff **pskb)
2538 +static inline int ip_output2(struct sk_buff **pskb)
2540 struct sk_buff *skb = *pskb;
2542 @@ -297,6 +306,16 @@
2543 return ip_finish_output(skb);
2546 +int ip_output(struct sk_buff *skb)
2548 + int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2552 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2553 + skb->dst->dev, ip_output2, transformed);
2556 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2558 struct sock *sk = skb->sk;
2560 skb->priority = sk->sk_priority;
2562 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2567 IP_INC_STATS(OutNoRoutes);
2568 @@ -1180,7 +1199,7 @@
2570 /* Netfilter gets whole the not fragmented skb. */
2571 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2572 - skb->dst->dev, dst_output);
2573 + skb->dst->dev, ip_dst_output);
2576 err = inet->recverr ? net_xmit_errno(err) : 0;
2577 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ipcomp.c linux-2.6.7-rc3/net/ipv4/ipcomp.c
2578 --- linux-2.6.7-rc3.org/net/ipv4/ipcomp.c 2004-06-07 21:14:58.000000000 +0200
2579 +++ linux-2.6.7-rc3/net/ipv4/ipcomp.c 2004-06-08 10:38:44.000000000 +0200
2581 err = -EHOSTUNREACH;
2584 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2585 err = NET_XMIT_BYPASS;
2589 .handler = xfrm4_rcv,
2590 .err_handler = ipcomp4_err,
2595 static int __init ipcomp4_init(void)
2596 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ipip.c linux-2.6.7-rc3/net/ipv4/ipip.c
2597 --- linux-2.6.7-rc3.org/net/ipv4/ipip.c 2004-06-07 21:15:21.000000000 +0200
2598 +++ linux-2.6.7-rc3/net/ipv4/ipip.c 2004-06-08 10:38:44.000000000 +0200
2599 @@ -478,6 +478,11 @@
2601 read_lock(&ipip_lock);
2602 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2603 + /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2604 + if (nf_xfrm_local_done(skb, NULL)) {
2605 + nf_rcv_postxfrm_local(skb);
2608 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2609 read_unlock(&ipip_lock);
2611 @@ -497,13 +502,7 @@
2612 skb->dev = tunnel->dev;
2613 dst_release(skb->dst);
2615 -#ifdef CONFIG_NETFILTER
2616 - nf_conntrack_put(skb->nfct);
2618 -#ifdef CONFIG_NETFILTER_DEBUG
2619 - skb->nf_debug = 0;
2623 ipip_ecn_decapsulate(iph, skb);
2625 read_unlock(&ipip_lock);
2626 @@ -648,13 +647,7 @@
2627 if ((iph->ttl = tiph->ttl) == 0)
2628 iph->ttl = old_iph->ttl;
2630 -#ifdef CONFIG_NETFILTER
2631 - nf_conntrack_put(skb->nfct);
2633 -#ifdef CONFIG_NETFILTER_DEBUG
2634 - skb->nf_debug = 0;
2640 tunnel->recursion--;
2641 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ipmr.c linux-2.6.7-rc3/net/ipv4/ipmr.c
2642 --- linux-2.6.7-rc3.org/net/ipv4/ipmr.c 2004-06-07 21:14:12.000000000 +0200
2643 +++ linux-2.6.7-rc3/net/ipv4/ipmr.c 2004-06-08 10:38:43.000000000 +0200
2644 @@ -1105,10 +1105,7 @@
2645 skb->h.ipiph = skb->nh.iph;
2647 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
2648 -#ifdef CONFIG_NETFILTER
2649 - nf_conntrack_put(skb->nfct);
2655 static inline int ipmr_forward_finish(struct sk_buff *skb)
2656 @@ -1120,7 +1117,7 @@
2657 if (unlikely(opt->optlen))
2658 ip_forward_options(skb);
2660 - return dst_output(skb);
2661 + return ip_dst_output(skb);
2665 @@ -1461,10 +1458,7 @@
2667 ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
2668 ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
2669 -#ifdef CONFIG_NETFILTER
2670 - nf_conntrack_put(skb->nfct);
2677 @@ -1520,10 +1514,7 @@
2678 ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
2679 ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
2681 -#ifdef CONFIG_NETFILTER
2682 - nf_conntrack_put(skb->nfct);
2689 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.7-rc3/net/ipv4/netfilter/Kconfig
2690 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/Kconfig 2004-06-07 21:14:56.000000000 +0200
2691 +++ linux-2.6.7-rc3/net/ipv4/netfilter/Kconfig 2004-06-08 10:42:36.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,492 @@
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_TRACE
3012 + tristate 'TRACE target support'
3013 + depends on IP_NF_RAW
3015 + The TRACE target allows packets to be traced as those
3016 + matches any subsequent rule in any table/rule. The matched
3017 + rule and the packet is logged with the prefix
3019 + TRACE: tablename/chainname/rulenum
3021 + If you want to compile it as a module, say M here and read
3022 + <file:Documentation/modules.txt>. If unsure, say `N'.
3024 +config IP_NF_TARGET_XOR
3025 + tristate 'XOR target support'
3026 + depends on IP_NF_MANGLE
3028 + This option adds a `XOR' target, which can encrypt TCP and
3029 + UDP traffic using a simple XOR encryption.
3031 + If you want to compile it as a module, say M here and read
3032 + Documentation/modules.txt. If unsure, say `N'.
3034 +config IP_NF_MATCH_ADDRTYPE
3035 + tristate 'address type match support'
3036 + depends on IP_NF_IPTABLES
3038 + This option allows you to match what routing thinks of an address,
3039 + eg. UNICAST, LOCAL, BROADCAST, ...
3041 + If you want to compile it as a module, say M here and read
3042 + Documentation/modules.txt. If unsure, say `N'.
3045 + tristate 'Eggdrop bot support'
3046 + depends on IP_NF_CONNTRACK
3048 + If you are running an eggdrop hub bot on this machine, then you
3049 + may want to enable this feature. This enables eggdrop bots to share
3050 + their user file to other eggdrop bots.
3052 + If you want to compile it as a module, say M here and read
3053 + Documentation/modules.txt. If unsure, say `N'.
3055 +config IP_NF_NAT_H323
3057 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3058 + default IP_NF_NAT if IP_NF_H323=y
3059 + default m if IP_NF_H323=m
3062 + tristate 'H.323 (netmeeting) support'
3063 + depends on IP_NF_CONNTRACK
3065 + H.323 is a standard signalling protocol used by teleconferencing
3066 + softwares like netmeeting. With the ip_conntrack_h323 and
3067 + the ip_nat_h323 modules you can support the protocol on a connection
3068 + tracking/NATing firewall.
3070 + If you want to compile it as a module, say 'M' here and read
3071 + Documentation/modules.txt. If unsure, say 'N'.
3073 +config IP_NF_NAT_MMS
3075 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3076 + default IP_NF_NAT if IP_NF_MMS=y
3077 + default m if IP_NF_MMS=m
3080 + tristate 'MMS protocol support'
3081 + depends on IP_NF_CONNTRACK
3083 + Tracking MMS (Microsoft Windows Media Services) connections
3084 + could be problematic if random ports are used to send the
3085 + streaming content. This option allows users to track streaming
3086 + connections over random UDP or TCP ports.
3088 + If you want to compile it as a module, say M here and read
3089 + <file:Documentation/modules.txt>. If unsure, say `Y'.
3091 +config IP_NF_NAT_QUAKE3
3093 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
3094 + default IP_NF_NAT if IP_NF_QUAKE3=y
3095 + default m if IP_NF_QUAKE3=m
3097 +config IP_NF_QUAKE3
3098 + tristate "Quake3 protocol support"
3099 + depends on IP_NF_CONNTRACK
3101 + Quake III Arena connection tracking helper. This module allows for a
3102 + stricter firewall rulebase if one only allows traffic to a master
3103 + server. Connections to Quake III server IP addresses and ports returned
3104 + by the master server will be tracked automatically.
3106 + If you want to compile it as a module, say M here and read
3107 + <file:Documentation/modules.txt>. If unsure, say `Y'.
3110 + tristate 'RSH protocol support'
3111 + depends on IP_NF_CONNTRACK
3113 + The RSH connection tracker is required if the dynamic
3114 + stderr "Server to Client" connection is to occur during a
3115 + normal RSH session. This typically operates as follows;
3117 + Client 0:1023 --> Server 514 (stream 1 - stdin/stdout)
3118 + Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
3120 + This connection tracker will identify new RSH sessions,
3121 + extract the outbound session details, and notify netfilter
3122 + of pending "related" sessions.
3124 + Warning: This module could be dangerous. It is not "best
3125 + practice" to use RSH, use SSH in all instances.
3126 + (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
3129 + If you want to compile it as a module, say M here and read
3130 + <file:Documentation/modules.txt>. If unsure, say `N'.
3132 +config IP_NF_NAT_RTSP
3134 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3135 + default IP_NF_NAT if IP_NF_RTSP=y
3136 + default m if IP_NF_RTSP=m
3139 + tristate ' RTSP protocol support'
3140 + depends on IP_NF_CONNTRACK
3142 + Support the RTSP protocol. This allows UDP transports to be setup
3143 + properly, including RTP and RDT.
3145 + If you want to compile it as a module, say 'M' here and read
3146 + Documentation/modules.txt. If unsure, say 'Y'.
3148 +config IP_NF_CT_PROTO_SCTP
3149 + tristate 'SCTP protocol connection tracking support'
3150 + depends on IP_NF_CONNTRACK
3152 +config IP_NF_MATCH_STRING
3153 + tristate 'String match support'
3154 + depends on IP_NF_IPTABLES
3156 + String matching alows you to match packets which contain a
3157 + specified string of characters.
3159 + If you want to compile it as a module, say M here and read
3160 + Documentation/modules.txt. If unsure, say `N'.
3162 +config IP_NF_NAT_TALK
3164 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3165 + default IP_NF_NAT if IP_NF_TALK=y
3166 + default m if IP_NF_TALK=m
3169 + tristate 'talk protocol support'
3170 + depends on IP_NF_CONNTRACK
3172 + The talk protocols (both otalk/talk - or talk/ntalk, to confuse
3173 + you by the different namings about which is old or which is new :-)
3174 + use an additional channel to setup the talk session and a separated
3175 + data channel for the actual conversation (like in FTP). Both the
3176 + initiating and the setup channels are over UDP, while the data channel
3177 + is over TCP, on a random port. The conntrack part of this extension
3178 + will enable you to let in/out talk sessions easily by matching these
3179 + connections as RELATED by the state match, while the NAT part helps
3180 + you to let talk sessions trough a NAT machine.
3182 + If you want to compile it as a module, say 'M' here and read
3183 + Documentation/modules.txt. If unsure, say 'N'.
3185 +config IP_NF_MATCH_POLICY
3186 + tristate "IPsec policy match support"
3187 + depends on IP_NF_IPTABLES && XFRM
3189 + Policy matching allows you to match packets based on the
3190 + IPsec policy that was used during decapsulation/will
3191 + be used during encapsulation.
3193 + To compile it as a module, choose M here. If unsure, say N.
3197 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.7-rc3/net/ipv4/netfilter/Makefile
3198 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/Makefile 2004-06-07 21:14:01.000000000 +0200
3199 +++ linux-2.6.7-rc3/net/ipv4/netfilter/Makefile 2004-06-08 10:42:36.000000000 +0200
3201 # connection tracking
3202 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
3204 +# talk protocol support
3205 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
3206 +ifdef CONFIG_IP_NF_TALK
3207 + export-objs += ip_conntrack_talk.o
3209 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
3212 +# SCTP protocol connection tracking
3213 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
3216 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
3217 +ifdef CONFIG_IP_NF_H323
3218 + export-objs += ip_conntrack_h323.o
3220 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
3223 # connection tracking helpers
3225 +# rtsp protocol support
3226 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
3227 +ifdef CONFIG_IP_NF_NAT_RTSP
3228 + export-objs += ip_conntrack_rtsp.o
3230 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
3232 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
3233 +ifdef CONFIG_IP_NF_NAT_QUAKE3
3234 + export-objs += ip_conntrack_quake3.o
3236 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
3237 +ifdef CONFIG_IP_NF_MMS
3238 + export-objs += ip_conntrack_mms.o
3240 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
3241 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
3242 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
3243 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
3245 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
3247 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
3251 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
3252 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
3253 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
3254 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
3255 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
3258 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
3261 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
3262 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
3263 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
3264 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
3265 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
3266 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
3267 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
3268 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
3269 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
3271 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
3272 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
3274 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
3276 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
3277 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
3279 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
3282 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
3284 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
3286 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
3289 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
3291 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
3294 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
3296 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
3298 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
3299 @@ -60,28 +125,47 @@
3301 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
3303 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
3306 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
3307 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
3308 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
3309 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
3310 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
3311 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
3312 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
3313 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
3314 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
3315 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
3317 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
3318 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
3321 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
3322 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
3323 obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
3324 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
3325 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
3326 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
3327 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
3328 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
3329 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
3330 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
3331 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
3332 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
3333 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
3334 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
3335 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
3336 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
3337 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
3338 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
3339 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
3340 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
3341 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
3342 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
3343 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
3344 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
3346 # generic ARP tables
3347 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_core.c
3348 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-07 21:13:34.000000000 +0200
3349 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-08 10:36:58.000000000 +0200
3351 static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
3352 struct list_head *ip_conntrack_hash;
3353 static kmem_cache_t *ip_conntrack_cachep;
3354 +static kmem_cache_t *ip_conntrack_expect_cachep;
3355 struct ip_conntrack ip_conntrack_untracked;
3357 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
3359 IP_NF_ASSERT(atomic_read(&exp->use));
3360 IP_NF_ASSERT(!timer_pending(&exp->timeout));
3363 + kmem_cache_free(ip_conntrack_expect_cachep, exp);
3368 ip_conntrack_destroyed(ct);
3370 WRITE_LOCK(&ip_conntrack_lock);
3371 - /* Delete us from our own list to prevent corruption later */
3372 - list_del(&ct->sibling_list);
3373 + /* Make sure don't leave any orphaned expectations lying around */
3374 + if (ct->expecting)
3375 + remove_expectations(ct, 1);
3377 /* Delete our master expectation */
3380 list_del(&ct->master->expected_list);
3381 master = ct->master->expectant;
3383 - kfree(ct->master);
3384 + kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
3386 WRITE_UNLOCK(&ip_conntrack_lock);
3388 @@ -692,25 +694,22 @@
3389 struct ip_conntrack_expect *, tuple);
3390 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3392 - /* If master is not in hash table yet (ie. packet hasn't left
3393 - this machine yet), how can other end know about expected?
3394 - Hence these are not the droids you are looking for (if
3395 - master ct never got confirmed, we'd hold a reference to it
3396 - and weird things would happen to future packets). */
3397 - if (expected && !is_confirmed(expected->expectant))
3400 - /* Look up the conntrack helper for master connections only */
3402 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
3404 + /* If master is not in hash table yet (ie. packet hasn't left
3405 + this machine yet), how can other end know about expected?
3406 + Hence these are not the droids you are looking for (if
3407 + master ct never got confirmed, we'd hold a reference to it
3408 + and weird things would happen to future packets). */
3409 + if (!is_confirmed(expected->expectant)) {
3410 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3414 - /* If the expectation is dying, then this is a loser. */
3416 - && expected->expectant->helper->timeout
3417 - && ! del_timer(&expected->timeout))
3419 + /* Expectation is dying... */
3420 + if (expected->expectant->helper->timeout
3421 + && !del_timer(&expected->timeout))
3425 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3426 conntrack, expected);
3427 /* Welcome, Mr. Bond. We've been expecting you... */
3428 @@ -718,16 +717,28 @@
3429 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3430 conntrack->master = expected;
3431 expected->sibling = conntrack;
3432 +#if CONFIG_IP_NF_CONNTRACK_MARK
3433 + conntrack->mark = expected->expectant->mark;
3435 LIST_DELETE(&ip_conntrack_expect_list, expected);
3436 expected->expectant->expecting--;
3437 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3439 - atomic_inc(&ip_conntrack_count);
3441 + /* this is a braindead... --pablo */
3442 + atomic_inc(&ip_conntrack_count);
3443 + WRITE_UNLOCK(&ip_conntrack_lock);
3445 + if (expected->expectfn)
3446 + expected->expectfn(conntrack);
3450 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3452 +end: atomic_inc(&ip_conntrack_count);
3453 WRITE_UNLOCK(&ip_conntrack_lock);
3455 - if (expected && expected->expectfn)
3456 - expected->expectfn(conntrack);
3457 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3458 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3461 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3463 ip_conntrack_expect_alloc(void)
3465 struct ip_conntrack_expect *new;
3467 - new = (struct ip_conntrack_expect *)
3468 - kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
3470 + new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
3472 DEBUGP("expect_related: OOM allocating expect\n");
3476 /* tuple_cmp compares whole union, we have to initialized cleanly */
3477 memset(new, 0, sizeof(struct ip_conntrack_expect));
3478 + atomic_set(&new->use, 1);
3482 @@ -944,12 +955,10 @@
3483 DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
3484 new->expectant = related_to;
3485 new->sibling = NULL;
3486 - atomic_set(&new->use, 1);
3488 /* add to expected list for this connection */
3489 - list_add(&new->expected_list, &related_to->sibling_list);
3490 + list_add_tail(&new->expected_list, &related_to->sibling_list);
3491 /* add to global list of expectations */
3493 list_prepend(&ip_conntrack_expect_list, &new->list);
3494 /* add and start timer if required */
3495 if (related_to->helper->timeout) {
3496 @@ -998,12 +1007,12 @@
3499 WRITE_UNLOCK(&ip_conntrack_lock);
3501 + /* This expectation is not inserted so no need to lock */
3502 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
3505 } else if (related_to->helper->max_expected &&
3506 related_to->expecting >= related_to->helper->max_expected) {
3507 - struct list_head *cur_item;
3509 if (!(related_to->helper->flags &
3510 IP_CT_HELPER_F_REUSE_EXPECT)) {
3511 @@ -1017,7 +1026,7 @@
3512 related_to->helper->name,
3513 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
3514 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3516 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
3519 DEBUGP("ip_conntrack: max number of expected "
3520 @@ -1029,21 +1038,14 @@
3521 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3523 /* choose the the oldest expectation to evict */
3524 - list_for_each(cur_item, &related_to->sibling_list) {
3525 - struct ip_conntrack_expect *cur;
3527 - cur = list_entry(cur_item,
3528 - struct ip_conntrack_expect,
3530 - if (cur->sibling == NULL) {
3532 + list_for_each_entry(old, &related_to->sibling_list,
3534 + if (old->sibling == NULL)
3539 - /* (!old) cannot happen, since related_to->expecting is the
3540 - * number of unconfirmed expects */
3541 - IP_NF_ASSERT(old);
3542 + /* We cannot fail since related_to->expecting is the number
3543 + * of unconfirmed expectations */
3544 + IP_NF_ASSERT(old && old->sibling == NULL);
3546 /* newnat14 does not reuse the real allocated memory
3547 * structures but rather unexpects the old and
3548 @@ -1058,7 +1060,7 @@
3549 WRITE_UNLOCK(&ip_conntrack_lock);
3550 DEBUGP("expect_related: busy!\n");
3553 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
3557 @@ -1127,10 +1129,8 @@
3558 DUMP_TUPLE(newreply);
3560 conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
3561 - if (!conntrack->master)
3562 - conntrack->helper = LIST_FIND(&helpers, helper_cmp,
3563 - struct ip_conntrack_helper *,
3565 + if (!conntrack->master && list_empty(&conntrack->sibling_list))
3566 + conntrack->helper = ip_ct_find_helper(newreply);
3567 WRITE_UNLOCK(&ip_conntrack_lock);
3570 @@ -1379,6 +1379,7 @@
3573 kmem_cache_destroy(ip_conntrack_cachep);
3574 + kmem_cache_destroy(ip_conntrack_expect_cachep);
3575 vfree(ip_conntrack_hash);
3576 nf_unregister_sockopt(&so_getorigdst);
3578 @@ -1431,6 +1432,15 @@
3579 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
3583 + ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
3584 + sizeof(struct ip_conntrack_expect),
3585 + 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
3586 + if (!ip_conntrack_expect_cachep) {
3587 + printk(KERN_ERR "Unable to create ip_expect slab cache\n");
3588 + goto err_free_conntrack_slab;
3591 /* Don't NEED lock here, but good form anyway. */
3592 WRITE_LOCK(&ip_conntrack_lock);
3593 /* Sew in builtin protocols. */
3594 @@ -1458,6 +1468,8 @@
3598 +err_free_conntrack_slab:
3599 + kmem_cache_destroy(ip_conntrack_cachep);
3601 vfree(ip_conntrack_hash);
3603 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
3604 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3605 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-06-08 10:38:25.000000000 +0200
3607 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3608 + * based on ip_conntrack_irc.c
3610 + * This module only supports the share userfile-send command,
3611 + * used by eggdrops to share it's userfile.
3613 + * There are no support for NAT at the moment.
3615 + * This program is free software; you can redistribute it and/or
3616 + * modify it under the terms of the GNU General Public License
3617 + * as published by the Free Software Foundation; either version
3618 + * 2 of the License, or (at your option) any later version.
3620 + * Module load syntax:
3622 + * please give the ports of all Eggdrops You have running
3623 + * on your system, the default port is 3333.
3625 + * 2001-04-19: Security update. IP addresses are now compared
3626 + * to prevent unauthorized "related" access.
3628 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3629 + * Port to netfilter 'newnat' API.
3632 +#include <linux/module.h>
3633 +#include <linux/netfilter.h>
3634 +#include <linux/ip.h>
3635 +#include <net/checksum.h>
3636 +#include <net/tcp.h>
3638 +#include <linux/netfilter_ipv4/lockhelp.h>
3639 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3641 +#define MAX_PORTS 8
3642 +static int ports[MAX_PORTS];
3643 +static int ports_c = 0;
3644 +static unsigned int egg_timeout = 300;
3646 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3647 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3648 +MODULE_LICENSE("GPL");
3650 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3651 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3654 +DECLARE_LOCK(ip_egg_lock);
3655 +struct module *ip_conntrack_egg = THIS_MODULE;
3658 +#define DEBUGP printk
3660 +#define DEBUGP(format, args...)
3663 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3664 +/* tries to get the ip_addr and port out of a eggdrop command
3665 + return value: -1 on failure, 0 on success
3666 + data pointer to first byte of DCC command data
3667 + data_end pointer to last byte of dcc command data
3668 + ip returns parsed ip of dcc command
3669 + port returns parsed port of dcc command */
3671 + if (data > data_end)
3674 + *ip = simple_strtoul(data, &data, 10);
3676 + /* skip blanks between ip and port */
3677 + while (*data == ' ' && data < data_end)
3680 + *port = simple_strtoul(data, &data, 10);
3685 +static int help(const struct iphdr *iph, size_t len,
3686 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3688 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3689 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3690 + char *data = (char *) tcph + tcph->doff * 4;
3692 + u_int32_t tcplen = len - iph->ihl * 4;
3693 + u_int32_t datalen = tcplen - tcph->doff * 4;
3694 + int dir = CTINFO2DIR(ctinfo);
3695 + int bytes_scanned = 0;
3696 + struct ip_conntrack_expect exp;
3699 + u_int16_t egg_port;
3701 + DEBUGP("entered\n");
3703 + /* If packet is coming from IRC server */
3704 + if (dir != IP_CT_DIR_REPLY)
3707 + /* Until there's been traffic both ways, don't look in packets. */
3708 + if (ctinfo != IP_CT_ESTABLISHED
3709 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3710 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
3714 + /* Not whole TCP header? */
3715 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3716 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3720 + /* Checksum invalid? Ignore. */
3721 + /* FIXME: Source route IP option packets --RR */
3722 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3723 + csum_partial((char *) tcph, tcplen, 0))) {
3724 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3725 + tcph, tcplen, NIPQUAD(iph->saddr),
3726 + NIPQUAD(iph->daddr));
3730 + data_limit = (char *) data + datalen;
3731 + while (datalen > 5 && bytes_scanned < 128) {
3732 + if (memcmp(data, "s us ", 5)) {
3741 + DEBUGP("Userfile-share found in connection "
3742 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3743 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3745 + if (parse_command((char *) data, data_limit, &egg_ip,
3747 + DEBUGP("no data in userfile-share pkt\n");
3751 + memset(&exp, 0, sizeof(exp));
3753 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3754 + if (net_ratelimit())
3755 + printk("Forged Eggdrop command from "
3756 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3757 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3758 + HIPQUAD(egg_ip), egg_port);
3762 + exp.tuple.src.ip = iph->daddr;
3763 + exp.tuple.src.u.tcp.port = 0;
3764 + exp.tuple.dst.ip = htonl(egg_ip);
3765 + exp.tuple.dst.u.tcp.port = htons(egg_port);
3766 + exp.tuple.dst.protonum = IPPROTO_TCP;
3768 + exp.mask.dst.u.tcp.port = 0xffff;
3769 + exp.mask.dst.protonum = 0xffff;
3771 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3772 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3773 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3775 + ip_conntrack_expect_related(ct, &exp);
3781 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3782 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3784 +static void deregister_helpers(void) {
3787 + for (i = 0; i < ports_c; i++) {
3788 + DEBUGP("unregistering helper for port %d\n", ports[i]);
3789 + ip_conntrack_helper_unregister(&egg_helpers[i]);
3793 +static int __init init(void)
3798 + /* If no port given, default to standard eggdrop port */
3799 + if (ports[0] == 0)
3802 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3803 + memset(&egg_helpers[i], 0,
3804 + sizeof(struct ip_conntrack_helper));
3805 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3806 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3807 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3808 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
3809 + egg_helpers[i].max_expected = 1;
3810 + egg_helpers[i].timeout = egg_timeout;
3811 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3812 + egg_helpers[i].me = THIS_MODULE;
3813 + egg_helpers[i].help = help;
3815 + tmpname = &egg_names[i][0];
3816 + if (ports[i] == 3333)
3817 + sprintf(tmpname, "eggdrop");
3819 + sprintf(tmpname, "eggdrop-%d", ports[i]);
3820 + egg_helpers[i].name = tmpname;
3822 + DEBUGP("port #%d: %d\n", i, ports[i]);
3824 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
3827 + printk("ip_conntrack_egg: ERROR registering helper "
3828 + "for port %d\n", ports[i]);
3829 + deregister_helpers();
3837 +static void __exit fini(void)
3839 + deregister_helpers();
3844 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
3845 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3846 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-06-08 10:38:40.000000000 +0200
3849 + * H.323 'brute force' extension for H.323 connection tracking.
3850 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3852 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3853 + * (http://www.coritel.it/projects/sofia/nat/)
3854 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3855 + * the unregistered helpers to the conntrack entries.
3859 +#include <linux/module.h>
3860 +#include <linux/netfilter.h>
3861 +#include <linux/ip.h>
3862 +#include <net/checksum.h>
3863 +#include <net/tcp.h>
3865 +#include <linux/netfilter_ipv4/lockhelp.h>
3866 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3867 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3868 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3869 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3870 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3872 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3873 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3874 +MODULE_LICENSE("GPL");
3876 +DECLARE_LOCK(ip_h323_lock);
3877 +struct module *ip_conntrack_h323 = THIS_MODULE;
3880 +#define DEBUGP printk
3882 +#define DEBUGP(format, args...)
3885 +/* FIXME: This should be in userspace. Later. */
3886 +static int h245_help(const struct iphdr *iph, size_t len,
3887 + struct ip_conntrack *ct,
3888 + enum ip_conntrack_info ctinfo)
3890 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3891 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3892 + unsigned char *data_limit;
3893 + u_int32_t tcplen = len - iph->ihl * 4;
3894 + u_int32_t datalen = tcplen - tcph->doff * 4;
3895 + int dir = CTINFO2DIR(ctinfo);
3896 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3897 + struct ip_conntrack_expect expect, *exp = &expect;
3898 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3899 + u_int16_t data_port;
3900 + u_int32_t data_ip;
3903 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3904 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3905 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3907 + /* Can't track connections formed before we registered */
3911 + /* Until there's been traffic both ways, don't look in packets. */
3912 + if (ctinfo != IP_CT_ESTABLISHED
3913 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3914 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3918 + /* Not whole TCP header or too short packet? */
3919 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3920 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3924 + /* Checksum invalid? Ignore. */
3925 + /* FIXME: Source route IP option packets --RR */
3926 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3927 + csum_partial((char *)tcph, tcplen, 0))) {
3928 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3929 + tcph, tcplen, NIPQUAD(iph->saddr),
3930 + NIPQUAD(iph->daddr));
3934 + data_limit = (unsigned char *) data + datalen;
3937 + for (i = 0; data < (data_limit - 5); data++, i++) {
3938 + data_ip = *((u_int32_t *)data);
3939 + if (data_ip == iph->saddr) {
3940 + data_port = *((u_int16_t *)(data + 4));
3941 + memset(&expect, 0, sizeof(expect));
3942 + /* update the H.225 info */
3943 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3944 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3945 + NIPQUAD(iph->saddr), ntohs(data_port));
3946 + LOCK_BH(&ip_h323_lock);
3947 + info->is_h225 = H225_PORT + 1;
3948 + exp_info->port = data_port;
3949 + exp_info->dir = dir;
3950 + exp_info->offset = i;
3952 + exp->seq = ntohl(tcph->seq) + i;
3954 + exp->tuple = ((struct ip_conntrack_tuple)
3955 + { { ct->tuplehash[!dir].tuple.src.ip,
3958 + { .tcp = { data_port } },
3960 + exp->mask = ((struct ip_conntrack_tuple)
3961 + { { 0xFFFFFFFF, { 0 } },
3962 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3964 + exp->expectfn = NULL;
3966 + /* Ignore failure; should only happen with NAT */
3967 + ip_conntrack_expect_related(ct, exp);
3969 + UNLOCK_BH(&ip_h323_lock);
3977 +/* H.245 helper is not registered! */
3978 +static struct ip_conntrack_helper h245 =
3980 + "H.245", /* name */
3981 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3982 + NULL, /* module */
3983 + 8, /* max_ expected */
3984 + 240, /* timeout */
3985 + { { 0, { 0 } }, /* tuple */
3986 + { 0, { 0 }, IPPROTO_TCP } },
3987 + { { 0, { 0xFFFF } }, /* mask */
3988 + { 0, { 0 }, 0xFFFF } },
3989 + h245_help /* helper */
3992 +static int h225_expect(struct ip_conntrack *ct)
3994 + WRITE_LOCK(&ip_conntrack_lock);
3995 + ct->helper = &h245;
3996 + DEBUGP("h225_expect: helper for %p added\n", ct);
3997 + WRITE_UNLOCK(&ip_conntrack_lock);
3999 + return NF_ACCEPT; /* unused */
4002 +/* FIXME: This should be in userspace. Later. */
4003 +static int h225_help(const struct iphdr *iph, size_t len,
4004 + struct ip_conntrack *ct,
4005 + enum ip_conntrack_info ctinfo)
4007 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4008 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
4009 + unsigned char *data_limit;
4010 + u_int32_t tcplen = len - iph->ihl * 4;
4011 + u_int32_t datalen = tcplen - tcph->doff * 4;
4012 + int dir = CTINFO2DIR(ctinfo);
4013 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
4014 + struct ip_conntrack_expect expect, *exp = &expect;
4015 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
4016 + u_int16_t data_port;
4017 + u_int32_t data_ip;
4020 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4021 + NIPQUAD(iph->saddr), ntohs(tcph->source),
4022 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
4024 + /* Can't track connections formed before we registered */
4028 + /* Until there's been traffic both ways, don't look in packets. */
4029 + if (ctinfo != IP_CT_ESTABLISHED
4030 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4031 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
4035 + /* Not whole TCP header or too short packet? */
4036 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
4037 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
4041 + /* Checksum invalid? Ignore. */
4042 + /* FIXME: Source route IP option packets --RR */
4043 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4044 + csum_partial((char *)tcph, tcplen, 0))) {
4045 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4046 + tcph, tcplen, NIPQUAD(iph->saddr),
4047 + NIPQUAD(iph->daddr));
4051 + data_limit = (unsigned char *) data + datalen;
4054 + for (i = 0; data < (data_limit - 5); data++, i++) {
4055 + data_ip = *((u_int32_t *)data);
4056 + if (data_ip == iph->saddr) {
4057 + data_port = *((u_int16_t *)(data + 4));
4058 + if (data_port == tcph->source) {
4059 + /* Signal address */
4060 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
4061 + NIPQUAD(iph->saddr));
4062 + /* Update the H.225 info so that NAT can mangle the address/port
4063 + even when we have no expected connection! */
4064 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4065 + LOCK_BH(&ip_h323_lock);
4067 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
4068 + info->offset[IP_CT_DIR_ORIGINAL] = i;
4069 + UNLOCK_BH(&ip_h323_lock);
4072 + memset(&expect, 0, sizeof(expect));
4074 + /* update the H.225 info */
4075 + LOCK_BH(&ip_h323_lock);
4076 + info->is_h225 = H225_PORT;
4077 + exp_info->port = data_port;
4078 + exp_info->dir = dir;
4079 + exp_info->offset = i;
4081 + exp->seq = ntohl(tcph->seq) + i;
4083 + exp->tuple = ((struct ip_conntrack_tuple)
4084 + { { ct->tuplehash[!dir].tuple.src.ip,
4087 + { .tcp = { data_port } },
4089 + exp->mask = ((struct ip_conntrack_tuple)
4090 + { { 0xFFFFFFFF, { 0 } },
4091 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4093 + exp->expectfn = h225_expect;
4095 + /* Ignore failure */
4096 + ip_conntrack_expect_related(ct, exp);
4098 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
4099 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4100 + NIPQUAD(iph->saddr), ntohs(data_port));
4102 + UNLOCK_BH(&ip_h323_lock);
4104 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4105 + } else if (data_ip == iph->daddr) {
4106 + data_port = *((u_int16_t *)(data + 4));
4107 + if (data_port == tcph->dest) {
4108 + /* Signal address */
4109 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
4110 + NIPQUAD(iph->daddr));
4111 + /* Update the H.225 info so that NAT can mangle the address/port
4112 + even when we have no expected connection! */
4113 + LOCK_BH(&ip_h323_lock);
4115 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
4116 + info->offset[IP_CT_DIR_REPLY] = i;
4117 + UNLOCK_BH(&ip_h323_lock);
4127 +static struct ip_conntrack_helper h225 =
4129 + "H.225", /* name */
4130 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
4131 + THIS_MODULE, /* module */
4132 + 2, /* max_expected */
4133 + 240, /* timeout */
4134 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
4135 + { 0, { 0 }, IPPROTO_TCP } },
4136 + { { 0, { 0xFFFF } }, /* mask */
4137 + { 0, { 0 }, 0xFFFF } },
4138 + h225_help /* helper */
4141 +static int __init init(void)
4143 + return ip_conntrack_helper_register(&h225);
4146 +static void __exit fini(void)
4148 + /* Unregister H.225 helper */
4149 + ip_conntrack_helper_unregister(&h225);
4152 +EXPORT_SYMBOL(ip_h323_lock);
4156 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
4157 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
4158 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-06-08 10:39:44.000000000 +0200
4160 +/* MMS extension for IP connection tracking
4161 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4162 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
4164 + * ip_conntrack_mms.c v0.3 2002-09-22
4166 + * This program is free software; you can redistribute it and/or
4167 + * modify it under the terms of the GNU General Public License
4168 + * as published by the Free Software Foundation; either version
4169 + * 2 of the License, or (at your option) any later version.
4171 + * Module load syntax:
4172 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
4174 + * Please give the ports of all MMS servers You wish to connect to.
4175 + * If you don't specify ports, the default will be TCP port 1755.
4177 + * More info on MMS protocol, firewalls and NAT:
4178 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
4179 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
4181 + * The SDP project people are reverse-engineering MMS:
4182 + * http://get.to/sdp
4185 +#include <linux/config.h>
4186 +#include <linux/module.h>
4187 +#include <linux/netfilter.h>
4188 +#include <linux/ip.h>
4189 +#include <linux/ctype.h>
4190 +#include <net/checksum.h>
4191 +#include <net/tcp.h>
4193 +#include <linux/netfilter_ipv4/lockhelp.h>
4194 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4195 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
4197 +DECLARE_LOCK(ip_mms_lock);
4198 +struct module *ip_conntrack_mms = THIS_MODULE;
4200 +#define MAX_PORTS 8
4201 +static int ports[MAX_PORTS];
4202 +static int ports_c;
4204 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4208 +#define DEBUGP printk
4210 +#define DEBUGP(format, args...)
4213 +EXPORT_SYMBOL(ip_mms_lock);
4215 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4216 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
4217 +MODULE_LICENSE("GPL");
4219 +/* #define isdigit(c) (c >= '0' && c <= '9') */
4221 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
4222 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
4225 + for (i = 0; i < unicode_size; ++i) {
4226 + string[i] = (char)(unicode[i]);
4228 + string[unicode_size] = 0x00;
4231 +__inline static int atoi(char *s)
4234 + while (isdigit(*s)) {
4235 + i = i*10 + *(s++) - '0';
4240 +/* convert ip address string like "192.168.0.10" to unsigned int */
4241 +__inline static u_int32_t asciiiptoi(char *s)
4243 + unsigned int i, j, k;
4245 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
4247 + for(j=0; (*(++s) != '.') && (j<3); ++j)
4254 +int parse_mms(const char *data,
4255 + const unsigned int datalen,
4256 + u_int32_t *mms_ip,
4257 + u_int16_t *mms_proto,
4258 + u_int16_t *mms_port,
4259 + char **mms_string_b,
4260 + char **mms_string_e,
4261 + char **mms_padding_e)
4263 + int unicode_size, i;
4264 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
4265 + char getlengthstring[28];
4267 + for(unicode_size=0;
4268 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
4270 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
4271 + return -1; /* out of bounds - incomplete packet */
4273 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
4274 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
4276 + /* IP address ? */
4277 + *mms_ip = asciiiptoi(tempstring+2);
4279 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
4282 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
4283 + *mms_proto = IPPROTO_TCP;
4284 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
4285 + *mms_proto = IPPROTO_UDP;
4288 + *mms_port = atoi(tempstring+7+i);
4290 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
4291 + unicode string, one to the end of the string, and one to the end
4292 + of the packet, since we must keep track of the number of bytes
4293 + between end of the unicode string and the end of packet (padding) */
4294 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
4295 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
4296 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
4301 +/* FIXME: This should be in userspace. Later. */
4302 +static int help(const struct iphdr *iph, size_t len,
4303 + struct ip_conntrack *ct,
4304 + enum ip_conntrack_info ctinfo)
4306 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
4307 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4308 + const char *data = (const char *)tcph + tcph->doff * 4;
4309 + unsigned int tcplen = len - iph->ihl * 4;
4310 + unsigned int datalen = tcplen - tcph->doff * 4;
4311 + int dir = CTINFO2DIR(ctinfo);
4312 + struct ip_conntrack_expect expect, *exp = &expect;
4313 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
4316 + u_int16_t mms_proto;
4317 + char mms_proto_string[8];
4318 + u_int16_t mms_port;
4319 + char *mms_string_b, *mms_string_e, *mms_padding_e;
4321 + /* Until there's been traffic both ways, don't look in packets. */
4322 + if (ctinfo != IP_CT_ESTABLISHED
4323 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4324 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
4328 + /* Not whole TCP header? */
4329 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
4330 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
4334 + /* Checksum invalid? Ignore. */
4335 + /* FIXME: Source route IP option packets --RR */
4336 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4337 + csum_partial((char *)tcph, tcplen, 0))) {
4338 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4339 + tcph, tcplen, NIPQUAD(iph->saddr),
4340 + NIPQUAD(iph->daddr));
4344 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
4345 + /* FIXME: There is an issue with only looking at this packet: before this packet,
4346 + the client has already sent a packet to the server with the server's hostname
4347 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
4348 + server will break the connection if this doesn't correspond to its own host
4349 + header. The client can also connect to an IP address; if it's the server's IP
4350 + address, it will not break the connection. When doing DNAT on a connection
4351 + where the client uses a server's IP address, the nat module should detect
4352 + this and change this string accordingly to the DNATed address. This should
4353 + probably be done by checking for an IP address, then storing it as a member
4354 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
4356 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
4357 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
4358 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
4359 + (u8)*(data+36), (u8)*(data+37),
4360 + (u8)*(data+38), (u8)*(data+39),
4362 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
4363 + &mms_string_b, &mms_string_e, &mms_padding_e))
4364 + if(net_ratelimit())
4365 + /* FIXME: more verbose debugging ? */
4366 + printk(KERN_WARNING
4367 + "ip_conntrack_mms: Unable to parse data payload\n");
4369 + memset(&expect, 0, sizeof(expect));
4371 + sprintf(mms_proto_string, "(%u)", mms_proto);
4372 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
4373 + mms_proto == IPPROTO_TCP ? "TCP"
4374 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
4375 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4379 + /* it's possible that the client will just ask the server to tunnel
4380 + the stream over the same TCP session (from port 1755): there's
4381 + shouldn't be a need to add an expectation in that case, but it
4382 + makes NAT packet mangling so much easier */
4383 + LOCK_BH(&ip_mms_lock);
4385 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
4387 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
4388 + exp_mms_info->len = (mms_string_e - mms_string_b);
4389 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
4390 + exp_mms_info->port = mms_port;
4392 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
4393 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
4395 + exp->tuple = ((struct ip_conntrack_tuple)
4396 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4398 + { .tcp = { (__u16) ntohs(mms_port) } },
4401 + exp->mask = ((struct ip_conntrack_tuple)
4402 + { { 0xFFFFFFFF, { 0 } },
4403 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4404 + exp->expectfn = NULL;
4405 + ip_conntrack_expect_related(ct, &expect);
4406 + UNLOCK_BH(&ip_mms_lock);
4412 +static struct ip_conntrack_helper mms[MAX_PORTS];
4413 +static char mms_names[MAX_PORTS][10];
4415 +/* Not __exit: called from init() */
4416 +static void fini(void)
4419 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4420 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
4422 + ip_conntrack_helper_unregister(&mms[i]);
4426 +static int __init init(void)
4431 + if (ports[0] == 0)
4432 + ports[0] = MMS_PORT;
4434 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4435 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
4436 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
4437 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
4438 + mms[i].mask.src.u.tcp.port = 0xFFFF;
4439 + mms[i].mask.dst.protonum = 0xFFFF;
4440 + mms[i].max_expected = 1;
4441 + mms[i].timeout = 0;
4442 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4443 + mms[i].me = THIS_MODULE;
4444 + mms[i].help = help;
4446 + tmpname = &mms_names[i][0];
4447 + if (ports[i] == MMS_PORT)
4448 + sprintf(tmpname, "mms");
4450 + sprintf(tmpname, "mms-%d", ports[i]);
4451 + mms[i].name = tmpname;
4453 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
4455 + ret = ip_conntrack_helper_register(&mms[i]);
4468 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
4469 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
4470 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-06-08 10:40:55.000000000 +0200
4473 + * Connection tracking protocol helper module for SCTP.
4475 + * SCTP is defined in RFC 2960. References to various sections in this code
4476 + * are to this RFC.
4478 + * This program is free software; you can redistribute it and/or modify
4479 + * it under the terms of the GNU General Public License version 2 as
4480 + * published by the Free Software Foundation.
4483 +#include <linux/types.h>
4484 +#include <linux/sched.h>
4485 +#include <linux/timer.h>
4486 +#include <linux/netfilter.h>
4487 +#include <linux/module.h>
4488 +#include <linux/in.h>
4489 +#include <linux/ip.h>
4490 +#include <linux/sctp.h>
4491 +#include <linux/string.h>
4493 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4494 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4495 +#include <linux/netfilter_ipv4/lockhelp.h>
4498 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4500 +#define DEBUGP(format, args...)
4503 +/* Protects conntrack->proto.sctp */
4504 +static DECLARE_RWLOCK(sctp_lock);
4506 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4507 + closely. They're more complex. --RR
4509 + And so for me for SCTP :D -Kiran */
4511 +static const char *sctp_conntrack_names[] = {
4519 + "SHUTDOWN_ACK_SENT",
4523 +#define MINS * 60 SECS
4524 +#define HOURS * 60 MINS
4525 +#define DAYS * 24 HOURS
4527 +unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
4528 +unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
4529 +unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
4530 +unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
4531 +unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
4532 +unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
4533 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
4535 +static unsigned long * sctp_timeouts[]
4536 += { 0, /* SCTP_CONNTRACK_NONE */
4537 + &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
4538 + &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
4539 + &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
4540 + &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
4541 + &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4542 + &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4543 + &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4546 +#define sNO SCTP_CONNTRACK_NONE
4547 +#define sCL SCTP_CONNTRACK_CLOSED
4548 +#define sCW SCTP_CONNTRACK_COOKIE_WAIT
4549 +#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
4550 +#define sES SCTP_CONNTRACK_ESTABLISHED
4551 +#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4552 +#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4553 +#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4554 +#define sIV SCTP_CONNTRACK_MAX
4557 + These are the descriptions of the states:
4559 +NOTE: These state names are tantalizingly similar to the states of an
4560 +SCTP endpoint. But the interpretation of the states is a little different,
4561 +considering that these are the states of the connection and not of an end
4562 +point. Please note the subtleties. -Kiran
4564 +NONE - Nothing so far.
4565 +COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
4566 + an INIT_ACK chunk in the reply direction.
4567 +COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
4568 +ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
4569 +SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
4570 +SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
4571 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4572 + to that of the SHUTDOWN chunk.
4573 +CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
4574 + the SHUTDOWN chunk. Connection is closed.
4578 + - I have assumed that the first INIT is in the original direction.
4579 + This messes things when an INIT comes in the reply direction in CLOSED
4581 + - Check the error type in the reply dir before transitioning from
4582 +cookie echoed to closed.
4583 + - Sec 5.2.4 of RFC 2960
4584 + - Multi Homing support.
4587 +/* SCTP conntrack state transitions */
4588 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4591 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4592 +/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4593 +/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4594 +/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4595 +/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4596 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4597 +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4598 +/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4599 +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4600 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4604 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4605 +/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4606 +/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4607 +/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4608 +/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4609 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4610 +/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4611 +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4612 +/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4613 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4617 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4618 + unsigned int dataoff,
4619 + struct ip_conntrack_tuple *tuple)
4621 + sctp_sctphdr_t hdr;
4623 + DEBUGP(__FUNCTION__);
4626 + /* Actually only need first 8 bytes. */
4627 + if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4630 + tuple->src.u.sctp.port = hdr.source;
4631 + tuple->dst.u.sctp.port = hdr.dest;
4636 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4637 + const struct ip_conntrack_tuple *orig)
4639 + DEBUGP(__FUNCTION__);
4642 + tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4643 + tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4647 +/* Print out the per-protocol part of the tuple. */
4648 +static unsigned int sctp_print_tuple(char *buffer,
4649 + const struct ip_conntrack_tuple *tuple)
4651 + DEBUGP(__FUNCTION__);
4654 + return sprintf(buffer, "sport=%hu dport=%hu ",
4655 + ntohs(tuple->src.u.sctp.port),
4656 + ntohs(tuple->dst.u.sctp.port));
4659 +/* Print out the private part of the conntrack. */
4660 +static unsigned int sctp_print_conntrack(char *buffer,
4661 + const struct ip_conntrack *conntrack)
4663 + enum sctp_conntrack state;
4665 + DEBUGP(__FUNCTION__);
4668 + READ_LOCK(&sctp_lock);
4669 + state = conntrack->proto.sctp.state;
4670 + READ_UNLOCK(&sctp_lock);
4672 + return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4675 +#define for_each_sctp_chunk(skb, sch, offset, count) \
4676 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
4677 + offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
4678 + offset += (htons(sch.length) + 3) & ~3, count++)
4680 +/* Some validity checks to make sure the chunks are fine */
4681 +static int do_basic_checks(struct ip_conntrack *conntrack,
4682 + const struct sk_buff *skb,
4685 + u_int32_t offset, count;
4686 + sctp_chunkhdr_t sch;
4689 + DEBUGP(__FUNCTION__);
4694 + for_each_sctp_chunk (skb, sch, offset, count) {
4695 + DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
4697 + if (sch.type == SCTP_CID_INIT
4698 + || sch.type == SCTP_CID_INIT_ACK
4699 + || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4703 + /* Cookie Ack/Echo chunks not the first OR
4704 + Init / Init Ack / Shutdown compl chunks not the only chunks */
4705 + if ((sch.type == SCTP_CID_COOKIE_ACK
4706 + || sch.type == SCTP_CID_COOKIE_ECHO
4709 + DEBUGP("Basic checks failed\n");
4714 + set_bit (sch.type, (void *)map);
4718 + DEBUGP("Basic checks passed\n");
4722 +static int new_state(enum ip_conntrack_dir dir,
4723 + enum sctp_conntrack cur_state,
4728 + DEBUGP(__FUNCTION__);
4731 + DEBUGP("Chunk type: %d\n", chunk_type);
4733 + switch (chunk_type) {
4734 + case SCTP_CID_INIT:
4735 + DEBUGP("SCTP_CID_INIT\n");
4737 + case SCTP_CID_INIT_ACK:
4738 + DEBUGP("SCTP_CID_INIT_ACK\n");
4740 + case SCTP_CID_ABORT:
4741 + DEBUGP("SCTP_CID_ABORT\n");
4743 + case SCTP_CID_SHUTDOWN:
4744 + DEBUGP("SCTP_CID_SHUTDOWN\n");
4746 + case SCTP_CID_SHUTDOWN_ACK:
4747 + DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4749 + case SCTP_CID_ERROR:
4750 + DEBUGP("SCTP_CID_ERROR\n");
4752 + case SCTP_CID_COOKIE_ECHO:
4753 + DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4755 + case SCTP_CID_COOKIE_ACK:
4756 + DEBUGP("SCTP_CID_COOKIE_ACK\n");
4758 + case SCTP_CID_SHUTDOWN_COMPLETE:
4759 + DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4762 + /* Other chunks like DATA, SACK, HEARTBEAT and
4763 + its ACK do not cause a change in state */
4764 + DEBUGP("Unknown chunk type, Will stay in %s\n",
4765 + sctp_conntrack_names[cur_state]);
4769 + DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
4770 + dir, sctp_conntrack_names[cur_state], chunk_type,
4771 + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4773 + return sctp_conntracks[dir][i][cur_state];
4776 +/* Returns verdict for packet, or -1 for invalid. */
4777 +static int sctp_packet(struct ip_conntrack *conntrack,
4778 + const struct sk_buff *skb,
4779 + enum ip_conntrack_info ctinfo)
4781 + enum sctp_conntrack newconntrack, oldsctpstate;
4782 + sctp_sctphdr_t sctph;
4783 + sctp_chunkhdr_t sch;
4784 + u_int32_t offset, count;
4785 + char map[256 / sizeof (char)] = {0};
4787 + DEBUGP(__FUNCTION__);
4790 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4793 + if (do_basic_checks(conntrack, skb, map) != 0)
4796 + /* Check the verification tag (Sec 8.5) */
4797 + if (!test_bit(SCTP_CID_INIT, (void *)map)
4798 + && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4799 + && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4800 + && !test_bit(SCTP_CID_ABORT, (void *)map)
4801 + && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4802 + && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4803 + DEBUGP("Verification tag check failed\n");
4807 + oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4808 + for_each_sctp_chunk (skb, sch, offset, count) {
4809 + WRITE_LOCK(&sctp_lock);
4811 + /* Special cases of Verification tag check (Sec 8.5.1) */
4812 + if (sch.type == SCTP_CID_INIT) {
4813 + /* Sec 8.5.1 (A) */
4814 + if (sctph.vtag != 0) {
4815 + WRITE_UNLOCK(&sctp_lock);
4818 + } else if (sch.type == SCTP_CID_ABORT) {
4819 + /* Sec 8.5.1 (B) */
4820 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4821 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4822 + [1 - CTINFO2DIR(ctinfo)])) {
4823 + WRITE_UNLOCK(&sctp_lock);
4826 + } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4827 + /* Sec 8.5.1 (C) */
4828 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4829 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4830 + [1 - CTINFO2DIR(ctinfo)]
4831 + && (sch.flags & 1))) {
4832 + WRITE_UNLOCK(&sctp_lock);
4835 + } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4836 + /* Sec 8.5.1 (D) */
4837 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4838 + WRITE_UNLOCK(&sctp_lock);
4843 + oldsctpstate = conntrack->proto.sctp.state;
4844 + newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4847 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4848 + DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4849 + CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4850 + WRITE_UNLOCK(&sctp_lock);
4854 + /* If it is an INIT or an INIT ACK note down the vtag */
4855 + if (sch.type == SCTP_CID_INIT
4856 + || sch.type == SCTP_CID_INIT_ACK) {
4857 + sctp_inithdr_t inithdr;
4859 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4860 + &inithdr, sizeof(inithdr)) != 0) {
4861 + WRITE_UNLOCK(&sctp_lock);
4864 + DEBUGP("Setting vtag %x for dir %d\n",
4865 + inithdr.init_tag, CTINFO2DIR(ctinfo));
4866 + conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4869 + conntrack->proto.sctp.state = newconntrack;
4870 + WRITE_UNLOCK(&sctp_lock);
4873 + ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4875 + if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4876 + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4877 + && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4878 + DEBUGP("Setting assured bit\n");
4879 + set_bit(IPS_ASSURED_BIT, &conntrack->status);
4885 +/* Called when a new connection for this protocol found. */
4886 +static int sctp_new(struct ip_conntrack *conntrack,
4887 + const struct sk_buff *skb)
4889 + enum sctp_conntrack newconntrack;
4890 + sctp_sctphdr_t sctph;
4891 + sctp_chunkhdr_t sch;
4892 + u_int32_t offset, count;
4893 + char map[256 / sizeof (char)] = {0};
4895 + DEBUGP(__FUNCTION__);
4898 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4901 + if (do_basic_checks(conntrack, skb, map) != 0)
4904 + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4905 + if ((test_bit (SCTP_CID_ABORT, (void *)map))
4906 + || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4907 + || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4911 + newconntrack = SCTP_CONNTRACK_MAX;
4912 + for_each_sctp_chunk (skb, sch, offset, count) {
4913 + /* Don't need lock here: this conntrack not in circulation yet */
4914 + newconntrack = new_state (IP_CT_DIR_ORIGINAL,
4915 + SCTP_CONNTRACK_NONE, sch.type);
4917 + /* Invalid: delete conntrack */
4918 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4919 + DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4923 + /* Copy the vtag into the state info */
4924 + if (sch.type == SCTP_CID_INIT) {
4925 + if (sctph.vtag == 0) {
4926 + sctp_inithdr_t inithdr;
4928 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4929 + &inithdr, sizeof(inithdr)) != 0) {
4933 + DEBUGP("Setting vtag %x for new conn\n",
4934 + inithdr.init_tag);
4936 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
4939 + /* Sec 8.5.1 (A) */
4943 + /* If it is a shutdown ack OOTB packet, we expect a return
4944 + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4946 + DEBUGP("Setting vtag %x for new conn OOTB\n",
4948 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4951 + conntrack->proto.sctp.state = newconntrack;
4957 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4958 + const struct sk_buff *skb)
4960 + /* To be implemented */
4964 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
4965 + .list = { NULL, NULL },
4966 + .proto = IPPROTO_SCTP,
4968 + .pkt_to_tuple = sctp_pkt_to_tuple,
4969 + .invert_tuple = sctp_invert_tuple,
4970 + .print_tuple = sctp_print_tuple,
4971 + .print_conntrack = sctp_print_conntrack,
4972 + .packet = sctp_packet,
4975 + .exp_matches_pkt = sctp_exp_matches_pkt,
4979 +int __init init(void)
4983 + ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4984 + DEBUGP("SCTP conntrack module loading %s\n",
4985 + ret ? "failed": "succeeded");
4989 +void __exit fini(void)
4991 + ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4992 + DEBUGP("SCTP conntrack module unloaded\n");
4998 +MODULE_LICENSE("GPL");
4999 +MODULE_AUTHOR("Kiran Kumar Immidi");
5000 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
5001 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
5002 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
5003 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-06-08 10:40:36.000000000 +0200
5005 +/* Quake3 extension for IP connection tracking
5006 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5007 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5009 + * ip_conntrack_quake3.c v0.04 2002-08-31
5011 + * This program is free software; you can redistribute it and/or
5012 + * modify it under the terms of the GNU General Public License
5013 + * as published by the Free Software Foundation; either version
5014 + * 2 of the License, or (at your option) any later version.
5016 + * Module load syntax:
5017 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5019 + * please give the ports of all Quake3 master servers You wish to
5020 + * connect to. If you don't specify ports, the default will be UDP
5023 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5026 +#include <linux/module.h>
5027 +#include <linux/ip.h>
5028 +#include <linux/udp.h>
5030 +#include <linux/netfilter.h>
5031 +#include <linux/netfilter_ipv4/ip_tables.h>
5032 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5033 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5035 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5037 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5038 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5039 +MODULE_LICENSE("GPL");
5041 +#define MAX_PORTS 8
5042 +static int ports[MAX_PORTS];
5043 +static int ports_c = 0;
5045 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5046 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5049 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5050 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5052 +#define DEBUGP printk
5054 +#define DEBUGP(format, args...)
5057 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5059 +static int quake3_help(const struct iphdr *iph, size_t len,
5060 + struct ip_conntrack *ct,
5061 + enum ip_conntrack_info ctinfo)
5063 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5064 + int dir = CTINFO2DIR(ctinfo);
5065 + struct ip_conntrack_expect exp;
5068 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5069 + if (ctinfo != IP_CT_ESTABLISHED
5070 + && ctinfo != IP_CT_IS_REPLY) {
5071 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5073 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5075 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5076 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5077 + i+6 < ntohs(udph->len);
5079 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5080 + i, ntohs(udph->len),
5081 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
5082 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5084 + memset(&exp, 0, sizeof(exp));
5086 + exp.tuple = ((struct ip_conntrack_tuple)
5087 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5088 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
5089 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
5092 + exp.mask = ((struct ip_conntrack_tuple)
5093 + { { 0xFFFFFFFF, { 0 } },
5094 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5095 + exp.expectfn = NULL;
5097 + ip_conntrack_expect_related(ct, &exp);
5102 + return(NF_ACCEPT);
5105 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5106 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
5108 +static void fini(void)
5112 + for(i = 0 ; (i < ports_c); i++) {
5113 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5115 + ip_conntrack_helper_unregister(&quake3[i]);
5119 +static int __init init(void)
5125 + ports[0]=QUAKE3_MASTER_PORT;
5127 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5128 + /* Create helper structure */
5129 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5131 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5132 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5133 + quake3[i].mask.dst.protonum = 0xFFFF;
5134 + quake3[i].mask.src.u.udp.port = 0xFFFF;
5135 + quake3[i].help = quake3_help;
5136 + quake3[i].me = THIS_MODULE;
5138 + tmpname = &quake3_names[i][0];
5139 + if (ports[i] == QUAKE3_MASTER_PORT)
5140 + sprintf(tmpname, "quake3");
5142 + sprintf(tmpname, "quake3-%d", i);
5143 + quake3[i].name = tmpname;
5145 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5148 + ret=ip_conntrack_helper_register(&quake3[i]);
5161 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
5162 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
5163 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-06-08 10:40:43.000000000 +0200
5165 +/* RSH extension for IP connection tracking, Version 1.0
5166 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5167 + * based on HW's ip_conntrack_irc.c
5169 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
5171 + * This program is free software; you can redistribute it and/or
5172 + * modify it under the terms of the GNU General Public License
5173 + * as published by the Free Software Foundation; either version
5174 + * 2 of the License, or (at your option) any later version.
5176 + * Module load syntax:
5177 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
5179 + * please give the ports of all RSH servers You wish to connect to.
5180 + * If You don't specify ports, the default will be port 514
5183 + * RSH blows ... you should use SSH (openssh.org) to replace it,
5184 + * unfortunately I babysit some sysadmins that won't migrate
5185 + * their legacy crap, in our second tier.
5190 + * Some docco ripped from the net to teach me all there is to know about
5191 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
5194 + * I have no idea what "unix rshd man pages" these guys have .. but that
5195 + * is some pretty detailed docco!
5198 + * 4. Of the rsh protocol.
5199 + * -----------------------
5201 + * The rshd listens on TCP port #514. The following info is from the unix
5202 + * rshd man pages :
5204 + * "Service Request Protocol
5206 + * When the rshd daemon receives a service request, it initiates the
5207 + * following protocol:
5209 + * 1. The rshd daemon checks the source port number for the request.
5210 + * If the port number is not in the range 0 through 1023, the rshd daemon
5211 + * terminates the connection.
5213 + * 2. The rshd daemon reads characters from the socket up to a null byte.
5214 + * The string read is interpreted as an ASCII number (base 10). If this
5215 + * number is nonzero, the rshd daemon interprets it as the port number
5216 + * of a secondary stream to be used as standard error. A second connection
5217 + * is created to the specified port on the client host. The source port
5218 + * on the local host is in the range 0 through 1023.
5220 + * 3. The rshd daemon uses the source address of the initial connection
5221 + * request to determine the name of the client host. If the name cannot
5222 + * be determined, the rshd daemon uses the dotted decimal representation
5223 + * of the client host's address.
5225 + * 4. The rshd daemon retrieves the following information from the initial
5228 + * * A null-terminated string of at most 16 bytes interpreted as
5229 + * the user name of the user on the client host.
5231 + * * A null-terminated string of at most 16 bytes interpreted as
5232 + * the user name to be used on the local server host.
5234 + * * Another null-terminated string interpreted as a command line
5235 + * to be passed to a shell on the local server host.
5237 + * 5. The rshd daemon attempts to validate the user using the following steps:
5239 + * a. The rshd daemon looks up the local user name in the /etc/passwd
5240 + * file and tries to switch to the home directory (using the chdir
5241 + * subroutine). If either the lookup or the directory change fails,
5242 + * the rshd daemon terminates the connection.
5244 + * b. If the local user ID is a nonzero value, the rshd daemon searches
5245 + * the /etc/hosts.equiv file to see if the name of the client
5246 + * workstation is listed. If the client workstation is listed as an
5247 + * equivalent host, the rshd daemon validates the user.
5249 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
5250 + * authenticate the user by checking the .rhosts file.
5252 + * d. If either the $HOME/.rhosts authentication fails or the
5253 + * client host is not an equivalent host, the rshd daemon
5254 + * terminates the connection.
5256 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
5257 + * on the initial connection and passes the command line to the user's
5258 + * local login shell. The shell then inherits the network connections
5259 + * established by the rshd daemon."
5264 +#include <linux/module.h>
5265 +#include <linux/netfilter.h>
5266 +#include <linux/ip.h>
5267 +#include <net/checksum.h>
5268 +#include <net/tcp.h>
5270 +#include <linux/netfilter_ipv4/lockhelp.h>
5271 +#include <linux/netfilter_ipv4/ip_tables.h>
5272 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5273 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
5275 +#define MAX_PORTS 8
5276 +static int ports[MAX_PORTS];
5277 +static int ports_n_c = 0;
5279 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
5280 +MODULE_DESCRIPTION("RSH connection tracking module");
5281 +MODULE_LICENSE("GPL");
5283 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5284 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
5287 +DECLARE_LOCK(ip_rsh_lock);
5288 +struct module *ip_conntrack_rsh = THIS_MODULE;
5291 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
5294 +#define DEBUGP(format, args...)
5299 +/* FIXME: This should be in userspace. Later. */
5300 +static int help(const struct iphdr *iph, size_t len,
5301 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5303 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5304 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5305 + const char *data = (const char *) tcph + tcph->doff * 4;
5306 + u_int32_t tcplen = len - iph->ihl * 4;
5307 + int dir = CTINFO2DIR(ctinfo);
5308 + struct ip_conntrack_expect expect, *exp = &expect;
5309 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
5313 + /* note that "maxoctet" is used to maintain sanity (8 was the
5314 + * original array size used in rshd/glibc) -- is there a
5315 + * vulnerability in rshd.c in the looped port *= 10?
5319 + DEBUGP("entered\n");
5321 + /* bail if packet is not from RSH client */
5322 + if (dir == IP_CT_DIR_REPLY)
5325 + /* Until there's been traffic both ways, don't look in packets. */
5326 + if (ctinfo != IP_CT_ESTABLISHED
5327 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5328 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
5332 + /* Not whole TCP header? */
5333 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5334 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
5338 + /* Checksum invalid? Ignore. */
5339 + /* FIXME: Source route IP option packets --RR */
5340 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5341 + csum_partial((char *) tcph, tcplen, 0))) {
5342 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5343 + tcph, tcplen, NIPQUAD(iph->saddr),
5344 + NIPQUAD(iph->daddr));
5348 + /* find the rsh stderr port */
5351 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
5356 + if (*data < 48 || *data > 57) {
5357 + DEBUGP("these aren't the packets you're looking for ..\n");
5360 + port = port * 10 + ( *data - 48 );
5363 + /* dont relate sessions that try to expose the client */
5364 + DEBUGP("found port %u\n", port);
5365 + if (port > 1023) {
5366 + DEBUGP("skipping, expected port size is greater than 1023!\n");
5371 + LOCK_BH(&ip_rsh_lock);
5373 + /* new(,related) connection is;
5374 + * reply + dst (uint)port + src port (0:1023)
5376 + memset(&expect, 0, sizeof(expect));
5378 + /* save some discovered data, in case someone ever wants to write
5379 + * a NAT module for this bastard ..
5381 + exp_rsh_info->port = port;
5383 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
5386 + /* Watch out, Radioactive-Man! */
5387 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5388 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5389 + exp->tuple.src.u.tcp.port = 0;
5390 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
5391 + exp->tuple.dst.protonum = IPPROTO_TCP;
5393 + exp->mask.src.ip = 0xffffffff;
5394 + exp->mask.dst.ip = 0xffffffff;
5396 + exp->mask.src.u.tcp.port = htons(0xfc00);
5397 + exp->mask.dst.u.tcp.port = htons(0xfc00);
5398 + exp->mask.dst.protonum = 0xffff;
5400 + exp->expectfn = NULL;
5402 + ip_conntrack_expect_related(ct, &expect);
5404 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5405 + NIPQUAD(exp->tuple.src.ip),
5406 + ntohs(exp->tuple.src.u.tcp.port),
5407 + NIPQUAD(exp->tuple.dst.ip),
5408 + ntohs(exp->tuple.dst.u.tcp.port));
5410 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5411 + NIPQUAD(exp->mask.src.ip),
5412 + ntohs(exp->mask.src.u.tcp.port),
5413 + NIPQUAD(exp->mask.dst.ip),
5414 + ntohs(exp->mask.dst.u.tcp.port));
5415 + UNLOCK_BH(&ip_rsh_lock);
5420 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
5422 +static void fini(void);
5424 +static int __init init(void)
5427 + static char name[10];
5430 + /* If no port given, default to standard RSH port */
5431 + if (ports[0] == 0)
5432 + ports[0] = RSH_PORT;
5434 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5435 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5437 + if (ports[port] == RSH_PORT)
5438 + sprintf(name, "rsh");
5440 + sprintf(name, "rsh-%d", port);
5442 + rsh_helpers[port].name = name;
5443 + rsh_helpers[port].me = THIS_MODULE;
5444 + rsh_helpers[port].max_expected = 1;
5445 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5446 + rsh_helpers[port].timeout = 0;
5448 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5449 + rsh_helpers[port].mask.dst.protonum = 0xffff;
5451 + /* RSH must come from ports 0:1023 to ports[port] (514) */
5452 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
5453 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
5454 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
5456 + rsh_helpers[port].help = help;
5458 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5459 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5460 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
5461 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
5462 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
5463 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
5464 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5465 + NIPQUAD(rsh_helpers[port].mask.src.ip),
5466 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
5467 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
5468 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
5470 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
5473 + printk("ERROR registering port %d\n",
5483 +/* This function is intentionally _NOT_ defined as __exit, because
5484 + * it is needed by the init function */
5485 +static void fini(void)
5488 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5489 + DEBUGP("unregistering port %d\n", ports[port]);
5490 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
5496 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
5497 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
5498 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-06-08 10:40:46.000000000 +0200
5501 + * RTSP extension for IP connection tracking
5502 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5503 + * based on ip_conntrack_irc.c
5505 + * This program is free software; you can redistribute it and/or
5506 + * modify it under the terms of the GNU General Public License
5507 + * as published by the Free Software Foundation; either version
5508 + * 2 of the License, or (at your option) any later version.
5510 + * Module load syntax:
5511 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5512 + * max_outstanding=n setup_timeout=secs
5514 + * If no ports are specified, the default will be port 554.
5516 + * With max_outstanding you can define the maximum number of not yet
5517 + * answered SETUP requests per RTSP session (default 8).
5518 + * With setup_timeout you can specify how long the system waits for
5519 + * an expected data channel (default 300 seconds).
5522 +#include <linux/config.h>
5523 +#include <linux/module.h>
5524 +#include <linux/netfilter.h>
5525 +#include <linux/ip.h>
5526 +#include <net/checksum.h>
5527 +#include <net/tcp.h>
5529 +#include <linux/netfilter_ipv4/lockhelp.h>
5530 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5531 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5533 +#include <linux/ctype.h>
5534 +#define NF_NEED_STRNCASECMP
5535 +#define NF_NEED_STRTOU16
5536 +#define NF_NEED_STRTOU32
5537 +#define NF_NEED_NEXTLINE
5538 +#include <linux/netfilter_helpers.h>
5539 +#define NF_NEED_MIME_NEXTLINE
5540 +#include <linux/netfilter_mime.h>
5542 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5544 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5545 +#ifdef IP_NF_RTSP_DEBUG
5546 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5548 +#define DEBUGP(fmt, args...)
5551 +#define MAX_PORTS 8
5552 +static int ports[MAX_PORTS];
5553 +static int num_ports = 0;
5554 +static int max_outstanding = 8;
5555 +static unsigned int setup_timeout = 300;
5557 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5558 +MODULE_DESCRIPTION("RTSP connection tracking module");
5559 +MODULE_LICENSE("GPL");
5561 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5562 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5563 +MODULE_PARM(max_outstanding, "i");
5564 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5565 +MODULE_PARM(setup_timeout, "i");
5566 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5569 +DECLARE_LOCK(ip_rtsp_lock);
5570 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5573 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5574 + * of allocated ports is twice this value). Note that SMIL burns a lot of
5575 + * ports so keep this reasonably high. If this is too low, you will see a
5576 + * lot of "no free client map entries" messages.
5578 +#define MAX_PORT_MAPS 16
5580 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5582 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5585 + * Parse an RTSP packet.
5587 + * Returns zero if parsing failed.
5590 + * IN ptcp tcp data pointer
5591 + * IN tcplen tcp data len
5592 + * IN/OUT ptcpoff points to current tcp offset
5593 + * OUT phdrsoff set to offset of rtsp headers
5594 + * OUT phdrslen set to length of rtsp headers
5595 + * OUT pcseqoff set to offset of CSeq header
5596 + * OUT pcseqlen set to length of CSeq header
5599 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5600 + uint* phdrsoff, uint* phdrslen,
5601 + uint* pcseqoff, uint* pcseqlen)
5603 + uint entitylen = 0;
5607 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5612 + *phdrsoff = *ptcpoff;
5613 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5617 + if (entitylen > 0)
5619 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5623 + if (lineoff+linelen > tcplen)
5625 + INFOP("!! overrun !!\n");
5629 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5631 + *pcseqoff = lineoff;
5632 + *pcseqlen = linelen;
5634 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5636 + uint off = lineoff+15;
5637 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
5638 + nf_strtou32(ptcp+off, &entitylen);
5641 + *phdrslen = (*ptcpoff) - (*phdrsoff);
5647 + * Find lo/hi client ports (if any) in transport header
5649 + * ptcp, tcplen = packet
5650 + * tranoff, tranlen = buffer to search
5653 + * pport_lo, pport_hi = lo/hi ports (host endian)
5655 + * Returns nonzero if any client ports found
5657 + * Note: it is valid (and expected) for the client to request multiple
5658 + * transports, so we need to parse the entire line.
5661 +rtsp_parse_transport(char* ptran, uint tranlen,
5662 + struct ip_ct_rtsp_expect* prtspexp)
5667 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5668 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
5670 + INFOP("sanity check failed\n");
5673 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5675 + SKIP_WSPACE(ptran, tranlen, off);
5677 + /* Transport: tran;field;field=val,tran;field;field=val,... */
5678 + while (off < tranlen)
5680 + const char* pparamend;
5681 + uint nextparamoff;
5683 + pparamend = memchr(ptran+off, ',', tranlen-off);
5684 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5685 + nextparamoff = pparamend-ptran;
5687 + while (off < nextparamoff)
5689 + const char* pfieldend;
5690 + uint nextfieldoff;
5692 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5693 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5695 + if (strncmp(ptran+off, "client_port=", 12) == 0)
5701 + numlen = nf_strtou16(ptran+off, &port);
5703 + if (prtspexp->loport != 0 && prtspexp->loport != port)
5705 + DEBUGP("multiple ports found, port %hu ignored\n", port);
5709 + prtspexp->loport = prtspexp->hiport = port;
5710 + if (ptran[off] == '-')
5713 + numlen = nf_strtou16(ptran+off, &port);
5715 + prtspexp->pbtype = pb_range;
5716 + prtspexp->hiport = port;
5718 + // If we have a range, assume rtp:
5719 + // loport must be even, hiport must be loport+1
5720 + if ((prtspexp->loport & 0x0001) != 0 ||
5721 + prtspexp->hiport != prtspexp->loport+1)
5723 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
5724 + prtspexp->loport, prtspexp->hiport);
5725 + prtspexp->loport &= 0xfffe;
5726 + prtspexp->hiport = prtspexp->loport+1;
5729 + else if (ptran[off] == '/')
5732 + numlen = nf_strtou16(ptran+off, &port);
5734 + prtspexp->pbtype = pb_discon;
5735 + prtspexp->hiport = port;
5742 + * Note we don't look for the destination parameter here.
5743 + * If we are using NAT, the NAT module will handle it. If not,
5744 + * and the client is sending packets elsewhere, the expectation
5745 + * will quietly time out.
5748 + off = nextfieldoff;
5751 + off = nextparamoff;
5757 +/*** conntrack functions ***/
5759 +/* outbound packet: client->server */
5761 +help_out(const struct iphdr* iph, size_t pktlen,
5762 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5764 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5765 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5766 + uint tcplen = pktlen - iph->ihl * 4;
5767 + char* pdata = (char*)tcph + tcph->doff * 4;
5768 + uint datalen = tcplen - tcph->doff * 4;
5771 + struct ip_conntrack_expect exp;
5773 + while (dataoff < datalen)
5775 + uint cmdoff = dataoff;
5785 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
5786 + &hdrsoff, &hdrslen,
5787 + &cseqoff, &cseqlen))
5789 + break; /* not a valid message */
5792 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5794 + continue; /* not a SETUP message */
5796 + DEBUGP("found a setup message\n");
5798 + memset(&exp, 0, sizeof(exp));
5801 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5802 + &lineoff, &linelen))
5808 + if (off > hdrsoff+hdrslen)
5810 + INFOP("!! overrun !!");
5814 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5816 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5817 + &exp.help.exp_rtsp_info);
5821 + if (exp.help.exp_rtsp_info.loport == 0)
5823 + DEBUGP("no udp transports found\n");
5824 + continue; /* no udp transports found */
5827 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5828 + (int)exp.help.exp_rtsp_info.pbtype,
5829 + exp.help.exp_rtsp_info.loport,
5830 + exp.help.exp_rtsp_info.hiport);
5832 + LOCK_BH(&ip_rtsp_lock);
5833 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5834 + exp.help.exp_rtsp_info.len = hdrslen;
5836 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5837 + exp.mask.src.ip = 0xffffffff;
5838 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5839 + exp.mask.dst.ip = 0xffffffff;
5840 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5841 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5842 + exp.tuple.dst.protonum = IPPROTO_UDP;
5843 + exp.mask.dst.protonum = 0xffff;
5845 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5846 + NIPQUAD(exp.tuple.src.ip),
5847 + ntohs(exp.tuple.src.u.tcp.port),
5848 + NIPQUAD(exp.tuple.dst.ip),
5849 + ntohs(exp.tuple.dst.u.tcp.port));
5851 + /* pass the request off to the nat helper */
5852 + rc = ip_conntrack_expect_related(ct, &exp);
5853 + UNLOCK_BH(&ip_rtsp_lock);
5856 + DEBUGP("ip_conntrack_expect_related succeeded\n");
5860 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5867 +/* inbound packet: server->client */
5869 +help_in(const struct iphdr* iph, size_t pktlen,
5870 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5876 +help(const struct iphdr* iph, size_t pktlen,
5877 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5879 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5880 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5881 + u_int32_t tcplen = pktlen - iph->ihl * 4;
5883 + /* Until there's been traffic both ways, don't look in packets. */
5884 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5886 + DEBUGP("conntrackinfo = %u\n", ctinfo);
5890 + /* Not whole TCP header? */
5891 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5893 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5897 + /* Checksum invalid? Ignore. */
5898 + /* FIXME: Source route IP option packets --RR */
5899 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5900 + csum_partial((char*)tcph, tcplen, 0)))
5902 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5903 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5907 + switch (CTINFO2DIR(ctinfo))
5909 + case IP_CT_DIR_ORIGINAL:
5910 + help_out(iph, pktlen, ct, ctinfo);
5912 + case IP_CT_DIR_REPLY:
5913 + help_in(iph, pktlen, ct, ctinfo);
5920 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5921 +static char rtsp_names[MAX_PORTS][10];
5923 +/* This function is intentionally _NOT_ defined as __exit */
5928 + for (i = 0; i < num_ports; i++)
5930 + DEBUGP("unregistering port %d\n", ports[i]);
5931 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5939 + struct ip_conntrack_helper *hlpr;
5942 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5944 + if (max_outstanding < 1)
5946 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5949 + if (setup_timeout < 0)
5951 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5955 + /* If no port given, default to standard rtsp port */
5956 + if (ports[0] == 0)
5958 + ports[0] = RTSP_PORT;
5961 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5963 + hlpr = &rtsp_helpers[i];
5964 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5965 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5966 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
5967 + hlpr->mask.src.u.tcp.port = 0xFFFF;
5968 + hlpr->mask.dst.protonum = 0xFFFF;
5969 + hlpr->max_expected = max_outstanding;
5970 + hlpr->timeout = setup_timeout;
5971 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5972 + hlpr->me = ip_conntrack_rtsp;
5973 + hlpr->help = help;
5975 + tmpname = &rtsp_names[i][0];
5976 + if (ports[i] == RTSP_PORT)
5978 + sprintf(tmpname, "rtsp");
5982 + sprintf(tmpname, "rtsp-%d", i);
5984 + hlpr->name = tmpname;
5986 + DEBUGP("port #%d: %d\n", i, ports[i]);
5988 + ret = ip_conntrack_helper_register(hlpr);
5992 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
6001 +#ifdef CONFIG_IP_NF_NAT_NEEDED
6002 +EXPORT_SYMBOL(ip_rtsp_lock);
6007 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
6008 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-07 21:14:11.000000000 +0200
6009 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-08 10:38:45.000000000 +0200
6011 len += sprintf(buffer + len, "[ASSURED] ");
6012 len += sprintf(buffer + len, "use=%u ",
6013 atomic_read(&conntrack->ct_general.use));
6014 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
6015 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
6017 len += sprintf(buffer + len, "\n");
6022 goto cleanup_nothing;
6024 - proc = proc_net_create("ip_conntrack",0,list_conntracks);
6025 + proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
6026 if (!proc) goto cleanup_init;
6027 proc->owner = THIS_MODULE;
6030 EXPORT_SYMBOL(ip_conntrack_alter_reply);
6031 EXPORT_SYMBOL(ip_conntrack_destroyed);
6032 EXPORT_SYMBOL(ip_conntrack_get);
6033 +EXPORT_SYMBOL(__ip_conntrack_confirm);
6034 EXPORT_SYMBOL(need_ip_conntrack);
6035 EXPORT_SYMBOL(ip_conntrack_helper_register);
6036 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
6037 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
6038 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
6039 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-06-08 10:41:27.000000000 +0200
6042 + * talk extension for IP connection tracking.
6043 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6045 + * This program is free software; you can redistribute it and/or
6046 + * modify it under the terms of the GNU General Public License
6047 + * as published by the Free Software Foundation; either version
6048 + * 2 of the License, or (at your option) any later version.
6050 + * Module load syntax:
6051 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
6053 + * talk=[0|1] disable|enable old talk support
6054 + * ntalk=[0|1] disable|enable ntalk support
6055 + * ntalk2=[0|1] disable|enable ntalk2 support
6057 + * The default is talk=1 ntalk=1 ntalk2=1
6059 + * The helper does not support simultaneous talk requests.
6062 + * ASCII art on talk protocols
6065 + * caller server callee server
6072 + * caller client ----------- callee client
6075 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
6076 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
6077 + * 3. callee client <-> caller server: LOOK_UP invitation
6078 + * 4. callee client <-> caller client: talk data channel
6080 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
6081 + * draft-hunter-talk-00.txt
6082 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
6084 +#include <linux/config.h>
6085 +#include <linux/module.h>
6086 +#include <linux/netfilter.h>
6087 +#include <linux/ip.h>
6088 +#include <net/checksum.h>
6089 +#include <net/udp.h>
6091 +#include <linux/netfilter_ipv4/lockhelp.h>
6092 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6093 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
6094 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6095 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
6097 +/* Default all talk protocols are supported */
6098 +static int talk = 1;
6099 +static int ntalk = 1;
6100 +static int ntalk2 = 1;
6101 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6102 +MODULE_DESCRIPTION("talk connection tracking module");
6103 +MODULE_LICENSE("GPL");
6105 +MODULE_PARM(talk, "i");
6106 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
6107 +MODULE_PARM(ntalk, "i");
6108 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
6109 +MODULE_PARM(ntalk2, "i");
6110 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
6113 +DECLARE_LOCK(ip_talk_lock);
6114 +struct module *ip_conntrack_talk = THIS_MODULE;
6117 +#define DEBUGP printk
6119 +#define DEBUGP(format, args...)
6122 +static int talk_expect(struct ip_conntrack *ct);
6123 +static int ntalk_expect(struct ip_conntrack *ct);
6125 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
6127 +static int talk_help_response(const struct iphdr *iph, size_t len,
6128 + struct ip_conntrack *ct,
6129 + enum ip_conntrack_info ctinfo,
6134 + struct talk_addr *addr)
6136 + int dir = CTINFO2DIR(ctinfo);
6137 + struct ip_conntrack_expect expect, *exp = &expect;
6138 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
6140 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
6141 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
6144 + if (!(answer == SUCCESS && type == mode))
6147 + memset(&expect, 0, sizeof(expect));
6149 + if (type == ANNOUNCE) {
6151 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
6153 + /* update the talk info */
6154 + LOCK_BH(&ip_talk_lock);
6155 + exp_talk_info->port = htons(talk_port);
6157 + /* expect callee client -> caller server message */
6158 + exp->tuple = ((struct ip_conntrack_tuple)
6159 + { { ct->tuplehash[dir].tuple.src.ip,
6161 + { ct->tuplehash[dir].tuple.dst.ip,
6162 + { .tcp = { htons(talk_port) } },
6164 + exp->mask = ((struct ip_conntrack_tuple)
6165 + { { 0xFFFFFFFF, { 0 } },
6166 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6168 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
6170 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
6171 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
6172 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
6174 + /* Ignore failure; should only happen with NAT */
6175 + ip_conntrack_expect_related(ct, &expect);
6176 + UNLOCK_BH(&ip_talk_lock);
6178 + if (type == LOOK_UP) {
6180 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
6182 + /* update the talk info */
6183 + LOCK_BH(&ip_talk_lock);
6184 + exp_talk_info->port = addr->ta_port;
6186 + /* expect callee client -> caller client connection */
6187 + exp->tuple = ((struct ip_conntrack_tuple)
6188 + { { ct->tuplehash[!dir].tuple.src.ip,
6191 + { addr->ta_port },
6193 + exp->mask = ((struct ip_conntrack_tuple)
6194 + { { 0xFFFFFFFF, { 0 } },
6195 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6197 + exp->expectfn = NULL;
6199 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
6200 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
6201 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
6203 + /* Ignore failure; should only happen with NAT */
6204 + ip_conntrack_expect_related(ct, &expect);
6205 + UNLOCK_BH(&ip_talk_lock);
6211 +/* FIXME: This should be in userspace. Later. */
6212 +static int talk_help(const struct iphdr *iph, size_t len,
6213 + struct ip_conntrack *ct,
6214 + enum ip_conntrack_info ctinfo,
6218 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6219 + const char *data = (const char *)udph + sizeof(struct udphdr);
6220 + int dir = CTINFO2DIR(ctinfo);
6223 + DEBUGP("ip_ct_talk_help: help entered\n");
6225 + /* Until there's been traffic both ways, don't look in packets. */
6226 + if (ctinfo != IP_CT_ESTABLISHED
6227 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6228 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
6232 + /* Not whole UDP header? */
6233 + udplen = len - iph->ihl * 4;
6234 + if (udplen < sizeof(struct udphdr)) {
6235 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
6239 + /* Checksum invalid? Ignore. */
6240 + /* FIXME: Source route IP option packets --RR */
6241 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6242 + csum_partial((char *)udph, udplen, 0))) {
6243 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6244 + udph, udplen, NIPQUAD(iph->saddr),
6245 + NIPQUAD(iph->daddr));
6249 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6250 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
6252 + if (dir == IP_CT_DIR_ORIGINAL)
6255 + if (talk_port == TALK_PORT
6256 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6257 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6258 + ((struct talk_response *)data)->type,
6259 + ((struct talk_response *)data)->answer,
6260 + &(((struct talk_response *)data)->addr));
6261 + else if (talk_port == NTALK_PORT
6263 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6264 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6265 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6266 + ((struct ntalk_response *)data)->type,
6267 + ((struct ntalk_response *)data)->answer,
6268 + &(((struct ntalk_response *)data)->addr));
6269 + else if (talk_port == NTALK_PORT
6271 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6272 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6273 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6274 + ((struct ntalk2_response *)data)->type,
6275 + ((struct ntalk2_response *)data)->answer,
6276 + &(((struct ntalk2_response *)data)->addr));
6278 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
6279 + (unsigned)udplen - sizeof(struct udphdr),
6280 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6285 +static int lookup_help(const struct iphdr *iph, size_t len,
6286 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6288 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
6291 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
6292 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6294 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
6297 +static struct ip_conntrack_helper lookup_helpers[2] =
6298 + { { { NULL, NULL },
6299 + "talk", /* name */
6301 + NULL, /* module */
6302 + 1, /* max_expected */
6303 + 240, /* timeout */
6304 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
6305 + { 0, { 0 }, IPPROTO_UDP } },
6306 + { { 0, { 0xFFFF } }, /* mask */
6307 + { 0, { 0 }, 0xFFFF } },
6308 + lookup_help }, /* helper */
6310 + "ntalk", /* name */
6312 + NULL, /* module */
6313 + 1, /* max_expected */
6314 + 240, /* timeout */
6315 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
6316 + { 0, { 0 }, IPPROTO_UDP } },
6317 + { { 0, { 0xFFFF } }, /* mask */
6318 + { 0, { 0 }, 0xFFFF } },
6319 + lookup_nhelp } /* helper */
6322 +static int talk_expect(struct ip_conntrack *ct)
6324 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
6325 + WRITE_LOCK(&ip_conntrack_lock);
6326 + ct->helper = &lookup_helpers[0];
6327 + WRITE_UNLOCK(&ip_conntrack_lock);
6329 + return NF_ACCEPT; /* unused */
6332 +static int ntalk_expect(struct ip_conntrack *ct)
6334 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
6335 + WRITE_LOCK(&ip_conntrack_lock);
6336 + ct->helper = &lookup_helpers[1];
6337 + WRITE_UNLOCK(&ip_conntrack_lock);
6339 + return NF_ACCEPT; /* unused */
6342 +static int help(const struct iphdr *iph, size_t len,
6343 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6345 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
6348 +static int nhelp(const struct iphdr *iph, size_t len,
6349 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6351 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
6354 +static struct ip_conntrack_helper talk_helpers[2] =
6355 + { { { NULL, NULL },
6356 + "talk", /* name */
6358 + THIS_MODULE, /* module */
6359 + 1, /* max_expected */
6360 + 240, /* timeout */
6361 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
6362 + { 0, { 0 }, IPPROTO_UDP } },
6363 + { { 0, { 0xFFFF } }, /* mask */
6364 + { 0, { 0 }, 0xFFFF } },
6365 + help }, /* helper */
6367 + "ntalk", /* name */
6369 + THIS_MODULE, /* module */
6370 + 1, /* max_expected */
6371 + 240, /* timeout */
6372 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
6373 + { 0, { 0 }, IPPROTO_UDP } },
6374 + { { 0, { 0xFFFF } }, /* mask */
6375 + { 0, { 0 }, 0xFFFF } },
6376 + nhelp } /* helper */
6379 +static int __init init(void)
6382 + ip_conntrack_helper_register(&talk_helpers[0]);
6383 + if (ntalk > 0 || ntalk2 > 0)
6384 + ip_conntrack_helper_register(&talk_helpers[1]);
6389 +static void __exit fini(void)
6392 + ip_conntrack_helper_unregister(&talk_helpers[0]);
6393 + if (ntalk > 0 || ntalk2 > 0)
6394 + ip_conntrack_helper_unregister(&talk_helpers[1]);
6397 +EXPORT_SYMBOL(ip_talk_lock);
6401 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_core.c
6402 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_core.c 2004-06-07 21:13:39.000000000 +0200
6403 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_core.c 2004-06-08 10:30:32.000000000 +0200
6406 /* Have to grab read lock before sibling_list traversal */
6407 READ_LOCK(&ip_conntrack_lock);
6408 - list_for_each(cur_item, &ct->sibling_list) {
6409 + list_for_each_prev(cur_item, &ct->sibling_list) {
6410 exp = list_entry(cur_item, struct ip_conntrack_expect,
6413 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_h323.c
6414 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
6415 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-06-08 10:38:40.000000000 +0200
6418 + * H.323 'brute force' extension for NAT alteration.
6419 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6421 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6422 + * (http://www.coritel.it/projects/sofia/nat.html)
6423 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6424 + * the unregistered helpers to the conntrack entries.
6428 +#include <linux/module.h>
6429 +#include <linux/netfilter.h>
6430 +#include <linux/ip.h>
6431 +#include <net/checksum.h>
6432 +#include <net/tcp.h>
6434 +#include <linux/netfilter_ipv4/lockhelp.h>
6435 +#include <linux/netfilter_ipv4/ip_nat.h>
6436 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6437 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6438 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6439 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6440 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6442 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6443 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6444 +MODULE_LICENSE("GPL");
6446 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6447 +struct module *ip_nat_h323 = THIS_MODULE;
6450 +#define DEBUGP printk
6452 +#define DEBUGP(format, args...)
6455 +/* FIXME: Time out? --RR */
6457 +static unsigned int
6458 +h225_nat_expected(struct sk_buff **pskb,
6459 + unsigned int hooknum,
6460 + struct ip_conntrack *ct,
6461 + struct ip_nat_info *info);
6463 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6464 + struct ip_conntrack_expect *exp,
6465 + struct ip_nat_info *info,
6466 + enum ip_conntrack_info ctinfo,
6467 + unsigned int hooknum,
6468 + struct sk_buff **pskb);
6470 +static struct ip_nat_helper h245 =
6472 + "H.245", /* name */
6474 + NULL, /* module */
6475 + { { 0, { 0 } }, /* tuple */
6476 + { 0, { 0 }, IPPROTO_TCP } },
6477 + { { 0, { 0xFFFF } }, /* mask */
6478 + { 0, { 0 }, 0xFFFF } },
6479 + h225_nat_help, /* helper */
6480 + h225_nat_expected /* expectfn */
6483 +static unsigned int
6484 +h225_nat_expected(struct sk_buff **pskb,
6485 + unsigned int hooknum,
6486 + struct ip_conntrack *ct,
6487 + struct ip_nat_info *info)
6489 + struct ip_nat_multi_range mr;
6490 + u_int32_t newdstip, newsrcip, newip;
6492 + struct ip_ct_h225_expect *exp_info;
6493 + struct ip_ct_h225_master *master_info;
6494 + struct ip_conntrack *master = master_ct(ct);
6495 + unsigned int is_h225, ret;
6497 + IP_NF_ASSERT(info);
6498 + IP_NF_ASSERT(master);
6500 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6502 + DEBUGP("h225_nat_expected: We have a connection!\n");
6503 + master_info = &ct->master->expectant->help.ct_h225_info;
6504 + exp_info = &ct->master->help.exp_h225_info;
6506 + LOCK_BH(&ip_h323_lock);
6508 + DEBUGP("master: ");
6509 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6510 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6511 + DEBUGP("conntrack: ");
6512 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6513 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6514 + /* Make connection go to the client. */
6515 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6516 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6517 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6518 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6520 + /* Make the connection go to the server */
6521 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6522 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6523 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6524 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6526 + port = exp_info->port;
6527 + is_h225 = master_info->is_h225 == H225_PORT;
6528 + UNLOCK_BH(&ip_h323_lock);
6530 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6535 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6538 + /* We don't want to manip the per-protocol, just the IPs... */
6539 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6540 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6542 + /* ... unless we're doing a MANIP_DST, in which case, make
6543 + sure we map to the correct port */
6544 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6545 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6546 + mr.range[0].min = mr.range[0].max
6547 + = ((union ip_conntrack_manip_proto)
6548 + { .tcp = { port } });
6551 + ret = ip_nat_setup_info(ct, &mr, hooknum);
6554 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6555 + /* NAT expectfn called with ip_nat_lock write-locked */
6556 + info->helper = &h245;
6561 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6562 + struct sk_buff **pskb,
6563 + enum ip_conntrack_info ctinfo)
6565 + struct iphdr *iph = (*pskb)->nh.iph;
6566 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6567 + char *data = (char *) tcph + tcph->doff * 4;
6568 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6569 + u_int32_t datalen = tcplen - tcph->doff*4;
6570 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6575 + MUST_BE_LOCKED(&ip_h323_lock);
6577 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6578 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6580 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6582 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6583 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6586 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6587 + info->offset[IP_CT_DIR_ORIGINAL],
6588 + info->offset[IP_CT_DIR_REPLY],
6590 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6591 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6593 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
6594 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6595 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6596 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6597 + if (!between(info->seq[i], ntohl(tcph->seq),
6598 + ntohl(tcph->seq) + datalen))
6600 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6601 + ntohl(tcph->seq) + datalen)) {
6602 + /* Partial retransmisison. It's a cracker being funky. */
6603 + if (net_ratelimit()) {
6604 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6607 + ntohl(tcph->seq) + datalen);
6612 + /* Change address inside packet to match way we're mapping
6613 + this connection. */
6614 + if (i == IP_CT_DIR_ORIGINAL) {
6615 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6616 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6618 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
6619 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6622 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6623 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6624 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6625 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6627 + /* Modify the packet */
6628 + *(u_int32_t *)(data + info->offset[i]) = newip;
6629 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
6631 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6632 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6633 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6634 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6637 + /* fix checksum information */
6639 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6643 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6644 + csum_partial((char *)tcph, tcph->doff*4,
6646 + ip_send_check(iph);
6651 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6652 + struct ip_conntrack *ct,
6653 + struct sk_buff **pskb,
6654 + enum ip_conntrack_info ctinfo,
6655 + struct ip_conntrack_expect *expect)
6659 + struct ip_conntrack_tuple newtuple;
6660 + struct iphdr *iph = (*pskb)->nh.iph;
6661 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6662 + char *data = (char *) tcph + tcph->doff * 4;
6663 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6664 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6667 + MUST_BE_LOCKED(&ip_h323_lock);
6668 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6669 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6670 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6672 + if (!between(expect->seq + 6, ntohl(tcph->seq),
6673 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6674 + /* Partial retransmisison. It's a cracker being funky. */
6675 + if (net_ratelimit()) {
6676 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6679 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6684 + /* Change address inside packet to match way we're mapping
6685 + this connection. */
6686 + if (info->dir == IP_CT_DIR_REPLY) {
6687 + /* Must be where client thinks server is */
6688 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6689 + /* Expect something from client->server */
6690 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6691 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6693 + /* Must be where server thinks client is */
6694 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6695 + /* Expect something from server->client */
6696 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6697 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6700 + is_h225 = (master_info->is_h225 == H225_PORT);
6703 + newtuple.dst.protonum = IPPROTO_TCP;
6704 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6706 + newtuple.dst.protonum = IPPROTO_UDP;
6707 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6710 + /* Try to get same port: if not, try to change it. */
6711 + for (port = ntohs(info->port); port != 0; port++) {
6713 + newtuple.dst.u.tcp.port = htons(port);
6715 + newtuple.dst.u.udp.port = htons(port);
6717 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6721 + DEBUGP("h323_data_fixup: no free port found!\n");
6725 + port = htons(port);
6727 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6728 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6729 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6731 + /* Modify the packet */
6732 + *(u_int32_t *)(data + info->offset) = newip;
6733 + *(u_int16_t *)(data + info->offset + 4) = port;
6735 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6736 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6737 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6739 + /* fix checksum information */
6740 + /* FIXME: usually repeated multiple times in the case of H.245! */
6742 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6743 + tcplen - tcph->doff*4, 0);
6746 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6747 + csum_partial((char *)tcph, tcph->doff*4,
6749 + ip_send_check(iph);
6754 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6755 + struct ip_conntrack_expect *exp,
6756 + struct ip_nat_info *info,
6757 + enum ip_conntrack_info ctinfo,
6758 + unsigned int hooknum,
6759 + struct sk_buff **pskb)
6762 + struct ip_ct_h225_expect *exp_info;
6764 + /* Only mangle things once: original direction in POST_ROUTING
6765 + and reply direction on PRE_ROUTING. */
6766 + dir = CTINFO2DIR(ctinfo);
6767 + DEBUGP("nat_h323: dir %s at hook %s\n",
6768 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6769 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6770 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6771 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6772 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6773 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6774 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6775 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6776 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6777 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6778 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6783 + LOCK_BH(&ip_h323_lock);
6784 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6785 + UNLOCK_BH(&ip_h323_lock);
6788 + UNLOCK_BH(&ip_h323_lock);
6792 + exp_info = &exp->help.exp_h225_info;
6794 + LOCK_BH(&ip_h323_lock);
6795 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6796 + UNLOCK_BH(&ip_h323_lock);
6799 + UNLOCK_BH(&ip_h323_lock);
6804 +static struct ip_nat_helper h225 =
6806 + "H.225", /* name */
6807 + IP_NAT_HELPER_F_ALWAYS, /* flags */
6808 + THIS_MODULE, /* module */
6809 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6810 + { 0, { 0 }, IPPROTO_TCP } },
6811 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6812 + { 0, { 0 }, 0xFFFF } },
6813 + h225_nat_help, /* helper */
6814 + h225_nat_expected /* expectfn */
6817 +static int __init init(void)
6821 + ret = ip_nat_helper_register(&h225);
6824 + printk("ip_nat_h323: cannot initialize the module!\n");
6829 +static void __exit fini(void)
6831 + ip_nat_helper_unregister(&h225);
6836 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_mms.c
6837 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6838 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-06-08 10:39:44.000000000 +0200
6840 +/* MMS extension for TCP NAT alteration.
6841 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6842 + * based on ip_nat_ftp.c and ip_nat_irc.c
6844 + * ip_nat_mms.c v0.3 2002-09-22
6846 + * This program is free software; you can redistribute it and/or
6847 + * modify it under the terms of the GNU General Public License
6848 + * as published by the Free Software Foundation; either version
6849 + * 2 of the License, or (at your option) any later version.
6851 + * Module load syntax:
6852 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6854 + * Please give the ports of all MMS servers You wish to connect to.
6855 + * If you don't specify ports, the default will be TCP port 1755.
6857 + * More info on MMS protocol, firewalls and NAT:
6858 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6859 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6861 + * The SDP project people are reverse-engineering MMS:
6862 + * http://get.to/sdp
6865 +/* FIXME: issue with UDP & fragmentation with this URL:
6866 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6867 + may be related to out-of-order first packets:
6868 + basically the expectation is set up correctly, then the server sends
6869 + a first UDP packet which is fragmented plus arrives out-of-order.
6870 + the MASQUERADING firewall with ip_nat_mms loaded responds with
6871 + an ICMP unreachable back to the server */
6873 +#include <linux/module.h>
6874 +#include <linux/netfilter_ipv4.h>
6875 +#include <linux/ip.h>
6876 +#include <linux/tcp.h>
6877 +#include <net/tcp.h>
6878 +#include <linux/netfilter_ipv4/ip_nat.h>
6879 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6880 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6881 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6882 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6885 +#define DEBUGP printk
6886 +#define DUMP_BYTES(address, counter) \
6888 + int temp_counter; \
6889 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6890 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
6895 +#define DEBUGP(format, args...)
6896 +#define DUMP_BYTES(address, counter)
6899 +#define MAX_PORTS 8
6900 +static int ports[MAX_PORTS];
6901 +static int ports_c = 0;
6904 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6907 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6908 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6909 +MODULE_LICENSE("GPL");
6911 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6913 +/* FIXME: Time out? --RR */
6915 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6916 + struct ip_conntrack *ct,
6917 + struct sk_buff **pskb,
6918 + enum ip_conntrack_info ctinfo,
6919 + struct ip_conntrack_expect *expect)
6922 + struct ip_conntrack_tuple t;
6923 + struct iphdr *iph = (*pskb)->nh.iph;
6924 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6925 + char *data = (char *)tcph + tcph->doff * 4;
6926 + int i, j, k, port;
6927 + u_int16_t mms_proto;
6929 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6930 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6931 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6935 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6936 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6937 + char proto_string[6];
6939 + MUST_BE_LOCKED(&ip_mms_lock);
6941 + /* what was the protocol again ? */
6942 + mms_proto = expect->tuple.dst.protonum;
6943 + sprintf(proto_string, "%u", mms_proto);
6945 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6946 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6947 + mms_proto == IPPROTO_UDP ? "UDP"
6948 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6950 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6952 + /* Alter conntrack's expectations. */
6953 + t = expect->tuple;
6955 + for (port = ct_mms_info->port; port != 0; port++) {
6956 + t.dst.u.tcp.port = htons(port);
6957 + if (ip_conntrack_change_expect(expect, &t) == 0) {
6958 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6966 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6968 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6969 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6971 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6973 + memset(unicode_buffer, 0, sizeof(char)*75);
6975 + for (i=0; i<strlen(buffer); ++i)
6976 + *(unicode_buffer+i*2)=*(buffer+i);
6978 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6979 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6980 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6982 + /* add end of packet to it */
6983 + for (j=0; j<ct_mms_info->padding; ++j) {
6984 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6985 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6986 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6989 + /* pad with zeroes at the end ? see explanation of weird math below */
6990 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6991 + for (k=0; k<zero_padding; ++k)
6992 + *(unicode_buffer+i*2+j+k)= (char)0;
6994 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6995 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6996 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6998 + /* explanation, before I forget what I did:
6999 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
7000 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
7001 + but note that things may have to be padded with zeroes to align by 8
7002 + bytes, hence we add 7 and divide by 8 to get the correct length */
7003 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
7004 + *mms_chunkLenLV = *mms_chunkLenLM+2;
7005 + *mms_messageLength = *mms_chunkLenLV*8;
7007 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
7008 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
7010 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7011 + expect->seq - ntohl(tcph->seq),
7012 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
7013 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
7014 + DUMP_BYTES(unicode_buffer, 60);
7019 +static unsigned int
7020 +mms_nat_expected(struct sk_buff **pskb,
7021 + unsigned int hooknum,
7022 + struct ip_conntrack *ct,
7023 + struct ip_nat_info *info)
7025 + struct ip_nat_multi_range mr;
7026 + u_int32_t newdstip, newsrcip, newip;
7028 + struct ip_conntrack *master = master_ct(ct);
7030 + IP_NF_ASSERT(info);
7031 + IP_NF_ASSERT(master);
7033 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7035 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
7037 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7038 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7039 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
7040 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7041 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7042 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7043 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
7045 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7050 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
7053 + /* We don't want to manip the per-protocol, just the IPs. */
7054 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7055 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7057 + return ip_nat_setup_info(ct, &mr, hooknum);
7061 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
7062 + struct ip_conntrack_expect *exp,
7063 + struct ip_nat_info *info,
7064 + enum ip_conntrack_info ctinfo,
7065 + unsigned int hooknum,
7066 + struct sk_buff **pskb)
7068 + struct iphdr *iph = (*pskb)->nh.iph;
7069 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7070 + unsigned int datalen;
7072 + struct ip_ct_mms_expect *ct_mms_info;
7075 + DEBUGP("ip_nat_mms: no exp!!");
7077 + ct_mms_info = &exp->help.exp_mms_info;
7079 + /* Only mangle things once: original direction in POST_ROUTING
7080 + and reply direction on PRE_ROUTING. */
7081 + dir = CTINFO2DIR(ctinfo);
7082 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7083 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7084 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
7085 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7086 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7087 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7088 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7091 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
7092 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7093 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7094 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7095 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7097 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7099 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
7100 + exp->seq + ct_mms_info->len,
7102 + ntohl(tcph->seq) + datalen);
7104 + LOCK_BH(&ip_mms_lock);
7105 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
7106 + if (between(exp->seq + ct_mms_info->len,
7108 + ntohl(tcph->seq) + datalen)) {
7109 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
7110 + UNLOCK_BH(&ip_mms_lock);
7114 + /* Half a match? This means a partial retransmisison.
7115 + It's a cracker being funky. */
7116 + if (net_ratelimit()) {
7117 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
7118 + exp->seq, ct_mms_info->len,
7120 + ntohl(tcph->seq) + datalen);
7122 + UNLOCK_BH(&ip_mms_lock);
7125 + UNLOCK_BH(&ip_mms_lock);
7130 +static struct ip_nat_helper mms[MAX_PORTS];
7131 +static char mms_names[MAX_PORTS][10];
7133 +/* Not __exit: called from init() */
7134 +static void fini(void)
7138 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7139 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
7140 + ip_nat_helper_unregister(&mms[i]);
7144 +static int __init init(void)
7149 + if (ports[0] == 0)
7150 + ports[0] = MMS_PORT;
7152 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7154 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
7156 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
7157 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
7158 + mms[i].mask.dst.protonum = 0xFFFF;
7159 + mms[i].mask.src.u.tcp.port = 0xFFFF;
7160 + mms[i].help = mms_nat_help;
7161 + mms[i].me = THIS_MODULE;
7163 + mms[i].expect = mms_nat_expected;
7165 + tmpname = &mms_names[i][0];
7166 + if (ports[i] == MMS_PORT)
7167 + sprintf(tmpname, "mms");
7169 + sprintf(tmpname, "mms-%d", i);
7170 + mms[i].name = tmpname;
7172 + DEBUGP("ip_nat_mms: register helper for port %d\n",
7174 + ret = ip_nat_helper_register(&mms[i]);
7177 + printk("ip_nat_mms: error registering "
7178 + "helper for port %d\n", ports[i]);
7190 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_quake3.c
7191 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
7192 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-06-08 10:40:36.000000000 +0200
7194 +/* Quake3 extension for UDP NAT alteration.
7195 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7196 + * based on ip_nat_ftp.c and ip_nat_tftp.c
7198 + * ip_nat_quake3.c v0.0.3 2002-08-31
7200 + * This program is free software; you can redistribute it and/or
7201 + * modify it under the terms of the GNU General Public License
7202 + * as published by the Free Software Foundation; either version
7203 + * 2 of the License, or (at your option) any later version.
7205 + * Module load syntax:
7206 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
7208 + * please give the ports of all Quake3 master servers You wish to
7209 + * connect to. If you don't specify ports, the default will be UDP
7212 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
7215 + * - If you're one of those people who would try anything to lower
7216 + * latency while playing Quake (and who isn't :-) ), you may want to
7217 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
7218 + * outgoing UDP traffic.
7219 + * This will make ip_conntrack_quake3 add the necessary expectations,
7220 + * but there will be no overhead for client->server UDP streams. If
7221 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
7222 + * hook for every packet in the client->server UDP stream.
7223 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
7224 + * The IP addresses in the master connection payload (=IP addresses
7225 + * of Quake servers) have no relation with the master server so
7226 + * DNAT'ing the master connection to a server should not change the
7227 + * expected connections.
7228 + * - Not tested due to lack of equipment:
7229 + * - multiple Quake3 clients behind one MASQUERADE gateway
7230 + * - what if Quake3 client is running on router too
7233 +#include <linux/module.h>
7234 +#include <linux/netfilter_ipv4.h>
7235 +#include <linux/ip.h>
7236 +#include <linux/udp.h>
7238 +#include <linux/netfilter.h>
7239 +#include <linux/netfilter_ipv4/ip_tables.h>
7240 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7241 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
7242 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7243 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7245 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7246 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
7247 +MODULE_LICENSE("GPL");
7249 +#define MAX_PORTS 8
7251 +static int ports[MAX_PORTS];
7252 +static int ports_c = 0;
7254 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7255 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7258 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7259 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7261 +#define DEBUGP printk
7263 +#define DEBUGP(format, args...)
7266 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7268 +static unsigned int
7269 +quake3_nat_help(struct ip_conntrack *ct,
7270 + struct ip_conntrack_expect *exp,
7271 + struct ip_nat_info *info,
7272 + enum ip_conntrack_info ctinfo,
7273 + unsigned int hooknum,
7274 + struct sk_buff **pskb)
7276 + struct iphdr *iph = (*pskb)->nh.iph;
7277 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7278 + struct ip_conntrack_tuple repl;
7279 + int dir = CTINFO2DIR(ctinfo);
7282 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7283 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7284 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7285 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7286 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7288 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7289 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7291 + /* Only mangle things once: original direction in POST_ROUTING
7292 + and reply direction on PRE_ROUTING. */
7293 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7294 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7295 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7296 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7297 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7298 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7299 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7304 + DEBUGP("no conntrack expectation to modify\n");
7308 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7309 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7310 + i+6 < ntohs(udph->len);
7312 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
7313 + i, ntohs(udph->len),
7314 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7315 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7317 + memset(&repl, 0, sizeof(repl));
7319 + repl.dst.protonum = IPPROTO_UDP;
7320 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7321 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7322 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
7324 + ip_conntrack_change_expect(exp, &repl);
7330 +static unsigned int
7331 +quake3_nat_expected(struct sk_buff **pskb,
7332 + unsigned int hooknum,
7333 + struct ip_conntrack *ct,
7334 + struct ip_nat_info *info)
7336 + const struct ip_conntrack *master = ct->master->expectant;
7337 + struct ip_nat_multi_range mr;
7338 + u_int32_t newsrcip, newdstip, newip;
7340 + const struct ip_conntrack_tuple *repl =
7341 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7342 + struct iphdr *iph = (*pskb)->nh.iph;
7343 + struct udphdr *udph = (void *)iph + iph->ihl*4;
7346 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7347 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7349 + IP_NF_ASSERT(info);
7350 + IP_NF_ASSERT(master);
7351 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7353 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7354 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7356 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7358 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7359 + "newsrc: %u.%u.%u.%u\n",
7360 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7361 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7362 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7363 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7364 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7369 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7370 + "newdst: %u.%u.%u.%u\n",
7371 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7372 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7373 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7374 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7375 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7380 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7381 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7383 + return ip_nat_setup_info(ct,&mr,hooknum);
7386 +static struct ip_nat_helper quake3[MAX_PORTS];
7387 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
7389 +static void fini(void)
7393 + for (i = 0 ; i < ports_c; i++) {
7394 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7395 + ip_nat_helper_unregister(&quake3[i]);
7399 +static int __init init(void)
7405 + ports[0] = QUAKE3_MASTER_PORT;
7407 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7408 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7410 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7411 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7412 + quake3[i].mask.dst.protonum = 0xFFFF;
7413 + quake3[i].mask.src.u.udp.port = 0xFFFF;
7414 + quake3[i].help = quake3_nat_help;
7415 + quake3[i].flags = 0;
7416 + quake3[i].me = THIS_MODULE;
7417 + quake3[i].expect = quake3_nat_expected;
7419 + tmpname = &quake3_names[i][0];
7420 + if (ports[i] == QUAKE3_MASTER_PORT)
7421 + sprintf(tmpname, "quake3");
7423 + sprintf(tmpname, "quake3-%d", i);
7424 + quake3[i].name = tmpname;
7426 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7427 + ports[i], quake3[i].name);
7428 + ret = ip_nat_helper_register(&quake3[i]);
7431 + printk("ip_nat_quake3: unable to register helper for port %d\n",
7443 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
7444 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
7445 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-06-08 10:40:46.000000000 +0200
7448 + * RTSP extension for TCP NAT alteration
7449 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7450 + * based on ip_nat_irc.c
7452 + * This program is free software; you can redistribute it and/or
7453 + * modify it under the terms of the GNU General Public License
7454 + * as published by the Free Software Foundation; either version
7455 + * 2 of the License, or (at your option) any later version.
7457 + * Module load syntax:
7458 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7459 + * stunaddr=<address>
7460 + * destaction=[auto|strip|none]
7462 + * If no ports are specified, the default will be port 554 only.
7464 + * stunaddr specifies the address used to detect that a client is using STUN.
7465 + * If this address is seen in the destination parameter, it is assumed that
7466 + * the client has already punched a UDP hole in the firewall, so we don't
7467 + * mangle the client_port. If none is specified, it is autodetected. It
7468 + * only needs to be set if you have multiple levels of NAT. It should be
7469 + * set to the external address that the STUN clients detect. Note that in
7470 + * this case, it will not be possible for clients to use UDP with servers
7471 + * between the NATs.
7473 + * If no destaction is specified, auto is used.
7474 + * destaction=auto: strip destination parameter if it is not stunaddr.
7475 + * destaction=strip: always strip destination parameter (not recommended).
7476 + * destaction=none: do not touch destination parameter (not recommended).
7479 +#include <linux/module.h>
7480 +#include <linux/netfilter_ipv4.h>
7481 +#include <linux/ip.h>
7482 +#include <linux/tcp.h>
7483 +#include <linux/kernel.h>
7484 +#include <net/tcp.h>
7485 +#include <linux/netfilter_ipv4/ip_nat.h>
7486 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7487 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7488 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7489 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7491 +#include <linux/inet.h>
7492 +#include <linux/ctype.h>
7493 +#define NF_NEED_STRNCASECMP
7494 +#define NF_NEED_STRTOU16
7495 +#include <linux/netfilter_helpers.h>
7496 +#define NF_NEED_MIME_NEXTLINE
7497 +#include <linux/netfilter_mime.h>
7499 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7500 +#ifdef IP_NF_RTSP_DEBUG
7501 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7503 +#define DEBUGP(fmt, args...)
7506 +#define MAX_PORTS 8
7507 +#define DSTACT_AUTO 0
7508 +#define DSTACT_STRIP 1
7509 +#define DSTACT_NONE 2
7511 +static int ports[MAX_PORTS];
7512 +static char* stunaddr = NULL;
7513 +static char* destaction = NULL;
7515 +static int num_ports = 0;
7516 +static u_int32_t extip = 0;
7517 +static int dstact = 0;
7519 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7520 +MODULE_DESCRIPTION("RTSP network address translation module");
7521 +MODULE_LICENSE("GPL");
7523 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7524 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7525 +MODULE_PARM(stunaddr, "s");
7526 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7527 +MODULE_PARM(destaction, "s");
7528 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7531 +/* protects rtsp part of conntracks */
7532 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7534 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7536 +/*** helper functions ***/
7539 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7541 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7542 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7544 + *pptcpdata = (char*)tcph + tcph->doff*4;
7545 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7548 +/*** nat functions ***/
7551 + * Mangle the "Transport:" header:
7552 + * - Replace all occurences of "client_port=<spec>"
7553 + * - Handle destination parameter
7556 + * ct, ctinfo = conntrack context
7558 + * tranoff = Transport header offset from TCP data
7559 + * tranlen = Transport header length (incl. CRLF)
7560 + * rport_lo = replacement low port (host endian)
7561 + * rport_hi = replacement high port (host endian)
7563 + * Returns packet size difference.
7565 + * Assumes that a complete transport header is present, ending with CR or LF
7568 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7569 + struct ip_conntrack_expect* exp,
7570 + struct sk_buff** pskb, uint tranoff, uint tranlen)
7575 + char rbuf1[16]; /* Replacement buffer (one port) */
7576 + uint rbuf1len; /* Replacement len (one port) */
7577 + char rbufa[16]; /* Replacement buffer (all ports) */
7578 + uint rbufalen; /* Replacement len (all ports) */
7580 + u_int16_t loport, hiport;
7582 + uint diff; /* Number of bytes we removed */
7584 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7585 + struct ip_conntrack_tuple t;
7587 + char szextaddr[15+1];
7591 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7592 + ptran = ptcp+tranoff;
7594 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7595 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7596 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
7598 + INFOP("sanity check failed\n");
7602 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7604 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7608 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7609 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7610 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7612 + rbuf1len = rbufalen = 0;
7613 + switch (prtspexp->pbtype)
7616 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7618 + t.dst.u.udp.port = htons(loport);
7619 + if (ip_conntrack_change_expect(exp, &t) == 0)
7621 + DEBUGP("using port %hu\n", loport);
7627 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7628 + rbufalen = sprintf(rbufa, "%hu", loport);
7632 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7634 + t.dst.u.udp.port = htons(loport);
7635 + if (ip_conntrack_change_expect(exp, &t) == 0)
7637 + hiport = loport + ~exp->mask.dst.u.udp.port;
7638 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
7644 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7645 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7649 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7651 + t.dst.u.udp.port = htons(loport);
7652 + if (ip_conntrack_change_expect(exp, &t) == 0)
7654 + DEBUGP("using port %hu (1 of 2)\n", loport);
7658 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7660 + t.dst.u.udp.port = htons(hiport);
7661 + if (ip_conntrack_change_expect(exp, &t) == 0)
7663 + DEBUGP("using port %hu (2 of 2)\n", hiport);
7667 + if (loport != 0 && hiport != 0)
7669 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7670 + if (hiport == loport+1)
7672 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7676 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7682 + if (rbuf1len == 0)
7684 + return 0; /* cannot get replacement port(s) */
7687 + /* Transport: tran;field;field=val,tran;field;field=val,... */
7688 + while (off < tranlen)
7691 + const char* pparamend;
7692 + uint nextparamoff;
7694 + pparamend = memchr(ptran+off, ',', tranlen-off);
7695 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7696 + nextparamoff = pparamend-ptcp;
7699 + * We pass over each param twice. On the first pass, we look for a
7700 + * destination= field. It is handled by the security policy. If it
7701 + * is present, allowed, and equal to our external address, we assume
7702 + * that STUN is being used and we leave the client_port= field alone.
7706 + while (off < nextparamoff)
7708 + const char* pfieldend;
7709 + uint nextfieldoff;
7711 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7712 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7714 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7716 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7720 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7722 + diff = nextfieldoff-off;
7723 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7724 + off, diff, NULL, 0))
7726 + /* mangle failed, all we can do is bail */
7729 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7730 + ptran = ptcp+tranoff;
7732 + nextparamoff -= diff;
7733 + nextfieldoff -= diff;
7737 + off = nextfieldoff;
7744 + while (off < nextparamoff)
7746 + const char* pfieldend;
7747 + uint nextfieldoff;
7749 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7750 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7752 + if (strncmp(ptran+off, "client_port=", 12) == 0)
7758 + char* rbuf = rbuf1;
7759 + uint rbuflen = rbuf1len;
7762 + origoff = (ptran-ptcp)+off;
7764 + numlen = nf_strtou16(ptran+off, &port);
7766 + origlen += numlen;
7767 + if (port != prtspexp->loport)
7769 + DEBUGP("multiple ports found, port %hu ignored\n", port);
7773 + if (ptran[off] == '-' || ptran[off] == '/')
7777 + numlen = nf_strtou16(ptran+off, &port);
7779 + origlen += numlen;
7781 + rbuflen = rbufalen;
7785 + * note we cannot just memcpy() if the sizes are the same.
7786 + * the mangle function does skb resizing, checks for a
7787 + * cloned skb, and updates the checksums.
7789 + * parameter 4 below is offset from start of tcp data.
7791 + diff = origlen-rbuflen;
7792 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7793 + origoff, origlen, rbuf, rbuflen))
7795 + /* mangle failed, all we can do is bail */
7798 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7799 + ptran = ptcp+tranoff;
7801 + nextparamoff -= diff;
7802 + nextfieldoff -= diff;
7806 + off = nextfieldoff;
7809 + off = nextparamoff;
7815 +static unsigned int
7816 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7818 + struct ip_nat_multi_range mr;
7819 + u_int32_t newdstip, newsrcip, newip;
7821 + struct ip_conntrack *master = master_ct(ct);
7823 + IP_NF_ASSERT(info);
7824 + IP_NF_ASSERT(master);
7826 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7828 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7829 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7830 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7832 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7833 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7836 + /* We don't want to manip the per-protocol, just the IPs. */
7837 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7838 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7840 + return ip_nat_setup_info(ct, &mr, hooknum);
7844 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7845 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7855 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7856 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7858 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7860 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7862 + hdrsoff = exp->seq - ntohl(tcph->seq);
7863 + hdrslen = prtspexp->len;
7866 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7872 + if (off > hdrsoff+hdrslen)
7874 + INFOP("!! overrun !!");
7877 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7879 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7881 + uint oldtcplen = tcplen;
7882 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7886 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7887 + hdrslen -= (oldtcplen-tcplen);
7888 + off -= (oldtcplen-tcplen);
7889 + lineoff -= (oldtcplen-tcplen);
7890 + linelen -= (oldtcplen-tcplen);
7891 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7899 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7900 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7902 + /* XXX: unmangle */
7907 +help(struct ip_conntrack* ct,
7908 + struct ip_conntrack_expect* exp,
7909 + struct ip_nat_info* info,
7910 + enum ip_conntrack_info ctinfo,
7911 + unsigned int hooknum,
7912 + struct sk_buff** pskb)
7914 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7915 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7918 + struct ip_ct_rtsp_expect* ct_rtsp_info;
7919 + int rc = NF_ACCEPT;
7921 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7923 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7927 + ct_rtsp_info = &exp->help.exp_rtsp_info;
7930 + * Only mangle things once: original direction in POST_ROUTING
7931 + * and reply direction on PRE_ROUTING.
7933 + dir = CTINFO2DIR(ctinfo);
7934 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7935 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7937 + DEBUGP("Not touching dir %s at hook %s\n",
7938 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7939 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7940 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7941 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7944 + DEBUGP("got beyond not touching\n");
7946 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7948 + LOCK_BH(&ip_rtsp_lock);
7949 + /* Ensure the packet contains all of the marked data */
7950 + if (!between(exp->seq + ct_rtsp_info->len,
7951 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7953 + /* Partial retransmission? Probably a hacker. */
7954 + if (net_ratelimit())
7956 + INFOP("partial packet %u/%u in %u/%u\n",
7957 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7959 + UNLOCK_BH(&ip_rtsp_lock);
7965 + case IP_CT_DIR_ORIGINAL:
7966 + rc = help_out(ct, ctinfo, exp, pskb);
7968 + case IP_CT_DIR_REPLY:
7969 + rc = help_in(ct, ctinfo, exp, pskb);
7972 + UNLOCK_BH(&ip_rtsp_lock);
7977 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7978 +static char rtsp_names[MAX_PORTS][10];
7980 +/* This function is intentionally _NOT_ defined as __exit */
7986 + for (i = 0; i < num_ports; i++)
7988 + DEBUGP("unregistering helper for port %d\n", ports[i]);
7989 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7998 + struct ip_nat_helper* hlpr;
8001 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
8003 + if (ports[0] == 0)
8005 + ports[0] = RTSP_PORT;
8008 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
8010 + hlpr = &ip_nat_rtsp_helpers[i];
8011 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
8013 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
8014 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
8015 + hlpr->mask.src.u.tcp.port = 0xFFFF;
8016 + hlpr->mask.dst.protonum = 0xFFFF;
8017 + hlpr->help = help;
8019 + hlpr->me = THIS_MODULE;
8020 + hlpr->expect = expected;
8022 + tmpname = &rtsp_names[i][0];
8023 + if (ports[i] == RTSP_PORT)
8025 + sprintf(tmpname, "rtsp");
8029 + sprintf(tmpname, "rtsp-%d", i);
8031 + hlpr->name = tmpname;
8033 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
8034 + ret = ip_nat_helper_register(hlpr);
8038 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
8044 + if (stunaddr != NULL)
8046 + extip = in_aton(stunaddr);
8048 + if (destaction != NULL)
8050 + if (strcmp(destaction, "auto") == 0)
8052 + dstact = DSTACT_AUTO;
8054 + if (strcmp(destaction, "strip") == 0)
8056 + dstact = DSTACT_STRIP;
8058 + if (strcmp(destaction, "none") == 0)
8060 + dstact = DSTACT_NONE;
8068 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rule.c
8069 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rule.c 2004-06-07 21:14:10.000000000 +0200
8070 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rule.c 2004-06-08 10:37:30.000000000 +0200
8073 sizeof(struct ipt_entry),
8074 sizeof(struct ipt_standard),
8075 - 0, { 0, 0 }, { } },
8076 + 0, NULL, 0, { 0, 0 }, { } },
8077 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
8082 sizeof(struct ipt_entry),
8083 sizeof(struct ipt_standard),
8084 - 0, { 0, 0 }, { } },
8085 + 0, NULL, 0, { 0, 0 }, { } },
8086 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
8091 sizeof(struct ipt_entry),
8092 sizeof(struct ipt_standard),
8093 - 0, { 0, 0 }, { } },
8094 + 0, NULL, 0, { 0, 0 }, { } },
8095 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
8100 sizeof(struct ipt_entry),
8101 sizeof(struct ipt_error),
8102 - 0, { 0, 0 }, { } },
8103 + 0, NULL, 0, { 0, 0 }, { } },
8104 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
8107 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_standalone.c
8108 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-07 21:14:56.000000000 +0200
8109 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-08 10:38:45.000000000 +0200
8110 @@ -176,6 +176,45 @@
8111 return do_bindings(ct, ctinfo, info, hooknum, pskb);
8114 +struct nat_route_key
8123 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
8125 + struct iphdr *iph = skb->nh.iph;
8127 + key->addr = which ? iph->daddr : iph->saddr;
8130 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8131 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8132 + key->port = ports[which];
8138 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
8140 + struct iphdr *iph = skb->nh.iph;
8142 + if (key->addr != (which ? iph->daddr : iph->saddr))
8145 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8146 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8147 + if (key->port != ports[which])
8154 ip_nat_out(unsigned int hooknum,
8155 struct sk_buff **pskb,
8157 const struct net_device *out,
8158 int (*okfn)(struct sk_buff *))
8160 + struct nat_route_key key;
8163 /* root is playing with raw sockets. */
8164 if ((*pskb)->len < sizeof(struct iphdr)
8165 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8166 @@ -205,7 +247,29 @@
8170 - return ip_nat_fn(hooknum, pskb, in, out, okfn);
8171 + nat_route_key_get(*pskb, &key, 0);
8172 + ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8174 + if (ret != NF_DROP && ret != NF_STOLEN
8175 + && nat_route_key_compare(*pskb, &key, 0)) {
8176 + if (ip_route_me_harder(pskb) != 0)
8180 + * POST_ROUTING hook is called with fixed outfn, we need
8181 + * to manually confirm the packet and direct it to the
8182 + * transformers if a policy matches.
8184 + else if ((*pskb)->dst->xfrm != NULL) {
8185 + ret = ip_conntrack_confirm(*pskb);
8186 + if (ret != NF_DROP) {
8187 + dst_output(*pskb);
8196 #ifdef CONFIG_IP_NF_NAT_LOCAL
8198 const struct net_device *out,
8199 int (*okfn)(struct sk_buff *))
8201 - u_int32_t saddr, daddr;
8202 + struct nat_route_key key;
8205 /* root is playing with raw sockets. */
8206 @@ -224,14 +288,14 @@
8207 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8210 - saddr = (*pskb)->nh.iph->saddr;
8211 - daddr = (*pskb)->nh.iph->daddr;
8213 + nat_route_key_get(*pskb, &key, 1);
8214 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8216 if (ret != NF_DROP && ret != NF_STOLEN
8217 - && ((*pskb)->nh.iph->saddr != saddr
8218 - || (*pskb)->nh.iph->daddr != daddr))
8219 - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
8220 + && nat_route_key_compare(*pskb, &key, 1)) {
8221 + if (ip_route_me_harder(pskb) != 0)
8227 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_talk.c
8228 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
8229 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-06-08 10:41:27.000000000 +0200
8232 + * talk extension for UDP NAT alteration.
8233 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8235 + * This program is free software; you can redistribute it and/or
8236 + * modify it under the terms of the GNU General Public License
8237 + * as published by the Free Software Foundation; either version
8238 + * 2 of the License, or (at your option) any later version.
8240 + * Module load syntax:
8241 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
8243 + * talk=[0|1] disable|enable old talk support
8244 + * ntalk=[0|1] disable|enable ntalk support
8245 + * ntalk2=[0|1] disable|enable ntalk2 support
8247 + * The default is talk=1 ntalk=1 ntalk2=1
8251 +#include <linux/module.h>
8252 +#include <linux/netfilter_ipv4.h>
8253 +#include <linux/ip.h>
8254 +#include <linux/udp.h>
8255 +#include <linux/kernel.h>
8256 +#include <net/tcp.h>
8257 +#include <net/udp.h>
8259 +#include <linux/netfilter_ipv4/ip_nat.h>
8260 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8261 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8262 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8263 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8265 +/* Default all talk protocols are supported */
8266 +static int talk = 1;
8267 +static int ntalk = 1;
8268 +static int ntalk2 = 1;
8269 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8270 +MODULE_DESCRIPTION("talk network address translation module");
8272 +MODULE_PARM(talk, "i");
8273 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8274 +MODULE_PARM(ntalk, "i");
8275 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8276 +MODULE_PARM(ntalk2, "i");
8277 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8281 +#define DEBUGP printk
8282 +#define IP_NAT_TALK_DEBUG
8284 +#define DEBUGP(format, args...)
8287 +/* FIXME: Time out? --RR */
8290 +mangle_packet(struct sk_buff **pskb,
8291 + struct ip_conntrack *ct,
8294 + struct talk_addr *addr,
8295 + struct talk_addr *ctl_addr)
8297 + struct iphdr *iph = (*pskb)->nh.iph;
8298 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8299 + size_t udplen = (*pskb)->len - iph->ihl * 4;
8301 + /* Fortunately talk sends a structure with the address and
8302 + port in it. The size of the packet won't change. */
8304 + if (ctl_addr == NULL) {
8306 + if (addr->ta_addr == INADDR_ANY)
8308 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8309 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8310 + NIPQUAD(newip), ntohs(port));
8311 + addr->ta_addr = newip;
8312 + addr->ta_port = port;
8315 + if (addr->ta_addr != INADDR_ANY) {
8316 + /* Change address inside packet to match way we're mapping
8317 + this connection. */
8318 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8319 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8320 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
8321 + ntohs(addr->ta_port));
8322 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8324 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8325 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8326 + NIPQUAD(newip), ntohs(port));
8327 + ctl_addr->ta_addr = newip;
8328 + ctl_addr->ta_port = port;
8331 + /* Fix checksums */
8332 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8334 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8335 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8337 + ip_send_check(iph);
8341 +static int talk_help_msg(struct ip_conntrack *ct,
8342 + struct sk_buff **pskb,
8344 + struct talk_addr *addr,
8345 + struct talk_addr *ctl_addr)
8350 + unsigned int verdict = NF_ACCEPT;
8352 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8353 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8354 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8357 + /* Change address inside packet to match way we're mapping
8358 + this connection. */
8359 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8360 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8361 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8362 + NIPQUAD(newip), ntohs(port));
8364 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8365 + verdict = NF_DROP;
8370 +static int talk_help_response(struct ip_conntrack *ct,
8371 + struct ip_conntrack_expect *exp,
8372 + struct sk_buff **pskb,
8375 + struct talk_addr *addr)
8379 + struct ip_conntrack_tuple t;
8380 + struct ip_ct_talk_expect *ct_talk_info;
8382 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8383 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8386 + LOCK_BH(&ip_talk_lock);
8387 + ct_talk_info = &exp->help.exp_talk_info;
8389 + if (!(answer == SUCCESS
8390 + && (type == LOOK_UP || type == ANNOUNCE)
8391 + && exp != NULL)) {
8392 + UNLOCK_BH(&ip_talk_lock);
8396 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
8397 + ntohs(ct_talk_info->port),
8398 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8400 + /* Change address inside packet to match way we're mapping
8401 + this connection. */
8402 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
8403 + IP_CT_DIR_REPLY].tuple.dst.ip;
8404 + /* We can read expect here without conntrack lock, since it's
8405 + only set in ip_conntrack_talk , with ip_talk_lock held
8410 + /* Try to get same port: if not, try to change it. */
8411 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8412 + if (type == LOOK_UP)
8413 + t.dst.u.tcp.port = htons(port);
8415 + t.dst.u.udp.port = htons(port);
8417 + if (ip_conntrack_change_expect(exp, &t) == 0) {
8418 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8422 + UNLOCK_BH(&ip_talk_lock);
8424 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8430 +static unsigned int talk_help(struct ip_conntrack *ct,
8431 + struct ip_conntrack_expect *exp,
8432 + struct ip_nat_info *info,
8433 + enum ip_conntrack_info ctinfo,
8434 + unsigned int hooknum,
8435 + struct sk_buff **pskb,
8438 + struct iphdr *iph = (*pskb)->nh.iph;
8439 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8440 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8441 + char *data = (char *)udph + sizeof(struct udphdr);
8444 + /* Only mangle things once: original direction in POST_ROUTING
8445 + and reply direction on PRE_ROUTING. */
8446 + dir = CTINFO2DIR(ctinfo);
8447 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8448 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8449 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8450 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8451 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8452 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8453 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8456 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8457 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8458 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8459 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8460 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8461 + NIPQUAD(iph->saddr), ntohs(udph->source),
8462 + NIPQUAD(iph->daddr), ntohs(udph->dest),
8465 + /* Because conntrack does not drop packets, checking must be repeated here... */
8466 + if (talk_port == TALK_PORT) {
8467 + if (dir == IP_CT_DIR_ORIGINAL
8468 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8469 + return talk_help_msg(ct, pskb,
8470 + ((struct talk_msg *)data)->type,
8471 + &(((struct talk_msg *)data)->addr),
8472 + &(((struct talk_msg *)data)->ctl_addr));
8473 + else if (dir == IP_CT_DIR_REPLY
8474 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8475 + return talk_help_response(ct, exp, pskb,
8476 + ((struct talk_response *)data)->type,
8477 + ((struct talk_response *)data)->answer,
8478 + &(((struct talk_response *)data)->addr));
8480 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8481 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
8482 + (unsigned)udplen - sizeof(struct udphdr),
8483 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8487 + if (dir == IP_CT_DIR_ORIGINAL) {
8489 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8490 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8491 + return talk_help_msg(ct, pskb,
8492 + ((struct ntalk_msg *)data)->type,
8493 + &(((struct ntalk_msg *)data)->addr),
8494 + &(((struct ntalk_msg *)data)->ctl_addr));
8496 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8497 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8498 + && udplen == sizeof(struct udphdr)
8499 + + sizeof(struct ntalk2_msg)
8500 + + ((struct ntalk2_msg *)data)->extended)
8501 + return talk_help_msg(ct, pskb,
8502 + ((struct ntalk2_msg *)data)->type,
8503 + &(((struct ntalk2_msg *)data)->addr),
8504 + &(((struct ntalk2_msg *)data)->ctl_addr));
8506 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8507 + (unsigned)udplen - sizeof(struct udphdr),
8508 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8513 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8514 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8515 + return talk_help_response(ct, exp, pskb,
8516 + ((struct ntalk_response *)data)->type,
8517 + ((struct ntalk_response *)data)->answer,
8518 + &(((struct ntalk_response *)data)->addr));
8520 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8521 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8522 + return talk_help_response(ct, exp, pskb,
8523 + ((struct ntalk2_response *)data)->type,
8524 + ((struct ntalk2_response *)data)->answer,
8525 + &(((struct ntalk2_response *)data)->addr));
8527 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8528 + (unsigned)udplen - sizeof(struct udphdr),
8529 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8536 +static unsigned int help(struct ip_conntrack *ct,
8537 + struct ip_conntrack_expect *exp,
8538 + struct ip_nat_info *info,
8539 + enum ip_conntrack_info ctinfo,
8540 + unsigned int hooknum,
8541 + struct sk_buff **pskb)
8543 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8546 +static unsigned int nhelp(struct ip_conntrack *ct,
8547 + struct ip_conntrack_expect *exp,
8548 + struct ip_nat_info *info,
8549 + enum ip_conntrack_info ctinfo,
8550 + unsigned int hooknum,
8551 + struct sk_buff **pskb)
8553 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8556 +static unsigned int
8557 +talk_nat_expected(struct sk_buff **pskb,
8558 + unsigned int hooknum,
8559 + struct ip_conntrack *ct,
8560 + struct ip_nat_info *info);
8562 +static struct ip_nat_helper talk_helpers[2] =
8563 + { { { NULL, NULL },
8564 + "talk", /* name */
8565 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8566 + THIS_MODULE, /* module */
8567 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8568 + { 0, { 0 }, IPPROTO_UDP } },
8569 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8570 + { 0, { 0 }, 0xFFFF } },
8571 + help, /* helper */
8572 + talk_nat_expected }, /* expectfn */
8574 + "ntalk", /* name */
8575 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8576 + THIS_MODULE, /* module */
8577 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8578 + { 0, { 0 }, IPPROTO_UDP } },
8579 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8580 + { 0, { 0 }, 0xFFFF } },
8581 + nhelp, /* helper */
8582 + talk_nat_expected } /* expectfn */
8585 +static unsigned int
8586 +talk_nat_expected(struct sk_buff **pskb,
8587 + unsigned int hooknum,
8588 + struct ip_conntrack *ct,
8589 + struct ip_nat_info *info)
8591 + struct ip_nat_multi_range mr;
8592 + u_int32_t newdstip, newsrcip, newip;
8596 + struct ip_conntrack *master = master_ct(ct);
8598 + IP_NF_ASSERT(info);
8599 + IP_NF_ASSERT(master);
8601 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8603 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8605 + LOCK_BH(&ip_talk_lock);
8606 + port = ct->master->help.exp_talk_info.port;
8607 + UNLOCK_BH(&ip_talk_lock);
8609 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8610 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8611 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8612 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8613 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8616 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8617 + /* Callee client -> caller server */
8618 +#ifdef IP_NAT_TALK_DEBUG
8619 + struct iphdr *iph = (*pskb)->nh.iph;
8620 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8622 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8623 + NIPQUAD(iph->saddr), ntohs(udph->source),
8624 + NIPQUAD(iph->daddr), ntohs(udph->dest));
8626 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8627 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8628 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8629 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8631 + /* Callee client -> caller client */
8632 +#ifdef IP_NAT_TALK_DEBUG
8633 + struct iphdr *iph = (*pskb)->nh.iph;
8634 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8636 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8637 + NIPQUAD(iph->saddr), ntohs(tcph->source),
8638 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
8640 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8641 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8642 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8643 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8645 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8650 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8653 + /* We don't want to manip the per-protocol, just the IPs... */
8654 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8655 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8657 + /* ... unless we're doing a MANIP_DST, in which case, make
8658 + sure we map to the correct port */
8659 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8660 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8661 + mr.range[0].min = mr.range[0].max
8662 + = ((union ip_conntrack_manip_proto)
8663 + { .udp = { port } });
8665 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8667 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8668 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8669 + /* NAT expectfn called with ip_nat_lock write-locked */
8670 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
8675 +static int __init init(void)
8680 + ret = ip_nat_helper_register(&talk_helpers[0]);
8685 + if (ntalk > 0 || ntalk2 > 0) {
8686 + ret = ip_nat_helper_register(&talk_helpers[1]);
8688 + if (ret != 0 && talk > 0)
8689 + ip_nat_helper_unregister(&talk_helpers[0]);
8694 +static void __exit fini(void)
8697 + ip_nat_helper_unregister(&talk_helpers[0]);
8698 + if (ntalk > 0 || ntalk2 > 0)
8699 + ip_nat_helper_unregister(&talk_helpers[1]);
8704 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_pool.c
8705 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
8706 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_pool.c 2004-06-08 10:31:45.000000000 +0200
8708 +/* Kernel module for IP pool management */
8710 +#include <linux/module.h>
8711 +#include <linux/ip.h>
8712 +#include <linux/skbuff.h>
8713 +#include <linux/netfilter_ipv4/ip_tables.h>
8714 +#include <linux/netfilter_ipv4/ip_pool.h>
8715 +#include <linux/errno.h>
8716 +#include <asm/uaccess.h>
8717 +#include <asm/bitops.h>
8718 +#include <linux/interrupt.h>
8719 +#include <linux/spinlock.h>
8724 +#define DP(format, args...)
8727 +MODULE_LICENSE("GPL");
8730 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8733 + u_int32_t first_ip; /* host byte order, included in range */
8734 + u_int32_t last_ip; /* host byte order, included in range */
8735 + void *members; /* the bitmap proper */
8736 + int nr_use; /* total nr. of tests through this */
8737 + int nr_match; /* total nr. of matches through this */
8741 +static struct ip_pool *POOL;
8743 +static inline struct ip_pool *lookup(ip_pool_t index)
8745 + if (index < 0 || index >= nr_pool) {
8746 + DP("ip_pool:lookup: bad index %d\n", index);
8749 + return POOL+index;
8752 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8754 + struct ip_pool *pool = lookup(index);
8757 + if (!pool || !pool->members)
8759 + read_lock_bh(&pool->lock);
8760 + if (pool->members) {
8761 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
8762 + addr -= pool->first_ip;
8763 + if (test_bit(addr, pool->members)) {
8765 +#ifdef CONFIG_IP_POOL_STATISTICS
8770 +#ifdef CONFIG_IP_POOL_STATISTICS
8774 + read_unlock_bh(&pool->lock);
8777 +EXPORT_SYMBOL(ip_pool_match);
8779 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8781 + struct ip_pool *pool;
8784 + pool = lookup(index);
8785 + if ( !pool || !pool->members
8786 + || addr < pool->first_ip || addr > pool->last_ip)
8788 + read_lock_bh(&pool->lock);
8789 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8790 + addr -= pool->first_ip;
8792 + ? (0 != test_and_clear_bit(addr, pool->members))
8793 + : (0 != test_and_set_bit(addr, pool->members));
8795 + read_unlock_bh(&pool->lock);
8799 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8801 + int res = pool_change(index,addr,isdel);
8803 + if (!isdel) res = !res;
8806 +EXPORT_SYMBOL(ip_pool_mod);
8808 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8810 + return 4*((((b-a+8)/8)+3)/4);
8813 +static inline int poolbytes(ip_pool_t index)
8815 + struct ip_pool *pool = lookup(index);
8817 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8820 +static int setpool(
8826 + struct ip_pool_request req;
8828 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8829 + if (!capable(CAP_NET_ADMIN))
8831 + if (optval != SO_IP_POOL)
8833 + if (len != sizeof(req))
8835 + if (copy_from_user(&req, user, sizeof(req)) != 0)
8837 + printk("obsolete op - upgrade your ippool(8) utility.\n");
8841 +static int getpool(
8847 + struct ip_pool_request req;
8848 + struct ip_pool *pool;
8854 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8855 + if (!capable(CAP_NET_ADMIN))
8857 + if (optval != SO_IP_POOL)
8859 + if (*len != sizeof(req)) {
8862 + if (copy_from_user(&req, user, sizeof(req)) != 0)
8864 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8865 + if (req.op < IP_POOL_BAD001) {
8866 + printk("obsolete op - upgrade your ippool(8) utility.\n");
8870 + case IP_POOL_HIGH_NR:
8871 + DP("ip_pool HIGH_NR\n");
8872 + req.index = IP_POOL_NONE;
8873 + for (i=0; i<nr_pool; i++)
8874 + if (POOL[i].members)
8876 + return copy_to_user(user, &req, sizeof(req));
8877 + case IP_POOL_LOOKUP:
8878 + DP("ip_pool LOOKUP\n");
8879 + pool = lookup(req.index);
8882 + if (!pool->members)
8884 + req.addr = htonl(pool->first_ip);
8885 + req.addr2 = htonl(pool->last_ip);
8886 + return copy_to_user(user, &req, sizeof(req));
8887 + case IP_POOL_USAGE:
8888 + DP("ip_pool USE\n");
8889 + pool = lookup(req.index);
8892 + if (!pool->members)
8894 + req.addr = pool->nr_use;
8895 + req.addr2 = pool->nr_match;
8896 + return copy_to_user(user, &req, sizeof(req));
8897 + case IP_POOL_TEST_ADDR:
8898 + DP("ip_pool TEST 0x%08x\n", req.addr);
8899 + pool = lookup(req.index);
8903 + read_lock_bh(&pool->lock);
8904 + if (!pool->members) {
8905 + DP("ip_pool TEST_ADDR no members in pool\n");
8907 + goto unlock_and_return_res;
8909 + req.addr = ntohl(req.addr);
8910 + if (req.addr < pool->first_ip) {
8911 + DP("ip_pool TEST_ADDR address < pool bounds\n");
8913 + goto unlock_and_return_res;
8915 + if (req.addr > pool->last_ip) {
8916 + DP("ip_pool TEST_ADDR address > pool bounds\n");
8918 + goto unlock_and_return_res;
8920 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
8922 + read_unlock_bh(&pool->lock);
8923 + return copy_to_user(user, &req, sizeof(req));
8924 + case IP_POOL_FLUSH:
8925 + DP("ip_pool FLUSH not yet implemented.\n");
8927 + case IP_POOL_DESTROY:
8928 + DP("ip_pool DESTROY not yet implemented.\n");
8930 + case IP_POOL_INIT:
8931 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8932 + pool = lookup(req.index);
8935 + req.addr = ntohl(req.addr);
8936 + req.addr2 = ntohl(req.addr2);
8937 + if (req.addr > req.addr2) {
8938 + DP("ip_pool INIT bad ip range\n");
8941 + newbytes = bitmap_bytes(req.addr, req.addr2);
8942 + newmembers = kmalloc(newbytes, GFP_KERNEL);
8943 + if (!newmembers) {
8944 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8947 + memset(newmembers, 0, newbytes);
8948 + write_lock_bh(&pool->lock);
8949 + if (pool->members) {
8950 + DP("ip_pool INIT pool %d exists\n", req.index);
8951 + kfree(newmembers);
8953 + goto unlock_and_return_res;
8955 + pool->first_ip = req.addr;
8956 + pool->last_ip = req.addr2;
8958 + pool->nr_match = 0;
8959 + pool->members = newmembers;
8960 + write_unlock_bh(&pool->lock);
8962 + case IP_POOL_ADD_ADDR:
8963 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8964 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
8965 + return copy_to_user(user, &req, sizeof(req));
8966 + case IP_POOL_DEL_ADDR:
8967 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8968 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
8969 + return copy_to_user(user, &req, sizeof(req));
8971 + DP("ip_pool:getpool bad op %d\n", req.op);
8976 +unlock_and_return_res:
8978 + read_unlock_bh(&pool->lock);
8982 +static struct nf_sockopt_ops so_pool
8983 += { { NULL, NULL }, PF_INET,
8984 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
8985 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
8988 +MODULE_PARM(nr_pool, "i");
8990 +static int __init init(void)
8995 + if (nr_pool < 1) {
8996 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8999 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
9001 + printk("ip_pool module init: out of memory for nr_pool %d\n",
9005 + for (i=0; i<nr_pool; i++) {
9006 + POOL[i].first_ip = 0;
9007 + POOL[i].last_ip = 0;
9008 + POOL[i].members = 0;
9009 + POOL[i].nr_use = 0;
9010 + POOL[i].nr_match = 0;
9011 + POOL[i].lock = RW_LOCK_UNLOCKED;
9013 + res = nf_register_sockopt(&so_pool);
9014 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
9022 +static void __exit fini(void)
9026 + DP("ip_pool:fini BYEBYE\n");
9027 + nf_unregister_sockopt(&so_pool);
9028 + for (i=0; i<nr_pool; i++) {
9029 + if (POOL[i].members) {
9030 + kfree(POOL[i].members);
9031 + POOL[i].members = 0;
9036 + DP("ip_pool:fini these are the famous last words\n");
9042 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_tables.c
9043 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-06-07 21:14:01.000000000 +0200
9044 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_tables.c 2004-06-08 10:37:30.000000000 +0200
9047 #include <linux/netfilter_ipv4/ip_tables.h>
9049 +static const char *hooknames[] = {
9050 + [NF_IP_PRE_ROUTING] "PREROUTING",
9051 + [NF_IP_LOCAL_IN] "INPUT",
9052 + [NF_IP_FORWARD] "FORWARD",
9053 + [NF_IP_LOCAL_OUT] "OUTPUT",
9054 + [NF_IP_POST_ROUTING] "POSTROUTING",
9057 MODULE_LICENSE("GPL");
9058 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
9059 MODULE_DESCRIPTION("IPv4 packet filter");
9060 @@ -323,6 +331,12 @@
9062 t = ipt_get_target(e);
9063 IP_NF_ASSERT(t->u.kernel.target);
9065 + /* The packet traced and the rule isn't an unconditional return/END. */
9066 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
9067 + nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
9068 + table->name, e->chainname, e->rulenum);
9070 /* Standard target? */
9071 if (!t->u.kernel.target->target) {
9074 /* set back pointer to next entry */
9078 e = get_entry(table_base, v);
9080 /* Targets which reenter must return
9081 @@ -475,6 +488,29 @@
9082 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
9086 +find_error_target(struct ipt_entry *s,
9087 + struct ipt_entry *e,
9090 + struct ipt_entry_target *t;
9091 + static struct ipt_entry *found = NULL;
9096 + t = ipt_get_target(found);
9097 + if (strcmp(t->u.user.name,
9098 + IPT_ERROR_TARGET) == 0) {
9099 + *chainname = t->data;
9108 /* All zeroes == unconditional rule. */
9110 unconditional(const struct ipt_ip *ip)
9112 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
9115 + char *chainname = NULL;
9116 + u_int32_t rulenum;
9118 /* No recursion; use packet counter to save back ptrs (reset
9119 to 0 as we leave), and comefrom to save source hook bitmask */
9122 /* Set initial back pointer. */
9123 e->counters.pcnt = pos;
9125 + chainname = (char *) hooknames[hook];
9128 struct ipt_standard_target *t
9132 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
9133 + e->rulenum = rulenum++;
9134 + e->chainname = chainname;
9136 /* Unconditional return/END. */
9137 if (e->target_offset == sizeof(struct ipt_entry)
9138 @@ -528,6 +570,10 @@
9139 && unconditional(&e->ip)) {
9140 unsigned int oldpos, size;
9142 + /* Set unconditional rulenum to zero. */
9144 + e->counters.bcnt = 0;
9146 /* Return: backtrack through the last
9149 @@ -553,6 +599,11 @@
9150 (newinfo->entries + pos);
9151 } while (oldpos == pos + e->next_offset);
9153 + /* Restore chainname, rulenum. */
9154 + chainname = e->chainname;
9155 + rulenum = e->counters.bcnt;
9156 + e->counters.bcnt = 0;
9158 /* Move along one */
9159 size = e->next_offset;
9160 e = (struct ipt_entry *)
9161 @@ -568,6 +619,17 @@
9162 /* This a jump; chase it. */
9163 duprintf("Jump rule %u -> %u\n",
9165 + e->counters.bcnt = rulenum++;
9167 + e = (struct ipt_entry *)
9168 + (newinfo->entries + newpos);
9169 + if (IPT_ENTRY_ITERATE(newinfo->entries,
9171 + find_error_target,
9172 + e, &chainname) == 0) {
9173 + printk("ip_tables: table screwed up!\n");
9177 /* ... this is a fallthru */
9178 newpos = pos + e->next_offset;
9179 @@ -1713,9 +1775,9 @@
9182 #ifdef CONFIG_PROC_FS
9183 -static inline int print_name(const char *i,
9184 - off_t start_offset, char *buffer, int length,
9185 - off_t *pos, unsigned int *count)
9186 +static int print_name(const char *i,
9187 + off_t start_offset, char *buffer, int length,
9188 + off_t *pos, unsigned int *count)
9190 if ((*count)++ >= start_offset) {
9191 unsigned int namelen;
9192 @@ -1749,6 +1811,15 @@
9196 +static inline int print_target(const struct ipt_target *t,
9197 + off_t start_offset, char *buffer, int length,
9198 + off_t *pos, unsigned int *count)
9200 + if (t == &ipt_standard_target || t == &ipt_error_target)
9202 + return print_name((char *)t, start_offset, buffer, length, pos, count);
9205 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
9208 @@ -1757,7 +1828,7 @@
9209 if (down_interruptible(&ipt_mutex) != 0)
9212 - LIST_FIND(&ipt_target, print_name, void *,
9213 + LIST_FIND(&ipt_target, print_target, struct ipt_target *,
9214 offset, buffer, length, &pos, &count);
9217 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
9218 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
9219 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-06-08 10:36:58.000000000 +0200
9221 +/* This kernel module is used to modify the connection mark values, or
9222 + * to optionally restore the skb nfmark from the connection mark
9224 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9225 + * by Henrik Nordstrom <hno@marasystems.com>
9227 + * This program is free software; you can redistribute it and/or modify
9228 + * it under the terms of the GNU General Public License as published by
9229 + * the Free Software Foundation; either version 2 of the License, or
9230 + * (at your option) any later version.
9232 + * This program is distributed in the hope that it will be useful,
9233 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9234 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9235 + * GNU General Public License for more details.
9237 + * You should have received a copy of the GNU General Public License
9238 + * along with this program; if not, write to the Free Software
9239 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9241 +#include <linux/module.h>
9242 +#include <linux/skbuff.h>
9243 +#include <linux/ip.h>
9244 +#include <net/checksum.h>
9246 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9247 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
9248 +MODULE_LICENSE("GPL");
9250 +#include <linux/netfilter_ipv4/ip_tables.h>
9251 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
9252 +#include <linux/netfilter_ipv4/ip_conntrack.h>
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_connmark_target_info *markinfo = targinfo;
9263 + unsigned long diff;
9264 + unsigned long nfmark;
9265 + unsigned long newmark;
9267 + enum ip_conntrack_info ctinfo;
9268 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
9270 + switch(markinfo->mode) {
9271 + case IPT_CONNMARK_SET:
9272 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
9273 + if (newmark != ct->mark)
9274 + ct->mark = newmark;
9276 + case IPT_CONNMARK_SAVE:
9277 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
9278 + if (ct->mark != newmark)
9279 + ct->mark = newmark;
9281 + case IPT_CONNMARK_RESTORE:
9282 + nfmark = (*pskb)->nfmark;
9283 + diff = (ct->mark ^ nfmark & markinfo->mask);
9285 + (*pskb)->nfmark = nfmark ^ diff;
9286 + (*pskb)->nfcache |= NFC_ALTERED;
9292 + return IPT_CONTINUE;
9296 +checkentry(const char *tablename,
9297 + const struct ipt_entry *e,
9299 + unsigned int targinfosize,
9300 + unsigned int hook_mask)
9302 + struct ipt_connmark_target_info *matchinfo = targinfo;
9303 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
9304 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
9306 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
9310 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
9311 + if (strcmp(tablename, "mangle") != 0) {
9312 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9320 +static struct ipt_target ipt_connmark_reg = {
9321 + .name = "CONNMARK",
9322 + .target = &target,
9323 + .checkentry = &checkentry,
9327 +static int __init init(void)
9329 + return ipt_register_target(&ipt_connmark_reg);
9332 +static void __exit fini(void)
9334 + ipt_unregister_target(&ipt_connmark_reg);
9339 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPMARK.c
9340 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
9341 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-06-08 10:37:02.000000000 +0200
9343 +/* This is a module which is used for setting the NFMARK field of an skb. */
9344 +#include <linux/module.h>
9345 +#include <linux/skbuff.h>
9346 +#include <linux/ip.h>
9347 +#include <net/checksum.h>
9349 +#include <linux/netfilter_ipv4/ip_tables.h>
9350 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
9352 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
9353 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
9354 +MODULE_LICENSE("GPL");
9356 +static unsigned int
9357 +target(struct sk_buff **pskb,
9358 + const struct net_device *in,
9359 + const struct net_device *out,
9360 + unsigned int hooknum,
9361 + const void *targinfo,
9364 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
9365 + struct iphdr *iph = (*pskb)->nh.iph;
9366 + unsigned long mark;
9368 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
9369 + mark = (unsigned long) ntohl(iph->saddr);
9371 + mark = (unsigned long) ntohl(iph->daddr);
9373 + mark &= ipmarkinfo->andmask;
9374 + mark |= ipmarkinfo->ormask;
9376 + if ((*pskb)->nfmark != mark) {
9377 + (*pskb)->nfmark = mark;
9378 + (*pskb)->nfcache |= NFC_ALTERED;
9380 + return IPT_CONTINUE;
9384 +checkentry(const char *tablename,
9385 + const struct ipt_entry *e,
9387 + unsigned int targinfosize,
9388 + unsigned int hook_mask)
9390 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
9391 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
9393 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
9397 + if (strcmp(tablename, "mangle") != 0) {
9398 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9405 +static struct ipt_target ipt_ipmark_reg = {
9408 + .checkentry = checkentry,
9412 +static int __init init(void)
9414 + return ipt_register_target(&ipt_ipmark_reg);
9417 +static void __exit fini(void)
9419 + ipt_unregister_target(&ipt_ipmark_reg);
9424 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
9425 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
9426 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-06-08 10:31:05.000000000 +0200
9429 + * Strip all IP options in the IP packet header.
9431 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
9432 + * This software is distributed under GNU GPL v2, 1991
9435 +#include <linux/module.h>
9436 +#include <linux/skbuff.h>
9437 +#include <linux/ip.h>
9438 +#include <net/checksum.h>
9440 +#include <linux/netfilter_ipv4/ip_tables.h>
9442 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
9443 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
9444 +MODULE_LICENSE("GPL");
9446 +static unsigned int
9447 +target(struct sk_buff **pskb,
9448 + const struct net_device *in,
9449 + const struct net_device *out,
9450 + unsigned int hooknum,
9451 + const void *targinfo,
9454 + struct iphdr *iph;
9455 + struct sk_buff *skb;
9456 + struct ip_options *opt;
9457 + unsigned char *optiph;
9460 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9464 + iph = (*pskb)->nh.iph;
9465 + optiph = skb->nh.raw;
9466 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
9468 + /* if no options in packet then nothing to clear. */
9469 + if (iph->ihl * 4 == sizeof(struct iphdr))
9470 + return IPT_CONTINUE;
9472 + /* else clear all options */
9473 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
9474 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
9475 + opt = &(IPCB(skb)->opt);
9479 + skb->nfcache |= NFC_ALTERED;
9481 + return IPT_CONTINUE;
9485 +checkentry(const char *tablename,
9486 + const struct ipt_entry *e,
9488 + unsigned int targinfosize,
9489 + unsigned int hook_mask)
9491 + if (strcmp(tablename, "mangle")) {
9492 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9495 + /* nothing else to check because no parameters */
9499 +static struct ipt_target ipt_ipv4optsstrip_reg = {
9500 + .name = "IPV4OPTSSTRIP",
9502 + .checkentry = checkentry,
9503 + .me = THIS_MODULE };
9505 +static int __init init(void)
9507 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
9510 +static void __exit fini(void)
9512 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9517 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_NETLINK.c
9518 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
9519 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_NETLINK.c 2004-06-08 10:31:09.000000000 +0200
9521 +#include <linux/module.h>
9522 +#include <linux/version.h>
9523 +#include <linux/config.h>
9524 +#include <linux/socket.h>
9525 +#include <linux/skbuff.h>
9526 +#include <linux/kernel.h>
9527 +#include <linux/netlink.h>
9528 +#include <linux/netdevice.h>
9529 +#include <linux/mm.h>
9530 +#include <linux/socket.h>
9531 +#include <linux/netfilter_ipv4/ip_tables.h>
9532 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9533 +#include <net/sock.h>
9535 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9536 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9537 +MODULE_LICENSE("GPL");
9540 +#define DEBUGP printk
9542 +#define DEBUGP(format, args...)
9545 +static struct sock *ipfwsk;
9547 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9548 + unsigned int hooknum,
9549 + const struct net_device *in,
9550 + const struct net_device *out,
9551 + const void *targinfo, void *userinfo)
9553 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9554 + struct iphdr *ip = (*pskb)->nh.iph;
9555 + struct sk_buff *outskb;
9556 + struct netlink_t nlhdr;
9559 + /* Allocate a socket buffer */
9560 + if ( MASK(nld->flags, USE_SIZE) )
9561 + len = nld->size+sizeof(nlhdr);
9563 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
9565 + outskb=alloc_skb(len, GFP_ATOMIC);
9570 + if ( MASK(nld->flags, USE_MARK) )
9571 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
9573 + nlhdr.mark=(*pskb)->nfmark;
9575 + if ( in && in->name ) {
9576 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9577 + }else if ( out && out->name ){
9578 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9581 + skb_put(outskb, len);
9582 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9583 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9584 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9586 + if (net_ratelimit())
9587 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9590 + if ( MASK(nld->flags, USE_DROP) )
9593 + return IPT_CONTINUE;
9596 +static int ipt_netlink_checkentry(const char *tablename,
9597 + const struct ipt_entry *e,
9599 + unsigned int targinfosize,
9600 + unsigned int hookmask)
9602 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9607 +static struct ipt_target ipt_netlink_reg = {
9610 + ipt_netlink_target,
9611 + ipt_netlink_checkentry,
9616 +static int __init init(void)
9618 + DEBUGP("ipt_NETLINK: init module\n");
9620 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
9624 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9631 +static void __exit fini(void)
9633 + DEBUGP("ipt_NETLINK: cleanup_module\n");
9634 + ipt_unregister_target(&ipt_netlink_reg);
9635 + if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9640 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_POOL.c
9641 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
9642 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_POOL.c 2004-06-08 10:31:45.000000000 +0200
9644 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9646 + * This target can be used almost everywhere. It acts on some specified
9647 + * IP pool, adding or deleting some IP address in the pool. The address
9648 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9649 + * of the packet under inspection.
9651 + * The target normally returns IPT_CONTINUE.
9654 +#include <linux/types.h>
9655 +#include <linux/ip.h>
9656 +#include <linux/timer.h>
9657 +#include <linux/module.h>
9658 +#include <linux/netfilter.h>
9659 +#include <linux/netdevice.h>
9660 +#include <linux/if.h>
9661 +#include <linux/inetdevice.h>
9662 +#include <net/protocol.h>
9663 +#include <net/checksum.h>
9664 +#include <linux/netfilter_ipv4.h>
9665 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9666 +#include <linux/netfilter_ipv4/ipt_pool.h>
9669 +#define DEBUGP printk
9671 +#define DEBUGP(format, args...)
9674 +/*** NOTE NOTE NOTE NOTE ***
9676 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9677 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9678 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9679 +** is modified for the source IP address of the packet under inspection.
9680 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9682 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9683 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9685 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9686 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9687 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9688 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9692 +do_check(const char *tablename,
9693 + const struct ipt_entry *e,
9695 + unsigned int targinfosize,
9696 + unsigned int hook_mask)
9698 + const struct ipt_pool_info *ipi = targinfo;
9700 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9701 + DEBUGP("POOL_check: size %u.\n", targinfosize);
9704 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9708 +static unsigned int
9709 +do_target(struct sk_buff **pskb,
9710 + unsigned int hooknum,
9711 + const struct net_device *in,
9712 + const struct net_device *out,
9713 + const void *targinfo,
9716 + const struct ipt_pool_info *ipi = targinfo;
9718 + unsigned int verdict = IPT_CONTINUE;
9720 + if (ipi->src != IP_POOL_NONE) {
9721 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9722 + ipi->flags & IPT_POOL_DEL_SRC);
9723 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9724 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9725 + verdict = NF_ACCEPT;
9726 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9727 + verdict = NF_DROP;
9730 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9731 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9732 + ipi->flags & IPT_POOL_DEL_DST);
9733 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9734 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9735 + verdict = NF_ACCEPT;
9736 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9737 + verdict = NF_DROP;
9743 +static struct ipt_target pool_reg
9744 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9746 +static int __init init(void)
9748 + DEBUGP("init ipt_POOL\n");
9749 + return ipt_register_target(&pool_reg);
9752 +static void __exit fini(void)
9754 + DEBUGP("fini ipt_POOL\n");
9755 + ipt_unregister_target(&pool_reg);
9760 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_REJECT.c
9761 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_REJECT.c 2004-06-07 21:14:56.000000000 +0200
9762 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_REJECT.c 2004-06-08 10:30:55.000000000 +0200
9763 @@ -142,12 +142,7 @@
9764 nskb->dst = &rt->u.dst;
9766 /* This packet will not be the same as the other: clear nf fields */
9767 - nf_conntrack_put(nskb->nfct);
9768 - nskb->nfct = NULL;
9769 - nskb->nfcache = 0;
9770 -#ifdef CONFIG_NETFILTER_DEBUG
9771 - nskb->nf_debug = 0;
9775 #ifdef CONFIG_BRIDGE_NETFILTER
9776 nf_bridge_put(nskb->nf_bridge);
9777 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ROUTE.c
9778 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
9779 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ROUTE.c 2004-06-08 10:37:08.000000000 +0200
9782 + * This implements the ROUTE target, which enables you to setup unusual
9783 + * routes not supported by the standard kernel routing table.
9785 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9787 + * v 1.9 2004/05/14
9789 + * This software is distributed under GNU GPL v2, 1991
9792 +#include <linux/module.h>
9793 +#include <linux/skbuff.h>
9794 +#include <linux/ip.h>
9795 +#include <linux/netfilter_ipv4/ip_tables.h>
9796 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
9797 +#include <linux/netdevice.h>
9798 +#include <linux/route.h>
9799 +#include <net/ip.h>
9800 +#include <net/route.h>
9801 +#include <net/icmp.h>
9802 +#include <net/checksum.h>
9805 +#define DEBUGP printk
9807 +#define DEBUGP(format, args...)
9810 +MODULE_LICENSE("GPL");
9811 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
9812 +MODULE_DESCRIPTION("iptables ROUTE target module");
9814 +/* Try to route the packet according to the routing keys specified in
9815 + * route_info. Keys are :
9817 + * 0 if no oif preferred,
9818 + * otherwise set to the index of the desired oif
9819 + * - route_info->gw :
9820 + * 0 if no gateway specified,
9821 + * otherwise set to the next host to which the pkt must be routed
9822 + * If success, skb->dev is the output device to which the packet must
9823 + * be sent and skb->dst is not NULL
9825 + * RETURN: -1 if an error occured
9826 + * 1 if the packet was succesfully routed to the
9827 + * destination desired
9828 + * 0 if the kernel routing table could not route the packet
9829 + * according to the keys specified
9831 +static int route(struct sk_buff *skb,
9832 + unsigned int ifindex,
9833 + const struct ipt_route_target_info *route_info)
9836 + struct rtable *rt;
9837 + struct iphdr *iph = skb->nh.iph;
9838 + struct flowi fl = {
9842 + .daddr = iph->daddr,
9844 + .tos = RT_TOS(iph->tos),
9845 + .scope = RT_SCOPE_UNIVERSE,
9850 + /* The destination address may be overloaded by the target */
9851 + if (route_info->gw)
9852 + fl.fld_dst = route_info->gw;
9854 + /* Trying to route the packet using the standard routing table. */
9855 + if ((err = ip_route_output_key(&rt, &fl))) {
9856 + if (net_ratelimit())
9857 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
9861 + /* Drop old route. */
9862 + dst_release(skb->dst);
9865 + /* Success if no oif specified or if the oif correspond to the
9867 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
9868 + skb->dst = &rt->u.dst;
9869 + skb->dev = skb->dst->dev;
9873 + /* The interface selected by the routing table is not the one
9874 + * specified by the user. This may happen because the dst address
9875 + * is one of our own addresses.
9877 + if (net_ratelimit())
9878 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
9879 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
9885 +/* Stolen from ip_finish_output2
9886 + * PRE : skb->dev is set to the device we are leaving by
9887 + * skb->dst is not NULL
9888 + * POST: the packet is sent with the link layer header pushed
9889 + * the packet is destroyed
9891 +static void ip_direct_send(struct sk_buff *skb)
9893 + struct dst_entry *dst = skb->dst;
9894 + struct hh_cache *hh = dst->hh;
9897 + read_lock_bh(&hh->hh_lock);
9898 + memcpy(skb->data - 16, hh->hh_data, 16);
9899 + read_unlock_bh(&hh->hh_lock);
9900 + skb_push(skb, hh->hh_len);
9901 + hh->hh_output(skb);
9902 + } else if (dst->neighbour)
9903 + dst->neighbour->output(skb);
9905 + if (net_ratelimit())
9906 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
9912 +/* PRE : skb->dev is set to the device we are leaving by
9913 + * POST: - the packet is directly sent to the skb->dev device, without
9914 + * pushing the link layer header.
9915 + * - the packet is destroyed
9917 +static inline int dev_direct_send(struct sk_buff *skb)
9919 + return dev_queue_xmit(skb);
9923 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
9924 + struct sk_buff *skb)
9926 + unsigned int ifindex = 0;
9927 + struct net_device *dev_out = NULL;
9929 + /* The user set the interface name to use.
9930 + * Getting the current interface index.
9932 + if ((dev_out = dev_get_by_name(route_info->oif))) {
9933 + ifindex = dev_out->ifindex;
9935 + /* Unknown interface name : packet dropped */
9936 + if (net_ratelimit())
9937 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
9941 + /* Trying the standard way of routing packets */
9942 + switch (route(skb, ifindex, route_info)) {
9945 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9946 + return IPT_CONTINUE;
9948 + ip_direct_send(skb);
9952 + /* Failed to send to oif. Trying the hard way */
9953 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9956 + if (net_ratelimit())
9957 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
9960 + /* We have to force the use of an interface.
9961 + * This interface must be a tunnel interface since
9962 + * otherwise we can't guess the hw address for
9963 + * the packet. For a tunnel interface, no hw address
9966 + if ((dev_out->type != ARPHRD_TUNNEL)
9967 + && (dev_out->type != ARPHRD_IPGRE)) {
9968 + if (net_ratelimit())
9969 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
9974 + /* Send the packet. This will also free skb
9975 + * Do not go through the POST_ROUTING hook because
9976 + * skb->dst is not set and because it will probably
9977 + * get confused by the destination IP address.
9979 + skb->dev = dev_out;
9980 + dev_direct_send(skb);
9985 + /* Unexpected error */
9992 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
9993 + struct sk_buff *skb)
9995 + struct net_device *dev_in = NULL;
9997 + /* Getting the current interface index. */
9998 + if (!(dev_in = dev_get_by_name(route_info->iif))) {
9999 + if (net_ratelimit())
10000 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
10004 + skb->dev = dev_in;
10005 + dst_release(skb->dst);
10010 + return NF_STOLEN;
10014 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
10015 + struct sk_buff *skb)
10017 + if (route(skb, 0, route_info)!=1)
10020 + if (route_info->flags & IPT_ROUTE_CONTINUE)
10021 + return IPT_CONTINUE;
10023 + ip_direct_send(skb);
10024 + return NF_STOLEN;
10028 +static unsigned int ipt_route_target(struct sk_buff **pskb,
10029 + const struct net_device *in,
10030 + const struct net_device *out,
10031 + unsigned int hooknum,
10032 + const void *targinfo,
10035 + const struct ipt_route_target_info *route_info = targinfo;
10036 + struct sk_buff *skb = *pskb;
10038 + /* If we are at PREROUTING or INPUT hook
10039 + * the TTL isn't decreased by the IP stack
10041 + if (hooknum == NF_IP_PRE_ROUTING ||
10042 + hooknum == NF_IP_LOCAL_IN) {
10044 + struct iphdr *iph = skb->nh.iph;
10046 + if (iph->ttl <= 1) {
10047 + struct rtable *rt;
10048 + struct flowi fl = {
10052 + .daddr = iph->daddr,
10053 + .saddr = iph->saddr,
10054 + .tos = RT_TOS(iph->tos),
10055 + .scope = ((iph->tos & RTO_ONLINK) ?
10057 + RT_SCOPE_UNIVERSE)
10062 + if (ip_route_output_key(&rt, &fl)) {
10066 + if (skb->dev == rt->u.dst.dev) {
10067 + /* Drop old route. */
10068 + dst_release(skb->dst);
10069 + skb->dst = &rt->u.dst;
10071 + /* this will traverse normal stack, and
10072 + * thus call conntrack on the icmp packet */
10073 + icmp_send(skb, ICMP_TIME_EXCEEDED,
10074 + ICMP_EXC_TTL, 0);
10081 + * If we are at INPUT the checksum must be recalculated since
10082 + * the length could change as the result of a defragmentation.
10084 + if(hooknum == NF_IP_LOCAL_IN) {
10085 + iph->ttl = iph->ttl - 1;
10087 + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
10089 + ip_decrease_ttl(iph);
10093 + /* Tell conntrack to forget this packet since it may get confused
10094 + * when a packet is leaving with dst address == our address.
10095 + * Good idea ? Dunno. Need advice.
10097 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
10098 + nf_conntrack_put(skb->nfct);
10099 + skb->nfct = NULL;
10100 + skb->nfcache = 0;
10101 +#ifdef CONFIG_NETFILTER_DEBUG
10102 + skb->nf_debug = 0;
10106 + if (route_info->oif[0] != '\0')
10107 + return route_oif(route_info, *pskb);
10109 + if (route_info->iif[0] != '\0')
10110 + return route_iif(route_info, *pskb);
10112 + if (route_info->gw)
10113 + return route_gw(route_info, *pskb);
10115 + if (net_ratelimit())
10116 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
10118 + return IPT_CONTINUE;
10122 +static int ipt_route_checkentry(const char *tablename,
10123 + const struct ipt_entry *e,
10125 + unsigned int targinfosize,
10126 + unsigned int hook_mask)
10128 + if (strcmp(tablename, "mangle") != 0) {
10129 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
10134 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
10135 + | (1 << NF_IP_LOCAL_IN)
10136 + | (1 << NF_IP_FORWARD)
10137 + | (1 << NF_IP_LOCAL_OUT)
10138 + | (1 << NF_IP_POST_ROUTING))) {
10139 + printk("ipt_ROUTE: bad hook\n");
10143 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
10144 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
10146 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
10154 +static struct ipt_target ipt_route_reg = {
10156 + .target = ipt_route_target,
10157 + .checkentry = ipt_route_checkentry,
10158 + .me = THIS_MODULE,
10161 +static int __init init(void)
10163 + return ipt_register_target(&ipt_route_reg);
10167 +static void __exit fini(void)
10169 + ipt_unregister_target(&ipt_route_reg);
10172 +module_init(init);
10173 +module_exit(fini);
10174 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TARPIT.c
10175 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
10176 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-06-08 10:37:16.000000000 +0200
10179 + * Kernel module to capture and hold incoming TCP connections using
10180 + * no local per-connection resources.
10182 + * Based on ipt_REJECT.c and offering functionality similar to
10183 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
10185 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
10187 + * This program is free software; you can redistribute it and/or modify
10188 + * it under the terms of the GNU General Public License as published by
10189 + * the Free Software Foundation; either version 2 of the License, or
10190 + * (at your option) any later version.
10192 + * This program is distributed in the hope that it will be useful,
10193 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10194 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10195 + * GNU General Public License for more details.
10197 + * You should have received a copy of the GNU General Public License
10198 + * along with this program; if not, write to the Free Software
10199 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10202 + * - Allow incoming TCP connections to be established.
10203 + * - Passing data should result in the connection being switched to the
10204 + * persist state (0 byte window), in which the remote side stops sending
10205 + * data and asks to continue every 60 seconds.
10206 + * - Attempts to shut down the connection should be ignored completely, so
10207 + * the remote side ends up having to time it out.
10210 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
10211 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
10212 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
10215 +#include <linux/config.h>
10216 +#include <linux/module.h>
10217 +#include <linux/skbuff.h>
10218 +#include <linux/ip.h>
10219 +#include <net/ip.h>
10220 +#include <net/tcp.h>
10221 +#include <net/icmp.h>
10223 +#include <net/route.h>
10224 +#include <linux/random.h>
10225 +#include <linux/netfilter_ipv4/ip_tables.h>
10228 +#define DEBUGP printk
10230 +#define DEBUGP(format, args...)
10233 +MODULE_LICENSE("GPL");
10234 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
10236 +/* Stolen from ip_finish_output2 */
10237 +static int ip_direct_send(struct sk_buff *skb)
10239 + struct dst_entry *dst = skb->dst;
10240 + struct hh_cache *hh = dst->hh;
10243 + read_lock_bh(&hh->hh_lock);
10244 + memcpy(skb->data - 16, hh->hh_data, 16);
10245 + read_unlock_bh(&hh->hh_lock);
10246 + skb_push(skb, hh->hh_len);
10247 + return hh->hh_output(skb);
10248 + } else if (dst->neighbour)
10249 + return dst->neighbour->output(skb);
10251 + if (net_ratelimit())
10252 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
10259 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
10261 + struct sk_buff *nskb;
10262 + struct rtable *nrt;
10263 + struct tcphdr *otcph, *ntcph;
10264 + struct flowi fl = {};
10265 + unsigned int otcplen;
10268 + /* A truncated TCP header isn't going to be useful */
10269 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
10272 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
10273 + + oskb->nh.iph->ihl);
10274 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
10276 + /* No replies for RST or FIN */
10277 + if (otcph->rst || otcph->fin)
10280 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
10281 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
10284 + /* Check checksum. */
10285 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
10286 + oskb->nh.iph->daddr,
10287 + csum_partial((char *)otcph, otcplen, 0)) != 0)
10290 + /* Copy skb (even if skb is about to be dropped, we can't just
10291 + clone it because there may be other things, such as tcpdump,
10292 + interested in it) */
10293 + nskb = skb_copy(oskb, GFP_ATOMIC);
10297 + /* This packet will not be the same as the other: clear nf fields */
10298 + nf_conntrack_put(nskb->nfct);
10299 + nskb->nfct = NULL;
10300 + nskb->nfcache = 0;
10301 +#ifdef CONFIG_NETFILTER_DEBUG
10302 + nskb->nf_debug = 0;
10305 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
10307 + /* Truncate to length (no data) */
10308 + ntcph->doff = sizeof(struct tcphdr)/4;
10309 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
10310 + nskb->nh.iph->tot_len = htons(nskb->len);
10312 + /* Swap source and dest */
10313 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
10314 + tmp = ntcph->source;
10315 + ntcph->source = ntcph->dest;
10316 + ntcph->dest = tmp;
10318 + /* Use supplied sequence number or make a new one */
10319 + ntcph->seq = otcph->ack ? otcph->ack_seq
10320 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
10321 + nskb->nh.iph->daddr,
10325 + /* Our SYN-ACKs must have a >0 window */
10326 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
10328 + ntcph->urg_ptr = 0;
10330 + /* Reset flags */
10331 + ((u_int8_t *)ntcph)[13] = 0;
10333 + if (otcph->syn && otcph->ack) {
10335 + ntcph->ack_seq = 0;
10337 + ntcph->syn = otcph->syn;
10339 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
10342 + /* Adjust TCP checksum */
10343 + ntcph->check = 0;
10344 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
10345 + nskb->nh.iph->saddr,
10346 + nskb->nh.iph->daddr,
10347 + csum_partial((char *)ntcph,
10348 + sizeof(struct tcphdr), 0));
10350 + /* Adjust IP TTL */
10351 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
10353 + /* Set DF, id = 0 */
10354 + nskb->nh.iph->frag_off = htons(IP_DF);
10355 + nskb->nh.iph->id = 0;
10357 + /* Adjust IP checksum */
10358 + nskb->nh.iph->check = 0;
10359 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
10360 + nskb->nh.iph->ihl);
10362 + fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
10363 + fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
10364 + fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
10367 + if (ip_route_output_key(&nrt, &fl))
10370 + dst_release(nskb->dst);
10371 + nskb->dst = &nrt->u.dst;
10373 + /* "Never happens" */
10374 + if (nskb->len > dst_pmtu(nskb->dst))
10377 + ip_direct_send (nskb);
10386 +static unsigned int tarpit(struct sk_buff **pskb,
10387 + const struct net_device *in,
10388 + const struct net_device *out,
10389 + unsigned int hooknum,
10390 + const void *targinfo,
10393 + struct sk_buff *skb = *pskb;
10394 + struct rtable *rt = (struct rtable*)skb->dst;
10396 + /* Do we have an input route cache entry? */
10400 + /* No replies to physical multicast/broadcast */
10401 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
10404 + /* Now check at the protocol level */
10405 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
10408 + /* Our naive response construction doesn't deal with IP
10409 + options, and probably shouldn't try. */
10410 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
10413 + /* We aren't interested in fragments */
10414 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
10417 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
10423 +static int check(const char *tablename,
10424 + const struct ipt_entry *e,
10426 + unsigned int targinfosize,
10427 + unsigned int hook_mask)
10429 + /* Only allow these for input/forward packet filtering. */
10430 + if (strcmp(tablename, "filter") != 0) {
10431 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
10434 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
10435 + | (1 << NF_IP_FORWARD))) != 0) {
10436 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
10440 + /* Must specify that it's a TCP packet */
10441 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
10442 + DEBUGP("TARPIT: not valid for non-tcp\n");
10449 +static struct ipt_target ipt_tarpit_reg = {
10450 + .name = "TARPIT",
10451 + .target = tarpit,
10452 + .checkentry = check,
10453 + .me = THIS_MODULE
10456 +static int __init init(void)
10458 + return ipt_register_target(&ipt_tarpit_reg);
10461 +static void __exit fini(void)
10463 + ipt_unregister_target(&ipt_tarpit_reg);
10466 +module_init(init);
10467 +module_exit(fini);
10468 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TRACE.c
10469 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
10470 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TRACE.c 2004-06-08 10:37:30.000000000 +0200
10472 +/* This is a module which is used for setting
10473 + * the NFC_TRACE flag in the nfcache field of an skb.
10475 +#include <linux/module.h>
10476 +#include <linux/skbuff.h>
10478 +#include <linux/netfilter_ipv4/ip_tables.h>
10480 +static unsigned int
10481 +target(struct sk_buff **pskb,
10482 + const struct net_device *in,
10483 + const struct net_device *out,
10484 + unsigned int hooknum,
10485 + const void *targinfo,
10488 + (*pskb)->nfcache |= NFC_TRACE;
10489 + return IPT_CONTINUE;
10493 +checkentry(const char *tablename,
10494 + const struct ipt_entry *e,
10496 + unsigned int targinfosize,
10497 + unsigned int hook_mask)
10499 + if (targinfosize != 0) {
10500 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
10505 + if (strcmp(tablename, "raw") != 0) {
10506 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
10513 +static struct ipt_target ipt_trace_reg = {
10515 + .target = target,
10516 + .checkentry = checkentry,
10517 + .me = THIS_MODULE
10520 +static int __init init(void)
10522 + if (ipt_register_target(&ipt_trace_reg))
10528 +static void __exit fini(void)
10530 + ipt_unregister_target(&ipt_trace_reg);
10533 +module_init(init);
10534 +module_exit(fini);
10535 +MODULE_LICENSE("GPL");
10536 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TTL.c
10537 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
10538 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TTL.c 2004-06-08 10:31:21.000000000 +0200
10540 +/* TTL modification target for IP tables
10541 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
10543 + * Version: $Revision$
10545 + * This software is distributed under the terms of GNU GPL
10548 +#include <linux/module.h>
10549 +#include <linux/skbuff.h>
10550 +#include <linux/ip.h>
10551 +#include <net/checksum.h>
10553 +#include <linux/netfilter_ipv4/ip_tables.h>
10554 +#include <linux/netfilter_ipv4/ipt_TTL.h>
10556 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
10557 +MODULE_DESCRIPTION("IP tables TTL modification module");
10558 +MODULE_LICENSE("GPL");
10560 +static unsigned int
10561 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
10562 + const struct net_device *out, unsigned int hooknum,
10563 + const void *targinfo, void *userinfo)
10565 + struct iphdr *iph;
10566 + const struct ipt_TTL_info *info = targinfo;
10567 + u_int16_t diffs[2];
10570 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
10573 + iph = (*pskb)->nh.iph;
10575 + switch (info->mode) {
10576 + case IPT_TTL_SET:
10577 + new_ttl = info->ttl;
10579 + case IPT_TTL_INC:
10580 + new_ttl = iph->ttl + info->ttl;
10581 + if (new_ttl > 255)
10584 + case IPT_TTL_DEC:
10585 + new_ttl = iph->ttl + info->ttl;
10590 + new_ttl = iph->ttl;
10594 + if (new_ttl != iph->ttl) {
10595 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
10596 + iph->ttl = new_ttl;
10597 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
10598 + iph->check = csum_fold(csum_partial((char *)diffs,
10600 + iph->check^0xFFFF));
10601 + (*pskb)->nfcache |= NFC_ALTERED;
10604 + return IPT_CONTINUE;
10607 +static int ipt_ttl_checkentry(const char *tablename,
10608 + const struct ipt_entry *e,
10610 + unsigned int targinfosize,
10611 + unsigned int hook_mask)
10613 + struct ipt_TTL_info *info = targinfo;
10615 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
10616 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
10618 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
10622 + if (strcmp(tablename, "mangle")) {
10623 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
10627 + if (info->mode > IPT_TTL_MAXMODE) {
10628 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
10633 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
10634 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
10641 +static struct ipt_target ipt_TTL = {
10643 + .target = ipt_ttl_target,
10644 + .checkentry = ipt_ttl_checkentry,
10645 + .me = THIS_MODULE
10648 +static int __init init(void)
10650 + return ipt_register_target(&ipt_TTL);
10653 +static void __exit fini(void)
10655 + ipt_unregister_target(&ipt_TTL);
10658 +module_init(init);
10659 +module_exit(fini);
10660 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_XOR.c
10661 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
10662 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-06-08 10:37:54.000000000 +0200
10664 +/* XOR target for IP tables
10665 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
10666 + * Based on ipt_TTL.c
10670 + * This software is distributed under the terms of GNU GPL
10673 +#include <linux/module.h>
10674 +#include <linux/skbuff.h>
10675 +#include <linux/ip.h>
10676 +#include <linux/tcp.h>
10677 +#include <linux/udp.h>
10679 +#include <linux/netfilter_ipv4/ip_tables.h>
10680 +#include <linux/netfilter_ipv4/ipt_XOR.h>
10682 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
10683 +MODULE_DESCRIPTION("IP tables XOR module");
10684 +MODULE_LICENSE("GPL");
10686 +static unsigned int
10687 +ipt_xor_target(struct sk_buff **pskb,
10688 + const struct net_device *in, const struct net_device *out,
10689 + unsigned int hooknum, const void *targinfo, void *userinfo)
10691 + struct ipt_XOR_info *info = (void *) targinfo;
10692 + struct iphdr *iph;
10693 + struct tcphdr *tcph;
10694 + struct udphdr *udph;
10697 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
10700 + iph = (*pskb)->nh.iph;
10702 + if (iph->protocol == IPPROTO_TCP) {
10703 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
10704 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
10705 + for (k=0; k<=info->block_size; k++) {
10706 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
10711 + if (info->key[j] == 0x00)
10714 + } else if (iph->protocol == IPPROTO_UDP) {
10715 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
10716 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
10717 + for (k=0; k<=info->block_size; k++) {
10718 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
10723 + if (info->key[j] == 0x00)
10728 + return IPT_CONTINUE;
10731 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
10732 + void *targinfo, unsigned int targinfosize,
10733 + unsigned int hook_mask)
10735 + struct ipt_XOR_info *info = targinfo;
10737 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
10738 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
10739 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
10743 + if (strcmp(tablename, "mangle")) {
10744 + printk(KERN_WARNING "XOR: can only be called from"
10745 + "\"mangle\" table, not \"%s\"\n", tablename);
10749 + if (!strcmp(info->key, "")) {
10750 + printk(KERN_WARNING "XOR: You must specify a key");
10754 + if (info->block_size == 0) {
10755 + printk(KERN_WARNING "XOR: You must specify a block-size");
10762 +static struct ipt_target ipt_XOR = {
10764 + .target = ipt_xor_target,
10765 + .checkentry = ipt_xor_checkentry,
10766 + .me = THIS_MODULE,
10769 +static int __init init(void)
10771 + return ipt_register_target(&ipt_XOR);
10774 +static void __exit fini(void)
10776 + ipt_unregister_target(&ipt_XOR);
10779 +module_init(init);
10780 +module_exit(fini);
10781 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_addrtype.c
10782 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
10783 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-06-08 10:38:04.000000000 +0200
10786 + * iptables module to match inet_addr_type() of an ip.
10788 + * Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
10790 + * This program is free software; you can redistribute it and/or modify
10791 + * it under the terms of the GNU General Public License version 2 as
10792 + * published by the Free Software Foundation.
10795 +#include <linux/module.h>
10796 +#include <linux/skbuff.h>
10797 +#include <linux/netdevice.h>
10798 +#include <net/route.h>
10800 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
10801 +#include <linux/netfilter_ipv4/ip_tables.h>
10803 +MODULE_LICENSE("GPL");
10804 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
10805 +MODULE_DESCRIPTION("iptables addrtype match");
10807 +static inline int match_type(u_int32_t addr, u_int16_t mask)
10809 + return !!(mask & (1 << inet_addr_type(addr)));
10812 +static int match(const struct sk_buff *skb, const struct net_device *in,
10813 + const struct net_device *out, const void *matchinfo,
10814 + int offset, int *hotdrop)
10816 + const struct ipt_addrtype_info *info = matchinfo;
10817 + const struct iphdr *iph = skb->nh.iph;
10820 + if (info->source)
10821 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
10823 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
10828 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
10829 + void *matchinfo, unsigned int matchsize,
10830 + unsigned int hook_mask)
10832 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
10833 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
10834 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
10841 +static struct ipt_match addrtype_match = {
10842 + .name = "addrtype",
10844 + .checkentry = checkentry,
10845 + .me = THIS_MODULE
10848 +static int __init init(void)
10850 + return ipt_register_match(&addrtype_match);
10853 +static void __exit fini(void)
10855 + ipt_unregister_match(&addrtype_match);
10858 +module_init(init);
10859 +module_exit(fini);
10860 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connlimit.c
10861 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
10862 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connlimit.c 2004-06-08 10:31:23.000000000 +0200
10865 + * netfilter module to limit the number of parallel tcp
10866 + * connections per IP address.
10867 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
10868 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
10869 + * only ignore TIME_WAIT or gone connections
10873 + * Kernel module to match connection tracking information.
10874 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
10876 +#include <linux/module.h>
10877 +#include <linux/skbuff.h>
10878 +#include <linux/list.h>
10879 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10880 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
10881 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
10882 +#include <linux/netfilter_ipv4/ip_tables.h>
10883 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
10887 +MODULE_LICENSE("GPL");
10889 +/* we'll save the tuples of all connections we care about */
10890 +struct ipt_connlimit_conn
10892 + struct list_head list;
10893 + struct ip_conntrack_tuple tuple;
10896 +struct ipt_connlimit_data {
10898 + struct list_head iphash[256];
10901 +static int ipt_iphash(u_int32_t addr)
10905 + hash = addr & 0xff;
10906 + hash ^= (addr >> 8) & 0xff;
10907 + hash ^= (addr >> 16) & 0xff;
10908 + hash ^= (addr >> 24) & 0xff;
10912 +static int count_them(struct ipt_connlimit_data *data,
10913 + u_int32_t addr, u_int32_t mask,
10914 + struct ip_conntrack *ct)
10917 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
10918 + "fin_wait", "time_wait", "close", "close_wait",
10919 + "last_ack", "listen" };
10921 + int addit = 1, matches = 0;
10922 + struct ip_conntrack_tuple tuple;
10923 + struct ip_conntrack_tuple_hash *found;
10924 + struct ipt_connlimit_conn *conn;
10925 + struct list_head *hash,*lh;
10927 + spin_lock(&data->lock);
10928 + tuple = ct->tuplehash[0].tuple;
10929 + hash = &data->iphash[ipt_iphash(addr & mask)];
10931 + /* check the saved connections */
10932 + for (lh = hash->next; lh != hash; lh = lh->next) {
10933 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
10934 + found = ip_conntrack_find_get(&conn->tuple,ct);
10935 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
10937 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
10938 + /* Just to be sure we have it only once in the list.
10939 + We should'nt see tuples twice unless someone hooks this
10940 + into a table without "-p tcp --syn" */
10944 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
10945 + ipt_iphash(addr & mask),
10946 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
10947 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
10948 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
10950 + if (NULL == found) {
10951 + /* this one is gone */
10953 + list_del(lh->next);
10957 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
10958 + /* we don't care about connections which are
10959 + closed already -> ditch it */
10961 + list_del(lh->next);
10963 + nf_conntrack_put(&found->ctrack->infos[0]);
10966 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
10967 + /* same source IP address -> be counted! */
10970 + nf_conntrack_put(&found->ctrack->infos[0]);
10973 + /* save the new connection in our list */
10975 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
10976 + ipt_iphash(addr & mask),
10977 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
10978 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
10980 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
10981 + if (NULL == conn)
10983 + memset(conn,0,sizeof(*conn));
10984 + INIT_LIST_HEAD(&conn->list);
10985 + conn->tuple = tuple;
10986 + list_add(&conn->list,hash);
10989 + spin_unlock(&data->lock);
10994 +match(const struct sk_buff *skb,
10995 + const struct net_device *in,
10996 + const struct net_device *out,
10997 + const void *matchinfo,
11001 + const struct ipt_connlimit_info *info = matchinfo;
11002 + int connections, match;
11003 + struct ip_conntrack *ct;
11004 + enum ip_conntrack_info ctinfo;
11006 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11007 + if (NULL == ct) {
11008 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
11012 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
11013 + if (-1 == connections) {
11014 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
11015 + *hotdrop = 1; /* let's free some memory :-) */
11018 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
11020 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
11021 + "connections=%d limit=%d match=%s\n",
11022 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
11023 + connections, info->limit, match ? "yes" : "no");
11029 +static int check(const char *tablename,
11030 + const struct ipt_ip *ip,
11032 + unsigned int matchsize,
11033 + unsigned int hook_mask)
11035 + struct ipt_connlimit_info *info = matchinfo;
11038 + /* verify size */
11039 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
11042 + /* refuse anything but tcp */
11043 + if (ip->proto != IPPROTO_TCP)
11046 + /* init private data */
11047 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
11048 + spin_lock_init(&(info->data->lock));
11049 + for (i = 0; i < 256; i++)
11050 + INIT_LIST_HEAD(&(info->data->iphash[i]));
11055 +static void destroy(void *matchinfo, unsigned int matchinfosize)
11057 + struct ipt_connlimit_info *info = matchinfo;
11058 + struct ipt_connlimit_conn *conn;
11059 + struct list_head *hash;
11063 + for (i = 0; i < 256; i++) {
11064 + hash = &(info->data->iphash[i]);
11065 + while (hash != hash->next) {
11066 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
11067 + list_del(hash->next);
11071 + kfree(info->data);
11074 +static struct ipt_match connlimit_match = {
11075 + .name = "connlimit",
11077 + .checkentry = &check,
11078 + .destroy = &destroy,
11079 + .me = THIS_MODULE
11082 +static int __init init(void)
11084 + return ipt_register_match(&connlimit_match);
11087 +static void __exit fini(void)
11089 + ipt_unregister_match(&connlimit_match);
11092 +module_init(init);
11093 +module_exit(fini);
11094 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connmark.c
11095 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
11096 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-06-08 10:36:58.000000000 +0200
11098 +/* This kernel module matches connection mark values set by the
11099 + * CONNMARK target
11101 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
11102 + * by Henrik Nordstrom <hno@marasystems.com>
11104 + * This program is free software; you can redistribute it and/or modify
11105 + * it under the terms of the GNU General Public License as published by
11106 + * the Free Software Foundation; either version 2 of the License, or
11107 + * (at your option) any later version.
11109 + * This program is distributed in the hope that it will be useful,
11110 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11111 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11112 + * GNU General Public License for more details.
11114 + * You should have received a copy of the GNU General Public License
11115 + * along with this program; if not, write to the Free Software
11116 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11119 +#include <linux/module.h>
11120 +#include <linux/skbuff.h>
11122 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
11123 +MODULE_DESCRIPTION("IP tables connmark match module");
11124 +MODULE_LICENSE("GPL");
11126 +#include <linux/netfilter_ipv4/ip_tables.h>
11127 +#include <linux/netfilter_ipv4/ipt_connmark.h>
11128 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11131 +match(const struct sk_buff *skb,
11132 + const struct net_device *in,
11133 + const struct net_device *out,
11134 + const void *matchinfo,
11138 + const struct ipt_connmark_info *info = matchinfo;
11139 + enum ip_conntrack_info ctinfo;
11140 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11144 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
11148 +checkentry(const char *tablename,
11149 + const struct ipt_ip *ip,
11151 + unsigned int matchsize,
11152 + unsigned int hook_mask)
11154 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
11160 +static struct ipt_match connmark_match = {
11161 + .name = "connmark",
11163 + .checkentry = &checkentry,
11164 + .me = THIS_MODULE
11167 +static int __init init(void)
11169 + return ipt_register_match(&connmark_match);
11172 +static void __exit fini(void)
11174 + ipt_unregister_match(&connmark_match);
11177 +module_init(init);
11178 +module_exit(fini);
11179 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_dstlimit.c
11180 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
11181 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_dstlimit.c 2004-06-08 10:31:34.000000000 +0200
11183 +/* iptables match extension to limit the number of packets per second
11184 + * seperately for each destination.
11186 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
11190 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
11192 + * based on ipt_limit.c by:
11193 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
11194 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
11195 + * Rusty Russell <rusty@rustcorp.com.au>
11197 + * The general idea is to create a hash table for every dstip and have a
11198 + * seperate limit counter per tuple. This way you can do something like 'limit
11199 + * the number of syn packets for each of my internal addresses.
11201 + * Ideally this would just be implemented as a general 'hash' match, which would
11202 + * allow us to attach any iptables target to it's hash buckets. But this is
11203 + * not possible in the current iptables architecture. As always, pkttables for
11204 + * 2.7.x will help ;)
11206 +#include <linux/module.h>
11207 +#include <linux/skbuff.h>
11208 +#include <linux/spinlock.h>
11209 +#include <linux/random.h>
11210 +#include <linux/jhash.h>
11211 +#include <linux/slab.h>
11212 +#include <linux/vmalloc.h>
11213 +#include <linux/tcp.h>
11214 +#include <linux/udp.h>
11215 +#include <linux/proc_fs.h>
11216 +#include <linux/seq_file.h>
11218 +#define ASSERT_READ_LOCK(x)
11219 +#define ASSERT_WRITE_LOCK(x)
11220 +#include <linux/netfilter_ipv4/lockhelp.h>
11221 +#include <linux/netfilter_ipv4/listhelp.h>
11223 +#include <linux/netfilter_ipv4/ip_tables.h>
11224 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
11226 +/* FIXME: this is just for IP_NF_ASSERRT */
11227 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11229 +#define MS2JIFFIES(x) ((x*HZ)/1000)
11231 +MODULE_LICENSE("GPL");
11232 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
11233 +MODULE_DESCRIPTION("iptables match for limiting per destination");
11235 +/* need to declare this at the top */
11236 +static struct proc_dir_entry *dstlimit_procdir;
11237 +static struct file_operations dl_file_ops;
11239 +/* hash table crap */
11241 +struct dsthash_dst {
11242 + u_int32_t src_ip;
11243 + u_int32_t dst_ip;
11247 +struct dsthash_ent {
11248 + /* static / read-only parts in the beginning */
11249 + struct list_head list;
11250 + struct dsthash_dst dst;
11252 + /* modified structure members in the end */
11253 + unsigned long expires; /* precalculated expiry time */
11255 + unsigned long prev; /* last modification */
11256 + u_int32_t credit;
11257 + u_int32_t credit_cap, cost;
11261 +struct ipt_dstlimit_htable {
11262 + struct list_head list; /* global list of all htables */
11265 + struct dstlimit_cfg cfg; /* config */
11267 + /* used internally */
11268 + spinlock_t lock; /* lock for list_head */
11269 + u_int32_t rnd; /* random seed for hash */
11270 + struct timer_list timer; /* timer for gc */
11271 + atomic_t count; /* number entries in table */
11273 + /* seq_file stuff */
11274 + struct proc_dir_entry *pde;
11276 + struct list_head hash[0]; /* hashtable itself */
11279 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
11280 +static LIST_HEAD(dstlimit_htables);
11281 +static kmem_cache_t *dstlimit_cachep;
11283 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
11285 + return (ent->dst.dst_ip == b->dst_ip
11286 + && ent->dst.port == b->port
11287 + && ent->dst.src_ip == b->src_ip);
11290 +static inline u_int32_t
11291 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
11293 + return (jhash_3words(dst->dst_ip, dst->port,
11294 + dst->src_ip, ht->rnd) % ht->cfg.size);
11297 +static inline struct dsthash_ent *
11298 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11300 + struct dsthash_ent *ent;
11301 + u_int32_t hash = hash_dst(ht, dst);
11302 + MUST_BE_LOCKED(&ht->lock);
11303 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
11307 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
11308 +static struct dsthash_ent *
11309 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11311 + struct dsthash_ent *ent;
11313 + /* initialize hash with random val at the time we allocate
11314 + * the first hashtable entry */
11316 + get_random_bytes(&ht->rnd, 4);
11318 + if (ht->cfg.max &&
11319 + atomic_read(&ht->count) >= ht->cfg.max) {
11320 + /* FIXME: do something. question is what.. */
11321 + if (net_ratelimit())
11322 + printk(KERN_WARNING
11323 + "ipt_dstlimit: max count of %u reached\n",
11328 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
11330 + if (net_ratelimit())
11332 + "ipt_dstlimit: can't allocate dsthash_ent\n");
11336 + atomic_inc(&ht->count);
11338 + ent->dst.dst_ip = dst->dst_ip;
11339 + ent->dst.port = dst->port;
11340 + ent->dst.src_ip = dst->src_ip;
11342 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
11347 +static inline void
11348 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
11350 + MUST_BE_LOCKED(&ht->lock);
11352 + list_del(&ent->list);
11353 + kmem_cache_free(dstlimit_cachep, ent);
11354 + atomic_dec(&ht->count);
11356 +static void htable_gc(unsigned long htlong);
11358 +static int htable_create(struct ipt_dstlimit_info *minfo)
11361 + unsigned int size;
11362 + struct ipt_dstlimit_htable *hinfo;
11364 + if (minfo->cfg.size)
11365 + size = minfo->cfg.size;
11367 + size = (((num_physpages << PAGE_SHIFT) / 16384)
11368 + / sizeof(struct list_head));
11369 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
11374 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
11375 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
11376 + + (sizeof(struct list_head) * size));
11378 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
11381 + minfo->hinfo = hinfo;
11383 + /* copy match config into hashtable config */
11384 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
11385 + hinfo->cfg.size = size;
11386 + if (!hinfo->cfg.max)
11387 + hinfo->cfg.max = 8 * hinfo->cfg.size;
11388 + else if (hinfo->cfg.max < hinfo->cfg.size)
11389 + hinfo->cfg.max = hinfo->cfg.size;
11391 + for (i = 0; i < hinfo->cfg.size; i++)
11392 + INIT_LIST_HEAD(&hinfo->hash[i]);
11394 + atomic_set(&hinfo->count, 0);
11395 + atomic_set(&hinfo->use, 1);
11397 + hinfo->lock = SPIN_LOCK_UNLOCKED;
11398 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
11399 + if (!hinfo->pde) {
11403 + hinfo->pde->proc_fops = &dl_file_ops;
11404 + hinfo->pde->data = hinfo;
11406 + init_timer(&hinfo->timer);
11407 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
11408 + hinfo->timer.data = (unsigned long )hinfo;
11409 + hinfo->timer.function = htable_gc;
11410 + add_timer(&hinfo->timer);
11412 + WRITE_LOCK(&dstlimit_lock);
11413 + list_add(&hinfo->list, &dstlimit_htables);
11414 + WRITE_UNLOCK(&dstlimit_lock);
11419 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11424 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11426 + return (jiffies >= he->expires);
11429 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
11430 + int (*select)(struct ipt_dstlimit_htable *ht,
11431 + struct dsthash_ent *he))
11435 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
11437 + /* lock hash table and iterate over it */
11438 + LOCK_BH(&ht->lock);
11439 + for (i = 0; i < ht->cfg.size; i++) {
11440 + struct dsthash_ent *dh, *n;
11441 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
11442 + if ((*select)(ht, dh))
11443 + __dsthash_free(ht, dh);
11446 + UNLOCK_BH(&ht->lock);
11449 +/* hash table garbage collector, run by timer */
11450 +static void htable_gc(unsigned long htlong)
11452 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
11454 + htable_selective_cleanup(ht, select_gc);
11456 + /* re-add the timer accordingly */
11457 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
11458 + add_timer(&ht->timer);
11461 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
11463 + /* remove timer, if it is pending */
11464 + if (timer_pending(&hinfo->timer))
11465 + del_timer(&hinfo->timer);
11467 + /* remove proc entry */
11468 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
11470 + htable_selective_cleanup(hinfo, select_all);
11474 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
11476 + struct ipt_dstlimit_htable *hinfo;
11478 + READ_LOCK(&dstlimit_lock);
11479 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
11480 + if (!strcmp(name, hinfo->pde->name)) {
11481 + atomic_inc(&hinfo->use);
11482 + READ_UNLOCK(&dstlimit_lock);
11486 + READ_UNLOCK(&dstlimit_lock);
11491 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
11493 + if (atomic_dec_and_test(&hinfo->use)) {
11494 + WRITE_LOCK(&dstlimit_lock);
11495 + list_del(&hinfo->list);
11496 + WRITE_UNLOCK(&dstlimit_lock);
11497 + htable_destroy(hinfo);
11502 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
11503 + * see net/sched/sch_tbf.c in the linux source tree
11506 +/* Rusty: This is my (non-mathematically-inclined) understanding of
11507 + this algorithm. The `average rate' in jiffies becomes your initial
11508 + amount of credit `credit' and the most credit you can ever have
11509 + `credit_cap'. The `peak rate' becomes the cost of passing the
11512 + `prev' tracks the last packet hit: you gain one credit per jiffy.
11513 + If you get credit balance more than this, the extra credit is
11514 + discarded. Every time the match passes, you lose `cost' credits;
11515 + if you don't have that many, the test fails.
11517 + See Alexey's formal explanation in net/sched/sch_tbf.c.
11519 + To get the maximum range, we multiply by this factor (ie. you get N
11520 + credits per jiffy). We want to allow a rate as low as 1 per day
11521 + (slowest userspace tool allows), which means
11522 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
11524 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
11526 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
11527 + * us the power of 2 below the theoretical max, so GCC simply does a
11529 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
11530 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
11531 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
11532 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
11533 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
11534 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
11536 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
11538 +/* Precision saver. */
11539 +static inline u_int32_t
11540 +user2credits(u_int32_t user)
11542 + /* If multiplying would overflow... */
11543 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
11544 + /* Divide first. */
11545 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
11547 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
11550 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
11552 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
11553 + * CREDITS_PER_JIFFY;
11554 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
11555 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
11559 +dstlimit_match(const struct sk_buff *skb,
11560 + const struct net_device *in,
11561 + const struct net_device *out,
11562 + const void *matchinfo,
11566 + struct ipt_dstlimit_info *r =
11567 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
11568 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
11569 + unsigned long now = jiffies;
11570 + struct dsthash_ent *dh;
11571 + struct dsthash_dst dst;
11573 + memset(&dst, 0, sizeof(dst));
11575 + /* dest ip is always in hash */
11576 + dst.dst_ip = skb->nh.iph->daddr;
11578 + /* source ip only if respective hashmode, otherwise set to
11580 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
11581 + dst.src_ip = skb->nh.iph->saddr;
11583 + /* dest port only if respective mode */
11584 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
11587 + /* Must not be a fragment. */
11591 + /* Must be big enough to read ports (both UDP and TCP have
11592 + them at the start). */
11593 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
11594 + /* We've been asked to examine this packet, and we
11595 + can't. Hence, no choice but to drop. */
11600 + switch (skb->nh.iph->protocol) {
11601 + struct tcphdr *th;
11602 + struct udphdr *uh;
11603 + case IPPROTO_TCP:
11604 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11605 + dst.port = th->dest;
11607 + case IPPROTO_UDP:
11608 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11609 + dst.port = uh->dest;
11616 + LOCK_BH(&hinfo->lock);
11617 + dh = __dsthash_find(hinfo, &dst);
11619 + dh = __dsthash_alloc_init(hinfo, &dst);
11622 + /* enomem... don't match == DROP */
11623 + if (net_ratelimit())
11624 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
11625 + UNLOCK_BH(&hinfo->lock);
11629 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
11631 + dh->rateinfo.prev = jiffies;
11632 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
11633 + hinfo->cfg.burst);
11634 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
11635 + hinfo->cfg.burst);
11636 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
11638 + UNLOCK_BH(&hinfo->lock);
11642 + /* update expiration timeout */
11643 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
11645 + rateinfo_recalc(dh, now);
11646 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
11647 + /* We're underlimit. */
11648 + dh->rateinfo.credit -= dh->rateinfo.cost;
11649 + UNLOCK_BH(&hinfo->lock);
11653 + UNLOCK_BH(&hinfo->lock);
11655 + /* default case: we're overlimit, thus don't match */
11660 +dstlimit_checkentry(const char *tablename,
11661 + const struct ipt_ip *ip,
11663 + unsigned int matchsize,
11664 + unsigned int hook_mask)
11666 + struct ipt_dstlimit_info *r = matchinfo;
11668 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
11671 + /* Check for overflow. */
11672 + if (r->cfg.burst == 0
11673 + || user2credits(r->cfg.avg * r->cfg.burst) <
11674 + user2credits(r->cfg.avg)) {
11675 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
11676 + r->cfg.avg, r->cfg.burst);
11680 + if (r->cfg.mode == 0
11681 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
11682 + |IPT_DSTLIMIT_HASH_DIP
11683 + |IPT_DSTLIMIT_HASH_SIP))
11686 + if (!r->cfg.gc_interval)
11689 + if (!r->cfg.expire)
11692 + r->hinfo = htable_find_get(r->name);
11693 + if (!r->hinfo && (htable_create(r) != 0)) {
11697 + /* Ugly hack: For SMP, we only want to use one set */
11704 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
11706 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
11708 + htable_put(r->hinfo);
11711 +static struct ipt_match ipt_dstlimit = {
11712 + .list = { .prev = NULL, .next = NULL },
11713 + .name = "dstlimit",
11714 + .match = dstlimit_match,
11715 + .checkentry = dstlimit_checkentry,
11716 + .destroy = dstlimit_destroy,
11717 + .me = THIS_MODULE
11722 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
11724 + struct proc_dir_entry *pde = s->private;
11725 + struct ipt_dstlimit_htable *htable = pde->data;
11726 + unsigned int *bucket;
11728 + LOCK_BH(&htable->lock);
11729 + if (*pos >= htable->cfg.size)
11732 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
11734 + return ERR_PTR(-ENOMEM);
11740 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
11742 + struct proc_dir_entry *pde = s->private;
11743 + struct ipt_dstlimit_htable *htable = pde->data;
11744 + unsigned int *bucket = (unsigned int *)v;
11746 + *pos = ++(*bucket);
11747 + if (*pos >= htable->cfg.size) {
11754 +static void dl_seq_stop(struct seq_file *s, void *v)
11756 + struct proc_dir_entry *pde = s->private;
11757 + struct ipt_dstlimit_htable *htable = pde->data;
11758 + unsigned int *bucket = (unsigned int *)v;
11762 + UNLOCK_BH(&htable->lock);
11765 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
11767 + /* recalculate to show accurate numbers */
11768 + rateinfo_recalc(ent, jiffies);
11770 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
11771 + (ent->expires - jiffies)/HZ,
11772 + NIPQUAD(ent->dst.src_ip),
11773 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
11774 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
11775 + ent->rateinfo.cost);
11778 +static int dl_seq_show(struct seq_file *s, void *v)
11780 + struct proc_dir_entry *pde = s->private;
11781 + struct ipt_dstlimit_htable *htable = pde->data;
11782 + unsigned int *bucket = (unsigned int *)v;
11784 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
11785 + struct dsthash_ent *, s)) {
11786 + /* buffer was filled and unable to print that tuple */
11792 +static struct seq_operations dl_seq_ops = {
11793 + .start = dl_seq_start,
11794 + .next = dl_seq_next,
11795 + .stop = dl_seq_stop,
11796 + .show = dl_seq_show
11799 +static int dl_proc_open(struct inode *inode, struct file *file)
11801 + int ret = seq_open(file, &dl_seq_ops);
11804 + struct seq_file *sf = file->private_data;
11805 + sf->private = PDE(inode);
11810 +static struct file_operations dl_file_ops = {
11811 + .owner = THIS_MODULE,
11812 + .open = dl_proc_open,
11813 + .read = seq_read,
11814 + .llseek = seq_lseek,
11815 + .release = seq_release
11818 +static int init_or_fini(int fini)
11825 + if (ipt_register_match(&ipt_dstlimit)) {
11827 + goto cleanup_nothing;
11830 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
11831 + * quite small ? */
11832 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
11833 + sizeof(struct dsthash_ent), 0,
11834 + SLAB_HWCACHE_ALIGN, NULL, NULL);
11835 + if (!dstlimit_cachep) {
11836 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
11838 + goto cleanup_unreg_match;
11841 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
11842 + if (!dstlimit_procdir) {
11843 + printk(KERN_ERR "Unable to create proc dir entry\n");
11845 + goto cleanup_free_slab;
11851 + remove_proc_entry("ipt_dstlimit", proc_net);
11852 +cleanup_free_slab:
11853 + kmem_cache_destroy(dstlimit_cachep);
11854 +cleanup_unreg_match:
11855 + ipt_unregister_match(&ipt_dstlimit);
11861 +static int __init init(void)
11863 + return init_or_fini(0);
11866 +static void __exit fini(void)
11871 +module_init(init);
11872 +module_exit(fini);
11873 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_fuzzy.c
11874 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
11875 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_fuzzy.c 2004-06-08 10:31:37.000000000 +0200
11878 + * This module implements a simple TSK FLC
11879 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
11880 + * to limit , in an adaptive and flexible way , the packet rate crossing
11881 + * a given stream . It serves as an initial and very simple (but effective)
11882 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
11883 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
11884 + * into our code in a precise , adaptive and efficient manner.
11885 + * The goal is very similar to that of "limit" match , but using techniques of
11886 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
11887 + * avoiding over and undershoots - and stuff like that .
11890 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
11891 + * 2002-08-17 : Changed to eliminate floating point operations .
11892 + * 2002-08-23 : Coding style changes .
11895 +#include <linux/module.h>
11896 +#include <linux/skbuff.h>
11897 +#include <linux/ip.h>
11898 +#include <linux/random.h>
11899 +#include <net/tcp.h>
11900 +#include <linux/spinlock.h>
11901 +#include <linux/netfilter_ipv4/ip_tables.h>
11902 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
11905 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
11906 + Expressed in percentage
11909 +#define PAR_LOW 1/100
11910 +#define PAR_HIGH 1
11912 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
11914 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
11915 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
11916 +MODULE_LICENSE("GPL");
11918 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11926 + return ( (100*(tx-mini)) / (maxi-mini) );
11929 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11937 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
11941 +ipt_fuzzy_match(const struct sk_buff *pskb,
11942 + const struct net_device *in,
11943 + const struct net_device *out,
11944 + const void *matchinfo,
11948 + /* From userspace */
11950 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
11952 + u_int8_t random_number;
11953 + unsigned long amount;
11954 + u_int8_t howhigh, howlow;
11957 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
11959 + info->bytes_total += pskb->len;
11960 + info->packets_total++;
11962 + info->present_time = jiffies;
11964 + if (info->present_time >= info->previous_time)
11965 + amount = info->present_time - info->previous_time;
11967 + /* There was a transition : I choose to re-sample
11968 + and keep the old acceptance rate...
11972 + info->previous_time = info->present_time;
11973 + info->bytes_total = info->packets_total = 0;
11976 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
11979 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
11982 + info->previous_time = info->present_time;
11983 + info->bytes_total = info->packets_total = 0;
11985 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
11986 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
11988 + info->acceptance_rate = (u_int8_t) \
11989 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
11991 + /* In fact , the above defuzzification would require a denominator
11992 + proportional to (howhigh+howlow) but , in this particular case ,
11993 + that expression is constant .
11994 + An imediate consequence is that it isn't necessary to call
11995 + both mf_high and mf_low - but to keep things understandable ,
12000 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
12003 + if ( info->acceptance_rate < 100 )
12005 + get_random_bytes((void *)(&random_number), 1);
12007 + /* If within the acceptance , it can pass => don't match */
12008 + if (random_number <= (255 * info->acceptance_rate) / 100)
12011 + return 1; /* It can't pass ( It matches ) */
12014 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
12019 +ipt_fuzzy_checkentry(const char *tablename,
12020 + const struct ipt_ip *e,
12022 + unsigned int matchsize,
12023 + unsigned int hook_mask)
12026 + const struct ipt_fuzzy_info *info = matchinfo;
12028 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
12029 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
12030 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
12034 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
12035 + || (info->minimum_rate >= info->maximum_rate )) {
12036 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
12043 +static struct ipt_match ipt_fuzzy_reg = {
12045 + .match = ipt_fuzzy_match,
12046 + .checkentry = ipt_fuzzy_checkentry,
12047 + .me = THIS_MODULE
12050 +static int __init init(void)
12052 + return ipt_register_match(&ipt_fuzzy_reg);
12055 +static void __exit fini(void)
12057 + ipt_unregister_match(&ipt_fuzzy_reg);
12060 +module_init(init);
12061 +module_exit(fini);
12062 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_helper.c
12063 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-06-07 21:14:55.000000000 +0200
12064 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_helper.c 2004-06-08 10:42:23.000000000 +0200
12065 @@ -41,17 +41,17 @@
12066 struct ip_conntrack_expect *exp;
12067 struct ip_conntrack *ct;
12068 enum ip_conntrack_info ctinfo;
12070 + int ret = info->invert;
12072 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12074 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
12080 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
12087 DEBUGP("master's name = %s , info->name = %s\n",
12088 exp->expectant->helper->name, info->name);
12090 - ret = !strncmp(exp->expectant->helper->name, info->name,
12091 - strlen(exp->expectant->helper->name)) ^ info->invert;
12092 + if (info->name[0] == '\0')
12095 + ret ^= !strncmp(exp->expectant->helper->name, info->name,
12096 + strlen(exp->expectant->helper->name));
12098 READ_UNLOCK(&ip_conntrack_lock);
12101 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
12104 - /* verify that we actually should match anything */
12105 - if ( strlen(info->name) == 0 )
12111 @@ -108,7 +107,6 @@
12113 static int __init init(void)
12115 - need_ip_conntrack();
12116 return ipt_register_match(&helper_match);
12119 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ipv4options.c
12120 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
12121 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ipv4options.c 2004-06-08 10:31:39.000000000 +0200
12124 + This is a module which is used to match ipv4 options.
12125 + This file is distributed under the terms of the GNU General Public
12126 + License (GPL). Copies of the GPL can be obtained from:
12127 + ftp://prep.ai.mit.edu/pub/gnu/GPL
12129 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
12130 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
12131 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
12132 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
12133 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
12136 +#include <linux/module.h>
12137 +#include <linux/skbuff.h>
12138 +#include <net/ip.h>
12140 +#include <linux/netfilter_ipv4/ip_tables.h>
12141 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
12143 +MODULE_LICENSE("GPL");
12144 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12147 +match(const struct sk_buff *skb,
12148 + const struct net_device *in,
12149 + const struct net_device *out,
12150 + const void *matchinfo,
12154 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
12155 + const struct iphdr *iph = skb->nh.iph;
12156 + const struct ip_options *opt;
12158 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
12159 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
12161 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
12162 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12163 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12164 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12165 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12166 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
12171 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
12172 + /* there are options, and we don't need to care which one */
12175 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
12176 + /* there are options but we don't want any ! */
12181 + opt = &(IPCB(skb)->opt);
12183 + /* source routing */
12184 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
12185 + if (!((opt->srr) & (opt->is_strictroute)))
12188 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
12189 + if (!((opt->srr) & (!opt->is_strictroute)))
12192 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
12196 + /* record route */
12197 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
12201 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
12206 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
12210 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
12214 + /* router-alert option */
12215 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
12216 + if (!opt->router_alert)
12219 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
12220 + if (opt->router_alert)
12229 +checkentry(const char *tablename,
12230 + const struct ipt_ip *ip,
12232 + unsigned int matchsize,
12233 + unsigned int hook_mask)
12235 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
12236 + /* Check the size */
12237 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
12239 + /* Now check the coherence of the data ... */
12240 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
12241 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
12242 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
12243 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
12244 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
12245 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
12246 + return 0; /* opposites */
12247 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
12248 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12249 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12250 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12251 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12252 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
12253 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
12254 + return 0; /* opposites */
12255 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
12256 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
12257 + return 0; /* cannot match in the same time loose and strict source routing */
12258 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12259 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
12260 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
12261 + return 0; /* opposites */
12262 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
12263 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
12264 + return 0; /* opposites */
12265 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
12266 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
12267 + return 0; /* opposites */
12268 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
12269 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
12270 + return 0; /* opposites */
12272 + /* everything looks ok. */
12276 +static struct ipt_match ipv4options_match = {
12277 + .name = "ipv4options",
12279 + .checkentry = checkentry,
12280 + .me = THIS_MODULE
12283 +static int __init init(void)
12285 + return ipt_register_match(&ipv4options_match);
12288 +static void __exit fini(void)
12290 + ipt_unregister_match(&ipv4options_match);
12293 +module_init(init);
12294 +module_exit(fini);
12295 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_mport.c
12296 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
12297 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_mport.c 2004-06-08 10:31:40.000000000 +0200
12299 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
12300 + the same place so we can treat them as equal. */
12301 +#include <linux/module.h>
12302 +#include <linux/types.h>
12303 +#include <linux/udp.h>
12304 +#include <linux/skbuff.h>
12306 +#include <linux/netfilter_ipv4/ipt_mport.h>
12307 +#include <linux/netfilter_ipv4/ip_tables.h>
12309 +MODULE_LICENSE("GPL");
12312 +#define duprintf(format, args...) printk(format , ## args)
12314 +#define duprintf(format, args...)
12317 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
12319 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
12323 + u_int16_t pflags = minfo->pflags;
12324 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
12328 + && minfo->ports[i] == 65535)
12331 + s = minfo->ports[i];
12333 + if (pflags & m) {
12334 + e = minfo->ports[++i];
12339 + if (minfo->flags & IPT_MPORT_SOURCE
12340 + && src >= s && src <= e)
12343 + if (minfo->flags & IPT_MPORT_DESTINATION
12344 + && dst >= s && dst <= e)
12352 +match(const struct sk_buff *skb,
12353 + const struct net_device *in,
12354 + const struct net_device *out,
12355 + const void *matchinfo,
12360 + const struct ipt_mport *minfo = matchinfo;
12365 + /* Must be big enough to read ports (both UDP and TCP have
12366 + them at the start). */
12367 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12368 + /* We've been asked to examine this packet, and we
12369 + can't. Hence, no choice but to drop. */
12370 + duprintf("ipt_multiport:"
12371 + " Dropping evil offset=0 tinygram.\n");
12376 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
12379 +/* Called when user tries to insert an entry of this type. */
12381 +checkentry(const char *tablename,
12382 + const struct ipt_ip *ip,
12384 + unsigned int matchsize,
12385 + unsigned int hook_mask)
12387 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
12390 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
12391 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
12392 + && !(ip->invflags & IPT_INV_PROTO)
12393 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
12396 +static struct ipt_match mport_match = {
12399 + .checkentry = &checkentry,
12400 + .me = THIS_MODULE
12403 +static int __init init(void)
12405 + return ipt_register_match(&mport_match);
12408 +static void __exit fini(void)
12410 + ipt_unregister_match(&mport_match);
12413 +module_init(init);
12414 +module_exit(fini);
12415 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_nth.c
12416 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
12417 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_nth.c 2004-06-08 10:31:42.000000000 +0200
12420 + This is a module which is used for match support for every Nth packet
12421 + This file is distributed under the terms of the GNU General Public
12422 + License (GPL). Copies of the GPL can be obtained from:
12423 + ftp://prep.ai.mit.edu/pub/gnu/GPL
12425 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
12426 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
12427 + * added support for multiple counters
12428 + * added support for matching on individual packets
12429 + in the counter cycle
12430 + 2004-02-19 Harald Welte <laforge@netfilter.org>
12435 +#include <linux/module.h>
12436 +#include <linux/skbuff.h>
12437 +#include <linux/ip.h>
12438 +#include <net/tcp.h>
12439 +#include <linux/spinlock.h>
12440 +#include <linux/netfilter_ipv4/ip_tables.h>
12441 +#include <linux/netfilter_ipv4/ipt_nth.h>
12443 +MODULE_LICENSE("GPL");
12444 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12447 + * State information.
12451 + u_int16_t number;
12454 +static struct state states[IPT_NTH_NUM_COUNTERS];
12457 +ipt_nth_match(const struct sk_buff *pskb,
12458 + const struct net_device *in,
12459 + const struct net_device *out,
12460 + const void *matchinfo,
12464 + /* Parameters from userspace */
12465 + const struct ipt_nth_info *info = matchinfo;
12466 + unsigned counter = info->counter;
12467 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
12469 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12473 + spin_lock(&states[counter].lock);
12475 + /* Are we matching every nth packet?*/
12476 + if (info->packet == 0xFF)
12478 + /* We're matching every nth packet and only every nth packet*/
12479 + /* Do we match or invert match? */
12480 + if (info->not == 0)
12482 + if (states[counter].number == 0)
12484 + ++states[counter].number;
12487 + if (states[counter].number >= info->every)
12488 + states[counter].number = 0; /* reset the counter */
12490 + ++states[counter].number;
12495 + if (states[counter].number == 0)
12497 + ++states[counter].number;
12500 + if (states[counter].number >= info->every)
12501 + states[counter].number = 0;
12503 + ++states[counter].number;
12509 + /* We're using the --packet, so there must be a rule for every value */
12510 + if (states[counter].number == info->packet)
12512 + /* only increment the counter when a match happens */
12513 + if (states[counter].number >= info->every)
12514 + states[counter].number = 0; /* reset the counter */
12516 + ++states[counter].number;
12524 + /* don't match */
12525 + spin_unlock(&states[counter].lock);
12529 + spin_unlock(&states[counter].lock);
12534 +ipt_nth_checkentry(const char *tablename,
12535 + const struct ipt_ip *e,
12537 + unsigned int matchsize,
12538 + unsigned int hook_mask)
12540 + /* Parameters from userspace */
12541 + const struct ipt_nth_info *info = matchinfo;
12542 + unsigned counter = info->counter;
12543 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
12545 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12549 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
12550 + printk("nth: matchsize %u != %u\n", matchsize,
12551 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
12555 + states[counter].number = info->startat;
12560 +static struct ipt_match ipt_nth_reg = {
12562 + .match = ipt_nth_match,
12563 + .checkentry = ipt_nth_checkentry,
12564 + .me = THIS_MODULE
12567 +static int __init init(void)
12569 + unsigned counter;
12571 + memset(&states, 0, sizeof(states));
12572 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
12573 + spin_lock_init(&(states[counter].lock));
12575 + return ipt_register_match(&ipt_nth_reg);
12578 +static void __exit fini(void)
12580 + ipt_unregister_match(&ipt_nth_reg);
12583 +module_init(init);
12584 +module_exit(fini);
12585 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_osf.c
12586 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
12587 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_osf.c 2004-06-08 10:31:44.000000000 +0200
12592 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
12595 + * This program is free software; you can redistribute it and/or modify
12596 + * it under the terms of the GNU General Public License as published by
12597 + * the Free Software Foundation; either version 2 of the License, or
12598 + * (at your option) any later version.
12600 + * This program is distributed in the hope that it will be useful,
12601 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12602 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12603 + * GNU General Public License for more details.
12605 + * You should have received a copy of the GNU General Public License
12606 + * along with this program; if not, write to the Free Software
12607 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12611 + * OS fingerprint matching module.
12612 + * It simply compares various parameters from SYN packet with
12613 + * some hardcoded ones.
12615 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
12619 +#include <linux/config.h>
12620 +#include <linux/kernel.h>
12621 +#include <linux/types.h>
12622 +#include <linux/string.h>
12623 +#include <linux/smp.h>
12624 +#include <linux/module.h>
12625 +#include <linux/skbuff.h>
12626 +#include <linux/file.h>
12627 +#include <linux/ip.h>
12628 +#include <linux/proc_fs.h>
12629 +#include <linux/fs.h>
12630 +#include <linux/slab.h>
12631 +#include <linux/spinlock.h>
12632 +#include <linux/ctype.h>
12633 +#include <linux/list.h>
12634 +#include <linux/if.h>
12636 +#include <net/sock.h>
12637 +#include <net/ip.h>
12639 +#include <linux/netfilter_ipv4/ip_tables.h>
12641 +#include <linux/netfilter_ipv4/ipt_osf.h>
12646 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
12647 +#define loga(x...) printk(x)
12649 +#define log(x...) do {} while(0)
12650 +#define loga(x...) do {} while(0)
12653 +#define FMATCH_WRONG 0
12654 +#define FMATCH_OK 1
12655 +#define FMATCH_OPT_WRONG 2
12657 +#define OPTDEL ','
12658 +#define OSFPDEL ':'
12659 +#define MAXOPTSTRLEN 128
12660 +#define OSFFLUSH "FLUSH"
12662 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
12663 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
12664 +static struct list_head finger_list;
12665 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
12666 + const void *, int,
12667 + const void *, u_int16_t,
12669 +static int checkentry(const char *, const struct ipt_ip *, void *,
12670 + unsigned int, unsigned int);
12672 +static unsigned long seq, ipt_osf_groups = 1;
12673 +static struct sock *nts;
12675 +static struct ipt_match osf_match =
12685 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
12687 + unsigned int size;
12688 + struct sk_buff *skb;
12689 + struct ipt_osf_nlmsg *data;
12690 + struct nlmsghdr *nlh;
12692 + size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
12694 + skb = alloc_skb(size, GFP_ATOMIC);
12697 + log("skb_alloc() failed.\n");
12701 + nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
12703 + data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
12705 + memcpy(&data->f, f, sizeof(struct osf_finger));
12706 + memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
12707 + memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
12709 + NETLINK_CB(skb).dst_groups = ipt_osf_groups;
12710 + netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
12716 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
12718 + struct iphdr *ip = skb->nh.iph;
12720 + if (flags & IPT_OSF_SMART)
12722 + struct in_device *in_dev = in_dev_get(skb->dev);
12726 + if (inet_ifa_match(ip->saddr, ifa))
12728 + in_dev_put(in_dev);
12729 + return (ip->ttl == f_ttl);
12732 + endfor_ifa(in_dev);
12734 + in_dev_put(in_dev);
12735 + return (ip->ttl <= f_ttl);
12738 + return (ip->ttl == f_ttl);
12742 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
12743 + const void *matchinfo, int offset,
12744 + const void *hdr, u_int16_t datalen,
12747 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
12748 + struct iphdr *ip = skb->nh.iph;
12749 + struct tcphdr *tcp;
12750 + int fmatch = FMATCH_WRONG, fcount = 0;
12751 + unsigned long totlen, optsize = 0, window;
12752 + unsigned char df, *optp = NULL, *_optp = NULL;
12753 + char check_WSS = 0;
12754 + struct list_head *ent;
12755 + struct osf_finger *f;
12757 + if (!ip || !info)
12760 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
12765 + totlen = ntohs(ip->tot_len);
12766 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
12767 + window = ntohs(tcp->window);
12769 + if (tcp->doff*4 > sizeof(struct tcphdr))
12771 + _optp = optp = (char *)(tcp+1);
12772 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
12776 + /* Actually we can create hash/table of all genres and search
12777 + * only in appropriate part, but here is initial variant,
12778 + * so will use slow path.
12780 + read_lock(&osf_lock);
12781 + list_for_each(ent, &finger_list)
12783 + f = list_entry(ent, struct osf_finger, flist);
12785 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
12789 + fmatch = FMATCH_WRONG;
12791 + if (totlen == f->ss && df == f->df &&
12792 + smart_dec(skb, info->flags, f->ttl))
12794 + unsigned long foptsize;
12796 + unsigned short mss = 0;
12800 + switch (f->wss.wc)
12802 + case 0: check_WSS = 0; break;
12803 + case 'S': check_WSS = 1; break;
12804 + case 'T': check_WSS = 2; break;
12805 + case '%': check_WSS = 3; break;
12806 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
12807 + f->wss.wc, f->genre, f->details);
12811 + if (check_WSS == 4)
12814 + /* Check options */
12817 + for (optnum=0; optnum<f->opt_num; ++optnum)
12818 + foptsize += f->opt[optnum].length;
12821 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
12826 + fmatch = FMATCH_OK;
12827 + loga("\tYEP : matching without options.\n");
12828 + if ((info->flags & IPT_OSF_LOG) &&
12829 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
12836 + for (optnum=0; optnum<f->opt_num; ++optnum)
12838 + if (f->opt[optnum].kind == (*optp))
12840 + unsigned char len = f->opt[optnum].length;
12841 + unsigned char *optend = optp + len;
12842 + int loop_cont = 0;
12844 + fmatch = FMATCH_OK;
12850 + mss = ntohs(*(unsigned short *)(optp+2));
12865 + /* Skip kind and length fields*/
12868 + if (f->opt[optnum].wc.val != 0)
12870 + unsigned long tmp = 0;
12872 + /* Hmmm... It looks a bit ugly. :) */
12873 + memcpy(&tmp, optp,
12874 + (len > sizeof(unsigned long)?
12875 + sizeof(unsigned long):len));
12876 + /* 2 + 2: optlen(2 bytes) +
12877 + * kind(1 byte) + length(1 byte) */
12879 + tmp = ntohs(tmp);
12881 + tmp = ntohl(tmp);
12883 + if (f->opt[optnum].wc.wc == '%')
12885 + if ((tmp % f->opt[optnum].wc.val) != 0)
12886 + fmatch = FMATCH_OPT_WRONG;
12888 + else if (tmp != f->opt[optnum].wc.val)
12889 + fmatch = FMATCH_OPT_WRONG;
12896 + fmatch = FMATCH_OPT_WRONG;
12898 + if (fmatch != FMATCH_OK)
12902 + if (fmatch != FMATCH_OPT_WRONG)
12904 + fmatch = FMATCH_WRONG;
12906 + switch (check_WSS)
12909 + if (f->wss.val == 0 || window == f->wss.val)
12910 + fmatch = FMATCH_OK;
12912 + case 1: /* MSS */
12913 +/* Lurked in OpenBSD */
12914 +#define SMART_MSS 1460
12915 + if (window == f->wss.val*mss ||
12916 + window == f->wss.val*SMART_MSS)
12917 + fmatch = FMATCH_OK;
12919 + case 2: /* MTU */
12920 + if (window == f->wss.val*(mss+40) ||
12921 + window == f->wss.val*(SMART_MSS+40))
12922 + fmatch = FMATCH_OK;
12924 + case 3: /* MOD */
12925 + if ((window % f->wss.val) == 0)
12926 + fmatch = FMATCH_OK;
12932 + if (fmatch == FMATCH_OK)
12935 + log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
12936 + f->genre, f->version,
12937 + f->subtype, f->details,
12938 + NIPQUAD(ip->saddr), ntohs(tcp->source),
12939 + NIPQUAD(ip->daddr), ntohs(tcp->dest),
12940 + f->ttl - ip->ttl);
12941 + if (info->flags & IPT_OSF_NETLINK)
12943 + spin_lock_bh(&ipt_osf_netlink_lock);
12944 + ipt_osf_nlsend(f, skb);
12945 + spin_unlock_bh(&ipt_osf_netlink_lock);
12947 + if ((info->flags & IPT_OSF_LOG) &&
12948 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
12953 + if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
12955 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
12956 + unsigned int i, optsize;
12957 + struct osf_finger fg;
12959 + memset(&fg, 0, sizeof(fg));
12961 + if ((info->flags & IPT_OSF_LOG))
12962 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
12965 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
12966 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
12967 + opt, optsize) < 0)
12969 + if (info->flags & IPT_OSF_LOG)
12970 + loga("TRUNCATED");
12971 + if (info->flags & IPT_OSF_NETLINK)
12972 + strcpy(fg.details, "TRUNCATED");
12976 + for (i = 0; i < optsize; i++)
12978 + if (info->flags & IPT_OSF_LOG)
12979 + loga("%02X", opt[i]);
12981 + if (info->flags & IPT_OSF_NETLINK)
12982 + memcpy(fg.details, opt, MAXDETLEN);
12985 + if ((info->flags & IPT_OSF_LOG))
12986 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
12987 + NIPQUAD(ip->saddr), ntohs(tcp->source),
12988 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
12990 + if (info->flags & IPT_OSF_NETLINK)
12992 + fg.wss.val = window;
12993 + fg.ttl = ip->ttl;
12996 + strncpy(fg.genre, "Unknown", MAXGENRELEN);
12998 + spin_lock_bh(&ipt_osf_netlink_lock);
12999 + ipt_osf_nlsend(&fg, skb);
13000 + spin_unlock_bh(&ipt_osf_netlink_lock);
13004 + read_unlock(&osf_lock);
13006 + return (fmatch == FMATCH_OK)?1:0;
13010 +checkentry(const char *tablename,
13011 + const struct ipt_ip *ip,
13013 + unsigned int matchsize,
13014 + unsigned int hook_mask)
13016 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
13018 + if (ip->proto != IPPROTO_TCP)
13024 +static char * osf_strchr(char *ptr, char c)
13028 + tmp = strchr(ptr, c);
13030 + while (tmp && tmp+1 && isspace(*(tmp+1)))
13036 +static struct osf_finger * finger_alloc(void)
13038 + struct osf_finger *f;
13040 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
13042 + memset(f, 0, sizeof(struct osf_finger));
13047 +static void finger_free(struct osf_finger *f)
13049 + memset(f, 0, sizeof(struct osf_finger));
13054 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
13058 + unsigned long val;
13062 + while (ptr != NULL && i < olen)
13071 + ptr = osf_strchr(&obuf[i], OPTDEL);
13076 + i += (int)(ptr-&obuf[i]);
13083 + op = OSFOPT_SACKP;
13084 + ptr = osf_strchr(&obuf[i], OPTDEL);
13089 + i += (int)(ptr-&obuf[i]);
13097 + ptr = osf_strchr(&obuf[i], OPTDEL);
13102 + i += (int)(ptr-&obuf[i]);
13110 + ptr = osf_strchr(&obuf[i], OPTDEL);
13113 + switch (obuf[i+1])
13115 + case '%': wc = '%'; break;
13116 + case 'S': wc = 'S'; break;
13117 + case 'T': wc = 'T'; break;
13118 + default: wc = 0; break;
13124 + val = simple_strtoul(&obuf[i+2], NULL, 10);
13126 + val = simple_strtoul(&obuf[i+1], NULL, 10);
13127 + i += (int)(ptr-&obuf[i]);
13135 + ptr = osf_strchr(&obuf[i], OPTDEL);
13138 + if (obuf[i+1] == '%')
13143 + val = simple_strtoul(&obuf[i+2], NULL, 10);
13145 + val = simple_strtoul(&obuf[i+1], NULL, 10);
13146 + i += (int)(ptr-&obuf[i]);
13154 + ptr = osf_strchr(&obuf[i], OPTDEL);
13159 + i += (int)(ptr-&obuf[i]);
13166 + ptr = osf_strchr(&obuf[i], OPTDEL);
13170 + i += (int)(ptr-&obuf[i]);
13178 + opt[*optnum].kind = IANA_opts[op].kind;
13179 + opt[*optnum].length = IANA_opts[op].length;
13180 + opt[*optnum].wc.wc = wc;
13181 + opt[*optnum].wc.val = val;
13187 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
13189 + struct list_head *ent;
13190 + struct osf_finger *f = NULL;
13196 + read_lock_bh(&osf_lock);
13197 + list_for_each(ent, &finger_list)
13199 + f = list_entry(ent, struct osf_finger, flist);
13201 + log("%s [%s]", f->genre, f->details);
13203 + count += sprintf(buf+count, "%s - %s[%s] : %s",
13204 + f->genre, f->version,
13205 + f->subtype, f->details);
13210 + //count += sprintf(buf+count, " OPT: ");
13211 + for (i=0; i<f->opt_num; ++i)
13213 + //count += sprintf(buf+count, "%d.%c%lu; ",
13214 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13215 + loga("%d.%c%lu; ",
13216 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13220 + count += sprintf(buf+count, "\n");
13222 + read_unlock_bh(&osf_lock);
13227 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
13231 + char obuf[MAXOPTSTRLEN];
13232 + struct osf_finger *finger;
13233 + struct list_head *ent, *n;
13235 + char *pbeg, *pend;
13237 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
13240 + write_lock_bh(&osf_lock);
13241 + list_for_each_safe(ent, n, &finger_list)
13244 + finger = list_entry(ent, struct osf_finger, flist);
13245 + list_del(&finger->flist);
13246 + finger_free(finger);
13248 + write_unlock_bh(&osf_lock);
13250 + log("Flushed %d entries.\n", i);
13257 + for (i=0; i<count && buffer[i] != '\0'; ++i)
13258 + if (buffer[i] == ':')
13261 + if (cnt != 8 || i != count)
13263 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
13268 + memset(obuf, 0, sizeof(obuf));
13270 + finger = finger_alloc();
13273 + log("Failed to allocate new fingerprint entry.\n");
13277 + pbeg = (char *)buffer;
13278 + pend = osf_strchr(pbeg, OSFPDEL);
13282 + if (pbeg[0] == 'S')
13284 + finger->wss.wc = 'S';
13285 + if (pbeg[1] == '%')
13286 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13287 + else if (pbeg[1] == '*')
13288 + finger->wss.val = 0;
13290 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13292 + else if (pbeg[0] == 'T')
13294 + finger->wss.wc = 'T';
13295 + if (pbeg[1] == '%')
13296 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13297 + else if (pbeg[1] == '*')
13298 + finger->wss.val = 0;
13300 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13302 + else if (pbeg[0] == '%')
13304 + finger->wss.wc = '%';
13305 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13307 + else if (isdigit(pbeg[0]))
13309 + finger->wss.wc = 0;
13310 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
13315 + pend = osf_strchr(pbeg, OSFPDEL);
13319 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
13322 + pend = osf_strchr(pbeg, OSFPDEL);
13326 + finger->df = simple_strtoul(pbeg, NULL, 10);
13329 + pend = osf_strchr(pbeg, OSFPDEL);
13333 + finger->ss = simple_strtoul(pbeg, NULL, 10);
13337 + pend = osf_strchr(pbeg, OSFPDEL);
13341 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
13345 + pend = osf_strchr(pbeg, OSFPDEL);
13349 + if (pbeg[0] == '@' || pbeg[0] == '*')
13350 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
13352 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
13356 + pend = osf_strchr(pbeg, OSFPDEL);
13360 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
13364 + pend = osf_strchr(pbeg, OSFPDEL);
13368 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
13372 + cnt = snprintf(finger->details,
13373 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
13376 + log("%s - %s[%s] : %s\n",
13377 + finger->genre, finger->version,
13378 + finger->subtype, finger->details);
13380 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
13383 + write_lock_bh(&osf_lock);
13384 + list_add_tail(&finger->flist, &finger_list);
13385 + write_unlock_bh(&osf_lock);
13390 +static int __init osf_init(void)
13393 + struct proc_dir_entry *p;
13395 + log("Startng OS fingerprint matching module.\n");
13397 + INIT_LIST_HEAD(&finger_list);
13399 + err = ipt_register_match(&osf_match);
13402 + log("Failed to register OS fingerprint matching module.\n");
13406 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
13409 + ipt_unregister_match(&osf_match);
13413 + p->write_proc = osf_proc_write;
13414 + p->read_proc = osf_proc_read;
13416 + nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
13419 + log("netlink_kernel_create() failed\n");
13420 + remove_proc_entry("sys/net/ipv4/osf", NULL);
13421 + ipt_unregister_match(&osf_match);
13428 +static void __exit osf_fini(void)
13430 + struct list_head *ent, *n;
13431 + struct osf_finger *f;
13433 + remove_proc_entry("sys/net/ipv4/osf", NULL);
13434 + ipt_unregister_match(&osf_match);
13435 + if (nts && nts->sk_socket)
13436 + sock_release(nts->sk_socket);
13438 + list_for_each_safe(ent, n, &finger_list)
13440 + f = list_entry(ent, struct osf_finger, flist);
13441 + list_del(&f->flist);
13445 + log("OS fingerprint matching module finished.\n");
13448 +module_init(osf_init);
13449 +module_exit(osf_fini);
13451 +MODULE_LICENSE("GPL");
13452 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
13453 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
13454 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_owner.c
13455 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_owner.c 2004-06-07 21:15:11.000000000 +0200
13456 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_owner.c 2004-06-08 10:39:56.000000000 +0200
13458 * This program is free software; you can redistribute it and/or modify
13459 * it under the terms of the GNU General Public License version 2 as
13460 * published by the Free Software Foundation.
13462 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
13465 #include <linux/module.h>
13466 #include <linux/skbuff.h>
13467 #include <linux/file.h>
13468 +#include <linux/ip.h>
13469 +#include <linux/tcp.h>
13470 +#include <linux/udp.h>
13471 #include <net/sock.h>
13472 +#include <net/tcp.h>
13473 +#include <net/udp.h>
13475 #include <linux/netfilter_ipv4/ipt_owner.h>
13476 #include <linux/netfilter_ipv4/ip_tables.h>
13478 MODULE_DESCRIPTION("iptables owner match");
13481 -match_comm(const struct sk_buff *skb, const char *comm)
13482 +match_comm(const struct sock *sk, const char *comm)
13484 struct task_struct *g, *p;
13485 struct files_struct *files;
13487 spin_lock(&files->file_lock);
13488 for (i=0; i < files->max_fds; i++) {
13489 if (fcheck_files(files, i) ==
13490 - skb->sk->sk_socket->file) {
13491 + sk->sk_socket->file) {
13492 spin_unlock(&files->file_lock);
13494 read_unlock(&tasklist_lock);
13499 -match_pid(const struct sk_buff *skb, pid_t pid)
13500 +match_pid(const struct sock *sk, pid_t pid)
13502 struct task_struct *p;
13503 struct files_struct *files;
13505 spin_lock(&files->file_lock);
13506 for (i=0; i < files->max_fds; i++) {
13507 if (fcheck_files(files, i) ==
13508 - skb->sk->sk_socket->file) {
13509 + sk->sk_socket->file) {
13510 spin_unlock(&files->file_lock);
13512 read_unlock(&tasklist_lock);
13513 @@ -86,10 +93,10 @@
13517 -match_sid(const struct sk_buff *skb, pid_t sid)
13518 +match_sid(const struct sock *sk, pid_t sid)
13520 struct task_struct *g, *p;
13521 - struct file *file = skb->sk->sk_socket->file;
13522 + struct file *file = sk->sk_socket->file;
13525 read_lock(&tasklist_lock);
13526 @@ -129,41 +136,71 @@
13529 const struct ipt_owner_info *info = matchinfo;
13530 + struct iphdr *iph = skb->nh.iph;
13531 + struct sock *sk = NULL;
13537 + if (iph->protocol == IPPROTO_TCP) {
13538 + struct tcphdr *tcph =
13539 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
13540 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
13541 + iph->daddr, tcph->dest,
13542 + skb->dev->ifindex);
13543 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
13544 + tcp_tw_put((struct tcp_tw_bucket *)sk);
13547 + } else if (iph->protocol == IPPROTO_UDP) {
13548 + struct udphdr *udph =
13549 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
13550 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
13551 + udph->dest, skb->dev->ifindex);
13555 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
13557 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
13560 if(info->match & IPT_OWNER_UID) {
13561 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
13562 + if ((sk->sk_socket->file->f_uid != info->uid) ^
13563 !!(info->invert & IPT_OWNER_UID))
13568 if(info->match & IPT_OWNER_GID) {
13569 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
13570 + if ((sk->sk_socket->file->f_gid != info->gid) ^
13571 !!(info->invert & IPT_OWNER_GID))
13576 if(info->match & IPT_OWNER_PID) {
13577 - if (!match_pid(skb, info->pid) ^
13578 + if (!match_pid(sk, info->pid) ^
13579 !!(info->invert & IPT_OWNER_PID))
13584 if(info->match & IPT_OWNER_SID) {
13585 - if (!match_sid(skb, info->sid) ^
13586 + if (!match_sid(sk, info->sid) ^
13587 !!(info->invert & IPT_OWNER_SID))
13592 if(info->match & IPT_OWNER_COMM) {
13593 - if (!match_comm(skb, info->comm) ^
13594 + if (!match_comm(sk, info->comm) ^
13595 !!(info->invert & IPT_OWNER_COMM))
13611 @@ -173,11 +210,19 @@
13612 unsigned int matchsize,
13613 unsigned int hook_mask)
13616 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
13617 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
13621 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
13622 + (1 << NF_IP_LOCAL_IN))) {
13623 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
13624 + "or POST_ROUTING.\n");
13628 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
13629 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
13630 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
13634 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
13635 printk("Matchsize %u != %Zu\n", matchsize,
13636 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_policy.c
13637 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
13638 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_policy.c 2004-06-08 10:42:36.000000000 +0200
13640 +/* IP tables module for matching IPsec policy
13642 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
13644 + * This program is free software; you can redistribute it and/or modify
13645 + * it under the terms of the GNU General Public License version 2 as
13646 + * published by the Free Software Foundation.
13649 +#include <linux/kernel.h>
13650 +#include <linux/config.h>
13651 +#include <linux/module.h>
13652 +#include <linux/skbuff.h>
13653 +#include <linux/init.h>
13654 +#include <net/xfrm.h>
13656 +#include <linux/netfilter_ipv4.h>
13657 +#include <linux/netfilter_ipv4/ipt_policy.h>
13658 +#include <linux/netfilter_ipv4/ip_tables.h>
13660 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
13661 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
13662 +MODULE_LICENSE("GPL");
13666 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
13668 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
13670 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
13671 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
13672 + MISMATCH(proto, x->id.proto) ||
13673 + MISMATCH(mode, x->props.mode) ||
13674 + MISMATCH(spi, x->id.spi) ||
13675 + MISMATCH(reqid, x->props.reqid))
13681 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
13683 + const struct ipt_policy_elem *e;
13684 + struct sec_path *sp = skb->sp;
13685 + int strict = info->flags & POLICY_MATCH_STRICT;
13690 + if (strict && info->len != sp->len)
13693 + for (i = sp->len - 1; i >= 0; i--) {
13694 + pos = strict ? i - sp->len + 1 : 0;
13695 + if (pos >= info->len)
13697 + e = &info->pol[pos];
13699 + if (match_xfrm_state(sp->x[i].xvec, e)) {
13702 + } else if (strict)
13706 + return strict ? 1 : 0;
13710 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
13712 + const struct ipt_policy_elem *e;
13713 + struct dst_entry *dst = skb->dst;
13714 + int strict = info->flags & POLICY_MATCH_STRICT;
13717 + if (dst->xfrm == NULL)
13720 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
13721 + pos = strict ? i : 0;
13722 + if (pos >= info->len)
13724 + e = &info->pol[pos];
13726 + if (match_xfrm_state(dst->xfrm, e)) {
13729 + } else if (strict)
13733 + return strict ? 1 : 0;
13736 +static int match(const struct sk_buff *skb,
13737 + const struct net_device *in,
13738 + const struct net_device *out,
13739 + const void *matchinfo, int offset, int *hotdrop)
13741 + const struct ipt_policy_info *info = matchinfo;
13744 + if (info->flags & POLICY_MATCH_IN)
13745 + ret = match_policy_in(skb, info);
13747 + ret = match_policy_out(skb, info);
13750 + if (info->flags & POLICY_MATCH_NONE)
13754 + } else if (info->flags & POLICY_MATCH_NONE)
13760 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
13761 + void *matchinfo, unsigned int matchsize,
13762 + unsigned int hook_mask)
13764 + struct ipt_policy_info *info = matchinfo;
13766 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
13767 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
13768 + matchsize, IPT_ALIGN(sizeof(*info)));
13771 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
13772 + printk(KERN_ERR "ipt_policy: neither incoming nor "
13773 + "outgoing policy selected\n");
13776 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
13777 + && info->flags & POLICY_MATCH_OUT) {
13778 + printk(KERN_ERR "ipt_policy: output policy not valid in "
13779 + "PRE_ROUTING and INPUT\n");
13782 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
13783 + && info->flags & POLICY_MATCH_IN) {
13784 + printk(KERN_ERR "ipt_policy: input policy not valid in "
13785 + "POST_ROUTING and OUTPUT\n");
13788 + if (info->len > POLICY_MAX_ELEM) {
13789 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
13796 +static struct ipt_match policy_match =
13798 + .name = "policy",
13800 + .checkentry = checkentry,
13801 + .me = THIS_MODULE,
13804 +static int __init init(void)
13806 + return ipt_register_match(&policy_match);
13809 +static void __exit fini(void)
13811 + ipt_unregister_match(&policy_match);
13814 +module_init(init);
13815 +module_exit(fini);
13816 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_pool.c
13817 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
13818 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_pool.c 2004-06-08 10:31:45.000000000 +0200
13820 +/* Kernel module to match an IP address pool. */
13822 +#include <linux/module.h>
13823 +#include <linux/ip.h>
13824 +#include <linux/skbuff.h>
13826 +#include <linux/netfilter_ipv4/ip_tables.h>
13827 +#include <linux/netfilter_ipv4/ip_pool.h>
13828 +#include <linux/netfilter_ipv4/ipt_pool.h>
13830 +static inline int match_pool(
13835 + if (ip_pool_match(index, ntohl(addr)))
13841 + const struct sk_buff *skb,
13842 + const struct net_device *in,
13843 + const struct net_device *out,
13844 + const void *matchinfo,
13847 + u_int16_t datalen,
13850 + const struct ipt_pool_info *info = matchinfo;
13851 + const struct iphdr *iph = skb->nh.iph;
13853 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
13854 + info->flags&IPT_POOL_INV_SRC))
13857 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
13858 + info->flags&IPT_POOL_INV_DST))
13864 +static int checkentry(
13865 + const char *tablename,
13866 + const struct ipt_ip *ip,
13868 + unsigned int matchsize,
13869 + unsigned int hook_mask
13871 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
13876 +static struct ipt_match pool_match
13877 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
13879 +static int __init init(void)
13881 + return ipt_register_match(&pool_match);
13884 +static void __exit fini(void)
13886 + ipt_unregister_match(&pool_match);
13889 +module_init(init);
13890 +module_exit(fini);
13891 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_psd.c
13892 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
13893 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_psd.c 2004-06-08 10:31:53.000000000 +0200
13896 + This is a module which is used for PSD (portscan detection)
13897 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
13898 + and LOG target module.
13900 + Copyright (C) 2000,2001 astaro AG
13902 + This file is distributed under the terms of the GNU General Public
13903 + License (GPL). Copies of the GPL can be obtained from:
13904 + ftp://prep.ai.mit.edu/pub/gnu/GPL
13906 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
13907 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
13908 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
13909 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
13910 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
13911 + 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
13914 +#include <linux/module.h>
13915 +#include <linux/skbuff.h>
13916 +#include <linux/ip.h>
13917 +#include <net/tcp.h>
13918 +#include <linux/spinlock.h>
13919 +#include <linux/netfilter_ipv4/ip_tables.h>
13920 +#include <linux/netfilter_ipv4/ipt_psd.h>
13923 +#define DEBUGP printk
13925 +#define DEBUGP(format, args...)
13928 +MODULE_LICENSE("GPL");
13929 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
13931 +#define HF_DADDR_CHANGING 0x01
13932 +#define HF_SPORT_CHANGING 0x02
13933 +#define HF_TOS_CHANGING 0x04
13934 +#define HF_TTL_CHANGING 0x08
13937 + * Information we keep per each target port
13940 + u_int16_t number; /* port number */
13941 + u_int8_t proto; /* protocol number */
13942 + u_int8_t and_flags; /* tcp ANDed flags */
13943 + u_int8_t or_flags; /* tcp ORed flags */
13947 + * Information we keep per each source address.
13950 + struct host *next; /* Next entry with the same hash */
13951 + clock_t timestamp; /* Last update time */
13952 + struct in_addr src_addr; /* Source address */
13953 + struct in_addr dest_addr; /* Destination address */
13954 + unsigned short src_port; /* Source port */
13955 + int count; /* Number of ports in the list */
13956 + int weight; /* Total weight of ports in the list */
13957 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
13958 + unsigned char tos; /* TOS */
13959 + unsigned char ttl; /* TTL */
13960 + unsigned char flags; /* HF_ flags bitmask */
13964 + * State information.
13968 + struct host list[LIST_SIZE]; /* List of source addresses */
13969 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
13970 + int index; /* Oldest entry to be replaced */
13974 + * Convert an IP address into a hash table index.
13976 +static inline int hashfunc(struct in_addr addr)
13978 + unsigned int value;
13981 + value = addr.s_addr;
13985 + } while ((value >>= HASH_LOG));
13987 + return hash & (HASH_SIZE - 1);
13991 +ipt_psd_match(const struct sk_buff *pskb,
13992 + const struct net_device *in,
13993 + const struct net_device *out,
13994 + const void *matchinfo,
13998 + struct iphdr *ip_hdr;
13999 + struct tcphdr *tcp_hdr;
14000 + struct in_addr addr;
14001 + u_int16_t src_port,dest_port;
14002 + u_int8_t tcp_flags, proto;
14004 + struct host *curr, *last, **head;
14005 + int hash, index, count;
14007 + /* Parameters from userspace */
14008 + const struct ipt_psd_info *psdinfo = matchinfo;
14011 + ip_hdr = pskb->nh.iph;
14013 + /* Sanity check */
14014 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
14015 + DEBUGP("PSD: sanity check failed\n");
14019 + /* TCP or UDP ? */
14020 + proto = ip_hdr->protocol;
14022 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
14023 + DEBUGP("PSD: protocol not supported\n");
14027 + /* Get the source address, source & destination ports, and TCP flags */
14029 + addr.s_addr = ip_hdr->saddr;
14031 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
14033 + /* Yep, it´s dirty */
14034 + src_port = tcp_hdr->source;
14035 + dest_port = tcp_hdr->dest;
14037 + if (proto == IPPROTO_TCP) {
14038 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
14041 + tcp_flags = 0x00;
14044 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
14045 + * them spoof us. [DHCP needs this feature - HW] */
14046 + if (!addr.s_addr) {
14047 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
14051 + /* Use jiffies here not to depend on someone setting the time while we're
14052 + * running; we need to be careful with possible return value overflows. */
14055 + spin_lock(&state.lock);
14057 + /* Do we know this source address already? */
14060 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
14062 + if (curr->src_addr.s_addr == addr.s_addr) break;
14064 + if (curr->next) last = curr;
14065 + } while ((curr = curr->next));
14069 + /* We know this address, and the entry isn't too old. Update it. */
14070 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
14071 + time_after_eq(now, curr->timestamp)) {
14073 + /* Just update the appropriate list entry if we've seen this port already */
14074 + for (index = 0; index < curr->count; index++) {
14075 + if (curr->ports[index].number == dest_port) {
14076 + curr->ports[index].proto = proto;
14077 + curr->ports[index].and_flags &= tcp_flags;
14078 + curr->ports[index].or_flags |= tcp_flags;
14079 + goto out_no_match;
14083 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
14084 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
14085 + goto out_no_match;
14087 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
14088 + curr->timestamp = now;
14090 + /* Logged this scan already? Then drop the packet. */
14091 + if (curr->weight >= psdinfo->weight_threshold)
14094 + /* Specify if destination address, source port, TOS or TTL are not fixed */
14095 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
14096 + curr->flags |= HF_DADDR_CHANGING;
14097 + if (curr->src_port != src_port)
14098 + curr->flags |= HF_SPORT_CHANGING;
14099 + if (curr->tos != ip_hdr->tos)
14100 + curr->flags |= HF_TOS_CHANGING;
14101 + if (curr->ttl != ip_hdr->ttl)
14102 + curr->flags |= HF_TTL_CHANGING;
14104 + /* Update the total weight */
14105 + curr->weight += (ntohs(dest_port) < 1024) ?
14106 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14108 + /* Got enough destination ports to decide that this is a scan? */
14109 + /* Then log it and drop the packet. */
14110 + if (curr->weight >= psdinfo->weight_threshold)
14113 + /* Remember the new port */
14114 + if (curr->count < SCAN_MAX_COUNT) {
14115 + curr->ports[curr->count].number = dest_port;
14116 + curr->ports[curr->count].proto = proto;
14117 + curr->ports[curr->count].and_flags = tcp_flags;
14118 + curr->ports[curr->count].or_flags = tcp_flags;
14122 + goto out_no_match;
14125 + /* We know this address, but the entry is outdated. Mark it unused, and
14126 + * remove from the hash table. We'll allocate a new entry instead since
14127 + * this one might get re-used too soon. */
14128 + curr->src_addr.s_addr = 0;
14130 + last->next = last->next->next;
14132 + *head = (*head)->next;
14136 + /* We don't need an ACK from a new source address */
14137 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
14138 + goto out_no_match;
14140 + /* Got too many source addresses with the same hash value? Then remove the
14141 + * oldest one from the hash table, so that they can't take too much of our
14142 + * CPU time even with carefully chosen spoofed IP addresses. */
14143 + if (count >= HASH_MAX && last) last->next = NULL;
14145 + /* We're going to re-use the oldest list entry, so remove it from the hash
14146 + * table first (if it is really already in use, and isn't removed from the
14147 + * hash table already because of the HASH_MAX check above). */
14149 + /* First, find it */
14150 + if (state.list[state.index].src_addr.s_addr)
14151 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
14155 + if ((curr = *head))
14157 + if (curr == &state.list[state.index]) break;
14159 + } while ((curr = curr->next));
14161 + /* Then, remove it */
14164 + last->next = last->next->next;
14166 + *head = (*head)->next;
14169 + /* Get our list entry */
14170 + curr = &state.list[state.index++];
14171 + if (state.index >= LIST_SIZE) state.index = 0;
14173 + /* Link it into the hash table */
14174 + head = &state.hash[hash];
14175 + curr->next = *head;
14178 + /* And fill in the fields */
14179 + curr->timestamp = now;
14180 + curr->src_addr = addr;
14181 + curr->dest_addr.s_addr = ip_hdr->daddr;
14182 + curr->src_port = src_port;
14184 + curr->weight = (ntohs(dest_port) < 1024) ?
14185 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14186 + curr->ports[0].number = dest_port;
14187 + curr->ports[0].proto = proto;
14188 + curr->ports[0].and_flags = tcp_flags;
14189 + curr->ports[0].or_flags = tcp_flags;
14190 + curr->tos = ip_hdr->tos;
14191 + curr->ttl = ip_hdr->ttl;
14194 + spin_unlock(&state.lock);
14198 + spin_unlock(&state.lock);
14202 +static int ipt_psd_checkentry(const char *tablename,
14203 + const struct ipt_ip *e,
14205 + unsigned int matchsize,
14206 + unsigned int hook_mask)
14208 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
14210 + /* we accept TCP only */
14211 +/* if (e->ip.proto != IPPROTO_TCP) { */
14212 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
14216 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
14217 + DEBUGP("PSD: matchsize %u != %u\n",
14219 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
14226 +static struct ipt_match ipt_psd_reg = {
14228 + .match = ipt_psd_match,
14229 + .checkentry = ipt_psd_checkentry,
14230 + .me = THIS_MODULE };
14232 +static int __init init(void)
14234 + if (ipt_register_match(&ipt_psd_reg))
14237 + memset(&state, 0, sizeof(state));
14239 + spin_lock_init(&(state.lock));
14241 + printk("netfilter PSD loaded - (c) astaro AG\n");
14245 +static void __exit fini(void)
14247 + ipt_unregister_match(&ipt_psd_reg);
14248 + printk("netfilter PSD unloaded - (c) astaro AG\n");
14251 +module_init(init);
14252 +module_exit(fini);
14253 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_quota.c
14254 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
14255 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_quota.c 2004-06-08 10:31:54.000000000 +0200
14258 + * netfilter module to enforce network quotas
14260 + * Sam Johnston <samj@samj.net>
14262 +#include <linux/module.h>
14263 +#include <linux/skbuff.h>
14264 +#include <linux/spinlock.h>
14265 +#include <linux/interrupt.h>
14267 +#include <linux/netfilter_ipv4/ip_tables.h>
14268 +#include <linux/netfilter_ipv4/ipt_quota.h>
14270 +MODULE_LICENSE("GPL");
14271 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14273 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
14276 +match(const struct sk_buff *skb,
14277 + const struct net_device *in,
14278 + const struct net_device *out,
14279 + const void *matchinfo,
14280 + int offset, int *hotdrop)
14282 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
14283 + unsigned int datalen;
14285 + if (skb->len < sizeof(struct iphdr))
14286 + return NF_ACCEPT;
14288 + datalen = skb->len - skb->nh.iph->ihl*4;
14290 + spin_lock_bh("a_lock);
14292 + if (q->quota >= datalen) {
14293 + /* we can afford this one */
14294 + q->quota -= datalen;
14295 + spin_unlock_bh("a_lock);
14297 +#ifdef DEBUG_IPT_QUOTA
14298 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
14303 + /* so we do not allow even small packets from now on */
14306 +#ifdef DEBUG_IPT_QUOTA
14307 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
14310 + spin_unlock_bh("a_lock);
14315 +checkentry(const char *tablename,
14316 + const struct ipt_ip *ip,
14317 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
14319 + /* TODO: spinlocks? sanity checks? */
14320 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
14326 +static struct ipt_match quota_match = {
14329 + .checkentry = checkentry,
14330 + .me = THIS_MODULE
14336 + return ipt_register_match("a_match);
14339 +static void __exit
14342 + ipt_unregister_match("a_match);
14345 +module_init(init);
14346 +module_exit(fini);
14348 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_random.c
14349 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
14350 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_random.c 2004-06-08 10:31:56.000000000 +0200
14353 + This is a module which is used for a "random" match support.
14354 + This file is distributed under the terms of the GNU General Public
14355 + License (GPL). Copies of the GPL can be obtained from:
14356 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14358 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14361 +#include <linux/module.h>
14362 +#include <linux/skbuff.h>
14363 +#include <linux/ip.h>
14364 +#include <linux/random.h>
14365 +#include <net/tcp.h>
14366 +#include <linux/spinlock.h>
14367 +#include <linux/netfilter_ipv4/ip_tables.h>
14368 +#include <linux/netfilter_ipv4/ipt_random.h>
14370 +MODULE_LICENSE("GPL");
14373 +ipt_rand_match(const struct sk_buff *pskb,
14374 + const struct net_device *in,
14375 + const struct net_device *out,
14376 + const void *matchinfo,
14379 + u_int16_t datalen,
14382 + /* Parameters from userspace */
14383 + const struct ipt_rand_info *info = matchinfo;
14384 + u_int8_t random_number;
14386 + /* get 1 random number from the kernel random number generation routine */
14387 + get_random_bytes((void *)(&random_number), 1);
14389 + /* Do we match ? */
14390 + if (random_number <= info->average)
14397 +ipt_rand_checkentry(const char *tablename,
14398 + const struct ipt_ip *e,
14400 + unsigned int matchsize,
14401 + unsigned int hook_mask)
14403 + /* Parameters from userspace */
14404 + const struct ipt_rand_info *info = matchinfo;
14406 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
14407 + printk("ipt_random: matchsize %u != %u\n", matchsize,
14408 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
14412 + /* must be 1 <= average % <= 99 */
14413 + /* 1 x 2.55 = 2 */
14414 + /* 99 x 2.55 = 252 */
14415 + if ((info->average < 2) || (info->average > 252)) {
14416 + printk("ipt_random: invalid average %u\n", info->average);
14423 +static struct ipt_match ipt_rand_reg = {
14427 + ipt_rand_checkentry,
14431 +static int __init init(void)
14433 + if (ipt_register_match(&ipt_rand_reg))
14436 + printk("ipt_random match loaded\n");
14440 +static void __exit fini(void)
14442 + ipt_unregister_match(&ipt_rand_reg);
14443 + printk("ipt_random match unloaded\n");
14446 +module_init(init);
14447 +module_exit(fini);
14448 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_realm.c
14449 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
14450 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_realm.c 2004-06-08 10:32:20.000000000 +0200
14452 +/* IP tables module for matching the routing realm
14456 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
14458 + * This program is free software; you can redistribute it and/or modify
14459 + * it under the terms of the GNU General Public License version 2 as
14460 + * published by the Free Software Foundation.
14463 +#include <linux/module.h>
14464 +#include <linux/skbuff.h>
14465 +#include <linux/netdevice.h>
14466 +#include <net/route.h>
14468 +#include <linux/netfilter_ipv4/ipt_realm.h>
14469 +#include <linux/netfilter_ipv4/ip_tables.h>
14471 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
14472 +MODULE_LICENSE("GPL");
14475 +match(const struct sk_buff *skb,
14476 + const struct net_device *in,
14477 + const struct net_device *out,
14478 + const void *matchinfo,
14482 + const struct ipt_realm_info *info = matchinfo;
14483 + struct dst_entry *dst = skb->dst;
14488 + return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
14491 +static int check(const char *tablename,
14492 + const struct ipt_ip *ip,
14494 + unsigned int matchsize,
14495 + unsigned int hook_mask)
14498 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
14499 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
14500 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
14501 + "LOCAL_IN or FORWARD.\n");
14505 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
14511 +static struct ipt_match realm_match = {
14514 + .checkentry = check,
14515 + .me = THIS_MODULE
14518 +static int __init init(void)
14520 + return ipt_register_match(&realm_match);
14523 +static void __exit fini(void)
14525 + ipt_unregister_match(&realm_match);
14528 +module_init(init);
14529 +module_exit(fini);
14530 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_sctp.c
14531 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
14532 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_sctp.c 2004-06-08 10:32:21.000000000 +0200
14534 +#include <linux/module.h>
14535 +#include <linux/skbuff.h>
14536 +#include <net/ip.h>
14537 +#include <linux/sctp.h>
14539 +#include <linux/netfilter_ipv4/ip_tables.h>
14540 +#include <linux/netfilter_ipv4/ipt_sctp.h>
14543 +#define duprintf(format, args...) printk(format , ## args)
14545 +#define duprintf(format, args...)
14548 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
14549 + || (!!((invflag) & (option)) ^ (cond)))
14552 +match_flags(const struct ipt_sctp_flag_info *flag_info,
14553 + const int flag_count,
14554 + u_int8_t chunktype,
14555 + u_int8_t chunkflags)
14559 + for (i = 0; i < flag_count; i++) {
14560 + if (flag_info[i].chunktype == chunktype) {
14561 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
14569 +match_packet(const struct sk_buff *skb,
14570 + const u_int32_t *chunkmap,
14571 + int chunk_match_type,
14572 + const struct ipt_sctp_flag_info *flag_info,
14573 + const int flag_count,
14577 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
14578 + sctp_chunkhdr_t sch;
14582 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
14583 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
14586 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
14588 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
14589 + duprintf("Dropping invalid SCTP packet.\n");
14594 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
14595 + ++i, offset, sch.type, htons(sch.length), sch.flags);
14597 + offset += (htons(sch.length) + 3) & ~3;
14599 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
14601 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
14602 + switch (chunk_match_type) {
14603 + case SCTP_CHUNK_MATCH_ANY:
14604 + if (match_flags(flag_info, flag_count,
14605 + sch.type, sch.flags)) {
14610 + case SCTP_CHUNK_MATCH_ALL:
14611 + if (match_flags(flag_info, flag_count,
14612 + sch.type, sch.flags)) {
14613 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
14617 + case SCTP_CHUNK_MATCH_ONLY:
14618 + if (!match_flags(flag_info, flag_count,
14619 + sch.type, sch.flags)) {
14625 + switch (chunk_match_type) {
14626 + case SCTP_CHUNK_MATCH_ONLY:
14630 + } while (offset < skb->len);
14632 + switch (chunk_match_type) {
14633 + case SCTP_CHUNK_MATCH_ALL:
14634 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
14635 + case SCTP_CHUNK_MATCH_ANY:
14637 + case SCTP_CHUNK_MATCH_ONLY:
14641 + /* This will never be reached, but required to stop compiler whine */
14646 +match(const struct sk_buff *skb,
14647 + const struct net_device *in,
14648 + const struct net_device *out,
14649 + const void *matchinfo,
14653 + const struct ipt_sctp_info *info;
14654 + sctp_sctphdr_t sh;
14656 + info = (const struct ipt_sctp_info *)matchinfo;
14659 + duprintf("Dropping non-first fragment.. FIXME\n");
14663 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
14664 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
14668 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
14670 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
14671 + && (ntohs(sh.source) <= info->spts[1])),
14672 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
14673 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
14674 + && (ntohs(sh.dest) <= info->dpts[1])),
14675 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
14676 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
14677 + info->flag_info, info->flag_count,
14679 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
14683 +checkentry(const char *tablename,
14684 + const struct ipt_ip *ip,
14686 + unsigned int matchsize,
14687 + unsigned int hook_mask)
14689 + const struct ipt_sctp_info *info;
14691 + info = (const struct ipt_sctp_info *)matchinfo;
14693 + return ip->proto == IPPROTO_SCTP
14694 + && !(ip->invflags & IPT_INV_PROTO)
14695 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
14696 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
14697 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
14698 + && !(info->invflags & ~info->flags)
14699 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
14700 + (info->chunk_match_type &
14701 + (SCTP_CHUNK_MATCH_ALL
14702 + | SCTP_CHUNK_MATCH_ANY
14703 + | SCTP_CHUNK_MATCH_ONLY)));
14706 +static struct ipt_match sctp_match =
14708 + .list = { NULL, NULL},
14711 + .checkentry = &checkentry,
14713 + .me = THIS_MODULE
14716 +static int __init init(void)
14718 + return ipt_register_match(&sctp_match);
14721 +static void __exit fini(void)
14723 + ipt_unregister_match(&sctp_match);
14726 +module_init(init);
14727 +module_exit(fini);
14729 +MODULE_LICENSE("GPL");
14730 +MODULE_AUTHOR("Kiran Kumar Immidi");
14731 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
14733 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_string.c
14734 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
14735 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_string.c 2004-06-08 10:41:24.000000000 +0200
14737 +/* Kernel module to match a string into a packet.
14739 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
14742 + * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
14743 + * Initial 2.6 port
14744 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
14745 + * Fixed SMP re-entrancy problem using per-cpu data areas
14746 + * for the skip/shift tables.
14747 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14748 + * Fixed kernel panic, due to overrunning boyer moore string
14749 + * tables. Also slightly tweaked heuristic for deciding what
14750 + * search algo to use.
14751 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14752 + * Implemented Boyer Moore Sublinear search algorithm
14753 + * alongside the existing linear search based on memcmp().
14754 + * Also a quick check to decide which method to use on a per
14758 +#include <linux/smp.h>
14759 +#include <linux/percpu.h>
14760 +#include <linux/module.h>
14761 +#include <linux/skbuff.h>
14762 +#include <linux/file.h>
14763 +#include <net/sock.h>
14765 +#include <linux/netfilter_ipv4/ip_tables.h>
14766 +#include <linux/netfilter_ipv4/ipt_string.h>
14768 +MODULE_LICENSE("GPL");
14770 +struct string_per_cpu {
14771 + int skip[BM_MAX_HLEN];
14772 + int shift[BM_MAX_HLEN];
14773 + int len[BM_MAX_HLEN];
14776 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
14779 +/* Boyer Moore Sublinear string search - VERY FAST */
14780 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
14782 + int M1, right_end, sk, sh;
14785 + int *skip, *shift, *len;
14787 + /* use data suitable for this CPU */
14788 + shift=__get_cpu_var(bm_string_data).shift;
14789 + skip=__get_cpu_var(bm_string_data).skip;
14790 + len=__get_cpu_var(bm_string_data).len;
14792 + /* Setup skip/shift tables */
14793 + M1 = right_end = needle_len-1;
14794 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
14795 + for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
14797 + for (i = 1; i < needle_len; i++) {
14798 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
14803 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
14804 + for (i = M1; i > 0; i--) shift[len[i]] = i;
14807 + for (i = 0; i < needle_len; i++) {
14808 + if (len[i] == M1 - i) ended = i;
14809 + if (ended) shift[i] = ended;
14812 + /* Do the search*/
14813 + while (right_end < haystack_len)
14815 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
14816 + if (i == needle_len) {
14817 + return haystack+(right_end - M1);
14820 + sk = skip[(int)haystack[right_end - i]];
14822 + right_end = max(right_end - i + sk, right_end + sh);
14828 +/* Linear string search based on memcmp() */
14829 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
14831 + char *k = haystack + (haystack_len-needle_len);
14832 + char *t = haystack;
14834 + while ( t <= k ) {
14835 + if (memcmp(t, needle, needle_len) == 0)
14844 +match(const struct sk_buff *skb,
14845 + const struct net_device *in,
14846 + const struct net_device *out,
14847 + const void *matchinfo,
14851 + const struct ipt_string_info *info = matchinfo;
14852 + struct iphdr *ip = skb->nh.iph;
14854 + char *needle, *haystack;
14855 + proc_ipt_search search=search_linear;
14857 + if ( !ip ) return 0;
14859 + /* get lenghts, and validate them */
14861 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
14862 + if ( nlen > hlen ) return 0;
14864 + needle=(char *)&info->string;
14865 + haystack=(char *)ip+(ip->ihl*4);
14867 + /* The sublinear search comes in to its own
14868 + * on the larger packets */
14869 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
14870 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
14871 + if ( hlen < BM_MAX_HLEN ) {
14872 + search=search_sublinear;
14874 + if (net_ratelimit())
14875 + printk(KERN_INFO "ipt_string: Packet too big "
14876 + "to attempt sublinear string search "
14877 + "(%d bytes)\n", hlen );
14881 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
14885 +checkentry(const char *tablename,
14886 + const struct ipt_ip *ip,
14888 + unsigned int matchsize,
14889 + unsigned int hook_mask)
14892 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
14898 +static struct ipt_match string_match = {
14899 + .name = "string",
14901 + .checkentry = &checkentry,
14902 + .me = THIS_MODULE
14906 +static int __init init(void)
14908 + return ipt_register_match(&string_match);
14911 +static void __exit fini(void)
14913 + ipt_unregister_match(&string_match);
14916 +module_init(init);
14917 +module_exit(fini);
14920 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_time.c
14921 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
14922 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_time.c 2004-06-08 10:32:31.000000000 +0200
14925 + This is a module which is used for time matching
14926 + It is using some modified code from dietlibc (localtime() function)
14927 + that you can find at http://www.fefe.de/dietlibc/
14928 + This file is distributed under the terms of the GNU General Public
14929 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
14930 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
14931 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
14932 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
14933 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
14934 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
14935 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
14936 + 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
14939 +#include <linux/module.h>
14940 +#include <linux/skbuff.h>
14941 +#include <linux/netfilter_ipv4/ip_tables.h>
14942 +#include <linux/netfilter_ipv4/ipt_time.h>
14943 +#include <linux/time.h>
14945 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
14946 +MODULE_DESCRIPTION("Match arrival timestamp/date");
14947 +MODULE_LICENSE("GPL");
14951 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
14952 + int tm_min; /* Minutes. [0-59] */
14953 + int tm_hour; /* Hours. [0-23] */
14954 + int tm_mday; /* Day. [1-31] */
14955 + int tm_mon; /* Month. [0-11] */
14956 + int tm_year; /* Year - 1900. */
14957 + int tm_wday; /* Day of week. [0-6] */
14958 + int tm_yday; /* Days in year.[0-365] */
14959 + int tm_isdst; /* DST. [-1/0/1]*/
14961 + long int tm_gmtoff; /* we don't care, we count from GMT */
14962 + const char *tm_zone; /* we don't care, we count from GMT */
14966 +localtime(const time_t *timepr, struct tm *r);
14969 +match(const struct sk_buff *skb,
14970 + const struct net_device *in,
14971 + const struct net_device *out,
14972 + const void *matchinfo,
14975 + u_int16_t datalen,
14978 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
14979 + struct tm currenttime; /* time human readable */
14980 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
14981 + u_int16_t packet_time;
14982 + struct timeval kerneltimeval;
14983 + time_t packet_local_time;
14985 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
14986 + if (info->kerneltime)
14988 + do_gettimeofday(&kerneltimeval);
14989 + packet_local_time = kerneltimeval.tv_sec;
14992 + packet_local_time = skb->stamp.tv_sec;
14994 + /* First we make sure we are in the date start-stop boundaries */
14995 + if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
14996 + return 0; /* We are outside the date boundaries */
14998 + /* Transform the timestamp of the packet, in a human readable form */
14999 + localtime(&packet_local_time, ¤ttime);
15001 + /* check if we match this timestamp, we start by the days... */
15002 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
15003 + return 0; /* the day doesn't match */
15005 + /* ... check the time now */
15006 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
15007 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
15010 + /* here we match ! */
15015 +checkentry(const char *tablename,
15016 + const struct ipt_ip *ip,
15018 + unsigned int matchsize,
15019 + unsigned int hook_mask)
15021 + struct ipt_time_info *info = matchinfo; /* match info for rule */
15023 + /* First, check that we are in the correct hooks */
15025 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15027 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
15030 + /* we use the kerneltime if we are in forward or output */
15031 + info->kerneltime = 1;
15032 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15033 + /* we use the skb time */
15034 + info->kerneltime = 0;
15036 + /* Check the size */
15037 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
15039 + /* Now check the coherence of the data ... */
15040 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
15041 + (info->time_stop > 1439))
15043 + printk(KERN_WARNING "ipt_time: invalid argument\n");
15050 +static struct ipt_match time_match
15051 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
15053 +static int __init init(void)
15055 + printk("ipt_time loading\n");
15056 + return ipt_register_match(&time_match);
15059 +static void __exit fini(void)
15061 + ipt_unregister_match(&time_match);
15062 + printk("ipt_time unloaded\n");
15065 +module_init(init);
15066 +module_exit(fini);
15069 +/* The part below is borowed and modified from dietlibc */
15071 +/* seconds per day */
15072 +#define SPD 24*60*60
15075 +localtime(const time_t *timepr, struct tm *r) {
15078 + extern struct timezone sys_tz;
15079 + const unsigned int __spm[12] =
15085 + (31+28+31+30+31),
15086 + (31+28+31+30+31+30),
15087 + (31+28+31+30+31+30+31),
15088 + (31+28+31+30+31+30+31+31),
15089 + (31+28+31+30+31+30+31+31+30),
15090 + (31+28+31+30+31+30+31+31+30+31),
15091 + (31+28+31+30+31+30+31+31+30+31+30),
15093 + register time_t work;
15095 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
15096 + work=timep%(SPD);
15097 + r->tm_sec=work%60; work/=60;
15098 + r->tm_min=work%60; r->tm_hour=work/60;
15099 + work=timep/(SPD);
15100 + r->tm_wday=(4+work)%7;
15101 + for (i=1970; ; ++i) {
15102 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
15108 + r->tm_year=i-1900;
15109 + for (i=11; i && __spm[i]>work; --i) ;
15111 + r->tm_mday=work-__spm[i]+1;
15113 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_u32.c
15114 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
15115 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_u32.c 2004-06-08 10:32:32.000000000 +0200
15117 +/* Kernel module to match u32 packet content. */
15120 +U32 tests whether quantities of up to 4 bytes extracted from a packet
15121 +have specified values. The specification of what to extract is general
15122 +enough to find data at given offsets from tcp headers or payloads.
15125 + The argument amounts to a program in a small language described below.
15126 + tests := location = value | tests && location = value
15127 + value := range | value , range
15128 + range := number | number : number
15129 + a single number, n, is interpreted the same as n:n
15130 + n:m is interpreted as the range of numbers >=n and <=m
15131 + location := number | location operator number
15132 + operator := & | << | >> | @
15134 + The operators &, <<, >>, && mean the same as in c. The = is really a set
15135 + membership operator and the value syntax describes a set. The @ operator
15136 + is what allows moving to the next header and is described further below.
15138 + *** Until I can find out how to avoid it, there are some artificial limits
15139 + on the size of the tests:
15140 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
15141 + - no more than 10 ranges (and 9 commas) per value
15142 + - no more than 10 numbers (and 9 operators) per location
15144 + To describe the meaning of location, imagine the following machine that
15145 + interprets it. There are three registers:
15146 + A is of type char*, initially the address of the IP header
15147 + B and C are unsigned 32 bit integers, initially zero
15149 + The instructions are:
15150 + number B = number;
15151 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
15152 + &number C = C&number
15153 + <<number C = C<<number
15154 + >>number C = C>>number
15155 + @number A = A+C; then do the instruction number
15156 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
15157 + Otherwise the result of the computation is the final value of C.
15159 + Whitespace is allowed but not required in the tests.
15160 + However the characters that do occur there are likely to require
15161 + shell quoting, so it's a good idea to enclose the arguments in quotes.
15164 + match IP packets with total length >= 256
15165 + The IP header contains a total length field in bytes 2-3.
15166 + --u32 "0&0xFFFF=0x100:0xFFFF"
15168 + AND that with FFFF (giving bytes 2-3),
15169 + and test whether that's in the range [0x100:0xFFFF]
15171 +Example: (more realistic, hence more complicated)
15172 + match icmp packets with icmp type 0
15173 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
15174 + --u32 "6&0xFF=1 && ...
15175 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
15176 + Next test that it's not a fragment.
15177 + (If so it might be part of such a packet but we can't always tell.)
15178 + n.b. This test is generally needed if you want to match anything
15179 + beyond the IP header.
15180 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
15181 + packet (not a fragment). Alternatively, you can allow first fragments
15182 + by only testing the last 5 bits of byte 6.
15183 + ... 4&0x3FFF=0 && ...
15184 + Last test: the first byte past the IP header (the type) is 0
15185 + This is where we have to use the @syntax. The length of the IP header
15186 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
15187 + IP header itself.
15188 + ... 0>>22&0x3C@0>>24=0"
15189 + The first 0 means read bytes 0-3,
15190 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
15191 + the first byte, so only 22 bits is four times that plus a few more bits.
15192 + &3C then eliminates the two extra bits on the right and the first four
15193 + bits of the first byte.
15194 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
15195 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
15196 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
15197 + @ means to use this number as a new offset into the packet, and read
15198 + four bytes starting from there. This is the first 4 bytes of the icmp
15199 + payload, of which byte 0 is the icmp type. Therefore we simply shift
15200 + the value 24 to the right to throw out all but the first byte and compare
15201 + the result with 0.
15204 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
15205 + First we test that the packet is a tcp packet (similar to icmp).
15206 + --u32 "6&0xFF=6 && ...
15207 + Next, test that it's not a fragment (same as above).
15208 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
15209 + 0>>22&3C as above computes the number of bytes in the IP header.
15210 + @ makes this the new offset into the packet, which is the start of the
15211 + tcp header. The length of the tcp header (again in 32 bit words) is
15212 + the left half of byte 12 of the tcp header. The 12>>26&3C
15213 + computes this length in bytes (similar to the IP header before).
15214 + @ makes this the new offset, which is the start of the tcp payload.
15215 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
15216 + result is any of 1, 2, 5 or 8
15219 +#include <linux/module.h>
15220 +#include <linux/skbuff.h>
15222 +#include <linux/netfilter_ipv4/ipt_u32.h>
15223 +#include <linux/netfilter_ipv4/ip_tables.h>
15225 +/* #include <asm-i386/timex.h> for timing */
15227 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
15228 +MODULE_DESCRIPTION("IP tables u32 matching module");
15229 +MODULE_LICENSE("GPL");
15232 +match(const struct sk_buff *skb,
15233 + const struct net_device *in,
15234 + const struct net_device *out,
15235 + const void *matchinfo,
15238 + u_int16_t datalen,
15241 + const struct ipt_u32 *data = matchinfo;
15243 + unsigned char* origbase = (char*)skb->nh.iph;
15244 + unsigned char* base = origbase;
15245 + unsigned char* head = skb->head;
15246 + unsigned char* end = skb->end;
15247 + int nnums, nvals;
15248 + u_int32_t pos, val;
15249 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
15250 + cycles1 = get_cycles(); */
15252 + for (testind=0; testind < data->ntests; testind++) {
15253 + base = origbase; /* reset for each test */
15254 + pos = data->tests[testind].location[0].number;
15255 + if (base+pos+3 > end || base+pos < head)
15257 + val = (base[pos]<<24) + (base[pos+1]<<16) +
15258 + (base[pos+2]<<8) + base[pos+3];
15259 + nnums = data->tests[testind].nnums;
15260 + for (i=1; i < nnums; i++) {
15261 + u_int32_t number = data->tests[testind].location[i].number;
15262 + switch (data->tests[testind].location[i].nextop) {
15263 + case IPT_U32_AND:
15264 + val = val & number;
15266 + case IPT_U32_LEFTSH:
15267 + val = val << number;
15269 + case IPT_U32_RIGHTSH:
15270 + val = val >> number;
15273 + base = base + val;
15275 + if (base+pos+3 > end || base+pos < head)
15277 + val = (base[pos]<<24) + (base[pos+1]<<16) +
15278 + (base[pos+2]<<8) + base[pos+3];
15282 + nvals = data->tests[testind].nvalues;
15283 + for (i=0; i < nvals; i++) {
15284 + if ((data->tests[testind].value[i].min <= val) &&
15285 + (val <= data->tests[testind].value[i].max)) {
15289 + if (i >= data->tests[testind].nvalues) {
15290 + /* cycles2 = get_cycles();
15291 + printk("failed %d in %d cycles\n", testind,
15292 + cycles2-cycles1); */
15296 + /* cycles2 = get_cycles();
15297 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
15302 +checkentry(const char *tablename,
15303 + const struct ipt_ip *ip,
15305 + unsigned int matchsize,
15306 + unsigned int hook_mask)
15308 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
15313 +static struct ipt_match u32_match
15314 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
15316 +static int __init init(void)
15318 + return ipt_register_match(&u32_match);
15321 +static void __exit fini(void)
15323 + ipt_unregister_match(&u32_match);
15326 +module_init(init);
15327 +module_exit(fini);
15328 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_unclean.c
15329 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
15330 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_unclean.c 2004-06-08 10:41:16.000000000 +0200
15332 +/* Kernel module to match suspect packets. */
15333 +#include <linux/module.h>
15334 +#include <linux/skbuff.h>
15335 +#include <linux/ip.h>
15336 +#include <linux/udp.h>
15337 +#include <linux/tcp.h>
15338 +#include <linux/icmp.h>
15339 +#include <net/checksum.h>
15341 +#include <linux/netfilter_ipv4/ip_tables.h>
15343 +#define limpk(format, args...) \
15345 + if (net_ratelimit()) \
15346 + printk("ipt_unclean: %s" format, \
15347 + embedded ? "(embedded packet) " : "" , ## args); \
15350 +enum icmp_error_status
15352 + ICMP_MAY_BE_ERROR,
15359 + size_t min_len, max_len;
15360 + enum icmp_error_status err;
15361 + u_int8_t min_code, max_code;
15365 +check_ip(struct iphdr *iph, size_t length, int embedded);
15367 +/* ICMP-specific checks. */
15369 +check_icmp(const struct icmphdr *icmph,
15370 + u_int16_t datalen,
15371 + unsigned int offset,
15375 + static struct icmp_info info[]
15376 + = { [ICMP_ECHOREPLY]
15377 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15378 + [ICMP_DEST_UNREACH]
15379 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
15380 + [ICMP_SOURCE_QUENCH]
15381 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
15383 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
15385 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15386 + /* Router advertisement. */
15388 + = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
15389 + /* Router solicitation. */
15391 + = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
15392 + [ICMP_TIME_EXCEEDED]
15393 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
15394 + [ICMP_PARAMETERPROB]
15395 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
15397 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15398 + [ICMP_TIMESTAMPREPLY]
15399 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15400 + [ICMP_INFO_REQUEST]
15401 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15402 + [ICMP_INFO_REPLY]
15403 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15405 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
15406 + [ICMP_ADDRESSREPLY]
15407 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
15409 + /* Can't do anything if it's a fragment. */
15413 + /* Must cover type and code. */
15414 + if (datalen < 2) {
15415 + limpk("ICMP len=%u too short\n", datalen);
15419 + /* If not embedded. */
15421 + /* Bad checksum? Don't print, just ignore. */
15423 + && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
15426 + /* CHECK: Truncated ICMP (even if first fragment). */
15427 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15428 + && info[icmph->type].min_len != 0
15429 + && datalen < info[icmph->type].min_len) {
15430 + limpk("ICMP type %u len %u too short\n",
15431 + icmph->type, datalen);
15435 + /* CHECK: Check within known error ICMPs. */
15436 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15437 + && info[icmph->type].err == ICMP_IS_ERROR) {
15438 + /* CHECK: Embedded packet must be at least
15439 + length of iph + 8 bytes. */
15440 + struct iphdr *inner = (void *)icmph + 8;
15442 + /* datalen > 8 since all ICMP_IS_ERROR types
15443 + have min length > 8 */
15444 + if (datalen - 8 < sizeof(struct iphdr)) {
15445 + limpk("ICMP error internal way too short\n");
15448 + if (datalen - 8 < inner->ihl*4 + 8) {
15449 + limpk("ICMP error internal too short\n");
15452 + if (!check_ip(inner, datalen - 8, 1))
15456 + /* CHECK: Can't embed ICMP unless known non-error. */
15457 + if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
15458 + || info[icmph->type].err != ICMP_NOT_ERROR) {
15459 + limpk("ICMP type %u not embeddable\n",
15465 + /* CHECK: Invalid ICMP codes. */
15466 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15467 + && (icmph->code < info[icmph->type].min_code
15468 + || icmph->code > info[icmph->type].max_code)) {
15469 + limpk("ICMP type=%u code=%u\n",
15470 + icmph->type, icmph->code);
15474 + /* CHECK: Above maximum length. */
15475 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15476 + && info[icmph->type].max_len != 0
15477 + && datalen > info[icmph->type].max_len) {
15478 + limpk("ICMP type=%u too long: %u bytes\n",
15479 + icmph->type, datalen);
15483 + switch (icmph->type) {
15484 + case ICMP_PARAMETERPROB: {
15485 + /* CHECK: Problem param must be within error packet's
15487 + struct iphdr *iph = (void *)icmph + 8;
15488 + u_int32_t arg = ntohl(icmph->un.gateway);
15490 + if (icmph->code == 0) {
15491 + /* Code 0 means that upper 8 bits is pointer
15493 + if ((arg >> 24) >= iph->ihl*4) {
15494 + limpk("ICMP PARAMETERPROB ptr = %u\n",
15495 + ntohl(icmph->un.gateway) >> 24);
15498 + arg &= 0x00FFFFFF;
15501 + /* CHECK: Rest must be zero. */
15503 + limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
15510 + case ICMP_TIME_EXCEEDED:
15511 + case ICMP_SOURCE_QUENCH:
15512 + /* CHECK: Unused must be zero. */
15513 + if (icmph->un.gateway != 0) {
15514 + limpk("ICMP type=%u unused = %u\n",
15515 + icmph->type, ntohl(icmph->un.gateway));
15524 +/* UDP-specific checks. */
15526 +check_udp(const struct iphdr *iph,
15527 + const struct udphdr *udph,
15528 + u_int16_t datalen,
15529 + unsigned int offset,
15533 + /* Can't do anything if it's a fragment. */
15537 + /* CHECK: Must cover UDP header. */
15538 + if (datalen < sizeof(struct udphdr)) {
15539 + limpk("UDP len=%u too short\n", datalen);
15543 + /* Bad checksum? Don't print, just say it's unclean. */
15544 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
15545 + if (!more_frags && !embedded && udph->check
15546 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
15547 + csum_partial((char *)udph, datalen, 0)) != 0)
15550 + /* CHECK: Destination port can't be zero. */
15551 + if (!udph->dest) {
15552 + limpk("UDP zero destination port\n");
15556 + if (!more_frags) {
15558 + /* CHECK: UDP length must match. */
15559 + if (ntohs(udph->len) != datalen) {
15560 + limpk("UDP len too short %u vs %u\n",
15561 + ntohs(udph->len), datalen);
15565 + /* CHECK: UDP length be >= this truncated pkt. */
15566 + if (ntohs(udph->len) < datalen) {
15567 + limpk("UDP len too long %u vs %u\n",
15568 + ntohs(udph->len), datalen);
15573 + /* CHECK: UDP length must be > this frag's length. */
15574 + if (ntohs(udph->len) <= datalen) {
15575 + limpk("UDP fragment len too short %u vs %u\n",
15576 + ntohs(udph->len), datalen);
15584 +#define TH_FIN 0x01
15585 +#define TH_SYN 0x02
15586 +#define TH_RST 0x04
15587 +#define TH_PUSH 0x08
15588 +#define TH_ACK 0x10
15589 +#define TH_URG 0x20
15590 +#define TH_ECE 0x40
15591 +#define TH_CWR 0x80
15593 +/* table of valid flag combinations - ECE and CWR are always valid */
15594 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
15597 + [TH_SYN|TH_ACK] = 1,
15599 + [TH_RST|TH_ACK] = 1,
15600 + [TH_RST|TH_ACK|TH_PUSH] = 1,
15601 + [TH_FIN|TH_ACK] = 1,
15603 + [TH_ACK|TH_PUSH] = 1,
15604 + [TH_ACK|TH_URG] = 1,
15605 + [TH_ACK|TH_URG|TH_PUSH] = 1,
15606 + [TH_FIN|TH_ACK|TH_PUSH] = 1,
15607 + [TH_FIN|TH_ACK|TH_URG] = 1,
15608 + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
15611 +/* TCP-specific checks. */
15613 +check_tcp(const struct iphdr *iph,
15614 + const struct tcphdr *tcph,
15615 + u_int16_t datalen,
15616 + unsigned int offset,
15620 + u_int8_t *opt = (u_int8_t *)tcph;
15621 + u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
15622 + u_int8_t tcpflags;
15623 + int end_of_options = 0;
15626 + /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
15627 + /* In fact, this is caught below (offset < 516). */
15629 + /* Can't do anything if it's a fragment. */
15633 + /* CHECK: Smaller than minimal TCP hdr. */
15634 + if (datalen < sizeof(struct tcphdr)) {
15636 + limpk("Packet length %u < TCP header.\n", datalen);
15639 + /* Must have ports available (datalen >= 8), from
15640 + check_icmp which set embedded = 1 */
15641 + /* CHECK: TCP ports inside ICMP error */
15642 + if (!tcph->source || !tcph->dest) {
15643 + limpk("Zero TCP ports %u/%u.\n",
15644 + htons(tcph->source), htons(tcph->dest));
15650 + /* CHECK: Smaller than actual TCP hdr. */
15651 + if (datalen < tcph->doff * 4) {
15653 + limpk("Packet length %u < actual TCP header.\n",
15660 + /* Bad checksum? Don't print, just say it's unclean. */
15661 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
15662 + if (!more_frags && !embedded
15663 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
15664 + csum_partial((char *)tcph, datalen, 0)) != 0)
15667 + /* CHECK: TCP ports non-zero */
15668 + if (!tcph->source || !tcph->dest) {
15669 + limpk("Zero TCP ports %u/%u.\n",
15670 + htons(tcph->source), htons(tcph->dest));
15674 + /* CHECK: TCP reserved bits zero. */
15675 + if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
15676 + limpk("TCP reserved bits not zero\n");
15680 + /* CHECK: TCP flags. */
15681 + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
15682 + if (!tcp_valid_flags[tcpflags]) {
15683 + limpk("TCP flags bad: %u\n", tcpflags);
15687 + for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
15688 + switch (opt[i]) {
15690 + end_of_options = 1;
15697 + /* CHECK: options after EOO. */
15698 + if (end_of_options) {
15699 + limpk("TCP option %u after end\n",
15703 + /* CHECK: options at tail. */
15704 + else if (i+1 >= tcph->doff * 4) {
15705 + limpk("TCP option %u at tail\n",
15709 + /* CHECK: zero-length options. */
15710 + else if (opt[i+1] == 0) {
15711 + limpk("TCP option %u 0 len\n",
15715 + /* CHECK: oversize options. */
15716 + else if (&opt[i] + opt[i+1] > endhdr) {
15717 + limpk("TCP option %u at %Zu too long\n",
15718 + (unsigned int) opt[i], i);
15721 + /* Move to next option */
15729 +/* Returns 1 if ok */
15730 +/* Standard IP checks. */
15732 +check_ip(struct iphdr *iph, size_t length, int embedded)
15734 + u_int8_t *opt = (u_int8_t *)iph;
15735 + u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
15736 + int end_of_options = 0;
15740 + unsigned int offset;
15742 + /* Should only happen for local outgoing raw-socket packets. */
15743 + /* CHECK: length >= ip header. */
15744 + if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
15745 + limpk("Packet length %Zu < IP header.\n", length);
15749 + offset = ntohs(iph->frag_off) & IP_OFFSET;
15750 + protoh = (void *)iph + iph->ihl * 4;
15751 + datalen = length - iph->ihl * 4;
15753 + /* CHECK: Embedded fragment. */
15754 + if (embedded && offset) {
15755 + limpk("Embedded fragment.\n");
15759 + for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
15760 + switch (opt[i]) {
15762 + end_of_options = 1;
15769 + /* CHECK: options after EOO. */
15770 + if (end_of_options) {
15771 + limpk("IP option %u after end\n",
15775 + /* CHECK: options at tail. */
15776 + else if (i+1 >= iph->ihl * 4) {
15777 + limpk("IP option %u at tail\n",
15781 + /* CHECK: zero-length or one-length options. */
15782 + else if (opt[i+1] < 2) {
15783 + limpk("IP option %u %u len\n",
15784 + opt[i], opt[i+1]);
15787 + /* CHECK: oversize options. */
15788 + else if (&opt[i] + opt[i+1] > endhdr) {
15789 + limpk("IP option %u at %u too long\n",
15793 + /* Move to next option */
15798 + /* Fragment checks. */
15800 + /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
15801 + if ((ntohs(iph->frag_off) & IP_MF)
15802 + && (ntohs(iph->tot_len) % 8) != 0) {
15803 + limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
15807 + /* CHECK: Oversize fragment a-la Ping of Death. */
15808 + if (offset * 8 + datalen > 65535) {
15809 + limpk("Oversize fragment to %u.\n", offset * 8);
15813 + /* CHECK: DF set and offset or MF set. */
15814 + if ((ntohs(iph->frag_off) & IP_DF)
15815 + && (offset || (ntohs(iph->frag_off) & IP_MF))) {
15816 + limpk("DF set and offset=%u, MF=%u.\n",
15817 + offset, ntohs(iph->frag_off) & IP_MF);
15821 + /* CHECK: Zero-sized fragments. */
15822 + if ((offset || (ntohs(iph->frag_off) & IP_MF))
15823 + && datalen == 0) {
15824 + limpk("Zero size fragment offset=%u\n", offset);
15828 + /* Note: we can have even middle fragments smaller than this:
15829 + consider a large packet passing through a 600MTU then
15830 + 576MTU link: this gives a fragment of 24 data bytes. But
15831 + everyone packs fragments largest first, hence a fragment
15832 + can't START before 576 - MAX_IP_HEADER_LEN. */
15834 + /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
15835 + down to 128 (576 taken from RFC 791: All hosts must be
15836 + prepared to accept datagrams of up to 576 octets). Use 128
15838 +#define MIN_LIKELY_MTU 128
15839 + /* CHECK: Min size of first frag = 128. */
15840 + if ((ntohs(iph->frag_off) & IP_MF)
15842 + && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
15843 + limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
15848 + /* CHECK: Min offset of frag = 128 - IP hdr len. */
15849 + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
15850 + limpk("Fragment starts at %u < %u\n", offset * 8,
15851 + MIN_LIKELY_MTU - iph->ihl * 4);
15855 + /* CHECK: Protocol specification non-zero. */
15856 + if (iph->protocol == 0) {
15857 + limpk("Zero protocol\n");
15861 + /* CHECK: Do not use what is unused.
15862 + * First bit of fragmentation flags should be unused.
15863 + * May be used by OS fingerprinting tools.
15864 + * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
15866 + if (ntohs(iph->frag_off)>>15) {
15867 + limpk("IP unused bit set\n");
15871 + /* Per-protocol checks. */
15872 + switch (iph->protocol) {
15873 + case IPPROTO_ICMP:
15874 + return check_icmp(protoh, datalen, offset,
15875 + (ntohs(iph->frag_off) & IP_MF),
15878 + case IPPROTO_UDP:
15879 + return check_udp(iph, protoh, datalen, offset,
15880 + (ntohs(iph->frag_off) & IP_MF),
15883 + case IPPROTO_TCP:
15884 + return check_tcp(iph, protoh, datalen, offset,
15885 + (ntohs(iph->frag_off) & IP_MF),
15888 + /* Ignorance is bliss. */
15894 +match(const struct sk_buff *skb,
15895 + const struct net_device *in,
15896 + const struct net_device *out,
15897 + const void *matchinfo,
15900 + u_int16_t datalen,
15903 + return !check_ip(skb->nh.iph, skb->len, 0);
15906 +/* Called when user tries to insert an entry of this type. */
15908 +checkentry(const char *tablename,
15909 + const struct ipt_ip *ip,
15911 + unsigned int matchsize,
15912 + unsigned int hook_mask)
15914 + if (matchsize != IPT_ALIGN(0))
15920 +static struct ipt_match unclean_match
15921 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
15923 +static int __init init(void)
15925 + return ipt_register_match(&unclean_match);
15928 +static void __exit fini(void)
15930 + ipt_unregister_match(&unclean_match);
15933 +module_init(init);
15934 +module_exit(fini);
15935 +MODULE_LICENSE("GPL");
15936 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.7-rc3/net/ipv4/netfilter/iptable_filter.c
15937 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_filter.c 2004-06-07 21:14:05.000000000 +0200
15938 +++ linux-2.6.7-rc3/net/ipv4/netfilter/iptable_filter.c 2004-06-08 10:37:30.000000000 +0200
15941 sizeof(struct ipt_entry),
15942 sizeof(struct ipt_standard),
15943 - 0, { 0, 0 }, { } },
15944 + 0, NULL, 0, { 0, 0 }, { } },
15945 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15946 -NF_ACCEPT - 1 } },
15950 sizeof(struct ipt_entry),
15951 sizeof(struct ipt_standard),
15952 - 0, { 0, 0 }, { } },
15953 + 0, NULL, 0, { 0, 0 }, { } },
15954 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15955 -NF_ACCEPT - 1 } },
15959 sizeof(struct ipt_entry),
15960 sizeof(struct ipt_standard),
15961 - 0, { 0, 0 }, { } },
15962 + 0, NULL, 0, { 0, 0 }, { } },
15963 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15968 sizeof(struct ipt_entry),
15969 sizeof(struct ipt_error),
15970 - 0, { 0, 0 }, { } },
15971 + 0, NULL, 0, { 0, 0 }, { } },
15972 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15975 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.7-rc3/net/ipv4/netfilter/iptable_mangle.c
15976 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_mangle.c 2004-06-07 21:14:58.000000000 +0200
15977 +++ linux-2.6.7-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-06-08 10:37:30.000000000 +0200
15980 sizeof(struct ipt_entry),
15981 sizeof(struct ipt_standard),
15982 - 0, { 0, 0 }, { } },
15983 + 0, NULL, 0, { 0, 0 }, { } },
15984 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15985 -NF_ACCEPT - 1 } },
15989 sizeof(struct ipt_entry),
15990 sizeof(struct ipt_standard),
15991 - 0, { 0, 0 }, { } },
15992 + 0, NULL, 0, { 0, 0 }, { } },
15993 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15994 -NF_ACCEPT - 1 } },
15998 sizeof(struct ipt_entry),
15999 sizeof(struct ipt_standard),
16000 - 0, { 0, 0 }, { } },
16001 + 0, NULL, 0, { 0, 0 }, { } },
16002 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16003 -NF_ACCEPT - 1 } },
16007 sizeof(struct ipt_entry),
16008 sizeof(struct ipt_standard),
16009 - 0, { 0, 0 }, { } },
16010 + 0, NULL, 0, { 0, 0 }, { } },
16011 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16012 -NF_ACCEPT - 1 } },
16014 @@ -106,7 +106,7 @@
16016 sizeof(struct ipt_entry),
16017 sizeof(struct ipt_standard),
16018 - 0, { 0, 0 }, { } },
16019 + 0, NULL, 0, { 0, 0 }, { } },
16020 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16021 -NF_ACCEPT - 1 } },
16023 @@ -115,7 +115,7 @@
16025 sizeof(struct ipt_entry),
16026 sizeof(struct ipt_error),
16027 - 0, { 0, 0 }, { } },
16028 + 0, NULL, 0, { 0, 0 }, { } },
16029 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16032 @@ -173,8 +173,13 @@
16033 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
16034 && ((*pskb)->nh.iph->saddr != saddr
16035 || (*pskb)->nh.iph->daddr != daddr
16036 +#ifdef CONFIG_IP_ROUTE_FWMARK
16037 || (*pskb)->nfmark != nfmark
16038 - || (*pskb)->nh.iph->tos != tos))
16040 +#ifdef CONFIG_IP_ROUTE_TOS
16041 + || (*pskb)->nh.iph->tos != tos
16044 return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
16047 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.7-rc3/net/ipv4/netfilter/iptable_raw.c
16048 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_raw.c 2004-06-07 21:14:59.000000000 +0200
16049 +++ linux-2.6.7-rc3/net/ipv4/netfilter/iptable_raw.c 2004-06-08 10:37:30.000000000 +0200
16052 sizeof(struct ipt_entry),
16053 sizeof(struct ipt_standard),
16054 - 0, { 0, 0 }, { } },
16055 + 0, NULL, 0, { 0, 0 }, { } },
16056 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16057 -NF_ACCEPT - 1 } },
16061 sizeof(struct ipt_entry),
16062 sizeof(struct ipt_standard),
16063 - 0, { 0, 0 }, { } },
16064 + 0, NULL, 0, { 0, 0 }, { } },
16065 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16070 sizeof(struct ipt_entry),
16071 sizeof(struct ipt_error),
16072 - 0, { 0, 0 }, { } },
16073 + 0, NULL, 0, { 0, 0 }, { } },
16074 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16077 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/string.2.6.patch linux-2.6.7-rc3/net/ipv4/netfilter/string.2.6.patch
16078 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/string.2.6.patch 1970-01-01 01:00:00.000000000 +0100
16079 +++ linux-2.6.7-rc3/net/ipv4/netfilter/string.2.6.patch 2004-06-08 10:41:24.000000000 +0200
16081 +--- ipt_string.c.old Mon Mar 29 06:00:23 2004
16082 ++++ ipt_string.c Mon Mar 29 06:01:04 2004
16084 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
16087 ++ * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
16088 ++ * Initial 2.6 port
16089 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
16090 + * Fixed SMP re-entrancy problem using per-cpu data areas
16091 + * for the skip/shift tables.
16095 + #include <linux/smp.h>
16096 ++#include <linux/percpu.h>
16097 + #include <linux/module.h>
16098 + #include <linux/skbuff.h>
16099 + #include <linux/file.h>
16100 +@@ -29,12 +32,13 @@
16101 + MODULE_LICENSE("GPL");
16103 + struct string_per_cpu {
16107 ++ int skip[BM_MAX_HLEN];
16108 ++ int shift[BM_MAX_HLEN];
16109 ++ int len[BM_MAX_HLEN];
16112 +-struct string_per_cpu *bm_string_data=NULL;
16113 ++static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
16116 + /* Boyer Moore Sublinear string search - VERY FAST */
16117 + char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
16118 +@@ -45,14 +49,14 @@
16119 + int *skip, *shift, *len;
16121 + /* use data suitable for this CPU */
16122 +- shift=bm_string_data[smp_processor_id()].shift;
16123 +- skip=bm_string_data[smp_processor_id()].skip;
16124 +- len=bm_string_data[smp_processor_id()].len;
16125 ++ shift=__get_cpu_var(bm_string_data).shift;
16126 ++ skip=__get_cpu_var(bm_string_data).skip;
16127 ++ len=__get_cpu_var(bm_string_data).len;
16129 + /* Setup skip/shift tables */
16130 + M1 = right_end = needle_len-1;
16131 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
16132 +- for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
16133 ++ for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
16135 + for (i = 1; i < needle_len; i++) {
16136 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
16138 + return haystack+(right_end - M1);
16141 +- sk = skip[haystack[right_end - i]];
16142 ++ sk = skip[(int)haystack[right_end - i]];
16144 + right_end = max(right_end - i + sk, right_end + sh);
16146 +@@ -100,15 +104,12 @@
16152 + match(const struct sk_buff *skb,
16153 + const struct net_device *in,
16154 + const struct net_device *out,
16155 + const void *matchinfo,
16157 +- const void *hdr,
16158 +- u_int16_t datalen,
16161 + const struct ipt_string_info *info = matchinfo;
16162 +@@ -158,61 +159,25 @@
16166 +-void string_freeup_data(void)
16170 +- if ( bm_string_data ) {
16171 +- for(c=0; c<smp_num_cpus; c++) {
16172 +- if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
16173 +- if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
16174 +- if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
16176 +- kfree(bm_string_data);
16179 ++static struct ipt_match string_match = {
16180 ++ .name = "string",
16181 ++ .match = &match,
16182 ++ .checkentry = &checkentry,
16183 ++ .me = THIS_MODULE
16186 +-static struct ipt_match string_match
16187 +-= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
16189 + static int __init init(void)
16195 +- tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
16196 +- alen=sizeof(int)*BM_MAX_HLEN;
16198 +- /* allocate array of structures */
16199 +- if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
16203 +- memset(bm_string_data, 0, tlen);
16205 +- /* allocate our skip/shift tables */
16206 +- for(c=0; c<smp_num_cpus; c++) {
16207 +- if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
16208 +- goto alloc_fail;
16209 +- if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
16210 +- goto alloc_fail;
16211 +- if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
16212 +- goto alloc_fail;
16215 + return ipt_register_match(&string_match);
16218 +- string_freeup_data();
16222 + static void __exit fini(void)
16224 + ipt_unregister_match(&string_match);
16225 +- string_freeup_data();
16228 + module_init(init);
16229 + module_exit(fini);
16233 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/raw.c linux-2.6.7-rc3/net/ipv4/raw.c
16234 --- linux-2.6.7-rc3.org/net/ipv4/raw.c 2004-06-07 21:14:25.000000000 +0200
16235 +++ linux-2.6.7-rc3/net/ipv4/raw.c 2004-06-08 10:38:46.000000000 +0200
16236 @@ -249,6 +249,7 @@
16238 return NET_RX_DROP;
16242 skb_push(skb, skb->data - skb->nh.raw);
16244 @@ -307,7 +308,7 @@
16247 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
16251 err = inet->recverr ? net_xmit_errno(err) : 0;
16253 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.7-rc3/net/ipv4/tcp_ipv4.c
16254 --- linux-2.6.7-rc3.org/net/ipv4/tcp_ipv4.c 2004-06-07 21:14:04.000000000 +0200
16255 +++ linux-2.6.7-rc3/net/ipv4/tcp_ipv4.c 2004-06-08 10:39:56.000000000 +0200
16256 @@ -1785,6 +1785,7 @@
16258 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
16259 goto discard_and_relse;
16262 if (sk_filter(sk, skb, 0))
16263 goto discard_and_relse;
16264 @@ -2636,6 +2637,7 @@
16265 EXPORT_SYMBOL(tcp_v4_connect);
16266 EXPORT_SYMBOL(tcp_v4_do_rcv);
16267 EXPORT_SYMBOL(tcp_v4_lookup_listener);
16268 +EXPORT_SYMBOL(tcp_v4_lookup);
16269 EXPORT_SYMBOL(tcp_v4_rebuild_header);
16270 EXPORT_SYMBOL(tcp_v4_remember_stamp);
16271 EXPORT_SYMBOL(tcp_v4_send_check);
16272 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/udp.c linux-2.6.7-rc3/net/ipv4/udp.c
16273 --- linux-2.6.7-rc3.org/net/ipv4/udp.c 2004-06-07 21:13:39.000000000 +0200
16274 +++ linux-2.6.7-rc3/net/ipv4/udp.c 2004-06-08 10:39:56.000000000 +0200
16275 @@ -1045,6 +1045,7 @@
16281 if (up->encap_type) {
16283 @@ -1210,6 +1211,7 @@
16285 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
16289 /* No socket. Drop packet silently, if checksum is wrong */
16290 if (udp_checksum_complete(skb))
16291 @@ -1558,6 +1560,7 @@
16292 EXPORT_SYMBOL(udp_port_rover);
16293 EXPORT_SYMBOL(udp_prot);
16294 EXPORT_SYMBOL(udp_sendmsg);
16295 +EXPORT_SYMBOL(udp_v4_lookup);
16297 #ifdef CONFIG_PROC_FS
16298 EXPORT_SYMBOL(udp_proc_register);
16299 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.7-rc3/net/ipv4/xfrm4_tunnel.c
16300 --- linux-2.6.7-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-06-07 21:13:38.000000000 +0200
16301 +++ linux-2.6.7-rc3/net/ipv4/xfrm4_tunnel.c 2004-06-08 10:38:44.000000000 +0200
16303 err = -EHOSTUNREACH;
16306 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
16307 return NET_XMIT_BYPASS;
16310 @@ -171,6 +172,7 @@
16311 .handler = ipip_rcv,
16312 .err_handler = ipip_err,
16317 static int __init ipip_init(void)
16318 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/ip6_tunnel.c linux-2.6.7-rc3/net/ipv6/ip6_tunnel.c
16319 --- linux-2.6.7-rc3.org/net/ipv6/ip6_tunnel.c 2004-06-07 21:13:37.000000000 +0200
16320 +++ linux-2.6.7-rc3/net/ipv6/ip6_tunnel.c 2004-06-08 10:30:55.000000000 +0200
16321 @@ -715,13 +715,7 @@
16322 ipv6h->nexthdr = proto;
16323 ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
16324 ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
16325 -#ifdef CONFIG_NETFILTER
16326 - nf_conntrack_put(skb->nfct);
16327 - skb->nfct = NULL;
16328 -#ifdef CONFIG_NETFILTER_DEBUG
16329 - skb->nf_debug = 0;
16333 pkt_len = skb->len;
16334 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
16335 skb->dst->dev, dst_output);
16336 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.7-rc3/net/ipv6/netfilter/Kconfig
16337 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/Kconfig 2004-06-07 21:14:58.000000000 +0200
16338 +++ linux-2.6.7-rc3/net/ipv6/netfilter/Kconfig 2004-06-08 10:42:36.000000000 +0200
16339 @@ -230,5 +230,107 @@
16340 <file:Documentation/modules.txt>. If unsure, say `N'.
16343 +config IP6_NF_TARGET_HL
16344 + tristate 'HL target support'
16345 + depends on IP6_NF_MANGLE
16347 + This option adds a `HL' target, which allows you to modify the value of
16348 + IPv6 Hop Limit field.
16350 + If you want to compile it as a module, say M here and read
16351 + <file:Documentation/modules.txt>. If unsure, say `N'.
16353 +config IP6_NF_TARGET_REJECT
16354 + tristate 'REJECT target support'
16355 + depends on IP6_NF_FILTER
16357 + The REJECT target allows a filtering rule to specify that an ICMPv6
16358 + error should be issued in response to an incoming packet, rather
16359 + than silently being dropped.
16361 + If you want to compile it as a module, say M here and read
16362 + Documentation/modules.txt. If unsure, say `N'.
16364 +config IP6_NF_MATCH_FUZZY
16365 + tristate 'Fuzzy match support'
16366 + depends on IP6_NF_FILTER
16368 + This option adds a `fuzzy' match, which allows you to match
16369 + packets according to a fuzzy logic based law.
16371 + If you want to compile it as a module, say M here and read
16372 + Documentation/modules.txt. If unsure, say `N'.
16374 +config IP6_NF_MATCH_NTH
16375 + tristate 'Nth match support'
16376 + depends on IP6_NF_IPTABLES
16378 + This option adds a `Nth' match, which allow you to make
16379 + rules that match every Nth packet. By default there are
16380 + 16 different counters.
16383 + --every Nth Match every Nth packet
16384 + [--counter] num Use counter 0-15 (default:0)
16385 + [--start] num Initialize the counter at the number 'num'
16386 + instead of 0. Must be between 0 and Nth-1
16387 + [--packet] num Match on 'num' packet. Must be between 0
16390 + If --packet is used for a counter than
16391 + there must be Nth number of --packet
16392 + rules, covering all values between 0 and
16393 + Nth-1 inclusively.
16395 + If you want to compile it as a module, say M here and read
16396 + Documentation/modules.txt. If unsure, say `N'.
16398 +config IP6_NF_MATCH_RANDOM
16399 + tristate 'Random match support'
16400 + depends on IP6_NF_IPTABLES
16402 + This option adds a `random' match,
16403 + which allow you to match packets randomly
16404 + following a given probability.
16406 + If you want to compile it as a module, say M here and read
16407 + Documentation/modules.txt. If unsure, say `N'.
16409 +config IP6_NF_TARGET_ROUTE
16410 + tristate ' ROUTE target support'
16411 + depends on IP6_NF_MANGLE
16413 + This option adds a `ROUTE' target, which enables you to setup unusual
16414 + routes. The ROUTE target is also able to change the incoming interface
16417 + The target can be or not a final target. It has to be used inside the
16420 + Not working as a module.
16422 +config IP6_NF_TARGET_TRACE
16423 + tristate 'TRACE target support'
16424 + depends on IP6_NF_RAW
16426 + The TRACE target allows packets to be traced as those
16427 + matches any subsequent rule in any table/rule. The matched
16428 + rule and the packet is logged with the prefix
16430 + TRACE: tablename/chainname/rulenum
16432 + If you want to compile it as a module, say M here and read
16433 + <file:Documentation/modules.txt>. If unsure, say `N'.
16435 +config IP6_NF_MATCH_POLICY
16436 + tristate "IPsec policy match support"
16437 + depends on IP6_NF_IPTABLES && XFRM
16439 + Policy matching allows you to match packets based on the
16440 + IPsec policy that was used during decapsulation/will
16441 + be used during encapsulation.
16443 + To compile it as a module, choose M here. If unsure, say N.
16447 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.7-rc3/net/ipv6/netfilter/Makefile
16448 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/Makefile 2004-06-07 21:14:33.000000000 +0200
16449 +++ linux-2.6.7-rc3/net/ipv6/netfilter/Makefile 2004-06-08 10:42:36.000000000 +0200
16451 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
16452 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
16453 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
16454 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
16455 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
16456 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
16457 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
16458 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
16459 obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
16460 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
16461 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
16462 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
16463 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
16464 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16465 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
16466 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
16467 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
16468 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
16469 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
16470 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
16472 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
16474 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
16475 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
16476 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
16477 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
16478 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
16479 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6_tables.c
16480 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-06-07 21:14:58.000000000 +0200
16481 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6_tables.c 2004-06-08 10:37:30.000000000 +0200
16483 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
16484 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
16486 +static const char *hook6names[] = {
16487 + [NF_IP6_PRE_ROUTING] "PREROUTING",
16488 + [NF_IP6_LOCAL_IN] "INPUT",
16489 + [NF_IP6_FORWARD] "FORWARD",
16490 + [NF_IP6_LOCAL_OUT] "OUTPUT",
16491 + [NF_IP6_POST_ROUTING] "POSTROUTING",
16494 /*#define DEBUG_IP_FIREWALL*/
16495 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
16496 /*#define DEBUG_IP_FIREWALL_USER*/
16497 @@ -406,6 +414,12 @@
16499 t = ip6t_get_target(e);
16500 IP_NF_ASSERT(t->u.kernel.target);
16502 + /* The packet traced and the rule isn't an unconditional return/END. */
16503 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
16504 + nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
16505 + table->name, e->chainname, e->rulenum);
16507 /* Standard target? */
16508 if (!t->u.kernel.target->target) {
16510 @@ -559,6 +573,29 @@
16511 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
16515 +find_error_target(struct ip6t_entry *s,
16516 + struct ip6t_entry *e,
16517 + char **chainname)
16519 + struct ip6t_entry_target *t;
16520 + static struct ip6t_entry *found = NULL;
16525 + t = ip6t_get_target(found);
16526 + if (strcmp(t->u.user.name,
16527 + IP6T_ERROR_TARGET) == 0) {
16528 + *chainname = t->data;
16537 /* All zeroes == unconditional rule. */
16539 unconditional(const struct ip6t_ip6 *ipv6)
16540 @@ -578,6 +615,8 @@
16541 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
16544 + char *chainname = NULL;
16545 + u_int32_t rulenum;
16547 /* No recursion; use packet counter to save back ptrs (reset
16548 to 0 as we leave), and comefrom to save source hook bitmask */
16549 @@ -591,6 +630,8 @@
16551 /* Set initial back pointer. */
16552 e->counters.pcnt = pos;
16554 + chainname = (char *) hook6names[hook];
16557 struct ip6t_standard_target *t
16558 @@ -603,6 +644,8 @@
16561 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
16562 + e->rulenum = rulenum++;
16563 + e->chainname = chainname;
16565 /* Unconditional return/END. */
16566 if (e->target_offset == sizeof(struct ip6t_entry)
16567 @@ -612,6 +655,10 @@
16568 && unconditional(&e->ipv6)) {
16569 unsigned int oldpos, size;
16571 + /* Set unconditional rulenum to zero. */
16573 + e->counters.bcnt = 0;
16575 /* Return: backtrack through the last
16578 @@ -637,6 +684,11 @@
16579 (newinfo->entries + pos);
16580 } while (oldpos == pos + e->next_offset);
16582 + /* Restore chainname, rulenum. */
16583 + chainname = e->chainname;
16584 + rulenum = e->counters.bcnt;
16585 + e->counters.bcnt = 0;
16587 /* Move along one */
16588 size = e->next_offset;
16589 e = (struct ip6t_entry *)
16590 @@ -652,6 +704,17 @@
16591 /* This a jump; chase it. */
16592 duprintf("Jump rule %u -> %u\n",
16594 + e->counters.bcnt = rulenum++;
16596 + e = (struct ip6t_entry *)
16597 + (newinfo->entries + newpos);
16598 + if (IP6T_ENTRY_ITERATE(newinfo->entries,
16600 + find_error_target,
16601 + e, &chainname) == 0) {
16602 + printk("ip6_tables: table screwed up!\n");
16606 /* ... this is a fallthru */
16607 newpos = pos + e->next_offset;
16608 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_HL.c
16609 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
16610 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_HL.c 2004-06-08 10:31:03.000000000 +0200
16613 + * Hop Limit modification target for ip6tables
16614 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
16615 + * Based on HW's TTL module
16617 + * This software is distributed under the terms of GNU GPL
16620 +#include <linux/module.h>
16621 +#include <linux/skbuff.h>
16622 +#include <linux/ip.h>
16624 +#include <linux/netfilter_ipv6/ip6_tables.h>
16625 +#include <linux/netfilter_ipv6/ip6t_HL.h>
16627 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
16628 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
16629 +MODULE_LICENSE("GPL");
16631 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
16632 + const struct net_device *in, const struct net_device *out,
16633 + const void *targinfo, void *userinfo)
16635 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
16636 + const struct ip6t_HL_info *info = targinfo;
16637 + u_int16_t diffs[2];
16640 + switch (info->mode) {
16641 + case IP6T_HL_SET:
16642 + new_hl = info->hop_limit;
16644 + case IP6T_HL_INC:
16645 + new_hl = ip6h->hop_limit + info->hop_limit;
16646 + if (new_hl > 255)
16649 + case IP6T_HL_DEC:
16650 + new_hl = ip6h->hop_limit + info->hop_limit;
16655 + new_hl = ip6h->hop_limit;
16659 + if (new_hl != ip6h->hop_limit) {
16660 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
16661 + ip6h->hop_limit = new_hl;
16662 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
16665 + return IP6T_CONTINUE;
16668 +static int ip6t_hl_checkentry(const char *tablename,
16669 + const struct ip6t_entry *e,
16671 + unsigned int targinfosize,
16672 + unsigned int hook_mask)
16674 + struct ip6t_HL_info *info = targinfo;
16676 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
16677 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
16679 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
16683 + if (strcmp(tablename, "mangle")) {
16684 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
16688 + if (info->mode > IP6T_HL_MAXMODE) {
16689 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
16694 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
16695 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
16702 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
16703 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
16705 +static int __init init(void)
16707 + return ip6t_register_target(&ip6t_HL);
16710 +static void __exit fini(void)
16712 + ip6t_unregister_target(&ip6t_HL);
16715 +module_init(init);
16716 +module_exit(fini);
16717 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_REJECT.c
16718 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
16719 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_REJECT.c 2004-06-08 10:31:20.000000000 +0200
16722 + * IP6 tables REJECT target module
16723 + * Linux INET6 implementation
16725 + * Copyright (C)2003 USAGI/WIDE Project
16728 + * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
16730 + * Based on net/ipv4/netfilter/ipt_REJECT.c
16732 + * This program is free software; you can redistribute it and/or
16733 + * modify it under the terms of the GNU General Public License
16734 + * as published by the Free Software Foundation; either version
16735 + * 2 of the License, or (at your option) any later version.
16738 +#include <linux/config.h>
16739 +#include <linux/module.h>
16740 +#include <linux/skbuff.h>
16741 +#include <linux/icmpv6.h>
16742 +#include <net/ipv6.h>
16743 +#include <net/tcp.h>
16744 +#include <net/icmp.h>
16745 +#include <net/ip6_fib.h>
16746 +#include <net/ip6_route.h>
16747 +#include <net/flow.h>
16748 +#include <linux/netfilter_ipv6/ip6_tables.h>
16749 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
16751 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
16752 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
16753 +MODULE_LICENSE("GPL");
16756 +#define DEBUGP printk
16758 +#define DEBUGP(format, args...)
16762 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
16764 + void (*attach)(struct sk_buff *, struct nf_ct_info *);
16765 + if (nfct && (attach = ip6_ct_attach) != NULL) {
16767 + attach(new_skb, nfct);
16772 +static int maybe_reroute(struct sk_buff *skb)
16774 + if (skb->nfcache & NFC_ALTERED){
16775 + if (ip6_route_me_harder(skb) != 0){
16781 + return dst_output(skb);
16784 +/* Send RST reply */
16785 +static void send_reset(struct sk_buff *oldskb)
16787 + struct sk_buff *nskb;
16788 + struct tcphdr otcph, *tcph;
16789 + unsigned int otcplen, tcphoff, hh_len;
16791 + struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
16792 + struct dst_entry *dst = NULL;
16795 + proto = oip6h->nexthdr;
16798 + if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
16799 + (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
16800 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
16804 + tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
16805 + &proto, oldskb->len - ((u8*)(oip6h+1)
16806 + - oldskb->data));
16808 + if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
16809 + DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
16813 + otcplen = oldskb->len - tcphoff;
16815 + /* IP header checks: fragment, too short. */
16816 + if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
16817 + DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
16822 + if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
16823 + if (net_ratelimit())
16824 + printk("ip6t_REJECT: Can't copy tcp header\n");
16828 + /* No RST for RST. */
16830 + DEBUGP("ip6t_REJECT: RST is set\n");
16834 + /* Check checksum. */
16835 + if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
16836 + skb_checksum(oldskb, tcphoff, otcplen, 0))) {
16837 + DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
16841 + memset(&fl, 0, sizeof(fl));
16842 + fl.proto = IPPROTO_TCP;
16843 + ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
16844 + ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
16845 + fl.fl_ip_sport = otcph.dest;
16846 + fl.fl_ip_dport = otcph.source;
16847 + err = ip6_dst_lookup(NULL, &dst, &fl);
16849 + if (net_ratelimit())
16850 + printk("ip6t_REJECT: can't find dst. err = %d\n", err);
16854 + hh_len = (dst->dev->hard_header_len + 15)&~15;
16855 + nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
16856 + + sizeof(struct tcphdr) + dst->trailer_len,
16860 + if (net_ratelimit())
16861 + printk("ip6t_REJECT: Can't alloc skb\n");
16862 + dst_release(dst);
16869 + skb_reserve(nskb, hh_len + dst->header_len);
16871 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
16872 + skb_put(nskb, sizeof(struct ipv6hdr));
16873 + ip6h->version = 6;
16874 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
16875 + ip6h->nexthdr = IPPROTO_TCP;
16876 + ip6h->payload_len = htons(sizeof(struct tcphdr));
16877 + ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
16878 + ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
16880 + tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
16881 + /* Truncate to length (no data) */
16882 + tcph->doff = sizeof(struct tcphdr)/4;
16883 + tcph->source = otcph.dest;
16884 + tcph->dest = otcph.source;
16888 + tcph->seq = otcph.ack_seq;
16889 + tcph->ack_seq = 0;
16892 + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
16893 + + otcplen - (otcph.doff<<2));
16897 + /* Reset flags */
16898 + ((u_int8_t *)tcph)[13] = 0;
16900 + tcph->ack = needs_ack;
16901 + tcph->window = 0;
16902 + tcph->urg_ptr = 0;
16905 + /* Adjust TCP checksum */
16906 + tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
16907 + &nskb->nh.ipv6h->daddr,
16908 + sizeof(struct tcphdr), IPPROTO_TCP,
16909 + csum_partial((char *)tcph,
16910 + sizeof(struct tcphdr), 0));
16913 + connection_attach(nskb, oldskb->nfct);
16916 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
16919 + dst_release(dst);
16922 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
16924 + struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
16925 + struct icmp6hdr *icmp6h;
16926 + struct dst_entry *dst = NULL;
16927 + struct rt6_info *rt;
16930 + unsigned int len, datalen, hh_len;
16931 + int saddr_type, daddr_type;
16932 + unsigned int ptr, ip6off;
16935 + struct sk_buff *nskb;
16938 + saddr_type = ipv6_addr_type(&hdr->saddr);
16939 + daddr_type = ipv6_addr_type(&hdr->daddr);
16941 + if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
16942 + (!(daddr_type & IPV6_ADDR_UNICAST))) {
16943 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
16947 + ip6off = skb_in->nh.raw - skb_in->data;
16948 + proto = hdr->nexthdr;
16949 + ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
16950 + skb_in->len - ip6off);
16952 + if ((ptr < 0) || (ptr > skb_in->len)) {
16953 + ptr = ip6off + sizeof(struct ipv6hdr);
16954 + proto = hdr->nexthdr;
16955 + } else if (proto == IPPROTO_ICMPV6) {
16958 + if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
16959 + icmp6_type), &type, 1)) {
16960 + DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
16964 + if (!(type & ICMPV6_INFOMSG_MASK)) {
16965 + DEBUGP("ip6t_REJECT: no reply to icmp error\n");
16968 + } else if (proto == IPPROTO_UDP) {
16969 + int plen = skb_in->len - (ptr - ip6off);
16972 + if (plen < sizeof(struct udphdr)) {
16973 + DEBUGP("ip6t_REJECT: too short\n");
16977 + if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
16979 + if (net_ratelimit())
16980 + printk("ip6t_REJECT: can't get copy from skb");
16985 + csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
16987 + skb_checksum(skb_in, ptr, plen, 0))) {
16988 + DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
16993 + memset(&fl, 0, sizeof(fl));
16994 + fl.proto = IPPROTO_ICMPV6;
16995 + ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
16996 + ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
16997 + fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
16998 + fl.fl_icmp_code = code;
17000 + if (ip6_dst_lookup(NULL, &dst, &fl)) {
17004 + rt = (struct rt6_info *)dst;
17007 + if (rt->rt6i_dst.plen < 128)
17008 + tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
17010 + if (!xrlim_allow(dst, tmo)) {
17011 + if (net_ratelimit())
17012 + printk("ip6t_REJECT: rate limitted\n");
17013 + goto dst_release_out;
17016 + len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
17018 + if (len > dst_pmtu(dst))
17019 + len = dst_pmtu(dst);
17020 + if (len > IPV6_MIN_MTU)
17021 + len = IPV6_MIN_MTU;
17023 + datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
17024 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
17026 + nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
17030 + if (net_ratelimit())
17031 + printk("ip6t_REJECT: can't alloc skb\n");
17032 + goto dst_release_out;
17035 + nskb->priority = 0;
17039 + skb_reserve(nskb, hh_len + dst->header_len);
17041 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17042 + skb_put(nskb, sizeof(struct ipv6hdr));
17043 + ip6h->version = 6;
17044 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17045 + ip6h->nexthdr = IPPROTO_ICMPV6;
17046 + ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
17047 + ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
17048 + ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
17050 + icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
17051 + icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
17052 + icmp6h->icmp6_code = code;
17053 + icmp6h->icmp6_cksum = 0;
17055 + data = skb_put(nskb, datalen);
17057 + csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
17058 + csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
17059 + icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
17060 + datalen + sizeof(struct icmp6hdr),
17061 + IPPROTO_ICMPV6, csum);
17064 + connection_attach(nskb, skb_in->nfct);
17066 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17070 + dst_release(dst);
17073 +static unsigned int reject6_target(struct sk_buff **pskb,
17074 + unsigned int hooknum,
17075 + const struct net_device *in,
17076 + const struct net_device *out,
17077 + const void *targinfo,
17080 + const struct ip6t_reject_info *reject = targinfo;
17082 + DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
17083 + /* WARNING: This code causes reentry within ip6tables.
17084 + This means that the ip6tables jump stack is now crap. We
17085 + must return an absolute verdict. --RR */
17086 + switch (reject->with) {
17087 + case IP6T_ICMP6_NO_ROUTE:
17088 + send_unreach(*pskb, ICMPV6_NOROUTE);
17090 + case IP6T_ICMP6_ADM_PROHIBITED:
17091 + send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
17093 + case IP6T_ICMP6_NOT_NEIGHBOUR:
17094 + send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
17096 + case IP6T_ICMP6_ADDR_UNREACH:
17097 + send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
17099 + case IP6T_ICMP6_PORT_UNREACH:
17100 + send_unreach(*pskb, ICMPV6_PORT_UNREACH);
17102 + case IP6T_ICMP6_ECHOREPLY:
17105 + case IP6T_TCP_RESET:
17106 + send_reset(*pskb);
17109 + if (net_ratelimit())
17110 + printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
17117 +static int check(const char *tablename,
17118 + const struct ip6t_entry *e,
17120 + unsigned int targinfosize,
17121 + unsigned int hook_mask)
17123 + const struct ip6t_reject_info *rejinfo = targinfo;
17125 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
17126 + DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
17130 + /* Only allow these for packet filtering. */
17131 + if (strcmp(tablename, "filter") != 0) {
17132 + DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
17136 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
17137 + | (1 << NF_IP6_FORWARD)
17138 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
17139 + DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
17143 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
17144 + printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
17146 + } else if (rejinfo->with == IP6T_TCP_RESET) {
17147 + /* Must specify that it's a TCP packet */
17148 + if (e->ipv6.proto != IPPROTO_TCP
17149 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
17150 + DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
17158 +static struct ip6t_target ip6t_reject_reg = {
17159 + .name = "REJECT",
17160 + .target = reject6_target,
17161 + .checkentry = check,
17162 + .me = THIS_MODULE
17165 +static int __init init(void)
17167 + if (ip6t_register_target(&ip6t_reject_reg))
17172 +static void __exit fini(void)
17174 + ip6t_unregister_target(&ip6t_reject_reg);
17177 +module_init(init);
17178 +module_exit(fini);
17179 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_ROUTE.c
17180 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
17181 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_ROUTE.c 2004-06-08 10:37:08.000000000 +0200
17184 + * This implements the ROUTE v6 target, which enables you to setup unusual
17185 + * routes not supported by the standard kernel routing table.
17187 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
17189 + * v 1.0 2003/08/05
17191 + * This software is distributed under GNU GPL v2, 1991
17194 +#include <linux/module.h>
17195 +#include <linux/skbuff.h>
17196 +#include <linux/ipv6.h>
17197 +#include <linux/netfilter_ipv6/ip6_tables.h>
17198 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17199 +#include <linux/netdevice.h>
17200 +#include <net/ipv6.h>
17201 +#include <net/ndisc.h>
17202 +#include <net/ip6_route.h>
17203 +#include <linux/icmpv6.h>
17206 +#define DEBUGP printk
17208 +#define DEBUGP(format, args...)
17211 +#define NIP6(addr) \
17212 + ntohs((addr).s6_addr16[0]), \
17213 + ntohs((addr).s6_addr16[1]), \
17214 + ntohs((addr).s6_addr16[2]), \
17215 + ntohs((addr).s6_addr16[3]), \
17216 + ntohs((addr).s6_addr16[4]), \
17217 + ntohs((addr).s6_addr16[5]), \
17218 + ntohs((addr).s6_addr16[6]), \
17219 + ntohs((addr).s6_addr16[7])
17221 +/* Route the packet according to the routing keys specified in
17222 + * route_info. Keys are :
17224 + * 0 if no oif preferred,
17225 + * otherwise set to the index of the desired oif
17226 + * - route_info->gw :
17227 + * 0 if no gateway specified,
17228 + * otherwise set to the next host to which the pkt must be routed
17229 + * If success, skb->dev is the output device to which the packet must
17230 + * be sent and skb->dst is not NULL
17232 + * RETURN: 1 if the packet was succesfully routed to the
17233 + * destination desired
17234 + * 0 if the kernel routing table could not route the packet
17235 + * according to the keys specified
17238 +route6(struct sk_buff *skb,
17239 + unsigned int ifindex,
17240 + const struct ip6t_route_target_info *route_info)
17242 + struct rt6_info *rt = NULL;
17243 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17244 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17246 + DEBUGP("ip6t_ROUTE: called with: ");
17247 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
17248 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
17249 + DEBUGP("OUT=%s\n", route_info->oif);
17251 + if (ipv6_addr_any(gw))
17252 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
17254 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
17259 + DEBUGP("ip6t_ROUTE: routing gives: ");
17260 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
17261 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
17262 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
17264 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
17265 + goto wrong_route;
17267 + if (!rt->rt6i_nexthop) {
17268 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
17269 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
17272 + /* Drop old route. */
17273 + dst_release(skb->dst);
17274 + skb->dst = &rt->u.dst;
17275 + skb->dev = rt->rt6i_dev;
17279 + dst_release(&rt->u.dst);
17281 + if (!net_ratelimit())
17284 + printk("ip6t_ROUTE: no explicit route found ");
17286 + printk("via interface %s ", route_info->oif);
17287 + if (!ipv6_addr_any(gw))
17288 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
17294 +/* Stolen from ip6_output_finish
17295 + * PRE : skb->dev is set to the device we are leaving by
17296 + * skb->dst is not NULL
17297 + * POST: the packet is sent with the link layer header pushed
17298 + * the packet is destroyed
17300 +static void ip_direct_send(struct sk_buff *skb)
17302 + struct dst_entry *dst = skb->dst;
17303 + struct hh_cache *hh = dst->hh;
17306 + read_lock_bh(&hh->hh_lock);
17307 + memcpy(skb->data - 16, hh->hh_data, 16);
17308 + read_unlock_bh(&hh->hh_lock);
17309 + skb_push(skb, hh->hh_len);
17310 + hh->hh_output(skb);
17311 + } else if (dst->neighbour)
17312 + dst->neighbour->output(skb);
17314 + if (net_ratelimit())
17315 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
17321 +static unsigned int
17322 +route6_oif(const struct ip6t_route_target_info *route_info,
17323 + struct sk_buff *skb)
17325 + unsigned int ifindex = 0;
17326 + struct net_device *dev_out = NULL;
17328 + /* The user set the interface name to use.
17329 + * Getting the current interface index.
17331 + if ((dev_out = dev_get_by_name(route_info->oif))) {
17332 + ifindex = dev_out->ifindex;
17334 + /* Unknown interface name : packet dropped */
17335 + if (net_ratelimit())
17336 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
17338 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17339 + return IP6T_CONTINUE;
17344 + /* Trying the standard way of routing packets */
17345 + if (route6(skb, ifindex, route_info)) {
17346 + dev_put(dev_out);
17347 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17348 + return IP6T_CONTINUE;
17350 + ip_direct_send(skb);
17351 + return NF_STOLEN;
17357 +static unsigned int
17358 +route6_gw(const struct ip6t_route_target_info *route_info,
17359 + struct sk_buff *skb)
17361 + if (route6(skb, 0, route_info)) {
17362 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17363 + return IP6T_CONTINUE;
17365 + ip_direct_send(skb);
17366 + return NF_STOLEN;
17372 +static unsigned int
17373 +ip6t_route_target(struct sk_buff **pskb,
17374 + unsigned int hooknum,
17375 + const struct net_device *in,
17376 + const struct net_device *out,
17377 + const void *targinfo,
17380 + const struct ip6t_route_target_info *route_info = targinfo;
17381 + struct sk_buff *skb = *pskb;
17382 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17384 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17387 + /* If we are at PREROUTING or INPUT hook
17388 + * the TTL isn't decreased by the IP stack
17390 + if (hooknum == NF_IP6_PRE_ROUTING ||
17391 + hooknum == NF_IP6_LOCAL_IN) {
17393 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17395 + if (ipv6h->hop_limit <= 1) {
17396 + /* Force OUTPUT device used as source address */
17397 + skb->dev = skb->dst->dev;
17399 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
17400 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
17405 + ipv6h->hop_limit--;
17410 + if (route_info->oif[0])
17411 + return route6_oif(route_info, *pskb);
17413 + if (!ipv6_addr_any(gw))
17414 + return route6_gw(route_info, *pskb);
17416 + if (net_ratelimit())
17417 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
17419 + return IP6T_CONTINUE;
17424 +ip6t_route_checkentry(const char *tablename,
17425 + const struct ip6t_entry *e,
17427 + unsigned int targinfosize,
17428 + unsigned int hook_mask)
17430 + if (strcmp(tablename, "mangle") != 0) {
17431 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
17435 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
17436 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
17438 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
17446 +static struct ip6t_target ip6t_route_reg = {
17448 + .target = ip6t_route_target,
17449 + .checkentry = ip6t_route_checkentry,
17450 + .me = THIS_MODULE
17454 +static int __init init(void)
17456 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
17457 + if (ip6t_register_target(&ip6t_route_reg))
17464 +static void __exit fini(void)
17466 + ip6t_unregister_target(&ip6t_route_reg);
17469 +module_init(init);
17470 +module_exit(fini);
17471 +MODULE_LICENSE("GPL");
17472 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_TRACE.c
17473 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
17474 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_TRACE.c 2004-06-08 10:37:30.000000000 +0200
17476 +/* This is a module which is used for setting
17477 + * the NFC_TRACE flag in the nfcache field of an skb.
17479 +#include <linux/module.h>
17480 +#include <linux/skbuff.h>
17482 +#include <linux/netfilter_ipv6/ip6_tables.h>
17484 +MODULE_LICENSE("GPL");
17486 +static unsigned int
17487 +target(struct sk_buff **pskb,
17488 + unsigned int hooknum,
17489 + const struct net_device *in,
17490 + const struct net_device *out,
17491 + const void *targinfo,
17494 + (*pskb)->nfcache |= NFC_TRACE;
17495 + return IP6T_CONTINUE;
17499 +checkentry(const char *tablename,
17500 + const struct ip6t_entry *e,
17502 + unsigned int targinfosize,
17503 + unsigned int hook_mask)
17505 + if (targinfosize != 0) {
17506 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17511 + if (strcmp(tablename, "raw") != 0) {
17512 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17519 +static struct ip6t_target ip6t_trace_reg = {
17521 + .target = target,
17522 + .checkentry = checkentry,
17523 + .me = THIS_MODULE
17526 +static int __init init(void)
17528 + if (ip6t_register_target(&ip6t_trace_reg))
17534 +static void __exit fini(void)
17536 + ip6t_unregister_target(&ip6t_trace_reg);
17539 +module_init(init);
17540 +module_exit(fini);
17541 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_fuzzy.c
17542 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
17543 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_fuzzy.c 2004-06-08 10:31:37.000000000 +0200
17546 + * This module implements a simple TSK FLC
17547 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
17548 + * to limit , in an adaptive and flexible way , the packet rate crossing
17549 + * a given stream . It serves as an initial and very simple (but effective)
17550 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
17551 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
17552 + * into our code in a precise , adaptive and efficient manner.
17553 + * The goal is very similar to that of "limit" match , but using techniques of
17554 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
17555 + * avoiding over and undershoots - and stuff like that .
17558 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
17559 + * 2002-08-17 : Changed to eliminate floating point operations .
17560 + * 2002-08-23 : Coding style changes .
17561 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
17564 +#include <linux/module.h>
17565 +#include <linux/skbuff.h>
17566 +#include <linux/ipv6.h>
17567 +#include <linux/random.h>
17568 +#include <net/tcp.h>
17569 +#include <linux/spinlock.h>
17570 +#include <linux/netfilter_ipv6/ip6_tables.h>
17571 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
17574 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
17575 + Expressed in percentage
17578 +#define PAR_LOW 1/100
17579 +#define PAR_HIGH 1
17581 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
17583 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
17584 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
17585 +MODULE_LICENSE("GPL");
17587 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17589 + if (tx >= maxi) return 100;
17591 + if (tx <= mini) return 0;
17593 + return ((100 * (tx-mini)) / (maxi-mini));
17596 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17598 + if (tx <= mini) return 100;
17600 + if (tx >= maxi) return 0;
17602 + return ((100 * (maxi - tx)) / (maxi - mini));
17607 +ip6t_fuzzy_match(const struct sk_buff *pskb,
17608 + const struct net_device *in,
17609 + const struct net_device *out,
17610 + const void *matchinfo,
17613 + u_int16_t datalen,
17616 + /* From userspace */
17618 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
17620 + u_int8_t random_number;
17621 + unsigned long amount;
17622 + u_int8_t howhigh, howlow;
17625 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
17627 + info->bytes_total += pskb->len;
17628 + info->packets_total++;
17630 + info->present_time = jiffies;
17632 + if (info->present_time >= info->previous_time)
17633 + amount = info->present_time - info->previous_time;
17635 + /* There was a transition : I choose to re-sample
17636 + and keep the old acceptance rate...
17640 + info->previous_time = info->present_time;
17641 + info->bytes_total = info->packets_total = 0;
17644 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
17646 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
17649 + info->previous_time = info->present_time;
17650 + info->bytes_total = info->packets_total = 0;
17652 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
17653 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
17655 + info->acceptance_rate = (u_int8_t) \
17656 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
17658 + /* In fact, the above defuzzification would require a denominator
17659 + * proportional to (howhigh+howlow) but, in this particular case,
17660 + * that expression is constant.
17661 + * An imediate consequence is that it is not necessary to call
17662 + * both mf_high and mf_low - but to keep things understandable,
17668 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
17671 + if (info->acceptance_rate < 100)
17673 + get_random_bytes((void *)(&random_number), 1);
17675 + /* If within the acceptance , it can pass => don't match */
17676 + if (random_number <= (255 * info->acceptance_rate) / 100)
17679 + return 1; /* It can't pass (It matches) */
17682 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
17687 +ip6t_fuzzy_checkentry(const char *tablename,
17688 + const struct ip6t_ip6 *ip,
17690 + unsigned int matchsize,
17691 + unsigned int hook_mask)
17694 + const struct ip6t_fuzzy_info *info = matchinfo;
17696 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
17697 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
17698 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
17702 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
17703 + || (info->minimum_rate >= info->maximum_rate)) {
17704 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
17711 +static struct ip6t_match ip6t_fuzzy_reg = {
17714 + ip6t_fuzzy_match,
17715 + ip6t_fuzzy_checkentry,
17719 +static int __init init(void)
17721 + if (ip6t_register_match(&ip6t_fuzzy_reg))
17727 +static void __exit fini(void)
17729 + ip6t_unregister_match(&ip6t_fuzzy_reg);
17732 +module_init(init);
17733 +module_exit(fini);
17734 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_nth.c
17735 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
17736 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_nth.c 2004-06-08 10:31:42.000000000 +0200
17739 + This is a module which is used for match support for every Nth packet
17740 + This file is distributed under the terms of the GNU General Public
17741 + License (GPL). Copies of the GPL can be obtained from:
17742 + ftp://prep.ai.mit.edu/pub/gnu/GPL
17744 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
17745 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
17746 + * added support for multiple counters
17747 + * added support for matching on individual packets
17748 + in the counter cycle
17749 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
17753 +#include <linux/module.h>
17754 +#include <linux/skbuff.h>
17755 +#include <linux/ip.h>
17756 +#include <net/tcp.h>
17757 +#include <linux/spinlock.h>
17758 +#include <linux/netfilter_ipv6/ip6_tables.h>
17759 +#include <linux/netfilter_ipv6/ip6t_nth.h>
17761 +MODULE_LICENSE("GPL");
17764 + * State information.
17768 + u_int16_t number;
17771 +static struct state states[IP6T_NTH_NUM_COUNTERS];
17774 +ip6t_nth_match(const struct sk_buff *pskb,
17775 + const struct net_device *in,
17776 + const struct net_device *out,
17777 + const void *matchinfo,
17780 + u_int16_t datalen,
17783 + /* Parameters from userspace */
17784 + const struct ip6t_nth_info *info = matchinfo;
17785 + unsigned counter = info->counter;
17786 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
17788 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
17792 + spin_lock(&states[counter].lock);
17794 + /* Are we matching every nth packet?*/
17795 + if (info->packet == 0xFF)
17797 + /* We're matching every nth packet and only every nth packet*/
17798 + /* Do we match or invert match? */
17799 + if (info->not == 0)
17801 + if (states[counter].number == 0)
17803 + ++states[counter].number;
17806 + if (states[counter].number >= info->every)
17807 + states[counter].number = 0; /* reset the counter */
17809 + ++states[counter].number;
17814 + if (states[counter].number == 0)
17816 + ++states[counter].number;
17819 + if (states[counter].number >= info->every)
17820 + states[counter].number = 0;
17822 + ++states[counter].number;
17828 + /* We're using the --packet, so there must be a rule for every value */
17829 + if (states[counter].number == info->packet)
17831 + /* only increment the counter when a match happens */
17832 + if (states[counter].number >= info->every)
17833 + states[counter].number = 0; /* reset the counter */
17835 + ++states[counter].number;
17843 + /* don't match */
17844 + spin_unlock(&states[counter].lock);
17848 + spin_unlock(&states[counter].lock);
17853 +ip6t_nth_checkentry(const char *tablename,
17854 + const struct ip6t_ip6 *e,
17856 + unsigned int matchsize,
17857 + unsigned int hook_mask)
17859 + /* Parameters from userspace */
17860 + const struct ip6t_nth_info *info = matchinfo;
17861 + unsigned counter = info->counter;
17862 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
17864 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
17868 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
17869 + printk("nth: matchsize %u != %u\n", matchsize,
17870 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
17874 + states[counter].number = info->startat;
17879 +static struct ip6t_match ip6t_nth_reg = {
17883 + ip6t_nth_checkentry,
17887 +static int __init init(void)
17889 + unsigned counter;
17890 + memset(&states, 0, sizeof(states));
17891 + if (ip6t_register_match(&ip6t_nth_reg))
17894 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
17896 + spin_lock_init(&(states[counter].lock));
17899 + printk("ip6t_nth match loaded\n");
17903 +static void __exit fini(void)
17905 + ip6t_unregister_match(&ip6t_nth_reg);
17906 + printk("ip6t_nth match unloaded\n");
17909 +module_init(init);
17910 +module_exit(fini);
17911 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_owner.c
17912 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-06-07 21:14:56.000000000 +0200
17913 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_owner.c 2004-06-08 10:40:01.000000000 +0200
17915 MODULE_LICENSE("GPL");
17918 +match_comm(const struct sk_buff *skb, const char *comm)
17920 + struct task_struct *p, *g;
17921 + struct files_struct *files;
17924 + read_lock(&tasklist_lock);
17925 + do_each_thread(g, p) {
17926 + if(strncmp(p->comm, comm, sizeof(p->comm)))
17930 + files = p->files;
17932 + read_lock(&files->file_lock);
17933 + for (i=0; i < files->max_fds; i++) {
17934 + if (fcheck_files(files, i) ==
17935 + skb->sk->sk_socket->file) {
17936 + read_unlock(&files->file_lock);
17938 + read_unlock(&tasklist_lock);
17942 + read_unlock(&files->file_lock);
17945 + } while_each_thread(g, p);
17946 + read_unlock(&tasklist_lock);
17951 match_pid(const struct sk_buff *skb, pid_t pid)
17953 struct task_struct *p;
17954 @@ -125,6 +158,12 @@
17958 + if(info->match & IP6T_OWNER_COMM) {
17959 + if (!match_comm(skb, info->comm) ^
17960 + !!(info->invert & IP6T_OWNER_COMM))
17967 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_policy.c
17968 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
17969 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_policy.c 2004-06-08 10:42:36.000000000 +0200
17971 +/* IP tables module for matching IPsec policy
17973 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
17975 + * This program is free software; you can redistribute it and/or modify
17976 + * it under the terms of the GNU General Public License version 2 as
17977 + * published by the Free Software Foundation.
17980 +#include <linux/kernel.h>
17981 +#include <linux/config.h>
17982 +#include <linux/module.h>
17983 +#include <linux/skbuff.h>
17984 +#include <linux/init.h>
17985 +#include <net/xfrm.h>
17987 +#include <linux/netfilter_ipv6.h>
17988 +#include <linux/netfilter_ipv6/ip6t_policy.h>
17989 +#include <linux/netfilter_ipv6/ip6_tables.h>
17991 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
17992 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
17993 +MODULE_LICENSE("GPL");
17996 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
17997 + struct in6_addr mask,
17998 + struct in6_addr addr2)
18002 + for (i = 0; i < 16; i++) {
18003 + if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
18004 + (addr2.s6_addr[i] & mask.s6_addr[i]))
18012 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
18014 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
18016 + struct in6_addr xfrm_saddr, xfrm_daddr;
18018 + if ((e->match.saddr
18019 + && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
18020 + ^ e->invert.saddr ) ||
18022 + && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
18023 + ^ e->invert.daddr ) ||
18024 + MISMATCH(proto, x->id.proto) ||
18025 + MISMATCH(mode, x->props.mode) ||
18026 + MISMATCH(spi, x->id.spi) ||
18027 + MISMATCH(reqid, x->props.reqid))
18033 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18035 + const struct ip6t_policy_elem *e;
18036 + struct sec_path *sp = skb->sp;
18037 + int strict = info->flags & POLICY_MATCH_STRICT;
18042 + if (strict && info->len != sp->len)
18045 + for (i = sp->len - 1; i >= 0; i--) {
18046 + pos = strict ? i - sp->len + 1 : 0;
18047 + if (pos >= info->len)
18049 + e = &info->pol[pos];
18051 + if (match_xfrm_state(sp->x[i].xvec, e)) {
18054 + } else if (strict)
18058 + return strict ? 1 : 0;
18062 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18064 + const struct ip6t_policy_elem *e;
18065 + struct dst_entry *dst = skb->dst;
18066 + int strict = info->flags & POLICY_MATCH_STRICT;
18069 + if (dst->xfrm == NULL)
18072 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
18073 + pos = strict ? i : 0;
18074 + if (pos >= info->len)
18076 + e = &info->pol[pos];
18078 + if (match_xfrm_state(dst->xfrm, e)) {
18081 + } else if (strict)
18085 + return strict ? 1 : 0;
18088 +static int match(const struct sk_buff *skb,
18089 + const struct net_device *in,
18090 + const struct net_device *out,
18091 + const void *matchinfo,
18094 + u_int16_t datalen,
18097 + const struct ip6t_policy_info *info = matchinfo;
18100 + if (info->flags & POLICY_MATCH_IN)
18101 + ret = match_policy_in(skb, info);
18103 + ret = match_policy_out(skb, info);
18106 + if (info->flags & POLICY_MATCH_NONE)
18110 + } else if (info->flags & POLICY_MATCH_NONE)
18116 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
18117 + void *matchinfo, unsigned int matchsize,
18118 + unsigned int hook_mask)
18120 + struct ip6t_policy_info *info = matchinfo;
18122 + if (matchsize != IP6T_ALIGN(sizeof(*info))) {
18123 + printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
18124 + matchsize, IP6T_ALIGN(sizeof(*info)));
18127 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
18128 + printk(KERN_ERR "ip6t_policy: neither incoming nor "
18129 + "outgoing policy selected\n");
18132 + if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
18133 + && info->flags & POLICY_MATCH_OUT) {
18134 + printk(KERN_ERR "ip6t_policy: output policy not valid in "
18135 + "PRE_ROUTING and INPUT\n");
18138 + if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
18139 + && info->flags & POLICY_MATCH_IN) {
18140 + printk(KERN_ERR "ip6t_policy: input policy not valid in "
18141 + "POST_ROUTING and OUTPUT\n");
18144 + if (info->len > POLICY_MAX_ELEM) {
18145 + printk(KERN_ERR "ip6t_policy: too many policy elements\n");
18152 +static struct ip6t_match policy_match =
18154 + .name = "policy",
18156 + .checkentry = checkentry,
18157 + .me = THIS_MODULE,
18160 +static int __init init(void)
18162 + return ip6t_register_match(&policy_match);
18165 +static void __exit fini(void)
18167 + ip6t_unregister_match(&policy_match);
18170 +module_init(init);
18171 +module_exit(fini);
18172 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_random.c
18173 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
18174 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_random.c 2004-06-08 10:31:56.000000000 +0200
18177 + This is a module which is used for a "random" match support.
18178 + This file is distributed under the terms of the GNU General Public
18179 + License (GPL). Copies of the GPL can be obtained from:
18180 + ftp://prep.ai.mit.edu/pub/gnu/GPL
18182 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18183 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18186 +#include <linux/module.h>
18187 +#include <linux/skbuff.h>
18188 +#include <linux/ip.h>
18189 +#include <linux/random.h>
18190 +#include <net/tcp.h>
18191 +#include <linux/spinlock.h>
18192 +#include <linux/netfilter_ipv6/ip6_tables.h>
18193 +#include <linux/netfilter_ipv6/ip6t_random.h>
18195 +MODULE_LICENSE("GPL");
18198 +ip6t_rand_match(const struct sk_buff *pskb,
18199 + const struct net_device *in,
18200 + const struct net_device *out,
18201 + const void *matchinfo,
18204 + u_int16_t datalen,
18207 + /* Parameters from userspace */
18208 + const struct ip6t_rand_info *info = matchinfo;
18209 + u_int8_t random_number;
18211 + /* get 1 random number from the kernel random number generation routine */
18212 + get_random_bytes((void *)(&random_number), 1);
18214 + /* Do we match ? */
18215 + if (random_number <= info->average)
18222 +ip6t_rand_checkentry(const char *tablename,
18223 + const struct ip6t_ip6 *e,
18225 + unsigned int matchsize,
18226 + unsigned int hook_mask)
18228 + /* Parameters from userspace */
18229 + const struct ip6t_rand_info *info = matchinfo;
18231 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
18232 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
18233 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
18237 + /* must be 1 <= average % <= 99 */
18238 + /* 1 x 2.55 = 2 */
18239 + /* 99 x 2.55 = 252 */
18240 + if ((info->average < 2) || (info->average > 252)) {
18241 + printk("ip6t_random: invalid average %u\n", info->average);
18248 +static struct ip6t_match ip6t_rand_reg = {
18252 + ip6t_rand_checkentry,
18256 +static int __init init(void)
18258 + if (ip6t_register_match(&ip6t_rand_reg))
18261 + printk("ip6t_random match loaded\n");
18265 +static void __exit fini(void)
18267 + ip6t_unregister_match(&ip6t_rand_reg);
18268 + printk("ip6t_random match unloaded\n");
18271 +module_init(init);
18272 +module_exit(fini);
18273 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_filter.c
18274 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_filter.c 2004-06-07 21:13:37.000000000 +0200
18275 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_filter.c 2004-06-08 10:37:30.000000000 +0200
18278 sizeof(struct ip6t_entry),
18279 sizeof(struct ip6t_standard),
18280 - 0, { 0, 0 }, { } },
18281 + 0, NULL, 0, { 0, 0 }, { } },
18282 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18283 -NF_ACCEPT - 1 } },
18287 sizeof(struct ip6t_entry),
18288 sizeof(struct ip6t_standard),
18289 - 0, { 0, 0 }, { } },
18290 + 0, NULL, 0, { 0, 0 }, { } },
18291 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18292 -NF_ACCEPT - 1 } },
18296 sizeof(struct ip6t_entry),
18297 sizeof(struct ip6t_standard),
18298 - 0, { 0, 0 }, { } },
18299 + 0, NULL, 0, { 0, 0 }, { } },
18300 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18305 sizeof(struct ip6t_entry),
18306 sizeof(struct ip6t_error),
18307 - 0, { 0, 0 }, { } },
18308 + 0, NULL, 0, { 0, 0 }, { } },
18309 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18312 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_mangle.c
18313 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_mangle.c 2004-06-07 21:14:05.000000000 +0200
18314 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_mangle.c 2004-06-08 10:37:30.000000000 +0200
18317 sizeof(struct ip6t_entry),
18318 sizeof(struct ip6t_standard),
18319 - 0, { 0, 0 }, { } },
18320 + 0, NULL, 0, { 0, 0 }, { } },
18321 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18322 -NF_ACCEPT - 1 } },
18326 sizeof(struct ip6t_entry),
18327 sizeof(struct ip6t_standard),
18328 - 0, { 0, 0 }, { } },
18329 + 0, NULL, 0, { 0, 0 }, { } },
18330 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18331 -NF_ACCEPT - 1 } },
18335 sizeof(struct ip6t_entry),
18336 sizeof(struct ip6t_standard),
18337 - 0, { 0, 0 }, { } },
18338 + 0, NULL, 0, { 0, 0 }, { } },
18339 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18340 -NF_ACCEPT - 1 } },
18344 sizeof(struct ip6t_entry),
18345 sizeof(struct ip6t_standard),
18346 - 0, { 0, 0 }, { } },
18347 + 0, NULL, 0, { 0, 0 }, { } },
18348 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18349 -NF_ACCEPT - 1 } },
18351 @@ -105,7 +105,7 @@
18353 sizeof(struct ip6t_entry),
18354 sizeof(struct ip6t_standard),
18355 - 0, { 0, 0 }, { } },
18356 + 0, NULL, 0, { 0, 0 }, { } },
18357 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18360 @@ -114,7 +114,7 @@
18362 sizeof(struct ip6t_entry),
18363 sizeof(struct ip6t_error),
18364 - 0, { 0, 0 }, { } },
18365 + 0, NULL, 0, { 0, 0 }, { } },
18366 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18369 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_raw.c
18370 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_raw.c 2004-06-07 21:14:43.000000000 +0200
18371 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_raw.c 2004-06-08 10:37:30.000000000 +0200
18374 sizeof(struct ip6t_entry),
18375 sizeof(struct ip6t_standard),
18376 - 0, { 0, 0 }, { } },
18377 + 0, NULL, 0, { 0, 0 }, { } },
18378 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18379 -NF_ACCEPT - 1 } },
18383 sizeof(struct ip6t_entry),
18384 sizeof(struct ip6t_standard),
18385 - 0, { 0, 0 }, { } },
18386 + 0, NULL, 0, { 0, 0 }, { } },
18387 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18388 -NF_ACCEPT - 1 } },
18392 sizeof(struct ip6t_entry),
18393 sizeof(struct ip6t_error),
18394 - 0, { 0, 0 }, { } },
18395 + 0, NULL, 0, { 0, 0 }, { } },
18396 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18399 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/sit.c linux-2.6.7-rc3/net/ipv6/sit.c
18400 --- linux-2.6.7-rc3.org/net/ipv6/sit.c 2004-06-07 21:14:59.000000000 +0200
18401 +++ linux-2.6.7-rc3/net/ipv6/sit.c 2004-06-08 10:30:55.000000000 +0200
18402 @@ -388,13 +388,7 @@
18403 skb->dev = tunnel->dev;
18404 dst_release(skb->dst);
18406 -#ifdef CONFIG_NETFILTER
18407 - nf_conntrack_put(skb->nfct);
18408 - skb->nfct = NULL;
18409 -#ifdef CONFIG_NETFILTER_DEBUG
18410 - skb->nf_debug = 0;
18414 ipip6_ecn_decapsulate(iph, skb);
18416 read_unlock(&ipip6_lock);
18417 @@ -580,13 +574,7 @@
18418 if ((iph->ttl = tiph->ttl) == 0)
18419 iph->ttl = iph6->hop_limit;
18421 -#ifdef CONFIG_NETFILTER
18422 - nf_conntrack_put(skb->nfct);
18423 - skb->nfct = NULL;
18424 -#ifdef CONFIG_NETFILTER_DEBUG
18425 - skb->nf_debug = 0;
18431 tunnel->recursion--;
18432 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/xfrm/xfrm_input.c linux-2.6.7-rc3/net/xfrm/xfrm_input.c
18433 --- linux-2.6.7-rc3.org/net/xfrm/xfrm_input.c 2004-06-07 21:13:35.000000000 +0200
18434 +++ linux-2.6.7-rc3/net/xfrm/xfrm_input.c 2004-06-08 10:38:44.000000000 +0200
18439 +#ifdef CONFIG_NETFILTER
18440 + sp->decap_done = 0;
18445 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.7-rc3/net/xfrm/xfrm_policy.c
18446 --- linux-2.6.7-rc3.org/net/xfrm/xfrm_policy.c 2004-06-07 21:14:24.000000000 +0200
18447 +++ linux-2.6.7-rc3/net/xfrm/xfrm_policy.c 2004-06-08 10:38:46.000000000 +0200
18449 #include <linux/workqueue.h>
18450 #include <linux/notifier.h>
18451 #include <linux/netdevice.h>
18452 +#include <linux/netfilter.h>
18453 #include <net/xfrm.h>
18454 #include <net/ip.h>
18456 @@ -911,6 +912,7 @@
18458 if (_decode_session(skb, &fl, family) < 0)
18460 + nf_nat_decode_session(skb, &fl, family);
18462 /* First, check used SA against their selectors. */