1 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter.h linux-2.6.6-rc1/include/linux/netfilter.h
2 --- linux-2.6.6-rc1.org/include/linux/netfilter.h 2004-04-16 08:59:08.000000000 +0200
3 +++ linux-2.6.6-rc1/include/linux/netfilter.h 2004-04-16 09:17:13.000000000 +0200
5 /* This is gross, but inline doesn't cut it for avoiding the function
6 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
7 #ifdef CONFIG_NETFILTER_DEBUG
8 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
9 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
10 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
13 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
14 #define NF_HOOK_THRESH nf_hook_slow
16 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
17 -(list_empty(&nf_hooks[(pf)][(hook)]) \
18 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
19 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
21 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
25 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
27 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
28 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
30 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
31 struct net_device *indev, struct net_device *outdev,
34 #else /* !CONFIG_NETFILTER */
35 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
36 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
37 #endif /*CONFIG_NETFILTER*/
40 +#ifdef CONFIG_IP_NF_NAT_NEEDED
42 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
45 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
47 + if (family == AF_INET)
48 + nf_nat_decode_session4(skb, fl);
50 +#else /* CONFIG_IP_NF_NAT_NEEDED */
51 +#define nf_nat_decode_session(skb,fl,family)
52 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
53 +#endif /* CONFIG_XFRM */
56 #endif /*__LINUX_NETFILTER_H*/
57 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack.h
58 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-16 08:59:08.000000000 +0200
59 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-16 09:18:58.000000000 +0200
63 /* Add protocol helper include file here */
64 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
65 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
66 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
67 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
68 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
69 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
70 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
72 /* per expectation: application helper private data */
73 union ip_conntrack_expect_help {
74 /* insert conntrack helper private data (expect) here */
75 + struct ip_ct_talk_expect exp_talk_info;
76 + struct ip_ct_rsh_expect exp_rsh_info;
77 + struct ip_ct_mms_expect exp_mms_info;
78 + struct ip_ct_h225_expect exp_h225_info;
79 struct ip_ct_amanda_expect exp_amanda_info;
80 struct ip_ct_ftp_expect exp_ftp_info;
81 struct ip_ct_irc_expect exp_irc_info;
83 /* per conntrack: application helper private data */
84 union ip_conntrack_help {
85 /* insert conntrack helper private data (master) here */
86 + struct ip_ct_talk_master ct_talk_info;
87 + struct ip_ct_rsh_master ct_rsh_info;
88 + struct ip_ct_mms_master ct_mms_info;
89 + struct ip_ct_h225_master ct_h225_info;
90 struct ip_ct_ftp_master ct_ftp_info;
91 struct ip_ct_irc_master ct_irc_info;
95 #endif /* CONFIG_IP_NF_NAT_NEEDED */
97 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
103 /* get master conntrack via master expectation */
104 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_h323.h
105 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
106 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-04-16 09:17:05.000000000 +0200
108 +#ifndef _IP_CONNTRACK_H323_H
109 +#define _IP_CONNTRACK_H323_H
110 +/* H.323 connection tracking. */
113 +/* Protects H.323 related data */
114 +#include <linux/netfilter_ipv4/lockhelp.h>
115 +DECLARE_LOCK_EXTERN(ip_h323_lock);
118 +/* Default H.225 port */
119 +#define H225_PORT 1720
121 +/* This structure is per expected connection */
122 +struct ip_ct_h225_expect {
123 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
124 + enum ip_conntrack_dir dir; /* Direction of the original connection */
125 + unsigned int offset; /* offset of the address in the payload */
128 +/* This structure exists only once per master */
129 +struct ip_ct_h225_master {
130 + int is_h225; /* H.225 or H.245 connection */
131 +#ifdef CONFIG_IP_NF_NAT_NEEDED
132 + enum ip_conntrack_dir dir; /* Direction of the original connection */
133 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
134 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
138 +#endif /* _IP_CONNTRACK_H323_H */
139 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_mms.h
140 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
141 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-04-16 09:17:32.000000000 +0200
143 +#ifndef _IP_CONNTRACK_MMS_H
144 +#define _IP_CONNTRACK_MMS_H
148 +#include <linux/netfilter_ipv4/lockhelp.h>
150 +DECLARE_LOCK_EXTERN(ip_mms_lock);
152 +#define MMS_PORT 1755
153 +#define MMS_SRV_MSG_ID 196610
155 +#define MMS_SRV_MSG_OFFSET 36
156 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
157 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
158 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
159 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
162 +/* This structure is per expected connection */
163 +struct ip_ct_mms_expect {
169 +/* This structure exists only once per master */
170 +struct ip_ct_mms_master {
173 +#endif /* _IP_CONNTRACK_MMS_H */
174 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
175 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
176 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-04-16 09:18:43.000000000 +0200
178 +#ifndef _IP_CT_QUAKE3
179 +#define _IP_CT_QUAKE3
181 +/* Don't confuse with 27960, often used as the Server Port */
182 +#define QUAKE3_MASTER_PORT 27950
184 +struct quake3_search {
185 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
186 + const char *pattern;
190 +/* This structure is per expected connection */
191 +struct ip_ct_quake3_expect {
194 +/* This structure exists only once per master */
195 +struct ip_ct_quake3_master {
198 +#endif /* _IP_CT_QUAKE3 */
199 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
200 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
201 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2004-04-16 09:18:44.000000000 +0200
203 +/* RPC extension for IP connection tracking, Version 2.2
204 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
205 + * - original rpc tracking module
206 + * - "recent" connection handling for kernel 2.3+ netfilter
208 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
209 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
211 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
212 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
213 + * - extended matching to support filtering on procedures
215 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
217 + * This program is free software; you can redistribute it and/or
218 + * modify it under the terms of the GNU General Public License
219 + * as published by the Free Software Foundation; either version
220 + * 2 of the License, or (at your option) any later version.
224 +#include <asm/param.h>
225 +#include <linux/sched.h>
226 +#include <linux/timer.h>
227 +#include <linux/stddef.h>
228 +#include <linux/list.h>
230 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
232 +#ifndef _IP_CONNTRACK_RPC_H
233 +#define _IP_CONNTRACK_RPC_H
235 +#define RPC_PORT 111
238 +/* Datum in RPC packets are encoded in XDR */
239 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
241 +/* Fast timeout, to deny DoS atacks */
242 +#define EXP (60 * HZ)
244 +/* Normal timeouts */
245 +#define EXPIRES (180 * HZ)
247 +/* For future conections RPC, using client's cache bindings
248 + * I'll use ip_conntrack_lock to lock these lists */
250 +/* This identifies each request and stores protocol */
252 + struct list_head list;
261 + struct timer_list timeout;
264 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
265 + u_int32_t ip, u_int32_t port) {
266 + return (p->xid == xid && p->ip == ip && p->port);
270 +#endif /* _IP_CONNTRACK_RPC_H */
271 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
272 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
273 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-04-16 09:18:45.000000000 +0200
275 +/* RSH extension for IP connection tracking, Version 1.0
276 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
277 + * based on HW's ip_conntrack_irc.c
279 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
281 + * This program is free software; you can redistribute it and/or
282 + * modify it under the terms of the GNU General Public License
283 + * as published by the Free Software Foundation; either version
284 + * 2 of the License, or (at your option) any later version.
286 +#ifndef _IP_CONNTRACK_RSH_H
287 +#define _IP_CONNTRACK_RSH_H
290 +#include <linux/netfilter_ipv4/lockhelp.h>
292 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
296 +#define RSH_PORT 514
298 +/* This structure is per expected connection */
299 +struct ip_ct_rsh_expect
304 +/* This structure exists only once per master */
305 +struct ip_ct_rsh_master {
308 +#endif /* _IP_CONNTRACK_RSH_H */
310 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_talk.h
311 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
312 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-04-16 09:18:58.000000000 +0200
314 +#ifndef _IP_CONNTRACK_TALK_H
315 +#define _IP_CONNTRACK_TALK_H
316 +/* TALK tracking. */
319 +#include <linux/in.h>
320 +#include <linux/netfilter_ipv4/lockhelp.h>
322 +/* Protects talk part of conntracks */
323 +DECLARE_LOCK_EXTERN(ip_talk_lock);
327 +#define TALK_PORT 517
328 +#define NTALK_PORT 518
330 +/* talk structures and constants from <protocols/talkd.h> */
333 + * 4.3BSD struct sockaddr
336 + u_int16_t ta_family;
339 + u_int32_t ta_junk1;
340 + u_int32_t ta_junk2;
343 +#define TALK_OLD_NSIZE 9
344 +#define TALK_NSIZE 12
345 +#define TALK_TTY_NSIZE 16
348 + * Client->server request message formats.
351 + u_char type; /* request type, see below */
352 + char l_name[TALK_OLD_NSIZE];/* caller's name */
353 + char r_name[TALK_OLD_NSIZE];/* callee's name */
355 + u_int32_t id_num; /* message id */
356 + int32_t pid; /* caller's process id */
357 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
358 + struct talk_addr addr; /* old (4.3) style */
359 + struct talk_addr ctl_addr; /* old (4.3) style */
363 + u_char vers; /* protocol version */
364 + u_char type; /* request type, see below */
365 + u_char answer; /* not used */
367 + u_int32_t id_num; /* message id */
368 + struct talk_addr addr; /* old (4.3) style */
369 + struct talk_addr ctl_addr; /* old (4.3) style */
370 + int32_t pid; /* caller's process id */
371 + char l_name[TALK_NSIZE];/* caller's name */
372 + char r_name[TALK_NSIZE];/* callee's name */
373 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
377 + u_char vers; /* talk protocol version */
378 + u_char type; /* request type */
379 + u_char answer; /* */
380 + u_char extended; /* !0 if additional parts */
381 + u_int32_t id_num; /* message id number (dels) */
382 + struct talk_addr addr; /* target address */
383 + struct talk_addr ctl_addr; /* reply to address */
384 + int32_t pid; /* caller's process id */
385 + char l_name[TALK_NSIZE]; /* caller's name */
386 + char r_name[TALK_NSIZE]; /* callee's name */
387 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
391 + * Server->client response message formats.
393 +struct talk_response {
394 + u_char type; /* type of request message, see below */
395 + u_char answer; /* response to request message, see below */
397 + u_int32_t id_num; /* message id */
398 + struct talk_addr addr; /* address for establishing conversation */
401 +struct ntalk_response {
402 + u_char vers; /* protocol version */
403 + u_char type; /* type of request message, see below */
404 + u_char answer; /* response to request message, see below */
406 + u_int32_t id_num; /* message id */
407 + struct talk_addr addr; /* address for establishing conversation */
410 +struct ntalk2_response {
411 + u_char vers; /* protocol version */
412 + u_char type; /* type of request message */
413 + u_char answer; /* response to request */
414 + u_char rvers; /* Version of answering vers*/
415 + u_int32_t id_num; /* message id number */
416 + struct talk_addr addr; /* address for connection */
417 + /* This is at the end to compatiblize this with NTALK version. */
418 + char r_name[TALK_NSIZE]; /* callee's name */
421 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
422 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
423 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
425 +#define TALK_VERSION 0 /* protocol versions */
426 +#define NTALK_VERSION 1
427 +#define NTALK2_VERSION 2
429 +/* message type values */
430 +#define LEAVE_INVITE 0 /* leave invitation with server */
431 +#define LOOK_UP 1 /* check for invitation by callee */
432 +#define DELETE 2 /* delete invitation by caller */
433 +#define ANNOUNCE 3 /* announce invitation by caller */
435 +#define REPLY_QUERY 4 /* request reply data from local daemon */
438 +#define SUCCESS 0 /* operation completed properly */
439 +#define NOT_HERE 1 /* callee not logged in */
440 +#define FAILED 2 /* operation failed for unexplained reason */
441 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
442 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
443 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
444 +#define BADVERSION 6 /* request has invalid protocol version */
445 +#define BADADDR 7 /* request has invalid addr value */
446 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
448 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
449 +#define TRY_HERE 10 /* Not on this machine, try this */
450 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
451 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
453 +/* We don't really need much for talk */
454 +struct ip_ct_talk_expect
456 + /* Port that was to be used */
460 +/* This structure exists only once per master */
461 +struct ip_ct_talk_master
465 +#endif /* _IP_CONNTRACK_TALK_H */
466 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
467 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-15 03:35:20.000000000 +0200
468 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-16 09:18:47.000000000 +0200
478 /* The manipulable part of the tuple. */
489 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h
490 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
491 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-16 09:15:41.000000000 +0200
493 +#ifndef _IPT_CONNMARK_H_target
494 +#define _IPT_CONNMARK_H_target
496 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
497 + * by Henrik Nordstrom <hno@marasystems.com>
499 + * This program is free software; you can redistribute it and/or modify
500 + * it under the terms of the GNU General Public License as published by
501 + * the Free Software Foundation; either version 2 of the License, or
502 + * (at your option) any later version.
506 + IPT_CONNMARK_SET = 0,
508 + IPT_CONNMARK_RESTORE
511 +struct ipt_connmark_target_info {
512 + unsigned long mark;
513 + unsigned long mask;
517 +#endif /*_IPT_CONNMARK_H_target*/
518 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h
519 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
520 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-16 09:15:43.000000000 +0200
522 +#ifndef _IPT_IPMARK_H_target
523 +#define _IPT_IPMARK_H_target
525 +struct ipt_ipmark_target_info {
526 + unsigned long andmask;
527 + unsigned long ormask;
531 +#define IPT_IPMARK_SRC 0
532 +#define IPT_IPMARK_DST 1
534 +#endif /*_IPT_IPMARK_H_target*/
535 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_ROUTE.h
536 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
537 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_ROUTE.h 2004-04-16 09:15:44.000000000 +0200
539 +/* Header file for iptables ipt_ROUTE target
541 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
543 + * This software is distributed under GNU GPL v2, 1991
545 +#ifndef _IPT_ROUTE_H_target
546 +#define _IPT_ROUTE_H_target
548 +#define IPT_ROUTE_IFNAMSIZ 16
550 +struct ipt_route_target_info {
551 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
552 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
553 + u_int32_t gw; /* IP address of gateway */
557 +/* Values for "flags" field */
558 +#define IPT_ROUTE_CONTINUE 0x01
560 +#endif /*_IPT_ROUTE_H_target*/
561 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_TCPLAG.h
562 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h 1970-01-01 01:00:00.000000000 +0100
563 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_TCPLAG.h 2004-04-16 09:15:55.000000000 +0200
565 +#ifndef _IPT_TCPLAG_H
566 +#define _IPT_TCPLAG_H
570 + unsigned char level;
571 + unsigned char prefix[ 15 ];
575 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_XOR.h
576 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
577 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-16 09:16:25.000000000 +0200
582 +struct ipt_XOR_info {
584 + u_int8_t block_size;
587 +#endif /* _IPT_XOR_H */
588 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h
589 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
590 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-16 09:16:27.000000000 +0200
592 +#ifndef _IPT_ADDRTYPE_H
593 +#define _IPT_ADDRTYPE_H
595 +struct ipt_addrtype_info {
596 + u_int16_t source; /* source-type mask */
597 + u_int16_t dest; /* dest-type mask */
603 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_connmark.h
604 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
605 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-16 09:15:41.000000000 +0200
607 +#ifndef _IPT_CONNMARK_H
608 +#define _IPT_CONNMARK_H
610 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
611 + * by Henrik Nordstrom <hno@marasystems.com>
613 + * This program is free software; you can redistribute it and/or modify
614 + * it under the terms of the GNU General Public License as published by
615 + * the Free Software Foundation; either version 2 of the License, or
616 + * (at your option) any later version.
619 +struct ipt_connmark_info {
620 + unsigned long mark, mask;
624 +#endif /*_IPT_CONNMARK_H*/
625 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_policy.h
626 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
627 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-16 09:18:18.000000000 +0200
629 +#ifndef _IPT_POLICY_H
630 +#define _IPT_POLICY_H
632 +#define POLICY_MAX_ELEM 4
634 +enum ipt_policy_flags
636 + POLICY_MATCH_IN = 0x1,
637 + POLICY_MATCH_OUT = 0x2,
638 + POLICY_MATCH_NONE = 0x4,
639 + POLICY_MATCH_STRICT = 0x8,
642 +enum ipt_policy_modes
644 + POLICY_MODE_TRANSPORT,
648 +struct ipt_policy_spec
658 +struct ipt_policy_elem
669 + struct ipt_policy_spec match;
670 + struct ipt_policy_spec invert;
673 +struct ipt_policy_info
675 + struct ipt_policy_elem pol[POLICY_MAX_ELEM];
680 +#endif /* _IPT_POLICY_H */
681 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_rpc.h
682 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
683 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_rpc.h 2004-04-16 09:18:44.000000000 +0200
685 +/* RPC extension for IP netfilter matching, Version 2.2
686 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
687 + * - original rpc tracking module
688 + * - "recent" connection handling for kernel 2.3+ netfilter
690 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
691 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
693 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
694 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
695 + * - extended matching to support filtering on procedures
697 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
699 + * This program is free software; you can redistribute it and/or
700 + * modify it under the terms of the GNU General Public License
701 + * as published by the Free Software Foundation; either version
702 + * 2 of the License, or (at your option) any later version.
709 +struct ipt_rpc_data;
711 +struct ipt_rpc_info {
714 + const char c_procs[1408];
716 + struct ipt_rpc_data *data;
719 +#endif /* _IPT_RPC_H */
720 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_string.h
721 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
722 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_string.h 2004-04-16 09:19:37.000000000 +0200
724 +#ifndef _IPT_STRING_H
725 +#define _IPT_STRING_H
727 +/* *** PERFORMANCE TWEAK ***
728 + * Packet size and search string threshold,
729 + * above which sublinear searches is used. */
730 +#define IPT_STRING_HAYSTACK_THRESH 100
731 +#define IPT_STRING_NEEDLE_THRESH 20
733 +#define BM_MAX_NLEN 256
734 +#define BM_MAX_HLEN 1024
736 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
738 +struct ipt_string_info {
739 + char string[BM_MAX_NLEN];
744 +#endif /* _IPT_STRING_H */
745 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc1/include/linux/netfilter_ipv4.h
746 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4.h 2004-04-16 08:59:08.000000000 +0200
747 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4.h 2004-04-16 09:17:09.000000000 +0200
750 #include <linux/config.h>
751 #include <linux/netfilter.h>
752 +#include <linux/netdevice.h>
753 +#include <net/protocol.h>
756 /* Src IP address. */
758 Returns true or false. */
759 extern int skb_ip_make_writable(struct sk_buff **pskb,
760 unsigned int writable_len);
763 +#include <net/route.h>
764 +#include <net/xfrm.h>
766 +static inline int nf_hook_input_cond(struct sk_buff *skb)
768 + return !skb->sp || skb->sp->decap_done;
772 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
774 + return skb->sp && !skb->sp->decap_done
775 + && (!ipprot || !ipprot->xfrm_prot);
778 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
780 + return skb->sp && !skb->sp->decap_done
781 + && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
784 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
785 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
786 +#else /* CONFIG_XFRM */
787 +static inline int nf_hook_input_cond(struct sk_buff *skb)
793 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
798 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
803 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
808 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
812 +#endif /* CONFIG_XFRM */
813 #endif /*__KERNEL__*/
815 #endif /*__LINUX_IP_NETFILTER_H*/
816 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_ROUTE.h
817 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
818 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2004-04-16 09:15:44.000000000 +0200
820 +/* Header file for iptables ip6t_ROUTE target
822 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
824 + * This software is distributed under GNU GPL v2, 1991
826 +#ifndef _IPT_ROUTE_H_target
827 +#define _IPT_ROUTE_H_target
829 +#define IP6T_ROUTE_IFNAMSIZ 16
831 +struct ip6t_route_target_info {
832 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
833 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
834 + u_int32_t gw[4]; /* IPv6 address of gateway */
838 +/* Values for "flags" field */
839 +#define IP6T_ROUTE_CONTINUE 0x01
841 +#endif /*_IP6T_ROUTE_H_target*/
842 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_owner.h
843 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-15 03:35:08.000000000 +0200
844 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-16 09:18:17.000000000 +0200
846 #define IP6T_OWNER_GID 0x02
847 #define IP6T_OWNER_PID 0x04
848 #define IP6T_OWNER_SID 0x08
849 +#define IP6T_OWNER_COMM 0x10
851 struct ip6t_owner_info {
857 u_int8_t match, invert; /* flags */
860 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/ip.h linux-2.6.6-rc1/include/net/ip.h
861 --- linux-2.6.6-rc1.org/include/net/ip.h 2004-04-15 03:35:18.000000000 +0200
862 +++ linux-2.6.6-rc1/include/net/ip.h 2004-04-16 09:17:07.000000000 +0200
864 #include <linux/netdevice.h>
865 #include <linux/inetdevice.h>
866 #include <linux/in_route.h>
867 +#include <linux/netfilter.h>
868 +#include <linux/netfilter_ipv4.h>
869 #include <net/route.h>
873 #define IPSKB_TRANSLATED 2
874 #define IPSKB_FORWARDED 4
875 #define IPSKB_XFRM_TUNNEL_SIZE 8
876 +#define IPSKB_XFRM_TRANSFORMED 16
881 __ip_select_ident(iph, dst, more);
884 +extern inline int ip_dst_output(struct sk_buff *skb)
886 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
887 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
891 * Map a multicast IP onto multicast MAC for type ethernet.
893 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/protocol.h linux-2.6.6-rc1/include/net/protocol.h
894 --- linux-2.6.6-rc1.org/include/net/protocol.h 2004-04-15 03:34:36.000000000 +0200
895 +++ linux-2.6.6-rc1/include/net/protocol.h 2004-04-16 09:17:09.000000000 +0200
897 int (*handler)(struct sk_buff *skb);
898 void (*err_handler)(struct sk_buff *skb, u32 info);
903 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
904 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/tcp.h linux-2.6.6-rc1/include/net/tcp.h
905 --- linux-2.6.6-rc1.org/include/net/tcp.h 2004-04-15 03:33:55.000000000 +0200
906 +++ linux-2.6.6-rc1/include/net/tcp.h 2004-04-16 09:18:14.000000000 +0200
908 extern void tcp_bucket_unlock(struct sock *sk);
909 extern int tcp_port_rover;
910 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
911 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
913 /* These are AF independent. */
914 static __inline__ int tcp_bhashfn(__u16 lport)
915 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/udp.h linux-2.6.6-rc1/include/net/udp.h
916 --- linux-2.6.6-rc1.org/include/net/udp.h 2004-04-15 03:35:20.000000000 +0200
917 +++ linux-2.6.6-rc1/include/net/udp.h 2004-04-16 09:18:14.000000000 +0200
919 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
920 extern int udp_disconnect(struct sock *sk, int flags);
922 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
924 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
925 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
926 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
927 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/xfrm.h linux-2.6.6-rc1/include/net/xfrm.h
928 --- linux-2.6.6-rc1.org/include/net/xfrm.h 2004-04-15 03:35:36.000000000 +0200
929 +++ linux-2.6.6-rc1/include/net/xfrm.h 2004-04-16 09:17:09.000000000 +0200
934 +#ifdef CONFIG_NETFILTER
937 struct sec_decap_state x[XFRM_MAX_DEPTH];
940 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/core/netfilter.c linux-2.6.6-rc1/net/core/netfilter.c
941 --- linux-2.6.6-rc1.org/net/core/netfilter.c 2004-04-16 08:59:08.000000000 +0200
942 +++ linux-2.6.6-rc1/net/core/netfilter.c 2004-04-16 09:17:13.000000000 +0200
944 #include <linux/icmp.h>
945 #include <net/sock.h>
946 #include <net/route.h>
947 +#include <net/xfrm.h>
949 #include <linux/ip.h>
951 /* In this code, we can be waiting indefinitely for userspace to
953 #ifdef CONFIG_IP_ROUTE_FWMARK
954 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
956 - fl.proto = iph->protocol;
957 if (ip_route_output_key(&rt, &fl) != 0)
961 if ((*pskb)->dst->error)
965 + if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
966 + struct xfrm_policy_afinfo *afinfo;
968 + afinfo = xfrm_policy_get_afinfo(AF_INET);
969 + if (afinfo != NULL) {
970 + afinfo->decode_session(*pskb, &fl);
971 + xfrm_policy_put_afinfo(afinfo);
972 + if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
978 /* Change in oif may mean change in hh_len. */
979 hh_len = (*pskb)->dst->dev->hard_header_len;
980 if (skb_headroom(*pskb) < hh_len) {
986 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
988 + skb->sp->decap_done = 1;
989 + dst_release(skb->dst);
992 + return netif_rx(skb);
995 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
997 + __skb_push(skb, skb->data - skb->nh.raw);
998 + /* Fix header len and checksum if last xfrm was transport mode */
999 + if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
1000 + skb->nh.iph->tot_len = htons(skb->len);
1001 + ip_send_check(skb->nh.iph);
1003 + return nf_rcv_postxfrm_nonlocal(skb);
1006 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1007 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1008 +#include <linux/netfilter_ipv4/ip_nat.h>
1010 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
1012 + struct ip_conntrack *ct;
1013 + struct ip_conntrack_tuple *t;
1014 + struct ip_nat_info_manip *m;
1017 + if (skb->nfct == NULL)
1019 + ct = (struct ip_conntrack *)skb->nfct->master;
1021 + for (i = 0; i < ct->nat.info.num_manips; i++) {
1022 + m = &ct->nat.info.manips[i];
1023 + t = &ct->tuplehash[m->direction].tuple;
1025 + switch (m->hooknum) {
1026 + case NF_IP_PRE_ROUTING:
1027 + if (m->maniptype != IP_NAT_MANIP_DST)
1029 + fl->fl4_dst = t->dst.ip;
1030 + if (t->dst.protonum == IPPROTO_TCP ||
1031 + t->dst.protonum == IPPROTO_UDP)
1032 + fl->fl_ip_dport = t->dst.u.tcp.port;
1034 +#ifdef CONFIG_IP_NF_NAT_LOCAL
1035 + case NF_IP_LOCAL_IN:
1036 + if (m->maniptype != IP_NAT_MANIP_SRC)
1038 + fl->fl4_src = t->src.ip;
1039 + if (t->dst.protonum == IPPROTO_TCP ||
1040 + t->dst.protonum == IPPROTO_UDP)
1041 + fl->fl_ip_sport = t->src.u.tcp.port;
1047 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
1050 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1052 struct sk_buff *nskb;
1053 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ah4.c linux-2.6.6-rc1/net/ipv4/ah4.c
1054 --- linux-2.6.6-rc1.org/net/ipv4/ah4.c 2004-04-15 03:35:37.000000000 +0200
1055 +++ linux-2.6.6-rc1/net/ipv4/ah4.c 2004-04-16 09:17:09.000000000 +0200
1057 err = -EHOSTUNREACH;
1060 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1061 return NET_XMIT_BYPASS;
1065 .handler = xfrm4_rcv,
1066 .err_handler = ah4_err,
1071 static int __init ah4_init(void)
1072 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/esp4.c linux-2.6.6-rc1/net/ipv4/esp4.c
1073 --- linux-2.6.6-rc1.org/net/ipv4/esp4.c 2004-04-15 03:35:04.000000000 +0200
1074 +++ linux-2.6.6-rc1/net/ipv4/esp4.c 2004-04-16 09:17:09.000000000 +0200
1076 err = -EHOSTUNREACH;
1079 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1080 return NET_XMIT_BYPASS;
1084 .handler = xfrm4_rcv,
1085 .err_handler = esp4_err,
1090 static int __init esp4_init(void)
1091 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/igmp.c linux-2.6.6-rc1/net/ipv4/igmp.c
1092 --- linux-2.6.6-rc1.org/net/ipv4/igmp.c 2004-04-15 03:36:01.000000000 +0200
1093 +++ linux-2.6.6-rc1/net/ipv4/igmp.c 2004-04-16 09:17:07.000000000 +0200
1095 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
1097 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
1102 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
1104 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
1106 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1111 static void igmp_gq_timer_expire(unsigned long data)
1112 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ip_forward.c linux-2.6.6-rc1/net/ipv4/ip_forward.c
1113 --- linux-2.6.6-rc1.org/net/ipv4/ip_forward.c 2004-04-15 03:33:50.000000000 +0200
1114 +++ linux-2.6.6-rc1/net/ipv4/ip_forward.c 2004-04-16 09:17:07.000000000 +0200
1116 if (unlikely(opt->optlen))
1117 ip_forward_options(skb);
1119 - return dst_output(skb);
1120 + return ip_dst_output(skb);
1123 int ip_forward(struct sk_buff *skb)
1124 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ip_input.c linux-2.6.6-rc1/net/ipv4/ip_input.c
1125 --- linux-2.6.6-rc1.org/net/ipv4/ip_input.c 2004-04-16 08:59:08.000000000 +0200
1126 +++ linux-2.6.6-rc1/net/ipv4/ip_input.c 2004-04-16 09:17:13.000000000 +0200
1127 @@ -206,10 +206,6 @@
1129 __skb_pull(skb, ihl);
1131 - /* Free reference early: we don't need it any more, and it may
1132 - hold ip_conntrack module loaded indefinitely. */
1135 /* Point into the IP datagram, just past the header. */
1136 skb->h.raw = skb->data;
1138 @@ -224,6 +220,13 @@
1140 hash = protocol & (MAX_INET_PROTOS - 1);
1141 raw_sk = sk_head(&raw_v4_htable[hash]);
1142 + ipprot = inet_protos[hash];
1143 + smp_read_barrier_depends();
1145 + if (nf_xfrm_local_done(skb, ipprot)) {
1146 + nf_rcv_postxfrm_local(skb);
1150 /* If there maybe a raw socket we must check - if not we
1152 @@ -231,14 +234,15 @@
1154 raw_v4_input(skb, skb->nh.iph, hash);
1156 - if ((ipprot = inet_protos[hash]) != NULL) {
1157 + if (ipprot != NULL) {
1160 - smp_read_barrier_depends();
1161 - if (!ipprot->no_policy &&
1162 - !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1165 + if (!ipprot->no_policy) {
1166 + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1172 ret = ipprot->handler(skb);
1178 - return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1179 - ip_local_deliver_finish);
1180 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1181 + ip_local_deliver_finish, nf_hook_input_cond(skb));
1184 static inline int ip_rcv_finish(struct sk_buff *skb)
1189 + if (nf_xfrm_nonlocal_done(skb))
1190 + return nf_rcv_postxfrm_nonlocal(skb);
1192 #ifdef CONFIG_NET_CLS_ROUTE
1193 if (skb->dst->tclassid) {
1194 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
1199 - return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1201 + return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1202 + ip_rcv_finish, nf_hook_input_cond(skb));
1205 IP_INC_STATS_BH(IpInHdrErrors);
1206 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ip_output.c linux-2.6.6-rc1/net/ipv4/ip_output.c
1207 --- linux-2.6.6-rc1.org/net/ipv4/ip_output.c 2004-04-15 03:36:01.000000000 +0200
1208 +++ linux-2.6.6-rc1/net/ipv4/ip_output.c 2004-04-16 09:17:07.000000000 +0200
1209 @@ -123,6 +123,15 @@
1213 +#ifdef CONFIG_NETFILTER
1214 +/* out-of-line copy is only required with netfilter */
1215 +int ip_dst_output(struct sk_buff *skb)
1217 + return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1218 + skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1223 * Add an ip header to a skbuff and send it out.
1228 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1233 static inline int ip_finish_output2(struct sk_buff *skb)
1235 return ip_finish_output(skb);
1238 -int ip_output(struct sk_buff *skb)
1239 +static inline int ip_output2(struct sk_buff *skb)
1241 IP_INC_STATS(IpOutRequests);
1243 @@ -294,6 +303,16 @@
1244 return ip_finish_output(skb);
1247 +int ip_output(struct sk_buff *skb)
1249 + int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
1253 + return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1254 + skb->dst->dev, ip_output2, transformed);
1257 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
1259 struct sock *sk = skb->sk;
1261 skb->priority = sk->sk_priority;
1263 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1268 IP_INC_STATS(IpOutNoRoutes);
1269 @@ -1177,7 +1196,7 @@
1271 /* Netfilter gets whole the not fragmented skb. */
1272 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1273 - skb->dst->dev, dst_output);
1274 + skb->dst->dev, ip_dst_output);
1277 err = inet->recverr ? net_xmit_errno(err) : 0;
1278 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ipcomp.c linux-2.6.6-rc1/net/ipv4/ipcomp.c
1279 --- linux-2.6.6-rc1.org/net/ipv4/ipcomp.c 2004-04-15 03:35:37.000000000 +0200
1280 +++ linux-2.6.6-rc1/net/ipv4/ipcomp.c 2004-04-16 09:17:09.000000000 +0200
1282 err = -EHOSTUNREACH;
1285 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1286 err = NET_XMIT_BYPASS;
1290 .handler = xfrm4_rcv,
1291 .err_handler = ipcomp4_err,
1296 static int __init ipcomp4_init(void)
1297 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ipip.c linux-2.6.6-rc1/net/ipv4/ipip.c
1298 --- linux-2.6.6-rc1.org/net/ipv4/ipip.c 2004-04-16 08:59:08.000000000 +0200
1299 +++ linux-2.6.6-rc1/net/ipv4/ipip.c 2004-04-16 09:17:09.000000000 +0200
1300 @@ -478,6 +478,11 @@
1302 read_lock(&ipip_lock);
1303 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
1304 + /* IPIP packets decapsulated by IPsec missed netfilter hooks */
1305 + if (nf_xfrm_local_done(skb, NULL)) {
1306 + nf_rcv_postxfrm_local(skb);
1309 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1312 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ipmr.c linux-2.6.6-rc1/net/ipv4/ipmr.c
1313 --- linux-2.6.6-rc1.org/net/ipv4/ipmr.c 2004-04-15 03:34:48.000000000 +0200
1314 +++ linux-2.6.6-rc1/net/ipv4/ipmr.c 2004-04-16 09:17:07.000000000 +0200
1315 @@ -1120,7 +1120,7 @@
1316 if (unlikely(opt->optlen))
1317 ip_forward_options(skb);
1319 - return dst_output(skb);
1320 + return ip_dst_output(skb);
1324 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc1/net/ipv4/netfilter/Kconfig
1325 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/Kconfig 2004-04-16 08:59:09.000000000 +0200
1326 +++ linux-2.6.6-rc1/net/ipv4/netfilter/Kconfig 2004-04-16 09:19:38.000000000 +0200
1327 @@ -206,6 +206,11 @@
1329 To compile it as a module, choose M here. If unsure, say N.
1331 +config IP_NF_MATCH_UNCLEAN
1332 + tristate 'unclean match support (EXPERIMENTAL)'
1333 + depends on EXPERIMENTAL && IP_NF_IPTABLES
1336 config IP_NF_MATCH_TTL
1337 tristate "TTL match support"
1338 depends on IP_NF_IPTABLES
1339 @@ -510,6 +515,38 @@
1341 To compile it as a module, choose M here. If unsure, say N.
1343 +config IP_NF_TARGET_TARPIT
1344 + tristate "TARPIT target support"
1345 + depends on IP_NF_IPTABLES
1347 + Adds a TARPIT target to iptables, which captures and holds
1348 + incoming TCP connections using no local per-connection resources.
1349 + Connections are accepted, but immediately switched to the persist
1350 + state (0 byte window), in which the remote side stops sending data
1351 + and asks to continue every 60-240 seconds. Attempts to close the
1352 + connection are ignored, forcing the remote side to time out the
1353 + connection in 12-24 minutes.
1355 + This offers similar functionality to LaBrea
1356 + <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
1357 + hardware or IPs. Any TCP port that you would normally DROP or REJECT
1358 + can instead become a tarpit.
1360 + To tarpit connections to TCP port 80 destined for the current machine:
1362 + iptables -A INPUT -p tcp -m tcp --dport 80 -j TARPIT
1364 + To significantly slow down Code Red/Nimda-style scans of unused
1365 + address space, forward unused ip addresses to a Linux box not acting
1366 + as a router (e.g. "ip route 10.0.0.0 255.0.0.0 ip.of.linux.box" on a Cisco),
1367 + enable IP forwarding on the Linux box, and add:
1369 + iptables -A FORWARD -p tcp -j TARPIT
1370 + iptables -A FORWARD -j DROP
1372 + You probably don't want the conntrack module loaded while you are using
1373 + TARPIT, or you will be using resources per connection.
1375 config IP_NF_TARGET_TCPMSS
1376 tristate "TCPMSS target support"
1377 depends on IP_NF_IPTABLES
1378 @@ -706,5 +743,114 @@
1379 depends on IP_NF_IPTABLES
1382 +config IP_NF_CONNTRACK_MARK
1383 + bool 'Connection mark tracking support'
1384 +config IP_NF_TARGET_CONNMARK
1385 + tristate 'CONNMARK target support'
1386 + depends on IP_NF_MANGLE
1387 +config IP_NF_MATCH_CONNMARK
1388 + tristate ' Connection mark match support'
1389 + depends on IP_NF_IPTABLES
1392 +config IP_NF_TARGET_IPMARK
1393 + tristate 'IPMARK target support'
1394 + depends on IP_NF_MANGLE
1397 +config IP_NF_TARGET_ROUTE
1398 + tristate 'ROUTE target support'
1399 + depends on IP_NF_MANGLE
1402 +config IP_NF_TARGET_TCPLAG
1403 + tristate 'TCPLAG target support'
1404 + depends on IP_NF_IPTABLES
1407 +config IP_NF_TARGET_XOR
1408 + tristate 'XOR target support'
1409 + depends on IP_NF_MANGLE
1412 +config IP_NF_MATCH_ADDRTYPE
1413 + tristate 'address type match support'
1414 + depends on IP_NF_IPTABLES
1417 +config IP_NF_NAT_H323
1419 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1420 + default IP_NF_NAT if IP_NF_H323=y
1421 + default m if IP_NF_H323=m
1424 + tristate 'H.323 (netmeeting) support'
1425 + depends on IP_NF_CONNTRACK
1428 +config IP_NF_NAT_MMS
1430 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1431 + default IP_NF_NAT if IP_NF_MMS=y
1432 + default m if IP_NF_MMS=m
1435 + tristate 'MMS protocol support'
1436 + depends on IP_NF_CONNTRACK
1439 +config IP_NF_MATCH_POLICY
1440 + tristate "IPsec policy match support"
1441 + depends on IP_NF_IPTABLES && XFRM
1443 + Policy matching allows you to match packets based on the
1444 + IPsec policy that was used during decapsulation/will
1445 + be used during encapsulation.
1447 + To compile it as a module, choose M here. If unsure, say N.
1450 +config IP_NF_NAT_QUAKE3
1452 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1453 + default IP_NF_NAT if IP_NF_QUAKE3=y
1454 + default m if IP_NF_QUAKE3=m
1456 +config IP_NF_QUAKE3
1457 + tristate "Quake3 protocol support"
1458 + depends on IP_NF_CONNTRACK
1461 +config IP_NF_MATCH_RPC
1462 + tristate 'RPC match support'
1463 + depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1467 + tristate 'RSH protocol support'
1468 + depends on IP_NF_CONNTRACK
1471 +config IP_NF_CT_PROTO_SCTP
1472 + tristate 'SCTP protocol connection tracking support'
1473 + depends on IP_NF_CONNTRACK
1476 +config IP_NF_NAT_TALK
1478 + depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1479 + default IP_NF_NAT if IP_NF_TALK=y
1480 + default m if IP_NF_TALK=m
1482 + tristate 'talk protocol support'
1483 + depends on IP_NF_CONNTRACK
1486 +config IP_NF_MATCH_STRING
1487 + tristate 'String match support'
1488 + depends on IP_NF_IPTABLES
1493 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc1/net/ipv4/netfilter/Makefile
1494 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/Makefile 2004-04-16 08:59:09.000000000 +0200
1495 +++ linux-2.6.6-rc1/net/ipv4/netfilter/Makefile 2004-04-16 09:19:38.000000000 +0200
1497 # connection tracking
1498 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1500 +# talk protocol support
1501 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1502 +ifdef CONFIG_IP_NF_TALK
1503 + export-objs += ip_conntrack_talk.o
1505 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1508 +# SCTP protocol connection tracking
1509 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
1512 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1513 +ifdef CONFIG_IP_NF_H323
1514 + export-objs += ip_conntrack_h323.o
1516 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1519 # connection tracking helpers
1520 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1521 +ifdef CONFIG_IP_NF_NAT_QUAKE3
1522 + export-objs += ip_conntrack_quake3.o
1524 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1525 +ifdef CONFIG_IP_NF_MMS
1526 + export-objs += ip_conntrack_mms.o
1528 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1529 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1530 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1531 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1533 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1537 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1538 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1539 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1540 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1541 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1544 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1546 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1549 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1550 +export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
1552 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1553 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1554 obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1555 @@ -87,14 +121,19 @@
1556 obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1559 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
1560 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
1561 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1562 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1563 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
1564 obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1565 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1566 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1567 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
1568 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1570 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1571 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
1574 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
1575 @@ -102,18 +141,24 @@
1576 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
1577 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
1578 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
1579 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
1580 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
1581 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
1582 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
1583 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
1584 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
1585 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
1586 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1587 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1588 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1589 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
1590 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
1591 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
1592 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1593 obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1594 obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1595 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1596 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
1597 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1598 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1600 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_core.c
1601 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-16 08:59:08.000000000 +0200
1602 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-16 09:15:41.000000000 +0200
1604 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1605 conntrack->master = expected;
1606 expected->sibling = conntrack;
1607 +#if CONFIG_IP_NF_CONNTRACK_MARK
1608 + conntrack->mark = expected->expectant->mark;
1610 LIST_DELETE(&ip_conntrack_expect_list, expected);
1611 expected->expectant->expecting--;
1612 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1613 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_h323.c
1614 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
1615 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_h323.c 2004-04-16 09:17:05.000000000 +0200
1618 + * H.323 'brute force' extension for H.323 connection tracking.
1619 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
1621 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
1622 + * (http://www.coritel.it/projects/sofia/nat/)
1623 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
1624 + * the unregistered helpers to the conntrack entries.
1628 +#include <linux/module.h>
1629 +#include <linux/netfilter.h>
1630 +#include <linux/ip.h>
1631 +#include <net/checksum.h>
1632 +#include <net/tcp.h>
1634 +#include <linux/netfilter_ipv4/lockhelp.h>
1635 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1636 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1637 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1638 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
1639 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
1641 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
1642 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
1643 +MODULE_LICENSE("GPL");
1645 +DECLARE_LOCK(ip_h323_lock);
1646 +struct module *ip_conntrack_h323 = THIS_MODULE;
1649 +#define DEBUGP printk
1651 +#define DEBUGP(format, args...)
1654 +/* FIXME: This should be in userspace. Later. */
1655 +static int h245_help(const struct iphdr *iph, size_t len,
1656 + struct ip_conntrack *ct,
1657 + enum ip_conntrack_info ctinfo)
1659 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
1660 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
1661 + unsigned char *data_limit;
1662 + u_int32_t tcplen = len - iph->ihl * 4;
1663 + u_int32_t datalen = tcplen - tcph->doff * 4;
1664 + int dir = CTINFO2DIR(ctinfo);
1665 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
1666 + struct ip_conntrack_expect expect, *exp = &expect;
1667 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
1668 + u_int16_t data_port;
1669 + u_int32_t data_ip;
1672 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1673 + NIPQUAD(iph->saddr), ntohs(tcph->source),
1674 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
1676 + /* Can't track connections formed before we registered */
1680 + /* Until there's been traffic both ways, don't look in packets. */
1681 + if (ctinfo != IP_CT_ESTABLISHED
1682 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1683 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
1687 + /* Not whole TCP header or too short packet? */
1688 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
1689 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
1693 + /* Checksum invalid? Ignore. */
1694 + /* FIXME: Source route IP option packets --RR */
1695 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1696 + csum_partial((char *)tcph, tcplen, 0))) {
1697 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
1698 + tcph, tcplen, NIPQUAD(iph->saddr),
1699 + NIPQUAD(iph->daddr));
1703 + data_limit = (unsigned char *) data + datalen;
1706 + for (i = 0; data < (data_limit - 5); data++, i++) {
1707 + data_ip = *((u_int32_t *)data);
1708 + if (data_ip == iph->saddr) {
1709 + data_port = *((u_int16_t *)(data + 4));
1710 + memset(&expect, 0, sizeof(expect));
1711 + /* update the H.225 info */
1712 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
1713 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
1714 + NIPQUAD(iph->saddr), ntohs(data_port));
1715 + LOCK_BH(&ip_h323_lock);
1716 + info->is_h225 = H225_PORT + 1;
1717 + exp_info->port = data_port;
1718 + exp_info->dir = dir;
1719 + exp_info->offset = i;
1721 + exp->seq = ntohl(tcph->seq) + i;
1723 + exp->tuple = ((struct ip_conntrack_tuple)
1724 + { { ct->tuplehash[!dir].tuple.src.ip,
1727 + { .tcp = { data_port } },
1729 + exp->mask = ((struct ip_conntrack_tuple)
1730 + { { 0xFFFFFFFF, { 0 } },
1731 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
1733 + exp->expectfn = NULL;
1735 + /* Ignore failure; should only happen with NAT */
1736 + ip_conntrack_expect_related(ct, exp);
1738 + UNLOCK_BH(&ip_h323_lock);
1746 +/* H.245 helper is not registered! */
1747 +static struct ip_conntrack_helper h245 =
1749 + "H.245", /* name */
1750 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
1751 + NULL, /* module */
1752 + 8, /* max_ expected */
1753 + 240, /* timeout */
1754 + { { 0, { 0 } }, /* tuple */
1755 + { 0, { 0 }, IPPROTO_TCP } },
1756 + { { 0, { 0xFFFF } }, /* mask */
1757 + { 0, { 0 }, 0xFFFF } },
1758 + h245_help /* helper */
1761 +static int h225_expect(struct ip_conntrack *ct)
1763 + WRITE_LOCK(&ip_conntrack_lock);
1764 + ct->helper = &h245;
1765 + DEBUGP("h225_expect: helper for %p added\n", ct);
1766 + WRITE_UNLOCK(&ip_conntrack_lock);
1768 + return NF_ACCEPT; /* unused */
1771 +/* FIXME: This should be in userspace. Later. */
1772 +static int h225_help(const struct iphdr *iph, size_t len,
1773 + struct ip_conntrack *ct,
1774 + enum ip_conntrack_info ctinfo)
1776 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
1777 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
1778 + unsigned char *data_limit;
1779 + u_int32_t tcplen = len - iph->ihl * 4;
1780 + u_int32_t datalen = tcplen - tcph->doff * 4;
1781 + int dir = CTINFO2DIR(ctinfo);
1782 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
1783 + struct ip_conntrack_expect expect, *exp = &expect;
1784 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
1785 + u_int16_t data_port;
1786 + u_int32_t data_ip;
1789 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1790 + NIPQUAD(iph->saddr), ntohs(tcph->source),
1791 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
1793 + /* Can't track connections formed before we registered */
1797 + /* Until there's been traffic both ways, don't look in packets. */
1798 + if (ctinfo != IP_CT_ESTABLISHED
1799 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1800 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
1804 + /* Not whole TCP header or too short packet? */
1805 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
1806 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
1810 + /* Checksum invalid? Ignore. */
1811 + /* FIXME: Source route IP option packets --RR */
1812 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1813 + csum_partial((char *)tcph, tcplen, 0))) {
1814 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
1815 + tcph, tcplen, NIPQUAD(iph->saddr),
1816 + NIPQUAD(iph->daddr));
1820 + data_limit = (unsigned char *) data + datalen;
1823 + for (i = 0; data < (data_limit - 5); data++, i++) {
1824 + data_ip = *((u_int32_t *)data);
1825 + if (data_ip == iph->saddr) {
1826 + data_port = *((u_int16_t *)(data + 4));
1827 + if (data_port == tcph->source) {
1828 + /* Signal address */
1829 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
1830 + NIPQUAD(iph->saddr));
1831 + /* Update the H.225 info so that NAT can mangle the address/port
1832 + even when we have no expected connection! */
1833 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1834 + LOCK_BH(&ip_h323_lock);
1836 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
1837 + info->offset[IP_CT_DIR_ORIGINAL] = i;
1838 + UNLOCK_BH(&ip_h323_lock);
1841 + memset(&expect, 0, sizeof(expect));
1843 + /* update the H.225 info */
1844 + LOCK_BH(&ip_h323_lock);
1845 + info->is_h225 = H225_PORT;
1846 + exp_info->port = data_port;
1847 + exp_info->dir = dir;
1848 + exp_info->offset = i;
1850 + exp->seq = ntohl(tcph->seq) + i;
1852 + exp->tuple = ((struct ip_conntrack_tuple)
1853 + { { ct->tuplehash[!dir].tuple.src.ip,
1856 + { .tcp = { data_port } },
1858 + exp->mask = ((struct ip_conntrack_tuple)
1859 + { { 0xFFFFFFFF, { 0 } },
1860 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
1862 + exp->expectfn = h225_expect;
1864 + /* Ignore failure */
1865 + ip_conntrack_expect_related(ct, exp);
1867 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
1868 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
1869 + NIPQUAD(iph->saddr), ntohs(data_port));
1871 + UNLOCK_BH(&ip_h323_lock);
1873 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1874 + } else if (data_ip == iph->daddr) {
1875 + data_port = *((u_int16_t *)(data + 4));
1876 + if (data_port == tcph->dest) {
1877 + /* Signal address */
1878 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
1879 + NIPQUAD(iph->daddr));
1880 + /* Update the H.225 info so that NAT can mangle the address/port
1881 + even when we have no expected connection! */
1882 + LOCK_BH(&ip_h323_lock);
1884 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
1885 + info->offset[IP_CT_DIR_REPLY] = i;
1886 + UNLOCK_BH(&ip_h323_lock);
1896 +static struct ip_conntrack_helper h225 =
1898 + "H.225", /* name */
1899 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
1900 + THIS_MODULE, /* module */
1901 + 2, /* max_expected */
1902 + 240, /* timeout */
1903 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
1904 + { 0, { 0 }, IPPROTO_TCP } },
1905 + { { 0, { 0xFFFF } }, /* mask */
1906 + { 0, { 0 }, 0xFFFF } },
1907 + h225_help /* helper */
1910 +static int __init init(void)
1912 + return ip_conntrack_helper_register(&h225);
1915 +static void __exit fini(void)
1917 + /* Unregister H.225 helper */
1918 + ip_conntrack_helper_unregister(&h225);
1921 +EXPORT_SYMBOL(ip_h323_lock);
1925 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_mms.c
1926 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
1927 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_mms.c 2004-04-16 09:17:32.000000000 +0200
1929 +/* MMS extension for IP connection tracking
1930 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
1931 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
1933 + * ip_conntrack_mms.c v0.3 2002-09-22
1935 + * This program is free software; you can redistribute it and/or
1936 + * modify it under the terms of the GNU General Public License
1937 + * as published by the Free Software Foundation; either version
1938 + * 2 of the License, or (at your option) any later version.
1940 + * Module load syntax:
1941 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
1943 + * Please give the ports of all MMS servers You wish to connect to.
1944 + * If you don't specify ports, the default will be TCP port 1755.
1946 + * More info on MMS protocol, firewalls and NAT:
1947 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
1948 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
1950 + * The SDP project people are reverse-engineering MMS:
1951 + * http://get.to/sdp
1954 +#include <linux/config.h>
1955 +#include <linux/module.h>
1956 +#include <linux/netfilter.h>
1957 +#include <linux/ip.h>
1958 +#include <linux/ctype.h>
1959 +#include <net/checksum.h>
1960 +#include <net/tcp.h>
1962 +#include <linux/netfilter_ipv4/lockhelp.h>
1963 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1964 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
1966 +DECLARE_LOCK(ip_mms_lock);
1967 +struct module *ip_conntrack_mms = THIS_MODULE;
1969 +#define MAX_PORTS 8
1970 +static int ports[MAX_PORTS];
1971 +static int ports_c;
1973 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
1977 +#define DEBUGP printk
1979 +#define DEBUGP(format, args...)
1982 +EXPORT_SYMBOL(ip_mms_lock);
1984 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
1985 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
1986 +MODULE_LICENSE("GPL");
1988 +/* #define isdigit(c) (c >= '0' && c <= '9') */
1990 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
1991 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
1994 + for (i = 0; i < unicode_size; ++i) {
1995 + string[i] = (char)(unicode[i]);
1997 + string[unicode_size] = 0x00;
2000 +__inline static int atoi(char *s)
2003 + while (isdigit(*s)) {
2004 + i = i*10 + *(s++) - '0';
2009 +/* convert ip address string like "192.168.0.10" to unsigned int */
2010 +__inline static u_int32_t asciiiptoi(char *s)
2012 + unsigned int i, j, k;
2014 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
2016 + for(j=0; (*(++s) != '.') && (j<3); ++j)
2023 +int parse_mms(const char *data,
2024 + const unsigned int datalen,
2025 + u_int32_t *mms_ip,
2026 + u_int16_t *mms_proto,
2027 + u_int16_t *mms_port,
2028 + char **mms_string_b,
2029 + char **mms_string_e,
2030 + char **mms_padding_e)
2032 + int unicode_size, i;
2033 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
2034 + char getlengthstring[28];
2036 + for(unicode_size=0;
2037 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2039 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
2040 + return -1; /* out of bounds - incomplete packet */
2042 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2043 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2045 + /* IP address ? */
2046 + *mms_ip = asciiiptoi(tempstring+2);
2048 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2051 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
2052 + *mms_proto = IPPROTO_TCP;
2053 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2054 + *mms_proto = IPPROTO_UDP;
2057 + *mms_port = atoi(tempstring+7+i);
2059 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
2060 + unicode string, one to the end of the string, and one to the end
2061 + of the packet, since we must keep track of the number of bytes
2062 + between end of the unicode string and the end of packet (padding) */
2063 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2064 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2065 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2070 +/* FIXME: This should be in userspace. Later. */
2071 +static int help(const struct iphdr *iph, size_t len,
2072 + struct ip_conntrack *ct,
2073 + enum ip_conntrack_info ctinfo)
2075 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2076 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2077 + const char *data = (const char *)tcph + tcph->doff * 4;
2078 + unsigned int tcplen = len - iph->ihl * 4;
2079 + unsigned int datalen = tcplen - tcph->doff * 4;
2080 + int dir = CTINFO2DIR(ctinfo);
2081 + struct ip_conntrack_expect expect, *exp = &expect;
2082 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2085 + u_int16_t mms_proto;
2086 + char mms_proto_string[8];
2087 + u_int16_t mms_port;
2088 + char *mms_string_b, *mms_string_e, *mms_padding_e;
2090 + /* Until there's been traffic both ways, don't look in packets. */
2091 + if (ctinfo != IP_CT_ESTABLISHED
2092 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2093 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2097 + /* Not whole TCP header? */
2098 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2099 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2103 + /* Checksum invalid? Ignore. */
2104 + /* FIXME: Source route IP option packets --RR */
2105 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2106 + csum_partial((char *)tcph, tcplen, 0))) {
2107 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2108 + tcph, tcplen, NIPQUAD(iph->saddr),
2109 + NIPQUAD(iph->daddr));
2113 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2114 + /* FIXME: There is an issue with only looking at this packet: before this packet,
2115 + the client has already sent a packet to the server with the server's hostname
2116 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
2117 + server will break the connection if this doesn't correspond to its own host
2118 + header. The client can also connect to an IP address; if it's the server's IP
2119 + address, it will not break the connection. When doing DNAT on a connection
2120 + where the client uses a server's IP address, the nat module should detect
2121 + this and change this string accordingly to the DNATed address. This should
2122 + probably be done by checking for an IP address, then storing it as a member
2123 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2125 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
2126 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2127 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
2128 + (u8)*(data+36), (u8)*(data+37),
2129 + (u8)*(data+38), (u8)*(data+39),
2131 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2132 + &mms_string_b, &mms_string_e, &mms_padding_e))
2133 + if(net_ratelimit())
2134 + /* FIXME: more verbose debugging ? */
2135 + printk(KERN_WARNING
2136 + "ip_conntrack_mms: Unable to parse data payload\n");
2138 + memset(&expect, 0, sizeof(expect));
2140 + sprintf(mms_proto_string, "(%u)", mms_proto);
2141 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2142 + mms_proto == IPPROTO_TCP ? "TCP"
2143 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2144 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2148 + /* it's possible that the client will just ask the server to tunnel
2149 + the stream over the same TCP session (from port 1755): there's
2150 + shouldn't be a need to add an expectation in that case, but it
2151 + makes NAT packet mangling so much easier */
2152 + LOCK_BH(&ip_mms_lock);
2154 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2156 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2157 + exp_mms_info->len = (mms_string_e - mms_string_b);
2158 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
2159 + exp_mms_info->port = mms_port;
2161 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2162 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2164 + exp->tuple = ((struct ip_conntrack_tuple)
2165 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2167 + { .tcp = { (__u16) ntohs(mms_port) } },
2170 + exp->mask = ((struct ip_conntrack_tuple)
2171 + { { 0xFFFFFFFF, { 0 } },
2172 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2173 + exp->expectfn = NULL;
2174 + ip_conntrack_expect_related(ct, &expect);
2175 + UNLOCK_BH(&ip_mms_lock);
2181 +static struct ip_conntrack_helper mms[MAX_PORTS];
2182 +static char mms_names[MAX_PORTS][10];
2184 +/* Not __exit: called from init() */
2185 +static void fini(void)
2188 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2189 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2191 + ip_conntrack_helper_unregister(&mms[i]);
2195 +static int __init init(void)
2200 + if (ports[0] == 0)
2201 + ports[0] = MMS_PORT;
2203 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2204 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2205 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2206 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
2207 + mms[i].mask.src.u.tcp.port = 0xFFFF;
2208 + mms[i].mask.dst.protonum = 0xFFFF;
2209 + mms[i].max_expected = 1;
2210 + mms[i].timeout = 0;
2211 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2212 + mms[i].me = THIS_MODULE;
2213 + mms[i].help = help;
2215 + tmpname = &mms_names[i][0];
2216 + if (ports[i] == MMS_PORT)
2217 + sprintf(tmpname, "mms");
2219 + sprintf(tmpname, "mms-%d", ports[i]);
2220 + mms[i].name = tmpname;
2222 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
2224 + ret = ip_conntrack_helper_register(&mms[i]);
2237 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
2238 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
2239 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-16 09:18:47.000000000 +0200
2242 + * Connection tracking protocol helper module for SCTP.
2244 + * SCTP is defined in RFC 2960. References to various sections in this code
2245 + * are to this RFC.
2247 + * This program is free software; you can redistribute it and/or modify
2248 + * it under the terms of the GNU General Public License version 2 as
2249 + * published by the Free Software Foundation.
2252 +#include <linux/types.h>
2253 +#include <linux/sched.h>
2254 +#include <linux/timer.h>
2255 +#include <linux/netfilter.h>
2256 +#include <linux/module.h>
2257 +#include <linux/in.h>
2258 +#include <linux/ip.h>
2259 +#include <linux/sctp.h>
2260 +#include <linux/string.h>
2262 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2263 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2264 +#include <linux/netfilter_ipv4/lockhelp.h>
2267 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
2269 +#define DEBUGP(format, args...)
2272 +/* Protects conntrack->proto.sctp */
2273 +static DECLARE_RWLOCK(sctp_lock);
2275 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
2276 + closely. They're more complex. --RR
2278 + And so for me for SCTP :D -Kiran */
2280 +static const char *sctp_conntrack_names[] = {
2288 + "SHUTDOWN_ACK_SENT",
2292 +#define MINS * 60 SECS
2293 +#define HOURS * 60 MINS
2294 +#define DAYS * 24 HOURS
2296 +unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
2297 +unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
2298 +unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
2299 +unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
2300 +unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
2301 +unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
2302 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
2304 +static unsigned long * sctp_timeouts[]
2305 += { 0, /* SCTP_CONNTRACK_NONE */
2306 + &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
2307 + &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
2308 + &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
2309 + &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
2310 + &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
2311 + &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
2312 + &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
2315 +#define sNO SCTP_CONNTRACK_NONE
2316 +#define sCL SCTP_CONNTRACK_CLOSED
2317 +#define sCW SCTP_CONNTRACK_COOKIE_WAIT
2318 +#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
2319 +#define sES SCTP_CONNTRACK_ESTABLISHED
2320 +#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
2321 +#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
2322 +#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
2323 +#define sIV SCTP_CONNTRACK_MAX
2326 + These are the descriptions of the states:
2328 +NOTE: These state names are tantalizingly similar to the states of an
2329 +SCTP endpoint. But the interpretation of the states is a little different,
2330 +considering that these are the states of the connection and not of an end
2331 +point. Please note the subtleties. -Kiran
2333 +NONE - Nothing so far.
2334 +COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
2335 + an INIT_ACK chunk in the reply direction.
2336 +COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
2337 +ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
2338 +SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
2339 +SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
2340 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
2341 + to that of the SHUTDOWN chunk.
2342 +CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
2343 + the SHUTDOWN chunk. Connection is closed.
2347 + - I have assumed that the first INIT is in the original direction.
2348 + This messes things when an INIT comes in the reply direction in CLOSED
2350 + - Check the error type in the reply dir before transitioning from
2351 +cookie echoed to closed.
2352 + - Sec 5.2.4 of RFC 2960
2353 + - Multi Homing support.
2356 +/* SCTP conntrack state transitions */
2357 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
2360 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
2361 +/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
2362 +/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
2363 +/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
2364 +/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
2365 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
2366 +/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
2367 +/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
2368 +/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
2369 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
2373 +/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
2374 +/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
2375 +/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
2376 +/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
2377 +/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
2378 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
2379 +/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
2380 +/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
2381 +/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
2382 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
2386 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
2387 + unsigned int dataoff,
2388 + struct ip_conntrack_tuple *tuple)
2390 + sctp_sctphdr_t hdr;
2392 + DEBUGP(__FUNCTION__);
2395 + /* Actually only need first 8 bytes. */
2396 + if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
2399 + tuple->src.u.sctp.port = hdr.source;
2400 + tuple->dst.u.sctp.port = hdr.dest;
2405 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
2406 + const struct ip_conntrack_tuple *orig)
2408 + DEBUGP(__FUNCTION__);
2411 + tuple->src.u.sctp.port = orig->dst.u.sctp.port;
2412 + tuple->dst.u.sctp.port = orig->src.u.sctp.port;
2416 +/* Print out the per-protocol part of the tuple. */
2417 +static unsigned int sctp_print_tuple(char *buffer,
2418 + const struct ip_conntrack_tuple *tuple)
2420 + DEBUGP(__FUNCTION__);
2423 + return sprintf(buffer, "sport=%hu dport=%hu ",
2424 + ntohs(tuple->src.u.sctp.port),
2425 + ntohs(tuple->dst.u.sctp.port));
2428 +/* Print out the private part of the conntrack. */
2429 +static unsigned int sctp_print_conntrack(char *buffer,
2430 + const struct ip_conntrack *conntrack)
2432 + enum sctp_conntrack state;
2434 + DEBUGP(__FUNCTION__);
2437 + READ_LOCK(&sctp_lock);
2438 + state = conntrack->proto.sctp.state;
2439 + READ_UNLOCK(&sctp_lock);
2441 + return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
2444 +#define for_each_sctp_chunk(skb, sch, offset, count) \
2445 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
2446 + offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
2447 + offset += (htons(sch.length) + 3) & ~3, count++)
2449 +/* Some validity checks to make sure the chunks are fine */
2450 +static int do_basic_checks(struct ip_conntrack *conntrack,
2451 + const struct sk_buff *skb,
2454 + u_int32_t offset, count;
2455 + sctp_chunkhdr_t sch;
2458 + DEBUGP(__FUNCTION__);
2463 + for_each_sctp_chunk (skb, sch, offset, count) {
2464 + DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
2466 + if (sch.type == SCTP_CID_INIT
2467 + || sch.type == SCTP_CID_INIT_ACK
2468 + || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
2472 + /* Cookie Ack/Echo chunks not the first OR
2473 + Init / Init Ack / Shutdown compl chunks not the only chunks */
2474 + if ((sch.type == SCTP_CID_COOKIE_ACK
2475 + || sch.type == SCTP_CID_COOKIE_ECHO
2478 + DEBUGP("Basic checks failed\n");
2483 + set_bit (sch.type, (void *)map);
2487 + DEBUGP("Basic checks passed\n");
2491 +static int new_state(enum ip_conntrack_dir dir,
2492 + enum sctp_conntrack cur_state,
2497 + DEBUGP(__FUNCTION__);
2500 + DEBUGP("Chunk type: %d\n", chunk_type);
2502 + switch (chunk_type) {
2503 + case SCTP_CID_INIT:
2504 + DEBUGP("SCTP_CID_INIT\n");
2506 + case SCTP_CID_INIT_ACK:
2507 + DEBUGP("SCTP_CID_INIT_ACK\n");
2509 + case SCTP_CID_ABORT:
2510 + DEBUGP("SCTP_CID_ABORT\n");
2512 + case SCTP_CID_SHUTDOWN:
2513 + DEBUGP("SCTP_CID_SHUTDOWN\n");
2515 + case SCTP_CID_SHUTDOWN_ACK:
2516 + DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
2518 + case SCTP_CID_ERROR:
2519 + DEBUGP("SCTP_CID_ERROR\n");
2521 + case SCTP_CID_COOKIE_ECHO:
2522 + DEBUGP("SCTP_CID_COOKIE_ECHO\n");
2524 + case SCTP_CID_COOKIE_ACK:
2525 + DEBUGP("SCTP_CID_COOKIE_ACK\n");
2527 + case SCTP_CID_SHUTDOWN_COMPLETE:
2528 + DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
2531 + /* Other chunks like DATA, SACK, HEARTBEAT and
2532 + its ACK do not cause a change in state */
2533 + DEBUGP("Unknown chunk type, Will stay in %s\n",
2534 + sctp_conntrack_names[cur_state]);
2538 + DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
2539 + dir, sctp_conntrack_names[cur_state], chunk_type,
2540 + sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
2542 + return sctp_conntracks[dir][i][cur_state];
2545 +/* Returns verdict for packet, or -1 for invalid. */
2546 +static int sctp_packet(struct ip_conntrack *conntrack,
2547 + const struct sk_buff *skb,
2548 + enum ip_conntrack_info ctinfo)
2550 + enum sctp_conntrack newconntrack, oldsctpstate;
2551 + sctp_sctphdr_t sctph;
2552 + sctp_chunkhdr_t sch;
2553 + u_int32_t offset, count;
2554 + char map[256 / sizeof (char)] = {0};
2556 + DEBUGP(__FUNCTION__);
2559 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
2562 + if (do_basic_checks(conntrack, skb, map) != 0)
2565 + /* Check the verification tag (Sec 8.5) */
2566 + if (!test_bit(SCTP_CID_INIT, (void *)map)
2567 + && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
2568 + && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
2569 + && !test_bit(SCTP_CID_ABORT, (void *)map)
2570 + && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
2571 + && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
2572 + DEBUGP("Verification tag check failed\n");
2576 + oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
2577 + for_each_sctp_chunk (skb, sch, offset, count) {
2578 + WRITE_LOCK(&sctp_lock);
2580 + /* Special cases of Verification tag check (Sec 8.5.1) */
2581 + if (sch.type == SCTP_CID_INIT) {
2582 + /* Sec 8.5.1 (A) */
2583 + if (sctph.vtag != 0) {
2584 + WRITE_UNLOCK(&sctp_lock);
2587 + } else if (sch.type == SCTP_CID_ABORT) {
2588 + /* Sec 8.5.1 (B) */
2589 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
2590 + && !(sctph.vtag == conntrack->proto.sctp.vtag
2591 + [1 - CTINFO2DIR(ctinfo)])) {
2592 + WRITE_UNLOCK(&sctp_lock);
2595 + } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
2596 + /* Sec 8.5.1 (C) */
2597 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
2598 + && !(sctph.vtag == conntrack->proto.sctp.vtag
2599 + [1 - CTINFO2DIR(ctinfo)]
2600 + && (sch.flags & 1))) {
2601 + WRITE_UNLOCK(&sctp_lock);
2604 + } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
2605 + /* Sec 8.5.1 (D) */
2606 + if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
2607 + WRITE_UNLOCK(&sctp_lock);
2612 + oldsctpstate = conntrack->proto.sctp.state;
2613 + newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
2616 + if (newconntrack == SCTP_CONNTRACK_MAX) {
2617 + DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
2618 + CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
2619 + WRITE_UNLOCK(&sctp_lock);
2623 + /* If it is an INIT or an INIT ACK note down the vtag */
2624 + if (sch.type == SCTP_CID_INIT
2625 + || sch.type == SCTP_CID_INIT_ACK) {
2626 + sctp_inithdr_t inithdr;
2628 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
2629 + &inithdr, sizeof(inithdr)) != 0) {
2630 + WRITE_UNLOCK(&sctp_lock);
2633 + DEBUGP("Setting vtag %x for dir %d\n",
2634 + inithdr.init_tag, CTINFO2DIR(ctinfo));
2635 + conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
2638 + conntrack->proto.sctp.state = newconntrack;
2639 + WRITE_UNLOCK(&sctp_lock);
2642 + ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
2644 + if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
2645 + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
2646 + && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
2647 + DEBUGP("Setting assured bit\n");
2648 + set_bit(IPS_ASSURED_BIT, &conntrack->status);
2654 +/* Called when a new connection for this protocol found. */
2655 +static int sctp_new(struct ip_conntrack *conntrack,
2656 + const struct sk_buff *skb)
2658 + enum sctp_conntrack newconntrack;
2659 + sctp_sctphdr_t sctph;
2660 + sctp_chunkhdr_t sch;
2661 + u_int32_t offset, count;
2662 + char map[256 / sizeof (char)] = {0};
2664 + DEBUGP(__FUNCTION__);
2667 + if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
2670 + if (do_basic_checks(conntrack, skb, map) != 0)
2673 + /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
2674 + if ((test_bit (SCTP_CID_ABORT, (void *)map))
2675 + || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
2676 + || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
2680 + newconntrack = SCTP_CONNTRACK_MAX;
2681 + for_each_sctp_chunk (skb, sch, offset, count) {
2682 + /* Don't need lock here: this conntrack not in circulation yet */
2683 + newconntrack = new_state (IP_CT_DIR_ORIGINAL,
2684 + SCTP_CONNTRACK_NONE, sch.type);
2686 + /* Invalid: delete conntrack */
2687 + if (newconntrack == SCTP_CONNTRACK_MAX) {
2688 + DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
2692 + /* Copy the vtag into the state info */
2693 + if (sch.type == SCTP_CID_INIT) {
2694 + if (sctph.vtag == 0) {
2695 + sctp_inithdr_t inithdr;
2697 + if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
2698 + &inithdr, sizeof(inithdr)) != 0) {
2702 + DEBUGP("Setting vtag %x for new conn\n",
2703 + inithdr.init_tag);
2705 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
2708 + /* Sec 8.5.1 (A) */
2712 + /* If it is a shutdown ack OOTB packet, we expect a return
2713 + shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
2715 + DEBUGP("Setting vtag %x for new conn OOTB\n",
2717 + conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
2720 + conntrack->proto.sctp.state = newconntrack;
2726 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
2727 + const struct sk_buff *skb)
2729 + /* To be implemented */
2733 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
2734 + .list = { NULL, NULL },
2735 + .proto = IPPROTO_SCTP,
2737 + .pkt_to_tuple = sctp_pkt_to_tuple,
2738 + .invert_tuple = sctp_invert_tuple,
2739 + .print_tuple = sctp_print_tuple,
2740 + .print_conntrack = sctp_print_conntrack,
2741 + .packet = sctp_packet,
2744 + .exp_matches_pkt = sctp_exp_matches_pkt,
2748 +int __init init(void)
2752 + ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
2753 + DEBUGP("SCTP conntrack module loading %s\n",
2754 + ret ? "failed": "succeeded");
2758 +void __exit fini(void)
2760 + ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
2761 + DEBUGP("SCTP conntrack module unloaded\n");
2767 +MODULE_LICENSE("GPL");
2768 +MODULE_AUTHOR("Kiran Kumar Immidi");
2769 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
2770 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_quake3.c
2771 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
2772 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-04-16 09:18:43.000000000 +0200
2774 +/* Quake3 extension for IP connection tracking
2775 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2776 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
2778 + * ip_conntrack_quake3.c v0.04 2002-08-31
2780 + * This program is free software; you can redistribute it and/or
2781 + * modify it under the terms of the GNU General Public License
2782 + * as published by the Free Software Foundation; either version
2783 + * 2 of the License, or (at your option) any later version.
2785 + * Module load syntax:
2786 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
2788 + * please give the ports of all Quake3 master servers You wish to
2789 + * connect to. If you don't specify ports, the default will be UDP
2792 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
2795 +#include <linux/module.h>
2796 +#include <linux/ip.h>
2797 +#include <linux/udp.h>
2799 +#include <linux/netfilter.h>
2800 +#include <linux/netfilter_ipv4/ip_tables.h>
2801 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2802 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
2804 +struct module *ip_conntrack_quake3 = THIS_MODULE;
2806 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2807 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
2808 +MODULE_LICENSE("GPL");
2810 +#define MAX_PORTS 8
2811 +static int ports[MAX_PORTS];
2812 +static int ports_c = 0;
2814 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2815 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
2818 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
2819 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
2821 +#define DEBUGP printk
2823 +#define DEBUGP(format, args...)
2826 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
2828 +static int quake3_help(const struct iphdr *iph, size_t len,
2829 + struct ip_conntrack *ct,
2830 + enum ip_conntrack_info ctinfo)
2832 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
2833 + int dir = CTINFO2DIR(ctinfo);
2834 + struct ip_conntrack_expect exp;
2837 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
2838 + if (ctinfo != IP_CT_ESTABLISHED
2839 + && ctinfo != IP_CT_IS_REPLY) {
2840 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
2842 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
2844 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
2845 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
2846 + i+6 < ntohs(udph->len);
2848 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
2849 + i, ntohs(udph->len),
2850 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
2851 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
2853 + memset(&exp, 0, sizeof(exp));
2855 + exp.tuple = ((struct ip_conntrack_tuple)
2856 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2857 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
2858 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
2861 + exp.mask = ((struct ip_conntrack_tuple)
2862 + { { 0xFFFFFFFF, { 0 } },
2863 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
2864 + exp.expectfn = NULL;
2866 + ip_conntrack_expect_related(ct, &exp);
2871 + return(NF_ACCEPT);
2874 +static struct ip_conntrack_helper quake3[MAX_PORTS];
2875 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
2877 +static void fini(void)
2881 + for(i = 0 ; (i < ports_c); i++) {
2882 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
2884 + ip_conntrack_helper_unregister(&quake3[i]);
2888 +static int __init init(void)
2894 + ports[0]=QUAKE3_MASTER_PORT;
2896 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
2897 + /* Create helper structure */
2898 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
2900 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
2901 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
2902 + quake3[i].mask.dst.protonum = 0xFFFF;
2903 + quake3[i].mask.src.u.udp.port = 0xFFFF;
2904 + quake3[i].help = quake3_help;
2905 + quake3[i].me = THIS_MODULE;
2907 + tmpname = &quake3_names[i][0];
2908 + if (ports[i] == QUAKE3_MASTER_PORT)
2909 + sprintf(tmpname, "quake3");
2911 + sprintf(tmpname, "quake3-%d", i);
2912 + quake3[i].name = tmpname;
2914 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
2917 + ret=ip_conntrack_helper_register(&quake3[i]);
2930 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
2931 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
2932 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2004-04-16 09:18:44.000000000 +0200
2934 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
2935 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2936 + * - original rpc tracking module
2937 + * - "recent" connection handling for kernel 2.3+ netfilter
2939 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2940 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2942 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2943 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
2944 + * - extended matching to support filtering on procedures
2946 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
2948 + * This program is free software; you can redistribute it and/or
2949 + * modify it under the terms of the GNU General Public License
2950 + * as published by the Free Software Foundation; either version
2951 + * 2 of the License, or (at your option) any later version.
2953 + * Module load syntax:
2954 + * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
2956 + * Please give the ports of all RPC servers you wish to connect to.
2957 + * If you don't specify ports, the default will be port 111.
2961 + * RPCs should not be exposed to the internet - ask the Pentagon;
2963 + * "The unidentified crackers pleaded guilty in July to charges
2964 + * of juvenile delinquency stemming from a string of Pentagon
2965 + * network intrusions in February.
2967 + * The youths, going by the names TooShort and Makaveli, used
2968 + * a common server security hole to break in, according to
2969 + * Dane Jasper, owner of the California Internet service
2970 + * provider, Sonic. They used the hole, known as the 'statd'
2971 + * exploit, to attempt more than 800 break-ins, Jasper said."
2973 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
2974 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
2978 +#include <linux/module.h>
2979 +#include <linux/netfilter.h>
2980 +#include <linux/ip.h>
2981 +#include <net/checksum.h>
2982 +#include <net/tcp.h>
2984 +#include <asm/param.h>
2985 +#include <linux/sched.h>
2986 +#include <linux/timer.h>
2987 +#include <linux/stddef.h>
2988 +#include <linux/list.h>
2990 +#include <linux/netfilter_ipv4/lockhelp.h>
2991 +#include <linux/netfilter_ipv4/ip_tables.h>
2992 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2993 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
2995 +#define MAX_PORTS 8
2996 +static int ports[MAX_PORTS];
2997 +static int ports_n_c = 0;
3000 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3001 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3004 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3005 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
3006 +MODULE_LICENSE("GPL");
3009 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
3012 +#define DEBUGP(format, args...)
3015 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
3016 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
3017 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
3018 +#include <linux/netfilter_ipv4/listhelp.h>
3020 +/* For future conections RPC, using client's cache bindings
3021 + * I'll use ip_conntrack_lock to lock these lists */
3023 +LIST_HEAD(request_p_list_tcp);
3026 +static void delete_request_p(unsigned long request_p_ul)
3028 + struct request_p *p = (void *)request_p_ul;
3030 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3031 + LIST_DELETE(&request_p_list_tcp, p);
3032 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3038 +static void req_cl(struct request_p * r)
3040 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3041 + del_timer(&r->timeout);
3042 + LIST_DELETE(&request_p_list_tcp, r);
3043 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3049 +static void clean_request(struct list_head *list)
3051 + struct list_head *first = list->prev;
3052 + struct list_head *temp = list->next;
3053 + struct list_head *aux;
3055 + if (list_empty(list))
3058 + while (first != temp) {
3060 + req_cl((struct request_p *)temp);
3063 + req_cl((struct request_p *)temp);
3068 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3071 + struct request_p *req_p;
3073 + /* Verifies if entry already exists */
3074 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3075 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3076 + struct request_p *, xid, ip, port);
3079 + /* Refresh timeout */
3080 + if (del_timer(&req_p->timeout)) {
3081 + req_p->timeout.expires = jiffies + EXP;
3082 + add_timer(&req_p->timeout);
3084 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3088 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3090 + /* Allocate new request_p */
3091 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3093 + DEBUGP("can't allocate request_p\n");
3096 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3097 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3100 + /* Initialize timer */
3101 + init_timer(&req_p->timeout);
3102 + req_p->timeout.function = delete_request_p;
3103 + add_timer(&req_p->timeout);
3106 + WRITE_LOCK(&ipct_rpc_tcp_lock);
3107 + list_prepend(&request_p_list_tcp, req_p);
3108 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3114 +static int check_rpc_packet(const u_int32_t *data,
3115 + int dir, struct ip_conntrack *ct,
3116 + struct list_head request_p_list)
3118 + struct request_p *req_p;
3120 + struct ip_conntrack_expect expect, *exp = &expect;
3122 + /* Translstion's buffer for XDR */
3123 + u_int16_t port_buf;
3129 + /* This does sanity checking on RPC payloads,
3130 + * and permits only the RPC "get port" (3)
3131 + * in authorised procedures in client
3132 + * communications with the portmapper.
3135 + /* perform direction dependant RPC work */
3136 + if (dir == IP_CT_DIR_ORIGINAL) {
3140 + /* Get RPC requestor */
3141 + if (IXDR_GET_INT32(data) != 3) {
3142 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3145 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3149 + /* Jump Credentials and Verfifier */
3150 + data += IXDR_GET_INT32(data) + 2;
3151 + data += IXDR_GET_INT32(data) + 2;
3153 + /* Get RPC procedure */
3154 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3155 + (unsigned int)IXDR_GET_INT32(data));
3157 + /* Get RPC protocol and store against client parameters */
3159 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3160 + ct->tuplehash[dir].tuple.src.u.all);
3162 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3163 + xid, IXDR_GET_INT32(data),
3164 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3165 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
3167 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
3168 + (unsigned int)IXDR_GET_INT32(data));
3172 + /* Check for returning packet's stored counterpart */
3173 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3174 + struct request_p *, xid,
3175 + ct->tuplehash[!dir].tuple.src.ip,
3176 + ct->tuplehash[!dir].tuple.src.u.all);
3178 + /* Drop unexpected packets */
3180 + DEBUGP("packet is not expected. [skip]\n");
3184 + /* Verifies if packet is really an RPC reply packet */
3186 + if (IXDR_GET_INT32(data) != 1) {
3187 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
3191 + /* Is status accept? */
3193 + if (IXDR_GET_INT32(data)) {
3194 + DEBUGP("packet is not an RPC accept. [skip]\n");
3198 + /* Get Verifier length. Jump verifier */
3200 + data = data + IXDR_GET_INT32(data) + 2;
3202 + /* Is accpet status "success"? */
3203 + if (IXDR_GET_INT32(data)) {
3204 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3208 + /* Get server port number */
3210 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
3212 + /* If a packet has made it this far then it deserves an
3213 + * expectation ... if port == 0, then this service is
3214 + * not going to be registered.
3217 + DEBUGP("port found: %u\n", port_buf);
3219 + memset(&expect, 0, sizeof(expect));
3221 + /* Watch out, Radioactive-Man! */
3222 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3223 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3224 + exp->mask.src.ip = 0xffffffff;
3225 + exp->mask.dst.ip = 0xffffffff;
3227 + switch (req_p->proto) {
3229 + exp->tuple.src.u.udp.port = 0;
3230 + exp->tuple.dst.u.udp.port = htons(port_buf);
3231 + exp->tuple.dst.protonum = IPPROTO_UDP;
3232 + exp->mask.src.u.udp.port = 0;
3233 + exp->mask.dst.u.udp.port = htons(0xffff);
3234 + exp->mask.dst.protonum = 0xffff;
3238 + exp->tuple.src.u.tcp.port = 0;
3239 + exp->tuple.dst.u.tcp.port = htons(port_buf);
3240 + exp->tuple.dst.protonum = IPPROTO_TCP;
3241 + exp->mask.src.u.tcp.port = 0;
3242 + exp->mask.dst.u.tcp.port = htons(0xffff);
3243 + exp->mask.dst.protonum = 0xffff;
3246 + exp->expectfn = NULL;
3248 + ip_conntrack_expect_related(ct, &expect);
3250 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3251 + NIPQUAD(exp->tuple.src.ip),
3252 + NIPQUAD(exp->tuple.dst.ip),
3253 + port_buf, req_p->proto);
3255 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3256 + NIPQUAD(exp->mask.src.ip),
3257 + NIPQUAD(exp->mask.dst.ip),
3258 + exp->mask.dst.protonum);
3264 + DEBUGP("packet evaluated. [expect]\n");
3273 +/* RPC TCP helper */
3274 +static int help(const struct iphdr *iph, size_t len,
3275 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3277 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3278 + const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3279 + size_t tcplen = len - iph->ihl * 4;
3281 + int dir = CTINFO2DIR(ctinfo);
3285 + DEBUGP("new packet to evaluate ..\n");
3287 + /* This works for packets like handshake packets, ignore */
3288 + if (len == ((tcph->doff + iph->ihl) * 4)) {
3289 + DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3293 + /* Until there's been traffic both ways, don't look in packets. */
3294 + if (ctinfo != IP_CT_ESTABLISHED
3295 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3296 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3297 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3298 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3302 + /* Not whole TCP header? */
3303 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3304 + DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3305 + DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3309 + /* FIXME: Source route IP option packets --RR */
3310 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3311 + csum_partial((char *) tcph, tcplen, 0))) {
3312 + DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3313 + tcph, tcplen, NIPQUAD(iph->saddr),
3314 + NIPQUAD(iph->daddr));
3315 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3316 + DEBUGP("packet contains a bad checksum. [skip]\n");
3320 + /* perform direction dependant protocol work */
3321 + if (dir == IP_CT_DIR_ORIGINAL) {
3323 + DEBUGP("packet is from the initiator. [cont]\n");
3325 + /* Tests if packet len is ok */
3326 + if ((tcplen - (tcph->doff * 4)) != 60) {
3327 + DEBUGP("packet length is not correct. [skip]\n");
3333 + DEBUGP("packet is from the receiver. [cont]\n");
3335 + /* Tests if packet len is ok */
3336 + if ((tcplen - (tcph->doff * 4)) != 32) {
3337 + DEBUGP("packet length is not correct. [skip]\n");
3342 + /* Get to the data */
3345 + /* Check the RPC data */
3346 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
3353 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3355 +static void fini(void);
3358 +static int __init init(void)
3361 + static char name[10];
3364 + /* If no port given, default to standard RPC port */
3365 + if (ports[0] == 0)
3366 + ports[0] = RPC_PORT;
3368 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3369 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3371 + if (ports[port] == RPC_PORT)
3372 + sprintf(name, "rpc");
3374 + sprintf(name, "rpc-%d", port);
3376 + rpc_helpers[port].name = name;
3377 + rpc_helpers[port].me = THIS_MODULE;
3378 + rpc_helpers[port].max_expected = 1;
3379 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3380 + rpc_helpers[port].timeout = 0;
3382 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
3383 + rpc_helpers[port].mask.dst.protonum = 0xffff;
3385 + /* RPC can come from ports 0:65535 to ports[port] (111) */
3386 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3387 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3388 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3390 + rpc_helpers[port].help = help;
3392 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
3393 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3394 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3395 + ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
3396 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
3397 + ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
3398 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3399 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
3400 + ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
3401 + NIPQUAD(rpc_helpers[port].mask.src.ip),
3402 + ntohs(rpc_helpers[port].mask.src.u.tcp.port));
3404 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3407 + printk("ERROR registering port %d\n",
3418 +/* This function is intentionally _NOT_ defined as __exit, because
3419 + * it is needed by the init function */
3420 +static void fini(void)
3424 + DEBUGP("cleaning request list\n");
3425 + clean_request(&request_p_list_tcp);
3427 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3428 + DEBUGP("unregistering port %d\n", ports[port]);
3429 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
3437 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
3438 +EXPORT_SYMBOL(request_p_list_tcp);
3439 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
3440 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
3442 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
3443 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
3444 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2004-04-16 09:18:44.000000000 +0200
3446 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
3447 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3448 + * - original rpc tracking module
3449 + * - "recent" connection handling for kernel 2.3+ netfilter
3451 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3452 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3454 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3455 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
3456 + * - extended matching to support filtering on procedures
3458 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
3460 + * This program is free software; you can redistribute it and/or
3461 + * modify it under the terms of the GNU General Public License
3462 + * as published by the Free Software Foundation; either version
3463 + * 2 of the License, or (at your option) any later version.
3465 + * Module load syntax:
3466 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
3468 + * Please give the ports of all RPC servers you wish to connect to.
3469 + * If you don't specify ports, the default will be port 111.
3473 + * RPCs should not be exposed to the internet - ask the Pentagon;
3475 + * "The unidentified crackers pleaded guilty in July to charges
3476 + * of juvenile delinquency stemming from a string of Pentagon
3477 + * network intrusions in February.
3479 + * The youths, going by the names TooShort and Makaveli, used
3480 + * a common server security hole to break in, according to
3481 + * Dane Jasper, owner of the California Internet service
3482 + * provider, Sonic. They used the hole, known as the 'statd'
3483 + * exploit, to attempt more than 800 break-ins, Jasper said."
3485 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3486 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
3490 +#include <linux/module.h>
3491 +#include <linux/netfilter.h>
3492 +#include <linux/ip.h>
3493 +#include <net/checksum.h>
3494 +#include <net/udp.h>
3496 +#include <asm/param.h>
3497 +#include <linux/sched.h>
3498 +#include <linux/timer.h>
3499 +#include <linux/stddef.h>
3500 +#include <linux/list.h>
3502 +#include <linux/netfilter_ipv4/lockhelp.h>
3503 +#include <linux/netfilter_ipv4/ip_tables.h>
3504 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3505 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3507 +#define MAX_PORTS 8
3508 +static int ports[MAX_PORTS];
3509 +static int ports_n_c = 0;
3512 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3513 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3516 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3517 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
3518 +MODULE_LICENSE("GPL");
3521 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
3524 +#define DEBUGP(format, args...)
3527 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
3528 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
3529 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
3530 +#include <linux/netfilter_ipv4/listhelp.h>
3532 +/* For future conections RPC, using client's cache bindings
3533 + * I'll use ip_conntrack_lock to lock these lists */
3535 +LIST_HEAD(request_p_list_udp);
3538 +static void delete_request_p(unsigned long request_p_ul)
3540 + struct request_p *p = (void *)request_p_ul;
3542 + WRITE_LOCK(&ipct_rpc_udp_lock);
3543 + LIST_DELETE(&request_p_list_udp, p);
3544 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3550 +static void req_cl(struct request_p * r)
3552 + WRITE_LOCK(&ipct_rpc_udp_lock);
3553 + del_timer(&r->timeout);
3554 + LIST_DELETE(&request_p_list_udp, r);
3555 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3561 +static void clean_request(struct list_head *list)
3563 + struct list_head *first = list->prev;
3564 + struct list_head *temp = list->next;
3565 + struct list_head *aux;
3567 + if (list_empty(list))
3570 + while (first != temp) {
3572 + req_cl((struct request_p *)temp);
3575 + req_cl((struct request_p *)temp);
3580 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3583 + struct request_p *req_p;
3585 + /* Verifies if entry already exists */
3586 + WRITE_LOCK(&ipct_rpc_udp_lock);
3587 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3588 + struct request_p *, xid, ip, port);
3591 + /* Refresh timeout */
3592 + if (del_timer(&req_p->timeout)) {
3593 + req_p->timeout.expires = jiffies + EXP;
3594 + add_timer(&req_p->timeout);
3596 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3600 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3602 + /* Allocate new request_p */
3603 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3605 + DEBUGP("can't allocate request_p\n");
3608 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3609 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3612 + /* Initialize timer */
3613 + init_timer(&req_p->timeout);
3614 + req_p->timeout.function = delete_request_p;
3615 + add_timer(&req_p->timeout);
3618 + WRITE_LOCK(&ipct_rpc_udp_lock);
3619 + list_prepend(&request_p_list_udp, req_p);
3620 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
3626 +static int check_rpc_packet(const u_int32_t *data,
3627 + int dir, struct ip_conntrack *ct,
3628 + struct list_head request_p_list)
3630 + struct request_p *req_p;
3632 + struct ip_conntrack_expect expect, *exp = &expect;
3634 + /* Translstion's buffer for XDR */
3635 + u_int16_t port_buf;
3641 + /* This does sanity checking on RPC payloads,
3642 + * and permits only the RPC "get port" (3)
3643 + * in authorised procedures in client
3644 + * communications with the portmapper.
3647 + /* perform direction dependant RPC work */
3648 + if (dir == IP_CT_DIR_ORIGINAL) {
3652 + /* Get RPC requestor */
3653 + if (IXDR_GET_INT32(data) != 3) {
3654 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3657 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3661 + /* Jump Credentials and Verfifier */
3662 + data = data + IXDR_GET_INT32(data) + 2;
3663 + data = data + IXDR_GET_INT32(data) + 2;
3665 + /* Get RPC procedure */
3666 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3667 + (unsigned int)IXDR_GET_INT32(data));
3669 + /* Get RPC protocol and store against client parameters */
3671 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3672 + ct->tuplehash[dir].tuple.src.u.all);
3674 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3675 + xid, IXDR_GET_INT32(data),
3676 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3677 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
3679 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
3680 + (unsigned int)IXDR_GET_INT32(data));
3684 + /* Check for returning packet's stored counterpart */
3685 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3686 + struct request_p *, xid,
3687 + ct->tuplehash[!dir].tuple.src.ip,
3688 + ct->tuplehash[!dir].tuple.src.u.all);
3690 + /* Drop unexpected packets */
3692 + DEBUGP("packet is not expected. [skip]\n");
3696 + /* Verifies if packet is really an RPC reply packet */
3698 + if (IXDR_GET_INT32(data) != 1) {
3699 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
3703 + /* Is status accept? */
3705 + if (IXDR_GET_INT32(data)) {
3706 + DEBUGP("packet is not an RPC accept. [skip]\n");
3710 + /* Get Verifier length. Jump verifier */
3712 + data = data + IXDR_GET_INT32(data) + 2;
3714 + /* Is accpet status "success"? */
3715 + if (IXDR_GET_INT32(data)) {
3716 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3720 + /* Get server port number */
3722 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
3724 + /* If a packet has made it this far then it deserves an
3725 + * expectation ... if port == 0, then this service is
3726 + * not going to be registered.
3729 + DEBUGP("port found: %u\n", port_buf);
3731 + memset(&expect, 0, sizeof(expect));
3733 + /* Watch out, Radioactive-Man! */
3734 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3735 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3736 + exp->mask.src.ip = 0xffffffff;
3737 + exp->mask.dst.ip = 0xffffffff;
3739 + switch (req_p->proto) {
3741 + exp->tuple.src.u.udp.port = 0;
3742 + exp->tuple.dst.u.udp.port = htons(port_buf);
3743 + exp->tuple.dst.protonum = IPPROTO_UDP;
3744 + exp->mask.src.u.udp.port = 0;
3745 + exp->mask.dst.u.udp.port = htons(0xffff);
3746 + exp->mask.dst.protonum = 0xffff;
3750 + exp->tuple.src.u.tcp.port = 0;
3751 + exp->tuple.dst.u.tcp.port = htons(port_buf);
3752 + exp->tuple.dst.protonum = IPPROTO_TCP;
3753 + exp->mask.src.u.tcp.port = 0;
3754 + exp->mask.dst.u.tcp.port = htons(0xffff);
3755 + exp->mask.dst.protonum = 0xffff;
3758 + exp->expectfn = NULL;
3760 + ip_conntrack_expect_related(ct, &expect);
3762 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3763 + NIPQUAD(exp->tuple.src.ip),
3764 + NIPQUAD(exp->tuple.dst.ip),
3765 + port_buf, req_p->proto);
3767 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3768 + NIPQUAD(exp->mask.src.ip),
3769 + NIPQUAD(exp->mask.dst.ip),
3770 + exp->mask.dst.protonum);
3776 + DEBUGP("packet evaluated. [expect]\n");
3785 +/* RPC UDP helper */
3786 +static int help(const struct iphdr *iph, size_t len,
3787 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3789 + struct udphdr *udph = (void *) iph + iph->ihl * 4;
3790 + const u_int32_t *data = (const u_int32_t *)udph + 2;
3791 + size_t udplen = len - iph->ihl * 4;
3792 + int dir = CTINFO2DIR(ctinfo);
3796 + const u_int16_t *chsm = (const u_int16_t *)udph + 3;
3799 + DEBUGP("new packet to evaluate ..\n");
3801 + /* Not whole UDP header? */
3802 + if (udplen < sizeof(struct udphdr)) {
3803 + DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
3804 + DEBUGP("packet does not contain a complete UDP header. [skip]\n");
3808 + /* FIXME: Source route IP option packets --RR */
3810 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
3811 + csum_partial((char *)udph, udplen, 0))) {
3812 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3813 + DEBUGP("packet contains a bad checksum. [skip]\n");
3818 + /* perform direction dependant protocol work */
3819 + if (dir == IP_CT_DIR_ORIGINAL) {
3821 + DEBUGP("packet is from the initiator. [cont]\n");
3823 + /* Tests if packet len is ok */
3824 + if ((udplen - sizeof(struct udphdr)) != 56) {
3825 + DEBUGP("packet length is not correct. [skip]\n");
3831 + DEBUGP("packet is from the receiver. [cont]\n");
3833 + /* Until there's been traffic both ways, don't look in packets. */
3834 + if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3835 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3836 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3837 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3841 + /* Tests if packet len is ok */
3842 + if ((udplen - sizeof(struct udphdr)) != 28) {
3843 + DEBUGP("packet length is not correct. [skip]\n");
3849 + /* Get to the data */
3850 + /* udp *data == *correct */
3852 + /* Check the RPC data */
3853 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
3860 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3862 +static void fini(void);
3865 +static int __init init(void)
3868 + static char name[10];
3871 + /* If no port given, default to standard RPC port */
3872 + if (ports[0] == 0)
3873 + ports[0] = RPC_PORT;
3875 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3876 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3878 + if (ports[port] == RPC_PORT)
3879 + sprintf(name, "rpc");
3881 + sprintf(name, "rpc-%d", port);
3883 + rpc_helpers[port].name = name;
3884 + rpc_helpers[port].me = THIS_MODULE;
3885 + rpc_helpers[port].max_expected = 1;
3886 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3887 + rpc_helpers[port].timeout = 0;
3889 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
3890 + rpc_helpers[port].mask.dst.protonum = 0xffff;
3892 + /* RPC can come from ports 0:65535 to ports[port] (111) */
3893 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3894 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3895 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3897 + rpc_helpers[port].help = help;
3899 + DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
3900 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3901 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3902 + ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
3903 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
3904 + ntohs(rpc_helpers[port].tuple.src.u.udp.port));
3905 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3906 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
3907 + ntohs(rpc_helpers[port].mask.dst.u.udp.port),
3908 + NIPQUAD(rpc_helpers[port].mask.src.ip),
3909 + ntohs(rpc_helpers[port].mask.src.u.udp.port));
3911 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3914 + printk("ERROR registering port %d\n",
3925 +/* This function is intentionally _NOT_ defined as __exit, because
3926 + * it is needed by the init function */
3927 +static void fini(void)
3931 + DEBUGP("cleaning request list\n");
3932 + clean_request(&request_p_list_udp);
3934 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3935 + DEBUGP("unregistering port %d\n", ports[port]);
3936 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
3944 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
3945 +EXPORT_SYMBOL(request_p_list_udp);
3946 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
3947 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
3949 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rsh.c
3950 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
3951 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-04-16 09:18:45.000000000 +0200
3953 +/* RSH extension for IP connection tracking, Version 1.0
3954 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3955 + * based on HW's ip_conntrack_irc.c
3957 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
3959 + * This program is free software; you can redistribute it and/or
3960 + * modify it under the terms of the GNU General Public License
3961 + * as published by the Free Software Foundation; either version
3962 + * 2 of the License, or (at your option) any later version.
3964 + * Module load syntax:
3965 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
3967 + * please give the ports of all RSH servers You wish to connect to.
3968 + * If You don't specify ports, the default will be port 514
3971 + * RSH blows ... you should use SSH (openssh.org) to replace it,
3972 + * unfortunately I babysit some sysadmins that won't migrate
3973 + * their legacy crap, in our second tier.
3978 + * Some docco ripped from the net to teach me all there is to know about
3979 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
3982 + * I have no idea what "unix rshd man pages" these guys have .. but that
3983 + * is some pretty detailed docco!
3986 + * 4. Of the rsh protocol.
3987 + * -----------------------
3989 + * The rshd listens on TCP port #514. The following info is from the unix
3990 + * rshd man pages :
3992 + * "Service Request Protocol
3994 + * When the rshd daemon receives a service request, it initiates the
3995 + * following protocol:
3997 + * 1. The rshd daemon checks the source port number for the request.
3998 + * If the port number is not in the range 0 through 1023, the rshd daemon
3999 + * terminates the connection.
4001 + * 2. The rshd daemon reads characters from the socket up to a null byte.
4002 + * The string read is interpreted as an ASCII number (base 10). If this
4003 + * number is nonzero, the rshd daemon interprets it as the port number
4004 + * of a secondary stream to be used as standard error. A second connection
4005 + * is created to the specified port on the client host. The source port
4006 + * on the local host is in the range 0 through 1023.
4008 + * 3. The rshd daemon uses the source address of the initial connection
4009 + * request to determine the name of the client host. If the name cannot
4010 + * be determined, the rshd daemon uses the dotted decimal representation
4011 + * of the client host's address.
4013 + * 4. The rshd daemon retrieves the following information from the initial
4016 + * * A null-terminated string of at most 16 bytes interpreted as
4017 + * the user name of the user on the client host.
4019 + * * A null-terminated string of at most 16 bytes interpreted as
4020 + * the user name to be used on the local server host.
4022 + * * Another null-terminated string interpreted as a command line
4023 + * to be passed to a shell on the local server host.
4025 + * 5. The rshd daemon attempts to validate the user using the following steps:
4027 + * a. The rshd daemon looks up the local user name in the /etc/passwd
4028 + * file and tries to switch to the home directory (using the chdir
4029 + * subroutine). If either the lookup or the directory change fails,
4030 + * the rshd daemon terminates the connection.
4032 + * b. If the local user ID is a nonzero value, the rshd daemon searches
4033 + * the /etc/hosts.equiv file to see if the name of the client
4034 + * workstation is listed. If the client workstation is listed as an
4035 + * equivalent host, the rshd daemon validates the user.
4037 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4038 + * authenticate the user by checking the .rhosts file.
4040 + * d. If either the $HOME/.rhosts authentication fails or the
4041 + * client host is not an equivalent host, the rshd daemon
4042 + * terminates the connection.
4044 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
4045 + * on the initial connection and passes the command line to the user's
4046 + * local login shell. The shell then inherits the network connections
4047 + * established by the rshd daemon."
4052 +#include <linux/module.h>
4053 +#include <linux/netfilter.h>
4054 +#include <linux/ip.h>
4055 +#include <net/checksum.h>
4056 +#include <net/tcp.h>
4058 +#include <linux/netfilter_ipv4/lockhelp.h>
4059 +#include <linux/netfilter_ipv4/ip_tables.h>
4060 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4061 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4063 +#define MAX_PORTS 8
4064 +static int ports[MAX_PORTS];
4065 +static int ports_n_c = 0;
4067 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4068 +MODULE_DESCRIPTION("RSH connection tracking module");
4069 +MODULE_LICENSE("GPL");
4071 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4072 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4075 +DECLARE_LOCK(ip_rsh_lock);
4076 +struct module *ip_conntrack_rsh = THIS_MODULE;
4079 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4082 +#define DEBUGP(format, args...)
4087 +/* FIXME: This should be in userspace. Later. */
4088 +static int help(const struct iphdr *iph, size_t len,
4089 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4091 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4092 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4093 + const char *data = (const char *) tcph + tcph->doff * 4;
4094 + u_int32_t tcplen = len - iph->ihl * 4;
4095 + int dir = CTINFO2DIR(ctinfo);
4096 + struct ip_conntrack_expect expect, *exp = &expect;
4097 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4101 + /* note that "maxoctet" is used to maintain sanity (8 was the
4102 + * original array size used in rshd/glibc) -- is there a
4103 + * vulnerability in rshd.c in the looped port *= 10?
4107 + DEBUGP("entered\n");
4109 + /* bail if packet is not from RSH client */
4110 + if (dir == IP_CT_DIR_REPLY)
4113 + /* Until there's been traffic both ways, don't look in packets. */
4114 + if (ctinfo != IP_CT_ESTABLISHED
4115 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4116 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
4120 + /* Not whole TCP header? */
4121 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4122 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4126 + /* Checksum invalid? Ignore. */
4127 + /* FIXME: Source route IP option packets --RR */
4128 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4129 + csum_partial((char *) tcph, tcplen, 0))) {
4130 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4131 + tcph, tcplen, NIPQUAD(iph->saddr),
4132 + NIPQUAD(iph->daddr));
4136 + /* find the rsh stderr port */
4139 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4144 + if (*data < 48 || *data > 57) {
4145 + DEBUGP("these aren't the packets you're looking for ..\n");
4148 + port = port * 10 + ( *data - 48 );
4151 + /* dont relate sessions that try to expose the client */
4152 + DEBUGP("found port %u\n", port);
4153 + if (port > 1023) {
4154 + DEBUGP("skipping, expected port size is greater than 1023!\n");
4159 + LOCK_BH(&ip_rsh_lock);
4161 + /* new(,related) connection is;
4162 + * reply + dst (uint)port + src port (0:1023)
4164 + memset(&expect, 0, sizeof(expect));
4166 + /* save some discovered data, in case someone ever wants to write
4167 + * a NAT module for this bastard ..
4169 + exp_rsh_info->port = port;
4171 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4174 + /* Watch out, Radioactive-Man! */
4175 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4176 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4177 + exp->tuple.src.u.tcp.port = 0;
4178 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4179 + exp->tuple.dst.protonum = IPPROTO_TCP;
4181 + exp->mask.src.ip = 0xffffffff;
4182 + exp->mask.dst.ip = 0xffffffff;
4184 + exp->mask.src.u.tcp.port = htons(0xfc00);
4185 + exp->mask.dst.u.tcp.port = htons(0xfc00);
4186 + exp->mask.dst.protonum = 0xffff;
4188 + exp->expectfn = NULL;
4190 + ip_conntrack_expect_related(ct, &expect);
4192 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4193 + NIPQUAD(exp->tuple.src.ip),
4194 + ntohs(exp->tuple.src.u.tcp.port),
4195 + NIPQUAD(exp->tuple.dst.ip),
4196 + ntohs(exp->tuple.dst.u.tcp.port));
4198 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4199 + NIPQUAD(exp->mask.src.ip),
4200 + ntohs(exp->mask.src.u.tcp.port),
4201 + NIPQUAD(exp->mask.dst.ip),
4202 + ntohs(exp->mask.dst.u.tcp.port));
4203 + UNLOCK_BH(&ip_rsh_lock);
4208 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4210 +static void fini(void);
4212 +static int __init init(void)
4215 + static char name[10];
4218 + /* If no port given, default to standard RSH port */
4219 + if (ports[0] == 0)
4220 + ports[0] = RSH_PORT;
4222 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4223 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4225 + if (ports[port] == RSH_PORT)
4226 + sprintf(name, "rsh");
4228 + sprintf(name, "rsh-%d", port);
4230 + rsh_helpers[port].name = name;
4231 + rsh_helpers[port].me = THIS_MODULE;
4232 + rsh_helpers[port].max_expected = 1;
4233 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4234 + rsh_helpers[port].timeout = 0;
4236 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4237 + rsh_helpers[port].mask.dst.protonum = 0xffff;
4239 + /* RSH must come from ports 0:1023 to ports[port] (514) */
4240 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4241 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4242 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4244 + rsh_helpers[port].help = help;
4246 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4247 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4248 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
4249 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4250 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4251 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4252 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4253 + NIPQUAD(rsh_helpers[port].mask.src.ip),
4254 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4255 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
4256 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4258 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4261 + printk("ERROR registering port %d\n",
4271 +/* This function is intentionally _NOT_ defined as __exit, because
4272 + * it is needed by the init function */
4273 +static void fini(void)
4276 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4277 + DEBUGP("unregistering port %d\n", ports[port]);
4278 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
4284 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c
4285 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-16 08:59:08.000000000 +0200
4286 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-16 09:17:11.000000000 +0200
4288 len += sprintf(buffer + len, "[ASSURED] ");
4289 len += sprintf(buffer + len, "use=%u ",
4290 atomic_read(&conntrack->ct_general.use));
4291 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
4292 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
4294 len += sprintf(buffer + len, "\n");
4298 EXPORT_SYMBOL(ip_conntrack_alter_reply);
4299 EXPORT_SYMBOL(ip_conntrack_destroyed);
4300 EXPORT_SYMBOL(ip_conntrack_get);
4301 +EXPORT_SYMBOL(__ip_conntrack_confirm);
4302 EXPORT_SYMBOL(need_ip_conntrack);
4303 EXPORT_SYMBOL(ip_conntrack_helper_register);
4304 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
4305 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_talk.c
4306 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
4307 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_talk.c 2004-04-16 09:18:58.000000000 +0200
4310 + * talk extension for IP connection tracking.
4311 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4313 + * This program is free software; you can redistribute it and/or
4314 + * modify it under the terms of the GNU General Public License
4315 + * as published by the Free Software Foundation; either version
4316 + * 2 of the License, or (at your option) any later version.
4318 + * Module load syntax:
4319 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
4321 + * talk=[0|1] disable|enable old talk support
4322 + * ntalk=[0|1] disable|enable ntalk support
4323 + * ntalk2=[0|1] disable|enable ntalk2 support
4325 + * The default is talk=1 ntalk=1 ntalk2=1
4327 + * The helper does not support simultaneous talk requests.
4330 + * ASCII art on talk protocols
4333 + * caller server callee server
4340 + * caller client ----------- callee client
4343 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
4344 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
4345 + * 3. callee client <-> caller server: LOOK_UP invitation
4346 + * 4. callee client <-> caller client: talk data channel
4348 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
4349 + * draft-hunter-talk-00.txt
4350 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
4352 +#include <linux/config.h>
4353 +#include <linux/module.h>
4354 +#include <linux/netfilter.h>
4355 +#include <linux/ip.h>
4356 +#include <net/checksum.h>
4357 +#include <net/udp.h>
4359 +#include <linux/netfilter_ipv4/lockhelp.h>
4360 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4361 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4362 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4363 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
4365 +/* Default all talk protocols are supported */
4366 +static int talk = 1;
4367 +static int ntalk = 1;
4368 +static int ntalk2 = 1;
4369 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4370 +MODULE_DESCRIPTION("talk connection tracking module");
4371 +MODULE_LICENSE("GPL");
4373 +MODULE_PARM(talk, "i");
4374 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
4375 +MODULE_PARM(ntalk, "i");
4376 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
4377 +MODULE_PARM(ntalk2, "i");
4378 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
4381 +DECLARE_LOCK(ip_talk_lock);
4382 +struct module *ip_conntrack_talk = THIS_MODULE;
4385 +#define DEBUGP printk
4387 +#define DEBUGP(format, args...)
4390 +static int talk_expect(struct ip_conntrack *ct);
4391 +static int ntalk_expect(struct ip_conntrack *ct);
4393 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
4395 +static int talk_help_response(const struct iphdr *iph, size_t len,
4396 + struct ip_conntrack *ct,
4397 + enum ip_conntrack_info ctinfo,
4402 + struct talk_addr *addr)
4404 + int dir = CTINFO2DIR(ctinfo);
4405 + struct ip_conntrack_expect expect, *exp = &expect;
4406 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
4408 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
4409 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
4412 + if (!(answer == SUCCESS && type == mode))
4415 + memset(&expect, 0, sizeof(expect));
4417 + if (type == ANNOUNCE) {
4419 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
4421 + /* update the talk info */
4422 + LOCK_BH(&ip_talk_lock);
4423 + exp_talk_info->port = htons(talk_port);
4425 + /* expect callee client -> caller server message */
4426 + exp->tuple = ((struct ip_conntrack_tuple)
4427 + { { ct->tuplehash[dir].tuple.src.ip,
4429 + { ct->tuplehash[dir].tuple.dst.ip,
4430 + { .tcp = { htons(talk_port) } },
4432 + exp->mask = ((struct ip_conntrack_tuple)
4433 + { { 0xFFFFFFFF, { 0 } },
4434 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4436 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
4438 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
4439 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
4440 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
4442 + /* Ignore failure; should only happen with NAT */
4443 + ip_conntrack_expect_related(ct, &expect);
4444 + UNLOCK_BH(&ip_talk_lock);
4446 + if (type == LOOK_UP) {
4448 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
4450 + /* update the talk info */
4451 + LOCK_BH(&ip_talk_lock);
4452 + exp_talk_info->port = addr->ta_port;
4454 + /* expect callee client -> caller client connection */
4455 + exp->tuple = ((struct ip_conntrack_tuple)
4456 + { { ct->tuplehash[!dir].tuple.src.ip,
4459 + { addr->ta_port },
4461 + exp->mask = ((struct ip_conntrack_tuple)
4462 + { { 0xFFFFFFFF, { 0 } },
4463 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
4465 + exp->expectfn = NULL;
4467 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
4468 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
4469 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
4471 + /* Ignore failure; should only happen with NAT */
4472 + ip_conntrack_expect_related(ct, &expect);
4473 + UNLOCK_BH(&ip_talk_lock);
4479 +/* FIXME: This should be in userspace. Later. */
4480 +static int talk_help(const struct iphdr *iph, size_t len,
4481 + struct ip_conntrack *ct,
4482 + enum ip_conntrack_info ctinfo,
4486 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
4487 + const char *data = (const char *)udph + sizeof(struct udphdr);
4488 + int dir = CTINFO2DIR(ctinfo);
4491 + DEBUGP("ip_ct_talk_help: help entered\n");
4493 + /* Until there's been traffic both ways, don't look in packets. */
4494 + if (ctinfo != IP_CT_ESTABLISHED
4495 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4496 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
4500 + /* Not whole UDP header? */
4501 + udplen = len - iph->ihl * 4;
4502 + if (udplen < sizeof(struct udphdr)) {
4503 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
4507 + /* Checksum invalid? Ignore. */
4508 + /* FIXME: Source route IP option packets --RR */
4509 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4510 + csum_partial((char *)udph, udplen, 0))) {
4511 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4512 + udph, udplen, NIPQUAD(iph->saddr),
4513 + NIPQUAD(iph->daddr));
4517 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4518 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
4520 + if (dir == IP_CT_DIR_ORIGINAL)
4523 + if (talk_port == TALK_PORT
4524 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
4525 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4526 + ((struct talk_response *)data)->type,
4527 + ((struct talk_response *)data)->answer,
4528 + &(((struct talk_response *)data)->addr));
4529 + else if (talk_port == NTALK_PORT
4531 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
4532 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
4533 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4534 + ((struct ntalk_response *)data)->type,
4535 + ((struct ntalk_response *)data)->answer,
4536 + &(((struct ntalk_response *)data)->addr));
4537 + else if (talk_port == NTALK_PORT
4539 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
4540 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
4541 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4542 + ((struct ntalk2_response *)data)->type,
4543 + ((struct ntalk2_response *)data)->answer,
4544 + &(((struct ntalk2_response *)data)->addr));
4546 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
4547 + (unsigned)udplen - sizeof(struct udphdr),
4548 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
4553 +static int lookup_help(const struct iphdr *iph, size_t len,
4554 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4556 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
4559 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
4560 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4562 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
4565 +static struct ip_conntrack_helper lookup_helpers[2] =
4566 + { { { NULL, NULL },
4567 + "talk", /* name */
4569 + NULL, /* module */
4570 + 1, /* max_expected */
4571 + 240, /* timeout */
4572 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
4573 + { 0, { 0 }, IPPROTO_UDP } },
4574 + { { 0, { 0xFFFF } }, /* mask */
4575 + { 0, { 0 }, 0xFFFF } },
4576 + lookup_help }, /* helper */
4578 + "ntalk", /* name */
4580 + NULL, /* module */
4581 + 1, /* max_expected */
4582 + 240, /* timeout */
4583 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
4584 + { 0, { 0 }, IPPROTO_UDP } },
4585 + { { 0, { 0xFFFF } }, /* mask */
4586 + { 0, { 0 }, 0xFFFF } },
4587 + lookup_nhelp } /* helper */
4590 +static int talk_expect(struct ip_conntrack *ct)
4592 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
4593 + WRITE_LOCK(&ip_conntrack_lock);
4594 + ct->helper = &lookup_helpers[0];
4595 + WRITE_UNLOCK(&ip_conntrack_lock);
4597 + return NF_ACCEPT; /* unused */
4600 +static int ntalk_expect(struct ip_conntrack *ct)
4602 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
4603 + WRITE_LOCK(&ip_conntrack_lock);
4604 + ct->helper = &lookup_helpers[1];
4605 + WRITE_UNLOCK(&ip_conntrack_lock);
4607 + return NF_ACCEPT; /* unused */
4610 +static int help(const struct iphdr *iph, size_t len,
4611 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4613 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
4616 +static int nhelp(const struct iphdr *iph, size_t len,
4617 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4619 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
4622 +static struct ip_conntrack_helper talk_helpers[2] =
4623 + { { { NULL, NULL },
4624 + "talk", /* name */
4626 + THIS_MODULE, /* module */
4627 + 1, /* max_expected */
4628 + 240, /* timeout */
4629 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
4630 + { 0, { 0 }, IPPROTO_UDP } },
4631 + { { 0, { 0xFFFF } }, /* mask */
4632 + { 0, { 0 }, 0xFFFF } },
4633 + help }, /* helper */
4635 + "ntalk", /* name */
4637 + THIS_MODULE, /* module */
4638 + 1, /* max_expected */
4639 + 240, /* timeout */
4640 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
4641 + { 0, { 0 }, IPPROTO_UDP } },
4642 + { { 0, { 0xFFFF } }, /* mask */
4643 + { 0, { 0 }, 0xFFFF } },
4644 + nhelp } /* helper */
4647 +static int __init init(void)
4650 + ip_conntrack_helper_register(&talk_helpers[0]);
4651 + if (ntalk > 0 || ntalk2 > 0)
4652 + ip_conntrack_helper_register(&talk_helpers[1]);
4657 +static void __exit fini(void)
4660 + ip_conntrack_helper_unregister(&talk_helpers[0]);
4661 + if (ntalk > 0 || ntalk2 > 0)
4662 + ip_conntrack_helper_unregister(&talk_helpers[1]);
4665 +EXPORT_SYMBOL(ip_talk_lock);
4669 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_h323.c
4670 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
4671 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_h323.c 2004-04-16 09:17:05.000000000 +0200
4674 + * H.323 'brute force' extension for NAT alteration.
4675 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4677 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
4678 + * (http://www.coritel.it/projects/sofia/nat.html)
4679 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
4680 + * the unregistered helpers to the conntrack entries.
4684 +#include <linux/module.h>
4685 +#include <linux/netfilter.h>
4686 +#include <linux/ip.h>
4687 +#include <net/checksum.h>
4688 +#include <net/tcp.h>
4690 +#include <linux/netfilter_ipv4/lockhelp.h>
4691 +#include <linux/netfilter_ipv4/ip_nat.h>
4692 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
4693 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
4694 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
4695 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4696 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
4698 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4699 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
4700 +MODULE_LICENSE("GPL");
4702 +DECLARE_LOCK_EXTERN(ip_h323_lock);
4703 +struct module *ip_nat_h323 = THIS_MODULE;
4706 +#define DEBUGP printk
4708 +#define DEBUGP(format, args...)
4711 +/* FIXME: Time out? --RR */
4713 +static unsigned int
4714 +h225_nat_expected(struct sk_buff **pskb,
4715 + unsigned int hooknum,
4716 + struct ip_conntrack *ct,
4717 + struct ip_nat_info *info);
4719 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
4720 + struct ip_conntrack_expect *exp,
4721 + struct ip_nat_info *info,
4722 + enum ip_conntrack_info ctinfo,
4723 + unsigned int hooknum,
4724 + struct sk_buff **pskb);
4726 +static struct ip_nat_helper h245 =
4728 + "H.245", /* name */
4730 + NULL, /* module */
4731 + { { 0, { 0 } }, /* tuple */
4732 + { 0, { 0 }, IPPROTO_TCP } },
4733 + { { 0, { 0xFFFF } }, /* mask */
4734 + { 0, { 0 }, 0xFFFF } },
4735 + h225_nat_help, /* helper */
4736 + h225_nat_expected /* expectfn */
4739 +static unsigned int
4740 +h225_nat_expected(struct sk_buff **pskb,
4741 + unsigned int hooknum,
4742 + struct ip_conntrack *ct,
4743 + struct ip_nat_info *info)
4745 + struct ip_nat_multi_range mr;
4746 + u_int32_t newdstip, newsrcip, newip;
4748 + struct ip_ct_h225_expect *exp_info;
4749 + struct ip_ct_h225_master *master_info;
4750 + struct ip_conntrack *master = master_ct(ct);
4751 + unsigned int is_h225, ret;
4753 + IP_NF_ASSERT(info);
4754 + IP_NF_ASSERT(master);
4756 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
4758 + DEBUGP("h225_nat_expected: We have a connection!\n");
4759 + master_info = &ct->master->expectant->help.ct_h225_info;
4760 + exp_info = &ct->master->help.exp_h225_info;
4762 + LOCK_BH(&ip_h323_lock);
4764 + DEBUGP("master: ");
4765 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4766 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
4767 + DEBUGP("conntrack: ");
4768 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4769 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
4770 + /* Make connection go to the client. */
4771 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4772 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4773 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
4774 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
4776 + /* Make the connection go to the server */
4777 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4778 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4779 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
4780 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
4782 + port = exp_info->port;
4783 + is_h225 = master_info->is_h225 == H225_PORT;
4784 + UNLOCK_BH(&ip_h323_lock);
4786 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
4791 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
4794 + /* We don't want to manip the per-protocol, just the IPs... */
4795 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
4796 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
4798 + /* ... unless we're doing a MANIP_DST, in which case, make
4799 + sure we map to the correct port */
4800 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
4801 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
4802 + mr.range[0].min = mr.range[0].max
4803 + = ((union ip_conntrack_manip_proto)
4804 + { .tcp = { port } });
4807 + ret = ip_nat_setup_info(ct, &mr, hooknum);
4810 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
4811 + /* NAT expectfn called with ip_nat_lock write-locked */
4812 + info->helper = &h245;
4817 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
4818 + struct sk_buff **pskb,
4819 + enum ip_conntrack_info ctinfo)
4821 + struct iphdr *iph = (*pskb)->nh.iph;
4822 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
4823 + char *data = (char *) tcph + tcph->doff * 4;
4824 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
4825 + u_int32_t datalen = tcplen - tcph->doff*4;
4826 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
4831 + MUST_BE_LOCKED(&ip_h323_lock);
4833 + DEBUGP("h323_signal_address_fixup: %s %s\n",
4834 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
4836 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
4838 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
4839 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
4842 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
4843 + info->offset[IP_CT_DIR_ORIGINAL],
4844 + info->offset[IP_CT_DIR_REPLY],
4846 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4847 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
4849 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
4850 + DEBUGP("h323_signal_address_fixup: %s %s\n",
4851 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
4852 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
4853 + if (!between(info->seq[i], ntohl(tcph->seq),
4854 + ntohl(tcph->seq) + datalen))
4856 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
4857 + ntohl(tcph->seq) + datalen)) {
4858 + /* Partial retransmisison. It's a cracker being funky. */
4859 + if (net_ratelimit()) {
4860 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
4863 + ntohl(tcph->seq) + datalen);
4868 + /* Change address inside packet to match way we're mapping
4869 + this connection. */
4870 + if (i == IP_CT_DIR_ORIGINAL) {
4871 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
4872 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
4874 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
4875 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
4878 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
4879 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
4880 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
4881 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
4883 + /* Modify the packet */
4884 + *(u_int32_t *)(data + info->offset[i]) = newip;
4885 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
4887 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
4888 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
4889 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
4890 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
4893 + /* fix checksum information */
4895 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
4899 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4900 + csum_partial((char *)tcph, tcph->doff*4,
4902 + ip_send_check(iph);
4907 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
4908 + struct ip_conntrack *ct,
4909 + struct sk_buff **pskb,
4910 + enum ip_conntrack_info ctinfo,
4911 + struct ip_conntrack_expect *expect)
4915 + struct ip_conntrack_tuple newtuple;
4916 + struct iphdr *iph = (*pskb)->nh.iph;
4917 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
4918 + char *data = (char *) tcph + tcph->doff * 4;
4919 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
4920 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
4923 + MUST_BE_LOCKED(&ip_h323_lock);
4924 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
4925 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4926 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
4928 + if (!between(expect->seq + 6, ntohl(tcph->seq),
4929 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
4930 + /* Partial retransmisison. It's a cracker being funky. */
4931 + if (net_ratelimit()) {
4932 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
4935 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
4940 + /* Change address inside packet to match way we're mapping
4941 + this connection. */
4942 + if (info->dir == IP_CT_DIR_REPLY) {
4943 + /* Must be where client thinks server is */
4944 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4945 + /* Expect something from client->server */
4946 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4947 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4949 + /* Must be where server thinks client is */
4950 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4951 + /* Expect something from server->client */
4952 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4953 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4956 + is_h225 = (master_info->is_h225 == H225_PORT);
4959 + newtuple.dst.protonum = IPPROTO_TCP;
4960 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
4962 + newtuple.dst.protonum = IPPROTO_UDP;
4963 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
4966 + /* Try to get same port: if not, try to change it. */
4967 + for (port = ntohs(info->port); port != 0; port++) {
4969 + newtuple.dst.u.tcp.port = htons(port);
4971 + newtuple.dst.u.udp.port = htons(port);
4973 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
4977 + DEBUGP("h323_data_fixup: no free port found!\n");
4981 + port = htons(port);
4983 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
4984 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
4985 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
4987 + /* Modify the packet */
4988 + *(u_int32_t *)(data + info->offset) = newip;
4989 + *(u_int16_t *)(data + info->offset + 4) = port;
4991 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
4992 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
4993 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
4995 + /* fix checksum information */
4996 + /* FIXME: usually repeated multiple times in the case of H.245! */
4998 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
4999 + tcplen - tcph->doff*4, 0);
5002 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5003 + csum_partial((char *)tcph, tcph->doff*4,
5005 + ip_send_check(iph);
5010 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5011 + struct ip_conntrack_expect *exp,
5012 + struct ip_nat_info *info,
5013 + enum ip_conntrack_info ctinfo,
5014 + unsigned int hooknum,
5015 + struct sk_buff **pskb)
5018 + struct ip_ct_h225_expect *exp_info;
5020 + /* Only mangle things once: original direction in POST_ROUTING
5021 + and reply direction on PRE_ROUTING. */
5022 + dir = CTINFO2DIR(ctinfo);
5023 + DEBUGP("nat_h323: dir %s at hook %s\n",
5024 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5025 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5026 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5027 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5028 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5029 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5030 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
5031 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5032 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5033 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5034 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5039 + LOCK_BH(&ip_h323_lock);
5040 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
5041 + UNLOCK_BH(&ip_h323_lock);
5044 + UNLOCK_BH(&ip_h323_lock);
5048 + exp_info = &exp->help.exp_h225_info;
5050 + LOCK_BH(&ip_h323_lock);
5051 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
5052 + UNLOCK_BH(&ip_h323_lock);
5055 + UNLOCK_BH(&ip_h323_lock);
5060 +static struct ip_nat_helper h225 =
5062 + "H.225", /* name */
5063 + IP_NAT_HELPER_F_ALWAYS, /* flags */
5064 + THIS_MODULE, /* module */
5065 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
5066 + { 0, { 0 }, IPPROTO_TCP } },
5067 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
5068 + { 0, { 0 }, 0xFFFF } },
5069 + h225_nat_help, /* helper */
5070 + h225_nat_expected /* expectfn */
5073 +static int __init init(void)
5077 + ret = ip_nat_helper_register(&h225);
5080 + printk("ip_nat_h323: cannot initialize the module!\n");
5085 +static void __exit fini(void)
5087 + ip_nat_helper_unregister(&h225);
5092 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_mms.c
5093 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
5094 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_mms.c 2004-04-16 09:17:32.000000000 +0200
5096 +/* MMS extension for TCP NAT alteration.
5097 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5098 + * based on ip_nat_ftp.c and ip_nat_irc.c
5100 + * ip_nat_mms.c v0.3 2002-09-22
5102 + * This program is free software; you can redistribute it and/or
5103 + * modify it under the terms of the GNU General Public License
5104 + * as published by the Free Software Foundation; either version
5105 + * 2 of the License, or (at your option) any later version.
5107 + * Module load syntax:
5108 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
5110 + * Please give the ports of all MMS servers You wish to connect to.
5111 + * If you don't specify ports, the default will be TCP port 1755.
5113 + * More info on MMS protocol, firewalls and NAT:
5114 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
5115 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
5117 + * The SDP project people are reverse-engineering MMS:
5118 + * http://get.to/sdp
5121 +/* FIXME: issue with UDP & fragmentation with this URL:
5122 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
5123 + may be related to out-of-order first packets:
5124 + basically the expectation is set up correctly, then the server sends
5125 + a first UDP packet which is fragmented plus arrives out-of-order.
5126 + the MASQUERADING firewall with ip_nat_mms loaded responds with
5127 + an ICMP unreachable back to the server */
5129 +#include <linux/module.h>
5130 +#include <linux/netfilter_ipv4.h>
5131 +#include <linux/ip.h>
5132 +#include <linux/tcp.h>
5133 +#include <net/tcp.h>
5134 +#include <linux/netfilter_ipv4/ip_nat.h>
5135 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5136 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5137 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
5138 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5141 +#define DEBUGP printk
5142 +#define DUMP_BYTES(address, counter) \
5144 + int temp_counter; \
5145 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
5146 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
5151 +#define DEBUGP(format, args...)
5152 +#define DUMP_BYTES(address, counter)
5155 +#define MAX_PORTS 8
5156 +static int ports[MAX_PORTS];
5157 +static int ports_c = 0;
5160 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5163 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5164 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
5165 +MODULE_LICENSE("GPL");
5167 +DECLARE_LOCK_EXTERN(ip_mms_lock);
5169 +/* FIXME: Time out? --RR */
5171 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
5172 + struct ip_conntrack *ct,
5173 + struct sk_buff **pskb,
5174 + enum ip_conntrack_info ctinfo,
5175 + struct ip_conntrack_expect *expect)
5178 + struct ip_conntrack_tuple t;
5179 + struct iphdr *iph = (*pskb)->nh.iph;
5180 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5181 + char *data = (char *)tcph + tcph->doff * 4;
5182 + int i, j, k, port;
5183 + u_int16_t mms_proto;
5185 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
5186 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
5187 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
5191 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
5192 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
5193 + char proto_string[6];
5195 + MUST_BE_LOCKED(&ip_mms_lock);
5197 + /* what was the protocol again ? */
5198 + mms_proto = expect->tuple.dst.protonum;
5199 + sprintf(proto_string, "%u", mms_proto);
5201 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
5202 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
5203 + mms_proto == IPPROTO_UDP ? "UDP"
5204 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
5206 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5208 + /* Alter conntrack's expectations. */
5209 + t = expect->tuple;
5211 + for (port = ct_mms_info->port; port != 0; port++) {
5212 + t.dst.u.tcp.port = htons(port);
5213 + if (ip_conntrack_change_expect(expect, &t) == 0) {
5214 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
5222 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
5224 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
5225 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
5227 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
5229 + memset(unicode_buffer, 0, sizeof(char)*75);
5231 + for (i=0; i<strlen(buffer); ++i)
5232 + *(unicode_buffer+i*2)=*(buffer+i);
5234 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
5235 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
5236 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
5238 + /* add end of packet to it */
5239 + for (j=0; j<ct_mms_info->padding; ++j) {
5240 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
5241 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
5242 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
5245 + /* pad with zeroes at the end ? see explanation of weird math below */
5246 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
5247 + for (k=0; k<zero_padding; ++k)
5248 + *(unicode_buffer+i*2+j+k)= (char)0;
5250 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
5251 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
5252 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
5254 + /* explanation, before I forget what I did:
5255 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
5256 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
5257 + but note that things may have to be padded with zeroes to align by 8
5258 + bytes, hence we add 7 and divide by 8 to get the correct length */
5259 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
5260 + *mms_chunkLenLV = *mms_chunkLenLM+2;
5261 + *mms_messageLength = *mms_chunkLenLV*8;
5263 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
5264 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
5266 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
5267 + expect->seq - ntohl(tcph->seq),
5268 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
5269 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
5270 + DUMP_BYTES(unicode_buffer, 60);
5275 +static unsigned int
5276 +mms_nat_expected(struct sk_buff **pskb,
5277 + unsigned int hooknum,
5278 + struct ip_conntrack *ct,
5279 + struct ip_nat_info *info)
5281 + struct ip_nat_multi_range mr;
5282 + u_int32_t newdstip, newsrcip, newip;
5284 + struct ip_conntrack *master = master_ct(ct);
5286 + IP_NF_ASSERT(info);
5287 + IP_NF_ASSERT(master);
5289 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
5291 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
5293 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5294 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5295 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
5296 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5297 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5298 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
5299 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
5301 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5306 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
5309 + /* We don't want to manip the per-protocol, just the IPs. */
5310 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5311 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
5313 + return ip_nat_setup_info(ct, &mr, hooknum);
5317 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
5318 + struct ip_conntrack_expect *exp,
5319 + struct ip_nat_info *info,
5320 + enum ip_conntrack_info ctinfo,
5321 + unsigned int hooknum,
5322 + struct sk_buff **pskb)
5324 + struct iphdr *iph = (*pskb)->nh.iph;
5325 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5326 + unsigned int datalen;
5328 + struct ip_ct_mms_expect *ct_mms_info;
5331 + DEBUGP("ip_nat_mms: no exp!!");
5333 + ct_mms_info = &exp->help.exp_mms_info;
5335 + /* Only mangle things once: original direction in POST_ROUTING
5336 + and reply direction on PRE_ROUTING. */
5337 + dir = CTINFO2DIR(ctinfo);
5338 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5339 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5340 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
5341 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5342 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5343 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5344 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5347 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
5348 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5349 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5350 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5351 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5353 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
5355 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
5356 + exp->seq + ct_mms_info->len,
5358 + ntohl(tcph->seq) + datalen);
5360 + LOCK_BH(&ip_mms_lock);
5361 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
5362 + if (between(exp->seq + ct_mms_info->len,
5364 + ntohl(tcph->seq) + datalen)) {
5365 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
5366 + UNLOCK_BH(&ip_mms_lock);
5370 + /* Half a match? This means a partial retransmisison.
5371 + It's a cracker being funky. */
5372 + if (net_ratelimit()) {
5373 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
5374 + exp->seq, ct_mms_info->len,
5376 + ntohl(tcph->seq) + datalen);
5378 + UNLOCK_BH(&ip_mms_lock);
5381 + UNLOCK_BH(&ip_mms_lock);
5386 +static struct ip_nat_helper mms[MAX_PORTS];
5387 +static char mms_names[MAX_PORTS][10];
5389 +/* Not __exit: called from init() */
5390 +static void fini(void)
5394 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
5395 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
5396 + ip_nat_helper_unregister(&mms[i]);
5400 +static int __init init(void)
5405 + if (ports[0] == 0)
5406 + ports[0] = MMS_PORT;
5408 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
5410 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
5412 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
5413 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
5414 + mms[i].mask.dst.protonum = 0xFFFF;
5415 + mms[i].mask.src.u.tcp.port = 0xFFFF;
5416 + mms[i].help = mms_nat_help;
5417 + mms[i].me = THIS_MODULE;
5419 + mms[i].expect = mms_nat_expected;
5421 + tmpname = &mms_names[i][0];
5422 + if (ports[i] == MMS_PORT)
5423 + sprintf(tmpname, "mms");
5425 + sprintf(tmpname, "mms-%d", i);
5426 + mms[i].name = tmpname;
5428 + DEBUGP("ip_nat_mms: register helper for port %d\n",
5430 + ret = ip_nat_helper_register(&mms[i]);
5433 + printk("ip_nat_mms: error registering "
5434 + "helper for port %d\n", ports[i]);
5446 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_quake3.c
5447 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
5448 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_quake3.c 2004-04-16 09:18:43.000000000 +0200
5450 +/* Quake3 extension for UDP NAT alteration.
5451 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5452 + * based on ip_nat_ftp.c and ip_nat_tftp.c
5454 + * ip_nat_quake3.c v0.0.3 2002-08-31
5456 + * This program is free software; you can redistribute it and/or
5457 + * modify it under the terms of the GNU General Public License
5458 + * as published by the Free Software Foundation; either version
5459 + * 2 of the License, or (at your option) any later version.
5461 + * Module load syntax:
5462 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
5464 + * please give the ports of all Quake3 master servers You wish to
5465 + * connect to. If you don't specify ports, the default will be UDP
5468 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5471 + * - If you're one of those people who would try anything to lower
5472 + * latency while playing Quake (and who isn't :-) ), you may want to
5473 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
5474 + * outgoing UDP traffic.
5475 + * This will make ip_conntrack_quake3 add the necessary expectations,
5476 + * but there will be no overhead for client->server UDP streams. If
5477 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
5478 + * hook for every packet in the client->server UDP stream.
5479 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
5480 + * The IP addresses in the master connection payload (=IP addresses
5481 + * of Quake servers) have no relation with the master server so
5482 + * DNAT'ing the master connection to a server should not change the
5483 + * expected connections.
5484 + * - Not tested due to lack of equipment:
5485 + * - multiple Quake3 clients behind one MASQUERADE gateway
5486 + * - what if Quake3 client is running on router too
5489 +#include <linux/module.h>
5490 +#include <linux/netfilter_ipv4.h>
5491 +#include <linux/ip.h>
5492 +#include <linux/udp.h>
5494 +#include <linux/netfilter.h>
5495 +#include <linux/netfilter_ipv4/ip_tables.h>
5496 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5497 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5498 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5499 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5501 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5502 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
5503 +MODULE_LICENSE("GPL");
5505 +#define MAX_PORTS 8
5507 +static int ports[MAX_PORTS];
5508 +static int ports_c = 0;
5510 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5511 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5514 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5515 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5517 +#define DEBUGP printk
5519 +#define DEBUGP(format, args...)
5522 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5524 +static unsigned int
5525 +quake3_nat_help(struct ip_conntrack *ct,
5526 + struct ip_conntrack_expect *exp,
5527 + struct ip_nat_info *info,
5528 + enum ip_conntrack_info ctinfo,
5529 + unsigned int hooknum,
5530 + struct sk_buff **pskb)
5532 + struct iphdr *iph = (*pskb)->nh.iph;
5533 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5534 + struct ip_conntrack_tuple repl;
5535 + int dir = CTINFO2DIR(ctinfo);
5538 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
5539 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5540 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5541 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5542 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
5544 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5545 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5547 + /* Only mangle things once: original direction in POST_ROUTING
5548 + and reply direction on PRE_ROUTING. */
5549 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5550 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5551 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
5552 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5553 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5554 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5555 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
5560 + DEBUGP("no conntrack expectation to modify\n");
5564 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
5565 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5566 + i+6 < ntohs(udph->len);
5568 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5569 + i, ntohs(udph->len),
5570 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
5571 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5573 + memset(&repl, 0, sizeof(repl));
5575 + repl.dst.protonum = IPPROTO_UDP;
5576 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5577 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
5578 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
5580 + ip_conntrack_change_expect(exp, &repl);
5586 +static unsigned int
5587 +quake3_nat_expected(struct sk_buff **pskb,
5588 + unsigned int hooknum,
5589 + struct ip_conntrack *ct,
5590 + struct ip_nat_info *info)
5592 + const struct ip_conntrack *master = ct->master->expectant;
5593 + struct ip_nat_multi_range mr;
5594 + u_int32_t newsrcip, newdstip, newip;
5596 + const struct ip_conntrack_tuple *repl =
5597 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
5598 + struct iphdr *iph = (*pskb)->nh.iph;
5599 + struct udphdr *udph = (void *)iph + iph->ihl*4;
5602 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
5603 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5605 + IP_NF_ASSERT(info);
5606 + IP_NF_ASSERT(master);
5607 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
5609 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5610 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5612 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
5614 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
5615 + "newsrc: %u.%u.%u.%u\n",
5616 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5617 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5618 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
5619 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
5620 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
5625 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
5626 + "newdst: %u.%u.%u.%u\n",
5627 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5628 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5629 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
5630 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
5631 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
5636 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5637 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
5639 + return ip_nat_setup_info(ct,&mr,hooknum);
5642 +static struct ip_nat_helper quake3[MAX_PORTS];
5643 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
5645 +static void fini(void)
5649 + for (i = 0 ; i < ports_c; i++) {
5650 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
5651 + ip_nat_helper_unregister(&quake3[i]);
5655 +static int __init init(void)
5661 + ports[0] = QUAKE3_MASTER_PORT;
5663 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5664 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
5666 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5667 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5668 + quake3[i].mask.dst.protonum = 0xFFFF;
5669 + quake3[i].mask.src.u.udp.port = 0xFFFF;
5670 + quake3[i].help = quake3_nat_help;
5671 + quake3[i].flags = 0;
5672 + quake3[i].me = THIS_MODULE;
5673 + quake3[i].expect = quake3_nat_expected;
5675 + tmpname = &quake3_names[i][0];
5676 + if (ports[i] == QUAKE3_MASTER_PORT)
5677 + sprintf(tmpname, "quake3");
5679 + sprintf(tmpname, "quake3-%d", i);
5680 + quake3[i].name = tmpname;
5682 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
5683 + ports[i], quake3[i].name);
5684 + ret = ip_nat_helper_register(&quake3[i]);
5687 + printk("ip_nat_quake3: unable to register helper for port %d\n",
5699 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_standalone.c
5700 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-15 03:35:20.000000000 +0200
5701 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-16 09:17:11.000000000 +0200
5702 @@ -175,6 +175,45 @@
5703 return do_bindings(ct, ctinfo, info, hooknum, pskb);
5706 +struct nat_route_key
5715 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
5717 + struct iphdr *iph = skb->nh.iph;
5719 + key->addr = which ? iph->daddr : iph->saddr;
5722 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
5723 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
5724 + key->port = ports[which];
5730 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
5732 + struct iphdr *iph = skb->nh.iph;
5734 + if (key->addr != (which ? iph->daddr : iph->saddr))
5737 + if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
5738 + u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
5739 + if (key->port != ports[which])
5746 ip_nat_out(unsigned int hooknum,
5747 struct sk_buff **pskb,
5749 const struct net_device *out,
5750 int (*okfn)(struct sk_buff *))
5752 + struct nat_route_key key;
5755 /* root is playing with raw sockets. */
5756 if ((*pskb)->len < sizeof(struct iphdr)
5757 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
5758 @@ -204,7 +246,29 @@
5762 - return ip_nat_fn(hooknum, pskb, in, out, okfn);
5763 + nat_route_key_get(*pskb, &key, 0);
5764 + ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
5766 + if (ret != NF_DROP && ret != NF_STOLEN
5767 + && nat_route_key_compare(*pskb, &key, 0)) {
5768 + if (ip_route_me_harder(pskb) != 0)
5772 + * POST_ROUTING hook is called with fixed outfn, we need
5773 + * to manually confirm the packet and direct it to the
5774 + * transformers if a policy matches.
5776 + else if ((*pskb)->dst->xfrm != NULL) {
5777 + ret = ip_conntrack_confirm(*pskb);
5778 + if (ret != NF_DROP) {
5779 + dst_output(*pskb);
5788 #ifdef CONFIG_IP_NF_NAT_LOCAL
5790 const struct net_device *out,
5791 int (*okfn)(struct sk_buff *))
5793 - u_int32_t saddr, daddr;
5794 + struct nat_route_key key;
5797 /* root is playing with raw sockets. */
5798 @@ -223,14 +287,14 @@
5799 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
5802 - saddr = (*pskb)->nh.iph->saddr;
5803 - daddr = (*pskb)->nh.iph->daddr;
5805 + nat_route_key_get(*pskb, &key, 1);
5806 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
5808 if (ret != NF_DROP && ret != NF_STOLEN
5809 - && ((*pskb)->nh.iph->saddr != saddr
5810 - || (*pskb)->nh.iph->daddr != daddr))
5811 - return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
5812 + && nat_route_key_compare(*pskb, &key, 1)) {
5813 + if (ip_route_me_harder(pskb) != 0)
5819 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_talk.c
5820 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
5821 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_talk.c 2004-04-16 09:18:58.000000000 +0200
5824 + * talk extension for UDP NAT alteration.
5825 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5827 + * This program is free software; you can redistribute it and/or
5828 + * modify it under the terms of the GNU General Public License
5829 + * as published by the Free Software Foundation; either version
5830 + * 2 of the License, or (at your option) any later version.
5832 + * Module load syntax:
5833 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
5835 + * talk=[0|1] disable|enable old talk support
5836 + * ntalk=[0|1] disable|enable ntalk support
5837 + * ntalk2=[0|1] disable|enable ntalk2 support
5839 + * The default is talk=1 ntalk=1 ntalk2=1
5843 +#include <linux/module.h>
5844 +#include <linux/netfilter_ipv4.h>
5845 +#include <linux/ip.h>
5846 +#include <linux/udp.h>
5847 +#include <linux/kernel.h>
5848 +#include <net/tcp.h>
5849 +#include <net/udp.h>
5851 +#include <linux/netfilter_ipv4/ip_nat.h>
5852 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5853 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5854 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5855 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5857 +/* Default all talk protocols are supported */
5858 +static int talk = 1;
5859 +static int ntalk = 1;
5860 +static int ntalk2 = 1;
5861 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5862 +MODULE_DESCRIPTION("talk network address translation module");
5864 +MODULE_PARM(talk, "i");
5865 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5866 +MODULE_PARM(ntalk, "i");
5867 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5868 +MODULE_PARM(ntalk2, "i");
5869 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5873 +#define DEBUGP printk
5874 +#define IP_NAT_TALK_DEBUG
5876 +#define DEBUGP(format, args...)
5879 +/* FIXME: Time out? --RR */
5882 +mangle_packet(struct sk_buff **pskb,
5883 + struct ip_conntrack *ct,
5886 + struct talk_addr *addr,
5887 + struct talk_addr *ctl_addr)
5889 + struct iphdr *iph = (*pskb)->nh.iph;
5890 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5891 + size_t udplen = (*pskb)->len - iph->ihl * 4;
5893 + /* Fortunately talk sends a structure with the address and
5894 + port in it. The size of the packet won't change. */
5896 + if (ctl_addr == NULL) {
5898 + if (addr->ta_addr == INADDR_ANY)
5900 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
5901 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5902 + NIPQUAD(newip), ntohs(port));
5903 + addr->ta_addr = newip;
5904 + addr->ta_port = port;
5907 + if (addr->ta_addr != INADDR_ANY) {
5908 + /* Change address inside packet to match way we're mapping
5909 + this connection. */
5910 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
5911 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5912 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5913 + ntohs(addr->ta_port));
5914 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5916 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
5917 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
5918 + NIPQUAD(newip), ntohs(port));
5919 + ctl_addr->ta_addr = newip;
5920 + ctl_addr->ta_port = port;
5923 + /* Fix checksums */
5924 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
5926 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5927 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
5929 + ip_send_check(iph);
5933 +static int talk_help_msg(struct ip_conntrack *ct,
5934 + struct sk_buff **pskb,
5936 + struct talk_addr *addr,
5937 + struct talk_addr *ctl_addr)
5942 + unsigned int verdict = NF_ACCEPT;
5944 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
5945 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5946 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
5949 + /* Change address inside packet to match way we're mapping
5950 + this connection. */
5951 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5952 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5953 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
5954 + NIPQUAD(newip), ntohs(port));
5956 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
5957 + verdict = NF_DROP;
5962 +static int talk_help_response(struct ip_conntrack *ct,
5963 + struct ip_conntrack_expect *exp,
5964 + struct sk_buff **pskb,
5967 + struct talk_addr *addr)
5971 + struct ip_conntrack_tuple t;
5972 + struct ip_ct_talk_expect *ct_talk_info;
5974 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
5975 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5978 + LOCK_BH(&ip_talk_lock);
5979 + ct_talk_info = &exp->help.exp_talk_info;
5981 + if (!(answer == SUCCESS
5982 + && (type == LOOK_UP || type == ANNOUNCE)
5983 + && exp != NULL)) {
5984 + UNLOCK_BH(&ip_talk_lock);
5988 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
5989 + ntohs(ct_talk_info->port),
5990 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
5992 + /* Change address inside packet to match way we're mapping
5993 + this connection. */
5994 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
5995 + IP_CT_DIR_REPLY].tuple.dst.ip;
5996 + /* We can read expect here without conntrack lock, since it's
5997 + only set in ip_conntrack_talk , with ip_talk_lock held
6002 + /* Try to get same port: if not, try to change it. */
6003 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
6004 + if (type == LOOK_UP)
6005 + t.dst.u.tcp.port = htons(port);
6007 + t.dst.u.udp.port = htons(port);
6009 + if (ip_conntrack_change_expect(exp, &t) == 0) {
6010 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
6014 + UNLOCK_BH(&ip_talk_lock);
6016 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
6022 +static unsigned int talk_help(struct ip_conntrack *ct,
6023 + struct ip_conntrack_expect *exp,
6024 + struct ip_nat_info *info,
6025 + enum ip_conntrack_info ctinfo,
6026 + unsigned int hooknum,
6027 + struct sk_buff **pskb,
6030 + struct iphdr *iph = (*pskb)->nh.iph;
6031 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6032 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
6033 + char *data = (char *)udph + sizeof(struct udphdr);
6036 + /* Only mangle things once: original direction in POST_ROUTING
6037 + and reply direction on PRE_ROUTING. */
6038 + dir = CTINFO2DIR(ctinfo);
6039 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6040 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6041 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
6042 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6043 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6044 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6045 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6048 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
6049 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6050 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6051 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6052 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6053 + NIPQUAD(iph->saddr), ntohs(udph->source),
6054 + NIPQUAD(iph->daddr), ntohs(udph->dest),
6057 + /* Because conntrack does not drop packets, checking must be repeated here... */
6058 + if (talk_port == TALK_PORT) {
6059 + if (dir == IP_CT_DIR_ORIGINAL
6060 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
6061 + return talk_help_msg(ct, pskb,
6062 + ((struct talk_msg *)data)->type,
6063 + &(((struct talk_msg *)data)->addr),
6064 + &(((struct talk_msg *)data)->ctl_addr));
6065 + else if (dir == IP_CT_DIR_REPLY
6066 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6067 + return talk_help_response(ct, exp, pskb,
6068 + ((struct talk_response *)data)->type,
6069 + ((struct talk_response *)data)->answer,
6070 + &(((struct talk_response *)data)->addr));
6072 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
6073 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
6074 + (unsigned)udplen - sizeof(struct udphdr),
6075 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
6079 + if (dir == IP_CT_DIR_ORIGINAL) {
6081 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
6082 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
6083 + return talk_help_msg(ct, pskb,
6084 + ((struct ntalk_msg *)data)->type,
6085 + &(((struct ntalk_msg *)data)->addr),
6086 + &(((struct ntalk_msg *)data)->ctl_addr));
6088 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
6089 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
6090 + && udplen == sizeof(struct udphdr)
6091 + + sizeof(struct ntalk2_msg)
6092 + + ((struct ntalk2_msg *)data)->extended)
6093 + return talk_help_msg(ct, pskb,
6094 + ((struct ntalk2_msg *)data)->type,
6095 + &(((struct ntalk2_msg *)data)->addr),
6096 + &(((struct ntalk2_msg *)data)->ctl_addr));
6098 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
6099 + (unsigned)udplen - sizeof(struct udphdr),
6100 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
6105 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6106 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6107 + return talk_help_response(ct, exp, pskb,
6108 + ((struct ntalk_response *)data)->type,
6109 + ((struct ntalk_response *)data)->answer,
6110 + &(((struct ntalk_response *)data)->addr));
6112 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6113 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6114 + return talk_help_response(ct, exp, pskb,
6115 + ((struct ntalk2_response *)data)->type,
6116 + ((struct ntalk2_response *)data)->answer,
6117 + &(((struct ntalk2_response *)data)->addr));
6119 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
6120 + (unsigned)udplen - sizeof(struct udphdr),
6121 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6128 +static unsigned int help(struct ip_conntrack *ct,
6129 + struct ip_conntrack_expect *exp,
6130 + struct ip_nat_info *info,
6131 + enum ip_conntrack_info ctinfo,
6132 + unsigned int hooknum,
6133 + struct sk_buff **pskb)
6135 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
6138 +static unsigned int nhelp(struct ip_conntrack *ct,
6139 + struct ip_conntrack_expect *exp,
6140 + struct ip_nat_info *info,
6141 + enum ip_conntrack_info ctinfo,
6142 + unsigned int hooknum,
6143 + struct sk_buff **pskb)
6145 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
6148 +static unsigned int
6149 +talk_nat_expected(struct sk_buff **pskb,
6150 + unsigned int hooknum,
6151 + struct ip_conntrack *ct,
6152 + struct ip_nat_info *info);
6154 +static struct ip_nat_helper talk_helpers[2] =
6155 + { { { NULL, NULL },
6156 + "talk", /* name */
6157 + IP_NAT_HELPER_F_ALWAYS, /* flags */
6158 + THIS_MODULE, /* module */
6159 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
6160 + { 0, { 0 }, IPPROTO_UDP } },
6161 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
6162 + { 0, { 0 }, 0xFFFF } },
6163 + help, /* helper */
6164 + talk_nat_expected }, /* expectfn */
6166 + "ntalk", /* name */
6167 + IP_NAT_HELPER_F_ALWAYS, /* flags */
6168 + THIS_MODULE, /* module */
6169 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
6170 + { 0, { 0 }, IPPROTO_UDP } },
6171 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
6172 + { 0, { 0 }, 0xFFFF } },
6173 + nhelp, /* helper */
6174 + talk_nat_expected } /* expectfn */
6177 +static unsigned int
6178 +talk_nat_expected(struct sk_buff **pskb,
6179 + unsigned int hooknum,
6180 + struct ip_conntrack *ct,
6181 + struct ip_nat_info *info)
6183 + struct ip_nat_multi_range mr;
6184 + u_int32_t newdstip, newsrcip, newip;
6188 + struct ip_conntrack *master = master_ct(ct);
6190 + IP_NF_ASSERT(info);
6191 + IP_NF_ASSERT(master);
6193 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6195 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
6197 + LOCK_BH(&ip_talk_lock);
6198 + port = ct->master->help.exp_talk_info.port;
6199 + UNLOCK_BH(&ip_talk_lock);
6201 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
6202 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6203 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6204 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6205 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6208 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
6209 + /* Callee client -> caller server */
6210 +#ifdef IP_NAT_TALK_DEBUG
6211 + struct iphdr *iph = (*pskb)->nh.iph;
6212 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
6214 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6215 + NIPQUAD(iph->saddr), ntohs(udph->source),
6216 + NIPQUAD(iph->daddr), ntohs(udph->dest));
6218 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6219 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6220 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
6221 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6223 + /* Callee client -> caller client */
6224 +#ifdef IP_NAT_TALK_DEBUG
6225 + struct iphdr *iph = (*pskb)->nh.iph;
6226 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
6228 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6229 + NIPQUAD(iph->saddr), ntohs(tcph->source),
6230 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
6232 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6233 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6234 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
6235 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
6237 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6242 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
6245 + /* We don't want to manip the per-protocol, just the IPs... */
6246 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6247 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
6249 + /* ... unless we're doing a MANIP_DST, in which case, make
6250 + sure we map to the correct port */
6251 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6252 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6253 + mr.range[0].min = mr.range[0].max
6254 + = ((union ip_conntrack_manip_proto)
6255 + { .udp = { port } });
6257 + ret = ip_nat_setup_info(ct, &mr, hooknum);
6259 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
6260 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
6261 + /* NAT expectfn called with ip_nat_lock write-locked */
6262 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
6267 +static int __init init(void)
6272 + ret = ip_nat_helper_register(&talk_helpers[0]);
6277 + if (ntalk > 0 || ntalk2 > 0) {
6278 + ret = ip_nat_helper_register(&talk_helpers[1]);
6280 + if (ret != 0 && talk > 0)
6281 + ip_nat_helper_unregister(&talk_helpers[0]);
6286 +static void __exit fini(void)
6289 + ip_nat_helper_unregister(&talk_helpers[0]);
6290 + if (ntalk > 0 || ntalk2 > 0)
6291 + ip_nat_helper_unregister(&talk_helpers[1]);
6296 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_tables.c
6297 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_tables.c 2004-04-16 08:59:08.000000000 +0200
6298 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_tables.c 2004-04-16 09:17:31.000000000 +0200
6300 * it under the terms of the GNU General Public License version 2 as
6301 * published by the Free Software Foundation.
6303 + * 6 Mar 2002 Robert Olsson <robban@robtex.com>
6304 + * 17 Apr 2003 Chris Wilson <chris@netservers.co.uk>
6305 + * - mark_source_chains speedup for complex chains
6307 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
6308 * - increase module usage count as soon as we have rules inside
6314 + /* keep track of where we have been: */
6315 + unsigned char *been = vmalloc(newinfo->size);
6317 /* No recursion; use packet counter to save back ptrs (reset
6318 to 0 as we leave), and comefrom to save source hook bitmask */
6319 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
6322 /* Set initial back pointer. */
6323 e->counters.pcnt = pos;
6324 + memset(been, 0, newinfo->size);
6327 struct ipt_standard_target *t
6329 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
6330 printk("iptables: loop hook %u pos %u %08X.\n",
6331 hook, pos, e->comefrom);
6336 @@ -565,10 +574,14 @@
6338 int newpos = t->verdict;
6340 - if (strcmp(t->target.u.user.name,
6341 + if ( (pos < 0 || pos >= newinfo->size
6343 + && strcmp(t->target.u.user.name,
6344 IPT_STANDARD_TARGET) == 0
6346 /* This a jump; chase it. */
6347 + if (pos >= 0 && pos < newinfo->size)
6349 duprintf("Jump rule %u -> %u\n",
6354 duprintf("Finished chain %u\n", hook);
6360 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_CONNMARK.c
6361 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
6362 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-16 09:15:41.000000000 +0200
6364 +/* This kernel module is used to modify the connection mark values, or
6365 + * to optionally restore the skb nfmark from the connection mark
6367 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
6368 + * by Henrik Nordstrom <hno@marasystems.com>
6370 + * This program is free software; you can redistribute it and/or modify
6371 + * it under the terms of the GNU General Public License as published by
6372 + * the Free Software Foundation; either version 2 of the License, or
6373 + * (at your option) any later version.
6375 + * This program is distributed in the hope that it will be useful,
6376 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6377 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6378 + * GNU General Public License for more details.
6380 + * You should have received a copy of the GNU General Public License
6381 + * along with this program; if not, write to the Free Software
6382 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6384 +#include <linux/module.h>
6385 +#include <linux/skbuff.h>
6386 +#include <linux/ip.h>
6387 +#include <net/checksum.h>
6389 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
6390 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
6391 +MODULE_LICENSE("GPL");
6393 +#include <linux/netfilter_ipv4/ip_tables.h>
6394 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
6395 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6397 +static unsigned int
6398 +target(struct sk_buff **pskb,
6399 + const struct net_device *in,
6400 + const struct net_device *out,
6401 + unsigned int hooknum,
6402 + const void *targinfo,
6405 + const struct ipt_connmark_target_info *markinfo = targinfo;
6406 + unsigned long diff;
6407 + unsigned long nfmark;
6408 + unsigned long newmark;
6410 + enum ip_conntrack_info ctinfo;
6411 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
6413 + switch(markinfo->mode) {
6414 + case IPT_CONNMARK_SET:
6415 + newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
6416 + if (newmark != ct->mark)
6417 + ct->mark = newmark;
6419 + case IPT_CONNMARK_SAVE:
6420 + newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
6421 + if (ct->mark != newmark)
6422 + ct->mark = newmark;
6424 + case IPT_CONNMARK_RESTORE:
6425 + nfmark = (*pskb)->nfmark;
6426 + diff = (ct->mark ^ nfmark & markinfo->mask);
6428 + (*pskb)->nfmark = nfmark ^ diff;
6429 + (*pskb)->nfcache |= NFC_ALTERED;
6435 + return IPT_CONTINUE;
6439 +checkentry(const char *tablename,
6440 + const struct ipt_entry *e,
6442 + unsigned int targinfosize,
6443 + unsigned int hook_mask)
6445 + struct ipt_connmark_target_info *matchinfo = targinfo;
6446 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
6447 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
6449 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
6453 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
6454 + if (strcmp(tablename, "mangle") != 0) {
6455 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6463 +static struct ipt_target ipt_connmark_reg = {
6464 + .name = "CONNMARK",
6465 + .target = &target,
6466 + .checkentry = &checkentry,
6470 +static int __init init(void)
6472 + return ipt_register_target(&ipt_connmark_reg);
6475 +static void __exit fini(void)
6477 + ipt_unregister_target(&ipt_connmark_reg);
6482 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_IPMARK.c
6483 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
6484 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-16 09:15:43.000000000 +0200
6486 +/* This is a module which is used for setting the NFMARK field of an skb. */
6487 +#include <linux/module.h>
6488 +#include <linux/skbuff.h>
6489 +#include <linux/ip.h>
6490 +#include <net/checksum.h>
6492 +#include <linux/netfilter_ipv4/ip_tables.h>
6493 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
6495 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
6496 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
6497 +MODULE_LICENSE("GPL");
6499 +static unsigned int
6500 +target(struct sk_buff **pskb,
6501 + const struct net_device *in,
6502 + const struct net_device *out,
6503 + unsigned int hooknum,
6504 + const void *targinfo,
6507 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
6508 + struct iphdr *iph = (*pskb)->nh.iph;
6509 + unsigned long mark;
6511 + if (ipmarkinfo->addr == IPT_IPMARK_SRC)
6512 + mark = (unsigned long) ntohl(iph->saddr);
6514 + mark = (unsigned long) ntohl(iph->daddr);
6516 + mark &= ipmarkinfo->andmask;
6517 + mark |= ipmarkinfo->ormask;
6519 + if ((*pskb)->nfmark != mark) {
6520 + (*pskb)->nfmark = mark;
6521 + (*pskb)->nfcache |= NFC_ALTERED;
6523 + return IPT_CONTINUE;
6527 +checkentry(const char *tablename,
6528 + const struct ipt_entry *e,
6530 + unsigned int targinfosize,
6531 + unsigned int hook_mask)
6533 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
6534 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
6536 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
6540 + if (strcmp(tablename, "mangle") != 0) {
6541 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6548 +static struct ipt_target ipt_ipmark_reg = {
6551 + .checkentry = checkentry,
6555 +static int __init init(void)
6557 + return ipt_register_target(&ipt_ipmark_reg);
6560 +static void __exit fini(void)
6562 + ipt_unregister_target(&ipt_ipmark_reg);
6567 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_ROUTE.c
6568 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
6569 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_ROUTE.c 2004-04-16 09:15:44.000000000 +0200
6572 + * This implements the ROUTE target, which enables you to setup unusual
6573 + * routes not supported by the standard kernel routing table.
6575 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
6577 + * v 1.8 2003/07/25
6579 + * This software is distributed under GNU GPL v2, 1991
6582 +#include <linux/module.h>
6583 +#include <linux/skbuff.h>
6584 +#include <linux/ip.h>
6585 +#include <linux/netfilter_ipv4/ip_tables.h>
6586 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
6587 +#include <linux/netdevice.h>
6588 +#include <linux/route.h>
6589 +#include <net/ip.h>
6590 +#include <net/route.h>
6591 +#include <net/icmp.h>
6594 +#define DEBUGP printk
6596 +#define DEBUGP(format, args...)
6599 +MODULE_LICENSE("GPL");
6600 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
6602 +/* Try to route the packet according to the routing keys specified in
6603 + * route_info. Keys are :
6605 + * 0 if no oif preferred,
6606 + * otherwise set to the index of the desired oif
6607 + * - route_info->gw :
6608 + * 0 if no gateway specified,
6609 + * otherwise set to the next host to which the pkt must be routed
6610 + * If success, skb->dev is the output device to which the packet must
6611 + * be sent and skb->dst is not NULL
6613 + * RETURN: -1 if an error occured
6614 + * 1 if the packet was succesfully routed to the
6615 + * destination desired
6616 + * 0 if the kernel routing table could not route the packet
6617 + * according to the keys specified
6619 +static int route(struct sk_buff *skb,
6620 + unsigned int ifindex,
6621 + const struct ipt_route_target_info *route_info)
6624 + struct rtable *rt;
6625 + struct iphdr *iph = skb->nh.iph;
6626 + struct rt_key key = {
6630 + tos:RT_TOS(iph->tos)
6633 + /* The destination address may be overloaded by the target */
6634 + if (route_info->gw)
6635 + key.dst = route_info->gw;
6637 + /* Trying to route the packet using the standard routing table. */
6638 + if ((err = ip_route_output_key(&rt, &key))) {
6639 + if (net_ratelimit())
6640 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
6644 + /* Drop old route. */
6645 + dst_release(skb->dst);
6648 + /* Success if no oif specified or if the oif correspond to the
6650 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
6651 + skb->dst = &rt->u.dst;
6652 + skb->dev = skb->dst->dev;
6656 + /* The interface selected by the routing table is not the one
6657 + * specified by the user. This may happen because the dst address
6658 + * is one of our own addresses.
6660 + if (net_ratelimit())
6661 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
6662 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
6668 +/* Stolen from ip_finish_output2
6669 + * PRE : skb->dev is set to the device we are leaving by
6670 + * skb->dst is not NULL
6671 + * POST: the packet is sent with the link layer header pushed
6672 + * the packet is destroyed
6674 +static void ip_direct_send(struct sk_buff *skb)
6676 + struct dst_entry *dst = skb->dst;
6677 + struct hh_cache *hh = dst->hh;
6680 + read_lock_bh(&hh->hh_lock);
6681 + memcpy(skb->data - 16, hh->hh_data, 16);
6682 + read_unlock_bh(&hh->hh_lock);
6683 + skb_push(skb, hh->hh_len);
6684 + hh->hh_output(skb);
6685 + } else if (dst->neighbour)
6686 + dst->neighbour->output(skb);
6688 + if (net_ratelimit())
6689 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
6695 +/* PRE : skb->dev is set to the device we are leaving by
6696 + * POST: - the packet is directly sent to the skb->dev device, without
6697 + * pushing the link layer header.
6698 + * - the packet is destroyed
6700 +static inline int dev_direct_send(struct sk_buff *skb)
6702 + return dev_queue_xmit(skb);
6706 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
6707 + struct sk_buff *skb)
6709 + unsigned int ifindex = 0;
6710 + struct net_device *dev_out = NULL;
6712 + /* The user set the interface name to use.
6713 + * Getting the current interface index.
6715 + if ((dev_out = dev_get_by_name(route_info->oif))) {
6716 + ifindex = dev_out->ifindex;
6718 + /* Unknown interface name : packet dropped */
6719 + if (net_ratelimit())
6720 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
6724 + /* Trying the standard way of routing packets */
6725 + switch (route(skb, ifindex, route_info)) {
6728 + if (route_info->flags & IPT_ROUTE_CONTINUE)
6729 + return IPT_CONTINUE;
6731 + ip_direct_send(skb);
6735 + /* Failed to send to oif. Trying the hard way */
6736 + if (route_info->flags & IPT_ROUTE_CONTINUE)
6739 + if (net_ratelimit())
6740 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
6743 + /* We have to force the use of an interface.
6744 + * This interface must be a tunnel interface since
6745 + * otherwise we can't guess the hw address for
6746 + * the packet. For a tunnel interface, no hw address
6749 + if ((dev_out->type != ARPHRD_TUNNEL)
6750 + && (dev_out->type != ARPHRD_IPGRE)) {
6751 + if (net_ratelimit())
6752 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
6757 + /* Send the packet. This will also free skb
6758 + * Do not go through the POST_ROUTING hook because
6759 + * skb->dst is not set and because it will probably
6760 + * get confused by the destination IP address.
6762 + skb->dev = dev_out;
6763 + dev_direct_send(skb);
6768 + /* Unexpected error */
6775 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
6776 + struct sk_buff *skb)
6778 + struct net_device *dev_out = NULL;
6779 + unsigned int ifindex = 0;
6781 + /* Getting the current interface index. */
6782 + if ((dev_out = dev_get_by_name(route_info->iif)))
6783 + ifindex = dev_out->ifindex;
6785 + /* Unknown interface name : packet dropped */
6786 + if (net_ratelimit())
6787 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
6791 + skb->dev = dev_out;
6792 + dst_release(skb->dst);
6801 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
6802 + struct sk_buff *skb)
6804 + if (route(skb, 0, route_info)!=1)
6807 + if (route_info->flags & IPT_ROUTE_CONTINUE)
6808 + return IPT_CONTINUE;
6810 + ip_direct_send(skb);
6815 +static unsigned int ipt_route_target(struct sk_buff **pskb,
6816 + const struct net_device *in,
6817 + const struct net_device *out,
6818 + unsigned int hooknum,
6819 + const void *targinfo,
6822 + const struct ipt_route_target_info *route_info = targinfo;
6823 + struct sk_buff *skb = *pskb;
6825 + /* If we are at PREROUTING or INPUT hook
6826 + * the TTL isn't decreased by the IP stack
6828 + if (hooknum == NF_IP_PRE_ROUTING ||
6829 + hooknum == NF_IP_LOCAL_IN) {
6831 + struct iphdr *iph = skb->nh.iph;
6833 + if (iph->ttl <= 1) {
6834 + struct rtable *rt;
6836 + if (ip_route_output(&rt, iph->saddr, iph->daddr,
6837 + RT_TOS(iph->tos) | RTO_CONN,
6842 + if (skb->dev == rt->u.dst.dev) {
6843 + /* Drop old route. */
6844 + dst_release(skb->dst);
6845 + skb->dst = &rt->u.dst;
6847 + /* this will traverse normal stack, and
6848 + * thus call conntrack on the icmp packet */
6849 + icmp_send(skb, ICMP_TIME_EXCEEDED,
6856 + ip_decrease_ttl(iph);
6859 + /* Tell conntrack to forget this packet since it may get confused
6860 + * when a packet is leaving with dst address == our address.
6861 + * Good idea ? Dunno. Need advice.
6863 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
6864 + nf_conntrack_put(skb->nfct);
6867 +#ifdef CONFIG_NETFILTER_DEBUG
6868 + skb->nf_debug = 0;
6872 + if (route_info->oif[0])
6873 + return route_oif(route_info, *pskb);
6875 + if (route_info->iif[0])
6876 + return route_iif(route_info, *pskb);
6878 + if (route_info->gw)
6879 + return route_gw(route_info, *pskb);
6881 + if (net_ratelimit())
6882 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
6884 + return IPT_CONTINUE;
6888 +static int ipt_route_checkentry(const char *tablename,
6889 + const struct ipt_entry *e,
6891 + unsigned int targinfosize,
6892 + unsigned int hook_mask)
6894 + if (strcmp(tablename, "mangle") != 0) {
6895 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
6900 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
6901 + | (1 << NF_IP_LOCAL_IN)
6902 + | (1 << NF_IP_FORWARD)
6903 + | (1 << NF_IP_LOCAL_OUT)
6904 + | (1 << NF_IP_POST_ROUTING))) {
6905 + printk("ipt_ROUTE: bad hook\n");
6909 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
6910 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
6912 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
6920 +static struct ipt_target ipt_route_reg = {
6922 + .target = ipt_route_target,
6923 + .checkentry = ipt_route_checkentry,
6924 + .me = THIS_MODULE,
6927 +static int __init init(void)
6929 + return ipt_register_target(&ipt_route_reg);
6933 +static void __exit fini(void)
6935 + ipt_unregister_target(&ipt_route_reg);
6940 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TARPIT.c
6941 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
6942 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-16 09:19:08.000000000 +0200
6945 + * Kernel module to capture and hold incoming TCP connections using
6946 + * no local per-connection resources.
6948 + * Based on ipt_REJECT.c and offering functionality similar to
6949 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
6951 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
6953 + * This program is free software; you can redistribute it and/or modify
6954 + * it under the terms of the GNU General Public License as published by
6955 + * the Free Software Foundation; either version 2 of the License, or
6956 + * (at your option) any later version.
6958 + * This program is distributed in the hope that it will be useful,
6959 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6960 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6961 + * GNU General Public License for more details.
6963 + * You should have received a copy of the GNU General Public License
6964 + * along with this program; if not, write to the Free Software
6965 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6968 + * - Allow incoming TCP connections to be established.
6969 + * - Passing data should result in the connection being switched to the
6970 + * persist state (0 byte window), in which the remote side stops sending
6971 + * data and asks to continue every 60 seconds.
6972 + * - Attempts to shut down the connection should be ignored completely, so
6973 + * the remote side ends up having to time it out.
6976 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
6977 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
6978 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
6981 +#include <linux/config.h>
6982 +#include <linux/module.h>
6983 +#include <linux/skbuff.h>
6984 +#include <linux/ip.h>
6985 +#include <net/ip.h>
6986 +#include <net/tcp.h>
6987 +#include <net/icmp.h>
6989 +#include <net/route.h>
6990 +#include <linux/random.h>
6991 +#include <linux/netfilter_ipv4/ip_tables.h>
6994 +#define DEBUGP printk
6996 +#define DEBUGP(format, args...)
7000 +/* Stolen from ip_finish_output2 */
7001 +static int ip_direct_send(struct sk_buff *skb)
7003 + struct dst_entry *dst = skb->dst;
7004 + struct hh_cache *hh = dst->hh;
7007 + read_lock_bh(&hh->hh_lock);
7008 + memcpy(skb->data - 16, hh->hh_data, 16);
7009 + read_unlock_bh(&hh->hh_lock);
7010 + skb_push(skb, hh->hh_len);
7011 + return hh->hh_output(skb);
7012 + } else if (dst->neighbour)
7013 + return dst->neighbour->output(skb);
7015 + if (net_ratelimit())
7016 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
7023 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
7025 + struct sk_buff *nskb;
7026 + struct rtable *nrt;
7027 + struct tcphdr *otcph, *ntcph;
7028 + unsigned int otcplen;
7030 + struct flowi fl = {};
7032 + /* A truncated TCP header isn't going to be useful */
7033 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
7036 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
7037 + + oskb->nh.iph->ihl);
7038 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
7040 + /* No replies for RST or FIN */
7041 + if (otcph->rst || otcph->fin)
7044 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
7045 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
7048 + /* Check checksum. */
7049 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
7050 + oskb->nh.iph->daddr,
7051 + csum_partial((char *)otcph, otcplen, 0)) != 0)
7054 + /* Copy skb (even if skb is about to be dropped, we can't just
7055 + clone it because there may be other things, such as tcpdump,
7056 + interested in it) */
7057 + nskb = skb_copy(oskb, GFP_ATOMIC);
7061 + /* This packet will not be the same as the other: clear nf fields */
7062 + nf_conntrack_put(nskb->nfct);
7063 + nskb->nfct = NULL;
7064 + nskb->nfcache = 0;
7065 +#ifdef CONFIG_NETFILTER_DEBUG
7066 + nskb->nf_debug = 0;
7069 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
7071 + /* Truncate to length (no data) */
7072 + ntcph->doff = sizeof(struct tcphdr)/4;
7073 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
7074 + nskb->nh.iph->tot_len = htons(nskb->len);
7076 + /* Swap source and dest */
7077 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
7078 + tmp = ntcph->source;
7079 + ntcph->source = ntcph->dest;
7080 + ntcph->dest = tmp;
7082 + /* Use supplied sequence number or make a new one */
7083 + ntcph->seq = otcph->ack ? otcph->ack_seq
7084 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
7085 + nskb->nh.iph->daddr,
7089 + /* Our SYN-ACKs must have a >0 window */
7090 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
7092 + ntcph->urg_ptr = 0;
7095 + ((u_int8_t *)ntcph)[13] = 0;
7097 + if (otcph->syn && otcph->ack) {
7099 + ntcph->ack_seq = 0;
7101 + ntcph->syn = otcph->syn;
7103 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
7106 + /* Adjust TCP checksum */
7108 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
7109 + nskb->nh.iph->saddr,
7110 + nskb->nh.iph->daddr,
7111 + csum_partial((char *)ntcph,
7112 + sizeof(struct tcphdr), 0));
7114 + /* Adjust IP TTL */
7115 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
7117 + /* Set DF, id = 0 */
7118 + nskb->nh.iph->frag_off = htons(IP_DF);
7119 + nskb->nh.iph->id = 0;
7121 + /* Adjust IP checksum */
7122 + nskb->nh.iph->check = 0;
7123 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
7124 + nskb->nh.iph->ihl);
7126 + fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
7127 + fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
7128 + fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
7130 + if (ip_route_output_key(&nrt, &fl) != 0)
7133 + dst_release(nskb->dst);
7134 + nskb->dst = &nrt->u.dst;
7136 + /* "Never happens" */
7137 + if (nskb->len > dst_pmtu(nskb->dst))
7140 + ip_direct_send (nskb);
7149 +static unsigned int tarpit(struct sk_buff **pskb,
7150 + unsigned int hooknum,
7151 + const struct net_device *in,
7152 + const struct net_device *out,
7153 + const void *targinfo,
7156 + struct sk_buff *skb = *pskb;
7157 + struct rtable *rt = (struct rtable*)skb->dst;
7159 + /* Do we have an input route cache entry? */
7163 + /* No replies to physical multicast/broadcast */
7164 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
7167 + /* Now check at the protocol level */
7168 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
7171 + /* Our naive response construction doesn't deal with IP
7172 + options, and probably shouldn't try. */
7173 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
7176 + /* We aren't interested in fragments */
7177 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
7180 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
7186 +static int check(const char *tablename,
7187 + const struct ipt_entry *e,
7189 + unsigned int targinfosize,
7190 + unsigned int hook_mask)
7192 + /* Only allow these for input/forward packet filtering. */
7193 + if (strcmp(tablename, "filter") != 0) {
7194 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
7197 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
7198 + | (1 << NF_IP_FORWARD))) != 0) {
7199 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
7203 + /* Must specify that it's a TCP packet */
7204 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
7205 + DEBUGP("TARPIT: not valid for non-tcp\n");
7212 +static struct ipt_target ipt_tarpit_reg = {
7215 + .checkentry = check,
7219 +static int __init init(void)
7221 + if (ipt_register_target(&ipt_tarpit_reg))
7226 +static void __exit fini(void)
7228 + ipt_unregister_target(&ipt_tarpit_reg);
7233 +MODULE_LICENSE("GPL");
7234 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TCPLAG.c
7235 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
7236 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TCPLAG.c 2004-04-16 09:15:54.000000000 +0200
7238 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
7239 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
7241 + * This program is free software; you can redistribute it and/or modify
7242 + * it under the terms of the GNU General Public License as published by
7243 + * the Free Software Foundation; either version 2 of the License, or
7244 + * (at your option) any later version.
7246 + * This program is distributed in the hope that it will be useful,
7247 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7248 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7249 + * GNU General Public License for more details.
7251 + * You should have received a copy of the GNU General Public License
7252 + * along with this program; if not, write to the Free Software
7253 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7257 + * This collects packets and attempts to make them into pairs
7258 + * based on its own knowledge of how typical network conversations
7259 + * operate. Once it has a pair, it logs the time between them.
7261 +#include <linux/module.h>
7262 +#include <linux/skbuff.h>
7263 +#include <linux/ip.h>
7264 +#include <linux/spinlock.h>
7265 +#include <net/icmp.h>
7266 +#include <net/udp.h>
7267 +#include <net/tcp.h>
7268 +#include <linux/netfilter_ipv4/ip_tables.h>
7270 +#include <net/route.h>
7271 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
7274 +#define DEBUGP printk
7276 +#define DEBUGP(format, args...)
7280 + * We need one spinlock for the hash table.
7282 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
7284 +typedef struct timeval timeval_T;
7287 + * Linked lists of events in the connection,
7288 + * these store the SEQ numbers and the newest is always
7289 + * at the start of the linked list, then they get older
7290 + * down to the end of the linked list (this is not perfect
7291 + * if packets get out of order but we don't worry about fine
7292 + * details like that).
7294 + * Matching any event wipes out that event and also all other
7295 + * events down the chain (i.e. all older events).
7296 + * This keeps the linked list as short as possible.
7298 +typedef struct tcplag_event_S
7300 + struct tcplag_event_S *next;
7304 + struct timeval stamp;
7308 + * This stores the connection statistics
7309 + * We define connections more loosely than TCP/IP does,
7310 + * because we only consider the two hosts, not the ports
7311 + * Also, we list the host-pairs in low,high order which
7312 + * means that we don't care who originated the connection.
7314 +typedef struct tcplag_hash_S
7318 + struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
7319 + struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
7320 + tcplag_event_T *h_ACK_list; /* Try to match ACK packets coming from h in this list */
7321 + tcplag_event_T *l_ACK_list; /* Try to match ACK packets coming from l in this list */
7322 + time_t stamp; /* When this bucket got added to the table */
7323 + u16 count_l_SEQ_h_ACK; /* Increment for each event */
7324 + u16 count_h_SEQ_l_ACK; /* Increment for each event */
7327 +static tcplag_hash_T **hashtab = 0;
7328 +static u32 hashsize = 0;
7329 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
7330 +static u32 reaper_ix = 0;
7332 +static void divide_down( timeval_T *T, int c )
7337 + remainder = T->tv_sec % c; /* Only works properly with positive numbers */
7338 + remainder *= 1000000;
7339 + T->tv_usec == remainder;
7343 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
7347 + x = tv1->tv_sec - tv2->tv_sec;
7348 + if( x ) return( x );
7349 + x = tv1->tv_usec - tv2->tv_usec;
7353 +void sprint_timeval( char *buf, timeval_T *tv )
7356 + sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
7358 + sprintf( buf, "%lu", tv->tv_usec );
7362 + * This generates the log messages through printk()
7364 + * There is really no particular interest in the port numbers at this stage,
7365 + * they are only useful for matching up the request with the reply.
7366 + * The IP numbers are useful because some sites may be slower than others
7367 + * or may travel different routes, etc (OK, in theory changing the port number
7368 + * could also change the route but I don't like that sort of theory).
7372 + * LIP= The IP number of the side with the lowest lag
7373 + * RIP= The IP number of the side with the highest lag
7374 + * LLAG= The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
7375 + * RLAG= The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
7377 +static void output( tcplag_hash_T *H, int level, const char *prefix )
7379 + struct timeval ltm, rtm;
7380 + u32 local_ip, remote_ip;
7381 + char r_buf[ 20 ], l_buf[ 20 ];
7383 + * We can't make sense of a connection that only passes data one way,
7384 + * In principle, at least the SYN and FIN should go both ways so we
7385 + * should get a few hits for every connection.
7387 + if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
7389 + * Calculate average times by dividing down
7391 + divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
7392 + divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
7394 + * Sort these two by the lag so the the local is always the short lag
7396 + if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
7398 + local_ip = H->low_ip;
7399 + remote_ip = H->high_ip;
7400 + rtm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
7401 + rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
7402 + ltm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
7403 + ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
7407 + local_ip = H->high_ip;
7408 + remote_ip = H->low_ip;
7409 + ltm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
7410 + ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
7411 + rtm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
7412 + rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
7415 + * Don't use a spinlock on the output,
7416 + * it is not guaranteed safe because some OTHER printk could
7417 + * split our log message so we want only one single printk.
7419 + * We use sprintf() to partially pre-digest the output
7421 + * Actually, neither this not the main netfilter LOG target is
7422 + * really safe from printk() overlap, basically syslog cannot
7423 + * be regarded as a guaranteed data output channel. It is good
7424 + * enough for most purposes.
7426 + sprint_timeval( l_buf, <m );
7427 + sprint_timeval( r_buf, &rtm );
7428 + printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
7429 + level & 7, prefix,
7430 + NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
7435 + * The reaper rolls through the hash table looking for old.
7436 + * Log entries are only generated at the reaping time
7437 + * (which means all log entries are out-of-date)
7439 +static void reaper( time_t now, int level, const char *prefix )
7443 + now -= max_seconds;
7444 + if( !hashsize ) return;
7445 + if( !hashtab ) return;
7446 + for( i = 0; i < 10; i++ )
7448 + if( ++reaper_ix >= hashsize ) reaper_ix = 0;
7450 +// DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
7452 + if( hashtab[ reaper_ix ])
7454 + tcplag_hash_T *found = 0;
7456 + spin_lock_bh( &hash_lock );
7457 + if( hashtab[ reaper_ix ])
7459 + if( now > hashtab[ reaper_ix ]->stamp )
7461 + DEBUGP( KERN_WARNING "reaper found expired entry\n" );
7462 + found = hashtab[ reaper_ix ];
7463 + hashtab[ reaper_ix ] = 0;
7466 + spin_unlock_bh( &hash_lock );
7470 + output( found, level, prefix );
7478 + * Convert the connection characteristics into a number
7479 + * (not including the timestamp) FIXME: this is a sucky hash function
7481 +static u32 make_hash( tcplag_hash_T *connection )
7485 + r = connection->low_ip;
7486 + r += connection->high_ip;
7490 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
7494 + x = con1->low_ip - con2->low_ip; if( x ) return( x );
7495 + x = con1->high_ip - con2->high_ip;
7499 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
7503 + DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
7504 + x = ev1->expected_ACK - ev2->expected_ACK;
7505 + if( x ) return( x );
7506 + DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
7507 + x = ev1->source_port - ev2->source_port;
7508 + if( x ) return( x );
7509 + DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
7510 + x = ev1->dest_port - ev2->dest_port;
7515 + * Go to the hash table and either find an existing connection that
7516 + * matches correctly or inject a new connection into the table.
7517 + * Once the connection is OK, chain the event onto the linked list.
7519 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
7523 + if( !event ) return; /* Just to be safe */
7524 + if( !hashsize ) return;
7525 + if( !hashtab ) return;
7527 + h = make_hash( connection );
7530 + DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
7532 + spin_lock_bh( &hash_lock );
7533 + for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
7535 + tcplag_hash_T *co_new = 0;
7537 + * Consider existing entry
7541 + if( compare_connections( hashtab[ h ], connection )) continue;
7542 + co_new = hashtab[ h ];
7543 + DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
7547 + * Use empty slot for new entry
7549 + if( !hashtab[ h ])
7551 + co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
7552 + memset( co_new, 0, sizeof( tcplag_hash_T ));
7553 + co_new->low_ip = connection->low_ip;
7554 + co_new->high_ip = connection->high_ip;
7555 + co_new->stamp = event->stamp.tv_sec;
7556 + hashtab[ h ] = co_new;
7557 + DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
7560 + tcplag_event_T *ev_new;
7562 + ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
7563 + memcpy( ev_new, event, sizeof( tcplag_event_T ));
7566 + ev_new->next = co_new->h_ACK_list;
7567 + co_new->h_ACK_list = ev_new;
7568 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
7572 + ev_new->next = co_new->l_ACK_list;
7573 + co_new->l_ACK_list = ev_new;
7574 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
7581 + spin_unlock_bh( &hash_lock );
7585 + * Search the hash table for a matching connection,
7586 + * if we can't find one of those then we are stuffed.
7588 + * Once a connection has been found, scan along the list for
7589 + * a matching SEQ number and if that is found then calculate
7590 + * the lag, update the counters and cut the chain at the
7591 + * point where the matching SEQ is found.
7593 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
7597 + if( !event ) return( 0 );
7598 + if( !hashsize ) return( 0 );
7599 + if( !hashtab ) return( 0 );
7600 + h = make_hash( connection );
7603 + DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
7605 + for( i = 0; i < hashsize; i++ )
7607 + tcplag_hash_T *found = 0;
7609 + if( !hashtab[ h ]) return( 0 );
7611 + spin_lock_bh( &hash_lock );
7614 + if( !compare_connections( hashtab[ h ], connection ))
7616 + tcplag_event_T *ev, **evroot;
7620 + found = hashtab[ h ];
7623 + evroot = &found->h_ACK_list;
7624 + tv = &found->lag_l_SEQ_h_ACK;
7625 + cn = &found->count_l_SEQ_h_ACK;
7626 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
7630 + evroot = &found->l_ACK_list;
7631 + tv = &found->lag_h_SEQ_l_ACK;
7632 + cn = &found->count_h_SEQ_l_ACK;
7633 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
7635 + for( ev = *evroot; ev; ev = ev->next )
7637 + if( !compare_events( ev, event ))
7640 + * Calculate the lag (in two parts) and add that to the collection
7642 + event->stamp.tv_sec -= ev->stamp.tv_sec;
7643 + event->stamp.tv_usec -= ev->stamp.tv_usec;
7644 + if( event->stamp.tv_usec < 0 )
7646 + event->stamp.tv_usec += 1000000;
7647 + event->stamp.tv_sec++;
7649 + if( event->stamp.tv_sec < 0 )
7651 + DEBUGP( KERN_WARNING "Negative lag detected\n" );
7655 + tv->tv_sec += event->stamp.tv_sec;
7656 + tv->tv_usec += event->stamp.tv_usec;
7658 + DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
7659 + " (accumulator is up to %lu.%06lu, %u events)\n",
7660 + event->stamp.tv_sec,
7661 + event->stamp.tv_usec,
7662 + tv->tv_sec, tv->tv_usec, *cn );
7665 + * Truncate the linked list.
7667 + * Visit each event in the list and return the memory to the pool.
7669 + * If a host is making multiple connections to the same remote host
7670 + * then this truncation will result in some requests not being
7671 + * monitored. Statistically we will still get some reasonable number
7672 + * of measurements and multiple simultaneous connections between host
7673 + * pairs don't happen all that often.
7678 + tcplag_event_T *ev_next = ev->next;
7679 + DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
7684 + * TODO: overflow limit for *cn, force premature output() if necessary
7685 + * (and drop this connection from the hash table)
7694 + spin_unlock_bh( &hash_lock );
7696 + if( found ) return( 1 );
7697 + if( ++h >= hashsize ) h = 0;
7703 + * Here is our target data:
7705 + * pskb -- The packet itself (see linux/skbuff.h for breakdown)
7709 + * in -- The device that this packet came in on
7710 + * (depending on the chain this may or may not exist)
7712 + * out -- The device that this packet is just about to go
7713 + * out onto (again existance depends on the chain)
7715 + * targinfo -- Our private data (handed through from iptables command util)
7717 + * userinfo -- Some more data
7721 +static unsigned int target( struct sk_buff **pskb,
7722 + unsigned int hooknum,
7723 + const struct net_device *in,
7724 + const struct net_device *out,
7725 + const void *targinfo,
7728 + struct iphdr *iph = ( *pskb )->nh.iph;
7729 + const struct ipt_tcplag *el = targinfo;
7730 + tcplag_hash_T connection;
7731 + tcplag_event_T event;
7734 + * We know we are dealing with IP here
7735 + * Fill in all the obvious fields
7737 + if( iph->saddr > iph->daddr )
7740 + connection.high_ip = iph->saddr;
7741 + connection.low_ip = iph->daddr;
7746 + connection.low_ip = iph->saddr;
7747 + connection.high_ip = iph->daddr;
7749 + do_gettimeofday( &event.stamp );
7751 + * Do a bit of cleaning
7753 + reaper( event.stamp.tv_sec, el->level, el->prefix );
7755 + DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
7756 + event.stamp.tv_sec,
7757 + event.stamp.tv_usec,
7758 + in ? in->name : "none", out ? out->name : "none" );
7760 + * Now start looking at the details
7762 + * First step is to identify this packet to see if it is
7763 + * the sort of packet that we are interested in.
7764 + * Don't hold any locks while we are doing this because often
7765 + * we will just let the packet go without any further consideration.
7767 + switch( iph->protocol )
7771 + struct tcphdr *tcp;
7773 + if( ntohs( iph->frag_off ) & IP_OFFSET )
7775 + DEBUGP( KERN_WARNING "ignoring fragment\n" );
7778 + tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
7779 + event.source_port = ntohs( tcp->source );
7780 + event.dest_port = ntohs( tcp->dest );
7782 + * Every packet should have a valid SEQ number so use this to
7783 + * generate an ACK number. This works along the formula:
7784 + * -- Start with the SEQ number
7785 + * -- For SYN or FIN add 1 to that number
7786 + * -- For data packet, add the data length to that number
7790 + * Data length requires a bit of fiddling around
7793 + unsigned int data_len;
7794 + if( tcp->syn || tcp->fin )
7796 + data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
7800 + data_len = ntohs( iph->tot_len );
7801 + data_len -= 4 * iph->ihl; /* Subtract away IP header & options */
7802 + data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
7805 + DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
7807 + if( data_len ) /* Only track events that demand an ACK */
7809 + event.expected_ACK = ntohl( tcp->seq ) + data_len;
7810 + hash_insert( &connection, &event, direction );
7814 + DEBUGP( "Don't bother to insert this, ACK not required\n" );
7821 + * Now we consider the matching of an existing event.
7822 + * Reverse the port numbers and change the ACK number to the actual ACK number
7823 + * Note that the direction is reversed because the reply will be going
7824 + * the opposite way to the request.
7826 + event.expected_ACK = ntohl( tcp->ack_seq );
7827 + event.dest_port = ntohs( tcp->source );
7828 + event.source_port = ntohs( tcp->dest );
7829 + request_complete( &connection, &event, !direction );
7833 + DEBUGP( "Don't bother to check this, ACK not valid\n" );
7837 + return( IPT_CONTINUE );
7841 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
7842 + * return( 1 ) if the entry is suitable
7848 + * targinfo -- Our private data block (handed to us from iptables plug-in)
7850 + * targinfosize -- The size of our private data block
7855 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
7856 + * all possible flag combos make sense. All we check for is correct data size.
7858 +static int checkentry( const char *tablename,
7859 + const struct ipt_entry *e,
7861 + unsigned int targinfosize,
7862 + unsigned int hook_mask )
7864 + const struct ipt_tcplag *el = targinfo;
7866 + if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
7868 + DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
7869 + IPT_ALIGN( sizeof( struct ipt_tcplag )));
7872 + if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
7876 +static struct ipt_target reg =
7886 +static int __init init( void )
7888 + if( ipt_register_target( ® )) return( -EINVAL );
7889 + hashsize = 123; /* should be configurable */
7890 + hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
7891 + memset( hashtab, 0, sizeof( void * ) * hashsize );
7896 + * This should not need locks (in theory)
7897 + * because it can only get punted after it is no longer
7898 + * chained into any of the netfilter lists.
7900 +static void __exit fini( void )
7904 + ipt_unregister_target( ® );
7906 + * Put back kernel memory
7908 + for( i = 0; i < hashsize; i++ )
7912 + if(( p = hashtab[ i ]))
7914 + tcplag_event_T *ev, *evn;
7917 + for( ev = p->h_ACK_list; ev; ev = evn )
7922 + for( ev = p->l_ACK_list; ev; ev = evn )
7935 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_XOR.c
7936 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
7937 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_XOR.c 2004-04-16 09:16:25.000000000 +0200
7939 +/* XOR target for IP tables
7940 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
7941 + * Based on ipt_TTL.c
7945 + * This software is distributed under the terms of GNU GPL
7948 +#include <linux/module.h>
7949 +#include <linux/skbuff.h>
7950 +#include <linux/ip.h>
7951 +#include <linux/tcp.h>
7952 +#include <linux/udp.h>
7954 +#include <linux/netfilter_ipv4/ip_tables.h>
7955 +#include <linux/netfilter_ipv4/ipt_XOR.h>
7957 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
7958 +MODULE_DESCRIPTION("IP tables XOR module");
7959 +MODULE_LICENSE("GPL");
7961 +static unsigned int
7962 +ipt_xor_target(struct sk_buff **pskb,
7963 + const struct net_device *in, const struct net_device *out,
7964 + unsigned int hooknum, const void *targinfo, void *userinfo)
7966 + struct ipt_XOR_info *info = (void *) targinfo;
7967 + struct iphdr *iph;
7968 + struct tcphdr *tcph;
7969 + struct udphdr *udph;
7972 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
7975 + iph = (*pskb)->nh.iph;
7977 + if (iph->protocol == IPPROTO_TCP) {
7978 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
7979 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
7980 + for (k=0; k<=info->block_size; k++) {
7981 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
7986 + if (info->key[j] == 0x00)
7989 + } else if (iph->protocol == IPPROTO_UDP) {
7990 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
7991 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
7992 + for (k=0; k<=info->block_size; k++) {
7993 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
7998 + if (info->key[j] == 0x00)
8003 + return IPT_CONTINUE;
8006 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
8007 + void *targinfo, unsigned int targinfosize,
8008 + unsigned int hook_mask)
8010 + struct ipt_XOR_info *info = targinfo;
8012 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
8013 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
8014 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
8018 + if (strcmp(tablename, "mangle")) {
8019 + printk(KERN_WARNING "XOR: can only be called from"
8020 + "\"mangle\" table, not \"%s\"\n", tablename);
8024 + if (!strcmp(info->key, "")) {
8025 + printk(KERN_WARNING "XOR: You must specify a key");
8029 + if (info->block_size == 0) {
8030 + printk(KERN_WARNING "XOR: You must specify a block-size");
8037 +static struct ipt_target ipt_XOR = {
8039 + .target = ipt_xor_target,
8040 + .checkentry = ipt_xor_checkentry,
8041 + .me = THIS_MODULE,
8044 +static int __init init(void)
8046 + return ipt_register_target(&ipt_XOR);
8049 +static void __exit fini(void)
8051 + ipt_unregister_target(&ipt_XOR);
8056 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_addrtype.c
8057 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
8058 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_addrtype.c 2004-04-16 09:16:27.000000000 +0200
8061 + * iptables module to match inet_addr_type() of an ip.
8064 +#include <linux/module.h>
8065 +#include <linux/skbuff.h>
8066 +#include <linux/netdevice.h>
8067 +#include <net/route.h>
8069 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
8070 +#include <linux/netfilter_ipv4/ip_tables.h>
8072 +MODULE_LICENSE("GPL");
8074 +static inline int match_type(u_int32_t addr, u_int16_t mask)
8076 + return !!(mask & (1 << inet_addr_type(addr)));
8079 +static int match(const struct sk_buff *skb, const struct net_device *in,
8080 + const struct net_device *out, const void *matchinfo,
8081 + int offset, int *hotdrop)
8083 + const struct ipt_addrtype_info *info = matchinfo;
8084 + const struct iphdr *iph = skb->nh.iph;
8088 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
8090 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
8095 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
8096 + void *matchinfo, unsigned int matchsize,
8097 + unsigned int hook_mask)
8099 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
8100 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
8101 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
8108 +static struct ipt_match addrtype_match = {
8109 + .name = "addrtype",
8111 + .checkentry = checkentry,
8115 +static int __init init(void)
8117 + return ipt_register_match(&addrtype_match);
8120 +static void __exit fini(void)
8122 + ipt_unregister_match(&addrtype_match);
8128 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_connmark.c
8129 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
8130 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_connmark.c 2004-04-16 09:15:41.000000000 +0200
8132 +/* This kernel module matches connection mark values set by the
8135 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8136 + * by Henrik Nordstrom <hno@marasystems.com>
8138 + * This program is free software; you can redistribute it and/or modify
8139 + * it under the terms of the GNU General Public License as published by
8140 + * the Free Software Foundation; either version 2 of the License, or
8141 + * (at your option) any later version.
8143 + * This program is distributed in the hope that it will be useful,
8144 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8145 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8146 + * GNU General Public License for more details.
8148 + * You should have received a copy of the GNU General Public License
8149 + * along with this program; if not, write to the Free Software
8150 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8153 +#include <linux/module.h>
8154 +#include <linux/skbuff.h>
8156 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8157 +MODULE_DESCRIPTION("IP tables connmark match module");
8158 +MODULE_LICENSE("GPL");
8160 +#include <linux/netfilter_ipv4/ip_tables.h>
8161 +#include <linux/netfilter_ipv4/ipt_connmark.h>
8162 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8165 +match(const struct sk_buff *skb,
8166 + const struct net_device *in,
8167 + const struct net_device *out,
8168 + const void *matchinfo,
8172 + const struct ipt_connmark_info *info = matchinfo;
8173 + enum ip_conntrack_info ctinfo;
8174 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
8178 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
8182 +checkentry(const char *tablename,
8183 + const struct ipt_ip *ip,
8185 + unsigned int matchsize,
8186 + unsigned int hook_mask)
8188 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
8194 +static struct ipt_match connmark_match = {
8195 + .name = "connmark",
8197 + .checkentry = &checkentry,
8201 +static int __init init(void)
8203 + return ipt_register_match(&connmark_match);
8206 +static void __exit fini(void)
8208 + ipt_unregister_match(&connmark_match);
8213 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_osf.c
8214 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_osf.c 2004-04-16 08:59:08.000000000 +0200
8215 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_osf.c 2004-04-16 09:20:53.000000000 +0200
8217 #include <linux/ctype.h>
8218 #include <linux/list.h>
8219 #include <linux/if.h>
8220 +#include <linux/tcp.h>
8222 #include <net/sock.h>
8224 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_owner.c
8225 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_owner.c 2004-04-15 03:35:57.000000000 +0200
8226 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_owner.c 2004-04-16 09:18:14.000000000 +0200
8228 * This program is free software; you can redistribute it and/or modify
8229 * it under the terms of the GNU General Public License version 2 as
8230 * published by the Free Software Foundation.
8232 + * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
8235 #include <linux/module.h>
8236 #include <linux/skbuff.h>
8237 #include <linux/file.h>
8238 +#include <linux/ip.h>
8239 +#include <linux/tcp.h>
8240 +#include <linux/udp.h>
8241 #include <net/sock.h>
8242 +#include <net/tcp.h>
8243 +#include <net/udp.h>
8245 #include <linux/netfilter_ipv4/ipt_owner.h>
8246 #include <linux/netfilter_ipv4/ip_tables.h>
8248 MODULE_DESCRIPTION("iptables owner match");
8251 -match_comm(const struct sk_buff *skb, const char *comm)
8252 +match_comm(const struct sock *sk, const char *comm)
8254 struct task_struct *g, *p;
8255 struct files_struct *files;
8257 spin_lock(&files->file_lock);
8258 for (i=0; i < files->max_fds; i++) {
8259 if (fcheck_files(files, i) ==
8260 - skb->sk->sk_socket->file) {
8261 + sk->sk_socket->file) {
8262 spin_unlock(&files->file_lock);
8264 read_unlock(&tasklist_lock);
8269 -match_pid(const struct sk_buff *skb, pid_t pid)
8270 +match_pid(const struct sock *sk, pid_t pid)
8272 struct task_struct *p;
8273 struct files_struct *files;
8275 spin_lock(&files->file_lock);
8276 for (i=0; i < files->max_fds; i++) {
8277 if (fcheck_files(files, i) ==
8278 - skb->sk->sk_socket->file) {
8279 + sk->sk_socket->file) {
8280 spin_unlock(&files->file_lock);
8282 read_unlock(&tasklist_lock);
8287 -match_sid(const struct sk_buff *skb, pid_t sid)
8288 +match_sid(const struct sock *sk, pid_t sid)
8290 struct task_struct *g, *p;
8291 - struct file *file = skb->sk->sk_socket->file;
8292 + struct file *file = sk->sk_socket->file;
8295 read_lock(&tasklist_lock);
8296 @@ -129,41 +136,71 @@
8299 const struct ipt_owner_info *info = matchinfo;
8300 + struct iphdr *iph = skb->nh.iph;
8301 + struct sock *sk = NULL;
8307 + if (iph->protocol == IPPROTO_TCP) {
8308 + struct tcphdr *tcph =
8309 + (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
8310 + sk = tcp_v4_lookup(iph->saddr, tcph->source,
8311 + iph->daddr, tcph->dest,
8312 + skb->dev->ifindex);
8313 + if (sk && sk->sk_state == TCP_TIME_WAIT) {
8314 + tcp_tw_put((struct tcp_tw_bucket *)sk);
8317 + } else if (iph->protocol == IPPROTO_UDP) {
8318 + struct udphdr *udph =
8319 + (struct udphdr *)((u_int32_t *)iph + iph->ihl);
8320 + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
8321 + udph->dest, skb->dev->ifindex);
8325 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
8327 + if (!sk || !sk->sk_socket || !sk->sk_socket->file)
8330 if(info->match & IPT_OWNER_UID) {
8331 - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
8332 + if ((sk->sk_socket->file->f_uid != info->uid) ^
8333 !!(info->invert & IPT_OWNER_UID))
8338 if(info->match & IPT_OWNER_GID) {
8339 - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
8340 + if ((sk->sk_socket->file->f_gid != info->gid) ^
8341 !!(info->invert & IPT_OWNER_GID))
8346 if(info->match & IPT_OWNER_PID) {
8347 - if (!match_pid(skb, info->pid) ^
8348 + if (!match_pid(sk, info->pid) ^
8349 !!(info->invert & IPT_OWNER_PID))
8354 if(info->match & IPT_OWNER_SID) {
8355 - if (!match_sid(skb, info->sid) ^
8356 + if (!match_sid(sk, info->sid) ^
8357 !!(info->invert & IPT_OWNER_SID))
8362 if(info->match & IPT_OWNER_COMM) {
8363 - if (!match_comm(skb, info->comm) ^
8364 + if (!match_comm(sk, info->comm) ^
8365 !!(info->invert & IPT_OWNER_COMM))
8381 @@ -173,11 +210,19 @@
8382 unsigned int matchsize,
8383 unsigned int hook_mask)
8386 - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
8387 - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
8391 + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
8392 + (1 << NF_IP_LOCAL_IN))) {
8393 + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
8394 + "or POST_ROUTING.\n");
8398 + if ((hook_mask & (1 << NF_IP_LOCAL_IN))
8399 + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
8400 + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
8404 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
8405 printk("Matchsize %u != %Zu\n", matchsize,
8406 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_policy.c
8407 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
8408 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_policy.c 2004-04-16 09:18:18.000000000 +0200
8410 +/* IP tables module for matching IPsec policy
8412 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
8414 + * This program is free software; you can redistribute it and/or modify
8415 + * it under the terms of the GNU General Public License version 2 as
8416 + * published by the Free Software Foundation.
8419 +#include <linux/kernel.h>
8420 +#include <linux/config.h>
8421 +#include <linux/module.h>
8422 +#include <linux/skbuff.h>
8423 +#include <linux/init.h>
8424 +#include <net/xfrm.h>
8426 +#include <linux/netfilter_ipv4.h>
8427 +#include <linux/netfilter_ipv4/ipt_policy.h>
8428 +#include <linux/netfilter_ipv4/ip_tables.h>
8430 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
8431 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
8432 +MODULE_LICENSE("GPL");
8436 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
8438 +#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
8440 + if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
8441 + MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
8442 + MISMATCH(proto, x->id.proto) ||
8443 + MISMATCH(mode, x->props.mode) ||
8444 + MISMATCH(spi, x->id.spi) ||
8445 + MISMATCH(reqid, x->props.reqid))
8451 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
8453 + const struct ipt_policy_elem *e;
8454 + struct sec_path *sp = skb->sp;
8455 + int strict = info->flags & POLICY_MATCH_STRICT;
8460 + if (strict && info->len != sp->len)
8463 + for (i = sp->len - 1; i >= 0; i--) {
8464 + pos = strict ? i - sp->len + 1 : 0;
8465 + if (pos >= info->len)
8467 + e = &info->pol[pos];
8469 + if (match_xfrm_state(sp->x[i].xvec, e)) {
8472 + } else if (strict)
8476 + return strict ? 1 : 0;
8480 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
8482 + const struct ipt_policy_elem *e;
8483 + struct dst_entry *dst = skb->dst;
8484 + int strict = info->flags & POLICY_MATCH_STRICT;
8487 + if (dst->xfrm == NULL)
8490 + for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
8491 + pos = strict ? i : 0;
8492 + if (pos >= info->len)
8494 + e = &info->pol[pos];
8496 + if (match_xfrm_state(dst->xfrm, e)) {
8499 + } else if (strict)
8503 + return strict ? 1 : 0;
8506 +static int match(const struct sk_buff *skb,
8507 + const struct net_device *in,
8508 + const struct net_device *out,
8509 + const void *matchinfo, int offset, int *hotdrop)
8511 + const struct ipt_policy_info *info = matchinfo;
8514 + if (info->flags & POLICY_MATCH_IN)
8515 + ret = match_policy_in(skb, info);
8517 + ret = match_policy_out(skb, info);
8520 + if (info->flags & POLICY_MATCH_NONE)
8524 + } else if (info->flags & POLICY_MATCH_NONE)
8530 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
8531 + void *matchinfo, unsigned int matchsize,
8532 + unsigned int hook_mask)
8534 + struct ipt_policy_info *info = matchinfo;
8536 + if (matchsize != IPT_ALIGN(sizeof(*info))) {
8537 + printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
8538 + matchsize, IPT_ALIGN(sizeof(*info)));
8541 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
8542 + printk(KERN_ERR "ipt_policy: neither incoming nor "
8543 + "outgoing policy selected\n");
8546 + if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
8547 + && info->flags & POLICY_MATCH_OUT) {
8548 + printk(KERN_ERR "ipt_policy: output policy not valid in "
8549 + "PRE_ROUTING and INPUT\n");
8552 + if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
8553 + && info->flags & POLICY_MATCH_IN) {
8554 + printk(KERN_ERR "ipt_policy: input policy not valid in "
8555 + "POST_ROUTING and OUTPUT\n");
8558 + if (info->len > POLICY_MAX_ELEM) {
8559 + printk(KERN_ERR "ipt_policy: too many policy elements\n");
8566 +static struct ipt_match policy_match =
8570 + .checkentry = checkentry,
8571 + .me = THIS_MODULE,
8574 +static int __init init(void)
8576 + return ipt_register_match(&policy_match);
8579 +static void __exit fini(void)
8581 + ipt_unregister_match(&policy_match);
8586 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_rpc.c
8587 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
8588 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_rpc.c 2004-04-16 09:18:44.000000000 +0200
8590 +/* RPC extension for IP connection matching, Version 2.2
8591 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
8592 + * - original rpc tracking module
8593 + * - "recent" connection handling for kernel 2.3+ netfilter
8595 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
8596 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
8598 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
8599 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
8600 + * - extended matching to support filtering on procedures
8602 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
8604 + * This program is free software; you can redistribute it and/or
8605 + * modify it under the terms of the GNU General Public License
8606 + * as published by the Free Software Foundation; either version
8607 + * 2 of the License, or (at your option) any later version.
8609 + * Module load syntax:
8610 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
8612 + * Please give the ports of all RPC servers you wish to connect to.
8613 + * If you don't specify ports, the default will be port 111.
8617 + * RPCs should not be exposed to the internet - ask the Pentagon;
8619 + * "The unidentified crackers pleaded guilty in July to charges
8620 + * of juvenile delinquency stemming from a string of Pentagon
8621 + * network intrusions in February.
8623 + * The youths, going by the names TooShort and Makaveli, used
8624 + * a common server security hole to break in, according to
8625 + * Dane Jasper, owner of the California Internet service
8626 + * provider, Sonic. They used the hole, known as the 'statd'
8627 + * exploit, to attempt more than 800 break-ins, Jasper said."
8629 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
8630 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
8634 +#include <linux/module.h>
8635 +#include <linux/skbuff.h>
8636 +#include <linux/list.h>
8637 +#include <linux/udp.h>
8638 +#include <linux/tcp.h>
8639 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8640 +#include <linux/netfilter_ipv4/ip_tables.h>
8641 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
8642 +#include <linux/netfilter_ipv4/lockhelp.h>
8643 +#include <linux/netfilter_ipv4/ipt_rpc.h>
8645 +#define MAX_PORTS 8
8646 +static int ports[MAX_PORTS];
8647 +static int ports_n_c = 0;
8650 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8651 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
8654 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
8655 +MODULE_DESCRIPTION("RPC connection matching module");
8656 +MODULE_LICENSE("GPL");
8659 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
8662 +#define DEBUGP(format, args...)
8667 +/* vars from ip_conntrack_rpc_tcp */
8668 +extern struct list_head request_p_list_tcp;
8669 +extern struct module *ip_conntrack_rpc_tcp;
8671 +/* vars from ip_conntrack_rpc_udp */
8672 +extern struct list_head request_p_list_udp;
8673 +extern struct module *ip_conntrack_rpc_udp;
8675 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
8676 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
8678 +#define ASSERT_READ_LOCK(x) \
8680 + if (x == &request_p_list_udp) \
8681 + MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
8682 + else if (x == &request_p_list_tcp) \
8683 + MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
8686 +#define ASSERT_WRITE_LOCK(x) \
8688 + if (x == &request_p_list_udp) \
8689 + MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
8690 + else if (x == &request_p_list_tcp) \
8691 + MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
8694 +#include <linux/netfilter_ipv4/listhelp.h>
8696 +const int IPT_RPC_CHAR_LEN = 11;
8699 +static int k_atoi(char *string)
8701 + unsigned int result = 0;
8702 + int maxoctet = IPT_RPC_CHAR_LEN;
8704 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
8709 + if (*string < 48 || *string > 57) {
8712 + result = result * 10 + ( *string - 48 );
8718 +static int match_rpcs(char *c_procs, int i_procs, int proc)
8722 + unsigned int proc_num;
8724 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
8726 + if (i_procs == -1)
8729 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
8731 + proc_ptr = c_procs;
8732 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
8733 + proc_num = k_atoi(proc_ptr);
8735 + if (proc_num == proc)
8743 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
8744 + int *hotdrop, int dir, struct ip_conntrack *ct,
8745 + int offset, struct list_head request_p_list)
8747 + const struct ipt_rpc_info *rpcinfo = matchinfo;
8748 + struct request_p *req_p;
8755 + /* This does sanity checking on RPC payloads,
8756 + * and permits only the RPC "get port" (3)
8757 + * in authorised procedures in client
8758 + * communications with the portmapper.
8763 + /* Get RPC requestor */
8764 + if (IXDR_GET_INT32(data) != 3) {
8765 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
8766 + if(rpcinfo->strict == 1)
8770 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
8774 + /* Jump Credentials and Verfifier */
8775 + data = data + IXDR_GET_INT32(data) + 2;
8776 + data = data + IXDR_GET_INT32(data) + 2;
8778 + /* Get RPC procedure */
8779 + if (match_rpcs((char *)&rpcinfo->c_procs,
8780 + rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
8781 + DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
8782 + (unsigned int)IXDR_GET_INT32(data));
8784 + /* If the RPC conntrack half entry already exists .. */
8786 + switch (ct->tuplehash[0].tuple.dst.protonum) {
8788 + WRITE_LOCK(&ipct_rpc_udp_lock);
8790 + WRITE_LOCK(&ipct_rpc_tcp_lock);
8792 + req_p = LIST_FIND(&request_p_list, request_p_cmp,
8793 + struct request_p *, xid,
8794 + ct->tuplehash[dir].tuple.src.ip,
8795 + ct->tuplehash[dir].tuple.src.u.all);
8798 + DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
8799 + xid, ct->tuplehash[dir].tuple.dst.protonum,
8800 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
8801 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
8803 + /* .. remove it */
8804 + if (del_timer(&req_p->timeout))
8805 + req_p->timeout.expires = 0;
8807 + LIST_DELETE(&request_p_list, req_p);
8808 + DEBUGP("RPC req_p removed. [done]\n");
8811 + DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
8812 + xid, ct->tuplehash[dir].tuple.dst.protonum,
8813 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
8814 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
8817 + switch (ct->tuplehash[0].tuple.dst.protonum) {
8819 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
8821 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8824 + if(rpcinfo->strict == 1)
8829 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
8830 + (unsigned int)IXDR_GET_INT32(data));
8831 + return (1 && (!offset));
8835 +static int match(const struct sk_buff *skb, const struct net_device *in,
8836 + const struct net_device *out, const void *matchinfo,
8837 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
8839 + struct ip_conntrack *ct;
8840 + enum ip_conntrack_info ctinfo;
8841 + const u_int32_t *data;
8842 + enum ip_conntrack_dir dir;
8843 + const struct tcphdr *tcp;
8844 + const struct ipt_rpc_info *rpcinfo = matchinfo;
8845 + int port, portsok;
8849 + DEBUGP("new packet to evaluate ..\n");
8851 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
8853 + DEBUGP("no ct available [skip]\n");
8857 + DEBUGP("ct detected. [cont]\n");
8858 + dir = CTINFO2DIR(ctinfo);
8860 + /* we only want the client to server packets for matching */
8861 + if (dir != IP_CT_DIR_ORIGINAL)
8864 + /* This does sanity checking on UDP or TCP packets,
8865 + * like their respective modules.
8868 + switch (ct->tuplehash[0].tuple.dst.protonum) {
8871 + DEBUGP("PROTO_UDP [cont]\n");
8872 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
8873 + DEBUGP("packet does not contain a complete header. [drop]\n");
8877 + for (port=0,portsok=0; port <= ports_n_c; port++) {
8878 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
8883 + if (portsok == 0) {
8884 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
8885 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
8889 + if ((datalen - sizeof(struct udphdr)) != 56) {
8890 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
8891 + if (rpcinfo->strict == 1)
8895 + DEBUGP("packet length is correct. [cont]\n");
8897 + /* Get to the data */
8898 + data = (const u_int32_t *)hdr + 2;
8900 + /* Check the RPC data */
8901 + tval = check_rpc_packet(data, matchinfo, hotdrop,
8903 + request_p_list_udp);
8909 + DEBUGP("PROTO_TCP [cont]\n");
8910 + if (offset == 0 && datalen < sizeof(struct tcphdr)) {
8911 + DEBUGP("packet does not contain a complete header. [drop]\n");
8915 + for (port=0,portsok=0; port <= ports_n_c; port++) {
8916 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
8921 + if (portsok == 0) {
8922 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
8923 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
8928 + if (datalen == (tcp->doff * 4)) {
8929 + DEBUGP("packet does not contain any data. [match]\n");
8930 + return (1 && (!offset));
8933 + /* Tests if packet len is ok */
8934 + if ((datalen - (tcp->doff * 4)) != 60) {
8935 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
8936 + if(rpcinfo->strict == 1)
8940 + DEBUGP("packet length is correct. [cont]\n");
8942 + /* Get to the data */
8943 + data = (const u_int32_t *)tcp + tcp->doff + 1;
8945 + /* Check the RPC data */
8946 + tval = check_rpc_packet(data, matchinfo, hotdrop,
8948 + request_p_list_tcp);
8954 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
8955 + ct->tuplehash[0].tuple.dst.protonum);
8960 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
8961 + unsigned int matchsize, unsigned int hook_mask)
8964 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
8965 + | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
8966 + printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
8970 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
8977 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
8978 + &match, &checkentry, NULL,
8982 +static int __init init(void)
8986 + DEBUGP("incrementing usage counts\n");
8987 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
8988 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
8990 + /* If no port given, default to standard RPC port */
8991 + if (ports[0] == 0)
8992 + ports[0] = RPC_PORT;
8994 + DEBUGP("registering match [%s] for;\n", rpc_match.name);
8995 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
8996 + DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
9000 + return ipt_register_match(&rpc_match);
9004 +static void fini(void)
9006 + DEBUGP("unregistering match\n");
9007 + ipt_unregister_match(&rpc_match);
9009 + DEBUGP("decrementing usage counts\n");
9010 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
9011 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
9018 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_string.c
9019 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
9020 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_string.c 2004-04-16 09:19:37.000000000 +0200
9022 +/* Kernel module to match a string into a packet.
9024 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
9027 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
9028 + * Fixed SMP re-entrancy problem using per-cpu data areas
9029 + * for the skip/shift tables.
9030 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
9031 + * Fixed kernel panic, due to overrunning boyer moore string
9032 + * tables. Also slightly tweaked heuristic for deciding what
9033 + * search algo to use.
9034 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
9035 + * Implemented Boyer Moore Sublinear search algorithm
9036 + * alongside the existing linear search based on memcmp().
9037 + * Also a quick check to decide which method to use on a per
9041 +#include <linux/smp.h>
9042 +#include <linux/module.h>
9043 +#include <linux/skbuff.h>
9044 +#include <linux/file.h>
9045 +#include <net/sock.h>
9047 +#include <linux/netfilter_ipv4/ip_tables.h>
9048 +#include <linux/netfilter_ipv4/ipt_string.h>
9050 +MODULE_LICENSE("GPL");
9052 +struct string_per_cpu {
9058 +struct string_per_cpu *bm_string_data=NULL;
9060 +/* Boyer Moore Sublinear string search - VERY FAST */
9061 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
9063 + int M1, right_end, sk, sh;
9066 + int *skip, *shift, *len;
9068 + /* use data suitable for this CPU */
9069 + shift=bm_string_data[smp_processor_id()].shift;
9070 + skip=bm_string_data[smp_processor_id()].skip;
9071 + len=bm_string_data[smp_processor_id()].len;
9073 + /* Setup skip/shift tables */
9074 + M1 = right_end = needle_len-1;
9075 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
9076 + for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
9078 + for (i = 1; i < needle_len; i++) {
9079 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
9084 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
9085 + for (i = M1; i > 0; i--) shift[len[i]] = i;
9088 + for (i = 0; i < needle_len; i++) {
9089 + if (len[i] == M1 - i) ended = i;
9090 + if (ended) shift[i] = ended;
9093 + /* Do the search*/
9094 + while (right_end < haystack_len)
9096 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
9097 + if (i == needle_len) {
9098 + return haystack+(right_end - M1);
9101 + sk = skip[haystack[right_end - i]];
9103 + right_end = max(right_end - i + sk, right_end + sh);
9109 +/* Linear string search based on memcmp() */
9110 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
9112 + char *k = haystack + (haystack_len-needle_len);
9113 + char *t = haystack;
9115 + while ( t <= k ) {
9116 + if (memcmp(t, needle, needle_len) == 0)
9126 +match(const struct sk_buff *skb,
9127 + const struct net_device *in,
9128 + const struct net_device *out,
9129 + const void *matchinfo,
9132 + u_int16_t datalen,
9135 + const struct ipt_string_info *info = matchinfo;
9136 + struct iphdr *ip = skb->nh.iph;
9138 + char *needle, *haystack;
9139 + proc_ipt_search search=search_linear;
9141 + if ( !ip ) return 0;
9143 + /* get lenghts, and validate them */
9145 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
9146 + if ( nlen > hlen ) return 0;
9148 + needle=(char *)&info->string;
9149 + haystack=(char *)ip+(ip->ihl*4);
9151 + /* The sublinear search comes in to its own
9152 + * on the larger packets */
9153 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
9154 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
9155 + if ( hlen < BM_MAX_HLEN ) {
9156 + search=search_sublinear;
9158 + if (net_ratelimit())
9159 + printk(KERN_INFO "ipt_string: Packet too big "
9160 + "to attempt sublinear string search "
9161 + "(%d bytes)\n", hlen );
9165 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
9169 +checkentry(const char *tablename,
9170 + const struct ipt_ip *ip,
9172 + unsigned int matchsize,
9173 + unsigned int hook_mask)
9176 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
9182 +void string_freeup_data(void)
9186 + if ( bm_string_data ) {
9187 + for(c=0; c<smp_num_cpus; c++) {
9188 + if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
9189 + if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
9190 + if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
9192 + kfree(bm_string_data);
9196 +static struct ipt_match string_match
9197 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
9199 +static int __init init(void)
9205 + tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
9206 + alen=sizeof(int)*BM_MAX_HLEN;
9208 + /* allocate array of structures */
9209 + if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
9213 + memset(bm_string_data, 0, tlen);
9215 + /* allocate our skip/shift tables */
9216 + for(c=0; c<smp_num_cpus; c++) {
9217 + if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
9219 + if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
9221 + if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
9225 + return ipt_register_match(&string_match);
9228 + string_freeup_data();
9232 +static void __exit fini(void)
9234 + ipt_unregister_match(&string_match);
9235 + string_freeup_data();
9240 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_unclean.c
9241 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
9242 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_unclean.c 2004-04-16 09:19:34.000000000 +0200
9244 +/* Kernel module to match suspect packets. */
9245 +#include <linux/module.h>
9246 +#include <linux/skbuff.h>
9247 +#include <linux/ip.h>
9248 +#include <linux/udp.h>
9249 +#include <linux/tcp.h>
9250 +#include <linux/icmp.h>
9251 +#include <net/checksum.h>
9253 +#include <linux/netfilter_ipv4/ip_tables.h>
9255 +#define limpk(format, args...) \
9257 + if (net_ratelimit()) \
9258 + printk("ipt_unclean: %s" format, \
9259 + embedded ? "(embedded packet) " : "" , ## args); \
9262 +enum icmp_error_status
9264 + ICMP_MAY_BE_ERROR,
9271 + size_t min_len, max_len;
9272 + enum icmp_error_status err;
9273 + u_int8_t min_code, max_code;
9277 +check_ip(struct iphdr *iph, size_t length, int embedded);
9279 +/* ICMP-specific checks. */
9281 +check_icmp(const struct icmphdr *icmph,
9282 + u_int16_t datalen,
9283 + unsigned int offset,
9287 + static struct icmp_info info[]
9288 + = { [ICMP_ECHOREPLY]
9289 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9290 + [ICMP_DEST_UNREACH]
9291 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
9292 + [ICMP_SOURCE_QUENCH]
9293 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
9295 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
9297 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9298 + /* Router advertisement. */
9300 + = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
9301 + /* Router solicitation. */
9303 + = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
9304 + [ICMP_TIME_EXCEEDED]
9305 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
9306 + [ICMP_PARAMETERPROB]
9307 + = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
9309 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
9310 + [ICMP_TIMESTAMPREPLY]
9311 + = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
9312 + [ICMP_INFO_REQUEST]
9313 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9315 + = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9317 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
9318 + [ICMP_ADDRESSREPLY]
9319 + = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
9321 + /* Can't do anything if it's a fragment. */
9325 + /* Must cover type and code. */
9326 + if (datalen < 2) {
9327 + limpk("ICMP len=%u too short\n", datalen);
9331 + /* If not embedded. */
9333 + /* Bad checksum? Don't print, just ignore. */
9335 + && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
9338 + /* CHECK: Truncated ICMP (even if first fragment). */
9339 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9340 + && info[icmph->type].min_len != 0
9341 + && datalen < info[icmph->type].min_len) {
9342 + limpk("ICMP type %u len %u too short\n",
9343 + icmph->type, datalen);
9347 + /* CHECK: Check within known error ICMPs. */
9348 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9349 + && info[icmph->type].err == ICMP_IS_ERROR) {
9350 + /* CHECK: Embedded packet must be at least
9351 + length of iph + 8 bytes. */
9352 + struct iphdr *inner = (void *)icmph + 8;
9354 + /* datalen > 8 since all ICMP_IS_ERROR types
9355 + have min length > 8 */
9356 + if (datalen - 8 < sizeof(struct iphdr)) {
9357 + limpk("ICMP error internal way too short\n");
9360 + if (datalen - 8 < inner->ihl*4 + 8) {
9361 + limpk("ICMP error internal too short\n");
9364 + if (!check_ip(inner, datalen - 8, 1))
9368 + /* CHECK: Can't embed ICMP unless known non-error. */
9369 + if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
9370 + || info[icmph->type].err != ICMP_NOT_ERROR) {
9371 + limpk("ICMP type %u not embeddable\n",
9377 + /* CHECK: Invalid ICMP codes. */
9378 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9379 + && (icmph->code < info[icmph->type].min_code
9380 + || icmph->code > info[icmph->type].max_code)) {
9381 + limpk("ICMP type=%u code=%u\n",
9382 + icmph->type, icmph->code);
9386 + /* CHECK: Above maximum length. */
9387 + if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9388 + && info[icmph->type].max_len != 0
9389 + && datalen > info[icmph->type].max_len) {
9390 + limpk("ICMP type=%u too long: %u bytes\n",
9391 + icmph->type, datalen);
9395 + switch (icmph->type) {
9396 + case ICMP_PARAMETERPROB: {
9397 + /* CHECK: Problem param must be within error packet's
9399 + struct iphdr *iph = (void *)icmph + 8;
9400 + u_int32_t arg = ntohl(icmph->un.gateway);
9402 + if (icmph->code == 0) {
9403 + /* Code 0 means that upper 8 bits is pointer
9405 + if ((arg >> 24) >= iph->ihl*4) {
9406 + limpk("ICMP PARAMETERPROB ptr = %u\n",
9407 + ntohl(icmph->un.gateway) >> 24);
9410 + arg &= 0x00FFFFFF;
9413 + /* CHECK: Rest must be zero. */
9415 + limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
9422 + case ICMP_TIME_EXCEEDED:
9423 + case ICMP_SOURCE_QUENCH:
9424 + /* CHECK: Unused must be zero. */
9425 + if (icmph->un.gateway != 0) {
9426 + limpk("ICMP type=%u unused = %u\n",
9427 + icmph->type, ntohl(icmph->un.gateway));
9436 +/* UDP-specific checks. */
9438 +check_udp(const struct iphdr *iph,
9439 + const struct udphdr *udph,
9440 + u_int16_t datalen,
9441 + unsigned int offset,
9445 + /* Can't do anything if it's a fragment. */
9449 + /* CHECK: Must cover UDP header. */
9450 + if (datalen < sizeof(struct udphdr)) {
9451 + limpk("UDP len=%u too short\n", datalen);
9455 + /* Bad checksum? Don't print, just say it's unclean. */
9456 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
9457 + if (!more_frags && !embedded && udph->check
9458 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
9459 + csum_partial((char *)udph, datalen, 0)) != 0)
9462 + /* CHECK: Destination port can't be zero. */
9463 + if (!udph->dest) {
9464 + limpk("UDP zero destination port\n");
9468 + if (!more_frags) {
9470 + /* CHECK: UDP length must match. */
9471 + if (ntohs(udph->len) != datalen) {
9472 + limpk("UDP len too short %u vs %u\n",
9473 + ntohs(udph->len), datalen);
9477 + /* CHECK: UDP length be >= this truncated pkt. */
9478 + if (ntohs(udph->len) < datalen) {
9479 + limpk("UDP len too long %u vs %u\n",
9480 + ntohs(udph->len), datalen);
9485 + /* CHECK: UDP length must be > this frag's length. */
9486 + if (ntohs(udph->len) <= datalen) {
9487 + limpk("UDP fragment len too short %u vs %u\n",
9488 + ntohs(udph->len), datalen);
9496 +#define TH_FIN 0x01
9497 +#define TH_SYN 0x02
9498 +#define TH_RST 0x04
9499 +#define TH_PUSH 0x08
9500 +#define TH_ACK 0x10
9501 +#define TH_URG 0x20
9502 +#define TH_ECE 0x40
9503 +#define TH_CWR 0x80
9505 +/* table of valid flag combinations - ECE and CWR are always valid */
9506 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
9509 + [TH_SYN|TH_ACK] = 1,
9511 + [TH_RST|TH_ACK] = 1,
9512 + [TH_RST|TH_ACK|TH_PUSH] = 1,
9513 + [TH_FIN|TH_ACK] = 1,
9515 + [TH_ACK|TH_PUSH] = 1,
9516 + [TH_ACK|TH_URG] = 1,
9517 + [TH_ACK|TH_URG|TH_PUSH] = 1,
9518 + [TH_FIN|TH_ACK|TH_PUSH] = 1,
9519 + [TH_FIN|TH_ACK|TH_URG] = 1,
9520 + [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
9523 +/* TCP-specific checks. */
9525 +check_tcp(const struct iphdr *iph,
9526 + const struct tcphdr *tcph,
9527 + u_int16_t datalen,
9528 + unsigned int offset,
9532 + u_int8_t *opt = (u_int8_t *)tcph;
9533 + u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
9534 + u_int8_t tcpflags;
9535 + int end_of_options = 0;
9538 + /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
9539 + /* In fact, this is caught below (offset < 516). */
9541 + /* Can't do anything if it's a fragment. */
9545 + /* CHECK: Smaller than minimal TCP hdr. */
9546 + if (datalen < sizeof(struct tcphdr)) {
9548 + limpk("Packet length %u < TCP header.\n", datalen);
9551 + /* Must have ports available (datalen >= 8), from
9552 + check_icmp which set embedded = 1 */
9553 + /* CHECK: TCP ports inside ICMP error */
9554 + if (!tcph->source || !tcph->dest) {
9555 + limpk("Zero TCP ports %u/%u.\n",
9556 + htons(tcph->source), htons(tcph->dest));
9562 + /* CHECK: Smaller than actual TCP hdr. */
9563 + if (datalen < tcph->doff * 4) {
9565 + limpk("Packet length %u < actual TCP header.\n",
9572 + /* Bad checksum? Don't print, just say it's unclean. */
9573 + /* FIXME: SRC ROUTE packets won't match checksum --RR */
9574 + if (!more_frags && !embedded
9575 + && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
9576 + csum_partial((char *)tcph, datalen, 0)) != 0)
9579 + /* CHECK: TCP ports non-zero */
9580 + if (!tcph->source || !tcph->dest) {
9581 + limpk("Zero TCP ports %u/%u.\n",
9582 + htons(tcph->source), htons(tcph->dest));
9586 + /* CHECK: TCP reserved bits zero. */
9587 + if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
9588 + limpk("TCP reserved bits not zero\n");
9592 + /* CHECK: TCP flags. */
9593 + tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
9594 + if (!tcp_valid_flags[tcpflags]) {
9595 + limpk("TCP flags bad: %u\n", tcpflags);
9599 + for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
9602 + end_of_options = 1;
9609 + /* CHECK: options after EOO. */
9610 + if (end_of_options) {
9611 + limpk("TCP option %u after end\n",
9615 + /* CHECK: options at tail. */
9616 + else if (i+1 >= tcph->doff * 4) {
9617 + limpk("TCP option %u at tail\n",
9621 + /* CHECK: zero-length options. */
9622 + else if (opt[i+1] == 0) {
9623 + limpk("TCP option %u 0 len\n",
9627 + /* CHECK: oversize options. */
9628 + else if (&opt[i] + opt[i+1] > endhdr) {
9629 + limpk("TCP option %u at %Zu too long\n",
9630 + (unsigned int) opt[i], i);
9633 + /* Move to next option */
9641 +/* Returns 1 if ok */
9642 +/* Standard IP checks. */
9644 +check_ip(struct iphdr *iph, size_t length, int embedded)
9646 + u_int8_t *opt = (u_int8_t *)iph;
9647 + u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
9648 + int end_of_options = 0;
9652 + unsigned int offset;
9654 + /* Should only happen for local outgoing raw-socket packets. */
9655 + /* CHECK: length >= ip header. */
9656 + if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
9657 + limpk("Packet length %Zu < IP header.\n", length);
9661 + offset = ntohs(iph->frag_off) & IP_OFFSET;
9662 + protoh = (void *)iph + iph->ihl * 4;
9663 + datalen = length - iph->ihl * 4;
9665 + /* CHECK: Embedded fragment. */
9666 + if (embedded && offset) {
9667 + limpk("Embedded fragment.\n");
9671 + for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
9674 + end_of_options = 1;
9681 + /* CHECK: options after EOO. */
9682 + if (end_of_options) {
9683 + limpk("IP option %u after end\n",
9687 + /* CHECK: options at tail. */
9688 + else if (i+1 >= iph->ihl * 4) {
9689 + limpk("IP option %u at tail\n",
9693 + /* CHECK: zero-length or one-length options. */
9694 + else if (opt[i+1] < 2) {
9695 + limpk("IP option %u %u len\n",
9696 + opt[i], opt[i+1]);
9699 + /* CHECK: oversize options. */
9700 + else if (&opt[i] + opt[i+1] > endhdr) {
9701 + limpk("IP option %u at %u too long\n",
9705 + /* Move to next option */
9710 + /* Fragment checks. */
9712 + /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
9713 + if ((ntohs(iph->frag_off) & IP_MF)
9714 + && (ntohs(iph->tot_len) % 8) != 0) {
9715 + limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
9719 + /* CHECK: Oversize fragment a-la Ping of Death. */
9720 + if (offset * 8 + datalen > 65535) {
9721 + limpk("Oversize fragment to %u.\n", offset * 8);
9725 + /* CHECK: DF set and offset or MF set. */
9726 + if ((ntohs(iph->frag_off) & IP_DF)
9727 + && (offset || (ntohs(iph->frag_off) & IP_MF))) {
9728 + limpk("DF set and offset=%u, MF=%u.\n",
9729 + offset, ntohs(iph->frag_off) & IP_MF);
9733 + /* CHECK: Zero-sized fragments. */
9734 + if ((offset || (ntohs(iph->frag_off) & IP_MF))
9735 + && datalen == 0) {
9736 + limpk("Zero size fragment offset=%u\n", offset);
9740 + /* Note: we can have even middle fragments smaller than this:
9741 + consider a large packet passing through a 600MTU then
9742 + 576MTU link: this gives a fragment of 24 data bytes. But
9743 + everyone packs fragments largest first, hence a fragment
9744 + can't START before 576 - MAX_IP_HEADER_LEN. */
9746 + /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
9747 + down to 128 (576 taken from RFC 791: All hosts must be
9748 + prepared to accept datagrams of up to 576 octets). Use 128
9750 +#define MIN_LIKELY_MTU 128
9751 + /* CHECK: Min size of first frag = 128. */
9752 + if ((ntohs(iph->frag_off) & IP_MF)
9754 + && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
9755 + limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
9760 + /* CHECK: Min offset of frag = 128 - IP hdr len. */
9761 + if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
9762 + limpk("Fragment starts at %u < %u\n", offset * 8,
9763 + MIN_LIKELY_MTU - iph->ihl * 4);
9767 + /* CHECK: Protocol specification non-zero. */
9768 + if (iph->protocol == 0) {
9769 + limpk("Zero protocol\n");
9773 + /* CHECK: Do not use what is unused.
9774 + * First bit of fragmentation flags should be unused.
9775 + * May be used by OS fingerprinting tools.
9776 + * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
9778 + if (ntohs(iph->frag_off)>>15) {
9779 + limpk("IP unused bit set\n");
9783 + /* Per-protocol checks. */
9784 + switch (iph->protocol) {
9785 + case IPPROTO_ICMP:
9786 + return check_icmp(protoh, datalen, offset,
9787 + (ntohs(iph->frag_off) & IP_MF),
9791 + return check_udp(iph, protoh, datalen, offset,
9792 + (ntohs(iph->frag_off) & IP_MF),
9796 + return check_tcp(iph, protoh, datalen, offset,
9797 + (ntohs(iph->frag_off) & IP_MF),
9800 + /* Ignorance is bliss. */
9806 +match(const struct sk_buff *skb,
9807 + const struct net_device *in,
9808 + const struct net_device *out,
9809 + const void *matchinfo,
9812 + u_int16_t datalen,
9815 + return !check_ip(skb->nh.iph, skb->len, 0);
9818 +/* Called when user tries to insert an entry of this type. */
9820 +checkentry(const char *tablename,
9821 + const struct ipt_ip *ip,
9823 + unsigned int matchsize,
9824 + unsigned int hook_mask)
9826 + if (matchsize != IPT_ALIGN(0))
9832 +static struct ipt_match unclean_match
9833 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
9835 +static int __init init(void)
9837 + return ipt_register_match(&unclean_match);
9840 +static void __exit fini(void)
9842 + ipt_unregister_match(&unclean_match);
9847 +MODULE_LICENSE("GPL");
9848 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/raw.c linux-2.6.6-rc1/net/ipv4/raw.c
9849 --- linux-2.6.6-rc1.org/net/ipv4/raw.c 2004-04-15 03:35:04.000000000 +0200
9850 +++ linux-2.6.6-rc1/net/ipv4/raw.c 2004-04-16 09:17:13.000000000 +0200
9857 skb_push(skb, skb->data - skb->nh.raw);
9862 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
9866 err = inet->recverr ? net_xmit_errno(err) : 0;
9868 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc1/net/ipv4/tcp_ipv4.c
9869 --- linux-2.6.6-rc1.org/net/ipv4/tcp_ipv4.c 2004-04-15 03:34:35.000000000 +0200
9870 +++ linux-2.6.6-rc1/net/ipv4/tcp_ipv4.c 2004-04-16 09:18:14.000000000 +0200
9871 @@ -1785,6 +1785,7 @@
9873 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
9874 goto discard_and_relse;
9877 if (sk_filter(sk, skb, 0))
9878 goto discard_and_relse;
9879 @@ -2670,6 +2671,7 @@
9880 EXPORT_SYMBOL(tcp_v4_connect);
9881 EXPORT_SYMBOL(tcp_v4_do_rcv);
9882 EXPORT_SYMBOL(tcp_v4_lookup_listener);
9883 +EXPORT_SYMBOL(tcp_v4_lookup);
9884 EXPORT_SYMBOL(tcp_v4_rebuild_header);
9885 EXPORT_SYMBOL(tcp_v4_remember_stamp);
9886 EXPORT_SYMBOL(tcp_v4_send_check);
9887 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/udp.c linux-2.6.6-rc1/net/ipv4/udp.c
9888 --- linux-2.6.6-rc1.org/net/ipv4/udp.c 2004-04-15 03:34:02.000000000 +0200
9889 +++ linux-2.6.6-rc1/net/ipv4/udp.c 2004-04-16 09:18:14.000000000 +0200
9890 @@ -1030,6 +1030,7 @@
9896 if (up->encap_type) {
9898 @@ -1195,6 +1196,7 @@
9900 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
9904 /* No socket. Drop packet silently, if checksum is wrong */
9905 if (udp_checksum_complete(skb))
9906 @@ -1543,6 +1545,7 @@
9907 EXPORT_SYMBOL(udp_port_rover);
9908 EXPORT_SYMBOL(udp_prot);
9909 EXPORT_SYMBOL(udp_sendmsg);
9910 +EXPORT_SYMBOL(udp_v4_lookup);
9912 #ifdef CONFIG_PROC_FS
9913 EXPORT_SYMBOL(udp_proc_register);
9914 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc1/net/ipv4/xfrm4_tunnel.c
9915 --- linux-2.6.6-rc1.org/net/ipv4/xfrm4_tunnel.c 2004-04-15 03:33:55.000000000 +0200
9916 +++ linux-2.6.6-rc1/net/ipv4/xfrm4_tunnel.c 2004-04-16 09:17:09.000000000 +0200
9918 err = -EHOSTUNREACH;
9921 + IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
9922 return NET_XMIT_BYPASS;
9926 .handler = ipip_rcv,
9927 .err_handler = ipip_err,
9932 static int __init ipip_init(void)
9933 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc1/net/ipv6/netfilter/Kconfig
9934 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/Kconfig 2004-04-16 08:59:09.000000000 +0200
9935 +++ linux-2.6.6-rc1/net/ipv6/netfilter/Kconfig 2004-04-16 09:15:44.000000000 +0200
9936 @@ -255,5 +255,10 @@
9937 <file:Documentation/modules.txt>. If unsure, say `N'.
9940 +config IP6_NF_TARGET_ROUTE
9941 + tristate ' ROUTE target support'
9942 + depends on IP6_NF_MANGLE
9947 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc1/net/ipv6/netfilter/Makefile
9948 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/Makefile 2004-04-16 08:59:09.000000000 +0200
9949 +++ linux-2.6.6-rc1/net/ipv6/netfilter/Makefile 2004-04-16 09:15:44.000000000 +0200
9951 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
9952 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
9953 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
9954 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
9955 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
9956 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
9957 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
9958 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_ROUTE.c
9959 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
9960 +++ linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_ROUTE.c 2004-04-16 09:15:44.000000000 +0200
9963 + * This implements the ROUTE v6 target, which enables you to setup unusual
9964 + * routes not supported by the standard kernel routing table.
9966 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
9968 + * v 1.0 2003/08/05
9970 + * This software is distributed under GNU GPL v2, 1991
9973 +#include <linux/module.h>
9974 +#include <linux/skbuff.h>
9975 +#include <linux/ipv6.h>
9976 +#include <linux/netfilter_ipv6/ip6_tables.h>
9977 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
9978 +#include <linux/netdevice.h>
9979 +#include <net/ipv6.h>
9980 +#include <net/ndisc.h>
9981 +#include <net/ip6_route.h>
9982 +#include <linux/icmpv6.h>
9985 +#define DEBUGP printk
9987 +#define DEBUGP(format, args...)
9990 +#define NIP6(addr) \
9991 + ntohs((addr).s6_addr16[0]), \
9992 + ntohs((addr).s6_addr16[1]), \
9993 + ntohs((addr).s6_addr16[2]), \
9994 + ntohs((addr).s6_addr16[3]), \
9995 + ntohs((addr).s6_addr16[4]), \
9996 + ntohs((addr).s6_addr16[5]), \
9997 + ntohs((addr).s6_addr16[6]), \
9998 + ntohs((addr).s6_addr16[7])
10000 +/* Route the packet according to the routing keys specified in
10001 + * route_info. Keys are :
10003 + * 0 if no oif preferred,
10004 + * otherwise set to the index of the desired oif
10005 + * - route_info->gw :
10006 + * 0 if no gateway specified,
10007 + * otherwise set to the next host to which the pkt must be routed
10008 + * If success, skb->dev is the output device to which the packet must
10009 + * be sent and skb->dst is not NULL
10011 + * RETURN: 1 if the packet was succesfully routed to the
10012 + * destination desired
10013 + * 0 if the kernel routing table could not route the packet
10014 + * according to the keys specified
10017 +route6(struct sk_buff *skb,
10018 + unsigned int ifindex,
10019 + const struct ip6t_route_target_info *route_info)
10021 + struct rt6_info *rt = NULL;
10022 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
10023 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
10025 + DEBUGP("ip6t_ROUTE: called with: ");
10026 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
10027 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
10028 + DEBUGP("OUT=%s\n", route_info->oif);
10030 + if (ipv6_addr_any(gw))
10031 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
10033 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
10038 + DEBUGP("ip6t_ROUTE: routing gives: ");
10039 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
10040 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
10041 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
10043 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
10044 + goto wrong_route;
10046 + if (!rt->rt6i_nexthop) {
10047 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
10048 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
10051 + /* Drop old route. */
10052 + dst_release(skb->dst);
10053 + skb->dst = &rt->u.dst;
10054 + skb->dev = rt->rt6i_dev;
10058 + dst_release(&rt->u.dst);
10060 + if (!net_ratelimit())
10063 + printk("ip6t_ROUTE: no explicit route found ");
10065 + printk("via interface %s ", route_info->oif);
10066 + if (!ipv6_addr_any(gw))
10067 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
10073 +/* Stolen from ip6_output_finish
10074 + * PRE : skb->dev is set to the device we are leaving by
10075 + * skb->dst is not NULL
10076 + * POST: the packet is sent with the link layer header pushed
10077 + * the packet is destroyed
10079 +static void ip_direct_send(struct sk_buff *skb)
10081 + struct dst_entry *dst = skb->dst;
10082 + struct hh_cache *hh = dst->hh;
10085 + read_lock_bh(&hh->hh_lock);
10086 + memcpy(skb->data - 16, hh->hh_data, 16);
10087 + read_unlock_bh(&hh->hh_lock);
10088 + skb_push(skb, hh->hh_len);
10089 + hh->hh_output(skb);
10090 + } else if (dst->neighbour)
10091 + dst->neighbour->output(skb);
10093 + if (net_ratelimit())
10094 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
10100 +static unsigned int
10101 +route6_oif(const struct ip6t_route_target_info *route_info,
10102 + struct sk_buff *skb)
10104 + unsigned int ifindex = 0;
10105 + struct net_device *dev_out = NULL;
10107 + /* The user set the interface name to use.
10108 + * Getting the current interface index.
10110 + if ((dev_out = dev_get_by_name(route_info->oif))) {
10111 + ifindex = dev_out->ifindex;
10113 + /* Unknown interface name : packet dropped */
10114 + if (net_ratelimit())
10115 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
10117 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
10118 + return IP6T_CONTINUE;
10123 + /* Trying the standard way of routing packets */
10124 + if (route6(skb, ifindex, route_info)) {
10125 + dev_put(dev_out);
10126 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
10127 + return IP6T_CONTINUE;
10129 + ip_direct_send(skb);
10130 + return NF_STOLEN;
10136 +static unsigned int
10137 +route6_gw(const struct ip6t_route_target_info *route_info,
10138 + struct sk_buff *skb)
10140 + if (route6(skb, 0, route_info)) {
10141 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
10142 + return IP6T_CONTINUE;
10144 + ip_direct_send(skb);
10145 + return NF_STOLEN;
10151 +static unsigned int
10152 +ip6t_route_target(struct sk_buff **pskb,
10153 + unsigned int hooknum,
10154 + const struct net_device *in,
10155 + const struct net_device *out,
10156 + const void *targinfo,
10159 + const struct ip6t_route_target_info *route_info = targinfo;
10160 + struct sk_buff *skb = *pskb;
10161 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
10163 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
10166 + /* If we are at PREROUTING or INPUT hook
10167 + * the TTL isn't decreased by the IP stack
10169 + if (hooknum == NF_IP6_PRE_ROUTING ||
10170 + hooknum == NF_IP6_LOCAL_IN) {
10172 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
10174 + if (ipv6h->hop_limit <= 1) {
10175 + /* Force OUTPUT device used as source address */
10176 + skb->dev = skb->dst->dev;
10178 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
10179 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
10184 + ipv6h->hop_limit--;
10189 + if (route_info->oif[0])
10190 + return route6_oif(route_info, *pskb);
10192 + if (!ipv6_addr_any(gw))
10193 + return route6_gw(route_info, *pskb);
10195 + if (net_ratelimit())
10196 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
10198 + return IP6T_CONTINUE;
10203 +ip6t_route_checkentry(const char *tablename,
10204 + const struct ip6t_entry *e,
10206 + unsigned int targinfosize,
10207 + unsigned int hook_mask)
10209 + if (strcmp(tablename, "mangle") != 0) {
10210 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
10214 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
10215 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
10217 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
10225 +static struct ip6t_target ip6t_route_reg = {
10227 + .target = ip6t_route_target,
10228 + .checkentry = ip6t_route_checkentry,
10229 + .me = THIS_MODULE
10233 +static int __init init(void)
10235 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
10236 + if (ip6t_register_target(&ip6t_route_reg))
10243 +static void __exit fini(void)
10245 + ip6t_unregister_target(&ip6t_route_reg);
10248 +module_init(init);
10249 +module_exit(fini);
10250 +MODULE_LICENSE("GPL");
10251 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_owner.c
10252 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-15 03:35:20.000000000 +0200
10253 +++ linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_owner.c 2004-04-16 09:18:17.000000000 +0200
10255 MODULE_LICENSE("GPL");
10258 +match_comm(const struct sk_buff *skb, const char *comm)
10260 + struct task_struct *p;
10261 + struct files_struct *files;
10264 + read_lock(&tasklist_lock);
10265 + for_each_task(p) {
10266 + if(strncmp(p->comm, comm, sizeof(p->comm)))
10270 + files = p->files;
10272 + read_lock(&files->file_lock);
10273 + for (i=0; i < files->max_fds; i++) {
10274 + if (fcheck_files(files, i) == skb->sk->socket->file) {
10275 + read_unlock(&files->file_lock);
10277 + read_unlock(&tasklist_lock);
10281 + read_unlock(&files->file_lock);
10285 + read_unlock(&tasklist_lock);
10290 match_pid(const struct sk_buff *skb, pid_t pid)
10292 struct task_struct *p;
10293 @@ -125,6 +157,12 @@
10297 + if(info->match & IP6T_OWNER_COMM) {
10298 + if (!match_comm(skb, info->comm) ^
10299 + !!(info->invert & IP6T_OWNER_COMM))
10306 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/xfrm/xfrm_input.c linux-2.6.6-rc1/net/xfrm/xfrm_input.c
10307 --- linux-2.6.6-rc1.org/net/xfrm/xfrm_input.c 2004-04-15 03:33:51.000000000 +0200
10308 +++ linux-2.6.6-rc1/net/xfrm/xfrm_input.c 2004-04-16 09:17:09.000000000 +0200
10313 +#ifdef CONFIG_NETFILTER
10314 + sp->decap_done = 0;
10319 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc1/net/xfrm/xfrm_policy.c
10320 --- linux-2.6.6-rc1.org/net/xfrm/xfrm_policy.c 2004-04-15 03:34:48.000000000 +0200
10321 +++ linux-2.6.6-rc1/net/xfrm/xfrm_policy.c 2004-04-16 09:17:13.000000000 +0200
10323 #include <linux/workqueue.h>
10324 #include <linux/notifier.h>
10325 #include <linux/netdevice.h>
10326 +#include <linux/netfilter.h>
10327 #include <net/xfrm.h>
10328 #include <net/ip.h>
10330 @@ -908,6 +909,7 @@
10332 if (_decode_session(skb, &fl, family) < 0)
10334 + nf_nat_decode_session(skb, &fl, family);
10336 /* First, check used SA against their selectors. */