1 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter.h linux-2.6.7/include/linux/netfilter.h
2 --- linux-2.6.7.org/include/linux/netfilter.h 2004-06-25 10:47:45.000000000 +0200
3 +++ linux-2.6.7/include/linux/netfilter.h 2004-06-25 12:21:38.694509280 +0200
5 /* This is gross, but inline doesn't cut it for avoiding the function
6 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
7 #ifdef CONFIG_NETFILTER_DEBUG
8 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
9 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
10 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
13 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
14 #define NF_HOOK_THRESH nf_hook_slow
16 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
17 -(list_empty(&nf_hooks[(pf)][(hook)]) \
18 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
19 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
21 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
25 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
27 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
28 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
30 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
31 struct net_device *indev, struct net_device *outdev,
34 #else /* !CONFIG_NETFILTER */
35 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
36 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
37 #endif /*CONFIG_NETFILTER*/
40 +#ifdef CONFIG_IP_NF_NAT_NEEDED
42 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
45 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
47 + if (family == AF_INET)
48 + nf_nat_decode_session4(skb, fl);
50 +#else /* CONFIG_IP_NF_NAT_NEEDED */
51 +#define nf_nat_decode_session(skb,fl,family)
52 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
53 +#endif /* CONFIG_XFRM */
56 #endif /*__LINUX_NETFILTER_H*/
57 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_helpers.h linux-2.6.7/include/linux/netfilter_helpers.h
58 --- linux-2.6.7.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
59 +++ linux-2.6.7/include/linux/netfilter_helpers.h 2004-06-25 12:24:50.026422408 +0200
62 + * Helpers for netfiler modules. This file provides implementations for basic
63 + * functions such as strncasecmp(), etc.
65 + * gcc will warn for defined but unused functions, so we only include the
66 + * functions requested. The following macros are used:
67 + * NF_NEED_STRNCASECMP nf_strncasecmp()
68 + * NF_NEED_STRTOU16 nf_strtou16()
69 + * NF_NEED_STRTOU32 nf_strtou32()
71 +#ifndef _NETFILTER_HELPERS_H
72 +#define _NETFILTER_HELPERS_H
74 +/* Only include these functions for kernel code. */
77 +#include <linux/ctype.h>
78 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
81 + * The standard strncasecmp()
83 +#ifdef NF_NEED_STRNCASECMP
85 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
87 + if (s1 == NULL || s2 == NULL)
89 + if (s1 == NULL && s2 == NULL)
93 + return (s1 == NULL) ? -1 : 1;
95 + while (len > 0 && tolower(*s1) == tolower(*s2))
101 + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
103 +#endif /* NF_NEED_STRNCASECMP */
106 + * Parse a string containing a 16-bit unsigned integer.
107 + * Returns the number of chars used, or zero if no number is found.
109 +#ifdef NF_NEED_STRTOU16
111 +nf_strtou16(const char* pbuf, u_int16_t* pval)
116 + while (isdigit(pbuf[n]))
118 + *pval = (*pval * 10) + (pbuf[n] - '0');
124 +#endif /* NF_NEED_STRTOU16 */
127 + * Parse a string containing a 32-bit unsigned integer.
128 + * Returns the number of chars used, or zero if no number is found.
130 +#ifdef NF_NEED_STRTOU32
132 +nf_strtou32(const char* pbuf, u_int32_t* pval)
137 + while (pbuf[n] >= '0' && pbuf[n] <= '9')
139 + *pval = (*pval * 10) + (pbuf[n] - '0');
145 +#endif /* NF_NEED_STRTOU32 */
148 + * Given a buffer and length, advance to the next line and mark the current
151 +#ifdef NF_NEED_NEXTLINE
153 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
163 + while (p[off] != '\n')
174 + /* if we saw a crlf, physlen needs adjusted */
175 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
180 + /* advance past the newline */
184 + *plinelen = physlen;
189 +#endif /* NF_NEED_NEXTLINE */
191 +#endif /* __KERNEL__ */
193 +#endif /* _NETFILTER_HELPERS_H */
194 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h
195 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-25 10:47:45.000000000 +0200
196 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-25 12:28:43.675902288 +0200
199 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
200 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
201 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
203 /* per conntrack: protocol private data */
204 union ip_conntrack_proto {
205 /* insert conntrack proto private data here */
206 + struct ip_ct_sctp sctp;
207 struct ip_ct_tcp tcp;
208 struct ip_ct_icmp icmp;
213 /* Add protocol helper include file here */
214 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
215 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
216 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
217 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
218 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
219 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
220 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
221 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
223 /* per expectation: application helper private data */
224 union ip_conntrack_expect_help {
225 /* insert conntrack helper private data (expect) here */
226 + struct ip_ct_talk_expect exp_talk_info;
227 + struct ip_ct_rtsp_expect exp_rtsp_info;
228 + struct ip_ct_rsh_expect exp_rsh_info;
229 + struct ip_ct_mms_expect exp_mms_info;
230 + struct ip_ct_h225_expect exp_h225_info;
231 struct ip_ct_amanda_expect exp_amanda_info;
232 struct ip_ct_ftp_expect exp_ftp_info;
233 struct ip_ct_irc_expect exp_irc_info;
235 /* per conntrack: application helper private data */
236 union ip_conntrack_help {
237 /* insert conntrack helper private data (master) here */
238 + struct ip_ct_talk_master ct_talk_info;
239 + struct ip_ct_rtsp_master ct_rtsp_info;
240 + struct ip_ct_rsh_master ct_rsh_info;
241 + struct ip_ct_mms_master ct_mms_info;
242 + struct ip_ct_h225_master ct_h225_info;
243 struct ip_ct_ftp_master ct_ftp_info;
244 struct ip_ct_irc_master ct_irc_info;
248 #endif /* CONFIG_IP_NF_NAT_NEEDED */
250 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
251 + unsigned long mark;
256 /* get master conntrack via master expectation */
257 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h
258 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-16 07:20:26.000000000 +0200
259 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-25 12:21:02.302041776 +0200
261 extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
262 extern struct list_head protocol_list;
264 -/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
265 -extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
266 - enum ip_conntrack_info *ctinfo,
267 - unsigned int hooknum);
268 -extern int get_tuple(const struct iphdr *iph,
269 - const struct sk_buff *skb,
270 - unsigned int dataoff,
271 - struct ip_conntrack_tuple *tuple,
272 - const struct ip_conntrack_protocol *protocol);
274 +ip_ct_get_tuple(const struct iphdr *iph,
275 + const struct sk_buff *skb,
276 + unsigned int dataoff,
277 + struct ip_conntrack_tuple *tuple,
278 + const struct ip_conntrack_protocol *protocol);
281 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
282 + const struct ip_conntrack_tuple *orig,
283 + const struct ip_conntrack_protocol *protocol);
285 /* Find a connection corresponding to a tuple. */
286 struct ip_conntrack_tuple_hash *
287 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_h323.h
288 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
289 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-06-25 12:21:34.914083992 +0200
291 +#ifndef _IP_CONNTRACK_H323_H
292 +#define _IP_CONNTRACK_H323_H
293 +/* H.323 connection tracking. */
296 +/* Protects H.323 related data */
297 +#include <linux/netfilter_ipv4/lockhelp.h>
298 +DECLARE_LOCK_EXTERN(ip_h323_lock);
301 +/* Default H.225 port */
302 +#define H225_PORT 1720
304 +/* This structure is per expected connection */
305 +struct ip_ct_h225_expect {
306 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
307 + enum ip_conntrack_dir dir; /* Direction of the original connection */
308 + unsigned int offset; /* offset of the address in the payload */
311 +/* This structure exists only once per master */
312 +struct ip_ct_h225_master {
313 + int is_h225; /* H.225 or H.245 connection */
314 +#ifdef CONFIG_IP_NF_NAT_NEEDED
315 + enum ip_conntrack_dir dir; /* Direction of the original connection */
316 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
317 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
321 +#endif /* _IP_CONNTRACK_H323_H */
322 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_mms.h
323 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
324 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-06-25 12:23:10.833502024 +0200
326 +#ifndef _IP_CONNTRACK_MMS_H
327 +#define _IP_CONNTRACK_MMS_H
331 +#include <linux/netfilter_ipv4/lockhelp.h>
333 +DECLARE_LOCK_EXTERN(ip_mms_lock);
335 +#define MMS_PORT 1755
336 +#define MMS_SRV_MSG_ID 196610
338 +#define MMS_SRV_MSG_OFFSET 36
339 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
340 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
341 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
342 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
345 +/* This structure is per expected connection */
346 +struct ip_ct_mms_expect {
352 +/* This structure exists only once per master */
353 +struct ip_ct_mms_master {
356 +#endif /* _IP_CONNTRACK_MMS_H */
357 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
358 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-06-16 07:20:04.000000000 +0200
359 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-06-25 12:21:02.304041472 +0200
361 int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
362 const struct sk_buff *skb);
364 + int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
365 + unsigned int hooknum);
367 /* Module (if any) which this is connected to. */
371 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
372 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
373 extern int ip_conntrack_protocol_tcp_init(void);
375 +/* Log invalid packets */
376 +extern unsigned int ip_ct_log_invalid;
378 +#ifdef DEBUG_INVALID_PACKETS
379 +#define LOG_INVALID(proto) \
380 + (ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
382 +#define LOG_INVALID(proto) \
383 + ((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
384 + && net_ratelimit())
387 #endif /*_IP_CONNTRACK_PROTOCOL_H*/
388 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
389 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
390 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-06-25 12:24:42.547559368 +0200
392 +#ifndef _IP_CT_QUAKE3
393 +#define _IP_CT_QUAKE3
395 +/* Don't confuse with 27960, often used as the Server Port */
396 +#define QUAKE3_MASTER_PORT 27950
398 +struct quake3_search {
399 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
400 + const char *pattern;
404 +/* This structure is per expected connection */
405 +struct ip_ct_quake3_expect {
408 +/* This structure exists only once per master */
409 +struct ip_ct_quake3_master {
412 +#endif /* _IP_CT_QUAKE3 */
413 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
414 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
415 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-06-25 12:24:48.839602832 +0200
417 +/* RSH extension for IP connection tracking, Version 1.0
418 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
419 + * based on HW's ip_conntrack_irc.c
421 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
423 + * This program is free software; you can redistribute it and/or
424 + * modify it under the terms of the GNU General Public License
425 + * as published by the Free Software Foundation; either version
426 + * 2 of the License, or (at your option) any later version.
428 +#ifndef _IP_CONNTRACK_RSH_H
429 +#define _IP_CONNTRACK_RSH_H
432 +#include <linux/netfilter_ipv4/lockhelp.h>
434 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
438 +#define RSH_PORT 514
440 +/* This structure is per expected connection */
441 +struct ip_ct_rsh_expect
446 +/* This structure exists only once per master */
447 +struct ip_ct_rsh_master {
450 +#endif /* _IP_CONNTRACK_RSH_H */
452 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
453 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
454 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-06-25 12:24:50.028422104 +0200
457 + * RTSP extension for IP connection tracking.
458 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
459 + * based on ip_conntrack_irc.h
461 + * This program is free software; you can redistribute it and/or
462 + * modify it under the terms of the GNU General Public License
463 + * as published by the Free Software Foundation; either version
464 + * 2 of the License, or (at your option) any later version.
466 +#ifndef _IP_CONNTRACK_RTSP_H
467 +#define _IP_CONNTRACK_RTSP_H
469 +/* #define IP_NF_RTSP_DEBUG */
470 +#define IP_NF_RTSP_VERSION "0.01"
472 +/* port block types */
474 + pb_single, /* client_port=x */
475 + pb_range, /* client_port=x-y */
476 + pb_discon /* client_port=x/y (rtspbis) */
479 +/* We record seq number and length of rtsp headers here, all in host order. */
482 + * This structure is per expected connection. It is a member of struct
483 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
484 + * there and we are expected to only store the length of the data which
485 + * needs replaced. If a packet contains multiple RTSP messages, we create
486 + * one expected connection per message.
488 + * We use these variables to mark the entire header block. This may seem
489 + * like overkill, but the nature of RTSP requires it. A header may appear
490 + * multiple times in a message. We must treat two Transport headers the
491 + * same as one Transport header with two entries.
493 +struct ip_ct_rtsp_expect
495 + u_int32_t len; /* length of header block */
496 + portblock_t pbtype; /* Type of port block that was requested */
497 + u_int16_t loport; /* Port that was requested, low or first */
498 + u_int16_t hiport; /* Port that was requested, high or second */
500 + uint method; /* RTSP method */
501 + uint cseq; /* CSeq from request */
505 +/* This structure exists only once per master */
506 +struct ip_ct_rtsp_master
514 +#include <linux/netfilter_ipv4/lockhelp.h>
516 +#define RTSP_PORT 554
518 +/* Protects rtsp part of conntracks */
519 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
521 +#endif /* __KERNEL__ */
523 +#endif /* _IP_CONNTRACK_RTSP_H */
524 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
525 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
526 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-06-25 12:24:51.922134216 +0200
528 +#ifndef _IP_CONNTRACK_SCTP_H
529 +#define _IP_CONNTRACK_SCTP_H
530 +/* SCTP tracking. */
532 +enum sctp_conntrack {
533 + SCTP_CONNTRACK_NONE,
534 + SCTP_CONNTRACK_CLOSED,
535 + SCTP_CONNTRACK_COOKIE_WAIT,
536 + SCTP_CONNTRACK_COOKIE_ECHOED,
537 + SCTP_CONNTRACK_ESTABLISHED,
538 + SCTP_CONNTRACK_SHUTDOWN_SENT,
539 + SCTP_CONNTRACK_SHUTDOWN_RECD,
540 + SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
546 + enum sctp_conntrack state;
548 + u_int32_t vtag[IP_CT_DIR_MAX];
549 + u_int32_t ttag[IP_CT_DIR_MAX];
552 +#endif /* _IP_CONNTRACK_SCTP_H */
553 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_talk.h
554 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
555 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-06-25 12:28:43.647906544 +0200
557 +#ifndef _IP_CONNTRACK_TALK_H
558 +#define _IP_CONNTRACK_TALK_H
559 +/* TALK tracking. */
562 +#include <linux/in.h>
563 +#include <linux/netfilter_ipv4/lockhelp.h>
565 +/* Protects talk part of conntracks */
566 +DECLARE_LOCK_EXTERN(ip_talk_lock);
570 +#define TALK_PORT 517
571 +#define NTALK_PORT 518
573 +/* talk structures and constants from <protocols/talkd.h> */
576 + * 4.3BSD struct sockaddr
579 + u_int16_t ta_family;
582 + u_int32_t ta_junk1;
583 + u_int32_t ta_junk2;
586 +#define TALK_OLD_NSIZE 9
587 +#define TALK_NSIZE 12
588 +#define TALK_TTY_NSIZE 16
591 + * Client->server request message formats.
594 + u_char type; /* request type, see below */
595 + char l_name[TALK_OLD_NSIZE];/* caller's name */
596 + char r_name[TALK_OLD_NSIZE];/* callee's name */
598 + u_int32_t id_num; /* message id */
599 + int32_t pid; /* caller's process id */
600 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
601 + struct talk_addr addr; /* old (4.3) style */
602 + struct talk_addr ctl_addr; /* old (4.3) style */
606 + u_char vers; /* protocol version */
607 + u_char type; /* request type, see below */
608 + u_char answer; /* not used */
610 + u_int32_t id_num; /* message id */
611 + struct talk_addr addr; /* old (4.3) style */
612 + struct talk_addr ctl_addr; /* old (4.3) style */
613 + int32_t pid; /* caller's process id */
614 + char l_name[TALK_NSIZE];/* caller's name */
615 + char r_name[TALK_NSIZE];/* callee's name */
616 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
620 + u_char vers; /* talk protocol version */
621 + u_char type; /* request type */
622 + u_char answer; /* */
623 + u_char extended; /* !0 if additional parts */
624 + u_int32_t id_num; /* message id number (dels) */
625 + struct talk_addr addr; /* target address */
626 + struct talk_addr ctl_addr; /* reply to address */
627 + int32_t pid; /* caller's process id */
628 + char l_name[TALK_NSIZE]; /* caller's name */
629 + char r_name[TALK_NSIZE]; /* callee's name */
630 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
634 + * Server->client response message formats.
636 +struct talk_response {
637 + u_char type; /* type of request message, see below */
638 + u_char answer; /* response to request message, see below */
640 + u_int32_t id_num; /* message id */
641 + struct talk_addr addr; /* address for establishing conversation */
644 +struct ntalk_response {
645 + u_char vers; /* protocol version */
646 + u_char type; /* type of request message, see below */
647 + u_char answer; /* response to request message, see below */
649 + u_int32_t id_num; /* message id */
650 + struct talk_addr addr; /* address for establishing conversation */
653 +struct ntalk2_response {
654 + u_char vers; /* protocol version */
655 + u_char type; /* type of request message */
656 + u_char answer; /* response to request */
657 + u_char rvers; /* Version of answering vers*/
658 + u_int32_t id_num; /* message id number */
659 + struct talk_addr addr; /* address for connection */
660 + /* This is at the end to compatiblize this with NTALK version. */
661 + char r_name[TALK_NSIZE]; /* callee's name */
664 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
665 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
666 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
668 +#define TALK_VERSION 0 /* protocol versions */
669 +#define NTALK_VERSION 1
670 +#define NTALK2_VERSION 2
672 +/* message type values */
673 +#define LEAVE_INVITE 0 /* leave invitation with server */
674 +#define LOOK_UP 1 /* check for invitation by callee */
675 +#define DELETE 2 /* delete invitation by caller */
676 +#define ANNOUNCE 3 /* announce invitation by caller */
678 +#define REPLY_QUERY 4 /* request reply data from local daemon */
681 +#define SUCCESS 0 /* operation completed properly */
682 +#define NOT_HERE 1 /* callee not logged in */
683 +#define FAILED 2 /* operation failed for unexplained reason */
684 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
685 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
686 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
687 +#define BADVERSION 6 /* request has invalid protocol version */
688 +#define BADADDR 7 /* request has invalid addr value */
689 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
691 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
692 +#define TRY_HERE 10 /* Not on this machine, try this */
693 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
694 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
696 +/* We don't really need much for talk */
697 +struct ip_ct_talk_expect
699 + /* Port that was to be used */
703 +/* This structure exists only once per master */
704 +struct ip_ct_talk_master
708 +#endif /* _IP_CONNTRACK_TALK_H */
709 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
710 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-06-16 07:19:43.000000000 +0200
711 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-06-25 12:24:52.000122360 +0200
721 /* The manipulable part of the tuple. */
732 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.7/include/linux/netfilter_ipv4/ip_pool.h
733 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
734 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_pool.h 2004-06-25 12:21:11.460649456 +0200
739 +/***************************************************************************/
740 +/* This program is free software; you can redistribute it and/or modify */
741 +/* it under the terms of the GNU General Public License as published by */
742 +/* the Free Software Foundation; either version 2 of the License, or */
743 +/* (at your option) any later version. */
745 +/* This program is distributed in the hope that it will be useful, */
746 +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
747 +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
748 +/* GNU General Public License for more details. */
750 +/* You should have received a copy of the GNU General Public License */
751 +/* along with this program; if not, write to the Free Software */
752 +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
753 +/***************************************************************************/
755 +/* A sockopt of such quality has hardly ever been seen before on the open
756 + * market! This little beauty, hardly ever used: above 64, so it's
757 + * traditionally used for firewalling, not touched (even once!) by the
758 + * 2.0, 2.2 and 2.4 kernels!
760 + * Comes with its own certificate of authenticity, valid anywhere in the
765 +#define SO_IP_POOL 81
767 +typedef int ip_pool_t; /* pool index */
768 +#define IP_POOL_NONE ((ip_pool_t)-1)
770 +struct ip_pool_request {
777 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
779 +#define IP_POOL_BAD001 0x00000010
781 +#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
782 +#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
783 +#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
784 +#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
785 +#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
786 +#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
787 +#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
788 +#define IP_POOL_USAGE 0x00000018 /* result in addr */
789 +#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
793 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
794 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
795 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
799 +#endif /*_IP_POOL_H*/
800 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_CONNMARK.h
801 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
802 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-06-25 12:21:25.479518264 +0200
804 +#ifndef _IPT_CONNMARK_H_target
805 +#define _IPT_CONNMARK_H_target
807 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
808 + * by Henrik Nordstrom <hno@marasystems.com>
810 + * This program is free software; you can redistribute it and/or modify
811 + * it under the terms of the GNU General Public License as published by
812 + * the Free Software Foundation; either version 2 of the License, or
813 + * (at your option) any later version.
817 + IPT_CONNMARK_SET = 0,
819 + IPT_CONNMARK_RESTORE
822 +struct ipt_connmark_target_info {
823 + unsigned long mark;
824 + unsigned long mask;
828 +#endif /*_IPT_CONNMARK_H_target*/
829 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_IPMARK.h
830 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
831 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-06-25 12:21:27.026283120 +0200
833 +#ifndef _IPT_IPMARK_H_target
834 +#define _IPT_IPMARK_H_target
836 +struct ipt_ipmark_target_info {
837 + unsigned long andmask;
838 + unsigned long ormask;
842 +#define IPT_IPMARK_SRC 0
843 +#define IPT_IPMARK_DST 1
845 +#endif /*_IPT_IPMARK_H_target*/
846 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_NETLINK.h
847 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
848 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-06-25 12:21:06.895343488 +0200
850 +#ifndef _IPT_FWMON_H
851 +#define _IPT_FWMON_H
853 +/* Bitmask macros */
854 +#define MASK(x,y) (x & y)
855 +#define MASK_SET(x,y) x |= y
856 +#define MASK_UNSET(x,y) x &= ~y
858 +#define USE_MARK 0x00000001
859 +#define USE_DROP 0x00000002
860 +#define USE_SIZE 0x00000004
864 + unsigned int flags;
873 + char iface[IFNAMSIZ];
876 +#endif /*_IPT_FWMON_H*/
877 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ROUTE.h
878 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
879 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ROUTE.h 2004-06-25 12:21:28.210103152 +0200
881 +/* Header file for iptables ipt_ROUTE target
883 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
885 + * This software is distributed under GNU GPL v2, 1991
887 +#ifndef _IPT_ROUTE_H_target
888 +#define _IPT_ROUTE_H_target
890 +#define IPT_ROUTE_IFNAMSIZ 16
892 +struct ipt_route_target_info {
893 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
894 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
895 + u_int32_t gw; /* IP address of gateway */
899 +/* Values for "flags" field */
900 +#define IPT_ROUTE_CONTINUE 0x01
902 +#endif /*_IPT_ROUTE_H_target*/
903 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h
904 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
905 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h 2004-06-25 12:21:07.940184648 +0200
907 +/* TTL modification module for IP tables
908 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
919 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
921 +struct ipt_TTL_info {
928 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_XOR.h
929 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
930 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_XOR.h 2004-06-25 12:21:31.653579664 +0200
935 +struct ipt_XOR_info {
937 + u_int8_t block_size;
940 +#endif /* _IPT_XOR_H */
941 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_account.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_account.h
942 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_account.h 1970-01-01 01:00:00.000000000 +0100
943 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_account.h 2004-06-25 12:21:32.612433896 +0200
946 + * accounting match (ipt_account.c)
947 + * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
951 + * This software is distributed under the terms of GNU GPL
954 +#ifndef _IPT_ACCOUNT_H_
955 +#define _IPT_ACCOUNT_H_
957 +#define IPT_ACCOUNT_NAME_LEN 64
959 +struct t_ipt_account_info {
960 + char name[IPT_ACCOUNT_NAME_LEN];
966 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_connmark.h
967 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
968 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_connmark.h 2004-06-25 12:21:25.482517808 +0200
970 +#ifndef _IPT_CONNMARK_H
971 +#define _IPT_CONNMARK_H
973 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
974 + * by Henrik Nordstrom <hno@marasystems.com>
976 + * This program is free software; you can redistribute it and/or modify
977 + * it under the terms of the GNU General Public License as published by
978 + * the Free Software Foundation; either version 2 of the License, or
979 + * (at your option) any later version.
982 +struct ipt_connmark_info {
983 + unsigned long mark, mask;
987 +#endif /*_IPT_CONNMARK_H*/
988 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h
989 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
990 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-06-25 12:21:08.427110624 +0200
992 +#ifndef _IPT_DSTLIMIT_H
993 +#define _IPT_DSTLIMIT_H
995 +/* timings are in milliseconds. */
996 +#define IPT_DSTLIMIT_SCALE 10000
997 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
998 + seconds, or one every 59 hours. */
1000 +/* details of this structure hidden by the implementation */
1001 +struct ipt_dstlimit_htable;
1003 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
1004 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
1005 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
1007 +struct dstlimit_cfg {
1008 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1009 + u_int32_t avg; /* Average secs between packets * scale */
1010 + u_int32_t burst; /* Period multiplier for upper limit. */
1012 + /* user specified */
1013 + u_int32_t size; /* how many buckets */
1014 + u_int32_t max; /* max number of entries */
1015 + u_int32_t gc_interval; /* gc interval */
1016 + u_int32_t expire; /* when do entries expire? */
1019 +struct ipt_dstlimit_info {
1020 + char name [IFNAMSIZ]; /* name */
1021 + struct dstlimit_cfg cfg;
1022 + struct ipt_dstlimit_htable *hinfo;
1024 + /* Used internally by the kernel */
1027 + struct ipt_dstlimit_info *master;
1030 +#endif /*_IPT_DSTLIMIT_H*/
1031 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h
1032 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1033 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-06-25 12:21:08.958029912 +0200
1035 +#ifndef _IPT_FUZZY_H
1036 +#define _IPT_FUZZY_H
1038 +#include <linux/param.h>
1039 +#include <linux/types.h>
1041 +#define MAXFUZZYRATE 10000000
1042 +#define MINFUZZYRATE 3
1044 +struct ipt_fuzzy_info {
1045 + u_int32_t minimum_rate;
1046 + u_int32_t maximum_rate;
1047 + u_int32_t packets_total;
1048 + u_int32_t bytes_total;
1049 + u_int32_t previous_time;
1050 + u_int32_t present_time;
1051 + u_int32_t mean_rate;
1052 + u_int8_t acceptance_rate;
1055 +#endif /*_IPT_FUZZY_H*/
1056 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h
1057 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1058 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-06-25 12:21:09.436957104 +0200
1060 +#ifndef __ipt_ipv4options_h_included__
1061 +#define __ipt_ipv4options_h_included__
1063 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1064 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1065 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1066 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1067 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1068 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1069 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1070 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1071 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1072 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1073 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1075 +struct ipt_ipv4options_info {
1076 + u_int16_t options;
1080 +#endif /* __ipt_ipv4options_h_included__ */
1081 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h
1082 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1083 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h 2004-06-25 12:21:09.924882928 +0200
1085 +#ifndef _IPT_MPORT_H
1086 +#define _IPT_MPORT_H
1087 +#include <linux/netfilter_ipv4/ip_tables.h>
1089 +#define IPT_MPORT_SOURCE (1<<0)
1090 +#define IPT_MPORT_DESTINATION (1<<1)
1091 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1093 +#define IPT_MULTI_PORTS 15
1095 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1096 +/* every entry in ports[] except for the last one has one bit in pflags
1097 + * associated with it. If this bit is set, the port is the first port of
1098 + * a portrange, with the next entry being the last.
1099 + * End of list is marked with pflags bit set and port=65535.
1100 + * If 14 ports are used (last one does not have a pflag), the last port
1101 + * is repeated to fill the last entry in ports[] */
1104 + u_int8_t flags:2; /* Type of comparison */
1105 + u_int16_t pflags:14; /* Port flags */
1106 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1108 +#endif /*_IPT_MPORT_H*/
1109 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h
1110 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1111 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h 2004-06-25 12:21:10.456802064 +0200
1116 +#include <linux/param.h>
1117 +#include <linux/types.h>
1119 +#ifndef IPT_NTH_NUM_COUNTERS
1120 +#define IPT_NTH_NUM_COUNTERS 16
1123 +struct ipt_nth_info {
1131 +#endif /*_IPT_NTH_H*/
1132 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h
1133 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1134 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h 2004-06-25 12:21:10.970723936 +0200
1139 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1142 + * This program is free software; you can redistribute it and/or modify
1143 + * it under the terms of the GNU General Public License as published by
1144 + * the Free Software Foundation; either version 2 of the License, or
1145 + * (at your option) any later version.
1147 + * This program is distributed in the hope that it will be useful,
1148 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1149 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1150 + * GNU General Public License for more details.
1152 + * You should have received a copy of the GNU General Public License
1153 + * along with this program; if not, write to the Free Software
1154 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1160 +#define MAXGENRELEN 32
1161 +#define MAXDETLEN 64
1163 +#define IPT_OSF_GENRE 1
1164 +#define IPT_OSF_SMART 2
1165 +#define IPT_OSF_LOG 4
1166 +#define IPT_OSF_NETLINK 8
1168 +#define IPT_OSF_LOGLEVEL_ALL 0
1169 +#define IPT_OSF_LOGLEVEL_FIRST 1
1171 +#include <linux/list.h>
1174 +#include <netinet/ip.h>
1175 +#include <netinet/tcp.h>
1179 + struct list_head *prev, *next;
1183 +struct ipt_osf_info
1185 + char genre[MAXGENRELEN];
1187 + unsigned long flags;
1189 + int invert; /* UNSUPPORTED */
1195 + unsigned long val;
1198 +/* This struct represents IANA options
1199 + * http://www.iana.org/assignments/tcp-parameters
1203 + unsigned char kind;
1204 + unsigned char length;
1210 + struct list_head flist;
1211 + struct osf_wc wss;
1212 + unsigned char ttl;
1215 + unsigned char genre[MAXGENRELEN];
1216 + unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
1218 + /* Not needed, but for consistency with original table from Michal Zalewski */
1219 + unsigned char details[MAXDETLEN];
1222 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1226 +struct ipt_osf_nlmsg
1228 + struct osf_finger f;
1230 + struct tcphdr tcp;
1235 +/* Defines for IANA option kinds */
1237 +#define OSFOPT_EOL 0 /* End of options */
1238 +#define OSFOPT_NOP 1 /* NOP */
1239 +#define OSFOPT_MSS 2 /* Maximum segment size */
1240 +#define OSFOPT_WSO 3 /* Window scale option */
1241 +#define OSFOPT_SACKP 4 /* SACK permitted */
1242 +#define OSFOPT_SACK 5 /* SACK */
1243 +#define OSFOPT_ECHO 6
1244 +#define OSFOPT_ECHOREPLY 7
1245 +#define OSFOPT_TS 8 /* Timestamp option */
1246 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1247 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1248 +/* Others are not used in current OSF */
1250 +static struct osf_opt IANA_opts[] =
1257 + {5, 1 ,}, /* SACK length is not defined */
1263 + {11, 1,}, /* CC: Suppose 1 */
1264 + {12, 1,}, /* the same */
1265 + {13, 1,}, /* and here too */
1267 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1281 +#endif /* __KERNEL__ */
1283 +#endif /* _IPT_OSF_H */
1284 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_policy.h
1285 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
1286 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_policy.h 2004-03-08 05:19:04.000000000 +0100
1288 +#ifndef _IPT_POLICY_H
1289 +#define _IPT_POLICY_H
1291 +#define POLICY_MAX_ELEM 4
1293 +enum ipt_policy_flags
1295 + POLICY_MATCH_IN = 0x1,
1296 + POLICY_MATCH_OUT = 0x2,
1297 + POLICY_MATCH_NONE = 0x4,
1298 + POLICY_MATCH_STRICT = 0x8,
1301 +enum ipt_policy_modes
1303 + POLICY_MODE_TRANSPORT,
1304 + POLICY_MODE_TUNNEL
1307 +struct ipt_policy_spec
1317 +struct ipt_policy_elem
1328 + struct ipt_policy_spec match;
1329 + struct ipt_policy_spec invert;
1332 +struct ipt_policy_info
1334 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1339 +#endif /* _IPT_POLICY_H */
1340 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_pool.h
1341 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1342 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_pool.h 2004-06-25 12:21:11.462649152 +0200
1344 +#ifndef _IPT_POOL_H
1345 +#define _IPT_POOL_H
1347 +#include <linux/netfilter_ipv4/ip_pool.h>
1349 +#define IPT_POOL_INV_SRC 0x00000001
1350 +#define IPT_POOL_INV_DST 0x00000002
1351 +#define IPT_POOL_DEL_SRC 0x00000004
1352 +#define IPT_POOL_DEL_DST 0x00000008
1353 +#define IPT_POOL_INV_MOD_SRC 0x00000010
1354 +#define IPT_POOL_INV_MOD_DST 0x00000020
1355 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1356 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1357 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
1358 +#define IPT_POOL_MOD_DST_DROP 0x00000200
1361 +struct ipt_pool_info
1368 +#endif /*_IPT_POOL_H*/
1369 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h
1370 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1371 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h 2004-06-25 12:21:11.945575736 +0200
1376 +#include <linux/param.h>
1377 +#include <linux/types.h>
1380 + * High port numbers have a lower weight to reduce the frequency of false
1381 + * positives, such as from passive mode FTP transfers.
1383 +#define PORT_WEIGHT_PRIV 3
1384 +#define PORT_WEIGHT_HIGH 1
1387 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1388 + * from the same source, with no longer than DELAY ticks between ports.
1390 +#define SCAN_MIN_COUNT 7
1391 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1392 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1393 +#define SCAN_DELAY_THRESHOLD (300) /* old usage of HZ here was erroneously and broke under uml */
1396 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1397 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1398 + * HASH_MAX source addresses per the same hash value.
1400 +#define LIST_SIZE 0x100
1402 +#define HASH_SIZE (1 << HASH_LOG)
1403 +#define HASH_MAX 0x10
1405 +struct ipt_psd_info {
1406 + unsigned int weight_threshold;
1407 + unsigned int delay_threshold;
1408 + unsigned short lo_ports_weight;
1409 + unsigned short hi_ports_weight;
1412 +#endif /*_IPT_PSD_H*/
1413 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h
1414 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1415 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h 2004-06-25 12:21:12.433501560 +0200
1417 +#ifndef _IPT_QUOTA_H
1418 +#define _IPT_QUOTA_H
1420 +/* print debug info in both kernel/netfilter module & iptable library */
1421 +//#define DEBUG_IPT_QUOTA
1423 +struct ipt_quota_info {
1427 +#endif /*_IPT_QUOTA_H*/
1428 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_random.h
1429 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1430 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_random.h 2004-06-25 12:21:12.934425408 +0200
1432 +#ifndef _IPT_RAND_H
1433 +#define _IPT_RAND_H
1435 +#include <linux/param.h>
1436 +#include <linux/types.h>
1438 +struct ipt_rand_info {
1442 +#endif /*_IPT_RAND_H*/
1443 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h
1444 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1445 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h 2004-06-25 12:21:13.445347736 +0200
1447 +#ifndef _IPT_SCTP_H_
1448 +#define _IPT_SCTP_H_
1450 +#define IPT_SCTP_SRC_PORTS 0x01
1451 +#define IPT_SCTP_DEST_PORTS 0x02
1452 +#define IPT_SCTP_CHUNK_TYPES 0x04
1454 +#define IPT_SCTP_VALID_FLAGS 0x07
1456 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1459 +struct ipt_sctp_flag_info {
1460 + u_int8_t chunktype;
1462 + u_int8_t flag_mask;
1465 +#define IPT_NUM_SCTP_FLAGS 4
1467 +struct ipt_sctp_info {
1468 + u_int16_t dpts[2]; /* Min, Max */
1469 + u_int16_t spts[2]; /* Min, Max */
1471 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
1473 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
1474 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
1475 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
1477 + u_int32_t chunk_match_type;
1478 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1482 + u_int32_t invflags;
1485 +#define bytes(type) (sizeof(type) * 8)
1487 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
1489 + chunkmap[type / bytes(u_int32_t)] |= \
1490 + 1 << (type % bytes(u_int32_t)); \
1493 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
1495 + chunkmap[type / bytes(u_int32_t)] &= \
1496 + ~(1 << (type % bytes(u_int32_t))); \
1499 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
1501 + (chunkmap[type / bytes (u_int32_t)] & \
1502 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
1505 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
1508 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1509 + chunkmap[i] = 0; \
1512 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
1515 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1516 + chunkmap[i] = ~0; \
1519 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
1522 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1523 + destmap[i] = srcmap[i]; \
1526 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
1530 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1531 + if (chunkmap[i]) { \
1539 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
1543 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1544 + if (chunkmap[i] != ~0) { \
1552 +#endif /* _IPT_SCTP_H_ */
1554 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_string.h
1555 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1556 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_string.h 2004-06-25 12:28:38.565679160 +0200
1558 +#ifndef _IPT_STRING_H
1559 +#define _IPT_STRING_H
1561 +/* *** PERFORMANCE TWEAK ***
1562 + * Packet size and search string threshold,
1563 + * above which sublinear searches is used. */
1564 +#define IPT_STRING_HAYSTACK_THRESH 100
1565 +#define IPT_STRING_NEEDLE_THRESH 20
1567 +#define BM_MAX_NLEN 256
1568 +#define BM_MAX_HLEN 1024
1570 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1572 +struct ipt_string_info {
1573 + char string[BM_MAX_NLEN];
1578 +#endif /* _IPT_STRING_H */
1579 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h
1580 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1581 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h 2004-06-25 12:21:13.932273712 +0200
1583 +#ifndef __ipt_time_h_included__
1584 +#define __ipt_time_h_included__
1587 +struct ipt_time_info {
1588 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
1589 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
1590 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
1591 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
1592 + time_t date_start;
1597 +#endif /* __ipt_time_h_included__ */
1598 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h
1599 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
1600 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h 2004-06-25 12:21:14.420199536 +0200
1604 +#include <linux/netfilter_ipv4/ip_tables.h>
1614 +struct ipt_u32_location_element
1619 +struct ipt_u32_value_element
1624 +/* *** any way to allow for an arbitrary number of elements?
1625 + for now I settle for a limit of 10 of each */
1626 +#define U32MAXSIZE 10
1627 +struct ipt_u32_test
1630 + struct ipt_u32_location_element location[U32MAXSIZE+1];
1632 + struct ipt_u32_value_element value[U32MAXSIZE+1];
1638 + struct ipt_u32_test tests[U32MAXSIZE+1];
1641 +#endif /*_IPT_U32_H*/
1642 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4.h linux-2.6.7/include/linux/netfilter_ipv4.h
1643 --- linux-2.6.7.org/include/linux/netfilter_ipv4.h 2004-06-16 07:19:52.000000000 +0200
1644 +++ linux-2.6.7/include/linux/netfilter_ipv4.h 2004-06-25 12:21:37.077755064 +0200
1647 #include <linux/config.h>
1648 #include <linux/netfilter.h>
1649 +#include <linux/netdevice.h>
1650 +#include <net/protocol.h>
1652 /* IP Cache bits. */
1653 /* Src IP address. */
1655 Returns true or false. */
1656 extern int skb_ip_make_writable(struct sk_buff **pskb,
1657 unsigned int writable_len);
1659 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1660 +#include <net/route.h>
1661 +#include <net/xfrm.h>
1663 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1665 + return !skb->sp || skb->sp->decap_done;
1669 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1671 + return skb->sp && !skb->sp->decap_done
1672 + && (!ipprot || !ipprot->xfrm_prot);
1675 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1677 + return skb->sp && !skb->sp->decap_done
1678 + && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1681 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1682 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1683 +#else /* CONFIG_XFRM */
1684 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1690 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1695 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1700 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1705 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1709 +#endif /* CONFIG_XFRM */
1710 #endif /*__KERNEL__*/
1712 #endif /*__LINUX_IP_NETFILTER_H*/
1713 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h
1714 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
1715 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h 2004-06-25 12:21:05.613538352 +0200
1717 +/* Hop Limit modification module for ip6tables
1718 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1719 + * Based on HW's TTL module */
1730 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
1732 +struct ip6t_HL_info {
1734 + u_int8_t hop_limit;
1739 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h
1740 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-06-16 07:18:38.000000000 +0200
1741 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-06-25 12:21:07.506250616 +0200
1743 #define _IP6T_REJECT_H
1745 enum ip6t_reject_with {
1746 - IP6T_ICMP_NET_UNREACHABLE,
1747 - IP6T_ICMP_HOST_UNREACHABLE,
1748 - IP6T_ICMP_PROT_UNREACHABLE,
1749 - IP6T_ICMP_PORT_UNREACHABLE,
1750 - IP6T_ICMP_ECHOREPLY
1751 + IP6T_ICMP6_NO_ROUTE,
1752 + IP6T_ICMP6_ADM_PROHIBITED,
1753 + IP6T_ICMP6_NOT_NEIGHBOUR,
1754 + IP6T_ICMP6_ADDR_UNREACH,
1755 + IP6T_ICMP6_PORT_UNREACH,
1756 + IP6T_ICMP6_ECHOREPLY,
1760 struct ip6t_reject_info {
1761 enum ip6t_reject_with with; /* reject type */
1764 -#endif /*_IPT_REJECT_H*/
1765 +#endif /*_IP6T_REJECT_H*/
1766 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h
1767 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
1768 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2004-06-25 12:21:28.212102848 +0200
1770 +/* Header file for iptables ip6t_ROUTE target
1772 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
1774 + * This software is distributed under GNU GPL v2, 1991
1776 +#ifndef _IPT_ROUTE_H_target
1777 +#define _IPT_ROUTE_H_target
1779 +#define IP6T_ROUTE_IFNAMSIZ 16
1781 +struct ip6t_route_target_info {
1782 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
1783 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
1784 + u_int32_t gw[4]; /* IPv6 address of gateway */
1788 +/* Values for "flags" field */
1789 +#define IP6T_ROUTE_CONTINUE 0x01
1791 +#endif /*_IP6T_ROUTE_H_target*/
1792 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1793 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1794 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-06-25 12:21:08.960029608 +0200
1796 +#ifndef _IP6T_FUZZY_H
1797 +#define _IP6T_FUZZY_H
1799 +#include <linux/param.h>
1800 +#include <linux/types.h>
1802 +#define MAXFUZZYRATE 10000000
1803 +#define MINFUZZYRATE 3
1805 +struct ip6t_fuzzy_info {
1806 + u_int32_t minimum_rate;
1807 + u_int32_t maximum_rate;
1808 + u_int32_t packets_total;
1809 + u_int32_t bytes_total;
1810 + u_int32_t previous_time;
1811 + u_int32_t present_time;
1812 + u_int32_t mean_rate;
1813 + u_int8_t acceptance_rate;
1816 +#endif /*_IP6T_FUZZY_H*/
1817 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h
1818 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1819 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h 2004-06-25 12:21:10.458801760 +0200
1821 +#ifndef _IP6T_NTH_H
1822 +#define _IP6T_NTH_H
1824 +#include <linux/param.h>
1825 +#include <linux/types.h>
1827 +#ifndef IP6T_NTH_NUM_COUNTERS
1828 +#define IP6T_NTH_NUM_COUNTERS 16
1831 +struct ip6t_nth_info {
1839 +#endif /*_IP6T_NTH_H*/
1840 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_owner.h
1841 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-06-16 07:19:37.000000000 +0200
1842 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_owner.h 2004-06-25 12:23:17.497488944 +0200
1844 #define IP6T_OWNER_GID 0x02
1845 #define IP6T_OWNER_PID 0x04
1846 #define IP6T_OWNER_SID 0x08
1847 +#define IP6T_OWNER_COMM 0x10
1849 struct ip6t_owner_info {
1855 u_int8_t match, invert; /* flags */
1858 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_policy.h
1859 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1860 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_policy.h 2004-05-07 18:20:56.000000000 +0200
1862 +#ifndef _IP6T_POLICY_H
1863 +#define _IP6T_POLICY_H
1865 +#define POLICY_MAX_ELEM 4
1867 +enum ip6t_policy_flags
1869 + POLICY_MATCH_IN = 0x1,
1870 + POLICY_MATCH_OUT = 0x2,
1871 + POLICY_MATCH_NONE = 0x4,
1872 + POLICY_MATCH_STRICT = 0x8,
1875 +enum ip6t_policy_modes
1877 + POLICY_MODE_TRANSPORT,
1878 + POLICY_MODE_TUNNEL
1881 +struct ip6t_policy_spec
1891 +struct ip6t_policy_elem
1893 + struct in6_addr saddr;
1894 + struct in6_addr smask;
1895 + struct in6_addr daddr;
1896 + struct in6_addr dmask;
1902 + struct ip6t_policy_spec match;
1903 + struct ip6t_policy_spec invert;
1906 +struct ip6t_policy_info
1908 + struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
1913 +#endif /* _IP6T_POLICY_H */
1914 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_random.h
1915 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
1916 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_random.h 2004-06-25 12:21:12.936425104 +0200
1918 +#ifndef _IP6T_RAND_H
1919 +#define _IP6T_RAND_H
1921 +#include <linux/param.h>
1922 +#include <linux/types.h>
1924 +struct ip6t_rand_info {
1928 +#endif /*_IP6T_RAND_H*/
1929 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_mime.h linux-2.6.7/include/linux/netfilter_mime.h
1930 --- linux-2.6.7.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1931 +++ linux-2.6.7/include/linux/netfilter_mime.h 2004-06-25 12:24:50.030421800 +0200
1934 + * MIME functions for netfilter modules. This file provides implementations
1935 + * for basic MIME parsing. MIME headers are used in many protocols, such as
1936 + * HTTP, RTSP, SIP, etc.
1938 + * gcc will warn for defined but unused functions, so we only include the
1939 + * functions requested. The following macros are used:
1940 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1942 +#ifndef _NETFILTER_MIME_H
1943 +#define _NETFILTER_MIME_H
1945 +/* Only include these functions for kernel code. */
1948 +#include <linux/ctype.h>
1951 + * Given a buffer and length, advance to the next line and mark the current
1952 + * line. If the current line is empty, *plinelen will be set to zero. If
1953 + * not, it will be set to the actual line length (including CRLF).
1955 + * 'line' in this context means logical line (includes LWS continuations).
1956 + * Returns 1 on success, 0 on failure.
1958 +#ifdef NF_NEED_MIME_NEXTLINE
1960 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1964 + int is_first_line = 1;
1973 + while (p[off] != '\n')
1984 + /* if we saw a crlf, physlen needs adjusted */
1985 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1990 + /* advance past the newline */
1993 + /* check for an empty line */
1999 + /* check for colon on the first physical line */
2000 + if (is_first_line)
2002 + is_first_line = 0;
2003 + if (memchr(p+(*poff), ':', physlen) == NULL)
2009 + while (p[off] == ' ' || p[off] == '\t');
2011 + *plineoff = *poff;
2012 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
2017 +#endif /* NF_NEED_MIME_NEXTLINE */
2019 +#endif /* __KERNEL__ */
2021 +#endif /* _NETFILTER_MIME_H */
2022 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/sysctl.h linux-2.6.7/include/linux/sysctl.h
2023 --- linux-2.6.7.org/include/linux/sysctl.h 2004-06-25 10:47:45.500884880 +0200
2024 +++ linux-2.6.7/include/linux/sysctl.h 2004-06-25 12:21:02.311040408 +0200
2026 NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
2027 NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
2028 NET_IPV4_NF_CONNTRACK_BUCKETS=14,
2029 + NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
2032 /* /proc/sys/net/ipv6 */
2033 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/ip.h linux-2.6.7/include/net/ip.h
2034 --- linux-2.6.7.org/include/net/ip.h 2004-06-25 10:47:45.530880320 +0200
2035 +++ linux-2.6.7/include/net/ip.h 2004-06-25 12:21:36.157894904 +0200
2037 #include <linux/netdevice.h>
2038 #include <linux/inetdevice.h>
2039 #include <linux/in_route.h>
2040 +#include <linux/netfilter.h>
2041 +#include <linux/netfilter_ipv4.h>
2042 #include <net/route.h>
2043 #include <net/arp.h>
2046 #define IPSKB_TRANSLATED 2
2047 #define IPSKB_FORWARDED 4
2048 #define IPSKB_XFRM_TUNNEL_SIZE 8
2049 +#define IPSKB_XFRM_TRANSFORMED 16
2053 @@ -212,6 +215,12 @@
2054 __ip_select_ident(iph, dst, more);
2057 +extern inline int ip_dst_output(struct sk_buff *skb)
2059 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2060 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2064 * Map a multicast IP onto multicast MAC for type ethernet.
2066 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/protocol.h linux-2.6.7/include/net/protocol.h
2067 --- linux-2.6.7.org/include/net/protocol.h 2004-06-25 10:47:45.548877584 +0200
2068 +++ linux-2.6.7/include/net/protocol.h 2004-06-25 12:21:37.079754760 +0200
2070 int (*handler)(struct sk_buff *skb);
2071 void (*err_handler)(struct sk_buff *skb, u32 info);
2076 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2077 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/tcp.h linux-2.6.7/include/net/tcp.h
2078 --- linux-2.6.7.org/include/net/tcp.h 2004-06-25 10:47:45.569874392 +0200
2079 +++ linux-2.6.7/include/net/tcp.h 2004-06-25 12:23:15.996717096 +0200
2081 extern void tcp_bucket_unlock(struct sock *sk);
2082 extern int tcp_port_rover;
2083 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2084 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2086 /* These are AF independent. */
2087 static __inline__ int tcp_bhashfn(__u16 lport)
2088 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/udp.h linux-2.6.7/include/net/udp.h
2089 --- linux-2.6.7.org/include/net/udp.h 2004-06-16 07:19:51.000000000 +0200
2090 +++ linux-2.6.7/include/net/udp.h 2004-06-25 12:23:15.998716792 +0200
2092 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2093 extern int udp_disconnect(struct sock *sk, int flags);
2095 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2097 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2098 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
2099 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
2100 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/xfrm.h linux-2.6.7/include/net/xfrm.h
2101 --- linux-2.6.7.org/include/net/xfrm.h 2004-06-25 10:47:45.574873632 +0200
2102 +++ linux-2.6.7/include/net/xfrm.h 2004-06-25 12:21:37.084754000 +0200
2107 +#ifdef CONFIG_NETFILTER
2110 struct sec_decap_state x[XFRM_MAX_DEPTH];
2113 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/core/netfilter.c linux-2.6.7/net/core/netfilter.c
2114 --- linux-2.6.7.org/net/core/netfilter.c 2004-06-16 07:19:22.000000000 +0200
2115 +++ linux-2.6.7/net/core/netfilter.c 2004-06-25 12:21:38.699508520 +0200
2117 #include <linux/icmp.h>
2118 #include <net/sock.h>
2119 #include <net/route.h>
2120 +#include <net/xfrm.h>
2121 +#include <net/ip.h>
2122 #include <linux/ip.h>
2124 /* In this code, we can be waiting indefinitely for userspace to
2126 #ifdef CONFIG_IP_ROUTE_FWMARK
2127 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2129 - fl.proto = iph->protocol;
2130 if (ip_route_output_key(&rt, &fl) != 0)
2133 @@ -657,6 +658,20 @@
2134 if ((*pskb)->dst->error)
2138 + if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2139 + struct xfrm_policy_afinfo *afinfo;
2141 + afinfo = xfrm_policy_get_afinfo(AF_INET);
2142 + if (afinfo != NULL) {
2143 + afinfo->decode_session(*pskb, &fl);
2144 + xfrm_policy_put_afinfo(afinfo);
2145 + if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2151 /* Change in oif may mean change in hh_len. */
2152 hh_len = (*pskb)->dst->dev->hard_header_len;
2153 if (skb_headroom(*pskb) < hh_len) {
2154 @@ -674,6 +689,71 @@
2159 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2161 + skb->sp->decap_done = 1;
2162 + dst_release(skb->dst);
2165 + return netif_rx(skb);
2168 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2170 + __skb_push(skb, skb->data - skb->nh.raw);
2171 + /* Fix header len and checksum if last xfrm was transport mode */
2172 + if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2173 + skb->nh.iph->tot_len = htons(skb->len);
2174 + ip_send_check(skb->nh.iph);
2176 + return nf_rcv_postxfrm_nonlocal(skb);
2179 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2180 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2181 +#include <linux/netfilter_ipv4/ip_nat.h>
2183 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2185 + struct ip_conntrack *ct;
2186 + struct ip_conntrack_tuple *t;
2187 + struct ip_nat_info_manip *m;
2190 + if (skb->nfct == NULL)
2192 + ct = (struct ip_conntrack *)skb->nfct->master;
2194 + for (i = 0; i < ct->nat.info.num_manips; i++) {
2195 + m = &ct->nat.info.manips[i];
2196 + t = &ct->tuplehash[m->direction].tuple;
2198 + switch (m->hooknum) {
2199 + case NF_IP_PRE_ROUTING:
2200 + if (m->maniptype != IP_NAT_MANIP_DST)
2202 + fl->fl4_dst = t->dst.ip;
2203 + if (t->dst.protonum == IPPROTO_TCP ||
2204 + t->dst.protonum == IPPROTO_UDP)
2205 + fl->fl_ip_dport = t->dst.u.tcp.port;
2207 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2208 + case NF_IP_LOCAL_IN:
2209 + if (m->maniptype != IP_NAT_MANIP_SRC)
2211 + fl->fl4_src = t->src.ip;
2212 + if (t->dst.protonum == IPPROTO_TCP ||
2213 + t->dst.protonum == IPPROTO_UDP)
2214 + fl->fl_ip_sport = t->src.u.tcp.port;
2220 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2223 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2225 struct sk_buff *nskb;
2227 EXPORT_SYMBOL(nf_unregister_hook);
2228 EXPORT_SYMBOL(nf_unregister_queue_handler);
2229 EXPORT_SYMBOL(nf_unregister_sockopt);
2230 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2231 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ah4.c linux-2.6.7/net/ipv4/ah4.c
2232 --- linux-2.6.7.org/net/ipv4/ah4.c 2004-06-25 10:47:45.935818760 +0200
2233 +++ linux-2.6.7/net/ipv4/ah4.c 2004-06-25 12:21:37.092752784 +0200
2235 err = -EHOSTUNREACH;
2238 + IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
2239 return NET_XMIT_BYPASS;
2243 .handler = xfrm4_rcv,
2244 .err_handler = ah4_err,
2249 static int __init ah4_init(void)
2250 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/esp4.c linux-2.6.7/net/ipv4/esp4.c
2251 --- linux-2.6.7.org/net/ipv4/esp4.c 2004-06-25 10:47:45.939818152 +0200
2252 +++ linux-2.6.7/net/ipv4/esp4.c 2004-06-25 12:21:37.095752328 +0200
2254 err = -EHOSTUNREACH;
2257 + IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
2258 return NET_XMIT_BYPASS;
2262 .handler = xfrm4_rcv,
2263 .err_handler = esp4_err,
2268 static int __init esp4_init(void)
2269 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/igmp.c linux-2.6.7/net/ipv4/igmp.c
2270 --- linux-2.6.7.org/net/ipv4/igmp.c 2004-06-16 07:20:22.000000000 +0200
2271 +++ linux-2.6.7/net/ipv4/igmp.c 2004-06-25 12:21:36.172892624 +0200
2273 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2275 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2280 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2282 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2284 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2289 static void igmp_gq_timer_expire(unsigned long data)
2290 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ip_forward.c linux-2.6.7/net/ipv4/ip_forward.c
2291 --- linux-2.6.7.org/net/ipv4/ip_forward.c 2004-06-16 07:18:38.000000000 +0200
2292 +++ linux-2.6.7/net/ipv4/ip_forward.c 2004-06-25 12:21:36.173892472 +0200
2294 if (unlikely(opt->optlen))
2295 ip_forward_options(skb);
2297 - return dst_output(skb);
2298 + return ip_dst_output(skb);
2301 int ip_forward(struct sk_buff *skb)
2302 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ip_input.c linux-2.6.7/net/ipv4/ip_input.c
2303 --- linux-2.6.7.org/net/ipv4/ip_input.c 2004-06-25 10:47:45.954815872 +0200
2304 +++ linux-2.6.7/net/ipv4/ip_input.c 2004-06-25 12:21:38.702508064 +0200
2305 @@ -206,10 +206,6 @@
2307 __skb_pull(skb, ihl);
2309 - /* Free reference early: we don't need it any more, and it may
2310 - hold ip_conntrack module loaded indefinitely. */
2313 /* Point into the IP datagram, just past the header. */
2314 skb->h.raw = skb->data;
2316 @@ -224,6 +220,13 @@
2318 hash = protocol & (MAX_INET_PROTOS - 1);
2319 raw_sk = sk_head(&raw_v4_htable[hash]);
2320 + ipprot = inet_protos[hash];
2321 + smp_read_barrier_depends();
2323 + if (nf_xfrm_local_done(skb, ipprot)) {
2324 + nf_rcv_postxfrm_local(skb);
2328 /* If there maybe a raw socket we must check - if not we
2330 @@ -231,14 +234,15 @@
2332 raw_v4_input(skb, skb->nh.iph, hash);
2334 - if ((ipprot = inet_protos[hash]) != NULL) {
2335 + if (ipprot != NULL) {
2338 - smp_read_barrier_depends();
2339 - if (!ipprot->no_policy &&
2340 - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2343 + if (!ipprot->no_policy) {
2344 + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2350 ret = ipprot->handler(skb);
2356 - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2357 - ip_local_deliver_finish);
2358 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2359 + ip_local_deliver_finish, nf_hook_input_cond(skb));
2362 static inline int ip_rcv_finish(struct sk_buff *skb)
2367 + if (nf_xfrm_nonlocal_done(skb))
2368 + return nf_rcv_postxfrm_nonlocal(skb);
2370 #ifdef CONFIG_NET_CLS_ROUTE
2371 if (skb->dst->tclassid) {
2372 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2377 - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2379 + return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2380 + ip_rcv_finish, nf_hook_input_cond(skb));
2383 IP_INC_STATS_BH(InHdrErrors);
2384 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ip_output.c linux-2.6.7/net/ipv4/ip_output.c
2385 --- linux-2.6.7.org/net/ipv4/ip_output.c 2004-06-25 10:47:45.959815112 +0200
2386 +++ linux-2.6.7/net/ipv4/ip_output.c 2004-06-25 12:21:36.181891256 +0200
2387 @@ -123,6 +123,15 @@
2391 +#ifdef CONFIG_NETFILTER
2392 +/* out-of-line copy is only required with netfilter */
2393 +int ip_dst_output(struct sk_buff *skb)
2395 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2396 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2401 * Add an ip header to a skbuff and send it out.
2406 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2411 static inline int ip_finish_output2(struct sk_buff *skb)
2413 return ip_finish_output(skb);
2416 -int ip_output(struct sk_buff **pskb)
2417 +static inline int ip_output2(struct sk_buff **pskb)
2419 struct sk_buff *skb = *pskb;
2421 @@ -297,6 +306,16 @@
2422 return ip_finish_output(skb);
2425 +int ip_output(struct sk_buff *skb)
2427 + int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2431 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2432 + skb->dst->dev, ip_output2, transformed);
2435 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2437 struct sock *sk = skb->sk;
2439 skb->priority = sk->sk_priority;
2441 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2446 IP_INC_STATS(OutNoRoutes);
2447 @@ -1169,7 +1188,7 @@
2449 /* Netfilter gets whole the not fragmented skb. */
2450 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2451 - skb->dst->dev, dst_output);
2452 + skb->dst->dev, ip_dst_output);
2455 err = inet->recverr ? net_xmit_errno(err) : 0;
2456 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ipcomp.c linux-2.6.7/net/ipv4/ipcomp.c
2457 --- linux-2.6.7.org/net/ipv4/ipcomp.c 2004-06-25 10:47:45.966814048 +0200
2458 +++ linux-2.6.7/net/ipv4/ipcomp.c 2004-06-25 12:21:37.102751264 +0200
2460 err = -EHOSTUNREACH;
2463 + IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
2464 err = NET_XMIT_BYPASS;
2468 .handler = xfrm4_rcv,
2469 .err_handler = ipcomp4_err,
2474 static int __init ipcomp4_init(void)
2475 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ipip.c linux-2.6.7/net/ipv4/ipip.c
2476 --- linux-2.6.7.org/net/ipv4/ipip.c 2004-06-25 10:47:45.975812680 +0200
2477 +++ linux-2.6.7/net/ipv4/ipip.c 2004-06-25 12:21:37.107750504 +0200
2478 @@ -478,6 +478,11 @@
2480 read_lock(&ipip_lock);
2481 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2482 + /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2483 + if (nf_xfrm_local_done(skb, NULL)) {
2484 + nf_rcv_postxfrm_local(skb);
2487 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2488 read_unlock(&ipip_lock);
2490 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ipmr.c linux-2.6.7/net/ipv4/ipmr.c
2491 --- linux-2.6.7.org/net/ipv4/ipmr.c 2004-06-25 10:47:45.982811616 +0200
2492 +++ linux-2.6.7/net/ipv4/ipmr.c 2004-06-25 12:21:36.190889888 +0200
2493 @@ -1117,7 +1117,7 @@
2494 if (unlikely(opt->optlen))
2495 ip_forward_options(skb);
2497 - return dst_output(skb);
2498 + return ip_dst_output(skb);
2502 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Kconfig linux-2.6.7/net/ipv4/netfilter/Kconfig
2503 --- linux-2.6.7.org/net/ipv4/netfilter/Kconfig 2004-06-25 10:47:45.000000000 +0200
2504 +++ linux-2.6.7/net/ipv4/netfilter/Kconfig 2004-06-25 12:28:43.699898640 +0200
2505 @@ -206,6 +206,11 @@
2507 To compile it as a module, choose M here. If unsure, say N.
2509 +config IP_NF_MATCH_UNCLEAN
2510 + tristate 'unclean match support (EXPERIMENTAL)'
2511 + depends on EXPERIMENTAL && IP_NF_IPTABLES
2514 config IP_NF_MATCH_TTL
2515 tristate "TTL match support"
2516 depends on IP_NF_IPTABLES
2517 @@ -627,5 +632,459 @@
2518 If you want to compile it as a module, say M here and read
2519 Documentation/modules.txt. If unsure, say `N'.
2521 +config IP_NF_TARGET_IPV4OPTSSTRIP
2522 + tristate 'IPV4OPTSSTRIP target support'
2523 + depends on IP_NF_MANGLE
2525 + This option adds an IPV4OPTSSTRIP target.
2526 + This target allows you to strip all IP options in a packet.
2528 + If you want to compile it as a module, say M here and read
2529 + Documentation/modules.txt. If unsure, say `N'.
2531 +config IP_NF_TARGET_NETLINK
2532 + tristate 'NETLINK target support'
2533 + depends on IP_NF_FILTER
2535 + The NETLINK target allows you to recieve packets in userspace via
2536 + the kernel firewall netlink socket. Apps such as fwmon
2537 + (http://firestorm.geek-ware.co.uk) can then recieve and dislpay
2538 + these packets. This option is basically a re-implementation of the
2539 + ipchains -o option.
2541 +config IP_NF_TARGET_TTL
2542 + tristate 'TTL target support'
2543 + depends on IP_NF_MANGLE
2545 + This option adds a `TTL' target, which enables the user to set
2546 + the TTL value or increment / decrement the TTL value by a given
2549 + If you want to compile it as a module, say M here and read
2550 + Documentation/modules.txt. If unsure, say `N'.
2552 +config IP_NF_MATCH_DSTLIMIT
2553 + tristate 'dstlimit match support'
2554 + depends on IP_NF_IPTABLES
2556 +config IP_NF_MATCH_FUZZY
2557 + tristate 'fuzzy match support'
2558 + depends on IP_NF_IPTABLES
2560 + This option adds a `fuzzy' match, which allows you to match
2561 + packets according to a fuzzy logic based law.
2563 + If you want to compile it as a module, say M here and read
2564 + Documentation/modules.txt. If unsure, say `N'.
2566 +config IP_NF_MATCH_IPV4OPTIONS
2567 + tristate 'IPV4OPTIONS match support'
2568 + depends on IP_NF_IPTABLES
2570 + This option adds a IPV4OPTIONS match.
2571 + It allows you to filter options like source routing,
2572 + record route, timestamp and router-altert.
2574 + If you say Y here, try iptables -m ipv4options --help for more information.
2576 + If you want to compile it as a module, say M here and read
2577 + Documentation/modules.txt. If unsure, say `N'.
2579 +config IP_NF_MATCH_MPORT
2580 + tristate 'Multiple port with ranges match support'
2581 + depends on IP_NF_IPTABLES
2583 + This is an enhanced multiport match which supports port
2584 + ranges as well as single ports.
2586 + If you want to compile it as a module, say M here and read
2587 + Documentation/modules.txt. If unsure, say `N'.
2589 +config IP_NF_MATCH_NTH
2590 + tristate 'Nth match support'
2591 + depends on IP_NF_IPTABLES
2593 + This option adds a `Nth' match, which allow you to make
2594 + rules that match every Nth packet. By default there are
2595 + 16 different counters.
2598 + --every Nth Match every Nth packet
2599 + [--counter] num Use counter 0-15 (default:0)
2600 + [--start] num Initialize the counter at the number 'num'
2601 + instead of 0. Must be between 0 and Nth-1
2602 + [--packet] num Match on 'num' packet. Must be between 0
2605 + If --packet is used for a counter than
2606 + there must be Nth number of --packet
2607 + rules, covering all values between 0 and
2608 + Nth-1 inclusively.
2610 + If you want to compile it as a module, say M here and read
2611 + Documentation/modules.txt. If unsure, say `N'.
2613 +config IP_NF_MATCH_OSF
2614 + tristate 'OSF match support'
2615 + depends on IP_NF_IPTABLES
2618 + The idea of passive OS fingerprint matching exists for quite a long time,
2619 + but was created as extension fo OpenBSD pf only some weeks ago.
2620 + Original idea was lurked in some OpenBSD mailing list (thanks
2621 + grange@open...) and than adopted for Linux netfilter in form of this code.
2623 + Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
2624 + his excellent p0f and than changed a bit for more convenience.
2626 + This module compares some data(WS, MSS, options and it's order, ttl,
2627 + df and others) from first SYN packet (actually from packets with SYN
2628 + bit set) with hardcoded in fingers[] table ones.
2630 + If you say Y here, try iptables -m osf --help for more information.
2632 + If you want to compile it as a module, say M here and read
2633 + Documentation/modules.txt. If unsure, say `N'.
2635 +config IP_POOL_STATISTICS
2636 + bool 'enable statistics on pool usage'
2637 + depends on IP_NF_POOL!=n
2639 + This option controls whether usage gathering code is compiled into the
2640 + ip_pool module. Disabling statistics may be substantially faster.
2643 + tristate 'IP address pool support'
2644 + depends on IP_NF_IPTABLES
2646 + Pool matching lets you use bitmaps with one bit per address from some
2647 + range of IP addresses; the match depends on whether a checked source
2648 + or destination address has its bit set in the pool.
2650 + There is also a POOL netfilter target, which can be used to set or remove
2651 + the addresses of a packet from a pool.
2653 + To define and use pools, you need userlevel utilities: a patched iptables,
2654 + and the program ippool(8), which defines the pools and their bounds.
2655 + The current release of pool matching is ippool-0.0.2, and can be found
2656 + in the archives of the netfilter mailing list at
2657 + http://lists.samba.org/netfilter/.
2659 + If you want to compile it as a module, say M here and read
2660 + Documentation/modules.txt. If unsure, say `N'.
2662 +config IP_NF_MATCH_PSD
2663 + tristate 'psd match support'
2664 + depends on IP_NF_IPTABLES
2666 + This option adds a `psd' match, which allows you to create rules in
2667 + any iptables table wich will detect TCP and UDP port scans.
2669 + If you want to compile it as a module, say M here and read
2670 + Documentation/modules.txt. If unsure, say `N'.
2672 +config IP_NF_MATCH_QUOTA
2673 + tristate 'quota match support'
2674 + depends on IP_NF_IPTABLES
2676 + This match implements network quotas.
2678 + If you want to compile it as a module, say M here and read
2679 + Documentation/modules.txt. If unsure, say `N'.
2682 +config IP_NF_MATCH_RANDOM
2683 + tristate 'random match support'
2684 + depends on IP_NF_IPTABLES
2686 + This option adds a `random' match,
2687 + which allow you to match packets randomly
2688 + following a given probability.
2690 + If you want to compile it as a module, say M here and read
2691 + Documentation/modules.txt. If unsure, say `N'.
2693 +config IP_NF_MATCH_SCTP
2694 + tristate 'SCTP protocol match support'
2695 + depends on IP_NF_IPTABLES
2697 +config IP_NF_MATCH_TIME
2698 + tristate 'TIME match support'
2699 + depends on IP_NF_IPTABLES
2701 + This option adds a `time' match, which allows you
2702 + to match based on the packet arrival time/date
2703 + (arrival time/date at the machine which netfilter is running on) or
2704 + departure time/date (for locally generated packets).
2706 + If you say Y here, try iptables -m time --help for more information.
2708 + If you want to compile it as a module, say M here and read
2709 + Documentation/modules.txt. If unsure, say `N'.
2711 +config IP_NF_MATCH_U32
2712 + tristate 'U32 match support'
2713 + depends on IP_NF_IPTABLES
2715 + U32 allows you to extract quantities of up to 4 bytes from a packet,
2716 + AND them with specified masks, shift them by specified amounts and
2717 + test whether the results are in any of a set of specified ranges.
2718 + The specification of what to extract is general enough to skip over
2719 + headers with lengths stored in the packet, as in IP or TCP header
2722 + Details and examples are in the kernel module source.
2724 +config IP_NF_CONNTRACK_MARK
2725 + bool 'Connection mark tracking support'
2727 + This option enables support for connection marks, used by the
2728 + `CONNMARK' target and `connmark' match. Similar to the mark value
2729 + of packets, but this mark value is kept in the conntrack session
2730 + instead of the individual packets.
2732 +config IP_NF_TARGET_CONNMARK
2733 + tristate 'CONNMARK target support'
2734 + depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
2736 + This option adds a `CONNMARK' target, which allows one to manipulate
2737 + the connection mark value. Similar to the MARK target, but
2738 + affects the connection mark value rather than the packet mark value.
2740 + If you want to compile it as a module, say M here and read
2741 + Documentation/modules.txt. The module will be called
2742 + ipt_CONNMARK.o. If unsure, say `N'.
2744 +config IP_NF_MATCH_CONNMARK
2745 + tristate ' Connection mark match support'
2746 + depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
2748 + This option adds a `connmark' match, which allows you to match the
2749 + connection mark value previously set for the session by `CONNMARK'.
2751 + If you want to compile it as a module, say M here and read
2752 + Documentation/modules.txt. The module will be called
2753 + ipt_connmark.o. If unsure, say `N'.
2755 +config IP_NF_TARGET_IPMARK
2756 + tristate 'IPMARK target support'
2757 + depends on IP_NF_MANGLE
2759 + This option adds a `IPMARK' target, which allows you to create rules
2760 + in the `mangle' table which alter the netfilter mark (nfmark) field
2761 + basing on the source or destination ip address of the packet.
2762 + This is very useful for very fast massive mangling and marking.
2764 + If you want to compile it as a module, say M here and read
2765 + <file:Documentation/modules.txt>. If unsure, say `N'.
2767 +config IP_NF_TARGET_ROUTE
2768 + tristate 'ROUTE target support'
2769 + depends on IP_NF_MANGLE
2771 + This option adds a `ROUTE' target, which enables you to setup unusual
2772 + routes. For example, the ROUTE lets you route a received packet through
2773 + an interface or towards a host, even if the regular destination of the
2774 + packet is the router itself. The ROUTE target is also able to change the
2775 + incoming interface of a packet.
2777 + The target can be or not a final target. It has to be used inside the
2780 + If you want to compile it as a module, say M here and read
2781 + Documentation/modules.txt. The module will be called ipt_ROUTE.o.
2782 + If unsure, say `N'.
2784 +config IP_NF_TARGET_TARPIT
2785 + tristate 'TARPIT target support'
2786 + depends on IP_NF_FILTER
2788 + Adds a TARPIT target to iptables, which captures and holds
2789 + incoming TCP connections using no local per-connection resources.
2790 + Connections are accepted, but immediately switched to the persist
2791 + state (0 byte window), in which the remote side stops sending data
2792 + and asks to continue every 60-240 seconds. Attempts to close the
2793 + connection are ignored, forcing the remote side to time out the
2794 + connection in 12-24 minutes.
2796 + This offers similar functionality to LaBrea
2797 + <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
2798 + hardware or IPs. Any TCP port that you would normally DROP or REJECT
2799 + can instead become a tarpit.
2801 +config IP_NF_TARGET_TRACE
2802 + tristate 'TRACE target support'
2803 + depends on IP_NF_RAW
2805 + The TRACE target allows packets to be traced as those
2806 + matches any subsequent rule in any table/rule. The matched
2807 + rule and the packet is logged with the prefix
2809 + TRACE: tablename/chainname/rulenum
2811 + If you want to compile it as a module, say M here and read
2812 + <file:Documentation/modules.txt>. If unsure, say `N'.
2814 +config IP_NF_TARGET_XOR
2815 + tristate 'XOR target support'
2816 + depends on IP_NF_MANGLE
2818 + This option adds a `XOR' target, which can encrypt TCP and
2819 + UDP traffic using a simple XOR encryption.
2821 + If you want to compile it as a module, say M here and read
2822 + Documentation/modules.txt. If unsure, say `N'.
2825 + tristate 'Eggdrop bot support'
2826 + depends on IP_NF_CONNTRACK
2828 + If you are running an eggdrop hub bot on this machine, then you
2829 + may want to enable this feature. This enables eggdrop bots to share
2830 + their user file to other eggdrop bots.
2832 + If you want to compile it as a module, say M here and read
2833 + Documentation/modules.txt. If unsure, say `N'.
2835 +config IP_NF_NAT_H323
2837 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2838 + default IP_NF_NAT if IP_NF_H323=y
2839 + default m if IP_NF_H323=m
2842 + tristate 'H.323 (netmeeting) support'
2843 + depends on IP_NF_CONNTRACK
2845 + H.323 is a standard signalling protocol used by teleconferencing
2846 + softwares like netmeeting. With the ip_conntrack_h323 and
2847 + the ip_nat_h323 modules you can support the protocol on a connection
2848 + tracking/NATing firewall.
2850 + If you want to compile it as a module, say 'M' here and read
2851 + Documentation/modules.txt. If unsure, say 'N'.
2853 +config IP_NF_NAT_MMS
2855 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2856 + default IP_NF_NAT if IP_NF_MMS=y
2857 + default m if IP_NF_MMS=m
2860 + tristate 'MMS protocol support'
2861 + depends on IP_NF_CONNTRACK
2863 + Tracking MMS (Microsoft Windows Media Services) connections
2864 + could be problematic if random ports are used to send the
2865 + streaming content. This option allows users to track streaming
2866 + connections over random UDP or TCP ports.
2868 + If you want to compile it as a module, say M here and read
2869 + <file:Documentation/modules.txt>. If unsure, say `Y'.
2871 +config IP_NF_NAT_QUAKE3
2873 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
2874 + default IP_NF_NAT if IP_NF_QUAKE3=y
2875 + default m if IP_NF_QUAKE3=m
2877 +config IP_NF_QUAKE3
2878 + tristate "Quake3 protocol support"
2879 + depends on IP_NF_CONNTRACK
2881 + Quake III Arena connection tracking helper. This module allows for a
2882 + stricter firewall rulebase if one only allows traffic to a master
2883 + server. Connections to Quake III server IP addresses and ports returned
2884 + by the master server will be tracked automatically.
2886 + If you want to compile it as a module, say M here and read
2887 + <file:Documentation/modules.txt>. If unsure, say `Y'.
2889 +config IP_NF_MATCH_POLICY
2890 + tristate "IPsec policy match support"
2891 + depends on IP_NF_IPTABLES && XFRM
2893 + Policy matching allows you to match packets based on the
2894 + IPsec policy that was used during decapsulation/will
2895 + be used during encapsulation.
2897 + To compile it as a module, choose M here. If unsure, say N.
2900 + tristate 'RSH protocol support'
2901 + depends on IP_NF_CONNTRACK
2903 + The RSH connection tracker is required if the dynamic
2904 + stderr "Server to Client" connection is to occur during a
2905 + normal RSH session. This typically operates as follows;
2907 + Client 0:1023 --> Server 514 (stream 1 - stdin/stdout)
2908 + Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
2910 + This connection tracker will identify new RSH sessions,
2911 + extract the outbound session details, and notify netfilter
2912 + of pending "related" sessions.
2914 + Warning: This module could be dangerous. It is not "best
2915 + practice" to use RSH, use SSH in all instances.
2916 + (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
2919 + If you want to compile it as a module, say M here and read
2920 + <file:Documentation/modules.txt>. If unsure, say `N'.
2922 +config IP_NF_NAT_RTSP
2924 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2925 + default IP_NF_NAT if IP_NF_RTSP=y
2926 + default m if IP_NF_RTSP=m
2929 + tristate ' RTSP protocol support'
2930 + depends on IP_NF_CONNTRACK
2932 + Support the RTSP protocol. This allows UDP transports to be setup
2933 + properly, including RTP and RDT.
2935 + If you want to compile it as a module, say 'M' here and read
2936 + Documentation/modules.txt. If unsure, say 'Y'.
2938 +config IP_NF_CT_PROTO_SCTP
2939 + tristate 'SCTP protocol connection tracking support'
2940 + depends on IP_NF_CONNTRACK
2942 +config IP_NF_MATCH_STRING
2943 + tristate 'String match support'
2944 + depends on IP_NF_IPTABLES
2946 + String matching alows you to match packets which contain a
2947 + specified string of characters.
2949 + If you want to compile it as a module, say M here and read
2950 + Documentation/modules.txt. If unsure, say `N'.
2952 +config IP_NF_NAT_TALK
2954 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2955 + default IP_NF_NAT if IP_NF_TALK=y
2956 + default m if IP_NF_TALK=m
2959 + tristate 'talk protocol support'
2960 + depends on IP_NF_CONNTRACK
2962 + The talk protocols (both otalk/talk - or talk/ntalk, to confuse
2963 + you by the different namings about which is old or which is new :-)
2964 + use an additional channel to setup the talk session and a separated
2965 + data channel for the actual conversation (like in FTP). Both the
2966 + initiating and the setup channels are over UDP, while the data channel
2967 + is over TCP, on a random port. The conntrack part of this extension
2968 + will enable you to let in/out talk sessions easily by matching these
2969 + connections as RELATED by the state match, while the NAT part helps
2970 + you to let talk sessions trough a NAT machine.
2972 + If you want to compile it as a module, say 'M' here and read
2973 + Documentation/modules.txt. If unsure, say 'N'.
2977 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Makefile linux-2.6.7/net/ipv4/netfilter/Makefile
2978 --- linux-2.6.7.org/net/ipv4/netfilter/Makefile 2004-06-25 10:47:45.000000000 +0200
2979 +++ linux-2.6.7/net/ipv4/netfilter/Makefile 2004-06-25 12:28:43.706897576 +0200
2981 # connection tracking
2982 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
2984 +# talk protocol support
2985 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
2986 +ifdef CONFIG_IP_NF_TALK
2987 + export-objs += ip_conntrack_talk.o
2989 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
2992 +# SCTP protocol connection tracking
2993 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
2996 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
2997 +ifdef CONFIG_IP_NF_H323
2998 + export-objs += ip_conntrack_h323.o
3000 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
3003 # connection tracking helpers
3005 +# rtsp protocol support
3006 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
3007 +ifdef CONFIG_IP_NF_NAT_RTSP
3008 + export-objs += ip_conntrack_rtsp.o
3010 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
3012 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
3013 +ifdef CONFIG_IP_NF_NAT_QUAKE3
3014 + export-objs += ip_conntrack_quake3.o
3016 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
3017 +ifdef CONFIG_IP_NF_MMS
3018 + export-objs += ip_conntrack_mms.o
3020 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
3021 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
3022 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
3023 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
3025 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
3027 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
3031 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
3032 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
3033 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
3034 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
3035 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
3038 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
3041 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
3042 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
3043 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
3044 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
3045 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
3046 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
3047 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
3048 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
3049 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
3051 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
3052 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
3054 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
3056 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
3057 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
3058 +obj-$(CONFIG_IP_NF_MATCH_ACCOUNT) += ipt_account.o
3060 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
3063 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
3065 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
3067 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
3070 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
3072 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
3075 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
3077 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
3079 @@ -60,30 +126,46 @@
3081 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
3083 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
3086 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
3087 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
3088 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
3089 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
3090 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
3091 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
3092 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
3093 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
3094 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
3096 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
3097 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
3100 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
3101 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
3102 obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
3103 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
3104 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
3105 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
3106 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
3107 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
3108 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
3109 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
3110 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
3111 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
3112 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
3113 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
3114 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
3115 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
3116 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
3117 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
3118 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
3119 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
3120 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
3121 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
3122 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
3123 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
3125 # generic ARP tables
3126 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c
3127 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-25 10:47:45.000000000 +0200
3128 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-25 12:21:25.558506256 +0200
3130 static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
3131 struct list_head *ip_conntrack_hash;
3132 static kmem_cache_t *ip_conntrack_cachep;
3133 +static kmem_cache_t *ip_conntrack_expect_cachep;
3134 struct ip_conntrack ip_conntrack_untracked;
3136 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
3137 @@ -127,11 +128,11 @@
3141 -get_tuple(const struct iphdr *iph,
3142 - const struct sk_buff *skb,
3143 - unsigned int dataoff,
3144 - struct ip_conntrack_tuple *tuple,
3145 - const struct ip_conntrack_protocol *protocol)
3146 +ip_ct_get_tuple(const struct iphdr *iph,
3147 + const struct sk_buff *skb,
3148 + unsigned int dataoff,
3149 + struct ip_conntrack_tuple *tuple,
3150 + const struct ip_conntrack_protocol *protocol)
3153 if (iph->frag_off & htons(IP_OFFSET)) {
3154 @@ -147,10 +148,10 @@
3155 return protocol->pkt_to_tuple(skb, dataoff, tuple);
3159 -invert_tuple(struct ip_conntrack_tuple *inverse,
3160 - const struct ip_conntrack_tuple *orig,
3161 - const struct ip_conntrack_protocol *protocol)
3163 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
3164 + const struct ip_conntrack_tuple *orig,
3165 + const struct ip_conntrack_protocol *protocol)
3167 inverse->src.ip = orig->dst.ip;
3168 inverse->dst.ip = orig->src.ip;
3170 IP_NF_ASSERT(atomic_read(&exp->use) == 0);
3171 IP_NF_ASSERT(!timer_pending(&exp->timeout));
3174 + kmem_cache_free(ip_conntrack_expect_cachep, exp);
3177 inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
3179 list_del(&ct->master->expected_list);
3180 master = ct->master->expectant;
3182 - kfree(ct->master);
3183 + kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
3185 WRITE_UNLOCK(&ip_conntrack_lock);
3187 @@ -496,83 +497,6 @@
3191 -/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
3192 -struct ip_conntrack *
3193 -icmp_error_track(struct sk_buff *skb,
3194 - enum ip_conntrack_info *ctinfo,
3195 - unsigned int hooknum)
3197 - struct ip_conntrack_tuple innertuple, origtuple;
3199 - struct icmphdr icmp;
3202 - struct ip_conntrack_protocol *innerproto;
3203 - struct ip_conntrack_tuple_hash *h;
3206 - IP_NF_ASSERT(skb->nfct == NULL);
3208 - /* Not enough header? */
3209 - if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
3212 - if (inside.icmp.type != ICMP_DEST_UNREACH
3213 - && inside.icmp.type != ICMP_SOURCE_QUENCH
3214 - && inside.icmp.type != ICMP_TIME_EXCEEDED
3215 - && inside.icmp.type != ICMP_PARAMETERPROB
3216 - && inside.icmp.type != ICMP_REDIRECT)
3219 - /* Ignore ICMP's containing fragments (shouldn't happen) */
3220 - if (inside.ip.frag_off & htons(IP_OFFSET)) {
3221 - DEBUGP("icmp_error_track: fragment of proto %u\n",
3222 - inside.ip.protocol);
3226 - innerproto = ip_ct_find_proto(inside.ip.protocol);
3227 - dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
3228 - /* Are they talking about one of our connections? */
3229 - if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
3230 - DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
3234 - /* Ordinarily, we'd expect the inverted tupleproto, but it's
3235 - been preserved inside the ICMP. */
3236 - if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
3237 - DEBUGP("icmp_error_track: Can't invert tuple\n");
3241 - *ctinfo = IP_CT_RELATED;
3243 - h = ip_conntrack_find_get(&innertuple, NULL);
3245 - /* Locally generated ICMPs will match inverted if they
3246 - haven't been SNAT'ed yet */
3247 - /* FIXME: NAT code has to handle half-done double NAT --RR */
3248 - if (hooknum == NF_IP_LOCAL_OUT)
3249 - h = ip_conntrack_find_get(&origtuple, NULL);
3252 - DEBUGP("icmp_error_track: no match\n");
3255 - /* Reverse direction from that found */
3256 - if (DIRECTION(h) != IP_CT_DIR_REPLY)
3257 - *ctinfo += IP_CT_IS_REPLY;
3259 - if (DIRECTION(h) == IP_CT_DIR_REPLY)
3260 - *ctinfo += IP_CT_IS_REPLY;
3263 - /* Update skb to refer to this connection */
3264 - skb->nfct = &h->ctrack->infos[*ctinfo];
3268 /* There's a small race here where we may free a just-assured
3269 connection. Too bad: we're in trouble anyway. */
3270 static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
3275 - if (!invert_tuple(&repl_tuple, tuple, protocol)) {
3276 + if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
3277 DEBUGP("Can't invert tuple.\n");
3280 @@ -693,41 +617,51 @@
3281 struct ip_conntrack_expect *, tuple);
3282 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3284 - /* If master is not in hash table yet (ie. packet hasn't left
3285 - this machine yet), how can other end know about expected?
3286 - Hence these are not the droids you are looking for (if
3287 - master ct never got confirmed, we'd hold a reference to it
3288 - and weird things would happen to future packets). */
3289 - if (expected && !is_confirmed(expected->expectant))
3292 - /* Look up the conntrack helper for master connections only */
3294 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
3296 + /* If master is not in hash table yet (ie. packet hasn't left
3297 + this machine yet), how can other end know about expected?
3298 + Hence these are not the droids you are looking for (if
3299 + master ct never got confirmed, we'd hold a reference to it
3300 + and weird things would happen to future packets). */
3301 + if (!is_confirmed(expected->expectant)) {
3302 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3306 - /* If the expectation is dying, then this is a loser. */
3308 - && expected->expectant->helper->timeout
3309 - && ! del_timer(&expected->timeout))
3311 + /* Expectation is dying... */
3312 + if (expected->expectant->helper->timeout
3313 + && !del_timer(&expected->timeout))
3317 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3318 conntrack, expected);
3319 /* Welcome, Mr. Bond. We've been expecting you... */
3320 + IP_NF_ASSERT(master_ct(conntrack));
3321 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3322 conntrack->master = expected;
3323 expected->sibling = conntrack;
3324 +#if CONFIG_IP_NF_CONNTRACK_MARK
3325 + conntrack->mark = expected->expectant->mark;
3327 LIST_DELETE(&ip_conntrack_expect_list, expected);
3328 expected->expectant->expecting--;
3329 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3331 - atomic_inc(&ip_conntrack_count);
3333 + /* this is a braindead... --pablo */
3334 + atomic_inc(&ip_conntrack_count);
3335 + WRITE_UNLOCK(&ip_conntrack_lock);
3337 + if (expected->expectfn)
3338 + expected->expectfn(conntrack);
3342 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
3344 +end: atomic_inc(&ip_conntrack_count);
3345 WRITE_UNLOCK(&ip_conntrack_lock);
3347 - if (expected && expected->expectfn)
3348 - expected->expectfn(conntrack);
3349 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3350 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3353 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3356 IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
3358 - if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
3359 + if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,
3363 /* look for tuple match */
3364 @@ -828,10 +763,12 @@
3366 proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
3368 - /* It may be an icmp error... */
3369 - if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
3370 - && icmp_error_track(*pskb, &ctinfo, hooknum))
3372 + /* It may be an special packet, error, unclean...
3373 + * inverse of the return code tells to the netfilter
3374 + * core what to do with the packet. */
3375 + if (proto->error != NULL
3376 + && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0)
3379 if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
3380 /* Not valid part of a connection */
3382 int invert_tuplepr(struct ip_conntrack_tuple *inverse,
3383 const struct ip_conntrack_tuple *orig)
3385 - return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
3386 + return ip_ct_invert_tuple(inverse, orig,
3387 + ip_ct_find_proto(orig->dst.protonum));
3390 static inline int resent_expect(const struct ip_conntrack_expect *i,
3392 ip_conntrack_expect_alloc(void)
3394 struct ip_conntrack_expect *new;
3396 - new = (struct ip_conntrack_expect *)
3397 - kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
3399 + new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
3401 DEBUGP("expect_related: OOM allocating expect\n");
3405 /* tuple_cmp compares whole union, we have to initialized cleanly */
3406 memset(new, 0, sizeof(struct ip_conntrack_expect));
3407 + atomic_set(&new->use, 1);
3412 DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
3413 new->expectant = related_to;
3414 new->sibling = NULL;
3415 - atomic_set(&new->use, 1);
3417 /* add to expected list for this connection */
3418 list_add_tail(&new->expected_list, &related_to->sibling_list);
3422 WRITE_UNLOCK(&ip_conntrack_lock);
3424 + /* This expectation is not inserted so no need to lock */
3425 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
3428 } else if (related_to->helper->max_expected &&
3429 @@ -1015,7 +953,7 @@
3430 related_to->helper->name,
3431 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
3432 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3434 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
3437 DEBUGP("ip_conntrack: max number of expected "
3438 @@ -1049,7 +987,7 @@
3439 WRITE_UNLOCK(&ip_conntrack_lock);
3440 DEBUGP("expect_related: busy!\n");
3443 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
3447 @@ -1368,6 +1306,7 @@
3450 kmem_cache_destroy(ip_conntrack_cachep);
3451 + kmem_cache_destroy(ip_conntrack_expect_cachep);
3452 vfree(ip_conntrack_hash);
3453 nf_unregister_sockopt(&so_getorigdst);
3455 @@ -1420,6 +1359,15 @@
3456 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
3460 + ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
3461 + sizeof(struct ip_conntrack_expect),
3462 + 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
3463 + if (!ip_conntrack_expect_cachep) {
3464 + printk(KERN_ERR "Unable to create ip_expect slab cache\n");
3465 + goto err_free_conntrack_slab;
3468 /* Don't NEED lock here, but good form anyway. */
3469 WRITE_LOCK(&ip_conntrack_lock);
3470 /* Sew in builtin protocols. */
3471 @@ -1447,6 +1395,8 @@
3475 +err_free_conntrack_slab:
3476 + kmem_cache_destroy(ip_conntrack_cachep);
3478 vfree(ip_conntrack_hash);
3480 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_egg.c
3481 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3482 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_egg.c 2004-06-25 12:21:33.570288280 +0200
3484 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3485 + * based on ip_conntrack_irc.c
3487 + * This module only supports the share userfile-send command,
3488 + * used by eggdrops to share it's userfile.
3490 + * There are no support for NAT at the moment.
3492 + * This program is free software; you can redistribute it and/or
3493 + * modify it under the terms of the GNU General Public License
3494 + * as published by the Free Software Foundation; either version
3495 + * 2 of the License, or (at your option) any later version.
3497 + * Module load syntax:
3499 + * please give the ports of all Eggdrops You have running
3500 + * on your system, the default port is 3333.
3502 + * 2001-04-19: Security update. IP addresses are now compared
3503 + * to prevent unauthorized "related" access.
3505 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3506 + * Port to netfilter 'newnat' API.
3509 +#include <linux/module.h>
3510 +#include <linux/netfilter.h>
3511 +#include <linux/ip.h>
3512 +#include <net/checksum.h>
3513 +#include <net/tcp.h>
3515 +#include <linux/netfilter_ipv4/lockhelp.h>
3516 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3518 +#define MAX_PORTS 8
3519 +static int ports[MAX_PORTS];
3520 +static int ports_c = 0;
3521 +static unsigned int egg_timeout = 300;
3523 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3524 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3525 +MODULE_LICENSE("GPL");
3527 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3528 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3531 +DECLARE_LOCK(ip_egg_lock);
3532 +struct module *ip_conntrack_egg = THIS_MODULE;
3535 +#define DEBUGP printk
3537 +#define DEBUGP(format, args...)
3540 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3541 +/* tries to get the ip_addr and port out of a eggdrop command
3542 + return value: -1 on failure, 0 on success
3543 + data pointer to first byte of DCC command data
3544 + data_end pointer to last byte of dcc command data
3545 + ip returns parsed ip of dcc command
3546 + port returns parsed port of dcc command */
3548 + if (data > data_end)
3551 + *ip = simple_strtoul(data, &data, 10);
3553 + /* skip blanks between ip and port */
3554 + while (*data == ' ' && data < data_end)
3557 + *port = simple_strtoul(data, &data, 10);
3562 +static int help(const struct iphdr *iph, size_t len,
3563 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3565 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3566 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3567 + char *data = (char *) tcph + tcph->doff * 4;
3569 + u_int32_t tcplen = len - iph->ihl * 4;
3570 + u_int32_t datalen = tcplen - tcph->doff * 4;
3571 + int dir = CTINFO2DIR(ctinfo);
3572 + int bytes_scanned = 0;
3573 + struct ip_conntrack_expect exp;
3576 + u_int16_t egg_port;
3578 + DEBUGP("entered\n");
3580 + /* If packet is coming from IRC server */
3581 + if (dir != IP_CT_DIR_REPLY)
3584 + /* Until there's been traffic both ways, don't look in packets. */
3585 + if (ctinfo != IP_CT_ESTABLISHED
3586 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3587 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
3591 + /* Not whole TCP header? */
3592 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3593 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3597 + /* Checksum invalid? Ignore. */
3598 + /* FIXME: Source route IP option packets --RR */
3599 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3600 + csum_partial((char *) tcph, tcplen, 0))) {
3601 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3602 + tcph, tcplen, NIPQUAD(iph->saddr),
3603 + NIPQUAD(iph->daddr));
3607 + data_limit = (char *) data + datalen;
3608 + while (datalen > 5 && bytes_scanned < 128) {
3609 + if (memcmp(data, "s us ", 5)) {
3618 + DEBUGP("Userfile-share found in connection "
3619 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3620 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3622 + if (parse_command((char *) data, data_limit, &egg_ip,
3624 + DEBUGP("no data in userfile-share pkt\n");
3628 + memset(&exp, 0, sizeof(exp));
3630 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3631 + if (net_ratelimit())
3632 + printk("Forged Eggdrop command from "
3633 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3634 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3635 + HIPQUAD(egg_ip), egg_port);
3639 + exp.tuple.src.ip = iph->daddr;
3640 + exp.tuple.src.u.tcp.port = 0;
3641 + exp.tuple.dst.ip = htonl(egg_ip);
3642 + exp.tuple.dst.u.tcp.port = htons(egg_port);
3643 + exp.tuple.dst.protonum = IPPROTO_TCP;
3645 + exp.mask.dst.u.tcp.port = 0xffff;
3646 + exp.mask.dst.protonum = 0xffff;
3648 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3649 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3650 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3652 + ip_conntrack_expect_related(&exp, ct);
3658 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3659 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3661 +static void deregister_helpers(void) {
3664 + for (i = 0; i < ports_c; i++) {
3665 + DEBUGP("unregistering helper for port %d\n", ports[i]);
3666 + ip_conntrack_helper_unregister(&egg_helpers[i]);
3670 +static int __init init(void)
3675 + /* If no port given, default to standard eggdrop port */
3676 + if (ports[0] == 0)
3679 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3680 + memset(&egg_helpers[i], 0,
3681 + sizeof(struct ip_conntrack_helper));
3682 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3683 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3684 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3685 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
3686 + egg_helpers[i].max_expected = 1;
3687 + egg_helpers[i].timeout = egg_timeout;
3688 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3689 + egg_helpers[i].me = THIS_MODULE;
3690 + egg_helpers[i].help = help;
3692 + tmpname = &egg_names[i][0];
3693 + if (ports[i] == 3333)
3694 + sprintf(tmpname, "eggdrop");
3696 + sprintf(tmpname, "eggdrop-%d", ports[i]);
3697 + egg_helpers[i].name = tmpname;
3699 + DEBUGP("port #%d: %d\n", i, ports[i]);
3701 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
3704 + printk("ip_conntrack_egg: ERROR registering helper "
3705 + "for port %d\n", ports[i]);
3706 + deregister_helpers();
3714 +static void __exit fini(void)
3716 + deregister_helpers();
3721 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_h323.c
3722 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3723 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_h323.c 2004-06-25 12:21:34.916083688 +0200
3726 + * H.323 'brute force' extension for H.323 connection tracking.
3727 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3729 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3730 + * (http://www.coritel.it/projects/sofia/nat/)
3731 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3732 + * the unregistered helpers to the conntrack entries.
3736 +#include <linux/module.h>
3737 +#include <linux/netfilter.h>
3738 +#include <linux/ip.h>
3739 +#include <net/checksum.h>
3740 +#include <net/tcp.h>
3742 +#include <linux/netfilter_ipv4/lockhelp.h>
3743 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3744 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3745 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3746 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3747 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3749 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3750 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3751 +MODULE_LICENSE("GPL");
3753 +DECLARE_LOCK(ip_h323_lock);
3754 +struct module *ip_conntrack_h323 = THIS_MODULE;
3757 +#define DEBUGP printk
3759 +#define DEBUGP(format, args...)
3762 +/* FIXME: This should be in userspace. Later. */
3763 +static int h245_help(const struct iphdr *iph, size_t len,
3764 + struct ip_conntrack *ct,
3765 + enum ip_conntrack_info ctinfo)
3767 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3768 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3769 + unsigned char *data_limit;
3770 + u_int32_t tcplen = len - iph->ihl * 4;
3771 + u_int32_t datalen = tcplen - tcph->doff * 4;
3772 + int dir = CTINFO2DIR(ctinfo);
3773 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3774 + struct ip_conntrack_expect expect, *exp = &expect;
3775 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3776 + u_int16_t data_port;
3777 + u_int32_t data_ip;
3780 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3781 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3782 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3784 + /* Can't track connections formed before we registered */
3788 + /* Until there's been traffic both ways, don't look in packets. */
3789 + if (ctinfo != IP_CT_ESTABLISHED
3790 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3791 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3795 + /* Not whole TCP header or too short packet? */
3796 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3797 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3801 + /* Checksum invalid? Ignore. */
3802 + /* FIXME: Source route IP option packets --RR */
3803 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3804 + csum_partial((char *)tcph, tcplen, 0))) {
3805 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3806 + tcph, tcplen, NIPQUAD(iph->saddr),
3807 + NIPQUAD(iph->daddr));
3811 + data_limit = (unsigned char *) data + datalen;
3814 + for (i = 0; data < (data_limit - 5); data++, i++) {
3815 + data_ip = *((u_int32_t *)data);
3816 + if (data_ip == iph->saddr) {
3817 + data_port = *((u_int16_t *)(data + 4));
3818 + memset(&expect, 0, sizeof(expect));
3819 + /* update the H.225 info */
3820 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3821 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3822 + NIPQUAD(iph->saddr), ntohs(data_port));
3823 + LOCK_BH(&ip_h323_lock);
3824 + info->is_h225 = H225_PORT + 1;
3825 + exp_info->port = data_port;
3826 + exp_info->dir = dir;
3827 + exp_info->offset = i;
3829 + exp->seq = ntohl(tcph->seq) + i;
3831 + exp->tuple = ((struct ip_conntrack_tuple)
3832 + { { ct->tuplehash[!dir].tuple.src.ip,
3835 + { .tcp = { data_port } },
3837 + exp->mask = ((struct ip_conntrack_tuple)
3838 + { { 0xFFFFFFFF, { 0 } },
3839 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3841 + exp->expectfn = NULL;
3843 + /* Ignore failure; should only happen with NAT */
3844 + ip_conntrack_expect_related(exp, ct);
3846 + UNLOCK_BH(&ip_h323_lock);
3854 +/* H.245 helper is not registered! */
3855 +static struct ip_conntrack_helper h245 =
3857 + "H.245", /* name */
3858 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3859 + NULL, /* module */
3860 + 8, /* max_ expected */
3861 + 240, /* timeout */
3862 + { { 0, { 0 } }, /* tuple */
3863 + { 0, { 0 }, IPPROTO_TCP } },
3864 + { { 0, { 0xFFFF } }, /* mask */
3865 + { 0, { 0 }, 0xFFFF } },
3866 + h245_help /* helper */
3869 +static int h225_expect(struct ip_conntrack *ct)
3871 + WRITE_LOCK(&ip_conntrack_lock);
3872 + ct->helper = &h245;
3873 + DEBUGP("h225_expect: helper for %p added\n", ct);
3874 + WRITE_UNLOCK(&ip_conntrack_lock);
3876 + return NF_ACCEPT; /* unused */
3879 +/* FIXME: This should be in userspace. Later. */
3880 +static int h225_help(const struct iphdr *iph, size_t len,
3881 + struct ip_conntrack *ct,
3882 + enum ip_conntrack_info ctinfo)
3884 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3885 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3886 + unsigned char *data_limit;
3887 + u_int32_t tcplen = len - iph->ihl * 4;
3888 + u_int32_t datalen = tcplen - tcph->doff * 4;
3889 + int dir = CTINFO2DIR(ctinfo);
3890 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3891 + struct ip_conntrack_expect expect, *exp = &expect;
3892 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3893 + u_int16_t data_port;
3894 + u_int32_t data_ip;
3897 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3898 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3899 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3901 + /* Can't track connections formed before we registered */
3905 + /* Until there's been traffic both ways, don't look in packets. */
3906 + if (ctinfo != IP_CT_ESTABLISHED
3907 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3908 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3912 + /* Not whole TCP header or too short packet? */
3913 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3914 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3918 + /* Checksum invalid? Ignore. */
3919 + /* FIXME: Source route IP option packets --RR */
3920 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3921 + csum_partial((char *)tcph, tcplen, 0))) {
3922 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3923 + tcph, tcplen, NIPQUAD(iph->saddr),
3924 + NIPQUAD(iph->daddr));
3928 + data_limit = (unsigned char *) data + datalen;
3931 + for (i = 0; data < (data_limit - 5); data++, i++) {
3932 + data_ip = *((u_int32_t *)data);
3933 + if (data_ip == iph->saddr) {
3934 + data_port = *((u_int16_t *)(data + 4));
3935 + if (data_port == tcph->source) {
3936 + /* Signal address */
3937 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3938 + NIPQUAD(iph->saddr));
3939 + /* Update the H.225 info so that NAT can mangle the address/port
3940 + even when we have no expected connection! */
3941 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3942 + LOCK_BH(&ip_h323_lock);
3944 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3945 + info->offset[IP_CT_DIR_ORIGINAL] = i;
3946 + UNLOCK_BH(&ip_h323_lock);
3949 + memset(&expect, 0, sizeof(expect));
3951 + /* update the H.225 info */
3952 + LOCK_BH(&ip_h323_lock);
3953 + info->is_h225 = H225_PORT;
3954 + exp_info->port = data_port;
3955 + exp_info->dir = dir;
3956 + exp_info->offset = i;
3958 + exp->seq = ntohl(tcph->seq) + i;
3960 + exp->tuple = ((struct ip_conntrack_tuple)
3961 + { { ct->tuplehash[!dir].tuple.src.ip,
3964 + { .tcp = { data_port } },
3966 + exp->mask = ((struct ip_conntrack_tuple)
3967 + { { 0xFFFFFFFF, { 0 } },
3968 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3970 + exp->expectfn = h225_expect;
3972 + /* Ignore failure */
3973 + ip_conntrack_expect_related(exp, ct);
3975 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3976 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3977 + NIPQUAD(iph->saddr), ntohs(data_port));
3979 + UNLOCK_BH(&ip_h323_lock);
3981 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3982 + } else if (data_ip == iph->daddr) {
3983 + data_port = *((u_int16_t *)(data + 4));
3984 + if (data_port == tcph->dest) {
3985 + /* Signal address */
3986 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3987 + NIPQUAD(iph->daddr));
3988 + /* Update the H.225 info so that NAT can mangle the address/port
3989 + even when we have no expected connection! */
3990 + LOCK_BH(&ip_h323_lock);
3992 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3993 + info->offset[IP_CT_DIR_REPLY] = i;
3994 + UNLOCK_BH(&ip_h323_lock);
4004 +static struct ip_conntrack_helper h225 =
4006 + "H.225", /* name */
4007 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
4008 + THIS_MODULE, /* module */
4009 + 2, /* max_expected */
4010 + 240, /* timeout */
4011 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
4012 + { 0, { 0 }, IPPROTO_TCP } },
4013 + { { 0, { 0xFFFF } }, /* mask */
4014 + { 0, { 0 }, 0xFFFF } },
4015 + h225_help /* helper */
4018 +static int __init init(void)
4020 + return ip_conntrack_helper_register(&h225);
4023 +static void __exit fini(void)
4025 + /* Unregister H.225 helper */
4026 + ip_conntrack_helper_unregister(&h225);
4029 +EXPORT_SYMBOL(ip_h323_lock);
4033 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_mms.c
4034 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
4035 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_mms.c 2004-06-25 12:23:10.835501720 +0200
4037 +/* MMS extension for IP connection tracking
4038 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4039 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
4041 + * ip_conntrack_mms.c v0.3 2002-09-22
4043 + * This program is free software; you can redistribute it and/or
4044 + * modify it under the terms of the GNU General Public License
4045 + * as published by the Free Software Foundation; either version
4046 + * 2 of the License, or (at your option) any later version.
4048 + * Module load syntax:
4049 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
4051 + * Please give the ports of all MMS servers You wish to connect to.
4052 + * If you don't specify ports, the default will be TCP port 1755.
4054 + * More info on MMS protocol, firewalls and NAT:
4055 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
4056 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
4058 + * The SDP project people are reverse-engineering MMS:
4059 + * http://get.to/sdp
4062 +#include <linux/config.h>
4063 +#include <linux/module.h>
4064 +#include <linux/netfilter.h>
4065 +#include <linux/ip.h>
4066 +#include <linux/ctype.h>
4067 +#include <net/checksum.h>
4068 +#include <net/tcp.h>
4070 +#include <linux/netfilter_ipv4/lockhelp.h>
4071 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4072 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
4074 +DECLARE_LOCK(ip_mms_lock);
4075 +struct module *ip_conntrack_mms = THIS_MODULE;
4077 +#define MAX_PORTS 8
4078 +static int ports[MAX_PORTS];
4079 +static int ports_c;
4081 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4085 +#define DEBUGP printk
4087 +#define DEBUGP(format, args...)
4090 +EXPORT_SYMBOL(ip_mms_lock);
4092 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4093 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
4094 +MODULE_LICENSE("GPL");
4096 +/* #define isdigit(c) (c >= '0' && c <= '9') */
4098 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
4099 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
4102 + for (i = 0; i < unicode_size; ++i) {
4103 + string[i] = (char)(unicode[i]);
4105 + string[unicode_size] = 0x00;
4108 +__inline static int atoi(char *s)
4111 + while (isdigit(*s)) {
4112 + i = i*10 + *(s++) - '0';
4117 +/* convert ip address string like "192.168.0.10" to unsigned int */
4118 +__inline static u_int32_t asciiiptoi(char *s)
4120 + unsigned int i, j, k;
4122 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
4124 + for(j=0; (*(++s) != '.') && (j<3); ++j)
4131 +int parse_mms(const char *data,
4132 + const unsigned int datalen,
4133 + u_int32_t *mms_ip,
4134 + u_int16_t *mms_proto,
4135 + u_int16_t *mms_port,
4136 + char **mms_string_b,
4137 + char **mms_string_e,
4138 + char **mms_padding_e)
4140 + int unicode_size, i;
4141 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
4142 + char getlengthstring[28];
4144 + for(unicode_size=0;
4145 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
4147 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
4148 + return -1; /* out of bounds - incomplete packet */
4150 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
4151 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
4153 + /* IP address ? */
4154 + *mms_ip = asciiiptoi(tempstring+2);
4156 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
4159 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
4160 + *mms_proto = IPPROTO_TCP;
4161 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
4162 + *mms_proto = IPPROTO_UDP;
4165 + *mms_port = atoi(tempstring+7+i);
4167 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
4168 + unicode string, one to the end of the string, and one to the end
4169 + of the packet, since we must keep track of the number of bytes
4170 + between end of the unicode string and the end of packet (padding) */
4171 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
4172 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
4173 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
4178 +/* FIXME: This should be in userspace. Later. */
4179 +static int help(const struct iphdr *iph, size_t len,
4180 + struct ip_conntrack *ct,
4181 + enum ip_conntrack_info ctinfo)
4183 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
4184 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4185 + const char *data = (const char *)tcph + tcph->doff * 4;
4186 + unsigned int tcplen = len - iph->ihl * 4;
4187 + unsigned int datalen = tcplen - tcph->doff * 4;
4188 + int dir = CTINFO2DIR(ctinfo);
4189 + struct ip_conntrack_expect expect, *exp = &expect;
4190 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
4193 + u_int16_t mms_proto;
4194 + char mms_proto_string[8];
4195 + u_int16_t mms_port;
4196 + char *mms_string_b, *mms_string_e, *mms_padding_e;
4198 + /* Until there's been traffic both ways, don't look in packets. */
4199 + if (ctinfo != IP_CT_ESTABLISHED
4200 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4201 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
4205 + /* Not whole TCP header? */
4206 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
4207 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
4211 + /* Checksum invalid? Ignore. */
4212 + /* FIXME: Source route IP option packets --RR */
4213 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4214 + csum_partial((char *)tcph, tcplen, 0))) {
4215 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4216 + tcph, tcplen, NIPQUAD(iph->saddr),
4217 + NIPQUAD(iph->daddr));
4221 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
4222 + /* FIXME: There is an issue with only looking at this packet: before this packet,
4223 + the client has already sent a packet to the server with the server's hostname
4224 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
4225 + server will break the connection if this doesn't correspond to its own host
4226 + header. The client can also connect to an IP address; if it's the server's IP
4227 + address, it will not break the connection. When doing DNAT on a connection
4228 + where the client uses a server's IP address, the nat module should detect
4229 + this and change this string accordingly to the DNATed address. This should
4230 + probably be done by checking for an IP address, then storing it as a member
4231 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
4233 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
4234 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
4235 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
4236 + (u8)*(data+36), (u8)*(data+37),
4237 + (u8)*(data+38), (u8)*(data+39),
4239 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
4240 + &mms_string_b, &mms_string_e, &mms_padding_e))
4241 + if(net_ratelimit())
4242 + /* FIXME: more verbose debugging ? */
4243 + printk(KERN_WARNING
4244 + "ip_conntrack_mms: Unable to parse data payload\n");
4246 + memset(&expect, 0, sizeof(expect));
4248 + sprintf(mms_proto_string, "(%u)", mms_proto);
4249 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
4250 + mms_proto == IPPROTO_TCP ? "TCP"
4251 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
4252 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4256 + /* it's possible that the client will just ask the server to tunnel
4257 + the stream over the same TCP session (from port 1755): there's
4258 + shouldn't be a need to add an expectation in that case, but it
4259 + makes NAT packet mangling so much easier */
4260 + LOCK_BH(&ip_mms_lock);
4262 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
4264 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
4265 + exp_mms_info->len = (mms_string_e - mms_string_b);
4266 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
4267 + exp_mms_info->port = mms_port;
4269 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
4270 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
4272 + exp->tuple = ((struct ip_conntrack_tuple)
4273 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4275 + { .tcp = { (__u16) ntohs(mms_port) } },
4278 + exp->mask = ((struct ip_conntrack_tuple)
4279 + { { 0xFFFFFFFF, { 0 } },
4280 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4281 + exp->expectfn = NULL;
4282 + ip_conntrack_expect_related(&expect, ct);
4283 + UNLOCK_BH(&ip_mms_lock);
4289 +static struct ip_conntrack_helper mms[MAX_PORTS];
4290 +static char mms_names[MAX_PORTS][10];
4292 +/* Not __exit: called from init() */
4293 +static void fini(void)
4296 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4297 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
4299 + ip_conntrack_helper_unregister(&mms[i]);
4303 +static int __init init(void)
4308 + if (ports[0] == 0)
4309 + ports[0] = MMS_PORT;
4311 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4312 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
4313 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
4314 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
4315 + mms[i].mask.src.u.tcp.port = 0xFFFF;
4316 + mms[i].mask.dst.protonum = 0xFFFF;
4317 + mms[i].max_expected = 1;
4318 + mms[i].timeout = 0;
4319 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4320 + mms[i].me = THIS_MODULE;
4321 + mms[i].help = help;
4323 + tmpname = &mms_names[i][0];
4324 + if (ports[i] == MMS_PORT)
4325 + sprintf(tmpname, "mms");
4327 + sprintf(tmpname, "mms-%d", ports[i]);
4328 + mms[i].name = tmpname;
4330 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
4332 + ret = ip_conntrack_helper_register(&mms[i]);
4345 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c
4346 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-06-16 07:19:13.000000000 +0200
4347 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-06-25 12:21:02.322038736 +0200
4352 -struct ip_conntrack_protocol ip_conntrack_generic_protocol
4353 -= { { NULL, NULL }, 0, "unknown",
4354 - generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
4355 - generic_print_conntrack, packet, new, NULL, NULL, NULL };
4357 +struct ip_conntrack_protocol ip_conntrack_generic_protocol =
4360 + .name = "unknown",
4361 + .pkt_to_tuple = generic_pkt_to_tuple,
4362 + .invert_tuple = generic_invert_tuple,
4363 + .print_tuple = generic_print_tuple,
4364 + .print_conntrack = generic_print_conntrack,
4368 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
4369 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-06-16 07:18:52.000000000 +0200
4370 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-06-25 12:21:02.370031440 +0200
4372 #include <linux/netfilter.h>
4373 #include <linux/in.h>
4374 #include <linux/icmp.h>
4375 +#include <net/ip.h>
4376 +#include <net/checksum.h>
4377 +#include <linux/netfilter.h>
4378 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4379 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4380 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4382 unsigned long ip_ct_icmp_timeout = 30*HZ;
4383 @@ -122,7 +127,147 @@
4387 -struct ip_conntrack_protocol ip_conntrack_protocol_icmp
4388 -= { { NULL, NULL }, IPPROTO_ICMP, "icmp",
4389 - icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
4390 - icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
4392 +icmp_error_message(struct sk_buff *skb,
4393 + enum ip_conntrack_info *ctinfo,
4394 + unsigned int hooknum)
4396 + struct ip_conntrack_tuple innertuple, origtuple;
4398 + struct icmphdr icmp;
4401 + struct ip_conntrack_protocol *innerproto;
4402 + struct ip_conntrack_tuple_hash *h;
4405 + IP_NF_ASSERT(skb->nfct == NULL);
4407 + /* Not enough header? */
4408 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
4411 + /* Ignore ICMP's containing fragments (shouldn't happen) */
4412 + if (inside.ip.frag_off & htons(IP_OFFSET)) {
4413 + DEBUGP("icmp_error_track: fragment of proto %u\n",
4414 + inside.ip.protocol);
4418 + innerproto = ip_ct_find_proto(inside.ip.protocol);
4419 + dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
4420 + /* Are they talking about one of our connections? */
4421 + if (!ip_ct_get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
4422 + DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
4426 + /* Ordinarily, we'd expect the inverted tupleproto, but it's
4427 + been preserved inside the ICMP. */
4428 + if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
4429 + DEBUGP("icmp_error_track: Can't invert tuple\n");
4433 + *ctinfo = IP_CT_RELATED;
4435 + h = ip_conntrack_find_get(&innertuple, NULL);
4437 + /* Locally generated ICMPs will match inverted if they
4438 + haven't been SNAT'ed yet */
4439 + /* FIXME: NAT code has to handle half-done double NAT --RR */
4440 + if (hooknum == NF_IP_LOCAL_OUT)
4441 + h = ip_conntrack_find_get(&origtuple, NULL);
4444 + DEBUGP("icmp_error_track: no match\n");
4447 + /* Reverse direction from that found */
4448 + if (DIRECTION(h) != IP_CT_DIR_REPLY)
4449 + *ctinfo += IP_CT_IS_REPLY;
4451 + if (DIRECTION(h) == IP_CT_DIR_REPLY)
4452 + *ctinfo += IP_CT_IS_REPLY;
4455 + /* Update skb to refer to this connection */
4456 + skb->nfct = &h->ctrack->infos[*ctinfo];
4457 + return -NF_ACCEPT;
4460 +/* Small and modified version of icmp_rcv */
4462 +icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
4463 + unsigned int hooknum)
4465 + struct icmphdr icmph;
4467 + /* Not enough header? */
4468 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph))!=0) {
4469 + if (LOG_INVALID(IPPROTO_ICMP))
4470 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
4471 + "ip_ct_icmp: short packet ");
4472 + return -NF_ACCEPT;
4475 + /* See ip_conntrack_proto_tcp.c */
4476 + if (hooknum != NF_IP_PRE_ROUTING)
4477 + goto checksum_skipped;
4479 + switch (skb->ip_summed) {
4481 + if (!(u16)csum_fold(skb->csum))
4483 + if (LOG_INVALID(IPPROTO_ICMP))
4484 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
4485 + "ip_ct_icmp: bad HW ICMP checksum ");
4486 + return -NF_ACCEPT;
4487 + case CHECKSUM_NONE:
4488 + if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
4489 + if (LOG_INVALID(IPPROTO_ICMP))
4490 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
4491 + "ip_ct_icmp: bad ICMP checksum ");
4492 + return -NF_ACCEPT;
4500 + * 18 is the highest 'known' ICMP type. Anything else is a mystery
4502 + * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently
4505 + if (icmph.type > NR_ICMP_TYPES) {
4506 + if (LOG_INVALID(IPPROTO_ICMP))
4507 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
4508 + "ip_ct_icmp: invalid ICMP type ");
4509 + return -NF_ACCEPT;
4512 + /* Need to track icmp error message? */
4513 + if (icmph.type != ICMP_DEST_UNREACH
4514 + && icmph.type != ICMP_SOURCE_QUENCH
4515 + && icmph.type != ICMP_TIME_EXCEEDED
4516 + && icmph.type != ICMP_PARAMETERPROB
4517 + && icmph.type != ICMP_REDIRECT)
4520 + return icmp_error_message(skb, ctinfo, hooknum);
4523 +struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
4525 + .proto = IPPROTO_ICMP,
4527 + .pkt_to_tuple = icmp_pkt_to_tuple,
4528 + .invert_tuple = icmp_invert_tuple,
4529 + .print_tuple = icmp_print_tuple,
4530 + .print_conntrack = icmp_print_conntrack,
4531 + .packet = icmp_packet,
4533 + .error = icmp_error,
4535 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
4536 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
4537 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-06-25 12:24:51.924133912 +0200
4540 + * Connection tracking protocol helper module for SCTP.
4542 + * SCTP is defined in RFC 2960. References to various sections in this code
4543 + * are to this RFC.
4545 + * This program is free software; you can redistribute it and/or modify
4546 + * it under the terms of the GNU General Public License version 2 as
4547 + * published by the Free Software Foundation.
4550 +#include <linux/types.h>
4551 +#include <linux/sched.h>
4552 +#include <linux/timer.h>
4553 +#include <linux/netfilter.h>
4554 +#include <linux/module.h>
4555 +#include <linux/in.h>
4556 +#include <linux/ip.h>
4557 +#include <linux/sctp.h>
4558 +#include <linux/string.h>
4560 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4561 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4562 +#include <linux/netfilter_ipv4/lockhelp.h>
4565 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4567 +#define DEBUGP(format, args...)
4570 +/* Protects conntrack->proto.sctp */
4571 +static DECLARE_RWLOCK(sctp_lock);
4573 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4574 + closely. They're more complex. --RR
4576 + And so for me for SCTP :D -Kiran */
4578 +static const char *sctp_conntrack_names[] = {
4586 + "SHUTDOWN_ACK_SENT",
4590 +#define MINS * 60 SECS
4591 +#define HOURS * 60 MINS
4592 +#define DAYS * 24 HOURS
4594 +unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
4595 +unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
4596 +unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
4597 +unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
4598 +unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
4599 +unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
4600 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
4602 +static unsigned long * sctp_timeouts[]
4603 += { 0, /* SCTP_CONNTRACK_NONE */
4604 + &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
4605 + &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
4606 + &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
4607 + &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
4608 + &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4609 + &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4610 + &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4613 +#define sNO SCTP_CONNTRACK_NONE
4614 +#define sCL SCTP_CONNTRACK_CLOSED
4615 +#define sCW SCTP_CONNTRACK_COOKIE_WAIT
4616 +#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
4617 +#define sES SCTP_CONNTRACK_ESTABLISHED
4618 +#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4619 +#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4620 +#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4621 +#define sIV SCTP_CONNTRACK_MAX
4624 + These are the descriptions of the states:
4626 +NOTE: These state names are tantalizingly similar to the states of an
4627 +SCTP endpoint. But the interpretation of the states is a little different,
4628 +considering that these are the states of the connection and not of an end
4629 +point. Please note the subtleties. -Kiran
4631 +NONE - Nothing so far.
4632 +COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
4633 + an INIT_ACK chunk in the reply direction.
4634 +COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
4635 +ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
4636 +SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
4637 +SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
4638 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4639 + to that of the SHUTDOWN chunk.
4640 +CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
4641 + the SHUTDOWN chunk. Connection is closed.
4645 + - I have assumed that the first INIT is in the original direction.
4646 + This messes things when an INIT comes in the reply direction in CLOSED
4648 + - Check the error type in the reply dir before transitioning from
4649 +cookie echoed to closed.
4650 + - Sec 5.2.4 of RFC 2960
4651 + - Multi Homing support.
4654 +/* SCTP conntrack state transitions */
4655 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4658 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4659 +/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4660 +/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4661 +/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4662 +/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4663 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4664 +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4665 +/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4666 +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4667 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4671 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4672 +/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4673 +/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4674 +/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4675 +/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4676 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4677 +/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4678 +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4679 +/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4680 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4684 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4685 + unsigned int dataoff,
4686 + struct ip_conntrack_tuple *tuple)
4688 + sctp_sctphdr_t hdr;
4690 + DEBUGP(__FUNCTION__);
4693 + /* Actually only need first 8 bytes. */
4694 + if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4697 + tuple->src.u.sctp.port = hdr.source;
4698 + tuple->dst.u.sctp.port = hdr.dest;
4703 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4704 + const struct ip_conntrack_tuple *orig)
4706 + DEBUGP(__FUNCTION__);
4709 + tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4710 + tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4714 +/* Print out the per-protocol part of the tuple. */
4715 +static unsigned int sctp_print_tuple(char *buffer,
4716 + const struct ip_conntrack_tuple *tuple)
4718 + DEBUGP(__FUNCTION__);
4721 + return sprintf(buffer, "sport=%hu dport=%hu ",
4722 + ntohs(tuple->src.u.sctp.port),
4723 + ntohs(tuple->dst.u.sctp.port));
4726 +/* Print out the private part of the conntrack. */
4727 +static unsigned int sctp_print_conntrack(char *buffer,
4728 + const struct ip_conntrack *conntrack)
4730 + enum sctp_conntrack state;
4732 + DEBUGP(__FUNCTION__);
4735 + READ_LOCK(&sctp_lock);
4736 + state = conntrack->proto.sctp.state;
4737 + READ_UNLOCK(&sctp_lock);
4739 + return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4742 +#define for_each_sctp_chunk(skb, sch, offset, count) \
4743 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
4744 + offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
4745 + offset += (htons(sch.length) + 3) & ~3, count++)
4747 +/* Some validity checks to make sure the chunks are fine */
4748 +static int do_basic_checks(struct ip_conntrack *conntrack,
4749 + const struct sk_buff *skb,
4752 + u_int32_t offset, count;
4753 + sctp_chunkhdr_t sch;
4756 + DEBUGP(__FUNCTION__);
4761 + for_each_sctp_chunk (skb, sch, offset, count) {
4762 + DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
4764 + if (sch.type == SCTP_CID_INIT
4765 + || sch.type == SCTP_CID_INIT_ACK
4766 + || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4770 + /* Cookie Ack/Echo chunks not the first OR
4771 + Init / Init Ack / Shutdown compl chunks not the only chunks */
4772 + if ((sch.type == SCTP_CID_COOKIE_ACK
4773 + || sch.type == SCTP_CID_COOKIE_ECHO
4776 + DEBUGP("Basic checks failed\n");
4781 + set_bit (sch.type, (void *)map);
4785 + DEBUGP("Basic checks passed\n");
4789 +static int new_state(enum ip_conntrack_dir dir,
4790 + enum sctp_conntrack cur_state,
4795 + DEBUGP(__FUNCTION__);
4798 + DEBUGP("Chunk type: %d\n", chunk_type);
4800 + switch (chunk_type) {
4801 + case SCTP_CID_INIT:
4802 + DEBUGP("SCTP_CID_INIT\n");
4804 + case SCTP_CID_INIT_ACK:
4805 + DEBUGP("SCTP_CID_INIT_ACK\n");
4807 + case SCTP_CID_ABORT:
4808 + DEBUGP("SCTP_CID_ABORT\n");
4810 + case SCTP_CID_SHUTDOWN:
4811 + DEBUGP("SCTP_CID_SHUTDOWN\n");
4813 + case SCTP_CID_SHUTDOWN_ACK:
4814 + DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4816 + case SCTP_CID_ERROR:
4817 + DEBUGP("SCTP_CID_ERROR\n");
4819 + case SCTP_CID_COOKIE_ECHO:
4820 + DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4822 + case SCTP_CID_COOKIE_ACK:
4823 + DEBUGP("SCTP_CID_COOKIE_ACK\n");
4825 + case SCTP_CID_SHUTDOWN_COMPLETE:
4826 + DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4829 + /* Other chunks like DATA, SACK, HEARTBEAT and
4830 + its ACK do not cause a change in state */
4831 + DEBUGP("Unknown chunk type, Will stay in %s\n",
4832 + sctp_conntrack_names[cur_state]);
4836 + DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
4837 + dir, sctp_conntrack_names[cur_state], chunk_type,
4838 + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4840 + return sctp_conntracks[dir][i][cur_state];
4843 +/* Returns verdict for packet, or -1 for invalid. */
4844 +static int sctp_packet(struct ip_conntrack *conntrack,
4845 + const struct sk_buff *skb,
4846 + enum ip_conntrack_info ctinfo)
4848 + enum sctp_conntrack newconntrack, oldsctpstate;
4849 + sctp_sctphdr_t sctph;
4850 + sctp_chunkhdr_t sch;
4851 + u_int32_t offset, count;
4852 + char map[256 / sizeof (char)] = {0};
4854 + DEBUGP(__FUNCTION__);
4857 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4860 + if (do_basic_checks(conntrack, skb, map) != 0)
4863 + /* Check the verification tag (Sec 8.5) */
4864 + if (!test_bit(SCTP_CID_INIT, (void *)map)
4865 + && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4866 + && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4867 + && !test_bit(SCTP_CID_ABORT, (void *)map)
4868 + && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4869 + && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4870 + DEBUGP("Verification tag check failed\n");
4874 + oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4875 + for_each_sctp_chunk (skb, sch, offset, count) {
4876 + WRITE_LOCK(&sctp_lock);
4878 + /* Special cases of Verification tag check (Sec 8.5.1) */
4879 + if (sch.type == SCTP_CID_INIT) {
4880 + /* Sec 8.5.1 (A) */
4881 + if (sctph.vtag != 0) {
4882 + WRITE_UNLOCK(&sctp_lock);
4885 + } else if (sch.type == SCTP_CID_ABORT) {
4886 + /* Sec 8.5.1 (B) */
4887 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4888 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4889 + [1 - CTINFO2DIR(ctinfo)])) {
4890 + WRITE_UNLOCK(&sctp_lock);
4893 + } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4894 + /* Sec 8.5.1 (C) */
4895 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4896 + && !(sctph.vtag == conntrack->proto.sctp.vtag
4897 + [1 - CTINFO2DIR(ctinfo)]
4898 + && (sch.flags & 1))) {
4899 + WRITE_UNLOCK(&sctp_lock);
4902 + } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4903 + /* Sec 8.5.1 (D) */
4904 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4905 + WRITE_UNLOCK(&sctp_lock);
4910 + oldsctpstate = conntrack->proto.sctp.state;
4911 + newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4914 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4915 + DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4916 + CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4917 + WRITE_UNLOCK(&sctp_lock);
4921 + /* If it is an INIT or an INIT ACK note down the vtag */
4922 + if (sch.type == SCTP_CID_INIT
4923 + || sch.type == SCTP_CID_INIT_ACK) {
4924 + sctp_inithdr_t inithdr;
4926 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4927 + &inithdr, sizeof(inithdr)) != 0) {
4928 + WRITE_UNLOCK(&sctp_lock);
4931 + DEBUGP("Setting vtag %x for dir %d\n",
4932 + inithdr.init_tag, CTINFO2DIR(ctinfo));
4933 + conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4936 + conntrack->proto.sctp.state = newconntrack;
4937 + WRITE_UNLOCK(&sctp_lock);
4940 + ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4942 + if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4943 + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4944 + && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4945 + DEBUGP("Setting assured bit\n");
4946 + set_bit(IPS_ASSURED_BIT, &conntrack->status);
4952 +/* Called when a new connection for this protocol found. */
4953 +static int sctp_new(struct ip_conntrack *conntrack,
4954 + const struct sk_buff *skb)
4956 + enum sctp_conntrack newconntrack;
4957 + sctp_sctphdr_t sctph;
4958 + sctp_chunkhdr_t sch;
4959 + u_int32_t offset, count;
4960 + char map[256 / sizeof (char)] = {0};
4962 + DEBUGP(__FUNCTION__);
4965 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4968 + if (do_basic_checks(conntrack, skb, map) != 0)
4971 + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4972 + if ((test_bit (SCTP_CID_ABORT, (void *)map))
4973 + || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4974 + || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4978 + newconntrack = SCTP_CONNTRACK_MAX;
4979 + for_each_sctp_chunk (skb, sch, offset, count) {
4980 + /* Don't need lock here: this conntrack not in circulation yet */
4981 + newconntrack = new_state (IP_CT_DIR_ORIGINAL,
4982 + SCTP_CONNTRACK_NONE, sch.type);
4984 + /* Invalid: delete conntrack */
4985 + if (newconntrack == SCTP_CONNTRACK_MAX) {
4986 + DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4990 + /* Copy the vtag into the state info */
4991 + if (sch.type == SCTP_CID_INIT) {
4992 + if (sctph.vtag == 0) {
4993 + sctp_inithdr_t inithdr;
4995 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4996 + &inithdr, sizeof(inithdr)) != 0) {
5000 + DEBUGP("Setting vtag %x for new conn\n",
5001 + inithdr.init_tag);
5003 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
5006 + /* Sec 8.5.1 (A) */
5010 + /* If it is a shutdown ack OOTB packet, we expect a return
5011 + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
5013 + DEBUGP("Setting vtag %x for new conn OOTB\n",
5015 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
5018 + conntrack->proto.sctp.state = newconntrack;
5024 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
5025 + const struct sk_buff *skb)
5027 + /* To be implemented */
5031 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
5032 + .list = { NULL, NULL },
5033 + .proto = IPPROTO_SCTP,
5035 + .pkt_to_tuple = sctp_pkt_to_tuple,
5036 + .invert_tuple = sctp_invert_tuple,
5037 + .print_tuple = sctp_print_tuple,
5038 + .print_conntrack = sctp_print_conntrack,
5039 + .packet = sctp_packet,
5042 + .exp_matches_pkt = sctp_exp_matches_pkt,
5046 +int __init init(void)
5050 + ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
5051 + DEBUGP("SCTP conntrack module loading %s\n",
5052 + ret ? "failed": "succeeded");
5056 +void __exit fini(void)
5058 + ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
5059 + DEBUGP("SCTP conntrack module unloaded\n");
5065 +MODULE_LICENSE("GPL");
5066 +MODULE_AUTHOR("Kiran Kumar Immidi");
5067 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
5068 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
5069 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-06-16 07:20:25.000000000 +0200
5070 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-06-25 12:21:02.329037672 +0200
5071 @@ -268,7 +268,15 @@
5072 return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
5075 -struct ip_conntrack_protocol ip_conntrack_protocol_tcp
5076 -= { { NULL, NULL }, IPPROTO_TCP, "tcp",
5077 - tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
5078 - tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
5079 +struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
5081 + .proto = IPPROTO_TCP,
5083 + .pkt_to_tuple = tcp_pkt_to_tuple,
5084 + .invert_tuple = tcp_invert_tuple,
5085 + .print_tuple = tcp_print_tuple,
5086 + .print_conntrack = tcp_print_conntrack,
5087 + .packet = tcp_packet,
5089 + .exp_matches_pkt = tcp_exp_matches_pkt,
5091 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c
5092 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-06-16 07:18:37.000000000 +0200
5093 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-06-25 12:21:02.373030984 +0200
5095 #include <linux/netfilter.h>
5096 #include <linux/in.h>
5097 #include <linux/udp.h>
5098 +#include <net/checksum.h>
5099 +#include <linux/netfilter.h>
5100 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
5102 unsigned long ip_ct_udp_timeout = 30*HZ;
5107 -struct ip_conntrack_protocol ip_conntrack_protocol_udp
5108 -= { { NULL, NULL }, IPPROTO_UDP, "udp",
5109 - udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
5110 - udp_packet, udp_new, NULL, NULL, NULL };
5111 +static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
5112 + unsigned int hooknum)
5114 + struct iphdr *iph = skb->nh.iph;
5115 + unsigned int udplen = skb->len - iph->ihl * 4;
5116 + struct udphdr hdr;
5118 + /* Header is too small? */
5119 + if (skb_copy_bits(skb, iph->ihl*4, &hdr, sizeof(hdr)) != 0) {
5120 + if (LOG_INVALID(IPPROTO_UDP))
5121 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
5122 + "ip_ct_udp: short packet ");
5123 + return -NF_ACCEPT;
5126 + /* Truncated/malformed packets */
5127 + if (ntohs(hdr.len) > udplen || ntohs(hdr.len) < sizeof(hdr)) {
5128 + if (LOG_INVALID(IPPROTO_UDP))
5129 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
5130 + "ip_ct_udp: truncated/malformed packet ");
5131 + return -NF_ACCEPT;
5134 + /* Packet with no checksum */
5138 + /* Checksum invalid? Ignore.
5139 + * We skip checking packets on the outgoing path
5140 + * because the semantic of CHECKSUM_HW is different there
5141 + * and moreover root might send raw packets.
5142 + * FIXME: Source route IP option packets --RR */
5143 + if (hooknum == NF_IP_PRE_ROUTING
5144 + && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5145 + skb->ip_summed == CHECKSUM_HW ? skb->csum
5146 + : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
5147 + if (LOG_INVALID(IPPROTO_UDP))
5148 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
5149 + "ip_ct_udp: bad UDP checksum ");
5150 + return -NF_ACCEPT;
5156 +struct ip_conntrack_protocol ip_conntrack_protocol_udp =
5158 + .proto = IPPROTO_UDP,
5160 + .pkt_to_tuple = udp_pkt_to_tuple,
5161 + .invert_tuple = udp_invert_tuple,
5162 + .print_tuple = udp_print_tuple,
5163 + .print_conntrack = udp_print_conntrack,
5164 + .packet = udp_packet,
5166 + .error = udp_error,
5168 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_quake3.c
5169 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
5170 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-06-25 12:24:42.549559064 +0200
5172 +/* Quake3 extension for IP connection tracking
5173 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5174 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5176 + * ip_conntrack_quake3.c v0.04 2002-08-31
5178 + * This program is free software; you can redistribute it and/or
5179 + * modify it under the terms of the GNU General Public License
5180 + * as published by the Free Software Foundation; either version
5181 + * 2 of the License, or (at your option) any later version.
5183 + * Module load syntax:
5184 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5186 + * please give the ports of all Quake3 master servers You wish to
5187 + * connect to. If you don't specify ports, the default will be UDP
5190 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5193 +#include <linux/module.h>
5194 +#include <linux/ip.h>
5195 +#include <linux/udp.h>
5197 +#include <linux/netfilter.h>
5198 +#include <linux/netfilter_ipv4/ip_tables.h>
5199 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5200 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5202 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5204 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5205 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5206 +MODULE_LICENSE("GPL");
5208 +#define MAX_PORTS 8
5209 +static int ports[MAX_PORTS];
5210 +static int ports_c = 0;
5212 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5213 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5216 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5217 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5219 +#define DEBUGP printk
5221 +#define DEBUGP(format, args...)
5224 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5226 +static int quake3_help(const struct iphdr *iph, size_t len,
5227 + struct ip_conntrack *ct,
5228 + enum ip_conntrack_info ctinfo)
5230 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5231 + int dir = CTINFO2DIR(ctinfo);
5232 + struct ip_conntrack_expect exp;
5235 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5236 + if (ctinfo != IP_CT_ESTABLISHED
5237 + && ctinfo != IP_CT_IS_REPLY) {
5238 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5240 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5242 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5243 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5244 + i+6 < ntohs(udph->len);
5246 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5247 + i, ntohs(udph->len),
5248 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
5249 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5251 + memset(&exp, 0, sizeof(exp));
5253 + exp.tuple = ((struct ip_conntrack_tuple)
5254 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5255 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
5256 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
5259 + exp.mask = ((struct ip_conntrack_tuple)
5260 + { { 0xFFFFFFFF, { 0 } },
5261 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5262 + exp.expectfn = NULL;
5264 + ip_conntrack_expect_related(&exp, ct);
5269 + return(NF_ACCEPT);
5272 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5273 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
5275 +static void fini(void)
5279 + for(i = 0 ; (i < ports_c); i++) {
5280 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5282 + ip_conntrack_helper_unregister(&quake3[i]);
5286 +static int __init init(void)
5292 + ports[0]=QUAKE3_MASTER_PORT;
5294 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5295 + /* Create helper structure */
5296 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5298 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5299 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5300 + quake3[i].mask.dst.protonum = 0xFFFF;
5301 + quake3[i].mask.src.u.udp.port = 0xFFFF;
5302 + quake3[i].help = quake3_help;
5303 + quake3[i].me = THIS_MODULE;
5305 + tmpname = &quake3_names[i][0];
5306 + if (ports[i] == QUAKE3_MASTER_PORT)
5307 + sprintf(tmpname, "quake3");
5309 + sprintf(tmpname, "quake3-%d", i);
5310 + quake3[i].name = tmpname;
5312 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5315 + ret=ip_conntrack_helper_register(&quake3[i]);
5328 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rsh.c
5329 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
5330 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-06-25 12:24:48.841602528 +0200
5332 +/* RSH extension for IP connection tracking, Version 1.0
5333 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5334 + * based on HW's ip_conntrack_irc.c
5336 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
5338 + * This program is free software; you can redistribute it and/or
5339 + * modify it under the terms of the GNU General Public License
5340 + * as published by the Free Software Foundation; either version
5341 + * 2 of the License, or (at your option) any later version.
5343 + * Module load syntax:
5344 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
5346 + * please give the ports of all RSH servers You wish to connect to.
5347 + * If You don't specify ports, the default will be port 514
5350 + * RSH blows ... you should use SSH (openssh.org) to replace it,
5351 + * unfortunately I babysit some sysadmins that won't migrate
5352 + * their legacy crap, in our second tier.
5357 + * Some docco ripped from the net to teach me all there is to know about
5358 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
5361 + * I have no idea what "unix rshd man pages" these guys have .. but that
5362 + * is some pretty detailed docco!
5365 + * 4. Of the rsh protocol.
5366 + * -----------------------
5368 + * The rshd listens on TCP port #514. The following info is from the unix
5369 + * rshd man pages :
5371 + * "Service Request Protocol
5373 + * When the rshd daemon receives a service request, it initiates the
5374 + * following protocol:
5376 + * 1. The rshd daemon checks the source port number for the request.
5377 + * If the port number is not in the range 0 through 1023, the rshd daemon
5378 + * terminates the connection.
5380 + * 2. The rshd daemon reads characters from the socket up to a null byte.
5381 + * The string read is interpreted as an ASCII number (base 10). If this
5382 + * number is nonzero, the rshd daemon interprets it as the port number
5383 + * of a secondary stream to be used as standard error. A second connection
5384 + * is created to the specified port on the client host. The source port
5385 + * on the local host is in the range 0 through 1023.
5387 + * 3. The rshd daemon uses the source address of the initial connection
5388 + * request to determine the name of the client host. If the name cannot
5389 + * be determined, the rshd daemon uses the dotted decimal representation
5390 + * of the client host's address.
5392 + * 4. The rshd daemon retrieves the following information from the initial
5395 + * * A null-terminated string of at most 16 bytes interpreted as
5396 + * the user name of the user on the client host.
5398 + * * A null-terminated string of at most 16 bytes interpreted as
5399 + * the user name to be used on the local server host.
5401 + * * Another null-terminated string interpreted as a command line
5402 + * to be passed to a shell on the local server host.
5404 + * 5. The rshd daemon attempts to validate the user using the following steps:
5406 + * a. The rshd daemon looks up the local user name in the /etc/passwd
5407 + * file and tries to switch to the home directory (using the chdir
5408 + * subroutine). If either the lookup or the directory change fails,
5409 + * the rshd daemon terminates the connection.
5411 + * b. If the local user ID is a nonzero value, the rshd daemon searches
5412 + * the /etc/hosts.equiv file to see if the name of the client
5413 + * workstation is listed. If the client workstation is listed as an
5414 + * equivalent host, the rshd daemon validates the user.
5416 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
5417 + * authenticate the user by checking the .rhosts file.
5419 + * d. If either the $HOME/.rhosts authentication fails or the
5420 + * client host is not an equivalent host, the rshd daemon
5421 + * terminates the connection.
5423 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
5424 + * on the initial connection and passes the command line to the user's
5425 + * local login shell. The shell then inherits the network connections
5426 + * established by the rshd daemon."
5431 +#include <linux/module.h>
5432 +#include <linux/netfilter.h>
5433 +#include <linux/ip.h>
5434 +#include <net/checksum.h>
5435 +#include <net/tcp.h>
5437 +#include <linux/netfilter_ipv4/lockhelp.h>
5438 +#include <linux/netfilter_ipv4/ip_tables.h>
5439 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5440 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
5442 +#define MAX_PORTS 8
5443 +static int ports[MAX_PORTS];
5444 +static int ports_n_c = 0;
5446 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
5447 +MODULE_DESCRIPTION("RSH connection tracking module");
5448 +MODULE_LICENSE("GPL");
5450 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5451 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
5454 +DECLARE_LOCK(ip_rsh_lock);
5455 +struct module *ip_conntrack_rsh = THIS_MODULE;
5458 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
5461 +#define DEBUGP(format, args...)
5466 +/* FIXME: This should be in userspace. Later. */
5467 +static int help(const struct iphdr *iph, size_t len,
5468 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5470 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5471 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5472 + const char *data = (const char *) tcph + tcph->doff * 4;
5473 + u_int32_t tcplen = len - iph->ihl * 4;
5474 + int dir = CTINFO2DIR(ctinfo);
5475 + struct ip_conntrack_expect expect, *exp = &expect;
5476 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
5480 + /* note that "maxoctet" is used to maintain sanity (8 was the
5481 + * original array size used in rshd/glibc) -- is there a
5482 + * vulnerability in rshd.c in the looped port *= 10?
5486 + DEBUGP("entered\n");
5488 + /* bail if packet is not from RSH client */
5489 + if (dir == IP_CT_DIR_REPLY)
5492 + /* Until there's been traffic both ways, don't look in packets. */
5493 + if (ctinfo != IP_CT_ESTABLISHED
5494 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5495 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
5499 + /* Not whole TCP header? */
5500 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5501 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
5505 + /* Checksum invalid? Ignore. */
5506 + /* FIXME: Source route IP option packets --RR */
5507 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5508 + csum_partial((char *) tcph, tcplen, 0))) {
5509 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5510 + tcph, tcplen, NIPQUAD(iph->saddr),
5511 + NIPQUAD(iph->daddr));
5515 + /* find the rsh stderr port */
5518 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
5523 + if (*data < 48 || *data > 57) {
5524 + DEBUGP("these aren't the packets you're looking for ..\n");
5527 + port = port * 10 + ( *data - 48 );
5530 + /* dont relate sessions that try to expose the client */
5531 + DEBUGP("found port %u\n", port);
5532 + if (port > 1023) {
5533 + DEBUGP("skipping, expected port size is greater than 1023!\n");
5538 + LOCK_BH(&ip_rsh_lock);
5540 + /* new(,related) connection is;
5541 + * reply + dst (uint)port + src port (0:1023)
5543 + memset(&expect, 0, sizeof(expect));
5545 + /* save some discovered data, in case someone ever wants to write
5546 + * a NAT module for this bastard ..
5548 + exp_rsh_info->port = port;
5550 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
5553 + /* Watch out, Radioactive-Man! */
5554 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5555 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5556 + exp->tuple.src.u.tcp.port = 0;
5557 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
5558 + exp->tuple.dst.protonum = IPPROTO_TCP;
5560 + exp->mask.src.ip = 0xffffffff;
5561 + exp->mask.dst.ip = 0xffffffff;
5563 + exp->mask.src.u.tcp.port = htons(0xfc00);
5564 + exp->mask.dst.u.tcp.port = htons(0xfc00);
5565 + exp->mask.dst.protonum = 0xffff;
5567 + exp->expectfn = NULL;
5569 + ip_conntrack_expect_related(&expect, ct);
5571 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5572 + NIPQUAD(exp->tuple.src.ip),
5573 + ntohs(exp->tuple.src.u.tcp.port),
5574 + NIPQUAD(exp->tuple.dst.ip),
5575 + ntohs(exp->tuple.dst.u.tcp.port));
5577 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5578 + NIPQUAD(exp->mask.src.ip),
5579 + ntohs(exp->mask.src.u.tcp.port),
5580 + NIPQUAD(exp->mask.dst.ip),
5581 + ntohs(exp->mask.dst.u.tcp.port));
5582 + UNLOCK_BH(&ip_rsh_lock);
5587 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
5589 +static void fini(void);
5591 +static int __init init(void)
5594 + static char name[10];
5597 + /* If no port given, default to standard RSH port */
5598 + if (ports[0] == 0)
5599 + ports[0] = RSH_PORT;
5601 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5602 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5604 + if (ports[port] == RSH_PORT)
5605 + sprintf(name, "rsh");
5607 + sprintf(name, "rsh-%d", port);
5609 + rsh_helpers[port].name = name;
5610 + rsh_helpers[port].me = THIS_MODULE;
5611 + rsh_helpers[port].max_expected = 1;
5612 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5613 + rsh_helpers[port].timeout = 0;
5615 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5616 + rsh_helpers[port].mask.dst.protonum = 0xffff;
5618 + /* RSH must come from ports 0:1023 to ports[port] (514) */
5619 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
5620 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
5621 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
5623 + rsh_helpers[port].help = help;
5625 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5626 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5627 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
5628 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
5629 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
5630 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
5631 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5632 + NIPQUAD(rsh_helpers[port].mask.src.ip),
5633 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
5634 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
5635 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
5637 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
5640 + printk("ERROR registering port %d\n",
5650 +/* This function is intentionally _NOT_ defined as __exit, because
5651 + * it is needed by the init function */
5652 +static void fini(void)
5655 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5656 + DEBUGP("unregistering port %d\n", ports[port]);
5657 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
5663 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rtsp.c
5664 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
5665 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-06-25 12:24:50.032421496 +0200
5668 + * RTSP extension for IP connection tracking
5669 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5670 + * based on ip_conntrack_irc.c
5672 + * This program is free software; you can redistribute it and/or
5673 + * modify it under the terms of the GNU General Public License
5674 + * as published by the Free Software Foundation; either version
5675 + * 2 of the License, or (at your option) any later version.
5677 + * Module load syntax:
5678 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5679 + * max_outstanding=n setup_timeout=secs
5681 + * If no ports are specified, the default will be port 554.
5683 + * With max_outstanding you can define the maximum number of not yet
5684 + * answered SETUP requests per RTSP session (default 8).
5685 + * With setup_timeout you can specify how long the system waits for
5686 + * an expected data channel (default 300 seconds).
5689 +#include <linux/config.h>
5690 +#include <linux/module.h>
5691 +#include <linux/netfilter.h>
5692 +#include <linux/ip.h>
5693 +#include <net/checksum.h>
5694 +#include <net/tcp.h>
5696 +#include <linux/netfilter_ipv4/lockhelp.h>
5697 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5698 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5700 +#include <linux/ctype.h>
5701 +#define NF_NEED_STRNCASECMP
5702 +#define NF_NEED_STRTOU16
5703 +#define NF_NEED_STRTOU32
5704 +#define NF_NEED_NEXTLINE
5705 +#include <linux/netfilter_helpers.h>
5706 +#define NF_NEED_MIME_NEXTLINE
5707 +#include <linux/netfilter_mime.h>
5709 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5711 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5712 +#ifdef IP_NF_RTSP_DEBUG
5713 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5715 +#define DEBUGP(fmt, args...)
5718 +#define MAX_PORTS 8
5719 +static int ports[MAX_PORTS];
5720 +static int num_ports = 0;
5721 +static int max_outstanding = 8;
5722 +static unsigned int setup_timeout = 300;
5724 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5725 +MODULE_DESCRIPTION("RTSP connection tracking module");
5726 +MODULE_LICENSE("GPL");
5728 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5729 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5730 +MODULE_PARM(max_outstanding, "i");
5731 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5732 +MODULE_PARM(setup_timeout, "i");
5733 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5736 +DECLARE_LOCK(ip_rtsp_lock);
5737 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5740 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5741 + * of allocated ports is twice this value). Note that SMIL burns a lot of
5742 + * ports so keep this reasonably high. If this is too low, you will see a
5743 + * lot of "no free client map entries" messages.
5745 +#define MAX_PORT_MAPS 16
5747 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5749 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5752 + * Parse an RTSP packet.
5754 + * Returns zero if parsing failed.
5757 + * IN ptcp tcp data pointer
5758 + * IN tcplen tcp data len
5759 + * IN/OUT ptcpoff points to current tcp offset
5760 + * OUT phdrsoff set to offset of rtsp headers
5761 + * OUT phdrslen set to length of rtsp headers
5762 + * OUT pcseqoff set to offset of CSeq header
5763 + * OUT pcseqlen set to length of CSeq header
5766 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5767 + uint* phdrsoff, uint* phdrslen,
5768 + uint* pcseqoff, uint* pcseqlen)
5770 + uint entitylen = 0;
5774 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5779 + *phdrsoff = *ptcpoff;
5780 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5784 + if (entitylen > 0)
5786 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5790 + if (lineoff+linelen > tcplen)
5792 + INFOP("!! overrun !!\n");
5796 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5798 + *pcseqoff = lineoff;
5799 + *pcseqlen = linelen;
5801 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5803 + uint off = lineoff+15;
5804 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
5805 + nf_strtou32(ptcp+off, &entitylen);
5808 + *phdrslen = (*ptcpoff) - (*phdrsoff);
5814 + * Find lo/hi client ports (if any) in transport header
5816 + * ptcp, tcplen = packet
5817 + * tranoff, tranlen = buffer to search
5820 + * pport_lo, pport_hi = lo/hi ports (host endian)
5822 + * Returns nonzero if any client ports found
5824 + * Note: it is valid (and expected) for the client to request multiple
5825 + * transports, so we need to parse the entire line.
5828 +rtsp_parse_transport(char* ptran, uint tranlen,
5829 + struct ip_ct_rtsp_expect* prtspexp)
5834 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5835 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
5837 + INFOP("sanity check failed\n");
5840 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5842 + SKIP_WSPACE(ptran, tranlen, off);
5844 + /* Transport: tran;field;field=val,tran;field;field=val,... */
5845 + while (off < tranlen)
5847 + const char* pparamend;
5848 + uint nextparamoff;
5850 + pparamend = memchr(ptran+off, ',', tranlen-off);
5851 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5852 + nextparamoff = pparamend-ptran;
5854 + while (off < nextparamoff)
5856 + const char* pfieldend;
5857 + uint nextfieldoff;
5859 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5860 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5862 + if (strncmp(ptran+off, "client_port=", 12) == 0)
5868 + numlen = nf_strtou16(ptran+off, &port);
5870 + if (prtspexp->loport != 0 && prtspexp->loport != port)
5872 + DEBUGP("multiple ports found, port %hu ignored\n", port);
5876 + prtspexp->loport = prtspexp->hiport = port;
5877 + if (ptran[off] == '-')
5880 + numlen = nf_strtou16(ptran+off, &port);
5882 + prtspexp->pbtype = pb_range;
5883 + prtspexp->hiport = port;
5885 + // If we have a range, assume rtp:
5886 + // loport must be even, hiport must be loport+1
5887 + if ((prtspexp->loport & 0x0001) != 0 ||
5888 + prtspexp->hiport != prtspexp->loport+1)
5890 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
5891 + prtspexp->loport, prtspexp->hiport);
5892 + prtspexp->loport &= 0xfffe;
5893 + prtspexp->hiport = prtspexp->loport+1;
5896 + else if (ptran[off] == '/')
5899 + numlen = nf_strtou16(ptran+off, &port);
5901 + prtspexp->pbtype = pb_discon;
5902 + prtspexp->hiport = port;
5909 + * Note we don't look for the destination parameter here.
5910 + * If we are using NAT, the NAT module will handle it. If not,
5911 + * and the client is sending packets elsewhere, the expectation
5912 + * will quietly time out.
5915 + off = nextfieldoff;
5918 + off = nextparamoff;
5924 +/*** conntrack functions ***/
5926 +/* outbound packet: client->server */
5928 +help_out(const struct iphdr* iph, size_t pktlen,
5929 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5931 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5932 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5933 + uint tcplen = pktlen - iph->ihl * 4;
5934 + char* pdata = (char*)tcph + tcph->doff * 4;
5935 + uint datalen = tcplen - tcph->doff * 4;
5938 + struct ip_conntrack_expect exp;
5940 + while (dataoff < datalen)
5942 + uint cmdoff = dataoff;
5952 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
5953 + &hdrsoff, &hdrslen,
5954 + &cseqoff, &cseqlen))
5956 + break; /* not a valid message */
5959 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5961 + continue; /* not a SETUP message */
5963 + DEBUGP("found a setup message\n");
5965 + memset(&exp, 0, sizeof(exp));
5968 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5969 + &lineoff, &linelen))
5975 + if (off > hdrsoff+hdrslen)
5977 + INFOP("!! overrun !!");
5981 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5983 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5984 + &exp.help.exp_rtsp_info);
5988 + if (exp.help.exp_rtsp_info.loport == 0)
5990 + DEBUGP("no udp transports found\n");
5991 + continue; /* no udp transports found */
5994 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5995 + (int)exp.help.exp_rtsp_info.pbtype,
5996 + exp.help.exp_rtsp_info.loport,
5997 + exp.help.exp_rtsp_info.hiport);
5999 + LOCK_BH(&ip_rtsp_lock);
6000 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
6001 + exp.help.exp_rtsp_info.len = hdrslen;
6003 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6004 + exp.mask.src.ip = 0xffffffff;
6005 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
6006 + exp.mask.dst.ip = 0xffffffff;
6007 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
6008 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
6009 + exp.tuple.dst.protonum = IPPROTO_UDP;
6010 + exp.mask.dst.protonum = 0xffff;
6012 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6013 + NIPQUAD(exp.tuple.src.ip),
6014 + ntohs(exp.tuple.src.u.tcp.port),
6015 + NIPQUAD(exp.tuple.dst.ip),
6016 + ntohs(exp.tuple.dst.u.tcp.port));
6018 + /* pass the request off to the nat helper */
6019 + rc = ip_conntrack_expect_related(&exp, ct);
6020 + UNLOCK_BH(&ip_rtsp_lock);
6023 + DEBUGP("ip_conntrack_expect_related succeeded\n");
6027 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
6034 +/* inbound packet: server->client */
6036 +help_in(const struct iphdr* iph, size_t pktlen,
6037 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6043 +help(const struct iphdr* iph, size_t pktlen,
6044 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6046 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6047 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6048 + u_int32_t tcplen = pktlen - iph->ihl * 4;
6050 + /* Until there's been traffic both ways, don't look in packets. */
6051 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
6053 + DEBUGP("conntrackinfo = %u\n", ctinfo);
6057 + /* Not whole TCP header? */
6058 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
6060 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
6064 + /* Checksum invalid? Ignore. */
6065 + /* FIXME: Source route IP option packets --RR */
6066 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6067 + csum_partial((char*)tcph, tcplen, 0)))
6069 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6070 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6074 + switch (CTINFO2DIR(ctinfo))
6076 + case IP_CT_DIR_ORIGINAL:
6077 + help_out(iph, pktlen, ct, ctinfo);
6079 + case IP_CT_DIR_REPLY:
6080 + help_in(iph, pktlen, ct, ctinfo);
6087 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
6088 +static char rtsp_names[MAX_PORTS][10];
6090 +/* This function is intentionally _NOT_ defined as __exit */
6095 + for (i = 0; i < num_ports; i++)
6097 + DEBUGP("unregistering port %d\n", ports[i]);
6098 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
6106 + struct ip_conntrack_helper *hlpr;
6109 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
6111 + if (max_outstanding < 1)
6113 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
6116 + if (setup_timeout < 0)
6118 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
6122 + /* If no port given, default to standard rtsp port */
6123 + if (ports[0] == 0)
6125 + ports[0] = RTSP_PORT;
6128 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
6130 + hlpr = &rtsp_helpers[i];
6131 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
6132 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
6133 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
6134 + hlpr->mask.src.u.tcp.port = 0xFFFF;
6135 + hlpr->mask.dst.protonum = 0xFFFF;
6136 + hlpr->max_expected = max_outstanding;
6137 + hlpr->timeout = setup_timeout;
6138 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
6139 + hlpr->me = ip_conntrack_rtsp;
6140 + hlpr->help = help;
6142 + tmpname = &rtsp_names[i][0];
6143 + if (ports[i] == RTSP_PORT)
6145 + sprintf(tmpname, "rtsp");
6149 + sprintf(tmpname, "rtsp-%d", i);
6151 + hlpr->name = tmpname;
6153 + DEBUGP("port #%d: %d\n", i, ports[i]);
6155 + ret = ip_conntrack_helper_register(hlpr);
6159 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
6168 +#ifdef CONFIG_IP_NF_NAT_NEEDED
6169 +EXPORT_SYMBOL(ip_rtsp_lock);
6174 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c
6175 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-25 10:47:46.000000000 +0200
6176 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-25 12:21:37.872634224 +0200
6178 len += sprintf(buffer + len, "[ASSURED] ");
6179 len += sprintf(buffer + len, "use=%u ",
6180 atomic_read(&conntrack->ct_general.use));
6181 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
6182 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
6184 len += sprintf(buffer + len, "\n");
6187 @@ -334,6 +337,11 @@
6188 /* From ip_conntrack_proto_icmp.c */
6189 extern unsigned long ip_ct_generic_timeout;
6191 +/* Log invalid packets of a given protocol */
6192 +unsigned int ip_ct_log_invalid = 0;
6193 +static int log_invalid_proto_min = 0;
6194 +static int log_invalid_proto_max = 255;
6196 static struct ctl_table_header *ip_ct_sysctl_header;
6198 static ctl_table ip_ct_sysctl_table[] = {
6199 @@ -449,6 +457,17 @@
6201 .proc_handler = &proc_dointvec_jiffies,
6204 + .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
6205 + .procname = "ip_conntrack_log_invalid",
6206 + .data = &ip_ct_log_invalid,
6207 + .maxlen = sizeof(unsigned int),
6209 + .proc_handler = &proc_dointvec_minmax,
6210 + .strategy = &sysctl_intvec,
6211 + .extra1 = &log_invalid_proto_min,
6212 + .extra2 = &log_invalid_proto_max,
6218 EXPORT_SYMBOL(ip_conntrack_alter_reply);
6219 EXPORT_SYMBOL(ip_conntrack_destroyed);
6220 EXPORT_SYMBOL(ip_conntrack_get);
6221 +EXPORT_SYMBOL(__ip_conntrack_confirm);
6222 EXPORT_SYMBOL(need_ip_conntrack);
6223 EXPORT_SYMBOL(ip_conntrack_helper_register);
6224 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
6225 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_talk.c
6226 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
6227 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_talk.c 2004-06-25 12:28:43.650906088 +0200
6230 + * talk extension for IP connection tracking.
6231 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6233 + * This program is free software; you can redistribute it and/or
6234 + * modify it under the terms of the GNU General Public License
6235 + * as published by the Free Software Foundation; either version
6236 + * 2 of the License, or (at your option) any later version.
6238 + * Module load syntax:
6239 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
6241 + * talk=[0|1] disable|enable old talk support
6242 + * ntalk=[0|1] disable|enable ntalk support
6243 + * ntalk2=[0|1] disable|enable ntalk2 support
6245 + * The default is talk=1 ntalk=1 ntalk2=1
6247 + * The helper does not support simultaneous talk requests.
6250 + * ASCII art on talk protocols
6253 + * caller server callee server
6260 + * caller client ----------- callee client
6263 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
6264 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
6265 + * 3. callee client <-> caller server: LOOK_UP invitation
6266 + * 4. callee client <-> caller client: talk data channel
6268 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
6269 + * draft-hunter-talk-00.txt
6270 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
6272 +#include <linux/config.h>
6273 +#include <linux/module.h>
6274 +#include <linux/netfilter.h>
6275 +#include <linux/ip.h>
6276 +#include <net/checksum.h>
6277 +#include <net/udp.h>
6279 +#include <linux/netfilter_ipv4/lockhelp.h>
6280 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6281 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
6282 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6283 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
6285 +/* Default all talk protocols are supported */
6286 +static int talk = 1;
6287 +static int ntalk = 1;
6288 +static int ntalk2 = 1;
6289 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6290 +MODULE_DESCRIPTION("talk connection tracking module");
6291 +MODULE_LICENSE("GPL");
6293 +MODULE_PARM(talk, "i");
6294 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
6295 +MODULE_PARM(ntalk, "i");
6296 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
6297 +MODULE_PARM(ntalk2, "i");
6298 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
6301 +DECLARE_LOCK(ip_talk_lock);
6302 +struct module *ip_conntrack_talk = THIS_MODULE;
6305 +#define DEBUGP printk
6307 +#define DEBUGP(format, args...)
6310 +static int talk_expect(struct ip_conntrack *ct);
6311 +static int ntalk_expect(struct ip_conntrack *ct);
6313 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
6315 +static int talk_help_response(const struct iphdr *iph, size_t len,
6316 + struct ip_conntrack *ct,
6317 + enum ip_conntrack_info ctinfo,
6322 + struct talk_addr *addr)
6324 + int dir = CTINFO2DIR(ctinfo);
6325 + struct ip_conntrack_expect expect, *exp = &expect;
6326 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
6328 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
6329 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
6332 + if (!(answer == SUCCESS && type == mode))
6335 + memset(&expect, 0, sizeof(expect));
6337 + if (type == ANNOUNCE) {
6339 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
6341 + /* update the talk info */
6342 + LOCK_BH(&ip_talk_lock);
6343 + exp_talk_info->port = htons(talk_port);
6345 + /* expect callee client -> caller server message */
6346 + exp->tuple = ((struct ip_conntrack_tuple)
6347 + { { ct->tuplehash[dir].tuple.src.ip,
6349 + { ct->tuplehash[dir].tuple.dst.ip,
6350 + { .tcp = { htons(talk_port) } },
6352 + exp->mask = ((struct ip_conntrack_tuple)
6353 + { { 0xFFFFFFFF, { 0 } },
6354 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6356 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
6358 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
6359 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
6360 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
6362 + /* Ignore failure; should only happen with NAT */
6363 + ip_conntrack_expect_related(&expect, ct);
6364 + UNLOCK_BH(&ip_talk_lock);
6366 + if (type == LOOK_UP) {
6368 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
6370 + /* update the talk info */
6371 + LOCK_BH(&ip_talk_lock);
6372 + exp_talk_info->port = addr->ta_port;
6374 + /* expect callee client -> caller client connection */
6375 + exp->tuple = ((struct ip_conntrack_tuple)
6376 + { { ct->tuplehash[!dir].tuple.src.ip,
6379 + { addr->ta_port },
6381 + exp->mask = ((struct ip_conntrack_tuple)
6382 + { { 0xFFFFFFFF, { 0 } },
6383 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6385 + exp->expectfn = NULL;
6387 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
6388 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
6389 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
6391 + /* Ignore failure; should only happen with NAT */
6392 + ip_conntrack_expect_related(&expect, ct);
6393 + UNLOCK_BH(&ip_talk_lock);
6399 +/* FIXME: This should be in userspace. Later. */
6400 +static int talk_help(const struct iphdr *iph, size_t len,
6401 + struct ip_conntrack *ct,
6402 + enum ip_conntrack_info ctinfo,
6406 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6407 + const char *data = (const char *)udph + sizeof(struct udphdr);
6408 + int dir = CTINFO2DIR(ctinfo);
6411 + DEBUGP("ip_ct_talk_help: help entered\n");
6413 + /* Until there's been traffic both ways, don't look in packets. */
6414 + if (ctinfo != IP_CT_ESTABLISHED
6415 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6416 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
6420 + /* Not whole UDP header? */
6421 + udplen = len - iph->ihl * 4;
6422 + if (udplen < sizeof(struct udphdr)) {
6423 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
6427 + /* Checksum invalid? Ignore. */
6428 + /* FIXME: Source route IP option packets --RR */
6429 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6430 + csum_partial((char *)udph, udplen, 0))) {
6431 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6432 + udph, udplen, NIPQUAD(iph->saddr),
6433 + NIPQUAD(iph->daddr));
6437 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6438 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
6440 + if (dir == IP_CT_DIR_ORIGINAL)
6443 + if (talk_port == TALK_PORT
6444 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6445 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6446 + ((struct talk_response *)data)->type,
6447 + ((struct talk_response *)data)->answer,
6448 + &(((struct talk_response *)data)->addr));
6449 + else if (talk_port == NTALK_PORT
6451 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6452 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6453 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6454 + ((struct ntalk_response *)data)->type,
6455 + ((struct ntalk_response *)data)->answer,
6456 + &(((struct ntalk_response *)data)->addr));
6457 + else if (talk_port == NTALK_PORT
6459 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6460 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6461 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6462 + ((struct ntalk2_response *)data)->type,
6463 + ((struct ntalk2_response *)data)->answer,
6464 + &(((struct ntalk2_response *)data)->addr));
6466 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
6467 + (unsigned)udplen - sizeof(struct udphdr),
6468 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6473 +static int lookup_help(const struct iphdr *iph, size_t len,
6474 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6476 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
6479 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
6480 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6482 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
6485 +static struct ip_conntrack_helper lookup_helpers[2] =
6486 + { { { NULL, NULL },
6487 + "talk", /* name */
6489 + NULL, /* module */
6490 + 1, /* max_expected */
6491 + 240, /* timeout */
6492 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
6493 + { 0, { 0 }, IPPROTO_UDP } },
6494 + { { 0, { 0xFFFF } }, /* mask */
6495 + { 0, { 0 }, 0xFFFF } },
6496 + lookup_help }, /* helper */
6498 + "ntalk", /* name */
6500 + NULL, /* module */
6501 + 1, /* max_expected */
6502 + 240, /* timeout */
6503 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
6504 + { 0, { 0 }, IPPROTO_UDP } },
6505 + { { 0, { 0xFFFF } }, /* mask */
6506 + { 0, { 0 }, 0xFFFF } },
6507 + lookup_nhelp } /* helper */
6510 +static int talk_expect(struct ip_conntrack *ct)
6512 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
6513 + WRITE_LOCK(&ip_conntrack_lock);
6514 + ct->helper = &lookup_helpers[0];
6515 + WRITE_UNLOCK(&ip_conntrack_lock);
6517 + return NF_ACCEPT; /* unused */
6520 +static int ntalk_expect(struct ip_conntrack *ct)
6522 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
6523 + WRITE_LOCK(&ip_conntrack_lock);
6524 + ct->helper = &lookup_helpers[1];
6525 + WRITE_UNLOCK(&ip_conntrack_lock);
6527 + return NF_ACCEPT; /* unused */
6530 +static int help(const struct iphdr *iph, size_t len,
6531 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6533 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
6536 +static int nhelp(const struct iphdr *iph, size_t len,
6537 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6539 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
6542 +static struct ip_conntrack_helper talk_helpers[2] =
6543 + { { { NULL, NULL },
6544 + "talk", /* name */
6546 + THIS_MODULE, /* module */
6547 + 1, /* max_expected */
6548 + 240, /* timeout */
6549 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
6550 + { 0, { 0 }, IPPROTO_UDP } },
6551 + { { 0, { 0xFFFF } }, /* mask */
6552 + { 0, { 0 }, 0xFFFF } },
6553 + help }, /* helper */
6555 + "ntalk", /* name */
6557 + THIS_MODULE, /* module */
6558 + 1, /* max_expected */
6559 + 240, /* timeout */
6560 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
6561 + { 0, { 0 }, IPPROTO_UDP } },
6562 + { { 0, { 0xFFFF } }, /* mask */
6563 + { 0, { 0 }, 0xFFFF } },
6564 + nhelp } /* helper */
6567 +static int __init init(void)
6570 + ip_conntrack_helper_register(&talk_helpers[0]);
6571 + if (ntalk > 0 || ntalk2 > 0)
6572 + ip_conntrack_helper_register(&talk_helpers[1]);
6577 +static void __exit fini(void)
6580 + ip_conntrack_helper_unregister(&talk_helpers[0]);
6581 + if (ntalk > 0 || ntalk2 > 0)
6582 + ip_conntrack_helper_unregister(&talk_helpers[1]);
6585 +EXPORT_SYMBOL(ip_talk_lock);
6589 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c
6590 --- linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c 2004-06-25 10:47:46.000000000 +0200
6591 +++ linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c 2004-06-25 12:21:02.340036000 +0200
6594 #include <linux/netfilter_ipv4/ip_conntrack.h>
6595 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
6596 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
6597 #include <linux/netfilter_ipv4/ip_nat.h>
6598 #include <linux/netfilter_ipv4/ip_nat_core.h>
6599 #include <linux/netfilter_ipv4/listhelp.h>
6601 switch ((*pskb)->nh.iph->protocol) {
6604 - ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
6605 + protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
6606 + ct = (struct ip_conntrack *)(*pskb)->nfct->master;
6608 /* We only do SNAT in the compatibility layer.
6609 So we can manipulate ICMP errors from
6612 IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
6614 - if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
6615 + if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
6616 + (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
6617 if (net_ratelimit())
6618 printk("ip_fw_compat_masq: Can't get tuple\n");
6620 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.7/net/ipv4/netfilter/ip_nat_h323.c
6621 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
6622 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_h323.c 2004-06-25 12:21:34.918083384 +0200
6625 + * H.323 'brute force' extension for NAT alteration.
6626 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6628 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6629 + * (http://www.coritel.it/projects/sofia/nat.html)
6630 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6631 + * the unregistered helpers to the conntrack entries.
6635 +#include <linux/module.h>
6636 +#include <linux/netfilter.h>
6637 +#include <linux/ip.h>
6638 +#include <net/checksum.h>
6639 +#include <net/tcp.h>
6641 +#include <linux/netfilter_ipv4/lockhelp.h>
6642 +#include <linux/netfilter_ipv4/ip_nat.h>
6643 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6644 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6645 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6646 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6647 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6649 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6650 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6651 +MODULE_LICENSE("GPL");
6653 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6654 +struct module *ip_nat_h323 = THIS_MODULE;
6657 +#define DEBUGP printk
6659 +#define DEBUGP(format, args...)
6662 +/* FIXME: Time out? --RR */
6664 +static unsigned int
6665 +h225_nat_expected(struct sk_buff **pskb,
6666 + unsigned int hooknum,
6667 + struct ip_conntrack *ct,
6668 + struct ip_nat_info *info);
6670 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6671 + struct ip_conntrack_expect *exp,
6672 + struct ip_nat_info *info,
6673 + enum ip_conntrack_info ctinfo,
6674 + unsigned int hooknum,
6675 + struct sk_buff **pskb);
6677 +static struct ip_nat_helper h245 =
6679 + "H.245", /* name */
6681 + NULL, /* module */
6682 + { { 0, { 0 } }, /* tuple */
6683 + { 0, { 0 }, IPPROTO_TCP } },
6684 + { { 0, { 0xFFFF } }, /* mask */
6685 + { 0, { 0 }, 0xFFFF } },
6686 + h225_nat_help, /* helper */
6687 + h225_nat_expected /* expectfn */
6690 +static unsigned int
6691 +h225_nat_expected(struct sk_buff **pskb,
6692 + unsigned int hooknum,
6693 + struct ip_conntrack *ct,
6694 + struct ip_nat_info *info)
6696 + struct ip_nat_multi_range mr;
6697 + u_int32_t newdstip, newsrcip, newip;
6699 + struct ip_ct_h225_expect *exp_info;
6700 + struct ip_ct_h225_master *master_info;
6701 + struct ip_conntrack *master = master_ct(ct);
6702 + unsigned int is_h225, ret;
6704 + IP_NF_ASSERT(info);
6705 + IP_NF_ASSERT(master);
6707 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6709 + DEBUGP("h225_nat_expected: We have a connection!\n");
6710 + master_info = &ct->master->expectant->help.ct_h225_info;
6711 + exp_info = &ct->master->help.exp_h225_info;
6713 + LOCK_BH(&ip_h323_lock);
6715 + DEBUGP("master: ");
6716 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6717 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6718 + DEBUGP("conntrack: ");
6719 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6720 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6721 + /* Make connection go to the client. */
6722 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6723 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6724 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6725 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6727 + /* Make the connection go to the server */
6728 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6729 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6730 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6731 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6733 + port = exp_info->port;
6734 + is_h225 = master_info->is_h225 == H225_PORT;
6735 + UNLOCK_BH(&ip_h323_lock);
6737 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6742 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6745 + /* We don't want to manip the per-protocol, just the IPs... */
6746 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6747 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6749 + /* ... unless we're doing a MANIP_DST, in which case, make
6750 + sure we map to the correct port */
6751 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6752 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6753 + mr.range[0].min = mr.range[0].max
6754 + = ((union ip_conntrack_manip_proto)
6755 + { .tcp = { port } });
6758 + ret = ip_nat_setup_info(ct, &mr, hooknum);
6761 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6762 + /* NAT expectfn called with ip_nat_lock write-locked */
6763 + info->helper = &h245;
6768 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6769 + struct sk_buff **pskb,
6770 + enum ip_conntrack_info ctinfo)
6772 + struct iphdr *iph = (*pskb)->nh.iph;
6773 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6774 + char *data = (char *) tcph + tcph->doff * 4;
6775 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6776 + u_int32_t datalen = tcplen - tcph->doff*4;
6777 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6782 + MUST_BE_LOCKED(&ip_h323_lock);
6784 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6785 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6787 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6789 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6790 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6793 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6794 + info->offset[IP_CT_DIR_ORIGINAL],
6795 + info->offset[IP_CT_DIR_REPLY],
6797 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6798 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6800 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
6801 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6802 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6803 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6804 + if (!between(info->seq[i], ntohl(tcph->seq),
6805 + ntohl(tcph->seq) + datalen))
6807 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6808 + ntohl(tcph->seq) + datalen)) {
6809 + /* Partial retransmisison. It's a cracker being funky. */
6810 + if (net_ratelimit()) {
6811 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6814 + ntohl(tcph->seq) + datalen);
6819 + /* Change address inside packet to match way we're mapping
6820 + this connection. */
6821 + if (i == IP_CT_DIR_ORIGINAL) {
6822 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6823 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6825 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
6826 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6829 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6830 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6831 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6832 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6834 + /* Modify the packet */
6835 + *(u_int32_t *)(data + info->offset[i]) = newip;
6836 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
6838 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6839 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6840 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6841 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6844 + /* fix checksum information */
6846 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6850 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6851 + csum_partial((char *)tcph, tcph->doff*4,
6853 + ip_send_check(iph);
6858 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6859 + struct ip_conntrack *ct,
6860 + struct sk_buff **pskb,
6861 + enum ip_conntrack_info ctinfo,
6862 + struct ip_conntrack_expect *expect)
6866 + struct ip_conntrack_tuple newtuple;
6867 + struct iphdr *iph = (*pskb)->nh.iph;
6868 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6869 + char *data = (char *) tcph + tcph->doff * 4;
6870 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6871 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6874 + MUST_BE_LOCKED(&ip_h323_lock);
6875 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6876 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6877 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6879 + if (!between(expect->seq + 6, ntohl(tcph->seq),
6880 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6881 + /* Partial retransmisison. It's a cracker being funky. */
6882 + if (net_ratelimit()) {
6883 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6886 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6891 + /* Change address inside packet to match way we're mapping
6892 + this connection. */
6893 + if (info->dir == IP_CT_DIR_REPLY) {
6894 + /* Must be where client thinks server is */
6895 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6896 + /* Expect something from client->server */
6897 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6898 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6900 + /* Must be where server thinks client is */
6901 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6902 + /* Expect something from server->client */
6903 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6904 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6907 + is_h225 = (master_info->is_h225 == H225_PORT);
6910 + newtuple.dst.protonum = IPPROTO_TCP;
6911 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6913 + newtuple.dst.protonum = IPPROTO_UDP;
6914 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6917 + /* Try to get same port: if not, try to change it. */
6918 + for (port = ntohs(info->port); port != 0; port++) {
6920 + newtuple.dst.u.tcp.port = htons(port);
6922 + newtuple.dst.u.udp.port = htons(port);
6924 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6928 + DEBUGP("h323_data_fixup: no free port found!\n");
6932 + port = htons(port);
6934 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6935 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6936 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6938 + /* Modify the packet */
6939 + *(u_int32_t *)(data + info->offset) = newip;
6940 + *(u_int16_t *)(data + info->offset + 4) = port;
6942 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6943 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6944 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6946 + /* fix checksum information */
6947 + /* FIXME: usually repeated multiple times in the case of H.245! */
6949 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6950 + tcplen - tcph->doff*4, 0);
6953 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6954 + csum_partial((char *)tcph, tcph->doff*4,
6956 + ip_send_check(iph);
6961 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6962 + struct ip_conntrack_expect *exp,
6963 + struct ip_nat_info *info,
6964 + enum ip_conntrack_info ctinfo,
6965 + unsigned int hooknum,
6966 + struct sk_buff **pskb)
6969 + struct ip_ct_h225_expect *exp_info;
6971 + /* Only mangle things once: original direction in POST_ROUTING
6972 + and reply direction on PRE_ROUTING. */
6973 + dir = CTINFO2DIR(ctinfo);
6974 + DEBUGP("nat_h323: dir %s at hook %s\n",
6975 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6976 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6977 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6978 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6979 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6980 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6981 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6982 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6983 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6984 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6985 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6990 + LOCK_BH(&ip_h323_lock);
6991 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6992 + UNLOCK_BH(&ip_h323_lock);
6995 + UNLOCK_BH(&ip_h323_lock);
6999 + exp_info = &exp->help.exp_h225_info;
7001 + LOCK_BH(&ip_h323_lock);
7002 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
7003 + UNLOCK_BH(&ip_h323_lock);
7006 + UNLOCK_BH(&ip_h323_lock);
7011 +static struct ip_nat_helper h225 =
7013 + "H.225", /* name */
7014 + IP_NAT_HELPER_F_ALWAYS, /* flags */
7015 + THIS_MODULE, /* module */
7016 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
7017 + { 0, { 0 }, IPPROTO_TCP } },
7018 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
7019 + { 0, { 0 }, 0xFFFF } },
7020 + h225_nat_help, /* helper */
7021 + h225_nat_expected /* expectfn */
7024 +static int __init init(void)
7028 + ret = ip_nat_helper_register(&h225);
7031 + printk("ip_nat_h323: cannot initialize the module!\n");
7036 +static void __exit fini(void)
7038 + ip_nat_helper_unregister(&h225);
7043 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.7/net/ipv4/netfilter/ip_nat_mms.c
7044 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
7045 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_mms.c 2004-06-25 12:23:10.837501416 +0200
7047 +/* MMS extension for TCP NAT alteration.
7048 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7049 + * based on ip_nat_ftp.c and ip_nat_irc.c
7051 + * ip_nat_mms.c v0.3 2002-09-22
7053 + * This program is free software; you can redistribute it and/or
7054 + * modify it under the terms of the GNU General Public License
7055 + * as published by the Free Software Foundation; either version
7056 + * 2 of the License, or (at your option) any later version.
7058 + * Module load syntax:
7059 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
7061 + * Please give the ports of all MMS servers You wish to connect to.
7062 + * If you don't specify ports, the default will be TCP port 1755.
7064 + * More info on MMS protocol, firewalls and NAT:
7065 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
7066 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
7068 + * The SDP project people are reverse-engineering MMS:
7069 + * http://get.to/sdp
7072 +/* FIXME: issue with UDP & fragmentation with this URL:
7073 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
7074 + may be related to out-of-order first packets:
7075 + basically the expectation is set up correctly, then the server sends
7076 + a first UDP packet which is fragmented plus arrives out-of-order.
7077 + the MASQUERADING firewall with ip_nat_mms loaded responds with
7078 + an ICMP unreachable back to the server */
7080 +#include <linux/module.h>
7081 +#include <linux/netfilter_ipv4.h>
7082 +#include <linux/ip.h>
7083 +#include <linux/tcp.h>
7084 +#include <net/tcp.h>
7085 +#include <linux/netfilter_ipv4/ip_nat.h>
7086 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7087 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7088 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
7089 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7092 +#define DEBUGP printk
7093 +#define DUMP_BYTES(address, counter) \
7095 + int temp_counter; \
7096 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
7097 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
7102 +#define DEBUGP(format, args...)
7103 +#define DUMP_BYTES(address, counter)
7106 +#define MAX_PORTS 8
7107 +static int ports[MAX_PORTS];
7108 +static int ports_c = 0;
7111 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7114 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7115 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
7116 +MODULE_LICENSE("GPL");
7118 +DECLARE_LOCK_EXTERN(ip_mms_lock);
7120 +/* FIXME: Time out? --RR */
7122 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
7123 + struct ip_conntrack *ct,
7124 + struct sk_buff **pskb,
7125 + enum ip_conntrack_info ctinfo,
7126 + struct ip_conntrack_expect *expect)
7129 + struct ip_conntrack_tuple t;
7130 + struct iphdr *iph = (*pskb)->nh.iph;
7131 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7132 + char *data = (char *)tcph + tcph->doff * 4;
7133 + int i, j, k, port;
7134 + u_int16_t mms_proto;
7136 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
7137 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
7138 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
7142 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
7143 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
7144 + char proto_string[6];
7146 + MUST_BE_LOCKED(&ip_mms_lock);
7148 + /* what was the protocol again ? */
7149 + mms_proto = expect->tuple.dst.protonum;
7150 + sprintf(proto_string, "%u", mms_proto);
7152 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
7153 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
7154 + mms_proto == IPPROTO_UDP ? "UDP"
7155 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
7157 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7159 + /* Alter conntrack's expectations. */
7160 + t = expect->tuple;
7162 + for (port = ct_mms_info->port; port != 0; port++) {
7163 + t.dst.u.tcp.port = htons(port);
7164 + if (ip_conntrack_change_expect(expect, &t) == 0) {
7165 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
7173 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
7175 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
7176 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
7178 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
7180 + memset(unicode_buffer, 0, sizeof(char)*75);
7182 + for (i=0; i<strlen(buffer); ++i)
7183 + *(unicode_buffer+i*2)=*(buffer+i);
7185 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
7186 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
7187 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
7189 + /* add end of packet to it */
7190 + for (j=0; j<ct_mms_info->padding; ++j) {
7191 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
7192 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
7193 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
7196 + /* pad with zeroes at the end ? see explanation of weird math below */
7197 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
7198 + for (k=0; k<zero_padding; ++k)
7199 + *(unicode_buffer+i*2+j+k)= (char)0;
7201 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
7202 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
7203 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
7205 + /* explanation, before I forget what I did:
7206 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
7207 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
7208 + but note that things may have to be padded with zeroes to align by 8
7209 + bytes, hence we add 7 and divide by 8 to get the correct length */
7210 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
7211 + *mms_chunkLenLV = *mms_chunkLenLM+2;
7212 + *mms_messageLength = *mms_chunkLenLV*8;
7214 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
7215 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
7217 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7218 + expect->seq - ntohl(tcph->seq),
7219 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
7220 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
7221 + DUMP_BYTES(unicode_buffer, 60);
7226 +static unsigned int
7227 +mms_nat_expected(struct sk_buff **pskb,
7228 + unsigned int hooknum,
7229 + struct ip_conntrack *ct,
7230 + struct ip_nat_info *info)
7232 + struct ip_nat_multi_range mr;
7233 + u_int32_t newdstip, newsrcip, newip;
7235 + struct ip_conntrack *master = master_ct(ct);
7237 + IP_NF_ASSERT(info);
7238 + IP_NF_ASSERT(master);
7240 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7242 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
7244 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7245 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7246 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
7247 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7248 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7249 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7250 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
7252 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7257 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
7260 + /* We don't want to manip the per-protocol, just the IPs. */
7261 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7262 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7264 + return ip_nat_setup_info(ct, &mr, hooknum);
7268 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
7269 + struct ip_conntrack_expect *exp,
7270 + struct ip_nat_info *info,
7271 + enum ip_conntrack_info ctinfo,
7272 + unsigned int hooknum,
7273 + struct sk_buff **pskb)
7275 + struct iphdr *iph = (*pskb)->nh.iph;
7276 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7277 + unsigned int datalen;
7279 + struct ip_ct_mms_expect *ct_mms_info;
7282 + DEBUGP("ip_nat_mms: no exp!!");
7284 + ct_mms_info = &exp->help.exp_mms_info;
7286 + /* Only mangle things once: original direction in POST_ROUTING
7287 + and reply direction on PRE_ROUTING. */
7288 + dir = CTINFO2DIR(ctinfo);
7289 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7290 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7291 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
7292 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7293 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7294 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7295 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7298 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
7299 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7300 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7301 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7302 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7304 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7306 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
7307 + exp->seq + ct_mms_info->len,
7309 + ntohl(tcph->seq) + datalen);
7311 + LOCK_BH(&ip_mms_lock);
7312 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
7313 + if (between(exp->seq + ct_mms_info->len,
7315 + ntohl(tcph->seq) + datalen)) {
7316 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
7317 + UNLOCK_BH(&ip_mms_lock);
7321 + /* Half a match? This means a partial retransmisison.
7322 + It's a cracker being funky. */
7323 + if (net_ratelimit()) {
7324 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
7325 + exp->seq, ct_mms_info->len,
7327 + ntohl(tcph->seq) + datalen);
7329 + UNLOCK_BH(&ip_mms_lock);
7332 + UNLOCK_BH(&ip_mms_lock);
7337 +static struct ip_nat_helper mms[MAX_PORTS];
7338 +static char mms_names[MAX_PORTS][10];
7340 +/* Not __exit: called from init() */
7341 +static void fini(void)
7345 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7346 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
7347 + ip_nat_helper_unregister(&mms[i]);
7351 +static int __init init(void)
7356 + if (ports[0] == 0)
7357 + ports[0] = MMS_PORT;
7359 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7361 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
7363 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
7364 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
7365 + mms[i].mask.dst.protonum = 0xFFFF;
7366 + mms[i].mask.src.u.tcp.port = 0xFFFF;
7367 + mms[i].help = mms_nat_help;
7368 + mms[i].me = THIS_MODULE;
7370 + mms[i].expect = mms_nat_expected;
7372 + tmpname = &mms_names[i][0];
7373 + if (ports[i] == MMS_PORT)
7374 + sprintf(tmpname, "mms");
7376 + sprintf(tmpname, "mms-%d", i);
7377 + mms[i].name = tmpname;
7379 + DEBUGP("ip_nat_mms: register helper for port %d\n",
7381 + ret = ip_nat_helper_register(&mms[i]);
7384 + printk("ip_nat_mms: error registering "
7385 + "helper for port %d\n", ports[i]);
7397 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.7/net/ipv4/netfilter/ip_nat_quake3.c
7398 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
7399 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_quake3.c 2004-06-25 12:24:42.551558760 +0200
7401 +/* Quake3 extension for UDP NAT alteration.
7402 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7403 + * based on ip_nat_ftp.c and ip_nat_tftp.c
7405 + * ip_nat_quake3.c v0.0.3 2002-08-31
7407 + * This program is free software; you can redistribute it and/or
7408 + * modify it under the terms of the GNU General Public License
7409 + * as published by the Free Software Foundation; either version
7410 + * 2 of the License, or (at your option) any later version.
7412 + * Module load syntax:
7413 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
7415 + * please give the ports of all Quake3 master servers You wish to
7416 + * connect to. If you don't specify ports, the default will be UDP
7419 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
7422 + * - If you're one of those people who would try anything to lower
7423 + * latency while playing Quake (and who isn't :-) ), you may want to
7424 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
7425 + * outgoing UDP traffic.
7426 + * This will make ip_conntrack_quake3 add the necessary expectations,
7427 + * but there will be no overhead for client->server UDP streams. If
7428 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
7429 + * hook for every packet in the client->server UDP stream.
7430 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
7431 + * The IP addresses in the master connection payload (=IP addresses
7432 + * of Quake servers) have no relation with the master server so
7433 + * DNAT'ing the master connection to a server should not change the
7434 + * expected connections.
7435 + * - Not tested due to lack of equipment:
7436 + * - multiple Quake3 clients behind one MASQUERADE gateway
7437 + * - what if Quake3 client is running on router too
7440 +#include <linux/module.h>
7441 +#include <linux/netfilter_ipv4.h>
7442 +#include <linux/ip.h>
7443 +#include <linux/udp.h>
7445 +#include <linux/netfilter.h>
7446 +#include <linux/netfilter_ipv4/ip_tables.h>
7447 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7448 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
7449 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7450 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7452 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7453 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
7454 +MODULE_LICENSE("GPL");
7456 +#define MAX_PORTS 8
7458 +static int ports[MAX_PORTS];
7459 +static int ports_c = 0;
7461 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7462 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7465 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7466 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7468 +#define DEBUGP printk
7470 +#define DEBUGP(format, args...)
7473 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7475 +static unsigned int
7476 +quake3_nat_help(struct ip_conntrack *ct,
7477 + struct ip_conntrack_expect *exp,
7478 + struct ip_nat_info *info,
7479 + enum ip_conntrack_info ctinfo,
7480 + unsigned int hooknum,
7481 + struct sk_buff **pskb)
7483 + struct iphdr *iph = (*pskb)->nh.iph;
7484 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7485 + struct ip_conntrack_tuple repl;
7486 + int dir = CTINFO2DIR(ctinfo);
7489 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7490 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7491 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7492 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7493 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7495 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7496 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7498 + /* Only mangle things once: original direction in POST_ROUTING
7499 + and reply direction on PRE_ROUTING. */
7500 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7501 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7502 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7503 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7504 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7505 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7506 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7511 + DEBUGP("no conntrack expectation to modify\n");
7515 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7516 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7517 + i+6 < ntohs(udph->len);
7519 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
7520 + i, ntohs(udph->len),
7521 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7522 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7524 + memset(&repl, 0, sizeof(repl));
7526 + repl.dst.protonum = IPPROTO_UDP;
7527 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7528 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7529 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
7531 + ip_conntrack_change_expect(exp, &repl);
7537 +static unsigned int
7538 +quake3_nat_expected(struct sk_buff **pskb,
7539 + unsigned int hooknum,
7540 + struct ip_conntrack *ct,
7541 + struct ip_nat_info *info)
7543 + const struct ip_conntrack *master = ct->master->expectant;
7544 + struct ip_nat_multi_range mr;
7545 + u_int32_t newsrcip, newdstip, newip;
7547 + const struct ip_conntrack_tuple *repl =
7548 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7549 + struct iphdr *iph = (*pskb)->nh.iph;
7550 + struct udphdr *udph = (void *)iph + iph->ihl*4;
7553 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7554 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7556 + IP_NF_ASSERT(info);
7557 + IP_NF_ASSERT(master);
7558 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7560 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7561 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7563 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7565 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7566 + "newsrc: %u.%u.%u.%u\n",
7567 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7568 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7569 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7570 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7571 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7576 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7577 + "newdst: %u.%u.%u.%u\n",
7578 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7579 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7580 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7581 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7582 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7587 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7588 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7590 + return ip_nat_setup_info(ct,&mr,hooknum);
7593 +static struct ip_nat_helper quake3[MAX_PORTS];
7594 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
7596 +static void fini(void)
7600 + for (i = 0 ; i < ports_c; i++) {
7601 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7602 + ip_nat_helper_unregister(&quake3[i]);
7606 +static int __init init(void)
7612 + ports[0] = QUAKE3_MASTER_PORT;
7614 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7615 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7617 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7618 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7619 + quake3[i].mask.dst.protonum = 0xFFFF;
7620 + quake3[i].mask.src.u.udp.port = 0xFFFF;
7621 + quake3[i].help = quake3_nat_help;
7622 + quake3[i].flags = 0;
7623 + quake3[i].me = THIS_MODULE;
7624 + quake3[i].expect = quake3_nat_expected;
7626 + tmpname = &quake3_names[i][0];
7627 + if (ports[i] == QUAKE3_MASTER_PORT)
7628 + sprintf(tmpname, "quake3");
7630 + sprintf(tmpname, "quake3-%d", i);
7631 + quake3[i].name = tmpname;
7633 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7634 + ports[i], quake3[i].name);
7635 + ret = ip_nat_helper_register(&quake3[i]);
7638 + printk("ip_nat_quake3: unable to register helper for port %d\n",
7650 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.7/net/ipv4/netfilter/ip_nat_rtsp.c
7651 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
7652 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_rtsp.c 2004-06-25 12:24:50.035421040 +0200
7655 + * RTSP extension for TCP NAT alteration
7656 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7657 + * based on ip_nat_irc.c
7659 + * This program is free software; you can redistribute it and/or
7660 + * modify it under the terms of the GNU General Public License
7661 + * as published by the Free Software Foundation; either version
7662 + * 2 of the License, or (at your option) any later version.
7664 + * Module load syntax:
7665 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7666 + * stunaddr=<address>
7667 + * destaction=[auto|strip|none]
7669 + * If no ports are specified, the default will be port 554 only.
7671 + * stunaddr specifies the address used to detect that a client is using STUN.
7672 + * If this address is seen in the destination parameter, it is assumed that
7673 + * the client has already punched a UDP hole in the firewall, so we don't
7674 + * mangle the client_port. If none is specified, it is autodetected. It
7675 + * only needs to be set if you have multiple levels of NAT. It should be
7676 + * set to the external address that the STUN clients detect. Note that in
7677 + * this case, it will not be possible for clients to use UDP with servers
7678 + * between the NATs.
7680 + * If no destaction is specified, auto is used.
7681 + * destaction=auto: strip destination parameter if it is not stunaddr.
7682 + * destaction=strip: always strip destination parameter (not recommended).
7683 + * destaction=none: do not touch destination parameter (not recommended).
7686 +#include <linux/module.h>
7687 +#include <linux/netfilter_ipv4.h>
7688 +#include <linux/ip.h>
7689 +#include <linux/tcp.h>
7690 +#include <linux/kernel.h>
7691 +#include <net/tcp.h>
7692 +#include <linux/netfilter_ipv4/ip_nat.h>
7693 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7694 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7695 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7696 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7698 +#include <linux/inet.h>
7699 +#include <linux/ctype.h>
7700 +#define NF_NEED_STRNCASECMP
7701 +#define NF_NEED_STRTOU16
7702 +#include <linux/netfilter_helpers.h>
7703 +#define NF_NEED_MIME_NEXTLINE
7704 +#include <linux/netfilter_mime.h>
7706 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7707 +#ifdef IP_NF_RTSP_DEBUG
7708 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7710 +#define DEBUGP(fmt, args...)
7713 +#define MAX_PORTS 8
7714 +#define DSTACT_AUTO 0
7715 +#define DSTACT_STRIP 1
7716 +#define DSTACT_NONE 2
7718 +static int ports[MAX_PORTS];
7719 +static char* stunaddr = NULL;
7720 +static char* destaction = NULL;
7722 +static int num_ports = 0;
7723 +static u_int32_t extip = 0;
7724 +static int dstact = 0;
7726 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7727 +MODULE_DESCRIPTION("RTSP network address translation module");
7728 +MODULE_LICENSE("GPL");
7730 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7731 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7732 +MODULE_PARM(stunaddr, "s");
7733 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7734 +MODULE_PARM(destaction, "s");
7735 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7738 +/* protects rtsp part of conntracks */
7739 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7741 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7743 +/*** helper functions ***/
7746 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7748 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7749 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7751 + *pptcpdata = (char*)tcph + tcph->doff*4;
7752 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7755 +/*** nat functions ***/
7758 + * Mangle the "Transport:" header:
7759 + * - Replace all occurences of "client_port=<spec>"
7760 + * - Handle destination parameter
7763 + * ct, ctinfo = conntrack context
7765 + * tranoff = Transport header offset from TCP data
7766 + * tranlen = Transport header length (incl. CRLF)
7767 + * rport_lo = replacement low port (host endian)
7768 + * rport_hi = replacement high port (host endian)
7770 + * Returns packet size difference.
7772 + * Assumes that a complete transport header is present, ending with CR or LF
7775 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7776 + struct ip_conntrack_expect* exp,
7777 + struct sk_buff** pskb, uint tranoff, uint tranlen)
7782 + char rbuf1[16]; /* Replacement buffer (one port) */
7783 + uint rbuf1len; /* Replacement len (one port) */
7784 + char rbufa[16]; /* Replacement buffer (all ports) */
7785 + uint rbufalen; /* Replacement len (all ports) */
7787 + u_int16_t loport, hiport;
7789 + uint diff; /* Number of bytes we removed */
7791 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7792 + struct ip_conntrack_tuple t;
7794 + char szextaddr[15+1];
7798 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7799 + ptran = ptcp+tranoff;
7801 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7802 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7803 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
7805 + INFOP("sanity check failed\n");
7809 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7811 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7815 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7816 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7817 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7819 + rbuf1len = rbufalen = 0;
7820 + switch (prtspexp->pbtype)
7823 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7825 + t.dst.u.udp.port = htons(loport);
7826 + if (ip_conntrack_change_expect(exp, &t) == 0)
7828 + DEBUGP("using port %hu\n", loport);
7834 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7835 + rbufalen = sprintf(rbufa, "%hu", loport);
7839 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7841 + t.dst.u.udp.port = htons(loport);
7842 + if (ip_conntrack_change_expect(exp, &t) == 0)
7844 + hiport = loport + ~exp->mask.dst.u.udp.port;
7845 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
7851 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7852 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7856 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7858 + t.dst.u.udp.port = htons(loport);
7859 + if (ip_conntrack_change_expect(exp, &t) == 0)
7861 + DEBUGP("using port %hu (1 of 2)\n", loport);
7865 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7867 + t.dst.u.udp.port = htons(hiport);
7868 + if (ip_conntrack_change_expect(exp, &t) == 0)
7870 + DEBUGP("using port %hu (2 of 2)\n", hiport);
7874 + if (loport != 0 && hiport != 0)
7876 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7877 + if (hiport == loport+1)
7879 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7883 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7889 + if (rbuf1len == 0)
7891 + return 0; /* cannot get replacement port(s) */
7894 + /* Transport: tran;field;field=val,tran;field;field=val,... */
7895 + while (off < tranlen)
7898 + const char* pparamend;
7899 + uint nextparamoff;
7901 + pparamend = memchr(ptran+off, ',', tranlen-off);
7902 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7903 + nextparamoff = pparamend-ptcp;
7906 + * We pass over each param twice. On the first pass, we look for a
7907 + * destination= field. It is handled by the security policy. If it
7908 + * is present, allowed, and equal to our external address, we assume
7909 + * that STUN is being used and we leave the client_port= field alone.
7913 + while (off < nextparamoff)
7915 + const char* pfieldend;
7916 + uint nextfieldoff;
7918 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7919 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7921 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7923 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7927 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7929 + diff = nextfieldoff-off;
7930 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7931 + off, diff, NULL, 0))
7933 + /* mangle failed, all we can do is bail */
7936 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7937 + ptran = ptcp+tranoff;
7939 + nextparamoff -= diff;
7940 + nextfieldoff -= diff;
7944 + off = nextfieldoff;
7951 + while (off < nextparamoff)
7953 + const char* pfieldend;
7954 + uint nextfieldoff;
7956 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7957 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7959 + if (strncmp(ptran+off, "client_port=", 12) == 0)
7965 + char* rbuf = rbuf1;
7966 + uint rbuflen = rbuf1len;
7969 + origoff = (ptran-ptcp)+off;
7971 + numlen = nf_strtou16(ptran+off, &port);
7973 + origlen += numlen;
7974 + if (port != prtspexp->loport)
7976 + DEBUGP("multiple ports found, port %hu ignored\n", port);
7980 + if (ptran[off] == '-' || ptran[off] == '/')
7984 + numlen = nf_strtou16(ptran+off, &port);
7986 + origlen += numlen;
7988 + rbuflen = rbufalen;
7992 + * note we cannot just memcpy() if the sizes are the same.
7993 + * the mangle function does skb resizing, checks for a
7994 + * cloned skb, and updates the checksums.
7996 + * parameter 4 below is offset from start of tcp data.
7998 + diff = origlen-rbuflen;
7999 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
8000 + origoff, origlen, rbuf, rbuflen))
8002 + /* mangle failed, all we can do is bail */
8005 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
8006 + ptran = ptcp+tranoff;
8008 + nextparamoff -= diff;
8009 + nextfieldoff -= diff;
8013 + off = nextfieldoff;
8016 + off = nextparamoff;
8022 +static unsigned int
8023 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
8025 + struct ip_nat_multi_range mr;
8026 + u_int32_t newdstip, newsrcip, newip;
8028 + struct ip_conntrack *master = master_ct(ct);
8030 + IP_NF_ASSERT(info);
8031 + IP_NF_ASSERT(master);
8033 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8035 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8036 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8037 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
8039 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
8040 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
8043 + /* We don't want to manip the per-protocol, just the IPs. */
8044 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8045 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8047 + return ip_nat_setup_info(ct, &mr, hooknum);
8051 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
8052 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
8062 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
8063 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
8065 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
8067 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
8069 + hdrsoff = exp->seq - ntohl(tcph->seq);
8070 + hdrslen = prtspexp->len;
8073 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
8079 + if (off > hdrsoff+hdrslen)
8081 + INFOP("!! overrun !!");
8084 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
8086 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
8088 + uint oldtcplen = tcplen;
8089 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
8093 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
8094 + hdrslen -= (oldtcplen-tcplen);
8095 + off -= (oldtcplen-tcplen);
8096 + lineoff -= (oldtcplen-tcplen);
8097 + linelen -= (oldtcplen-tcplen);
8098 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
8106 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
8107 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
8109 + /* XXX: unmangle */
8114 +help(struct ip_conntrack* ct,
8115 + struct ip_conntrack_expect* exp,
8116 + struct ip_nat_info* info,
8117 + enum ip_conntrack_info ctinfo,
8118 + unsigned int hooknum,
8119 + struct sk_buff** pskb)
8121 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
8122 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
8125 + struct ip_ct_rtsp_expect* ct_rtsp_info;
8126 + int rc = NF_ACCEPT;
8128 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
8130 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
8134 + ct_rtsp_info = &exp->help.exp_rtsp_info;
8137 + * Only mangle things once: original direction in POST_ROUTING
8138 + * and reply direction on PRE_ROUTING.
8140 + dir = CTINFO2DIR(ctinfo);
8141 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8142 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
8144 + DEBUGP("Not touching dir %s at hook %s\n",
8145 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8146 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8147 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8148 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8151 + DEBUGP("got beyond not touching\n");
8153 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
8155 + LOCK_BH(&ip_rtsp_lock);
8156 + /* Ensure the packet contains all of the marked data */
8157 + if (!between(exp->seq + ct_rtsp_info->len,
8158 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
8160 + /* Partial retransmission? Probably a hacker. */
8161 + if (net_ratelimit())
8163 + INFOP("partial packet %u/%u in %u/%u\n",
8164 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
8166 + UNLOCK_BH(&ip_rtsp_lock);
8172 + case IP_CT_DIR_ORIGINAL:
8173 + rc = help_out(ct, ctinfo, exp, pskb);
8175 + case IP_CT_DIR_REPLY:
8176 + rc = help_in(ct, ctinfo, exp, pskb);
8179 + UNLOCK_BH(&ip_rtsp_lock);
8184 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
8185 +static char rtsp_names[MAX_PORTS][10];
8187 +/* This function is intentionally _NOT_ defined as __exit */
8193 + for (i = 0; i < num_ports; i++)
8195 + DEBUGP("unregistering helper for port %d\n", ports[i]);
8196 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
8205 + struct ip_nat_helper* hlpr;
8208 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
8210 + if (ports[0] == 0)
8212 + ports[0] = RTSP_PORT;
8215 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
8217 + hlpr = &ip_nat_rtsp_helpers[i];
8218 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
8220 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
8221 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
8222 + hlpr->mask.src.u.tcp.port = 0xFFFF;
8223 + hlpr->mask.dst.protonum = 0xFFFF;
8224 + hlpr->help = help;
8226 + hlpr->me = THIS_MODULE;
8227 + hlpr->expect = expected;
8229 + tmpname = &rtsp_names[i][0];
8230 + if (ports[i] == RTSP_PORT)
8232 + sprintf(tmpname, "rtsp");
8236 + sprintf(tmpname, "rtsp-%d", i);
8238 + hlpr->name = tmpname;
8240 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
8241 + ret = ip_nat_helper_register(hlpr);
8245 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
8251 + if (stunaddr != NULL)
8253 + extip = in_aton(stunaddr);
8255 + if (destaction != NULL)
8257 + if (strcmp(destaction, "auto") == 0)
8259 + dstact = DSTACT_AUTO;
8261 + if (strcmp(destaction, "strip") == 0)
8263 + dstact = DSTACT_STRIP;
8265 + if (strcmp(destaction, "none") == 0)
8267 + dstact = DSTACT_NONE;
8275 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_nat_standalone.c
8276 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-25 10:47:46.000000000 +0200
8277 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_standalone.c 2004-06-25 12:21:37.877633464 +0200
8278 @@ -177,6 +177,45 @@
8279 return do_bindings(ct, ctinfo, info, hooknum, pskb);
8282 +struct nat_route_key
8291 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
8293 + struct iphdr *iph = skb->nh.iph;
8295 + key->addr = which ? iph->daddr : iph->saddr;
8298 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8299 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8300 + key->port = ports[which];
8306 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
8308 + struct iphdr *iph = skb->nh.iph;
8310 + if (key->addr != (which ? iph->daddr : iph->saddr))
8313 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8314 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8315 + if (key->port != ports[which])
8322 ip_nat_out(unsigned int hooknum,
8323 struct sk_buff **pskb,
8325 const struct net_device *out,
8326 int (*okfn)(struct sk_buff *))
8328 + struct nat_route_key key;
8331 /* root is playing with raw sockets. */
8332 if ((*pskb)->len < sizeof(struct iphdr)
8333 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8334 @@ -206,7 +248,29 @@
8338 - return ip_nat_fn(hooknum, pskb, in, out, okfn);
8339 + nat_route_key_get(*pskb, &key, 0);
8340 + ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8342 + if (ret != NF_DROP && ret != NF_STOLEN
8343 + && nat_route_key_compare(*pskb, &key, 0)) {
8344 + if (ip_route_me_harder(pskb) != 0)
8348 + * POST_ROUTING hook is called with fixed outfn, we need
8349 + * to manually confirm the packet and direct it to the
8350 + * transformers if a policy matches.
8352 + else if ((*pskb)->dst->xfrm != NULL) {
8353 + ret = ip_conntrack_confirm(*pskb);
8354 + if (ret != NF_DROP) {
8355 + dst_output(*pskb);
8364 #ifdef CONFIG_IP_NF_NAT_LOCAL
8366 const struct net_device *out,
8367 int (*okfn)(struct sk_buff *))
8369 - u_int32_t saddr, daddr;
8370 + struct nat_route_key key;
8373 /* root is playing with raw sockets. */
8374 @@ -225,14 +289,14 @@
8375 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8378 - saddr = (*pskb)->nh.iph->saddr;
8379 - daddr = (*pskb)->nh.iph->daddr;
8381 + nat_route_key_get(*pskb, &key, 1);
8382 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8384 if (ret != NF_DROP && ret != NF_STOLEN
8385 - && ((*pskb)->nh.iph->saddr != saddr
8386 - || (*pskb)->nh.iph->daddr != daddr))
8387 - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
8388 + && nat_route_key_compare(*pskb, &key, 1)) {
8389 + if (ip_route_me_harder(pskb) != 0)
8395 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.7/net/ipv4/netfilter/ip_nat_talk.c
8396 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
8397 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_talk.c 2004-06-25 12:28:43.653905632 +0200
8400 + * talk extension for UDP NAT alteration.
8401 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8403 + * This program is free software; you can redistribute it and/or
8404 + * modify it under the terms of the GNU General Public License
8405 + * as published by the Free Software Foundation; either version
8406 + * 2 of the License, or (at your option) any later version.
8408 + * Module load syntax:
8409 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
8411 + * talk=[0|1] disable|enable old talk support
8412 + * ntalk=[0|1] disable|enable ntalk support
8413 + * ntalk2=[0|1] disable|enable ntalk2 support
8415 + * The default is talk=1 ntalk=1 ntalk2=1
8419 +#include <linux/module.h>
8420 +#include <linux/netfilter_ipv4.h>
8421 +#include <linux/ip.h>
8422 +#include <linux/udp.h>
8423 +#include <linux/kernel.h>
8424 +#include <net/tcp.h>
8425 +#include <net/udp.h>
8427 +#include <linux/netfilter_ipv4/ip_nat.h>
8428 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8429 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8430 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8431 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8433 +/* Default all talk protocols are supported */
8434 +static int talk = 1;
8435 +static int ntalk = 1;
8436 +static int ntalk2 = 1;
8437 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8438 +MODULE_DESCRIPTION("talk network address translation module");
8440 +MODULE_PARM(talk, "i");
8441 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8442 +MODULE_PARM(ntalk, "i");
8443 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8444 +MODULE_PARM(ntalk2, "i");
8445 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8449 +#define DEBUGP printk
8450 +#define IP_NAT_TALK_DEBUG
8452 +#define DEBUGP(format, args...)
8455 +/* FIXME: Time out? --RR */
8458 +mangle_packet(struct sk_buff **pskb,
8459 + struct ip_conntrack *ct,
8462 + struct talk_addr *addr,
8463 + struct talk_addr *ctl_addr)
8465 + struct iphdr *iph = (*pskb)->nh.iph;
8466 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8467 + size_t udplen = (*pskb)->len - iph->ihl * 4;
8469 + /* Fortunately talk sends a structure with the address and
8470 + port in it. The size of the packet won't change. */
8472 + if (ctl_addr == NULL) {
8474 + if (addr->ta_addr == INADDR_ANY)
8476 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8477 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8478 + NIPQUAD(newip), ntohs(port));
8479 + addr->ta_addr = newip;
8480 + addr->ta_port = port;
8483 + if (addr->ta_addr != INADDR_ANY) {
8484 + /* Change address inside packet to match way we're mapping
8485 + this connection. */
8486 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8487 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8488 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
8489 + ntohs(addr->ta_port));
8490 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8492 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8493 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8494 + NIPQUAD(newip), ntohs(port));
8495 + ctl_addr->ta_addr = newip;
8496 + ctl_addr->ta_port = port;
8499 + /* Fix checksums */
8500 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8502 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8503 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8505 + ip_send_check(iph);
8509 +static int talk_help_msg(struct ip_conntrack *ct,
8510 + struct sk_buff **pskb,
8512 + struct talk_addr *addr,
8513 + struct talk_addr *ctl_addr)
8518 + unsigned int verdict = NF_ACCEPT;
8520 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8521 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8522 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8525 + /* Change address inside packet to match way we're mapping
8526 + this connection. */
8527 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8528 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8529 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8530 + NIPQUAD(newip), ntohs(port));
8532 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8533 + verdict = NF_DROP;
8538 +static int talk_help_response(struct ip_conntrack *ct,
8539 + struct ip_conntrack_expect *exp,
8540 + struct sk_buff **pskb,
8543 + struct talk_addr *addr)
8547 + struct ip_conntrack_tuple t;
8548 + struct ip_ct_talk_expect *ct_talk_info;
8550 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8551 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8554 + LOCK_BH(&ip_talk_lock);
8555 + ct_talk_info = &exp->help.exp_talk_info;
8557 + if (!(answer == SUCCESS
8558 + && (type == LOOK_UP || type == ANNOUNCE)
8559 + && exp != NULL)) {
8560 + UNLOCK_BH(&ip_talk_lock);
8564 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
8565 + ntohs(ct_talk_info->port),
8566 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8568 + /* Change address inside packet to match way we're mapping
8569 + this connection. */
8570 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
8571 + IP_CT_DIR_REPLY].tuple.dst.ip;
8572 + /* We can read expect here without conntrack lock, since it's
8573 + only set in ip_conntrack_talk , with ip_talk_lock held
8578 + /* Try to get same port: if not, try to change it. */
8579 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8580 + if (type == LOOK_UP)
8581 + t.dst.u.tcp.port = htons(port);
8583 + t.dst.u.udp.port = htons(port);
8585 + if (ip_conntrack_change_expect(exp, &t) == 0) {
8586 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8590 + UNLOCK_BH(&ip_talk_lock);
8592 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8598 +static unsigned int talk_help(struct ip_conntrack *ct,
8599 + struct ip_conntrack_expect *exp,
8600 + struct ip_nat_info *info,
8601 + enum ip_conntrack_info ctinfo,
8602 + unsigned int hooknum,
8603 + struct sk_buff **pskb,
8606 + struct iphdr *iph = (*pskb)->nh.iph;
8607 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8608 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8609 + char *data = (char *)udph + sizeof(struct udphdr);
8612 + /* Only mangle things once: original direction in POST_ROUTING
8613 + and reply direction on PRE_ROUTING. */
8614 + dir = CTINFO2DIR(ctinfo);
8615 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8616 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8617 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8618 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8619 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8620 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8621 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8624 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8625 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8626 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8627 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8628 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8629 + NIPQUAD(iph->saddr), ntohs(udph->source),
8630 + NIPQUAD(iph->daddr), ntohs(udph->dest),
8633 + /* Because conntrack does not drop packets, checking must be repeated here... */
8634 + if (talk_port == TALK_PORT) {
8635 + if (dir == IP_CT_DIR_ORIGINAL
8636 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8637 + return talk_help_msg(ct, pskb,
8638 + ((struct talk_msg *)data)->type,
8639 + &(((struct talk_msg *)data)->addr),
8640 + &(((struct talk_msg *)data)->ctl_addr));
8641 + else if (dir == IP_CT_DIR_REPLY
8642 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8643 + return talk_help_response(ct, exp, pskb,
8644 + ((struct talk_response *)data)->type,
8645 + ((struct talk_response *)data)->answer,
8646 + &(((struct talk_response *)data)->addr));
8648 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8649 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
8650 + (unsigned)udplen - sizeof(struct udphdr),
8651 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8655 + if (dir == IP_CT_DIR_ORIGINAL) {
8657 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8658 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8659 + return talk_help_msg(ct, pskb,
8660 + ((struct ntalk_msg *)data)->type,
8661 + &(((struct ntalk_msg *)data)->addr),
8662 + &(((struct ntalk_msg *)data)->ctl_addr));
8664 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8665 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8666 + && udplen == sizeof(struct udphdr)
8667 + + sizeof(struct ntalk2_msg)
8668 + + ((struct ntalk2_msg *)data)->extended)
8669 + return talk_help_msg(ct, pskb,
8670 + ((struct ntalk2_msg *)data)->type,
8671 + &(((struct ntalk2_msg *)data)->addr),
8672 + &(((struct ntalk2_msg *)data)->ctl_addr));
8674 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8675 + (unsigned)udplen - sizeof(struct udphdr),
8676 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8681 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8682 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8683 + return talk_help_response(ct, exp, pskb,
8684 + ((struct ntalk_response *)data)->type,
8685 + ((struct ntalk_response *)data)->answer,
8686 + &(((struct ntalk_response *)data)->addr));
8688 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8689 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8690 + return talk_help_response(ct, exp, pskb,
8691 + ((struct ntalk2_response *)data)->type,
8692 + ((struct ntalk2_response *)data)->answer,
8693 + &(((struct ntalk2_response *)data)->addr));
8695 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8696 + (unsigned)udplen - sizeof(struct udphdr),
8697 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8704 +static unsigned int help(struct ip_conntrack *ct,
8705 + struct ip_conntrack_expect *exp,
8706 + struct ip_nat_info *info,
8707 + enum ip_conntrack_info ctinfo,
8708 + unsigned int hooknum,
8709 + struct sk_buff **pskb)
8711 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8714 +static unsigned int nhelp(struct ip_conntrack *ct,
8715 + struct ip_conntrack_expect *exp,
8716 + struct ip_nat_info *info,
8717 + enum ip_conntrack_info ctinfo,
8718 + unsigned int hooknum,
8719 + struct sk_buff **pskb)
8721 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8724 +static unsigned int
8725 +talk_nat_expected(struct sk_buff **pskb,
8726 + unsigned int hooknum,
8727 + struct ip_conntrack *ct,
8728 + struct ip_nat_info *info);
8730 +static struct ip_nat_helper talk_helpers[2] =
8731 + { { { NULL, NULL },
8732 + "talk", /* name */
8733 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8734 + THIS_MODULE, /* module */
8735 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8736 + { 0, { 0 }, IPPROTO_UDP } },
8737 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8738 + { 0, { 0 }, 0xFFFF } },
8739 + help, /* helper */
8740 + talk_nat_expected }, /* expectfn */
8742 + "ntalk", /* name */
8743 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8744 + THIS_MODULE, /* module */
8745 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8746 + { 0, { 0 }, IPPROTO_UDP } },
8747 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8748 + { 0, { 0 }, 0xFFFF } },
8749 + nhelp, /* helper */
8750 + talk_nat_expected } /* expectfn */
8753 +static unsigned int
8754 +talk_nat_expected(struct sk_buff **pskb,
8755 + unsigned int hooknum,
8756 + struct ip_conntrack *ct,
8757 + struct ip_nat_info *info)
8759 + struct ip_nat_multi_range mr;
8760 + u_int32_t newdstip, newsrcip, newip;
8764 + struct ip_conntrack *master = master_ct(ct);
8766 + IP_NF_ASSERT(info);
8767 + IP_NF_ASSERT(master);
8769 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8771 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8773 + LOCK_BH(&ip_talk_lock);
8774 + port = ct->master->help.exp_talk_info.port;
8775 + UNLOCK_BH(&ip_talk_lock);
8777 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8778 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8779 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8780 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8781 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8784 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8785 + /* Callee client -> caller server */
8786 +#ifdef IP_NAT_TALK_DEBUG
8787 + struct iphdr *iph = (*pskb)->nh.iph;
8788 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8790 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8791 + NIPQUAD(iph->saddr), ntohs(udph->source),
8792 + NIPQUAD(iph->daddr), ntohs(udph->dest));
8794 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8795 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8796 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8797 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8799 + /* Callee client -> caller client */
8800 +#ifdef IP_NAT_TALK_DEBUG
8801 + struct iphdr *iph = (*pskb)->nh.iph;
8802 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8804 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8805 + NIPQUAD(iph->saddr), ntohs(tcph->source),
8806 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
8808 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8809 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8810 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8811 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8813 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8818 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8821 + /* We don't want to manip the per-protocol, just the IPs... */
8822 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8823 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8825 + /* ... unless we're doing a MANIP_DST, in which case, make
8826 + sure we map to the correct port */
8827 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8828 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8829 + mr.range[0].min = mr.range[0].max
8830 + = ((union ip_conntrack_manip_proto)
8831 + { .udp = { port } });
8833 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8835 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8836 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8837 + /* NAT expectfn called with ip_nat_lock write-locked */
8838 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
8843 +static int __init init(void)
8848 + ret = ip_nat_helper_register(&talk_helpers[0]);
8853 + if (ntalk > 0 || ntalk2 > 0) {
8854 + ret = ip_nat_helper_register(&talk_helpers[1]);
8856 + if (ret != 0 && talk > 0)
8857 + ip_nat_helper_unregister(&talk_helpers[0]);
8862 +static void __exit fini(void)
8865 + ip_nat_helper_unregister(&talk_helpers[0]);
8866 + if (ntalk > 0 || ntalk2 > 0)
8867 + ip_nat_helper_unregister(&talk_helpers[1]);
8872 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_pool.c linux-2.6.7/net/ipv4/netfilter/ip_pool.c
8873 --- linux-2.6.7.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
8874 +++ linux-2.6.7/net/ipv4/netfilter/ip_pool.c 2004-06-25 12:21:11.464648848 +0200
8876 +/* Kernel module for IP pool management */
8878 +#include <linux/module.h>
8879 +#include <linux/ip.h>
8880 +#include <linux/skbuff.h>
8881 +#include <linux/netfilter_ipv4/ip_tables.h>
8882 +#include <linux/netfilter_ipv4/ip_pool.h>
8883 +#include <linux/errno.h>
8884 +#include <asm/uaccess.h>
8885 +#include <asm/bitops.h>
8886 +#include <linux/interrupt.h>
8887 +#include <linux/spinlock.h>
8892 +#define DP(format, args...)
8895 +MODULE_LICENSE("GPL");
8898 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8901 + u_int32_t first_ip; /* host byte order, included in range */
8902 + u_int32_t last_ip; /* host byte order, included in range */
8903 + void *members; /* the bitmap proper */
8904 + int nr_use; /* total nr. of tests through this */
8905 + int nr_match; /* total nr. of matches through this */
8909 +static struct ip_pool *POOL;
8911 +static inline struct ip_pool *lookup(ip_pool_t index)
8913 + if (index < 0 || index >= nr_pool) {
8914 + DP("ip_pool:lookup: bad index %d\n", index);
8917 + return POOL+index;
8920 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8922 + struct ip_pool *pool = lookup(index);
8925 + if (!pool || !pool->members)
8927 + read_lock_bh(&pool->lock);
8928 + if (pool->members) {
8929 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
8930 + addr -= pool->first_ip;
8931 + if (test_bit(addr, pool->members)) {
8933 +#ifdef CONFIG_IP_POOL_STATISTICS
8938 +#ifdef CONFIG_IP_POOL_STATISTICS
8942 + read_unlock_bh(&pool->lock);
8946 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8948 + struct ip_pool *pool;
8951 + pool = lookup(index);
8952 + if ( !pool || !pool->members
8953 + || addr < pool->first_ip || addr > pool->last_ip)
8955 + read_lock_bh(&pool->lock);
8956 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8957 + addr -= pool->first_ip;
8959 + ? (0 != test_and_clear_bit(addr, pool->members))
8960 + : (0 != test_and_set_bit(addr, pool->members));
8962 + read_unlock_bh(&pool->lock);
8966 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8968 + int res = pool_change(index,addr,isdel);
8970 + if (!isdel) res = !res;
8974 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8976 + return 4*((((b-a+8)/8)+3)/4);
8979 +static inline int poolbytes(ip_pool_t index)
8981 + struct ip_pool *pool = lookup(index);
8983 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8986 +static int setpool(
8992 + struct ip_pool_request req;
8994 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8995 + if (!capable(CAP_NET_ADMIN))
8997 + if (optval != SO_IP_POOL)
8999 + if (len != sizeof(req))
9001 + if (copy_from_user(&req, user, sizeof(req)) != 0)
9003 + printk("obsolete op - upgrade your ippool(8) utility.\n");
9007 +static int getpool(
9013 + struct ip_pool_request req;
9014 + struct ip_pool *pool;
9020 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
9021 + if (!capable(CAP_NET_ADMIN))
9023 + if (optval != SO_IP_POOL)
9025 + if (*len != sizeof(req)) {
9028 + if (copy_from_user(&req, user, sizeof(req)) != 0)
9030 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
9031 + if (req.op < IP_POOL_BAD001) {
9032 + printk("obsolete op - upgrade your ippool(8) utility.\n");
9036 + case IP_POOL_HIGH_NR:
9037 + DP("ip_pool HIGH_NR\n");
9038 + req.index = IP_POOL_NONE;
9039 + for (i=0; i<nr_pool; i++)
9040 + if (POOL[i].members)
9042 + return copy_to_user(user, &req, sizeof(req));
9043 + case IP_POOL_LOOKUP:
9044 + DP("ip_pool LOOKUP\n");
9045 + pool = lookup(req.index);
9048 + if (!pool->members)
9050 + req.addr = htonl(pool->first_ip);
9051 + req.addr2 = htonl(pool->last_ip);
9052 + return copy_to_user(user, &req, sizeof(req));
9053 + case IP_POOL_USAGE:
9054 + DP("ip_pool USE\n");
9055 + pool = lookup(req.index);
9058 + if (!pool->members)
9060 + req.addr = pool->nr_use;
9061 + req.addr2 = pool->nr_match;
9062 + return copy_to_user(user, &req, sizeof(req));
9063 + case IP_POOL_TEST_ADDR:
9064 + DP("ip_pool TEST 0x%08x\n", req.addr);
9065 + pool = lookup(req.index);
9069 + read_lock_bh(&pool->lock);
9070 + if (!pool->members) {
9071 + DP("ip_pool TEST_ADDR no members in pool\n");
9073 + goto unlock_and_return_res;
9075 + req.addr = ntohl(req.addr);
9076 + if (req.addr < pool->first_ip) {
9077 + DP("ip_pool TEST_ADDR address < pool bounds\n");
9079 + goto unlock_and_return_res;
9081 + if (req.addr > pool->last_ip) {
9082 + DP("ip_pool TEST_ADDR address > pool bounds\n");
9084 + goto unlock_and_return_res;
9086 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
9088 + read_unlock_bh(&pool->lock);
9089 + return copy_to_user(user, &req, sizeof(req));
9090 + case IP_POOL_FLUSH:
9091 + DP("ip_pool FLUSH not yet implemented.\n");
9093 + case IP_POOL_DESTROY:
9094 + DP("ip_pool DESTROY not yet implemented.\n");
9096 + case IP_POOL_INIT:
9097 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
9098 + pool = lookup(req.index);
9101 + req.addr = ntohl(req.addr);
9102 + req.addr2 = ntohl(req.addr2);
9103 + if (req.addr > req.addr2) {
9104 + DP("ip_pool INIT bad ip range\n");
9107 + newbytes = bitmap_bytes(req.addr, req.addr2);
9108 + newmembers = kmalloc(newbytes, GFP_KERNEL);
9109 + if (!newmembers) {
9110 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
9113 + memset(newmembers, 0, newbytes);
9114 + write_lock_bh(&pool->lock);
9115 + if (pool->members) {
9116 + DP("ip_pool INIT pool %d exists\n", req.index);
9117 + kfree(newmembers);
9119 + goto unlock_and_return_res;
9121 + pool->first_ip = req.addr;
9122 + pool->last_ip = req.addr2;
9124 + pool->nr_match = 0;
9125 + pool->members = newmembers;
9126 + write_unlock_bh(&pool->lock);
9128 + case IP_POOL_ADD_ADDR:
9129 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
9130 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
9131 + return copy_to_user(user, &req, sizeof(req));
9132 + case IP_POOL_DEL_ADDR:
9133 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
9134 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
9135 + return copy_to_user(user, &req, sizeof(req));
9137 + DP("ip_pool:getpool bad op %d\n", req.op);
9142 +unlock_and_return_res:
9144 + read_unlock_bh(&pool->lock);
9148 +static struct nf_sockopt_ops so_pool
9149 += { { NULL, NULL }, PF_INET,
9150 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
9151 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
9154 +MODULE_PARM(nr_pool, "i");
9156 +static int __init init(void)
9161 + if (nr_pool < 1) {
9162 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
9165 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
9167 + printk("ip_pool module init: out of memory for nr_pool %d\n",
9171 + for (i=0; i<nr_pool; i++) {
9172 + POOL[i].first_ip = 0;
9173 + POOL[i].last_ip = 0;
9174 + POOL[i].members = 0;
9175 + POOL[i].nr_use = 0;
9176 + POOL[i].nr_match = 0;
9177 + POOL[i].lock = RW_LOCK_UNLOCKED;
9179 + res = nf_register_sockopt(&so_pool);
9180 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
9188 +static void __exit fini(void)
9192 + DP("ip_pool:fini BYEBYE\n");
9193 + nf_unregister_sockopt(&so_pool);
9194 + for (i=0; i<nr_pool; i++) {
9195 + if (POOL[i].members) {
9196 + kfree(POOL[i].members);
9197 + POOL[i].members = 0;
9202 + DP("ip_pool:fini these are the famous last words\n");
9208 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.7/net/ipv4/netfilter/ipt_CONNMARK.c
9209 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
9210 +++ linux-2.6.7/net/ipv4/netfilter/ipt_CONNMARK.c 2004-06-25 12:21:25.484517504 +0200
9212 +/* This kernel module is used to modify the connection mark values, or
9213 + * to optionally restore the skb nfmark from the connection mark
9215 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9216 + * by Henrik Nordstrom <hno@marasystems.com>
9218 + * This program is free software; you can redistribute it and/or modify
9219 + * it under the terms of the GNU General Public License as published by
9220 + * the Free Software Foundation; either version 2 of the License, or
9221 + * (at your option) any later version.
9223 + * This program is distributed in the hope that it will be useful,
9224 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9225 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9226 + * GNU General Public License for more details.
9228 + * You should have received a copy of the GNU General Public License
9229 + * along with this program; if not, write to the Free Software
9230 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9232 +#include <linux/module.h>
9233 +#include <linux/skbuff.h>
9234 +#include <linux/ip.h>
9235 +#include <net/checksum.h>
9237 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9238 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
9239 +MODULE_LICENSE("GPL");
9241 +#include <linux/netfilter_ipv4/ip_tables.h>
9242 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
9243 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9245 +static unsigned int
9246 +target(struct sk_buff **pskb,
9247 + const struct net_device *in,
9248 + const struct net_device *out,
9249 + unsigned int hooknum,
9250 + const void *targinfo,
9253 + const struct ipt_connmark_target_info *markinfo = targinfo;
9254 + unsigned long diff;
9255 + unsigned long nfmark;
9256 + unsigned long newmark;
9258 + enum ip_conntrack_info ctinfo;
9259 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
9261 + switch(markinfo->mode) {
9262 + case IPT_CONNMARK_SET:
9263 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
9264 + if (newmark != ct->mark)
9265 + ct->mark = newmark;
9267 + case IPT_CONNMARK_SAVE:
9268 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
9269 + if (ct->mark != newmark)
9270 + ct->mark = newmark;
9272 + case IPT_CONNMARK_RESTORE:
9273 + nfmark = (*pskb)->nfmark;
9274 + diff = (ct->mark ^ nfmark & markinfo->mask);
9276 + (*pskb)->nfmark = nfmark ^ diff;
9277 + (*pskb)->nfcache |= NFC_ALTERED;
9283 + return IPT_CONTINUE;
9287 +checkentry(const char *tablename,
9288 + const struct ipt_entry *e,
9290 + unsigned int targinfosize,
9291 + unsigned int hook_mask)
9293 + struct ipt_connmark_target_info *matchinfo = targinfo;
9294 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
9295 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
9297 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
9301 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
9302 + if (strcmp(tablename, "mangle") != 0) {
9303 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9311 +static struct ipt_target ipt_connmark_reg = {
9312 + .name = "CONNMARK",
9313 + .target = &target,
9314 + .checkentry = &checkentry,
9318 +static int __init init(void)
9320 + return ipt_register_target(&ipt_connmark_reg);
9323 +static void __exit fini(void)
9325 + ipt_unregister_target(&ipt_connmark_reg);
9330 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.7/net/ipv4/netfilter/ipt_IPMARK.c
9331 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
9332 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPMARK.c 2004-06-25 12:21:27.028282816 +0200
9334 +/* This is a module which is used for setting the NFMARK field of an skb. */
9335 +#include <linux/module.h>
9336 +#include <linux/skbuff.h>
9337 +#include <linux/ip.h>
9338 +#include <net/checksum.h>
9340 +#include <linux/netfilter_ipv4/ip_tables.h>
9341 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
9343 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
9344 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
9345 +MODULE_LICENSE("GPL");
9347 +static unsigned int
9348 +target(struct sk_buff **pskb,
9349 + const struct net_device *in,
9350 + const struct net_device *out,
9351 + unsigned int hooknum,
9352 + const void *targinfo,
9355 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
9356 + struct iphdr *iph = (*pskb)->nh.iph;
9357 + unsigned long mark;
9359 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
9360 + mark = (unsigned long) ntohl(iph->saddr);
9362 + mark = (unsigned long) ntohl(iph->daddr);
9364 + mark &= ipmarkinfo->andmask;
9365 + mark |= ipmarkinfo->ormask;
9367 + if ((*pskb)->nfmark != mark) {
9368 + (*pskb)->nfmark = mark;
9369 + (*pskb)->nfcache |= NFC_ALTERED;
9371 + return IPT_CONTINUE;
9375 +checkentry(const char *tablename,
9376 + const struct ipt_entry *e,
9378 + unsigned int targinfosize,
9379 + unsigned int hook_mask)
9381 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
9382 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
9384 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
9388 + if (strcmp(tablename, "mangle") != 0) {
9389 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9396 +static struct ipt_target ipt_ipmark_reg = {
9399 + .checkentry = checkentry,
9403 +static int __init init(void)
9405 + return ipt_register_target(&ipt_ipmark_reg);
9408 +static void __exit fini(void)
9410 + ipt_unregister_target(&ipt_ipmark_reg);
9415 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
9416 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
9417 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-06-25 12:21:06.371423136 +0200
9420 + * Strip all IP options in the IP packet header.
9422 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
9423 + * This software is distributed under GNU GPL v2, 1991
9426 +#include <linux/module.h>
9427 +#include <linux/skbuff.h>
9428 +#include <linux/ip.h>
9429 +#include <net/checksum.h>
9431 +#include <linux/netfilter_ipv4/ip_tables.h>
9433 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
9434 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
9435 +MODULE_LICENSE("GPL");
9437 +static unsigned int
9438 +target(struct sk_buff **pskb,
9439 + const struct net_device *in,
9440 + const struct net_device *out,
9441 + unsigned int hooknum,
9442 + const void *targinfo,
9445 + struct iphdr *iph;
9446 + struct sk_buff *skb;
9447 + struct ip_options *opt;
9448 + unsigned char *optiph;
9451 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9455 + iph = (*pskb)->nh.iph;
9456 + optiph = skb->nh.raw;
9457 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
9459 + /* if no options in packet then nothing to clear. */
9460 + if (iph->ihl * 4 == sizeof(struct iphdr))
9461 + return IPT_CONTINUE;
9463 + /* else clear all options */
9464 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
9465 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
9466 + opt = &(IPCB(skb)->opt);
9470 + skb->nfcache |= NFC_ALTERED;
9472 + return IPT_CONTINUE;
9476 +checkentry(const char *tablename,
9477 + const struct ipt_entry *e,
9479 + unsigned int targinfosize,
9480 + unsigned int hook_mask)
9482 + if (strcmp(tablename, "mangle")) {
9483 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9486 + /* nothing else to check because no parameters */
9490 +static struct ipt_target ipt_ipv4optsstrip_reg = {
9491 + .name = "IPV4OPTSSTRIP",
9493 + .checkentry = checkentry,
9494 + .me = THIS_MODULE };
9496 +static int __init init(void)
9498 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
9501 +static void __exit fini(void)
9503 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9508 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.7/net/ipv4/netfilter/ipt_NETLINK.c
9509 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
9510 +++ linux-2.6.7/net/ipv4/netfilter/ipt_NETLINK.c 2004-06-25 12:21:06.897343184 +0200
9512 +#include <linux/module.h>
9513 +#include <linux/version.h>
9514 +#include <linux/config.h>
9515 +#include <linux/socket.h>
9516 +#include <linux/skbuff.h>
9517 +#include <linux/kernel.h>
9518 +#include <linux/netlink.h>
9519 +#include <linux/netdevice.h>
9520 +#include <linux/mm.h>
9521 +#include <linux/socket.h>
9522 +#include <linux/netfilter_ipv4/ip_tables.h>
9523 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9524 +#include <net/sock.h>
9526 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9527 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9528 +MODULE_LICENSE("GPL");
9531 +#define DEBUGP printk
9533 +#define DEBUGP(format, args...)
9536 +static struct sock *ipfwsk;
9538 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9539 + unsigned int hooknum,
9540 + const struct net_device *in,
9541 + const struct net_device *out,
9542 + const void *targinfo, void *userinfo)
9544 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9545 + struct iphdr *ip = (*pskb)->nh.iph;
9546 + struct sk_buff *outskb;
9547 + struct netlink_t nlhdr;
9550 + /* Allocate a socket buffer */
9551 + if ( MASK(nld->flags, USE_SIZE) )
9552 + len = nld->size+sizeof(nlhdr);
9554 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
9556 + outskb=alloc_skb(len, GFP_ATOMIC);
9561 + if ( MASK(nld->flags, USE_MARK) )
9562 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
9564 + nlhdr.mark=(*pskb)->nfmark;
9566 + if ( in && in->name ) {
9567 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9568 + }else if ( out && out->name ){
9569 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9572 + skb_put(outskb, len);
9573 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9574 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9575 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9577 + if (net_ratelimit())
9578 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9581 + if ( MASK(nld->flags, USE_DROP) )
9584 + return IPT_CONTINUE;
9587 +static int ipt_netlink_checkentry(const char *tablename,
9588 + const struct ipt_entry *e,
9590 + unsigned int targinfosize,
9591 + unsigned int hookmask)
9593 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9598 +static struct ipt_target ipt_netlink_reg = {
9601 + ipt_netlink_target,
9602 + ipt_netlink_checkentry,
9607 +static int __init init(void)
9609 + DEBUGP("ipt_NETLINK: init module\n");
9611 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
9615 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9622 +static void __exit fini(void)
9624 + DEBUGP("ipt_NETLINK: cleanup_module\n");
9625 + ipt_unregister_target(&ipt_netlink_reg);
9626 + if(ipfwsk->socket) sock_release(ipfwsk->socket);
9631 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.7/net/ipv4/netfilter/ipt_POOL.c
9632 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
9633 +++ linux-2.6.7/net/ipv4/netfilter/ipt_POOL.c 2004-06-25 12:21:11.466648544 +0200
9635 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9637 + * This target can be used almost everywhere. It acts on some specified
9638 + * IP pool, adding or deleting some IP address in the pool. The address
9639 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9640 + * of the packet under inspection.
9642 + * The target normally returns IPT_CONTINUE.
9645 +#include <linux/types.h>
9646 +#include <linux/ip.h>
9647 +#include <linux/timer.h>
9648 +#include <linux/module.h>
9649 +#include <linux/netfilter.h>
9650 +#include <linux/netdevice.h>
9651 +#include <linux/if.h>
9652 +#include <linux/inetdevice.h>
9653 +#include <net/protocol.h>
9654 +#include <net/checksum.h>
9655 +#include <linux/netfilter_ipv4.h>
9656 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9657 +#include <linux/netfilter_ipv4/ipt_pool.h>
9660 +#define DEBUGP printk
9662 +#define DEBUGP(format, args...)
9665 +/*** NOTE NOTE NOTE NOTE ***
9667 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9668 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9669 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9670 +** is modified for the source IP address of the packet under inspection.
9671 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9673 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9674 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9676 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9677 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9678 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9679 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9683 +do_check(const char *tablename,
9684 + const struct ipt_entry *e,
9686 + unsigned int targinfosize,
9687 + unsigned int hook_mask)
9689 + const struct ipt_pool_info *ipi = targinfo;
9691 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9692 + DEBUGP("POOL_check: size %u.\n", targinfosize);
9695 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9699 +static unsigned int
9700 +do_target(struct sk_buff **pskb,
9701 + unsigned int hooknum,
9702 + const struct net_device *in,
9703 + const struct net_device *out,
9704 + const void *targinfo,
9707 + const struct ipt_pool_info *ipi = targinfo;
9709 + unsigned int verdict = IPT_CONTINUE;
9711 + if (ipi->src != IP_POOL_NONE) {
9712 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9713 + ipi->flags & IPT_POOL_DEL_SRC);
9714 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9715 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9716 + verdict = NF_ACCEPT;
9717 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9718 + verdict = NF_DROP;
9721 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9722 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9723 + ipi->flags & IPT_POOL_DEL_DST);
9724 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9725 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9726 + verdict = NF_ACCEPT;
9727 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9728 + verdict = NF_DROP;
9734 +static struct ipt_target pool_reg
9735 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9737 +static int __init init(void)
9739 + DEBUGP("init ipt_POOL\n");
9740 + return ipt_register_target(&pool_reg);
9743 +static void __exit fini(void)
9745 + DEBUGP("fini ipt_POOL\n");
9746 + ipt_unregister_target(&pool_reg);
9751 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.7/net/ipv4/netfilter/ipt_ROUTE.c
9752 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
9753 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ROUTE.c 2004-06-25 12:21:28.214102544 +0200
9756 + * This implements the ROUTE target, which enables you to setup unusual
9757 + * routes not supported by the standard kernel routing table.
9759 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9761 + * v 1.9 2004/05/14
9763 + * This software is distributed under GNU GPL v2, 1991
9766 +#include <linux/module.h>
9767 +#include <linux/skbuff.h>
9768 +#include <linux/ip.h>
9769 +#include <linux/netfilter_ipv4/ip_tables.h>
9770 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
9771 +#include <linux/netdevice.h>
9772 +#include <linux/route.h>
9773 +#include <net/ip.h>
9774 +#include <net/route.h>
9775 +#include <net/icmp.h>
9776 +#include <net/checksum.h>
9779 +#define DEBUGP printk
9781 +#define DEBUGP(format, args...)
9784 +MODULE_LICENSE("GPL");
9785 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
9786 +MODULE_DESCRIPTION("iptables ROUTE target module");
9788 +/* Try to route the packet according to the routing keys specified in
9789 + * route_info. Keys are :
9791 + * 0 if no oif preferred,
9792 + * otherwise set to the index of the desired oif
9793 + * - route_info->gw :
9794 + * 0 if no gateway specified,
9795 + * otherwise set to the next host to which the pkt must be routed
9796 + * If success, skb->dev is the output device to which the packet must
9797 + * be sent and skb->dst is not NULL
9799 + * RETURN: -1 if an error occured
9800 + * 1 if the packet was succesfully routed to the
9801 + * destination desired
9802 + * 0 if the kernel routing table could not route the packet
9803 + * according to the keys specified
9805 +static int route(struct sk_buff *skb,
9806 + unsigned int ifindex,
9807 + const struct ipt_route_target_info *route_info)
9810 + struct rtable *rt;
9811 + struct iphdr *iph = skb->nh.iph;
9812 + struct flowi fl = {
9816 + .daddr = iph->daddr,
9818 + .tos = RT_TOS(iph->tos),
9819 + .scope = RT_SCOPE_UNIVERSE,
9824 + /* The destination address may be overloaded by the target */
9825 + if (route_info->gw)
9826 + fl.fld_dst = route_info->gw;
9828 + /* Trying to route the packet using the standard routing table. */
9829 + if ((err = ip_route_output_key(&rt, &fl))) {
9830 + if (net_ratelimit())
9831 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
9835 + /* Drop old route. */
9836 + dst_release(skb->dst);
9839 + /* Success if no oif specified or if the oif correspond to the
9841 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
9842 + skb->dst = &rt->u.dst;
9843 + skb->dev = skb->dst->dev;
9847 + /* The interface selected by the routing table is not the one
9848 + * specified by the user. This may happen because the dst address
9849 + * is one of our own addresses.
9851 + if (net_ratelimit())
9852 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
9853 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
9859 +/* Stolen from ip_finish_output2
9860 + * PRE : skb->dev is set to the device we are leaving by
9861 + * skb->dst is not NULL
9862 + * POST: the packet is sent with the link layer header pushed
9863 + * the packet is destroyed
9865 +static void ip_direct_send(struct sk_buff *skb)
9867 + struct dst_entry *dst = skb->dst;
9868 + struct hh_cache *hh = dst->hh;
9871 + read_lock_bh(&hh->hh_lock);
9872 + memcpy(skb->data - 16, hh->hh_data, 16);
9873 + read_unlock_bh(&hh->hh_lock);
9874 + skb_push(skb, hh->hh_len);
9875 + hh->hh_output(skb);
9876 + } else if (dst->neighbour)
9877 + dst->neighbour->output(skb);
9879 + if (net_ratelimit())
9880 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
9886 +/* PRE : skb->dev is set to the device we are leaving by
9887 + * POST: - the packet is directly sent to the skb->dev device, without
9888 + * pushing the link layer header.
9889 + * - the packet is destroyed
9891 +static inline int dev_direct_send(struct sk_buff *skb)
9893 + return dev_queue_xmit(skb);
9897 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
9898 + struct sk_buff *skb)
9900 + unsigned int ifindex = 0;
9901 + struct net_device *dev_out = NULL;
9903 + /* The user set the interface name to use.
9904 + * Getting the current interface index.
9906 + if ((dev_out = dev_get_by_name(route_info->oif))) {
9907 + ifindex = dev_out->ifindex;
9909 + /* Unknown interface name : packet dropped */
9910 + if (net_ratelimit())
9911 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
9915 + /* Trying the standard way of routing packets */
9916 + switch (route(skb, ifindex, route_info)) {
9919 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9920 + return IPT_CONTINUE;
9922 + ip_direct_send(skb);
9926 + /* Failed to send to oif. Trying the hard way */
9927 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9930 + if (net_ratelimit())
9931 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
9934 + /* We have to force the use of an interface.
9935 + * This interface must be a tunnel interface since
9936 + * otherwise we can't guess the hw address for
9937 + * the packet. For a tunnel interface, no hw address
9940 + if ((dev_out->type != ARPHRD_TUNNEL)
9941 + && (dev_out->type != ARPHRD_IPGRE)) {
9942 + if (net_ratelimit())
9943 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
9948 + /* Send the packet. This will also free skb
9949 + * Do not go through the POST_ROUTING hook because
9950 + * skb->dst is not set and because it will probably
9951 + * get confused by the destination IP address.
9953 + skb->dev = dev_out;
9954 + dev_direct_send(skb);
9959 + /* Unexpected error */
9966 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
9967 + struct sk_buff *skb)
9969 + struct net_device *dev_in = NULL;
9971 + /* Getting the current interface index. */
9972 + if (!(dev_in = dev_get_by_name(route_info->iif))) {
9973 + if (net_ratelimit())
9974 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
9978 + skb->dev = dev_in;
9979 + dst_release(skb->dst);
9988 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
9989 + struct sk_buff *skb)
9991 + if (route(skb, 0, route_info)!=1)
9994 + if (route_info->flags & IPT_ROUTE_CONTINUE)
9995 + return IPT_CONTINUE;
9997 + ip_direct_send(skb);
10002 +static unsigned int ipt_route_target(struct sk_buff **pskb,
10003 + const struct net_device *in,
10004 + const struct net_device *out,
10005 + unsigned int hooknum,
10006 + const void *targinfo,
10009 + const struct ipt_route_target_info *route_info = targinfo;
10010 + struct sk_buff *skb = *pskb;
10012 + /* If we are at PREROUTING or INPUT hook
10013 + * the TTL isn't decreased by the IP stack
10015 + if (hooknum == NF_IP_PRE_ROUTING ||
10016 + hooknum == NF_IP_LOCAL_IN) {
10018 + struct iphdr *iph = skb->nh.iph;
10020 + if (iph->ttl <= 1) {
10021 + struct rtable *rt;
10022 + struct flowi fl = {
10026 + .daddr = iph->daddr,
10027 + .saddr = iph->saddr,
10028 + .tos = RT_TOS(iph->tos),
10029 + .scope = ((iph->tos & RTO_ONLINK) ?
10031 + RT_SCOPE_UNIVERSE)
10036 + if (ip_route_output_key(&rt, &fl)) {
10040 + if (skb->dev == rt->u.dst.dev) {
10041 + /* Drop old route. */
10042 + dst_release(skb->dst);
10043 + skb->dst = &rt->u.dst;
10045 + /* this will traverse normal stack, and
10046 + * thus call conntrack on the icmp packet */
10047 + icmp_send(skb, ICMP_TIME_EXCEEDED,
10048 + ICMP_EXC_TTL, 0);
10055 + * If we are at INPUT the checksum must be recalculated since
10056 + * the length could change as the result of a defragmentation.
10058 + if(hooknum == NF_IP_LOCAL_IN) {
10059 + iph->ttl = iph->ttl - 1;
10061 + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
10063 + ip_decrease_ttl(iph);
10067 + /* Tell conntrack to forget this packet since it may get confused
10068 + * when a packet is leaving with dst address == our address.
10069 + * Good idea ? Dunno. Need advice.
10071 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
10072 + nf_conntrack_put(skb->nfct);
10073 + skb->nfct = NULL;
10074 + skb->nfcache = 0;
10075 +#ifdef CONFIG_NETFILTER_DEBUG
10076 + skb->nf_debug = 0;
10080 + if (route_info->oif[0] != '\0')
10081 + return route_oif(route_info, *pskb);
10083 + if (route_info->iif[0] != '\0')
10084 + return route_iif(route_info, *pskb);
10086 + if (route_info->gw)
10087 + return route_gw(route_info, *pskb);
10089 + if (net_ratelimit())
10090 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
10092 + return IPT_CONTINUE;
10096 +static int ipt_route_checkentry(const char *tablename,
10097 + const struct ipt_entry *e,
10099 + unsigned int targinfosize,
10100 + unsigned int hook_mask)
10102 + if (strcmp(tablename, "mangle") != 0) {
10103 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
10108 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
10109 + | (1 << NF_IP_LOCAL_IN)
10110 + | (1 << NF_IP_FORWARD)
10111 + | (1 << NF_IP_LOCAL_OUT)
10112 + | (1 << NF_IP_POST_ROUTING))) {
10113 + printk("ipt_ROUTE: bad hook\n");
10117 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
10118 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
10120 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
10128 +static struct ipt_target ipt_route_reg = {
10130 + .target = ipt_route_target,
10131 + .checkentry = ipt_route_checkentry,
10132 + .me = THIS_MODULE,
10135 +static int __init init(void)
10137 + return ipt_register_target(&ipt_route_reg);
10141 +static void __exit fini(void)
10143 + ipt_unregister_target(&ipt_route_reg);
10146 +module_init(init);
10147 +module_exit(fini);
10148 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.7/net/ipv4/netfilter/ipt_TARPIT.c
10149 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
10150 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TARPIT.c 2004-06-25 12:21:29.280940360 +0200
10153 + * Kernel module to capture and hold incoming TCP connections using
10154 + * no local per-connection resources.
10156 + * Based on ipt_REJECT.c and offering functionality similar to
10157 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
10159 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
10161 + * This program is free software; you can redistribute it and/or modify
10162 + * it under the terms of the GNU General Public License as published by
10163 + * the Free Software Foundation; either version 2 of the License, or
10164 + * (at your option) any later version.
10166 + * This program is distributed in the hope that it will be useful,
10167 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10168 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10169 + * GNU General Public License for more details.
10171 + * You should have received a copy of the GNU General Public License
10172 + * along with this program; if not, write to the Free Software
10173 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10176 + * - Allow incoming TCP connections to be established.
10177 + * - Passing data should result in the connection being switched to the
10178 + * persist state (0 byte window), in which the remote side stops sending
10179 + * data and asks to continue every 60 seconds.
10180 + * - Attempts to shut down the connection should be ignored completely, so
10181 + * the remote side ends up having to time it out.
10184 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
10185 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
10186 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
10189 +#include <linux/config.h>
10190 +#include <linux/module.h>
10191 +#include <linux/skbuff.h>
10192 +#include <linux/ip.h>
10193 +#include <net/ip.h>
10194 +#include <net/tcp.h>
10195 +#include <net/icmp.h>
10197 +#include <net/route.h>
10198 +#include <linux/random.h>
10199 +#include <linux/netfilter_ipv4/ip_tables.h>
10202 +#define DEBUGP printk
10204 +#define DEBUGP(format, args...)
10207 +MODULE_LICENSE("GPL");
10208 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
10210 +/* Stolen from ip_finish_output2 */
10211 +static int ip_direct_send(struct sk_buff *skb)
10213 + struct dst_entry *dst = skb->dst;
10214 + struct hh_cache *hh = dst->hh;
10217 + read_lock_bh(&hh->hh_lock);
10218 + memcpy(skb->data - 16, hh->hh_data, 16);
10219 + read_unlock_bh(&hh->hh_lock);
10220 + skb_push(skb, hh->hh_len);
10221 + return hh->hh_output(skb);
10222 + } else if (dst->neighbour)
10223 + return dst->neighbour->output(skb);
10225 + if (net_ratelimit())
10226 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
10233 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
10235 + struct sk_buff *nskb;
10236 + struct rtable *nrt;
10237 + struct tcphdr *otcph, *ntcph;
10238 + struct flowi fl = {};
10239 + unsigned int otcplen;
10242 + /* A truncated TCP header isn't going to be useful */
10243 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
10246 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
10247 + + oskb->nh.iph->ihl);
10248 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
10250 + /* No replies for RST or FIN */
10251 + if (otcph->rst || otcph->fin)
10254 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
10255 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
10258 + /* Check checksum. */
10259 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
10260 + oskb->nh.iph->daddr,
10261 + csum_partial((char *)otcph, otcplen, 0)) != 0)
10264 + /* Copy skb (even if skb is about to be dropped, we can't just
10265 + clone it because there may be other things, such as tcpdump,
10266 + interested in it) */
10267 + nskb = skb_copy(oskb, GFP_ATOMIC);
10271 + /* This packet will not be the same as the other: clear nf fields */
10272 + nf_conntrack_put(nskb->nfct);
10273 + nskb->nfct = NULL;
10274 + nskb->nfcache = 0;
10275 +#ifdef CONFIG_NETFILTER_DEBUG
10276 + nskb->nf_debug = 0;
10279 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
10281 + /* Truncate to length (no data) */
10282 + ntcph->doff = sizeof(struct tcphdr)/4;
10283 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
10284 + nskb->nh.iph->tot_len = htons(nskb->len);
10286 + /* Swap source and dest */
10287 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
10288 + tmp = ntcph->source;
10289 + ntcph->source = ntcph->dest;
10290 + ntcph->dest = tmp;
10292 + /* Use supplied sequence number or make a new one */
10293 + ntcph->seq = otcph->ack ? otcph->ack_seq
10294 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
10295 + nskb->nh.iph->daddr,
10299 + /* Our SYN-ACKs must have a >0 window */
10300 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
10302 + ntcph->urg_ptr = 0;
10304 + /* Reset flags */
10305 + ((u_int8_t *)ntcph)[13] = 0;
10307 + if (otcph->syn && otcph->ack) {
10309 + ntcph->ack_seq = 0;
10311 + ntcph->syn = otcph->syn;
10313 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
10316 + /* Adjust TCP checksum */
10317 + ntcph->check = 0;
10318 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
10319 + nskb->nh.iph->saddr,
10320 + nskb->nh.iph->daddr,
10321 + csum_partial((char *)ntcph,
10322 + sizeof(struct tcphdr), 0));
10324 + /* Adjust IP TTL */
10325 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
10327 + /* Set DF, id = 0 */
10328 + nskb->nh.iph->frag_off = htons(IP_DF);
10329 + nskb->nh.iph->id = 0;
10331 + /* Adjust IP checksum */
10332 + nskb->nh.iph->check = 0;
10333 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
10334 + nskb->nh.iph->ihl);
10336 + fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
10337 + fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
10338 + fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
10341 + if (ip_route_output_key(&nrt, &fl))
10344 + dst_release(nskb->dst);
10345 + nskb->dst = &nrt->u.dst;
10347 + /* "Never happens" */
10348 + if (nskb->len > dst_pmtu(nskb->dst))
10351 + ip_direct_send (nskb);
10360 +static unsigned int tarpit(struct sk_buff **pskb,
10361 + const struct net_device *in,
10362 + const struct net_device *out,
10363 + unsigned int hooknum,
10364 + const void *targinfo,
10367 + struct sk_buff *skb = *pskb;
10368 + struct rtable *rt = (struct rtable*)skb->dst;
10370 + /* Do we have an input route cache entry? */
10374 + /* No replies to physical multicast/broadcast */
10375 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
10378 + /* Now check at the protocol level */
10379 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
10382 + /* Our naive response construction doesn't deal with IP
10383 + options, and probably shouldn't try. */
10384 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
10387 + /* We aren't interested in fragments */
10388 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
10391 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
10397 +static int check(const char *tablename,
10398 + const struct ipt_entry *e,
10400 + unsigned int targinfosize,
10401 + unsigned int hook_mask)
10403 + /* Only allow these for input/forward packet filtering. */
10404 + if (strcmp(tablename, "filter") != 0) {
10405 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
10408 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
10409 + | (1 << NF_IP_FORWARD))) != 0) {
10410 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
10414 + /* Must specify that it's a TCP packet */
10415 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
10416 + DEBUGP("TARPIT: not valid for non-tcp\n");
10423 +static struct ipt_target ipt_tarpit_reg = {
10424 + .name = "TARPIT",
10425 + .target = tarpit,
10426 + .checkentry = check,
10427 + .me = THIS_MODULE
10430 +static int __init init(void)
10432 + return ipt_register_target(&ipt_tarpit_reg);
10435 +static void __exit fini(void)
10437 + ipt_unregister_target(&ipt_tarpit_reg);
10440 +module_init(init);
10441 +module_exit(fini);
10442 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.7/net/ipv4/netfilter/ipt_TRACE.c
10443 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
10444 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TRACE.c 2004-06-25 12:21:30.341779088 +0200
10446 +/* This is a module which is used for setting
10447 + * the NFC_TRACE flag in the nfcache field of an skb.
10449 +#include <linux/module.h>
10450 +#include <linux/skbuff.h>
10452 +#include <linux/netfilter_ipv4/ip_tables.h>
10454 +static unsigned int
10455 +target(struct sk_buff **pskb,
10456 + const struct net_device *in,
10457 + const struct net_device *out,
10458 + unsigned int hooknum,
10459 + const void *targinfo,
10462 + (*pskb)->nfcache |= NFC_TRACE;
10463 + return IPT_CONTINUE;
10467 +checkentry(const char *tablename,
10468 + const struct ipt_entry *e,
10470 + unsigned int targinfosize,
10471 + unsigned int hook_mask)
10473 + if (targinfosize != 0) {
10474 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
10479 + if (strcmp(tablename, "raw") != 0) {
10480 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
10487 +static struct ipt_target ipt_trace_reg = {
10489 + .target = target,
10490 + .checkentry = checkentry,
10491 + .me = THIS_MODULE
10494 +static int __init init(void)
10496 + if (ipt_register_target(&ipt_trace_reg))
10502 +static void __exit fini(void)
10504 + ipt_unregister_target(&ipt_trace_reg);
10507 +module_init(init);
10508 +module_exit(fini);
10509 +MODULE_LICENSE("GPL");
10510 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c
10511 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
10512 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c 2004-06-25 12:21:07.942184344 +0200
10514 +/* TTL modification target for IP tables
10515 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
10517 + * Version: $Revision$
10519 + * This software is distributed under the terms of GNU GPL
10522 +#include <linux/module.h>
10523 +#include <linux/skbuff.h>
10524 +#include <linux/ip.h>
10525 +#include <net/checksum.h>
10527 +#include <linux/netfilter_ipv4/ip_tables.h>
10528 +#include <linux/netfilter_ipv4/ipt_TTL.h>
10530 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
10531 +MODULE_DESCRIPTION("IP tables TTL modification module");
10532 +MODULE_LICENSE("GPL");
10534 +static unsigned int
10535 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
10536 + const struct net_device *out, unsigned int hooknum,
10537 + const void *targinfo, void *userinfo)
10539 + struct iphdr *iph;
10540 + const struct ipt_TTL_info *info = targinfo;
10541 + u_int16_t diffs[2];
10544 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
10547 + iph = (*pskb)->nh.iph;
10549 + switch (info->mode) {
10550 + case IPT_TTL_SET:
10551 + new_ttl = info->ttl;
10553 + case IPT_TTL_INC:
10554 + new_ttl = iph->ttl + info->ttl;
10555 + if (new_ttl > 255)
10558 + case IPT_TTL_DEC:
10559 + new_ttl = iph->ttl + info->ttl;
10564 + new_ttl = iph->ttl;
10568 + if (new_ttl != iph->ttl) {
10569 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
10570 + iph->ttl = new_ttl;
10571 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
10572 + iph->check = csum_fold(csum_partial((char *)diffs,
10574 + iph->check^0xFFFF));
10575 + (*pskb)->nfcache |= NFC_ALTERED;
10578 + return IPT_CONTINUE;
10581 +static int ipt_ttl_checkentry(const char *tablename,
10582 + const struct ipt_entry *e,
10584 + unsigned int targinfosize,
10585 + unsigned int hook_mask)
10587 + struct ipt_TTL_info *info = targinfo;
10589 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
10590 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
10592 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
10596 + if (strcmp(tablename, "mangle")) {
10597 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
10601 + if (info->mode > IPT_TTL_MAXMODE) {
10602 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
10607 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
10608 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
10615 +static struct ipt_target ipt_TTL = {
10617 + .target = ipt_ttl_target,
10618 + .checkentry = ipt_ttl_checkentry,
10619 + .me = THIS_MODULE
10622 +static int __init init(void)
10624 + return ipt_register_target(&ipt_TTL);
10627 +static void __exit fini(void)
10629 + ipt_unregister_target(&ipt_TTL);
10632 +module_init(init);
10633 +module_exit(fini);
10634 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.7/net/ipv4/netfilter/ipt_XOR.c
10635 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
10636 +++ linux-2.6.7/net/ipv4/netfilter/ipt_XOR.c 2004-06-25 12:21:31.655579360 +0200
10638 +/* XOR target for IP tables
10639 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
10640 + * Based on ipt_TTL.c
10644 + * This software is distributed under the terms of GNU GPL
10647 +#include <linux/module.h>
10648 +#include <linux/skbuff.h>
10649 +#include <linux/ip.h>
10650 +#include <linux/tcp.h>
10651 +#include <linux/udp.h>
10653 +#include <linux/netfilter_ipv4/ip_tables.h>
10654 +#include <linux/netfilter_ipv4/ipt_XOR.h>
10656 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
10657 +MODULE_DESCRIPTION("IP tables XOR module");
10658 +MODULE_LICENSE("GPL");
10660 +static unsigned int
10661 +ipt_xor_target(struct sk_buff **pskb,
10662 + const struct net_device *in, const struct net_device *out,
10663 + unsigned int hooknum, const void *targinfo, void *userinfo)
10665 + struct ipt_XOR_info *info = (void *) targinfo;
10666 + struct iphdr *iph;
10667 + struct tcphdr *tcph;
10668 + struct udphdr *udph;
10671 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
10674 + iph = (*pskb)->nh.iph;
10676 + if (iph->protocol == IPPROTO_TCP) {
10677 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
10678 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
10679 + for (k=0; k<=info->block_size; k++) {
10680 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
10685 + if (info->key[j] == 0x00)
10688 + } else if (iph->protocol == IPPROTO_UDP) {
10689 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
10690 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
10691 + for (k=0; k<=info->block_size; k++) {
10692 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
10697 + if (info->key[j] == 0x00)
10702 + return IPT_CONTINUE;
10705 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
10706 + void *targinfo, unsigned int targinfosize,
10707 + unsigned int hook_mask)
10709 + struct ipt_XOR_info *info = targinfo;
10711 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
10712 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
10713 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
10717 + if (strcmp(tablename, "mangle")) {
10718 + printk(KERN_WARNING "XOR: can only be called from"
10719 + "\"mangle\" table, not \"%s\"\n", tablename);
10723 + if (!strcmp(info->key, "")) {
10724 + printk(KERN_WARNING "XOR: You must specify a key");
10728 + if (info->block_size == 0) {
10729 + printk(KERN_WARNING "XOR: You must specify a block-size");
10736 +static struct ipt_target ipt_XOR = {
10738 + .target = ipt_xor_target,
10739 + .checkentry = ipt_xor_checkentry,
10740 + .me = THIS_MODULE,
10743 +static int __init init(void)
10745 + return ipt_register_target(&ipt_XOR);
10748 +static void __exit fini(void)
10750 + ipt_unregister_target(&ipt_XOR);
10753 +module_init(init);
10754 +module_exit(fini);
10755 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_account.c linux-2.6.7/net/ipv4/netfilter/ipt_account.c
10756 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_account.c 1970-01-01 01:00:00.000000000 +0100
10757 +++ linux-2.6.7/net/ipv4/netfilter/ipt_account.c 2004-06-25 12:21:32.614433592 +0200
10760 + * accounting match (ipt_account.c)
10761 + * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
10765 + * This software is distributed under the terms of GNU GPL
10768 +#include <linux/module.h>
10769 +#include <linux/skbuff.h>
10770 +#include <linux/proc_fs.h>
10771 +#include <linux/spinlock.h>
10772 +#include <linux/vmalloc.h>
10773 +#include <linux/interrupt.h>
10775 +#include <asm/uaccess.h>
10777 +#include <linux/ip.h>
10778 +#include <linux/tcp.h>
10779 +#include <linux/udp.h>
10781 +#include <linux/netfilter_ipv4/ip_tables.h>
10782 +#include <linux/netfilter_ipv4/ipt_account.h>
10784 +static char version[] =
10785 +KERN_INFO "ipt_account 0.1.5 : Piotr Gasid³o <quaker@barbara.eu.org>, http://www.barbara.eu.org/~quaker/ipt_account/\n";
10787 +/* default rights for files created in /proc/net/ipt_account/ */
10788 +static int ip_list_perms = 0644;
10791 + * safe netmask, if you want account traffic for networks
10792 + * bigger that /17 you must specify ip_list_max_hosts parameter
10795 +static int ip_list_max_mask = 17;
10796 +static int ip_list_max_hosts_count;
10797 +static int debug = 0;
10799 +/* module information */
10800 +MODULE_AUTHOR("Piotr Gasid³o <quaker@barbara.eu.org>");
10801 +MODULE_DESCRIPTION("Traffic accounting modules");
10802 +MODULE_LICENSE("GPL");
10803 +MODULE_PARM(ip_list_perms,"i");
10804 +MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_account/* files");
10805 +MODULE_PARM(ip_list_max_mask, "i");
10806 +MODULE_PARM_DESC(ip_list_max_mask, "maximum *save* size of one list (netmask)");
10808 +MODULE_PARM(debug,"i");
10809 +MODULE_PARM_DESC(debug,"debugging level, defaults to 0");
10812 +/* structure with statistics counters */
10813 +struct t_ipt_account_stat {
10814 + u_int64_t b_all, b_tcp, b_udp, b_icmp, b_other; /* byte counters for all/tcp/udp/icmp/other traffic */
10815 + u_int64_t p_all, p_tcp, p_udp, p_icmp, p_other; /* packet counters for all/tcp/udp/icmp/other traffic */
10818 +/* structure holding to/from statistics for single ip */
10819 +struct t_ipt_account_ip_list {
10820 + struct t_ipt_account_stat src;
10821 + struct t_ipt_account_stat dest;
10824 +/* structure describing single table */
10825 +struct t_ipt_account_table {
10826 + char name[IPT_ACCOUNT_NAME_LEN]; /* table name ( = filename in /proc/net/ipt_account/) */
10827 + struct t_ipt_account_ip_list *ip_list; /* table with statistics for each ip in network/netmask */
10828 + struct t_ipt_account_table *next;
10829 + u_int32_t network; /* network/netmask covered by table*/
10830 + u_int32_t netmask;
10831 + int use_count; /* rules counter - counting number of rules using this table */
10832 + spinlock_t ip_list_lock;
10833 + struct proc_dir_entry *status_proc_64, *status_proc_32;
10836 +/* we must use spinlocks to avoid parallel modifications of table list */
10837 +static spinlock_t ipt_account_tables_lock = SPIN_LOCK_UNLOCKED;
10839 +static struct proc_dir_entry *proc_net_ipt_account = NULL;
10841 +/* root pointer holding list of the tables */
10842 +static struct t_ipt_account_table *ipt_account_tables = NULL;
10844 +static int ip_list_read_proc_64(char *buffer, char **start, off_t offset,
10845 + int length, int *eof, void *data) {
10847 + int len = 0, last_len = 0;
10848 + off_t pos = 0, begin = 0;
10850 + u_int32_t address, index;
10852 + struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
10854 + spin_lock(&table->ip_list_lock);
10855 + for (address = table->network; (u_int32_t)(address & table->netmask) == (u_int32_t)(table->network); address++) {
10857 + index = address - table->network;
10858 + len += sprintf(buffer + len,
10859 + "ip = %u.%u.%u.%u bytes_src = %llu %llu %llu %llu %llu packets_src = %llu %llu %llu %llu %llu bytes_dest = %llu %llu %llu %llu %llu packets_dest = %llu %llu %llu %llu %llu\n",
10860 + HIPQUAD(address),
10861 + table->ip_list[index].src.b_all,
10862 + table->ip_list[index].src.b_tcp,
10863 + table->ip_list[index].src.b_udp,
10864 + table->ip_list[index].src.b_icmp,
10865 + table->ip_list[index].src.b_other,
10867 + table->ip_list[index].src.p_all,
10868 + table->ip_list[index].src.p_tcp,
10869 + table->ip_list[index].src.p_udp,
10870 + table->ip_list[index].src.p_icmp,
10871 + table->ip_list[index].src.p_other,
10873 + table->ip_list[index].dest.b_all,
10874 + table->ip_list[index].dest.b_tcp,
10875 + table->ip_list[index].dest.b_udp,
10876 + table->ip_list[index].dest.b_icmp,
10877 + table->ip_list[index].dest.b_other,
10879 + table->ip_list[index].dest.p_all,
10880 + table->ip_list[index].dest.p_tcp,
10881 + table->ip_list[index].dest.p_udp,
10882 + table->ip_list[index].dest.p_icmp,
10883 + table->ip_list[index].dest.p_other
10885 + pos = begin + len;
10886 + if (pos < offset) {
10890 + if (pos > offset + length) {
10895 + spin_unlock(&table->ip_list_lock);
10896 + *start = buffer + (offset - begin);
10897 + len -= (offset - begin);
10898 + if (len > length)
10903 +static int ip_list_read_proc_32(char *buffer, char **start, off_t offset,
10904 + int length, int *eof, void *data) {
10906 + int len = 0, last_len = 0;
10907 + off_t pos = 0, begin = 0;
10909 + u_int32_t address, index;
10911 + struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
10913 + spin_lock(&table->ip_list_lock);
10914 + for (address = table->network; (u_int32_t)(address & table->netmask) == (u_int32_t)(table->network); address++) {
10916 + index = address - table->network;
10917 + len += sprintf(buffer + len,
10918 + "ip = %u.%u.%u.%u bytes_src = %u %u %u %u %u packets_src = %u %u %u %u %u bytes_dest = %u %u %u %u %u packets_dest = %u %u %u %u %u\n",
10919 + HIPQUAD(address),
10920 + (u_int32_t)table->ip_list[index].src.b_all,
10921 + (u_int32_t)table->ip_list[index].src.b_tcp,
10922 + (u_int32_t)table->ip_list[index].src.b_udp,
10923 + (u_int32_t)table->ip_list[index].src.b_icmp,
10924 + (u_int32_t)table->ip_list[index].src.b_other,
10926 + (u_int32_t)table->ip_list[index].src.p_all,
10927 + (u_int32_t)table->ip_list[index].src.p_tcp,
10928 + (u_int32_t)table->ip_list[index].src.p_udp,
10929 + (u_int32_t)table->ip_list[index].src.p_icmp,
10930 + (u_int32_t)table->ip_list[index].src.p_other,
10932 + (u_int32_t)table->ip_list[index].dest.b_all,
10933 + (u_int32_t)table->ip_list[index].dest.b_tcp,
10934 + (u_int32_t)table->ip_list[index].dest.b_udp,
10935 + (u_int32_t)table->ip_list[index].dest.b_icmp,
10936 + (u_int32_t)table->ip_list[index].dest.b_other,
10938 + (u_int32_t)table->ip_list[index].dest.p_all,
10939 + (u_int32_t)table->ip_list[index].dest.p_tcp,
10940 + (u_int32_t)table->ip_list[index].dest.p_udp,
10941 + (u_int32_t)table->ip_list[index].dest.p_icmp,
10942 + (u_int32_t)table->ip_list[index].dest.p_other
10945 + pos = begin + len;
10946 + if (pos < offset) {
10950 + if (pos > offset + length) {
10955 + spin_unlock(&table->ip_list_lock);
10956 + *start = buffer + (offset - begin);
10957 + len -= (offset - begin);
10958 + if (len > length)
10963 +static int ip_list_write_proc(struct file *file, const char *buffer,
10964 + unsigned long length, void *data) {
10966 + int len = (length > 1024) ? length : 1024;
10967 + struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
10968 + char kernel_buffer[1024];
10969 + u_int32_t hosts_count = INADDR_BROADCAST - table->netmask + 1;
10971 + copy_from_user(kernel_buffer, buffer, len);
10972 + kernel_buffer[len - 1] = 0;
10974 + /* echo "reset" > /proc/net/ipt_recent/table clears the table */
10975 + if (!strncmp(kernel_buffer, "reset", len)) {
10976 + spin_lock(&table->ip_list_lock);
10977 + memset(table->ip_list, 0, sizeof(struct t_ipt_account_ip_list) * hosts_count);
10978 + spin_unlock(&table->ip_list_lock);
10984 +/* do raw accounting */
10985 +static void do_account(struct t_ipt_account_stat *stat, u_int8_t proto, u_int16_t pktlen) {
10987 + /* update packet & bytes counters in *stat structure */
10988 + stat->b_all += pktlen;
10992 + case IPPROTO_TCP:
10993 + stat->b_tcp += pktlen;
10996 + case IPPROTO_UDP:
10997 + stat->b_udp += pktlen;
11000 + case IPPROTO_ICMP:
11001 + stat->b_icmp += pktlen;
11005 + stat->b_other += pktlen;
11010 +static int match(const struct sk_buff *skb,
11011 + const struct net_device *in,
11012 + const struct net_device *out,
11013 + const void *matchinfo,
11016 + u_int16_t datalen,
11020 + const struct t_ipt_account_info *info = (struct t_ipt_account_info*)matchinfo;
11021 + struct t_ipt_account_table *table;
11024 + u_int32_t address;
11025 + u_int16_t pktlen;
11029 + printk(KERN_INFO "ipt_account: match() entering.\n");
11030 + printk(KERN_INFO "ipt_account: match() match name = %s.\n", info->name);
11033 + spin_lock(&ipt_account_tables_lock);
11034 + /* find the right table */
11035 + table = ipt_account_tables;
11036 + while (table && strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
11037 + spin_unlock(&ipt_account_tables_lock);
11039 + if (table == NULL) {
11040 + /* ups, no table with that name */
11042 + printk(KERN_INFO "ipt_account: match() table %s not found. Leaving.\n", info->name);
11047 + printk(KERN_INFO "ipt_account: match() table found %s\n", table->name);
11049 + /* default: no match */
11052 + /* get packet protocol/length */
11053 + pktlen = skb->len;
11054 + proto = skb->nh.iph->protocol;
11057 + printk(KERN_INFO "ipt_account: match() got packet src = %u.%u.%u.%u, dst = %u.%u.%u.%u, proto = %u.\n",
11058 + NIPQUAD(skb->nh.iph->saddr),
11059 + NIPQUAD(skb->nh.iph->daddr),
11063 + /* check whether traffic from source ip address ... */
11064 + address = ntohl(skb->nh.iph->saddr);
11066 + /* ... is being accounted by this table */
11067 + if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
11069 + printk(KERN_INFO "ipt_account: match() accounting packet src = %u.%u.%u.%u, proto = %u.\n",
11070 + HIPQUAD(address),
11073 + /* yes, account this packet */
11074 + spin_lock(&table->ip_list_lock);
11075 + /* update counters this host */
11076 + do_account(&table->ip_list[(u_int32_t)(address - table->network)].src, proto, pktlen);
11077 + /* update counters for all hosts in this table (network address) */
11078 + if (table->netmask != INADDR_BROADCAST)
11079 + do_account(&table->ip_list[0].src, proto, pktlen);
11080 + spin_unlock(&table->ip_list_lock);
11081 + /* yes, it's a match */
11085 + /* do the same thing with destination ip address */
11086 + address = ntohl(skb->nh.iph->daddr);
11087 + if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
11089 + printk(KERN_INFO "ipt_account: match() accounting packet dst = %u.%u.%u.%u, proto = %u.\n",
11090 + HIPQUAD(address),
11093 + spin_lock(&table->ip_list_lock);
11094 + do_account(&table->ip_list[(u_int32_t)(address - table->network)].dest, proto, pktlen);
11095 + if (table->netmask != INADDR_BROADCAST)
11096 + do_account(&table->ip_list[0].dest, proto, pktlen);
11097 + spin_unlock(&table->ip_list_lock);
11103 + printk(KERN_INFO "ipt_account: match() leaving.\n");
11109 +static int checkentry(const char *tablename,
11110 + const struct ipt_ip *ip,
11112 + unsigned int matchinfosize,
11113 + unsigned int hook_mask)
11115 + const struct t_ipt_account_info *info = matchinfo;
11116 + struct t_ipt_account_table *table;
11118 + char proc_entry_name[IPT_ACCOUNT_NAME_LEN + 3];
11120 + u_int32_t hosts_count;
11123 + printk(KERN_INFO "ipt_account: checkentry() entering.\n");
11125 + if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info)))
11128 + if (!info->name || !info->name[0])
11131 + /* find whether table with this name already exists */
11132 + spin_lock(&ipt_account_tables_lock);
11133 + table = ipt_account_tables;
11134 + while (table && strncmp(info->name, table->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
11137 + /* yes, table exists */
11138 + if (info->network != table->network || info->netmask != table->netmask) {
11140 + * tried to do accounting in existing table, but network/netmask in iptable rule
11141 + * doesn't match network/netmask in table structure - deny adding the rule
11143 + printk(KERN_ERR "ipt_account: checkentry() table %s found. But table netmask/network %u.%u.%u.%u/%u.%u.%u.%u differs from rule netmask/network %u.%u.%u.%u/%u.%u.%u.%u. Leaving without creating entry.\n",
11145 + HIPQUAD(table->network),
11146 + HIPQUAD(table->netmask),
11147 + HIPQUAD(info->network),
11148 + HIPQUAD(info->netmask)
11150 + spin_unlock(&ipt_account_tables_lock);
11154 + printk(KERN_INFO "ipt_account: checkentry() table %s found. Incrementing use count (use_count = %i). Leaving.\n", table->name, table->use_count);
11155 + /* increase table use count */
11156 + table->use_count++;
11157 + spin_unlock(&ipt_account_tables_lock);
11158 + /* everything went okey */
11163 + printk(KERN_INFO "ipt_account: checkentry() table %s not found. Creating.\n", info->name);
11165 + /* table doesn't exist - create one */
11166 + table = vmalloc(sizeof(struct t_ipt_account_table));
11167 + if (table == NULL) {
11169 + printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (t_account_table) for table %s. Leaving.\n", info->name);
11170 + spin_unlock(&ipt_account_tables_lock);
11174 + /* set table parameters */
11175 + strncpy(table->name, info->name, IPT_ACCOUNT_NAME_LEN);
11176 + table->use_count = 1;
11177 + table->network = info->network;
11178 + table->netmask = info->netmask;
11179 + table->ip_list_lock = SPIN_LOCK_UNLOCKED;
11181 + hosts_count = INADDR_BROADCAST - table->netmask + 1;
11184 + printk(KERN_INFO "ipt_account: checkentry() allocating memory for %u hosts (%u netmask).\n", hosts_count, info->netmask);
11186 + /* check whether table is not too big */
11187 + if (hosts_count > ip_list_max_hosts_count) {
11188 + printk(KERN_ERR "ipt_account: checkentry() unable allocate memory for %u hosts (%u netmask). Increase value of ip_list_max_mask parameter.\n", hosts_count, info->netmask);
11190 + spin_unlock(&ipt_account_tables_lock);
11194 + table->ip_list = vmalloc(sizeof(struct t_ipt_account_ip_list) * hosts_count);
11195 + if (table->ip_list == NULL) {
11197 + printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (t_account_ip_list) for table %s. Leaving.\n", table->name);
11199 + spin_unlock(&ipt_account_tables_lock);
11203 + memset(table->ip_list, 0, sizeof(struct t_ipt_account_ip_list) * hosts_count);
11206 + * create entries in /proc/net/ipt_account: one with full 64-bit counters and
11207 + * second with 32-bit ones. The second can be used in programs supporting only 32-bit numbers
11208 + * (mrtg, rrdtool).
11211 + strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11212 + strncat(proc_entry_name, "_64", 4);
11214 + table->status_proc_64 = create_proc_entry(proc_entry_name, ip_list_perms, proc_net_ipt_account);
11215 + if (table->status_proc_64 == NULL) {
11217 + printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (status_proc_64) for table %s. Leaving.\n", table->name);
11218 + vfree(table->ip_list);
11220 + spin_unlock(&ipt_account_tables_lock);
11224 + table->status_proc_64->owner = THIS_MODULE;
11225 + table->status_proc_64->read_proc = ip_list_read_proc_64;
11226 + table->status_proc_64->write_proc = ip_list_write_proc;
11227 + table->status_proc_64->data = table;
11229 + strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11230 + strncat(proc_entry_name, "_32", 4);
11232 + table->status_proc_32 = create_proc_entry(proc_entry_name, ip_list_perms, proc_net_ipt_account);
11233 + if (table->status_proc_32 == NULL) {
11235 + printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (status_proc_32) for table %s. Leaving.\n", table->name);
11236 + vfree(table->ip_list);
11238 + spin_unlock(&ipt_account_tables_lock);
11242 + table->status_proc_32->owner = THIS_MODULE;
11243 + table->status_proc_32->read_proc = ip_list_read_proc_32;
11244 + table->status_proc_32->write_proc = ip_list_write_proc;
11245 + table->status_proc_32->data = table;
11247 + /* finaly, insert table into list */
11248 + table->next = ipt_account_tables;
11249 + ipt_account_tables = table;
11252 + printk(KERN_INFO "ipt_account: checkentry() successfully created table %s (use_count = %i).\n", table->name, table->use_count);
11254 + spin_unlock(&ipt_account_tables_lock);
11257 + printk(KERN_INFO "ipt_account: checkentry() leaving.\n");
11261 +static void destroy(void *matchinfo,
11262 + unsigned int matchinfosize)
11264 + const struct t_ipt_account_info *info = matchinfo;
11265 + struct t_ipt_account_table *table, *last_table;
11266 + char proc_entry_name[IPT_ACCOUNT_NAME_LEN + 3];
11269 + printk(KERN_INFO "ipt_account: destroy() entered.\n");
11271 + if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info)))
11274 + spin_lock(&ipt_account_tables_lock);
11275 + table = ipt_account_tables;
11277 + if (table == NULL) {
11278 + /* list is empty, sometheing is realy wrong! */
11280 + printk(KERN_INFO "ipt_account: destroy() unable to found any tables (asked for %s). Leaving.\n", info->name);
11281 + spin_unlock(&ipt_account_tables_lock);
11285 + /* find table combined with this rule - this code is taken for ipt_recent ;) */
11286 + last_table = NULL;
11287 + while (strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next));
11289 + if (table == NULL) {
11290 + printk(KERN_ERR "ipt_account: destroy() unable to found table %s. Leaving.\n", info->name);
11291 + spin_unlock(&ipt_account_tables_lock);
11295 + /* decrease table use counter */
11296 + table->use_count--;
11297 + if (table->use_count != 0) {
11298 + /* table is used by other rule, can't remove it */
11300 + printk(KERN_INFO "ipt_account: destroy() table %s is still used (use_count = %i). Leaving.\n", table->name, table->use_count);
11301 + spin_unlock(&ipt_account_tables_lock);
11305 + /* table is not used by any other tule - remove it */
11307 + printk(KERN_INFO "ipt_account: destroy() removing table %s (use_count = %i).\n", table->name, table->use_count);
11310 + last_table->next = table->next;
11312 + ipt_account_tables = table->next;
11314 + spin_lock(&table->ip_list_lock);
11315 + spin_unlock(&table->ip_list_lock);
11317 + /* remove procfs entries */
11318 + strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11319 + strncat(proc_entry_name, "_64", 4);
11320 + remove_proc_entry(proc_entry_name, proc_net_ipt_account);
11321 + strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11322 + strncat(proc_entry_name, "_32", 4);
11323 + remove_proc_entry(proc_entry_name, proc_net_ipt_account);
11324 + vfree(table->ip_list);
11327 + spin_unlock(&ipt_account_tables_lock);
11330 + printk(KERN_INFO "account: destroy() leaving.\n");
11335 +static struct ipt_match account_match = {
11344 +static int __init init(void)
11348 + printk(KERN_INFO "account: __init(): ip_list_perms = %i, ip_list_max_mask = %i\n", ip_list_perms, ip_list_max_mask);
11349 + /* check params */
11350 + if (ip_list_max_mask > 32 || ip_list_max_mask < 0) {
11351 + printk(KERN_ERR "account: Wrong netmask given by ip_list_max_mask parameter (%u). Valid is 32 to 0.\n", ip_list_max_mask);
11355 + ip_list_max_hosts_count = (1 << (32 - ip_list_max_mask)) + 1;
11357 + /* create /proc/net/ipt_account directory */
11358 + proc_net_ipt_account = proc_mkdir("ipt_account", proc_net);
11359 + if (!proc_net_ipt_account)
11362 + return ipt_register_match(&account_match);
11365 +/* procedura usuwaj±ca modu³ */
11366 +static void __exit fini(void)
11368 + ipt_unregister_match(&account_match);
11369 + /* remove /proc/net/ipt_account/ directory */
11370 + remove_proc_entry("ipt_account", proc_net);
11373 +module_init(init);
11374 +module_exit(fini);
11376 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.7/net/ipv4/netfilter/ipt_connmark.c
11377 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
11378 +++ linux-2.6.7/net/ipv4/netfilter/ipt_connmark.c 2004-06-25 12:21:25.486517200 +0200
11380 +/* This kernel module matches connection mark values set by the
11381 + * CONNMARK target
11383 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
11384 + * by Henrik Nordstrom <hno@marasystems.com>
11386 + * This program is free software; you can redistribute it and/or modify
11387 + * it under the terms of the GNU General Public License as published by
11388 + * the Free Software Foundation; either version 2 of the License, or
11389 + * (at your option) any later version.
11391 + * This program is distributed in the hope that it will be useful,
11392 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11393 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11394 + * GNU General Public License for more details.
11396 + * You should have received a copy of the GNU General Public License
11397 + * along with this program; if not, write to the Free Software
11398 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11401 +#include <linux/module.h>
11402 +#include <linux/skbuff.h>
11404 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
11405 +MODULE_DESCRIPTION("IP tables connmark match module");
11406 +MODULE_LICENSE("GPL");
11408 +#include <linux/netfilter_ipv4/ip_tables.h>
11409 +#include <linux/netfilter_ipv4/ipt_connmark.h>
11410 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11413 +match(const struct sk_buff *skb,
11414 + const struct net_device *in,
11415 + const struct net_device *out,
11416 + const void *matchinfo,
11420 + const struct ipt_connmark_info *info = matchinfo;
11421 + enum ip_conntrack_info ctinfo;
11422 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11426 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
11430 +checkentry(const char *tablename,
11431 + const struct ipt_ip *ip,
11433 + unsigned int matchsize,
11434 + unsigned int hook_mask)
11436 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
11442 +static struct ipt_match connmark_match = {
11443 + .name = "connmark",
11445 + .checkentry = &checkentry,
11446 + .me = THIS_MODULE
11449 +static int __init init(void)
11451 + return ipt_register_match(&connmark_match);
11454 +static void __exit fini(void)
11456 + ipt_unregister_match(&connmark_match);
11459 +module_init(init);
11460 +module_exit(fini);
11461 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c
11462 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
11463 +++ linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c 2004-06-25 12:21:08.429110320 +0200
11465 +/* iptables match extension to limit the number of packets per second
11466 + * seperately for each destination.
11468 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
11472 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
11474 + * based on ipt_limit.c by:
11475 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
11476 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
11477 + * Rusty Russell <rusty@rustcorp.com.au>
11479 + * The general idea is to create a hash table for every dstip and have a
11480 + * seperate limit counter per tuple. This way you can do something like 'limit
11481 + * the number of syn packets for each of my internal addresses.
11483 + * Ideally this would just be implemented as a general 'hash' match, which would
11484 + * allow us to attach any iptables target to it's hash buckets. But this is
11485 + * not possible in the current iptables architecture. As always, pkttables for
11486 + * 2.7.x will help ;)
11488 +#include <linux/module.h>
11489 +#include <linux/skbuff.h>
11490 +#include <linux/spinlock.h>
11491 +#include <linux/random.h>
11492 +#include <linux/jhash.h>
11493 +#include <linux/slab.h>
11494 +#include <linux/vmalloc.h>
11495 +#include <linux/tcp.h>
11496 +#include <linux/udp.h>
11497 +#include <linux/proc_fs.h>
11498 +#include <linux/seq_file.h>
11500 +#define ASSERT_READ_LOCK(x)
11501 +#define ASSERT_WRITE_LOCK(x)
11502 +#include <linux/netfilter_ipv4/lockhelp.h>
11503 +#include <linux/netfilter_ipv4/listhelp.h>
11505 +#include <linux/netfilter_ipv4/ip_tables.h>
11506 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
11508 +/* FIXME: this is just for IP_NF_ASSERRT */
11509 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11511 +#define MS2JIFFIES(x) ((x*HZ)/1000)
11513 +MODULE_LICENSE("GPL");
11514 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
11515 +MODULE_DESCRIPTION("iptables match for limiting per destination");
11517 +/* need to declare this at the top */
11518 +static struct proc_dir_entry *dstlimit_procdir;
11519 +static struct file_operations dl_file_ops;
11521 +/* hash table crap */
11523 +struct dsthash_dst {
11524 + u_int32_t src_ip;
11525 + u_int32_t dst_ip;
11529 +struct dsthash_ent {
11530 + /* static / read-only parts in the beginning */
11531 + struct list_head list;
11532 + struct dsthash_dst dst;
11534 + /* modified structure members in the end */
11535 + unsigned long expires; /* precalculated expiry time */
11537 + unsigned long prev; /* last modification */
11538 + u_int32_t credit;
11539 + u_int32_t credit_cap, cost;
11543 +struct ipt_dstlimit_htable {
11544 + struct list_head list; /* global list of all htables */
11547 + struct dstlimit_cfg cfg; /* config */
11549 + /* used internally */
11550 + spinlock_t lock; /* lock for list_head */
11551 + u_int32_t rnd; /* random seed for hash */
11552 + struct timer_list timer; /* timer for gc */
11553 + atomic_t count; /* number entries in table */
11555 + /* seq_file stuff */
11556 + struct proc_dir_entry *pde;
11558 + struct list_head hash[0]; /* hashtable itself */
11561 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
11562 +static LIST_HEAD(dstlimit_htables);
11563 +static kmem_cache_t *dstlimit_cachep;
11565 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
11567 + return (ent->dst.dst_ip == b->dst_ip
11568 + && ent->dst.port == b->port
11569 + && ent->dst.src_ip == b->src_ip);
11572 +static inline u_int32_t
11573 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
11575 + return (jhash_3words(dst->dst_ip, dst->port,
11576 + dst->src_ip, ht->rnd) % ht->cfg.size);
11579 +static inline struct dsthash_ent *
11580 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11582 + struct dsthash_ent *ent;
11583 + u_int32_t hash = hash_dst(ht, dst);
11584 + MUST_BE_LOCKED(&ht->lock);
11585 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
11589 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
11590 +static struct dsthash_ent *
11591 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11593 + struct dsthash_ent *ent;
11595 + /* initialize hash with random val at the time we allocate
11596 + * the first hashtable entry */
11598 + get_random_bytes(&ht->rnd, 4);
11600 + if (ht->cfg.max &&
11601 + atomic_read(&ht->count) >= ht->cfg.max) {
11602 + /* FIXME: do something. question is what.. */
11603 + if (net_ratelimit())
11604 + printk(KERN_WARNING
11605 + "ipt_dstlimit: max count of %u reached\n",
11610 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
11612 + if (net_ratelimit())
11614 + "ipt_dstlimit: can't allocate dsthash_ent\n");
11618 + atomic_inc(&ht->count);
11620 + ent->dst.dst_ip = dst->dst_ip;
11621 + ent->dst.port = dst->port;
11622 + ent->dst.src_ip = dst->src_ip;
11624 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
11629 +static inline void
11630 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
11632 + MUST_BE_LOCKED(&ht->lock);
11634 + list_del(&ent->list);
11635 + kmem_cache_free(dstlimit_cachep, ent);
11636 + atomic_dec(&ht->count);
11638 +static void htable_gc(unsigned long htlong);
11640 +static int htable_create(struct ipt_dstlimit_info *minfo)
11643 + unsigned int size;
11644 + struct ipt_dstlimit_htable *hinfo;
11646 + if (minfo->cfg.size)
11647 + size = minfo->cfg.size;
11649 + size = (((num_physpages << PAGE_SHIFT) / 16384)
11650 + / sizeof(struct list_head));
11651 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
11656 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
11657 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
11658 + + (sizeof(struct list_head) * size));
11660 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
11663 + minfo->hinfo = hinfo;
11665 + /* copy match config into hashtable config */
11666 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
11667 + hinfo->cfg.size = size;
11668 + if (!hinfo->cfg.max)
11669 + hinfo->cfg.max = 8 * hinfo->cfg.size;
11670 + else if (hinfo->cfg.max < hinfo->cfg.size)
11671 + hinfo->cfg.max = hinfo->cfg.size;
11673 + for (i = 0; i < hinfo->cfg.size; i++)
11674 + INIT_LIST_HEAD(&hinfo->hash[i]);
11676 + atomic_set(&hinfo->count, 0);
11677 + atomic_set(&hinfo->use, 1);
11679 + hinfo->lock = SPIN_LOCK_UNLOCKED;
11680 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
11681 + if (!hinfo->pde) {
11685 + hinfo->pde->proc_fops = &dl_file_ops;
11686 + hinfo->pde->data = hinfo;
11688 + init_timer(&hinfo->timer);
11689 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
11690 + hinfo->timer.data = (unsigned long )hinfo;
11691 + hinfo->timer.function = htable_gc;
11692 + add_timer(&hinfo->timer);
11694 + WRITE_LOCK(&dstlimit_lock);
11695 + list_add(&hinfo->list, &dstlimit_htables);
11696 + WRITE_UNLOCK(&dstlimit_lock);
11701 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11706 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11708 + return (jiffies >= he->expires);
11711 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
11712 + int (*select)(struct ipt_dstlimit_htable *ht,
11713 + struct dsthash_ent *he))
11717 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
11719 + /* lock hash table and iterate over it */
11720 + LOCK_BH(&ht->lock);
11721 + for (i = 0; i < ht->cfg.size; i++) {
11722 + struct dsthash_ent *dh, *n;
11723 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
11724 + if ((*select)(ht, dh))
11725 + __dsthash_free(ht, dh);
11728 + UNLOCK_BH(&ht->lock);
11731 +/* hash table garbage collector, run by timer */
11732 +static void htable_gc(unsigned long htlong)
11734 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
11736 + htable_selective_cleanup(ht, select_gc);
11738 + /* re-add the timer accordingly */
11739 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
11740 + add_timer(&ht->timer);
11743 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
11745 + /* remove timer, if it is pending */
11746 + if (timer_pending(&hinfo->timer))
11747 + del_timer(&hinfo->timer);
11749 + /* remove proc entry */
11750 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
11752 + htable_selective_cleanup(hinfo, select_all);
11756 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
11758 + struct ipt_dstlimit_htable *hinfo;
11760 + READ_LOCK(&dstlimit_lock);
11761 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
11762 + if (!strcmp(name, hinfo->pde->name)) {
11763 + atomic_inc(&hinfo->use);
11764 + READ_UNLOCK(&dstlimit_lock);
11768 + READ_UNLOCK(&dstlimit_lock);
11773 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
11775 + if (atomic_dec_and_test(&hinfo->use)) {
11776 + WRITE_LOCK(&dstlimit_lock);
11777 + list_del(&hinfo->list);
11778 + WRITE_UNLOCK(&dstlimit_lock);
11779 + htable_destroy(hinfo);
11784 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
11785 + * see net/sched/sch_tbf.c in the linux source tree
11788 +/* Rusty: This is my (non-mathematically-inclined) understanding of
11789 + this algorithm. The `average rate' in jiffies becomes your initial
11790 + amount of credit `credit' and the most credit you can ever have
11791 + `credit_cap'. The `peak rate' becomes the cost of passing the
11794 + `prev' tracks the last packet hit: you gain one credit per jiffy.
11795 + If you get credit balance more than this, the extra credit is
11796 + discarded. Every time the match passes, you lose `cost' credits;
11797 + if you don't have that many, the test fails.
11799 + See Alexey's formal explanation in net/sched/sch_tbf.c.
11801 + To get the maximum range, we multiply by this factor (ie. you get N
11802 + credits per jiffy). We want to allow a rate as low as 1 per day
11803 + (slowest userspace tool allows), which means
11804 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
11806 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
11808 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
11809 + * us the power of 2 below the theoretical max, so GCC simply does a
11811 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
11812 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
11813 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
11814 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
11815 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
11816 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
11818 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
11820 +/* Precision saver. */
11821 +static inline u_int32_t
11822 +user2credits(u_int32_t user)
11824 + /* If multiplying would overflow... */
11825 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
11826 + /* Divide first. */
11827 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
11829 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
11832 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
11834 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
11835 + * CREDITS_PER_JIFFY;
11836 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
11837 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
11841 +dstlimit_match(const struct sk_buff *skb,
11842 + const struct net_device *in,
11843 + const struct net_device *out,
11844 + const void *matchinfo,
11848 + struct ipt_dstlimit_info *r =
11849 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
11850 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
11851 + unsigned long now = jiffies;
11852 + struct dsthash_ent *dh;
11853 + struct dsthash_dst dst;
11855 + memset(&dst, 0, sizeof(dst));
11857 + /* dest ip is always in hash */
11858 + dst.dst_ip = skb->nh.iph->daddr;
11860 + /* source ip only if respective hashmode, otherwise set to
11862 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
11863 + dst.src_ip = skb->nh.iph->saddr;
11865 + /* dest port only if respective mode */
11866 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
11869 + /* Must not be a fragment. */
11873 + /* Must be big enough to read ports (both UDP and TCP have
11874 + them at the start). */
11875 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
11876 + /* We've been asked to examine this packet, and we
11877 + can't. Hence, no choice but to drop. */
11882 + switch (skb->nh.iph->protocol) {
11883 + struct tcphdr *th;
11884 + struct udphdr *uh;
11885 + case IPPROTO_TCP:
11886 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11887 + dst.port = th->dest;
11889 + case IPPROTO_UDP:
11890 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11891 + dst.port = uh->dest;
11898 + LOCK_BH(&hinfo->lock);
11899 + dh = __dsthash_find(hinfo, &dst);
11901 + dh = __dsthash_alloc_init(hinfo, &dst);
11904 + /* enomem... don't match == DROP */
11905 + if (net_ratelimit())
11906 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
11907 + UNLOCK_BH(&hinfo->lock);
11911 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
11913 + dh->rateinfo.prev = jiffies;
11914 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
11915 + hinfo->cfg.burst);
11916 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
11917 + hinfo->cfg.burst);
11918 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
11920 + UNLOCK_BH(&hinfo->lock);
11924 + /* update expiration timeout */
11925 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
11927 + rateinfo_recalc(dh, now);
11928 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
11929 + /* We're underlimit. */
11930 + dh->rateinfo.credit -= dh->rateinfo.cost;
11931 + UNLOCK_BH(&hinfo->lock);
11935 + UNLOCK_BH(&hinfo->lock);
11937 + /* default case: we're overlimit, thus don't match */
11942 +dstlimit_checkentry(const char *tablename,
11943 + const struct ipt_ip *ip,
11945 + unsigned int matchsize,
11946 + unsigned int hook_mask)
11948 + struct ipt_dstlimit_info *r = matchinfo;
11950 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
11953 + /* Check for overflow. */
11954 + if (r->cfg.burst == 0
11955 + || user2credits(r->cfg.avg * r->cfg.burst) <
11956 + user2credits(r->cfg.avg)) {
11957 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
11958 + r->cfg.avg, r->cfg.burst);
11962 + if (r->cfg.mode == 0
11963 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
11964 + |IPT_DSTLIMIT_HASH_DIP
11965 + |IPT_DSTLIMIT_HASH_SIP))
11968 + if (!r->cfg.gc_interval)
11971 + if (!r->cfg.expire)
11974 + r->hinfo = htable_find_get(r->name);
11975 + if (!r->hinfo && (htable_create(r) != 0)) {
11979 + /* Ugly hack: For SMP, we only want to use one set */
11986 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
11988 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
11990 + htable_put(r->hinfo);
11993 +static struct ipt_match ipt_dstlimit = {
11994 + .list = { .prev = NULL, .next = NULL },
11995 + .name = "dstlimit",
11996 + .match = dstlimit_match,
11997 + .checkentry = dstlimit_checkentry,
11998 + .destroy = dstlimit_destroy,
11999 + .me = THIS_MODULE
12004 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
12006 + struct proc_dir_entry *pde = s->private;
12007 + struct ipt_dstlimit_htable *htable = pde->data;
12008 + unsigned int *bucket;
12010 + LOCK_BH(&htable->lock);
12011 + if (*pos >= htable->cfg.size)
12014 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
12016 + return ERR_PTR(-ENOMEM);
12022 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
12024 + struct proc_dir_entry *pde = s->private;
12025 + struct ipt_dstlimit_htable *htable = pde->data;
12026 + unsigned int *bucket = (unsigned int *)v;
12028 + *pos = ++(*bucket);
12029 + if (*pos >= htable->cfg.size) {
12036 +static void dl_seq_stop(struct seq_file *s, void *v)
12038 + struct proc_dir_entry *pde = s->private;
12039 + struct ipt_dstlimit_htable *htable = pde->data;
12040 + unsigned int *bucket = (unsigned int *)v;
12044 + UNLOCK_BH(&htable->lock);
12047 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
12049 + /* recalculate to show accurate numbers */
12050 + rateinfo_recalc(ent, jiffies);
12052 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
12053 + (ent->expires - jiffies)/HZ,
12054 + NIPQUAD(ent->dst.src_ip),
12055 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
12056 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
12057 + ent->rateinfo.cost);
12060 +static int dl_seq_show(struct seq_file *s, void *v)
12062 + struct proc_dir_entry *pde = s->private;
12063 + struct ipt_dstlimit_htable *htable = pde->data;
12064 + unsigned int *bucket = (unsigned int *)v;
12066 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
12067 + struct dsthash_ent *, s)) {
12068 + /* buffer was filled and unable to print that tuple */
12074 +static struct seq_operations dl_seq_ops = {
12075 + .start = dl_seq_start,
12076 + .next = dl_seq_next,
12077 + .stop = dl_seq_stop,
12078 + .show = dl_seq_show
12081 +static int dl_proc_open(struct inode *inode, struct file *file)
12083 + int ret = seq_open(file, &dl_seq_ops);
12086 + struct seq_file *sf = file->private_data;
12087 + sf->private = PDE(inode);
12092 +static struct file_operations dl_file_ops = {
12093 + .owner = THIS_MODULE,
12094 + .open = dl_proc_open,
12095 + .read = seq_read,
12096 + .llseek = seq_lseek,
12097 + .release = seq_release
12100 +static int init_or_fini(int fini)
12107 + if (ipt_register_match(&ipt_dstlimit)) {
12109 + goto cleanup_nothing;
12112 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
12113 + * quite small ? */
12114 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
12115 + sizeof(struct dsthash_ent), 0,
12116 + SLAB_HWCACHE_ALIGN, NULL, NULL);
12117 + if (!dstlimit_cachep) {
12118 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
12120 + goto cleanup_unreg_match;
12123 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
12124 + if (!dstlimit_procdir) {
12125 + printk(KERN_ERR "Unable to create proc dir entry\n");
12127 + goto cleanup_free_slab;
12133 + remove_proc_entry("ipt_dstlimit", proc_net);
12134 +cleanup_free_slab:
12135 + kmem_cache_destroy(dstlimit_cachep);
12136 +cleanup_unreg_match:
12137 + ipt_unregister_match(&ipt_dstlimit);
12143 +static int __init init(void)
12145 + return init_or_fini(0);
12148 +static void __exit fini(void)
12153 +module_init(init);
12154 +module_exit(fini);
12155 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c
12156 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
12157 +++ linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c 2004-06-25 12:21:08.962029304 +0200
12160 + * This module implements a simple TSK FLC
12161 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
12162 + * to limit , in an adaptive and flexible way , the packet rate crossing
12163 + * a given stream . It serves as an initial and very simple (but effective)
12164 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
12165 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
12166 + * into our code in a precise , adaptive and efficient manner.
12167 + * The goal is very similar to that of "limit" match , but using techniques of
12168 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
12169 + * avoiding over and undershoots - and stuff like that .
12172 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
12173 + * 2002-08-17 : Changed to eliminate floating point operations .
12174 + * 2002-08-23 : Coding style changes .
12177 +#include <linux/module.h>
12178 +#include <linux/skbuff.h>
12179 +#include <linux/ip.h>
12180 +#include <linux/random.h>
12181 +#include <net/tcp.h>
12182 +#include <linux/spinlock.h>
12183 +#include <linux/netfilter_ipv4/ip_tables.h>
12184 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
12187 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
12188 + Expressed in percentage
12191 +#define PAR_LOW 1/100
12192 +#define PAR_HIGH 1
12194 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
12196 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
12197 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
12198 +MODULE_LICENSE("GPL");
12200 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12208 + return ( (100*(tx-mini)) / (maxi-mini) );
12211 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12219 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
12223 +ipt_fuzzy_match(const struct sk_buff *pskb,
12224 + const struct net_device *in,
12225 + const struct net_device *out,
12226 + const void *matchinfo,
12230 + /* From userspace */
12232 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
12234 + u_int8_t random_number;
12235 + unsigned long amount;
12236 + u_int8_t howhigh, howlow;
12239 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
12241 + info->bytes_total += pskb->len;
12242 + info->packets_total++;
12244 + info->present_time = jiffies;
12246 + if (info->present_time >= info->previous_time)
12247 + amount = info->present_time - info->previous_time;
12249 + /* There was a transition : I choose to re-sample
12250 + and keep the old acceptance rate...
12254 + info->previous_time = info->present_time;
12255 + info->bytes_total = info->packets_total = 0;
12258 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
12261 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
12264 + info->previous_time = info->present_time;
12265 + info->bytes_total = info->packets_total = 0;
12267 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
12268 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
12270 + info->acceptance_rate = (u_int8_t) \
12271 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
12273 + /* In fact , the above defuzzification would require a denominator
12274 + proportional to (howhigh+howlow) but , in this particular case ,
12275 + that expression is constant .
12276 + An imediate consequence is that it isn't necessary to call
12277 + both mf_high and mf_low - but to keep things understandable ,
12282 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
12285 + if ( info->acceptance_rate < 100 )
12287 + get_random_bytes((void *)(&random_number), 1);
12289 + /* If within the acceptance , it can pass => don't match */
12290 + if (random_number <= (255 * info->acceptance_rate) / 100)
12293 + return 1; /* It can't pass ( It matches ) */
12296 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
12301 +ipt_fuzzy_checkentry(const char *tablename,
12302 + const struct ipt_ip *e,
12304 + unsigned int matchsize,
12305 + unsigned int hook_mask)
12308 + const struct ipt_fuzzy_info *info = matchinfo;
12310 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
12311 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
12312 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
12316 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
12317 + || (info->minimum_rate >= info->maximum_rate )) {
12318 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
12325 +static struct ipt_match ipt_fuzzy_reg = {
12327 + .match = ipt_fuzzy_match,
12328 + .checkentry = ipt_fuzzy_checkentry,
12329 + .me = THIS_MODULE
12332 +static int __init init(void)
12334 + return ipt_register_match(&ipt_fuzzy_reg);
12337 +static void __exit fini(void)
12339 + ipt_unregister_match(&ipt_fuzzy_reg);
12342 +module_init(init);
12343 +module_exit(fini);
12344 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c
12345 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
12346 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c 2004-06-25 12:21:09.438956800 +0200
12349 + This is a module which is used to match ipv4 options.
12350 + This file is distributed under the terms of the GNU General Public
12351 + License (GPL). Copies of the GPL can be obtained from:
12352 + ftp://prep.ai.mit.edu/pub/gnu/GPL
12354 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
12355 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
12356 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
12357 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
12358 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
12361 +#include <linux/module.h>
12362 +#include <linux/skbuff.h>
12363 +#include <net/ip.h>
12365 +#include <linux/netfilter_ipv4/ip_tables.h>
12366 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
12368 +MODULE_LICENSE("GPL");
12369 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12372 +match(const struct sk_buff *skb,
12373 + const struct net_device *in,
12374 + const struct net_device *out,
12375 + const void *matchinfo,
12379 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
12380 + const struct iphdr *iph = skb->nh.iph;
12381 + const struct ip_options *opt;
12383 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
12384 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
12386 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
12387 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12388 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12389 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12390 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12391 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
12396 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
12397 + /* there are options, and we don't need to care which one */
12400 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
12401 + /* there are options but we don't want any ! */
12406 + opt = &(IPCB(skb)->opt);
12408 + /* source routing */
12409 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
12410 + if (!((opt->srr) & (opt->is_strictroute)))
12413 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
12414 + if (!((opt->srr) & (!opt->is_strictroute)))
12417 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
12421 + /* record route */
12422 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
12426 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
12431 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
12435 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
12439 + /* router-alert option */
12440 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
12441 + if (!opt->router_alert)
12444 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
12445 + if (opt->router_alert)
12454 +checkentry(const char *tablename,
12455 + const struct ipt_ip *ip,
12457 + unsigned int matchsize,
12458 + unsigned int hook_mask)
12460 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
12461 + /* Check the size */
12462 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
12464 + /* Now check the coherence of the data ... */
12465 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
12466 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
12467 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
12468 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
12469 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
12470 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
12471 + return 0; /* opposites */
12472 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
12473 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12474 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12475 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12476 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12477 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
12478 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
12479 + return 0; /* opposites */
12480 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
12481 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
12482 + return 0; /* cannot match in the same time loose and strict source routing */
12483 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12484 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
12485 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
12486 + return 0; /* opposites */
12487 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
12488 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
12489 + return 0; /* opposites */
12490 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
12491 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
12492 + return 0; /* opposites */
12493 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
12494 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
12495 + return 0; /* opposites */
12497 + /* everything looks ok. */
12501 +static struct ipt_match ipv4options_match = {
12502 + .name = "ipv4options",
12504 + .checkentry = checkentry,
12505 + .me = THIS_MODULE
12508 +static int __init init(void)
12510 + return ipt_register_match(&ipv4options_match);
12513 +static void __exit fini(void)
12515 + ipt_unregister_match(&ipv4options_match);
12518 +module_init(init);
12519 +module_exit(fini);
12520 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7/net/ipv4/netfilter/ipt_mport.c
12521 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
12522 +++ linux-2.6.7/net/ipv4/netfilter/ipt_mport.c 2004-06-25 12:21:09.926882624 +0200
12524 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
12525 + the same place so we can treat them as equal. */
12526 +#include <linux/module.h>
12527 +#include <linux/types.h>
12528 +#include <linux/udp.h>
12529 +#include <linux/skbuff.h>
12531 +#include <linux/netfilter_ipv4/ipt_mport.h>
12532 +#include <linux/netfilter_ipv4/ip_tables.h>
12534 +MODULE_LICENSE("GPL");
12537 +#define duprintf(format, args...) printk(format , ## args)
12539 +#define duprintf(format, args...)
12542 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
12544 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
12548 + u_int16_t pflags = minfo->pflags;
12549 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
12553 + && minfo->ports[i] == 65535)
12556 + s = minfo->ports[i];
12558 + if (pflags & m) {
12559 + e = minfo->ports[++i];
12564 + if (minfo->flags & IPT_MPORT_SOURCE
12565 + && src >= s && src <= e)
12568 + if (minfo->flags & IPT_MPORT_DESTINATION
12569 + && dst >= s && dst <= e)
12577 +match(const struct sk_buff *skb,
12578 + const struct net_device *in,
12579 + const struct net_device *out,
12580 + const void *matchinfo,
12585 + const struct ipt_mport *minfo = matchinfo;
12590 + /* Must be big enough to read ports (both UDP and TCP have
12591 + them at the start). */
12592 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12593 + /* We've been asked to examine this packet, and we
12594 + can't. Hence, no choice but to drop. */
12595 + duprintf("ipt_multiport:"
12596 + " Dropping evil offset=0 tinygram.\n");
12601 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
12604 +/* Called when user tries to insert an entry of this type. */
12606 +checkentry(const char *tablename,
12607 + const struct ipt_ip *ip,
12609 + unsigned int matchsize,
12610 + unsigned int hook_mask)
12612 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
12615 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
12616 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
12617 + && !(ip->invflags & IPT_INV_PROTO)
12618 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
12621 +static struct ipt_match mport_match = {
12624 + .checkentry = &checkentry,
12625 + .me = THIS_MODULE
12628 +static int __init init(void)
12630 + return ipt_register_match(&mport_match);
12633 +static void __exit fini(void)
12635 + ipt_unregister_match(&mport_match);
12638 +module_init(init);
12639 +module_exit(fini);
12640 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7/net/ipv4/netfilter/ipt_nth.c
12641 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
12642 +++ linux-2.6.7/net/ipv4/netfilter/ipt_nth.c 2004-06-25 12:21:10.460801456 +0200
12645 + This is a module which is used for match support for every Nth packet
12646 + This file is distributed under the terms of the GNU General Public
12647 + License (GPL). Copies of the GPL can be obtained from:
12648 + ftp://prep.ai.mit.edu/pub/gnu/GPL
12650 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
12651 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
12652 + * added support for multiple counters
12653 + * added support for matching on individual packets
12654 + in the counter cycle
12655 + 2004-02-19 Harald Welte <laforge@netfilter.org>
12660 +#include <linux/module.h>
12661 +#include <linux/skbuff.h>
12662 +#include <linux/ip.h>
12663 +#include <net/tcp.h>
12664 +#include <linux/spinlock.h>
12665 +#include <linux/netfilter_ipv4/ip_tables.h>
12666 +#include <linux/netfilter_ipv4/ipt_nth.h>
12668 +MODULE_LICENSE("GPL");
12669 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12672 + * State information.
12676 + u_int16_t number;
12679 +static struct state states[IPT_NTH_NUM_COUNTERS];
12682 +ipt_nth_match(const struct sk_buff *pskb,
12683 + const struct net_device *in,
12684 + const struct net_device *out,
12685 + const void *matchinfo,
12689 + /* Parameters from userspace */
12690 + const struct ipt_nth_info *info = matchinfo;
12691 + unsigned counter = info->counter;
12692 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
12694 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12698 + spin_lock(&states[counter].lock);
12700 + /* Are we matching every nth packet?*/
12701 + if (info->packet == 0xFF)
12703 + /* We're matching every nth packet and only every nth packet*/
12704 + /* Do we match or invert match? */
12705 + if (info->not == 0)
12707 + if (states[counter].number == 0)
12709 + ++states[counter].number;
12712 + if (states[counter].number >= info->every)
12713 + states[counter].number = 0; /* reset the counter */
12715 + ++states[counter].number;
12720 + if (states[counter].number == 0)
12722 + ++states[counter].number;
12725 + if (states[counter].number >= info->every)
12726 + states[counter].number = 0;
12728 + ++states[counter].number;
12734 + /* We're using the --packet, so there must be a rule for every value */
12735 + if (states[counter].number == info->packet)
12737 + /* only increment the counter when a match happens */
12738 + if (states[counter].number >= info->every)
12739 + states[counter].number = 0; /* reset the counter */
12741 + ++states[counter].number;
12749 + /* don't match */
12750 + spin_unlock(&states[counter].lock);
12754 + spin_unlock(&states[counter].lock);
12759 +ipt_nth_checkentry(const char *tablename,
12760 + const struct ipt_ip *e,
12762 + unsigned int matchsize,
12763 + unsigned int hook_mask)
12765 + /* Parameters from userspace */
12766 + const struct ipt_nth_info *info = matchinfo;
12767 + unsigned counter = info->counter;
12768 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
12770 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12774 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
12775 + printk("nth: matchsize %u != %u\n", matchsize,
12776 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
12780 + states[counter].number = info->startat;
12785 +static struct ipt_match ipt_nth_reg = {
12787 + .match = ipt_nth_match,
12788 + .checkentry = ipt_nth_checkentry,
12789 + .me = THIS_MODULE
12792 +static int __init init(void)
12794 + unsigned counter;
12796 + memset(&states, 0, sizeof(states));
12797 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
12798 + spin_lock_init(&(states[counter].lock));
12800 + return ipt_register_match(&ipt_nth_reg);
12803 +static void __exit fini(void)
12805 + ipt_unregister_match(&ipt_nth_reg);
12808 +module_init(init);
12809 +module_exit(fini);
12810 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.7/net/ipv4/netfilter/ipt_osf.c
12811 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
12812 +++ linux-2.6.7/net/ipv4/netfilter/ipt_osf.c 2004-06-25 12:21:10.972723632 +0200
12817 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
12820 + * This program is free software; you can redistribute it and/or modify
12821 + * it under the terms of the GNU General Public License as published by
12822 + * the Free Software Foundation; either version 2 of the License, or
12823 + * (at your option) any later version.
12825 + * This program is distributed in the hope that it will be useful,
12826 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12827 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12828 + * GNU General Public License for more details.
12830 + * You should have received a copy of the GNU General Public License
12831 + * along with this program; if not, write to the Free Software
12832 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12836 + * OS fingerprint matching module.
12837 + * It simply compares various parameters from SYN packet with
12838 + * some hardcoded ones.
12840 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
12844 +#include <linux/config.h>
12845 +#include <linux/kernel.h>
12846 +#include <linux/types.h>
12847 +#include <linux/string.h>
12848 +#include <linux/smp.h>
12849 +#include <linux/module.h>
12850 +#include <linux/skbuff.h>
12851 +#include <linux/file.h>
12852 +#include <linux/ip.h>
12853 +#include <linux/proc_fs.h>
12854 +#include <linux/fs.h>
12855 +#include <linux/slab.h>
12856 +#include <linux/spinlock.h>
12857 +#include <linux/ctype.h>
12858 +#include <linux/list.h>
12859 +#include <linux/if.h>
12861 +#include <net/sock.h>
12862 +#include <net/ip.h>
12864 +#include <linux/netfilter_ipv4/ip_tables.h>
12866 +#include <linux/netfilter_ipv4/ipt_osf.h>
12871 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
12872 +#define loga(x...) printk(x)
12874 +#define log(x...) do {} while(0)
12875 +#define loga(x...) do {} while(0)
12878 +#define FMATCH_WRONG 0
12879 +#define FMATCH_OK 1
12880 +#define FMATCH_OPT_WRONG 2
12882 +#define OPTDEL ','
12883 +#define OSFPDEL ':'
12884 +#define MAXOPTSTRLEN 128
12885 +#define OSFFLUSH "FLUSH"
12887 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
12888 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
12889 +static struct list_head finger_list;
12890 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
12891 + const void *, int,
12892 + const void *, u_int16_t,
12894 +static int checkentry(const char *, const struct ipt_ip *, void *,
12895 + unsigned int, unsigned int);
12897 +static unsigned long seq, ipt_osf_groups = 1;
12898 +static struct sock *nts;
12900 +static struct ipt_match osf_match =
12910 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
12912 + unsigned int size;
12913 + struct sk_buff *skb;
12914 + struct ipt_osf_nlmsg *data;
12915 + struct nlmsghdr *nlh;
12917 + size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
12919 + skb = alloc_skb(size, GFP_ATOMIC);
12922 + log("skb_alloc() failed.\n");
12926 + nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
12928 + data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
12930 + memcpy(&data->f, f, sizeof(struct osf_finger));
12931 + memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
12932 + memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
12934 + NETLINK_CB(skb).dst_groups = ipt_osf_groups;
12935 + netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
12941 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
12943 + struct iphdr *ip = skb->nh.iph;
12945 + if (flags & IPT_OSF_SMART)
12947 + struct in_device *in_dev = in_dev_get(skb->dev);
12951 + if (inet_ifa_match(ip->saddr, ifa))
12953 + in_dev_put(in_dev);
12954 + return (ip->ttl == f_ttl);
12957 + endfor_ifa(in_dev);
12959 + in_dev_put(in_dev);
12960 + return (ip->ttl <= f_ttl);
12963 + return (ip->ttl == f_ttl);
12967 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
12968 + const void *matchinfo, int offset,
12969 + const void *hdr, u_int16_t datalen,
12972 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
12973 + struct iphdr *ip = skb->nh.iph;
12974 + struct tcphdr *tcp;
12975 + int fmatch = FMATCH_WRONG, fcount = 0;
12976 + unsigned long totlen, optsize = 0, window;
12977 + unsigned char df, *optp = NULL, *_optp = NULL;
12978 + char check_WSS = 0;
12979 + struct list_head *ent;
12980 + struct osf_finger *f;
12982 + if (!ip || !info)
12985 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
12990 + totlen = ntohs(ip->tot_len);
12991 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
12992 + window = ntohs(tcp->window);
12994 + if (tcp->doff*4 > sizeof(struct tcphdr))
12996 + _optp = optp = (char *)(tcp+1);
12997 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
13001 + /* Actually we can create hash/table of all genres and search
13002 + * only in appropriate part, but here is initial variant,
13003 + * so will use slow path.
13005 + read_lock(&osf_lock);
13006 + list_for_each(ent, &finger_list)
13008 + f = list_entry(ent, struct osf_finger, flist);
13010 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
13014 + fmatch = FMATCH_WRONG;
13016 + if (totlen == f->ss && df == f->df &&
13017 + smart_dec(skb, info->flags, f->ttl))
13019 + unsigned long foptsize;
13021 + unsigned short mss = 0;
13025 + switch (f->wss.wc)
13027 + case 0: check_WSS = 0; break;
13028 + case 'S': check_WSS = 1; break;
13029 + case 'T': check_WSS = 2; break;
13030 + case '%': check_WSS = 3; break;
13031 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
13032 + f->wss.wc, f->genre, f->details);
13036 + if (check_WSS == 4)
13039 + /* Check options */
13042 + for (optnum=0; optnum<f->opt_num; ++optnum)
13043 + foptsize += f->opt[optnum].length;
13046 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
13051 + fmatch = FMATCH_OK;
13052 + loga("\tYEP : matching without options.\n");
13053 + if ((info->flags & IPT_OSF_LOG) &&
13054 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13061 + for (optnum=0; optnum<f->opt_num; ++optnum)
13063 + if (f->opt[optnum].kind == (*optp))
13065 + unsigned char len = f->opt[optnum].length;
13066 + unsigned char *optend = optp + len;
13067 + int loop_cont = 0;
13069 + fmatch = FMATCH_OK;
13075 + mss = ntohs(*(unsigned short *)(optp+2));
13090 + /* Skip kind and length fields*/
13093 + if (f->opt[optnum].wc.val != 0)
13095 + unsigned long tmp = 0;
13097 + /* Hmmm... It looks a bit ugly. :) */
13098 + memcpy(&tmp, optp,
13099 + (len > sizeof(unsigned long)?
13100 + sizeof(unsigned long):len));
13101 + /* 2 + 2: optlen(2 bytes) +
13102 + * kind(1 byte) + length(1 byte) */
13104 + tmp = ntohs(tmp);
13106 + tmp = ntohl(tmp);
13108 + if (f->opt[optnum].wc.wc == '%')
13110 + if ((tmp % f->opt[optnum].wc.val) != 0)
13111 + fmatch = FMATCH_OPT_WRONG;
13113 + else if (tmp != f->opt[optnum].wc.val)
13114 + fmatch = FMATCH_OPT_WRONG;
13121 + fmatch = FMATCH_OPT_WRONG;
13123 + if (fmatch != FMATCH_OK)
13127 + if (fmatch != FMATCH_OPT_WRONG)
13129 + fmatch = FMATCH_WRONG;
13131 + switch (check_WSS)
13134 + if (f->wss.val == 0 || window == f->wss.val)
13135 + fmatch = FMATCH_OK;
13137 + case 1: /* MSS */
13138 +/* Lurked in OpenBSD */
13139 +#define SMART_MSS 1460
13140 + if (window == f->wss.val*mss ||
13141 + window == f->wss.val*SMART_MSS)
13142 + fmatch = FMATCH_OK;
13144 + case 2: /* MTU */
13145 + if (window == f->wss.val*(mss+40) ||
13146 + window == f->wss.val*(SMART_MSS+40))
13147 + fmatch = FMATCH_OK;
13149 + case 3: /* MOD */
13150 + if ((window % f->wss.val) == 0)
13151 + fmatch = FMATCH_OK;
13157 + if (fmatch == FMATCH_OK)
13160 + log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
13161 + f->genre, f->version,
13162 + f->subtype, f->details,
13163 + NIPQUAD(ip->saddr), ntohs(tcp->source),
13164 + NIPQUAD(ip->daddr), ntohs(tcp->dest),
13165 + f->ttl - ip->ttl);
13166 + if (info->flags & IPT_OSF_NETLINK)
13168 + spin_lock_bh(&ipt_osf_netlink_lock);
13169 + ipt_osf_nlsend(f, skb);
13170 + spin_unlock_bh(&ipt_osf_netlink_lock);
13172 + if ((info->flags & IPT_OSF_LOG) &&
13173 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13178 + if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
13180 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
13181 + unsigned int i, optsize;
13182 + struct osf_finger fg;
13184 + memset(&fg, 0, sizeof(fg));
13186 + if ((info->flags & IPT_OSF_LOG))
13187 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
13190 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
13191 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
13192 + opt, optsize) < 0)
13194 + if (info->flags & IPT_OSF_LOG)
13195 + loga("TRUNCATED");
13196 + if (info->flags & IPT_OSF_NETLINK)
13197 + strcpy(fg.details, "TRUNCATED");
13201 + for (i = 0; i < optsize; i++)
13203 + if (info->flags & IPT_OSF_LOG)
13204 + loga("%02X", opt[i]);
13206 + if (info->flags & IPT_OSF_NETLINK)
13207 + memcpy(fg.details, opt, MAXDETLEN);
13210 + if ((info->flags & IPT_OSF_LOG))
13211 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
13212 + NIPQUAD(ip->saddr), ntohs(tcp->source),
13213 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
13215 + if (info->flags & IPT_OSF_NETLINK)
13217 + fg.wss.val = window;
13218 + fg.ttl = ip->ttl;
13221 + strncpy(fg.genre, "Unknown", MAXGENRELEN);
13223 + spin_lock_bh(&ipt_osf_netlink_lock);
13224 + ipt_osf_nlsend(&fg, skb);
13225 + spin_unlock_bh(&ipt_osf_netlink_lock);
13229 + read_unlock(&osf_lock);
13231 + return (fmatch == FMATCH_OK)?1:0;
13235 +checkentry(const char *tablename,
13236 + const struct ipt_ip *ip,
13238 + unsigned int matchsize,
13239 + unsigned int hook_mask)
13241 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
13243 + if (ip->proto != IPPROTO_TCP)
13249 +static char * osf_strchr(char *ptr, char c)
13253 + tmp = strchr(ptr, c);
13255 + while (tmp && tmp+1 && isspace(*(tmp+1)))
13261 +static struct osf_finger * finger_alloc(void)
13263 + struct osf_finger *f;
13265 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
13267 + memset(f, 0, sizeof(struct osf_finger));
13272 +static void finger_free(struct osf_finger *f)
13274 + memset(f, 0, sizeof(struct osf_finger));
13279 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
13283 + unsigned long val;
13287 + while (ptr != NULL && i < olen)
13296 + ptr = osf_strchr(&obuf[i], OPTDEL);
13301 + i += (int)(ptr-&obuf[i]);
13308 + op = OSFOPT_SACKP;
13309 + ptr = osf_strchr(&obuf[i], OPTDEL);
13314 + i += (int)(ptr-&obuf[i]);
13322 + ptr = osf_strchr(&obuf[i], OPTDEL);
13327 + i += (int)(ptr-&obuf[i]);
13335 + ptr = osf_strchr(&obuf[i], OPTDEL);
13338 + switch (obuf[i+1])
13340 + case '%': wc = '%'; break;
13341 + case 'S': wc = 'S'; break;
13342 + case 'T': wc = 'T'; break;
13343 + default: wc = 0; break;
13349 + val = simple_strtoul(&obuf[i+2], NULL, 10);
13351 + val = simple_strtoul(&obuf[i+1], NULL, 10);
13352 + i += (int)(ptr-&obuf[i]);
13360 + ptr = osf_strchr(&obuf[i], OPTDEL);
13363 + if (obuf[i+1] == '%')
13368 + val = simple_strtoul(&obuf[i+2], NULL, 10);
13370 + val = simple_strtoul(&obuf[i+1], NULL, 10);
13371 + i += (int)(ptr-&obuf[i]);
13379 + ptr = osf_strchr(&obuf[i], OPTDEL);
13384 + i += (int)(ptr-&obuf[i]);
13391 + ptr = osf_strchr(&obuf[i], OPTDEL);
13395 + i += (int)(ptr-&obuf[i]);
13403 + opt[*optnum].kind = IANA_opts[op].kind;
13404 + opt[*optnum].length = IANA_opts[op].length;
13405 + opt[*optnum].wc.wc = wc;
13406 + opt[*optnum].wc.val = val;
13412 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
13414 + struct list_head *ent;
13415 + struct osf_finger *f = NULL;
13421 + read_lock_bh(&osf_lock);
13422 + list_for_each(ent, &finger_list)
13424 + f = list_entry(ent, struct osf_finger, flist);
13426 + log("%s [%s]", f->genre, f->details);
13428 + count += sprintf(buf+count, "%s - %s[%s] : %s",
13429 + f->genre, f->version,
13430 + f->subtype, f->details);
13435 + //count += sprintf(buf+count, " OPT: ");
13436 + for (i=0; i<f->opt_num; ++i)
13438 + //count += sprintf(buf+count, "%d.%c%lu; ",
13439 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13440 + loga("%d.%c%lu; ",
13441 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13445 + count += sprintf(buf+count, "\n");
13447 + read_unlock_bh(&osf_lock);
13452 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
13456 + char obuf[MAXOPTSTRLEN];
13457 + struct osf_finger *finger;
13458 + struct list_head *ent, *n;
13460 + char *pbeg, *pend;
13462 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
13465 + write_lock_bh(&osf_lock);
13466 + list_for_each_safe(ent, n, &finger_list)
13469 + finger = list_entry(ent, struct osf_finger, flist);
13470 + list_del(&finger->flist);
13471 + finger_free(finger);
13473 + write_unlock_bh(&osf_lock);
13475 + log("Flushed %d entries.\n", i);
13482 + for (i=0; i<count && buffer[i] != '\0'; ++i)
13483 + if (buffer[i] == ':')
13486 + if (cnt != 8 || i != count)
13488 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
13493 + memset(obuf, 0, sizeof(obuf));
13495 + finger = finger_alloc();
13498 + log("Failed to allocate new fingerprint entry.\n");
13502 + pbeg = (char *)buffer;
13503 + pend = osf_strchr(pbeg, OSFPDEL);
13507 + if (pbeg[0] == 'S')
13509 + finger->wss.wc = 'S';
13510 + if (pbeg[1] == '%')
13511 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13512 + else if (pbeg[1] == '*')
13513 + finger->wss.val = 0;
13515 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13517 + else if (pbeg[0] == 'T')
13519 + finger->wss.wc = 'T';
13520 + if (pbeg[1] == '%')
13521 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13522 + else if (pbeg[1] == '*')
13523 + finger->wss.val = 0;
13525 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13527 + else if (pbeg[0] == '%')
13529 + finger->wss.wc = '%';
13530 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13532 + else if (isdigit(pbeg[0]))
13534 + finger->wss.wc = 0;
13535 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
13540 + pend = osf_strchr(pbeg, OSFPDEL);
13544 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
13547 + pend = osf_strchr(pbeg, OSFPDEL);
13551 + finger->df = simple_strtoul(pbeg, NULL, 10);
13554 + pend = osf_strchr(pbeg, OSFPDEL);
13558 + finger->ss = simple_strtoul(pbeg, NULL, 10);
13562 + pend = osf_strchr(pbeg, OSFPDEL);
13566 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
13570 + pend = osf_strchr(pbeg, OSFPDEL);
13574 + if (pbeg[0] == '@' || pbeg[0] == '*')
13575 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
13577 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
13581 + pend = osf_strchr(pbeg, OSFPDEL);
13585 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
13589 + pend = osf_strchr(pbeg, OSFPDEL);
13593 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
13597 + cnt = snprintf(finger->details,
13598 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
13601 + log("%s - %s[%s] : %s\n",
13602 + finger->genre, finger->version,
13603 + finger->subtype, finger->details);
13605 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
13608 + write_lock_bh(&osf_lock);
13609 + list_add_tail(&finger->flist, &finger_list);
13610 + write_unlock_bh(&osf_lock);
13615 +static int __init osf_init(void)
13618 + struct proc_dir_entry *p;
13620 + log("Startng OS fingerprint matching module.\n");
13622 + INIT_LIST_HEAD(&finger_list);
13624 + err = ipt_register_match(&osf_match);
13627 + log("Failed to register OS fingerprint matching module.\n");
13631 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
13634 + ipt_unregister_match(&osf_match);
13638 + p->write_proc = osf_proc_write;
13639 + p->read_proc = osf_proc_read;
13641 + nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
13644 + log("netlink_kernel_create() failed\n");
13645 + remove_proc_entry("sys/net/ipv4/osf", NULL);
13646 + ipt_unregister_match(&osf_match);
13653 +static void __exit osf_fini(void)
13655 + struct list_head *ent, *n;
13656 + struct osf_finger *f;
13658 + remove_proc_entry("sys/net/ipv4/osf", NULL);
13659 + ipt_unregister_match(&osf_match);
13660 + if (nts && nts->socket)
13661 + sock_release(nts->socket);
13663 + list_for_each_safe(ent, n, &finger_list)
13665 + f = list_entry(ent, struct osf_finger, flist);
13666 + list_del(&f->flist);
13670 + log("OS fingerprint matching module finished.\n");
13673 +module_init(osf_init);
13674 +module_exit(osf_fini);
13676 +MODULE_LICENSE("GPL");
13677 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
13678 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
13679 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.7/net/ipv4/netfilter/ipt_owner.c
13680 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_owner.c 2004-06-25 10:47:46.000000000 +0200
13681 +++ linux-2.6.7/net/ipv4/netfilter/ipt_owner.c 2004-06-25 12:23:16.003716032 +0200
13683 * This program is free software; you can redistribute it and/or modify
13684 * it under the terms of the GNU General Public License version 2 as
13685 * published by the Free Software Foundation.
13687 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
13690 #include <linux/module.h>
13691 #include <linux/skbuff.h>
13692 #include <linux/file.h>
13693 +#include <linux/ip.h>
13694 +#include <linux/tcp.h>
13695 +#include <linux/udp.h>
13696 #include <net/sock.h>
13697 +#include <net/tcp.h>
13698 +#include <net/udp.h>
13700 #include <linux/netfilter_ipv4/ipt_owner.h>
13701 #include <linux/netfilter_ipv4/ip_tables.h>
13703 MODULE_DESCRIPTION("iptables owner match");
13706 -match_comm(const struct sk_buff *skb, const char *comm)
13707 +match_comm(const struct sock *sk, const char *comm)
13709 struct task_struct *g, *p;
13710 struct files_struct *files;
13712 spin_lock(&files->file_lock);
13713 for (i=0; i < files->max_fds; i++) {
13714 if (fcheck_files(files, i) ==
13715 - skb->sk->sk_socket->file) {
13716 + sk->sk_socket->file) {
13717 spin_unlock(&files->file_lock);
13719 read_unlock(&tasklist_lock);
13724 -match_pid(const struct sk_buff *skb, pid_t pid)
13725 +match_pid(const struct sock *sk, pid_t pid)
13727 struct task_struct *p;
13728 struct files_struct *files;
13730 spin_lock(&files->file_lock);
13731 for (i=0; i < files->max_fds; i++) {
13732 if (fcheck_files(files, i) ==
13733 - skb->sk->sk_socket->file) {
13734 + sk->sk_socket->file) {
13735 spin_unlock(&files->file_lock);
13737 read_unlock(&tasklist_lock);
13738 @@ -86,10 +93,10 @@
13742 -match_sid(const struct sk_buff *skb, pid_t sid)
13743 +match_sid(const struct sock *sk, pid_t sid)
13745 struct task_struct *g, *p;
13746 - struct file *file = skb->sk->sk_socket->file;
13747 + struct file *file = sk->sk_socket->file;
13750 read_lock(&tasklist_lock);
13751 @@ -129,41 +136,71 @@
13754 const struct ipt_owner_info *info = matchinfo;
13755 + struct iphdr *iph = skb->nh.iph;
13756 + struct sock *sk = NULL;
13762 + if (iph->protocol == IPPROTO_TCP) {
13763 + struct tcphdr *tcph =
13764 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
13765 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
13766 + iph->daddr, tcph->dest,
13767 + skb->dev->ifindex);
13768 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
13769 + tcp_tw_put((struct tcp_tw_bucket *)sk);
13772 + } else if (iph->protocol == IPPROTO_UDP) {
13773 + struct udphdr *udph =
13774 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
13775 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
13776 + udph->dest, skb->dev->ifindex);
13780 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
13782 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
13785 if(info->match & IPT_OWNER_UID) {
13786 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
13787 + if ((sk->sk_socket->file->f_uid != info->uid) ^
13788 !!(info->invert & IPT_OWNER_UID))
13793 if(info->match & IPT_OWNER_GID) {
13794 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
13795 + if ((sk->sk_socket->file->f_gid != info->gid) ^
13796 !!(info->invert & IPT_OWNER_GID))
13801 if(info->match & IPT_OWNER_PID) {
13802 - if (!match_pid(skb, info->pid) ^
13803 + if (!match_pid(sk, info->pid) ^
13804 !!(info->invert & IPT_OWNER_PID))
13809 if(info->match & IPT_OWNER_SID) {
13810 - if (!match_sid(skb, info->sid) ^
13811 + if (!match_sid(sk, info->sid) ^
13812 !!(info->invert & IPT_OWNER_SID))
13817 if(info->match & IPT_OWNER_COMM) {
13818 - if (!match_comm(skb, info->comm) ^
13819 + if (!match_comm(sk, info->comm) ^
13820 !!(info->invert & IPT_OWNER_COMM))
13836 @@ -173,11 +210,19 @@
13837 unsigned int matchsize,
13838 unsigned int hook_mask)
13841 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
13842 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
13846 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
13847 + (1 << NF_IP_LOCAL_IN))) {
13848 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
13849 + "or POST_ROUTING.\n");
13853 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
13854 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
13855 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
13859 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
13860 printk("Matchsize %u != %Zu\n", matchsize,
13861 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.7/net/ipv4/netfilter/ipt_policy.c
13862 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
13863 +++ linux-2.6.7/net/ipv4/netfilter/ipt_policy.c 2004-03-08 05:19:04.000000000 +0100
13865 +/* IP tables module for matching IPsec policy
13867 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
13869 + * This program is free software; you can redistribute it and/or modify
13870 + * it under the terms of the GNU General Public License version 2 as
13871 + * published by the Free Software Foundation.
13874 +#include <linux/kernel.h>
13875 +#include <linux/config.h>
13876 +#include <linux/module.h>
13877 +#include <linux/skbuff.h>
13878 +#include <linux/init.h>
13879 +#include <net/xfrm.h>
13881 +#include <linux/netfilter_ipv4.h>
13882 +#include <linux/netfilter_ipv4/ipt_policy.h>
13883 +#include <linux/netfilter_ipv4/ip_tables.h>
13885 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
13886 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
13887 +MODULE_LICENSE("GPL");
13891 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
13893 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
13895 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
13896 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
13897 + MISMATCH(proto, x->id.proto) ||
13898 + MISMATCH(mode, x->props.mode) ||
13899 + MISMATCH(spi, x->id.spi) ||
13900 + MISMATCH(reqid, x->props.reqid))
13906 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
13908 + const struct ipt_policy_elem *e;
13909 + struct sec_path *sp = skb->sp;
13910 + int strict = info->flags & POLICY_MATCH_STRICT;
13915 + if (strict && info->len != sp->len)
13918 + for (i = sp->len - 1; i >= 0; i--) {
13919 + pos = strict ? i - sp->len + 1 : 0;
13920 + if (pos >= info->len)
13922 + e = &info->pol[pos];
13924 + if (match_xfrm_state(sp->x[i].xvec, e)) {
13927 + } else if (strict)
13931 + return strict ? 1 : 0;
13935 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
13937 + const struct ipt_policy_elem *e;
13938 + struct dst_entry *dst = skb->dst;
13939 + int strict = info->flags & POLICY_MATCH_STRICT;
13942 + if (dst->xfrm == NULL)
13945 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
13946 + pos = strict ? i : 0;
13947 + if (pos >= info->len)
13949 + e = &info->pol[pos];
13951 + if (match_xfrm_state(dst->xfrm, e)) {
13954 + } else if (strict)
13958 + return strict ? 1 : 0;
13961 +static int match(const struct sk_buff *skb,
13962 + const struct net_device *in,
13963 + const struct net_device *out,
13964 + const void *matchinfo, int offset, int *hotdrop)
13966 + const struct ipt_policy_info *info = matchinfo;
13969 + if (info->flags & POLICY_MATCH_IN)
13970 + ret = match_policy_in(skb, info);
13972 + ret = match_policy_out(skb, info);
13975 + if (info->flags & POLICY_MATCH_NONE)
13979 + } else if (info->flags & POLICY_MATCH_NONE)
13985 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
13986 + void *matchinfo, unsigned int matchsize,
13987 + unsigned int hook_mask)
13989 + struct ipt_policy_info *info = matchinfo;
13991 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
13992 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
13993 + matchsize, IPT_ALIGN(sizeof(*info)));
13996 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
13997 + printk(KERN_ERR "ipt_policy: neither incoming nor "
13998 + "outgoing policy selected\n");
14001 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
14002 + && info->flags & POLICY_MATCH_OUT) {
14003 + printk(KERN_ERR "ipt_policy: output policy not valid in "
14004 + "PRE_ROUTING and INPUT\n");
14007 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
14008 + && info->flags & POLICY_MATCH_IN) {
14009 + printk(KERN_ERR "ipt_policy: input policy not valid in "
14010 + "POST_ROUTING and OUTPUT\n");
14013 + if (info->len > POLICY_MAX_ELEM) {
14014 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
14021 +static struct ipt_match policy_match =
14023 + .name = "policy",
14025 + .checkentry = checkentry,
14026 + .me = THIS_MODULE,
14029 +static int __init init(void)
14031 + return ipt_register_match(&policy_match);
14034 +static void __exit fini(void)
14036 + ipt_unregister_match(&policy_match);
14039 +module_init(init);
14040 +module_exit(fini);
14041 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.7/net/ipv4/netfilter/ipt_pool.c
14042 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
14043 +++ linux-2.6.7/net/ipv4/netfilter/ipt_pool.c 2004-06-25 12:21:11.468648240 +0200
14045 +/* Kernel module to match an IP address pool. */
14047 +#include <linux/module.h>
14048 +#include <linux/ip.h>
14049 +#include <linux/skbuff.h>
14051 +#include <linux/netfilter_ipv4/ip_tables.h>
14052 +#include <linux/netfilter_ipv4/ip_pool.h>
14053 +#include <linux/netfilter_ipv4/ipt_pool.h>
14055 +static inline int match_pool(
14060 + if (ip_pool_match(index, ntohl(addr)))
14066 + const struct sk_buff *skb,
14067 + const struct net_device *in,
14068 + const struct net_device *out,
14069 + const void *matchinfo,
14072 + u_int16_t datalen,
14075 + const struct ipt_pool_info *info = matchinfo;
14076 + const struct iphdr *iph = skb->nh.iph;
14078 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
14079 + info->flags&IPT_POOL_INV_SRC))
14082 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
14083 + info->flags&IPT_POOL_INV_DST))
14089 +static int checkentry(
14090 + const char *tablename,
14091 + const struct ipt_ip *ip,
14093 + unsigned int matchsize,
14094 + unsigned int hook_mask
14096 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
14101 +static struct ipt_match pool_match
14102 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
14104 +static int __init init(void)
14106 + return ipt_register_match(&pool_match);
14109 +static void __exit fini(void)
14111 + ipt_unregister_match(&pool_match);
14114 +module_init(init);
14115 +module_exit(fini);
14116 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7/net/ipv4/netfilter/ipt_psd.c
14117 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
14118 +++ linux-2.6.7/net/ipv4/netfilter/ipt_psd.c 2004-06-25 12:21:11.947575432 +0200
14121 + This is a module which is used for PSD (portscan detection)
14122 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
14123 + and LOG target module.
14125 + Copyright (C) 2000,2001 astaro AG
14127 + This file is distributed under the terms of the GNU General Public
14128 + License (GPL). Copies of the GPL can be obtained from:
14129 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14131 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
14132 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
14133 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
14134 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
14135 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
14136 + 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
14139 +#include <linux/module.h>
14140 +#include <linux/skbuff.h>
14141 +#include <linux/ip.h>
14142 +#include <net/tcp.h>
14143 +#include <linux/spinlock.h>
14144 +#include <linux/netfilter_ipv4/ip_tables.h>
14145 +#include <linux/netfilter_ipv4/ipt_psd.h>
14148 +#define DEBUGP printk
14150 +#define DEBUGP(format, args...)
14153 +MODULE_LICENSE("GPL");
14154 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
14156 +#define HF_DADDR_CHANGING 0x01
14157 +#define HF_SPORT_CHANGING 0x02
14158 +#define HF_TOS_CHANGING 0x04
14159 +#define HF_TTL_CHANGING 0x08
14162 + * Information we keep per each target port
14165 + u_int16_t number; /* port number */
14166 + u_int8_t proto; /* protocol number */
14167 + u_int8_t and_flags; /* tcp ANDed flags */
14168 + u_int8_t or_flags; /* tcp ORed flags */
14172 + * Information we keep per each source address.
14175 + struct host *next; /* Next entry with the same hash */
14176 + clock_t timestamp; /* Last update time */
14177 + struct in_addr src_addr; /* Source address */
14178 + struct in_addr dest_addr; /* Destination address */
14179 + unsigned short src_port; /* Source port */
14180 + int count; /* Number of ports in the list */
14181 + int weight; /* Total weight of ports in the list */
14182 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
14183 + unsigned char tos; /* TOS */
14184 + unsigned char ttl; /* TTL */
14185 + unsigned char flags; /* HF_ flags bitmask */
14189 + * State information.
14193 + struct host list[LIST_SIZE]; /* List of source addresses */
14194 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
14195 + int index; /* Oldest entry to be replaced */
14199 + * Convert an IP address into a hash table index.
14201 +static inline int hashfunc(struct in_addr addr)
14203 + unsigned int value;
14206 + value = addr.s_addr;
14210 + } while ((value >>= HASH_LOG));
14212 + return hash & (HASH_SIZE - 1);
14216 +ipt_psd_match(const struct sk_buff *pskb,
14217 + const struct net_device *in,
14218 + const struct net_device *out,
14219 + const void *matchinfo,
14223 + struct iphdr *ip_hdr;
14224 + struct tcphdr *tcp_hdr;
14225 + struct in_addr addr;
14226 + u_int16_t src_port,dest_port;
14227 + u_int8_t tcp_flags, proto;
14229 + struct host *curr, *last, **head;
14230 + int hash, index, count;
14232 + /* Parameters from userspace */
14233 + const struct ipt_psd_info *psdinfo = matchinfo;
14236 + ip_hdr = pskb->nh.iph;
14238 + /* Sanity check */
14239 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
14240 + DEBUGP("PSD: sanity check failed\n");
14244 + /* TCP or UDP ? */
14245 + proto = ip_hdr->protocol;
14247 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
14248 + DEBUGP("PSD: protocol not supported\n");
14252 + /* Get the source address, source & destination ports, and TCP flags */
14254 + addr.s_addr = ip_hdr->saddr;
14256 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
14258 + /* Yep, it´s dirty */
14259 + src_port = tcp_hdr->source;
14260 + dest_port = tcp_hdr->dest;
14262 + if (proto == IPPROTO_TCP) {
14263 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
14266 + tcp_flags = 0x00;
14269 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
14270 + * them spoof us. [DHCP needs this feature - HW] */
14271 + if (!addr.s_addr) {
14272 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
14276 + /* Use jiffies here not to depend on someone setting the time while we're
14277 + * running; we need to be careful with possible return value overflows. */
14280 + spin_lock(&state.lock);
14282 + /* Do we know this source address already? */
14285 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
14287 + if (curr->src_addr.s_addr == addr.s_addr) break;
14289 + if (curr->next) last = curr;
14290 + } while ((curr = curr->next));
14294 + /* We know this address, and the entry isn't too old. Update it. */
14295 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
14296 + time_after_eq(now, curr->timestamp)) {
14298 + /* Just update the appropriate list entry if we've seen this port already */
14299 + for (index = 0; index < curr->count; index++) {
14300 + if (curr->ports[index].number == dest_port) {
14301 + curr->ports[index].proto = proto;
14302 + curr->ports[index].and_flags &= tcp_flags;
14303 + curr->ports[index].or_flags |= tcp_flags;
14304 + goto out_no_match;
14308 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
14309 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
14310 + goto out_no_match;
14312 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
14313 + curr->timestamp = now;
14315 + /* Logged this scan already? Then drop the packet. */
14316 + if (curr->weight >= psdinfo->weight_threshold)
14319 + /* Specify if destination address, source port, TOS or TTL are not fixed */
14320 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
14321 + curr->flags |= HF_DADDR_CHANGING;
14322 + if (curr->src_port != src_port)
14323 + curr->flags |= HF_SPORT_CHANGING;
14324 + if (curr->tos != ip_hdr->tos)
14325 + curr->flags |= HF_TOS_CHANGING;
14326 + if (curr->ttl != ip_hdr->ttl)
14327 + curr->flags |= HF_TTL_CHANGING;
14329 + /* Update the total weight */
14330 + curr->weight += (ntohs(dest_port) < 1024) ?
14331 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14333 + /* Got enough destination ports to decide that this is a scan? */
14334 + /* Then log it and drop the packet. */
14335 + if (curr->weight >= psdinfo->weight_threshold)
14338 + /* Remember the new port */
14339 + if (curr->count < SCAN_MAX_COUNT) {
14340 + curr->ports[curr->count].number = dest_port;
14341 + curr->ports[curr->count].proto = proto;
14342 + curr->ports[curr->count].and_flags = tcp_flags;
14343 + curr->ports[curr->count].or_flags = tcp_flags;
14347 + goto out_no_match;
14350 + /* We know this address, but the entry is outdated. Mark it unused, and
14351 + * remove from the hash table. We'll allocate a new entry instead since
14352 + * this one might get re-used too soon. */
14353 + curr->src_addr.s_addr = 0;
14355 + last->next = last->next->next;
14357 + *head = (*head)->next;
14361 + /* We don't need an ACK from a new source address */
14362 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
14363 + goto out_no_match;
14365 + /* Got too many source addresses with the same hash value? Then remove the
14366 + * oldest one from the hash table, so that they can't take too much of our
14367 + * CPU time even with carefully chosen spoofed IP addresses. */
14368 + if (count >= HASH_MAX && last) last->next = NULL;
14370 + /* We're going to re-use the oldest list entry, so remove it from the hash
14371 + * table first (if it is really already in use, and isn't removed from the
14372 + * hash table already because of the HASH_MAX check above). */
14374 + /* First, find it */
14375 + if (state.list[state.index].src_addr.s_addr)
14376 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
14380 + if ((curr = *head))
14382 + if (curr == &state.list[state.index]) break;
14384 + } while ((curr = curr->next));
14386 + /* Then, remove it */
14389 + last->next = last->next->next;
14391 + *head = (*head)->next;
14394 + /* Get our list entry */
14395 + curr = &state.list[state.index++];
14396 + if (state.index >= LIST_SIZE) state.index = 0;
14398 + /* Link it into the hash table */
14399 + head = &state.hash[hash];
14400 + curr->next = *head;
14403 + /* And fill in the fields */
14404 + curr->timestamp = now;
14405 + curr->src_addr = addr;
14406 + curr->dest_addr.s_addr = ip_hdr->daddr;
14407 + curr->src_port = src_port;
14409 + curr->weight = (ntohs(dest_port) < 1024) ?
14410 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14411 + curr->ports[0].number = dest_port;
14412 + curr->ports[0].proto = proto;
14413 + curr->ports[0].and_flags = tcp_flags;
14414 + curr->ports[0].or_flags = tcp_flags;
14415 + curr->tos = ip_hdr->tos;
14416 + curr->ttl = ip_hdr->ttl;
14419 + spin_unlock(&state.lock);
14423 + spin_unlock(&state.lock);
14427 +static int ipt_psd_checkentry(const char *tablename,
14428 + const struct ipt_ip *e,
14430 + unsigned int matchsize,
14431 + unsigned int hook_mask)
14433 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
14435 + /* we accept TCP only */
14436 +/* if (e->ip.proto != IPPROTO_TCP) { */
14437 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
14441 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
14442 + DEBUGP("PSD: matchsize %u != %u\n",
14444 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
14451 +static struct ipt_match ipt_psd_reg = {
14453 + .match = ipt_psd_match,
14454 + .checkentry = ipt_psd_checkentry,
14455 + .me = THIS_MODULE };
14457 +static int __init init(void)
14459 + if (ipt_register_match(&ipt_psd_reg))
14462 + memset(&state, 0, sizeof(state));
14464 + spin_lock_init(&(state.lock));
14466 + printk("netfilter PSD loaded - (c) astaro AG\n");
14470 +static void __exit fini(void)
14472 + ipt_unregister_match(&ipt_psd_reg);
14473 + printk("netfilter PSD unloaded - (c) astaro AG\n");
14476 +module_init(init);
14477 +module_exit(fini);
14478 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7/net/ipv4/netfilter/ipt_quota.c
14479 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
14480 +++ linux-2.6.7/net/ipv4/netfilter/ipt_quota.c 2004-06-25 12:21:12.435501256 +0200
14483 + * netfilter module to enforce network quotas
14485 + * Sam Johnston <samj@samj.net>
14487 +#include <linux/module.h>
14488 +#include <linux/skbuff.h>
14489 +#include <linux/spinlock.h>
14490 +#include <linux/interrupt.h>
14492 +#include <linux/netfilter_ipv4/ip_tables.h>
14493 +#include <linux/netfilter_ipv4/ipt_quota.h>
14495 +MODULE_LICENSE("GPL");
14496 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14498 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
14501 +match(const struct sk_buff *skb,
14502 + const struct net_device *in,
14503 + const struct net_device *out,
14504 + const void *matchinfo,
14505 + int offset, int *hotdrop)
14507 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
14508 + unsigned int datalen;
14510 + if (skb->len < sizeof(struct iphdr))
14511 + return NF_ACCEPT;
14513 + datalen = skb->len - skb->nh.iph->ihl*4;
14515 + spin_lock_bh("a_lock);
14517 + if (q->quota >= datalen) {
14518 + /* we can afford this one */
14519 + q->quota -= datalen;
14520 + spin_unlock_bh("a_lock);
14522 +#ifdef DEBUG_IPT_QUOTA
14523 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
14528 + /* so we do not allow even small packets from now on */
14531 +#ifdef DEBUG_IPT_QUOTA
14532 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
14535 + spin_unlock_bh("a_lock);
14540 +checkentry(const char *tablename,
14541 + const struct ipt_ip *ip,
14542 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
14544 + /* TODO: spinlocks? sanity checks? */
14545 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
14551 +static struct ipt_match quota_match = {
14554 + .checkentry = checkentry,
14555 + .me = THIS_MODULE
14561 + return ipt_register_match("a_match);
14564 +static void __exit
14567 + ipt_unregister_match("a_match);
14570 +module_init(init);
14571 +module_exit(fini);
14573 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_random.c linux-2.6.7/net/ipv4/netfilter/ipt_random.c
14574 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
14575 +++ linux-2.6.7/net/ipv4/netfilter/ipt_random.c 2004-06-25 12:21:12.938424800 +0200
14578 + This is a module which is used for a "random" match support.
14579 + This file is distributed under the terms of the GNU General Public
14580 + License (GPL). Copies of the GPL can be obtained from:
14581 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14583 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14586 +#include <linux/module.h>
14587 +#include <linux/skbuff.h>
14588 +#include <linux/ip.h>
14589 +#include <linux/random.h>
14590 +#include <net/tcp.h>
14591 +#include <linux/spinlock.h>
14592 +#include <linux/netfilter_ipv4/ip_tables.h>
14593 +#include <linux/netfilter_ipv4/ipt_random.h>
14595 +MODULE_LICENSE("GPL");
14598 +ipt_rand_match(const struct sk_buff *pskb,
14599 + const struct net_device *in,
14600 + const struct net_device *out,
14601 + const void *matchinfo,
14604 + u_int16_t datalen,
14607 + /* Parameters from userspace */
14608 + const struct ipt_rand_info *info = matchinfo;
14609 + u_int8_t random_number;
14611 + /* get 1 random number from the kernel random number generation routine */
14612 + get_random_bytes((void *)(&random_number), 1);
14614 + /* Do we match ? */
14615 + if (random_number <= info->average)
14622 +ipt_rand_checkentry(const char *tablename,
14623 + const struct ipt_ip *e,
14625 + unsigned int matchsize,
14626 + unsigned int hook_mask)
14628 + /* Parameters from userspace */
14629 + const struct ipt_rand_info *info = matchinfo;
14631 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
14632 + printk("ipt_random: matchsize %u != %u\n", matchsize,
14633 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
14637 + /* must be 1 <= average % <= 99 */
14638 + /* 1 x 2.55 = 2 */
14639 + /* 99 x 2.55 = 252 */
14640 + if ((info->average < 2) || (info->average > 252)) {
14641 + printk("ipt_random: invalid average %u\n", info->average);
14648 +static struct ipt_match ipt_rand_reg = {
14652 + ipt_rand_checkentry,
14656 +static int __init init(void)
14658 + if (ipt_register_match(&ipt_rand_reg))
14661 + printk("ipt_random match loaded\n");
14665 +static void __exit fini(void)
14667 + ipt_unregister_match(&ipt_rand_reg);
14668 + printk("ipt_random match unloaded\n");
14671 +module_init(init);
14672 +module_exit(fini);
14673 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c
14674 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
14675 +++ linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c 2004-06-25 12:21:13.447347432 +0200
14677 +#include <linux/module.h>
14678 +#include <linux/skbuff.h>
14679 +#include <net/ip.h>
14680 +#include <linux/sctp.h>
14682 +#include <linux/netfilter_ipv4/ip_tables.h>
14683 +#include <linux/netfilter_ipv4/ipt_sctp.h>
14686 +#define duprintf(format, args...) printk(format , ## args)
14688 +#define duprintf(format, args...)
14691 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
14692 + || (!!((invflag) & (option)) ^ (cond)))
14695 +match_flags(const struct ipt_sctp_flag_info *flag_info,
14696 + const int flag_count,
14697 + u_int8_t chunktype,
14698 + u_int8_t chunkflags)
14702 + for (i = 0; i < flag_count; i++) {
14703 + if (flag_info[i].chunktype == chunktype) {
14704 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
14712 +match_packet(const struct sk_buff *skb,
14713 + const u_int32_t *chunkmap,
14714 + int chunk_match_type,
14715 + const struct ipt_sctp_flag_info *flag_info,
14716 + const int flag_count,
14720 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
14721 + sctp_chunkhdr_t sch;
14725 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
14726 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
14729 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
14731 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
14732 + duprintf("Dropping invalid SCTP packet.\n");
14737 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
14738 + ++i, offset, sch.type, htons(sch.length), sch.flags);
14740 + offset += (htons(sch.length) + 3) & ~3;
14742 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
14744 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
14745 + switch (chunk_match_type) {
14746 + case SCTP_CHUNK_MATCH_ANY:
14747 + if (match_flags(flag_info, flag_count,
14748 + sch.type, sch.flags)) {
14753 + case SCTP_CHUNK_MATCH_ALL:
14754 + if (match_flags(flag_info, flag_count,
14755 + sch.type, sch.flags)) {
14756 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
14760 + case SCTP_CHUNK_MATCH_ONLY:
14761 + if (!match_flags(flag_info, flag_count,
14762 + sch.type, sch.flags)) {
14768 + switch (chunk_match_type) {
14769 + case SCTP_CHUNK_MATCH_ONLY:
14773 + } while (offset < skb->len);
14775 + switch (chunk_match_type) {
14776 + case SCTP_CHUNK_MATCH_ALL:
14777 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
14778 + case SCTP_CHUNK_MATCH_ANY:
14780 + case SCTP_CHUNK_MATCH_ONLY:
14784 + /* This will never be reached, but required to stop compiler whine */
14789 +match(const struct sk_buff *skb,
14790 + const struct net_device *in,
14791 + const struct net_device *out,
14792 + const void *matchinfo,
14796 + const struct ipt_sctp_info *info;
14797 + sctp_sctphdr_t sh;
14799 + info = (const struct ipt_sctp_info *)matchinfo;
14802 + duprintf("Dropping non-first fragment.. FIXME\n");
14806 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
14807 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
14811 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
14813 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
14814 + && (ntohs(sh.source) <= info->spts[1])),
14815 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
14816 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
14817 + && (ntohs(sh.dest) <= info->dpts[1])),
14818 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
14819 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
14820 + info->flag_info, info->flag_count,
14822 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
14826 +checkentry(const char *tablename,
14827 + const struct ipt_ip *ip,
14829 + unsigned int matchsize,
14830 + unsigned int hook_mask)
14832 + const struct ipt_sctp_info *info;
14834 + info = (const struct ipt_sctp_info *)matchinfo;
14836 + return ip->proto == IPPROTO_SCTP
14837 + && !(ip->invflags & IPT_INV_PROTO)
14838 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
14839 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
14840 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
14841 + && !(info->invflags & ~info->flags)
14842 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
14843 + (info->chunk_match_type &
14844 + (SCTP_CHUNK_MATCH_ALL
14845 + | SCTP_CHUNK_MATCH_ANY
14846 + | SCTP_CHUNK_MATCH_ONLY)));
14849 +static struct ipt_match sctp_match =
14851 + .list = { NULL, NULL},
14854 + .checkentry = &checkentry,
14856 + .me = THIS_MODULE
14859 +static int __init init(void)
14861 + return ipt_register_match(&sctp_match);
14864 +static void __exit fini(void)
14866 + ipt_unregister_match(&sctp_match);
14869 +module_init(init);
14870 +module_exit(fini);
14872 +MODULE_LICENSE("GPL");
14873 +MODULE_AUTHOR("Kiran Kumar Immidi");
14874 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
14876 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_string.c linux-2.6.7/net/ipv4/netfilter/ipt_string.c
14877 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
14878 +++ linux-2.6.7/net/ipv4/netfilter/ipt_string.c 2004-06-25 12:28:38.572678096 +0200
14880 +/* Kernel module to match a string into a packet.
14882 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
14885 + * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
14886 + * Initial 2.6 port
14887 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
14888 + * Fixed SMP re-entrancy problem using per-cpu data areas
14889 + * for the skip/shift tables.
14890 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14891 + * Fixed kernel panic, due to overrunning boyer moore string
14892 + * tables. Also slightly tweaked heuristic for deciding what
14893 + * search algo to use.
14894 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14895 + * Implemented Boyer Moore Sublinear search algorithm
14896 + * alongside the existing linear search based on memcmp().
14897 + * Also a quick check to decide which method to use on a per
14901 +#include <linux/smp.h>
14902 +#include <linux/percpu.h>
14903 +#include <linux/module.h>
14904 +#include <linux/skbuff.h>
14905 +#include <linux/file.h>
14906 +#include <net/sock.h>
14908 +#include <linux/netfilter_ipv4/ip_tables.h>
14909 +#include <linux/netfilter_ipv4/ipt_string.h>
14911 +MODULE_LICENSE("GPL");
14913 +struct string_per_cpu {
14914 + int skip[BM_MAX_HLEN];
14915 + int shift[BM_MAX_HLEN];
14916 + int len[BM_MAX_HLEN];
14919 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
14922 +/* Boyer Moore Sublinear string search - VERY FAST */
14923 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
14925 + int M1, right_end, sk, sh;
14928 + int *skip, *shift, *len;
14930 + /* use data suitable for this CPU */
14931 + shift=__get_cpu_var(bm_string_data).shift;
14932 + skip=__get_cpu_var(bm_string_data).skip;
14933 + len=__get_cpu_var(bm_string_data).len;
14935 + /* Setup skip/shift tables */
14936 + M1 = right_end = needle_len-1;
14937 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
14938 + for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
14940 + for (i = 1; i < needle_len; i++) {
14941 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
14946 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
14947 + for (i = M1; i > 0; i--) shift[len[i]] = i;
14950 + for (i = 0; i < needle_len; i++) {
14951 + if (len[i] == M1 - i) ended = i;
14952 + if (ended) shift[i] = ended;
14955 + /* Do the search*/
14956 + while (right_end < haystack_len)
14958 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
14959 + if (i == needle_len) {
14960 + return haystack+(right_end - M1);
14963 + sk = skip[(int)haystack[right_end - i]];
14965 + right_end = max(right_end - i + sk, right_end + sh);
14971 +/* Linear string search based on memcmp() */
14972 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
14974 + char *k = haystack + (haystack_len-needle_len);
14975 + char *t = haystack;
14977 + while ( t <= k ) {
14978 + if (memcmp(t, needle, needle_len) == 0)
14987 +match(const struct sk_buff *skb,
14988 + const struct net_device *in,
14989 + const struct net_device *out,
14990 + const void *matchinfo,
14994 + const struct ipt_string_info *info = matchinfo;
14995 + struct iphdr *ip = skb->nh.iph;
14997 + char *needle, *haystack;
14998 + proc_ipt_search search=search_linear;
15000 + if ( !ip ) return 0;
15002 + /* get lenghts, and validate them */
15004 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
15005 + if ( nlen > hlen ) return 0;
15007 + needle=(char *)&info->string;
15008 + haystack=(char *)ip+(ip->ihl*4);
15010 + /* The sublinear search comes in to its own
15011 + * on the larger packets */
15012 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
15013 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
15014 + if ( hlen < BM_MAX_HLEN ) {
15015 + search=search_sublinear;
15017 + if (net_ratelimit())
15018 + printk(KERN_INFO "ipt_string: Packet too big "
15019 + "to attempt sublinear string search "
15020 + "(%d bytes)\n", hlen );
15024 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
15028 +checkentry(const char *tablename,
15029 + const struct ipt_ip *ip,
15031 + unsigned int matchsize,
15032 + unsigned int hook_mask)
15035 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
15041 +static struct ipt_match string_match = {
15042 + .name = "string",
15044 + .checkentry = &checkentry,
15045 + .me = THIS_MODULE
15049 +static int __init init(void)
15051 + return ipt_register_match(&string_match);
15054 +static void __exit fini(void)
15056 + ipt_unregister_match(&string_match);
15059 +module_init(init);
15060 +module_exit(fini);
15063 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7/net/ipv4/netfilter/ipt_time.c
15064 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
15065 +++ linux-2.6.7/net/ipv4/netfilter/ipt_time.c 2004-06-25 12:21:13.934273408 +0200
15068 + This is a module which is used for time matching
15069 + It is using some modified code from dietlibc (localtime() function)
15070 + that you can find at http://www.fefe.de/dietlibc/
15071 + This file is distributed under the terms of the GNU General Public
15072 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
15073 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
15074 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
15075 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
15076 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
15077 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
15078 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
15079 + 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
15082 +#include <linux/module.h>
15083 +#include <linux/skbuff.h>
15084 +#include <linux/netfilter_ipv4/ip_tables.h>
15085 +#include <linux/netfilter_ipv4/ipt_time.h>
15086 +#include <linux/time.h>
15088 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
15089 +MODULE_DESCRIPTION("Match arrival timestamp/date");
15090 +MODULE_LICENSE("GPL");
15094 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
15095 + int tm_min; /* Minutes. [0-59] */
15096 + int tm_hour; /* Hours. [0-23] */
15097 + int tm_mday; /* Day. [1-31] */
15098 + int tm_mon; /* Month. [0-11] */
15099 + int tm_year; /* Year - 1900. */
15100 + int tm_wday; /* Day of week. [0-6] */
15101 + int tm_yday; /* Days in year.[0-365] */
15102 + int tm_isdst; /* DST. [-1/0/1]*/
15104 + long int tm_gmtoff; /* we don't care, we count from GMT */
15105 + const char *tm_zone; /* we don't care, we count from GMT */
15109 +localtime(const time_t *timepr, struct tm *r);
15112 +match(const struct sk_buff *skb,
15113 + const struct net_device *in,
15114 + const struct net_device *out,
15115 + const void *matchinfo,
15118 + u_int16_t datalen,
15121 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
15122 + struct tm currenttime; /* time human readable */
15123 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
15124 + u_int16_t packet_time;
15125 + struct timeval kerneltimeval;
15126 + time_t packet_local_time;
15128 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
15129 + if (info->kerneltime)
15131 + do_gettimeofday(&kerneltimeval);
15132 + packet_local_time = kerneltimeval.tv_sec;
15135 + packet_local_time = skb->stamp.tv_sec;
15137 + /* First we make sure we are in the date start-stop boundaries */
15138 + if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
15139 + return 0; /* We are outside the date boundaries */
15141 + /* Transform the timestamp of the packet, in a human readable form */
15142 + localtime(&packet_local_time, ¤ttime);
15144 + /* check if we match this timestamp, we start by the days... */
15145 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
15146 + return 0; /* the day doesn't match */
15148 + /* ... check the time now */
15149 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
15150 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
15153 + /* here we match ! */
15158 +checkentry(const char *tablename,
15159 + const struct ipt_ip *ip,
15161 + unsigned int matchsize,
15162 + unsigned int hook_mask)
15164 + struct ipt_time_info *info = matchinfo; /* match info for rule */
15166 + /* First, check that we are in the correct hooks */
15168 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15170 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
15173 + /* we use the kerneltime if we are in forward or output */
15174 + info->kerneltime = 1;
15175 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15176 + /* we use the skb time */
15177 + info->kerneltime = 0;
15179 + /* Check the size */
15180 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
15182 + /* Now check the coherence of the data ... */
15183 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
15184 + (info->time_stop > 1439))
15186 + printk(KERN_WARNING "ipt_time: invalid argument\n");
15193 +static struct ipt_match time_match
15194 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
15196 +static int __init init(void)
15198 + printk("ipt_time loading\n");
15199 + return ipt_register_match(&time_match);
15202 +static void __exit fini(void)
15204 + ipt_unregister_match(&time_match);
15205 + printk("ipt_time unloaded\n");
15208 +module_init(init);
15209 +module_exit(fini);
15212 +/* The part below is borowed and modified from dietlibc */
15214 +/* seconds per day */
15215 +#define SPD 24*60*60
15218 +localtime(const time_t *timepr, struct tm *r) {
15221 + extern struct timezone sys_tz;
15222 + const unsigned int __spm[12] =
15228 + (31+28+31+30+31),
15229 + (31+28+31+30+31+30),
15230 + (31+28+31+30+31+30+31),
15231 + (31+28+31+30+31+30+31+31),
15232 + (31+28+31+30+31+30+31+31+30),
15233 + (31+28+31+30+31+30+31+31+30+31),
15234 + (31+28+31+30+31+30+31+31+30+31+30),
15236 + register time_t work;
15238 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
15239 + work=timep%(SPD);
15240 + r->tm_sec=work%60; work/=60;
15241 + r->tm_min=work%60; r->tm_hour=work/60;
15242 + work=timep/(SPD);
15243 + r->tm_wday=(4+work)%7;
15244 + for (i=1970; ; ++i) {
15245 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
15251 + r->tm_year=i-1900;
15252 + for (i=11; i && __spm[i]>work; --i) ;
15254 + r->tm_mday=work-__spm[i]+1;
15256 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.7/net/ipv4/netfilter/ipt_u32.c
15257 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
15258 +++ linux-2.6.7/net/ipv4/netfilter/ipt_u32.c 2004-06-25 12:21:14.422199232 +0200
15260 +/* Kernel module to match u32 packet content. */
15263 +U32 tests whether quantities of up to 4 bytes extracted from a packet
15264 +have specified values. The specification of what to extract is general
15265 +enough to find data at given offsets from tcp headers or payloads.
15268 + The argument amounts to a program in a small language described below.
15269 + tests := location = value | tests && location = value
15270 + value := range | value , range
15271 + range := number | number : number
15272 + a single number, n, is interpreted the same as n:n
15273 + n:m is interpreted as the range of numbers >=n and <=m
15274 + location := number | location operator number
15275 + operator := & | << | >> | @
15277 + The operators &, <<, >>, && mean the same as in c. The = is really a set
15278 + membership operator and the value syntax describes a set. The @ operator
15279 + is what allows moving to the next header and is described further below.
15281 + *** Until I can find out how to avoid it, there are some artificial limits
15282 + on the size of the tests:
15283 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
15284 + - no more than 10 ranges (and 9 commas) per value
15285 + - no more than 10 numbers (and 9 operators) per location
15287 + To describe the meaning of location, imagine the following machine that
15288 + interprets it. There are three registers:
15289 + A is of type char*, initially the address of the IP header
15290 + B and C are unsigned 32 bit integers, initially zero
15292 + The instructions are:
15293 + number B = number;
15294 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
15295 + &number C = C&number
15296 + <<number C = C<<number
15297 + >>number C = C>>number
15298 + @number A = A+C; then do the instruction number
15299 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
15300 + Otherwise the result of the computation is the final value of C.
15302 + Whitespace is allowed but not required in the tests.
15303 + However the characters that do occur there are likely to require
15304 + shell quoting, so it's a good idea to enclose the arguments in quotes.
15307 + match IP packets with total length >= 256
15308 + The IP header contains a total length field in bytes 2-3.
15309 + --u32 "0&0xFFFF=0x100:0xFFFF"
15311 + AND that with FFFF (giving bytes 2-3),
15312 + and test whether that's in the range [0x100:0xFFFF]
15314 +Example: (more realistic, hence more complicated)
15315 + match icmp packets with icmp type 0
15316 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
15317 + --u32 "6&0xFF=1 && ...
15318 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
15319 + Next test that it's not a fragment.
15320 + (If so it might be part of such a packet but we can't always tell.)
15321 + n.b. This test is generally needed if you want to match anything
15322 + beyond the IP header.
15323 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
15324 + packet (not a fragment). Alternatively, you can allow first fragments
15325 + by only testing the last 5 bits of byte 6.
15326 + ... 4&0x3FFF=0 && ...
15327 + Last test: the first byte past the IP header (the type) is 0
15328 + This is where we have to use the @syntax. The length of the IP header
15329 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
15330 + IP header itself.
15331 + ... 0>>22&0x3C@0>>24=0"
15332 + The first 0 means read bytes 0-3,
15333 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
15334 + the first byte, so only 22 bits is four times that plus a few more bits.
15335 + &3C then eliminates the two extra bits on the right and the first four
15336 + bits of the first byte.
15337 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
15338 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
15339 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
15340 + @ means to use this number as a new offset into the packet, and read
15341 + four bytes starting from there. This is the first 4 bytes of the icmp
15342 + payload, of which byte 0 is the icmp type. Therefore we simply shift
15343 + the value 24 to the right to throw out all but the first byte and compare
15344 + the result with 0.
15347 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
15348 + First we test that the packet is a tcp packet (similar to icmp).
15349 + --u32 "6&0xFF=6 && ...
15350 + Next, test that it's not a fragment (same as above).
15351 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
15352 + 0>>22&3C as above computes the number of bytes in the IP header.
15353 + @ makes this the new offset into the packet, which is the start of the
15354 + tcp header. The length of the tcp header (again in 32 bit words) is
15355 + the left half of byte 12 of the tcp header. The 12>>26&3C
15356 + computes this length in bytes (similar to the IP header before).
15357 + @ makes this the new offset, which is the start of the tcp payload.
15358 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
15359 + result is any of 1, 2, 5 or 8
15362 +#include <linux/module.h>
15363 +#include <linux/skbuff.h>
15365 +#include <linux/netfilter_ipv4/ipt_u32.h>
15366 +#include <linux/netfilter_ipv4/ip_tables.h>
15368 +/* #include <asm-i386/timex.h> for timing */
15370 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
15371 +MODULE_DESCRIPTION("IP tables u32 matching module");
15372 +MODULE_LICENSE("GPL");
15375 +match(const struct sk_buff *skb,
15376 + const struct net_device *in,
15377 + const struct net_device *out,
15378 + const void *matchinfo,
15381 + u_int16_t datalen,
15384 + const struct ipt_u32 *data = matchinfo;
15386 + unsigned char* origbase = (char*)skb->nh.iph;
15387 + unsigned char* base = origbase;
15388 + unsigned char* head = skb->head;
15389 + unsigned char* end = skb->end;
15390 + int nnums, nvals;
15391 + u_int32_t pos, val;
15392 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
15393 + cycles1 = get_cycles(); */
15395 + for (testind=0; testind < data->ntests; testind++) {
15396 + base = origbase; /* reset for each test */
15397 + pos = data->tests[testind].location[0].number;
15398 + if (base+pos+3 > end || base+pos < head)
15400 + val = (base[pos]<<24) + (base[pos+1]<<16) +
15401 + (base[pos+2]<<8) + base[pos+3];
15402 + nnums = data->tests[testind].nnums;
15403 + for (i=1; i < nnums; i++) {
15404 + u_int32_t number = data->tests[testind].location[i].number;
15405 + switch (data->tests[testind].location[i].nextop) {
15406 + case IPT_U32_AND:
15407 + val = val & number;
15409 + case IPT_U32_LEFTSH:
15410 + val = val << number;
15412 + case IPT_U32_RIGHTSH:
15413 + val = val >> number;
15416 + base = base + val;
15418 + if (base+pos+3 > end || base+pos < head)
15420 + val = (base[pos]<<24) + (base[pos+1]<<16) +
15421 + (base[pos+2]<<8) + base[pos+3];
15425 + nvals = data->tests[testind].nvalues;
15426 + for (i=0; i < nvals; i++) {
15427 + if ((data->tests[testind].value[i].min <= val) &&
15428 + (val <= data->tests[testind].value[i].max)) {
15432 + if (i >= data->tests[testind].nvalues) {
15433 + /* cycles2 = get_cycles();
15434 + printk("failed %d in %d cycles\n", testind,
15435 + cycles2-cycles1); */
15439 + /* cycles2 = get_cycles();
15440 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
15445 +checkentry(const char *tablename,
15446 + const struct ipt_ip *ip,
15448 + unsigned int matchsize,
15449 + unsigned int hook_mask)
15451 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
15456 +static struct ipt_match u32_match
15457 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
15459 +static int __init init(void)
15461 + return ipt_register_match(&u32_match);
15464 +static void __exit fini(void)
15466 + ipt_unregister_match(&u32_match);
15469 +module_init(init);
15470 +module_exit(fini);
15471 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.7/net/ipv4/netfilter/ipt_unclean.c
15472 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
15473 +++ linux-2.6.7/net/ipv4/netfilter/ipt_unclean.c 2004-06-25 12:28:34.799251744 +0200
15475 +/* Kernel module to match suspect packets. */
15476 +#include <linux/module.h>
15477 +#include <linux/skbuff.h>
15478 +#include <linux/ip.h>
15479 +#include <linux/udp.h>
15480 +#include <linux/tcp.h>
15481 +#include <linux/icmp.h>
15482 +#include <net/checksum.h>
15484 +#include <linux/netfilter_ipv4/ip_tables.h>
15486 +#define limpk(format, args...) \
15488 + if (net_ratelimit()) \
15489 + printk("ipt_unclean: %s" format, \
15490 + embedded ? "(embedded packet) " : "" , ## args); \
15493 +enum icmp_error_status
15495 + ICMP_MAY_BE_ERROR,
15502 + size_t min_len, max_len;
15503 + enum icmp_error_status err;
15504 + u_int8_t min_code, max_code;
15508 +check_ip(struct iphdr *iph, size_t length, int embedded);
15510 +/* ICMP-specific checks. */
15512 +check_icmp(const struct icmphdr *icmph,
15513 + u_int16_t datalen,
15514 + unsigned int offset,
15518 + static struct icmp_info info[]
15519 + = { [ICMP_ECHOREPLY]
15520 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15521 + [ICMP_DEST_UNREACH]
15522 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
15523 + [ICMP_SOURCE_QUENCH]
15524 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
15526 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
15528 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15529 + /* Router advertisement. */
15531 + = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
15532 + /* Router solicitation. */
15534 + = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
15535 + [ICMP_TIME_EXCEEDED]
15536 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
15537 + [ICMP_PARAMETERPROB]
15538 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
15540 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15541 + [ICMP_TIMESTAMPREPLY]
15542 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15543 + [ICMP_INFO_REQUEST]
15544 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15545 + [ICMP_INFO_REPLY]
15546 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15548 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
15549 + [ICMP_ADDRESSREPLY]
15550 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
15552 + /* Can't do anything if it's a fragment. */
15556 + /* Must cover type and code. */
15557 + if (datalen < 2) {
15558 + limpk("ICMP len=%u too short\n", datalen);
15562 + /* If not embedded. */
15564 + /* Bad checksum? Don't print, just ignore. */
15566 + && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
15569 + /* CHECK: Truncated ICMP (even if first fragment). */
15570 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15571 + && info[icmph->type].min_len != 0
15572 + && datalen < info[icmph->type].min_len) {
15573 + limpk("ICMP type %u len %u too short\n",
15574 + icmph->type, datalen);
15578 + /* CHECK: Check within known error ICMPs. */
15579 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15580 + && info[icmph->type].err == ICMP_IS_ERROR) {
15581 + /* CHECK: Embedded packet must be at least
15582 + length of iph + 8 bytes. */
15583 + struct iphdr *inner = (void *)icmph + 8;
15585 + /* datalen > 8 since all ICMP_IS_ERROR types
15586 + have min length > 8 */
15587 + if (datalen - 8 < sizeof(struct iphdr)) {
15588 + limpk("ICMP error internal way too short\n");
15591 + if (datalen - 8 < inner->ihl*4 + 8) {
15592 + limpk("ICMP error internal too short\n");
15595 + if (!check_ip(inner, datalen - 8, 1))
15599 + /* CHECK: Can't embed ICMP unless known non-error. */
15600 + if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
15601 + || info[icmph->type].err != ICMP_NOT_ERROR) {
15602 + limpk("ICMP type %u not embeddable\n",
15608 + /* CHECK: Invalid ICMP codes. */
15609 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15610 + && (icmph->code < info[icmph->type].min_code
15611 + || icmph->code > info[icmph->type].max_code)) {
15612 + limpk("ICMP type=%u code=%u\n",
15613 + icmph->type, icmph->code);
15617 + /* CHECK: Above maximum length. */
15618 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15619 + && info[icmph->type].max_len != 0
15620 + && datalen > info[icmph->type].max_len) {
15621 + limpk("ICMP type=%u too long: %u bytes\n",
15622 + icmph->type, datalen);
15626 + switch (icmph->type) {
15627 + case ICMP_PARAMETERPROB: {
15628 + /* CHECK: Problem param must be within error packet's
15630 + struct iphdr *iph = (void *)icmph + 8;
15631 + u_int32_t arg = ntohl(icmph->un.gateway);
15633 + if (icmph->code == 0) {
15634 + /* Code 0 means that upper 8 bits is pointer
15636 + if ((arg >> 24) >= iph->ihl*4) {
15637 + limpk("ICMP PARAMETERPROB ptr = %u\n",
15638 + ntohl(icmph->un.gateway) >> 24);
15641 + arg &= 0x00FFFFFF;
15644 + /* CHECK: Rest must be zero. */
15646 + limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
15653 + case ICMP_TIME_EXCEEDED:
15654 + case ICMP_SOURCE_QUENCH:
15655 + /* CHECK: Unused must be zero. */
15656 + if (icmph->un.gateway != 0) {
15657 + limpk("ICMP type=%u unused = %u\n",
15658 + icmph->type, ntohl(icmph->un.gateway));
15667 +/* UDP-specific checks. */
15669 +check_udp(const struct iphdr *iph,
15670 + const struct udphdr *udph,
15671 + u_int16_t datalen,
15672 + unsigned int offset,
15676 + /* Can't do anything if it's a fragment. */
15680 + /* CHECK: Must cover UDP header. */
15681 + if (datalen < sizeof(struct udphdr)) {
15682 + limpk("UDP len=%u too short\n", datalen);
15686 + /* Bad checksum? Don't print, just say it's unclean. */
15687 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
15688 + if (!more_frags && !embedded && udph->check
15689 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
15690 + csum_partial((char *)udph, datalen, 0)) != 0)
15693 + /* CHECK: Destination port can't be zero. */
15694 + if (!udph->dest) {
15695 + limpk("UDP zero destination port\n");
15699 + if (!more_frags) {
15701 + /* CHECK: UDP length must match. */
15702 + if (ntohs(udph->len) != datalen) {
15703 + limpk("UDP len too short %u vs %u\n",
15704 + ntohs(udph->len), datalen);
15708 + /* CHECK: UDP length be >= this truncated pkt. */
15709 + if (ntohs(udph->len) < datalen) {
15710 + limpk("UDP len too long %u vs %u\n",
15711 + ntohs(udph->len), datalen);
15716 + /* CHECK: UDP length must be > this frag's length. */
15717 + if (ntohs(udph->len) <= datalen) {
15718 + limpk("UDP fragment len too short %u vs %u\n",
15719 + ntohs(udph->len), datalen);
15727 +#define TH_FIN 0x01
15728 +#define TH_SYN 0x02
15729 +#define TH_RST 0x04
15730 +#define TH_PUSH 0x08
15731 +#define TH_ACK 0x10
15732 +#define TH_URG 0x20
15733 +#define TH_ECE 0x40
15734 +#define TH_CWR 0x80
15736 +/* table of valid flag combinations - ECE and CWR are always valid */
15737 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
15740 + [TH_SYN|TH_ACK] = 1,
15742 + [TH_RST|TH_ACK] = 1,
15743 + [TH_RST|TH_ACK|TH_PUSH] = 1,
15744 + [TH_FIN|TH_ACK] = 1,
15746 + [TH_ACK|TH_PUSH] = 1,
15747 + [TH_ACK|TH_URG] = 1,
15748 + [TH_ACK|TH_URG|TH_PUSH] = 1,
15749 + [TH_FIN|TH_ACK|TH_PUSH] = 1,
15750 + [TH_FIN|TH_ACK|TH_URG] = 1,
15751 + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
15754 +/* TCP-specific checks. */
15756 +check_tcp(const struct iphdr *iph,
15757 + const struct tcphdr *tcph,
15758 + u_int16_t datalen,
15759 + unsigned int offset,
15763 + u_int8_t *opt = (u_int8_t *)tcph;
15764 + u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
15765 + u_int8_t tcpflags;
15766 + int end_of_options = 0;
15769 + /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
15770 + /* In fact, this is caught below (offset < 516). */
15772 + /* Can't do anything if it's a fragment. */
15776 + /* CHECK: Smaller than minimal TCP hdr. */
15777 + if (datalen < sizeof(struct tcphdr)) {
15779 + limpk("Packet length %u < TCP header.\n", datalen);
15782 + /* Must have ports available (datalen >= 8), from
15783 + check_icmp which set embedded = 1 */
15784 + /* CHECK: TCP ports inside ICMP error */
15785 + if (!tcph->source || !tcph->dest) {
15786 + limpk("Zero TCP ports %u/%u.\n",
15787 + htons(tcph->source), htons(tcph->dest));
15793 + /* CHECK: Smaller than actual TCP hdr. */
15794 + if (datalen < tcph->doff * 4) {
15796 + limpk("Packet length %u < actual TCP header.\n",
15803 + /* Bad checksum? Don't print, just say it's unclean. */
15804 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
15805 + if (!more_frags && !embedded
15806 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
15807 + csum_partial((char *)tcph, datalen, 0)) != 0)
15810 + /* CHECK: TCP ports non-zero */
15811 + if (!tcph->source || !tcph->dest) {
15812 + limpk("Zero TCP ports %u/%u.\n",
15813 + htons(tcph->source), htons(tcph->dest));
15817 + /* CHECK: TCP reserved bits zero. */
15818 + if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
15819 + limpk("TCP reserved bits not zero\n");
15823 + /* CHECK: TCP flags. */
15824 + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
15825 + if (!tcp_valid_flags[tcpflags]) {
15826 + limpk("TCP flags bad: %u\n", tcpflags);
15830 + for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
15831 + switch (opt[i]) {
15833 + end_of_options = 1;
15840 + /* CHECK: options after EOO. */
15841 + if (end_of_options) {
15842 + limpk("TCP option %u after end\n",
15846 + /* CHECK: options at tail. */
15847 + else if (i+1 >= tcph->doff * 4) {
15848 + limpk("TCP option %u at tail\n",
15852 + /* CHECK: zero-length options. */
15853 + else if (opt[i+1] == 0) {
15854 + limpk("TCP option %u 0 len\n",
15858 + /* CHECK: oversize options. */
15859 + else if (&opt[i] + opt[i+1] > endhdr) {
15860 + limpk("TCP option %u at %Zu too long\n",
15861 + (unsigned int) opt[i], i);
15864 + /* Move to next option */
15872 +/* Returns 1 if ok */
15873 +/* Standard IP checks. */
15875 +check_ip(struct iphdr *iph, size_t length, int embedded)
15877 + u_int8_t *opt = (u_int8_t *)iph;
15878 + u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
15879 + int end_of_options = 0;
15883 + unsigned int offset;
15885 + /* Should only happen for local outgoing raw-socket packets. */
15886 + /* CHECK: length >= ip header. */
15887 + if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
15888 + limpk("Packet length %Zu < IP header.\n", length);
15892 + offset = ntohs(iph->frag_off) & IP_OFFSET;
15893 + protoh = (void *)iph + iph->ihl * 4;
15894 + datalen = length - iph->ihl * 4;
15896 + /* CHECK: Embedded fragment. */
15897 + if (embedded && offset) {
15898 + limpk("Embedded fragment.\n");
15902 + for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
15903 + switch (opt[i]) {
15905 + end_of_options = 1;
15912 + /* CHECK: options after EOO. */
15913 + if (end_of_options) {
15914 + limpk("IP option %u after end\n",
15918 + /* CHECK: options at tail. */
15919 + else if (i+1 >= iph->ihl * 4) {
15920 + limpk("IP option %u at tail\n",
15924 + /* CHECK: zero-length or one-length options. */
15925 + else if (opt[i+1] < 2) {
15926 + limpk("IP option %u %u len\n",
15927 + opt[i], opt[i+1]);
15930 + /* CHECK: oversize options. */
15931 + else if (&opt[i] + opt[i+1] > endhdr) {
15932 + limpk("IP option %u at %u too long\n",
15936 + /* Move to next option */
15941 + /* Fragment checks. */
15943 + /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
15944 + if ((ntohs(iph->frag_off) & IP_MF)
15945 + && (ntohs(iph->tot_len) % 8) != 0) {
15946 + limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
15950 + /* CHECK: Oversize fragment a-la Ping of Death. */
15951 + if (offset * 8 + datalen > 65535) {
15952 + limpk("Oversize fragment to %u.\n", offset * 8);
15956 + /* CHECK: DF set and offset or MF set. */
15957 + if ((ntohs(iph->frag_off) & IP_DF)
15958 + && (offset || (ntohs(iph->frag_off) & IP_MF))) {
15959 + limpk("DF set and offset=%u, MF=%u.\n",
15960 + offset, ntohs(iph->frag_off) & IP_MF);
15964 + /* CHECK: Zero-sized fragments. */
15965 + if ((offset || (ntohs(iph->frag_off) & IP_MF))
15966 + && datalen == 0) {
15967 + limpk("Zero size fragment offset=%u\n", offset);
15971 + /* Note: we can have even middle fragments smaller than this:
15972 + consider a large packet passing through a 600MTU then
15973 + 576MTU link: this gives a fragment of 24 data bytes. But
15974 + everyone packs fragments largest first, hence a fragment
15975 + can't START before 576 - MAX_IP_HEADER_LEN. */
15977 + /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
15978 + down to 128 (576 taken from RFC 791: All hosts must be
15979 + prepared to accept datagrams of up to 576 octets). Use 128
15981 +#define MIN_LIKELY_MTU 128
15982 + /* CHECK: Min size of first frag = 128. */
15983 + if ((ntohs(iph->frag_off) & IP_MF)
15985 + && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
15986 + limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
15991 + /* CHECK: Min offset of frag = 128 - IP hdr len. */
15992 + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
15993 + limpk("Fragment starts at %u < %u\n", offset * 8,
15994 + MIN_LIKELY_MTU - iph->ihl * 4);
15998 + /* CHECK: Protocol specification non-zero. */
15999 + if (iph->protocol == 0) {
16000 + limpk("Zero protocol\n");
16004 + /* CHECK: Do not use what is unused.
16005 + * First bit of fragmentation flags should be unused.
16006 + * May be used by OS fingerprinting tools.
16007 + * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
16009 + if (ntohs(iph->frag_off)>>15) {
16010 + limpk("IP unused bit set\n");
16014 + /* Per-protocol checks. */
16015 + switch (iph->protocol) {
16016 + case IPPROTO_ICMP:
16017 + return check_icmp(protoh, datalen, offset,
16018 + (ntohs(iph->frag_off) & IP_MF),
16021 + case IPPROTO_UDP:
16022 + return check_udp(iph, protoh, datalen, offset,
16023 + (ntohs(iph->frag_off) & IP_MF),
16026 + case IPPROTO_TCP:
16027 + return check_tcp(iph, protoh, datalen, offset,
16028 + (ntohs(iph->frag_off) & IP_MF),
16031 + /* Ignorance is bliss. */
16037 +match(const struct sk_buff *skb,
16038 + const struct net_device *in,
16039 + const struct net_device *out,
16040 + const void *matchinfo,
16043 + u_int16_t datalen,
16046 + return !check_ip(skb->nh.iph, skb->len, 0);
16049 +/* Called when user tries to insert an entry of this type. */
16051 +checkentry(const char *tablename,
16052 + const struct ipt_ip *ip,
16054 + unsigned int matchsize,
16055 + unsigned int hook_mask)
16057 + if (matchsize != IPT_ALIGN(0))
16063 +static struct ipt_match unclean_match
16064 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
16066 +static int __init init(void)
16068 + return ipt_register_match(&unclean_match);
16071 +static void __exit fini(void)
16073 + ipt_unregister_match(&unclean_match);
16076 +module_init(init);
16077 +module_exit(fini);
16078 +MODULE_LICENSE("GPL");
16079 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/string.2.6.patch linux-2.6.7/net/ipv4/netfilter/string.2.6.patch
16080 --- linux-2.6.7.org/net/ipv4/netfilter/string.2.6.patch 1970-01-01 01:00:00.000000000 +0100
16081 +++ linux-2.6.7/net/ipv4/netfilter/string.2.6.patch 2004-06-25 12:28:38.580676880 +0200
16083 +--- ipt_string.c.old Mon Mar 29 06:00:23 2004
16084 ++++ ipt_string.c Mon Mar 29 06:01:04 2004
16086 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
16089 ++ * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
16090 ++ * Initial 2.6 port
16091 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
16092 + * Fixed SMP re-entrancy problem using per-cpu data areas
16093 + * for the skip/shift tables.
16097 + #include <linux/smp.h>
16098 ++#include <linux/percpu.h>
16099 + #include <linux/module.h>
16100 + #include <linux/skbuff.h>
16101 + #include <linux/file.h>
16102 +@@ -29,12 +32,13 @@
16103 + MODULE_LICENSE("GPL");
16105 + struct string_per_cpu {
16109 ++ int skip[BM_MAX_HLEN];
16110 ++ int shift[BM_MAX_HLEN];
16111 ++ int len[BM_MAX_HLEN];
16114 +-struct string_per_cpu *bm_string_data=NULL;
16115 ++static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
16118 + /* Boyer Moore Sublinear string search - VERY FAST */
16119 + char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
16120 +@@ -45,14 +49,14 @@
16121 + int *skip, *shift, *len;
16123 + /* use data suitable for this CPU */
16124 +- shift=bm_string_data[smp_processor_id()].shift;
16125 +- skip=bm_string_data[smp_processor_id()].skip;
16126 +- len=bm_string_data[smp_processor_id()].len;
16127 ++ shift=__get_cpu_var(bm_string_data).shift;
16128 ++ skip=__get_cpu_var(bm_string_data).skip;
16129 ++ len=__get_cpu_var(bm_string_data).len;
16131 + /* Setup skip/shift tables */
16132 + M1 = right_end = needle_len-1;
16133 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
16134 +- for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
16135 ++ for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
16137 + for (i = 1; i < needle_len; i++) {
16138 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
16140 + return haystack+(right_end - M1);
16143 +- sk = skip[haystack[right_end - i]];
16144 ++ sk = skip[(int)haystack[right_end - i]];
16146 + right_end = max(right_end - i + sk, right_end + sh);
16148 +@@ -100,15 +104,12 @@
16154 + match(const struct sk_buff *skb,
16155 + const struct net_device *in,
16156 + const struct net_device *out,
16157 + const void *matchinfo,
16159 +- const void *hdr,
16160 +- u_int16_t datalen,
16163 + const struct ipt_string_info *info = matchinfo;
16164 +@@ -158,61 +159,25 @@
16168 +-void string_freeup_data(void)
16172 +- if ( bm_string_data ) {
16173 +- for(c=0; c<smp_num_cpus; c++) {
16174 +- if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
16175 +- if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
16176 +- if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
16178 +- kfree(bm_string_data);
16181 ++static struct ipt_match string_match = {
16182 ++ .name = "string",
16183 ++ .match = &match,
16184 ++ .checkentry = &checkentry,
16185 ++ .me = THIS_MODULE
16188 +-static struct ipt_match string_match
16189 +-= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
16191 + static int __init init(void)
16197 +- tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
16198 +- alen=sizeof(int)*BM_MAX_HLEN;
16200 +- /* allocate array of structures */
16201 +- if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
16205 +- memset(bm_string_data, 0, tlen);
16207 +- /* allocate our skip/shift tables */
16208 +- for(c=0; c<smp_num_cpus; c++) {
16209 +- if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
16210 +- goto alloc_fail;
16211 +- if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
16212 +- goto alloc_fail;
16213 +- if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
16214 +- goto alloc_fail;
16217 + return ipt_register_match(&string_match);
16220 +- string_freeup_data();
16224 + static void __exit fini(void)
16226 + ipt_unregister_match(&string_match);
16227 +- string_freeup_data();
16230 + module_init(init);
16231 + module_exit(fini);
16235 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/raw.c linux-2.6.7/net/ipv4/raw.c
16236 --- linux-2.6.7.org/net/ipv4/raw.c 2004-06-16 07:19:36.000000000 +0200
16237 +++ linux-2.6.7/net/ipv4/raw.c 2004-06-25 12:21:38.705507608 +0200
16238 @@ -249,6 +249,7 @@
16240 return NET_RX_DROP;
16244 skb_push(skb, skb->data - skb->nh.raw);
16246 @@ -307,7 +308,7 @@
16249 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
16253 err = inet->recverr ? net_xmit_errno(err) : 0;
16255 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/tcp_ipv4.c linux-2.6.7/net/ipv4/tcp_ipv4.c
16256 --- linux-2.6.7.org/net/ipv4/tcp_ipv4.c 2004-06-25 10:47:46.000000000 +0200
16257 +++ linux-2.6.7/net/ipv4/tcp_ipv4.c 2004-06-25 12:23:16.012714664 +0200
16258 @@ -1785,6 +1785,7 @@
16260 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
16261 goto discard_and_relse;
16264 if (sk_filter(sk, skb, 0))
16265 goto discard_and_relse;
16266 @@ -2640,6 +2641,7 @@
16267 EXPORT_SYMBOL(tcp_v4_connect);
16268 EXPORT_SYMBOL(tcp_v4_do_rcv);
16269 EXPORT_SYMBOL(tcp_v4_lookup_listener);
16270 +EXPORT_SYMBOL(tcp_v4_lookup);
16271 EXPORT_SYMBOL(tcp_v4_rebuild_header);
16272 EXPORT_SYMBOL(tcp_v4_remember_stamp);
16273 EXPORT_SYMBOL(tcp_v4_send_check);
16274 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/udp.c linux-2.6.7/net/ipv4/udp.c
16275 --- linux-2.6.7.org/net/ipv4/udp.c 2004-06-16 07:18:59.000000000 +0200
16276 +++ linux-2.6.7/net/ipv4/udp.c 2004-06-25 12:23:16.018713752 +0200
16277 @@ -1045,6 +1045,7 @@
16283 if (up->encap_type) {
16285 @@ -1210,6 +1211,7 @@
16287 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
16291 /* No socket. Drop packet silently, if checksum is wrong */
16292 if (udp_checksum_complete(skb))
16293 @@ -1558,6 +1560,7 @@
16294 EXPORT_SYMBOL(udp_port_rover);
16295 EXPORT_SYMBOL(udp_prot);
16296 EXPORT_SYMBOL(udp_sendmsg);
16297 +EXPORT_SYMBOL(udp_v4_lookup);
16299 #ifdef CONFIG_PROC_FS
16300 EXPORT_SYMBOL(udp_proc_register);
16301 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/xfrm4_tunnel.c linux-2.6.7/net/ipv4/xfrm4_tunnel.c
16302 --- linux-2.6.7.org/net/ipv4/xfrm4_tunnel.c 2004-06-25 10:47:46.000000000 +0200
16303 +++ linux-2.6.7/net/ipv4/xfrm4_tunnel.c 2004-06-25 12:21:37.109750200 +0200
16305 err = -EHOSTUNREACH;
16308 + IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
16309 return NET_XMIT_BYPASS;
16312 @@ -171,6 +172,7 @@
16313 .handler = ipip_rcv,
16314 .err_handler = ipip_err,
16319 static int __init ipip_init(void)
16320 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/K linux-2.6.7/net/ipv6/netfilter/K
16321 --- linux-2.6.7.org/net/ipv6/netfilter/K 1970-01-01 01:00:00.000000000 +0100
16322 +++ linux-2.6.7/net/ipv6/netfilter/K 2004-05-07 18:20:57.000000000 +0200
16324 +config IP6_NF_MATCH_POLICY
16325 + tristate "IPsec policy match support"
16326 + depends on IP6_NF_IPTABLES && XFRM
16328 + Policy matching allows you to match packets based on the
16329 + IPsec policy that was used during decapsulation/will
16330 + be used during encapsulation.
16332 + To compile it as a module, choose M here. If unsure, say N.
16333 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig linux-2.6.7/net/ipv6/netfilter/Kconfig
16334 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig 2004-06-16 07:19:52.000000000 +0200
16335 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig 2004-06-25 12:27:59.398633456 +0200
16336 @@ -230,5 +230,107 @@
16337 <file:Documentation/modules.txt>. If unsure, say `N'.
16340 +config IP6_NF_TARGET_HL
16341 + tristate 'HL target support'
16342 + depends on IP6_NF_MANGLE
16344 + This option adds a `HL' target, which allows you to modify the value of
16345 + IPv6 Hop Limit field.
16347 + If you want to compile it as a module, say M here and read
16348 + <file:Documentation/modules.txt>. If unsure, say `N'.
16350 +config IP6_NF_TARGET_REJECT
16351 + tristate 'REJECT target support'
16352 + depends on IP6_NF_FILTER
16354 + The REJECT target allows a filtering rule to specify that an ICMPv6
16355 + error should be issued in response to an incoming packet, rather
16356 + than silently being dropped.
16358 + If you want to compile it as a module, say M here and read
16359 + Documentation/modules.txt. If unsure, say `N'.
16361 +config IP6_NF_MATCH_POLICY
16362 + tristate "IPsec policy match support"
16363 + depends on IP6_NF_IPTABLES && XFRM
16365 + Policy matching allows you to match packets based on the
16366 + IPsec policy that was used during decapsulation/will
16367 + be used during encapsulation.
16369 + To compile it as a module, choose M here. If unsure, say N.
16371 +config IP6_NF_MATCH_FUZZY
16372 + tristate 'Fuzzy match support'
16373 + depends on IP6_NF_FILTER
16375 + This option adds a `fuzzy' match, which allows you to match
16376 + packets according to a fuzzy logic based law.
16378 + If you want to compile it as a module, say M here and read
16379 + Documentation/modules.txt. If unsure, say `N'.
16381 +config IP6_NF_MATCH_NTH
16382 + tristate 'Nth match support'
16383 + depends on IP6_NF_IPTABLES
16385 + This option adds a `Nth' match, which allow you to make
16386 + rules that match every Nth packet. By default there are
16387 + 16 different counters.
16390 + --every Nth Match every Nth packet
16391 + [--counter] num Use counter 0-15 (default:0)
16392 + [--start] num Initialize the counter at the number 'num'
16393 + instead of 0. Must be between 0 and Nth-1
16394 + [--packet] num Match on 'num' packet. Must be between 0
16397 + If --packet is used for a counter than
16398 + there must be Nth number of --packet
16399 + rules, covering all values between 0 and
16400 + Nth-1 inclusively.
16402 + If you want to compile it as a module, say M here and read
16403 + Documentation/modules.txt. If unsure, say `N'.
16405 +config IP6_NF_MATCH_RANDOM
16406 + tristate 'Random match support'
16407 + depends on IP6_NF_IPTABLES
16409 + This option adds a `random' match,
16410 + which allow you to match packets randomly
16411 + following a given probability.
16413 + If you want to compile it as a module, say M here and read
16414 + Documentation/modules.txt. If unsure, say `N'.
16416 +config IP6_NF_TARGET_ROUTE
16417 + tristate ' ROUTE target support'
16418 + depends on IP6_NF_MANGLE
16420 + This option adds a `ROUTE' target, which enables you to setup unusual
16421 + routes. The ROUTE target is also able to change the incoming interface
16424 + The target can be or not a final target. It has to be used inside the
16427 + Not working as a module.
16429 +config IP6_NF_TARGET_TRACE
16430 + tristate 'TRACE target support'
16431 + depends on IP6_NF_RAW
16433 + The TRACE target allows packets to be traced as those
16434 + matches any subsequent rule in any table/rule. The matched
16435 + rule and the packet is logged with the prefix
16437 + TRACE: tablename/chainname/rulenum
16439 + If you want to compile it as a module, say M here and read
16440 + <file:Documentation/modules.txt>. If unsure, say `N'.
16444 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig~ linux-2.6.7/net/ipv6/netfilter/Kconfig~
16445 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig~ 1970-01-01 01:00:00.000000000 +0100
16446 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig~ 2004-06-25 12:21:30.376773768 +0200
16449 +# IP netfilter configuration
16452 +menu "IPv6: Netfilter Configuration"
16453 + depends on INET && IPV6 && NETFILTER
16455 +#tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
16456 +#if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
16457 +# dep_tristate ' FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK
16459 +config IP6_NF_QUEUE
16460 + tristate "Userspace queueing via NETLINK"
16463 + This option adds a queue handler to the kernel for IPv6
16464 + packets which lets us to receive the filtered packets
16465 + with QUEUE target using libiptc as we can do with
16468 + (C) Fernando Anton 2001
16469 + IPv64 Project - Work based in IPv64 draft by Arturo Azcorra.
16470 + Universidad Carlos III de Madrid
16471 + Universidad Politecnica de Alcala de Henares
16472 + email: <fanton@it.uc3m.es>.
16474 + To compile it as a module, choose M here. If unsure, say N.
16476 +config IP6_NF_IPTABLES
16477 + tristate "IP6 tables support (required for filtering/masq/NAT)"
16479 + ip6tables is a general, extensible packet identification framework.
16480 + Currently only the packet filtering and packet mangling subsystem
16481 + for IPv6 use this, but connection tracking is going to follow.
16482 + Say 'Y' or 'M' here if you want to use either of those.
16484 + To compile it as a module, choose M here. If unsure, say N.
16486 +# The simple matches.
16487 +config IP6_NF_MATCH_LIMIT
16488 + tristate "limit match support"
16489 + depends on IP6_NF_IPTABLES
16491 + limit matching allows you to control the rate at which a rule can be
16492 + matched: mainly useful in combination with the LOG target ("LOG
16493 + target support", below) and to avoid some Denial of Service attacks.
16495 + To compile it as a module, choose M here. If unsure, say N.
16497 +config IP6_NF_MATCH_MAC
16498 + tristate "MAC address match support"
16499 + depends on IP6_NF_IPTABLES
16501 + mac matching allows you to match packets based on the source
16502 + Ethernet address of the packet.
16504 + To compile it as a module, choose M here. If unsure, say N.
16506 +config IP6_NF_MATCH_RT
16507 + tristate "Routing header match support"
16508 + depends on IP6_NF_IPTABLES
16510 + rt matching allows you to match packets based on the routing
16511 + header of the packet.
16513 + To compile it as a module, choose M here. If unsure, say N.
16515 +config IP6_NF_MATCH_OPTS
16516 + tristate "Hop-by-hop and Dst opts header match support"
16517 + depends on IP6_NF_IPTABLES
16519 + This allows one to match packets based on the hop-by-hop
16520 + and destination options headers of a packet.
16522 + To compile it as a module, choose M here. If unsure, say N.
16524 +config IP6_NF_MATCH_FRAG
16525 + tristate "Fragmentation header match support"
16526 + depends on IP6_NF_IPTABLES
16528 + frag matching allows you to match packets based on the fragmentation
16529 + header of the packet.
16531 + To compile it as a module, choose M here. If unsure, say N.
16533 +config IP6_NF_MATCH_HL
16534 + tristate "HL match support"
16535 + depends on IP6_NF_IPTABLES
16537 + HL matching allows you to match packets based on the hop
16538 + limit of the packet.
16540 + To compile it as a module, choose M here. If unsure, say N.
16542 +config IP6_NF_MATCH_MULTIPORT
16543 + tristate "Multiple port match support"
16544 + depends on IP6_NF_IPTABLES
16546 + Multiport matching allows you to match TCP or UDP packets based on
16547 + a series of source or destination ports: normally a rule can only
16548 + match a single range of ports.
16550 + To compile it as a module, choose M here. If unsure, say N.
16552 +config IP6_NF_MATCH_OWNER
16553 + tristate "Owner match support"
16554 + depends on IP6_NF_IPTABLES
16556 + Packet owner matching allows you to match locally-generated packets
16557 + based on who created them: the user, group, process or session.
16559 + To compile it as a module, choose M here. If unsure, say N.
16561 +# dep_tristate ' MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
16562 +config IP6_NF_MATCH_MARK
16563 + tristate "netfilter MARK match support"
16564 + depends on IP6_NF_IPTABLES
16566 + Netfilter mark matching allows you to match packets based on the
16567 + `nfmark' value in the packet. This can be set by the MARK target
16570 + To compile it as a module, choose M here. If unsure, say N.
16572 +config IP6_NF_MATCH_IPV6HEADER
16573 + tristate "IPv6 Extension Headers Match"
16574 + depends on IP6_NF_IPTABLES
16576 + This module allows one to match packets based upon
16577 + the ipv6 extension headers.
16579 + To compile it as a module, choose M here. If unsure, say N.
16581 +config IP6_NF_MATCH_AHESP
16582 + tristate "AH/ESP match support"
16583 + depends on IP6_NF_IPTABLES
16585 + This module allows one to match AH and ESP packets.
16587 + To compile it as a module, choose M here. If unsure, say N.
16589 +config IP6_NF_MATCH_LENGTH
16590 + tristate "Packet Length match support"
16591 + depends on IP6_NF_IPTABLES
16593 + This option allows you to match the length of a packet against a
16594 + specific value or range of values.
16596 + To compile it as a module, choose M here. If unsure, say N.
16598 +config IP6_NF_MATCH_EUI64
16599 + tristate "EUI64 address check"
16600 + depends on IP6_NF_IPTABLES
16602 + This module performs checking on the IPv6 source address
16603 + Compares the last 64 bits with the EUI64 (delivered
16604 + from the MAC address) address
16606 + To compile it as a module, choose M here. If unsure, say N.
16608 +# dep_tristate ' Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
16609 +# dep_tristate ' TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
16610 +# if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
16611 +# dep_tristate ' Connection state match support' CONFIG_IP6_NF_MATCH_STATE $CONFIG_IP6_NF_CONNTRACK $CONFIG_IP6_NF_IPTABLES
16613 +# if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
16614 +# dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_UNCLEAN $CONFIG_IP6_NF_IPTABLES
16615 +# dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_OWNER $CONFIG_IP6_NF_IPTABLES
16618 +config IP6_NF_FILTER
16619 + tristate "Packet filtering"
16620 + depends on IP6_NF_IPTABLES
16622 + Packet filtering defines a table `filter', which has a series of
16623 + rules for simple packet filtering at local input, forwarding and
16624 + local output. See the man page for iptables(8).
16626 + To compile it as a module, choose M here. If unsure, say N.
16628 +config IP6_NF_TARGET_LOG
16629 + tristate "LOG target support"
16630 + depends on IP6_NF_FILTER
16632 + This option adds a `LOG' target, which allows you to create rules in
16633 + any iptables table which records the packet header to the syslog.
16635 + To compile it as a module, choose M here. If unsure, say N.
16637 +# if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
16638 +# dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
16639 +# if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
16640 +# dep_tristate ' MIRROR target support (EXPERIMENTAL)' CONFIG_IP6_NF_TARGET_MIRROR $CONFIG_IP6_NF_FILTER
16643 +config IP6_NF_MANGLE
16644 + tristate "Packet mangling"
16645 + depends on IP6_NF_IPTABLES
16647 + This option adds a `mangle' table to iptables: see the man page for
16648 + iptables(8). This table is used for various packet alterations
16649 + which can effect how the packet is routed.
16651 + To compile it as a module, choose M here. If unsure, say N.
16653 +# dep_tristate ' TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
16654 +config IP6_NF_TARGET_MARK
16655 + tristate "MARK target support"
16656 + depends on IP6_NF_MANGLE
16658 + This option adds a `MARK' target, which allows you to create rules
16659 + in the `mangle' table which alter the netfilter mark (nfmark) field
16660 + associated with the packet packet prior to routing. This can change
16661 + the routing method (see `Use netfilter MARK value as routing
16662 + key') and can also be used by other subsystems to change their
16665 + To compile it as a module, choose M here. If unsure, say N.
16667 +#dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
16669 + tristate 'raw table support (required for TRACE)'
16670 + depends on IP6_NF_IPTABLES
16672 + This option adds a `raw' table to ip6tables. This table is the very
16673 + first in the netfilter framework and hooks in at the PREROUTING
16674 + and OUTPUT chains.
16676 + If you want to compile it as a module, say M here and read
16677 + <file:Documentation/modules.txt>. If unsure, say `N'.
16680 +config IP6_NF_TARGET_HL
16681 + tristate 'HL target support'
16682 + depends on IP6_NF_MANGLE
16684 + This option adds a `HL' target, which allows you to modify the value of
16685 + IPv6 Hop Limit field.
16687 + If you want to compile it as a module, say M here and read
16688 + <file:Documentation/modules.txt>. If unsure, say `N'.
16690 +config IP6_NF_TARGET_REJECT
16691 + tristate 'REJECT target support'
16692 + depends on IP6_NF_FILTER
16694 + The REJECT target allows a filtering rule to specify that an ICMPv6
16695 + error should be issued in response to an incoming packet, rather
16696 + than silently being dropped.
16698 + If you want to compile it as a module, say M here and read
16699 + Documentation/modules.txt. If unsure, say `N'.
16701 +config IP6_NF_MATCH_FUZZY
16702 + tristate 'Fuzzy match support'
16703 + depends on IP6_NF_FILTER
16705 + This option adds a `fuzzy' match, which allows you to match
16706 + packets according to a fuzzy logic based law.
16708 + If you want to compile it as a module, say M here and read
16709 + Documentation/modules.txt. If unsure, say `N'.
16711 +config IP6_NF_MATCH_NTH
16712 + tristate 'Nth match support'
16713 + depends on IP6_NF_IPTABLES
16715 + This option adds a `Nth' match, which allow you to make
16716 + rules that match every Nth packet. By default there are
16717 + 16 different counters.
16720 + --every Nth Match every Nth packet
16721 + [--counter] num Use counter 0-15 (default:0)
16722 + [--start] num Initialize the counter at the number 'num'
16723 + instead of 0. Must be between 0 and Nth-1
16724 + [--packet] num Match on 'num' packet. Must be between 0
16727 + If --packet is used for a counter than
16728 + there must be Nth number of --packet
16729 + rules, covering all values between 0 and
16730 + Nth-1 inclusively.
16732 + If you want to compile it as a module, say M here and read
16733 + Documentation/modules.txt. If unsure, say `N'.
16735 +config IP6_NF_MATCH_RANDOM
16736 + tristate 'Random match support'
16737 + depends on IP6_NF_IPTABLES
16739 + This option adds a `random' match,
16740 + which allow you to match packets randomly
16741 + following a given probability.
16743 + If you want to compile it as a module, say M here and read
16744 + Documentation/modules.txt. If unsure, say `N'.
16746 +config IP6_NF_TARGET_ROUTE
16747 + tristate ' ROUTE target support'
16748 + depends on IP6_NF_MANGLE
16750 + This option adds a `ROUTE' target, which enables you to setup unusual
16751 + routes. The ROUTE target is also able to change the incoming interface
16754 + The target can be or not a final target. It has to be used inside the
16757 + Not working as a module.
16759 +config IP6_NF_TARGET_TRACE
16760 + tristate 'TRACE target support'
16761 + depends on IP6_NF_RAW
16763 + The TRACE target allows packets to be traced as those
16764 + matches any subsequent rule in any table/rule. The matched
16765 + rule and the packet is logged with the prefix
16767 + TRACE: tablename/chainname/rulenum
16769 + If you want to compile it as a module, say M here and read
16770 + <file:Documentation/modules.txt>. If unsure, say `N'.
16774 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Makefile linux-2.6.7/net/ipv6/netfilter/Makefile
16775 --- linux-2.6.7.org/net/ipv6/netfilter/Makefile 2004-06-16 07:19:36.000000000 +0200
16776 +++ linux-2.6.7/net/ipv6/netfilter/Makefile 2004-06-25 12:27:27.387499888 +0200
16778 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
16779 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
16780 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
16781 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
16782 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
16783 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
16784 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
16785 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
16786 obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
16787 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
16788 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
16789 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
16790 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
16791 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16792 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
16793 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
16794 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
16795 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
16796 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
16797 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
16799 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
16801 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
16802 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
16803 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
16804 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
16805 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
16806 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c
16807 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
16808 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c 2004-06-25 12:21:05.615538048 +0200
16811 + * Hop Limit modification target for ip6tables
16812 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
16813 + * Based on HW's TTL module
16815 + * This software is distributed under the terms of GNU GPL
16818 +#include <linux/module.h>
16819 +#include <linux/skbuff.h>
16820 +#include <linux/ip.h>
16822 +#include <linux/netfilter_ipv6/ip6_tables.h>
16823 +#include <linux/netfilter_ipv6/ip6t_HL.h>
16825 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
16826 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
16827 +MODULE_LICENSE("GPL");
16829 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
16830 + const struct net_device *in, const struct net_device *out,
16831 + const void *targinfo, void *userinfo)
16833 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
16834 + const struct ip6t_HL_info *info = targinfo;
16835 + u_int16_t diffs[2];
16838 + switch (info->mode) {
16839 + case IP6T_HL_SET:
16840 + new_hl = info->hop_limit;
16842 + case IP6T_HL_INC:
16843 + new_hl = ip6h->hop_limit + info->hop_limit;
16844 + if (new_hl > 255)
16847 + case IP6T_HL_DEC:
16848 + new_hl = ip6h->hop_limit + info->hop_limit;
16853 + new_hl = ip6h->hop_limit;
16857 + if (new_hl != ip6h->hop_limit) {
16858 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
16859 + ip6h->hop_limit = new_hl;
16860 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
16863 + return IP6T_CONTINUE;
16866 +static int ip6t_hl_checkentry(const char *tablename,
16867 + const struct ip6t_entry *e,
16869 + unsigned int targinfosize,
16870 + unsigned int hook_mask)
16872 + struct ip6t_HL_info *info = targinfo;
16874 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
16875 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
16877 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
16881 + if (strcmp(tablename, "mangle")) {
16882 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
16886 + if (info->mode > IP6T_HL_MAXMODE) {
16887 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
16892 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
16893 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
16900 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
16901 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
16903 +static int __init init(void)
16905 + return ip6t_register_target(&ip6t_HL);
16908 +static void __exit fini(void)
16910 + ip6t_unregister_target(&ip6t_HL);
16913 +module_init(init);
16914 +module_exit(fini);
16915 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c
16916 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
16917 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c 2004-06-25 12:21:07.477255024 +0200
16920 + * IP6 tables REJECT target module
16921 + * Linux INET6 implementation
16923 + * Copyright (C)2003 USAGI/WIDE Project
16926 + * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
16928 + * Based on net/ipv4/netfilter/ipt_REJECT.c
16930 + * This program is free software; you can redistribute it and/or
16931 + * modify it under the terms of the GNU General Public License
16932 + * as published by the Free Software Foundation; either version
16933 + * 2 of the License, or (at your option) any later version.
16936 +#include <linux/config.h>
16937 +#include <linux/module.h>
16938 +#include <linux/skbuff.h>
16939 +#include <linux/icmpv6.h>
16940 +#include <net/ipv6.h>
16941 +#include <net/tcp.h>
16942 +#include <net/icmp.h>
16943 +#include <net/ip6_fib.h>
16944 +#include <net/ip6_route.h>
16945 +#include <net/flow.h>
16946 +#include <linux/netfilter_ipv6/ip6_tables.h>
16947 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
16949 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
16950 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
16951 +MODULE_LICENSE("GPL");
16954 +#define DEBUGP printk
16956 +#define DEBUGP(format, args...)
16960 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
16962 + void (*attach)(struct sk_buff *, struct nf_ct_info *);
16963 + if (nfct && (attach = ip6_ct_attach) != NULL) {
16965 + attach(new_skb, nfct);
16970 +static int maybe_reroute(struct sk_buff *skb)
16972 + if (skb->nfcache & NFC_ALTERED){
16973 + if (ip6_route_me_harder(skb) != 0){
16979 + return dst_output(skb);
16982 +/* Send RST reply */
16983 +static void send_reset(struct sk_buff *oldskb)
16985 + struct sk_buff *nskb;
16986 + struct tcphdr otcph, *tcph;
16987 + unsigned int otcplen, tcphoff, hh_len;
16989 + struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
16990 + struct dst_entry *dst = NULL;
16993 + proto = oip6h->nexthdr;
16996 + if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
16997 + (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
16998 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17002 + tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
17003 + &proto, oldskb->len - ((u8*)(oip6h+1)
17004 + - oldskb->data));
17006 + if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
17007 + DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
17011 + otcplen = oldskb->len - tcphoff;
17013 + /* IP header checks: fragment, too short. */
17014 + if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
17015 + DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
17020 + if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
17021 + if (net_ratelimit())
17022 + printk("ip6t_REJECT: Can't copy tcp header\n");
17026 + /* No RST for RST. */
17028 + DEBUGP("ip6t_REJECT: RST is set\n");
17032 + /* Check checksum. */
17033 + if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
17034 + skb_checksum(oldskb, tcphoff, otcplen, 0))) {
17035 + DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
17039 + memset(&fl, 0, sizeof(fl));
17040 + fl.proto = IPPROTO_TCP;
17041 + ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
17042 + ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
17043 + fl.fl_ip_sport = otcph.dest;
17044 + fl.fl_ip_dport = otcph.source;
17045 + err = ip6_dst_lookup(NULL, &dst, &fl);
17047 + if (net_ratelimit())
17048 + printk("ip6t_REJECT: can't find dst. err = %d\n", err);
17052 + hh_len = (dst->dev->hard_header_len + 15)&~15;
17053 + nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
17054 + + sizeof(struct tcphdr) + dst->trailer_len,
17058 + if (net_ratelimit())
17059 + printk("ip6t_REJECT: Can't alloc skb\n");
17060 + dst_release(dst);
17067 + skb_reserve(nskb, hh_len + dst->header_len);
17069 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17070 + skb_put(nskb, sizeof(struct ipv6hdr));
17071 + ip6h->version = 6;
17072 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17073 + ip6h->nexthdr = IPPROTO_TCP;
17074 + ip6h->payload_len = htons(sizeof(struct tcphdr));
17075 + ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
17076 + ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
17078 + tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
17079 + /* Truncate to length (no data) */
17080 + tcph->doff = sizeof(struct tcphdr)/4;
17081 + tcph->source = otcph.dest;
17082 + tcph->dest = otcph.source;
17086 + tcph->seq = otcph.ack_seq;
17087 + tcph->ack_seq = 0;
17090 + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
17091 + + otcplen - (otcph.doff<<2));
17095 + /* Reset flags */
17096 + ((u_int8_t *)tcph)[13] = 0;
17098 + tcph->ack = needs_ack;
17099 + tcph->window = 0;
17100 + tcph->urg_ptr = 0;
17103 + /* Adjust TCP checksum */
17104 + tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
17105 + &nskb->nh.ipv6h->daddr,
17106 + sizeof(struct tcphdr), IPPROTO_TCP,
17107 + csum_partial((char *)tcph,
17108 + sizeof(struct tcphdr), 0));
17111 + connection_attach(nskb, oldskb->nfct);
17114 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17117 + dst_release(dst);
17120 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
17122 + struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
17123 + struct icmp6hdr *icmp6h;
17124 + struct dst_entry *dst = NULL;
17125 + struct rt6_info *rt;
17128 + unsigned int len, datalen, hh_len;
17129 + int saddr_type, daddr_type;
17130 + unsigned int ptr, ip6off;
17133 + struct sk_buff *nskb;
17136 + saddr_type = ipv6_addr_type(&hdr->saddr);
17137 + daddr_type = ipv6_addr_type(&hdr->daddr);
17139 + if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
17140 + (!(daddr_type & IPV6_ADDR_UNICAST))) {
17141 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17145 + ip6off = skb_in->nh.raw - skb_in->data;
17146 + proto = hdr->nexthdr;
17147 + ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
17148 + skb_in->len - ip6off);
17150 + if ((ptr < 0) || (ptr > skb_in->len)) {
17151 + ptr = ip6off + sizeof(struct ipv6hdr);
17152 + proto = hdr->nexthdr;
17153 + } else if (proto == IPPROTO_ICMPV6) {
17156 + if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
17157 + icmp6_type), &type, 1)) {
17158 + DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
17162 + if (!(type & ICMPV6_INFOMSG_MASK)) {
17163 + DEBUGP("ip6t_REJECT: no reply to icmp error\n");
17166 + } else if (proto == IPPROTO_UDP) {
17167 + int plen = skb_in->len - (ptr - ip6off);
17170 + if (plen < sizeof(struct udphdr)) {
17171 + DEBUGP("ip6t_REJECT: too short\n");
17175 + if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
17177 + if (net_ratelimit())
17178 + printk("ip6t_REJECT: can't get copy from skb");
17183 + csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
17185 + skb_checksum(skb_in, ptr, plen, 0))) {
17186 + DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
17191 + memset(&fl, 0, sizeof(fl));
17192 + fl.proto = IPPROTO_ICMPV6;
17193 + ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
17194 + ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
17195 + fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
17196 + fl.fl_icmp_code = code;
17198 + if (ip6_dst_lookup(NULL, &dst, &fl)) {
17202 + rt = (struct rt6_info *)dst;
17205 + if (rt->rt6i_dst.plen < 128)
17206 + tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
17208 + if (!xrlim_allow(dst, tmo)) {
17209 + if (net_ratelimit())
17210 + printk("ip6t_REJECT: rate limitted\n");
17211 + goto dst_release_out;
17214 + len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
17216 + if (len > dst_pmtu(dst))
17217 + len = dst_pmtu(dst);
17218 + if (len > IPV6_MIN_MTU)
17219 + len = IPV6_MIN_MTU;
17221 + datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
17222 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
17224 + nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
17228 + if (net_ratelimit())
17229 + printk("ip6t_REJECT: can't alloc skb\n");
17230 + goto dst_release_out;
17233 + nskb->priority = 0;
17237 + skb_reserve(nskb, hh_len + dst->header_len);
17239 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17240 + skb_put(nskb, sizeof(struct ipv6hdr));
17241 + ip6h->version = 6;
17242 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17243 + ip6h->nexthdr = IPPROTO_ICMPV6;
17244 + ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
17245 + ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
17246 + ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
17248 + icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
17249 + icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
17250 + icmp6h->icmp6_code = code;
17251 + icmp6h->icmp6_cksum = 0;
17253 + data = skb_put(nskb, datalen);
17255 + csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
17256 + csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
17257 + icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
17258 + datalen + sizeof(struct icmp6hdr),
17259 + IPPROTO_ICMPV6, csum);
17262 + connection_attach(nskb, skb_in->nfct);
17264 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17268 + dst_release(dst);
17271 +static unsigned int reject6_target(struct sk_buff **pskb,
17272 + unsigned int hooknum,
17273 + const struct net_device *in,
17274 + const struct net_device *out,
17275 + const void *targinfo,
17278 + const struct ip6t_reject_info *reject = targinfo;
17280 + DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
17281 + /* WARNING: This code causes reentry within ip6tables.
17282 + This means that the ip6tables jump stack is now crap. We
17283 + must return an absolute verdict. --RR */
17284 + switch (reject->with) {
17285 + case IP6T_ICMP6_NO_ROUTE:
17286 + send_unreach(*pskb, ICMPV6_NOROUTE);
17288 + case IP6T_ICMP6_ADM_PROHIBITED:
17289 + send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
17291 + case IP6T_ICMP6_NOT_NEIGHBOUR:
17292 + send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
17294 + case IP6T_ICMP6_ADDR_UNREACH:
17295 + send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
17297 + case IP6T_ICMP6_PORT_UNREACH:
17298 + send_unreach(*pskb, ICMPV6_PORT_UNREACH);
17300 + case IP6T_ICMP6_ECHOREPLY:
17303 + case IP6T_TCP_RESET:
17304 + send_reset(*pskb);
17307 + if (net_ratelimit())
17308 + printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
17315 +static int check(const char *tablename,
17316 + const struct ip6t_entry *e,
17318 + unsigned int targinfosize,
17319 + unsigned int hook_mask)
17321 + const struct ip6t_reject_info *rejinfo = targinfo;
17323 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
17324 + DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
17328 + /* Only allow these for packet filtering. */
17329 + if (strcmp(tablename, "filter") != 0) {
17330 + DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
17334 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
17335 + | (1 << NF_IP6_FORWARD)
17336 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
17337 + DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
17341 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
17342 + printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
17344 + } else if (rejinfo->with == IP6T_TCP_RESET) {
17345 + /* Must specify that it's a TCP packet */
17346 + if (e->ipv6.proto != IPPROTO_TCP
17347 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
17348 + DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
17356 +static struct ip6t_target ip6t_reject_reg = {
17357 + .name = "REJECT",
17358 + .target = reject6_target,
17359 + .checkentry = check,
17360 + .me = THIS_MODULE
17363 +static int __init init(void)
17365 + if (ip6t_register_target(&ip6t_reject_reg))
17370 +static void __exit fini(void)
17372 + ip6t_unregister_target(&ip6t_reject_reg);
17375 +module_init(init);
17376 +module_exit(fini);
17377 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.7/net/ipv6/netfilter/ip6t_ROUTE.c
17378 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
17379 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_ROUTE.c 2004-06-25 12:21:28.216102240 +0200
17382 + * This implements the ROUTE v6 target, which enables you to setup unusual
17383 + * routes not supported by the standard kernel routing table.
17385 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
17387 + * v 1.0 2003/08/05
17389 + * This software is distributed under GNU GPL v2, 1991
17392 +#include <linux/module.h>
17393 +#include <linux/skbuff.h>
17394 +#include <linux/ipv6.h>
17395 +#include <linux/netfilter_ipv6/ip6_tables.h>
17396 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17397 +#include <linux/netdevice.h>
17398 +#include <net/ipv6.h>
17399 +#include <net/ndisc.h>
17400 +#include <net/ip6_route.h>
17401 +#include <linux/icmpv6.h>
17404 +#define DEBUGP printk
17406 +#define DEBUGP(format, args...)
17409 +#define NIP6(addr) \
17410 + ntohs((addr).s6_addr16[0]), \
17411 + ntohs((addr).s6_addr16[1]), \
17412 + ntohs((addr).s6_addr16[2]), \
17413 + ntohs((addr).s6_addr16[3]), \
17414 + ntohs((addr).s6_addr16[4]), \
17415 + ntohs((addr).s6_addr16[5]), \
17416 + ntohs((addr).s6_addr16[6]), \
17417 + ntohs((addr).s6_addr16[7])
17419 +/* Route the packet according to the routing keys specified in
17420 + * route_info. Keys are :
17422 + * 0 if no oif preferred,
17423 + * otherwise set to the index of the desired oif
17424 + * - route_info->gw :
17425 + * 0 if no gateway specified,
17426 + * otherwise set to the next host to which the pkt must be routed
17427 + * If success, skb->dev is the output device to which the packet must
17428 + * be sent and skb->dst is not NULL
17430 + * RETURN: 1 if the packet was succesfully routed to the
17431 + * destination desired
17432 + * 0 if the kernel routing table could not route the packet
17433 + * according to the keys specified
17436 +route6(struct sk_buff *skb,
17437 + unsigned int ifindex,
17438 + const struct ip6t_route_target_info *route_info)
17440 + struct rt6_info *rt = NULL;
17441 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17442 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17444 + DEBUGP("ip6t_ROUTE: called with: ");
17445 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
17446 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
17447 + DEBUGP("OUT=%s\n", route_info->oif);
17449 + if (ipv6_addr_any(gw))
17450 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
17452 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
17457 + DEBUGP("ip6t_ROUTE: routing gives: ");
17458 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
17459 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
17460 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
17462 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
17463 + goto wrong_route;
17465 + if (!rt->rt6i_nexthop) {
17466 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
17467 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
17470 + /* Drop old route. */
17471 + dst_release(skb->dst);
17472 + skb->dst = &rt->u.dst;
17473 + skb->dev = rt->rt6i_dev;
17477 + dst_release(&rt->u.dst);
17479 + if (!net_ratelimit())
17482 + printk("ip6t_ROUTE: no explicit route found ");
17484 + printk("via interface %s ", route_info->oif);
17485 + if (!ipv6_addr_any(gw))
17486 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
17492 +/* Stolen from ip6_output_finish
17493 + * PRE : skb->dev is set to the device we are leaving by
17494 + * skb->dst is not NULL
17495 + * POST: the packet is sent with the link layer header pushed
17496 + * the packet is destroyed
17498 +static void ip_direct_send(struct sk_buff *skb)
17500 + struct dst_entry *dst = skb->dst;
17501 + struct hh_cache *hh = dst->hh;
17504 + read_lock_bh(&hh->hh_lock);
17505 + memcpy(skb->data - 16, hh->hh_data, 16);
17506 + read_unlock_bh(&hh->hh_lock);
17507 + skb_push(skb, hh->hh_len);
17508 + hh->hh_output(skb);
17509 + } else if (dst->neighbour)
17510 + dst->neighbour->output(skb);
17512 + if (net_ratelimit())
17513 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
17519 +static unsigned int
17520 +route6_oif(const struct ip6t_route_target_info *route_info,
17521 + struct sk_buff *skb)
17523 + unsigned int ifindex = 0;
17524 + struct net_device *dev_out = NULL;
17526 + /* The user set the interface name to use.
17527 + * Getting the current interface index.
17529 + if ((dev_out = dev_get_by_name(route_info->oif))) {
17530 + ifindex = dev_out->ifindex;
17532 + /* Unknown interface name : packet dropped */
17533 + if (net_ratelimit())
17534 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
17536 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17537 + return IP6T_CONTINUE;
17542 + /* Trying the standard way of routing packets */
17543 + if (route6(skb, ifindex, route_info)) {
17544 + dev_put(dev_out);
17545 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17546 + return IP6T_CONTINUE;
17548 + ip_direct_send(skb);
17549 + return NF_STOLEN;
17555 +static unsigned int
17556 +route6_gw(const struct ip6t_route_target_info *route_info,
17557 + struct sk_buff *skb)
17559 + if (route6(skb, 0, route_info)) {
17560 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17561 + return IP6T_CONTINUE;
17563 + ip_direct_send(skb);
17564 + return NF_STOLEN;
17570 +static unsigned int
17571 +ip6t_route_target(struct sk_buff **pskb,
17572 + unsigned int hooknum,
17573 + const struct net_device *in,
17574 + const struct net_device *out,
17575 + const void *targinfo,
17578 + const struct ip6t_route_target_info *route_info = targinfo;
17579 + struct sk_buff *skb = *pskb;
17580 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17582 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
17585 + /* If we are at PREROUTING or INPUT hook
17586 + * the TTL isn't decreased by the IP stack
17588 + if (hooknum == NF_IP6_PRE_ROUTING ||
17589 + hooknum == NF_IP6_LOCAL_IN) {
17591 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17593 + if (ipv6h->hop_limit <= 1) {
17594 + /* Force OUTPUT device used as source address */
17595 + skb->dev = skb->dst->dev;
17597 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
17598 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
17603 + ipv6h->hop_limit--;
17608 + if (route_info->oif[0])
17609 + return route6_oif(route_info, *pskb);
17611 + if (!ipv6_addr_any(gw))
17612 + return route6_gw(route_info, *pskb);
17614 + if (net_ratelimit())
17615 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
17617 + return IP6T_CONTINUE;
17622 +ip6t_route_checkentry(const char *tablename,
17623 + const struct ip6t_entry *e,
17625 + unsigned int targinfosize,
17626 + unsigned int hook_mask)
17628 + if (strcmp(tablename, "mangle") != 0) {
17629 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
17633 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
17634 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
17636 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
17644 +static struct ip6t_target ip6t_route_reg = {
17646 + .target = ip6t_route_target,
17647 + .checkentry = ip6t_route_checkentry,
17648 + .me = THIS_MODULE
17652 +static int __init init(void)
17654 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
17655 + if (ip6t_register_target(&ip6t_route_reg))
17662 +static void __exit fini(void)
17664 + ip6t_unregister_target(&ip6t_route_reg);
17667 +module_init(init);
17668 +module_exit(fini);
17669 +MODULE_LICENSE("GPL");
17670 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.7/net/ipv6/netfilter/ip6t_TRACE.c
17671 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
17672 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_TRACE.c 2004-06-25 12:21:30.343778784 +0200
17674 +/* This is a module which is used for setting
17675 + * the NFC_TRACE flag in the nfcache field of an skb.
17677 +#include <linux/module.h>
17678 +#include <linux/skbuff.h>
17680 +#include <linux/netfilter_ipv6/ip6_tables.h>
17682 +MODULE_LICENSE("GPL");
17684 +static unsigned int
17685 +target(struct sk_buff **pskb,
17686 + unsigned int hooknum,
17687 + const struct net_device *in,
17688 + const struct net_device *out,
17689 + const void *targinfo,
17692 + (*pskb)->nfcache |= NFC_TRACE;
17693 + return IP6T_CONTINUE;
17697 +checkentry(const char *tablename,
17698 + const struct ip6t_entry *e,
17700 + unsigned int targinfosize,
17701 + unsigned int hook_mask)
17703 + if (targinfosize != 0) {
17704 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17709 + if (strcmp(tablename, "raw") != 0) {
17710 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17717 +static struct ip6t_target ip6t_trace_reg = {
17719 + .target = target,
17720 + .checkentry = checkentry,
17721 + .me = THIS_MODULE
17724 +static int __init init(void)
17726 + if (ip6t_register_target(&ip6t_trace_reg))
17732 +static void __exit fini(void)
17734 + ip6t_unregister_target(&ip6t_trace_reg);
17737 +module_init(init);
17738 +module_exit(fini);
17739 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c
17740 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
17741 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c 2004-06-25 12:21:08.963029152 +0200
17744 + * This module implements a simple TSK FLC
17745 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
17746 + * to limit , in an adaptive and flexible way , the packet rate crossing
17747 + * a given stream . It serves as an initial and very simple (but effective)
17748 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
17749 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
17750 + * into our code in a precise , adaptive and efficient manner.
17751 + * The goal is very similar to that of "limit" match , but using techniques of
17752 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
17753 + * avoiding over and undershoots - and stuff like that .
17756 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
17757 + * 2002-08-17 : Changed to eliminate floating point operations .
17758 + * 2002-08-23 : Coding style changes .
17759 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
17762 +#include <linux/module.h>
17763 +#include <linux/skbuff.h>
17764 +#include <linux/ipv6.h>
17765 +#include <linux/random.h>
17766 +#include <net/tcp.h>
17767 +#include <linux/spinlock.h>
17768 +#include <linux/netfilter_ipv6/ip6_tables.h>
17769 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
17772 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
17773 + Expressed in percentage
17776 +#define PAR_LOW 1/100
17777 +#define PAR_HIGH 1
17779 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
17781 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
17782 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
17783 +MODULE_LICENSE("GPL");
17785 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17787 + if (tx >= maxi) return 100;
17789 + if (tx <= mini) return 0;
17791 + return ((100 * (tx-mini)) / (maxi-mini));
17794 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17796 + if (tx <= mini) return 100;
17798 + if (tx >= maxi) return 0;
17800 + return ((100 * (maxi - tx)) / (maxi - mini));
17805 +ip6t_fuzzy_match(const struct sk_buff *pskb,
17806 + const struct net_device *in,
17807 + const struct net_device *out,
17808 + const void *matchinfo,
17811 + u_int16_t datalen,
17814 + /* From userspace */
17816 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
17818 + u_int8_t random_number;
17819 + unsigned long amount;
17820 + u_int8_t howhigh, howlow;
17823 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
17825 + info->bytes_total += pskb->len;
17826 + info->packets_total++;
17828 + info->present_time = jiffies;
17830 + if (info->present_time >= info->previous_time)
17831 + amount = info->present_time - info->previous_time;
17833 + /* There was a transition : I choose to re-sample
17834 + and keep the old acceptance rate...
17838 + info->previous_time = info->present_time;
17839 + info->bytes_total = info->packets_total = 0;
17842 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
17844 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
17847 + info->previous_time = info->present_time;
17848 + info->bytes_total = info->packets_total = 0;
17850 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
17851 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
17853 + info->acceptance_rate = (u_int8_t) \
17854 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
17856 + /* In fact, the above defuzzification would require a denominator
17857 + * proportional to (howhigh+howlow) but, in this particular case,
17858 + * that expression is constant.
17859 + * An imediate consequence is that it is not necessary to call
17860 + * both mf_high and mf_low - but to keep things understandable,
17866 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
17869 + if (info->acceptance_rate < 100)
17871 + get_random_bytes((void *)(&random_number), 1);
17873 + /* If within the acceptance , it can pass => don't match */
17874 + if (random_number <= (255 * info->acceptance_rate) / 100)
17877 + return 1; /* It can't pass (It matches) */
17880 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
17885 +ip6t_fuzzy_checkentry(const char *tablename,
17886 + const struct ip6t_ip6 *ip,
17888 + unsigned int matchsize,
17889 + unsigned int hook_mask)
17892 + const struct ip6t_fuzzy_info *info = matchinfo;
17894 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
17895 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
17896 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
17900 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
17901 + || (info->minimum_rate >= info->maximum_rate)) {
17902 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
17909 +static struct ip6t_match ip6t_fuzzy_reg = {
17912 + ip6t_fuzzy_match,
17913 + ip6t_fuzzy_checkentry,
17917 +static int __init init(void)
17919 + if (ip6t_register_match(&ip6t_fuzzy_reg))
17925 +static void __exit fini(void)
17927 + ip6t_unregister_match(&ip6t_fuzzy_reg);
17930 +module_init(init);
17931 +module_exit(fini);
17932 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c
17933 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
17934 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c 2004-06-25 12:21:10.462801152 +0200
17937 + This is a module which is used for match support for every Nth packet
17938 + This file is distributed under the terms of the GNU General Public
17939 + License (GPL). Copies of the GPL can be obtained from:
17940 + ftp://prep.ai.mit.edu/pub/gnu/GPL
17942 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
17943 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
17944 + * added support for multiple counters
17945 + * added support for matching on individual packets
17946 + in the counter cycle
17947 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
17951 +#include <linux/module.h>
17952 +#include <linux/skbuff.h>
17953 +#include <linux/ip.h>
17954 +#include <net/tcp.h>
17955 +#include <linux/spinlock.h>
17956 +#include <linux/netfilter_ipv6/ip6_tables.h>
17957 +#include <linux/netfilter_ipv6/ip6t_nth.h>
17959 +MODULE_LICENSE("GPL");
17962 + * State information.
17966 + u_int16_t number;
17969 +static struct state states[IP6T_NTH_NUM_COUNTERS];
17972 +ip6t_nth_match(const struct sk_buff *pskb,
17973 + const struct net_device *in,
17974 + const struct net_device *out,
17975 + const void *matchinfo,
17978 + u_int16_t datalen,
17981 + /* Parameters from userspace */
17982 + const struct ip6t_nth_info *info = matchinfo;
17983 + unsigned counter = info->counter;
17984 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
17986 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
17990 + spin_lock(&states[counter].lock);
17992 + /* Are we matching every nth packet?*/
17993 + if (info->packet == 0xFF)
17995 + /* We're matching every nth packet and only every nth packet*/
17996 + /* Do we match or invert match? */
17997 + if (info->not == 0)
17999 + if (states[counter].number == 0)
18001 + ++states[counter].number;
18004 + if (states[counter].number >= info->every)
18005 + states[counter].number = 0; /* reset the counter */
18007 + ++states[counter].number;
18012 + if (states[counter].number == 0)
18014 + ++states[counter].number;
18017 + if (states[counter].number >= info->every)
18018 + states[counter].number = 0;
18020 + ++states[counter].number;
18026 + /* We're using the --packet, so there must be a rule for every value */
18027 + if (states[counter].number == info->packet)
18029 + /* only increment the counter when a match happens */
18030 + if (states[counter].number >= info->every)
18031 + states[counter].number = 0; /* reset the counter */
18033 + ++states[counter].number;
18041 + /* don't match */
18042 + spin_unlock(&states[counter].lock);
18046 + spin_unlock(&states[counter].lock);
18051 +ip6t_nth_checkentry(const char *tablename,
18052 + const struct ip6t_ip6 *e,
18054 + unsigned int matchsize,
18055 + unsigned int hook_mask)
18057 + /* Parameters from userspace */
18058 + const struct ip6t_nth_info *info = matchinfo;
18059 + unsigned counter = info->counter;
18060 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
18062 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
18066 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
18067 + printk("nth: matchsize %u != %u\n", matchsize,
18068 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
18072 + states[counter].number = info->startat;
18077 +static struct ip6t_match ip6t_nth_reg = {
18081 + ip6t_nth_checkentry,
18085 +static int __init init(void)
18087 + unsigned counter;
18088 + memset(&states, 0, sizeof(states));
18089 + if (ip6t_register_match(&ip6t_nth_reg))
18092 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
18094 + spin_lock_init(&(states[counter].lock));
18097 + printk("ip6t_nth match loaded\n");
18101 +static void __exit fini(void)
18103 + ip6t_unregister_match(&ip6t_nth_reg);
18104 + printk("ip6t_nth match unloaded\n");
18107 +module_init(init);
18108 +module_exit(fini);
18109 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.7/net/ipv6/netfilter/ip6t_owner.c
18110 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_owner.c 2004-06-25 10:47:46.000000000 +0200
18111 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_owner.c 2004-06-25 12:23:17.499488640 +0200
18113 MODULE_LICENSE("GPL");
18116 +match_comm(const struct sk_buff *skb, const char *comm)
18118 + struct task_struct *p, *g;
18119 + struct files_struct *files;
18122 + read_lock(&tasklist_lock);
18123 + do_each_thread(g, p) {
18124 + if(strncmp(p->comm, comm, sizeof(p->comm)))
18128 + files = p->files;
18130 + read_lock(&files->file_lock);
18131 + for (i=0; i < files->max_fds; i++) {
18132 + if (fcheck_files(files, i) ==
18133 + skb->sk->sk_socket->file) {
18134 + read_unlock(&files->file_lock);
18136 + read_unlock(&tasklist_lock);
18140 + read_unlock(&files->file_lock);
18143 + } while_each_thread(g, p);
18144 + read_unlock(&tasklist_lock);
18149 match_pid(const struct sk_buff *skb, pid_t pid)
18151 struct task_struct *p;
18152 @@ -125,6 +158,12 @@
18156 + if(info->match & IP6T_OWNER_COMM) {
18157 + if (!match_comm(skb, info->comm) ^
18158 + !!(info->invert & IP6T_OWNER_COMM))
18165 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.7/net/ipv6/netfilter/ip6t_policy.c
18166 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
18167 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_policy.c 2004-05-07 18:20:57.000000000 +0200
18169 +/* IP tables module for matching IPsec policy
18171 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
18173 + * This program is free software; you can redistribute it and/or modify
18174 + * it under the terms of the GNU General Public License version 2 as
18175 + * published by the Free Software Foundation.
18178 +#include <linux/kernel.h>
18179 +#include <linux/config.h>
18180 +#include <linux/module.h>
18181 +#include <linux/skbuff.h>
18182 +#include <linux/init.h>
18183 +#include <net/xfrm.h>
18185 +#include <linux/netfilter_ipv6.h>
18186 +#include <linux/netfilter_ipv6/ip6t_policy.h>
18187 +#include <linux/netfilter_ipv6/ip6_tables.h>
18189 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
18190 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
18191 +MODULE_LICENSE("GPL");
18194 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
18195 + struct in6_addr mask,
18196 + struct in6_addr addr2)
18200 + for (i = 0; i < 16; i++) {
18201 + if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
18202 + (addr2.s6_addr[i] & mask.s6_addr[i]))
18210 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
18212 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
18214 + struct in6_addr xfrm_saddr, xfrm_daddr;
18216 + if ((e->match.saddr
18217 + && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
18218 + ^ e->invert.saddr ) ||
18220 + && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
18221 + ^ e->invert.daddr ) ||
18222 + MISMATCH(proto, x->id.proto) ||
18223 + MISMATCH(mode, x->props.mode) ||
18224 + MISMATCH(spi, x->id.spi) ||
18225 + MISMATCH(reqid, x->props.reqid))
18231 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18233 + const struct ip6t_policy_elem *e;
18234 + struct sec_path *sp = skb->sp;
18235 + int strict = info->flags & POLICY_MATCH_STRICT;
18240 + if (strict && info->len != sp->len)
18243 + for (i = sp->len - 1; i >= 0; i--) {
18244 + pos = strict ? i - sp->len + 1 : 0;
18245 + if (pos >= info->len)
18247 + e = &info->pol[pos];
18249 + if (match_xfrm_state(sp->x[i].xvec, e)) {
18252 + } else if (strict)
18256 + return strict ? 1 : 0;
18260 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18262 + const struct ip6t_policy_elem *e;
18263 + struct dst_entry *dst = skb->dst;
18264 + int strict = info->flags & POLICY_MATCH_STRICT;
18267 + if (dst->xfrm == NULL)
18270 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
18271 + pos = strict ? i : 0;
18272 + if (pos >= info->len)
18274 + e = &info->pol[pos];
18276 + if (match_xfrm_state(dst->xfrm, e)) {
18279 + } else if (strict)
18283 + return strict ? 1 : 0;
18286 +static int match(const struct sk_buff *skb,
18287 + const struct net_device *in,
18288 + const struct net_device *out,
18289 + const void *matchinfo,
18292 + u_int16_t datalen,
18295 + const struct ip6t_policy_info *info = matchinfo;
18298 + if (info->flags & POLICY_MATCH_IN)
18299 + ret = match_policy_in(skb, info);
18301 + ret = match_policy_out(skb, info);
18304 + if (info->flags & POLICY_MATCH_NONE)
18308 + } else if (info->flags & POLICY_MATCH_NONE)
18314 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
18315 + void *matchinfo, unsigned int matchsize,
18316 + unsigned int hook_mask)
18318 + struct ip6t_policy_info *info = matchinfo;
18320 + if (matchsize != IP6T_ALIGN(sizeof(*info))) {
18321 + printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
18322 + matchsize, IP6T_ALIGN(sizeof(*info)));
18325 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
18326 + printk(KERN_ERR "ip6t_policy: neither incoming nor "
18327 + "outgoing policy selected\n");
18330 + if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
18331 + && info->flags & POLICY_MATCH_OUT) {
18332 + printk(KERN_ERR "ip6t_policy: output policy not valid in "
18333 + "PRE_ROUTING and INPUT\n");
18336 + if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
18337 + && info->flags & POLICY_MATCH_IN) {
18338 + printk(KERN_ERR "ip6t_policy: input policy not valid in "
18339 + "POST_ROUTING and OUTPUT\n");
18342 + if (info->len > POLICY_MAX_ELEM) {
18343 + printk(KERN_ERR "ip6t_policy: too many policy elements\n");
18350 +static struct ip6t_match policy_match =
18352 + .name = "policy",
18354 + .checkentry = checkentry,
18355 + .me = THIS_MODULE,
18358 +static int __init init(void)
18360 + return ip6t_register_match(&policy_match);
18363 +static void __exit fini(void)
18365 + ip6t_unregister_match(&policy_match);
18368 +module_init(init);
18369 +module_exit(fini);
18370 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.7/net/ipv6/netfilter/ip6t_random.c
18371 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
18372 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_random.c 2004-06-25 12:21:12.940424496 +0200
18375 + This is a module which is used for a "random" match support.
18376 + This file is distributed under the terms of the GNU General Public
18377 + License (GPL). Copies of the GPL can be obtained from:
18378 + ftp://prep.ai.mit.edu/pub/gnu/GPL
18380 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18381 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18384 +#include <linux/module.h>
18385 +#include <linux/skbuff.h>
18386 +#include <linux/ip.h>
18387 +#include <linux/random.h>
18388 +#include <net/tcp.h>
18389 +#include <linux/spinlock.h>
18390 +#include <linux/netfilter_ipv6/ip6_tables.h>
18391 +#include <linux/netfilter_ipv6/ip6t_random.h>
18393 +MODULE_LICENSE("GPL");
18396 +ip6t_rand_match(const struct sk_buff *pskb,
18397 + const struct net_device *in,
18398 + const struct net_device *out,
18399 + const void *matchinfo,
18402 + u_int16_t datalen,
18405 + /* Parameters from userspace */
18406 + const struct ip6t_rand_info *info = matchinfo;
18407 + u_int8_t random_number;
18409 + /* get 1 random number from the kernel random number generation routine */
18410 + get_random_bytes((void *)(&random_number), 1);
18412 + /* Do we match ? */
18413 + if (random_number <= info->average)
18420 +ip6t_rand_checkentry(const char *tablename,
18421 + const struct ip6t_ip6 *e,
18423 + unsigned int matchsize,
18424 + unsigned int hook_mask)
18426 + /* Parameters from userspace */
18427 + const struct ip6t_rand_info *info = matchinfo;
18429 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
18430 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
18431 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
18435 + /* must be 1 <= average % <= 99 */
18436 + /* 1 x 2.55 = 2 */
18437 + /* 99 x 2.55 = 252 */
18438 + if ((info->average < 2) || (info->average > 252)) {
18439 + printk("ip6t_random: invalid average %u\n", info->average);
18446 +static struct ip6t_match ip6t_rand_reg = {
18450 + ip6t_rand_checkentry,
18454 +static int __init init(void)
18456 + if (ip6t_register_match(&ip6t_rand_reg))
18459 + printk("ip6t_random match loaded\n");
18463 +static void __exit fini(void)
18465 + ip6t_unregister_match(&ip6t_rand_reg);
18466 + printk("ip6t_random match unloaded\n");
18469 +module_init(init);
18470 +module_exit(fini);
18471 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/xfrm/xfrm_input.c linux-2.6.7/net/xfrm/xfrm_input.c
18472 --- linux-2.6.7.org/net/xfrm/xfrm_input.c 2004-06-16 07:18:54.000000000 +0200
18473 +++ linux-2.6.7/net/xfrm/xfrm_input.c 2004-06-25 12:21:37.111749896 +0200
18478 +#ifdef CONFIG_NETFILTER
18479 + sp->decap_done = 0;
18484 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/xfrm/xfrm_policy.c linux-2.6.7/net/xfrm/xfrm_policy.c
18485 --- linux-2.6.7.org/net/xfrm/xfrm_policy.c 2004-06-16 07:19:23.000000000 +0200
18486 +++ linux-2.6.7/net/xfrm/xfrm_policy.c 2004-06-25 12:21:38.725504568 +0200
18488 #include <linux/workqueue.h>
18489 #include <linux/notifier.h>
18490 #include <linux/netdevice.h>
18491 +#include <linux/netfilter.h>
18492 #include <net/xfrm.h>
18493 #include <net/ip.h>
18495 @@ -911,6 +912,7 @@
18497 if (_decode_session(skb, &fl, family) < 0)
18499 + nf_nat_decode_session(skb, &fl, family);
18501 /* First, check used SA against their selectors. */