1 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_helpers.h linux-2.6.5-rc3/include/linux/netfilter_helpers.h
2 --- linux-2.6.5-rc3.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.5-rc3/include/linux/netfilter_helpers.h 2004-03-30 11:52:01.000000000 +0200
6 + * Helpers for netfiler modules. This file provides implementations for basic
7 + * functions such as strncasecmp(), etc.
9 + * gcc will warn for defined but unused functions, so we only include the
10 + * functions requested. The following macros are used:
11 + * NF_NEED_STRNCASECMP nf_strncasecmp()
12 + * NF_NEED_STRTOU16 nf_strtou16()
13 + * NF_NEED_STRTOU32 nf_strtou32()
15 +#ifndef _NETFILTER_HELPERS_H
16 +#define _NETFILTER_HELPERS_H
18 +/* Only include these functions for kernel code. */
21 +#include <linux/ctype.h>
22 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
25 + * The standard strncasecmp()
27 +#ifdef NF_NEED_STRNCASECMP
29 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
31 + if (s1 == NULL || s2 == NULL)
33 + if (s1 == NULL && s2 == NULL)
37 + return (s1 == NULL) ? -1 : 1;
39 + while (len > 0 && tolower(*s1) == tolower(*s2))
45 + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
47 +#endif /* NF_NEED_STRNCASECMP */
50 + * Parse a string containing a 16-bit unsigned integer.
51 + * Returns the number of chars used, or zero if no number is found.
53 +#ifdef NF_NEED_STRTOU16
55 +nf_strtou16(const char* pbuf, u_int16_t* pval)
60 + while (isdigit(pbuf[n]))
62 + *pval = (*pval * 10) + (pbuf[n] - '0');
68 +#endif /* NF_NEED_STRTOU16 */
71 + * Parse a string containing a 32-bit unsigned integer.
72 + * Returns the number of chars used, or zero if no number is found.
74 +#ifdef NF_NEED_STRTOU32
76 +nf_strtou32(const char* pbuf, u_int32_t* pval)
81 + while (pbuf[n] >= '0' && pbuf[n] <= '9')
83 + *pval = (*pval * 10) + (pbuf[n] - '0');
89 +#endif /* NF_NEED_STRTOU32 */
92 + * Given a buffer and length, advance to the next line and mark the current
95 +#ifdef NF_NEED_NEXTLINE
97 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
107 + while (p[off] != '\n')
118 + /* if we saw a crlf, physlen needs adjusted */
119 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
124 + /* advance past the newline */
128 + *plinelen = physlen;
133 +#endif /* NF_NEED_NEXTLINE */
135 +#endif /* __KERNEL__ */
137 +#endif /* _NETFILTER_HELPERS_H */
138 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
139 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-03-30 11:31:19.000000000 +0200
140 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-03-30 11:53:01.000000000 +0200
144 /* Add protocol helper include file here */
145 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
146 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
147 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
148 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
149 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
150 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
151 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
152 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
154 /* per expectation: application helper private data */
155 union ip_conntrack_expect_help {
156 /* insert conntrack helper private data (expect) here */
157 + struct ip_ct_talk_expect exp_talk_info;
158 + struct ip_ct_rtsp_expect exp_rtsp_info;
159 + struct ip_ct_rtsp_master ct_rtsp_info;
160 + struct ip_ct_rsh_expect exp_rsh_info;
161 + struct ip_ct_mms_expect exp_mms_info;
162 + struct ip_ct_h225_expect exp_h225_info;
163 struct ip_ct_amanda_expect exp_amanda_info;
164 struct ip_ct_ftp_expect exp_ftp_info;
165 struct ip_ct_irc_expect exp_irc_info;
167 /* per conntrack: application helper private data */
168 union ip_conntrack_help {
169 /* insert conntrack helper private data (master) here */
170 + struct ip_ct_talk_master ct_talk_info;
171 + struct ip_ct_rsh_master ct_rsh_info;
172 + struct ip_ct_mms_master ct_mms_info;
173 + struct ip_ct_h225_master ct_h225_info;
174 struct ip_ct_ftp_master ct_ftp_info;
175 struct ip_ct_irc_master ct_irc_info;
179 #endif /* CONFIG_IP_NF_NAT_NEEDED */
181 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
182 + unsigned long mark;
187 /* get master conntrack via master expectation */
188 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
189 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 1970-01-01 01:00:00.000000000 +0100
190 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 2004-03-30 11:50:58.000000000 +0200
192 +#ifndef _IP_CT_CUSEEME
193 +#define _IP_CT_CUSEEME
195 +#define CUSEEME_PORT 7648
197 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
200 +/* CuSeeMe data header */
202 + u_int16_t dest_family;
203 + u_int16_t dest_port;
204 + u_int32_t dest_addr;
210 + u_int16_t data_type;
211 + /* possible values:
215 + * 100 acknowledge connectivity when there
216 + * is nothing else to send
217 + * 101 OpenContinue packet
218 + * 104 display a text message and
219 + * disconnect (used by reflector to
220 + * kick clients off)
221 + * 105 display a text message (welcome
222 + * message from reflector)
223 + * 106 exchanged among reflectors for
224 + * reflector interoperation
225 + * 107 carry aux stream data when there is
226 + * no video to piggy-back on
227 + * 108 obsolete (used in Mac alpha version)
228 + * 109 obsolete (used in Mac alpha version)
229 + * 110 used for data rate control
230 + * 111 used for data rate control
231 + * 256 aux data control messages
232 + * 257 aux data packets
234 + u_int16_t packet_len;
237 +/* Open Continue Header */
239 + struct cu_header cu_head;
240 + u_int16_t client_count; /* Number of client info structs */
242 + char user_name[20];
243 + char stuff[4]; /* Flags, version stuff, etc */
246 +/* Client info structures */
247 +struct client_info {
248 + u_int32_t address; /* Client address */
249 + char stuff[8]; /* Flags, pruning bitfield, packet counts, etc */
253 +/* This structure is per expected connection */
254 +struct ip_ct_cuseeme_expect {
257 +/* This structure exists only once per master */
258 +struct ip_ct_cuseeme_master {
261 +#endif /* _IP_CT_CUSEEME */
262 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
263 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
264 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-03-30 11:51:04.000000000 +0200
266 +#ifndef _IP_CONNTRACK_H323_H
267 +#define _IP_CONNTRACK_H323_H
268 +/* H.323 connection tracking. */
271 +/* Protects H.323 related data */
272 +#include <linux/netfilter_ipv4/lockhelp.h>
273 +DECLARE_LOCK_EXTERN(ip_h323_lock);
276 +/* Default H.225 port */
277 +#define H225_PORT 1720
279 +/* This structure is per expected connection */
280 +struct ip_ct_h225_expect {
281 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
282 + enum ip_conntrack_dir dir; /* Direction of the original connection */
283 + unsigned int offset; /* offset of the address in the payload */
286 +/* This structure exists only once per master */
287 +struct ip_ct_h225_master {
288 + int is_h225; /* H.225 or H.245 connection */
289 +#ifdef CONFIG_IP_NF_NAT_NEEDED
290 + enum ip_conntrack_dir dir; /* Direction of the original connection */
291 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
292 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
296 +#endif /* _IP_CONNTRACK_H323_H */
297 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
298 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
299 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-03-30 11:51:24.000000000 +0200
301 +#ifndef _IP_CONNTRACK_MMS_H
302 +#define _IP_CONNTRACK_MMS_H
306 +#include <linux/netfilter_ipv4/lockhelp.h>
308 +DECLARE_LOCK_EXTERN(ip_mms_lock);
310 +#define MMS_PORT 1755
311 +#define MMS_SRV_MSG_ID 196610
313 +#define MMS_SRV_MSG_OFFSET 36
314 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
315 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
316 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
317 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
320 +/* This structure is per expected connection */
321 +struct ip_ct_mms_expect {
327 +/* This structure exists only once per master */
328 +struct ip_ct_mms_master {
331 +#endif /* _IP_CONNTRACK_MMS_H */
332 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
333 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
334 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-03-30 11:51:52.000000000 +0200
336 +#ifndef _IP_CT_QUAKE3
337 +#define _IP_CT_QUAKE3
339 +/* Don't confuse with 27960, often used as the Server Port */
340 +#define QUAKE3_MASTER_PORT 27950
342 +struct quake3_search {
343 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
344 + const char *pattern;
348 +/* This structure is per expected connection */
349 +struct ip_ct_quake3_expect {
352 +/* This structure exists only once per master */
353 +struct ip_ct_quake3_master {
356 +#endif /* _IP_CT_QUAKE3 */
357 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
358 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
359 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2004-03-30 11:51:55.000000000 +0200
361 +/* RPC extension for IP connection tracking, Version 2.2
362 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
363 + * - original rpc tracking module
364 + * - "recent" connection handling for kernel 2.3+ netfilter
366 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
367 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
369 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
370 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
371 + * - extended matching to support filtering on procedures
373 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
375 + * This program is free software; you can redistribute it and/or
376 + * modify it under the terms of the GNU General Public License
377 + * as published by the Free Software Foundation; either version
378 + * 2 of the License, or (at your option) any later version.
382 +#include <asm/param.h>
383 +#include <linux/sched.h>
384 +#include <linux/timer.h>
385 +#include <linux/stddef.h>
386 +#include <linux/list.h>
388 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
390 +#ifndef _IP_CONNTRACK_RPC_H
391 +#define _IP_CONNTRACK_RPC_H
393 +#define RPC_PORT 111
396 +/* Datum in RPC packets are encoded in XDR */
397 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
399 +/* Fast timeout, to deny DoS atacks */
400 +#define EXP (60 * HZ)
402 +/* Normal timeouts */
403 +#define EXPIRES (180 * HZ)
405 +/* For future conections RPC, using client's cache bindings
406 + * I'll use ip_conntrack_lock to lock these lists */
408 +/* This identifies each request and stores protocol */
410 + struct list_head list;
419 + struct timer_list timeout;
422 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
423 + u_int32_t ip, u_int32_t port) {
424 + return (p->xid == xid && p->ip == ip && p->port);
428 +#endif /* _IP_CONNTRACK_RPC_H */
429 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
430 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
431 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-03-30 11:51:56.000000000 +0200
433 +/* RSH extension for IP connection tracking, Version 1.0
434 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
435 + * based on HW's ip_conntrack_irc.c
437 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
439 + * This program is free software; you can redistribute it and/or
440 + * modify it under the terms of the GNU General Public License
441 + * as published by the Free Software Foundation; either version
442 + * 2 of the License, or (at your option) any later version.
444 +#ifndef _IP_CONNTRACK_RSH_H
445 +#define _IP_CONNTRACK_RSH_H
448 +#include <linux/netfilter_ipv4/lockhelp.h>
450 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
454 +#define RSH_PORT 514
456 +/* This structure is per expected connection */
457 +struct ip_ct_rsh_expect
462 +/* This structure exists only once per master */
463 +struct ip_ct_rsh_master {
466 +#endif /* _IP_CONNTRACK_RSH_H */
468 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
469 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
470 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-03-30 11:52:01.000000000 +0200
473 + * RTSP extension for IP connection tracking.
474 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
475 + * based on ip_conntrack_irc.h
477 + * This program is free software; you can redistribute it and/or
478 + * modify it under the terms of the GNU General Public License
479 + * as published by the Free Software Foundation; either version
480 + * 2 of the License, or (at your option) any later version.
482 +#ifndef _IP_CONNTRACK_RTSP_H
483 +#define _IP_CONNTRACK_RTSP_H
485 +/* #define IP_NF_RTSP_DEBUG */
486 +#define IP_NF_RTSP_VERSION "0.01"
488 +/* port block types */
490 + pb_single, /* client_port=x */
491 + pb_range, /* client_port=x-y */
492 + pb_discon /* client_port=x/y (rtspbis) */
495 +/* We record seq number and length of rtsp headers here, all in host order. */
498 + * This structure is per expected connection. It is a member of struct
499 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
500 + * there and we are expected to only store the length of the data which
501 + * needs replaced. If a packet contains multiple RTSP messages, we create
502 + * one expected connection per message.
504 + * We use these variables to mark the entire header block. This may seem
505 + * like overkill, but the nature of RTSP requires it. A header may appear
506 + * multiple times in a message. We must treat two Transport headers the
507 + * same as one Transport header with two entries.
509 +struct ip_ct_rtsp_expect
511 + u_int32_t len; /* length of header block */
512 + portblock_t pbtype; /* Type of port block that was requested */
513 + u_int16_t loport; /* Port that was requested, low or first */
514 + u_int16_t hiport; /* Port that was requested, high or second */
516 + uint method; /* RTSP method */
517 + uint cseq; /* CSeq from request */
521 +/* This structure exists only once per master */
522 +struct ip_ct_rtsp_master
530 +#include <linux/netfilter_ipv4/lockhelp.h>
532 +#define RTSP_PORT 554
534 +/* Protects rtsp part of conntracks */
535 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
537 +#endif /* __KERNEL__ */
539 +#endif /* _IP_CONNTRACK_RTSP_H */
540 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
541 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
542 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-03-30 11:53:01.000000000 +0200
544 +#ifndef _IP_CONNTRACK_TALK_H
545 +#define _IP_CONNTRACK_TALK_H
546 +/* TALK tracking. */
549 +#include <linux/in.h>
550 +#include <linux/netfilter_ipv4/lockhelp.h>
552 +/* Protects talk part of conntracks */
553 +DECLARE_LOCK_EXTERN(ip_talk_lock);
557 +#define TALK_PORT 517
558 +#define NTALK_PORT 518
560 +/* talk structures and constants from <protocols/talkd.h> */
563 + * 4.3BSD struct sockaddr
566 + u_int16_t ta_family;
569 + u_int32_t ta_junk1;
570 + u_int32_t ta_junk2;
573 +#define TALK_OLD_NSIZE 9
574 +#define TALK_NSIZE 12
575 +#define TALK_TTY_NSIZE 16
578 + * Client->server request message formats.
581 + u_char type; /* request type, see below */
582 + char l_name[TALK_OLD_NSIZE];/* caller's name */
583 + char r_name[TALK_OLD_NSIZE];/* callee's name */
585 + u_int32_t id_num; /* message id */
586 + int32_t pid; /* caller's process id */
587 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
588 + struct talk_addr addr; /* old (4.3) style */
589 + struct talk_addr ctl_addr; /* old (4.3) style */
593 + u_char vers; /* protocol version */
594 + u_char type; /* request type, see below */
595 + u_char answer; /* not used */
597 + u_int32_t id_num; /* message id */
598 + struct talk_addr addr; /* old (4.3) style */
599 + struct talk_addr ctl_addr; /* old (4.3) style */
600 + int32_t pid; /* caller's process id */
601 + char l_name[TALK_NSIZE];/* caller's name */
602 + char r_name[TALK_NSIZE];/* callee's name */
603 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
607 + u_char vers; /* talk protocol version */
608 + u_char type; /* request type */
609 + u_char answer; /* */
610 + u_char extended; /* !0 if additional parts */
611 + u_int32_t id_num; /* message id number (dels) */
612 + struct talk_addr addr; /* target address */
613 + struct talk_addr ctl_addr; /* reply to address */
614 + int32_t pid; /* caller's process id */
615 + char l_name[TALK_NSIZE]; /* caller's name */
616 + char r_name[TALK_NSIZE]; /* callee's name */
617 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
621 + * Server->client response message formats.
623 +struct talk_response {
624 + u_char type; /* type of request message, see below */
625 + u_char answer; /* response to request message, see below */
627 + u_int32_t id_num; /* message id */
628 + struct talk_addr addr; /* address for establishing conversation */
631 +struct ntalk_response {
632 + u_char vers; /* protocol version */
633 + u_char type; /* type of request message, see below */
634 + u_char answer; /* response to request message, see below */
636 + u_int32_t id_num; /* message id */
637 + struct talk_addr addr; /* address for establishing conversation */
640 +struct ntalk2_response {
641 + u_char vers; /* protocol version */
642 + u_char type; /* type of request message */
643 + u_char answer; /* response to request */
644 + u_char rvers; /* Version of answering vers*/
645 + u_int32_t id_num; /* message id number */
646 + struct talk_addr addr; /* address for connection */
647 + /* This is at the end to compatiblize this with NTALK version. */
648 + char r_name[TALK_NSIZE]; /* callee's name */
651 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
652 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
653 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
655 +#define TALK_VERSION 0 /* protocol versions */
656 +#define NTALK_VERSION 1
657 +#define NTALK2_VERSION 2
659 +/* message type values */
660 +#define LEAVE_INVITE 0 /* leave invitation with server */
661 +#define LOOK_UP 1 /* check for invitation by callee */
662 +#define DELETE 2 /* delete invitation by caller */
663 +#define ANNOUNCE 3 /* announce invitation by caller */
665 +#define REPLY_QUERY 4 /* request reply data from local daemon */
668 +#define SUCCESS 0 /* operation completed properly */
669 +#define NOT_HERE 1 /* callee not logged in */
670 +#define FAILED 2 /* operation failed for unexplained reason */
671 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
672 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
673 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
674 +#define BADVERSION 6 /* request has invalid protocol version */
675 +#define BADADDR 7 /* request has invalid addr value */
676 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
678 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
679 +#define TRY_HERE 10 /* Not on this machine, try this */
680 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
681 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
683 +/* We don't really need much for talk */
684 +struct ip_ct_talk_expect
686 + /* Port that was to be used */
690 +/* This structure exists only once per master */
691 +struct ip_ct_talk_master
695 +#endif /* _IP_CONNTRACK_TALK_H */
696 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
697 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
698 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-03-30 11:48:14.000000000 +0200
700 +#ifndef _IPT_CONNMARK_H_target
701 +#define _IPT_CONNMARK_H_target
703 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
704 + * by Henrik Nordstrom <hno@marasystems.com>
706 + * This program is free software; you can redistribute it and/or modify
707 + * it under the terms of the GNU General Public License as published by
708 + * the Free Software Foundation; either version 2 of the License, or
709 + * (at your option) any later version.
713 + IPT_CONNMARK_SET = 0,
715 + IPT_CONNMARK_RESTORE
718 +struct ipt_connmark_target_info {
719 + unsigned long mark;
720 + unsigned long mask;
724 +#endif /*_IPT_CONNMARK_H_target*/
725 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
726 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
727 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-03-30 11:48:25.000000000 +0200
729 +#ifndef _IPT_IPMARK_H_target
730 +#define _IPT_IPMARK_H_target
732 +struct ipt_ipmark_target_info {
733 + unsigned long andmask;
734 + unsigned long ormask;
738 +#define IPT_IPMARK_SRC 0
739 +#define IPT_IPMARK_DST 1
741 +#endif /*_IPT_IPMARK_H_target*/
742 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h
743 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
744 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h 2004-03-30 11:48:31.000000000 +0200
746 +/* Header file for iptables ipt_ROUTE target
748 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
750 + * This software is distributed under GNU GPL v2, 1991
752 +#ifndef _IPT_ROUTE_H_target
753 +#define _IPT_ROUTE_H_target
755 +#define IPT_ROUTE_IFNAMSIZ 16
757 +struct ipt_route_target_info {
758 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
759 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
760 + u_int32_t gw; /* IP address of gateway */
764 +/* Values for "flags" field */
765 +#define IPT_ROUTE_CONTINUE 0x01
767 +#endif /*_IPT_ROUTE_H_target*/
768 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_TCPLAG.h
769 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h 1970-01-01 01:00:00.000000000 +0100
770 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_TCPLAG.h 2004-03-30 11:50:30.000000000 +0200
772 +#ifndef _IPT_TCPLAG_H
773 +#define _IPT_TCPLAG_H
777 + unsigned char level;
778 + unsigned char prefix[ 15 ];
782 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
783 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
784 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-03-30 11:50:41.000000000 +0200
789 +struct ipt_XOR_info {
791 + u_int8_t block_size;
794 +#endif /* _IPT_XOR_H */
795 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
796 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
797 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-03-30 11:50:44.000000000 +0200
799 +#ifndef _IPT_ADDRTYPE_H
800 +#define _IPT_ADDRTYPE_H
802 +struct ipt_addrtype_info {
803 + u_int16_t source; /* source-type mask */
804 + u_int16_t dest; /* dest-type mask */
810 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_condition.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_condition.h
811 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_condition.h 1970-01-01 01:00:00.000000000 +0100
812 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_condition.h 2004-03-30 11:50:47.000000000 +0200
814 +#ifndef __IPT_CONDITION_MATCH__
815 +#define __IPT_CONDITION_MATCH__
817 +#define CONDITION_NAME_LEN 32
819 +struct condition_info {
820 + char name[CONDITION_NAME_LEN];
825 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
826 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
827 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-03-30 11:48:14.000000000 +0200
829 +#ifndef _IPT_CONNMARK_H
830 +#define _IPT_CONNMARK_H
832 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
833 + * by Henrik Nordstrom <hno@marasystems.com>
835 + * This program is free software; you can redistribute it and/or modify
836 + * it under the terms of the GNU General Public License as published by
837 + * the Free Software Foundation; either version 2 of the License, or
838 + * (at your option) any later version.
841 +struct ipt_connmark_info {
842 + unsigned long mark, mask;
846 +#endif /*_IPT_CONNMARK_H*/
847 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_policy.h
848 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
849 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-03-30 11:51:40.000000000 +0200
851 +#ifndef _IPT_POLICY_H
852 +#define _IPT_POLICY_H
854 +#define POLICY_MAX_ELEM 4
856 +enum ipt_policy_flags
858 + POLICY_MATCH_IN = 0x1,
859 + POLICY_MATCH_OUT = 0x2,
860 + POLICY_MATCH_NONE = 0x4,
861 + POLICY_MATCH_STRICT = 0x8,
864 +enum ipt_policy_modes
866 + POLICY_MODE_TRANSPORT,
870 +struct ipt_policy_spec
880 +struct ipt_policy_elem
891 + struct ipt_policy_spec match;
892 + struct ipt_policy_spec invert;
895 +struct ipt_policy_info
897 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
902 +#endif /* _IPT_POLICY_H */
903 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_rpc.h
904 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
905 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_rpc.h 2004-03-30 11:51:55.000000000 +0200
907 +/* RPC extension for IP netfilter matching, Version 2.2
908 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
909 + * - original rpc tracking module
910 + * - "recent" connection handling for kernel 2.3+ netfilter
912 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
913 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
915 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
916 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
917 + * - extended matching to support filtering on procedures
919 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
921 + * This program is free software; you can redistribute it and/or
922 + * modify it under the terms of the GNU General Public License
923 + * as published by the Free Software Foundation; either version
924 + * 2 of the License, or (at your option) any later version.
931 +struct ipt_rpc_data;
933 +struct ipt_rpc_info {
936 + const char c_procs[1408];
938 + struct ipt_rpc_data *data;
941 +#endif /* _IPT_RPC_H */
942 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_string.h
943 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
944 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-03-30 11:52:56.000000000 +0200
946 +#ifndef _IPT_STRING_H
947 +#define _IPT_STRING_H
949 +/* *** PERFORMANCE TWEAK ***
950 + * Packet size and search string threshold,
951 + * above which sublinear searches is used. */
952 +#define IPT_STRING_HAYSTACK_THRESH 100
953 +#define IPT_STRING_NEEDLE_THRESH 20
955 +#define BM_MAX_NLEN 256
956 +#define BM_MAX_HLEN 1024
958 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
960 +struct ipt_string_info {
961 + char string[BM_MAX_NLEN];
966 +#endif /* _IPT_STRING_H */
967 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h
968 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
969 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2004-03-30 11:48:31.000000000 +0200
971 +/* Header file for iptables ip6t_ROUTE target
973 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
975 + * This software is distributed under GNU GPL v2, 1991
977 +#ifndef _IPT_ROUTE_H_target
978 +#define _IPT_ROUTE_H_target
980 +#define IP6T_ROUTE_IFNAMSIZ 16
982 +struct ip6t_route_target_info {
983 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
984 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
985 + u_int32_t gw[4]; /* IPv6 address of gateway */
989 +/* Values for "flags" field */
990 +#define IP6T_ROUTE_CONTINUE 0x01
992 +#endif /*_IP6T_ROUTE_H_target*/
993 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_condition.h
994 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_condition.h 1970-01-01 01:00:00.000000000 +0100
995 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_condition.h 2004-03-30 11:50:47.000000000 +0200
997 +#ifndef __IP6T_CONDITION_MATCH__
998 +#define __IP6T_CONDITION_MATCH__
1000 +#define CONDITION6_NAME_LEN 32
1002 +struct condition6_info {
1003 + char name[CONDITION6_NAME_LEN];
1008 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_mime.h linux-2.6.5-rc3/include/linux/netfilter_mime.h
1009 --- linux-2.6.5-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1010 +++ linux-2.6.5-rc3/include/linux/netfilter_mime.h 2004-03-30 11:52:01.000000000 +0200
1013 + * MIME functions for netfilter modules. This file provides implementations
1014 + * for basic MIME parsing. MIME headers are used in many protocols, such as
1015 + * HTTP, RTSP, SIP, etc.
1017 + * gcc will warn for defined but unused functions, so we only include the
1018 + * functions requested. The following macros are used:
1019 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1021 +#ifndef _NETFILTER_MIME_H
1022 +#define _NETFILTER_MIME_H
1024 +/* Only include these functions for kernel code. */
1027 +#include <linux/ctype.h>
1030 + * Given a buffer and length, advance to the next line and mark the current
1031 + * line. If the current line is empty, *plinelen will be set to zero. If
1032 + * not, it will be set to the actual line length (including CRLF).
1034 + * 'line' in this context means logical line (includes LWS continuations).
1035 + * Returns 1 on success, 0 on failure.
1037 +#ifdef NF_NEED_MIME_NEXTLINE
1039 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1043 + int is_first_line = 1;
1052 + while (p[off] != '\n')
1063 + /* if we saw a crlf, physlen needs adjusted */
1064 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1069 + /* advance past the newline */
1072 + /* check for an empty line */
1078 + /* check for colon on the first physical line */
1079 + if (is_first_line)
1081 + is_first_line = 0;
1082 + if (memchr(p+(*poff), ':', physlen) == NULL)
1088 + while (p[off] == ' ' || p[off] == '\t');
1090 + *plineoff = *poff;
1091 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
1096 +#endif /* NF_NEED_MIME_NEXTLINE */
1098 +#endif /* __KERNEL__ */
1100 +#endif /* _NETFILTER_MIME_H */
1101 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/net/tcp.h linux-2.6.5-rc3/include/net/tcp.h
1102 --- linux-2.6.5-rc3.org/include/net/tcp.h 2004-03-30 05:25:33.000000000 +0200
1103 +++ linux-2.6.5-rc3/include/net/tcp.h 2004-03-30 11:51:33.000000000 +0200
1105 extern void tcp_bucket_unlock(struct sock *sk);
1106 extern int tcp_port_rover;
1107 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
1108 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
1110 /* These are AF independent. */
1111 static __inline__ int tcp_bhashfn(__u16 lport)
1112 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/net/udp.h linux-2.6.5-rc3/include/net/udp.h
1113 --- linux-2.6.5-rc3.org/include/net/udp.h 2004-03-30 05:27:01.000000000 +0200
1114 +++ linux-2.6.5-rc3/include/net/udp.h 2004-03-30 11:51:33.000000000 +0200
1116 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
1117 extern int udp_disconnect(struct sock *sk, int flags);
1119 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
1121 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
1122 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
1123 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
1124 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/core/netfilter.c linux-2.6.5-rc3/net/core/netfilter.c
1125 --- linux-2.6.5-rc3.org/net/core/netfilter.c 2004-03-30 11:31:19.000000000 +0200
1126 +++ linux-2.6.5-rc3/net/core/netfilter.c 2004-03-30 11:51:26.000000000 +0200
1128 } queue_handler[NPROTO];
1129 static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
1132 + * nf_register_hook - Register with a netfilter hook
1133 + * @reg: Hook operations to be registered
1135 int nf_register_hook(struct nf_hook_ops *reg)
1137 struct list_head *i;
1143 + * nf_unregister_hook - Unregister from a netfilter hook
1144 + * @reg: hook operations to be unregistered
1146 void nf_unregister_hook(struct nf_hook_ops *reg)
1148 spin_lock_bh(&nf_hook_lock);
1149 @@ -388,6 +396,18 @@
1154 + * nf_register_queue_handler - Registere a queue handler with netfilter
1155 + * @pf: protocol family
1156 + * @outfn: function called by core to enqueue a packet
1157 + * @data: opaque parameter, passed through
1159 + * This function registers a queue handler with netfilter. There can only
1160 + * be one queue handler for every protocol family.
1162 + * A queue handler _must_ reinject every packet via nf_reinject, no
1165 int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
1168 @@ -405,7 +425,12 @@
1172 -/* The caller must flush their queue before this */
1174 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
1175 + * @pf: protocol family
1177 + * The caller must flush their queue before unregistering
1179 int nf_unregister_queue_handler(int pf)
1181 write_lock_bh(&queue_handler_lock);
1182 @@ -548,6 +573,15 @@
1187 + * nf_reinject - Reinject a packet from a queue handler
1188 + * @skb: the packet to be reinjected
1189 + * @info: info which was passed to the outfn() of the queue handler
1190 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
1192 + * This is the function called by a queue handler to reinject a
1195 void nf_reinject(struct sk_buff *skb, struct nf_info *info,
1196 unsigned int verdict)
1198 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.5-rc3/net/ipv4/netfilter/Kconfig
1199 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/Kconfig 2004-03-30 11:31:20.000000000 +0200
1200 +++ linux-2.6.5-rc3/net/ipv4/netfilter/Kconfig 2004-03-30 11:53:01.000000000 +0200
1201 @@ -706,5 +706,149 @@
1202 depends on IP_NF_IPTABLES
1205 +config IP_NF_CONNTRACK_MARK
1206 + bool 'Connection mark tracking support'
1208 +config IP_NF_TARGET_CONNMARK
1209 + tristate 'CONNMARK target support'
1210 + depends on IP_NF_MANGLE
1212 +config IP_NF_MATCH_CONNMARK
1213 + tristate ' Connection mark match support'
1214 + depends on IP_NF_IPTABLES
1217 +config IP_NF_TARGET_IPMARK
1218 + tristate 'IPMARK target support'
1219 + depends on IP_NF_MANGLE
1222 +config IP_NF_TARGET_ROUTE
1223 + tristate 'ROUTE target support'
1224 + depends on IP_NF_MANGLE
1227 +config IP_NF_TARGET_TARPIT
1228 + tristate 'TARPIT target support'
1229 + depends on IP_NF_FILTER
1232 +config IP_NF_TARGET_TCPLAG
1233 + tristate 'TCPLAG target support'
1234 + depends on IP_NF_IPTABLES
1237 +config IP_NF_TARGET_XOR
1238 + tristate 'XOR target support'
1239 + depends on IP_NF_MANGLE
1242 +config IP_NF_MATCH_ADDRTYPE
1243 + tristate 'address type match support'
1244 + depends on IP_NF_IPTABLES
1247 +config IP_NF_MATCH_CONDITION
1248 + tristate 'condition match support'
1249 + depends on IP_NF_IPTABLES
1252 +config IP_NF_NAT_CUSEEME
1254 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1255 + default IP_NF_NAT if IP_NF_CUSEEME=y
1256 + default m if IP_NF_CUSEEME=m
1258 +config IP_NF_CUSEEME
1259 + tristate 'CuSeeMe protocol support'
1260 + depends on IP_NF_CONNTRACK
1264 + tristate 'Eggdrop bot support'
1265 + depends on IP_NF_CONNTRACK
1268 +config IP_NF_NAT_H323
1270 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1271 + default IP_NF_NAT if IP_NF_H323=y
1272 + default m if IP_NF_H323=m
1275 + tristate 'H.323 (netmeeting) support'
1276 + depends on IP_NF_CONNTRACK
1279 +config IP_NF_NAT_MMS
1281 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1282 + default IP_NF_NAT if IP_NF_MMS=y
1283 + default m if IP_NF_MMS=m
1286 + tristate 'MMS protocol support'
1287 + depends on IP_NF_CONNTRACK
1290 +config IP_NF_MATCH_POLICY
1291 + tristate "IPsec policy match support"
1292 + depends on IP_NF_IPTABLES && XFRM
1294 + Policy matching allows you to match packets based on the
1295 + IPsec policy that was used during decapsulation/will
1296 + be used during encapsulation.
1298 + To compile it as a module, choose M here. If unsure, say N.
1301 +config IP_NF_NAT_QUAKE3
1303 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1304 + default IP_NF_NAT if IP_NF_QUAKE3=y
1305 + default m if IP_NF_QUAKE3=m
1307 +config IP_NF_QUAKE3
1308 + tristate "Quake3 protocol support"
1309 + depends on IP_NF_CONNTRACK
1312 +config IP_NF_MATCH_RPC
1313 + tristate 'RPC match support'
1314 + depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1318 + tristate 'RSH protocol support'
1319 + depends on IP_NF_CONNTRACK
1322 +config IP_NF_NAT_RTSP
1324 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1325 + default IP_NF_NAT if IP_NF_RTSP=y
1326 + default m if IP_NF_RTSP=m
1329 + tristate ' RTSP protocol support'
1330 + depends on IP_NF_CONNTRACK
1333 +config IP_NF_MATCH_STRING
1334 + tristate 'String match support'
1335 + depends on IP_NF_IPTABLES
1338 +config IP_NF_NAT_TALK
1340 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1341 + default IP_NF_NAT if IP_NF_TALK=y
1342 + default m if IP_NF_TALK=m
1345 + tristate 'talk protocol support'
1346 + depends on IP_NF_CONNTRACK
1351 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.5-rc3/net/ipv4/netfilter/Makefile
1352 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/Makefile 2004-03-30 11:31:20.000000000 +0200
1353 +++ linux-2.6.5-rc3/net/ipv4/netfilter/Makefile 2004-03-30 11:53:01.000000000 +0200
1355 # connection tracking
1356 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1358 +# talk protocol support
1359 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1360 +ifdef CONFIG_IP_NF_TALK
1361 + export-objs += ip_conntrack_talk.o
1363 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1367 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1368 +ifdef CONFIG_IP_NF_H323
1369 + export-objs += ip_conntrack_h323.o
1371 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1374 # connection tracking helpers
1376 +# rtsp protocol support
1377 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
1378 +ifdef CONFIG_IP_NF_NAT_RTSP
1379 + export-objs += ip_conntrack_rtsp.o
1381 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
1383 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1384 +ifdef CONFIG_IP_NF_NAT_QUAKE3
1385 + export-objs += ip_conntrack_quake3.o
1387 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1388 +ifdef CONFIG_IP_NF_MMS
1389 + export-objs += ip_conntrack_mms.o
1391 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1392 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1393 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1394 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1396 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
1398 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1401 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
1402 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
1403 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1404 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1405 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1406 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1407 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1410 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1412 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1415 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1416 +export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
1418 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1419 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1420 obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1422 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1424 obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1425 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
1427 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1428 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1429 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
1431 obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1433 @@ -89,12 +133,15 @@
1435 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1436 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1437 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
1438 obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1439 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1440 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1441 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
1442 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1444 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1445 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
1448 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
1449 @@ -102,14 +149,20 @@
1450 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
1451 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
1452 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
1453 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
1454 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
1455 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
1456 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
1457 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
1458 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
1459 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
1460 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
1461 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1462 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1463 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1464 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
1465 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
1466 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
1467 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1468 obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1469 obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1470 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_core.c
1471 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-03-30 11:31:19.000000000 +0200
1472 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-03-30 11:51:26.000000000 +0200
1474 * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
1475 * - add usage/reference counts to ip_conntrack_expect
1476 * - export ip_conntrack[_expect]_{find_get,put} functions
1477 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
1478 + * - added DocBook-style comments for public API
1481 #include <linux/config.h>
1487 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
1488 + * @protocol: protocol number
1490 struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
1492 struct ip_conntrack_protocol *p;
1493 @@ -113,6 +119,11 @@
1494 static int ip_conntrack_hash_rnd_initted;
1495 static unsigned int ip_conntrack_hash_rnd;
1498 + * hash_conntrack - Calculate the position of an entry in the connection
1500 + * @tuple: conntrack tuple which we want to calculate the hash position
1503 hash_conntrack(const struct ip_conntrack_tuple *tuple)
1505 @@ -125,6 +136,19 @@
1506 ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
1510 + * get_tuple - set all the fields of a tuple which is passed as parameter
1511 + * given a network buffer.
1512 + * @iph:pointer an IP header.
1513 + * @skb:network buffer for which we want to generate the tuple
1514 + * @dataoff: FIXME: Deprecated?
1515 + * @tuple: tuple which will be generate. Used as return parameter.
1516 + * @protocol: structure which contains pointer to protocol specific functions.
1518 + * Note: This function doesn't allocate space for the tuple passed as
1519 + * parameter. The function pkt_to_packet which set all the protocol specific
1520 + * fields of a given tuple.
1523 get_tuple(const struct iphdr *iph,
1524 const struct sk_buff *skb,
1525 @@ -146,6 +170,15 @@
1526 return protocol->pkt_to_tuple(skb, dataoff, tuple);
1530 + * invert_tuple - Returns the inverse of a given tuple. It is used to
1531 + * calculate the tuple which represents the other sense of the flow
1532 + * of a connection.
1533 + * @inverse: the inverted tuple. Use as return value.
1534 + * @orig: the original tuple which will be inverted.
1535 + * @protocol: a pointer to the protocol structure which contains all the
1536 + * specifical functions available for this tuple.
1539 invert_tuple(struct ip_conntrack_tuple *inverse,
1540 const struct ip_conntrack_tuple *orig,
1541 @@ -161,7 +194,15 @@
1543 /* ip_conntrack_expect helper functions */
1545 -/* Compare tuple parts depending on mask. */
1547 + * expect_cmp - compare a tuple with a expectation depending on a mask
1548 + * @i: pointer to an expectation.
1549 + * @tuple: tuple which will be compared with the expectation tuple.
1551 + * Actually the tuple field of an expectation is compared with a tuple
1552 + * This function is used by LIST_FIND to find a expectation which match a te
1555 static inline int expect_cmp(const struct ip_conntrack_expect *i,
1556 const struct ip_conntrack_tuple *tuple)
1558 @@ -169,6 +210,10 @@
1559 return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask);
1563 + * destroy_expect - Release all the resources allocated by an expectation.
1564 + * @exp: pointer to the expectation which we want to release.
1567 destroy_expect(struct ip_conntrack_expect *exp)
1569 @@ -179,7 +224,11 @@
1575 + * ip_conntrack_expect_put - it decrements the counter of use related
1576 + * associated to an expectation and it calls destroy_expect.
1577 + * @exp: pointer to the expectation which we want to release.
1579 inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
1582 @@ -199,7 +248,14 @@
1583 struct ip_conntrack_expect *, tuple);
1586 -/* Find a expectation corresponding to a tuple. */
1588 + * ip_conntrack_find_get - find conntrack according to tuple
1589 + * @tuple: conntrack tuple for which we search conntrack
1590 + * @ignored_conntrack: ignore this conntrack during search
1592 + * This function increments the reference count of the found
1593 + * conntrack (if any).
1595 struct ip_conntrack_expect *
1596 ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
1598 @@ -382,7 +438,14 @@
1602 -/* Find a connection corresponding to a tuple. */
1604 + * ip_conntrack_find_get - find conntrack according to tuple
1605 + * @tuple: conntrack tuple for which we search conntrack
1606 + * @ignored_conntrack: ignore this conntrack during search
1608 + * This function increments the reference count of the found
1609 + * conntrack (if any).
1611 struct ip_conntrack_tuple_hash *
1612 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
1613 const struct ip_conntrack *ignored_conntrack)
1614 @@ -410,7 +473,14 @@
1618 -/* Return conntrack and conntrack_info given skb->nfct->master */
1620 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
1621 + * @skb: skb for which we want to find conntrack and conntrack_info
1622 + * @ctinfo: pointer to ctinfo, used as return value
1624 + * This function resolves the respective conntrack and conntrack_info
1625 + * structures for the connection this packet (skb) is part of.
1627 struct ip_conntrack *
1628 ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
1630 @@ -480,8 +550,14 @@
1634 -/* Returns true if a connection correspondings to the tuple (required
1637 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
1638 + * @tuple: tuple to be used for this test
1639 + * @ignored_conntrack: conntrack which is excluded from result
1641 + * This function is called by the NAT code in order to find out if
1642 + * a particular tuple is already in use by some connection.
1645 ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
1646 const struct ip_conntrack *ignored_conntrack)
1647 @@ -607,7 +683,13 @@
1649 return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
1653 + * ip_ct_find_helper - Find application helper according to tuple
1654 + * @tuple: tuple for which helper needs to be found
1656 + * This function is used to determine if any registered conntrack helper
1657 + * is to be used for the given tuple.
1659 struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
1661 return LIST_FIND(&helpers, helper_cmp,
1663 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1664 conntrack->master = expected;
1665 expected->sibling = conntrack;
1666 +#if CONFIG_IP_NF_CONNTRACK_MARK
1667 + conntrack->mark = expected->expectant->mark;
1669 LIST_DELETE(&ip_conntrack_expect_list, expected);
1670 expected->expectant->expecting--;
1671 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1672 @@ -910,6 +995,14 @@
1673 return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
1677 + * ip_conntrack_unexpect_related - Unexpect a related connection
1678 + * @expect: expecattin to be removed
1680 + * This function removes an existing expectation, that has not yet been
1681 + * confirmed (i.e. expectation was issued, but expected connection didn't
1684 inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
1686 WRITE_LOCK(&ip_conntrack_lock);
1687 @@ -927,7 +1020,20 @@
1688 WRITE_UNLOCK(&ip_conntrack_lock);
1691 -/* Add a related connection. */
1693 + * ip_conntrack_expect_related - Expect a related connection
1694 + * @related_to: master conntrack
1695 + * @expect: expectation with all values filled in
1697 + * This function is called by conntrack application helpers who
1698 + * have detected that the control (master) connection is just about
1699 + * to negotiate a related slave connection.
1701 + * Note: This function allocates it's own struct ip_conntrack_expect,
1702 + * copying the values from the 'expect' parameter. Thus, 'expect' can
1703 + * be allocated on the stack and does not need to be valid after this
1704 + * function returns.
1706 int ip_conntrack_expect_related(struct ip_conntrack *related_to,
1707 struct ip_conntrack_expect *expect)
1709 @@ -1057,7 +1163,15 @@
1713 -/* Change tuple in an existing expectation */
1715 + * ip_conntrack_change_expect - Change tuple in existing expectation
1716 + * @expect: expectation which is to be changed
1717 + * @newtuple: new tuple for expect
1719 + * This function is mostly called by NAT application helpers, who want to
1720 + * change an expectation issued by their respective conntrack application
1721 + * helper counterpart.
1723 int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
1724 struct ip_conntrack_tuple *newtuple)
1726 @@ -1098,8 +1212,15 @@
1730 -/* Alter reply tuple (maybe alter helper). If it's already taken,
1731 - return 0 and don't do alteration. */
1733 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
1734 + * @conntrack: conntrack whose reply tuple we want to alter
1735 + * @newreply: designated reply tuple for this conntrack
1737 + * This function alters the reply tuple of a conntrack to the given
1738 + * newreply tuple. If this newreply tuple is already taken, return 0
1739 + * and don't do alteration
1741 int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
1742 const struct ip_conntrack_tuple *newreply)
1744 @@ -1124,6 +1245,13 @@
1749 + * ip_conntrack_helper_register - Register a conntrack application helper
1750 + * @me: structure describing the helper
1752 + * This function is called by conntrack application helpers to register
1753 + * themselves with the conntrack core.
1755 int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
1757 WRITE_LOCK(&ip_conntrack_lock);
1758 @@ -1145,6 +1273,13 @@
1763 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
1764 + * @me: structure describing the helper
1766 + * This function is called by conntrack application helpers to unregister
1767 + * themselvers from the conntrack core.
1769 void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1772 @@ -1163,7 +1298,14 @@
1776 -/* Refresh conntrack for this many jiffies. */
1778 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
1779 + * @ct: conntrack which we want to refresh
1780 + * @extra_jiffies: number of jiffies to add
1782 + * This function is called by protocol helpers and application helpers in
1783 + * order to change the expiration timer of a conntrack entry.
1785 void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
1787 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1788 @@ -1182,7 +1324,16 @@
1789 WRITE_UNLOCK(&ip_conntrack_lock);
1792 -/* Returns new sk_buff, or NULL */
1795 + * ip_ct_gather_frags - Gather fragments of a particular skb
1796 + * @skb: pointer to sk_buff of fragmented IP packet
1798 + * This code is just a wrapper around the defragmentation code in the core IPv4
1799 + * stack. It also takes care of nonlinear skb's.
1801 + * Returns new sk_buff, or NULL
1804 ip_ct_gather_frags(struct sk_buff *skb)
1806 @@ -1266,6 +1417,16 @@
1811 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
1812 + * @kill: callback function selecting which entries to delete
1813 + * @data: opaque data pointer, becomes 2nd argument for kill function
1815 + * This function can be used to selectively delete elements of the conntrack
1816 + * hashtable. The function iterates over the list of conntrack entries and
1817 + * calls the 'kill' function for every entry. If the return value is true,
1818 + * the connection is deleted (death_by_timeout).
1821 ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
1823 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
1824 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
1825 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-03-30 11:51:02.000000000 +0200
1827 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
1828 + * based on ip_conntrack_irc.c
1830 + * This module only supports the share userfile-send command,
1831 + * used by eggdrops to share it's userfile.
1833 + * There are no support for NAT at the moment.
1835 + * This program is free software; you can redistribute it and/or
1836 + * modify it under the terms of the GNU General Public License
1837 + * as published by the Free Software Foundation; either version
1838 + * 2 of the License, or (at your option) any later version.
1840 + * Module load syntax:
1842 + * please give the ports of all Eggdrops You have running
1843 + * on your system, the default port is 3333.
1845 + * 2001-04-19: Security update. IP addresses are now compared
1846 + * to prevent unauthorized "related" access.
1848 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
1849 + * Port to netfilter 'newnat' API.
1852 +#include <linux/module.h>
1853 +#include <linux/netfilter.h>
1854 +#include <linux/ip.h>
1855 +#include <net/checksum.h>
1856 +#include <net/tcp.h>
1858 +#include <linux/netfilter_ipv4/lockhelp.h>
1859 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1861 +#define MAX_PORTS 8
1862 +static int ports[MAX_PORTS];
1863 +static int ports_c = 0;
1864 +static unsigned int egg_timeout = 300;
1866 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
1867 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
1868 +MODULE_LICENSE("GPL");
1870 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
1871 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
1874 +DECLARE_LOCK(ip_egg_lock);
1875 +struct module *ip_conntrack_egg = THIS_MODULE;
1878 +#define DEBUGP printk
1880 +#define DEBUGP(format, args...)
1883 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
1884 +/* tries to get the ip_addr and port out of a eggdrop command
1885 + return value: -1 on failure, 0 on success
1886 + data pointer to first byte of DCC command data
1887 + data_end pointer to last byte of dcc command data
1888 + ip returns parsed ip of dcc command
1889 + port returns parsed port of dcc command */
1891 + if (data > data_end)
1894 + *ip = simple_strtoul(data, &data, 10);
1896 + /* skip blanks between ip and port */
1897 + while (*data == ' ' && data < data_end)
1900 + *port = simple_strtoul(data, &data, 10);
1905 +static int help(const struct iphdr *iph, size_t len,
1906 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
1908 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
1909 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
1910 + char *data = (char *) tcph + tcph->doff * 4;
1912 + u_int32_t tcplen = len - iph->ihl * 4;
1913 + u_int32_t datalen = tcplen - tcph->doff * 4;
1914 + int dir = CTINFO2DIR(ctinfo);
1915 + int bytes_scanned = 0;
1916 + struct ip_conntrack_expect exp;
1919 + u_int16_t egg_port;
1921 + DEBUGP("entered\n");
1923 + /* If packet is coming from IRC server */
1924 + if (dir != IP_CT_DIR_REPLY)
1927 + /* Until there's been traffic both ways, don't look in packets. */
1928 + if (ctinfo != IP_CT_ESTABLISHED
1929 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1930 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
1934 + /* Not whole TCP header? */
1935 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
1936 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
1940 + /* Checksum invalid? Ignore. */
1941 + /* FIXME: Source route IP option packets --RR */
1942 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1943 + csum_partial((char *) tcph, tcplen, 0))) {
1944 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
1945 + tcph, tcplen, NIPQUAD(iph->saddr),
1946 + NIPQUAD(iph->daddr));
1950 + data_limit = (char *) data + datalen;
1951 + while (datalen > 5 && bytes_scanned < 128) {
1952 + if (memcmp(data, "s us ", 5)) {
1961 + DEBUGP("Userfile-share found in connection "
1962 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
1963 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
1965 + if (parse_command((char *) data, data_limit, &egg_ip,
1967 + DEBUGP("no data in userfile-share pkt\n");
1971 + memset(&exp, 0, sizeof(exp));
1973 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
1974 + if (net_ratelimit())
1975 + printk("Forged Eggdrop command from "
1976 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
1977 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
1978 + HIPQUAD(egg_ip), egg_port);
1982 + exp.tuple.src.ip = iph->daddr;
1983 + exp.tuple.src.u.tcp.port = 0;
1984 + exp.tuple.dst.ip = htonl(egg_ip);
1985 + exp.tuple.dst.u.tcp.port = htons(egg_port);
1986 + exp.tuple.dst.protonum = IPPROTO_TCP;
1988 + exp.mask.dst.u.tcp.port = 0xffff;
1989 + exp.mask.dst.protonum = 0xffff;
1991 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
1992 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
1993 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
1995 + ip_conntrack_expect_related(ct, &exp);
2001 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
2002 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
2004 +static void deregister_helpers(void) {
2007 + for (i = 0; i < ports_c; i++) {
2008 + DEBUGP("unregistering helper for port %d\n", ports[i]);
2009 + ip_conntrack_helper_unregister(&egg_helpers[i]);
2013 +static int __init init(void)
2018 + /* If no port given, default to standard eggdrop port */
2019 + if (ports[0] == 0)
2022 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2023 + memset(&egg_helpers[i], 0,
2024 + sizeof(struct ip_conntrack_helper));
2025 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
2026 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
2027 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
2028 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
2029 + egg_helpers[i].max_expected = 1;
2030 + egg_helpers[i].timeout = egg_timeout;
2031 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2032 + egg_helpers[i].me = THIS_MODULE;
2033 + egg_helpers[i].help = help;
2035 + tmpname = &egg_names[i][0];
2036 + if (ports[i] == 3333)
2037 + sprintf(tmpname, "eggdrop");
2039 + sprintf(tmpname, "eggdrop-%d", ports[i]);
2040 + egg_helpers[i].name = tmpname;
2042 + DEBUGP("port #%d: %d\n", i, ports[i]);
2044 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
2047 + printk("ip_conntrack_egg: ERROR registering helper "
2048 + "for port %d\n", ports[i]);
2049 + deregister_helpers();
2057 +static void __exit fini(void)
2059 + deregister_helpers();
2064 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
2065 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
2066 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-03-30 11:51:04.000000000 +0200
2069 + * H.323 'brute force' extension for H.323 connection tracking.
2070 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2072 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
2073 + * (http://www.coritel.it/projects/sofia/nat/)
2074 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
2075 + * the unregistered helpers to the conntrack entries.
2079 +#include <linux/module.h>
2080 +#include <linux/netfilter.h>
2081 +#include <linux/ip.h>
2082 +#include <net/checksum.h>
2083 +#include <net/tcp.h>
2085 +#include <linux/netfilter_ipv4/lockhelp.h>
2086 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2087 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2088 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2089 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
2090 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
2092 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
2093 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
2094 +MODULE_LICENSE("GPL");
2096 +DECLARE_LOCK(ip_h323_lock);
2097 +struct module *ip_conntrack_h323 = THIS_MODULE;
2100 +#define DEBUGP printk
2102 +#define DEBUGP(format, args...)
2105 +/* FIXME: This should be in userspace. Later. */
2106 +static int h245_help(const struct iphdr *iph, size_t len,
2107 + struct ip_conntrack *ct,
2108 + enum ip_conntrack_info ctinfo)
2110 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2111 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2112 + unsigned char *data_limit;
2113 + u_int32_t tcplen = len - iph->ihl * 4;
2114 + u_int32_t datalen = tcplen - tcph->doff * 4;
2115 + int dir = CTINFO2DIR(ctinfo);
2116 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2117 + struct ip_conntrack_expect expect, *exp = &expect;
2118 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2119 + u_int16_t data_port;
2120 + u_int32_t data_ip;
2123 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2124 + NIPQUAD(iph->saddr), ntohs(tcph->source),
2125 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
2127 + /* Can't track connections formed before we registered */
2131 + /* Until there's been traffic both ways, don't look in packets. */
2132 + if (ctinfo != IP_CT_ESTABLISHED
2133 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2134 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
2138 + /* Not whole TCP header or too short packet? */
2139 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2140 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
2144 + /* Checksum invalid? Ignore. */
2145 + /* FIXME: Source route IP option packets --RR */
2146 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2147 + csum_partial((char *)tcph, tcplen, 0))) {
2148 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2149 + tcph, tcplen, NIPQUAD(iph->saddr),
2150 + NIPQUAD(iph->daddr));
2154 + data_limit = (unsigned char *) data + datalen;
2157 + for (i = 0; data < (data_limit - 5); data++, i++) {
2158 + data_ip = *((u_int32_t *)data);
2159 + if (data_ip == iph->saddr) {
2160 + data_port = *((u_int16_t *)(data + 4));
2161 + memset(&expect, 0, sizeof(expect));
2162 + /* update the H.225 info */
2163 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
2164 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2165 + NIPQUAD(iph->saddr), ntohs(data_port));
2166 + LOCK_BH(&ip_h323_lock);
2167 + info->is_h225 = H225_PORT + 1;
2168 + exp_info->port = data_port;
2169 + exp_info->dir = dir;
2170 + exp_info->offset = i;
2172 + exp->seq = ntohl(tcph->seq) + i;
2174 + exp->tuple = ((struct ip_conntrack_tuple)
2175 + { { ct->tuplehash[!dir].tuple.src.ip,
2178 + { .tcp = { data_port } },
2180 + exp->mask = ((struct ip_conntrack_tuple)
2181 + { { 0xFFFFFFFF, { 0 } },
2182 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2184 + exp->expectfn = NULL;
2186 + /* Ignore failure; should only happen with NAT */
2187 + ip_conntrack_expect_related(ct, exp);
2189 + UNLOCK_BH(&ip_h323_lock);
2197 +/* H.245 helper is not registered! */
2198 +static struct ip_conntrack_helper h245 =
2200 + "H.245", /* name */
2201 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2202 + NULL, /* module */
2203 + 8, /* max_ expected */
2204 + 240, /* timeout */
2205 + { { 0, { 0 } }, /* tuple */
2206 + { 0, { 0 }, IPPROTO_TCP } },
2207 + { { 0, { 0xFFFF } }, /* mask */
2208 + { 0, { 0 }, 0xFFFF } },
2209 + h245_help /* helper */
2212 +static int h225_expect(struct ip_conntrack *ct)
2214 + WRITE_LOCK(&ip_conntrack_lock);
2215 + ct->helper = &h245;
2216 + DEBUGP("h225_expect: helper for %p added\n", ct);
2217 + WRITE_UNLOCK(&ip_conntrack_lock);
2219 + return NF_ACCEPT; /* unused */
2222 +/* FIXME: This should be in userspace. Later. */
2223 +static int h225_help(const struct iphdr *iph, size_t len,
2224 + struct ip_conntrack *ct,
2225 + enum ip_conntrack_info ctinfo)
2227 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2228 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2229 + unsigned char *data_limit;
2230 + u_int32_t tcplen = len - iph->ihl * 4;
2231 + u_int32_t datalen = tcplen - tcph->doff * 4;
2232 + int dir = CTINFO2DIR(ctinfo);
2233 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2234 + struct ip_conntrack_expect expect, *exp = &expect;
2235 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2236 + u_int16_t data_port;
2237 + u_int32_t data_ip;
2240 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2241 + NIPQUAD(iph->saddr), ntohs(tcph->source),
2242 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
2244 + /* Can't track connections formed before we registered */
2248 + /* Until there's been traffic both ways, don't look in packets. */
2249 + if (ctinfo != IP_CT_ESTABLISHED
2250 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2251 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
2255 + /* Not whole TCP header or too short packet? */
2256 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2257 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
2261 + /* Checksum invalid? Ignore. */
2262 + /* FIXME: Source route IP option packets --RR */
2263 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2264 + csum_partial((char *)tcph, tcplen, 0))) {
2265 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2266 + tcph, tcplen, NIPQUAD(iph->saddr),
2267 + NIPQUAD(iph->daddr));
2271 + data_limit = (unsigned char *) data + datalen;
2274 + for (i = 0; data < (data_limit - 5); data++, i++) {
2275 + data_ip = *((u_int32_t *)data);
2276 + if (data_ip == iph->saddr) {
2277 + data_port = *((u_int16_t *)(data + 4));
2278 + if (data_port == tcph->source) {
2279 + /* Signal address */
2280 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
2281 + NIPQUAD(iph->saddr));
2282 + /* Update the H.225 info so that NAT can mangle the address/port
2283 + even when we have no expected connection! */
2284 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2285 + LOCK_BH(&ip_h323_lock);
2287 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
2288 + info->offset[IP_CT_DIR_ORIGINAL] = i;
2289 + UNLOCK_BH(&ip_h323_lock);
2292 + memset(&expect, 0, sizeof(expect));
2294 + /* update the H.225 info */
2295 + LOCK_BH(&ip_h323_lock);
2296 + info->is_h225 = H225_PORT;
2297 + exp_info->port = data_port;
2298 + exp_info->dir = dir;
2299 + exp_info->offset = i;
2301 + exp->seq = ntohl(tcph->seq) + i;
2303 + exp->tuple = ((struct ip_conntrack_tuple)
2304 + { { ct->tuplehash[!dir].tuple.src.ip,
2307 + { .tcp = { data_port } },
2309 + exp->mask = ((struct ip_conntrack_tuple)
2310 + { { 0xFFFFFFFF, { 0 } },
2311 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2313 + exp->expectfn = h225_expect;
2315 + /* Ignore failure */
2316 + ip_conntrack_expect_related(ct, exp);
2318 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
2319 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2320 + NIPQUAD(iph->saddr), ntohs(data_port));
2322 + UNLOCK_BH(&ip_h323_lock);
2324 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2325 + } else if (data_ip == iph->daddr) {
2326 + data_port = *((u_int16_t *)(data + 4));
2327 + if (data_port == tcph->dest) {
2328 + /* Signal address */
2329 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
2330 + NIPQUAD(iph->daddr));
2331 + /* Update the H.225 info so that NAT can mangle the address/port
2332 + even when we have no expected connection! */
2333 + LOCK_BH(&ip_h323_lock);
2335 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
2336 + info->offset[IP_CT_DIR_REPLY] = i;
2337 + UNLOCK_BH(&ip_h323_lock);
2347 +static struct ip_conntrack_helper h225 =
2349 + "H.225", /* name */
2350 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2351 + THIS_MODULE, /* module */
2352 + 2, /* max_expected */
2353 + 240, /* timeout */
2354 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
2355 + { 0, { 0 }, IPPROTO_TCP } },
2356 + { { 0, { 0xFFFF } }, /* mask */
2357 + { 0, { 0 }, 0xFFFF } },
2358 + h225_help /* helper */
2361 +static int __init init(void)
2363 + return ip_conntrack_helper_register(&h225);
2366 +static void __exit fini(void)
2368 + /* Unregister H.225 helper */
2369 + ip_conntrack_helper_unregister(&h225);
2372 +EXPORT_SYMBOL(ip_h323_lock);
2376 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
2377 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
2378 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-03-30 11:51:24.000000000 +0200
2380 +/* MMS extension for IP connection tracking
2381 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2382 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
2384 + * ip_conntrack_mms.c v0.3 2002-09-22
2386 + * This program is free software; you can redistribute it and/or
2387 + * modify it under the terms of the GNU General Public License
2388 + * as published by the Free Software Foundation; either version
2389 + * 2 of the License, or (at your option) any later version.
2391 + * Module load syntax:
2392 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
2394 + * Please give the ports of all MMS servers You wish to connect to.
2395 + * If you don't specify ports, the default will be TCP port 1755.
2397 + * More info on MMS protocol, firewalls and NAT:
2398 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
2399 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
2401 + * The SDP project people are reverse-engineering MMS:
2402 + * http://get.to/sdp
2405 +#include <linux/config.h>
2406 +#include <linux/module.h>
2407 +#include <linux/netfilter.h>
2408 +#include <linux/ip.h>
2409 +#include <linux/ctype.h>
2410 +#include <net/checksum.h>
2411 +#include <net/tcp.h>
2413 +#include <linux/netfilter_ipv4/lockhelp.h>
2414 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2415 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
2417 +DECLARE_LOCK(ip_mms_lock);
2418 +struct module *ip_conntrack_mms = THIS_MODULE;
2420 +#define MAX_PORTS 8
2421 +static int ports[MAX_PORTS];
2422 +static int ports_c;
2424 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2428 +#define DEBUGP printk
2430 +#define DEBUGP(format, args...)
2433 +EXPORT_SYMBOL(ip_mms_lock);
2435 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2436 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
2437 +MODULE_LICENSE("GPL");
2439 +/* #define isdigit(c) (c >= '0' && c <= '9') */
2441 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
2442 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
2445 + for (i = 0; i < unicode_size; ++i) {
2446 + string[i] = (char)(unicode[i]);
2448 + string[unicode_size] = 0x00;
2451 +__inline static int atoi(char *s)
2454 + while (isdigit(*s)) {
2455 + i = i*10 + *(s++) - '0';
2460 +/* convert ip address string like "192.168.0.10" to unsigned int */
2461 +__inline static u_int32_t asciiiptoi(char *s)
2463 + unsigned int i, j, k;
2465 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
2467 + for(j=0; (*(++s) != '.') && (j<3); ++j)
2474 +int parse_mms(const char *data,
2475 + const unsigned int datalen,
2476 + u_int32_t *mms_ip,
2477 + u_int16_t *mms_proto,
2478 + u_int16_t *mms_port,
2479 + char **mms_string_b,
2480 + char **mms_string_e,
2481 + char **mms_padding_e)
2483 + int unicode_size, i;
2484 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
2485 + char getlengthstring[28];
2487 + for(unicode_size=0;
2488 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2490 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
2491 + return -1; /* out of bounds - incomplete packet */
2493 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2494 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2496 + /* IP address ? */
2497 + *mms_ip = asciiiptoi(tempstring+2);
2499 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2502 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
2503 + *mms_proto = IPPROTO_TCP;
2504 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2505 + *mms_proto = IPPROTO_UDP;
2508 + *mms_port = atoi(tempstring+7+i);
2510 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
2511 + unicode string, one to the end of the string, and one to the end
2512 + of the packet, since we must keep track of the number of bytes
2513 + between end of the unicode string and the end of packet (padding) */
2514 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2515 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2516 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2521 +/* FIXME: This should be in userspace. Later. */
2522 +static int help(const struct iphdr *iph, size_t len,
2523 + struct ip_conntrack *ct,
2524 + enum ip_conntrack_info ctinfo)
2526 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2527 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2528 + const char *data = (const char *)tcph + tcph->doff * 4;
2529 + unsigned int tcplen = len - iph->ihl * 4;
2530 + unsigned int datalen = tcplen - tcph->doff * 4;
2531 + int dir = CTINFO2DIR(ctinfo);
2532 + struct ip_conntrack_expect expect, *exp = &expect;
2533 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2536 + u_int16_t mms_proto;
2537 + char mms_proto_string[8];
2538 + u_int16_t mms_port;
2539 + char *mms_string_b, *mms_string_e, *mms_padding_e;
2541 + /* Until there's been traffic both ways, don't look in packets. */
2542 + if (ctinfo != IP_CT_ESTABLISHED
2543 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2544 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2548 + /* Not whole TCP header? */
2549 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2550 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2554 + /* Checksum invalid? Ignore. */
2555 + /* FIXME: Source route IP option packets --RR */
2556 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2557 + csum_partial((char *)tcph, tcplen, 0))) {
2558 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2559 + tcph, tcplen, NIPQUAD(iph->saddr),
2560 + NIPQUAD(iph->daddr));
2564 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2565 + /* FIXME: There is an issue with only looking at this packet: before this packet,
2566 + the client has already sent a packet to the server with the server's hostname
2567 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
2568 + server will break the connection if this doesn't correspond to its own host
2569 + header. The client can also connect to an IP address; if it's the server's IP
2570 + address, it will not break the connection. When doing DNAT on a connection
2571 + where the client uses a server's IP address, the nat module should detect
2572 + this and change this string accordingly to the DNATed address. This should
2573 + probably be done by checking for an IP address, then storing it as a member
2574 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2576 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
2577 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2578 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
2579 + (u8)*(data+36), (u8)*(data+37),
2580 + (u8)*(data+38), (u8)*(data+39),
2582 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2583 + &mms_string_b, &mms_string_e, &mms_padding_e))
2584 + if(net_ratelimit())
2585 + /* FIXME: more verbose debugging ? */
2586 + printk(KERN_WARNING
2587 + "ip_conntrack_mms: Unable to parse data payload\n");
2589 + memset(&expect, 0, sizeof(expect));
2591 + sprintf(mms_proto_string, "(%u)", mms_proto);
2592 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2593 + mms_proto == IPPROTO_TCP ? "TCP"
2594 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2595 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2599 + /* it's possible that the client will just ask the server to tunnel
2600 + the stream over the same TCP session (from port 1755): there's
2601 + shouldn't be a need to add an expectation in that case, but it
2602 + makes NAT packet mangling so much easier */
2603 + LOCK_BH(&ip_mms_lock);
2605 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2607 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2608 + exp_mms_info->len = (mms_string_e - mms_string_b);
2609 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
2610 + exp_mms_info->port = mms_port;
2612 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2613 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2615 + exp->tuple = ((struct ip_conntrack_tuple)
2616 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2618 + { .tcp = { (__u16) ntohs(mms_port) } },
2621 + exp->mask = ((struct ip_conntrack_tuple)
2622 + { { 0xFFFFFFFF, { 0 } },
2623 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2624 + exp->expectfn = NULL;
2625 + ip_conntrack_expect_related(ct, &expect);
2626 + UNLOCK_BH(&ip_mms_lock);
2632 +static struct ip_conntrack_helper mms[MAX_PORTS];
2633 +static char mms_names[MAX_PORTS][10];
2635 +/* Not __exit: called from init() */
2636 +static void fini(void)
2639 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2640 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2642 + ip_conntrack_helper_unregister(&mms[i]);
2646 +static int __init init(void)
2651 + if (ports[0] == 0)
2652 + ports[0] = MMS_PORT;
2654 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2655 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2656 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2657 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
2658 + mms[i].mask.src.u.tcp.port = 0xFFFF;
2659 + mms[i].mask.dst.protonum = 0xFFFF;
2660 + mms[i].max_expected = 1;
2661 + mms[i].timeout = 0;
2662 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2663 + mms[i].me = THIS_MODULE;
2664 + mms[i].help = help;
2666 + tmpname = &mms_names[i][0];
2667 + if (ports[i] == MMS_PORT)
2668 + sprintf(tmpname, "mms");
2670 + sprintf(tmpname, "mms-%d", ports[i]);
2671 + mms[i].name = tmpname;
2673 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
2675 + ret = ip_conntrack_helper_register(&mms[i]);
2688 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
2689 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
2690 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-03-30 11:51:52.000000000 +0200
2692 +/* Quake3 extension for IP connection tracking
2693 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2694 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
2696 + * ip_conntrack_quake3.c v0.04 2002-08-31
2698 + * This program is free software; you can redistribute it and/or
2699 + * modify it under the terms of the GNU General Public License
2700 + * as published by the Free Software Foundation; either version
2701 + * 2 of the License, or (at your option) any later version.
2703 + * Module load syntax:
2704 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
2706 + * please give the ports of all Quake3 master servers You wish to
2707 + * connect to. If you don't specify ports, the default will be UDP
2710 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
2713 +#include <linux/module.h>
2714 +#include <linux/ip.h>
2715 +#include <linux/udp.h>
2717 +#include <linux/netfilter.h>
2718 +#include <linux/netfilter_ipv4/ip_tables.h>
2719 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2720 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
2722 +struct module *ip_conntrack_quake3 = THIS_MODULE;
2724 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2725 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
2726 +MODULE_LICENSE("GPL");
2728 +#define MAX_PORTS 8
2729 +static int ports[MAX_PORTS];
2730 +static int ports_c = 0;
2732 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2733 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
2736 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
2737 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
2739 +#define DEBUGP printk
2741 +#define DEBUGP(format, args...)
2744 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
2746 +static int quake3_help(const struct iphdr *iph, size_t len,
2747 + struct ip_conntrack *ct,
2748 + enum ip_conntrack_info ctinfo)
2750 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
2751 + int dir = CTINFO2DIR(ctinfo);
2752 + struct ip_conntrack_expect exp;
2755 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
2756 + if (ctinfo != IP_CT_ESTABLISHED
2757 + && ctinfo != IP_CT_IS_REPLY) {
2758 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
2760 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
2762 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
2763 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
2764 + i+6 < ntohs(udph->len);
2766 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
2767 + i, ntohs(udph->len),
2768 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
2769 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
2771 + memset(&exp, 0, sizeof(exp));
2773 + exp.tuple = ((struct ip_conntrack_tuple)
2774 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2775 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
2776 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
2779 + exp.mask = ((struct ip_conntrack_tuple)
2780 + { { 0xFFFFFFFF, { 0 } },
2781 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
2782 + exp.expectfn = NULL;
2784 + ip_conntrack_expect_related(ct, &exp);
2789 + return(NF_ACCEPT);
2792 +static struct ip_conntrack_helper quake3[MAX_PORTS];
2793 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
2795 +static void fini(void)
2799 + for(i = 0 ; (i < ports_c); i++) {
2800 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
2802 + ip_conntrack_helper_unregister(&quake3[i]);
2806 +static int __init init(void)
2812 + ports[0]=QUAKE3_MASTER_PORT;
2814 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
2815 + /* Create helper structure */
2816 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
2818 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
2819 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
2820 + quake3[i].mask.dst.protonum = 0xFFFF;
2821 + quake3[i].mask.src.u.udp.port = 0xFFFF;
2822 + quake3[i].help = quake3_help;
2823 + quake3[i].me = THIS_MODULE;
2825 + tmpname = &quake3_names[i][0];
2826 + if (ports[i] == QUAKE3_MASTER_PORT)
2827 + sprintf(tmpname, "quake3");
2829 + sprintf(tmpname, "quake3-%d", i);
2830 + quake3[i].name = tmpname;
2832 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
2835 + ret=ip_conntrack_helper_register(&quake3[i]);
2848 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
2849 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
2850 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2004-03-30 11:51:55.000000000 +0200
2852 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
2853 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2854 + * - original rpc tracking module
2855 + * - "recent" connection handling for kernel 2.3+ netfilter
2857 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2858 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2860 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2861 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
2862 + * - extended matching to support filtering on procedures
2864 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
2866 + * This program is free software; you can redistribute it and/or
2867 + * modify it under the terms of the GNU General Public License
2868 + * as published by the Free Software Foundation; either version
2869 + * 2 of the License, or (at your option) any later version.
2871 + * Module load syntax:
2872 + * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
2874 + * Please give the ports of all RPC servers you wish to connect to.
2875 + * If you don't specify ports, the default will be port 111.
2879 + * RPCs should not be exposed to the internet - ask the Pentagon;
2881 + * "The unidentified crackers pleaded guilty in July to charges
2882 + * of juvenile delinquency stemming from a string of Pentagon
2883 + * network intrusions in February.
2885 + * The youths, going by the names TooShort and Makaveli, used
2886 + * a common server security hole to break in, according to
2887 + * Dane Jasper, owner of the California Internet service
2888 + * provider, Sonic. They used the hole, known as the 'statd'
2889 + * exploit, to attempt more than 800 break-ins, Jasper said."
2891 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
2892 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
2896 +#include <linux/module.h>
2897 +#include <linux/netfilter.h>
2898 +#include <linux/ip.h>
2899 +#include <net/checksum.h>
2900 +#include <net/tcp.h>
2902 +#include <asm/param.h>
2903 +#include <linux/sched.h>
2904 +#include <linux/timer.h>
2905 +#include <linux/stddef.h>
2906 +#include <linux/list.h>
2908 +#include <linux/netfilter_ipv4/lockhelp.h>
2909 +#include <linux/netfilter_ipv4/ip_tables.h>
2910 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2911 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
2913 +#define MAX_PORTS 8
2914 +static int ports[MAX_PORTS];
2915 +static int ports_n_c = 0;
2918 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2919 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
2922 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
2923 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
2924 +MODULE_LICENSE("GPL");
2927 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
2930 +#define DEBUGP(format, args...)
2933 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
2934 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
2935 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
2936 +#include <linux/netfilter_ipv4/listhelp.h>
2938 +/* For future conections RPC, using client's cache bindings
2939 + * I'll use ip_conntrack_lock to lock these lists */
2941 +LIST_HEAD(request_p_list_tcp);
2944 +static void delete_request_p(unsigned long request_p_ul)
2946 + struct request_p *p = (void *)request_p_ul;
2948 + WRITE_LOCK(&ipct_rpc_tcp_lock);
2949 + LIST_DELETE(&request_p_list_tcp, p);
2950 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
2956 +static void req_cl(struct request_p * r)
2958 + WRITE_LOCK(&ipct_rpc_tcp_lock);
2959 + del_timer(&r->timeout);
2960 + LIST_DELETE(&request_p_list_tcp, r);
2961 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
2967 +static void clean_request(struct list_head *list)
2969 + struct list_head *first = list->prev;
2970 + struct list_head *temp = list->next;
2971 + struct list_head *aux;
2973 + if (list_empty(list))
2976 + while (first != temp) {
2978 + req_cl((struct request_p *)temp);
2981 + req_cl((struct request_p *)temp);
2986 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
2989 + struct request_p *req_p;
2991 + /* Verifies if entry already exists */
2992 + WRITE_LOCK(&ipct_rpc_tcp_lock);
2993 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
2994 + struct request_p *, xid, ip, port);
2997 + /* Refresh timeout */
2998 + if (del_timer(&req_p->timeout)) {
2999 + req_p->timeout.expires = jiffies + EXP;
3000 + add_timer(&req_p->timeout);
3002 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3006 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3008 + /* Allocate new request_p */
3009 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3011 + DEBUGP("can't allocate request_p\n");
3014 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3015 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3018 + /* Initialize timer */
3019 + init_timer(&req_p->timeout);
3020 + req_p->timeout.function = delete_request_p;
3021 + add_timer(&req_p->timeout);
3024 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3025 + list_prepend(&request_p_list_tcp, req_p);
3026 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3032 +static int check_rpc_packet(const u_int32_t *data,
3033 + int dir, struct ip_conntrack *ct,
3034 + struct list_head request_p_list)
3036 + struct request_p *req_p;
3038 + struct ip_conntrack_expect expect, *exp = &expect;
3040 + /* Translstion's buffer for XDR */
3041 + u_int16_t port_buf;
3047 + /* This does sanity checking on RPC payloads,
3048 + * and permits only the RPC "get port" (3)
3049 + * in authorised procedures in client
3050 + * communications with the portmapper.
3053 + /* perform direction dependant RPC work */
3054 + if (dir == IP_CT_DIR_ORIGINAL) {
3058 + /* Get RPC requestor */
3059 + if (IXDR_GET_INT32(data) != 3) {
3060 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3063 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3067 + /* Jump Credentials and Verfifier */
3068 + data += IXDR_GET_INT32(data) + 2;
3069 + data += IXDR_GET_INT32(data) + 2;
3071 + /* Get RPC procedure */
3072 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3073 + (unsigned int)IXDR_GET_INT32(data));
3075 + /* Get RPC protocol and store against client parameters */
3077 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3078 + ct->tuplehash[dir].tuple.src.u.all);
3080 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3081 + xid, IXDR_GET_INT32(data),
3082 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3083 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
3085 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
3086 + (unsigned int)IXDR_GET_INT32(data));
3090 + /* Check for returning packet's stored counterpart */
3091 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3092 + struct request_p *, xid,
3093 + ct->tuplehash[!dir].tuple.src.ip,
3094 + ct->tuplehash[!dir].tuple.src.u.all);
3096 + /* Drop unexpected packets */
3098 + DEBUGP("packet is not expected. [skip]\n");
3102 + /* Verifies if packet is really an RPC reply packet */
3104 + if (IXDR_GET_INT32(data) != 1) {
3105 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
3109 + /* Is status accept? */
3111 + if (IXDR_GET_INT32(data)) {
3112 + DEBUGP("packet is not an RPC accept. [skip]\n");
3116 + /* Get Verifier length. Jump verifier */
3118 + data = data + IXDR_GET_INT32(data) + 2;
3120 + /* Is accpet status "success"? */
3121 + if (IXDR_GET_INT32(data)) {
3122 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3126 + /* Get server port number */
3128 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
3130 + /* If a packet has made it this far then it deserves an
3131 + * expectation ... if port == 0, then this service is
3132 + * not going to be registered.
3135 + DEBUGP("port found: %u\n", port_buf);
3137 + memset(&expect, 0, sizeof(expect));
3139 + /* Watch out, Radioactive-Man! */
3140 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3141 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3142 + exp->mask.src.ip = 0xffffffff;
3143 + exp->mask.dst.ip = 0xffffffff;
3145 + switch (req_p->proto) {
3147 + exp->tuple.src.u.udp.port = 0;
3148 + exp->tuple.dst.u.udp.port = htons(port_buf);
3149 + exp->tuple.dst.protonum = IPPROTO_UDP;
3150 + exp->mask.src.u.udp.port = 0;
3151 + exp->mask.dst.u.udp.port = htons(0xffff);
3152 + exp->mask.dst.protonum = 0xffff;
3156 + exp->tuple.src.u.tcp.port = 0;
3157 + exp->tuple.dst.u.tcp.port = htons(port_buf);
3158 + exp->tuple.dst.protonum = IPPROTO_TCP;
3159 + exp->mask.src.u.tcp.port = 0;
3160 + exp->mask.dst.u.tcp.port = htons(0xffff);
3161 + exp->mask.dst.protonum = 0xffff;
3164 + exp->expectfn = NULL;
3166 + ip_conntrack_expect_related(ct, &expect);
3168 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3169 + NIPQUAD(exp->tuple.src.ip),
3170 + NIPQUAD(exp->tuple.dst.ip),
3171 + port_buf, req_p->proto);
3173 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3174 + NIPQUAD(exp->mask.src.ip),
3175 + NIPQUAD(exp->mask.dst.ip),
3176 + exp->mask.dst.protonum);
3182 + DEBUGP("packet evaluated. [expect]\n");
3191 +/* RPC TCP helper */
3192 +static int help(const struct iphdr *iph, size_t len,
3193 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3195 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3196 + const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3197 + size_t tcplen = len - iph->ihl * 4;
3199 + int dir = CTINFO2DIR(ctinfo);
3203 + DEBUGP("new packet to evaluate ..\n");
3205 + /* This works for packets like handshake packets, ignore */
3206 + if (len == ((tcph->doff + iph->ihl) * 4)) {
3207 + DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3211 + /* Until there's been traffic both ways, don't look in packets. */
3212 + if (ctinfo != IP_CT_ESTABLISHED
3213 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3214 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3215 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3216 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3220 + /* Not whole TCP header? */
3221 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3222 + DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3223 + DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3227 + /* FIXME: Source route IP option packets --RR */
3228 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3229 + csum_partial((char *) tcph, tcplen, 0))) {
3230 + DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3231 + tcph, tcplen, NIPQUAD(iph->saddr),
3232 + NIPQUAD(iph->daddr));
3233 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3234 + DEBUGP("packet contains a bad checksum. [skip]\n");
3238 + /* perform direction dependant protocol work */
3239 + if (dir == IP_CT_DIR_ORIGINAL) {
3241 + DEBUGP("packet is from the initiator. [cont]\n");
3243 + /* Tests if packet len is ok */
3244 + if ((tcplen - (tcph->doff * 4)) != 60) {
3245 + DEBUGP("packet length is not correct. [skip]\n");
3251 + DEBUGP("packet is from the receiver. [cont]\n");
3253 + /* Tests if packet len is ok */
3254 + if ((tcplen - (tcph->doff * 4)) != 32) {
3255 + DEBUGP("packet length is not correct. [skip]\n");
3260 + /* Get to the data */
3263 + /* Check the RPC data */
3264 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
3271 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3273 +static void fini(void);
3276 +static int __init init(void)
3279 + static char name[10];
3282 + /* If no port given, default to standard RPC port */
3283 + if (ports[0] == 0)
3284 + ports[0] = RPC_PORT;
3286 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3287 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3289 + if (ports[port] == RPC_PORT)
3290 + sprintf(name, "rpc");
3292 + sprintf(name, "rpc-%d", port);
3294 + rpc_helpers[port].name = name;
3295 + rpc_helpers[port].me = THIS_MODULE;
3296 + rpc_helpers[port].max_expected = 1;
3297 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3298 + rpc_helpers[port].timeout = 0;
3300 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
3301 + rpc_helpers[port].mask.dst.protonum = 0xffff;
3303 + /* RPC can come from ports 0:65535 to ports[port] (111) */
3304 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3305 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3306 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3308 + rpc_helpers[port].help = help;
3310 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
3311 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3312 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3313 + ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
3314 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
3315 + ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
3316 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3317 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
3318 + ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
3319 + NIPQUAD(rpc_helpers[port].mask.src.ip),
3320 + ntohs(rpc_helpers[port].mask.src.u.tcp.port));
3322 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3325 + printk("ERROR registering port %d\n",
3336 +/* This function is intentionally _NOT_ defined as __exit, because
3337 + * it is needed by the init function */
3338 +static void fini(void)
3342 + DEBUGP("cleaning request list\n");
3343 + clean_request(&request_p_list_tcp);
3345 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3346 + DEBUGP("unregistering port %d\n", ports[port]);
3347 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
3355 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
3356 +EXPORT_SYMBOL(request_p_list_tcp);
3357 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
3358 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
3360 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
3361 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
3362 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2004-03-30 11:51:55.000000000 +0200
3364 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
3365 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3366 + * - original rpc tracking module
3367 + * - "recent" connection handling for kernel 2.3+ netfilter
3369 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3370 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3372 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3373 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
3374 + * - extended matching to support filtering on procedures
3376 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
3378 + * This program is free software; you can redistribute it and/or
3379 + * modify it under the terms of the GNU General Public License
3380 + * as published by the Free Software Foundation; either version
3381 + * 2 of the License, or (at your option) any later version.
3383 + * Module load syntax:
3384 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
3386 + * Please give the ports of all RPC servers you wish to connect to.
3387 + * If you don't specify ports, the default will be port 111.
3391 + * RPCs should not be exposed to the internet - ask the Pentagon;
3393 + * "The unidentified crackers pleaded guilty in July to charges
3394 + * of juvenile delinquency stemming from a string of Pentagon
3395 + * network intrusions in February.
3397 + * The youths, going by the names TooShort and Makaveli, used
3398 + * a common server security hole to break in, according to
3399 + * Dane Jasper, owner of the California Internet service
3400 + * provider, Sonic. They used the hole, known as the 'statd'
3401 + * exploit, to attempt more than 800 break-ins, Jasper said."
3403 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3404 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
3408 +#include <linux/module.h>
3409 +#include <linux/netfilter.h>
3410 +#include <linux/ip.h>
3411 +#include <net/checksum.h>
3412 +#include <net/udp.h>
3414 +#include <asm/param.h>
3415 +#include <linux/sched.h>
3416 +#include <linux/timer.h>
3417 +#include <linux/stddef.h>
3418 +#include <linux/list.h>
3420 +#include <linux/netfilter_ipv4/lockhelp.h>
3421 +#include <linux/netfilter_ipv4/ip_tables.h>
3422 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3423 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3425 +#define MAX_PORTS 8
3426 +static int ports[MAX_PORTS];
3427 +static int ports_n_c = 0;
3430 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3431 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3434 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3435 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
3436 +MODULE_LICENSE("GPL");
3439 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
3442 +#define DEBUGP(format, args...)
3445 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
3446 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
3447 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
3448 +#include <linux/netfilter_ipv4/listhelp.h>
3450 +/* For future conections RPC, using client's cache bindings
3451 + * I'll use ip_conntrack_lock to lock these lists */
3453 +LIST_HEAD(request_p_list_udp);
3456 +static void delete_request_p(unsigned long request_p_ul)
3458 + struct request_p *p = (void *)request_p_ul;
3460 + WRITE_LOCK(&ipct_rpc_udp_lock);
3461 + LIST_DELETE(&request_p_list_udp, p);
3462 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3468 +static void req_cl(struct request_p * r)
3470 + WRITE_LOCK(&ipct_rpc_udp_lock);
3471 + del_timer(&r->timeout);
3472 + LIST_DELETE(&request_p_list_udp, r);
3473 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3479 +static void clean_request(struct list_head *list)
3481 + struct list_head *first = list->prev;
3482 + struct list_head *temp = list->next;
3483 + struct list_head *aux;
3485 + if (list_empty(list))
3488 + while (first != temp) {
3490 + req_cl((struct request_p *)temp);
3493 + req_cl((struct request_p *)temp);
3498 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3501 + struct request_p *req_p;
3503 + /* Verifies if entry already exists */
3504 + WRITE_LOCK(&ipct_rpc_udp_lock);
3505 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3506 + struct request_p *, xid, ip, port);
3509 + /* Refresh timeout */
3510 + if (del_timer(&req_p->timeout)) {
3511 + req_p->timeout.expires = jiffies + EXP;
3512 + add_timer(&req_p->timeout);
3514 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3518 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3520 + /* Allocate new request_p */
3521 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3523 + DEBUGP("can't allocate request_p\n");
3526 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3527 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3530 + /* Initialize timer */
3531 + init_timer(&req_p->timeout);
3532 + req_p->timeout.function = delete_request_p;
3533 + add_timer(&req_p->timeout);
3536 + WRITE_LOCK(&ipct_rpc_udp_lock);
3537 + list_prepend(&request_p_list_udp, req_p);
3538 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3544 +static int check_rpc_packet(const u_int32_t *data,
3545 + int dir, struct ip_conntrack *ct,
3546 + struct list_head request_p_list)
3548 + struct request_p *req_p;
3550 + struct ip_conntrack_expect expect, *exp = &expect;
3552 + /* Translstion's buffer for XDR */
3553 + u_int16_t port_buf;
3559 + /* This does sanity checking on RPC payloads,
3560 + * and permits only the RPC "get port" (3)
3561 + * in authorised procedures in client
3562 + * communications with the portmapper.
3565 + /* perform direction dependant RPC work */
3566 + if (dir == IP_CT_DIR_ORIGINAL) {
3570 + /* Get RPC requestor */
3571 + if (IXDR_GET_INT32(data) != 3) {
3572 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3575 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3579 + /* Jump Credentials and Verfifier */
3580 + data = data + IXDR_GET_INT32(data) + 2;
3581 + data = data + IXDR_GET_INT32(data) + 2;
3583 + /* Get RPC procedure */
3584 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3585 + (unsigned int)IXDR_GET_INT32(data));
3587 + /* Get RPC protocol and store against client parameters */
3589 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3590 + ct->tuplehash[dir].tuple.src.u.all);
3592 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3593 + xid, IXDR_GET_INT32(data),
3594 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3595 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
3597 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
3598 + (unsigned int)IXDR_GET_INT32(data));
3602 + /* Check for returning packet's stored counterpart */
3603 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3604 + struct request_p *, xid,
3605 + ct->tuplehash[!dir].tuple.src.ip,
3606 + ct->tuplehash[!dir].tuple.src.u.all);
3608 + /* Drop unexpected packets */
3610 + DEBUGP("packet is not expected. [skip]\n");
3614 + /* Verifies if packet is really an RPC reply packet */
3616 + if (IXDR_GET_INT32(data) != 1) {
3617 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
3621 + /* Is status accept? */
3623 + if (IXDR_GET_INT32(data)) {
3624 + DEBUGP("packet is not an RPC accept. [skip]\n");
3628 + /* Get Verifier length. Jump verifier */
3630 + data = data + IXDR_GET_INT32(data) + 2;
3632 + /* Is accpet status "success"? */
3633 + if (IXDR_GET_INT32(data)) {
3634 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3638 + /* Get server port number */
3640 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
3642 + /* If a packet has made it this far then it deserves an
3643 + * expectation ... if port == 0, then this service is
3644 + * not going to be registered.
3647 + DEBUGP("port found: %u\n", port_buf);
3649 + memset(&expect, 0, sizeof(expect));
3651 + /* Watch out, Radioactive-Man! */
3652 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3653 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3654 + exp->mask.src.ip = 0xffffffff;
3655 + exp->mask.dst.ip = 0xffffffff;
3657 + switch (req_p->proto) {
3659 + exp->tuple.src.u.udp.port = 0;
3660 + exp->tuple.dst.u.udp.port = htons(port_buf);
3661 + exp->tuple.dst.protonum = IPPROTO_UDP;
3662 + exp->mask.src.u.udp.port = 0;
3663 + exp->mask.dst.u.udp.port = htons(0xffff);
3664 + exp->mask.dst.protonum = 0xffff;
3668 + exp->tuple.src.u.tcp.port = 0;
3669 + exp->tuple.dst.u.tcp.port = htons(port_buf);
3670 + exp->tuple.dst.protonum = IPPROTO_TCP;
3671 + exp->mask.src.u.tcp.port = 0;
3672 + exp->mask.dst.u.tcp.port = htons(0xffff);
3673 + exp->mask.dst.protonum = 0xffff;
3676 + exp->expectfn = NULL;
3678 + ip_conntrack_expect_related(ct, &expect);
3680 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3681 + NIPQUAD(exp->tuple.src.ip),
3682 + NIPQUAD(exp->tuple.dst.ip),
3683 + port_buf, req_p->proto);
3685 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3686 + NIPQUAD(exp->mask.src.ip),
3687 + NIPQUAD(exp->mask.dst.ip),
3688 + exp->mask.dst.protonum);
3694 + DEBUGP("packet evaluated. [expect]\n");
3703 +/* RPC UDP helper */
3704 +static int help(const struct iphdr *iph, size_t len,
3705 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3707 + struct udphdr *udph = (void *) iph + iph->ihl * 4;
3708 + const u_int32_t *data = (const u_int32_t *)udph + 2;
3709 + size_t udplen = len - iph->ihl * 4;
3710 + int dir = CTINFO2DIR(ctinfo);
3714 + const u_int16_t *chsm = (const u_int16_t *)udph + 3;
3717 + DEBUGP("new packet to evaluate ..\n");
3719 + /* Not whole UDP header? */
3720 + if (udplen < sizeof(struct udphdr)) {
3721 + DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
3722 + DEBUGP("packet does not contain a complete UDP header. [skip]\n");
3726 + /* FIXME: Source route IP option packets --RR */
3728 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
3729 + csum_partial((char *)udph, udplen, 0))) {
3730 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3731 + DEBUGP("packet contains a bad checksum. [skip]\n");
3736 + /* perform direction dependant protocol work */
3737 + if (dir == IP_CT_DIR_ORIGINAL) {
3739 + DEBUGP("packet is from the initiator. [cont]\n");
3741 + /* Tests if packet len is ok */
3742 + if ((udplen - sizeof(struct udphdr)) != 56) {
3743 + DEBUGP("packet length is not correct. [skip]\n");
3749 + DEBUGP("packet is from the receiver. [cont]\n");
3751 + /* Until there's been traffic both ways, don't look in packets. */
3752 + if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3753 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3754 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3755 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3759 + /* Tests if packet len is ok */
3760 + if ((udplen - sizeof(struct udphdr)) != 28) {
3761 + DEBUGP("packet length is not correct. [skip]\n");
3767 + /* Get to the data */
3768 + /* udp *data == *correct */
3770 + /* Check the RPC data */
3771 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
3778 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3780 +static void fini(void);
3783 +static int __init init(void)
3786 + static char name[10];
3789 + /* If no port given, default to standard RPC port */
3790 + if (ports[0] == 0)
3791 + ports[0] = RPC_PORT;
3793 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3794 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3796 + if (ports[port] == RPC_PORT)
3797 + sprintf(name, "rpc");
3799 + sprintf(name, "rpc-%d", port);
3801 + rpc_helpers[port].name = name;
3802 + rpc_helpers[port].me = THIS_MODULE;
3803 + rpc_helpers[port].max_expected = 1;
3804 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3805 + rpc_helpers[port].timeout = 0;
3807 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
3808 + rpc_helpers[port].mask.dst.protonum = 0xffff;
3810 + /* RPC can come from ports 0:65535 to ports[port] (111) */
3811 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3812 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3813 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3815 + rpc_helpers[port].help = help;
3817 + DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
3818 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3819 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3820 + ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
3821 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
3822 + ntohs(rpc_helpers[port].tuple.src.u.udp.port));
3823 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3824 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
3825 + ntohs(rpc_helpers[port].mask.dst.u.udp.port),
3826 + NIPQUAD(rpc_helpers[port].mask.src.ip),
3827 + ntohs(rpc_helpers[port].mask.src.u.udp.port));
3829 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3832 + printk("ERROR registering port %d\n",
3843 +/* This function is intentionally _NOT_ defined as __exit, because
3844 + * it is needed by the init function */
3845 +static void fini(void)
3849 + DEBUGP("cleaning request list\n");
3850 + clean_request(&request_p_list_udp);
3852 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3853 + DEBUGP("unregistering port %d\n", ports[port]);
3854 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
3862 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
3863 +EXPORT_SYMBOL(request_p_list_udp);
3864 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
3865 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
3867 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
3868 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
3869 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-03-30 11:51:56.000000000 +0200
3871 +/* RSH extension for IP connection tracking, Version 1.0
3872 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3873 + * based on HW's ip_conntrack_irc.c
3875 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
3877 + * This program is free software; you can redistribute it and/or
3878 + * modify it under the terms of the GNU General Public License
3879 + * as published by the Free Software Foundation; either version
3880 + * 2 of the License, or (at your option) any later version.
3882 + * Module load syntax:
3883 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
3885 + * please give the ports of all RSH servers You wish to connect to.
3886 + * If You don't specify ports, the default will be port 514
3889 + * RSH blows ... you should use SSH (openssh.org) to replace it,
3890 + * unfortunately I babysit some sysadmins that won't migrate
3891 + * their legacy crap, in our second tier.
3896 + * Some docco ripped from the net to teach me all there is to know about
3897 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
3900 + * I have no idea what "unix rshd man pages" these guys have .. but that
3901 + * is some pretty detailed docco!
3904 + * 4. Of the rsh protocol.
3905 + * -----------------------
3907 + * The rshd listens on TCP port #514. The following info is from the unix
3908 + * rshd man pages :
3910 + * "Service Request Protocol
3912 + * When the rshd daemon receives a service request, it initiates the
3913 + * following protocol:
3915 + * 1. The rshd daemon checks the source port number for the request.
3916 + * If the port number is not in the range 0 through 1023, the rshd daemon
3917 + * terminates the connection.
3919 + * 2. The rshd daemon reads characters from the socket up to a null byte.
3920 + * The string read is interpreted as an ASCII number (base 10). If this
3921 + * number is nonzero, the rshd daemon interprets it as the port number
3922 + * of a secondary stream to be used as standard error. A second connection
3923 + * is created to the specified port on the client host. The source port
3924 + * on the local host is in the range 0 through 1023.
3926 + * 3. The rshd daemon uses the source address of the initial connection
3927 + * request to determine the name of the client host. If the name cannot
3928 + * be determined, the rshd daemon uses the dotted decimal representation
3929 + * of the client host's address.
3931 + * 4. The rshd daemon retrieves the following information from the initial
3934 + * * A null-terminated string of at most 16 bytes interpreted as
3935 + * the user name of the user on the client host.
3937 + * * A null-terminated string of at most 16 bytes interpreted as
3938 + * the user name to be used on the local server host.
3940 + * * Another null-terminated string interpreted as a command line
3941 + * to be passed to a shell on the local server host.
3943 + * 5. The rshd daemon attempts to validate the user using the following steps:
3945 + * a. The rshd daemon looks up the local user name in the /etc/passwd
3946 + * file and tries to switch to the home directory (using the chdir
3947 + * subroutine). If either the lookup or the directory change fails,
3948 + * the rshd daemon terminates the connection.
3950 + * b. If the local user ID is a nonzero value, the rshd daemon searches
3951 + * the /etc/hosts.equiv file to see if the name of the client
3952 + * workstation is listed. If the client workstation is listed as an
3953 + * equivalent host, the rshd daemon validates the user.
3955 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
3956 + * authenticate the user by checking the .rhosts file.
3958 + * d. If either the $HOME/.rhosts authentication fails or the
3959 + * client host is not an equivalent host, the rshd daemon
3960 + * terminates the connection.
3962 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
3963 + * on the initial connection and passes the command line to the user's
3964 + * local login shell. The shell then inherits the network connections
3965 + * established by the rshd daemon."
3970 +#include <linux/module.h>
3971 +#include <linux/netfilter.h>
3972 +#include <linux/ip.h>
3973 +#include <net/checksum.h>
3974 +#include <net/tcp.h>
3976 +#include <linux/netfilter_ipv4/lockhelp.h>
3977 +#include <linux/netfilter_ipv4/ip_tables.h>
3978 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3979 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
3981 +#define MAX_PORTS 8
3982 +static int ports[MAX_PORTS];
3983 +static int ports_n_c = 0;
3985 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
3986 +MODULE_DESCRIPTION("RSH connection tracking module");
3987 +MODULE_LICENSE("GPL");
3989 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3990 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
3993 +DECLARE_LOCK(ip_rsh_lock);
3994 +struct module *ip_conntrack_rsh = THIS_MODULE;
3997 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4000 +#define DEBUGP(format, args...)
4005 +/* FIXME: This should be in userspace. Later. */
4006 +static int help(const struct iphdr *iph, size_t len,
4007 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4009 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4010 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4011 + const char *data = (const char *) tcph + tcph->doff * 4;
4012 + u_int32_t tcplen = len - iph->ihl * 4;
4013 + int dir = CTINFO2DIR(ctinfo);
4014 + struct ip_conntrack_expect expect, *exp = &expect;
4015 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4019 + /* note that "maxoctet" is used to maintain sanity (8 was the
4020 + * original array size used in rshd/glibc) -- is there a
4021 + * vulnerability in rshd.c in the looped port *= 10?
4025 + DEBUGP("entered\n");
4027 + /* bail if packet is not from RSH client */
4028 + if (dir == IP_CT_DIR_REPLY)
4031 + /* Until there's been traffic both ways, don't look in packets. */
4032 + if (ctinfo != IP_CT_ESTABLISHED
4033 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4034 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
4038 + /* Not whole TCP header? */
4039 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4040 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4044 + /* Checksum invalid? Ignore. */
4045 + /* FIXME: Source route IP option packets --RR */
4046 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4047 + csum_partial((char *) tcph, tcplen, 0))) {
4048 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4049 + tcph, tcplen, NIPQUAD(iph->saddr),
4050 + NIPQUAD(iph->daddr));
4054 + /* find the rsh stderr port */
4057 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4062 + if (*data < 48 || *data > 57) {
4063 + DEBUGP("these aren't the packets you're looking for ..\n");
4066 + port = port * 10 + ( *data - 48 );
4069 + /* dont relate sessions that try to expose the client */
4070 + DEBUGP("found port %u\n", port);
4071 + if (port > 1023) {
4072 + DEBUGP("skipping, expected port size is greater than 1023!\n");
4077 + LOCK_BH(&ip_rsh_lock);
4079 + /* new(,related) connection is;
4080 + * reply + dst (uint)port + src port (0:1023)
4082 + memset(&expect, 0, sizeof(expect));
4084 + /* save some discovered data, in case someone ever wants to write
4085 + * a NAT module for this bastard ..
4087 + exp_rsh_info->port = port;
4089 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4092 + /* Watch out, Radioactive-Man! */
4093 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4094 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4095 + exp->tuple.src.u.tcp.port = 0;
4096 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4097 + exp->tuple.dst.protonum = IPPROTO_TCP;
4099 + exp->mask.src.ip = 0xffffffff;
4100 + exp->mask.dst.ip = 0xffffffff;
4102 + exp->mask.src.u.tcp.port = htons(0xfc00);
4103 + exp->mask.dst.u.tcp.port = htons(0xfc00);
4104 + exp->mask.dst.protonum = 0xffff;
4106 + exp->expectfn = NULL;
4108 + ip_conntrack_expect_related(ct, &expect);
4110 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4111 + NIPQUAD(exp->tuple.src.ip),
4112 + ntohs(exp->tuple.src.u.tcp.port),
4113 + NIPQUAD(exp->tuple.dst.ip),
4114 + ntohs(exp->tuple.dst.u.tcp.port));
4116 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4117 + NIPQUAD(exp->mask.src.ip),
4118 + ntohs(exp->mask.src.u.tcp.port),
4119 + NIPQUAD(exp->mask.dst.ip),
4120 + ntohs(exp->mask.dst.u.tcp.port));
4121 + UNLOCK_BH(&ip_rsh_lock);
4126 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4128 +static void fini(void);
4130 +static int __init init(void)
4133 + static char name[10];
4136 + /* If no port given, default to standard RSH port */
4137 + if (ports[0] == 0)
4138 + ports[0] = RSH_PORT;
4140 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4141 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4143 + if (ports[port] == RSH_PORT)
4144 + sprintf(name, "rsh");
4146 + sprintf(name, "rsh-%d", port);
4148 + rsh_helpers[port].name = name;
4149 + rsh_helpers[port].me = THIS_MODULE;
4150 + rsh_helpers[port].max_expected = 1;
4151 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4152 + rsh_helpers[port].timeout = 0;
4154 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4155 + rsh_helpers[port].mask.dst.protonum = 0xffff;
4157 + /* RSH must come from ports 0:1023 to ports[port] (514) */
4158 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4159 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4160 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4162 + rsh_helpers[port].help = help;
4164 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4165 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4166 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
4167 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4168 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4169 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4170 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4171 + NIPQUAD(rsh_helpers[port].mask.src.ip),
4172 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4173 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
4174 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4176 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4179 + printk("ERROR registering port %d\n",
4189 +/* This function is intentionally _NOT_ defined as __exit, because
4190 + * it is needed by the init function */
4191 +static void fini(void)
4194 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4195 + DEBUGP("unregistering port %d\n", ports[port]);
4196 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
4202 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
4203 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
4204 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-03-30 11:52:01.000000000 +0200
4207 + * RTSP extension for IP connection tracking
4208 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
4209 + * based on ip_conntrack_irc.c
4211 + * This program is free software; you can redistribute it and/or
4212 + * modify it under the terms of the GNU General Public License
4213 + * as published by the Free Software Foundation; either version
4214 + * 2 of the License, or (at your option) any later version.
4216 + * Module load syntax:
4217 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
4218 + * max_outstanding=n setup_timeout=secs
4220 + * If no ports are specified, the default will be port 554.
4222 + * With max_outstanding you can define the maximum number of not yet
4223 + * answered SETUP requests per RTSP session (default 8).
4224 + * With setup_timeout you can specify how long the system waits for
4225 + * an expected data channel (default 300 seconds).
4228 +#include <linux/config.h>
4229 +#include <linux/module.h>
4230 +#include <linux/netfilter.h>
4231 +#include <linux/ip.h>
4232 +#include <net/checksum.h>
4233 +#include <net/tcp.h>
4235 +#include <linux/netfilter_ipv4/lockhelp.h>
4236 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4237 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
4239 +#include <linux/ctype.h>
4240 +#define NF_NEED_STRNCASECMP
4241 +#define NF_NEED_STRTOU16
4242 +#define NF_NEED_STRTOU32
4243 +#define NF_NEED_NEXTLINE
4244 +#include <linux/netfilter_helpers.h>
4245 +#define NF_NEED_MIME_NEXTLINE
4246 +#include <linux/netfilter_mime.h>
4248 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
4250 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
4251 +#ifdef IP_NF_RTSP_DEBUG
4252 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
4254 +#define DEBUGP(args...)
4257 +#define MAX_PORTS 8
4258 +static int ports[MAX_PORTS];
4259 +static int num_ports = 0;
4260 +static int max_outstanding = 8;
4261 +static unsigned int setup_timeout = 300;
4263 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
4264 +MODULE_DESCRIPTION("RTSP connection tracking module");
4265 +MODULE_LICENSE("GPL");
4267 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4268 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
4269 +MODULE_PARM(max_outstanding, "i");
4270 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
4271 +MODULE_PARM(setup_timeout, "i");
4272 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
4275 +DECLARE_LOCK(ip_rtsp_lock);
4276 +struct module* ip_conntrack_rtsp = THIS_MODULE;
4279 + * Max mappings we will allow for one RTSP connection (for RTP, the number
4280 + * of allocated ports is twice this value). Note that SMIL burns a lot of
4281 + * ports so keep this reasonably high. If this is too low, you will see a
4282 + * lot of "no free client map entries" messages.
4284 +#define MAX_PORT_MAPS 16
4286 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
4288 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
4291 + * Parse an RTSP packet.
4293 + * Returns zero if parsing failed.
4296 + * IN ptcp tcp data pointer
4297 + * IN tcplen tcp data len
4298 + * IN/OUT ptcpoff points to current tcp offset
4299 + * OUT phdrsoff set to offset of rtsp headers
4300 + * OUT phdrslen set to length of rtsp headers
4301 + * OUT pcseqoff set to offset of CSeq header
4302 + * OUT pcseqlen set to length of CSeq header
4305 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
4306 + uint* phdrsoff, uint* phdrslen,
4307 + uint* pcseqoff, uint* pcseqlen)
4309 + uint entitylen = 0;
4313 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
4318 + *phdrsoff = *ptcpoff;
4319 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
4323 + if (entitylen > 0)
4325 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
4329 + if (lineoff+linelen > tcplen)
4331 + INFOP("!! overrun !!\n");
4335 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
4337 + *pcseqoff = lineoff;
4338 + *pcseqlen = linelen;
4340 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
4342 + uint off = lineoff+15;
4343 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
4344 + nf_strtou32(ptcp+off, &entitylen);
4347 + *phdrslen = (*ptcpoff) - (*phdrsoff);
4353 + * Find lo/hi client ports (if any) in transport header
4355 + * ptcp, tcplen = packet
4356 + * tranoff, tranlen = buffer to search
4359 + * pport_lo, pport_hi = lo/hi ports (host endian)
4361 + * Returns nonzero if any client ports found
4363 + * Note: it is valid (and expected) for the client to request multiple
4364 + * transports, so we need to parse the entire line.
4367 +rtsp_parse_transport(char* ptran, uint tranlen,
4368 + struct ip_ct_rtsp_expect* prtspexp)
4373 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
4374 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
4376 + INFOP("sanity check failed\n");
4379 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
4381 + SKIP_WSPACE(ptran, tranlen, off);
4383 + /* Transport: tran;field;field=val,tran;field;field=val,... */
4384 + while (off < tranlen)
4386 + const char* pparamend;
4387 + uint nextparamoff;
4389 + pparamend = memchr(ptran+off, ',', tranlen-off);
4390 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
4391 + nextparamoff = pparamend-ptran;
4393 + while (off < nextparamoff)
4395 + const char* pfieldend;
4396 + uint nextfieldoff;
4398 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
4399 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
4401 + if (strncmp(ptran+off, "client_port=", 12) == 0)
4407 + numlen = nf_strtou16(ptran+off, &port);
4409 + if (prtspexp->loport != 0 && prtspexp->loport != port)
4411 + DEBUGP("multiple ports found, port %hu ignored\n", port);
4415 + prtspexp->loport = prtspexp->hiport = port;
4416 + if (ptran[off] == '-')
4419 + numlen = nf_strtou16(ptran+off, &port);
4421 + prtspexp->pbtype = pb_range;
4422 + prtspexp->hiport = port;
4424 + // If we have a range, assume rtp:
4425 + // loport must be even, hiport must be loport+1
4426 + if ((prtspexp->loport & 0x0001) != 0 ||
4427 + prtspexp->hiport != prtspexp->loport+1)
4429 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
4430 + prtspexp->loport, prtspexp->hiport);
4431 + prtspexp->loport &= 0xfffe;
4432 + prtspexp->hiport = prtspexp->loport+1;
4435 + else if (ptran[off] == '/')
4438 + numlen = nf_strtou16(ptran+off, &port);
4440 + prtspexp->pbtype = pb_discon;
4441 + prtspexp->hiport = port;
4448 + * Note we don't look for the destination parameter here.
4449 + * If we are using NAT, the NAT module will handle it. If not,
4450 + * and the client is sending packets elsewhere, the expectation
4451 + * will quietly time out.
4454 + off = nextfieldoff;
4457 + off = nextparamoff;
4463 +/*** conntrack functions ***/
4465 +/* outbound packet: client->server */
4467 +help_out(const struct iphdr* iph, size_t pktlen,
4468 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
4470 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
4471 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
4472 + uint tcplen = pktlen - iph->ihl * 4;
4473 + char* pdata = (char*)tcph + tcph->doff * 4;
4474 + uint datalen = tcplen - tcph->doff * 4;
4477 + struct ip_conntrack_expect exp;
4479 + while (dataoff < datalen)
4481 + uint cmdoff = dataoff;
4491 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
4492 + &hdrsoff, &hdrslen,
4493 + &cseqoff, &cseqlen))
4495 + break; /* not a valid message */
4498 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
4500 + continue; /* not a SETUP message */
4502 + DEBUGP("found a setup message\n");
4504 + memset(&exp, 0, sizeof(exp));
4507 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
4508 + &lineoff, &linelen))
4514 + if (off > hdrsoff+hdrslen)
4516 + INFOP("!! overrun !!");
4520 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
4522 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
4523 + &exp.help.exp_rtsp_info);
4527 + if (exp.help.exp_rtsp_info.loport == 0)
4529 + DEBUGP("no udp transports found\n");
4530 + continue; /* no udp transports found */
4533 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
4534 + (int)exp.help.exp_rtsp_info.pbtype,
4535 + exp.help.exp_rtsp_info.loport,
4536 + exp.help.exp_rtsp_info.hiport);
4538 + LOCK_BH(&ip_rtsp_lock);
4539 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
4540 + exp.help.exp_rtsp_info.len = hdrslen;
4542 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4543 + exp.mask.src.ip = 0xffffffff;
4544 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
4545 + exp.mask.dst.ip = 0xffffffff;
4546 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
4547 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
4548 + exp.tuple.dst.protonum = IPPROTO_UDP;
4549 + exp.mask.dst.protonum = 0xffff;
4551 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4552 + NIPQUAD(exp.tuple.src.ip),
4553 + ntohs(exp.tuple.src.u.tcp.port),
4554 + NIPQUAD(exp.tuple.dst.ip),
4555 + ntohs(exp.tuple.dst.u.tcp.port));
4557 + /* pass the request off to the nat helper */
4558 + rc = ip_conntrack_expect_related(ct, &exp);
4559 + UNLOCK_BH(&ip_rtsp_lock);
4562 + DEBUGP("ip_conntrack_expect_related succeeded\n");
4566 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
4573 +/* inbound packet: server->client */
4575 +help_in(const struct iphdr* iph, size_t pktlen,
4576 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
4582 +help(const struct iphdr* iph, size_t pktlen,
4583 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
4585 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4586 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
4587 + u_int32_t tcplen = pktlen - iph->ihl * 4;
4589 + /* Until there's been traffic both ways, don't look in packets. */
4590 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
4592 + DEBUGP("conntrackinfo = %u\n", ctinfo);
4596 + /* Not whole TCP header? */
4597 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
4599 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
4603 + /* Checksum invalid? Ignore. */
4604 + /* FIXME: Source route IP option packets --RR */
4605 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4606 + csum_partial((char*)tcph, tcplen, 0)))
4608 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4609 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
4613 + switch (CTINFO2DIR(ctinfo))
4615 + case IP_CT_DIR_ORIGINAL:
4616 + help_out(iph, pktlen, ct, ctinfo);
4618 + case IP_CT_DIR_REPLY:
4619 + help_in(iph, pktlen, ct, ctinfo);
4628 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
4629 +static char rtsp_names[MAX_PORTS][10];
4631 +/* This function is intentionally _NOT_ defined as __exit */
4636 + for (i = 0; i < num_ports; i++)
4638 + DEBUGP("unregistering port %d\n", ports[i]);
4639 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
4647 + struct ip_conntrack_helper *hlpr;
4650 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
4652 + if (max_outstanding < 1)
4654 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
4657 + if (setup_timeout < 0)
4659 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
4663 + /* If no port given, default to standard rtsp port */
4664 + if (ports[0] == 0)
4666 + ports[0] = RTSP_PORT;
4669 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
4671 + hlpr = &rtsp_helpers[i];
4672 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
4673 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
4674 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
4675 + hlpr->mask.src.u.tcp.port = 0xFFFF;
4676 + hlpr->mask.dst.protonum = 0xFFFF;
4677 + hlpr->max_expected = max_outstanding;
4678 + hlpr->timeout = setup_timeout;
4679 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
4680 + hlpr->me = ip_conntrack_rtsp;
4681 + hlpr->help = help;
4683 + tmpname = &rtsp_names[i][0];
4684 + if (ports[i] == RTSP_PORT)
4686 + sprintf(tmpname, "rtsp");
4690 + sprintf(tmpname, "rtsp-%d", i);
4692 + hlpr->name = tmpname;
4694 + DEBUGP("port #%d: %d\n", i, ports[i]);
4696 + ret = ip_conntrack_helper_register(hlpr);
4700 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
4709 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4710 +EXPORT_SYMBOL(ip_rtsp_lock);
4715 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
4716 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-03-30 11:31:19.000000000 +0200
4717 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-03-30 11:51:26.000000000 +0200
4719 len += sprintf(buffer + len, "[ASSURED] ");
4720 len += sprintf(buffer + len, "use=%u ",
4721 atomic_read(&conntrack->ct_general.use));
4722 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
4723 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
4725 len += sprintf(buffer + len, "\n");
4728 @@ -569,13 +572,20 @@
4732 -/* FIXME: Allow NULL functions and sub in pointers to generic for
4735 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
4736 + * @proto: structure describing this layer 4 protocol helper
4738 + * This function is called by layer 4 protocol helpers to register
4739 + * themselves with the conntrack core.
4741 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
4744 struct list_head *i;
4746 + /* FIXME: Allow NULL functions and sub in pointers to generic for
4748 WRITE_LOCK(&ip_conntrack_lock);
4749 list_for_each(i, &protocol_list) {
4750 if (((struct ip_conntrack_protocol *)i)->proto
4751 @@ -592,12 +602,20 @@
4756 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
4757 + * @proto: structure describing this layer 4 protocol helper
4759 + * This function is called byh layer 4 protocol helpers to unregister
4760 + * themselvers from the conntrack core. Please note that all conntrack
4761 + * entries for this protocol are deleted from the conntrack hash table.
4763 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
4765 WRITE_LOCK(&ip_conntrack_lock);
4767 - /* ip_ct_find_proto() returns proto_generic in case there is no protocol
4768 - * helper. So this should be enough - HW */
4769 + /* ip_ct_find_proto() returns proto_generic in case there is no
4770 + * protocol helper. So this should be enough - HW */
4771 LIST_DELETE(&protocol_list, proto);
4772 WRITE_UNLOCK(&ip_conntrack_lock);
4774 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
4775 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
4776 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-03-30 11:53:01.000000000 +0200
4779 + * talk extension for IP connection tracking.
4780 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4782 + * This program is free software; you can redistribute it and/or
4783 + * modify it under the terms of the GNU General Public License
4784 + * as published by the Free Software Foundation; either version
4785 + * 2 of the License, or (at your option) any later version.
4787 + * Module load syntax:
4788 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
4790 + * talk=[0|1] disable|enable old talk support
4791 + * ntalk=[0|1] disable|enable ntalk support
4792 + * ntalk2=[0|1] disable|enable ntalk2 support
4794 + * The default is talk=1 ntalk=1 ntalk2=1
4796 + * The helper does not support simultaneous talk requests.
4799 + * ASCII art on talk protocols
4802 + * caller server callee server
4809 + * caller client ----------- callee client
4812 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
4813 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
4814 + * 3. callee client <-> caller server: LOOK_UP invitation
4815 + * 4. callee client <-> caller client: talk data channel
4817 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
4818 + * draft-hunter-talk-00.txt
4819 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
4821 +#include <linux/config.h>
4822 +#include <linux/module.h>
4823 +#include <linux/netfilter.h>
4824 +#include <linux/ip.h>
4825 +#include <net/checksum.h>
4826 +#include <net/udp.h>
4828 +#include <linux/netfilter_ipv4/lockhelp.h>
4829 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4830 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4831 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4832 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
4834 +/* Default all talk protocols are supported */
4835 +static int talk = 1;
4836 +static int ntalk = 1;
4837 +static int ntalk2 = 1;
4838 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4839 +MODULE_DESCRIPTION("talk connection tracking module");
4840 +MODULE_LICENSE("GPL");
4842 +MODULE_PARM(talk, "i");
4843 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
4844 +MODULE_PARM(ntalk, "i");
4845 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
4846 +MODULE_PARM(ntalk2, "i");
4847 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
4850 +DECLARE_LOCK(ip_talk_lock);
4851 +struct module *ip_conntrack_talk = THIS_MODULE;
4854 +#define DEBUGP printk
4856 +#define DEBUGP(format, args...)
4859 +static int talk_expect(struct ip_conntrack *ct);
4860 +static int ntalk_expect(struct ip_conntrack *ct);
4862 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
4864 +static int talk_help_response(const struct iphdr *iph, size_t len,
4865 + struct ip_conntrack *ct,
4866 + enum ip_conntrack_info ctinfo,
4871 + struct talk_addr *addr)
4873 + int dir = CTINFO2DIR(ctinfo);
4874 + struct ip_conntrack_expect expect, *exp = &expect;
4875 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
4877 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
4878 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
4881 + if (!(answer == SUCCESS && type == mode))
4884 + memset(&expect, 0, sizeof(expect));
4886 + if (type == ANNOUNCE) {
4888 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
4890 + /* update the talk info */
4891 + LOCK_BH(&ip_talk_lock);
4892 + exp_talk_info->port = htons(talk_port);
4894 + /* expect callee client -> caller server message */
4895 + exp->tuple = ((struct ip_conntrack_tuple)
4896 + { { ct->tuplehash[dir].tuple.src.ip,
4898 + { ct->tuplehash[dir].tuple.dst.ip,
4899 + { .tcp = { htons(talk_port) } },
4901 + exp->mask = ((struct ip_conntrack_tuple)
4902 + { { 0xFFFFFFFF, { 0 } },
4903 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4905 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
4907 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
4908 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
4909 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
4911 + /* Ignore failure; should only happen with NAT */
4912 + ip_conntrack_expect_related(ct, &expect);
4913 + UNLOCK_BH(&ip_talk_lock);
4915 + if (type == LOOK_UP) {
4917 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
4919 + /* update the talk info */
4920 + LOCK_BH(&ip_talk_lock);
4921 + exp_talk_info->port = addr->ta_port;
4923 + /* expect callee client -> caller client connection */
4924 + exp->tuple = ((struct ip_conntrack_tuple)
4925 + { { ct->tuplehash[!dir].tuple.src.ip,
4928 + { addr->ta_port },
4930 + exp->mask = ((struct ip_conntrack_tuple)
4931 + { { 0xFFFFFFFF, { 0 } },
4932 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
4934 + exp->expectfn = NULL;
4936 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
4937 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
4938 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
4940 + /* Ignore failure; should only happen with NAT */
4941 + ip_conntrack_expect_related(ct, &expect);
4942 + UNLOCK_BH(&ip_talk_lock);
4948 +/* FIXME: This should be in userspace. Later. */
4949 +static int talk_help(const struct iphdr *iph, size_t len,
4950 + struct ip_conntrack *ct,
4951 + enum ip_conntrack_info ctinfo,
4955 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
4956 + const char *data = (const char *)udph + sizeof(struct udphdr);
4957 + int dir = CTINFO2DIR(ctinfo);
4960 + DEBUGP("ip_ct_talk_help: help entered\n");
4962 + /* Until there's been traffic both ways, don't look in packets. */
4963 + if (ctinfo != IP_CT_ESTABLISHED
4964 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4965 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
4969 + /* Not whole UDP header? */
4970 + udplen = len - iph->ihl * 4;
4971 + if (udplen < sizeof(struct udphdr)) {
4972 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
4976 + /* Checksum invalid? Ignore. */
4977 + /* FIXME: Source route IP option packets --RR */
4978 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4979 + csum_partial((char *)udph, udplen, 0))) {
4980 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4981 + udph, udplen, NIPQUAD(iph->saddr),
4982 + NIPQUAD(iph->daddr));
4986 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4987 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
4989 + if (dir == IP_CT_DIR_ORIGINAL)
4992 + if (talk_port == TALK_PORT
4993 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
4994 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4995 + ((struct talk_response *)data)->type,
4996 + ((struct talk_response *)data)->answer,
4997 + &(((struct talk_response *)data)->addr));
4998 + else if (talk_port == NTALK_PORT
5000 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5001 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5002 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5003 + ((struct ntalk_response *)data)->type,
5004 + ((struct ntalk_response *)data)->answer,
5005 + &(((struct ntalk_response *)data)->addr));
5006 + else if (talk_port == NTALK_PORT
5008 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5009 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5010 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5011 + ((struct ntalk2_response *)data)->type,
5012 + ((struct ntalk2_response *)data)->answer,
5013 + &(((struct ntalk2_response *)data)->addr));
5015 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
5016 + (unsigned)udplen - sizeof(struct udphdr),
5017 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5022 +static int lookup_help(const struct iphdr *iph, size_t len,
5023 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5025 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5028 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
5029 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5031 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5034 +static struct ip_conntrack_helper lookup_helpers[2] =
5035 + { { { NULL, NULL },
5036 + "talk", /* name */
5038 + NULL, /* module */
5039 + 1, /* max_expected */
5040 + 240, /* timeout */
5041 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5042 + { 0, { 0 }, IPPROTO_UDP } },
5043 + { { 0, { 0xFFFF } }, /* mask */
5044 + { 0, { 0 }, 0xFFFF } },
5045 + lookup_help }, /* helper */
5047 + "ntalk", /* name */
5049 + NULL, /* module */
5050 + 1, /* max_expected */
5051 + 240, /* timeout */
5052 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5053 + { 0, { 0 }, IPPROTO_UDP } },
5054 + { { 0, { 0xFFFF } }, /* mask */
5055 + { 0, { 0 }, 0xFFFF } },
5056 + lookup_nhelp } /* helper */
5059 +static int talk_expect(struct ip_conntrack *ct)
5061 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5062 + WRITE_LOCK(&ip_conntrack_lock);
5063 + ct->helper = &lookup_helpers[0];
5064 + WRITE_UNLOCK(&ip_conntrack_lock);
5066 + return NF_ACCEPT; /* unused */
5069 +static int ntalk_expect(struct ip_conntrack *ct)
5071 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5072 + WRITE_LOCK(&ip_conntrack_lock);
5073 + ct->helper = &lookup_helpers[1];
5074 + WRITE_UNLOCK(&ip_conntrack_lock);
5076 + return NF_ACCEPT; /* unused */
5079 +static int help(const struct iphdr *iph, size_t len,
5080 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5082 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5085 +static int nhelp(const struct iphdr *iph, size_t len,
5086 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5088 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5091 +static struct ip_conntrack_helper talk_helpers[2] =
5092 + { { { NULL, NULL },
5093 + "talk", /* name */
5095 + THIS_MODULE, /* module */
5096 + 1, /* max_expected */
5097 + 240, /* timeout */
5098 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5099 + { 0, { 0 }, IPPROTO_UDP } },
5100 + { { 0, { 0xFFFF } }, /* mask */
5101 + { 0, { 0 }, 0xFFFF } },
5102 + help }, /* helper */
5104 + "ntalk", /* name */
5106 + THIS_MODULE, /* module */
5107 + 1, /* max_expected */
5108 + 240, /* timeout */
5109 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5110 + { 0, { 0 }, IPPROTO_UDP } },
5111 + { { 0, { 0xFFFF } }, /* mask */
5112 + { 0, { 0 }, 0xFFFF } },
5113 + nhelp } /* helper */
5116 +static int __init init(void)
5119 + ip_conntrack_helper_register(&talk_helpers[0]);
5120 + if (ntalk > 0 || ntalk2 > 0)
5121 + ip_conntrack_helper_register(&talk_helpers[1]);
5126 +static void __exit fini(void)
5129 + ip_conntrack_helper_unregister(&talk_helpers[0]);
5130 + if (ntalk > 0 || ntalk2 > 0)
5131 + ip_conntrack_helper_unregister(&talk_helpers[1]);
5134 +EXPORT_SYMBOL(ip_talk_lock);
5138 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_core.c
5139 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_core.c 2004-03-30 11:31:19.000000000 +0200
5140 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_core.c 2004-03-30 11:51:26.000000000 +0200
5142 WRITE_UNLOCK(&ip_nat_lock);
5145 -/* We do checksum mangling, so if they were wrong before they're still
5146 - * wrong. Also works for incomplete packets (eg. ICMP dest
5147 - * unreachables.) */
5149 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
5150 + * @oldvalinv: bit-inverted old value of 32bit word
5151 + * @newval: new value of 32bit word
5152 + * @oldcheck: old checksum value
5154 + * This function implements incremental checksum mangling, so if a checksum
5155 + * was wrong it will still be wrong after mangling. Also works for incomplete
5156 + * packets (eg. ICMP dest unreachables). Return value is the new checksum.
5159 ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
5161 @@ -124,7 +131,14 @@
5165 -/* Is this tuple already taken? (not by us) */
5167 + * ip_nat_used_tuple - Is this tuple already in use?
5168 + * @tuple: tuple to be used for this check
5169 + * @ignored_conntrack: conntrack excluded from this check
5171 + * This function checks for the reply (inverted) tuple in the conntrack
5172 + * hash. This is necessarry with NAT, since there is no fixed mapping.
5175 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
5176 const struct ip_conntrack *ignored_conntrack)
5177 @@ -515,6 +529,19 @@
5182 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
5183 + * @conntrack: conntrack on which we operate
5184 + * @mr: address/port range which is valid for this NAT mapping
5185 + * @hooknum: hook at which this NAT mapping applies
5187 + * This function is called by NAT targets (SNAT,DNAT,...) and by
5188 + * the NAT application helper modules. It is called for the NEW packet
5189 + * of a connection in order to specify which NAT mappings shall apply to
5190 + * this connection at a given hook.
5192 + * Note: The reply mappings are created automagically by this function.
5195 ip_nat_setup_info(struct ip_conntrack *conntrack,
5196 const struct ip_nat_multi_range *mr,
5197 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c
5198 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c 1970-01-01 01:00:00.000000000 +0100
5199 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c 2004-03-30 11:50:58.000000000 +0200
5201 +/* CuSeeMe extension for UDP NAT alteration.
5202 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5203 + * based on ip_masq_cuseeme.c in 2.2 kernels
5205 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
5207 + * This program is free software; you can redistribute it and/or
5208 + * modify it under the terms of the GNU General Public License
5209 + * as published by the Free Software Foundation; either version
5210 + * 2 of the License, or (at your option) any later version.
5212 + * Module load syntax:
5213 + * insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
5215 + * Please give the ports of the CuSeeMe traffic you want to track.
5216 + * If you don't specify ports, the default will be UDP port 7648.
5218 + * CuSeeMe Protocol Documentation:
5219 + * http://cu-seeme.net/squeek/tech/contents.html
5223 +#include <linux/module.h>
5224 +#include <linux/netfilter_ipv4.h>
5225 +#include <linux/ip.h>
5226 +#include <linux/udp.h>
5228 +#include <linux/netfilter.h>
5229 +#include <linux/netfilter_ipv4/ip_tables.h>
5230 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5231 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
5232 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5233 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5235 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5236 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
5237 +MODULE_LICENSE("GPL");
5239 +#define MAX_PORTS 8
5241 +static int ports[MAX_PORTS];
5242 +static int ports_c = 0;
5244 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5245 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
5249 +#define DEBUGP printk
5251 +#define DEBUGP(format, args...)
5254 +/* process packet from client->reflector, possibly manipulate client IP in payload */
5255 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
5256 + struct ip_nat_info *info,
5257 + enum ip_conntrack_info ctinfo,
5258 + struct sk_buff **pskb,
5260 + unsigned int datalen)
5262 + char new_port_ip[6];
5263 + struct cu_header *cu_head=(struct cu_header *)data;
5265 + DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n",
5266 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5268 + /* At least check that the data at offset 10 is the client's port and IP address */
5269 + if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
5270 + (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
5271 + DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
5272 + NIPQUAD(cu_head->addr),
5273 + ntohs(cu_head->port),
5274 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5275 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
5276 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5277 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5278 + /* at offset 10, replace 6 bytes containing port + IP address */
5279 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5280 + 10, 6, (char *)(new_port_ip), 6);
5282 + DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5283 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5284 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
5285 + NIPQUAD(cu_head->addr),
5286 + ntohs(cu_head->port));
5289 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
5290 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
5291 + struct ip_nat_info *info,
5292 + enum ip_conntrack_info ctinfo,
5293 + struct sk_buff **pskb,
5295 + unsigned int datalen)
5297 + char new_port_ip[6];
5298 + struct cu_header *cu_head = (struct cu_header *)data;
5299 + struct oc_header *oc_head = (struct oc_header *)data;
5300 + struct client_info *ci;
5304 + DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n",
5305 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5307 + /* Check if we're really dealing with the client's port + IP address before rewriting */
5308 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
5309 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
5310 + DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
5311 + NIPQUAD(cu_head->dest_addr),
5312 + ntohs(cu_head->dest_port),
5313 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5314 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
5315 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
5316 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5317 + /* at offset 2, replace 6 bytes containing port + IP address */
5318 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5319 + 2, 6, (char *)(new_port_ip), 6);
5321 + DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5322 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5323 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
5324 + NIPQUAD(cu_head->dest_addr),
5325 + ntohs(cu_head->dest_port));
5327 + /* Check if we're really dealing with the server's port + IP address before rewriting.
5328 + In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
5329 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
5330 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
5331 + DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
5332 + NIPQUAD(cu_head->addr),
5333 + ntohs(cu_head->port),
5334 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
5335 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
5336 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
5337 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5338 + /* at offset 10, replace 6 bytes containing port + IP address */
5339 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5340 + 10, 6, (char *)(new_port_ip), 6);
5342 + /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
5343 + is not that important so we're not logging this unless we're debugging */
5344 + DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5345 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
5346 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
5347 + NIPQUAD(cu_head->addr),
5348 + ntohs(cu_head->port));
5350 + /* Spin through client_info structs until we find our own */
5351 + if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
5352 + DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
5353 + for(i=0, off=sizeof(struct oc_header);
5354 + (i < oc_head->client_count &&
5355 + off+sizeof(struct client_info) <= datalen);
5357 + ci=(struct client_info *)(data+off);
5358 + DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n",
5359 + NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5360 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
5361 + if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
5362 + /* mangle this IP address */
5363 + DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
5364 + NIPQUAD(ci->address),
5365 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5366 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
5367 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5368 + (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4,
5369 + (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
5372 + off+=sizeof(struct client_info);
5375 + DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n",
5376 + ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
5379 +static unsigned int
5380 +cuseeme_nat_help(struct ip_conntrack *ct,
5381 + struct ip_conntrack_expect *exp,
5382 + struct ip_nat_info *info,
5383 + enum ip_conntrack_info ctinfo,
5384 + unsigned int hooknum,
5385 + struct sk_buff **pskb)
5387 + struct iphdr *iph = (*pskb)->nh.iph;
5388 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5389 + int dir = CTINFO2DIR(ctinfo);
5390 + unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
5391 + char *data = (char *) &udph[1];
5393 + DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
5394 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5395 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5396 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5397 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
5400 + /* Only mangle things once: original direction in POST_ROUTING
5401 + and reply direction on PRE_ROUTING. */
5402 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5403 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5404 + DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
5405 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5406 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5407 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5408 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
5412 + if(datalen < sizeof(struct cu_header)) {
5413 + /* packet too small */
5414 + if (net_ratelimit())
5415 + printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n",
5416 + datalen, sizeof(struct cu_header));
5421 + /* In the debugging output, "outgoing" is from client to server, and
5422 + "incoming" is from server to client */
5423 + if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5424 + cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
5426 + cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
5431 +static struct ip_nat_helper cuseeme[MAX_PORTS];
5432 +static char cuseeme_names[MAX_PORTS][14]; /* cuseeme-65535 */
5434 +static void fini(void)
5438 + for (i = 0 ; i < ports_c; i++) {
5439 + DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
5440 + ip_nat_helper_unregister(&cuseeme[i]);
5444 +static int __init init(void)
5450 + ports[0] = CUSEEME_PORT;
5452 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5453 + memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
5455 + cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
5456 + cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
5457 + cuseeme[i].mask.dst.protonum = 0xFFFF;
5458 + cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
5459 + cuseeme[i].help = cuseeme_nat_help;
5460 + cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE +
5461 + IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
5462 + is stricly needed... */
5463 + cuseeme[i].me = THIS_MODULE;
5464 + cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
5466 + tmpname = &cuseeme_names[i][0];
5467 + if (ports[i] == CUSEEME_PORT)
5468 + sprintf(tmpname, "cuseeme");
5470 + sprintf(tmpname, "cuseeme-%d", ports[i]);
5471 + cuseeme[i].name = tmpname;
5473 + DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
5474 + ports[i], cuseeme[i].name);
5475 + ret = ip_nat_helper_register(&cuseeme[i]);
5478 + printk("ip_nat_cuseeme: unable to register helper for port %d\n",
5490 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_h323.c
5491 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
5492 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-03-30 11:51:04.000000000 +0200
5495 + * H.323 'brute force' extension for NAT alteration.
5496 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5498 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
5499 + * (http://www.coritel.it/projects/sofia/nat.html)
5500 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
5501 + * the unregistered helpers to the conntrack entries.
5505 +#include <linux/module.h>
5506 +#include <linux/netfilter.h>
5507 +#include <linux/ip.h>
5508 +#include <net/checksum.h>
5509 +#include <net/tcp.h>
5511 +#include <linux/netfilter_ipv4/lockhelp.h>
5512 +#include <linux/netfilter_ipv4/ip_nat.h>
5513 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5514 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5515 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5516 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5517 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
5519 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5520 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
5521 +MODULE_LICENSE("GPL");
5523 +DECLARE_LOCK_EXTERN(ip_h323_lock);
5524 +struct module *ip_nat_h323 = THIS_MODULE;
5527 +#define DEBUGP printk
5529 +#define DEBUGP(format, args...)
5532 +/* FIXME: Time out? --RR */
5534 +static unsigned int
5535 +h225_nat_expected(struct sk_buff **pskb,
5536 + unsigned int hooknum,
5537 + struct ip_conntrack *ct,
5538 + struct ip_nat_info *info);
5540 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5541 + struct ip_conntrack_expect *exp,
5542 + struct ip_nat_info *info,
5543 + enum ip_conntrack_info ctinfo,
5544 + unsigned int hooknum,
5545 + struct sk_buff **pskb);
5547 +static struct ip_nat_helper h245 =
5549 + "H.245", /* name */
5551 + NULL, /* module */
5552 + { { 0, { 0 } }, /* tuple */
5553 + { 0, { 0 }, IPPROTO_TCP } },
5554 + { { 0, { 0xFFFF } }, /* mask */
5555 + { 0, { 0 }, 0xFFFF } },
5556 + h225_nat_help, /* helper */
5557 + h225_nat_expected /* expectfn */
5560 +static unsigned int
5561 +h225_nat_expected(struct sk_buff **pskb,
5562 + unsigned int hooknum,
5563 + struct ip_conntrack *ct,
5564 + struct ip_nat_info *info)
5566 + struct ip_nat_multi_range mr;
5567 + u_int32_t newdstip, newsrcip, newip;
5569 + struct ip_ct_h225_expect *exp_info;
5570 + struct ip_ct_h225_master *master_info;
5571 + struct ip_conntrack *master = master_ct(ct);
5572 + unsigned int is_h225, ret;
5574 + IP_NF_ASSERT(info);
5575 + IP_NF_ASSERT(master);
5577 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
5579 + DEBUGP("h225_nat_expected: We have a connection!\n");
5580 + master_info = &ct->master->expectant->help.ct_h225_info;
5581 + exp_info = &ct->master->help.exp_h225_info;
5583 + LOCK_BH(&ip_h323_lock);
5585 + DEBUGP("master: ");
5586 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5587 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
5588 + DEBUGP("conntrack: ");
5589 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5590 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
5591 + /* Make connection go to the client. */
5592 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5593 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5594 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
5595 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
5597 + /* Make the connection go to the server */
5598 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
5599 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5600 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
5601 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
5603 + port = exp_info->port;
5604 + is_h225 = master_info->is_h225 == H225_PORT;
5605 + UNLOCK_BH(&ip_h323_lock);
5607 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5612 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
5615 + /* We don't want to manip the per-protocol, just the IPs... */
5616 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5617 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
5619 + /* ... unless we're doing a MANIP_DST, in which case, make
5620 + sure we map to the correct port */
5621 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
5622 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
5623 + mr.range[0].min = mr.range[0].max
5624 + = ((union ip_conntrack_manip_proto)
5625 + { .tcp = { port } });
5628 + ret = ip_nat_setup_info(ct, &mr, hooknum);
5631 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
5632 + /* NAT expectfn called with ip_nat_lock write-locked */
5633 + info->helper = &h245;
5638 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
5639 + struct sk_buff **pskb,
5640 + enum ip_conntrack_info ctinfo)
5642 + struct iphdr *iph = (*pskb)->nh.iph;
5643 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
5644 + char *data = (char *) tcph + tcph->doff * 4;
5645 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
5646 + u_int32_t datalen = tcplen - tcph->doff*4;
5647 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
5652 + MUST_BE_LOCKED(&ip_h323_lock);
5654 + DEBUGP("h323_signal_address_fixup: %s %s\n",
5655 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5657 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5659 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5660 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
5663 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
5664 + info->offset[IP_CT_DIR_ORIGINAL],
5665 + info->offset[IP_CT_DIR_REPLY],
5667 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5668 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5670 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
5671 + DEBUGP("h323_signal_address_fixup: %s %s\n",
5672 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
5673 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
5674 + if (!between(info->seq[i], ntohl(tcph->seq),
5675 + ntohl(tcph->seq) + datalen))
5677 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
5678 + ntohl(tcph->seq) + datalen)) {
5679 + /* Partial retransmisison. It's a cracker being funky. */
5680 + if (net_ratelimit()) {
5681 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
5684 + ntohl(tcph->seq) + datalen);
5689 + /* Change address inside packet to match way we're mapping
5690 + this connection. */
5691 + if (i == IP_CT_DIR_ORIGINAL) {
5692 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
5693 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
5695 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
5696 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
5699 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
5700 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
5701 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
5702 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
5704 + /* Modify the packet */
5705 + *(u_int32_t *)(data + info->offset[i]) = newip;
5706 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
5708 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
5709 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
5710 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
5711 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
5714 + /* fix checksum information */
5716 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
5720 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5721 + csum_partial((char *)tcph, tcph->doff*4,
5723 + ip_send_check(iph);
5728 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
5729 + struct ip_conntrack *ct,
5730 + struct sk_buff **pskb,
5731 + enum ip_conntrack_info ctinfo,
5732 + struct ip_conntrack_expect *expect)
5736 + struct ip_conntrack_tuple newtuple;
5737 + struct iphdr *iph = (*pskb)->nh.iph;
5738 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
5739 + char *data = (char *) tcph + tcph->doff * 4;
5740 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
5741 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
5744 + MUST_BE_LOCKED(&ip_h323_lock);
5745 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
5746 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5747 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5749 + if (!between(expect->seq + 6, ntohl(tcph->seq),
5750 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
5751 + /* Partial retransmisison. It's a cracker being funky. */
5752 + if (net_ratelimit()) {
5753 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
5756 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
5761 + /* Change address inside packet to match way we're mapping
5762 + this connection. */
5763 + if (info->dir == IP_CT_DIR_REPLY) {
5764 + /* Must be where client thinks server is */
5765 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5766 + /* Expect something from client->server */
5767 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5768 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5770 + /* Must be where server thinks client is */
5771 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5772 + /* Expect something from server->client */
5773 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
5774 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5777 + is_h225 = (master_info->is_h225 == H225_PORT);
5780 + newtuple.dst.protonum = IPPROTO_TCP;
5781 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
5783 + newtuple.dst.protonum = IPPROTO_UDP;
5784 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
5787 + /* Try to get same port: if not, try to change it. */
5788 + for (port = ntohs(info->port); port != 0; port++) {
5790 + newtuple.dst.u.tcp.port = htons(port);
5792 + newtuple.dst.u.udp.port = htons(port);
5794 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
5798 + DEBUGP("h323_data_fixup: no free port found!\n");
5802 + port = htons(port);
5804 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
5805 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
5806 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
5808 + /* Modify the packet */
5809 + *(u_int32_t *)(data + info->offset) = newip;
5810 + *(u_int16_t *)(data + info->offset + 4) = port;
5812 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
5813 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
5814 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
5816 + /* fix checksum information */
5817 + /* FIXME: usually repeated multiple times in the case of H.245! */
5819 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
5820 + tcplen - tcph->doff*4, 0);
5823 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5824 + csum_partial((char *)tcph, tcph->doff*4,
5826 + ip_send_check(iph);
5831 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5832 + struct ip_conntrack_expect *exp,
5833 + struct ip_nat_info *info,
5834 + enum ip_conntrack_info ctinfo,
5835 + unsigned int hooknum,
5836 + struct sk_buff **pskb)
5839 + struct ip_ct_h225_expect *exp_info;
5841 + /* Only mangle things once: original direction in POST_ROUTING
5842 + and reply direction on PRE_ROUTING. */
5843 + dir = CTINFO2DIR(ctinfo);
5844 + DEBUGP("nat_h323: dir %s at hook %s\n",
5845 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5846 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5847 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5848 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5849 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5850 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5851 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
5852 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5853 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5854 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5855 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5860 + LOCK_BH(&ip_h323_lock);
5861 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
5862 + UNLOCK_BH(&ip_h323_lock);
5865 + UNLOCK_BH(&ip_h323_lock);
5869 + exp_info = &exp->help.exp_h225_info;
5871 + LOCK_BH(&ip_h323_lock);
5872 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
5873 + UNLOCK_BH(&ip_h323_lock);
5876 + UNLOCK_BH(&ip_h323_lock);
5881 +static struct ip_nat_helper h225 =
5883 + "H.225", /* name */
5884 + IP_NAT_HELPER_F_ALWAYS, /* flags */
5885 + THIS_MODULE, /* module */
5886 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
5887 + { 0, { 0 }, IPPROTO_TCP } },
5888 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
5889 + { 0, { 0 }, 0xFFFF } },
5890 + h225_nat_help, /* helper */
5891 + h225_nat_expected /* expectfn */
5894 +static int __init init(void)
5898 + ret = ip_nat_helper_register(&h225);
5901 + printk("ip_nat_h323: cannot initialize the module!\n");
5906 +static void __exit fini(void)
5908 + ip_nat_helper_unregister(&h225);
5913 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_helper.c
5914 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_helper.c 2004-03-30 05:25:34.000000000 +0200
5915 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_helper.c 2004-03-30 11:51:26.000000000 +0200
5916 @@ -150,9 +150,19 @@
5920 -/* Generic function for mangling variable-length address changes inside
5921 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
5922 - * command in FTP).
5924 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
5925 + * @skb: pointer to skb of packet on which we operate
5926 + * @ct: conntrack of the connection to which this packet belongs
5927 + * @ctinfo: conntrack_info of the connection to which this packet belongs
5928 + * @match_offset: offset in bytes where to-be-manipulated part starts
5929 + * @match_len: lenght of the to-be-manipulated part
5930 + * @rep_buffer: pointer to buffer containing replacement
5931 + * @rep_len: length of replacement
5933 + * Generic function for mangling fixed and variable-length changes inside
5934 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command
5937 * Takes care about all the nasty sequence number changes, checksumming,
5938 * skb enlargement, ...
5939 @@ -198,16 +208,27 @@
5943 -/* Generic function for mangling variable-length address changes inside
5944 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
5945 - * command in the Amanda protocol)
5947 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
5948 + * @skb: pointer to skb of packet on which we operate
5949 + * @ct: conntrack of the connection to which this packet belongs
5950 + * @ctinfo: conntrack_info of the connection to which this packet belongs
5951 + * @match_offset: offset in bytes where to-be-manipulated part starts
5952 + * @match_len: lenght of the to-be-manipulated part
5953 + * @rep_buffer: pointer to buffer containing replacement
5954 + * @rep_len: length of replacement
5956 + * Generic function for mangling fixed and variable-length changes inside
5957 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
5958 + * commad in the Amanda protocol)
5960 * Takes care about all the nasty sequence number changes, checksumming,
5961 * skb enlargement, ...
5963 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
5964 - * should be fairly easy to do.
5966 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
5971 ip_nat_mangle_udp_packet(struct sk_buff **pskb,
5972 struct ip_conntrack *ct,
5973 @@ -405,6 +426,13 @@
5974 return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
5978 + * ip_nat_helper_register - Register NAT application helper
5979 + * @me: structure describing the helper
5981 + * This function is called by NAT application helpers to register
5982 + * themselves with the NAT core.
5984 int ip_nat_helper_register(struct ip_nat_helper *me)
5987 @@ -431,6 +459,13 @@
5992 + * ip_nat_helper_unregister - Unregister NAT application helper
5993 + * @me: structure describing the helper
5995 + * This function is called by NAT application helpers to unregister
5996 + * themselves from the NAT core.
5998 void ip_nat_helper_unregister(struct ip_nat_helper *me)
6000 WRITE_LOCK(&ip_nat_lock);
6001 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_mms.c
6002 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6003 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-03-30 11:51:24.000000000 +0200
6005 +/* MMS extension for TCP NAT alteration.
6006 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6007 + * based on ip_nat_ftp.c and ip_nat_irc.c
6009 + * ip_nat_mms.c v0.3 2002-09-22
6011 + * This program is free software; you can redistribute it and/or
6012 + * modify it under the terms of the GNU General Public License
6013 + * as published by the Free Software Foundation; either version
6014 + * 2 of the License, or (at your option) any later version.
6016 + * Module load syntax:
6017 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6019 + * Please give the ports of all MMS servers You wish to connect to.
6020 + * If you don't specify ports, the default will be TCP port 1755.
6022 + * More info on MMS protocol, firewalls and NAT:
6023 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6024 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6026 + * The SDP project people are reverse-engineering MMS:
6027 + * http://get.to/sdp
6030 +/* FIXME: issue with UDP & fragmentation with this URL:
6031 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6032 + may be related to out-of-order first packets:
6033 + basically the expectation is set up correctly, then the server sends
6034 + a first UDP packet which is fragmented plus arrives out-of-order.
6035 + the MASQUERADING firewall with ip_nat_mms loaded responds with
6036 + an ICMP unreachable back to the server */
6038 +#include <linux/module.h>
6039 +#include <linux/netfilter_ipv4.h>
6040 +#include <linux/ip.h>
6041 +#include <linux/tcp.h>
6042 +#include <net/tcp.h>
6043 +#include <linux/netfilter_ipv4/ip_nat.h>
6044 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6045 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6046 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6047 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6050 +#define DEBUGP printk
6051 +#define DUMP_BYTES(address, counter) \
6053 + int temp_counter; \
6054 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6055 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
6060 +#define DEBUGP(format, args...)
6061 +#define DUMP_BYTES(address, counter)
6064 +#define MAX_PORTS 8
6065 +static int ports[MAX_PORTS];
6066 +static int ports_c = 0;
6069 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6072 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6073 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6074 +MODULE_LICENSE("GPL");
6076 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6078 +/* FIXME: Time out? --RR */
6080 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6081 + struct ip_conntrack *ct,
6082 + struct sk_buff **pskb,
6083 + enum ip_conntrack_info ctinfo,
6084 + struct ip_conntrack_expect *expect)
6087 + struct ip_conntrack_tuple t;
6088 + struct iphdr *iph = (*pskb)->nh.iph;
6089 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6090 + char *data = (char *)tcph + tcph->doff * 4;
6091 + int i, j, k, port;
6092 + u_int16_t mms_proto;
6094 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6095 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6096 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6100 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6101 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6102 + char proto_string[6];
6104 + MUST_BE_LOCKED(&ip_mms_lock);
6106 + /* what was the protocol again ? */
6107 + mms_proto = expect->tuple.dst.protonum;
6108 + sprintf(proto_string, "%u", mms_proto);
6110 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6111 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6112 + mms_proto == IPPROTO_UDP ? "UDP"
6113 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6115 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6117 + /* Alter conntrack's expectations. */
6118 + t = expect->tuple;
6120 + for (port = ct_mms_info->port; port != 0; port++) {
6121 + t.dst.u.tcp.port = htons(port);
6122 + if (ip_conntrack_change_expect(expect, &t) == 0) {
6123 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6131 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6133 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6134 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6136 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6138 + memset(unicode_buffer, 0, sizeof(char)*75);
6140 + for (i=0; i<strlen(buffer); ++i)
6141 + *(unicode_buffer+i*2)=*(buffer+i);
6143 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6144 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6145 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6147 + /* add end of packet to it */
6148 + for (j=0; j<ct_mms_info->padding; ++j) {
6149 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6150 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6151 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6154 + /* pad with zeroes at the end ? see explanation of weird math below */
6155 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6156 + for (k=0; k<zero_padding; ++k)
6157 + *(unicode_buffer+i*2+j+k)= (char)0;
6159 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6160 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6161 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6163 + /* explanation, before I forget what I did:
6164 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6165 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
6166 + but note that things may have to be padded with zeroes to align by 8
6167 + bytes, hence we add 7 and divide by 8 to get the correct length */
6168 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6169 + *mms_chunkLenLV = *mms_chunkLenLM+2;
6170 + *mms_messageLength = *mms_chunkLenLV*8;
6172 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6173 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6175 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6176 + expect->seq - ntohl(tcph->seq),
6177 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6178 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6179 + DUMP_BYTES(unicode_buffer, 60);
6184 +static unsigned int
6185 +mms_nat_expected(struct sk_buff **pskb,
6186 + unsigned int hooknum,
6187 + struct ip_conntrack *ct,
6188 + struct ip_nat_info *info)
6190 + struct ip_nat_multi_range mr;
6191 + u_int32_t newdstip, newsrcip, newip;
6193 + struct ip_conntrack *master = master_ct(ct);
6195 + IP_NF_ASSERT(info);
6196 + IP_NF_ASSERT(master);
6198 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6200 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6202 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6203 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6204 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6205 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6206 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6207 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6208 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6210 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6215 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6218 + /* We don't want to manip the per-protocol, just the IPs. */
6219 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6220 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6222 + return ip_nat_setup_info(ct, &mr, hooknum);
6226 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6227 + struct ip_conntrack_expect *exp,
6228 + struct ip_nat_info *info,
6229 + enum ip_conntrack_info ctinfo,
6230 + unsigned int hooknum,
6231 + struct sk_buff **pskb)
6233 + struct iphdr *iph = (*pskb)->nh.iph;
6234 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6235 + unsigned int datalen;
6237 + struct ip_ct_mms_expect *ct_mms_info;
6240 + DEBUGP("ip_nat_mms: no exp!!");
6242 + ct_mms_info = &exp->help.exp_mms_info;
6244 + /* Only mangle things once: original direction in POST_ROUTING
6245 + and reply direction on PRE_ROUTING. */
6246 + dir = CTINFO2DIR(ctinfo);
6247 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6248 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6249 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6250 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6251 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6252 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6253 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6256 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6257 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6258 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6259 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6260 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6262 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6264 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6265 + exp->seq + ct_mms_info->len,
6267 + ntohl(tcph->seq) + datalen);
6269 + LOCK_BH(&ip_mms_lock);
6270 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
6271 + if (between(exp->seq + ct_mms_info->len,
6273 + ntohl(tcph->seq) + datalen)) {
6274 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6275 + UNLOCK_BH(&ip_mms_lock);
6279 + /* Half a match? This means a partial retransmisison.
6280 + It's a cracker being funky. */
6281 + if (net_ratelimit()) {
6282 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6283 + exp->seq, ct_mms_info->len,
6285 + ntohl(tcph->seq) + datalen);
6287 + UNLOCK_BH(&ip_mms_lock);
6290 + UNLOCK_BH(&ip_mms_lock);
6295 +static struct ip_nat_helper mms[MAX_PORTS];
6296 +static char mms_names[MAX_PORTS][10];
6298 +/* Not __exit: called from init() */
6299 +static void fini(void)
6303 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6304 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6305 + ip_nat_helper_unregister(&mms[i]);
6309 +static int __init init(void)
6314 + if (ports[0] == 0)
6315 + ports[0] = MMS_PORT;
6317 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6319 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6321 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
6322 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6323 + mms[i].mask.dst.protonum = 0xFFFF;
6324 + mms[i].mask.src.u.tcp.port = 0xFFFF;
6325 + mms[i].help = mms_nat_help;
6326 + mms[i].me = THIS_MODULE;
6328 + mms[i].expect = mms_nat_expected;
6330 + tmpname = &mms_names[i][0];
6331 + if (ports[i] == MMS_PORT)
6332 + sprintf(tmpname, "mms");
6334 + sprintf(tmpname, "mms-%d", i);
6335 + mms[i].name = tmpname;
6337 + DEBUGP("ip_nat_mms: register helper for port %d\n",
6339 + ret = ip_nat_helper_register(&mms[i]);
6342 + printk("ip_nat_mms: error registering "
6343 + "helper for port %d\n", ports[i]);
6355 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6356 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
6357 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-03-30 11:51:52.000000000 +0200
6359 +/* Quake3 extension for UDP NAT alteration.
6360 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6361 + * based on ip_nat_ftp.c and ip_nat_tftp.c
6363 + * ip_nat_quake3.c v0.0.3 2002-08-31
6365 + * This program is free software; you can redistribute it and/or
6366 + * modify it under the terms of the GNU General Public License
6367 + * as published by the Free Software Foundation; either version
6368 + * 2 of the License, or (at your option) any later version.
6370 + * Module load syntax:
6371 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6373 + * please give the ports of all Quake3 master servers You wish to
6374 + * connect to. If you don't specify ports, the default will be UDP
6377 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6380 + * - If you're one of those people who would try anything to lower
6381 + * latency while playing Quake (and who isn't :-) ), you may want to
6382 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
6383 + * outgoing UDP traffic.
6384 + * This will make ip_conntrack_quake3 add the necessary expectations,
6385 + * but there will be no overhead for client->server UDP streams. If
6386 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6387 + * hook for every packet in the client->server UDP stream.
6388 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6389 + * The IP addresses in the master connection payload (=IP addresses
6390 + * of Quake servers) have no relation with the master server so
6391 + * DNAT'ing the master connection to a server should not change the
6392 + * expected connections.
6393 + * - Not tested due to lack of equipment:
6394 + * - multiple Quake3 clients behind one MASQUERADE gateway
6395 + * - what if Quake3 client is running on router too
6398 +#include <linux/module.h>
6399 +#include <linux/netfilter_ipv4.h>
6400 +#include <linux/ip.h>
6401 +#include <linux/udp.h>
6403 +#include <linux/netfilter.h>
6404 +#include <linux/netfilter_ipv4/ip_tables.h>
6405 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6406 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6407 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6408 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6410 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6411 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6412 +MODULE_LICENSE("GPL");
6414 +#define MAX_PORTS 8
6416 +static int ports[MAX_PORTS];
6417 +static int ports_c = 0;
6419 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
6420 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
6423 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
6424 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
6426 +#define DEBUGP printk
6428 +#define DEBUGP(format, args...)
6431 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
6433 +static unsigned int
6434 +quake3_nat_help(struct ip_conntrack *ct,
6435 + struct ip_conntrack_expect *exp,
6436 + struct ip_nat_info *info,
6437 + enum ip_conntrack_info ctinfo,
6438 + unsigned int hooknum,
6439 + struct sk_buff **pskb)
6441 + struct iphdr *iph = (*pskb)->nh.iph;
6442 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6443 + struct ip_conntrack_tuple repl;
6444 + int dir = CTINFO2DIR(ctinfo);
6447 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
6448 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6449 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6450 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6451 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6453 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6454 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6456 + /* Only mangle things once: original direction in POST_ROUTING
6457 + and reply direction on PRE_ROUTING. */
6458 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6459 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6460 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
6461 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6462 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6463 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6464 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6469 + DEBUGP("no conntrack expectation to modify\n");
6473 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
6474 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
6475 + i+6 < ntohs(udph->len);
6477 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
6478 + i, ntohs(udph->len),
6479 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
6480 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
6482 + memset(&repl, 0, sizeof(repl));
6484 + repl.dst.protonum = IPPROTO_UDP;
6485 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6486 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
6487 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
6489 + ip_conntrack_change_expect(exp, &repl);
6495 +static unsigned int
6496 +quake3_nat_expected(struct sk_buff **pskb,
6497 + unsigned int hooknum,
6498 + struct ip_conntrack *ct,
6499 + struct ip_nat_info *info)
6501 + const struct ip_conntrack *master = ct->master->expectant;
6502 + struct ip_nat_multi_range mr;
6503 + u_int32_t newsrcip, newdstip, newip;
6505 + const struct ip_conntrack_tuple *repl =
6506 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
6507 + struct iphdr *iph = (*pskb)->nh.iph;
6508 + struct udphdr *udph = (void *)iph + iph->ihl*4;
6511 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
6512 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6514 + IP_NF_ASSERT(info);
6515 + IP_NF_ASSERT(master);
6516 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6518 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6519 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6521 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
6523 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6524 + "newsrc: %u.%u.%u.%u\n",
6525 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6526 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6527 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6528 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6529 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6534 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6535 + "newdst: %u.%u.%u.%u\n",
6536 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6537 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6538 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6539 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6540 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6545 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6546 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6548 + return ip_nat_setup_info(ct,&mr,hooknum);
6551 +static struct ip_nat_helper quake3[MAX_PORTS];
6552 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
6554 +static void fini(void)
6558 + for (i = 0 ; i < ports_c; i++) {
6559 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
6560 + ip_nat_helper_unregister(&quake3[i]);
6564 +static int __init init(void)
6570 + ports[0] = QUAKE3_MASTER_PORT;
6572 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6573 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
6575 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
6576 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
6577 + quake3[i].mask.dst.protonum = 0xFFFF;
6578 + quake3[i].mask.src.u.udp.port = 0xFFFF;
6579 + quake3[i].help = quake3_nat_help;
6580 + quake3[i].flags = 0;
6581 + quake3[i].me = THIS_MODULE;
6582 + quake3[i].expect = quake3_nat_expected;
6584 + tmpname = &quake3_names[i][0];
6585 + if (ports[i] == QUAKE3_MASTER_PORT)
6586 + sprintf(tmpname, "quake3");
6588 + sprintf(tmpname, "quake3-%d", i);
6589 + quake3[i].name = tmpname;
6591 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
6592 + ports[i], quake3[i].name);
6593 + ret = ip_nat_helper_register(&quake3[i]);
6596 + printk("ip_nat_quake3: unable to register helper for port %d\n",
6608 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
6609 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
6610 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-03-30 11:52:01.000000000 +0200
6613 + * RTSP extension for TCP NAT alteration
6614 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6615 + * based on ip_nat_irc.c
6617 + * This program is free software; you can redistribute it and/or
6618 + * modify it under the terms of the GNU General Public License
6619 + * as published by the Free Software Foundation; either version
6620 + * 2 of the License, or (at your option) any later version.
6622 + * Module load syntax:
6623 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6624 + * stunaddr=<address>
6625 + * destaction=[auto|strip|none]
6627 + * If no ports are specified, the default will be port 554 only.
6629 + * stunaddr specifies the address used to detect that a client is using STUN.
6630 + * If this address is seen in the destination parameter, it is assumed that
6631 + * the client has already punched a UDP hole in the firewall, so we don't
6632 + * mangle the client_port. If none is specified, it is autodetected. It
6633 + * only needs to be set if you have multiple levels of NAT. It should be
6634 + * set to the external address that the STUN clients detect. Note that in
6635 + * this case, it will not be possible for clients to use UDP with servers
6636 + * between the NATs.
6638 + * If no destaction is specified, auto is used.
6639 + * destaction=auto: strip destination parameter if it is not stunaddr.
6640 + * destaction=strip: always strip destination parameter (not recommended).
6641 + * destaction=none: do not touch destination parameter (not recommended).
6644 +#include <linux/module.h>
6645 +#include <linux/netfilter_ipv4.h>
6646 +#include <linux/ip.h>
6647 +#include <linux/tcp.h>
6648 +#include <linux/kernel.h>
6649 +#include <net/tcp.h>
6650 +#include <linux/netfilter_ipv4/ip_nat.h>
6651 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6652 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6653 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6654 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6656 +#include <linux/inet.h>
6657 +#include <linux/ctype.h>
6658 +#define NF_NEED_STRNCASECMP
6659 +#define NF_NEED_STRTOU16
6660 +#include <linux/netfilter_helpers.h>
6661 +#define NF_NEED_MIME_NEXTLINE
6662 +#include <linux/netfilter_mime.h>
6664 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
6665 +#ifdef IP_NF_RTSP_DEBUG
6666 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
6668 +#define DEBUGP(args...)
6671 +#define MAX_PORTS 8
6672 +#define DSTACT_AUTO 0
6673 +#define DSTACT_STRIP 1
6674 +#define DSTACT_NONE 2
6676 +static int ports[MAX_PORTS];
6677 +static char* stunaddr = NULL;
6678 +static char* destaction = NULL;
6680 +static int num_ports = 0;
6681 +static u_int32_t extip = 0;
6682 +static int dstact = 0;
6684 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6685 +MODULE_DESCRIPTION("RTSP network address translation module");
6686 +MODULE_LICENSE("GPL");
6688 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6689 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6690 +MODULE_PARM(stunaddr, "s");
6691 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
6692 +MODULE_PARM(destaction, "s");
6693 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
6696 +/* protects rtsp part of conntracks */
6697 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
6699 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6701 +/*** helper functions ***/
6704 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
6706 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
6707 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
6709 + *pptcpdata = (char*)tcph + tcph->doff*4;
6710 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
6713 +/*** nat functions ***/
6716 + * Mangle the "Transport:" header:
6717 + * - Replace all occurences of "client_port=<spec>"
6718 + * - Handle destination parameter
6721 + * ct, ctinfo = conntrack context
6723 + * tranoff = Transport header offset from TCP data
6724 + * tranlen = Transport header length (incl. CRLF)
6725 + * rport_lo = replacement low port (host endian)
6726 + * rport_hi = replacement high port (host endian)
6728 + * Returns packet size difference.
6730 + * Assumes that a complete transport header is present, ending with CR or LF
6733 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
6734 + struct ip_conntrack_expect* exp,
6735 + struct sk_buff** pskb, uint tranoff, uint tranlen)
6740 + char rbuf1[16]; /* Replacement buffer (one port) */
6741 + uint rbuf1len; /* Replacement len (one port) */
6742 + char rbufa[16]; /* Replacement buffer (all ports) */
6743 + uint rbufalen; /* Replacement len (all ports) */
6745 + u_int16_t loport, hiport;
6747 + uint diff; /* Number of bytes we removed */
6749 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
6750 + struct ip_conntrack_tuple t;
6752 + char szextaddr[15+1];
6756 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6757 + ptran = ptcp+tranoff;
6759 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
6760 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6761 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
6763 + INFOP("sanity check failed\n");
6767 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
6769 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6773 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
6774 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
6775 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
6777 + rbuf1len = rbufalen = 0;
6778 + switch (prtspexp->pbtype)
6781 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
6783 + t.dst.u.udp.port = htons(loport);
6784 + if (ip_conntrack_change_expect(exp, &t) == 0)
6786 + DEBUGP("using port %hu\n", loport);
6792 + rbuf1len = sprintf(rbuf1, "%hu", loport);
6793 + rbufalen = sprintf(rbufa, "%hu", loport);
6797 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
6799 + t.dst.u.udp.port = htons(loport);
6800 + if (ip_conntrack_change_expect(exp, &t) == 0)
6802 + hiport = loport + ~exp->mask.dst.u.udp.port;
6803 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
6809 + rbuf1len = sprintf(rbuf1, "%hu", loport);
6810 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
6814 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
6816 + t.dst.u.udp.port = htons(loport);
6817 + if (ip_conntrack_change_expect(exp, &t) == 0)
6819 + DEBUGP("using port %hu (1 of 2)\n", loport);
6823 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
6825 + t.dst.u.udp.port = htons(hiport);
6826 + if (ip_conntrack_change_expect(exp, &t) == 0)
6828 + DEBUGP("using port %hu (2 of 2)\n", hiport);
6832 + if (loport != 0 && hiport != 0)
6834 + rbuf1len = sprintf(rbuf1, "%hu", loport);
6835 + if (hiport == loport+1)
6837 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
6841 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
6849 + if (rbuf1len == 0)
6851 + return 0; /* cannot get replacement port(s) */
6854 + /* Transport: tran;field;field=val,tran;field;field=val,... */
6855 + while (off < tranlen)
6858 + const char* pparamend;
6859 + uint nextparamoff;
6861 + pparamend = memchr(ptran+off, ',', tranlen-off);
6862 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
6863 + nextparamoff = pparamend-ptcp;
6866 + * We pass over each param twice. On the first pass, we look for a
6867 + * destination= field. It is handled by the security policy. If it
6868 + * is present, allowed, and equal to our external address, we assume
6869 + * that STUN is being used and we leave the client_port= field alone.
6873 + while (off < nextparamoff)
6875 + const char* pfieldend;
6876 + uint nextfieldoff;
6878 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6879 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6881 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
6883 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
6887 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
6889 + diff = nextfieldoff-off;
6890 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6891 + off, diff, NULL, 0))
6893 + /* mangle failed, all we can do is bail */
6896 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6897 + ptran = ptcp+tranoff;
6899 + nextparamoff -= diff;
6900 + nextfieldoff -= diff;
6904 + off = nextfieldoff;
6911 + while (off < nextparamoff)
6913 + const char* pfieldend;
6914 + uint nextfieldoff;
6916 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6917 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6919 + if (strncmp(ptran+off, "client_port=", 12) == 0)
6925 + char* rbuf = rbuf1;
6926 + uint rbuflen = rbuf1len;
6929 + origoff = (ptran-ptcp)+off;
6931 + numlen = nf_strtou16(ptran+off, &port);
6933 + origlen += numlen;
6934 + if (port != prtspexp->loport)
6936 + DEBUGP("multiple ports found, port %hu ignored\n", port);
6940 + if (ptran[off] == '-' || ptran[off] == '/')
6944 + numlen = nf_strtou16(ptran+off, &port);
6946 + origlen += numlen;
6948 + rbuflen = rbufalen;
6952 + * note we cannot just memcpy() if the sizes are the same.
6953 + * the mangle function does skb resizing, checks for a
6954 + * cloned skb, and updates the checksums.
6956 + * parameter 4 below is offset from start of tcp data.
6958 + diff = origlen-rbuflen;
6959 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6960 + origoff, origlen, rbuf, rbuflen))
6962 + /* mangle failed, all we can do is bail */
6965 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6966 + ptran = ptcp+tranoff;
6968 + nextparamoff -= diff;
6969 + nextfieldoff -= diff;
6973 + off = nextfieldoff;
6976 + off = nextparamoff;
6982 +static unsigned int
6983 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
6985 + struct ip_nat_multi_range mr;
6986 + u_int32_t newdstip, newsrcip, newip;
6988 + struct ip_conntrack *master = master_ct(ct);
6990 + IP_NF_ASSERT(info);
6991 + IP_NF_ASSERT(master);
6993 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6995 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6996 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6997 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
6999 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7000 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7003 + /* We don't want to manip the per-protocol, just the IPs. */
7004 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7005 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7007 + return ip_nat_setup_info(ct, &mr, hooknum);
7011 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7012 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7022 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7023 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7025 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7027 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7029 + hdrsoff = exp->seq - ntohl(tcph->seq);
7030 + hdrslen = prtspexp->len;
7033 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7039 + if (off > hdrsoff+hdrslen)
7041 + INFOP("!! overrun !!");
7044 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7046 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7048 + uint oldtcplen = tcplen;
7049 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7053 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7054 + hdrslen -= (oldtcplen-tcplen);
7055 + off -= (oldtcplen-tcplen);
7056 + lineoff -= (oldtcplen-tcplen);
7057 + linelen -= (oldtcplen-tcplen);
7058 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7066 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7067 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7069 + /* XXX: unmangle */
7074 +help(struct ip_conntrack* ct,
7075 + struct ip_conntrack_expect* exp,
7076 + struct ip_nat_info* info,
7077 + enum ip_conntrack_info ctinfo,
7078 + unsigned int hooknum,
7079 + struct sk_buff** pskb)
7081 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7082 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7085 + struct ip_ct_rtsp_expect* ct_rtsp_info;
7086 + int rc = NF_ACCEPT;
7088 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7090 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7094 + ct_rtsp_info = &exp->help.exp_rtsp_info;
7097 + * Only mangle things once: original direction in POST_ROUTING
7098 + * and reply direction on PRE_ROUTING.
7100 + dir = CTINFO2DIR(ctinfo);
7101 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7102 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7104 + DEBUGP("Not touching dir %s at hook %s\n",
7105 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7106 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7107 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7108 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7111 + DEBUGP("got beyond not touching\n");
7113 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7115 + LOCK_BH(&ip_rtsp_lock);
7116 + /* Ensure the packet contains all of the marked data */
7117 + if (!between(exp->seq + ct_rtsp_info->len,
7118 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7120 + /* Partial retransmission? Probably a hacker. */
7121 + if (net_ratelimit())
7123 + INFOP("partial packet %u/%u in %u/%u\n",
7124 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7126 + UNLOCK_BH(&ip_rtsp_lock);
7132 + case IP_CT_DIR_ORIGINAL:
7133 + rc = help_out(ct, ctinfo, exp, pskb);
7135 + case IP_CT_DIR_REPLY:
7136 + rc = help_in(ct, ctinfo, exp, pskb);
7141 + UNLOCK_BH(&ip_rtsp_lock);
7146 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7147 +static char rtsp_names[MAX_PORTS][10];
7149 +/* This function is intentionally _NOT_ defined as __exit */
7155 + for (i = 0; i < num_ports; i++)
7157 + DEBUGP("unregistering helper for port %d\n", ports[i]);
7158 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7167 + struct ip_nat_helper* hlpr;
7170 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7172 + if (ports[0] == 0)
7174 + ports[0] = RTSP_PORT;
7177 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7179 + hlpr = &ip_nat_rtsp_helpers[i];
7180 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
7182 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
7183 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7184 + hlpr->mask.src.u.tcp.port = 0xFFFF;
7185 + hlpr->mask.dst.protonum = 0xFFFF;
7186 + hlpr->help = help;
7188 + hlpr->me = THIS_MODULE;
7189 + hlpr->expect = expected;
7191 + tmpname = &rtsp_names[i][0];
7192 + if (ports[i] == RTSP_PORT)
7194 + sprintf(tmpname, "rtsp");
7198 + sprintf(tmpname, "rtsp-%d", i);
7200 + hlpr->name = tmpname;
7202 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7203 + ret = ip_nat_helper_register(hlpr);
7207 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7213 + if (stunaddr != NULL)
7215 + extip = in_aton(stunaddr);
7217 + if (destaction != NULL)
7219 + if (strcmp(destaction, "auto") == 0)
7221 + dstact = DSTACT_AUTO;
7223 + if (strcmp(destaction, "strip") == 0)
7225 + dstact = DSTACT_STRIP;
7227 + if (strcmp(destaction, "none") == 0)
7229 + dstact = DSTACT_NONE;
7237 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7238 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-03-30 05:27:01.000000000 +0200
7239 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-03-30 11:51:26.000000000 +0200
7240 @@ -266,7 +266,13 @@
7244 -/* Protocol registration. */
7246 + * ip_nat_protocol_register - Register a layer 4 protocol helper
7247 + * @proto: structure describing this helper
7249 + * This function is called by NAT layer 4 protocol helpers to register
7250 + * themselvers with the NAT core.
7252 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
7255 @@ -287,9 +293,16 @@
7259 -/* Noone stores the protocol anywhere; simply delete it. */
7261 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
7262 + * @proto: structure describing the helper
7264 + * This function is called by NAT layer 4 protocol helpers to
7265 + * unregister themselves from the NAT core.
7267 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
7269 + /* Noone stores the protocol anywhere; simply delete it. */
7270 WRITE_LOCK(&ip_nat_lock);
7271 LIST_DELETE(&protos, proto);
7272 WRITE_UNLOCK(&ip_nat_lock);
7273 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_talk.c
7274 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
7275 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-03-30 11:53:01.000000000 +0200
7278 + * talk extension for UDP NAT alteration.
7279 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7281 + * This program is free software; you can redistribute it and/or
7282 + * modify it under the terms of the GNU General Public License
7283 + * as published by the Free Software Foundation; either version
7284 + * 2 of the License, or (at your option) any later version.
7286 + * Module load syntax:
7287 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7289 + * talk=[0|1] disable|enable old talk support
7290 + * ntalk=[0|1] disable|enable ntalk support
7291 + * ntalk2=[0|1] disable|enable ntalk2 support
7293 + * The default is talk=1 ntalk=1 ntalk2=1
7297 +#include <linux/module.h>
7298 +#include <linux/netfilter_ipv4.h>
7299 +#include <linux/ip.h>
7300 +#include <linux/udp.h>
7301 +#include <linux/kernel.h>
7302 +#include <net/tcp.h>
7303 +#include <net/udp.h>
7305 +#include <linux/netfilter_ipv4/ip_nat.h>
7306 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7307 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7308 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7309 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7311 +/* Default all talk protocols are supported */
7312 +static int talk = 1;
7313 +static int ntalk = 1;
7314 +static int ntalk2 = 1;
7315 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7316 +MODULE_DESCRIPTION("talk network address translation module");
7318 +MODULE_PARM(talk, "i");
7319 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7320 +MODULE_PARM(ntalk, "i");
7321 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7322 +MODULE_PARM(ntalk2, "i");
7323 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7327 +#define DEBUGP printk
7328 +#define IP_NAT_TALK_DEBUG
7330 +#define DEBUGP(format, args...)
7333 +/* FIXME: Time out? --RR */
7336 +mangle_packet(struct sk_buff **pskb,
7337 + struct ip_conntrack *ct,
7340 + struct talk_addr *addr,
7341 + struct talk_addr *ctl_addr)
7343 + struct iphdr *iph = (*pskb)->nh.iph;
7344 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7345 + size_t udplen = (*pskb)->len - iph->ihl * 4;
7347 + /* Fortunately talk sends a structure with the address and
7348 + port in it. The size of the packet won't change. */
7350 + if (ctl_addr == NULL) {
7352 + if (addr->ta_addr == INADDR_ANY)
7354 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7355 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7356 + NIPQUAD(newip), ntohs(port));
7357 + addr->ta_addr = newip;
7358 + addr->ta_port = port;
7361 + if (addr->ta_addr != INADDR_ANY) {
7362 + /* Change address inside packet to match way we're mapping
7363 + this connection. */
7364 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7365 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7366 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7367 + ntohs(addr->ta_port));
7368 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7370 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7371 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7372 + NIPQUAD(newip), ntohs(port));
7373 + ctl_addr->ta_addr = newip;
7374 + ctl_addr->ta_port = port;
7377 + /* Fix checksums */
7378 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
7380 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7381 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
7383 + ip_send_check(iph);
7387 +static int talk_help_msg(struct ip_conntrack *ct,
7388 + struct sk_buff **pskb,
7390 + struct talk_addr *addr,
7391 + struct talk_addr *ctl_addr)
7396 + unsigned int verdict = NF_ACCEPT;
7398 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
7399 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7400 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7403 + /* Change address inside packet to match way we're mapping
7404 + this connection. */
7405 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7406 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7407 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
7408 + NIPQUAD(newip), ntohs(port));
7410 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
7411 + verdict = NF_DROP;
7416 +static int talk_help_response(struct ip_conntrack *ct,
7417 + struct ip_conntrack_expect *exp,
7418 + struct sk_buff **pskb,
7421 + struct talk_addr *addr)
7425 + struct ip_conntrack_tuple t;
7426 + struct ip_ct_talk_expect *ct_talk_info;
7428 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
7429 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7432 + LOCK_BH(&ip_talk_lock);
7433 + ct_talk_info = &exp->help.exp_talk_info;
7435 + if (!(answer == SUCCESS
7436 + && (type == LOOK_UP || type == ANNOUNCE)
7437 + && exp != NULL)) {
7438 + UNLOCK_BH(&ip_talk_lock);
7442 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
7443 + ntohs(ct_talk_info->port),
7444 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
7446 + /* Change address inside packet to match way we're mapping
7447 + this connection. */
7448 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
7449 + IP_CT_DIR_REPLY].tuple.dst.ip;
7450 + /* We can read expect here without conntrack lock, since it's
7451 + only set in ip_conntrack_talk , with ip_talk_lock held
7456 + /* Try to get same port: if not, try to change it. */
7457 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
7458 + if (type == LOOK_UP)
7459 + t.dst.u.tcp.port = htons(port);
7461 + t.dst.u.udp.port = htons(port);
7463 + if (ip_conntrack_change_expect(exp, &t) == 0) {
7464 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
7468 + UNLOCK_BH(&ip_talk_lock);
7470 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
7476 +static unsigned int talk_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,
7484 + struct iphdr *iph = (*pskb)->nh.iph;
7485 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7486 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
7487 + char *data = (char *)udph + sizeof(struct udphdr);
7490 + /* Only mangle things once: original direction in POST_ROUTING
7491 + and reply direction on PRE_ROUTING. */
7492 + dir = CTINFO2DIR(ctinfo);
7493 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7494 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7495 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
7496 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7497 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7498 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7499 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7502 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\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" : "???",
7507 + NIPQUAD(iph->saddr), ntohs(udph->source),
7508 + NIPQUAD(iph->daddr), ntohs(udph->dest),
7511 + /* Because conntrack does not drop packets, checking must be repeated here... */
7512 + if (talk_port == TALK_PORT) {
7513 + if (dir == IP_CT_DIR_ORIGINAL
7514 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
7515 + return talk_help_msg(ct, pskb,
7516 + ((struct talk_msg *)data)->type,
7517 + &(((struct talk_msg *)data)->addr),
7518 + &(((struct talk_msg *)data)->ctl_addr));
7519 + else if (dir == IP_CT_DIR_REPLY
7520 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7521 + return talk_help_response(ct, exp, pskb,
7522 + ((struct talk_response *)data)->type,
7523 + ((struct talk_response *)data)->answer,
7524 + &(((struct talk_response *)data)->addr));
7526 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
7527 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
7528 + (unsigned)udplen - sizeof(struct udphdr),
7529 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
7533 + if (dir == IP_CT_DIR_ORIGINAL) {
7535 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
7536 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
7537 + return talk_help_msg(ct, pskb,
7538 + ((struct ntalk_msg *)data)->type,
7539 + &(((struct ntalk_msg *)data)->addr),
7540 + &(((struct ntalk_msg *)data)->ctl_addr));
7542 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
7543 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
7544 + && udplen == sizeof(struct udphdr)
7545 + + sizeof(struct ntalk2_msg)
7546 + + ((struct ntalk2_msg *)data)->extended)
7547 + return talk_help_msg(ct, pskb,
7548 + ((struct ntalk2_msg *)data)->type,
7549 + &(((struct ntalk2_msg *)data)->addr),
7550 + &(((struct ntalk2_msg *)data)->ctl_addr));
7552 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
7553 + (unsigned)udplen - sizeof(struct udphdr),
7554 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
7559 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7560 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7561 + return talk_help_response(ct, exp, pskb,
7562 + ((struct ntalk_response *)data)->type,
7563 + ((struct ntalk_response *)data)->answer,
7564 + &(((struct ntalk_response *)data)->addr));
7566 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7567 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7568 + return talk_help_response(ct, exp, pskb,
7569 + ((struct ntalk2_response *)data)->type,
7570 + ((struct ntalk2_response *)data)->answer,
7571 + &(((struct ntalk2_response *)data)->addr));
7573 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
7574 + (unsigned)udplen - sizeof(struct udphdr),
7575 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7582 +static unsigned int help(struct ip_conntrack *ct,
7583 + struct ip_conntrack_expect *exp,
7584 + struct ip_nat_info *info,
7585 + enum ip_conntrack_info ctinfo,
7586 + unsigned int hooknum,
7587 + struct sk_buff **pskb)
7589 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
7592 +static unsigned int nhelp(struct ip_conntrack *ct,
7593 + struct ip_conntrack_expect *exp,
7594 + struct ip_nat_info *info,
7595 + enum ip_conntrack_info ctinfo,
7596 + unsigned int hooknum,
7597 + struct sk_buff **pskb)
7599 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
7602 +static unsigned int
7603 +talk_nat_expected(struct sk_buff **pskb,
7604 + unsigned int hooknum,
7605 + struct ip_conntrack *ct,
7606 + struct ip_nat_info *info);
7608 +static struct ip_nat_helper talk_helpers[2] =
7609 + { { { NULL, NULL },
7610 + "talk", /* name */
7611 + IP_NAT_HELPER_F_ALWAYS, /* flags */
7612 + THIS_MODULE, /* module */
7613 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
7614 + { 0, { 0 }, IPPROTO_UDP } },
7615 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
7616 + { 0, { 0 }, 0xFFFF } },
7617 + help, /* helper */
7618 + talk_nat_expected }, /* expectfn */
7620 + "ntalk", /* name */
7621 + IP_NAT_HELPER_F_ALWAYS, /* flags */
7622 + THIS_MODULE, /* module */
7623 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
7624 + { 0, { 0 }, IPPROTO_UDP } },
7625 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
7626 + { 0, { 0 }, 0xFFFF } },
7627 + nhelp, /* helper */
7628 + talk_nat_expected } /* expectfn */
7631 +static unsigned int
7632 +talk_nat_expected(struct sk_buff **pskb,
7633 + unsigned int hooknum,
7634 + struct ip_conntrack *ct,
7635 + struct ip_nat_info *info)
7637 + struct ip_nat_multi_range mr;
7638 + u_int32_t newdstip, newsrcip, newip;
7642 + struct ip_conntrack *master = master_ct(ct);
7644 + IP_NF_ASSERT(info);
7645 + IP_NF_ASSERT(master);
7647 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
7649 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
7651 + LOCK_BH(&ip_talk_lock);
7652 + port = ct->master->help.exp_talk_info.port;
7653 + UNLOCK_BH(&ip_talk_lock);
7655 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
7656 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7657 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7658 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7659 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7662 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
7663 + /* Callee client -> caller server */
7664 +#ifdef IP_NAT_TALK_DEBUG
7665 + struct iphdr *iph = (*pskb)->nh.iph;
7666 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7668 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7669 + NIPQUAD(iph->saddr), ntohs(udph->source),
7670 + NIPQUAD(iph->daddr), ntohs(udph->dest));
7672 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7673 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7674 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
7675 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
7677 + /* Callee client -> caller client */
7678 +#ifdef IP_NAT_TALK_DEBUG
7679 + struct iphdr *iph = (*pskb)->nh.iph;
7680 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
7682 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7683 + NIPQUAD(iph->saddr), ntohs(tcph->source),
7684 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
7686 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
7687 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7688 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
7689 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
7691 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7696 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
7699 + /* We don't want to manip the per-protocol, just the IPs... */
7700 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7701 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7703 + /* ... unless we're doing a MANIP_DST, in which case, make
7704 + sure we map to the correct port */
7705 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
7706 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
7707 + mr.range[0].min = mr.range[0].max
7708 + = ((union ip_conntrack_manip_proto)
7709 + { .udp = { port } });
7711 + ret = ip_nat_setup_info(ct, &mr, hooknum);
7713 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
7714 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
7715 + /* NAT expectfn called with ip_nat_lock write-locked */
7716 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
7721 +static int __init init(void)
7726 + ret = ip_nat_helper_register(&talk_helpers[0]);
7731 + if (ntalk > 0 || ntalk2 > 0) {
7732 + ret = ip_nat_helper_register(&talk_helpers[1]);
7734 + if (ret != 0 && talk > 0)
7735 + ip_nat_helper_unregister(&talk_helpers[0]);
7740 +static void __exit fini(void)
7743 + ip_nat_helper_unregister(&talk_helpers[0]);
7744 + if (ntalk > 0 || ntalk2 > 0)
7745 + ip_nat_helper_unregister(&talk_helpers[1]);
7750 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_tables.c
7751 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-03-30 11:31:19.000000000 +0200
7752 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_tables.c 2004-03-30 11:51:11.000000000 +0200
7754 * it under the terms of the GNU General Public License version 2 as
7755 * published by the Free Software Foundation.
7757 + * 6 Mar 2002 Robert Olsson <robban@robtex.com>
7758 + * 17 Apr 2003 Chris Wilson <chris@netservers.co.uk>
7759 + * - mark_source_chains speedup for complex chains
7761 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
7762 * - increase module usage count as soon as we have rules inside
7768 + /* keep track of where we have been: */
7769 + unsigned char *been = vmalloc(newinfo->size);
7771 /* No recursion; use packet counter to save back ptrs (reset
7772 to 0 as we leave), and comefrom to save source hook bitmask */
7773 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
7776 /* Set initial back pointer. */
7777 e->counters.pcnt = pos;
7778 + memset(been, 0, newinfo->size);
7781 struct ipt_standard_target *t
7783 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
7784 printk("iptables: loop hook %u pos %u %08X.\n",
7785 hook, pos, e->comefrom);
7790 @@ -565,10 +574,14 @@
7792 int newpos = t->verdict;
7794 - if (strcmp(t->target.u.user.name,
7795 + if ( (pos < 0 || pos >= newinfo->size
7797 + && strcmp(t->target.u.user.name,
7798 IPT_STANDARD_TARGET) == 0
7800 /* This a jump; chase it. */
7801 + if (pos >= 0 && pos < newinfo->size)
7803 duprintf("Jump rule %u -> %u\n",
7808 duprintf("Finished chain %u\n", hook);
7814 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
7815 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
7816 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-03-30 11:48:14.000000000 +0200
7818 +/* This kernel module is used to modify the connection mark values, or
7819 + * to optionally restore the skb nfmark from the connection mark
7821 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
7822 + * by Henrik Nordstrom <hno@marasystems.com>
7824 + * This program is free software; you can redistribute it and/or modify
7825 + * it under the terms of the GNU General Public License as published by
7826 + * the Free Software Foundation; either version 2 of the License, or
7827 + * (at your option) any later version.
7829 + * This program is distributed in the hope that it will be useful,
7830 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7831 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7832 + * GNU General Public License for more details.
7834 + * You should have received a copy of the GNU General Public License
7835 + * along with this program; if not, write to the Free Software
7836 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7838 +#include <linux/module.h>
7839 +#include <linux/skbuff.h>
7840 +#include <linux/ip.h>
7841 +#include <net/checksum.h>
7843 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
7844 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
7845 +MODULE_LICENSE("GPL");
7847 +#include <linux/netfilter_ipv4/ip_tables.h>
7848 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
7849 +#include <linux/netfilter_ipv4/ip_conntrack.h>
7851 +static unsigned int
7852 +target(struct sk_buff **pskb,
7853 + const struct net_device *in,
7854 + const struct net_device *out,
7855 + unsigned int hooknum,
7856 + const void *targinfo,
7859 + const struct ipt_connmark_target_info *markinfo = targinfo;
7860 + unsigned long diff;
7861 + unsigned long nfmark;
7862 + unsigned long newmark;
7864 + enum ip_conntrack_info ctinfo;
7865 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
7867 + switch(markinfo->mode) {
7868 + case IPT_CONNMARK_SET:
7869 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
7870 + if (newmark != ct->mark)
7871 + ct->mark = newmark;
7873 + case IPT_CONNMARK_SAVE:
7874 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
7875 + if (ct->mark != newmark)
7876 + ct->mark = newmark;
7878 + case IPT_CONNMARK_RESTORE:
7879 + nfmark = (*pskb)->nfmark;
7880 + diff = (ct->mark ^ nfmark & markinfo->mask);
7882 + (*pskb)->nfmark = nfmark ^ diff;
7883 + (*pskb)->nfcache |= NFC_ALTERED;
7889 + return IPT_CONTINUE;
7893 +checkentry(const char *tablename,
7894 + const struct ipt_entry *e,
7896 + unsigned int targinfosize,
7897 + unsigned int hook_mask)
7899 + struct ipt_connmark_target_info *matchinfo = targinfo;
7900 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
7901 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
7903 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
7907 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
7908 + if (strcmp(tablename, "mangle") != 0) {
7909 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
7917 +static struct ipt_target ipt_connmark_reg = {
7918 + .name = "CONNMARK",
7919 + .target = &target,
7920 + .checkentry = &checkentry,
7924 +static int __init init(void)
7926 + return ipt_register_target(&ipt_connmark_reg);
7929 +static void __exit fini(void)
7931 + ipt_unregister_target(&ipt_connmark_reg);
7936 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_IPMARK.c
7937 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
7938 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-03-30 11:48:25.000000000 +0200
7940 +/* This is a module which is used for setting the NFMARK field of an skb. */
7941 +#include <linux/module.h>
7942 +#include <linux/skbuff.h>
7943 +#include <linux/ip.h>
7944 +#include <net/checksum.h>
7946 +#include <linux/netfilter_ipv4/ip_tables.h>
7947 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
7949 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
7950 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
7951 +MODULE_LICENSE("GPL");
7953 +static unsigned int
7954 +target(struct sk_buff **pskb,
7955 + const struct net_device *in,
7956 + const struct net_device *out,
7957 + unsigned int hooknum,
7958 + const void *targinfo,
7961 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
7962 + struct iphdr *iph = (*pskb)->nh.iph;
7963 + unsigned long mark;
7965 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
7966 + mark = (unsigned long) ntohl(iph->saddr);
7968 + mark = (unsigned long) ntohl(iph->daddr);
7970 + mark &= ipmarkinfo->andmask;
7971 + mark |= ipmarkinfo->ormask;
7973 + if ((*pskb)->nfmark != mark) {
7974 + (*pskb)->nfmark = mark;
7975 + (*pskb)->nfcache |= NFC_ALTERED;
7977 + return IPT_CONTINUE;
7981 +checkentry(const char *tablename,
7982 + const struct ipt_entry *e,
7984 + unsigned int targinfosize,
7985 + unsigned int hook_mask)
7987 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
7988 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
7990 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
7994 + if (strcmp(tablename, "mangle") != 0) {
7995 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8002 +static struct ipt_target ipt_ipmark_reg = {
8005 + .checkentry = checkentry,
8009 +static int __init init(void)
8011 + return ipt_register_target(&ipt_ipmark_reg);
8014 +static void __exit fini(void)
8016 + ipt_unregister_target(&ipt_ipmark_reg);
8021 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_ROUTE.c
8022 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
8023 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_ROUTE.c 2004-03-30 11:48:31.000000000 +0200
8026 + * This implements the ROUTE target, which enables you to setup unusual
8027 + * routes not supported by the standard kernel routing table.
8029 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
8031 + * v 1.8 2003/07/25
8033 + * This software is distributed under GNU GPL v2, 1991
8036 +#include <linux/module.h>
8037 +#include <linux/skbuff.h>
8038 +#include <linux/ip.h>
8039 +#include <linux/netfilter_ipv4/ip_tables.h>
8040 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
8041 +#include <linux/netdevice.h>
8042 +#include <linux/route.h>
8043 +#include <net/ip.h>
8044 +#include <net/route.h>
8045 +#include <net/icmp.h>
8048 +#define DEBUGP printk
8050 +#define DEBUGP(format, args...)
8053 +MODULE_LICENSE("GPL");
8054 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
8056 +/* Try to route the packet according to the routing keys specified in
8057 + * route_info. Keys are :
8059 + * 0 if no oif preferred,
8060 + * otherwise set to the index of the desired oif
8061 + * - route_info->gw :
8062 + * 0 if no gateway specified,
8063 + * otherwise set to the next host to which the pkt must be routed
8064 + * If success, skb->dev is the output device to which the packet must
8065 + * be sent and skb->dst is not NULL
8067 + * RETURN: -1 if an error occured
8068 + * 1 if the packet was succesfully routed to the
8069 + * destination desired
8070 + * 0 if the kernel routing table could not route the packet
8071 + * according to the keys specified
8073 +static int route(struct sk_buff *skb,
8074 + unsigned int ifindex,
8075 + const struct ipt_route_target_info *route_info)
8078 + struct rtable *rt;
8079 + struct iphdr *iph = skb->nh.iph;
8080 + struct rt_key key = {
8084 + tos:RT_TOS(iph->tos)
8087 + /* The destination address may be overloaded by the target */
8088 + if (route_info->gw)
8089 + key.dst = route_info->gw;
8091 + /* Trying to route the packet using the standard routing table. */
8092 + if ((err = ip_route_output_key(&rt, &key))) {
8093 + if (net_ratelimit())
8094 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
8098 + /* Drop old route. */
8099 + dst_release(skb->dst);
8102 + /* Success if no oif specified or if the oif correspond to the
8104 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
8105 + skb->dst = &rt->u.dst;
8106 + skb->dev = skb->dst->dev;
8110 + /* The interface selected by the routing table is not the one
8111 + * specified by the user. This may happen because the dst address
8112 + * is one of our own addresses.
8114 + if (net_ratelimit())
8115 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
8116 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
8122 +/* Stolen from ip_finish_output2
8123 + * PRE : skb->dev is set to the device we are leaving by
8124 + * skb->dst is not NULL
8125 + * POST: the packet is sent with the link layer header pushed
8126 + * the packet is destroyed
8128 +static void ip_direct_send(struct sk_buff *skb)
8130 + struct dst_entry *dst = skb->dst;
8131 + struct hh_cache *hh = dst->hh;
8134 + read_lock_bh(&hh->hh_lock);
8135 + memcpy(skb->data - 16, hh->hh_data, 16);
8136 + read_unlock_bh(&hh->hh_lock);
8137 + skb_push(skb, hh->hh_len);
8138 + hh->hh_output(skb);
8139 + } else if (dst->neighbour)
8140 + dst->neighbour->output(skb);
8142 + if (net_ratelimit())
8143 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
8149 +/* PRE : skb->dev is set to the device we are leaving by
8150 + * POST: - the packet is directly sent to the skb->dev device, without
8151 + * pushing the link layer header.
8152 + * - the packet is destroyed
8154 +static inline int dev_direct_send(struct sk_buff *skb)
8156 + return dev_queue_xmit(skb);
8160 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
8161 + struct sk_buff *skb)
8163 + unsigned int ifindex = 0;
8164 + struct net_device *dev_out = NULL;
8166 + /* The user set the interface name to use.
8167 + * Getting the current interface index.
8169 + if ((dev_out = dev_get_by_name(route_info->oif))) {
8170 + ifindex = dev_out->ifindex;
8172 + /* Unknown interface name : packet dropped */
8173 + if (net_ratelimit())
8174 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
8178 + /* Trying the standard way of routing packets */
8179 + switch (route(skb, ifindex, route_info)) {
8182 + if (route_info->flags & IPT_ROUTE_CONTINUE)
8183 + return IPT_CONTINUE;
8185 + ip_direct_send(skb);
8189 + /* Failed to send to oif. Trying the hard way */
8190 + if (route_info->flags & IPT_ROUTE_CONTINUE)
8193 + if (net_ratelimit())
8194 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
8197 + /* We have to force the use of an interface.
8198 + * This interface must be a tunnel interface since
8199 + * otherwise we can't guess the hw address for
8200 + * the packet. For a tunnel interface, no hw address
8203 + if ((dev_out->type != ARPHRD_TUNNEL)
8204 + && (dev_out->type != ARPHRD_IPGRE)) {
8205 + if (net_ratelimit())
8206 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
8211 + /* Send the packet. This will also free skb
8212 + * Do not go through the POST_ROUTING hook because
8213 + * skb->dst is not set and because it will probably
8214 + * get confused by the destination IP address.
8216 + skb->dev = dev_out;
8217 + dev_direct_send(skb);
8222 + /* Unexpected error */
8229 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
8230 + struct sk_buff *skb)
8232 + struct net_device *dev_out = NULL;
8233 + unsigned int ifindex = 0;
8235 + /* Getting the current interface index. */
8236 + if ((dev_out = dev_get_by_name(route_info->iif)))
8237 + ifindex = dev_out->ifindex;
8239 + /* Unknown interface name : packet dropped */
8240 + if (net_ratelimit())
8241 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
8245 + skb->dev = dev_out;
8246 + dst_release(skb->dst);
8255 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
8256 + struct sk_buff *skb)
8258 + if (route(skb, 0, route_info)!=1)
8261 + if (route_info->flags & IPT_ROUTE_CONTINUE)
8262 + return IPT_CONTINUE;
8264 + ip_direct_send(skb);
8269 +static unsigned int ipt_route_target(struct sk_buff **pskb,
8270 + const struct net_device *in,
8271 + const struct net_device *out,
8272 + unsigned int hooknum,
8273 + const void *targinfo,
8276 + const struct ipt_route_target_info *route_info = targinfo;
8277 + struct sk_buff *skb = *pskb;
8279 + /* If we are at PREROUTING or INPUT hook
8280 + * the TTL isn't decreased by the IP stack
8282 + if (hooknum == NF_IP_PRE_ROUTING ||
8283 + hooknum == NF_IP_LOCAL_IN) {
8285 + struct iphdr *iph = skb->nh.iph;
8287 + if (iph->ttl <= 1) {
8288 + struct rtable *rt;
8290 + if (ip_route_output(&rt, iph->saddr, iph->daddr,
8291 + RT_TOS(iph->tos) | RTO_CONN,
8296 + if (skb->dev == rt->u.dst.dev) {
8297 + /* Drop old route. */
8298 + dst_release(skb->dst);
8299 + skb->dst = &rt->u.dst;
8301 + /* this will traverse normal stack, and
8302 + * thus call conntrack on the icmp packet */
8303 + icmp_send(skb, ICMP_TIME_EXCEEDED,
8310 + ip_decrease_ttl(iph);
8313 + /* Tell conntrack to forget this packet since it may get confused
8314 + * when a packet is leaving with dst address == our address.
8315 + * Good idea ? Dunno. Need advice.
8317 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
8318 + nf_conntrack_put(skb->nfct);
8321 +#ifdef CONFIG_NETFILTER_DEBUG
8322 + skb->nf_debug = 0;
8326 + if (route_info->oif[0])
8327 + return route_oif(route_info, *pskb);
8329 + if (route_info->iif[0])
8330 + return route_iif(route_info, *pskb);
8332 + if (route_info->gw)
8333 + return route_gw(route_info, *pskb);
8335 + if (net_ratelimit())
8336 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
8338 + return IPT_CONTINUE;
8342 +static int ipt_route_checkentry(const char *tablename,
8343 + const struct ipt_entry *e,
8345 + unsigned int targinfosize,
8346 + unsigned int hook_mask)
8348 + if (strcmp(tablename, "mangle") != 0) {
8349 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
8354 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
8355 + | (1 << NF_IP_LOCAL_IN)
8356 + | (1 << NF_IP_FORWARD)
8357 + | (1 << NF_IP_LOCAL_OUT)
8358 + | (1 << NF_IP_POST_ROUTING))) {
8359 + printk("ipt_ROUTE: bad hook\n");
8363 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
8364 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
8366 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
8374 +static struct ipt_target ipt_route_reg = {
8376 + .target = ipt_route_target,
8377 + .checkentry = ipt_route_checkentry,
8378 + .me = THIS_MODULE,
8381 +static int __init init(void)
8383 + return ipt_register_target(&ipt_route_reg);
8387 +static void __exit fini(void)
8389 + ipt_unregister_target(&ipt_route_reg);
8394 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TARPIT.c
8395 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
8396 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-03-30 11:50:27.000000000 +0200
8399 + * Kernel module to capture and hold incoming TCP connections using
8400 + * no local per-connection resources.
8402 + * Based on ipt_REJECT.c and offering functionality similar to
8403 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
8405 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
8407 + * This program is free software; you can redistribute it and/or modify
8408 + * it under the terms of the GNU General Public License as published by
8409 + * the Free Software Foundation; either version 2 of the License, or
8410 + * (at your option) any later version.
8412 + * This program is distributed in the hope that it will be useful,
8413 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8414 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8415 + * GNU General Public License for more details.
8417 + * You should have received a copy of the GNU General Public License
8418 + * along with this program; if not, write to the Free Software
8419 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8422 + * - Allow incoming TCP connections to be established.
8423 + * - Passing data should result in the connection being switched to the
8424 + * persist state (0 byte window), in which the remote side stops sending
8425 + * data and asks to continue every 60 seconds.
8426 + * - Attempts to shut down the connection should be ignored completely, so
8427 + * the remote side ends up having to time it out.
8430 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
8431 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
8432 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
8435 +#include <linux/config.h>
8436 +#include <linux/module.h>
8437 +#include <linux/skbuff.h>
8438 +#include <linux/ip.h>
8439 +#include <net/ip.h>
8440 +#include <net/tcp.h>
8441 +#include <net/icmp.h>
8443 +#include <net/route.h>
8444 +#include <linux/random.h>
8445 +#include <linux/netfilter_ipv4/ip_tables.h>
8448 +#define DEBUGP printk
8450 +#define DEBUGP(format, args...)
8453 +MODULE_LICENSE("GPL");
8454 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
8456 +/* Stolen from ip_finish_output2 */
8457 +static int ip_direct_send(struct sk_buff *skb)
8459 + struct dst_entry *dst = skb->dst;
8460 + struct hh_cache *hh = dst->hh;
8463 + read_lock_bh(&hh->hh_lock);
8464 + memcpy(skb->data - 16, hh->hh_data, 16);
8465 + read_unlock_bh(&hh->hh_lock);
8466 + skb_push(skb, hh->hh_len);
8467 + return hh->hh_output(skb);
8468 + } else if (dst->neighbour)
8469 + return dst->neighbour->output(skb);
8471 + if (net_ratelimit())
8472 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
8479 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
8481 + struct sk_buff *nskb;
8482 + struct rtable *nrt;
8483 + struct tcphdr *otcph, *ntcph;
8484 + unsigned int otcplen;
8487 + /* A truncated TCP header isn't going to be useful */
8488 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
8491 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
8492 + + oskb->nh.iph->ihl);
8493 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
8495 + /* No replies for RST or FIN */
8496 + if (otcph->rst || otcph->fin)
8499 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
8500 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
8503 + /* Check checksum. */
8504 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
8505 + oskb->nh.iph->daddr,
8506 + csum_partial((char *)otcph, otcplen, 0)) != 0)
8509 + /* Copy skb (even if skb is about to be dropped, we can't just
8510 + clone it because there may be other things, such as tcpdump,
8511 + interested in it) */
8512 + nskb = skb_copy(oskb, GFP_ATOMIC);
8516 + /* This packet will not be the same as the other: clear nf fields */
8517 + nf_conntrack_put(nskb->nfct);
8518 + nskb->nfct = NULL;
8519 + nskb->nfcache = 0;
8520 +#ifdef CONFIG_NETFILTER_DEBUG
8521 + nskb->nf_debug = 0;
8524 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
8526 + /* Truncate to length (no data) */
8527 + ntcph->doff = sizeof(struct tcphdr)/4;
8528 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
8529 + nskb->nh.iph->tot_len = htons(nskb->len);
8531 + /* Swap source and dest */
8532 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
8533 + tmp = ntcph->source;
8534 + ntcph->source = ntcph->dest;
8535 + ntcph->dest = tmp;
8537 + /* Use supplied sequence number or make a new one */
8538 + ntcph->seq = otcph->ack ? otcph->ack_seq
8539 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
8540 + nskb->nh.iph->daddr,
8544 + /* Our SYN-ACKs must have a >0 window */
8545 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
8547 + ntcph->urg_ptr = 0;
8550 + ((u_int8_t *)ntcph)[13] = 0;
8552 + if (otcph->syn && otcph->ack) {
8554 + ntcph->ack_seq = 0;
8556 + ntcph->syn = otcph->syn;
8558 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
8561 + /* Adjust TCP checksum */
8563 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
8564 + nskb->nh.iph->saddr,
8565 + nskb->nh.iph->daddr,
8566 + csum_partial((char *)ntcph,
8567 + sizeof(struct tcphdr), 0));
8569 + /* Adjust IP TTL */
8570 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
8572 + /* Set DF, id = 0 */
8573 + nskb->nh.iph->frag_off = htons(IP_DF);
8574 + nskb->nh.iph->id = 0;
8576 + /* Adjust IP checksum */
8577 + nskb->nh.iph->check = 0;
8578 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
8579 + nskb->nh.iph->ihl);
8581 + if (ip_route_output(&nrt, nskb->nh.iph->daddr,
8582 + local ? nskb->nh.iph->saddr : 0,
8583 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
8587 + dst_release(nskb->dst);
8588 + nskb->dst = &nrt->u.dst;
8590 + /* "Never happens" */
8591 + if (nskb->len > nskb->dst->pmtu)
8594 + ip_direct_send (nskb);
8603 +static unsigned int tarpit(struct sk_buff **pskb,
8604 + const struct net_device *in,
8605 + const struct net_device *out,
8606 + unsigned int hooknum,
8607 + const void *targinfo,
8610 + struct sk_buff *skb = *pskb;
8611 + struct rtable *rt = (struct rtable*)skb->dst;
8613 + /* Do we have an input route cache entry? */
8617 + /* No replies to physical multicast/broadcast */
8618 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
8621 + /* Now check at the protocol level */
8622 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
8625 + /* Our naive response construction doesn't deal with IP
8626 + options, and probably shouldn't try. */
8627 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
8630 + /* We aren't interested in fragments */
8631 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
8634 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
8640 +static int check(const char *tablename,
8641 + const struct ipt_entry *e,
8643 + unsigned int targinfosize,
8644 + unsigned int hook_mask)
8646 + /* Only allow these for input/forward packet filtering. */
8647 + if (strcmp(tablename, "filter") != 0) {
8648 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
8651 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
8652 + | (1 << NF_IP_FORWARD))) != 0) {
8653 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
8657 + /* Must specify that it's a TCP packet */
8658 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
8659 + DEBUGP("TARPIT: not valid for non-tcp\n");
8666 +static struct ipt_target ipt_tarpit_reg = {
8669 + .checkentry = check,
8673 +static int __init init(void)
8675 + return ipt_register_target(&ipt_tarpit_reg);
8678 +static void __exit fini(void)
8680 + ipt_unregister_target(&ipt_tarpit_reg);
8685 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TCPLAG.c
8686 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
8687 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TCPLAG.c 2004-03-30 11:50:30.000000000 +0200
8689 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
8690 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
8692 + * This program is free software; you can redistribute it and/or modify
8693 + * it under the terms of the GNU General Public License as published by
8694 + * the Free Software Foundation; either version 2 of the License, or
8695 + * (at your option) any later version.
8697 + * This program is distributed in the hope that it will be useful,
8698 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8699 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8700 + * GNU General Public License for more details.
8702 + * You should have received a copy of the GNU General Public License
8703 + * along with this program; if not, write to the Free Software
8704 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8708 + * This collects packets and attempts to make them into pairs
8709 + * based on its own knowledge of how typical network conversations
8710 + * operate. Once it has a pair, it logs the time between them.
8712 +#include <linux/module.h>
8713 +#include <linux/skbuff.h>
8714 +#include <linux/ip.h>
8715 +#include <linux/spinlock.h>
8716 +#include <net/icmp.h>
8717 +#include <net/udp.h>
8718 +#include <net/tcp.h>
8719 +#include <linux/netfilter_ipv4/ip_tables.h>
8721 +#include <net/route.h>
8722 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
8725 +#define DEBUGP printk
8727 +#define DEBUGP(format, args...)
8731 + * We need one spinlock for the hash table.
8733 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
8735 +typedef struct timeval timeval_T;
8738 + * Linked lists of events in the connection,
8739 + * these store the SEQ numbers and the newest is always
8740 + * at the start of the linked list, then they get older
8741 + * down to the end of the linked list (this is not perfect
8742 + * if packets get out of order but we don't worry about fine
8743 + * details like that).
8745 + * Matching any event wipes out that event and also all other
8746 + * events down the chain (i.e. all older events).
8747 + * This keeps the linked list as short as possible.
8749 +typedef struct tcplag_event_S
8751 + struct tcplag_event_S *next;
8755 + struct timeval stamp;
8759 + * This stores the connection statistics
8760 + * We define connections more loosely than TCP/IP does,
8761 + * because we only consider the two hosts, not the ports
8762 + * Also, we list the host-pairs in low,high order which
8763 + * means that we don't care who originated the connection.
8765 +typedef struct tcplag_hash_S
8769 + struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
8770 + struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
8771 + tcplag_event_T *h_ACK_list; /* Try to match ACK packets coming from h in this list */
8772 + tcplag_event_T *l_ACK_list; /* Try to match ACK packets coming from l in this list */
8773 + time_t stamp; /* When this bucket got added to the table */
8774 + u16 count_l_SEQ_h_ACK; /* Increment for each event */
8775 + u16 count_h_SEQ_l_ACK; /* Increment for each event */
8778 +static tcplag_hash_T **hashtab = 0;
8779 +static u32 hashsize = 0;
8780 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
8781 +static u32 reaper_ix = 0;
8783 +static void divide_down( timeval_T *T, int c )
8788 + remainder = T->tv_sec % c; /* Only works properly with positive numbers */
8789 + remainder *= 1000000;
8790 + T->tv_usec == remainder;
8794 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
8798 + x = tv1->tv_sec - tv2->tv_sec;
8799 + if( x ) return( x );
8800 + x = tv1->tv_usec - tv2->tv_usec;
8804 +void sprint_timeval( char *buf, timeval_T *tv )
8807 + sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
8809 + sprintf( buf, "%lu", tv->tv_usec );
8813 + * This generates the log messages through printk()
8815 + * There is really no particular interest in the port numbers at this stage,
8816 + * they are only useful for matching up the request with the reply.
8817 + * The IP numbers are useful because some sites may be slower than others
8818 + * or may travel different routes, etc (OK, in theory changing the port number
8819 + * could also change the route but I don't like that sort of theory).
8823 + * LIP= The IP number of the side with the lowest lag
8824 + * RIP= The IP number of the side with the highest lag
8825 + * LLAG= The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
8826 + * RLAG= The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
8828 +static void output( tcplag_hash_T *H, int level, const char *prefix )
8830 + struct timeval ltm, rtm;
8831 + u32 local_ip, remote_ip;
8832 + char r_buf[ 20 ], l_buf[ 20 ];
8834 + * We can't make sense of a connection that only passes data one way,
8835 + * In principle, at least the SYN and FIN should go both ways so we
8836 + * should get a few hits for every connection.
8838 + if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
8840 + * Calculate average times by dividing down
8842 + divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
8843 + divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
8845 + * Sort these two by the lag so the the local is always the short lag
8847 + if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
8849 + local_ip = H->low_ip;
8850 + remote_ip = H->high_ip;
8851 + rtm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
8852 + rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
8853 + ltm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
8854 + ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
8858 + local_ip = H->high_ip;
8859 + remote_ip = H->low_ip;
8860 + ltm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
8861 + ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
8862 + rtm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
8863 + rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
8866 + * Don't use a spinlock on the output,
8867 + * it is not guaranteed safe because some OTHER printk could
8868 + * split our log message so we want only one single printk.
8870 + * We use sprintf() to partially pre-digest the output
8872 + * Actually, neither this not the main netfilter LOG target is
8873 + * really safe from printk() overlap, basically syslog cannot
8874 + * be regarded as a guaranteed data output channel. It is good
8875 + * enough for most purposes.
8877 + sprint_timeval( l_buf, <m );
8878 + sprint_timeval( r_buf, &rtm );
8879 + printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
8880 + level & 7, prefix,
8881 + NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
8886 + * The reaper rolls through the hash table looking for old.
8887 + * Log entries are only generated at the reaping time
8888 + * (which means all log entries are out-of-date)
8890 +static void reaper( time_t now, int level, const char *prefix )
8894 + now -= max_seconds;
8895 + if( !hashsize ) return;
8896 + if( !hashtab ) return;
8897 + for( i = 0; i < 10; i++ )
8899 + if( ++reaper_ix >= hashsize ) reaper_ix = 0;
8901 +// DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
8903 + if( hashtab[ reaper_ix ])
8905 + tcplag_hash_T *found = 0;
8907 + spin_lock_bh( &hash_lock );
8908 + if( hashtab[ reaper_ix ])
8910 + if( now > hashtab[ reaper_ix ]->stamp )
8912 + DEBUGP( KERN_WARNING "reaper found expired entry\n" );
8913 + found = hashtab[ reaper_ix ];
8914 + hashtab[ reaper_ix ] = 0;
8917 + spin_unlock_bh( &hash_lock );
8921 + output( found, level, prefix );
8929 + * Convert the connection characteristics into a number
8930 + * (not including the timestamp) FIXME: this is a sucky hash function
8932 +static u32 make_hash( tcplag_hash_T *connection )
8936 + r = connection->low_ip;
8937 + r += connection->high_ip;
8941 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
8945 + x = con1->low_ip - con2->low_ip; if( x ) return( x );
8946 + x = con1->high_ip - con2->high_ip;
8950 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
8954 + DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
8955 + x = ev1->expected_ACK - ev2->expected_ACK;
8956 + if( x ) return( x );
8957 + DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
8958 + x = ev1->source_port - ev2->source_port;
8959 + if( x ) return( x );
8960 + DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
8961 + x = ev1->dest_port - ev2->dest_port;
8966 + * Go to the hash table and either find an existing connection that
8967 + * matches correctly or inject a new connection into the table.
8968 + * Once the connection is OK, chain the event onto the linked list.
8970 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
8974 + if( !event ) return; /* Just to be safe */
8975 + if( !hashsize ) return;
8976 + if( !hashtab ) return;
8978 + h = make_hash( connection );
8981 + DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
8983 + spin_lock_bh( &hash_lock );
8984 + for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
8986 + tcplag_hash_T *co_new = 0;
8988 + * Consider existing entry
8992 + if( compare_connections( hashtab[ h ], connection )) continue;
8993 + co_new = hashtab[ h ];
8994 + DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
8998 + * Use empty slot for new entry
9000 + if( !hashtab[ h ])
9002 + co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
9003 + memset( co_new, 0, sizeof( tcplag_hash_T ));
9004 + co_new->low_ip = connection->low_ip;
9005 + co_new->high_ip = connection->high_ip;
9006 + co_new->stamp = event->stamp.tv_sec;
9007 + hashtab[ h ] = co_new;
9008 + DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
9011 + tcplag_event_T *ev_new;
9013 + ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
9014 + memcpy( ev_new, event, sizeof( tcplag_event_T ));
9017 + ev_new->next = co_new->h_ACK_list;
9018 + co_new->h_ACK_list = ev_new;
9019 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
9023 + ev_new->next = co_new->l_ACK_list;
9024 + co_new->l_ACK_list = ev_new;
9025 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
9032 + spin_unlock_bh( &hash_lock );
9036 + * Search the hash table for a matching connection,
9037 + * if we can't find one of those then we are stuffed.
9039 + * Once a connection has been found, scan along the list for
9040 + * a matching SEQ number and if that is found then calculate
9041 + * the lag, update the counters and cut the chain at the
9042 + * point where the matching SEQ is found.
9044 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
9048 + if( !event ) return( 0 );
9049 + if( !hashsize ) return( 0 );
9050 + if( !hashtab ) return( 0 );
9051 + h = make_hash( connection );
9054 + DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
9056 + for( i = 0; i < hashsize; i++ )
9058 + tcplag_hash_T *found = 0;
9060 + if( !hashtab[ h ]) return( 0 );
9062 + spin_lock_bh( &hash_lock );
9065 + if( !compare_connections( hashtab[ h ], connection ))
9067 + tcplag_event_T *ev, **evroot;
9071 + found = hashtab[ h ];
9074 + evroot = &found->h_ACK_list;
9075 + tv = &found->lag_l_SEQ_h_ACK;
9076 + cn = &found->count_l_SEQ_h_ACK;
9077 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
9081 + evroot = &found->l_ACK_list;
9082 + tv = &found->lag_h_SEQ_l_ACK;
9083 + cn = &found->count_h_SEQ_l_ACK;
9084 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
9086 + for( ev = *evroot; ev; ev = ev->next )
9088 + if( !compare_events( ev, event ))
9091 + * Calculate the lag (in two parts) and add that to the collection
9093 + event->stamp.tv_sec -= ev->stamp.tv_sec;
9094 + event->stamp.tv_usec -= ev->stamp.tv_usec;
9095 + if( event->stamp.tv_usec < 0 )
9097 + event->stamp.tv_usec += 1000000;
9098 + event->stamp.tv_sec++;
9100 + if( event->stamp.tv_sec < 0 )
9102 + DEBUGP( KERN_WARNING "Negative lag detected\n" );
9106 + tv->tv_sec += event->stamp.tv_sec;
9107 + tv->tv_usec += event->stamp.tv_usec;
9109 + DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
9110 + " (accumulator is up to %lu.%06lu, %u events)\n",
9111 + event->stamp.tv_sec,
9112 + event->stamp.tv_usec,
9113 + tv->tv_sec, tv->tv_usec, *cn );
9116 + * Truncate the linked list.
9118 + * Visit each event in the list and return the memory to the pool.
9120 + * If a host is making multiple connections to the same remote host
9121 + * then this truncation will result in some requests not being
9122 + * monitored. Statistically we will still get some reasonable number
9123 + * of measurements and multiple simultaneous connections between host
9124 + * pairs don't happen all that often.
9129 + tcplag_event_T *ev_next = ev->next;
9130 + DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
9135 + * TODO: overflow limit for *cn, force premature output() if necessary
9136 + * (and drop this connection from the hash table)
9145 + spin_unlock_bh( &hash_lock );
9147 + if( found ) return( 1 );
9148 + if( ++h >= hashsize ) h = 0;
9154 + * Here is our target data:
9156 + * pskb -- The packet itself (see linux/skbuff.h for breakdown)
9160 + * in -- The device that this packet came in on
9161 + * (depending on the chain this may or may not exist)
9163 + * out -- The device that this packet is just about to go
9164 + * out onto (again existance depends on the chain)
9166 + * targinfo -- Our private data (handed through from iptables command util)
9168 + * userinfo -- Some more data
9172 +static unsigned int target( struct sk_buff **pskb,
9173 + unsigned int hooknum,
9174 + const struct net_device *in,
9175 + const struct net_device *out,
9176 + const void *targinfo,
9179 + struct iphdr *iph = ( *pskb )->nh.iph;
9180 + const struct ipt_tcplag *el = targinfo;
9181 + tcplag_hash_T connection;
9182 + tcplag_event_T event;
9185 + * We know we are dealing with IP here
9186 + * Fill in all the obvious fields
9188 + if( iph->saddr > iph->daddr )
9191 + connection.high_ip = iph->saddr;
9192 + connection.low_ip = iph->daddr;
9197 + connection.low_ip = iph->saddr;
9198 + connection.high_ip = iph->daddr;
9200 + do_gettimeofday( &event.stamp );
9202 + * Do a bit of cleaning
9204 + reaper( event.stamp.tv_sec, el->level, el->prefix );
9206 + DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
9207 + event.stamp.tv_sec,
9208 + event.stamp.tv_usec,
9209 + in ? in->name : "none", out ? out->name : "none" );
9211 + * Now start looking at the details
9213 + * First step is to identify this packet to see if it is
9214 + * the sort of packet that we are interested in.
9215 + * Don't hold any locks while we are doing this because often
9216 + * we will just let the packet go without any further consideration.
9218 + switch( iph->protocol )
9222 + struct tcphdr *tcp;
9224 + if( ntohs( iph->frag_off ) & IP_OFFSET )
9226 + DEBUGP( KERN_WARNING "ignoring fragment\n" );
9229 + tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
9230 + event.source_port = ntohs( tcp->source );
9231 + event.dest_port = ntohs( tcp->dest );
9233 + * Every packet should have a valid SEQ number so use this to
9234 + * generate an ACK number. This works along the formula:
9235 + * -- Start with the SEQ number
9236 + * -- For SYN or FIN add 1 to that number
9237 + * -- For data packet, add the data length to that number
9241 + * Data length requires a bit of fiddling around
9244 + unsigned int data_len;
9245 + if( tcp->syn || tcp->fin )
9247 + data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
9251 + data_len = ntohs( iph->tot_len );
9252 + data_len -= 4 * iph->ihl; /* Subtract away IP header & options */
9253 + data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
9256 + DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
9258 + if( data_len ) /* Only track events that demand an ACK */
9260 + event.expected_ACK = ntohl( tcp->seq ) + data_len;
9261 + hash_insert( &connection, &event, direction );
9265 + DEBUGP( "Don't bother to insert this, ACK not required\n" );
9272 + * Now we consider the matching of an existing event.
9273 + * Reverse the port numbers and change the ACK number to the actual ACK number
9274 + * Note that the direction is reversed because the reply will be going
9275 + * the opposite way to the request.
9277 + event.expected_ACK = ntohl( tcp->ack_seq );
9278 + event.dest_port = ntohs( tcp->source );
9279 + event.source_port = ntohs( tcp->dest );
9280 + request_complete( &connection, &event, !direction );
9284 + DEBUGP( "Don't bother to check this, ACK not valid\n" );
9288 + return( IPT_CONTINUE );
9292 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
9293 + * return( 1 ) if the entry is suitable
9299 + * targinfo -- Our private data block (handed to us from iptables plug-in)
9301 + * targinfosize -- The size of our private data block
9306 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
9307 + * all possible flag combos make sense. All we check for is correct data size.
9309 +static int checkentry( const char *tablename,
9310 + const struct ipt_entry *e,
9312 + unsigned int targinfosize,
9313 + unsigned int hook_mask )
9315 + const struct ipt_tcplag *el = targinfo;
9317 + if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
9319 + DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
9320 + IPT_ALIGN( sizeof( struct ipt_tcplag )));
9323 + if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
9327 +static struct ipt_target reg =
9337 +static int __init init( void )
9339 + if( ipt_register_target( ® )) return( -EINVAL );
9340 + hashsize = 123; /* should be configurable */
9341 + hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
9342 + memset( hashtab, 0, sizeof( void * ) * hashsize );
9347 + * This should not need locks (in theory)
9348 + * because it can only get punted after it is no longer
9349 + * chained into any of the netfilter lists.
9351 +static void __exit fini( void )
9355 + ipt_unregister_target( ® );
9357 + * Put back kernel memory
9359 + for( i = 0; i < hashsize; i++ )
9363 + if(( p = hashtab[ i ]))
9365 + tcplag_event_T *ev, *evn;
9368 + for( ev = p->h_ACK_list; ev; ev = evn )
9373 + for( ev = p->l_ACK_list; ev; ev = evn )
9386 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_XOR.c
9387 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
9388 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-03-30 11:50:41.000000000 +0200
9390 +/* XOR target for IP tables
9391 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9392 + * Based on ipt_TTL.c
9396 + * This software is distributed under the terms of GNU GPL
9399 +#include <linux/module.h>
9400 +#include <linux/skbuff.h>
9401 +#include <linux/ip.h>
9402 +#include <linux/tcp.h>
9403 +#include <linux/udp.h>
9405 +#include <linux/netfilter_ipv4/ip_tables.h>
9406 +#include <linux/netfilter_ipv4/ipt_XOR.h>
9408 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9409 +MODULE_DESCRIPTION("IP tables XOR module");
9410 +MODULE_LICENSE("GPL");
9412 +static unsigned int
9413 +ipt_xor_target(struct sk_buff **pskb,
9414 + const struct net_device *in, const struct net_device *out,
9415 + unsigned int hooknum, const void *targinfo, void *userinfo)
9417 + struct ipt_XOR_info *info = (void *) targinfo;
9418 + struct iphdr *iph;
9419 + struct tcphdr *tcph;
9420 + struct udphdr *udph;
9423 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9426 + iph = (*pskb)->nh.iph;
9428 + if (iph->protocol == IPPROTO_TCP) {
9429 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9430 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9431 + for (k=0; k<=info->block_size; k++) {
9432 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
9437 + if (info->key[j] == 0x00)
9440 + } else if (iph->protocol == IPPROTO_UDP) {
9441 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9442 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9443 + for (k=0; k<=info->block_size; k++) {
9444 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
9449 + if (info->key[j] == 0x00)
9454 + return IPT_CONTINUE;
9457 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9458 + void *targinfo, unsigned int targinfosize,
9459 + unsigned int hook_mask)
9461 + struct ipt_XOR_info *info = targinfo;
9463 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9464 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
9465 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9469 + if (strcmp(tablename, "mangle")) {
9470 + printk(KERN_WARNING "XOR: can only be called from"
9471 + "\"mangle\" table, not \"%s\"\n", tablename);
9475 + if (!strcmp(info->key, "")) {
9476 + printk(KERN_WARNING "XOR: You must specify a key");
9480 + if (info->block_size == 0) {
9481 + printk(KERN_WARNING "XOR: You must specify a block-size");
9488 +static struct ipt_target ipt_XOR = {
9490 + .target = ipt_xor_target,
9491 + .checkentry = ipt_xor_checkentry,
9492 + .me = THIS_MODULE,
9495 +static int __init init(void)
9497 + return ipt_register_target(&ipt_XOR);
9500 +static void __exit fini(void)
9502 + ipt_unregister_target(&ipt_XOR);
9507 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_addrtype.c
9508 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
9509 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-03-30 11:50:44.000000000 +0200
9512 + * iptables module to match inet_addr_type() of an ip.
9515 +#include <linux/module.h>
9516 +#include <linux/skbuff.h>
9517 +#include <linux/netdevice.h>
9518 +#include <net/route.h>
9520 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
9521 +#include <linux/netfilter_ipv4/ip_tables.h>
9523 +MODULE_LICENSE("GPL");
9525 +static inline int match_type(u_int32_t addr, u_int16_t mask)
9527 + return !!(mask & (1 << inet_addr_type(addr)));
9530 +static int match(const struct sk_buff *skb, const struct net_device *in,
9531 + const struct net_device *out, const void *matchinfo,
9532 + int offset, int *hotdrop)
9534 + const struct ipt_addrtype_info *info = matchinfo;
9535 + const struct iphdr *iph = skb->nh.iph;
9539 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
9541 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9546 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9547 + void *matchinfo, unsigned int matchsize,
9548 + unsigned int hook_mask)
9550 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9551 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9552 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9559 +static struct ipt_match addrtype_match = {
9560 + .name = "addrtype",
9562 + .checkentry = checkentry,
9566 +static int __init init(void)
9568 + return ipt_register_match(&addrtype_match);
9571 +static void __exit fini(void)
9573 + ipt_unregister_match(&addrtype_match);
9579 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_condition.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_condition.c
9580 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_condition.c 1970-01-01 01:00:00.000000000 +0100
9581 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_condition.c 2004-03-30 11:50:47.000000000 +0200
9583 +/*-------------------------------------------*\
9584 +| Netfilter Condition Module |
9586 +| Description: This module allows firewall |
9587 +| rules to match using condition variables |
9588 +| stored in /proc files. |
9590 +| Author: Stephane Ouellette 2002-10-22 |
9591 +| <ouellettes@videotron.ca> |
9594 +| 2003-02-10 Second version with improved |
9595 +| locking and simplified code. |
9597 +| This software is distributed under the |
9598 +| terms of the GNU GPL. |
9599 +\*-------------------------------------------*/
9601 +#include<linux/module.h>
9602 +#include<linux/proc_fs.h>
9603 +#include<linux/spinlock.h>
9604 +#include<linux/string.h>
9605 +#include<asm/atomic.h>
9606 +#include<linux/netfilter_ipv4/ip_tables.h>
9607 +#include<linux/netfilter_ipv4/ipt_condition.h>
9610 +#ifndef CONFIG_PROC_FS
9611 +#error "Proc file system support is required for this module"
9615 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
9616 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
9617 +MODULE_LICENSE("GPL");
9620 +struct condition_variable {
9621 + struct condition_variable *next;
9622 + struct proc_dir_entry *status_proc;
9623 + atomic_t refcount;
9624 + int enabled; /* TRUE == 1, FALSE == 0 */
9628 +static rwlock_t list_lock;
9629 +static struct condition_variable *head = NULL;
9630 +static struct proc_dir_entry *proc_net_condition = NULL;
9634 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
9635 + int length, int *eof, void *data)
9637 + struct condition_variable *var =
9638 + (struct condition_variable *) data;
9640 + if (offset == 0) {
9642 + buffer[0] = (var->enabled) ? '1' : '0';
9653 +ipt_condition_write_info(struct file *file, const char *buffer,
9654 + unsigned long length, void *data)
9656 + struct condition_variable *var =
9657 + (struct condition_variable *) data;
9660 + /* Match only on the first character */
9661 + switch (buffer[0]) {
9670 + return (int) length;
9675 +match(const struct sk_buff *skb, const struct net_device *in,
9676 + const struct net_device *out, const void *matchinfo, int offset,
9677 + const void *hdr, u_int16_t datalen, int *hotdrop)
9679 + const struct condition_info *info =
9680 + (const struct condition_info *) matchinfo;
9681 + struct condition_variable *var;
9682 + int condition_status = 0;
9684 + read_lock(&list_lock);
9686 + for (var = head; var; var = var->next) {
9687 + if (strcmp(info->name, var->status_proc->name) == 0) {
9688 + condition_status = var->enabled;
9693 + read_unlock(&list_lock);
9695 + return condition_status ^ info->invert;
9701 +checkentry(const char *tablename, const struct ipt_ip *ip,
9702 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
9704 + struct condition_info *info = (struct condition_info *) matchinfo;
9705 + struct condition_variable *var, *newvar;
9707 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
9710 + /* The first step is to check if the condition variable already exists. */
9711 + /* Here, a read lock is sufficient because we won't change the list */
9712 + read_lock(&list_lock);
9714 + for (var = head; var; var = var->next) {
9715 + if (strcmp(info->name, var->status_proc->name) == 0) {
9716 + atomic_inc(&var->refcount);
9717 + read_unlock(&list_lock);
9722 + read_unlock(&list_lock);
9724 + /* At this point, we need to allocate a new condition variable */
9725 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
9730 + /* Create the condition variable's proc file entry */
9731 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
9733 + if (!newvar->status_proc) {
9735 + * There are two possibilities:
9736 + * 1- Another condition variable with the same name has been created, which is valid.
9737 + * 2- There was a memory allocation error.
9740 + read_lock(&list_lock);
9742 + for (var = head; var; var = var->next) {
9743 + if (strcmp(info->name, var->status_proc->name) == 0) {
9744 + atomic_inc(&var->refcount);
9745 + read_unlock(&list_lock);
9750 + read_unlock(&list_lock);
9754 + atomic_set(&newvar->refcount, 1);
9755 + newvar->enabled = 0;
9756 + newvar->status_proc->owner = THIS_MODULE;
9757 + newvar->status_proc->data = newvar;
9759 + newvar->status_proc->read_proc = ipt_condition_read_info;
9760 + newvar->status_proc->write_proc = ipt_condition_write_info;
9762 + write_lock(&list_lock);
9764 + newvar->next = head;
9767 + write_unlock(&list_lock);
9774 +destroy(void *matchinfo, unsigned int matchsize)
9776 + struct condition_info *info = (struct condition_info *) matchinfo;
9777 + struct condition_variable *var, *prev = NULL;
9779 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
9782 + write_lock(&list_lock);
9784 + for (var = head; var && strcmp(info->name, var->status_proc->name);
9785 + prev = var, var = var->next);
9787 + if (var && atomic_dec_and_test(&var->refcount)) {
9789 + prev->next = var->next;
9793 + write_unlock(&list_lock);
9794 + remove_proc_entry(var->status_proc->name, proc_net_condition);
9797 + write_unlock(&list_lock);
9801 +static struct ipt_match condition_match = {
9802 + .name = "condition",
9804 + .checkentry = &checkentry,
9805 + .destroy = &destroy,
9815 + rwlock_init(&list_lock);
9816 + proc_net_condition = proc_mkdir("ipt_condition", proc_net);
9818 + if (proc_net_condition) {
9819 + errorcode = ipt_register_match(&condition_match);
9822 + remove_proc_entry("ipt_condition", proc_net);
9824 + errorcode = -EACCES;
9833 + ipt_unregister_match(&condition_match);
9834 + remove_proc_entry("ipt_condition", proc_net);
9839 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_connmark.c
9840 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
9841 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-03-30 11:48:14.000000000 +0200
9843 +/* This kernel module matches connection mark values set by the
9846 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9847 + * by Henrik Nordstrom <hno@marasystems.com>
9849 + * This program is free software; you can redistribute it and/or modify
9850 + * it under the terms of the GNU General Public License as published by
9851 + * the Free Software Foundation; either version 2 of the License, or
9852 + * (at your option) any later version.
9854 + * This program is distributed in the hope that it will be useful,
9855 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9856 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9857 + * GNU General Public License for more details.
9859 + * You should have received a copy of the GNU General Public License
9860 + * along with this program; if not, write to the Free Software
9861 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9864 +#include <linux/module.h>
9865 +#include <linux/skbuff.h>
9867 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9868 +MODULE_DESCRIPTION("IP tables connmark match module");
9869 +MODULE_LICENSE("GPL");
9871 +#include <linux/netfilter_ipv4/ip_tables.h>
9872 +#include <linux/netfilter_ipv4/ipt_connmark.h>
9873 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9876 +match(const struct sk_buff *skb,
9877 + const struct net_device *in,
9878 + const struct net_device *out,
9879 + const void *matchinfo,
9883 + const struct ipt_connmark_info *info = matchinfo;
9884 + enum ip_conntrack_info ctinfo;
9885 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9889 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
9893 +checkentry(const char *tablename,
9894 + const struct ipt_ip *ip,
9896 + unsigned int matchsize,
9897 + unsigned int hook_mask)
9899 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
9905 +static struct ipt_match connmark_match = {
9906 + .name = "connmark",
9908 + .checkentry = &checkentry,
9912 +static int __init init(void)
9914 + return ipt_register_match(&connmark_match);
9917 +static void __exit fini(void)
9919 + ipt_unregister_match(&connmark_match);
9924 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_helper.c
9925 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-03-30 11:31:19.000000000 +0200
9926 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_helper.c 2004-03-30 11:51:07.000000000 +0200
9928 DEBUGP("master's name = %s , info->name = %s\n",
9929 exp->expectant->helper->name, info->name);
9931 - ret ^= !strncmp(exp->expectant->helper->name, info->name,
9932 - strlen(exp->expectant->helper->name));
9933 + if (info->name[0] == '\0')
9936 + ret ^= !strncmp(exp->expectant->helper->name, info->name,
9937 + strlen(exp->expectant->helper->name));
9939 READ_UNLOCK(&ip_conntrack_lock);
9942 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
9945 - /* verify that we actually should match anything */
9946 - if ( strlen(info->name) == 0 )
9952 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_owner.c
9953 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_owner.c 2004-03-30 05:27:17.000000000 +0200
9954 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_owner.c 2004-03-30 11:51:33.000000000 +0200
9956 * This program is free software; you can redistribute it and/or modify
9957 * it under the terms of the GNU General Public License version 2 as
9958 * published by the Free Software Foundation.
9960 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
9963 #include <linux/module.h>
9964 #include <linux/skbuff.h>
9965 #include <linux/file.h>
9966 +#include <linux/ip.h>
9967 +#include <linux/tcp.h>
9968 +#include <linux/udp.h>
9969 #include <net/sock.h>
9970 +#include <net/tcp.h>
9971 +#include <net/udp.h>
9973 #include <linux/netfilter_ipv4/ipt_owner.h>
9974 #include <linux/netfilter_ipv4/ip_tables.h>
9976 MODULE_DESCRIPTION("iptables owner match");
9979 -match_comm(const struct sk_buff *skb, const char *comm)
9980 +match_comm(const struct sock *sk, const char *comm)
9982 struct task_struct *g, *p;
9983 struct files_struct *files;
9985 spin_lock(&files->file_lock);
9986 for (i=0; i < files->max_fds; i++) {
9987 if (fcheck_files(files, i) ==
9988 - skb->sk->sk_socket->file) {
9989 + sk->sk_socket->file) {
9990 spin_unlock(&files->file_lock);
9992 read_unlock(&tasklist_lock);
9997 -match_pid(const struct sk_buff *skb, pid_t pid)
9998 +match_pid(const struct sock *sk, pid_t pid)
10000 struct task_struct *p;
10001 struct files_struct *files;
10003 spin_lock(&files->file_lock);
10004 for (i=0; i < files->max_fds; i++) {
10005 if (fcheck_files(files, i) ==
10006 - skb->sk->sk_socket->file) {
10007 + sk->sk_socket->file) {
10008 spin_unlock(&files->file_lock);
10010 read_unlock(&tasklist_lock);
10011 @@ -86,10 +93,10 @@
10015 -match_sid(const struct sk_buff *skb, pid_t sid)
10016 +match_sid(const struct sock *sk, pid_t sid)
10018 struct task_struct *g, *p;
10019 - struct file *file = skb->sk->sk_socket->file;
10020 + struct file *file = sk->sk_socket->file;
10023 read_lock(&tasklist_lock);
10024 @@ -129,41 +136,71 @@
10027 const struct ipt_owner_info *info = matchinfo;
10028 + struct iphdr *iph = skb->nh.iph;
10029 + struct sock *sk = NULL;
10035 + if (iph->protocol == IPPROTO_TCP) {
10036 + struct tcphdr *tcph =
10037 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
10038 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
10039 + iph->daddr, tcph->dest,
10040 + skb->dev->ifindex);
10041 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
10042 + tcp_tw_put((struct tcp_tw_bucket *)sk);
10045 + } else if (iph->protocol == IPPROTO_UDP) {
10046 + struct udphdr *udph =
10047 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
10048 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
10049 + udph->dest, skb->dev->ifindex);
10053 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
10055 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
10058 if(info->match & IPT_OWNER_UID) {
10059 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
10060 + if ((sk->sk_socket->file->f_uid != info->uid) ^
10061 !!(info->invert & IPT_OWNER_UID))
10066 if(info->match & IPT_OWNER_GID) {
10067 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
10068 + if ((sk->sk_socket->file->f_gid != info->gid) ^
10069 !!(info->invert & IPT_OWNER_GID))
10074 if(info->match & IPT_OWNER_PID) {
10075 - if (!match_pid(skb, info->pid) ^
10076 + if (!match_pid(sk, info->pid) ^
10077 !!(info->invert & IPT_OWNER_PID))
10082 if(info->match & IPT_OWNER_SID) {
10083 - if (!match_sid(skb, info->sid) ^
10084 + if (!match_sid(sk, info->sid) ^
10085 !!(info->invert & IPT_OWNER_SID))
10090 if(info->match & IPT_OWNER_COMM) {
10091 - if (!match_comm(skb, info->comm) ^
10092 + if (!match_comm(sk, info->comm) ^
10093 !!(info->invert & IPT_OWNER_COMM))
10109 @@ -173,11 +210,19 @@
10110 unsigned int matchsize,
10111 unsigned int hook_mask)
10114 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
10115 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
10119 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
10120 + (1 << NF_IP_LOCAL_IN))) {
10121 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
10122 + "or POST_ROUTING.\n");
10126 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
10127 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
10128 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
10132 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
10133 printk("Matchsize %u != %Zu\n", matchsize,
10134 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_policy.c
10135 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
10136 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_policy.c 2004-03-30 11:51:40.000000000 +0200
10138 +/* IP tables module for matching IPsec policy
10140 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
10142 + * This program is free software; you can redistribute it and/or modify
10143 + * it under the terms of the GNU General Public License version 2 as
10144 + * published by the Free Software Foundation.
10147 +#include <linux/kernel.h>
10148 +#include <linux/config.h>
10149 +#include <linux/module.h>
10150 +#include <linux/skbuff.h>
10151 +#include <linux/init.h>
10152 +#include <net/xfrm.h>
10154 +#include <linux/netfilter_ipv4.h>
10155 +#include <linux/netfilter_ipv4/ipt_policy.h>
10156 +#include <linux/netfilter_ipv4/ip_tables.h>
10158 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
10159 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
10160 +MODULE_LICENSE("GPL");
10164 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
10166 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
10168 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
10169 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
10170 + MISMATCH(proto, x->id.proto) ||
10171 + MISMATCH(mode, x->props.mode) ||
10172 + MISMATCH(spi, x->id.spi) ||
10173 + MISMATCH(reqid, x->props.reqid))
10179 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
10181 + const struct ipt_policy_elem *e;
10182 + struct sec_path *sp = skb->sp;
10183 + int strict = info->flags & POLICY_MATCH_STRICT;
10188 + if (strict && info->len != sp->len)
10191 + for (i = sp->len - 1; i >= 0; i--) {
10192 + pos = strict ? i - sp->len + 1 : 0;
10193 + if (pos >= info->len)
10195 + e = &info->pol[pos];
10197 + if (match_xfrm_state(sp->x[i].xvec, e)) {
10200 + } else if (strict)
10204 + return strict ? 1 : 0;
10208 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
10210 + const struct ipt_policy_elem *e;
10211 + struct dst_entry *dst = skb->dst;
10212 + int strict = info->flags & POLICY_MATCH_STRICT;
10215 + if (dst->xfrm == NULL)
10218 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
10219 + pos = strict ? i : 0;
10220 + if (pos >= info->len)
10222 + e = &info->pol[pos];
10224 + if (match_xfrm_state(dst->xfrm, e)) {
10227 + } else if (strict)
10231 + return strict ? 1 : 0;
10234 +static int match(const struct sk_buff *skb,
10235 + const struct net_device *in,
10236 + const struct net_device *out,
10237 + const void *matchinfo, int offset, int *hotdrop)
10239 + const struct ipt_policy_info *info = matchinfo;
10242 + if (info->flags & POLICY_MATCH_IN)
10243 + ret = match_policy_in(skb, info);
10245 + ret = match_policy_out(skb, info);
10248 + if (info->flags & POLICY_MATCH_NONE)
10252 + } else if (info->flags & POLICY_MATCH_NONE)
10258 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
10259 + void *matchinfo, unsigned int matchsize,
10260 + unsigned int hook_mask)
10262 + struct ipt_policy_info *info = matchinfo;
10264 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
10265 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
10266 + matchsize, IPT_ALIGN(sizeof(*info)));
10269 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
10270 + printk(KERN_ERR "ipt_policy: neither incoming nor "
10271 + "outgoing policy selected\n");
10274 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
10275 + && info->flags & POLICY_MATCH_OUT) {
10276 + printk(KERN_ERR "ipt_policy: output policy not valid in "
10277 + "PRE_ROUTING and INPUT\n");
10280 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
10281 + && info->flags & POLICY_MATCH_IN) {
10282 + printk(KERN_ERR "ipt_policy: input policy not valid in "
10283 + "POST_ROUTING and OUTPUT\n");
10286 + if (info->len > POLICY_MAX_ELEM) {
10287 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
10294 +static struct ipt_match policy_match =
10296 + .name = "policy",
10298 + .checkentry = checkentry,
10299 + .me = THIS_MODULE,
10302 +static int __init init(void)
10304 + return ipt_register_match(&policy_match);
10307 +static void __exit fini(void)
10309 + ipt_unregister_match(&policy_match);
10312 +module_init(init);
10313 +module_exit(fini);
10314 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_rpc.c
10315 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
10316 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_rpc.c 2004-03-30 11:51:55.000000000 +0200
10318 +/* RPC extension for IP connection matching, Version 2.2
10319 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
10320 + * - original rpc tracking module
10321 + * - "recent" connection handling for kernel 2.3+ netfilter
10323 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
10324 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
10326 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
10327 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
10328 + * - extended matching to support filtering on procedures
10330 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
10332 + * This program is free software; you can redistribute it and/or
10333 + * modify it under the terms of the GNU General Public License
10334 + * as published by the Free Software Foundation; either version
10335 + * 2 of the License, or (at your option) any later version.
10337 + * Module load syntax:
10338 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
10340 + * Please give the ports of all RPC servers you wish to connect to.
10341 + * If you don't specify ports, the default will be port 111.
10345 + * RPCs should not be exposed to the internet - ask the Pentagon;
10347 + * "The unidentified crackers pleaded guilty in July to charges
10348 + * of juvenile delinquency stemming from a string of Pentagon
10349 + * network intrusions in February.
10351 + * The youths, going by the names TooShort and Makaveli, used
10352 + * a common server security hole to break in, according to
10353 + * Dane Jasper, owner of the California Internet service
10354 + * provider, Sonic. They used the hole, known as the 'statd'
10355 + * exploit, to attempt more than 800 break-ins, Jasper said."
10357 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
10358 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
10362 +#include <linux/module.h>
10363 +#include <linux/skbuff.h>
10364 +#include <linux/list.h>
10365 +#include <linux/udp.h>
10366 +#include <linux/tcp.h>
10367 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10368 +#include <linux/netfilter_ipv4/ip_tables.h>
10369 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
10370 +#include <linux/netfilter_ipv4/lockhelp.h>
10371 +#include <linux/netfilter_ipv4/ipt_rpc.h>
10373 +#define MAX_PORTS 8
10374 +static int ports[MAX_PORTS];
10375 +static int ports_n_c = 0;
10377 +#ifdef MODULE_PARM
10378 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
10379 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
10382 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
10383 +MODULE_DESCRIPTION("RPC connection matching module");
10384 +MODULE_LICENSE("GPL");
10387 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
10390 +#define DEBUGP(format, args...)
10393 +EXPORT_NO_SYMBOLS;
10395 +/* vars from ip_conntrack_rpc_tcp */
10396 +extern struct list_head request_p_list_tcp;
10397 +extern struct module *ip_conntrack_rpc_tcp;
10399 +/* vars from ip_conntrack_rpc_udp */
10400 +extern struct list_head request_p_list_udp;
10401 +extern struct module *ip_conntrack_rpc_udp;
10403 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
10404 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
10406 +#define ASSERT_READ_LOCK(x) \
10408 + if (x == &request_p_list_udp) \
10409 + MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
10410 + else if (x == &request_p_list_tcp) \
10411 + MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
10414 +#define ASSERT_WRITE_LOCK(x) \
10416 + if (x == &request_p_list_udp) \
10417 + MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
10418 + else if (x == &request_p_list_tcp) \
10419 + MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
10422 +#include <linux/netfilter_ipv4/listhelp.h>
10424 +const int IPT_RPC_CHAR_LEN = 11;
10427 +static int k_atoi(char *string)
10429 + unsigned int result = 0;
10430 + int maxoctet = IPT_RPC_CHAR_LEN;
10432 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
10435 + if (*string == 0)
10437 + if (*string < 48 || *string > 57) {
10440 + result = result * 10 + ( *string - 48 );
10446 +static int match_rpcs(char *c_procs, int i_procs, int proc)
10450 + unsigned int proc_num;
10452 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
10454 + if (i_procs == -1)
10457 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
10459 + proc_ptr = c_procs;
10460 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
10461 + proc_num = k_atoi(proc_ptr);
10463 + if (proc_num == proc)
10471 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
10472 + int *hotdrop, int dir, struct ip_conntrack *ct,
10473 + int offset, struct list_head request_p_list)
10475 + const struct ipt_rpc_info *rpcinfo = matchinfo;
10476 + struct request_p *req_p;
10483 + /* This does sanity checking on RPC payloads,
10484 + * and permits only the RPC "get port" (3)
10485 + * in authorised procedures in client
10486 + * communications with the portmapper.
10491 + /* Get RPC requestor */
10492 + if (IXDR_GET_INT32(data) != 3) {
10493 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
10494 + if(rpcinfo->strict == 1)
10498 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
10502 + /* Jump Credentials and Verfifier */
10503 + data = data + IXDR_GET_INT32(data) + 2;
10504 + data = data + IXDR_GET_INT32(data) + 2;
10506 + /* Get RPC procedure */
10507 + if (match_rpcs((char *)&rpcinfo->c_procs,
10508 + rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
10509 + DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
10510 + (unsigned int)IXDR_GET_INT32(data));
10512 + /* If the RPC conntrack half entry already exists .. */
10514 + switch (ct->tuplehash[0].tuple.dst.protonum) {
10515 + case IPPROTO_UDP:
10516 + WRITE_LOCK(&ipct_rpc_udp_lock);
10517 + case IPPROTO_TCP:
10518 + WRITE_LOCK(&ipct_rpc_tcp_lock);
10520 + req_p = LIST_FIND(&request_p_list, request_p_cmp,
10521 + struct request_p *, xid,
10522 + ct->tuplehash[dir].tuple.src.ip,
10523 + ct->tuplehash[dir].tuple.src.u.all);
10526 + DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10527 + xid, ct->tuplehash[dir].tuple.dst.protonum,
10528 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10529 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
10531 + /* .. remove it */
10532 + if (del_timer(&req_p->timeout))
10533 + req_p->timeout.expires = 0;
10535 + LIST_DELETE(&request_p_list, req_p);
10536 + DEBUGP("RPC req_p removed. [done]\n");
10539 + DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10540 + xid, ct->tuplehash[dir].tuple.dst.protonum,
10541 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10542 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
10545 + switch (ct->tuplehash[0].tuple.dst.protonum) {
10546 + case IPPROTO_UDP:
10547 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
10548 + case IPPROTO_TCP:
10549 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
10552 + if(rpcinfo->strict == 1)
10557 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
10558 + (unsigned int)IXDR_GET_INT32(data));
10559 + return (1 && (!offset));
10563 +static int match(const struct sk_buff *skb, const struct net_device *in,
10564 + const struct net_device *out, const void *matchinfo,
10565 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
10567 + struct ip_conntrack *ct;
10568 + enum ip_conntrack_info ctinfo;
10569 + const u_int32_t *data;
10570 + enum ip_conntrack_dir dir;
10571 + const struct tcphdr *tcp;
10572 + const struct ipt_rpc_info *rpcinfo = matchinfo;
10573 + int port, portsok;
10577 + DEBUGP("new packet to evaluate ..\n");
10579 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10581 + DEBUGP("no ct available [skip]\n");
10585 + DEBUGP("ct detected. [cont]\n");
10586 + dir = CTINFO2DIR(ctinfo);
10588 + /* we only want the client to server packets for matching */
10589 + if (dir != IP_CT_DIR_ORIGINAL)
10592 + /* This does sanity checking on UDP or TCP packets,
10593 + * like their respective modules.
10596 + switch (ct->tuplehash[0].tuple.dst.protonum) {
10598 + case IPPROTO_UDP:
10599 + DEBUGP("PROTO_UDP [cont]\n");
10600 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
10601 + DEBUGP("packet does not contain a complete header. [drop]\n");
10605 + for (port=0,portsok=0; port <= ports_n_c; port++) {
10606 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10611 + if (portsok == 0) {
10612 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10613 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10617 + if ((datalen - sizeof(struct udphdr)) != 56) {
10618 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
10619 + if (rpcinfo->strict == 1)
10623 + DEBUGP("packet length is correct. [cont]\n");
10625 + /* Get to the data */
10626 + data = (const u_int32_t *)hdr + 2;
10628 + /* Check the RPC data */
10629 + tval = check_rpc_packet(data, matchinfo, hotdrop,
10631 + request_p_list_udp);
10636 + case IPPROTO_TCP:
10637 + DEBUGP("PROTO_TCP [cont]\n");
10638 + if (offset == 0 && datalen < sizeof(struct tcphdr)) {
10639 + DEBUGP("packet does not contain a complete header. [drop]\n");
10643 + for (port=0,portsok=0; port <= ports_n_c; port++) {
10644 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10649 + if (portsok == 0) {
10650 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10651 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10656 + if (datalen == (tcp->doff * 4)) {
10657 + DEBUGP("packet does not contain any data. [match]\n");
10658 + return (1 && (!offset));
10661 + /* Tests if packet len is ok */
10662 + if ((datalen - (tcp->doff * 4)) != 60) {
10663 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
10664 + if(rpcinfo->strict == 1)
10668 + DEBUGP("packet length is correct. [cont]\n");
10670 + /* Get to the data */
10671 + data = (const u_int32_t *)tcp + tcp->doff + 1;
10673 + /* Check the RPC data */
10674 + tval = check_rpc_packet(data, matchinfo, hotdrop,
10676 + request_p_list_tcp);
10682 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
10683 + ct->tuplehash[0].tuple.dst.protonum);
10688 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
10689 + unsigned int matchsize, unsigned int hook_mask)
10692 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
10693 + | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
10694 + printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
10698 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
10705 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
10706 + &match, &checkentry, NULL,
10710 +static int __init init(void)
10714 + DEBUGP("incrementing usage counts\n");
10715 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
10716 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
10718 + /* If no port given, default to standard RPC port */
10719 + if (ports[0] == 0)
10720 + ports[0] = RPC_PORT;
10722 + DEBUGP("registering match [%s] for;\n", rpc_match.name);
10723 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
10724 + DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
10728 + return ipt_register_match(&rpc_match);
10732 +static void fini(void)
10734 + DEBUGP("unregistering match\n");
10735 + ipt_unregister_match(&rpc_match);
10737 + DEBUGP("decrementing usage counts\n");
10738 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
10739 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
10743 +module_init(init);
10744 +module_exit(fini);
10746 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_string.c
10747 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
10748 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_string.c 2004-03-30 11:52:56.000000000 +0200
10750 +/* Kernel module to match a string into a packet.
10752 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
10755 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
10756 + * Fixed SMP re-entrancy problem using per-cpu data areas
10757 + * for the skip/shift tables.
10758 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10759 + * Fixed kernel panic, due to overrunning boyer moore string
10760 + * tables. Also slightly tweaked heuristic for deciding what
10761 + * search algo to use.
10762 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10763 + * Implemented Boyer Moore Sublinear search algorithm
10764 + * alongside the existing linear search based on memcmp().
10765 + * Also a quick check to decide which method to use on a per
10769 +#include <linux/smp.h>
10770 +#include <linux/module.h>
10771 +#include <linux/skbuff.h>
10772 +#include <linux/file.h>
10773 +#include <net/sock.h>
10775 +#include <linux/netfilter_ipv4/ip_tables.h>
10776 +#include <linux/netfilter_ipv4/ipt_string.h>
10778 +MODULE_LICENSE("GPL");
10780 +struct string_per_cpu {
10786 +struct string_per_cpu *bm_string_data=NULL;
10788 +/* Boyer Moore Sublinear string search - VERY FAST */
10789 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
10791 + int M1, right_end, sk, sh;
10794 + int *skip, *shift, *len;
10796 + /* use data suitable for this CPU */
10797 + shift=bm_string_data[smp_processor_id()].shift;
10798 + skip=bm_string_data[smp_processor_id()].skip;
10799 + len=bm_string_data[smp_processor_id()].len;
10801 + /* Setup skip/shift tables */
10802 + M1 = right_end = needle_len-1;
10803 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
10804 + for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
10806 + for (i = 1; i < needle_len; i++) {
10807 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
10812 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
10813 + for (i = M1; i > 0; i--) shift[len[i]] = i;
10816 + for (i = 0; i < needle_len; i++) {
10817 + if (len[i] == M1 - i) ended = i;
10818 + if (ended) shift[i] = ended;
10821 + /* Do the search*/
10822 + while (right_end < haystack_len)
10824 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
10825 + if (i == needle_len) {
10826 + return haystack+(right_end - M1);
10829 + sk = skip[haystack[right_end - i]];
10831 + right_end = max(right_end - i + sk, right_end + sh);
10837 +/* Linear string search based on memcmp() */
10838 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
10840 + char *k = haystack + (haystack_len-needle_len);
10841 + char *t = haystack;
10843 + while ( t <= k ) {
10844 + if (memcmp(t, needle, needle_len) == 0)
10854 +match(const struct sk_buff *skb,
10855 + const struct net_device *in,
10856 + const struct net_device *out,
10857 + const void *matchinfo,
10860 + u_int16_t datalen,
10863 + const struct ipt_string_info *info = matchinfo;
10864 + struct iphdr *ip = skb->nh.iph;
10866 + char *needle, *haystack;
10867 + proc_ipt_search search=search_linear;
10869 + if ( !ip ) return 0;
10871 + /* get lenghts, and validate them */
10873 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
10874 + if ( nlen > hlen ) return 0;
10876 + needle=(char *)&info->string;
10877 + haystack=(char *)ip+(ip->ihl*4);
10879 + /* The sublinear search comes in to its own
10880 + * on the larger packets */
10881 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
10882 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
10883 + if ( hlen < BM_MAX_HLEN ) {
10884 + search=search_sublinear;
10886 + if (net_ratelimit())
10887 + printk(KERN_INFO "ipt_string: Packet too big "
10888 + "to attempt sublinear string search "
10889 + "(%d bytes)\n", hlen );
10893 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
10897 +checkentry(const char *tablename,
10898 + const struct ipt_ip *ip,
10900 + unsigned int matchsize,
10901 + unsigned int hook_mask)
10904 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
10910 +void string_freeup_data(void)
10914 + if ( bm_string_data ) {
10915 + for(c=0; c<smp_num_cpus; c++) {
10916 + if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
10917 + if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
10918 + if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
10920 + kfree(bm_string_data);
10924 +static struct ipt_match string_match
10925 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
10927 +static int __init init(void)
10933 + tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
10934 + alen=sizeof(int)*BM_MAX_HLEN;
10936 + /* allocate array of structures */
10937 + if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
10941 + memset(bm_string_data, 0, tlen);
10943 + /* allocate our skip/shift tables */
10944 + for(c=0; c<smp_num_cpus; c++) {
10945 + if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
10947 + if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
10949 + if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
10953 + return ipt_register_match(&string_match);
10956 + string_freeup_data();
10960 +static void __exit fini(void)
10962 + ipt_unregister_match(&string_match);
10963 + string_freeup_data();
10966 +module_init(init);
10967 +module_exit(fini);
10968 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.5-rc3/net/ipv4/tcp_ipv4.c
10969 --- linux-2.6.5-rc3.org/net/ipv4/tcp_ipv4.c 2004-03-30 05:26:01.000000000 +0200
10970 +++ linux-2.6.5-rc3/net/ipv4/tcp_ipv4.c 2004-03-30 11:51:33.000000000 +0200
10971 @@ -2667,6 +2667,7 @@
10972 EXPORT_SYMBOL(tcp_v4_connect);
10973 EXPORT_SYMBOL(tcp_v4_do_rcv);
10974 EXPORT_SYMBOL(tcp_v4_lookup_listener);
10975 +EXPORT_SYMBOL(tcp_v4_lookup);
10976 EXPORT_SYMBOL(tcp_v4_rebuild_header);
10977 EXPORT_SYMBOL(tcp_v4_remember_stamp);
10978 EXPORT_SYMBOL(tcp_v4_send_check);
10979 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/udp.c linux-2.6.5-rc3/net/ipv4/udp.c
10980 --- linux-2.6.5-rc3.org/net/ipv4/udp.c 2004-03-30 05:25:34.000000000 +0200
10981 +++ linux-2.6.5-rc3/net/ipv4/udp.c 2004-03-30 11:51:33.000000000 +0200
10982 @@ -1543,6 +1543,7 @@
10983 EXPORT_SYMBOL(udp_port_rover);
10984 EXPORT_SYMBOL(udp_prot);
10985 EXPORT_SYMBOL(udp_sendmsg);
10986 +EXPORT_SYMBOL(udp_v4_lookup);
10988 #ifdef CONFIG_PROC_FS
10989 EXPORT_SYMBOL(udp_proc_register);
10990 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.5-rc3/net/ipv6/netfilter/Kconfig
10991 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/Kconfig 2004-03-30 11:31:19.000000000 +0200
10992 +++ linux-2.6.5-rc3/net/ipv6/netfilter/Kconfig 2004-03-30 11:50:47.000000000 +0200
10993 @@ -255,5 +255,15 @@
10994 <file:Documentation/modules.txt>. If unsure, say `N'.
10997 +config IP6_NF_TARGET_ROUTE
10998 + tristate ' ROUTE target support'
10999 + depends on IP6_NF_MANGLE
11002 +config IP6_NF_MATCH_CONDITION
11003 + tristate 'condition match support'
11004 + depends on IP6_NF_IPTABLES
11009 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.5-rc3/net/ipv6/netfilter/Makefile
11010 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/Makefile 2004-03-30 11:31:19.000000000 +0200
11011 +++ linux-2.6.5-rc3/net/ipv6/netfilter/Makefile 2004-03-30 11:50:47.000000000 +0200
11013 # Link order matters here.
11014 obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
11015 obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
11016 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
11017 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
11018 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
11019 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
11021 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
11022 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
11023 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
11024 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
11025 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
11026 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
11027 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
11028 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_ROUTE.c
11029 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
11030 +++ linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_ROUTE.c 2004-03-30 11:48:31.000000000 +0200
11033 + * This implements the ROUTE v6 target, which enables you to setup unusual
11034 + * routes not supported by the standard kernel routing table.
11036 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
11038 + * v 1.0 2003/08/05
11040 + * This software is distributed under GNU GPL v2, 1991
11043 +#include <linux/module.h>
11044 +#include <linux/skbuff.h>
11045 +#include <linux/ipv6.h>
11046 +#include <linux/netfilter_ipv6/ip6_tables.h>
11047 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
11048 +#include <linux/netdevice.h>
11049 +#include <net/ipv6.h>
11050 +#include <net/ndisc.h>
11051 +#include <net/ip6_route.h>
11052 +#include <linux/icmpv6.h>
11055 +#define DEBUGP printk
11057 +#define DEBUGP(format, args...)
11060 +#define NIP6(addr) \
11061 + ntohs((addr).s6_addr16[0]), \
11062 + ntohs((addr).s6_addr16[1]), \
11063 + ntohs((addr).s6_addr16[2]), \
11064 + ntohs((addr).s6_addr16[3]), \
11065 + ntohs((addr).s6_addr16[4]), \
11066 + ntohs((addr).s6_addr16[5]), \
11067 + ntohs((addr).s6_addr16[6]), \
11068 + ntohs((addr).s6_addr16[7])
11070 +/* Route the packet according to the routing keys specified in
11071 + * route_info. Keys are :
11073 + * 0 if no oif preferred,
11074 + * otherwise set to the index of the desired oif
11075 + * - route_info->gw :
11076 + * 0 if no gateway specified,
11077 + * otherwise set to the next host to which the pkt must be routed
11078 + * If success, skb->dev is the output device to which the packet must
11079 + * be sent and skb->dst is not NULL
11081 + * RETURN: 1 if the packet was succesfully routed to the
11082 + * destination desired
11083 + * 0 if the kernel routing table could not route the packet
11084 + * according to the keys specified
11087 +route6(struct sk_buff *skb,
11088 + unsigned int ifindex,
11089 + const struct ip6t_route_target_info *route_info)
11091 + struct rt6_info *rt = NULL;
11092 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
11093 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
11095 + DEBUGP("ip6t_ROUTE: called with: ");
11096 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
11097 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
11098 + DEBUGP("OUT=%s\n", route_info->oif);
11100 + if (ipv6_addr_any(gw))
11101 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
11103 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
11108 + DEBUGP("ip6t_ROUTE: routing gives: ");
11109 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
11110 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
11111 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
11113 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
11114 + goto wrong_route;
11116 + if (!rt->rt6i_nexthop) {
11117 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
11118 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
11121 + /* Drop old route. */
11122 + dst_release(skb->dst);
11123 + skb->dst = &rt->u.dst;
11124 + skb->dev = rt->rt6i_dev;
11128 + dst_release(&rt->u.dst);
11130 + if (!net_ratelimit())
11133 + printk("ip6t_ROUTE: no explicit route found ");
11135 + printk("via interface %s ", route_info->oif);
11136 + if (!ipv6_addr_any(gw))
11137 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
11143 +/* Stolen from ip6_output_finish
11144 + * PRE : skb->dev is set to the device we are leaving by
11145 + * skb->dst is not NULL
11146 + * POST: the packet is sent with the link layer header pushed
11147 + * the packet is destroyed
11149 +static void ip_direct_send(struct sk_buff *skb)
11151 + struct dst_entry *dst = skb->dst;
11152 + struct hh_cache *hh = dst->hh;
11155 + read_lock_bh(&hh->hh_lock);
11156 + memcpy(skb->data - 16, hh->hh_data, 16);
11157 + read_unlock_bh(&hh->hh_lock);
11158 + skb_push(skb, hh->hh_len);
11159 + hh->hh_output(skb);
11160 + } else if (dst->neighbour)
11161 + dst->neighbour->output(skb);
11163 + if (net_ratelimit())
11164 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
11170 +static unsigned int
11171 +route6_oif(const struct ip6t_route_target_info *route_info,
11172 + struct sk_buff *skb)
11174 + unsigned int ifindex = 0;
11175 + struct net_device *dev_out = NULL;
11177 + /* The user set the interface name to use.
11178 + * Getting the current interface index.
11180 + if ((dev_out = dev_get_by_name(route_info->oif))) {
11181 + ifindex = dev_out->ifindex;
11183 + /* Unknown interface name : packet dropped */
11184 + if (net_ratelimit())
11185 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
11187 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
11188 + return IP6T_CONTINUE;
11193 + /* Trying the standard way of routing packets */
11194 + if (route6(skb, ifindex, route_info)) {
11195 + dev_put(dev_out);
11196 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
11197 + return IP6T_CONTINUE;
11199 + ip_direct_send(skb);
11200 + return NF_STOLEN;
11206 +static unsigned int
11207 +route6_gw(const struct ip6t_route_target_info *route_info,
11208 + struct sk_buff *skb)
11210 + if (route6(skb, 0, route_info)) {
11211 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
11212 + return IP6T_CONTINUE;
11214 + ip_direct_send(skb);
11215 + return NF_STOLEN;
11221 +static unsigned int
11222 +ip6t_route_target(struct sk_buff **pskb,
11223 + unsigned int hooknum,
11224 + const struct net_device *in,
11225 + const struct net_device *out,
11226 + const void *targinfo,
11229 + const struct ip6t_route_target_info *route_info = targinfo;
11230 + struct sk_buff *skb = *pskb;
11231 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
11233 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
11236 + /* If we are at PREROUTING or INPUT hook
11237 + * the TTL isn't decreased by the IP stack
11239 + if (hooknum == NF_IP6_PRE_ROUTING ||
11240 + hooknum == NF_IP6_LOCAL_IN) {
11242 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
11244 + if (ipv6h->hop_limit <= 1) {
11245 + /* Force OUTPUT device used as source address */
11246 + skb->dev = skb->dst->dev;
11248 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
11249 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
11254 + ipv6h->hop_limit--;
11259 + if (route_info->oif[0])
11260 + return route6_oif(route_info, *pskb);
11262 + if (!ipv6_addr_any(gw))
11263 + return route6_gw(route_info, *pskb);
11265 + if (net_ratelimit())
11266 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
11268 + return IP6T_CONTINUE;
11273 +ip6t_route_checkentry(const char *tablename,
11274 + const struct ip6t_entry *e,
11276 + unsigned int targinfosize,
11277 + unsigned int hook_mask)
11279 + if (strcmp(tablename, "mangle") != 0) {
11280 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
11284 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
11285 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
11287 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
11295 +static struct ip6t_target ip6t_route_reg = {
11297 + .target = ip6t_route_target,
11298 + .checkentry = ip6t_route_checkentry,
11299 + .me = THIS_MODULE
11303 +static int __init init(void)
11305 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
11306 + if (ip6t_register_target(&ip6t_route_reg))
11313 +static void __exit fini(void)
11315 + ip6t_unregister_target(&ip6t_route_reg);
11318 +module_init(init);
11319 +module_exit(fini);
11320 +MODULE_LICENSE("GPL");
11321 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_condition.c linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_condition.c
11322 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_condition.c 1970-01-01 01:00:00.000000000 +0100
11323 +++ linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_condition.c 2004-03-30 11:50:47.000000000 +0200
11325 +/*-------------------------------------------*\
11326 +| Netfilter Condition Module for IPv6 |
11328 +| Description: This module allows firewall |
11329 +| rules to match using condition variables |
11330 +| stored in /proc files. |
11332 +| Author: Stephane Ouellette 2003-02-10 |
11333 +| <ouellettes@videotron.ca> |
11335 +| This software is distributed under the |
11336 +| terms of the GNU GPL. |
11337 +\*-------------------------------------------*/
11339 +#include<linux/module.h>
11340 +#include<linux/proc_fs.h>
11341 +#include<linux/spinlock.h>
11342 +#include<linux/string.h>
11343 +#include<asm/atomic.h>
11344 +#include<linux/netfilter_ipv6/ip6_tables.h>
11345 +#include<linux/netfilter_ipv6/ip6t_condition.h>
11348 +#ifndef CONFIG_PROC_FS
11349 +#error "Proc file system support is required for this module"
11353 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
11354 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
11355 +MODULE_LICENSE("GPL");
11358 +struct condition_variable {
11359 + struct condition_variable *next;
11360 + struct proc_dir_entry *status_proc;
11361 + atomic_t refcount;
11362 + int enabled; /* TRUE == 1, FALSE == 0 */
11366 +static rwlock_t list_lock;
11367 +static struct condition_variable *head = NULL;
11368 +static struct proc_dir_entry *proc_net_condition = NULL;
11372 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
11373 + int length, int *eof, void *data)
11375 + struct condition_variable *var =
11376 + (struct condition_variable *) data;
11378 + if (offset == 0) {
11380 + buffer[0] = (var->enabled) ? '1' : '0';
11381 + buffer[1] = '\n';
11391 +ipt_condition_write_info(struct file *file, const char *buffer,
11392 + unsigned long length, void *data)
11394 + struct condition_variable *var =
11395 + (struct condition_variable *) data;
11398 + /* Match only on the first character */
11399 + switch (buffer[0]) {
11401 + var->enabled = 0;
11404 + var->enabled = 1;
11408 + return (int) length;
11413 +match(const struct sk_buff *skb, const struct net_device *in,
11414 + const struct net_device *out, const void *matchinfo, int offset,
11415 + const void *hdr, u_int16_t datalen, int *hotdrop)
11417 + const struct condition6_info *info =
11418 + (const struct condition6_info *) matchinfo;
11419 + struct condition_variable *var;
11420 + int condition_status = 0;
11422 + read_lock(&list_lock);
11424 + for (var = head; var; var = var->next) {
11425 + if (strcmp(info->name, var->status_proc->name) == 0) {
11426 + condition_status = var->enabled;
11431 + read_unlock(&list_lock);
11433 + return condition_status ^ info->invert;
11439 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
11440 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
11442 + struct condition6_info *info =
11443 + (struct condition6_info *) matchinfo;
11444 + struct condition_variable *var, *newvar;
11446 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
11449 + /* The first step is to check if the condition variable already exists. */
11450 + /* Here, a read lock is sufficient because we won't change the list */
11451 + read_lock(&list_lock);
11453 + for (var = head; var; var = var->next) {
11454 + if (strcmp(info->name, var->status_proc->name) == 0) {
11455 + atomic_inc(&var->refcount);
11456 + read_unlock(&list_lock);
11461 + read_unlock(&list_lock);
11463 + /* At this point, we need to allocate a new condition variable */
11464 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
11469 + /* Create the condition variable's proc file entry */
11470 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
11472 + if (!newvar->status_proc) {
11474 + * There are two possibilities:
11475 + * 1- Another condition variable with the same name has been created, which is valid.
11476 + * 2- There was a memory allocation error.
11479 + read_lock(&list_lock);
11481 + for (var = head; var; var = var->next) {
11482 + if (strcmp(info->name, var->status_proc->name) == 0) {
11483 + atomic_inc(&var->refcount);
11484 + read_unlock(&list_lock);
11489 + read_unlock(&list_lock);
11493 + atomic_set(&newvar->refcount, 1);
11494 + newvar->enabled = 0;
11495 + newvar->status_proc->owner = THIS_MODULE;
11496 + newvar->status_proc->data = newvar;
11498 + newvar->status_proc->read_proc = ipt_condition_read_info;
11499 + newvar->status_proc->write_proc = ipt_condition_write_info;
11501 + write_lock(&list_lock);
11503 + newvar->next = head;
11506 + write_unlock(&list_lock);
11513 +destroy(void *matchinfo, unsigned int matchsize)
11515 + struct condition6_info *info =
11516 + (struct condition6_info *) matchinfo;
11517 + struct condition_variable *var, *prev = NULL;
11519 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
11522 + write_lock(&list_lock);
11524 + for (var = head; var && strcmp(info->name, var->status_proc->name);
11525 + prev = var, var = var->next);
11527 + if (var && atomic_dec_and_test(&var->refcount)) {
11529 + prev->next = var->next;
11531 + head = var->next;
11533 + write_unlock(&list_lock);
11534 + remove_proc_entry(var->status_proc->name, proc_net_condition);
11537 + write_unlock(&list_lock);
11541 +static struct ip6t_match condition_match = {
11542 + .name = "condition",
11544 + .checkentry = &checkentry,
11545 + .destroy = &destroy,
11546 + .me = THIS_MODULE
11555 + rwlock_init(&list_lock);
11556 + proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
11558 + if (proc_net_condition) {
11559 + errorcode = ipt_register_match(&condition_match);
11562 + remove_proc_entry("ip6t_condition", proc_net);
11564 + errorcode = -EACCES;
11566 + return errorcode;
11570 +static void __exit
11573 + ipt_unregister_match(&condition_match);
11574 + remove_proc_entry("ip6t_condition", proc_net);
11577 +module_init(init);
11578 +module_exit(fini);