1 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter.h linux-2.6.6-rc3/include/linux/netfilter.h
2 --- linux-2.6.6-rc3.org/include/linux/netfilter.h 2004-04-28 03:35:48.000000000 +0200
3 +++ linux-2.6.6-rc3/include/linux/netfilter.h 2004-04-29 11:18:06.000000000 +0200
5 <= 0x2000 is used for protocol-flags. */
6 #define NFC_UNKNOWN 0x4000
7 #define NFC_ALTERED 0x8000
8 +#define NFC_TRACE 0x10000
11 #include <linux/config.h>
13 /* This is gross, but inline doesn't cut it for avoiding the function
14 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
15 #ifdef CONFIG_NETFILTER_DEBUG
16 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
17 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
18 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
21 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22 #define NF_HOOK_THRESH nf_hook_slow
24 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
25 -(list_empty(&nf_hooks[(pf)][(hook)]) \
26 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
27 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
29 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
30 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
33 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
35 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
36 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
38 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
39 struct net_device *indev, struct net_device *outdev,
42 #else /* !CONFIG_NETFILTER */
43 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
44 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
45 #endif /*CONFIG_NETFILTER*/
48 +#ifdef CONFIG_IP_NF_NAT_NEEDED
50 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
53 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
55 + if (family == AF_INET)
56 + nf_nat_decode_session4(skb, fl);
58 +#else /* CONFIG_IP_NF_NAT_NEEDED */
59 +#define nf_nat_decode_session(skb,fl,family)
60 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
61 +#endif /* CONFIG_XFRM */
64 #endif /*__LINUX_NETFILTER_H*/
65 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h linux-2.6.6-rc3/include/linux/netfilter_helpers.h
66 --- linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
67 +++ linux-2.6.6-rc3/include/linux/netfilter_helpers.h 2004-04-29 11:20:13.000000000 +0200
70 + * Helpers for netfiler modules. This file provides implementations for basic
71 + * functions such as strncasecmp(), etc.
73 + * gcc will warn for defined but unused functions, so we only include the
74 + * functions requested. The following macros are used:
75 + * NF_NEED_STRNCASECMP nf_strncasecmp()
76 + * NF_NEED_STRTOU16 nf_strtou16()
77 + * NF_NEED_STRTOU32 nf_strtou32()
79 +#ifndef _NETFILTER_HELPERS_H
80 +#define _NETFILTER_HELPERS_H
82 +/* Only include these functions for kernel code. */
85 +#include <linux/ctype.h>
86 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
89 + * The standard strncasecmp()
91 +#ifdef NF_NEED_STRNCASECMP
93 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
95 + if (s1 == NULL || s2 == NULL)
97 + if (s1 == NULL && s2 == NULL)
101 + return (s1 == NULL) ? -1 : 1;
103 + while (len > 0 && tolower(*s1) == tolower(*s2))
109 + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
111 +#endif /* NF_NEED_STRNCASECMP */
114 + * Parse a string containing a 16-bit unsigned integer.
115 + * Returns the number of chars used, or zero if no number is found.
117 +#ifdef NF_NEED_STRTOU16
119 +nf_strtou16(const char* pbuf, u_int16_t* pval)
124 + while (isdigit(pbuf[n]))
126 + *pval = (*pval * 10) + (pbuf[n] - '0');
132 +#endif /* NF_NEED_STRTOU16 */
135 + * Parse a string containing a 32-bit unsigned integer.
136 + * Returns the number of chars used, or zero if no number is found.
138 +#ifdef NF_NEED_STRTOU32
140 +nf_strtou32(const char* pbuf, u_int32_t* pval)
145 + while (pbuf[n] >= '0' && pbuf[n] <= '9')
147 + *pval = (*pval * 10) + (pbuf[n] - '0');
153 +#endif /* NF_NEED_STRTOU32 */
156 + * Given a buffer and length, advance to the next line and mark the current
159 +#ifdef NF_NEED_NEXTLINE
161 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
171 + while (p[off] != '\n')
182 + /* if we saw a crlf, physlen needs adjusted */
183 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
188 + /* advance past the newline */
192 + *plinelen = physlen;
197 +#endif /* NF_NEED_NEXTLINE */
199 +#endif /* __KERNEL__ */
201 +#endif /* _NETFILTER_HELPERS_H */
202 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
203 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-28 03:36:37.000000000 +0200
204 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-29 11:21:43.000000000 +0200
207 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
208 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
209 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
211 /* per conntrack: protocol private data */
212 union ip_conntrack_proto {
213 /* insert conntrack proto private data here */
214 + struct ip_ct_sctp sctp;
215 struct ip_ct_tcp tcp;
216 struct ip_ct_icmp icmp;
221 /* Add protocol helper include file here */
222 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
223 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
224 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
225 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
226 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
227 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
228 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
229 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
231 /* per expectation: application helper private data */
232 union ip_conntrack_expect_help {
233 /* insert conntrack helper private data (expect) here */
234 + struct ip_ct_talk_expect exp_talk_info;
235 + struct ip_ct_rtsp_expect exp_rtsp_info;
236 + struct ip_ct_rsh_expect exp_rsh_info;
237 + struct ip_ct_mms_expect exp_mms_info;
238 + struct ip_ct_h225_expect exp_h225_info;
239 struct ip_ct_amanda_expect exp_amanda_info;
240 struct ip_ct_ftp_expect exp_ftp_info;
241 struct ip_ct_irc_expect exp_irc_info;
243 /* per conntrack: application helper private data */
244 union ip_conntrack_help {
245 /* insert conntrack helper private data (master) here */
246 + struct ip_ct_talk_master ct_talk_info;
247 + struct ip_ct_rtsp_master ct_rtsp_info;
248 + struct ip_ct_rsh_master ct_rsh_info;
249 + struct ip_ct_mms_master ct_mms_info;
250 + struct ip_ct_h225_master ct_h225_info;
251 struct ip_ct_ftp_master ct_ftp_info;
252 struct ip_ct_irc_master ct_irc_info;
256 #endif /* CONFIG_IP_NF_NAT_NEEDED */
258 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
259 + unsigned long mark;
264 /* get master conntrack via master expectation */
265 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
266 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 1970-01-01 01:00:00.000000000 +0100
267 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 2004-04-29 11:17:55.000000000 +0200
269 +#ifndef _IP_CT_CUSEEME
270 +#define _IP_CT_CUSEEME
272 +#define CUSEEME_PORT 7648
274 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
277 +/* CuSeeMe data header */
279 + u_int16_t dest_family;
280 + u_int16_t dest_port;
281 + u_int32_t dest_addr;
287 + u_int16_t data_type;
288 + /* possible values:
292 + * 100 acknowledge connectivity when there
293 + * is nothing else to send
294 + * 101 OpenContinue packet
295 + * 104 display a text message and
296 + * disconnect (used by reflector to
297 + * kick clients off)
298 + * 105 display a text message (welcome
299 + * message from reflector)
300 + * 106 exchanged among reflectors for
301 + * reflector interoperation
302 + * 107 carry aux stream data when there is
303 + * no video to piggy-back on
304 + * 108 obsolete (used in Mac alpha version)
305 + * 109 obsolete (used in Mac alpha version)
306 + * 110 used for data rate control
307 + * 111 used for data rate control
308 + * 256 aux data control messages
309 + * 257 aux data packets
311 + u_int16_t packet_len;
314 +/* Open Continue Header */
316 + struct cu_header cu_head;
317 + u_int16_t client_count; /* Number of client info structs */
319 + char user_name[20];
320 + char stuff[4]; /* Flags, version stuff, etc */
323 +/* Client info structures */
324 +struct client_info {
325 + u_int32_t address; /* Client address */
326 + char stuff[8]; /* Flags, pruning bitfield, packet counts, etc */
330 +/* This structure is per expected connection */
331 +struct ip_ct_cuseeme_expect {
334 +/* This structure exists only once per master */
335 +struct ip_ct_cuseeme_master {
338 +#endif /* _IP_CT_CUSEEME */
339 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
340 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
341 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-04-29 11:18:00.000000000 +0200
343 +#ifndef _IP_CONNTRACK_H323_H
344 +#define _IP_CONNTRACK_H323_H
345 +/* H.323 connection tracking. */
348 +/* Protects H.323 related data */
349 +#include <linux/netfilter_ipv4/lockhelp.h>
350 +DECLARE_LOCK_EXTERN(ip_h323_lock);
353 +/* Default H.225 port */
354 +#define H225_PORT 1720
356 +/* This structure is per expected connection */
357 +struct ip_ct_h225_expect {
358 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
359 + enum ip_conntrack_dir dir; /* Direction of the original connection */
360 + unsigned int offset; /* offset of the address in the payload */
363 +/* This structure exists only once per master */
364 +struct ip_ct_h225_master {
365 + int is_h225; /* H.225 or H.245 connection */
366 +#ifdef CONFIG_IP_NF_NAT_NEEDED
367 + enum ip_conntrack_dir dir; /* Direction of the original connection */
368 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
369 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
373 +#endif /* _IP_CONNTRACK_H323_H */
374 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
375 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
376 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-04-29 11:19:01.000000000 +0200
378 +#ifndef _IP_CONNTRACK_MMS_H
379 +#define _IP_CONNTRACK_MMS_H
383 +#include <linux/netfilter_ipv4/lockhelp.h>
385 +DECLARE_LOCK_EXTERN(ip_mms_lock);
387 +#define MMS_PORT 1755
388 +#define MMS_SRV_MSG_ID 196610
390 +#define MMS_SRV_MSG_OFFSET 36
391 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
392 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
393 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
394 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
397 +/* This structure is per expected connection */
398 +struct ip_ct_mms_expect {
404 +/* This structure exists only once per master */
405 +struct ip_ct_mms_master {
408 +#endif /* _IP_CONNTRACK_MMS_H */
409 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
410 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
411 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-04-29 11:19:53.000000000 +0200
413 +#ifndef _IP_CT_QUAKE3
414 +#define _IP_CT_QUAKE3
416 +/* Don't confuse with 27960, often used as the Server Port */
417 +#define QUAKE3_MASTER_PORT 27950
419 +struct quake3_search {
420 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
421 + const char *pattern;
425 +/* This structure is per expected connection */
426 +struct ip_ct_quake3_expect {
429 +/* This structure exists only once per master */
430 +struct ip_ct_quake3_master {
433 +#endif /* _IP_CT_QUAKE3 */
434 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
435 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
436 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2004-04-29 11:20:02.000000000 +0200
438 +/* RPC extension for IP connection tracking, Version 2.2
439 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
440 + * - original rpc tracking module
441 + * - "recent" connection handling for kernel 2.3+ netfilter
443 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
444 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
446 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
447 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
448 + * - extended matching to support filtering on procedures
450 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
452 + * This program is free software; you can redistribute it and/or
453 + * modify it under the terms of the GNU General Public License
454 + * as published by the Free Software Foundation; either version
455 + * 2 of the License, or (at your option) any later version.
459 +#include <asm/param.h>
460 +#include <linux/sched.h>
461 +#include <linux/timer.h>
462 +#include <linux/stddef.h>
463 +#include <linux/list.h>
465 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
467 +#ifndef _IP_CONNTRACK_RPC_H
468 +#define _IP_CONNTRACK_RPC_H
470 +#define RPC_PORT 111
473 +/* Datum in RPC packets are encoded in XDR */
474 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
476 +/* Fast timeout, to deny DoS atacks */
477 +#define EXP (60 * HZ)
479 +/* Normal timeouts */
480 +#define EXPIRES (180 * HZ)
482 +/* For future conections RPC, using client's cache bindings
483 + * I'll use ip_conntrack_lock to lock these lists */
485 +/* This identifies each request and stores protocol */
487 + struct list_head list;
496 + struct timer_list timeout;
499 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
500 + u_int32_t ip, u_int32_t port) {
501 + return (p->xid == xid && p->ip == ip && p->port);
505 +#endif /* _IP_CONNTRACK_RPC_H */
506 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
507 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
508 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-04-29 11:20:06.000000000 +0200
510 +/* RSH extension for IP connection tracking, Version 1.0
511 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
512 + * based on HW's ip_conntrack_irc.c
514 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
516 + * This program is free software; you can redistribute it and/or
517 + * modify it under the terms of the GNU General Public License
518 + * as published by the Free Software Foundation; either version
519 + * 2 of the License, or (at your option) any later version.
521 +#ifndef _IP_CONNTRACK_RSH_H
522 +#define _IP_CONNTRACK_RSH_H
525 +#include <linux/netfilter_ipv4/lockhelp.h>
527 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
531 +#define RSH_PORT 514
533 +/* This structure is per expected connection */
534 +struct ip_ct_rsh_expect
539 +/* This structure exists only once per master */
540 +struct ip_ct_rsh_master {
543 +#endif /* _IP_CONNTRACK_RSH_H */
545 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
546 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
547 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-04-29 11:20:13.000000000 +0200
550 + * RTSP extension for IP connection tracking.
551 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
552 + * based on ip_conntrack_irc.h
554 + * This program is free software; you can redistribute it and/or
555 + * modify it under the terms of the GNU General Public License
556 + * as published by the Free Software Foundation; either version
557 + * 2 of the License, or (at your option) any later version.
559 +#ifndef _IP_CONNTRACK_RTSP_H
560 +#define _IP_CONNTRACK_RTSP_H
562 +/* #define IP_NF_RTSP_DEBUG */
563 +#define IP_NF_RTSP_VERSION "0.01"
565 +/* port block types */
567 + pb_single, /* client_port=x */
568 + pb_range, /* client_port=x-y */
569 + pb_discon /* client_port=x/y (rtspbis) */
572 +/* We record seq number and length of rtsp headers here, all in host order. */
575 + * This structure is per expected connection. It is a member of struct
576 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
577 + * there and we are expected to only store the length of the data which
578 + * needs replaced. If a packet contains multiple RTSP messages, we create
579 + * one expected connection per message.
581 + * We use these variables to mark the entire header block. This may seem
582 + * like overkill, but the nature of RTSP requires it. A header may appear
583 + * multiple times in a message. We must treat two Transport headers the
584 + * same as one Transport header with two entries.
586 +struct ip_ct_rtsp_expect
588 + u_int32_t len; /* length of header block */
589 + portblock_t pbtype; /* Type of port block that was requested */
590 + u_int16_t loport; /* Port that was requested, low or first */
591 + u_int16_t hiport; /* Port that was requested, high or second */
593 + uint method; /* RTSP method */
594 + uint cseq; /* CSeq from request */
598 +/* This structure exists only once per master */
599 +struct ip_ct_rtsp_master
607 +#include <linux/netfilter_ipv4/lockhelp.h>
609 +#define RTSP_PORT 554
611 +/* Protects rtsp part of conntracks */
612 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
614 +#endif /* __KERNEL__ */
616 +#endif /* _IP_CONNTRACK_RTSP_H */
617 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
618 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
619 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-04-29 11:20:17.000000000 +0200
621 +#ifndef _IP_CONNTRACK_SCTP_H
622 +#define _IP_CONNTRACK_SCTP_H
623 +/* SCTP tracking. */
625 +enum sctp_conntrack {
626 + SCTP_CONNTRACK_NONE,
627 + SCTP_CONNTRACK_CLOSED,
628 + SCTP_CONNTRACK_COOKIE_WAIT,
629 + SCTP_CONNTRACK_COOKIE_ECHOED,
630 + SCTP_CONNTRACK_ESTABLISHED,
631 + SCTP_CONNTRACK_SHUTDOWN_SENT,
632 + SCTP_CONNTRACK_SHUTDOWN_RECD,
633 + SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
639 + enum sctp_conntrack state;
641 + u_int32_t vtag[IP_CT_DIR_MAX];
642 + u_int32_t ttag[IP_CT_DIR_MAX];
645 +#endif /* _IP_CONNTRACK_SCTP_H */
646 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
647 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
648 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-04-29 11:21:43.000000000 +0200
650 +#ifndef _IP_CONNTRACK_TALK_H
651 +#define _IP_CONNTRACK_TALK_H
652 +/* TALK tracking. */
655 +#include <linux/in.h>
656 +#include <linux/netfilter_ipv4/lockhelp.h>
658 +/* Protects talk part of conntracks */
659 +DECLARE_LOCK_EXTERN(ip_talk_lock);
663 +#define TALK_PORT 517
664 +#define NTALK_PORT 518
666 +/* talk structures and constants from <protocols/talkd.h> */
669 + * 4.3BSD struct sockaddr
672 + u_int16_t ta_family;
675 + u_int32_t ta_junk1;
676 + u_int32_t ta_junk2;
679 +#define TALK_OLD_NSIZE 9
680 +#define TALK_NSIZE 12
681 +#define TALK_TTY_NSIZE 16
684 + * Client->server request message formats.
687 + u_char type; /* request type, see below */
688 + char l_name[TALK_OLD_NSIZE];/* caller's name */
689 + char r_name[TALK_OLD_NSIZE];/* callee's name */
691 + u_int32_t id_num; /* message id */
692 + int32_t pid; /* caller's process id */
693 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
694 + struct talk_addr addr; /* old (4.3) style */
695 + struct talk_addr ctl_addr; /* old (4.3) style */
699 + u_char vers; /* protocol version */
700 + u_char type; /* request type, see below */
701 + u_char answer; /* not used */
703 + u_int32_t id_num; /* message id */
704 + struct talk_addr addr; /* old (4.3) style */
705 + struct talk_addr ctl_addr; /* old (4.3) style */
706 + int32_t pid; /* caller's process id */
707 + char l_name[TALK_NSIZE];/* caller's name */
708 + char r_name[TALK_NSIZE];/* callee's name */
709 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
713 + u_char vers; /* talk protocol version */
714 + u_char type; /* request type */
715 + u_char answer; /* */
716 + u_char extended; /* !0 if additional parts */
717 + u_int32_t id_num; /* message id number (dels) */
718 + struct talk_addr addr; /* target address */
719 + struct talk_addr ctl_addr; /* reply to address */
720 + int32_t pid; /* caller's process id */
721 + char l_name[TALK_NSIZE]; /* caller's name */
722 + char r_name[TALK_NSIZE]; /* callee's name */
723 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
727 + * Server->client response message formats.
729 +struct talk_response {
730 + u_char type; /* type of request message, see below */
731 + u_char answer; /* response to request message, see below */
733 + u_int32_t id_num; /* message id */
734 + struct talk_addr addr; /* address for establishing conversation */
737 +struct ntalk_response {
738 + u_char vers; /* protocol version */
739 + u_char type; /* type of request message, see below */
740 + u_char answer; /* response to request message, see below */
742 + u_int32_t id_num; /* message id */
743 + struct talk_addr addr; /* address for establishing conversation */
746 +struct ntalk2_response {
747 + u_char vers; /* protocol version */
748 + u_char type; /* type of request message */
749 + u_char answer; /* response to request */
750 + u_char rvers; /* Version of answering vers*/
751 + u_int32_t id_num; /* message id number */
752 + struct talk_addr addr; /* address for connection */
753 + /* This is at the end to compatiblize this with NTALK version. */
754 + char r_name[TALK_NSIZE]; /* callee's name */
757 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
758 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
759 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
761 +#define TALK_VERSION 0 /* protocol versions */
762 +#define NTALK_VERSION 1
763 +#define NTALK2_VERSION 2
765 +/* message type values */
766 +#define LEAVE_INVITE 0 /* leave invitation with server */
767 +#define LOOK_UP 1 /* check for invitation by callee */
768 +#define DELETE 2 /* delete invitation by caller */
769 +#define ANNOUNCE 3 /* announce invitation by caller */
771 +#define REPLY_QUERY 4 /* request reply data from local daemon */
774 +#define SUCCESS 0 /* operation completed properly */
775 +#define NOT_HERE 1 /* callee not logged in */
776 +#define FAILED 2 /* operation failed for unexplained reason */
777 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
778 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
779 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
780 +#define BADVERSION 6 /* request has invalid protocol version */
781 +#define BADADDR 7 /* request has invalid addr value */
782 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
784 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
785 +#define TRY_HERE 10 /* Not on this machine, try this */
786 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
787 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
789 +/* We don't really need much for talk */
790 +struct ip_ct_talk_expect
792 + /* Port that was to be used */
796 +/* This structure exists only once per master */
797 +struct ip_ct_talk_master
801 +#endif /* _IP_CONNTRACK_TALK_H */
802 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
803 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-28 03:36:22.000000000 +0200
804 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-29 11:20:17.000000000 +0200
814 /* The manipulable part of the tuple. */
825 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h
826 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h 2004-04-28 03:35:48.000000000 +0200
827 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h 2004-04-29 11:17:15.000000000 +0200
830 unsigned int comefrom;
832 + /* Name of the chain */
835 + /* Rule number in the chain. */
838 /* Packet and byte counters. */
839 struct ipt_counters counters;
841 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
842 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
843 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-29 11:10:59.000000000 +0200
845 +#ifndef _IPT_CONNMARK_H_target
846 +#define _IPT_CONNMARK_H_target
848 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
849 + * by Henrik Nordstrom <hno@marasystems.com>
851 + * This program is free software; you can redistribute it and/or modify
852 + * it under the terms of the GNU General Public License as published by
853 + * the Free Software Foundation; either version 2 of the License, or
854 + * (at your option) any later version.
858 + IPT_CONNMARK_SET = 0,
860 + IPT_CONNMARK_RESTORE
863 +struct ipt_connmark_target_info {
864 + unsigned long mark;
865 + unsigned long mask;
869 +#endif /*_IPT_CONNMARK_H_target*/
870 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
871 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
872 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-29 11:17:03.000000000 +0200
874 +#ifndef _IPT_IPMARK_H_target
875 +#define _IPT_IPMARK_H_target
877 +struct ipt_ipmark_target_info {
878 + unsigned long andmask;
879 + unsigned long ormask;
883 +#define IPT_IPMARK_SRC 0
884 +#define IPT_IPMARK_DST 1
886 +#endif /*_IPT_IPMARK_H_target*/
887 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
888 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
889 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-29 11:17:18.000000000 +0200
894 +struct ipt_XOR_info {
896 + u_int8_t block_size;
899 +#endif /* _IPT_XOR_H */
900 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
901 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
902 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-29 11:17:23.000000000 +0200
904 +#ifndef _IPT_ADDRTYPE_H
905 +#define _IPT_ADDRTYPE_H
907 +struct ipt_addrtype_info {
908 + u_int16_t source; /* source-type mask */
909 + u_int16_t dest; /* dest-type mask */
915 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
916 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
917 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-29 11:10:59.000000000 +0200
919 +#ifndef _IPT_CONNMARK_H
920 +#define _IPT_CONNMARK_H
922 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
923 + * by Henrik Nordstrom <hno@marasystems.com>
925 + * This program is free software; you can redistribute it and/or modify
926 + * it under the terms of the GNU General Public License as published by
927 + * the Free Software Foundation; either version 2 of the License, or
928 + * (at your option) any later version.
931 +struct ipt_connmark_info {
932 + unsigned long mark, mask;
936 +#endif /*_IPT_CONNMARK_H*/
937 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h
938 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
939 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-29 11:19:41.000000000 +0200
941 +#ifndef _IPT_POLICY_H
942 +#define _IPT_POLICY_H
944 +#define POLICY_MAX_ELEM 4
946 +enum ipt_policy_flags
948 + POLICY_MATCH_IN = 0x1,
949 + POLICY_MATCH_OUT = 0x2,
950 + POLICY_MATCH_NONE = 0x4,
951 + POLICY_MATCH_STRICT = 0x8,
954 +enum ipt_policy_modes
956 + POLICY_MODE_TRANSPORT,
960 +struct ipt_policy_spec
970 +struct ipt_policy_elem
981 + struct ipt_policy_spec match;
982 + struct ipt_policy_spec invert;
985 +struct ipt_policy_info
987 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
992 +#endif /* _IPT_POLICY_H */
993 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h
994 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
995 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h 2004-04-29 11:20:02.000000000 +0200
997 +/* RPC extension for IP netfilter matching, Version 2.2
998 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
999 + * - original rpc tracking module
1000 + * - "recent" connection handling for kernel 2.3+ netfilter
1002 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1003 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1005 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1006 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
1007 + * - extended matching to support filtering on procedures
1009 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
1011 + * This program is free software; you can redistribute it and/or
1012 + * modify it under the terms of the GNU General Public License
1013 + * as published by the Free Software Foundation; either version
1014 + * 2 of the License, or (at your option) any later version.
1021 +struct ipt_rpc_data;
1023 +struct ipt_rpc_info {
1026 + const char c_procs[1408];
1028 + struct ipt_rpc_data *data;
1031 +#endif /* _IPT_RPC_H */
1032 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h
1033 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1034 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-04-29 11:21:38.000000000 +0200
1036 +#ifndef _IPT_STRING_H
1037 +#define _IPT_STRING_H
1039 +/* *** PERFORMANCE TWEAK ***
1040 + * Packet size and search string threshold,
1041 + * above which sublinear searches is used. */
1042 +#define IPT_STRING_HAYSTACK_THRESH 100
1043 +#define IPT_STRING_NEEDLE_THRESH 20
1045 +#define BM_MAX_NLEN 256
1046 +#define BM_MAX_HLEN 1024
1048 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1050 +struct ipt_string_info {
1051 + char string[BM_MAX_NLEN];
1056 +#endif /* _IPT_STRING_H */
1057 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
1058 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h 2004-04-28 03:36:31.000000000 +0200
1059 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h 2004-04-29 11:18:03.000000000 +0200
1062 #include <linux/config.h>
1063 #include <linux/netfilter.h>
1064 +#include <linux/netdevice.h>
1065 +#include <net/protocol.h>
1067 /* IP Cache bits. */
1068 /* Src IP address. */
1070 Returns true or false. */
1071 extern int skb_ip_make_writable(struct sk_buff **pskb,
1072 unsigned int writable_len);
1074 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1075 +#include <net/route.h>
1076 +#include <net/xfrm.h>
1078 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1080 + return !skb->sp || skb->sp->decap_done;
1084 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1086 + return skb->sp && !skb->sp->decap_done
1087 + && (!ipprot || !ipprot->xfrm_prot);
1090 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1092 + return skb->sp && !skb->sp->decap_done
1093 + && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1096 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1097 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1098 +#else /* CONFIG_XFRM */
1099 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1105 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1110 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1115 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1120 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1124 +#endif /* CONFIG_XFRM */
1125 #endif /*__KERNEL__*/
1127 #endif /*__LINUX_IP_NETFILTER_H*/
1128 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1129 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-28 03:36:37.000000000 +0200
1130 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-29 11:17:15.000000000 +0200
1131 @@ -140,6 +140,12 @@
1133 unsigned int comefrom;
1135 + /* Name of the chain */
1138 + /* Rule number in the chain. */
1139 + u_int32_t rulenum;
1141 /* Packet and byte counters. */
1142 struct ip6t_counters counters;
1144 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1145 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-28 03:36:03.000000000 +0200
1146 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-29 11:19:40.000000000 +0200
1148 #define IP6T_OWNER_GID 0x02
1149 #define IP6T_OWNER_PID 0x04
1150 #define IP6T_OWNER_SID 0x08
1151 +#define IP6T_OWNER_COMM 0x10
1153 struct ip6t_owner_info {
1159 u_int8_t match, invert; /* flags */
1162 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1163 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1164 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h 2004-04-29 11:19:41.000000000 +0200
1166 +#ifndef _IP6T_POLICY_H
\r
1167 +#define _IP6T_POLICY_H
\r
1169 +#define POLICY_MAX_ELEM 4
\r
1171 +enum ip6t_policy_flags
\r
1173 + POLICY_MATCH_IN = 0x1,
\r
1174 + POLICY_MATCH_OUT = 0x2,
\r
1175 + POLICY_MATCH_NONE = 0x4,
\r
1176 + POLICY_MATCH_STRICT = 0x8,
\r
1179 +enum ip6t_policy_modes
\r
1181 + POLICY_MODE_TRANSPORT,
\r
1182 + POLICY_MODE_TUNNEL
\r
1185 +struct ip6t_policy_spec
\r
1187 + u_int8_t saddr:1,
\r
1195 +struct ip6t_policy_elem
\r
1197 + struct in6_addr saddr;
\r
1198 + struct in6_addr smask;
\r
1199 + struct in6_addr daddr;
\r
1200 + struct in6_addr dmask;
\r
1202 + u_int32_t reqid;
\r
1206 + struct ip6t_policy_spec match;
\r
1207 + struct ip6t_policy_spec invert;
\r
1210 +struct ip6t_policy_info
\r
1212 + struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
\r
1213 + u_int16_t flags;
\r
1217 +#endif /* _IP6T_POLICY_H */
\r
1218 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1219 --- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1220 +++ linux-2.6.6-rc3/include/linux/netfilter_mime.h 2004-04-29 11:20:13.000000000 +0200
1223 + * MIME functions for netfilter modules. This file provides implementations
1224 + * for basic MIME parsing. MIME headers are used in many protocols, such as
1225 + * HTTP, RTSP, SIP, etc.
1227 + * gcc will warn for defined but unused functions, so we only include the
1228 + * functions requested. The following macros are used:
1229 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1231 +#ifndef _NETFILTER_MIME_H
1232 +#define _NETFILTER_MIME_H
1234 +/* Only include these functions for kernel code. */
1237 +#include <linux/ctype.h>
1240 + * Given a buffer and length, advance to the next line and mark the current
1241 + * line. If the current line is empty, *plinelen will be set to zero. If
1242 + * not, it will be set to the actual line length (including CRLF).
1244 + * 'line' in this context means logical line (includes LWS continuations).
1245 + * Returns 1 on success, 0 on failure.
1247 +#ifdef NF_NEED_MIME_NEXTLINE
1249 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1253 + int is_first_line = 1;
1262 + while (p[off] != '\n')
1273 + /* if we saw a crlf, physlen needs adjusted */
1274 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1279 + /* advance past the newline */
1282 + /* check for an empty line */
1288 + /* check for colon on the first physical line */
1289 + if (is_first_line)
1291 + is_first_line = 0;
1292 + if (memchr(p+(*poff), ':', physlen) == NULL)
1298 + while (p[off] == ' ' || p[off] == '\t');
1300 + *plineoff = *poff;
1301 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
1306 +#endif /* NF_NEED_MIME_NEXTLINE */
1308 +#endif /* __KERNEL__ */
1310 +#endif /* _NETFILTER_MIME_H */
1311 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
1312 --- linux-2.6.6-rc3.org/include/net/ip.h 2004-04-28 03:36:16.000000000 +0200
1313 +++ linux-2.6.6-rc3/include/net/ip.h 2004-04-29 11:18:02.000000000 +0200
1315 #include <linux/netdevice.h>
1316 #include <linux/inetdevice.h>
1317 #include <linux/in_route.h>
1318 +#include <linux/netfilter.h>
1319 +#include <linux/netfilter_ipv4.h>
1320 #include <net/route.h>
1321 #include <net/arp.h>
1324 #define IPSKB_TRANSLATED 2
1325 #define IPSKB_FORWARDED 4
1326 #define IPSKB_XFRM_TUNNEL_SIZE 8
1327 +#define IPSKB_XFRM_TRANSFORMED 16
1331 @@ -212,6 +215,12 @@
1332 __ip_select_ident(iph, dst, more);
1335 +extern inline int ip_dst_output(struct sk_buff *skb)
1337 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1338 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1342 * Map a multicast IP onto multicast MAC for type ethernet.
1344 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
1345 --- linux-2.6.6-rc3.org/include/net/protocol.h 2004-04-28 03:35:44.000000000 +0200
1346 +++ linux-2.6.6-rc3/include/net/protocol.h 2004-04-29 11:18:03.000000000 +0200
1348 int (*handler)(struct sk_buff *skb);
1349 void (*err_handler)(struct sk_buff *skb, u32 info);
1354 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
1355 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
1356 --- linux-2.6.6-rc3.org/include/net/tcp.h 2004-04-29 11:24:38.000000000 +0200
1357 +++ linux-2.6.6-rc3/include/net/tcp.h 2004-04-29 11:19:32.000000000 +0200
1359 extern void tcp_bucket_unlock(struct sock *sk);
1360 extern int tcp_port_rover;
1361 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
1362 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
1364 /* These are AF independent. */
1365 static __inline__ int tcp_bhashfn(__u16 lport)
1366 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
1367 --- linux-2.6.6-rc3.org/include/net/udp.h 2004-04-28 03:36:29.000000000 +0200
1368 +++ linux-2.6.6-rc3/include/net/udp.h 2004-04-29 11:19:32.000000000 +0200
1370 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
1371 extern int udp_disconnect(struct sock *sk, int flags);
1373 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
1375 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
1376 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
1377 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
1378 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
1379 --- linux-2.6.6-rc3.org/include/net/xfrm.h 2004-04-28 03:36:31.000000000 +0200
1380 +++ linux-2.6.6-rc3/include/net/xfrm.h 2004-04-29 11:18:03.000000000 +0200
1385 +#ifdef CONFIG_NETFILTER
1388 struct sec_decap_state x[XFRM_MAX_DEPTH];
1391 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
1392 --- linux-2.6.6-rc3.org/net/core/netfilter.c 2004-04-28 03:35:46.000000000 +0200
1393 +++ linux-2.6.6-rc3/net/core/netfilter.c 2004-04-29 11:18:06.000000000 +0200
1395 #include <linux/icmp.h>
1396 #include <net/sock.h>
1397 #include <net/route.h>
1398 +#include <net/xfrm.h>
1399 +#include <net/ip.h>
1400 #include <linux/ip.h>
1402 /* In this code, we can be waiting indefinitely for userspace to
1404 #ifdef CONFIG_IP_ROUTE_FWMARK
1405 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
1407 - fl.proto = iph->protocol;
1408 if (ip_route_output_key(&rt, &fl) != 0)
1411 @@ -665,6 +666,20 @@
1412 if ((*pskb)->dst->error)
1416 + if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
1417 + struct xfrm_policy_afinfo *afinfo;
1419 + afinfo = xfrm_policy_get_afinfo(AF_INET);
1420 + if (afinfo != NULL) {
1421 + afinfo->decode_session(*pskb, &fl);
1422 + xfrm_policy_put_afinfo(afinfo);
1423 + if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
1429 /* Change in oif may mean change in hh_len. */
1430 hh_len = (*pskb)->dst->dev->hard_header_len;
1431 if (skb_headroom(*pskb) < hh_len) {
1432 @@ -682,6 +697,71 @@
1437 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1439 + skb->sp->decap_done = 1;
1440 + dst_release(skb->dst);
1443 + return netif_rx(skb);
1446 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
1448 + __skb_push(skb, skb->data - skb->nh.raw);
1449 + /* Fix header len and checksum if last xfrm was transport mode */
1450 + if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
1451 + skb->nh.iph->tot_len = htons(skb->len);
1452 + ip_send_check(skb->nh.iph);
1454 + return nf_rcv_postxfrm_nonlocal(skb);
1457 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1458 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1459 +#include <linux/netfilter_ipv4/ip_nat.h>
1461 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
1463 + struct ip_conntrack *ct;
1464 + struct ip_conntrack_tuple *t;
1465 + struct ip_nat_info_manip *m;
1468 + if (skb->nfct == NULL)
1470 + ct = (struct ip_conntrack *)skb->nfct->master;
1472 + for (i = 0; i < ct->nat.info.num_manips; i++) {
1473 + m = &ct->nat.info.manips[i];
1474 + t = &ct->tuplehash[m->direction].tuple;
1476 + switch (m->hooknum) {
1477 + case NF_IP_PRE_ROUTING:
1478 + if (m->maniptype != IP_NAT_MANIP_DST)
1480 + fl->fl4_dst = t->dst.ip;
1481 + if (t->dst.protonum == IPPROTO_TCP ||
1482 + t->dst.protonum == IPPROTO_UDP)
1483 + fl->fl_ip_dport = t->dst.u.tcp.port;
1485 +#ifdef CONFIG_IP_NF_NAT_LOCAL
1486 + case NF_IP_LOCAL_IN:
1487 + if (m->maniptype != IP_NAT_MANIP_SRC)
1489 + fl->fl4_src = t->src.ip;
1490 + if (t->dst.protonum == IPPROTO_TCP ||
1491 + t->dst.protonum == IPPROTO_UDP)
1492 + fl->fl_ip_sport = t->src.u.tcp.port;
1498 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
1501 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1503 struct sk_buff *nskb;
1505 EXPORT_SYMBOL(nf_unregister_hook);
1506 EXPORT_SYMBOL(nf_unregister_queue_handler);
1507 EXPORT_SYMBOL(nf_unregister_sockopt);
1508 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
1509 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
1510 --- linux-2.6.6-rc3.org/net/ipv4/ah4.c 2004-04-28 03:36:34.000000000 +0200
1511 +++ linux-2.6.6-rc3/net/ipv4/ah4.c 2004-04-29 11:18:03.000000000 +0200
1513 err = -EHOSTUNREACH;
1516 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1517 return NET_XMIT_BYPASS;
1521 .handler = xfrm4_rcv,
1522 .err_handler = ah4_err,
1527 static int __init ah4_init(void)
1528 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
1529 --- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
1530 +++ linux-2.6.6-rc3/net/ipv4/esp4.c 2004-04-29 11:18:03.000000000 +0200
1532 err = -EHOSTUNREACH;
1535 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1536 return NET_XMIT_BYPASS;
1540 .handler = xfrm4_rcv,
1541 .err_handler = esp4_err,
1546 static int __init esp4_init(void)
1547 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
1548 --- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
1549 +++ linux-2.6.6-rc3/net/ipv4/igmp.c 2004-04-29 11:18:02.000000000 +0200
1551 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
1553 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
1558 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
1560 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
1562 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1567 static void igmp_gq_timer_expire(unsigned long data)
1568 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
1569 --- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c 2004-04-28 03:34:59.000000000 +0200
1570 +++ linux-2.6.6-rc3/net/ipv4/ip_forward.c 2004-04-29 11:18:03.000000000 +0200
1572 if (unlikely(opt->optlen))
1573 ip_forward_options(skb);
1575 - return dst_output(skb);
1576 + return ip_dst_output(skb);
1579 int ip_forward(struct sk_buff *skb)
1580 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
1581 --- linux-2.6.6-rc3.org/net/ipv4/ip_input.c 2004-04-29 11:24:39.000000000 +0200
1582 +++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-29 11:18:06.000000000 +0200
1583 @@ -206,10 +206,6 @@
1585 __skb_pull(skb, ihl);
1587 - /* Free reference early: we don't need it any more, and it may
1588 - hold ip_conntrack module loaded indefinitely. */
1591 /* Point into the IP datagram, just past the header. */
1592 skb->h.raw = skb->data;
1594 @@ -224,6 +220,13 @@
1596 hash = protocol & (MAX_INET_PROTOS - 1);
1597 raw_sk = sk_head(&raw_v4_htable[hash]);
1598 + ipprot = inet_protos[hash];
1599 + smp_read_barrier_depends();
1601 + if (nf_xfrm_local_done(skb, ipprot)) {
1602 + nf_rcv_postxfrm_local(skb);
1606 /* If there maybe a raw socket we must check - if not we
1608 @@ -231,14 +234,15 @@
1610 raw_v4_input(skb, skb->nh.iph, hash);
1612 - if ((ipprot = inet_protos[hash]) != NULL) {
1613 + if (ipprot != NULL) {
1616 - smp_read_barrier_depends();
1617 - if (!ipprot->no_policy &&
1618 - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1621 + if (!ipprot->no_policy) {
1622 + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1628 ret = ipprot->handler(skb);
1634 - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1635 - ip_local_deliver_finish);
1636 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1637 + ip_local_deliver_finish, nf_hook_input_cond(skb));
1640 static inline int ip_rcv_finish(struct sk_buff *skb)
1645 + if (nf_xfrm_nonlocal_done(skb))
1646 + return nf_rcv_postxfrm_nonlocal(skb);
1648 #ifdef CONFIG_NET_CLS_ROUTE
1649 if (skb->dst->tclassid) {
1650 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
1655 - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1657 + return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1658 + ip_rcv_finish, nf_hook_input_cond(skb));
1661 IP_INC_STATS_BH(IpInHdrErrors);
1662 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
1663 --- linux-2.6.6-rc3.org/net/ipv4/ip_output.c 2004-04-28 03:36:55.000000000 +0200
1664 +++ linux-2.6.6-rc3/net/ipv4/ip_output.c 2004-04-29 11:18:03.000000000 +0200
1665 @@ -123,6 +123,15 @@
1669 +#ifdef CONFIG_NETFILTER
1670 +/* out-of-line copy is only required with netfilter */
1671 +int ip_dst_output(struct sk_buff *skb)
1673 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1674 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1679 * Add an ip header to a skbuff and send it out.
1684 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1689 static inline int ip_finish_output2(struct sk_buff *skb)
1691 return ip_finish_output(skb);
1694 -int ip_output(struct sk_buff *skb)
1695 +static inline int ip_output2(struct sk_buff *skb)
1697 IP_INC_STATS(IpOutRequests);
1699 @@ -294,6 +303,16 @@
1700 return ip_finish_output(skb);
1703 +int ip_output(struct sk_buff *skb)
1705 + int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
1709 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1710 + skb->dst->dev, ip_output2, transformed);
1713 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
1715 struct sock *sk = skb->sk;
1717 skb->priority = sk->sk_priority;
1719 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1724 IP_INC_STATS(IpOutNoRoutes);
1725 @@ -1177,7 +1196,7 @@
1727 /* Netfilter gets whole the not fragmented skb. */
1728 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1729 - skb->dst->dev, dst_output);
1730 + skb->dst->dev, ip_dst_output);
1733 err = inet->recverr ? net_xmit_errno(err) : 0;
1734 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
1735 --- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c 2004-04-28 03:36:33.000000000 +0200
1736 +++ linux-2.6.6-rc3/net/ipv4/ipcomp.c 2004-04-29 11:18:03.000000000 +0200
1738 err = -EHOSTUNREACH;
1741 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1742 err = NET_XMIT_BYPASS;
1746 .handler = xfrm4_rcv,
1747 .err_handler = ipcomp4_err,
1752 static int __init ipcomp4_init(void)
1753 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
1754 --- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-29 11:24:39.000000000 +0200
1755 +++ linux-2.6.6-rc3/net/ipv4/ipip.c 2004-04-29 11:18:03.000000000 +0200
1756 @@ -478,6 +478,11 @@
1758 read_lock(&ipip_lock);
1759 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
1760 + /* IPIP packets decapsulated by IPsec missed netfilter hooks */
1761 + if (nf_xfrm_local_done(skb, NULL)) {
1762 + nf_rcv_postxfrm_local(skb);
1765 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1768 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
1769 --- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
1770 +++ linux-2.6.6-rc3/net/ipv4/ipmr.c 2004-04-29 11:18:03.000000000 +0200
1771 @@ -1120,7 +1120,7 @@
1772 if (unlikely(opt->optlen))
1773 ip_forward_options(skb);
1775 - return dst_output(skb);
1776 + return ip_dst_output(skb);
1780 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
1781 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig 2004-04-29 11:24:40.000000000 +0200
1782 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig 2004-04-29 11:21:43.000000000 +0200
1783 @@ -206,6 +206,11 @@
1785 To compile it as a module, choose M here. If unsure, say N.
1787 +config IP_NF_MATCH_UNCLEAN
1788 + tristate 'unclean match support (EXPERIMENTAL)'
1789 + depends on EXPERIMENTAL && IP_NF_IPTABLES
1792 config IP_NF_MATCH_TTL
1793 tristate "TTL match support"
1794 depends on IP_NF_IPTABLES
1795 @@ -706,5 +711,149 @@
1796 depends on IP_NF_IPTABLES
1799 +config IP_NF_CONNTRACK_MARK
1800 + bool 'Connection mark tracking support'
1801 +config IP_NF_TARGET_CONNMARK
1802 + tristate 'CONNMARK target support'
1803 + depends on IP_NF_MANGLE
1804 +config IP_NF_MATCH_CONNMARK
1805 + tristate ' Connection mark match support'
1806 + depends on IP_NF_IPTABLES
1809 +config IP_NF_TARGET_IPMARK
1810 + tristate 'IPMARK target support'
1811 + depends on IP_NF_MANGLE
1814 +config IP_NF_TARGET_TARPIT
1815 + tristate 'TARPIT target support'
1816 + depends on IP_NF_FILTER
1819 +config IP_NF_TARGET_TRACE
1820 + tristate 'TRACE target support'
1821 + depends on IP_NF_RAW
1823 + The TRACE target allows packets to be traced as those
1824 + matches any subsequent rule in any table/rule. The matched
1825 + rule and the packet is logged with the prefix
1827 + TRACE: tablename/chainname/rulenum
1829 + If you want to compile it as a module, say M here and read
1830 + <file:Documentation/modules.txt>. If unsure, say `N'.
1833 +config IP_NF_TARGET_XOR
1834 + tristate 'XOR target support'
1835 + depends on IP_NF_MANGLE
1838 +config IP_NF_MATCH_ADDRTYPE
1839 + tristate 'address type match support'
1840 + depends on IP_NF_IPTABLES
1843 +config IP_NF_NAT_CUSEEME
1845 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1846 + default IP_NF_NAT if IP_NF_CUSEEME=y
1847 + default m if IP_NF_CUSEEME=m
1849 +config IP_NF_CUSEEME
1850 + tristate 'CuSeeMe protocol support'
1851 + depends on IP_NF_CONNTRACK
1855 + tristate 'Eggdrop bot support'
1856 + depends on IP_NF_CONNTRACK
1859 +config IP_NF_NAT_H323
1861 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1862 + default IP_NF_NAT if IP_NF_H323=y
1863 + default m if IP_NF_H323=m
1866 + tristate 'H.323 (netmeeting) support'
1867 + depends on IP_NF_CONNTRACK
1870 +config IP_NF_NAT_MMS
1872 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1873 + default IP_NF_NAT if IP_NF_MMS=y
1874 + default m if IP_NF_MMS=m
1877 + tristate 'MMS protocol support'
1878 + depends on IP_NF_CONNTRACK
1881 +config IP_NF_MATCH_POLICY
1882 + tristate "IPsec policy match support"
1883 + depends on IP_NF_IPTABLES && XFRM
1885 + Policy matching allows you to match packets based on the
1886 + IPsec policy that was used during decapsulation/will
1887 + be used during encapsulation.
1889 + To compile it as a module, choose M here. If unsure, say N.
1892 +config IP_NF_NAT_QUAKE3
1894 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1895 + default IP_NF_NAT if IP_NF_QUAKE3=y
1896 + default m if IP_NF_QUAKE3=m
1898 +config IP_NF_QUAKE3
1899 + tristate "Quake3 protocol support"
1900 + depends on IP_NF_CONNTRACK
1903 +config IP_NF_MATCH_RPC
1904 + tristate 'RPC match support'
1905 + depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1909 + tristate 'RSH protocol support'
1910 + depends on IP_NF_CONNTRACK
1913 +config IP_NF_NAT_RTSP
1915 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1916 + default IP_NF_NAT if IP_NF_RTSP=y
1917 + default m if IP_NF_RTSP=m
1919 + tristate ' RTSP protocol support'
1920 + depends on IP_NF_CONNTRACK
1923 +config IP_NF_CT_PROTO_SCTP
1924 + tristate 'SCTP protocol connection tracking support'
1925 + depends on IP_NF_CONNTRACK
1928 +config IP_NF_MATCH_STRING
1929 + tristate 'String match support'
1930 + depends on IP_NF_IPTABLES
1933 +config IP_NF_NAT_TALK
1935 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1936 + default IP_NF_NAT if IP_NF_TALK=y
1937 + default m if IP_NF_TALK=m
1939 + tristate 'talk protocol support'
1940 + depends on IP_NF_CONNTRACK
1945 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
1946 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile 2004-04-29 11:24:40.000000000 +0200
1947 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-29 11:21:43.000000000 +0200
1949 # connection tracking
1950 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1952 +# talk protocol support
1953 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1954 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1957 +# SCTP protocol connection tracking
1958 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
1961 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1962 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1965 # connection tracking helpers
1967 +# rtsp protocol support
1968 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
1969 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
1971 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1972 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1973 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1974 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1975 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1976 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1978 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
1980 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1983 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
1984 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
1985 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1986 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1987 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1988 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1989 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1992 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1994 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1997 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1999 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2000 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2001 obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2002 @@ -87,14 +132,19 @@
2003 obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
2006 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
2007 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
2008 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
2009 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
2010 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
2011 obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
2012 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
2013 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
2014 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
2015 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
2017 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
2018 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
2021 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
2023 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
2024 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
2025 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
2026 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
2027 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
2028 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
2029 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
2030 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
2031 @@ -110,11 +162,14 @@
2032 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
2033 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
2034 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2035 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
2036 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
2037 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
2038 obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
2039 obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
2040 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2041 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2042 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2043 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2045 # generic ARP tables
2046 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c
2047 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 11:24:39.000000000 +0200
2048 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 11:11:00.000000000 +0200
2050 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2051 conntrack->master = expected;
2052 expected->sibling = conntrack;
2053 +#if CONFIG_IP_NF_CONNTRACK_MARK
2054 + conntrack->mark = expected->expectant->mark;
2056 LIST_DELETE(&ip_conntrack_expect_list, expected);
2057 expected->expectant->expecting--;
2058 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2059 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
2060 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
2061 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-04-29 11:17:59.000000000 +0200
2063 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
2064 + * based on ip_conntrack_irc.c
2066 + * This module only supports the share userfile-send command,
2067 + * used by eggdrops to share it's userfile.
2069 + * There are no support for NAT at the moment.
2071 + * This program is free software; you can redistribute it and/or
2072 + * modify it under the terms of the GNU General Public License
2073 + * as published by the Free Software Foundation; either version
2074 + * 2 of the License, or (at your option) any later version.
2076 + * Module load syntax:
2078 + * please give the ports of all Eggdrops You have running
2079 + * on your system, the default port is 3333.
2081 + * 2001-04-19: Security update. IP addresses are now compared
2082 + * to prevent unauthorized "related" access.
2084 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
2085 + * Port to netfilter 'newnat' API.
2088 +#include <linux/module.h>
2089 +#include <linux/netfilter.h>
2090 +#include <linux/ip.h>
2091 +#include <net/checksum.h>
2092 +#include <net/tcp.h>
2094 +#include <linux/netfilter_ipv4/lockhelp.h>
2095 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2097 +#define MAX_PORTS 8
2098 +static int ports[MAX_PORTS];
2099 +static int ports_c = 0;
2100 +static unsigned int egg_timeout = 300;
2102 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
2103 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
2104 +MODULE_LICENSE("GPL");
2106 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2107 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
2110 +DECLARE_LOCK(ip_egg_lock);
2111 +struct module *ip_conntrack_egg = THIS_MODULE;
2114 +#define DEBUGP printk
2116 +#define DEBUGP(format, args...)
2119 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
2120 +/* tries to get the ip_addr and port out of a eggdrop command
2121 + return value: -1 on failure, 0 on success
2122 + data pointer to first byte of DCC command data
2123 + data_end pointer to last byte of dcc command data
2124 + ip returns parsed ip of dcc command
2125 + port returns parsed port of dcc command */
2127 + if (data > data_end)
2130 + *ip = simple_strtoul(data, &data, 10);
2132 + /* skip blanks between ip and port */
2133 + while (*data == ' ' && data < data_end)
2136 + *port = simple_strtoul(data, &data, 10);
2141 +static int help(const struct iphdr *iph, size_t len,
2142 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
2144 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
2145 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
2146 + char *data = (char *) tcph + tcph->doff * 4;
2148 + u_int32_t tcplen = len - iph->ihl * 4;
2149 + u_int32_t datalen = tcplen - tcph->doff * 4;
2150 + int dir = CTINFO2DIR(ctinfo);
2151 + int bytes_scanned = 0;
2152 + struct ip_conntrack_expect exp;
2155 + u_int16_t egg_port;
2157 + DEBUGP("entered\n");
2159 + /* If packet is coming from IRC server */
2160 + if (dir != IP_CT_DIR_REPLY)
2163 + /* Until there's been traffic both ways, don't look in packets. */
2164 + if (ctinfo != IP_CT_ESTABLISHED
2165 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2166 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
2170 + /* Not whole TCP header? */
2171 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
2172 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
2176 + /* Checksum invalid? Ignore. */
2177 + /* FIXME: Source route IP option packets --RR */
2178 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2179 + csum_partial((char *) tcph, tcplen, 0))) {
2180 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
2181 + tcph, tcplen, NIPQUAD(iph->saddr),
2182 + NIPQUAD(iph->daddr));
2186 + data_limit = (char *) data + datalen;
2187 + while (datalen > 5 && bytes_scanned < 128) {
2188 + if (memcmp(data, "s us ", 5)) {
2197 + DEBUGP("Userfile-share found in connection "
2198 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
2199 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
2201 + if (parse_command((char *) data, data_limit, &egg_ip,
2203 + DEBUGP("no data in userfile-share pkt\n");
2207 + memset(&exp, 0, sizeof(exp));
2209 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
2210 + if (net_ratelimit())
2211 + printk("Forged Eggdrop command from "
2212 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
2213 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
2214 + HIPQUAD(egg_ip), egg_port);
2218 + exp.tuple.src.ip = iph->daddr;
2219 + exp.tuple.src.u.tcp.port = 0;
2220 + exp.tuple.dst.ip = htonl(egg_ip);
2221 + exp.tuple.dst.u.tcp.port = htons(egg_port);
2222 + exp.tuple.dst.protonum = IPPROTO_TCP;
2224 + exp.mask.dst.u.tcp.port = 0xffff;
2225 + exp.mask.dst.protonum = 0xffff;
2227 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
2228 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
2229 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
2231 + ip_conntrack_expect_related(ct, &exp);
2237 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
2238 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
2240 +static void deregister_helpers(void) {
2243 + for (i = 0; i < ports_c; i++) {
2244 + DEBUGP("unregistering helper for port %d\n", ports[i]);
2245 + ip_conntrack_helper_unregister(&egg_helpers[i]);
2249 +static int __init init(void)
2254 + /* If no port given, default to standard eggdrop port */
2255 + if (ports[0] == 0)
2258 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2259 + memset(&egg_helpers[i], 0,
2260 + sizeof(struct ip_conntrack_helper));
2261 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
2262 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
2263 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
2264 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
2265 + egg_helpers[i].max_expected = 1;
2266 + egg_helpers[i].timeout = egg_timeout;
2267 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2268 + egg_helpers[i].me = THIS_MODULE;
2269 + egg_helpers[i].help = help;
2271 + tmpname = &egg_names[i][0];
2272 + if (ports[i] == 3333)
2273 + sprintf(tmpname, "eggdrop");
2275 + sprintf(tmpname, "eggdrop-%d", ports[i]);
2276 + egg_helpers[i].name = tmpname;
2278 + DEBUGP("port #%d: %d\n", i, ports[i]);
2280 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
2283 + printk("ip_conntrack_egg: ERROR registering helper "
2284 + "for port %d\n", ports[i]);
2285 + deregister_helpers();
2293 +static void __exit fini(void)
2295 + deregister_helpers();
2300 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
2301 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
2302 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-04-29 11:18:00.000000000 +0200
2305 + * H.323 'brute force' extension for H.323 connection tracking.
2306 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2308 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
2309 + * (http://www.coritel.it/projects/sofia/nat/)
2310 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
2311 + * the unregistered helpers to the conntrack entries.
2315 +#include <linux/module.h>
2316 +#include <linux/netfilter.h>
2317 +#include <linux/ip.h>
2318 +#include <net/checksum.h>
2319 +#include <net/tcp.h>
2321 +#include <linux/netfilter_ipv4/lockhelp.h>
2322 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2323 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2324 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2325 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
2326 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
2328 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
2329 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
2330 +MODULE_LICENSE("GPL");
2332 +DECLARE_LOCK(ip_h323_lock);
2333 +struct module *ip_conntrack_h323 = THIS_MODULE;
2336 +#define DEBUGP printk
2338 +#define DEBUGP(format, args...)
2341 +/* FIXME: This should be in userspace. Later. */
2342 +static int h245_help(const struct iphdr *iph, size_t len,
2343 + struct ip_conntrack *ct,
2344 + enum ip_conntrack_info ctinfo)
2346 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2347 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2348 + unsigned char *data_limit;
2349 + u_int32_t tcplen = len - iph->ihl * 4;
2350 + u_int32_t datalen = tcplen - tcph->doff * 4;
2351 + int dir = CTINFO2DIR(ctinfo);
2352 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2353 + struct ip_conntrack_expect expect, *exp = &expect;
2354 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2355 + u_int16_t data_port;
2356 + u_int32_t data_ip;
2359 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2360 + NIPQUAD(iph->saddr), ntohs(tcph->source),
2361 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
2363 + /* Can't track connections formed before we registered */
2367 + /* Until there's been traffic both ways, don't look in packets. */
2368 + if (ctinfo != IP_CT_ESTABLISHED
2369 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2370 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
2374 + /* Not whole TCP header or too short packet? */
2375 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2376 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
2380 + /* Checksum invalid? Ignore. */
2381 + /* FIXME: Source route IP option packets --RR */
2382 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2383 + csum_partial((char *)tcph, tcplen, 0))) {
2384 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2385 + tcph, tcplen, NIPQUAD(iph->saddr),
2386 + NIPQUAD(iph->daddr));
2390 + data_limit = (unsigned char *) data + datalen;
2393 + for (i = 0; data < (data_limit - 5); data++, i++) {
2394 + data_ip = *((u_int32_t *)data);
2395 + if (data_ip == iph->saddr) {
2396 + data_port = *((u_int16_t *)(data + 4));
2397 + memset(&expect, 0, sizeof(expect));
2398 + /* update the H.225 info */
2399 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
2400 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2401 + NIPQUAD(iph->saddr), ntohs(data_port));
2402 + LOCK_BH(&ip_h323_lock);
2403 + info->is_h225 = H225_PORT + 1;
2404 + exp_info->port = data_port;
2405 + exp_info->dir = dir;
2406 + exp_info->offset = i;
2408 + exp->seq = ntohl(tcph->seq) + i;
2410 + exp->tuple = ((struct ip_conntrack_tuple)
2411 + { { ct->tuplehash[!dir].tuple.src.ip,
2414 + { .tcp = { data_port } },
2416 + exp->mask = ((struct ip_conntrack_tuple)
2417 + { { 0xFFFFFFFF, { 0 } },
2418 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2420 + exp->expectfn = NULL;
2422 + /* Ignore failure; should only happen with NAT */
2423 + ip_conntrack_expect_related(ct, exp);
2425 + UNLOCK_BH(&ip_h323_lock);
2433 +/* H.245 helper is not registered! */
2434 +static struct ip_conntrack_helper h245 =
2436 + "H.245", /* name */
2437 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2438 + NULL, /* module */
2439 + 8, /* max_ expected */
2440 + 240, /* timeout */
2441 + { { 0, { 0 } }, /* tuple */
2442 + { 0, { 0 }, IPPROTO_TCP } },
2443 + { { 0, { 0xFFFF } }, /* mask */
2444 + { 0, { 0 }, 0xFFFF } },
2445 + h245_help /* helper */
2448 +static int h225_expect(struct ip_conntrack *ct)
2450 + WRITE_LOCK(&ip_conntrack_lock);
2451 + ct->helper = &h245;
2452 + DEBUGP("h225_expect: helper for %p added\n", ct);
2453 + WRITE_UNLOCK(&ip_conntrack_lock);
2455 + return NF_ACCEPT; /* unused */
2458 +/* FIXME: This should be in userspace. Later. */
2459 +static int h225_help(const struct iphdr *iph, size_t len,
2460 + struct ip_conntrack *ct,
2461 + enum ip_conntrack_info ctinfo)
2463 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2464 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2465 + unsigned char *data_limit;
2466 + u_int32_t tcplen = len - iph->ihl * 4;
2467 + u_int32_t datalen = tcplen - tcph->doff * 4;
2468 + int dir = CTINFO2DIR(ctinfo);
2469 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2470 + struct ip_conntrack_expect expect, *exp = &expect;
2471 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2472 + u_int16_t data_port;
2473 + u_int32_t data_ip;
2476 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2477 + NIPQUAD(iph->saddr), ntohs(tcph->source),
2478 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
2480 + /* Can't track connections formed before we registered */
2484 + /* Until there's been traffic both ways, don't look in packets. */
2485 + if (ctinfo != IP_CT_ESTABLISHED
2486 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2487 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
2491 + /* Not whole TCP header or too short packet? */
2492 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2493 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
2497 + /* Checksum invalid? Ignore. */
2498 + /* FIXME: Source route IP option packets --RR */
2499 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2500 + csum_partial((char *)tcph, tcplen, 0))) {
2501 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2502 + tcph, tcplen, NIPQUAD(iph->saddr),
2503 + NIPQUAD(iph->daddr));
2507 + data_limit = (unsigned char *) data + datalen;
2510 + for (i = 0; data < (data_limit - 5); data++, i++) {
2511 + data_ip = *((u_int32_t *)data);
2512 + if (data_ip == iph->saddr) {
2513 + data_port = *((u_int16_t *)(data + 4));
2514 + if (data_port == tcph->source) {
2515 + /* Signal address */
2516 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
2517 + NIPQUAD(iph->saddr));
2518 + /* Update the H.225 info so that NAT can mangle the address/port
2519 + even when we have no expected connection! */
2520 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2521 + LOCK_BH(&ip_h323_lock);
2523 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
2524 + info->offset[IP_CT_DIR_ORIGINAL] = i;
2525 + UNLOCK_BH(&ip_h323_lock);
2528 + memset(&expect, 0, sizeof(expect));
2530 + /* update the H.225 info */
2531 + LOCK_BH(&ip_h323_lock);
2532 + info->is_h225 = H225_PORT;
2533 + exp_info->port = data_port;
2534 + exp_info->dir = dir;
2535 + exp_info->offset = i;
2537 + exp->seq = ntohl(tcph->seq) + i;
2539 + exp->tuple = ((struct ip_conntrack_tuple)
2540 + { { ct->tuplehash[!dir].tuple.src.ip,
2543 + { .tcp = { data_port } },
2545 + exp->mask = ((struct ip_conntrack_tuple)
2546 + { { 0xFFFFFFFF, { 0 } },
2547 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2549 + exp->expectfn = h225_expect;
2551 + /* Ignore failure */
2552 + ip_conntrack_expect_related(ct, exp);
2554 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
2555 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2556 + NIPQUAD(iph->saddr), ntohs(data_port));
2558 + UNLOCK_BH(&ip_h323_lock);
2560 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2561 + } else if (data_ip == iph->daddr) {
2562 + data_port = *((u_int16_t *)(data + 4));
2563 + if (data_port == tcph->dest) {
2564 + /* Signal address */
2565 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
2566 + NIPQUAD(iph->daddr));
2567 + /* Update the H.225 info so that NAT can mangle the address/port
2568 + even when we have no expected connection! */
2569 + LOCK_BH(&ip_h323_lock);
2571 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
2572 + info->offset[IP_CT_DIR_REPLY] = i;
2573 + UNLOCK_BH(&ip_h323_lock);
2583 +static struct ip_conntrack_helper h225 =
2585 + "H.225", /* name */
2586 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2587 + THIS_MODULE, /* module */
2588 + 2, /* max_expected */
2589 + 240, /* timeout */
2590 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
2591 + { 0, { 0 }, IPPROTO_TCP } },
2592 + { { 0, { 0xFFFF } }, /* mask */
2593 + { 0, { 0 }, 0xFFFF } },
2594 + h225_help /* helper */
2597 +static int __init init(void)
2599 + return ip_conntrack_helper_register(&h225);
2602 +static void __exit fini(void)
2604 + /* Unregister H.225 helper */
2605 + ip_conntrack_helper_unregister(&h225);
2608 +EXPORT_SYMBOL(ip_h323_lock);
2612 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
2613 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
2614 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-04-29 11:19:01.000000000 +0200
2616 +/* MMS extension for IP connection tracking
2617 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2618 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
2620 + * ip_conntrack_mms.c v0.3 2002-09-22
2622 + * This program is free software; you can redistribute it and/or
2623 + * modify it under the terms of the GNU General Public License
2624 + * as published by the Free Software Foundation; either version
2625 + * 2 of the License, or (at your option) any later version.
2627 + * Module load syntax:
2628 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
2630 + * Please give the ports of all MMS servers You wish to connect to.
2631 + * If you don't specify ports, the default will be TCP port 1755.
2633 + * More info on MMS protocol, firewalls and NAT:
2634 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
2635 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
2637 + * The SDP project people are reverse-engineering MMS:
2638 + * http://get.to/sdp
2641 +#include <linux/config.h>
2642 +#include <linux/module.h>
2643 +#include <linux/netfilter.h>
2644 +#include <linux/ip.h>
2645 +#include <linux/ctype.h>
2646 +#include <net/checksum.h>
2647 +#include <net/tcp.h>
2649 +#include <linux/netfilter_ipv4/lockhelp.h>
2650 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2651 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
2653 +DECLARE_LOCK(ip_mms_lock);
2654 +struct module *ip_conntrack_mms = THIS_MODULE;
2656 +#define MAX_PORTS 8
2657 +static int ports[MAX_PORTS];
2658 +static int ports_c;
2660 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2664 +#define DEBUGP printk
2666 +#define DEBUGP(format, args...)
2669 +EXPORT_SYMBOL(ip_mms_lock);
2671 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2672 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
2673 +MODULE_LICENSE("GPL");
2675 +/* #define isdigit(c) (c >= '0' && c <= '9') */
2677 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
2678 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
2681 + for (i = 0; i < unicode_size; ++i) {
2682 + string[i] = (char)(unicode[i]);
2684 + string[unicode_size] = 0x00;
2687 +__inline static int atoi(char *s)
2690 + while (isdigit(*s)) {
2691 + i = i*10 + *(s++) - '0';
2696 +/* convert ip address string like "192.168.0.10" to unsigned int */
2697 +__inline static u_int32_t asciiiptoi(char *s)
2699 + unsigned int i, j, k;
2701 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
2703 + for(j=0; (*(++s) != '.') && (j<3); ++j)
2710 +int parse_mms(const char *data,
2711 + const unsigned int datalen,
2712 + u_int32_t *mms_ip,
2713 + u_int16_t *mms_proto,
2714 + u_int16_t *mms_port,
2715 + char **mms_string_b,
2716 + char **mms_string_e,
2717 + char **mms_padding_e)
2719 + int unicode_size, i;
2720 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
2721 + char getlengthstring[28];
2723 + for(unicode_size=0;
2724 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2726 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
2727 + return -1; /* out of bounds - incomplete packet */
2729 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2730 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2732 + /* IP address ? */
2733 + *mms_ip = asciiiptoi(tempstring+2);
2735 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2738 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
2739 + *mms_proto = IPPROTO_TCP;
2740 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2741 + *mms_proto = IPPROTO_UDP;
2744 + *mms_port = atoi(tempstring+7+i);
2746 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
2747 + unicode string, one to the end of the string, and one to the end
2748 + of the packet, since we must keep track of the number of bytes
2749 + between end of the unicode string and the end of packet (padding) */
2750 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2751 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2752 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2757 +/* FIXME: This should be in userspace. Later. */
2758 +static int help(const struct iphdr *iph, size_t len,
2759 + struct ip_conntrack *ct,
2760 + enum ip_conntrack_info ctinfo)
2762 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2763 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2764 + const char *data = (const char *)tcph + tcph->doff * 4;
2765 + unsigned int tcplen = len - iph->ihl * 4;
2766 + unsigned int datalen = tcplen - tcph->doff * 4;
2767 + int dir = CTINFO2DIR(ctinfo);
2768 + struct ip_conntrack_expect expect, *exp = &expect;
2769 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2772 + u_int16_t mms_proto;
2773 + char mms_proto_string[8];
2774 + u_int16_t mms_port;
2775 + char *mms_string_b, *mms_string_e, *mms_padding_e;
2777 + /* Until there's been traffic both ways, don't look in packets. */
2778 + if (ctinfo != IP_CT_ESTABLISHED
2779 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2780 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2784 + /* Not whole TCP header? */
2785 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2786 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2790 + /* Checksum invalid? Ignore. */
2791 + /* FIXME: Source route IP option packets --RR */
2792 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2793 + csum_partial((char *)tcph, tcplen, 0))) {
2794 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2795 + tcph, tcplen, NIPQUAD(iph->saddr),
2796 + NIPQUAD(iph->daddr));
2800 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2801 + /* FIXME: There is an issue with only looking at this packet: before this packet,
2802 + the client has already sent a packet to the server with the server's hostname
2803 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
2804 + server will break the connection if this doesn't correspond to its own host
2805 + header. The client can also connect to an IP address; if it's the server's IP
2806 + address, it will not break the connection. When doing DNAT on a connection
2807 + where the client uses a server's IP address, the nat module should detect
2808 + this and change this string accordingly to the DNATed address. This should
2809 + probably be done by checking for an IP address, then storing it as a member
2810 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2812 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
2813 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2814 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
2815 + (u8)*(data+36), (u8)*(data+37),
2816 + (u8)*(data+38), (u8)*(data+39),
2818 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2819 + &mms_string_b, &mms_string_e, &mms_padding_e))
2820 + if(net_ratelimit())
2821 + /* FIXME: more verbose debugging ? */
2822 + printk(KERN_WARNING
2823 + "ip_conntrack_mms: Unable to parse data payload\n");
2825 + memset(&expect, 0, sizeof(expect));
2827 + sprintf(mms_proto_string, "(%u)", mms_proto);
2828 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2829 + mms_proto == IPPROTO_TCP ? "TCP"
2830 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2831 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2835 + /* it's possible that the client will just ask the server to tunnel
2836 + the stream over the same TCP session (from port 1755): there's
2837 + shouldn't be a need to add an expectation in that case, but it
2838 + makes NAT packet mangling so much easier */
2839 + LOCK_BH(&ip_mms_lock);
2841 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2843 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2844 + exp_mms_info->len = (mms_string_e - mms_string_b);
2845 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
2846 + exp_mms_info->port = mms_port;
2848 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2849 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2851 + exp->tuple = ((struct ip_conntrack_tuple)
2852 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2854 + { .tcp = { (__u16) ntohs(mms_port) } },
2857 + exp->mask = ((struct ip_conntrack_tuple)
2858 + { { 0xFFFFFFFF, { 0 } },
2859 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2860 + exp->expectfn = NULL;
2861 + ip_conntrack_expect_related(ct, &expect);
2862 + UNLOCK_BH(&ip_mms_lock);
2868 +static struct ip_conntrack_helper mms[MAX_PORTS];
2869 +static char mms_names[MAX_PORTS][10];
2871 +/* Not __exit: called from init() */
2872 +static void fini(void)
2875 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2876 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2878 + ip_conntrack_helper_unregister(&mms[i]);
2882 +static int __init init(void)
2887 + if (ports[0] == 0)
2888 + ports[0] = MMS_PORT;
2890 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2891 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2892 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2893 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
2894 + mms[i].mask.src.u.tcp.port = 0xFFFF;
2895 + mms[i].mask.dst.protonum = 0xFFFF;
2896 + mms[i].max_expected = 1;
2897 + mms[i].timeout = 0;
2898 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2899 + mms[i].me = THIS_MODULE;
2900 + mms[i].help = help;
2902 + tmpname = &mms_names[i][0];
2903 + if (ports[i] == MMS_PORT)
2904 + sprintf(tmpname, "mms");
2906 + sprintf(tmpname, "mms-%d", ports[i]);
2907 + mms[i].name = tmpname;
2909 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
2911 + ret = ip_conntrack_helper_register(&mms[i]);
2924 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
2925 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
2926 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-29 11:20:17.000000000 +0200
2929 + * Connection tracking protocol helper module for SCTP.
2931 + * SCTP is defined in RFC 2960. References to various sections in this code
2932 + * are to this RFC.
2934 + * This program is free software; you can redistribute it and/or modify
2935 + * it under the terms of the GNU General Public License version 2 as
2936 + * published by the Free Software Foundation.
2939 +#include <linux/types.h>
2940 +#include <linux/sched.h>
2941 +#include <linux/timer.h>
2942 +#include <linux/netfilter.h>
2943 +#include <linux/module.h>
2944 +#include <linux/in.h>
2945 +#include <linux/ip.h>
2946 +#include <linux/sctp.h>
2947 +#include <linux/string.h>
2949 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2950 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2951 +#include <linux/netfilter_ipv4/lockhelp.h>
2954 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
2956 +#define DEBUGP(format, args...)
2959 +/* Protects conntrack->proto.sctp */
2960 +static DECLARE_RWLOCK(sctp_lock);
2962 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
2963 + closely. They're more complex. --RR
2965 + And so for me for SCTP :D -Kiran */
2967 +static const char *sctp_conntrack_names[] = {
2975 + "SHUTDOWN_ACK_SENT",
2979 +#define MINS * 60 SECS
2980 +#define HOURS * 60 MINS
2981 +#define DAYS * 24 HOURS
2983 +unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
2984 +unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
2985 +unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
2986 +unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
2987 +unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
2988 +unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
2989 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
2991 +static unsigned long * sctp_timeouts[]
2992 += { 0, /* SCTP_CONNTRACK_NONE */
2993 + &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
2994 + &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
2995 + &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
2996 + &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
2997 + &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
2998 + &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
2999 + &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
3002 +#define sNO SCTP_CONNTRACK_NONE
3003 +#define sCL SCTP_CONNTRACK_CLOSED
3004 +#define sCW SCTP_CONNTRACK_COOKIE_WAIT
3005 +#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
3006 +#define sES SCTP_CONNTRACK_ESTABLISHED
3007 +#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
3008 +#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
3009 +#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
3010 +#define sIV SCTP_CONNTRACK_MAX
3013 + These are the descriptions of the states:
3015 +NOTE: These state names are tantalizingly similar to the states of an
3016 +SCTP endpoint. But the interpretation of the states is a little different,
3017 +considering that these are the states of the connection and not of an end
3018 +point. Please note the subtleties. -Kiran
3020 +NONE - Nothing so far.
3021 +COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
3022 + an INIT_ACK chunk in the reply direction.
3023 +COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
3024 +ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
3025 +SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
3026 +SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
3027 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
3028 + to that of the SHUTDOWN chunk.
3029 +CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
3030 + the SHUTDOWN chunk. Connection is closed.
3034 + - I have assumed that the first INIT is in the original direction.
3035 + This messes things when an INIT comes in the reply direction in CLOSED
3037 + - Check the error type in the reply dir before transitioning from
3038 +cookie echoed to closed.
3039 + - Sec 5.2.4 of RFC 2960
3040 + - Multi Homing support.
3043 +/* SCTP conntrack state transitions */
3044 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
3047 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
3048 +/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
3049 +/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
3050 +/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
3051 +/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
3052 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
3053 +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
3054 +/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
3055 +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
3056 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
3060 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
3061 +/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
3062 +/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
3063 +/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
3064 +/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
3065 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
3066 +/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
3067 +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
3068 +/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
3069 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
3073 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
3074 + unsigned int dataoff,
3075 + struct ip_conntrack_tuple *tuple)
3077 + sctp_sctphdr_t hdr;
3079 + DEBUGP(__FUNCTION__);
3082 + /* Actually only need first 8 bytes. */
3083 + if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
3086 + tuple->src.u.sctp.port = hdr.source;
3087 + tuple->dst.u.sctp.port = hdr.dest;
3092 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
3093 + const struct ip_conntrack_tuple *orig)
3095 + DEBUGP(__FUNCTION__);
3098 + tuple->src.u.sctp.port = orig->dst.u.sctp.port;
3099 + tuple->dst.u.sctp.port = orig->src.u.sctp.port;
3103 +/* Print out the per-protocol part of the tuple. */
3104 +static unsigned int sctp_print_tuple(char *buffer,
3105 + const struct ip_conntrack_tuple *tuple)
3107 + DEBUGP(__FUNCTION__);
3110 + return sprintf(buffer, "sport=%hu dport=%hu ",
3111 + ntohs(tuple->src.u.sctp.port),
3112 + ntohs(tuple->dst.u.sctp.port));
3115 +/* Print out the private part of the conntrack. */
3116 +static unsigned int sctp_print_conntrack(char *buffer,
3117 + const struct ip_conntrack *conntrack)
3119 + enum sctp_conntrack state;
3121 + DEBUGP(__FUNCTION__);
3124 + READ_LOCK(&sctp_lock);
3125 + state = conntrack->proto.sctp.state;
3126 + READ_UNLOCK(&sctp_lock);
3128 + return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
3131 +#define for_each_sctp_chunk(skb, sch, offset, count) \
3132 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
3133 + offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
3134 + offset += (htons(sch.length) + 3) & ~3, count++)
3136 +/* Some validity checks to make sure the chunks are fine */
3137 +static int do_basic_checks(struct ip_conntrack *conntrack,
3138 + const struct sk_buff *skb,
3141 + u_int32_t offset, count;
3142 + sctp_chunkhdr_t sch;
3145 + DEBUGP(__FUNCTION__);
3150 + for_each_sctp_chunk (skb, sch, offset, count) {
3151 + DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
3153 + if (sch.type == SCTP_CID_INIT
3154 + || sch.type == SCTP_CID_INIT_ACK
3155 + || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3159 + /* Cookie Ack/Echo chunks not the first OR
3160 + Init / Init Ack / Shutdown compl chunks not the only chunks */
3161 + if ((sch.type == SCTP_CID_COOKIE_ACK
3162 + || sch.type == SCTP_CID_COOKIE_ECHO
3165 + DEBUGP("Basic checks failed\n");
3170 + set_bit (sch.type, (void *)map);
3174 + DEBUGP("Basic checks passed\n");
3178 +static int new_state(enum ip_conntrack_dir dir,
3179 + enum sctp_conntrack cur_state,
3184 + DEBUGP(__FUNCTION__);
3187 + DEBUGP("Chunk type: %d\n", chunk_type);
3189 + switch (chunk_type) {
3190 + case SCTP_CID_INIT:
3191 + DEBUGP("SCTP_CID_INIT\n");
3193 + case SCTP_CID_INIT_ACK:
3194 + DEBUGP("SCTP_CID_INIT_ACK\n");
3196 + case SCTP_CID_ABORT:
3197 + DEBUGP("SCTP_CID_ABORT\n");
3199 + case SCTP_CID_SHUTDOWN:
3200 + DEBUGP("SCTP_CID_SHUTDOWN\n");
3202 + case SCTP_CID_SHUTDOWN_ACK:
3203 + DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
3205 + case SCTP_CID_ERROR:
3206 + DEBUGP("SCTP_CID_ERROR\n");
3208 + case SCTP_CID_COOKIE_ECHO:
3209 + DEBUGP("SCTP_CID_COOKIE_ECHO\n");
3211 + case SCTP_CID_COOKIE_ACK:
3212 + DEBUGP("SCTP_CID_COOKIE_ACK\n");
3214 + case SCTP_CID_SHUTDOWN_COMPLETE:
3215 + DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
3218 + /* Other chunks like DATA, SACK, HEARTBEAT and
3219 + its ACK do not cause a change in state */
3220 + DEBUGP("Unknown chunk type, Will stay in %s\n",
3221 + sctp_conntrack_names[cur_state]);
3225 + DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
3226 + dir, sctp_conntrack_names[cur_state], chunk_type,
3227 + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
3229 + return sctp_conntracks[dir][i][cur_state];
3232 +/* Returns verdict for packet, or -1 for invalid. */
3233 +static int sctp_packet(struct ip_conntrack *conntrack,
3234 + const struct sk_buff *skb,
3235 + enum ip_conntrack_info ctinfo)
3237 + enum sctp_conntrack newconntrack, oldsctpstate;
3238 + sctp_sctphdr_t sctph;
3239 + sctp_chunkhdr_t sch;
3240 + u_int32_t offset, count;
3241 + char map[256 / sizeof (char)] = {0};
3243 + DEBUGP(__FUNCTION__);
3246 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3249 + if (do_basic_checks(conntrack, skb, map) != 0)
3252 + /* Check the verification tag (Sec 8.5) */
3253 + if (!test_bit(SCTP_CID_INIT, (void *)map)
3254 + && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
3255 + && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
3256 + && !test_bit(SCTP_CID_ABORT, (void *)map)
3257 + && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
3258 + && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3259 + DEBUGP("Verification tag check failed\n");
3263 + oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
3264 + for_each_sctp_chunk (skb, sch, offset, count) {
3265 + WRITE_LOCK(&sctp_lock);
3267 + /* Special cases of Verification tag check (Sec 8.5.1) */
3268 + if (sch.type == SCTP_CID_INIT) {
3269 + /* Sec 8.5.1 (A) */
3270 + if (sctph.vtag != 0) {
3271 + WRITE_UNLOCK(&sctp_lock);
3274 + } else if (sch.type == SCTP_CID_ABORT) {
3275 + /* Sec 8.5.1 (B) */
3276 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3277 + && !(sctph.vtag == conntrack->proto.sctp.vtag
3278 + [1 - CTINFO2DIR(ctinfo)])) {
3279 + WRITE_UNLOCK(&sctp_lock);
3282 + } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3283 + /* Sec 8.5.1 (C) */
3284 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3285 + && !(sctph.vtag == conntrack->proto.sctp.vtag
3286 + [1 - CTINFO2DIR(ctinfo)]
3287 + && (sch.flags & 1))) {
3288 + WRITE_UNLOCK(&sctp_lock);
3291 + } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
3292 + /* Sec 8.5.1 (D) */
3293 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3294 + WRITE_UNLOCK(&sctp_lock);
3299 + oldsctpstate = conntrack->proto.sctp.state;
3300 + newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
3303 + if (newconntrack == SCTP_CONNTRACK_MAX) {
3304 + DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
3305 + CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
3306 + WRITE_UNLOCK(&sctp_lock);
3310 + /* If it is an INIT or an INIT ACK note down the vtag */
3311 + if (sch.type == SCTP_CID_INIT
3312 + || sch.type == SCTP_CID_INIT_ACK) {
3313 + sctp_inithdr_t inithdr;
3315 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3316 + &inithdr, sizeof(inithdr)) != 0) {
3317 + WRITE_UNLOCK(&sctp_lock);
3320 + DEBUGP("Setting vtag %x for dir %d\n",
3321 + inithdr.init_tag, CTINFO2DIR(ctinfo));
3322 + conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
3325 + conntrack->proto.sctp.state = newconntrack;
3326 + WRITE_UNLOCK(&sctp_lock);
3329 + ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
3331 + if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
3332 + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
3333 + && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
3334 + DEBUGP("Setting assured bit\n");
3335 + set_bit(IPS_ASSURED_BIT, &conntrack->status);
3341 +/* Called when a new connection for this protocol found. */
3342 +static int sctp_new(struct ip_conntrack *conntrack,
3343 + const struct sk_buff *skb)
3345 + enum sctp_conntrack newconntrack;
3346 + sctp_sctphdr_t sctph;
3347 + sctp_chunkhdr_t sch;
3348 + u_int32_t offset, count;
3349 + char map[256 / sizeof (char)] = {0};
3351 + DEBUGP(__FUNCTION__);
3354 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3357 + if (do_basic_checks(conntrack, skb, map) != 0)
3360 + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
3361 + if ((test_bit (SCTP_CID_ABORT, (void *)map))
3362 + || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
3363 + || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
3367 + newconntrack = SCTP_CONNTRACK_MAX;
3368 + for_each_sctp_chunk (skb, sch, offset, count) {
3369 + /* Don't need lock here: this conntrack not in circulation yet */
3370 + newconntrack = new_state (IP_CT_DIR_ORIGINAL,
3371 + SCTP_CONNTRACK_NONE, sch.type);
3373 + /* Invalid: delete conntrack */
3374 + if (newconntrack == SCTP_CONNTRACK_MAX) {
3375 + DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
3379 + /* Copy the vtag into the state info */
3380 + if (sch.type == SCTP_CID_INIT) {
3381 + if (sctph.vtag == 0) {
3382 + sctp_inithdr_t inithdr;
3384 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3385 + &inithdr, sizeof(inithdr)) != 0) {
3389 + DEBUGP("Setting vtag %x for new conn\n",
3390 + inithdr.init_tag);
3392 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
3395 + /* Sec 8.5.1 (A) */
3399 + /* If it is a shutdown ack OOTB packet, we expect a return
3400 + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
3402 + DEBUGP("Setting vtag %x for new conn OOTB\n",
3404 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
3407 + conntrack->proto.sctp.state = newconntrack;
3413 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
3414 + const struct sk_buff *skb)
3416 + /* To be implemented */
3420 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
3421 + .list = { NULL, NULL },
3422 + .proto = IPPROTO_SCTP,
3424 + .pkt_to_tuple = sctp_pkt_to_tuple,
3425 + .invert_tuple = sctp_invert_tuple,
3426 + .print_tuple = sctp_print_tuple,
3427 + .print_conntrack = sctp_print_conntrack,
3428 + .packet = sctp_packet,
3431 + .exp_matches_pkt = sctp_exp_matches_pkt,
3435 +int __init init(void)
3439 + ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
3440 + DEBUGP("SCTP conntrack module loading %s\n",
3441 + ret ? "failed": "succeeded");
3445 +void __exit fini(void)
3447 + ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
3448 + DEBUGP("SCTP conntrack module unloaded\n");
3454 +MODULE_LICENSE("GPL");
3455 +MODULE_AUTHOR("Kiran Kumar Immidi");
3456 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
3457 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
3458 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
3459 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-04-29 11:19:53.000000000 +0200
3461 +/* Quake3 extension for IP connection tracking
3462 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3463 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
3465 + * ip_conntrack_quake3.c v0.04 2002-08-31
3467 + * This program is free software; you can redistribute it and/or
3468 + * modify it under the terms of the GNU General Public License
3469 + * as published by the Free Software Foundation; either version
3470 + * 2 of the License, or (at your option) any later version.
3472 + * Module load syntax:
3473 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
3475 + * please give the ports of all Quake3 master servers You wish to
3476 + * connect to. If you don't specify ports, the default will be UDP
3479 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
3482 +#include <linux/module.h>
3483 +#include <linux/ip.h>
3484 +#include <linux/udp.h>
3486 +#include <linux/netfilter.h>
3487 +#include <linux/netfilter_ipv4/ip_tables.h>
3488 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3489 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
3491 +struct module *ip_conntrack_quake3 = THIS_MODULE;
3493 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3494 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
3495 +MODULE_LICENSE("GPL");
3497 +#define MAX_PORTS 8
3498 +static int ports[MAX_PORTS];
3499 +static int ports_c = 0;
3501 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3502 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
3505 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
3506 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
3508 +#define DEBUGP printk
3510 +#define DEBUGP(format, args...)
3513 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
3515 +static int quake3_help(const struct iphdr *iph, size_t len,
3516 + struct ip_conntrack *ct,
3517 + enum ip_conntrack_info ctinfo)
3519 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
3520 + int dir = CTINFO2DIR(ctinfo);
3521 + struct ip_conntrack_expect exp;
3524 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
3525 + if (ctinfo != IP_CT_ESTABLISHED
3526 + && ctinfo != IP_CT_IS_REPLY) {
3527 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
3529 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
3531 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
3532 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
3533 + i+6 < ntohs(udph->len);
3535 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
3536 + i, ntohs(udph->len),
3537 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
3538 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
3540 + memset(&exp, 0, sizeof(exp));
3542 + exp.tuple = ((struct ip_conntrack_tuple)
3543 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3544 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
3545 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
3548 + exp.mask = ((struct ip_conntrack_tuple)
3549 + { { 0xFFFFFFFF, { 0 } },
3550 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
3551 + exp.expectfn = NULL;
3553 + ip_conntrack_expect_related(ct, &exp);
3558 + return(NF_ACCEPT);
3561 +static struct ip_conntrack_helper quake3[MAX_PORTS];
3562 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
3564 +static void fini(void)
3568 + for(i = 0 ; (i < ports_c); i++) {
3569 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
3571 + ip_conntrack_helper_unregister(&quake3[i]);
3575 +static int __init init(void)
3581 + ports[0]=QUAKE3_MASTER_PORT;
3583 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
3584 + /* Create helper structure */
3585 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
3587 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
3588 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
3589 + quake3[i].mask.dst.protonum = 0xFFFF;
3590 + quake3[i].mask.src.u.udp.port = 0xFFFF;
3591 + quake3[i].help = quake3_help;
3592 + quake3[i].me = THIS_MODULE;
3594 + tmpname = &quake3_names[i][0];
3595 + if (ports[i] == QUAKE3_MASTER_PORT)
3596 + sprintf(tmpname, "quake3");
3598 + sprintf(tmpname, "quake3-%d", i);
3599 + quake3[i].name = tmpname;
3601 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
3604 + ret=ip_conntrack_helper_register(&quake3[i]);
3617 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
3618 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
3619 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2004-04-29 11:20:02.000000000 +0200
3621 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
3622 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3623 + * - original rpc tracking module
3624 + * - "recent" connection handling for kernel 2.3+ netfilter
3626 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3627 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3629 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3630 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
3631 + * - extended matching to support filtering on procedures
3633 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
3635 + * This program is free software; you can redistribute it and/or
3636 + * modify it under the terms of the GNU General Public License
3637 + * as published by the Free Software Foundation; either version
3638 + * 2 of the License, or (at your option) any later version.
3640 + * Module load syntax:
3641 + * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
3643 + * Please give the ports of all RPC servers you wish to connect to.
3644 + * If you don't specify ports, the default will be port 111.
3648 + * RPCs should not be exposed to the internet - ask the Pentagon;
3650 + * "The unidentified crackers pleaded guilty in July to charges
3651 + * of juvenile delinquency stemming from a string of Pentagon
3652 + * network intrusions in February.
3654 + * The youths, going by the names TooShort and Makaveli, used
3655 + * a common server security hole to break in, according to
3656 + * Dane Jasper, owner of the California Internet service
3657 + * provider, Sonic. They used the hole, known as the 'statd'
3658 + * exploit, to attempt more than 800 break-ins, Jasper said."
3660 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3661 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
3665 +#include <linux/module.h>
3666 +#include <linux/netfilter.h>
3667 +#include <linux/ip.h>
3668 +#include <net/checksum.h>
3669 +#include <net/tcp.h>
3671 +#include <asm/param.h>
3672 +#include <linux/sched.h>
3673 +#include <linux/timer.h>
3674 +#include <linux/stddef.h>
3675 +#include <linux/list.h>
3677 +#include <linux/netfilter_ipv4/lockhelp.h>
3678 +#include <linux/netfilter_ipv4/ip_tables.h>
3679 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3680 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3682 +#define MAX_PORTS 8
3683 +static int ports[MAX_PORTS];
3684 +static int ports_n_c = 0;
3687 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3688 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3691 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3692 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
3693 +MODULE_LICENSE("GPL");
3696 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
3699 +#define DEBUGP(format, args...)
3702 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
3703 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
3704 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
3705 +#include <linux/netfilter_ipv4/listhelp.h>
3707 +/* For future conections RPC, using client's cache bindings
3708 + * I'll use ip_conntrack_lock to lock these lists */
3710 +LIST_HEAD(request_p_list_tcp);
3713 +static void delete_request_p(unsigned long request_p_ul)
3715 + struct request_p *p = (void *)request_p_ul;
3717 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3718 + LIST_DELETE(&request_p_list_tcp, p);
3719 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3725 +static void req_cl(struct request_p * r)
3727 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3728 + del_timer(&r->timeout);
3729 + LIST_DELETE(&request_p_list_tcp, r);
3730 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3736 +static void clean_request(struct list_head *list)
3738 + struct list_head *first = list->prev;
3739 + struct list_head *temp = list->next;
3740 + struct list_head *aux;
3742 + if (list_empty(list))
3745 + while (first != temp) {
3747 + req_cl((struct request_p *)temp);
3750 + req_cl((struct request_p *)temp);
3755 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3758 + struct request_p *req_p;
3760 + /* Verifies if entry already exists */
3761 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3762 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3763 + struct request_p *, xid, ip, port);
3766 + /* Refresh timeout */
3767 + if (del_timer(&req_p->timeout)) {
3768 + req_p->timeout.expires = jiffies + EXP;
3769 + add_timer(&req_p->timeout);
3771 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3775 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3777 + /* Allocate new request_p */
3778 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3780 + DEBUGP("can't allocate request_p\n");
3783 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3784 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3787 + /* Initialize timer */
3788 + init_timer(&req_p->timeout);
3789 + req_p->timeout.function = delete_request_p;
3790 + add_timer(&req_p->timeout);
3793 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3794 + list_prepend(&request_p_list_tcp, req_p);
3795 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3801 +static int check_rpc_packet(const u_int32_t *data,
3802 + int dir, struct ip_conntrack *ct,
3803 + struct list_head request_p_list)
3805 + struct request_p *req_p;
3807 + struct ip_conntrack_expect expect, *exp = &expect;
3809 + /* Translstion's buffer for XDR */
3810 + u_int16_t port_buf;
3816 + /* This does sanity checking on RPC payloads,
3817 + * and permits only the RPC "get port" (3)
3818 + * in authorised procedures in client
3819 + * communications with the portmapper.
3822 + /* perform direction dependant RPC work */
3823 + if (dir == IP_CT_DIR_ORIGINAL) {
3827 + /* Get RPC requestor */
3828 + if (IXDR_GET_INT32(data) != 3) {
3829 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3832 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3836 + /* Jump Credentials and Verfifier */
3837 + data += IXDR_GET_INT32(data) + 2;
3838 + data += IXDR_GET_INT32(data) + 2;
3840 + /* Get RPC procedure */
3841 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3842 + (unsigned int)IXDR_GET_INT32(data));
3844 + /* Get RPC protocol and store against client parameters */
3846 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3847 + ct->tuplehash[dir].tuple.src.u.all);
3849 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3850 + xid, IXDR_GET_INT32(data),
3851 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3852 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
3854 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
3855 + (unsigned int)IXDR_GET_INT32(data));
3859 + /* Check for returning packet's stored counterpart */
3860 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3861 + struct request_p *, xid,
3862 + ct->tuplehash[!dir].tuple.src.ip,
3863 + ct->tuplehash[!dir].tuple.src.u.all);
3865 + /* Drop unexpected packets */
3867 + DEBUGP("packet is not expected. [skip]\n");
3871 + /* Verifies if packet is really an RPC reply packet */
3873 + if (IXDR_GET_INT32(data) != 1) {
3874 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
3878 + /* Is status accept? */
3880 + if (IXDR_GET_INT32(data)) {
3881 + DEBUGP("packet is not an RPC accept. [skip]\n");
3885 + /* Get Verifier length. Jump verifier */
3887 + data = data + IXDR_GET_INT32(data) + 2;
3889 + /* Is accpet status "success"? */
3890 + if (IXDR_GET_INT32(data)) {
3891 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3895 + /* Get server port number */
3897 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
3899 + /* If a packet has made it this far then it deserves an
3900 + * expectation ... if port == 0, then this service is
3901 + * not going to be registered.
3904 + DEBUGP("port found: %u\n", port_buf);
3906 + memset(&expect, 0, sizeof(expect));
3908 + /* Watch out, Radioactive-Man! */
3909 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3910 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3911 + exp->mask.src.ip = 0xffffffff;
3912 + exp->mask.dst.ip = 0xffffffff;
3914 + switch (req_p->proto) {
3916 + exp->tuple.src.u.udp.port = 0;
3917 + exp->tuple.dst.u.udp.port = htons(port_buf);
3918 + exp->tuple.dst.protonum = IPPROTO_UDP;
3919 + exp->mask.src.u.udp.port = 0;
3920 + exp->mask.dst.u.udp.port = htons(0xffff);
3921 + exp->mask.dst.protonum = 0xffff;
3925 + exp->tuple.src.u.tcp.port = 0;
3926 + exp->tuple.dst.u.tcp.port = htons(port_buf);
3927 + exp->tuple.dst.protonum = IPPROTO_TCP;
3928 + exp->mask.src.u.tcp.port = 0;
3929 + exp->mask.dst.u.tcp.port = htons(0xffff);
3930 + exp->mask.dst.protonum = 0xffff;
3933 + exp->expectfn = NULL;
3935 + ip_conntrack_expect_related(ct, &expect);
3937 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3938 + NIPQUAD(exp->tuple.src.ip),
3939 + NIPQUAD(exp->tuple.dst.ip),
3940 + port_buf, req_p->proto);
3942 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3943 + NIPQUAD(exp->mask.src.ip),
3944 + NIPQUAD(exp->mask.dst.ip),
3945 + exp->mask.dst.protonum);
3951 + DEBUGP("packet evaluated. [expect]\n");
3960 +/* RPC TCP helper */
3961 +static int help(const struct iphdr *iph, size_t len,
3962 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3964 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3965 + const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3966 + size_t tcplen = len - iph->ihl * 4;
3968 + int dir = CTINFO2DIR(ctinfo);
3972 + DEBUGP("new packet to evaluate ..\n");
3974 + /* This works for packets like handshake packets, ignore */
3975 + if (len == ((tcph->doff + iph->ihl) * 4)) {
3976 + DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3980 + /* Until there's been traffic both ways, don't look in packets. */
3981 + if (ctinfo != IP_CT_ESTABLISHED
3982 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3983 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3984 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3985 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3989 + /* Not whole TCP header? */
3990 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3991 + DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3992 + DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3996 + /* FIXME: Source route IP option packets --RR */
3997 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3998 + csum_partial((char *) tcph, tcplen, 0))) {
3999 + DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4000 + tcph, tcplen, NIPQUAD(iph->saddr),
4001 + NIPQUAD(iph->daddr));
4002 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4003 + DEBUGP("packet contains a bad checksum. [skip]\n");
4007 + /* perform direction dependant protocol work */
4008 + if (dir == IP_CT_DIR_ORIGINAL) {
4010 + DEBUGP("packet is from the initiator. [cont]\n");
4012 + /* Tests if packet len is ok */
4013 + if ((tcplen - (tcph->doff * 4)) != 60) {
4014 + DEBUGP("packet length is not correct. [skip]\n");
4020 + DEBUGP("packet is from the receiver. [cont]\n");
4022 + /* Tests if packet len is ok */
4023 + if ((tcplen - (tcph->doff * 4)) != 32) {
4024 + DEBUGP("packet length is not correct. [skip]\n");
4029 + /* Get to the data */
4032 + /* Check the RPC data */
4033 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
4040 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4042 +static void fini(void);
4045 +static int __init init(void)
4048 + static char name[10];
4051 + /* If no port given, default to standard RPC port */
4052 + if (ports[0] == 0)
4053 + ports[0] = RPC_PORT;
4055 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4056 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4058 + if (ports[port] == RPC_PORT)
4059 + sprintf(name, "rpc");
4061 + sprintf(name, "rpc-%d", port);
4063 + rpc_helpers[port].name = name;
4064 + rpc_helpers[port].me = THIS_MODULE;
4065 + rpc_helpers[port].max_expected = 1;
4066 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4067 + rpc_helpers[port].timeout = 0;
4069 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4070 + rpc_helpers[port].mask.dst.protonum = 0xffff;
4072 + /* RPC can come from ports 0:65535 to ports[port] (111) */
4073 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4074 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4075 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4077 + rpc_helpers[port].help = help;
4079 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4080 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4081 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4082 + ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
4083 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
4084 + ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
4085 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4086 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
4087 + ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
4088 + NIPQUAD(rpc_helpers[port].mask.src.ip),
4089 + ntohs(rpc_helpers[port].mask.src.u.tcp.port));
4091 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4094 + printk("ERROR registering port %d\n",
4105 +/* This function is intentionally _NOT_ defined as __exit, because
4106 + * it is needed by the init function */
4107 +static void fini(void)
4111 + DEBUGP("cleaning request list\n");
4112 + clean_request(&request_p_list_tcp);
4114 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4115 + DEBUGP("unregistering port %d\n", ports[port]);
4116 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
4124 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
4125 +EXPORT_SYMBOL(request_p_list_tcp);
4126 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
4127 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
4129 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
4130 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
4131 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2004-04-29 11:20:02.000000000 +0200
4133 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
4134 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
4135 + * - original rpc tracking module
4136 + * - "recent" connection handling for kernel 2.3+ netfilter
4138 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
4139 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
4141 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4142 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
4143 + * - extended matching to support filtering on procedures
4145 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
4147 + * This program is free software; you can redistribute it and/or
4148 + * modify it under the terms of the GNU General Public License
4149 + * as published by the Free Software Foundation; either version
4150 + * 2 of the License, or (at your option) any later version.
4152 + * Module load syntax:
4153 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
4155 + * Please give the ports of all RPC servers you wish to connect to.
4156 + * If you don't specify ports, the default will be port 111.
4160 + * RPCs should not be exposed to the internet - ask the Pentagon;
4162 + * "The unidentified crackers pleaded guilty in July to charges
4163 + * of juvenile delinquency stemming from a string of Pentagon
4164 + * network intrusions in February.
4166 + * The youths, going by the names TooShort and Makaveli, used
4167 + * a common server security hole to break in, according to
4168 + * Dane Jasper, owner of the California Internet service
4169 + * provider, Sonic. They used the hole, known as the 'statd'
4170 + * exploit, to attempt more than 800 break-ins, Jasper said."
4172 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
4173 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
4177 +#include <linux/module.h>
4178 +#include <linux/netfilter.h>
4179 +#include <linux/ip.h>
4180 +#include <net/checksum.h>
4181 +#include <net/udp.h>
4183 +#include <asm/param.h>
4184 +#include <linux/sched.h>
4185 +#include <linux/timer.h>
4186 +#include <linux/stddef.h>
4187 +#include <linux/list.h>
4189 +#include <linux/netfilter_ipv4/lockhelp.h>
4190 +#include <linux/netfilter_ipv4/ip_tables.h>
4191 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4192 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
4194 +#define MAX_PORTS 8
4195 +static int ports[MAX_PORTS];
4196 +static int ports_n_c = 0;
4199 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4200 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
4203 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
4204 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
4205 +MODULE_LICENSE("GPL");
4208 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
4211 +#define DEBUGP(format, args...)
4214 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
4215 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
4216 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
4217 +#include <linux/netfilter_ipv4/listhelp.h>
4219 +/* For future conections RPC, using client's cache bindings
4220 + * I'll use ip_conntrack_lock to lock these lists */
4222 +LIST_HEAD(request_p_list_udp);
4225 +static void delete_request_p(unsigned long request_p_ul)
4227 + struct request_p *p = (void *)request_p_ul;
4229 + WRITE_LOCK(&ipct_rpc_udp_lock);
4230 + LIST_DELETE(&request_p_list_udp, p);
4231 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
4237 +static void req_cl(struct request_p * r)
4239 + WRITE_LOCK(&ipct_rpc_udp_lock);
4240 + del_timer(&r->timeout);
4241 + LIST_DELETE(&request_p_list_udp, r);
4242 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
4248 +static void clean_request(struct list_head *list)
4250 + struct list_head *first = list->prev;
4251 + struct list_head *temp = list->next;
4252 + struct list_head *aux;
4254 + if (list_empty(list))
4257 + while (first != temp) {
4259 + req_cl((struct request_p *)temp);
4262 + req_cl((struct request_p *)temp);
4267 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
4270 + struct request_p *req_p;
4272 + /* Verifies if entry already exists */
4273 + WRITE_LOCK(&ipct_rpc_udp_lock);
4274 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4275 + struct request_p *, xid, ip, port);
4278 + /* Refresh timeout */
4279 + if (del_timer(&req_p->timeout)) {
4280 + req_p->timeout.expires = jiffies + EXP;
4281 + add_timer(&req_p->timeout);
4283 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
4287 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
4289 + /* Allocate new request_p */
4290 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
4292 + DEBUGP("can't allocate request_p\n");
4295 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
4296 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
4299 + /* Initialize timer */
4300 + init_timer(&req_p->timeout);
4301 + req_p->timeout.function = delete_request_p;
4302 + add_timer(&req_p->timeout);
4305 + WRITE_LOCK(&ipct_rpc_udp_lock);
4306 + list_prepend(&request_p_list_udp, req_p);
4307 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
4313 +static int check_rpc_packet(const u_int32_t *data,
4314 + int dir, struct ip_conntrack *ct,
4315 + struct list_head request_p_list)
4317 + struct request_p *req_p;
4319 + struct ip_conntrack_expect expect, *exp = &expect;
4321 + /* Translstion's buffer for XDR */
4322 + u_int16_t port_buf;
4328 + /* This does sanity checking on RPC payloads,
4329 + * and permits only the RPC "get port" (3)
4330 + * in authorised procedures in client
4331 + * communications with the portmapper.
4334 + /* perform direction dependant RPC work */
4335 + if (dir == IP_CT_DIR_ORIGINAL) {
4339 + /* Get RPC requestor */
4340 + if (IXDR_GET_INT32(data) != 3) {
4341 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
4344 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
4348 + /* Jump Credentials and Verfifier */
4349 + data = data + IXDR_GET_INT32(data) + 2;
4350 + data = data + IXDR_GET_INT32(data) + 2;
4352 + /* Get RPC procedure */
4353 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
4354 + (unsigned int)IXDR_GET_INT32(data));
4356 + /* Get RPC protocol and store against client parameters */
4358 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
4359 + ct->tuplehash[dir].tuple.src.u.all);
4361 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
4362 + xid, IXDR_GET_INT32(data),
4363 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
4364 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
4366 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
4367 + (unsigned int)IXDR_GET_INT32(data));
4371 + /* Check for returning packet's stored counterpart */
4372 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4373 + struct request_p *, xid,
4374 + ct->tuplehash[!dir].tuple.src.ip,
4375 + ct->tuplehash[!dir].tuple.src.u.all);
4377 + /* Drop unexpected packets */
4379 + DEBUGP("packet is not expected. [skip]\n");
4383 + /* Verifies if packet is really an RPC reply packet */
4385 + if (IXDR_GET_INT32(data) != 1) {
4386 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
4390 + /* Is status accept? */
4392 + if (IXDR_GET_INT32(data)) {
4393 + DEBUGP("packet is not an RPC accept. [skip]\n");
4397 + /* Get Verifier length. Jump verifier */
4399 + data = data + IXDR_GET_INT32(data) + 2;
4401 + /* Is accpet status "success"? */
4402 + if (IXDR_GET_INT32(data)) {
4403 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
4407 + /* Get server port number */
4409 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
4411 + /* If a packet has made it this far then it deserves an
4412 + * expectation ... if port == 0, then this service is
4413 + * not going to be registered.
4416 + DEBUGP("port found: %u\n", port_buf);
4418 + memset(&expect, 0, sizeof(expect));
4420 + /* Watch out, Radioactive-Man! */
4421 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4422 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4423 + exp->mask.src.ip = 0xffffffff;
4424 + exp->mask.dst.ip = 0xffffffff;
4426 + switch (req_p->proto) {
4428 + exp->tuple.src.u.udp.port = 0;
4429 + exp->tuple.dst.u.udp.port = htons(port_buf);
4430 + exp->tuple.dst.protonum = IPPROTO_UDP;
4431 + exp->mask.src.u.udp.port = 0;
4432 + exp->mask.dst.u.udp.port = htons(0xffff);
4433 + exp->mask.dst.protonum = 0xffff;
4437 + exp->tuple.src.u.tcp.port = 0;
4438 + exp->tuple.dst.u.tcp.port = htons(port_buf);
4439 + exp->tuple.dst.protonum = IPPROTO_TCP;
4440 + exp->mask.src.u.tcp.port = 0;
4441 + exp->mask.dst.u.tcp.port = htons(0xffff);
4442 + exp->mask.dst.protonum = 0xffff;
4445 + exp->expectfn = NULL;
4447 + ip_conntrack_expect_related(ct, &expect);
4449 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
4450 + NIPQUAD(exp->tuple.src.ip),
4451 + NIPQUAD(exp->tuple.dst.ip),
4452 + port_buf, req_p->proto);
4454 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
4455 + NIPQUAD(exp->mask.src.ip),
4456 + NIPQUAD(exp->mask.dst.ip),
4457 + exp->mask.dst.protonum);
4463 + DEBUGP("packet evaluated. [expect]\n");
4472 +/* RPC UDP helper */
4473 +static int help(const struct iphdr *iph, size_t len,
4474 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4476 + struct udphdr *udph = (void *) iph + iph->ihl * 4;
4477 + const u_int32_t *data = (const u_int32_t *)udph + 2;
4478 + size_t udplen = len - iph->ihl * 4;
4479 + int dir = CTINFO2DIR(ctinfo);
4483 + const u_int16_t *chsm = (const u_int16_t *)udph + 3;
4486 + DEBUGP("new packet to evaluate ..\n");
4488 + /* Not whole UDP header? */
4489 + if (udplen < sizeof(struct udphdr)) {
4490 + DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
4491 + DEBUGP("packet does not contain a complete UDP header. [skip]\n");
4495 + /* FIXME: Source route IP option packets --RR */
4497 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4498 + csum_partial((char *)udph, udplen, 0))) {
4499 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4500 + DEBUGP("packet contains a bad checksum. [skip]\n");
4505 + /* perform direction dependant protocol work */
4506 + if (dir == IP_CT_DIR_ORIGINAL) {
4508 + DEBUGP("packet is from the initiator. [cont]\n");
4510 + /* Tests if packet len is ok */
4511 + if ((udplen - sizeof(struct udphdr)) != 56) {
4512 + DEBUGP("packet length is not correct. [skip]\n");
4518 + DEBUGP("packet is from the receiver. [cont]\n");
4520 + /* Until there's been traffic both ways, don't look in packets. */
4521 + if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4522 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
4523 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
4524 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
4528 + /* Tests if packet len is ok */
4529 + if ((udplen - sizeof(struct udphdr)) != 28) {
4530 + DEBUGP("packet length is not correct. [skip]\n");
4536 + /* Get to the data */
4537 + /* udp *data == *correct */
4539 + /* Check the RPC data */
4540 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
4547 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4549 +static void fini(void);
4552 +static int __init init(void)
4555 + static char name[10];
4558 + /* If no port given, default to standard RPC port */
4559 + if (ports[0] == 0)
4560 + ports[0] = RPC_PORT;
4562 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4563 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4565 + if (ports[port] == RPC_PORT)
4566 + sprintf(name, "rpc");
4568 + sprintf(name, "rpc-%d", port);
4570 + rpc_helpers[port].name = name;
4571 + rpc_helpers[port].me = THIS_MODULE;
4572 + rpc_helpers[port].max_expected = 1;
4573 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4574 + rpc_helpers[port].timeout = 0;
4576 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
4577 + rpc_helpers[port].mask.dst.protonum = 0xffff;
4579 + /* RPC can come from ports 0:65535 to ports[port] (111) */
4580 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4581 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4582 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4584 + rpc_helpers[port].help = help;
4586 + DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
4587 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4588 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4589 + ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
4590 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
4591 + ntohs(rpc_helpers[port].tuple.src.u.udp.port));
4592 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4593 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
4594 + ntohs(rpc_helpers[port].mask.dst.u.udp.port),
4595 + NIPQUAD(rpc_helpers[port].mask.src.ip),
4596 + ntohs(rpc_helpers[port].mask.src.u.udp.port));
4598 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4601 + printk("ERROR registering port %d\n",
4612 +/* This function is intentionally _NOT_ defined as __exit, because
4613 + * it is needed by the init function */
4614 +static void fini(void)
4618 + DEBUGP("cleaning request list\n");
4619 + clean_request(&request_p_list_udp);
4621 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4622 + DEBUGP("unregistering port %d\n", ports[port]);
4623 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
4631 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
4632 +EXPORT_SYMBOL(request_p_list_udp);
4633 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
4634 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
4636 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
4637 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
4638 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-04-29 11:20:06.000000000 +0200
4640 +/* RSH extension for IP connection tracking, Version 1.0
4641 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4642 + * based on HW's ip_conntrack_irc.c
4644 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4646 + * This program is free software; you can redistribute it and/or
4647 + * modify it under the terms of the GNU General Public License
4648 + * as published by the Free Software Foundation; either version
4649 + * 2 of the License, or (at your option) any later version.
4651 + * Module load syntax:
4652 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4654 + * please give the ports of all RSH servers You wish to connect to.
4655 + * If You don't specify ports, the default will be port 514
4658 + * RSH blows ... you should use SSH (openssh.org) to replace it,
4659 + * unfortunately I babysit some sysadmins that won't migrate
4660 + * their legacy crap, in our second tier.
4665 + * Some docco ripped from the net to teach me all there is to know about
4666 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4669 + * I have no idea what "unix rshd man pages" these guys have .. but that
4670 + * is some pretty detailed docco!
4673 + * 4. Of the rsh protocol.
4674 + * -----------------------
4676 + * The rshd listens on TCP port #514. The following info is from the unix
4677 + * rshd man pages :
4679 + * "Service Request Protocol
4681 + * When the rshd daemon receives a service request, it initiates the
4682 + * following protocol:
4684 + * 1. The rshd daemon checks the source port number for the request.
4685 + * If the port number is not in the range 0 through 1023, the rshd daemon
4686 + * terminates the connection.
4688 + * 2. The rshd daemon reads characters from the socket up to a null byte.
4689 + * The string read is interpreted as an ASCII number (base 10). If this
4690 + * number is nonzero, the rshd daemon interprets it as the port number
4691 + * of a secondary stream to be used as standard error. A second connection
4692 + * is created to the specified port on the client host. The source port
4693 + * on the local host is in the range 0 through 1023.
4695 + * 3. The rshd daemon uses the source address of the initial connection
4696 + * request to determine the name of the client host. If the name cannot
4697 + * be determined, the rshd daemon uses the dotted decimal representation
4698 + * of the client host's address.
4700 + * 4. The rshd daemon retrieves the following information from the initial
4703 + * * A null-terminated string of at most 16 bytes interpreted as
4704 + * the user name of the user on the client host.
4706 + * * A null-terminated string of at most 16 bytes interpreted as
4707 + * the user name to be used on the local server host.
4709 + * * Another null-terminated string interpreted as a command line
4710 + * to be passed to a shell on the local server host.
4712 + * 5. The rshd daemon attempts to validate the user using the following steps:
4714 + * a. The rshd daemon looks up the local user name in the /etc/passwd
4715 + * file and tries to switch to the home directory (using the chdir
4716 + * subroutine). If either the lookup or the directory change fails,
4717 + * the rshd daemon terminates the connection.
4719 + * b. If the local user ID is a nonzero value, the rshd daemon searches
4720 + * the /etc/hosts.equiv file to see if the name of the client
4721 + * workstation is listed. If the client workstation is listed as an
4722 + * equivalent host, the rshd daemon validates the user.
4724 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4725 + * authenticate the user by checking the .rhosts file.
4727 + * d. If either the $HOME/.rhosts authentication fails or the
4728 + * client host is not an equivalent host, the rshd daemon
4729 + * terminates the connection.
4731 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
4732 + * on the initial connection and passes the command line to the user's
4733 + * local login shell. The shell then inherits the network connections
4734 + * established by the rshd daemon."
4739 +#include <linux/module.h>
4740 +#include <linux/netfilter.h>
4741 +#include <linux/ip.h>
4742 +#include <net/checksum.h>
4743 +#include <net/tcp.h>
4745 +#include <linux/netfilter_ipv4/lockhelp.h>
4746 +#include <linux/netfilter_ipv4/ip_tables.h>
4747 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4748 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4750 +#define MAX_PORTS 8
4751 +static int ports[MAX_PORTS];
4752 +static int ports_n_c = 0;
4754 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4755 +MODULE_DESCRIPTION("RSH connection tracking module");
4756 +MODULE_LICENSE("GPL");
4758 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4759 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4762 +DECLARE_LOCK(ip_rsh_lock);
4763 +struct module *ip_conntrack_rsh = THIS_MODULE;
4766 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4769 +#define DEBUGP(format, args...)
4774 +/* FIXME: This should be in userspace. Later. */
4775 +static int help(const struct iphdr *iph, size_t len,
4776 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4778 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4779 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4780 + const char *data = (const char *) tcph + tcph->doff * 4;
4781 + u_int32_t tcplen = len - iph->ihl * 4;
4782 + int dir = CTINFO2DIR(ctinfo);
4783 + struct ip_conntrack_expect expect, *exp = &expect;
4784 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4788 + /* note that "maxoctet" is used to maintain sanity (8 was the
4789 + * original array size used in rshd/glibc) -- is there a
4790 + * vulnerability in rshd.c in the looped port *= 10?
4794 + DEBUGP("entered\n");
4796 + /* bail if packet is not from RSH client */
4797 + if (dir == IP_CT_DIR_REPLY)
4800 + /* Until there's been traffic both ways, don't look in packets. */
4801 + if (ctinfo != IP_CT_ESTABLISHED
4802 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4803 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
4807 + /* Not whole TCP header? */
4808 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4809 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4813 + /* Checksum invalid? Ignore. */
4814 + /* FIXME: Source route IP option packets --RR */
4815 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4816 + csum_partial((char *) tcph, tcplen, 0))) {
4817 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4818 + tcph, tcplen, NIPQUAD(iph->saddr),
4819 + NIPQUAD(iph->daddr));
4823 + /* find the rsh stderr port */
4826 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4831 + if (*data < 48 || *data > 57) {
4832 + DEBUGP("these aren't the packets you're looking for ..\n");
4835 + port = port * 10 + ( *data - 48 );
4838 + /* dont relate sessions that try to expose the client */
4839 + DEBUGP("found port %u\n", port);
4840 + if (port > 1023) {
4841 + DEBUGP("skipping, expected port size is greater than 1023!\n");
4846 + LOCK_BH(&ip_rsh_lock);
4848 + /* new(,related) connection is;
4849 + * reply + dst (uint)port + src port (0:1023)
4851 + memset(&expect, 0, sizeof(expect));
4853 + /* save some discovered data, in case someone ever wants to write
4854 + * a NAT module for this bastard ..
4856 + exp_rsh_info->port = port;
4858 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4861 + /* Watch out, Radioactive-Man! */
4862 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4863 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4864 + exp->tuple.src.u.tcp.port = 0;
4865 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4866 + exp->tuple.dst.protonum = IPPROTO_TCP;
4868 + exp->mask.src.ip = 0xffffffff;
4869 + exp->mask.dst.ip = 0xffffffff;
4871 + exp->mask.src.u.tcp.port = htons(0xfc00);
4872 + exp->mask.dst.u.tcp.port = htons(0xfc00);
4873 + exp->mask.dst.protonum = 0xffff;
4875 + exp->expectfn = NULL;
4877 + ip_conntrack_expect_related(ct, &expect);
4879 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4880 + NIPQUAD(exp->tuple.src.ip),
4881 + ntohs(exp->tuple.src.u.tcp.port),
4882 + NIPQUAD(exp->tuple.dst.ip),
4883 + ntohs(exp->tuple.dst.u.tcp.port));
4885 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4886 + NIPQUAD(exp->mask.src.ip),
4887 + ntohs(exp->mask.src.u.tcp.port),
4888 + NIPQUAD(exp->mask.dst.ip),
4889 + ntohs(exp->mask.dst.u.tcp.port));
4890 + UNLOCK_BH(&ip_rsh_lock);
4895 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4897 +static void fini(void);
4899 +static int __init init(void)
4902 + static char name[10];
4905 + /* If no port given, default to standard RSH port */
4906 + if (ports[0] == 0)
4907 + ports[0] = RSH_PORT;
4909 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4910 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4912 + if (ports[port] == RSH_PORT)
4913 + sprintf(name, "rsh");
4915 + sprintf(name, "rsh-%d", port);
4917 + rsh_helpers[port].name = name;
4918 + rsh_helpers[port].me = THIS_MODULE;
4919 + rsh_helpers[port].max_expected = 1;
4920 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4921 + rsh_helpers[port].timeout = 0;
4923 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4924 + rsh_helpers[port].mask.dst.protonum = 0xffff;
4926 + /* RSH must come from ports 0:1023 to ports[port] (514) */
4927 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4928 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4929 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4931 + rsh_helpers[port].help = help;
4933 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4934 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4935 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
4936 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4937 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4938 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4939 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4940 + NIPQUAD(rsh_helpers[port].mask.src.ip),
4941 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4942 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
4943 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4945 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4948 + printk("ERROR registering port %d\n",
4958 +/* This function is intentionally _NOT_ defined as __exit, because
4959 + * it is needed by the init function */
4960 +static void fini(void)
4963 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4964 + DEBUGP("unregistering port %d\n", ports[port]);
4965 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
4971 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
4972 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
4973 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-04-29 11:20:13.000000000 +0200
4976 + * RTSP extension for IP connection tracking
4977 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
4978 + * based on ip_conntrack_irc.c
4980 + * This program is free software; you can redistribute it and/or
4981 + * modify it under the terms of the GNU General Public License
4982 + * as published by the Free Software Foundation; either version
4983 + * 2 of the License, or (at your option) any later version.
4985 + * Module load syntax:
4986 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
4987 + * max_outstanding=n setup_timeout=secs
4989 + * If no ports are specified, the default will be port 554.
4991 + * With max_outstanding you can define the maximum number of not yet
4992 + * answered SETUP requests per RTSP session (default 8).
4993 + * With setup_timeout you can specify how long the system waits for
4994 + * an expected data channel (default 300 seconds).
4997 +#include <linux/config.h>
4998 +#include <linux/module.h>
4999 +#include <linux/netfilter.h>
5000 +#include <linux/ip.h>
5001 +#include <net/checksum.h>
5002 +#include <net/tcp.h>
5004 +#include <linux/netfilter_ipv4/lockhelp.h>
5005 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5006 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5008 +#include <linux/ctype.h>
5009 +#define NF_NEED_STRNCASECMP
5010 +#define NF_NEED_STRTOU16
5011 +#define NF_NEED_STRTOU32
5012 +#define NF_NEED_NEXTLINE
5013 +#include <linux/netfilter_helpers.h>
5014 +#define NF_NEED_MIME_NEXTLINE
5015 +#include <linux/netfilter_mime.h>
5017 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5019 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5020 +#ifdef IP_NF_RTSP_DEBUG
5021 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5023 +#define DEBUGP(fmt, args...)
5026 +#define MAX_PORTS 8
5027 +static int ports[MAX_PORTS];
5028 +static int num_ports = 0;
5029 +static int max_outstanding = 8;
5030 +static unsigned int setup_timeout = 300;
5032 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5033 +MODULE_DESCRIPTION("RTSP connection tracking module");
5034 +MODULE_LICENSE("GPL");
5036 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5037 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5038 +MODULE_PARM(max_outstanding, "i");
5039 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5040 +MODULE_PARM(setup_timeout, "i");
5041 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5044 +DECLARE_LOCK(ip_rtsp_lock);
5045 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5048 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5049 + * of allocated ports is twice this value). Note that SMIL burns a lot of
5050 + * ports so keep this reasonably high. If this is too low, you will see a
5051 + * lot of "no free client map entries" messages.
5053 +#define MAX_PORT_MAPS 16
5055 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5057 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5060 + * Parse an RTSP packet.
5062 + * Returns zero if parsing failed.
5065 + * IN ptcp tcp data pointer
5066 + * IN tcplen tcp data len
5067 + * IN/OUT ptcpoff points to current tcp offset
5068 + * OUT phdrsoff set to offset of rtsp headers
5069 + * OUT phdrslen set to length of rtsp headers
5070 + * OUT pcseqoff set to offset of CSeq header
5071 + * OUT pcseqlen set to length of CSeq header
5074 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5075 + uint* phdrsoff, uint* phdrslen,
5076 + uint* pcseqoff, uint* pcseqlen)
5078 + uint entitylen = 0;
5082 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5087 + *phdrsoff = *ptcpoff;
5088 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5092 + if (entitylen > 0)
5094 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5098 + if (lineoff+linelen > tcplen)
5100 + INFOP("!! overrun !!\n");
5104 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5106 + *pcseqoff = lineoff;
5107 + *pcseqlen = linelen;
5109 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5111 + uint off = lineoff+15;
5112 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
5113 + nf_strtou32(ptcp+off, &entitylen);
5116 + *phdrslen = (*ptcpoff) - (*phdrsoff);
5122 + * Find lo/hi client ports (if any) in transport header
5124 + * ptcp, tcplen = packet
5125 + * tranoff, tranlen = buffer to search
5128 + * pport_lo, pport_hi = lo/hi ports (host endian)
5130 + * Returns nonzero if any client ports found
5132 + * Note: it is valid (and expected) for the client to request multiple
5133 + * transports, so we need to parse the entire line.
5136 +rtsp_parse_transport(char* ptran, uint tranlen,
5137 + struct ip_ct_rtsp_expect* prtspexp)
5142 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5143 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
5145 + INFOP("sanity check failed\n");
5148 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5150 + SKIP_WSPACE(ptran, tranlen, off);
5152 + /* Transport: tran;field;field=val,tran;field;field=val,... */
5153 + while (off < tranlen)
5155 + const char* pparamend;
5156 + uint nextparamoff;
5158 + pparamend = memchr(ptran+off, ',', tranlen-off);
5159 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5160 + nextparamoff = pparamend-ptran;
5162 + while (off < nextparamoff)
5164 + const char* pfieldend;
5165 + uint nextfieldoff;
5167 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5168 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5170 + if (strncmp(ptran+off, "client_port=", 12) == 0)
5176 + numlen = nf_strtou16(ptran+off, &port);
5178 + if (prtspexp->loport != 0 && prtspexp->loport != port)
5180 + DEBUGP("multiple ports found, port %hu ignored\n", port);
5184 + prtspexp->loport = prtspexp->hiport = port;
5185 + if (ptran[off] == '-')
5188 + numlen = nf_strtou16(ptran+off, &port);
5190 + prtspexp->pbtype = pb_range;
5191 + prtspexp->hiport = port;
5193 + // If we have a range, assume rtp:
5194 + // loport must be even, hiport must be loport+1
5195 + if ((prtspexp->loport & 0x0001) != 0 ||
5196 + prtspexp->hiport != prtspexp->loport+1)
5198 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
5199 + prtspexp->loport, prtspexp->hiport);
5200 + prtspexp->loport &= 0xfffe;
5201 + prtspexp->hiport = prtspexp->loport+1;
5204 + else if (ptran[off] == '/')
5207 + numlen = nf_strtou16(ptran+off, &port);
5209 + prtspexp->pbtype = pb_discon;
5210 + prtspexp->hiport = port;
5217 + * Note we don't look for the destination parameter here.
5218 + * If we are using NAT, the NAT module will handle it. If not,
5219 + * and the client is sending packets elsewhere, the expectation
5220 + * will quietly time out.
5223 + off = nextfieldoff;
5226 + off = nextparamoff;
5232 +/*** conntrack functions ***/
5234 +/* outbound packet: client->server */
5236 +help_out(const struct iphdr* iph, size_t pktlen,
5237 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5239 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5240 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5241 + uint tcplen = pktlen - iph->ihl * 4;
5242 + char* pdata = (char*)tcph + tcph->doff * 4;
5243 + uint datalen = tcplen - tcph->doff * 4;
5246 + struct ip_conntrack_expect exp;
5248 + while (dataoff < datalen)
5250 + uint cmdoff = dataoff;
5260 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
5261 + &hdrsoff, &hdrslen,
5262 + &cseqoff, &cseqlen))
5264 + break; /* not a valid message */
5267 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5269 + continue; /* not a SETUP message */
5271 + DEBUGP("found a setup message\n");
5273 + memset(&exp, 0, sizeof(exp));
5276 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5277 + &lineoff, &linelen))
5283 + if (off > hdrsoff+hdrslen)
5285 + INFOP("!! overrun !!");
5289 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5291 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5292 + &exp.help.exp_rtsp_info);
5296 + if (exp.help.exp_rtsp_info.loport == 0)
5298 + DEBUGP("no udp transports found\n");
5299 + continue; /* no udp transports found */
5302 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5303 + (int)exp.help.exp_rtsp_info.pbtype,
5304 + exp.help.exp_rtsp_info.loport,
5305 + exp.help.exp_rtsp_info.hiport);
5307 + LOCK_BH(&ip_rtsp_lock);
5308 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5309 + exp.help.exp_rtsp_info.len = hdrslen;
5311 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5312 + exp.mask.src.ip = 0xffffffff;
5313 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5314 + exp.mask.dst.ip = 0xffffffff;
5315 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5316 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5317 + exp.tuple.dst.protonum = IPPROTO_UDP;
5318 + exp.mask.dst.protonum = 0xffff;
5320 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5321 + NIPQUAD(exp.tuple.src.ip),
5322 + ntohs(exp.tuple.src.u.tcp.port),
5323 + NIPQUAD(exp.tuple.dst.ip),
5324 + ntohs(exp.tuple.dst.u.tcp.port));
5326 + /* pass the request off to the nat helper */
5327 + rc = ip_conntrack_expect_related(ct, &exp);
5328 + UNLOCK_BH(&ip_rtsp_lock);
5331 + DEBUGP("ip_conntrack_expect_related succeeded\n");
5335 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5342 +/* inbound packet: server->client */
5344 +help_in(const struct iphdr* iph, size_t pktlen,
5345 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5351 +help(const struct iphdr* iph, size_t pktlen,
5352 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5354 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5355 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5356 + u_int32_t tcplen = pktlen - iph->ihl * 4;
5358 + /* Until there's been traffic both ways, don't look in packets. */
5359 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5361 + DEBUGP("conntrackinfo = %u\n", ctinfo);
5365 + /* Not whole TCP header? */
5366 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5368 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5372 + /* Checksum invalid? Ignore. */
5373 + /* FIXME: Source route IP option packets --RR */
5374 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5375 + csum_partial((char*)tcph, tcplen, 0)))
5377 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5378 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5382 + switch (CTINFO2DIR(ctinfo))
5384 + case IP_CT_DIR_ORIGINAL:
5385 + help_out(iph, pktlen, ct, ctinfo);
5387 + case IP_CT_DIR_REPLY:
5388 + help_in(iph, pktlen, ct, ctinfo);
5395 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5396 +static char rtsp_names[MAX_PORTS][10];
5398 +/* This function is intentionally _NOT_ defined as __exit */
5403 + for (i = 0; i < num_ports; i++)
5405 + DEBUGP("unregistering port %d\n", ports[i]);
5406 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5414 + struct ip_conntrack_helper *hlpr;
5417 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5419 + if (max_outstanding < 1)
5421 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5424 + if (setup_timeout < 0)
5426 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5430 + /* If no port given, default to standard rtsp port */
5431 + if (ports[0] == 0)
5433 + ports[0] = RTSP_PORT;
5436 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5438 + hlpr = &rtsp_helpers[i];
5439 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5440 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5441 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
5442 + hlpr->mask.src.u.tcp.port = 0xFFFF;
5443 + hlpr->mask.dst.protonum = 0xFFFF;
5444 + hlpr->max_expected = max_outstanding;
5445 + hlpr->timeout = setup_timeout;
5446 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5447 + hlpr->me = ip_conntrack_rtsp;
5448 + hlpr->help = help;
5450 + tmpname = &rtsp_names[i][0];
5451 + if (ports[i] == RTSP_PORT)
5453 + sprintf(tmpname, "rtsp");
5457 + sprintf(tmpname, "rtsp-%d", i);
5459 + hlpr->name = tmpname;
5461 + DEBUGP("port #%d: %d\n", i, ports[i]);
5463 + ret = ip_conntrack_helper_register(hlpr);
5467 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5476 +#ifdef CONFIG_IP_NF_NAT_NEEDED
5477 +EXPORT_SYMBOL(ip_rtsp_lock);
5482 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
5483 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-28 03:35:45.000000000 +0200
5484 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-29 11:18:04.000000000 +0200
5486 len += sprintf(buffer + len, "[ASSURED] ");
5487 len += sprintf(buffer + len, "use=%u ",
5488 atomic_read(&conntrack->ct_general.use));
5489 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5490 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5492 len += sprintf(buffer + len, "\n");
5496 EXPORT_SYMBOL(ip_conntrack_alter_reply);
5497 EXPORT_SYMBOL(ip_conntrack_destroyed);
5498 EXPORT_SYMBOL(ip_conntrack_get);
5499 +EXPORT_SYMBOL(__ip_conntrack_confirm);
5500 EXPORT_SYMBOL(need_ip_conntrack);
5501 EXPORT_SYMBOL(ip_conntrack_helper_register);
5502 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5503 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
5504 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
5505 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-04-29 11:21:43.000000000 +0200
5508 + * talk extension for IP connection tracking.
5509 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5511 + * This program is free software; you can redistribute it and/or
5512 + * modify it under the terms of the GNU General Public License
5513 + * as published by the Free Software Foundation; either version
5514 + * 2 of the License, or (at your option) any later version.
5516 + * Module load syntax:
5517 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5519 + * talk=[0|1] disable|enable old talk support
5520 + * ntalk=[0|1] disable|enable ntalk support
5521 + * ntalk2=[0|1] disable|enable ntalk2 support
5523 + * The default is talk=1 ntalk=1 ntalk2=1
5525 + * The helper does not support simultaneous talk requests.
5528 + * ASCII art on talk protocols
5531 + * caller server callee server
5538 + * caller client ----------- callee client
5541 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
5542 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5543 + * 3. callee client <-> caller server: LOOK_UP invitation
5544 + * 4. callee client <-> caller client: talk data channel
5546 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
5547 + * draft-hunter-talk-00.txt
5548 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
5550 +#include <linux/config.h>
5551 +#include <linux/module.h>
5552 +#include <linux/netfilter.h>
5553 +#include <linux/ip.h>
5554 +#include <net/checksum.h>
5555 +#include <net/udp.h>
5557 +#include <linux/netfilter_ipv4/lockhelp.h>
5558 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5559 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5560 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5561 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5563 +/* Default all talk protocols are supported */
5564 +static int talk = 1;
5565 +static int ntalk = 1;
5566 +static int ntalk2 = 1;
5567 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5568 +MODULE_DESCRIPTION("talk connection tracking module");
5569 +MODULE_LICENSE("GPL");
5571 +MODULE_PARM(talk, "i");
5572 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5573 +MODULE_PARM(ntalk, "i");
5574 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5575 +MODULE_PARM(ntalk2, "i");
5576 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5579 +DECLARE_LOCK(ip_talk_lock);
5580 +struct module *ip_conntrack_talk = THIS_MODULE;
5583 +#define DEBUGP printk
5585 +#define DEBUGP(format, args...)
5588 +static int talk_expect(struct ip_conntrack *ct);
5589 +static int ntalk_expect(struct ip_conntrack *ct);
5591 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5593 +static int talk_help_response(const struct iphdr *iph, size_t len,
5594 + struct ip_conntrack *ct,
5595 + enum ip_conntrack_info ctinfo,
5600 + struct talk_addr *addr)
5602 + int dir = CTINFO2DIR(ctinfo);
5603 + struct ip_conntrack_expect expect, *exp = &expect;
5604 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5606 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5607 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5610 + if (!(answer == SUCCESS && type == mode))
5613 + memset(&expect, 0, sizeof(expect));
5615 + if (type == ANNOUNCE) {
5617 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5619 + /* update the talk info */
5620 + LOCK_BH(&ip_talk_lock);
5621 + exp_talk_info->port = htons(talk_port);
5623 + /* expect callee client -> caller server message */
5624 + exp->tuple = ((struct ip_conntrack_tuple)
5625 + { { ct->tuplehash[dir].tuple.src.ip,
5627 + { ct->tuplehash[dir].tuple.dst.ip,
5628 + { .tcp = { htons(talk_port) } },
5630 + exp->mask = ((struct ip_conntrack_tuple)
5631 + { { 0xFFFFFFFF, { 0 } },
5632 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5634 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5636 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5637 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5638 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5640 + /* Ignore failure; should only happen with NAT */
5641 + ip_conntrack_expect_related(ct, &expect);
5642 + UNLOCK_BH(&ip_talk_lock);
5644 + if (type == LOOK_UP) {
5646 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5648 + /* update the talk info */
5649 + LOCK_BH(&ip_talk_lock);
5650 + exp_talk_info->port = addr->ta_port;
5652 + /* expect callee client -> caller client connection */
5653 + exp->tuple = ((struct ip_conntrack_tuple)
5654 + { { ct->tuplehash[!dir].tuple.src.ip,
5657 + { addr->ta_port },
5659 + exp->mask = ((struct ip_conntrack_tuple)
5660 + { { 0xFFFFFFFF, { 0 } },
5661 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5663 + exp->expectfn = NULL;
5665 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5666 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5667 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5669 + /* Ignore failure; should only happen with NAT */
5670 + ip_conntrack_expect_related(ct, &expect);
5671 + UNLOCK_BH(&ip_talk_lock);
5677 +/* FIXME: This should be in userspace. Later. */
5678 +static int talk_help(const struct iphdr *iph, size_t len,
5679 + struct ip_conntrack *ct,
5680 + enum ip_conntrack_info ctinfo,
5684 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5685 + const char *data = (const char *)udph + sizeof(struct udphdr);
5686 + int dir = CTINFO2DIR(ctinfo);
5689 + DEBUGP("ip_ct_talk_help: help entered\n");
5691 + /* Until there's been traffic both ways, don't look in packets. */
5692 + if (ctinfo != IP_CT_ESTABLISHED
5693 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5694 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5698 + /* Not whole UDP header? */
5699 + udplen = len - iph->ihl * 4;
5700 + if (udplen < sizeof(struct udphdr)) {
5701 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5705 + /* Checksum invalid? Ignore. */
5706 + /* FIXME: Source route IP option packets --RR */
5707 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5708 + csum_partial((char *)udph, udplen, 0))) {
5709 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5710 + udph, udplen, NIPQUAD(iph->saddr),
5711 + NIPQUAD(iph->daddr));
5715 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5716 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5718 + if (dir == IP_CT_DIR_ORIGINAL)
5721 + if (talk_port == TALK_PORT
5722 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5723 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5724 + ((struct talk_response *)data)->type,
5725 + ((struct talk_response *)data)->answer,
5726 + &(((struct talk_response *)data)->addr));
5727 + else if (talk_port == NTALK_PORT
5729 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5730 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5731 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5732 + ((struct ntalk_response *)data)->type,
5733 + ((struct ntalk_response *)data)->answer,
5734 + &(((struct ntalk_response *)data)->addr));
5735 + else if (talk_port == NTALK_PORT
5737 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5738 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5739 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5740 + ((struct ntalk2_response *)data)->type,
5741 + ((struct ntalk2_response *)data)->answer,
5742 + &(((struct ntalk2_response *)data)->addr));
5744 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
5745 + (unsigned)udplen - sizeof(struct udphdr),
5746 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5751 +static int lookup_help(const struct iphdr *iph, size_t len,
5752 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5754 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5757 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
5758 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5760 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5763 +static struct ip_conntrack_helper lookup_helpers[2] =
5764 + { { { NULL, NULL },
5765 + "talk", /* name */
5767 + NULL, /* module */
5768 + 1, /* max_expected */
5769 + 240, /* timeout */
5770 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5771 + { 0, { 0 }, IPPROTO_UDP } },
5772 + { { 0, { 0xFFFF } }, /* mask */
5773 + { 0, { 0 }, 0xFFFF } },
5774 + lookup_help }, /* helper */
5776 + "ntalk", /* name */
5778 + NULL, /* module */
5779 + 1, /* max_expected */
5780 + 240, /* timeout */
5781 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5782 + { 0, { 0 }, IPPROTO_UDP } },
5783 + { { 0, { 0xFFFF } }, /* mask */
5784 + { 0, { 0 }, 0xFFFF } },
5785 + lookup_nhelp } /* helper */
5788 +static int talk_expect(struct ip_conntrack *ct)
5790 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5791 + WRITE_LOCK(&ip_conntrack_lock);
5792 + ct->helper = &lookup_helpers[0];
5793 + WRITE_UNLOCK(&ip_conntrack_lock);
5795 + return NF_ACCEPT; /* unused */
5798 +static int ntalk_expect(struct ip_conntrack *ct)
5800 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5801 + WRITE_LOCK(&ip_conntrack_lock);
5802 + ct->helper = &lookup_helpers[1];
5803 + WRITE_UNLOCK(&ip_conntrack_lock);
5805 + return NF_ACCEPT; /* unused */
5808 +static int help(const struct iphdr *iph, size_t len,
5809 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5811 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5814 +static int nhelp(const struct iphdr *iph, size_t len,
5815 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5817 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5820 +static struct ip_conntrack_helper talk_helpers[2] =
5821 + { { { NULL, NULL },
5822 + "talk", /* name */
5824 + THIS_MODULE, /* module */
5825 + 1, /* max_expected */
5826 + 240, /* timeout */
5827 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5828 + { 0, { 0 }, IPPROTO_UDP } },
5829 + { { 0, { 0xFFFF } }, /* mask */
5830 + { 0, { 0 }, 0xFFFF } },
5831 + help }, /* helper */
5833 + "ntalk", /* name */
5835 + THIS_MODULE, /* module */
5836 + 1, /* max_expected */
5837 + 240, /* timeout */
5838 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5839 + { 0, { 0 }, IPPROTO_UDP } },
5840 + { { 0, { 0xFFFF } }, /* mask */
5841 + { 0, { 0 }, 0xFFFF } },
5842 + nhelp } /* helper */
5845 +static int __init init(void)
5848 + ip_conntrack_helper_register(&talk_helpers[0]);
5849 + if (ntalk > 0 || ntalk2 > 0)
5850 + ip_conntrack_helper_register(&talk_helpers[1]);
5855 +static void __exit fini(void)
5858 + ip_conntrack_helper_unregister(&talk_helpers[0]);
5859 + if (ntalk > 0 || ntalk2 > 0)
5860 + ip_conntrack_helper_unregister(&talk_helpers[1]);
5863 +EXPORT_SYMBOL(ip_talk_lock);
5867 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c
5868 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c 1970-01-01 01:00:00.000000000 +0100
5869 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c 2004-04-29 11:17:55.000000000 +0200
5871 +/* CuSeeMe extension for UDP NAT alteration.
5872 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5873 + * based on ip_masq_cuseeme.c in 2.2 kernels
5875 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
5877 + * This program is free software; you can redistribute it and/or
5878 + * modify it under the terms of the GNU General Public License
5879 + * as published by the Free Software Foundation; either version
5880 + * 2 of the License, or (at your option) any later version.
5882 + * Module load syntax:
5883 + * insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
5885 + * Please give the ports of the CuSeeMe traffic you want to track.
5886 + * If you don't specify ports, the default will be UDP port 7648.
5888 + * CuSeeMe Protocol Documentation:
5889 + * http://cu-seeme.net/squeek/tech/contents.html
5893 +#include <linux/module.h>
5894 +#include <linux/netfilter_ipv4.h>
5895 +#include <linux/ip.h>
5896 +#include <linux/udp.h>
5898 +#include <linux/netfilter.h>
5899 +#include <linux/netfilter_ipv4/ip_tables.h>
5900 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5901 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
5902 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5903 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5905 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5906 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
5907 +MODULE_LICENSE("GPL");
5909 +#define MAX_PORTS 8
5911 +static int ports[MAX_PORTS];
5912 +static int ports_c = 0;
5914 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5915 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
5919 +#define DEBUGP printk
5921 +#define DEBUGP(format, args...)
5924 +/* process packet from client->reflector, possibly manipulate client IP in payload */
5925 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
5926 + struct ip_nat_info *info,
5927 + enum ip_conntrack_info ctinfo,
5928 + struct sk_buff **pskb,
5930 + unsigned int datalen)
5932 + char new_port_ip[6];
5933 + struct cu_header *cu_head=(struct cu_header *)data;
5935 + DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n",
5936 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5938 + /* At least check that the data at offset 10 is the client's port and IP address */
5939 + if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
5940 + (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
5941 + DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
5942 + NIPQUAD(cu_head->addr),
5943 + ntohs(cu_head->port),
5944 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5945 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
5946 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5947 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5948 + /* at offset 10, replace 6 bytes containing port + IP address */
5949 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5950 + 10, 6, (char *)(new_port_ip), 6);
5952 + DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5953 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5954 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
5955 + NIPQUAD(cu_head->addr),
5956 + ntohs(cu_head->port));
5959 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
5960 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
5961 + struct ip_nat_info *info,
5962 + enum ip_conntrack_info ctinfo,
5963 + struct sk_buff **pskb,
5965 + unsigned int datalen)
5967 + char new_port_ip[6];
5968 + struct cu_header *cu_head = (struct cu_header *)data;
5969 + struct oc_header *oc_head = (struct oc_header *)data;
5970 + struct client_info *ci;
5974 + DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n",
5975 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5977 + /* Check if we're really dealing with the client's port + IP address before rewriting */
5978 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
5979 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
5980 + DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
5981 + NIPQUAD(cu_head->dest_addr),
5982 + ntohs(cu_head->dest_port),
5983 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5984 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
5985 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
5986 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5987 + /* at offset 2, replace 6 bytes containing port + IP address */
5988 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5989 + 2, 6, (char *)(new_port_ip), 6);
5991 + DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5992 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5993 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
5994 + NIPQUAD(cu_head->dest_addr),
5995 + ntohs(cu_head->dest_port));
5997 + /* Check if we're really dealing with the server's port + IP address before rewriting.
5998 + In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
5999 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
6000 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
6001 + DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
6002 + NIPQUAD(cu_head->addr),
6003 + ntohs(cu_head->port),
6004 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
6005 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
6006 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
6007 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6008 + /* at offset 10, replace 6 bytes containing port + IP address */
6009 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
6010 + 10, 6, (char *)(new_port_ip), 6);
6012 + /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
6013 + is not that important so we're not logging this unless we're debugging */
6014 + DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
6015 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
6016 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
6017 + NIPQUAD(cu_head->addr),
6018 + ntohs(cu_head->port));
6020 + /* Spin through client_info structs until we find our own */
6021 + if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
6022 + DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
6023 + for(i=0, off=sizeof(struct oc_header);
6024 + (i < oc_head->client_count &&
6025 + off+sizeof(struct client_info) <= datalen);
6027 + ci=(struct client_info *)(data+off);
6028 + DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n",
6029 + NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
6030 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
6031 + if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
6032 + /* mangle this IP address */
6033 + DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
6034 + NIPQUAD(ci->address),
6035 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
6036 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
6037 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
6038 + (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4,
6039 + (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
6042 + off+=sizeof(struct client_info);
6045 + DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n",
6046 + ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
6049 +static unsigned int
6050 +cuseeme_nat_help(struct ip_conntrack *ct,
6051 + struct ip_conntrack_expect *exp,
6052 + struct ip_nat_info *info,
6053 + enum ip_conntrack_info ctinfo,
6054 + unsigned int hooknum,
6055 + struct sk_buff **pskb)
6057 + struct iphdr *iph = (*pskb)->nh.iph;
6058 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6059 + int dir = CTINFO2DIR(ctinfo);
6060 + unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
6061 + char *data = (char *) &udph[1];
6063 + DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
6064 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6065 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6066 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6067 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6070 + /* Only mangle things once: original direction in POST_ROUTING
6071 + and reply direction on PRE_ROUTING. */
6072 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6073 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6074 + DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
6075 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6076 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6077 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6078 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6082 + if(datalen < sizeof(struct cu_header)) {
6083 + /* packet too small */
6084 + if (net_ratelimit())
6085 + printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n",
6086 + datalen, sizeof(struct cu_header));
6091 + /* In the debugging output, "outgoing" is from client to server, and
6092 + "incoming" is from server to client */
6093 + if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6094 + cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
6096 + cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
6101 +static struct ip_nat_helper cuseeme[MAX_PORTS];
6102 +static char cuseeme_names[MAX_PORTS][14]; /* cuseeme-65535 */
6104 +static void fini(void)
6108 + for (i = 0 ; i < ports_c; i++) {
6109 + DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
6110 + ip_nat_helper_unregister(&cuseeme[i]);
6114 +static int __init init(void)
6120 + ports[0] = CUSEEME_PORT;
6122 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6123 + memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
6125 + cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
6126 + cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
6127 + cuseeme[i].mask.dst.protonum = 0xFFFF;
6128 + cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
6129 + cuseeme[i].help = cuseeme_nat_help;
6130 + cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE +
6131 + IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
6132 + is stricly needed... */
6133 + cuseeme[i].me = THIS_MODULE;
6134 + cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
6136 + tmpname = &cuseeme_names[i][0];
6137 + if (ports[i] == CUSEEME_PORT)
6138 + sprintf(tmpname, "cuseeme");
6140 + sprintf(tmpname, "cuseeme-%d", ports[i]);
6141 + cuseeme[i].name = tmpname;
6143 + DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
6144 + ports[i], cuseeme[i].name);
6145 + ret = ip_nat_helper_register(&cuseeme[i]);
6148 + printk("ip_nat_cuseeme: unable to register helper for port %d\n",
6160 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c
6161 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
6162 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-04-29 11:18:00.000000000 +0200
6165 + * H.323 'brute force' extension for NAT alteration.
6166 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6168 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6169 + * (http://www.coritel.it/projects/sofia/nat.html)
6170 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6171 + * the unregistered helpers to the conntrack entries.
6175 +#include <linux/module.h>
6176 +#include <linux/netfilter.h>
6177 +#include <linux/ip.h>
6178 +#include <net/checksum.h>
6179 +#include <net/tcp.h>
6181 +#include <linux/netfilter_ipv4/lockhelp.h>
6182 +#include <linux/netfilter_ipv4/ip_nat.h>
6183 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6184 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6185 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6186 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6187 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6189 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6190 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6191 +MODULE_LICENSE("GPL");
6193 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6194 +struct module *ip_nat_h323 = THIS_MODULE;
6197 +#define DEBUGP printk
6199 +#define DEBUGP(format, args...)
6202 +/* FIXME: Time out? --RR */
6204 +static unsigned int
6205 +h225_nat_expected(struct sk_buff **pskb,
6206 + unsigned int hooknum,
6207 + struct ip_conntrack *ct,
6208 + struct ip_nat_info *info);
6210 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6211 + struct ip_conntrack_expect *exp,
6212 + struct ip_nat_info *info,
6213 + enum ip_conntrack_info ctinfo,
6214 + unsigned int hooknum,
6215 + struct sk_buff **pskb);
6217 +static struct ip_nat_helper h245 =
6219 + "H.245", /* name */
6221 + NULL, /* module */
6222 + { { 0, { 0 } }, /* tuple */
6223 + { 0, { 0 }, IPPROTO_TCP } },
6224 + { { 0, { 0xFFFF } }, /* mask */
6225 + { 0, { 0 }, 0xFFFF } },
6226 + h225_nat_help, /* helper */
6227 + h225_nat_expected /* expectfn */
6230 +static unsigned int
6231 +h225_nat_expected(struct sk_buff **pskb,
6232 + unsigned int hooknum,
6233 + struct ip_conntrack *ct,
6234 + struct ip_nat_info *info)
6236 + struct ip_nat_multi_range mr;
6237 + u_int32_t newdstip, newsrcip, newip;
6239 + struct ip_ct_h225_expect *exp_info;
6240 + struct ip_ct_h225_master *master_info;
6241 + struct ip_conntrack *master = master_ct(ct);
6242 + unsigned int is_h225, ret;
6244 + IP_NF_ASSERT(info);
6245 + IP_NF_ASSERT(master);
6247 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6249 + DEBUGP("h225_nat_expected: We have a connection!\n");
6250 + master_info = &ct->master->expectant->help.ct_h225_info;
6251 + exp_info = &ct->master->help.exp_h225_info;
6253 + LOCK_BH(&ip_h323_lock);
6255 + DEBUGP("master: ");
6256 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6257 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6258 + DEBUGP("conntrack: ");
6259 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6260 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6261 + /* Make connection go to the client. */
6262 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6263 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6264 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6265 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6267 + /* Make the connection go to the server */
6268 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6269 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6270 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6271 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6273 + port = exp_info->port;
6274 + is_h225 = master_info->is_h225 == H225_PORT;
6275 + UNLOCK_BH(&ip_h323_lock);
6277 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6282 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6285 + /* We don't want to manip the per-protocol, just the IPs... */
6286 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6287 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6289 + /* ... unless we're doing a MANIP_DST, in which case, make
6290 + sure we map to the correct port */
6291 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6292 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6293 + mr.range[0].min = mr.range[0].max
6294 + = ((union ip_conntrack_manip_proto)
6295 + { .tcp = { port } });
6298 + ret = ip_nat_setup_info(ct, &mr, hooknum);
6301 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6302 + /* NAT expectfn called with ip_nat_lock write-locked */
6303 + info->helper = &h245;
6308 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6309 + struct sk_buff **pskb,
6310 + enum ip_conntrack_info ctinfo)
6312 + struct iphdr *iph = (*pskb)->nh.iph;
6313 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6314 + char *data = (char *) tcph + tcph->doff * 4;
6315 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6316 + u_int32_t datalen = tcplen - tcph->doff*4;
6317 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6322 + MUST_BE_LOCKED(&ip_h323_lock);
6324 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6325 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6327 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6329 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6330 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6333 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6334 + info->offset[IP_CT_DIR_ORIGINAL],
6335 + info->offset[IP_CT_DIR_REPLY],
6337 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6338 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6340 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
6341 + DEBUGP("h323_signal_address_fixup: %s %s\n",
6342 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6343 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6344 + if (!between(info->seq[i], ntohl(tcph->seq),
6345 + ntohl(tcph->seq) + datalen))
6347 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6348 + ntohl(tcph->seq) + datalen)) {
6349 + /* Partial retransmisison. It's a cracker being funky. */
6350 + if (net_ratelimit()) {
6351 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6354 + ntohl(tcph->seq) + datalen);
6359 + /* Change address inside packet to match way we're mapping
6360 + this connection. */
6361 + if (i == IP_CT_DIR_ORIGINAL) {
6362 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6363 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6365 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
6366 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6369 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6370 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6371 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6372 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6374 + /* Modify the packet */
6375 + *(u_int32_t *)(data + info->offset[i]) = newip;
6376 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
6378 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6379 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6380 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6381 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6384 + /* fix checksum information */
6386 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6390 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6391 + csum_partial((char *)tcph, tcph->doff*4,
6393 + ip_send_check(iph);
6398 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6399 + struct ip_conntrack *ct,
6400 + struct sk_buff **pskb,
6401 + enum ip_conntrack_info ctinfo,
6402 + struct ip_conntrack_expect *expect)
6406 + struct ip_conntrack_tuple newtuple;
6407 + struct iphdr *iph = (*pskb)->nh.iph;
6408 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6409 + char *data = (char *) tcph + tcph->doff * 4;
6410 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6411 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6414 + MUST_BE_LOCKED(&ip_h323_lock);
6415 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6416 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6417 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6419 + if (!between(expect->seq + 6, ntohl(tcph->seq),
6420 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6421 + /* Partial retransmisison. It's a cracker being funky. */
6422 + if (net_ratelimit()) {
6423 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6426 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6431 + /* Change address inside packet to match way we're mapping
6432 + this connection. */
6433 + if (info->dir == IP_CT_DIR_REPLY) {
6434 + /* Must be where client thinks server is */
6435 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6436 + /* Expect something from client->server */
6437 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6438 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6440 + /* Must be where server thinks client is */
6441 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6442 + /* Expect something from server->client */
6443 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6444 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6447 + is_h225 = (master_info->is_h225 == H225_PORT);
6450 + newtuple.dst.protonum = IPPROTO_TCP;
6451 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6453 + newtuple.dst.protonum = IPPROTO_UDP;
6454 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6457 + /* Try to get same port: if not, try to change it. */
6458 + for (port = ntohs(info->port); port != 0; port++) {
6460 + newtuple.dst.u.tcp.port = htons(port);
6462 + newtuple.dst.u.udp.port = htons(port);
6464 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6468 + DEBUGP("h323_data_fixup: no free port found!\n");
6472 + port = htons(port);
6474 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6475 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6476 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6478 + /* Modify the packet */
6479 + *(u_int32_t *)(data + info->offset) = newip;
6480 + *(u_int16_t *)(data + info->offset + 4) = port;
6482 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6483 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
6484 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
6486 + /* fix checksum information */
6487 + /* FIXME: usually repeated multiple times in the case of H.245! */
6489 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6490 + tcplen - tcph->doff*4, 0);
6493 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6494 + csum_partial((char *)tcph, tcph->doff*4,
6496 + ip_send_check(iph);
6501 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6502 + struct ip_conntrack_expect *exp,
6503 + struct ip_nat_info *info,
6504 + enum ip_conntrack_info ctinfo,
6505 + unsigned int hooknum,
6506 + struct sk_buff **pskb)
6509 + struct ip_ct_h225_expect *exp_info;
6511 + /* Only mangle things once: original direction in POST_ROUTING
6512 + and reply direction on PRE_ROUTING. */
6513 + dir = CTINFO2DIR(ctinfo);
6514 + DEBUGP("nat_h323: dir %s at hook %s\n",
6515 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6516 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6517 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6518 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6519 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6520 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6521 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6522 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6523 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6524 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6525 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6530 + LOCK_BH(&ip_h323_lock);
6531 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6532 + UNLOCK_BH(&ip_h323_lock);
6535 + UNLOCK_BH(&ip_h323_lock);
6539 + exp_info = &exp->help.exp_h225_info;
6541 + LOCK_BH(&ip_h323_lock);
6542 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6543 + UNLOCK_BH(&ip_h323_lock);
6546 + UNLOCK_BH(&ip_h323_lock);
6551 +static struct ip_nat_helper h225 =
6553 + "H.225", /* name */
6554 + IP_NAT_HELPER_F_ALWAYS, /* flags */
6555 + THIS_MODULE, /* module */
6556 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6557 + { 0, { 0 }, IPPROTO_TCP } },
6558 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6559 + { 0, { 0 }, 0xFFFF } },
6560 + h225_nat_help, /* helper */
6561 + h225_nat_expected /* expectfn */
6564 +static int __init init(void)
6568 + ret = ip_nat_helper_register(&h225);
6571 + printk("ip_nat_h323: cannot initialize the module!\n");
6576 +static void __exit fini(void)
6578 + ip_nat_helper_unregister(&h225);
6583 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c
6584 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6585 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-04-29 11:19:01.000000000 +0200
6587 +/* MMS extension for TCP NAT alteration.
6588 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6589 + * based on ip_nat_ftp.c and ip_nat_irc.c
6591 + * ip_nat_mms.c v0.3 2002-09-22
6593 + * This program is free software; you can redistribute it and/or
6594 + * modify it under the terms of the GNU General Public License
6595 + * as published by the Free Software Foundation; either version
6596 + * 2 of the License, or (at your option) any later version.
6598 + * Module load syntax:
6599 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6601 + * Please give the ports of all MMS servers You wish to connect to.
6602 + * If you don't specify ports, the default will be TCP port 1755.
6604 + * More info on MMS protocol, firewalls and NAT:
6605 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6606 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6608 + * The SDP project people are reverse-engineering MMS:
6609 + * http://get.to/sdp
6612 +/* FIXME: issue with UDP & fragmentation with this URL:
6613 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6614 + may be related to out-of-order first packets:
6615 + basically the expectation is set up correctly, then the server sends
6616 + a first UDP packet which is fragmented plus arrives out-of-order.
6617 + the MASQUERADING firewall with ip_nat_mms loaded responds with
6618 + an ICMP unreachable back to the server */
6620 +#include <linux/module.h>
6621 +#include <linux/netfilter_ipv4.h>
6622 +#include <linux/ip.h>
6623 +#include <linux/tcp.h>
6624 +#include <net/tcp.h>
6625 +#include <linux/netfilter_ipv4/ip_nat.h>
6626 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6627 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6628 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6629 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6632 +#define DEBUGP printk
6633 +#define DUMP_BYTES(address, counter) \
6635 + int temp_counter; \
6636 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6637 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
6642 +#define DEBUGP(format, args...)
6643 +#define DUMP_BYTES(address, counter)
6646 +#define MAX_PORTS 8
6647 +static int ports[MAX_PORTS];
6648 +static int ports_c = 0;
6651 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6654 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6655 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6656 +MODULE_LICENSE("GPL");
6658 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6660 +/* FIXME: Time out? --RR */
6662 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6663 + struct ip_conntrack *ct,
6664 + struct sk_buff **pskb,
6665 + enum ip_conntrack_info ctinfo,
6666 + struct ip_conntrack_expect *expect)
6669 + struct ip_conntrack_tuple t;
6670 + struct iphdr *iph = (*pskb)->nh.iph;
6671 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6672 + char *data = (char *)tcph + tcph->doff * 4;
6673 + int i, j, k, port;
6674 + u_int16_t mms_proto;
6676 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6677 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6678 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6682 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6683 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6684 + char proto_string[6];
6686 + MUST_BE_LOCKED(&ip_mms_lock);
6688 + /* what was the protocol again ? */
6689 + mms_proto = expect->tuple.dst.protonum;
6690 + sprintf(proto_string, "%u", mms_proto);
6692 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6693 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6694 + mms_proto == IPPROTO_UDP ? "UDP"
6695 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6697 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6699 + /* Alter conntrack's expectations. */
6700 + t = expect->tuple;
6702 + for (port = ct_mms_info->port; port != 0; port++) {
6703 + t.dst.u.tcp.port = htons(port);
6704 + if (ip_conntrack_change_expect(expect, &t) == 0) {
6705 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6713 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6715 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6716 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6718 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6720 + memset(unicode_buffer, 0, sizeof(char)*75);
6722 + for (i=0; i<strlen(buffer); ++i)
6723 + *(unicode_buffer+i*2)=*(buffer+i);
6725 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6726 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6727 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6729 + /* add end of packet to it */
6730 + for (j=0; j<ct_mms_info->padding; ++j) {
6731 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6732 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6733 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6736 + /* pad with zeroes at the end ? see explanation of weird math below */
6737 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6738 + for (k=0; k<zero_padding; ++k)
6739 + *(unicode_buffer+i*2+j+k)= (char)0;
6741 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6742 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6743 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6745 + /* explanation, before I forget what I did:
6746 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6747 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
6748 + but note that things may have to be padded with zeroes to align by 8
6749 + bytes, hence we add 7 and divide by 8 to get the correct length */
6750 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6751 + *mms_chunkLenLV = *mms_chunkLenLM+2;
6752 + *mms_messageLength = *mms_chunkLenLV*8;
6754 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6755 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6757 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6758 + expect->seq - ntohl(tcph->seq),
6759 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6760 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6761 + DUMP_BYTES(unicode_buffer, 60);
6766 +static unsigned int
6767 +mms_nat_expected(struct sk_buff **pskb,
6768 + unsigned int hooknum,
6769 + struct ip_conntrack *ct,
6770 + struct ip_nat_info *info)
6772 + struct ip_nat_multi_range mr;
6773 + u_int32_t newdstip, newsrcip, newip;
6775 + struct ip_conntrack *master = master_ct(ct);
6777 + IP_NF_ASSERT(info);
6778 + IP_NF_ASSERT(master);
6780 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6782 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6784 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6785 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6786 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6787 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6788 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6789 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6790 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6792 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6797 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6800 + /* We don't want to manip the per-protocol, just the IPs. */
6801 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6802 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6804 + return ip_nat_setup_info(ct, &mr, hooknum);
6808 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6809 + struct ip_conntrack_expect *exp,
6810 + struct ip_nat_info *info,
6811 + enum ip_conntrack_info ctinfo,
6812 + unsigned int hooknum,
6813 + struct sk_buff **pskb)
6815 + struct iphdr *iph = (*pskb)->nh.iph;
6816 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6817 + unsigned int datalen;
6819 + struct ip_ct_mms_expect *ct_mms_info;
6822 + DEBUGP("ip_nat_mms: no exp!!");
6824 + ct_mms_info = &exp->help.exp_mms_info;
6826 + /* Only mangle things once: original direction in POST_ROUTING
6827 + and reply direction on PRE_ROUTING. */
6828 + dir = CTINFO2DIR(ctinfo);
6829 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6830 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6831 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6832 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6833 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6834 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6835 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6838 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6839 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6840 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6841 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6842 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6844 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6846 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6847 + exp->seq + ct_mms_info->len,
6849 + ntohl(tcph->seq) + datalen);
6851 + LOCK_BH(&ip_mms_lock);
6852 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
6853 + if (between(exp->seq + ct_mms_info->len,
6855 + ntohl(tcph->seq) + datalen)) {
6856 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6857 + UNLOCK_BH(&ip_mms_lock);
6861 + /* Half a match? This means a partial retransmisison.
6862 + It's a cracker being funky. */
6863 + if (net_ratelimit()) {
6864 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6865 + exp->seq, ct_mms_info->len,
6867 + ntohl(tcph->seq) + datalen);
6869 + UNLOCK_BH(&ip_mms_lock);
6872 + UNLOCK_BH(&ip_mms_lock);
6877 +static struct ip_nat_helper mms[MAX_PORTS];
6878 +static char mms_names[MAX_PORTS][10];
6880 +/* Not __exit: called from init() */
6881 +static void fini(void)
6885 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6886 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6887 + ip_nat_helper_unregister(&mms[i]);
6891 +static int __init init(void)
6896 + if (ports[0] == 0)
6897 + ports[0] = MMS_PORT;
6899 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6901 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6903 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
6904 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6905 + mms[i].mask.dst.protonum = 0xFFFF;
6906 + mms[i].mask.src.u.tcp.port = 0xFFFF;
6907 + mms[i].help = mms_nat_help;
6908 + mms[i].me = THIS_MODULE;
6910 + mms[i].expect = mms_nat_expected;
6912 + tmpname = &mms_names[i][0];
6913 + if (ports[i] == MMS_PORT)
6914 + sprintf(tmpname, "mms");
6916 + sprintf(tmpname, "mms-%d", i);
6917 + mms[i].name = tmpname;
6919 + DEBUGP("ip_nat_mms: register helper for port %d\n",
6921 + ret = ip_nat_helper_register(&mms[i]);
6924 + printk("ip_nat_mms: error registering "
6925 + "helper for port %d\n", ports[i]);
6937 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6938 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
6939 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-04-29 11:19:53.000000000 +0200
6941 +/* Quake3 extension for UDP NAT alteration.
6942 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6943 + * based on ip_nat_ftp.c and ip_nat_tftp.c
6945 + * ip_nat_quake3.c v0.0.3 2002-08-31
6947 + * This program is free software; you can redistribute it and/or
6948 + * modify it under the terms of the GNU General Public License
6949 + * as published by the Free Software Foundation; either version
6950 + * 2 of the License, or (at your option) any later version.
6952 + * Module load syntax:
6953 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6955 + * please give the ports of all Quake3 master servers You wish to
6956 + * connect to. If you don't specify ports, the default will be UDP
6959 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6962 + * - If you're one of those people who would try anything to lower
6963 + * latency while playing Quake (and who isn't :-) ), you may want to
6964 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
6965 + * outgoing UDP traffic.
6966 + * This will make ip_conntrack_quake3 add the necessary expectations,
6967 + * but there will be no overhead for client->server UDP streams. If
6968 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6969 + * hook for every packet in the client->server UDP stream.
6970 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6971 + * The IP addresses in the master connection payload (=IP addresses
6972 + * of Quake servers) have no relation with the master server so
6973 + * DNAT'ing the master connection to a server should not change the
6974 + * expected connections.
6975 + * - Not tested due to lack of equipment:
6976 + * - multiple Quake3 clients behind one MASQUERADE gateway
6977 + * - what if Quake3 client is running on router too
6980 +#include <linux/module.h>
6981 +#include <linux/netfilter_ipv4.h>
6982 +#include <linux/ip.h>
6983 +#include <linux/udp.h>
6985 +#include <linux/netfilter.h>
6986 +#include <linux/netfilter_ipv4/ip_tables.h>
6987 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6988 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6989 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6990 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6992 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6993 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6994 +MODULE_LICENSE("GPL");
6996 +#define MAX_PORTS 8
6998 +static int ports[MAX_PORTS];
6999 +static int ports_c = 0;
7001 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7002 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7005 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7006 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7008 +#define DEBUGP printk
7010 +#define DEBUGP(format, args...)
7013 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7015 +static unsigned int
7016 +quake3_nat_help(struct ip_conntrack *ct,
7017 + struct ip_conntrack_expect *exp,
7018 + struct ip_nat_info *info,
7019 + enum ip_conntrack_info ctinfo,
7020 + unsigned int hooknum,
7021 + struct sk_buff **pskb)
7023 + struct iphdr *iph = (*pskb)->nh.iph;
7024 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7025 + struct ip_conntrack_tuple repl;
7026 + int dir = CTINFO2DIR(ctinfo);
7029 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7030 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7031 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7032 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7033 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7035 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7036 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7038 + /* Only mangle things once: original direction in POST_ROUTING
7039 + and reply direction on PRE_ROUTING. */
7040 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7041 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7042 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7043 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7044 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7045 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7046 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7051 + DEBUGP("no conntrack expectation to modify\n");
7055 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7056 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7057 + i+6 < ntohs(udph->len);
7059 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
7060 + i, ntohs(udph->len),
7061 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7062 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7064 + memset(&repl, 0, sizeof(repl));
7066 + repl.dst.protonum = IPPROTO_UDP;
7067 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7068 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7069 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
7071 + ip_conntrack_change_expect(exp, &repl);
7077 +static unsigned int
7078 +quake3_nat_expected(struct sk_buff **pskb,
7079 + unsigned int hooknum,
7080 + struct ip_conntrack *ct,
7081 + struct ip_nat_info *info)
7083 + const struct ip_conntrack *master = ct->master->expectant;
7084 + struct ip_nat_multi_range mr;
7085 + u_int32_t newsrcip, newdstip, newip;
7087 + const struct ip_conntrack_tuple *repl =
7088 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7089 + struct iphdr *iph = (*pskb)->nh.iph;
7090 + struct udphdr *udph = (void *)iph + iph->ihl*4;
7093 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7094 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7096 + IP_NF_ASSERT(info);
7097 + IP_NF_ASSERT(master);
7098 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7100 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7101 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7103 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7105 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7106 + "newsrc: %u.%u.%u.%u\n",
7107 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7108 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7109 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7110 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7111 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7116 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7117 + "newdst: %u.%u.%u.%u\n",
7118 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7119 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7120 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7121 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7122 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7127 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7128 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7130 + return ip_nat_setup_info(ct,&mr,hooknum);
7133 +static struct ip_nat_helper quake3[MAX_PORTS];
7134 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
7136 +static void fini(void)
7140 + for (i = 0 ; i < ports_c; i++) {
7141 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7142 + ip_nat_helper_unregister(&quake3[i]);
7146 +static int __init init(void)
7152 + ports[0] = QUAKE3_MASTER_PORT;
7154 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7155 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7157 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7158 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7159 + quake3[i].mask.dst.protonum = 0xFFFF;
7160 + quake3[i].mask.src.u.udp.port = 0xFFFF;
7161 + quake3[i].help = quake3_nat_help;
7162 + quake3[i].flags = 0;
7163 + quake3[i].me = THIS_MODULE;
7164 + quake3[i].expect = quake3_nat_expected;
7166 + tmpname = &quake3_names[i][0];
7167 + if (ports[i] == QUAKE3_MASTER_PORT)
7168 + sprintf(tmpname, "quake3");
7170 + sprintf(tmpname, "quake3-%d", i);
7171 + quake3[i].name = tmpname;
7173 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7174 + ports[i], quake3[i].name);
7175 + ret = ip_nat_helper_register(&quake3[i]);
7178 + printk("ip_nat_quake3: unable to register helper for port %d\n",
7190 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
7191 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
7192 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-04-29 11:20:13.000000000 +0200
7195 + * RTSP extension for TCP NAT alteration
7196 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7197 + * based on ip_nat_irc.c
7199 + * This program is free software; you can redistribute it and/or
7200 + * modify it under the terms of the GNU General Public License
7201 + * as published by the Free Software Foundation; either version
7202 + * 2 of the License, or (at your option) any later version.
7204 + * Module load syntax:
7205 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7206 + * stunaddr=<address>
7207 + * destaction=[auto|strip|none]
7209 + * If no ports are specified, the default will be port 554 only.
7211 + * stunaddr specifies the address used to detect that a client is using STUN.
7212 + * If this address is seen in the destination parameter, it is assumed that
7213 + * the client has already punched a UDP hole in the firewall, so we don't
7214 + * mangle the client_port. If none is specified, it is autodetected. It
7215 + * only needs to be set if you have multiple levels of NAT. It should be
7216 + * set to the external address that the STUN clients detect. Note that in
7217 + * this case, it will not be possible for clients to use UDP with servers
7218 + * between the NATs.
7220 + * If no destaction is specified, auto is used.
7221 + * destaction=auto: strip destination parameter if it is not stunaddr.
7222 + * destaction=strip: always strip destination parameter (not recommended).
7223 + * destaction=none: do not touch destination parameter (not recommended).
7226 +#include <linux/module.h>
7227 +#include <linux/netfilter_ipv4.h>
7228 +#include <linux/ip.h>
7229 +#include <linux/tcp.h>
7230 +#include <linux/kernel.h>
7231 +#include <net/tcp.h>
7232 +#include <linux/netfilter_ipv4/ip_nat.h>
7233 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7234 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7235 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7236 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7238 +#include <linux/inet.h>
7239 +#include <linux/ctype.h>
7240 +#define NF_NEED_STRNCASECMP
7241 +#define NF_NEED_STRTOU16
7242 +#include <linux/netfilter_helpers.h>
7243 +#define NF_NEED_MIME_NEXTLINE
7244 +#include <linux/netfilter_mime.h>
7246 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7247 +#ifdef IP_NF_RTSP_DEBUG
7248 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7250 +#define DEBUGP(fmt, args...)
7253 +#define MAX_PORTS 8
7254 +#define DSTACT_AUTO 0
7255 +#define DSTACT_STRIP 1
7256 +#define DSTACT_NONE 2
7258 +static int ports[MAX_PORTS];
7259 +static char* stunaddr = NULL;
7260 +static char* destaction = NULL;
7262 +static int num_ports = 0;
7263 +static u_int32_t extip = 0;
7264 +static int dstact = 0;
7266 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7267 +MODULE_DESCRIPTION("RTSP network address translation module");
7268 +MODULE_LICENSE("GPL");
7270 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7271 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7272 +MODULE_PARM(stunaddr, "s");
7273 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7274 +MODULE_PARM(destaction, "s");
7275 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7278 +/* protects rtsp part of conntracks */
7279 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7281 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7283 +/*** helper functions ***/
7286 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7288 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7289 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7291 + *pptcpdata = (char*)tcph + tcph->doff*4;
7292 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7295 +/*** nat functions ***/
7298 + * Mangle the "Transport:" header:
7299 + * - Replace all occurences of "client_port=<spec>"
7300 + * - Handle destination parameter
7303 + * ct, ctinfo = conntrack context
7305 + * tranoff = Transport header offset from TCP data
7306 + * tranlen = Transport header length (incl. CRLF)
7307 + * rport_lo = replacement low port (host endian)
7308 + * rport_hi = replacement high port (host endian)
7310 + * Returns packet size difference.
7312 + * Assumes that a complete transport header is present, ending with CR or LF
7315 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7316 + struct ip_conntrack_expect* exp,
7317 + struct sk_buff** pskb, uint tranoff, uint tranlen)
7322 + char rbuf1[16]; /* Replacement buffer (one port) */
7323 + uint rbuf1len; /* Replacement len (one port) */
7324 + char rbufa[16]; /* Replacement buffer (all ports) */
7325 + uint rbufalen; /* Replacement len (all ports) */
7327 + u_int16_t loport, hiport;
7329 + uint diff; /* Number of bytes we removed */
7331 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7332 + struct ip_conntrack_tuple t;
7334 + char szextaddr[15+1];
7338 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7339 + ptran = ptcp+tranoff;
7341 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7342 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7343 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
7345 + INFOP("sanity check failed\n");
7349 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7351 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7355 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7356 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7357 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7359 + rbuf1len = rbufalen = 0;
7360 + switch (prtspexp->pbtype)
7363 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7365 + t.dst.u.udp.port = htons(loport);
7366 + if (ip_conntrack_change_expect(exp, &t) == 0)
7368 + DEBUGP("using port %hu\n", loport);
7374 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7375 + rbufalen = sprintf(rbufa, "%hu", loport);
7379 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7381 + t.dst.u.udp.port = htons(loport);
7382 + if (ip_conntrack_change_expect(exp, &t) == 0)
7384 + hiport = loport + ~exp->mask.dst.u.udp.port;
7385 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
7391 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7392 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7396 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7398 + t.dst.u.udp.port = htons(loport);
7399 + if (ip_conntrack_change_expect(exp, &t) == 0)
7401 + DEBUGP("using port %hu (1 of 2)\n", loport);
7405 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7407 + t.dst.u.udp.port = htons(hiport);
7408 + if (ip_conntrack_change_expect(exp, &t) == 0)
7410 + DEBUGP("using port %hu (2 of 2)\n", hiport);
7414 + if (loport != 0 && hiport != 0)
7416 + rbuf1len = sprintf(rbuf1, "%hu", loport);
7417 + if (hiport == loport+1)
7419 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7423 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7429 + if (rbuf1len == 0)
7431 + return 0; /* cannot get replacement port(s) */
7434 + /* Transport: tran;field;field=val,tran;field;field=val,... */
7435 + while (off < tranlen)
7438 + const char* pparamend;
7439 + uint nextparamoff;
7441 + pparamend = memchr(ptran+off, ',', tranlen-off);
7442 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7443 + nextparamoff = pparamend-ptcp;
7446 + * We pass over each param twice. On the first pass, we look for a
7447 + * destination= field. It is handled by the security policy. If it
7448 + * is present, allowed, and equal to our external address, we assume
7449 + * that STUN is being used and we leave the client_port= field alone.
7453 + while (off < nextparamoff)
7455 + const char* pfieldend;
7456 + uint nextfieldoff;
7458 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7459 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7461 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7463 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7467 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7469 + diff = nextfieldoff-off;
7470 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7471 + off, diff, NULL, 0))
7473 + /* mangle failed, all we can do is bail */
7476 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7477 + ptran = ptcp+tranoff;
7479 + nextparamoff -= diff;
7480 + nextfieldoff -= diff;
7484 + off = nextfieldoff;
7491 + while (off < nextparamoff)
7493 + const char* pfieldend;
7494 + uint nextfieldoff;
7496 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7497 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7499 + if (strncmp(ptran+off, "client_port=", 12) == 0)
7505 + char* rbuf = rbuf1;
7506 + uint rbuflen = rbuf1len;
7509 + origoff = (ptran-ptcp)+off;
7511 + numlen = nf_strtou16(ptran+off, &port);
7513 + origlen += numlen;
7514 + if (port != prtspexp->loport)
7516 + DEBUGP("multiple ports found, port %hu ignored\n", port);
7520 + if (ptran[off] == '-' || ptran[off] == '/')
7524 + numlen = nf_strtou16(ptran+off, &port);
7526 + origlen += numlen;
7528 + rbuflen = rbufalen;
7532 + * note we cannot just memcpy() if the sizes are the same.
7533 + * the mangle function does skb resizing, checks for a
7534 + * cloned skb, and updates the checksums.
7536 + * parameter 4 below is offset from start of tcp data.
7538 + diff = origlen-rbuflen;
7539 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7540 + origoff, origlen, rbuf, rbuflen))
7542 + /* mangle failed, all we can do is bail */
7545 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7546 + ptran = ptcp+tranoff;
7548 + nextparamoff -= diff;
7549 + nextfieldoff -= diff;
7553 + off = nextfieldoff;
7556 + off = nextparamoff;
7562 +static unsigned int
7563 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7565 + struct ip_nat_multi_range mr;
7566 + u_int32_t newdstip, newsrcip, newip;
7568 + struct ip_conntrack *master = master_ct(ct);
7570 + IP_NF_ASSERT(info);
7571 + IP_NF_ASSERT(master);
7573 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7575 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7576 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7577 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7579 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7580 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7583 + /* We don't want to manip the per-protocol, just the IPs. */
7584 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7585 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
7587 + return ip_nat_setup_info(ct, &mr, hooknum);
7591 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7592 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7602 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7603 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7605 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7607 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7609 + hdrsoff = exp->seq - ntohl(tcph->seq);
7610 + hdrslen = prtspexp->len;
7613 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7619 + if (off > hdrsoff+hdrslen)
7621 + INFOP("!! overrun !!");
7624 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7626 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7628 + uint oldtcplen = tcplen;
7629 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7633 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7634 + hdrslen -= (oldtcplen-tcplen);
7635 + off -= (oldtcplen-tcplen);
7636 + lineoff -= (oldtcplen-tcplen);
7637 + linelen -= (oldtcplen-tcplen);
7638 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7646 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7647 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7649 + /* XXX: unmangle */
7654 +help(struct ip_conntrack* ct,
7655 + struct ip_conntrack_expect* exp,
7656 + struct ip_nat_info* info,
7657 + enum ip_conntrack_info ctinfo,
7658 + unsigned int hooknum,
7659 + struct sk_buff** pskb)
7661 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7662 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7665 + struct ip_ct_rtsp_expect* ct_rtsp_info;
7666 + int rc = NF_ACCEPT;
7668 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7670 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7674 + ct_rtsp_info = &exp->help.exp_rtsp_info;
7677 + * Only mangle things once: original direction in POST_ROUTING
7678 + * and reply direction on PRE_ROUTING.
7680 + dir = CTINFO2DIR(ctinfo);
7681 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7682 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7684 + DEBUGP("Not touching dir %s at hook %s\n",
7685 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7686 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7687 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7688 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7691 + DEBUGP("got beyond not touching\n");
7693 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7695 + LOCK_BH(&ip_rtsp_lock);
7696 + /* Ensure the packet contains all of the marked data */
7697 + if (!between(exp->seq + ct_rtsp_info->len,
7698 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7700 + /* Partial retransmission? Probably a hacker. */
7701 + if (net_ratelimit())
7703 + INFOP("partial packet %u/%u in %u/%u\n",
7704 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7706 + UNLOCK_BH(&ip_rtsp_lock);
7712 + case IP_CT_DIR_ORIGINAL:
7713 + rc = help_out(ct, ctinfo, exp, pskb);
7715 + case IP_CT_DIR_REPLY:
7716 + rc = help_in(ct, ctinfo, exp, pskb);
7719 + UNLOCK_BH(&ip_rtsp_lock);
7724 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7725 +static char rtsp_names[MAX_PORTS][10];
7727 +/* This function is intentionally _NOT_ defined as __exit */
7733 + for (i = 0; i < num_ports; i++)
7735 + DEBUGP("unregistering helper for port %d\n", ports[i]);
7736 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7745 + struct ip_nat_helper* hlpr;
7748 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7750 + if (ports[0] == 0)
7752 + ports[0] = RTSP_PORT;
7755 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7757 + hlpr = &ip_nat_rtsp_helpers[i];
7758 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
7760 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
7761 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7762 + hlpr->mask.src.u.tcp.port = 0xFFFF;
7763 + hlpr->mask.dst.protonum = 0xFFFF;
7764 + hlpr->help = help;
7766 + hlpr->me = THIS_MODULE;
7767 + hlpr->expect = expected;
7769 + tmpname = &rtsp_names[i][0];
7770 + if (ports[i] == RTSP_PORT)
7772 + sprintf(tmpname, "rtsp");
7776 + sprintf(tmpname, "rtsp-%d", i);
7778 + hlpr->name = tmpname;
7780 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7781 + ret = ip_nat_helper_register(hlpr);
7785 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7791 + if (stunaddr != NULL)
7793 + extip = in_aton(stunaddr);
7795 + if (destaction != NULL)
7797 + if (strcmp(destaction, "auto") == 0)
7799 + dstact = DSTACT_AUTO;
7801 + if (strcmp(destaction, "strip") == 0)
7803 + dstact = DSTACT_STRIP;
7805 + if (strcmp(destaction, "none") == 0)
7807 + dstact = DSTACT_NONE;
7815 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c
7816 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c 2004-04-28 03:35:44.000000000 +0200
7817 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c 2004-04-29 11:17:15.000000000 +0200
7820 sizeof(struct ipt_entry),
7821 sizeof(struct ipt_standard),
7822 - 0, { 0, 0 }, { } },
7823 + 0, NULL, 0, { 0, 0 }, { } },
7824 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7829 sizeof(struct ipt_entry),
7830 sizeof(struct ipt_standard),
7831 - 0, { 0, 0 }, { } },
7832 + 0, NULL, 0, { 0, 0 }, { } },
7833 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7838 sizeof(struct ipt_entry),
7839 sizeof(struct ipt_standard),
7840 - 0, { 0, 0 }, { } },
7841 + 0, NULL, 0, { 0, 0 }, { } },
7842 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7847 sizeof(struct ipt_entry),
7848 sizeof(struct ipt_error),
7849 - 0, { 0, 0 }, { } },
7850 + 0, NULL, 0, { 0, 0 }, { } },
7851 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7854 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7855 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-28 03:36:29.000000000 +0200
7856 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-29 11:18:04.000000000 +0200
7857 @@ -175,6 +175,45 @@
7858 return do_bindings(ct, ctinfo, info, hooknum, pskb);
7861 +struct nat_route_key
7870 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7872 + struct iphdr *iph = skb->nh.iph;
7874 + key->addr = which ? iph->daddr : iph->saddr;
7877 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7878 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7879 + key->port = ports[which];
7885 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7887 + struct iphdr *iph = skb->nh.iph;
7889 + if (key->addr != (which ? iph->daddr : iph->saddr))
7892 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7893 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7894 + if (key->port != ports[which])
7901 ip_nat_out(unsigned int hooknum,
7902 struct sk_buff **pskb,
7904 const struct net_device *out,
7905 int (*okfn)(struct sk_buff *))
7907 + struct nat_route_key key;
7910 /* root is playing with raw sockets. */
7911 if ((*pskb)->len < sizeof(struct iphdr)
7912 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7913 @@ -204,7 +246,29 @@
7917 - return ip_nat_fn(hooknum, pskb, in, out, okfn);
7918 + nat_route_key_get(*pskb, &key, 0);
7919 + ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7921 + if (ret != NF_DROP && ret != NF_STOLEN
7922 + && nat_route_key_compare(*pskb, &key, 0)) {
7923 + if (ip_route_me_harder(pskb) != 0)
7927 + * POST_ROUTING hook is called with fixed outfn, we need
7928 + * to manually confirm the packet and direct it to the
7929 + * transformers if a policy matches.
7931 + else if ((*pskb)->dst->xfrm != NULL) {
7932 + ret = ip_conntrack_confirm(*pskb);
7933 + if (ret != NF_DROP) {
7934 + dst_output(*pskb);
7943 #ifdef CONFIG_IP_NF_NAT_LOCAL
7945 const struct net_device *out,
7946 int (*okfn)(struct sk_buff *))
7948 - u_int32_t saddr, daddr;
7949 + struct nat_route_key key;
7952 /* root is playing with raw sockets. */
7953 @@ -223,14 +287,14 @@
7954 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7957 - saddr = (*pskb)->nh.iph->saddr;
7958 - daddr = (*pskb)->nh.iph->daddr;
7960 + nat_route_key_get(*pskb, &key, 1);
7961 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7963 if (ret != NF_DROP && ret != NF_STOLEN
7964 - && ((*pskb)->nh.iph->saddr != saddr
7965 - || (*pskb)->nh.iph->daddr != daddr))
7966 - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7967 + && nat_route_key_compare(*pskb, &key, 1)) {
7968 + if (ip_route_me_harder(pskb) != 0)
7974 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c
7975 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
7976 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-04-29 11:21:43.000000000 +0200
7979 + * talk extension for UDP NAT alteration.
7980 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7982 + * This program is free software; you can redistribute it and/or
7983 + * modify it under the terms of the GNU General Public License
7984 + * as published by the Free Software Foundation; either version
7985 + * 2 of the License, or (at your option) any later version.
7987 + * Module load syntax:
7988 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7990 + * talk=[0|1] disable|enable old talk support
7991 + * ntalk=[0|1] disable|enable ntalk support
7992 + * ntalk2=[0|1] disable|enable ntalk2 support
7994 + * The default is talk=1 ntalk=1 ntalk2=1
7998 +#include <linux/module.h>
7999 +#include <linux/netfilter_ipv4.h>
8000 +#include <linux/ip.h>
8001 +#include <linux/udp.h>
8002 +#include <linux/kernel.h>
8003 +#include <net/tcp.h>
8004 +#include <net/udp.h>
8006 +#include <linux/netfilter_ipv4/ip_nat.h>
8007 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8008 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8009 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8010 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8012 +/* Default all talk protocols are supported */
8013 +static int talk = 1;
8014 +static int ntalk = 1;
8015 +static int ntalk2 = 1;
8016 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8017 +MODULE_DESCRIPTION("talk network address translation module");
8019 +MODULE_PARM(talk, "i");
8020 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8021 +MODULE_PARM(ntalk, "i");
8022 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8023 +MODULE_PARM(ntalk2, "i");
8024 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8028 +#define DEBUGP printk
8029 +#define IP_NAT_TALK_DEBUG
8031 +#define DEBUGP(format, args...)
8034 +/* FIXME: Time out? --RR */
8037 +mangle_packet(struct sk_buff **pskb,
8038 + struct ip_conntrack *ct,
8041 + struct talk_addr *addr,
8042 + struct talk_addr *ctl_addr)
8044 + struct iphdr *iph = (*pskb)->nh.iph;
8045 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8046 + size_t udplen = (*pskb)->len - iph->ihl * 4;
8048 + /* Fortunately talk sends a structure with the address and
8049 + port in it. The size of the packet won't change. */
8051 + if (ctl_addr == NULL) {
8053 + if (addr->ta_addr == INADDR_ANY)
8055 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8056 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8057 + NIPQUAD(newip), ntohs(port));
8058 + addr->ta_addr = newip;
8059 + addr->ta_port = port;
8062 + if (addr->ta_addr != INADDR_ANY) {
8063 + /* Change address inside packet to match way we're mapping
8064 + this connection. */
8065 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8066 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8067 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
8068 + ntohs(addr->ta_port));
8069 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8071 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8072 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8073 + NIPQUAD(newip), ntohs(port));
8074 + ctl_addr->ta_addr = newip;
8075 + ctl_addr->ta_port = port;
8078 + /* Fix checksums */
8079 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8081 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8082 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8084 + ip_send_check(iph);
8088 +static int talk_help_msg(struct ip_conntrack *ct,
8089 + struct sk_buff **pskb,
8091 + struct talk_addr *addr,
8092 + struct talk_addr *ctl_addr)
8097 + unsigned int verdict = NF_ACCEPT;
8099 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8100 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8101 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8104 + /* Change address inside packet to match way we're mapping
8105 + this connection. */
8106 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8107 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8108 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8109 + NIPQUAD(newip), ntohs(port));
8111 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8112 + verdict = NF_DROP;
8117 +static int talk_help_response(struct ip_conntrack *ct,
8118 + struct ip_conntrack_expect *exp,
8119 + struct sk_buff **pskb,
8122 + struct talk_addr *addr)
8126 + struct ip_conntrack_tuple t;
8127 + struct ip_ct_talk_expect *ct_talk_info;
8129 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8130 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8133 + LOCK_BH(&ip_talk_lock);
8134 + ct_talk_info = &exp->help.exp_talk_info;
8136 + if (!(answer == SUCCESS
8137 + && (type == LOOK_UP || type == ANNOUNCE)
8138 + && exp != NULL)) {
8139 + UNLOCK_BH(&ip_talk_lock);
8143 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
8144 + ntohs(ct_talk_info->port),
8145 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8147 + /* Change address inside packet to match way we're mapping
8148 + this connection. */
8149 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
8150 + IP_CT_DIR_REPLY].tuple.dst.ip;
8151 + /* We can read expect here without conntrack lock, since it's
8152 + only set in ip_conntrack_talk , with ip_talk_lock held
8157 + /* Try to get same port: if not, try to change it. */
8158 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8159 + if (type == LOOK_UP)
8160 + t.dst.u.tcp.port = htons(port);
8162 + t.dst.u.udp.port = htons(port);
8164 + if (ip_conntrack_change_expect(exp, &t) == 0) {
8165 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8169 + UNLOCK_BH(&ip_talk_lock);
8171 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8177 +static unsigned int talk_help(struct ip_conntrack *ct,
8178 + struct ip_conntrack_expect *exp,
8179 + struct ip_nat_info *info,
8180 + enum ip_conntrack_info ctinfo,
8181 + unsigned int hooknum,
8182 + struct sk_buff **pskb,
8185 + struct iphdr *iph = (*pskb)->nh.iph;
8186 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8187 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8188 + char *data = (char *)udph + sizeof(struct udphdr);
8191 + /* Only mangle things once: original direction in POST_ROUTING
8192 + and reply direction on PRE_ROUTING. */
8193 + dir = CTINFO2DIR(ctinfo);
8194 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8195 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8196 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8197 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8198 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8199 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8200 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8203 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8204 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8205 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8206 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8207 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8208 + NIPQUAD(iph->saddr), ntohs(udph->source),
8209 + NIPQUAD(iph->daddr), ntohs(udph->dest),
8212 + /* Because conntrack does not drop packets, checking must be repeated here... */
8213 + if (talk_port == TALK_PORT) {
8214 + if (dir == IP_CT_DIR_ORIGINAL
8215 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8216 + return talk_help_msg(ct, pskb,
8217 + ((struct talk_msg *)data)->type,
8218 + &(((struct talk_msg *)data)->addr),
8219 + &(((struct talk_msg *)data)->ctl_addr));
8220 + else if (dir == IP_CT_DIR_REPLY
8221 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8222 + return talk_help_response(ct, exp, pskb,
8223 + ((struct talk_response *)data)->type,
8224 + ((struct talk_response *)data)->answer,
8225 + &(((struct talk_response *)data)->addr));
8227 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8228 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
8229 + (unsigned)udplen - sizeof(struct udphdr),
8230 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8234 + if (dir == IP_CT_DIR_ORIGINAL) {
8236 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8237 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8238 + return talk_help_msg(ct, pskb,
8239 + ((struct ntalk_msg *)data)->type,
8240 + &(((struct ntalk_msg *)data)->addr),
8241 + &(((struct ntalk_msg *)data)->ctl_addr));
8243 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8244 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8245 + && udplen == sizeof(struct udphdr)
8246 + + sizeof(struct ntalk2_msg)
8247 + + ((struct ntalk2_msg *)data)->extended)
8248 + return talk_help_msg(ct, pskb,
8249 + ((struct ntalk2_msg *)data)->type,
8250 + &(((struct ntalk2_msg *)data)->addr),
8251 + &(((struct ntalk2_msg *)data)->ctl_addr));
8253 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8254 + (unsigned)udplen - sizeof(struct udphdr),
8255 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8260 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8261 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8262 + return talk_help_response(ct, exp, pskb,
8263 + ((struct ntalk_response *)data)->type,
8264 + ((struct ntalk_response *)data)->answer,
8265 + &(((struct ntalk_response *)data)->addr));
8267 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8268 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8269 + return talk_help_response(ct, exp, pskb,
8270 + ((struct ntalk2_response *)data)->type,
8271 + ((struct ntalk2_response *)data)->answer,
8272 + &(((struct ntalk2_response *)data)->addr));
8274 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8275 + (unsigned)udplen - sizeof(struct udphdr),
8276 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8283 +static unsigned int help(struct ip_conntrack *ct,
8284 + struct ip_conntrack_expect *exp,
8285 + struct ip_nat_info *info,
8286 + enum ip_conntrack_info ctinfo,
8287 + unsigned int hooknum,
8288 + struct sk_buff **pskb)
8290 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8293 +static unsigned int nhelp(struct ip_conntrack *ct,
8294 + struct ip_conntrack_expect *exp,
8295 + struct ip_nat_info *info,
8296 + enum ip_conntrack_info ctinfo,
8297 + unsigned int hooknum,
8298 + struct sk_buff **pskb)
8300 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8303 +static unsigned int
8304 +talk_nat_expected(struct sk_buff **pskb,
8305 + unsigned int hooknum,
8306 + struct ip_conntrack *ct,
8307 + struct ip_nat_info *info);
8309 +static struct ip_nat_helper talk_helpers[2] =
8310 + { { { NULL, NULL },
8311 + "talk", /* name */
8312 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8313 + THIS_MODULE, /* module */
8314 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8315 + { 0, { 0 }, IPPROTO_UDP } },
8316 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8317 + { 0, { 0 }, 0xFFFF } },
8318 + help, /* helper */
8319 + talk_nat_expected }, /* expectfn */
8321 + "ntalk", /* name */
8322 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8323 + THIS_MODULE, /* module */
8324 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8325 + { 0, { 0 }, IPPROTO_UDP } },
8326 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
8327 + { 0, { 0 }, 0xFFFF } },
8328 + nhelp, /* helper */
8329 + talk_nat_expected } /* expectfn */
8332 +static unsigned int
8333 +talk_nat_expected(struct sk_buff **pskb,
8334 + unsigned int hooknum,
8335 + struct ip_conntrack *ct,
8336 + struct ip_nat_info *info)
8338 + struct ip_nat_multi_range mr;
8339 + u_int32_t newdstip, newsrcip, newip;
8343 + struct ip_conntrack *master = master_ct(ct);
8345 + IP_NF_ASSERT(info);
8346 + IP_NF_ASSERT(master);
8348 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8350 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8352 + LOCK_BH(&ip_talk_lock);
8353 + port = ct->master->help.exp_talk_info.port;
8354 + UNLOCK_BH(&ip_talk_lock);
8356 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8357 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8358 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8359 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8360 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8363 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8364 + /* Callee client -> caller server */
8365 +#ifdef IP_NAT_TALK_DEBUG
8366 + struct iphdr *iph = (*pskb)->nh.iph;
8367 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8369 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8370 + NIPQUAD(iph->saddr), ntohs(udph->source),
8371 + NIPQUAD(iph->daddr), ntohs(udph->dest));
8373 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8374 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8375 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8376 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8378 + /* Callee client -> caller client */
8379 +#ifdef IP_NAT_TALK_DEBUG
8380 + struct iphdr *iph = (*pskb)->nh.iph;
8381 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8383 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8384 + NIPQUAD(iph->saddr), ntohs(tcph->source),
8385 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
8387 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8388 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8389 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8390 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8392 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8397 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8400 + /* We don't want to manip the per-protocol, just the IPs... */
8401 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8402 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8404 + /* ... unless we're doing a MANIP_DST, in which case, make
8405 + sure we map to the correct port */
8406 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8407 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8408 + mr.range[0].min = mr.range[0].max
8409 + = ((union ip_conntrack_manip_proto)
8410 + { .udp = { port } });
8412 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8414 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8415 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8416 + /* NAT expectfn called with ip_nat_lock write-locked */
8417 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
8422 +static int __init init(void)
8427 + ret = ip_nat_helper_register(&talk_helpers[0]);
8432 + if (ntalk > 0 || ntalk2 > 0) {
8433 + ret = ip_nat_helper_register(&talk_helpers[1]);
8435 + if (ret != 0 && talk > 0)
8436 + ip_nat_helper_unregister(&talk_helpers[0]);
8441 +static void __exit fini(void)
8444 + ip_nat_helper_unregister(&talk_helpers[0]);
8445 + if (ntalk > 0 || ntalk2 > 0)
8446 + ip_nat_helper_unregister(&talk_helpers[1]);
8451 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
8452 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-04-29 11:24:39.000000000 +0200
8453 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c 2004-04-29 11:17:15.000000000 +0200
8456 #include <linux/netfilter_ipv4/ip_tables.h>
8458 +static const char *hooknames[] = {
8459 + [NF_IP_PRE_ROUTING] "PREROUTING",
8460 + [NF_IP_LOCAL_IN] "INPUT",
8461 + [NF_IP_FORWARD] "FORWARD",
8462 + [NF_IP_LOCAL_OUT] "OUTPUT",
8463 + [NF_IP_POST_ROUTING] "POSTROUTING",
8466 MODULE_LICENSE("GPL");
8467 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8468 MODULE_DESCRIPTION("IPv4 packet filter");
8469 @@ -326,6 +334,12 @@
8471 t = ipt_get_target(e);
8472 IP_NF_ASSERT(t->u.kernel.target);
8474 + /* The packet traced and the rule isn't an unconditional return/END. */
8475 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
8476 + nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8477 + table->name, e->chainname, e->rulenum);
8479 /* Standard target? */
8480 if (!t->u.kernel.target->target) {
8483 /* set back pointer to next entry */
8487 e = get_entry(table_base, v);
8489 /* Targets which reenter must return
8490 @@ -478,6 +491,29 @@
8491 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8495 +find_error_target(struct ipt_entry *s,
8496 + struct ipt_entry *e,
8499 + struct ipt_entry_target *t;
8500 + static struct ipt_entry *found = NULL;
8505 + t = ipt_get_target(found);
8506 + if (strcmp(t->u.user.name,
8507 + IPT_ERROR_TARGET) == 0) {
8508 + *chainname = t->data;
8517 /* All zeroes == unconditional rule. */
8519 unconditional(const struct ipt_ip *ip)
8521 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8524 + char *chainname = NULL;
8525 + u_int32_t rulenum;
8527 /* No recursion; use packet counter to save back ptrs (reset
8528 to 0 as we leave), and comefrom to save source hook bitmask */
8531 /* Set initial back pointer. */
8532 e->counters.pcnt = pos;
8534 + chainname = (char *) hooknames[hook];
8537 struct ipt_standard_target *t
8541 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8542 + e->rulenum = rulenum++;
8543 + e->chainname = chainname;
8545 /* Unconditional return/END. */
8546 if (e->target_offset == sizeof(struct ipt_entry)
8547 @@ -531,6 +573,10 @@
8548 && unconditional(&e->ip)) {
8549 unsigned int oldpos, size;
8551 + /* Set unconditional rulenum to zero. */
8553 + e->counters.bcnt = 0;
8555 /* Return: backtrack through the last
8558 @@ -556,6 +602,11 @@
8559 (newinfo->entries + pos);
8560 } while (oldpos == pos + e->next_offset);
8562 + /* Restore chainname, rulenum. */
8563 + chainname = e->chainname;
8564 + rulenum = e->counters.bcnt;
8565 + e->counters.bcnt = 0;
8567 /* Move along one */
8568 size = e->next_offset;
8569 e = (struct ipt_entry *)
8570 @@ -571,6 +622,17 @@
8571 /* This a jump; chase it. */
8572 duprintf("Jump rule %u -> %u\n",
8574 + e->counters.bcnt = rulenum++;
8576 + e = (struct ipt_entry *)
8577 + (newinfo->entries + newpos);
8578 + if (IPT_ENTRY_ITERATE(newinfo->entries,
8580 + find_error_target,
8581 + e, &chainname) == 0) {
8582 + printk("ip_tables: table screwed up!\n");
8586 /* ... this is a fallthru */
8587 newpos = pos + e->next_offset;
8588 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
8589 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
8590 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-29 11:10:59.000000000 +0200
8592 +/* This kernel module is used to modify the connection mark values, or
8593 + * to optionally restore the skb nfmark from the connection mark
8595 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8596 + * by Henrik Nordstrom <hno@marasystems.com>
8598 + * This program is free software; you can redistribute it and/or modify
8599 + * it under the terms of the GNU General Public License as published by
8600 + * the Free Software Foundation; either version 2 of the License, or
8601 + * (at your option) any later version.
8603 + * This program is distributed in the hope that it will be useful,
8604 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8605 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8606 + * GNU General Public License for more details.
8608 + * You should have received a copy of the GNU General Public License
8609 + * along with this program; if not, write to the Free Software
8610 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8612 +#include <linux/module.h>
8613 +#include <linux/skbuff.h>
8614 +#include <linux/ip.h>
8615 +#include <net/checksum.h>
8617 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8618 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8619 +MODULE_LICENSE("GPL");
8621 +#include <linux/netfilter_ipv4/ip_tables.h>
8622 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8623 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8625 +static unsigned int
8626 +target(struct sk_buff **pskb,
8627 + const struct net_device *in,
8628 + const struct net_device *out,
8629 + unsigned int hooknum,
8630 + const void *targinfo,
8633 + const struct ipt_connmark_target_info *markinfo = targinfo;
8634 + unsigned long diff;
8635 + unsigned long nfmark;
8636 + unsigned long newmark;
8638 + enum ip_conntrack_info ctinfo;
8639 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8641 + switch(markinfo->mode) {
8642 + case IPT_CONNMARK_SET:
8643 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8644 + if (newmark != ct->mark)
8645 + ct->mark = newmark;
8647 + case IPT_CONNMARK_SAVE:
8648 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8649 + if (ct->mark != newmark)
8650 + ct->mark = newmark;
8652 + case IPT_CONNMARK_RESTORE:
8653 + nfmark = (*pskb)->nfmark;
8654 + diff = (ct->mark ^ nfmark & markinfo->mask);
8656 + (*pskb)->nfmark = nfmark ^ diff;
8657 + (*pskb)->nfcache |= NFC_ALTERED;
8663 + return IPT_CONTINUE;
8667 +checkentry(const char *tablename,
8668 + const struct ipt_entry *e,
8670 + unsigned int targinfosize,
8671 + unsigned int hook_mask)
8673 + struct ipt_connmark_target_info *matchinfo = targinfo;
8674 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8675 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8677 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8681 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8682 + if (strcmp(tablename, "mangle") != 0) {
8683 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8691 +static struct ipt_target ipt_connmark_reg = {
8692 + .name = "CONNMARK",
8693 + .target = &target,
8694 + .checkentry = &checkentry,
8698 +static int __init init(void)
8700 + return ipt_register_target(&ipt_connmark_reg);
8703 +static void __exit fini(void)
8705 + ipt_unregister_target(&ipt_connmark_reg);
8710 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c
8711 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8712 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-29 11:17:03.000000000 +0200
8714 +/* This is a module which is used for setting the NFMARK field of an skb. */
8715 +#include <linux/module.h>
8716 +#include <linux/skbuff.h>
8717 +#include <linux/ip.h>
8718 +#include <net/checksum.h>
8720 +#include <linux/netfilter_ipv4/ip_tables.h>
8721 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8723 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8724 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8725 +MODULE_LICENSE("GPL");
8727 +static unsigned int
8728 +target(struct sk_buff **pskb,
8729 + const struct net_device *in,
8730 + const struct net_device *out,
8731 + unsigned int hooknum,
8732 + const void *targinfo,
8735 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8736 + struct iphdr *iph = (*pskb)->nh.iph;
8737 + unsigned long mark;
8739 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8740 + mark = (unsigned long) ntohl(iph->saddr);
8742 + mark = (unsigned long) ntohl(iph->daddr);
8744 + mark &= ipmarkinfo->andmask;
8745 + mark |= ipmarkinfo->ormask;
8747 + if ((*pskb)->nfmark != mark) {
8748 + (*pskb)->nfmark = mark;
8749 + (*pskb)->nfcache |= NFC_ALTERED;
8751 + return IPT_CONTINUE;
8755 +checkentry(const char *tablename,
8756 + const struct ipt_entry *e,
8758 + unsigned int targinfosize,
8759 + unsigned int hook_mask)
8761 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8762 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8764 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8768 + if (strcmp(tablename, "mangle") != 0) {
8769 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8776 +static struct ipt_target ipt_ipmark_reg = {
8779 + .checkentry = checkentry,
8783 +static int __init init(void)
8785 + return ipt_register_target(&ipt_ipmark_reg);
8788 +static void __exit fini(void)
8790 + ipt_unregister_target(&ipt_ipmark_reg);
8795 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c
8796 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
8797 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-29 11:17:08.000000000 +0200
8800 + * Kernel module to capture and hold incoming TCP connections using
8801 + * no local per-connection resources.
8803 + * Based on ipt_REJECT.c and offering functionality similar to
8804 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
8806 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
8808 + * This program is free software; you can redistribute it and/or modify
8809 + * it under the terms of the GNU General Public License as published by
8810 + * the Free Software Foundation; either version 2 of the License, or
8811 + * (at your option) any later version.
8813 + * This program is distributed in the hope that it will be useful,
8814 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8815 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8816 + * GNU General Public License for more details.
8818 + * You should have received a copy of the GNU General Public License
8819 + * along with this program; if not, write to the Free Software
8820 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8823 + * - Allow incoming TCP connections to be established.
8824 + * - Passing data should result in the connection being switched to the
8825 + * persist state (0 byte window), in which the remote side stops sending
8826 + * data and asks to continue every 60 seconds.
8827 + * - Attempts to shut down the connection should be ignored completely, so
8828 + * the remote side ends up having to time it out.
8831 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
8832 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
8833 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
8836 +#include <linux/config.h>
8837 +#include <linux/module.h>
8838 +#include <linux/skbuff.h>
8839 +#include <linux/ip.h>
8840 +#include <net/ip.h>
8841 +#include <net/tcp.h>
8842 +#include <net/icmp.h>
8844 +#include <net/route.h>
8845 +#include <linux/random.h>
8846 +#include <linux/netfilter_ipv4/ip_tables.h>
8849 +#define DEBUGP printk
8851 +#define DEBUGP(format, args...)
8854 +MODULE_LICENSE("GPL");
8855 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
8857 +/* Stolen from ip_finish_output2 */
8858 +static int ip_direct_send(struct sk_buff *skb)
8860 + struct dst_entry *dst = skb->dst;
8861 + struct hh_cache *hh = dst->hh;
8864 + read_lock_bh(&hh->hh_lock);
8865 + memcpy(skb->data - 16, hh->hh_data, 16);
8866 + read_unlock_bh(&hh->hh_lock);
8867 + skb_push(skb, hh->hh_len);
8868 + return hh->hh_output(skb);
8869 + } else if (dst->neighbour)
8870 + return dst->neighbour->output(skb);
8872 + if (net_ratelimit())
8873 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
8880 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
8882 + struct sk_buff *nskb;
8883 + struct rtable *nrt;
8884 + struct tcphdr *otcph, *ntcph;
8885 + unsigned int otcplen;
8887 + struct flowi fl = {};
8889 + /* A truncated TCP header isn't going to be useful */
8890 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
8893 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
8894 + + oskb->nh.iph->ihl);
8895 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
8897 + /* No replies for RST or FIN */
8898 + if (otcph->rst || otcph->fin)
8901 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
8902 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
8905 + /* Check checksum. */
8906 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
8907 + oskb->nh.iph->daddr,
8908 + csum_partial((char *)otcph, otcplen, 0)) != 0)
8911 + /* Copy skb (even if skb is about to be dropped, we can't just
8912 + clone it because there may be other things, such as tcpdump,
8913 + interested in it) */
8914 + nskb = skb_copy(oskb, GFP_ATOMIC);
8918 + /* This packet will not be the same as the other: clear nf fields */
8919 + nf_conntrack_put(nskb->nfct);
8920 + nskb->nfct = NULL;
8921 + nskb->nfcache = 0;
8922 +#ifdef CONFIG_NETFILTER_DEBUG
8923 + nskb->nf_debug = 0;
8926 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
8928 + /* Truncate to length (no data) */
8929 + ntcph->doff = sizeof(struct tcphdr)/4;
8930 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
8931 + nskb->nh.iph->tot_len = htons(nskb->len);
8933 + /* Swap source and dest */
8934 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
8935 + tmp = ntcph->source;
8936 + ntcph->source = ntcph->dest;
8937 + ntcph->dest = tmp;
8939 + /* Use supplied sequence number or make a new one */
8940 + ntcph->seq = otcph->ack ? otcph->ack_seq
8941 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
8942 + nskb->nh.iph->daddr,
8946 + /* Our SYN-ACKs must have a >0 window */
8947 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
8949 + ntcph->urg_ptr = 0;
8952 + ((u_int8_t *)ntcph)[13] = 0;
8954 + if (otcph->syn && otcph->ack) {
8956 + ntcph->ack_seq = 0;
8958 + ntcph->syn = otcph->syn;
8960 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
8963 + /* Adjust TCP checksum */
8965 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
8966 + nskb->nh.iph->saddr,
8967 + nskb->nh.iph->daddr,
8968 + csum_partial((char *)ntcph,
8969 + sizeof(struct tcphdr), 0));
8971 + /* Adjust IP TTL */
8972 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
8974 + /* Set DF, id = 0 */
8975 + nskb->nh.iph->frag_off = htons(IP_DF);
8976 + nskb->nh.iph->id = 0;
8978 + /* Adjust IP checksum */
8979 + nskb->nh.iph->check = 0;
8980 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
8981 + nskb->nh.iph->ihl);
8983 + fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
8984 + fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
8985 + fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
8987 + if (ip_route_output_key(&nrt, &fl) != 0)
8990 + dst_release(nskb->dst);
8991 + nskb->dst = &nrt->u.dst;
8993 + /* "Never happens" */
8994 + if (nskb->len > dst_pmtu(nskb->dst))
8997 + ip_direct_send (nskb);
9006 +static unsigned int tarpit(struct sk_buff **pskb,
9007 + const struct net_device *in,
9008 + const struct net_device *out,
9009 + unsigned int hooknum,
9010 + const void *targinfo,
9013 + struct sk_buff *skb = *pskb;
9014 + struct rtable *rt = (struct rtable*)skb->dst;
9016 + /* Do we have an input route cache entry? */
9020 + /* No replies to physical multicast/broadcast */
9021 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
9024 + /* Now check at the protocol level */
9025 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
9028 + /* Our naive response construction doesn't deal with IP
9029 + options, and probably shouldn't try. */
9030 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
9033 + /* We aren't interested in fragments */
9034 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
9037 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
9043 +static int check(const char *tablename,
9044 + const struct ipt_entry *e,
9046 + unsigned int targinfosize,
9047 + unsigned int hook_mask)
9049 + /* Only allow these for input/forward packet filtering. */
9050 + if (strcmp(tablename, "filter") != 0) {
9051 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
9054 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
9055 + | (1 << NF_IP_FORWARD))) != 0) {
9056 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
9060 + /* Must specify that it's a TCP packet */
9061 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
9062 + DEBUGP("TARPIT: not valid for non-tcp\n");
9069 +static struct ipt_target ipt_tarpit_reg = {
9072 + .checkentry = check,
9076 +static int __init init(void)
9078 + return ipt_register_target(&ipt_tarpit_reg);
9081 +static void __exit fini(void)
9083 + ipt_unregister_target(&ipt_tarpit_reg);
9088 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c
9089 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
9090 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c 2004-04-29 11:17:15.000000000 +0200
9092 +/* This is a module which is used for setting
9093 + * the NFC_TRACE flag in the nfcache field of an skb.
9095 +#include <linux/module.h>
9096 +#include <linux/skbuff.h>
9098 +#include <linux/netfilter_ipv4/ip_tables.h>
9100 +static unsigned int
9101 +target(struct sk_buff **pskb,
9102 + const struct net_device *in,
9103 + const struct net_device *out,
9104 + unsigned int hooknum,
9105 + const void *targinfo,
9108 + (*pskb)->nfcache |= NFC_TRACE;
9109 + return IPT_CONTINUE;
9113 +checkentry(const char *tablename,
9114 + const struct ipt_entry *e,
9116 + unsigned int targinfosize,
9117 + unsigned int hook_mask)
9119 + if (targinfosize != 0) {
9120 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
9125 + if (strcmp(tablename, "raw") != 0) {
9126 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
9133 +static struct ipt_target ipt_trace_reg = {
9136 + .checkentry = checkentry,
9140 +static int __init init(void)
9142 + if (ipt_register_target(&ipt_trace_reg))
9148 +static void __exit fini(void)
9150 + ipt_unregister_target(&ipt_trace_reg);
9155 +MODULE_LICENSE("GPL");
9156 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c
9157 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
9158 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-04-29 11:17:18.000000000 +0200
9160 +/* XOR target for IP tables
9161 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9162 + * Based on ipt_TTL.c
9166 + * This software is distributed under the terms of GNU GPL
9169 +#include <linux/module.h>
9170 +#include <linux/skbuff.h>
9171 +#include <linux/ip.h>
9172 +#include <linux/tcp.h>
9173 +#include <linux/udp.h>
9175 +#include <linux/netfilter_ipv4/ip_tables.h>
9176 +#include <linux/netfilter_ipv4/ipt_XOR.h>
9178 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9179 +MODULE_DESCRIPTION("IP tables XOR module");
9180 +MODULE_LICENSE("GPL");
9182 +static unsigned int
9183 +ipt_xor_target(struct sk_buff **pskb,
9184 + const struct net_device *in, const struct net_device *out,
9185 + unsigned int hooknum, const void *targinfo, void *userinfo)
9187 + struct ipt_XOR_info *info = (void *) targinfo;
9188 + struct iphdr *iph;
9189 + struct tcphdr *tcph;
9190 + struct udphdr *udph;
9193 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
9196 + iph = (*pskb)->nh.iph;
9198 + if (iph->protocol == IPPROTO_TCP) {
9199 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9200 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9201 + for (k=0; k<=info->block_size; k++) {
9202 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
9207 + if (info->key[j] == 0x00)
9210 + } else if (iph->protocol == IPPROTO_UDP) {
9211 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9212 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9213 + for (k=0; k<=info->block_size; k++) {
9214 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
9219 + if (info->key[j] == 0x00)
9224 + return IPT_CONTINUE;
9227 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9228 + void *targinfo, unsigned int targinfosize,
9229 + unsigned int hook_mask)
9231 + struct ipt_XOR_info *info = targinfo;
9233 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9234 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
9235 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9239 + if (strcmp(tablename, "mangle")) {
9240 + printk(KERN_WARNING "XOR: can only be called from"
9241 + "\"mangle\" table, not \"%s\"\n", tablename);
9245 + if (!strcmp(info->key, "")) {
9246 + printk(KERN_WARNING "XOR: You must specify a key");
9250 + if (info->block_size == 0) {
9251 + printk(KERN_WARNING "XOR: You must specify a block-size");
9258 +static struct ipt_target ipt_XOR = {
9260 + .target = ipt_xor_target,
9261 + .checkentry = ipt_xor_checkentry,
9262 + .me = THIS_MODULE,
9265 +static int __init init(void)
9267 + return ipt_register_target(&ipt_XOR);
9270 +static void __exit fini(void)
9272 + ipt_unregister_target(&ipt_XOR);
9277 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c
9278 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
9279 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-04-29 11:17:23.000000000 +0200
9282 + * iptables module to match inet_addr_type() of an ip.
9285 +#include <linux/module.h>
9286 +#include <linux/skbuff.h>
9287 +#include <linux/netdevice.h>
9288 +#include <net/route.h>
9290 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
9291 +#include <linux/netfilter_ipv4/ip_tables.h>
9293 +MODULE_LICENSE("GPL");
9295 +static inline int match_type(u_int32_t addr, u_int16_t mask)
9297 + return !!(mask & (1 << inet_addr_type(addr)));
9300 +static int match(const struct sk_buff *skb, const struct net_device *in,
9301 + const struct net_device *out, const void *matchinfo,
9302 + int offset, int *hotdrop)
9304 + const struct ipt_addrtype_info *info = matchinfo;
9305 + const struct iphdr *iph = skb->nh.iph;
9309 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
9311 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9316 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9317 + void *matchinfo, unsigned int matchsize,
9318 + unsigned int hook_mask)
9320 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9321 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9322 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9329 +static struct ipt_match addrtype_match = {
9330 + .name = "addrtype",
9332 + .checkentry = checkentry,
9336 +static int __init init(void)
9338 + return ipt_register_match(&addrtype_match);
9341 +static void __exit fini(void)
9343 + ipt_unregister_match(&addrtype_match);
9349 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c
9350 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
9351 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-04-29 11:10:59.000000000 +0200
9353 +/* This kernel module matches connection mark values set by the
9356 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9357 + * by Henrik Nordstrom <hno@marasystems.com>
9359 + * This program is free software; you can redistribute it and/or modify
9360 + * it under the terms of the GNU General Public License as published by
9361 + * the Free Software Foundation; either version 2 of the License, or
9362 + * (at your option) any later version.
9364 + * This program is distributed in the hope that it will be useful,
9365 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9366 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9367 + * GNU General Public License for more details.
9369 + * You should have received a copy of the GNU General Public License
9370 + * along with this program; if not, write to the Free Software
9371 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9374 +#include <linux/module.h>
9375 +#include <linux/skbuff.h>
9377 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9378 +MODULE_DESCRIPTION("IP tables connmark match module");
9379 +MODULE_LICENSE("GPL");
9381 +#include <linux/netfilter_ipv4/ip_tables.h>
9382 +#include <linux/netfilter_ipv4/ipt_connmark.h>
9383 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9386 +match(const struct sk_buff *skb,
9387 + const struct net_device *in,
9388 + const struct net_device *out,
9389 + const void *matchinfo,
9393 + const struct ipt_connmark_info *info = matchinfo;
9394 + enum ip_conntrack_info ctinfo;
9395 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9399 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
9403 +checkentry(const char *tablename,
9404 + const struct ipt_ip *ip,
9406 + unsigned int matchsize,
9407 + unsigned int hook_mask)
9409 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
9415 +static struct ipt_match connmark_match = {
9416 + .name = "connmark",
9418 + .checkentry = &checkentry,
9422 +static int __init init(void)
9424 + return ipt_register_match(&connmark_match);
9427 +static void __exit fini(void)
9429 + ipt_unregister_match(&connmark_match);
9434 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c
9435 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:24:39.000000000 +0200
9436 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:18:37.000000000 +0200
9438 DEBUGP("master's name = %s , info->name = %s\n",
9439 exp->expectant->helper->name, info->name);
9441 - ret ^= !strncmp(exp->expectant->helper->name, info->name,
9442 - strlen(exp->expectant->helper->name));
9443 + if (info->name[0] == '\0')
9446 + ret ^= !strncmp(exp->expectant->helper->name, info->name,
9447 + strlen(exp->expectant->helper->name));
9449 READ_UNLOCK(&ip_conntrack_lock);
9452 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
9455 - /* verify that we actually should match anything */
9456 - if ( strlen(info->name) == 0 )
9462 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c
9463 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c 2004-04-28 03:36:37.000000000 +0200
9464 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c 2004-04-29 11:19:32.000000000 +0200
9466 * This program is free software; you can redistribute it and/or modify
9467 * it under the terms of the GNU General Public License version 2 as
9468 * published by the Free Software Foundation.
9470 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
9473 #include <linux/module.h>
9474 #include <linux/skbuff.h>
9475 #include <linux/file.h>
9476 +#include <linux/ip.h>
9477 +#include <linux/tcp.h>
9478 +#include <linux/udp.h>
9479 #include <net/sock.h>
9480 +#include <net/tcp.h>
9481 +#include <net/udp.h>
9483 #include <linux/netfilter_ipv4/ipt_owner.h>
9484 #include <linux/netfilter_ipv4/ip_tables.h>
9486 MODULE_DESCRIPTION("iptables owner match");
9489 -match_comm(const struct sk_buff *skb, const char *comm)
9490 +match_comm(const struct sock *sk, const char *comm)
9492 struct task_struct *g, *p;
9493 struct files_struct *files;
9495 spin_lock(&files->file_lock);
9496 for (i=0; i < files->max_fds; i++) {
9497 if (fcheck_files(files, i) ==
9498 - skb->sk->sk_socket->file) {
9499 + sk->sk_socket->file) {
9500 spin_unlock(&files->file_lock);
9502 read_unlock(&tasklist_lock);
9507 -match_pid(const struct sk_buff *skb, pid_t pid)
9508 +match_pid(const struct sock *sk, pid_t pid)
9510 struct task_struct *p;
9511 struct files_struct *files;
9513 spin_lock(&files->file_lock);
9514 for (i=0; i < files->max_fds; i++) {
9515 if (fcheck_files(files, i) ==
9516 - skb->sk->sk_socket->file) {
9517 + sk->sk_socket->file) {
9518 spin_unlock(&files->file_lock);
9520 read_unlock(&tasklist_lock);
9525 -match_sid(const struct sk_buff *skb, pid_t sid)
9526 +match_sid(const struct sock *sk, pid_t sid)
9528 struct task_struct *g, *p;
9529 - struct file *file = skb->sk->sk_socket->file;
9530 + struct file *file = sk->sk_socket->file;
9533 read_lock(&tasklist_lock);
9534 @@ -129,41 +136,71 @@
9537 const struct ipt_owner_info *info = matchinfo;
9538 + struct iphdr *iph = skb->nh.iph;
9539 + struct sock *sk = NULL;
9545 + if (iph->protocol == IPPROTO_TCP) {
9546 + struct tcphdr *tcph =
9547 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
9548 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
9549 + iph->daddr, tcph->dest,
9550 + skb->dev->ifindex);
9551 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
9552 + tcp_tw_put((struct tcp_tw_bucket *)sk);
9555 + } else if (iph->protocol == IPPROTO_UDP) {
9556 + struct udphdr *udph =
9557 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
9558 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
9559 + udph->dest, skb->dev->ifindex);
9563 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
9565 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
9568 if(info->match & IPT_OWNER_UID) {
9569 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
9570 + if ((sk->sk_socket->file->f_uid != info->uid) ^
9571 !!(info->invert & IPT_OWNER_UID))
9576 if(info->match & IPT_OWNER_GID) {
9577 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
9578 + if ((sk->sk_socket->file->f_gid != info->gid) ^
9579 !!(info->invert & IPT_OWNER_GID))
9584 if(info->match & IPT_OWNER_PID) {
9585 - if (!match_pid(skb, info->pid) ^
9586 + if (!match_pid(sk, info->pid) ^
9587 !!(info->invert & IPT_OWNER_PID))
9592 if(info->match & IPT_OWNER_SID) {
9593 - if (!match_sid(skb, info->sid) ^
9594 + if (!match_sid(sk, info->sid) ^
9595 !!(info->invert & IPT_OWNER_SID))
9600 if(info->match & IPT_OWNER_COMM) {
9601 - if (!match_comm(skb, info->comm) ^
9602 + if (!match_comm(sk, info->comm) ^
9603 !!(info->invert & IPT_OWNER_COMM))
9619 @@ -173,11 +210,19 @@
9620 unsigned int matchsize,
9621 unsigned int hook_mask)
9624 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
9625 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
9629 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
9630 + (1 << NF_IP_LOCAL_IN))) {
9631 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
9632 + "or POST_ROUTING.\n");
9636 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
9637 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
9638 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
9642 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
9643 printk("Matchsize %u != %Zu\n", matchsize,
9644 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c
9645 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
9646 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c 2004-04-29 11:19:41.000000000 +0200
9648 +/* IP tables module for matching IPsec policy
9650 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
9652 + * This program is free software; you can redistribute it and/or modify
9653 + * it under the terms of the GNU General Public License version 2 as
9654 + * published by the Free Software Foundation.
9657 +#include <linux/kernel.h>
9658 +#include <linux/config.h>
9659 +#include <linux/module.h>
9660 +#include <linux/skbuff.h>
9661 +#include <linux/init.h>
9662 +#include <net/xfrm.h>
9664 +#include <linux/netfilter_ipv4.h>
9665 +#include <linux/netfilter_ipv4/ipt_policy.h>
9666 +#include <linux/netfilter_ipv4/ip_tables.h>
9668 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
9669 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
9670 +MODULE_LICENSE("GPL");
9674 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
9676 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
9678 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
9679 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
9680 + MISMATCH(proto, x->id.proto) ||
9681 + MISMATCH(mode, x->props.mode) ||
9682 + MISMATCH(spi, x->id.spi) ||
9683 + MISMATCH(reqid, x->props.reqid))
9689 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
9691 + const struct ipt_policy_elem *e;
9692 + struct sec_path *sp = skb->sp;
9693 + int strict = info->flags & POLICY_MATCH_STRICT;
9698 + if (strict && info->len != sp->len)
9701 + for (i = sp->len - 1; i >= 0; i--) {
9702 + pos = strict ? i - sp->len + 1 : 0;
9703 + if (pos >= info->len)
9705 + e = &info->pol[pos];
9707 + if (match_xfrm_state(sp->x[i].xvec, e)) {
9710 + } else if (strict)
9714 + return strict ? 1 : 0;
9718 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
9720 + const struct ipt_policy_elem *e;
9721 + struct dst_entry *dst = skb->dst;
9722 + int strict = info->flags & POLICY_MATCH_STRICT;
9725 + if (dst->xfrm == NULL)
9728 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
9729 + pos = strict ? i : 0;
9730 + if (pos >= info->len)
9732 + e = &info->pol[pos];
9734 + if (match_xfrm_state(dst->xfrm, e)) {
9737 + } else if (strict)
9741 + return strict ? 1 : 0;
9744 +static int match(const struct sk_buff *skb,
9745 + const struct net_device *in,
9746 + const struct net_device *out,
9747 + const void *matchinfo, int offset, int *hotdrop)
9749 + const struct ipt_policy_info *info = matchinfo;
9752 + if (info->flags & POLICY_MATCH_IN)
9753 + ret = match_policy_in(skb, info);
9755 + ret = match_policy_out(skb, info);
9758 + if (info->flags & POLICY_MATCH_NONE)
9762 + } else if (info->flags & POLICY_MATCH_NONE)
9768 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9769 + void *matchinfo, unsigned int matchsize,
9770 + unsigned int hook_mask)
9772 + struct ipt_policy_info *info = matchinfo;
9774 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
9775 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
9776 + matchsize, IPT_ALIGN(sizeof(*info)));
9779 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
9780 + printk(KERN_ERR "ipt_policy: neither incoming nor "
9781 + "outgoing policy selected\n");
9784 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
9785 + && info->flags & POLICY_MATCH_OUT) {
9786 + printk(KERN_ERR "ipt_policy: output policy not valid in "
9787 + "PRE_ROUTING and INPUT\n");
9790 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
9791 + && info->flags & POLICY_MATCH_IN) {
9792 + printk(KERN_ERR "ipt_policy: input policy not valid in "
9793 + "POST_ROUTING and OUTPUT\n");
9796 + if (info->len > POLICY_MAX_ELEM) {
9797 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
9804 +static struct ipt_match policy_match =
9808 + .checkentry = checkentry,
9809 + .me = THIS_MODULE,
9812 +static int __init init(void)
9814 + return ipt_register_match(&policy_match);
9817 +static void __exit fini(void)
9819 + ipt_unregister_match(&policy_match);
9824 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c
9825 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
9826 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c 2004-04-29 11:20:02.000000000 +0200
9828 +/* RPC extension for IP connection matching, Version 2.2
9829 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
9830 + * - original rpc tracking module
9831 + * - "recent" connection handling for kernel 2.3+ netfilter
9833 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
9834 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
9836 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
9837 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
9838 + * - extended matching to support filtering on procedures
9840 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
9842 + * This program is free software; you can redistribute it and/or
9843 + * modify it under the terms of the GNU General Public License
9844 + * as published by the Free Software Foundation; either version
9845 + * 2 of the License, or (at your option) any later version.
9847 + * Module load syntax:
9848 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
9850 + * Please give the ports of all RPC servers you wish to connect to.
9851 + * If you don't specify ports, the default will be port 111.
9855 + * RPCs should not be exposed to the internet - ask the Pentagon;
9857 + * "The unidentified crackers pleaded guilty in July to charges
9858 + * of juvenile delinquency stemming from a string of Pentagon
9859 + * network intrusions in February.
9861 + * The youths, going by the names TooShort and Makaveli, used
9862 + * a common server security hole to break in, according to
9863 + * Dane Jasper, owner of the California Internet service
9864 + * provider, Sonic. They used the hole, known as the 'statd'
9865 + * exploit, to attempt more than 800 break-ins, Jasper said."
9867 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
9868 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
9872 +#include <linux/module.h>
9873 +#include <linux/skbuff.h>
9874 +#include <linux/list.h>
9875 +#include <linux/udp.h>
9876 +#include <linux/tcp.h>
9877 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9878 +#include <linux/netfilter_ipv4/ip_tables.h>
9879 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
9880 +#include <linux/netfilter_ipv4/lockhelp.h>
9881 +#include <linux/netfilter_ipv4/ipt_rpc.h>
9883 +#define MAX_PORTS 8
9884 +static int ports[MAX_PORTS];
9885 +static int ports_n_c = 0;
9888 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9889 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
9892 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
9893 +MODULE_DESCRIPTION("RPC connection matching module");
9894 +MODULE_LICENSE("GPL");
9897 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
9900 +#define DEBUGP(format, args...)
9905 +/* vars from ip_conntrack_rpc_tcp */
9906 +extern struct list_head request_p_list_tcp;
9907 +extern struct module *ip_conntrack_rpc_tcp;
9909 +/* vars from ip_conntrack_rpc_udp */
9910 +extern struct list_head request_p_list_udp;
9911 +extern struct module *ip_conntrack_rpc_udp;
9913 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
9914 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
9916 +#define ASSERT_READ_LOCK(x) \
9918 + if (x == &request_p_list_udp) \
9919 + MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
9920 + else if (x == &request_p_list_tcp) \
9921 + MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
9924 +#define ASSERT_WRITE_LOCK(x) \
9926 + if (x == &request_p_list_udp) \
9927 + MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
9928 + else if (x == &request_p_list_tcp) \
9929 + MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
9932 +#include <linux/netfilter_ipv4/listhelp.h>
9934 +const int IPT_RPC_CHAR_LEN = 11;
9937 +static int k_atoi(char *string)
9939 + unsigned int result = 0;
9940 + int maxoctet = IPT_RPC_CHAR_LEN;
9942 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
9947 + if (*string < 48 || *string > 57) {
9950 + result = result * 10 + ( *string - 48 );
9956 +static int match_rpcs(char *c_procs, int i_procs, int proc)
9960 + unsigned int proc_num;
9962 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
9964 + if (i_procs == -1)
9967 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
9969 + proc_ptr = c_procs;
9970 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
9971 + proc_num = k_atoi(proc_ptr);
9973 + if (proc_num == proc)
9981 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
9982 + int *hotdrop, int dir, struct ip_conntrack *ct,
9983 + int offset, struct list_head request_p_list)
9985 + const struct ipt_rpc_info *rpcinfo = matchinfo;
9986 + struct request_p *req_p;
9993 + /* This does sanity checking on RPC payloads,
9994 + * and permits only the RPC "get port" (3)
9995 + * in authorised procedures in client
9996 + * communications with the portmapper.
10001 + /* Get RPC requestor */
10002 + if (IXDR_GET_INT32(data) != 3) {
10003 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
10004 + if(rpcinfo->strict == 1)
10008 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
10012 + /* Jump Credentials and Verfifier */
10013 + data = data + IXDR_GET_INT32(data) + 2;
10014 + data = data + IXDR_GET_INT32(data) + 2;
10016 + /* Get RPC procedure */
10017 + if (match_rpcs((char *)&rpcinfo->c_procs,
10018 + rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
10019 + DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
10020 + (unsigned int)IXDR_GET_INT32(data));
10022 + /* If the RPC conntrack half entry already exists .. */
10024 + switch (ct->tuplehash[0].tuple.dst.protonum) {
10025 + case IPPROTO_UDP:
10026 + WRITE_LOCK(&ipct_rpc_udp_lock);
10027 + case IPPROTO_TCP:
10028 + WRITE_LOCK(&ipct_rpc_tcp_lock);
10030 + req_p = LIST_FIND(&request_p_list, request_p_cmp,
10031 + struct request_p *, xid,
10032 + ct->tuplehash[dir].tuple.src.ip,
10033 + ct->tuplehash[dir].tuple.src.u.all);
10036 + DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10037 + xid, ct->tuplehash[dir].tuple.dst.protonum,
10038 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10039 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
10041 + /* .. remove it */
10042 + if (del_timer(&req_p->timeout))
10043 + req_p->timeout.expires = 0;
10045 + LIST_DELETE(&request_p_list, req_p);
10046 + DEBUGP("RPC req_p removed. [done]\n");
10049 + DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10050 + xid, ct->tuplehash[dir].tuple.dst.protonum,
10051 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10052 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
10055 + switch (ct->tuplehash[0].tuple.dst.protonum) {
10056 + case IPPROTO_UDP:
10057 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
10058 + case IPPROTO_TCP:
10059 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
10062 + if(rpcinfo->strict == 1)
10067 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
10068 + (unsigned int)IXDR_GET_INT32(data));
10069 + return (1 && (!offset));
10073 +static int match(const struct sk_buff *skb, const struct net_device *in,
10074 + const struct net_device *out, const void *matchinfo,
10075 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
10077 + struct ip_conntrack *ct;
10078 + enum ip_conntrack_info ctinfo;
10079 + const u_int32_t *data;
10080 + enum ip_conntrack_dir dir;
10081 + const struct tcphdr *tcp;
10082 + const struct ipt_rpc_info *rpcinfo = matchinfo;
10083 + int port, portsok;
10087 + DEBUGP("new packet to evaluate ..\n");
10089 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10091 + DEBUGP("no ct available [skip]\n");
10095 + DEBUGP("ct detected. [cont]\n");
10096 + dir = CTINFO2DIR(ctinfo);
10098 + /* we only want the client to server packets for matching */
10099 + if (dir != IP_CT_DIR_ORIGINAL)
10102 + /* This does sanity checking on UDP or TCP packets,
10103 + * like their respective modules.
10106 + switch (ct->tuplehash[0].tuple.dst.protonum) {
10108 + case IPPROTO_UDP:
10109 + DEBUGP("PROTO_UDP [cont]\n");
10110 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
10111 + DEBUGP("packet does not contain a complete header. [drop]\n");
10115 + for (port=0,portsok=0; port <= ports_n_c; port++) {
10116 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10121 + if (portsok == 0) {
10122 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10123 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10127 + if ((datalen - sizeof(struct udphdr)) != 56) {
10128 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
10129 + if (rpcinfo->strict == 1)
10133 + DEBUGP("packet length is correct. [cont]\n");
10135 + /* Get to the data */
10136 + data = (const u_int32_t *)hdr + 2;
10138 + /* Check the RPC data */
10139 + tval = check_rpc_packet(data, matchinfo, hotdrop,
10141 + request_p_list_udp);
10146 + case IPPROTO_TCP:
10147 + DEBUGP("PROTO_TCP [cont]\n");
10148 + if (offset == 0 && datalen < sizeof(struct tcphdr)) {
10149 + DEBUGP("packet does not contain a complete header. [drop]\n");
10153 + for (port=0,portsok=0; port <= ports_n_c; port++) {
10154 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10159 + if (portsok == 0) {
10160 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10161 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10166 + if (datalen == (tcp->doff * 4)) {
10167 + DEBUGP("packet does not contain any data. [match]\n");
10168 + return (1 && (!offset));
10171 + /* Tests if packet len is ok */
10172 + if ((datalen - (tcp->doff * 4)) != 60) {
10173 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
10174 + if(rpcinfo->strict == 1)
10178 + DEBUGP("packet length is correct. [cont]\n");
10180 + /* Get to the data */
10181 + data = (const u_int32_t *)tcp + tcp->doff + 1;
10183 + /* Check the RPC data */
10184 + tval = check_rpc_packet(data, matchinfo, hotdrop,
10186 + request_p_list_tcp);
10192 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
10193 + ct->tuplehash[0].tuple.dst.protonum);
10198 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
10199 + unsigned int matchsize, unsigned int hook_mask)
10202 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
10203 + | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
10204 + printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
10208 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
10215 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
10216 + &match, &checkentry, NULL,
10220 +static int __init init(void)
10224 + DEBUGP("incrementing usage counts\n");
10225 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
10226 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
10228 + /* If no port given, default to standard RPC port */
10229 + if (ports[0] == 0)
10230 + ports[0] = RPC_PORT;
10232 + DEBUGP("registering match [%s] for;\n", rpc_match.name);
10233 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
10234 + DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
10238 + return ipt_register_match(&rpc_match);
10242 +static void fini(void)
10244 + DEBUGP("unregistering match\n");
10245 + ipt_unregister_match(&rpc_match);
10247 + DEBUGP("decrementing usage counts\n");
10248 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
10249 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
10253 +module_init(init);
10254 +module_exit(fini);
10256 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c
10257 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
10258 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c 2004-04-29 11:21:38.000000000 +0200
10260 +/* Kernel module to match a string into a packet.
10262 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
10265 + * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
10266 + * Initial 2.6 port
10267 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
10268 + * Fixed SMP re-entrancy problem using per-cpu data areas
10269 + * for the skip/shift tables.
10270 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10271 + * Fixed kernel panic, due to overrunning boyer moore string
10272 + * tables. Also slightly tweaked heuristic for deciding what
10273 + * search algo to use.
10274 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10275 + * Implemented Boyer Moore Sublinear search algorithm
10276 + * alongside the existing linear search based on memcmp().
10277 + * Also a quick check to decide which method to use on a per
10281 +#include <linux/smp.h>
10282 +#include <linux/percpu.h>
10283 +#include <linux/module.h>
10284 +#include <linux/skbuff.h>
10285 +#include <linux/file.h>
10286 +#include <net/sock.h>
10288 +#include <linux/netfilter_ipv4/ip_tables.h>
10289 +#include <linux/netfilter_ipv4/ipt_string.h>
10291 +MODULE_LICENSE("GPL");
10293 +struct string_per_cpu {
10294 + int skip[BM_MAX_HLEN];
10295 + int shift[BM_MAX_HLEN];
10296 + int len[BM_MAX_HLEN];
10299 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
10302 +/* Boyer Moore Sublinear string search - VERY FAST */
10303 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
10305 + int M1, right_end, sk, sh;
10308 + int *skip, *shift, *len;
10310 + /* use data suitable for this CPU */
10311 + shift=__get_cpu_var(bm_string_data).shift;
10312 + skip=__get_cpu_var(bm_string_data).skip;
10313 + len=__get_cpu_var(bm_string_data).len;
10315 + /* Setup skip/shift tables */
10316 + M1 = right_end = needle_len-1;
10317 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
10318 + for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
10320 + for (i = 1; i < needle_len; i++) {
10321 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
10326 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
10327 + for (i = M1; i > 0; i--) shift[len[i]] = i;
10330 + for (i = 0; i < needle_len; i++) {
10331 + if (len[i] == M1 - i) ended = i;
10332 + if (ended) shift[i] = ended;
10335 + /* Do the search*/
10336 + while (right_end < haystack_len)
10338 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
10339 + if (i == needle_len) {
10340 + return haystack+(right_end - M1);
10343 + sk = skip[(int)haystack[right_end - i]];
10345 + right_end = max(right_end - i + sk, right_end + sh);
10351 +/* Linear string search based on memcmp() */
10352 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
10354 + char *k = haystack + (haystack_len-needle_len);
10355 + char *t = haystack;
10357 + while ( t <= k ) {
10358 + if (memcmp(t, needle, needle_len) == 0)
10367 +match(const struct sk_buff *skb,
10368 + const struct net_device *in,
10369 + const struct net_device *out,
10370 + const void *matchinfo,
10374 + const struct ipt_string_info *info = matchinfo;
10375 + struct iphdr *ip = skb->nh.iph;
10377 + char *needle, *haystack;
10378 + proc_ipt_search search=search_linear;
10380 + if ( !ip ) return 0;
10382 + /* get lenghts, and validate them */
10384 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
10385 + if ( nlen > hlen ) return 0;
10387 + needle=(char *)&info->string;
10388 + haystack=(char *)ip+(ip->ihl*4);
10390 + /* The sublinear search comes in to its own
10391 + * on the larger packets */
10392 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
10393 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
10394 + if ( hlen < BM_MAX_HLEN ) {
10395 + search=search_sublinear;
10397 + if (net_ratelimit())
10398 + printk(KERN_INFO "ipt_string: Packet too big "
10399 + "to attempt sublinear string search "
10400 + "(%d bytes)\n", hlen );
10404 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
10408 +checkentry(const char *tablename,
10409 + const struct ipt_ip *ip,
10411 + unsigned int matchsize,
10412 + unsigned int hook_mask)
10415 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
10421 +static struct ipt_match string_match = {
10422 + .name = "string",
10424 + .checkentry = &checkentry,
10425 + .me = THIS_MODULE
10429 +static int __init init(void)
10431 + return ipt_register_match(&string_match);
10434 +static void __exit fini(void)
10436 + ipt_unregister_match(&string_match);
10439 +module_init(init);
10440 +module_exit(fini);
10443 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c
10444 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
10445 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c 2004-04-29 11:21:33.000000000 +0200
10447 +/* Kernel module to match suspect packets. */
10448 +#include <linux/module.h>
10449 +#include <linux/skbuff.h>
10450 +#include <linux/ip.h>
10451 +#include <linux/udp.h>
10452 +#include <linux/tcp.h>
10453 +#include <linux/icmp.h>
10454 +#include <net/checksum.h>
10456 +#include <linux/netfilter_ipv4/ip_tables.h>
10458 +#define limpk(format, args...) \
10460 + if (net_ratelimit()) \
10461 + printk("ipt_unclean: %s" format, \
10462 + embedded ? "(embedded packet) " : "" , ## args); \
10465 +enum icmp_error_status
10467 + ICMP_MAY_BE_ERROR,
10474 + size_t min_len, max_len;
10475 + enum icmp_error_status err;
10476 + u_int8_t min_code, max_code;
10480 +check_ip(struct iphdr *iph, size_t length, int embedded);
10482 +/* ICMP-specific checks. */
10484 +check_icmp(const struct icmphdr *icmph,
10485 + u_int16_t datalen,
10486 + unsigned int offset,
10490 + static struct icmp_info info[]
10491 + = { [ICMP_ECHOREPLY]
10492 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10493 + [ICMP_DEST_UNREACH]
10494 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
10495 + [ICMP_SOURCE_QUENCH]
10496 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
10498 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
10500 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10501 + /* Router advertisement. */
10503 + = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
10504 + /* Router solicitation. */
10506 + = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
10507 + [ICMP_TIME_EXCEEDED]
10508 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10509 + [ICMP_PARAMETERPROB]
10510 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10512 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10513 + [ICMP_TIMESTAMPREPLY]
10514 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10515 + [ICMP_INFO_REQUEST]
10516 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10517 + [ICMP_INFO_REPLY]
10518 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10520 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
10521 + [ICMP_ADDRESSREPLY]
10522 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
10524 + /* Can't do anything if it's a fragment. */
10528 + /* Must cover type and code. */
10529 + if (datalen < 2) {
10530 + limpk("ICMP len=%u too short\n", datalen);
10534 + /* If not embedded. */
10536 + /* Bad checksum? Don't print, just ignore. */
10538 + && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
10541 + /* CHECK: Truncated ICMP (even if first fragment). */
10542 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10543 + && info[icmph->type].min_len != 0
10544 + && datalen < info[icmph->type].min_len) {
10545 + limpk("ICMP type %u len %u too short\n",
10546 + icmph->type, datalen);
10550 + /* CHECK: Check within known error ICMPs. */
10551 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10552 + && info[icmph->type].err == ICMP_IS_ERROR) {
10553 + /* CHECK: Embedded packet must be at least
10554 + length of iph + 8 bytes. */
10555 + struct iphdr *inner = (void *)icmph + 8;
10557 + /* datalen > 8 since all ICMP_IS_ERROR types
10558 + have min length > 8 */
10559 + if (datalen - 8 < sizeof(struct iphdr)) {
10560 + limpk("ICMP error internal way too short\n");
10563 + if (datalen - 8 < inner->ihl*4 + 8) {
10564 + limpk("ICMP error internal too short\n");
10567 + if (!check_ip(inner, datalen - 8, 1))
10571 + /* CHECK: Can't embed ICMP unless known non-error. */
10572 + if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
10573 + || info[icmph->type].err != ICMP_NOT_ERROR) {
10574 + limpk("ICMP type %u not embeddable\n",
10580 + /* CHECK: Invalid ICMP codes. */
10581 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10582 + && (icmph->code < info[icmph->type].min_code
10583 + || icmph->code > info[icmph->type].max_code)) {
10584 + limpk("ICMP type=%u code=%u\n",
10585 + icmph->type, icmph->code);
10589 + /* CHECK: Above maximum length. */
10590 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10591 + && info[icmph->type].max_len != 0
10592 + && datalen > info[icmph->type].max_len) {
10593 + limpk("ICMP type=%u too long: %u bytes\n",
10594 + icmph->type, datalen);
10598 + switch (icmph->type) {
10599 + case ICMP_PARAMETERPROB: {
10600 + /* CHECK: Problem param must be within error packet's
10602 + struct iphdr *iph = (void *)icmph + 8;
10603 + u_int32_t arg = ntohl(icmph->un.gateway);
10605 + if (icmph->code == 0) {
10606 + /* Code 0 means that upper 8 bits is pointer
10608 + if ((arg >> 24) >= iph->ihl*4) {
10609 + limpk("ICMP PARAMETERPROB ptr = %u\n",
10610 + ntohl(icmph->un.gateway) >> 24);
10613 + arg &= 0x00FFFFFF;
10616 + /* CHECK: Rest must be zero. */
10618 + limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
10625 + case ICMP_TIME_EXCEEDED:
10626 + case ICMP_SOURCE_QUENCH:
10627 + /* CHECK: Unused must be zero. */
10628 + if (icmph->un.gateway != 0) {
10629 + limpk("ICMP type=%u unused = %u\n",
10630 + icmph->type, ntohl(icmph->un.gateway));
10639 +/* UDP-specific checks. */
10641 +check_udp(const struct iphdr *iph,
10642 + const struct udphdr *udph,
10643 + u_int16_t datalen,
10644 + unsigned int offset,
10648 + /* Can't do anything if it's a fragment. */
10652 + /* CHECK: Must cover UDP header. */
10653 + if (datalen < sizeof(struct udphdr)) {
10654 + limpk("UDP len=%u too short\n", datalen);
10658 + /* Bad checksum? Don't print, just say it's unclean. */
10659 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
10660 + if (!more_frags && !embedded && udph->check
10661 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
10662 + csum_partial((char *)udph, datalen, 0)) != 0)
10665 + /* CHECK: Destination port can't be zero. */
10666 + if (!udph->dest) {
10667 + limpk("UDP zero destination port\n");
10671 + if (!more_frags) {
10673 + /* CHECK: UDP length must match. */
10674 + if (ntohs(udph->len) != datalen) {
10675 + limpk("UDP len too short %u vs %u\n",
10676 + ntohs(udph->len), datalen);
10680 + /* CHECK: UDP length be >= this truncated pkt. */
10681 + if (ntohs(udph->len) < datalen) {
10682 + limpk("UDP len too long %u vs %u\n",
10683 + ntohs(udph->len), datalen);
10688 + /* CHECK: UDP length must be > this frag's length. */
10689 + if (ntohs(udph->len) <= datalen) {
10690 + limpk("UDP fragment len too short %u vs %u\n",
10691 + ntohs(udph->len), datalen);
10699 +#define TH_FIN 0x01
10700 +#define TH_SYN 0x02
10701 +#define TH_RST 0x04
10702 +#define TH_PUSH 0x08
10703 +#define TH_ACK 0x10
10704 +#define TH_URG 0x20
10705 +#define TH_ECE 0x40
10706 +#define TH_CWR 0x80
10708 +/* table of valid flag combinations - ECE and CWR are always valid */
10709 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
10712 + [TH_SYN|TH_ACK] = 1,
10714 + [TH_RST|TH_ACK] = 1,
10715 + [TH_RST|TH_ACK|TH_PUSH] = 1,
10716 + [TH_FIN|TH_ACK] = 1,
10718 + [TH_ACK|TH_PUSH] = 1,
10719 + [TH_ACK|TH_URG] = 1,
10720 + [TH_ACK|TH_URG|TH_PUSH] = 1,
10721 + [TH_FIN|TH_ACK|TH_PUSH] = 1,
10722 + [TH_FIN|TH_ACK|TH_URG] = 1,
10723 + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
10726 +/* TCP-specific checks. */
10728 +check_tcp(const struct iphdr *iph,
10729 + const struct tcphdr *tcph,
10730 + u_int16_t datalen,
10731 + unsigned int offset,
10735 + u_int8_t *opt = (u_int8_t *)tcph;
10736 + u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
10737 + u_int8_t tcpflags;
10738 + int end_of_options = 0;
10741 + /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
10742 + /* In fact, this is caught below (offset < 516). */
10744 + /* Can't do anything if it's a fragment. */
10748 + /* CHECK: Smaller than minimal TCP hdr. */
10749 + if (datalen < sizeof(struct tcphdr)) {
10751 + limpk("Packet length %u < TCP header.\n", datalen);
10754 + /* Must have ports available (datalen >= 8), from
10755 + check_icmp which set embedded = 1 */
10756 + /* CHECK: TCP ports inside ICMP error */
10757 + if (!tcph->source || !tcph->dest) {
10758 + limpk("Zero TCP ports %u/%u.\n",
10759 + htons(tcph->source), htons(tcph->dest));
10765 + /* CHECK: Smaller than actual TCP hdr. */
10766 + if (datalen < tcph->doff * 4) {
10768 + limpk("Packet length %u < actual TCP header.\n",
10775 + /* Bad checksum? Don't print, just say it's unclean. */
10776 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
10777 + if (!more_frags && !embedded
10778 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
10779 + csum_partial((char *)tcph, datalen, 0)) != 0)
10782 + /* CHECK: TCP ports non-zero */
10783 + if (!tcph->source || !tcph->dest) {
10784 + limpk("Zero TCP ports %u/%u.\n",
10785 + htons(tcph->source), htons(tcph->dest));
10789 + /* CHECK: TCP reserved bits zero. */
10790 + if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
10791 + limpk("TCP reserved bits not zero\n");
10795 + /* CHECK: TCP flags. */
10796 + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
10797 + if (!tcp_valid_flags[tcpflags]) {
10798 + limpk("TCP flags bad: %u\n", tcpflags);
10802 + for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
10803 + switch (opt[i]) {
10805 + end_of_options = 1;
10812 + /* CHECK: options after EOO. */
10813 + if (end_of_options) {
10814 + limpk("TCP option %u after end\n",
10818 + /* CHECK: options at tail. */
10819 + else if (i+1 >= tcph->doff * 4) {
10820 + limpk("TCP option %u at tail\n",
10824 + /* CHECK: zero-length options. */
10825 + else if (opt[i+1] == 0) {
10826 + limpk("TCP option %u 0 len\n",
10830 + /* CHECK: oversize options. */
10831 + else if (&opt[i] + opt[i+1] > endhdr) {
10832 + limpk("TCP option %u at %Zu too long\n",
10833 + (unsigned int) opt[i], i);
10836 + /* Move to next option */
10844 +/* Returns 1 if ok */
10845 +/* Standard IP checks. */
10847 +check_ip(struct iphdr *iph, size_t length, int embedded)
10849 + u_int8_t *opt = (u_int8_t *)iph;
10850 + u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
10851 + int end_of_options = 0;
10855 + unsigned int offset;
10857 + /* Should only happen for local outgoing raw-socket packets. */
10858 + /* CHECK: length >= ip header. */
10859 + if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
10860 + limpk("Packet length %Zu < IP header.\n", length);
10864 + offset = ntohs(iph->frag_off) & IP_OFFSET;
10865 + protoh = (void *)iph + iph->ihl * 4;
10866 + datalen = length - iph->ihl * 4;
10868 + /* CHECK: Embedded fragment. */
10869 + if (embedded && offset) {
10870 + limpk("Embedded fragment.\n");
10874 + for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
10875 + switch (opt[i]) {
10877 + end_of_options = 1;
10884 + /* CHECK: options after EOO. */
10885 + if (end_of_options) {
10886 + limpk("IP option %u after end\n",
10890 + /* CHECK: options at tail. */
10891 + else if (i+1 >= iph->ihl * 4) {
10892 + limpk("IP option %u at tail\n",
10896 + /* CHECK: zero-length or one-length options. */
10897 + else if (opt[i+1] < 2) {
10898 + limpk("IP option %u %u len\n",
10899 + opt[i], opt[i+1]);
10902 + /* CHECK: oversize options. */
10903 + else if (&opt[i] + opt[i+1] > endhdr) {
10904 + limpk("IP option %u at %u too long\n",
10908 + /* Move to next option */
10913 + /* Fragment checks. */
10915 + /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
10916 + if ((ntohs(iph->frag_off) & IP_MF)
10917 + && (ntohs(iph->tot_len) % 8) != 0) {
10918 + limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
10922 + /* CHECK: Oversize fragment a-la Ping of Death. */
10923 + if (offset * 8 + datalen > 65535) {
10924 + limpk("Oversize fragment to %u.\n", offset * 8);
10928 + /* CHECK: DF set and offset or MF set. */
10929 + if ((ntohs(iph->frag_off) & IP_DF)
10930 + && (offset || (ntohs(iph->frag_off) & IP_MF))) {
10931 + limpk("DF set and offset=%u, MF=%u.\n",
10932 + offset, ntohs(iph->frag_off) & IP_MF);
10936 + /* CHECK: Zero-sized fragments. */
10937 + if ((offset || (ntohs(iph->frag_off) & IP_MF))
10938 + && datalen == 0) {
10939 + limpk("Zero size fragment offset=%u\n", offset);
10943 + /* Note: we can have even middle fragments smaller than this:
10944 + consider a large packet passing through a 600MTU then
10945 + 576MTU link: this gives a fragment of 24 data bytes. But
10946 + everyone packs fragments largest first, hence a fragment
10947 + can't START before 576 - MAX_IP_HEADER_LEN. */
10949 + /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
10950 + down to 128 (576 taken from RFC 791: All hosts must be
10951 + prepared to accept datagrams of up to 576 octets). Use 128
10953 +#define MIN_LIKELY_MTU 128
10954 + /* CHECK: Min size of first frag = 128. */
10955 + if ((ntohs(iph->frag_off) & IP_MF)
10957 + && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
10958 + limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
10963 + /* CHECK: Min offset of frag = 128 - IP hdr len. */
10964 + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
10965 + limpk("Fragment starts at %u < %u\n", offset * 8,
10966 + MIN_LIKELY_MTU - iph->ihl * 4);
10970 + /* CHECK: Protocol specification non-zero. */
10971 + if (iph->protocol == 0) {
10972 + limpk("Zero protocol\n");
10976 + /* CHECK: Do not use what is unused.
10977 + * First bit of fragmentation flags should be unused.
10978 + * May be used by OS fingerprinting tools.
10979 + * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
10981 + if (ntohs(iph->frag_off)>>15) {
10982 + limpk("IP unused bit set\n");
10986 + /* Per-protocol checks. */
10987 + switch (iph->protocol) {
10988 + case IPPROTO_ICMP:
10989 + return check_icmp(protoh, datalen, offset,
10990 + (ntohs(iph->frag_off) & IP_MF),
10993 + case IPPROTO_UDP:
10994 + return check_udp(iph, protoh, datalen, offset,
10995 + (ntohs(iph->frag_off) & IP_MF),
10998 + case IPPROTO_TCP:
10999 + return check_tcp(iph, protoh, datalen, offset,
11000 + (ntohs(iph->frag_off) & IP_MF),
11003 + /* Ignorance is bliss. */
11009 +match(const struct sk_buff *skb,
11010 + const struct net_device *in,
11011 + const struct net_device *out,
11012 + const void *matchinfo,
11015 + u_int16_t datalen,
11018 + return !check_ip(skb->nh.iph, skb->len, 0);
11021 +/* Called when user tries to insert an entry of this type. */
11023 +checkentry(const char *tablename,
11024 + const struct ipt_ip *ip,
11026 + unsigned int matchsize,
11027 + unsigned int hook_mask)
11029 + if (matchsize != IPT_ALIGN(0))
11035 +static struct ipt_match unclean_match
11036 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
11038 +static int __init init(void)
11040 + return ipt_register_match(&unclean_match);
11043 +static void __exit fini(void)
11045 + ipt_unregister_match(&unclean_match);
11048 +module_init(init);
11049 +module_exit(fini);
11050 +MODULE_LICENSE("GPL");
11051 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c
11052 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c 2004-04-28 03:35:43.000000000 +0200
11053 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c 2004-04-29 11:17:15.000000000 +0200
11056 sizeof(struct ipt_entry),
11057 sizeof(struct ipt_standard),
11058 - 0, { 0, 0 }, { } },
11059 + 0, NULL, 0, { 0, 0 }, { } },
11060 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11061 -NF_ACCEPT - 1 } },
11065 sizeof(struct ipt_entry),
11066 sizeof(struct ipt_standard),
11067 - 0, { 0, 0 }, { } },
11068 + 0, NULL, 0, { 0, 0 }, { } },
11069 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11070 -NF_ACCEPT - 1 } },
11074 sizeof(struct ipt_entry),
11075 sizeof(struct ipt_standard),
11076 - 0, { 0, 0 }, { } },
11077 + 0, NULL, 0, { 0, 0 }, { } },
11078 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11083 sizeof(struct ipt_entry),
11084 sizeof(struct ipt_error),
11085 - 0, { 0, 0 }, { } },
11086 + 0, NULL, 0, { 0, 0 }, { } },
11087 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11090 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c
11091 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c 2004-04-28 03:36:34.000000000 +0200
11092 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-04-29 11:17:15.000000000 +0200
11095 sizeof(struct ipt_entry),
11096 sizeof(struct ipt_standard),
11097 - 0, { 0, 0 }, { } },
11098 + 0, NULL, 0, { 0, 0 }, { } },
11099 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11100 -NF_ACCEPT - 1 } },
11104 sizeof(struct ipt_entry),
11105 sizeof(struct ipt_standard),
11106 - 0, { 0, 0 }, { } },
11107 + 0, NULL, 0, { 0, 0 }, { } },
11108 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11109 -NF_ACCEPT - 1 } },
11113 sizeof(struct ipt_entry),
11114 sizeof(struct ipt_standard),
11115 - 0, { 0, 0 }, { } },
11116 + 0, NULL, 0, { 0, 0 }, { } },
11117 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11118 -NF_ACCEPT - 1 } },
11122 sizeof(struct ipt_entry),
11123 sizeof(struct ipt_standard),
11124 - 0, { 0, 0 }, { } },
11125 + 0, NULL, 0, { 0, 0 }, { } },
11126 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11127 -NF_ACCEPT - 1 } },
11129 @@ -106,7 +106,7 @@
11131 sizeof(struct ipt_entry),
11132 sizeof(struct ipt_standard),
11133 - 0, { 0, 0 }, { } },
11134 + 0, NULL, 0, { 0, 0 }, { } },
11135 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11136 -NF_ACCEPT - 1 } },
11138 @@ -115,7 +115,7 @@
11140 sizeof(struct ipt_entry),
11141 sizeof(struct ipt_error),
11142 - 0, { 0, 0 }, { } },
11143 + 0, NULL, 0, { 0, 0 }, { } },
11144 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11147 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c
11148 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c 2004-04-28 03:36:36.000000000 +0200
11149 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c 2004-04-29 11:17:15.000000000 +0200
11152 sizeof(struct ipt_entry),
11153 sizeof(struct ipt_standard),
11154 - 0, { 0, 0 }, { } },
11155 + 0, NULL, 0, { 0, 0 }, { } },
11156 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11157 -NF_ACCEPT - 1 } },
11161 sizeof(struct ipt_entry),
11162 sizeof(struct ipt_standard),
11163 - 0, { 0, 0 }, { } },
11164 + 0, NULL, 0, { 0, 0 }, { } },
11165 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11170 sizeof(struct ipt_entry),
11171 sizeof(struct ipt_error),
11172 - 0, { 0, 0 }, { } },
11173 + 0, NULL, 0, { 0, 0 }, { } },
11174 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11177 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/raw.c linux-2.6.6-rc3/net/ipv4/raw.c
11178 --- linux-2.6.6-rc3.org/net/ipv4/raw.c 2004-04-28 03:35:49.000000000 +0200
11179 +++ linux-2.6.6-rc3/net/ipv4/raw.c 2004-04-29 11:18:06.000000000 +0200
11180 @@ -249,6 +249,7 @@
11182 return NET_RX_DROP;
11186 skb_push(skb, skb->data - skb->nh.raw);
11188 @@ -307,7 +308,7 @@
11191 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
11195 err = inet->recverr ? net_xmit_errno(err) : 0;
11197 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c
11198 --- linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c 2004-04-28 03:35:40.000000000 +0200
11199 +++ linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c 2004-04-29 11:19:32.000000000 +0200
11200 @@ -1785,6 +1785,7 @@
11202 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
11203 goto discard_and_relse;
11206 if (sk_filter(sk, skb, 0))
11207 goto discard_and_relse;
11208 @@ -2670,6 +2671,7 @@
11209 EXPORT_SYMBOL(tcp_v4_connect);
11210 EXPORT_SYMBOL(tcp_v4_do_rcv);
11211 EXPORT_SYMBOL(tcp_v4_lookup_listener);
11212 +EXPORT_SYMBOL(tcp_v4_lookup);
11213 EXPORT_SYMBOL(tcp_v4_rebuild_header);
11214 EXPORT_SYMBOL(tcp_v4_remember_stamp);
11215 EXPORT_SYMBOL(tcp_v4_send_check);
11216 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/udp.c linux-2.6.6-rc3/net/ipv4/udp.c
11217 --- linux-2.6.6-rc3.org/net/ipv4/udp.c 2004-04-28 03:35:19.000000000 +0200
11218 +++ linux-2.6.6-rc3/net/ipv4/udp.c 2004-04-29 11:19:32.000000000 +0200
11219 @@ -1045,6 +1045,7 @@
11225 if (up->encap_type) {
11227 @@ -1210,6 +1211,7 @@
11229 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
11233 /* No socket. Drop packet silently, if checksum is wrong */
11234 if (udp_checksum_complete(skb))
11235 @@ -1558,6 +1560,7 @@
11236 EXPORT_SYMBOL(udp_port_rover);
11237 EXPORT_SYMBOL(udp_prot);
11238 EXPORT_SYMBOL(udp_sendmsg);
11239 +EXPORT_SYMBOL(udp_v4_lookup);
11241 #ifdef CONFIG_PROC_FS
11242 EXPORT_SYMBOL(udp_proc_register);
11243 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c
11244 --- linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-04-28 03:35:08.000000000 +0200
11245 +++ linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c 2004-04-29 11:18:03.000000000 +0200
11247 err = -EHOSTUNREACH;
11250 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
11251 return NET_XMIT_BYPASS;
11254 @@ -170,6 +171,7 @@
11255 .handler = ipip_rcv,
11256 .err_handler = ipip_err,
11261 static int __init ipip_init(void)
11262 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
11263 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig 2004-04-29 11:24:39.000000000 +0200
11264 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig 2004-04-29 11:19:41.000000000 +0200
11265 @@ -255,5 +255,29 @@
11266 depends on IP6_NF_IPTABLES
11269 +config IP6_NF_TARGET_TRACE
11270 + tristate 'TRACE target support'
11271 + depends on IP6_NF_RAW
11273 + The TRACE target allows packets to be traced as those
11274 + matches any subsequent rule in any table/rule. The matched
11275 + rule and the packet is logged with the prefix
11277 + TRACE: tablename/chainname/rulenum
11279 + If you want to compile it as a module, say M here and read
11280 + <file:Documentation/modules.txt>. If unsure, say `N'.
11283 +config IP6_NF_MATCH_POLICY
11284 + tristate "IPsec policy match support"
11285 + depends on IP6_NF_IPTABLES && XFRM
11287 + Policy matching allows you to match packets based on the
11288 + IPsec policy that was used during decapsulation/will
11289 + be used during encapsulation.
11291 + To compile it as a module, choose M here. If unsure, say N.
11295 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
11296 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile 2004-04-29 11:24:39.000000000 +0200
11297 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-29 11:19:41.000000000 +0200
11299 obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
11300 obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
11301 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
11302 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
11303 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
11304 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
11305 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c
11306 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-04-28 03:36:34.000000000 +0200
11307 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c 2004-04-29 11:17:15.000000000 +0200
11309 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
11310 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
11312 +static const char *hook6names[] = {
11313 + [NF_IP6_PRE_ROUTING] "PREROUTING",
11314 + [NF_IP6_LOCAL_IN] "INPUT",
11315 + [NF_IP6_FORWARD] "FORWARD",
11316 + [NF_IP6_LOCAL_OUT] "OUTPUT",
11317 + [NF_IP6_POST_ROUTING] "POSTROUTING",
11320 /*#define DEBUG_IP_FIREWALL*/
11321 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
11322 /*#define DEBUG_IP_FIREWALL_USER*/
11323 @@ -408,6 +416,12 @@
11325 t = ip6t_get_target(e);
11326 IP_NF_ASSERT(t->u.kernel.target);
11328 + /* The packet traced and the rule isn't an unconditional return/END. */
11329 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
11330 + nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11331 + table->name, e->chainname, e->rulenum);
11333 /* Standard target? */
11334 if (!t->u.kernel.target->target) {
11336 @@ -561,6 +575,29 @@
11337 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
11341 +find_error_target(struct ip6t_entry *s,
11342 + struct ip6t_entry *e,
11343 + char **chainname)
11345 + struct ip6t_entry_target *t;
11346 + static struct ip6t_entry *found = NULL;
11351 + t = ip6t_get_target(found);
11352 + if (strcmp(t->u.user.name,
11353 + IP6T_ERROR_TARGET) == 0) {
11354 + *chainname = t->data;
11363 /* All zeroes == unconditional rule. */
11365 unconditional(const struct ip6t_ip6 *ipv6)
11366 @@ -580,6 +617,8 @@
11367 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
11370 + char *chainname = NULL;
11371 + u_int32_t rulenum;
11373 /* No recursion; use packet counter to save back ptrs (reset
11374 to 0 as we leave), and comefrom to save source hook bitmask */
11375 @@ -593,6 +632,8 @@
11377 /* Set initial back pointer. */
11378 e->counters.pcnt = pos;
11380 + chainname = (char *) hook6names[hook];
11383 struct ip6t_standard_target *t
11384 @@ -605,6 +646,8 @@
11387 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
11388 + e->rulenum = rulenum++;
11389 + e->chainname = chainname;
11391 /* Unconditional return/END. */
11392 if (e->target_offset == sizeof(struct ip6t_entry)
11393 @@ -614,6 +657,10 @@
11394 && unconditional(&e->ipv6)) {
11395 unsigned int oldpos, size;
11397 + /* Set unconditional rulenum to zero. */
11399 + e->counters.bcnt = 0;
11401 /* Return: backtrack through the last
11404 @@ -639,6 +686,11 @@
11405 (newinfo->entries + pos);
11406 } while (oldpos == pos + e->next_offset);
11408 + /* Restore chainname, rulenum. */
11409 + chainname = e->chainname;
11410 + rulenum = e->counters.bcnt;
11411 + e->counters.bcnt = 0;
11413 /* Move along one */
11414 size = e->next_offset;
11415 e = (struct ip6t_entry *)
11416 @@ -654,6 +706,17 @@
11417 /* This a jump; chase it. */
11418 duprintf("Jump rule %u -> %u\n",
11420 + e->counters.bcnt = rulenum++;
11422 + e = (struct ip6t_entry *)
11423 + (newinfo->entries + newpos);
11424 + if (IP6T_ENTRY_ITERATE(newinfo->entries,
11426 + find_error_target,
11427 + e, &chainname) == 0) {
11428 + printk("ip6_tables: table screwed up!\n");
11432 /* ... this is a fallthru */
11433 newpos = pos + e->next_offset;
11434 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c
11435 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
11436 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c 2004-04-29 11:17:15.000000000 +0200
11438 +/* This is a module which is used for setting
11439 + * the NFC_TRACE flag in the nfcache field of an skb.
11441 +#include <linux/module.h>
11442 +#include <linux/skbuff.h>
11444 +#include <linux/netfilter_ipv6/ip6_tables.h>
11446 +MODULE_LICENSE("GPL");
11448 +static unsigned int
11449 +target(struct sk_buff **pskb,
11450 + unsigned int hooknum,
11451 + const struct net_device *in,
11452 + const struct net_device *out,
11453 + const void *targinfo,
11456 + (*pskb)->nfcache |= NFC_TRACE;
11457 + return IP6T_CONTINUE;
11461 +checkentry(const char *tablename,
11462 + const struct ip6t_entry *e,
11464 + unsigned int targinfosize,
11465 + unsigned int hook_mask)
11467 + if (targinfosize != 0) {
11468 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
11473 + if (strcmp(tablename, "raw") != 0) {
11474 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
11481 +static struct ip6t_target ip6t_trace_reg = {
11483 + .target = target,
11484 + .checkentry = checkentry,
11485 + .me = THIS_MODULE
11488 +static int __init init(void)
11490 + if (ip6t_register_target(&ip6t_trace_reg))
11496 +static void __exit fini(void)
11498 + ip6t_unregister_target(&ip6t_trace_reg);
11501 +module_init(init);
11502 +module_exit(fini);
11503 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c
11504 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-28 03:36:30.000000000 +0200
11505 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c 2004-04-29 11:19:40.000000000 +0200
11507 MODULE_LICENSE("GPL");
11510 +match_comm(const struct sk_buff *skb, const char *comm)
11512 + struct task_struct *p, *g;
11513 + struct files_struct *files;
11516 + read_lock(&tasklist_lock);
11517 + do_each_thread(g, p) {
11518 + if(strncmp(p->comm, comm, sizeof(p->comm)))
11522 + files = p->files;
11524 + read_lock(&files->file_lock);
11525 + for (i=0; i < files->max_fds; i++) {
11526 + if (fcheck_files(files, i) ==
11527 + skb->sk->sk_socket->file) {
11528 + read_unlock(&files->file_lock);
11530 + read_unlock(&tasklist_lock);
11534 + read_unlock(&files->file_lock);
11537 + } while_each_thread(g, p);
11538 + read_unlock(&tasklist_lock);
11543 match_pid(const struct sk_buff *skb, pid_t pid)
11545 struct task_struct *p;
11546 @@ -125,6 +158,12 @@
11550 + if(info->match & IP6T_OWNER_COMM) {
11551 + if (!match_comm(skb, info->comm) ^
11552 + !!(info->invert & IP6T_OWNER_COMM))
11559 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c
11560 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
11561 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c 2004-04-29 11:19:41.000000000 +0200
11563 +/* IP tables module for matching IPsec policy
\r
11565 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
\r
11567 + * This program is free software; you can redistribute it and/or modify
\r
11568 + * it under the terms of the GNU General Public License version 2 as
\r
11569 + * published by the Free Software Foundation.
\r
11572 +#include <linux/kernel.h>
\r
11573 +#include <linux/config.h>
\r
11574 +#include <linux/module.h>
\r
11575 +#include <linux/skbuff.h>
\r
11576 +#include <linux/init.h>
\r
11577 +#include <net/xfrm.h>
\r
11579 +#include <linux/netfilter_ipv6.h>
\r
11580 +#include <linux/netfilter_ipv6/ip6t_policy.h>
\r
11581 +#include <linux/netfilter_ipv6/ip6_tables.h>
\r
11583 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
\r
11584 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
\r
11585 +MODULE_LICENSE("GPL");
\r
11588 +static inline int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,
\r
11589 + struct in6_addr addr2)
\r
11593 + for (i = 0; i < 16; i++) {
\r
11594 + if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
\r
11595 + (addr2.s6_addr[i] & mask.s6_addr[i]))
\r
11602 +static inline int
\r
11603 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
\r
11605 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
\r
11607 + struct in6_addr xfrm_saddr, xfrm_daddr;
\r
11609 + if ((e->match.saddr
\r
11610 + && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
\r
11611 + ^ e->invert.saddr ) ||
\r
11612 + (e->match.daddr
\r
11613 + && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
\r
11614 + ^ e->invert.daddr ) ||
\r
11615 + MISMATCH(proto, x->id.proto) ||
\r
11616 + MISMATCH(mode, x->props.mode) ||
\r
11617 + MISMATCH(spi, x->id.spi) ||
\r
11618 + MISMATCH(reqid, x->props.reqid))
\r
11624 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
\r
11626 + const struct ip6t_policy_elem *e;
\r
11627 + struct sec_path *sp = skb->sp;
\r
11628 + int strict = info->flags & POLICY_MATCH_STRICT;
\r
11631 + if (sp == NULL)
\r
11633 + if (strict && info->len != sp->len)
\r
11636 + for (i = sp->len - 1; i >= 0; i--) {
\r
11637 + pos = strict ? i - sp->len + 1 : 0;
\r
11638 + if (pos >= info->len)
\r
11640 + e = &info->pol[pos];
\r
11642 + if (match_xfrm_state(sp->x[i].xvec, e)) {
\r
11645 + } else if (strict)
\r
11649 + return strict ? 1 : 0;
\r
11653 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
\r
11655 + const struct ip6t_policy_elem *e;
\r
11656 + struct dst_entry *dst = skb->dst;
\r
11657 + int strict = info->flags & POLICY_MATCH_STRICT;
\r
11660 + if (dst->xfrm == NULL)
\r
11663 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
\r
11664 + pos = strict ? i : 0;
\r
11665 + if (pos >= info->len)
\r
11667 + e = &info->pol[pos];
\r
11669 + if (match_xfrm_state(dst->xfrm, e)) {
\r
11672 + } else if (strict)
\r
11676 + return strict ? 1 : 0;
\r
11679 +static int match(const struct sk_buff *skb,
\r
11680 + const struct net_device *in,
\r
11681 + const struct net_device *out,
\r
11682 + const void *matchinfo,
\r
11684 + const void *hdr,
\r
11685 + u_int16_t datalen,
\r
11688 + const struct ip6t_policy_info *info = matchinfo;
\r
11691 + if (info->flags & POLICY_MATCH_IN)
\r
11692 + ret = match_policy_in(skb, info);
\r
11694 + ret = match_policy_out(skb, info);
\r
11697 + if (info->flags & POLICY_MATCH_NONE)
\r
11701 + } else if (info->flags & POLICY_MATCH_NONE)
\r
11707 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
\r
11708 + void *matchinfo, unsigned int matchsize,
\r
11709 + unsigned int hook_mask)
\r
11711 + struct ip6t_policy_info *info = matchinfo;
\r
11713 + if (matchsize != IP6T_ALIGN(sizeof(*info))) {
\r
11714 + printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
\r
11715 + matchsize, IP6T_ALIGN(sizeof(*info)));
\r
11718 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
\r
11719 + printk(KERN_ERR "ip6t_policy: neither incoming nor "
\r
11720 + "outgoing policy selected\n");
\r
11723 + if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
\r
11724 + && info->flags & POLICY_MATCH_OUT) {
\r
11725 + printk(KERN_ERR "ip6t_policy: output policy not valid in "
\r
11726 + "PRE_ROUTING and INPUT\n");
\r
11729 + if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
\r
11730 + && info->flags & POLICY_MATCH_IN) {
\r
11731 + printk(KERN_ERR "ip6t_policy: input policy not valid in "
\r
11732 + "POST_ROUTING and OUTPUT\n");
\r
11735 + if (info->len > POLICY_MAX_ELEM) {
\r
11736 + printk(KERN_ERR "ip6t_policy: too many policy elements\n");
\r
11743 +static struct ip6t_match policy_match =
\r
11745 + .name = "policy",
\r
11746 + .match = match,
\r
11747 + .checkentry = checkentry,
\r
11748 + .me = THIS_MODULE,
\r
11751 +static int __init init(void)
\r
11753 + return ip6t_register_match(&policy_match);
\r
11756 +static void __exit fini(void)
\r
11758 + ip6t_unregister_match(&policy_match);
\r
11761 +module_init(init);
\r
11762 +module_exit(fini);
\r
11763 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c
11764 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c 2004-04-28 03:35:07.000000000 +0200
11765 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c 2004-04-29 11:17:15.000000000 +0200
11768 sizeof(struct ip6t_entry),
11769 sizeof(struct ip6t_standard),
11770 - 0, { 0, 0 }, { } },
11771 + 0, NULL, 0, { 0, 0 }, { } },
11772 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11773 -NF_ACCEPT - 1 } },
11777 sizeof(struct ip6t_entry),
11778 sizeof(struct ip6t_standard),
11779 - 0, { 0, 0 }, { } },
11780 + 0, NULL, 0, { 0, 0 }, { } },
11781 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11782 -NF_ACCEPT - 1 } },
11786 sizeof(struct ip6t_entry),
11787 sizeof(struct ip6t_standard),
11788 - 0, { 0, 0 }, { } },
11789 + 0, NULL, 0, { 0, 0 }, { } },
11790 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11795 sizeof(struct ip6t_entry),
11796 sizeof(struct ip6t_error),
11797 - 0, { 0, 0 }, { } },
11798 + 0, NULL, 0, { 0, 0 }, { } },
11799 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11802 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c
11803 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c 2004-04-28 03:35:43.000000000 +0200
11804 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c 2004-04-29 11:17:15.000000000 +0200
11807 sizeof(struct ip6t_entry),
11808 sizeof(struct ip6t_standard),
11809 - 0, { 0, 0 }, { } },
11810 + 0, NULL, 0, { 0, 0 }, { } },
11811 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11812 -NF_ACCEPT - 1 } },
11816 sizeof(struct ip6t_entry),
11817 sizeof(struct ip6t_standard),
11818 - 0, { 0, 0 }, { } },
11819 + 0, NULL, 0, { 0, 0 }, { } },
11820 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11821 -NF_ACCEPT - 1 } },
11825 sizeof(struct ip6t_entry),
11826 sizeof(struct ip6t_standard),
11827 - 0, { 0, 0 }, { } },
11828 + 0, NULL, 0, { 0, 0 }, { } },
11829 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11830 -NF_ACCEPT - 1 } },
11834 sizeof(struct ip6t_entry),
11835 sizeof(struct ip6t_standard),
11836 - 0, { 0, 0 }, { } },
11837 + 0, NULL, 0, { 0, 0 }, { } },
11838 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11839 -NF_ACCEPT - 1 } },
11841 @@ -105,7 +105,7 @@
11843 sizeof(struct ip6t_entry),
11844 sizeof(struct ip6t_standard),
11845 - 0, { 0, 0 }, { } },
11846 + 0, NULL, 0, { 0, 0 }, { } },
11847 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11850 @@ -114,7 +114,7 @@
11852 sizeof(struct ip6t_entry),
11853 sizeof(struct ip6t_error),
11854 - 0, { 0, 0 }, { } },
11855 + 0, NULL, 0, { 0, 0 }, { } },
11856 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11859 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c
11860 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c 2004-04-28 03:36:19.000000000 +0200
11861 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c 2004-04-29 11:17:15.000000000 +0200
11864 sizeof(struct ip6t_entry),
11865 sizeof(struct ip6t_standard),
11866 - 0, { 0, 0 }, { } },
11867 + 0, NULL, 0, { 0, 0 }, { } },
11868 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11869 -NF_ACCEPT - 1 } },
11873 sizeof(struct ip6t_entry),
11874 sizeof(struct ip6t_standard),
11875 - 0, { 0, 0 }, { } },
11876 + 0, NULL, 0, { 0, 0 }, { } },
11877 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11878 -NF_ACCEPT - 1 } },
11882 sizeof(struct ip6t_entry),
11883 sizeof(struct ip6t_error),
11884 - 0, { 0, 0 }, { } },
11885 + 0, NULL, 0, { 0, 0 }, { } },
11886 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11889 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c linux-2.6.6-rc3/net/xfrm/xfrm_input.c
11890 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c 2004-04-28 03:35:05.000000000 +0200
11891 +++ linux-2.6.6-rc3/net/xfrm/xfrm_input.c 2004-04-29 11:18:03.000000000 +0200
11896 +#ifdef CONFIG_NETFILTER
11897 + sp->decap_done = 0;
11902 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc3/net/xfrm/xfrm_policy.c
11903 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c 2004-04-28 03:35:48.000000000 +0200
11904 +++ linux-2.6.6-rc3/net/xfrm/xfrm_policy.c 2004-04-29 11:18:06.000000000 +0200
11906 #include <linux/workqueue.h>
11907 #include <linux/notifier.h>
11908 #include <linux/netdevice.h>
11909 +#include <linux/netfilter.h>
11910 #include <net/xfrm.h>
11911 #include <net/ip.h>
11913 @@ -908,6 +909,7 @@
11915 if (_decode_session(skb, &fl, family) < 0)
11917 + nf_nat_decode_session(skb, &fl, family);
11919 /* First, check used SA against their selectors. */