1 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter.h linux-2.6.0-test11/include/linux/netfilter.h
2 --- linux-2.6.0-test11.org/include/linux/netfilter.h 2003-11-26 21:44:11.000000000 +0100
3 +++ linux-2.6.0-test11/include/linux/netfilter.h 2003-12-11 10:23:17.221319936 +0100
5 <= 0x2000 is used for protocol-flags. */
6 #define NFC_UNKNOWN 0x4000
7 #define NFC_ALTERED 0x8000
8 +#define NFC_TRACE 0x10000
11 #include <linux/config.h>
14 extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
16 +typedef void nf_logfn(unsigned int hooknum,
17 + const struct sk_buff *skb,
18 + const struct net_device *in,
19 + const struct net_device *out,
20 + const char *prefix);
22 +/* Function to register/unregister log function. */
23 +int nf_log_register(int pf, nf_logfn *logfn);
24 +void nf_log_unregister(int pf, nf_logfn *logfn);
26 +/* Calls the registered backend logging function */
27 +void nf_log_packet(int pf,
28 + unsigned int hooknum,
29 + const struct sk_buff *skb,
30 + const struct net_device *in,
31 + const struct net_device *out,
32 + const char *fmt, ...);
34 /* Activate hook; either okfn or kfree_skb called, unless a hook
35 returns NF_STOLEN (in which case, it's up to the hook to deal with
37 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_helpers.h linux-2.6.0-test11/include/linux/netfilter_helpers.h
38 --- linux-2.6.0-test11.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
39 +++ linux-2.6.0-test11/include/linux/netfilter_helpers.h 2003-12-11 10:24:06.854774504 +0100
42 + * Helpers for netfiler modules. This file provides implementations for basic
43 + * functions such as strncasecmp(), etc.
45 + * gcc will warn for defined but unused functions, so we only include the
46 + * functions requested. The following macros are used:
47 + * NF_NEED_STRNCASECMP nf_strncasecmp()
48 + * NF_NEED_STRTOU16 nf_strtou16()
49 + * NF_NEED_STRTOU32 nf_strtou32()
51 +#ifndef _NETFILTER_HELPERS_H
52 +#define _NETFILTER_HELPERS_H
54 +/* Only include these functions for kernel code. */
57 +#include <linux/ctype.h>
58 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
61 + * The standard strncasecmp()
63 +#ifdef NF_NEED_STRNCASECMP
65 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
67 + if (s1 == NULL || s2 == NULL)
69 + if (s1 == NULL && s2 == NULL)
73 + return (s1 == NULL) ? -1 : 1;
75 + while (len > 0 && tolower(*s1) == tolower(*s2))
81 + return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
83 +#endif /* NF_NEED_STRNCASECMP */
86 + * Parse a string containing a 16-bit unsigned integer.
87 + * Returns the number of chars used, or zero if no number is found.
89 +#ifdef NF_NEED_STRTOU16
91 +nf_strtou16(const char* pbuf, u_int16_t* pval)
96 + while (isdigit(pbuf[n]))
98 + *pval = (*pval * 10) + (pbuf[n] - '0');
104 +#endif /* NF_NEED_STRTOU16 */
107 + * Parse a string containing a 32-bit unsigned integer.
108 + * Returns the number of chars used, or zero if no number is found.
110 +#ifdef NF_NEED_STRTOU32
112 +nf_strtou32(const char* pbuf, u_int32_t* pval)
117 + while (pbuf[n] >= '0' && pbuf[n] <= '9')
119 + *pval = (*pval * 10) + (pbuf[n] - '0');
125 +#endif /* NF_NEED_STRTOU32 */
128 + * Given a buffer and length, advance to the next line and mark the current
131 +#ifdef NF_NEED_NEXTLINE
133 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
143 + while (p[off] != '\n')
154 + /* if we saw a crlf, physlen needs adjusted */
155 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
160 + /* advance past the newline */
164 + *plinelen = physlen;
169 +#endif /* NF_NEED_NEXTLINE */
171 +#endif /* __KERNEL__ */
173 +#endif /* _NETFILTER_HELPERS_H */
174 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
175 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 1970-01-01 01:00:00.000000000 +0100
176 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 2003-12-11 10:23:48.969493480 +0100
178 +#ifndef _IP_CT_CUSEEME
179 +#define _IP_CT_CUSEEME
181 +#define CUSEEME_PORT 7648
183 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
186 +/* CuSeeMe data header */
188 + u_int16_t dest_family;
189 + u_int16_t dest_port;
190 + u_int32_t dest_addr;
196 + u_int16_t data_type;
197 + /* possible values:
201 + * 100 acknowledge connectivity when there
202 + * is nothing else to send
203 + * 101 OpenContinue packet
204 + * 104 display a text message and
205 + * disconnect (used by reflector to
206 + * kick clients off)
207 + * 105 display a text message (welcome
208 + * message from reflector)
209 + * 106 exchanged among reflectors for
210 + * reflector interoperation
211 + * 107 carry aux stream data when there is
212 + * no video to piggy-back on
213 + * 108 obsolete (used in Mac alpha version)
214 + * 109 obsolete (used in Mac alpha version)
215 + * 110 used for data rate control
216 + * 111 used for data rate control
217 + * 256 aux data control messages
218 + * 257 aux data packets
220 + u_int16_t packet_len;
223 +/* Open Continue Header */
225 + struct cu_header cu_head;
226 + u_int16_t client_count; /* Number of client info structs */
228 + char user_name[20];
229 + char stuff[4]; /* Flags, version stuff, etc */
232 +/* Client info structures */
233 +struct client_info {
234 + u_int32_t address; /* Client address */
235 + char stuff[8]; /* Flags, pruning bitfield, packet counts, etc */
239 +/* This structure is per expected connection */
240 +struct ip_ct_cuseeme_expect {
243 +/* This structure exists only once per master */
244 +struct ip_ct_cuseeme_master {
247 +#endif /* _IP_CT_CUSEEME */
248 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack.h
249 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack.h 2003-11-26 21:45:37.000000000 +0100
250 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack.h 2003-12-11 10:24:15.984386592 +0100
253 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
254 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
255 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
257 /* per conntrack: protocol private data */
258 union ip_conntrack_proto {
259 /* insert conntrack proto private data here */
260 + struct ip_ct_gre gre;
261 struct ip_ct_tcp tcp;
262 struct ip_ct_icmp icmp;
265 union ip_conntrack_expect_proto {
266 /* insert expect proto private data here */
267 + struct ip_ct_gre_expect gre;
270 /* Add protocol helper include file here */
271 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
272 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
273 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
274 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
275 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
276 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
278 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
279 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
280 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
282 /* per expectation: application helper private data */
283 union ip_conntrack_expect_help {
284 /* insert conntrack helper private data (expect) here */
285 + struct ip_ct_talk_expect exp_talk_info;
286 + struct ip_ct_rtsp_master ct_rtsp_info;
287 + struct ip_ct_rtsp_expect exp_rtsp_info;
288 + struct ip_ct_rsh_expect exp_rsh_info;
289 + struct ip_ct_pptp_expect exp_pptp_info;
290 + struct ip_ct_mms_expect exp_mms_info;
291 + struct ip_ct_h225_expect exp_h225_info;
292 struct ip_ct_amanda_expect exp_amanda_info;
293 struct ip_ct_ftp_expect exp_ftp_info;
294 struct ip_ct_irc_expect exp_irc_info;
296 /* per conntrack: application helper private data */
297 union ip_conntrack_help {
298 /* insert conntrack helper private data (master) here */
299 + struct ip_ct_talk_master ct_talk_info;
300 + struct ip_ct_rsh_master ct_rsh_info;
301 + struct ip_ct_pptp_master ct_pptp_info;
302 + struct ip_ct_mms_master ct_mms_info;
303 + struct ip_ct_h225_master ct_h225_info;
304 struct ip_ct_ftp_master ct_ftp_info;
305 struct ip_ct_irc_master ct_irc_info;
308 #ifdef CONFIG_IP_NF_NAT_NEEDED
309 #include <linux/netfilter_ipv4/ip_nat.h>
310 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
312 /* per conntrack: nat application helper private data */
313 union ip_conntrack_nat_help {
314 /* insert nat helper private data here */
315 + struct ip_nat_pptp nat_pptp_info;
321 #endif /* CONFIG_IP_NF_NAT_NEEDED */
323 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
324 + unsigned long mark;
328 /* get master conntrack via master expectation */
330 extern void ip_ct_refresh(struct ip_conntrack *ct,
331 unsigned long extra_jiffies);
333 +/* Kill conntrack */
334 +extern void ip_ct_death_by_timeout(unsigned long ul_conntrack);
336 /* These are for NAT. Icky. */
337 /* Call me when a conntrack is destroyed. */
338 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
341 extern unsigned int ip_conntrack_htable_size;
343 +/* A fake conntrack entry which never vanishes. */
344 +extern struct ip_conntrack ip_conntrack_untracked;
346 /* eg. PROVIDES_CONNTRACK(ftp); */
347 #define PROVIDES_CONNTRACK(name) \
348 int needs_ip_conntrack_##name; \
349 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_h323.h
350 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
351 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2003-12-11 10:23:51.334134000 +0100
353 +#ifndef _IP_CONNTRACK_H323_H
354 +#define _IP_CONNTRACK_H323_H
355 +/* H.323 connection tracking. */
358 +/* Protects H.323 related data */
359 +DECLARE_LOCK_EXTERN(ip_h323_lock);
362 +/* Default H.225 port */
363 +#define H225_PORT 1720
365 +/* This structure is per expected connection */
366 +struct ip_ct_h225_expect {
367 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
368 + enum ip_conntrack_dir dir; /* Direction of the original connection */
369 + unsigned int offset; /* offset of the address in the payload */
372 +/* This structure exists only once per master */
373 +struct ip_ct_h225_master {
374 + int is_h225; /* H.225 or H.245 connection */
375 +#ifdef CONFIG_IP_NF_NAT_NEEDED
376 + enum ip_conntrack_dir dir; /* Direction of the original connection */
377 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
378 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
382 +#endif /* _IP_CONNTRACK_H323_H */
383 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_mms.h
384 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
385 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2003-12-11 10:23:55.932434952 +0100
387 +#ifndef _IP_CONNTRACK_MMS_H
388 +#define _IP_CONNTRACK_MMS_H
392 +#include <linux/netfilter_ipv4/lockhelp.h>
394 +DECLARE_LOCK_EXTERN(ip_mms_lock);
396 +#define MMS_PORT 1755
397 +#define MMS_SRV_MSG_ID 196610
399 +#define MMS_SRV_MSG_OFFSET 36
400 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
401 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
402 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
403 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
406 +/* This structure is per expected connection */
407 +struct ip_ct_mms_expect {
413 +/* This structure exists only once per master */
414 +struct ip_ct_mms_master {
417 +#endif /* _IP_CONNTRACK_MMS_H */
418 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
419 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 1970-01-01 01:00:00.000000000 +0100
420 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2003-11-17 09:09:34.000000000 +0100
422 +/* PPTP constants and structs */
423 +#ifndef _CONNTRACK_PPTP_H
424 +#define _CONNTRACK_PPTP_H
426 +/* state of the control session */
427 +enum pptp_ctrlsess_state {
428 + PPTP_SESSION_NONE, /* no session present */
429 + PPTP_SESSION_ERROR, /* some session error */
430 + PPTP_SESSION_STOPREQ, /* stop_sess request seen */
431 + PPTP_SESSION_REQUESTED, /* start_sess request seen */
432 + PPTP_SESSION_CONFIRMED, /* session established */
435 +/* state of the call inside the control session */
436 +enum pptp_ctrlcall_state {
440 + PPTP_CALL_OUT_CONF,
444 + PPTP_CALL_CLEAR_REQ,
448 +/* conntrack private data */
449 +struct ip_ct_pptp_master {
450 + enum pptp_ctrlsess_state sstate; /* session state */
452 + /* everything below is going to be per-expectation in newnat,
453 + * since there could be more than one call within one session */
454 + enum pptp_ctrlcall_state cstate; /* call state */
455 + u_int16_t pac_call_id; /* call id of PAC, host byte order */
456 + u_int16_t pns_call_id; /* call id of PNS, host byte order */
459 +/* conntrack_expect private member */
460 +struct ip_ct_pptp_expect {
461 + enum pptp_ctrlcall_state cstate; /* call state */
462 + u_int16_t pac_call_id; /* call id of PAC */
463 + u_int16_t pns_call_id; /* call id of PNS */
469 +#include <linux/netfilter_ipv4/lockhelp.h>
470 +DECLARE_LOCK_EXTERN(ip_pptp_lock);
472 +#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
474 +union pptp_ctrl_union {
476 + struct PptpStartSessionRequest *sreq;
477 + struct PptpStartSessionReply *srep;
478 + struct PptpStopSessionReqest *streq;
479 + struct PptpStopSessionReply *strep;
480 + struct PptpOutCallRequest *ocreq;
481 + struct PptpOutCallReply *ocack;
482 + struct PptpInCallRequest *icreq;
483 + struct PptpInCallReply *icack;
484 + struct PptpInCallConnected *iccon;
485 + struct PptpClearCallRequest *clrreq;
486 + struct PptpCallDisconnectNotify *disc;
487 + struct PptpWanErrorNotify *wanerr;
488 + struct PptpSetLinkInfo *setlink;
493 +#define PPTP_CONTROL_PORT 1723
495 +#define PPTP_PACKET_CONTROL 1
496 +#define PPTP_PACKET_MGMT 2
498 +#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
500 +struct pptp_pkt_hdr {
501 + __u16 packetLength;
506 +/* PptpControlMessageType values */
507 +#define PPTP_START_SESSION_REQUEST 1
508 +#define PPTP_START_SESSION_REPLY 2
509 +#define PPTP_STOP_SESSION_REQUEST 3
510 +#define PPTP_STOP_SESSION_REPLY 4
511 +#define PPTP_ECHO_REQUEST 5
512 +#define PPTP_ECHO_REPLY 6
513 +#define PPTP_OUT_CALL_REQUEST 7
514 +#define PPTP_OUT_CALL_REPLY 8
515 +#define PPTP_IN_CALL_REQUEST 9
516 +#define PPTP_IN_CALL_REPLY 10
517 +#define PPTP_IN_CALL_CONNECT 11
518 +#define PPTP_CALL_CLEAR_REQUEST 12
519 +#define PPTP_CALL_DISCONNECT_NOTIFY 13
520 +#define PPTP_WAN_ERROR_NOTIFY 14
521 +#define PPTP_SET_LINK_INFO 15
523 +#define PPTP_MSG_MAX 15
525 +/* PptpGeneralError values */
526 +#define PPTP_ERROR_CODE_NONE 0
527 +#define PPTP_NOT_CONNECTED 1
528 +#define PPTP_BAD_FORMAT 2
529 +#define PPTP_BAD_VALUE 3
530 +#define PPTP_NO_RESOURCE 4
531 +#define PPTP_BAD_CALLID 5
532 +#define PPTP_REMOVE_DEVICE_ERROR 6
534 +struct PptpControlHeader {
539 +/* FramingCapability Bitmap Values */
540 +#define PPTP_FRAME_CAP_ASYNC 0x1
541 +#define PPTP_FRAME_CAP_SYNC 0x2
543 +/* BearerCapability Bitmap Values */
544 +#define PPTP_BEARER_CAP_ANALOG 0x1
545 +#define PPTP_BEARER_CAP_DIGITAL 0x2
547 +struct PptpStartSessionRequest {
548 + __u16 protocolVersion;
551 + __u32 framingCapability;
552 + __u32 bearerCapability;
554 + __u16 firmwareRevision;
556 + __u8 vendorString[64];
559 +/* PptpStartSessionResultCode Values */
560 +#define PPTP_START_OK 1
561 +#define PPTP_START_GENERAL_ERROR 2
562 +#define PPTP_START_ALREADY_CONNECTED 3
563 +#define PPTP_START_NOT_AUTHORIZED 4
564 +#define PPTP_START_UNKNOWN_PROTOCOL 5
566 +struct PptpStartSessionReply {
567 + __u16 protocolVersion;
569 + __u8 generalErrorCode;
570 + __u32 framingCapability;
571 + __u32 bearerCapability;
573 + __u16 firmwareRevision;
575 + __u8 vendorString[64];
578 +/* PptpStopReasons */
579 +#define PPTP_STOP_NONE 1
580 +#define PPTP_STOP_PROTOCOL 2
581 +#define PPTP_STOP_LOCAL_SHUTDOWN 3
583 +struct PptpStopSessionRequest {
587 +/* PptpStopSessionResultCode */
588 +#define PPTP_STOP_OK 1
589 +#define PPTP_STOP_GENERAL_ERROR 2
591 +struct PptpStopSessionReply {
593 + __u8 generalErrorCode;
596 +struct PptpEchoRequest {
600 +/* PptpEchoReplyResultCode */
601 +#define PPTP_ECHO_OK 1
602 +#define PPTP_ECHO_GENERAL_ERROR 2
604 +struct PptpEchoReply {
607 + __u8 generalErrorCode;
611 +/* PptpFramingType */
612 +#define PPTP_ASYNC_FRAMING 1
613 +#define PPTP_SYNC_FRAMING 2
614 +#define PPTP_DONT_CARE_FRAMING 3
616 +/* PptpCallBearerType */
617 +#define PPTP_ANALOG_TYPE 1
618 +#define PPTP_DIGITAL_TYPE 2
619 +#define PPTP_DONT_CARE_BEARER_TYPE 3
621 +struct PptpOutCallRequest {
623 + __u16 callSerialNumber;
628 + __u16 packetWindow;
629 + __u16 packetProcDelay;
631 + __u16 phoneNumberLength;
633 + __u8 phoneNumber[64];
634 + __u8 subAddress[64];
637 +/* PptpCallResultCode */
638 +#define PPTP_OUTCALL_CONNECT 1
639 +#define PPTP_OUTCALL_GENERAL_ERROR 2
640 +#define PPTP_OUTCALL_NO_CARRIER 3
641 +#define PPTP_OUTCALL_BUSY 4
642 +#define PPTP_OUTCALL_NO_DIAL_TONE 5
643 +#define PPTP_OUTCALL_TIMEOUT 6
644 +#define PPTP_OUTCALL_DONT_ACCEPT 7
646 +struct PptpOutCallReply {
650 + __u8 generalErrorCode;
652 + __u32 connectSpeed;
653 + __u16 packetWindow;
654 + __u16 packetProcDelay;
655 + __u32 physChannelID;
658 +struct PptpInCallRequest {
660 + __u16 callSerialNumber;
661 + __u32 callBearerType;
662 + __u32 physChannelID;
663 + __u16 dialedNumberLength;
664 + __u16 dialingNumberLength;
665 + __u8 dialedNumber[64];
666 + __u8 dialingNumber[64];
667 + __u8 subAddress[64];
670 +/* PptpInCallResultCode */
671 +#define PPTP_INCALL_ACCEPT 1
672 +#define PPTP_INCALL_GENERAL_ERROR 2
673 +#define PPTP_INCALL_DONT_ACCEPT 3
675 +struct PptpInCallReply {
679 + __u8 generalErrorCode;
680 + __u16 packetWindow;
681 + __u16 packetProcDelay;
685 +struct PptpInCallConnected {
688 + __u32 connectSpeed;
689 + __u16 packetWindow;
690 + __u16 packetProcDelay;
691 + __u32 callFramingType;
694 +struct PptpClearCallRequest {
699 +struct PptpCallDisconnectNotify {
702 + __u8 generalErrorCode;
705 + __u8 callStatistics[128];
708 +struct PptpWanErrorNotify {
712 + __u32 framingErrors;
713 + __u32 hardwareOverRuns;
714 + __u32 bufferOverRuns;
715 + __u32 timeoutErrors;
716 + __u32 alignmentErrors;
719 +struct PptpSetLinkInfo {
727 +struct pptp_priv_data {
733 +#endif /* __KERNEL__ */
734 +#endif /* _CONNTRACK_PPTP_H */
735 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
736 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 1970-01-01 01:00:00.000000000 +0100
737 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 2003-11-17 09:09:34.000000000 +0100
739 +#ifndef _CONNTRACK_PROTO_GRE_H
740 +#define _CONNTRACK_PROTO_GRE_H
741 +#include <asm/byteorder.h>
743 +/* GRE PROTOCOL HEADER */
745 +/* GRE Version field */
746 +#define GRE_VERSION_1701 0x0
747 +#define GRE_VERSION_PPTP 0x1
749 +/* GRE Protocol field */
750 +#define GRE_PROTOCOL_PPTP 0x880B
753 +#define GRE_FLAG_C 0x80
754 +#define GRE_FLAG_R 0x40
755 +#define GRE_FLAG_K 0x20
756 +#define GRE_FLAG_S 0x10
757 +#define GRE_FLAG_A 0x80
759 +#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
760 +#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
761 +#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
762 +#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
763 +#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
765 +/* GRE is a mess: Four different standards */
767 +#if defined(__LITTLE_ENDIAN_BITFIELD)
777 +#elif defined(__BIG_ENDIAN_BITFIELD)
788 +#error "Adjust your <asm/byteorder.h> defines"
793 +/* modified GRE header for PPTP */
794 +struct gre_hdr_pptp {
795 + __u8 flags; /* bitfield */
796 + __u8 version; /* should be GRE_VERSION_PPTP */
797 + __u16 protocol; /* should be GRE_PROTOCOL_PPTP */
798 + __u16 payload_len; /* size of ppp payload, not inc. gre header */
799 + __u16 call_id; /* peer's call_id for this session */
800 + __u32 seq; /* sequence number. Present if S==1 */
801 + __u32 ack; /* seq number of highest packet recieved by */
802 + /* sender in this session */
806 +/* this is part of ip_conntrack */
808 + unsigned int stream_timeout;
809 + unsigned int timeout;
812 +/* this is part of ip_conntrack_expect */
813 +struct ip_ct_gre_expect {
814 + struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
818 +struct ip_conntrack_expect;
820 +/* structure for original <-> reply keymap */
821 +struct ip_ct_gre_keymap {
822 + struct list_head list;
824 + struct ip_conntrack_tuple tuple;
828 +/* add new tuple->key_reply pair to keymap */
829 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
830 + struct ip_conntrack_tuple *t,
833 +/* change an existing keymap entry */
834 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
835 + struct ip_conntrack_tuple *t);
837 +/* delete keymap entries */
838 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
841 +/* get pointer to gre key, if present */
842 +static inline u_int32_t *gre_key(struct gre_hdr *greh)
846 + if (greh->csum || greh->routing)
847 + return (u_int32_t *) (greh+sizeof(*greh)+4);
848 + return (u_int32_t *) (greh+sizeof(*greh));
851 +/* get pointer ot gre csum, if present */
852 +static inline u_int16_t *gre_csum(struct gre_hdr *greh)
856 + return (u_int16_t *) (greh+sizeof(*greh));
859 +#endif /* __KERNEL__ */
861 +#endif /* _CONNTRACK_PROTO_GRE_H */
862 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
863 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
864 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2003-12-11 10:24:00.844688176 +0100
866 +#ifndef _IP_CT_QUAKE3
867 +#define _IP_CT_QUAKE3
869 +/* Don't confuse with 27960, often used as the Server Port */
870 +#define QUAKE3_MASTER_PORT 27950
872 +struct quake3_search {
873 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
874 + const char *pattern;
878 +/* This structure is per expected connection */
879 +struct ip_ct_quake3_expect {
882 +/* This structure exists only once per master */
883 +struct ip_ct_quake3_master {
886 +#endif /* _IP_CT_QUAKE3 */
887 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
888 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
889 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2003-12-11 10:24:04.354154656 +0100
891 +/* RPC extension for IP connection tracking, Version 2.2
892 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
893 + * - original rpc tracking module
894 + * - "recent" connection handling for kernel 2.3+ netfilter
896 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
897 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
899 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
900 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
901 + * - extended matching to support filtering on procedures
903 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
905 + * This program is free software; you can redistribute it and/or
906 + * modify it under the terms of the GNU General Public License
907 + * as published by the Free Software Foundation; either version
908 + * 2 of the License, or (at your option) any later version.
912 +#include <asm/param.h>
913 +#include <linux/sched.h>
914 +#include <linux/timer.h>
915 +#include <linux/stddef.h>
916 +#include <linux/list.h>
918 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
920 +#ifndef _IP_CONNTRACK_RPC_H
921 +#define _IP_CONNTRACK_RPC_H
923 +#define RPC_PORT 111
926 +/* Datum in RPC packets are encoded in XDR */
927 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
929 +/* Fast timeout, to deny DoS atacks */
930 +#define EXP (60 * HZ)
932 +/* Normal timeouts */
933 +#define EXPIRES (180 * HZ)
935 +/* For future conections RPC, using client's cache bindings
936 + * I'll use ip_conntrack_lock to lock these lists */
938 +/* This identifies each request and stores protocol */
940 + struct list_head list;
949 + struct timer_list timeout;
952 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
953 + u_int32_t ip, u_int32_t port) {
954 + return (p->xid == xid && p->ip == ip && p->port);
958 +#endif /* _IP_CONNTRACK_RPC_H */
959 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
960 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
961 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2003-12-11 10:24:05.586967240 +0100
963 +/* RSH extension for IP connection tracking, Version 1.0
964 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
965 + * based on HW's ip_conntrack_irc.c
967 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
969 + * This program is free software; you can redistribute it and/or
970 + * modify it under the terms of the GNU General Public License
971 + * as published by the Free Software Foundation; either version
972 + * 2 of the License, or (at your option) any later version.
974 +#ifndef _IP_CONNTRACK_RSH_H
975 +#define _IP_CONNTRACK_RSH_H
978 +#include <linux/netfilter_ipv4/lockhelp.h>
980 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
984 +#define RSH_PORT 514
986 +/* This structure is per expected connection */
987 +struct ip_ct_rsh_expect
992 +/* This structure exists only once per master */
993 +struct ip_ct_rsh_master {
996 +#endif /* _IP_CONNTRACK_RSH_H */
998 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
999 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
1000 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2003-12-11 10:24:06.854774504 +0100
1003 + * RTSP extension for IP connection tracking.
1004 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
1005 + * based on ip_conntrack_irc.h
1007 + * This program is free software; you can redistribute it and/or
1008 + * modify it under the terms of the GNU General Public License
1009 + * as published by the Free Software Foundation; either version
1010 + * 2 of the License, or (at your option) any later version.
1012 +#ifndef _IP_CONNTRACK_RTSP_H
1013 +#define _IP_CONNTRACK_RTSP_H
1015 +/* #define IP_NF_RTSP_DEBUG */
1016 +#define IP_NF_RTSP_VERSION "0.01"
1018 +/* port block types */
1020 + pb_single, /* client_port=x */
1021 + pb_range, /* client_port=x-y */
1022 + pb_discon /* client_port=x/y (rtspbis) */
1025 +/* We record seq number and length of rtsp headers here, all in host order. */
1028 + * This structure is per expected connection. It is a member of struct
1029 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
1030 + * there and we are expected to only store the length of the data which
1031 + * needs replaced. If a packet contains multiple RTSP messages, we create
1032 + * one expected connection per message.
1034 + * We use these variables to mark the entire header block. This may seem
1035 + * like overkill, but the nature of RTSP requires it. A header may appear
1036 + * multiple times in a message. We must treat two Transport headers the
1037 + * same as one Transport header with two entries.
1039 +struct ip_ct_rtsp_expect
1041 + u_int32_t len; /* length of header block */
1042 + portblock_t pbtype; /* Type of port block that was requested */
1043 + u_int16_t loport; /* Port that was requested, low or first */
1044 + u_int16_t hiport; /* Port that was requested, high or second */
1046 + uint method; /* RTSP method */
1047 + uint cseq; /* CSeq from request */
1051 +/* This structure exists only once per master */
1052 +struct ip_ct_rtsp_master
1060 +#include <linux/netfilter_ipv4/lockhelp.h>
1062 +#define RTSP_PORT 554
1064 +/* Protects rtsp part of conntracks */
1065 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
1067 +#endif /* __KERNEL__ */
1069 +#endif /* _IP_CONNTRACK_RTSP_H */
1070 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_talk.h
1071 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
1072 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2003-12-11 10:24:09.248410616 +0100
1074 +#ifndef _IP_CONNTRACK_TALK_H
1075 +#define _IP_CONNTRACK_TALK_H
1076 +/* TALK tracking. */
1079 +#include <linux/in.h>
1080 +#include <linux/netfilter_ipv4/lockhelp.h>
1082 +/* Protects talk part of conntracks */
1083 +DECLARE_LOCK_EXTERN(ip_talk_lock);
1087 +#define TALK_PORT 517
1088 +#define NTALK_PORT 518
1090 +/* talk structures and constants from <protocols/talkd.h> */
1093 + * 4.3BSD struct sockaddr
1096 + u_int16_t ta_family;
1097 + u_int16_t ta_port;
1098 + u_int32_t ta_addr;
1099 + u_int32_t ta_junk1;
1100 + u_int32_t ta_junk2;
1103 +#define TALK_OLD_NSIZE 9
1104 +#define TALK_NSIZE 12
1105 +#define TALK_TTY_NSIZE 16
1108 + * Client->server request message formats.
1111 + u_char type; /* request type, see below */
1112 + char l_name[TALK_OLD_NSIZE];/* caller's name */
1113 + char r_name[TALK_OLD_NSIZE];/* callee's name */
1115 + u_int32_t id_num; /* message id */
1116 + int32_t pid; /* caller's process id */
1117 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1118 + struct talk_addr addr; /* old (4.3) style */
1119 + struct talk_addr ctl_addr; /* old (4.3) style */
1123 + u_char vers; /* protocol version */
1124 + u_char type; /* request type, see below */
1125 + u_char answer; /* not used */
1127 + u_int32_t id_num; /* message id */
1128 + struct talk_addr addr; /* old (4.3) style */
1129 + struct talk_addr ctl_addr; /* old (4.3) style */
1130 + int32_t pid; /* caller's process id */
1131 + char l_name[TALK_NSIZE];/* caller's name */
1132 + char r_name[TALK_NSIZE];/* callee's name */
1133 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1136 +struct ntalk2_msg {
1137 + u_char vers; /* talk protocol version */
1138 + u_char type; /* request type */
1139 + u_char answer; /* */
1140 + u_char extended; /* !0 if additional parts */
1141 + u_int32_t id_num; /* message id number (dels) */
1142 + struct talk_addr addr; /* target address */
1143 + struct talk_addr ctl_addr; /* reply to address */
1144 + int32_t pid; /* caller's process id */
1145 + char l_name[TALK_NSIZE]; /* caller's name */
1146 + char r_name[TALK_NSIZE]; /* callee's name */
1147 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
1151 + * Server->client response message formats.
1153 +struct talk_response {
1154 + u_char type; /* type of request message, see below */
1155 + u_char answer; /* response to request message, see below */
1157 + u_int32_t id_num; /* message id */
1158 + struct talk_addr addr; /* address for establishing conversation */
1161 +struct ntalk_response {
1162 + u_char vers; /* protocol version */
1163 + u_char type; /* type of request message, see below */
1164 + u_char answer; /* response to request message, see below */
1166 + u_int32_t id_num; /* message id */
1167 + struct talk_addr addr; /* address for establishing conversation */
1170 +struct ntalk2_response {
1171 + u_char vers; /* protocol version */
1172 + u_char type; /* type of request message */
1173 + u_char answer; /* response to request */
1174 + u_char rvers; /* Version of answering vers*/
1175 + u_int32_t id_num; /* message id number */
1176 + struct talk_addr addr; /* address for connection */
1177 + /* This is at the end to compatiblize this with NTALK version. */
1178 + char r_name[TALK_NSIZE]; /* callee's name */
1181 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
1182 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
1183 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
1185 +#define TALK_VERSION 0 /* protocol versions */
1186 +#define NTALK_VERSION 1
1187 +#define NTALK2_VERSION 2
1189 +/* message type values */
1190 +#define LEAVE_INVITE 0 /* leave invitation with server */
1191 +#define LOOK_UP 1 /* check for invitation by callee */
1192 +#define DELETE 2 /* delete invitation by caller */
1193 +#define ANNOUNCE 3 /* announce invitation by caller */
1195 +#define REPLY_QUERY 4 /* request reply data from local daemon */
1197 +/* answer values */
1198 +#define SUCCESS 0 /* operation completed properly */
1199 +#define NOT_HERE 1 /* callee not logged in */
1200 +#define FAILED 2 /* operation failed for unexplained reason */
1201 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
1202 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
1203 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
1204 +#define BADVERSION 6 /* request has invalid protocol version */
1205 +#define BADADDR 7 /* request has invalid addr value */
1206 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
1208 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
1209 +#define TRY_HERE 10 /* Not on this machine, try this */
1210 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
1211 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
1213 +/* We don't really need much for talk */
1214 +struct ip_ct_talk_expect
1216 + /* Port that was to be used */
1220 +/* This structure exists only once per master */
1221 +struct ip_ct_talk_master
1225 +#endif /* _IP_CONNTRACK_TALK_H */
1226 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
1227 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-11-26 21:44:58.000000000 +0100
1228 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-12-11 10:23:59.480895504 +0100
1230 union ip_conntrack_manip_proto
1232 /* Add other protocols here. */
1247 /* The manipulable part of the tuple. */
1251 /* Add other protocols here. */
1259 u_int8_t type, code;
1262 + u_int16_t protocol;
1272 #define DUMP_TUPLE(tp) \
1273 -DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
1274 +DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", \
1275 (tp), (tp)->dst.protonum, \
1276 - NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \
1277 - NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
1278 + NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all), \
1279 + NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
1281 +#define DUMP_TUPLE_RAW(x) \
1282 + DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
1283 + (x), (x)->dst.protonum, \
1284 + NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), \
1285 + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
1287 #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
1289 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_nat_pptp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_nat_pptp.h
1290 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_nat_pptp.h 1970-01-01 01:00:00.000000000 +0100
1291 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_nat_pptp.h 2003-11-17 09:09:34.000000000 +0100
1293 +/* PPTP constants and structs */
1294 +#ifndef _NAT_PPTP_H
1295 +#define _NAT_PPTP_H
1297 +/* conntrack private data */
1298 +struct ip_nat_pptp {
1299 + u_int16_t pns_call_id; /* NAT'ed PNS call id */
1300 + u_int16_t pac_call_id; /* NAT'ed PAC call id */
1303 +#endif /* _NAT_PPTP_H */
1304 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_pool.h
1305 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
1306 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_pool.h 2003-12-11 10:23:32.943929736 +0100
1311 +/***************************************************************************/
1312 +/* This program is free software; you can redistribute it and/or modify */
1313 +/* it under the terms of the GNU General Public License as published by */
1314 +/* the Free Software Foundation; either version 2 of the License, or */
1315 +/* (at your option) any later version. */
1317 +/* This program is distributed in the hope that it will be useful, */
1318 +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
1319 +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
1320 +/* GNU General Public License for more details. */
1322 +/* You should have received a copy of the GNU General Public License */
1323 +/* along with this program; if not, write to the Free Software */
1324 +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
1325 +/***************************************************************************/
1327 +/* A sockopt of such quality has hardly ever been seen before on the open
1328 + * market! This little beauty, hardly ever used: above 64, so it's
1329 + * traditionally used for firewalling, not touched (even once!) by the
1330 + * 2.0, 2.2 and 2.4 kernels!
1332 + * Comes with its own certificate of authenticity, valid anywhere in the
1335 + * Rusty, 19.4.2000
1337 +#define SO_IP_POOL 81
1339 +typedef int ip_pool_t; /* pool index */
1340 +#define IP_POOL_NONE ((ip_pool_t)-1)
1342 +struct ip_pool_request {
1349 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
1351 +#define IP_POOL_BAD001 0x00000010
1353 +#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
1354 +#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
1355 +#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
1356 +#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
1357 +#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
1358 +#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
1359 +#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
1360 +#define IP_POOL_USAGE 0x00000018 /* result in addr */
1361 +#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
1365 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
1366 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
1367 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
1371 +#endif /*_IP_POOL_H*/
1372 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_queue.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_queue.h
1373 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_queue.h 2003-11-26 21:45:32.000000000 +0100
1374 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_queue.h 2003-12-11 10:24:12.844863872 +0100
1376 unsigned char payload[0]; /* Optional replacement packet */
1377 } ipq_verdict_msg_t;
1379 +typedef struct ipq_vwmark_msg {
1380 + unsigned int value; /* Verdict to hand to netfilter */
1381 + unsigned long id; /* Packet ID for this verdict */
1382 + size_t data_len; /* Length of replacement data */
1383 + unsigned char payload[0]; /* Optional replacement packet */
1384 + unsigned long nfmark; /* Mark for the Packet */
1385 +} ipq_vwmark_msg_t;
1388 typedef struct ipq_peer_msg {
1390 ipq_verdict_msg_t verdict;
1391 ipq_mode_msg_t mode;
1392 + ipq_vwmark_msg_t vwmark;
1397 #define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */
1398 #define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */
1399 #define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */
1400 -#define IPQM_MAX (IPQM_BASE + 4)
1401 +#define IPQM_VWMARK (IPQM_BASE + 4) /* Verdict and mark from peer */
1402 +#define IPQM_MAX (IPQM_BASE + 5)
1404 #endif /*_IP_QUEUE_H*/
1405 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_tables.h
1406 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_tables.h 2003-11-26 21:44:17.000000000 +0100
1407 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_tables.h 2003-12-11 10:23:17.222319784 +0100
1408 @@ -134,6 +134,12 @@
1410 unsigned int comefrom;
1412 + /* Name of the chain */
1415 + /* Rule number in the chain. */
1416 + u_int32_t rulenum;
1418 /* Packet and byte counters. */
1419 struct ipt_counters counters;
1421 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_addrtype.h
1422 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
1423 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_addrtype.h 2003-12-11 10:23:44.236213048 +0100
1425 +#ifndef _IPT_ADDRTYPE_H
1426 +#define _IPT_ADDRTYPE_H
1428 +struct ipt_addrtype_info {
1429 + u_int16_t source; /* source-type mask */
1430 + u_int16_t dest; /* dest-type mask */
1431 + int invert_source;
1436 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_condition.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_condition.h
1437 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_condition.h 1970-01-01 01:00:00.000000000 +0100
1438 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_condition.h 2003-12-11 10:23:46.621850376 +0100
1440 +#ifndef __IPT_CONDITION_MATCH__
1441 +#define __IPT_CONDITION_MATCH__
1443 +#define CONDITION_NAME_LEN 32
1445 +struct condition_info {
1446 + char name[CONDITION_NAME_LEN];
1451 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connlimit.h
1452 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
1453 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connlimit.h 2003-12-11 10:23:19.417985992 +0100
1455 +#ifndef _IPT_CONNLIMIT_H
1456 +#define _IPT_CONNLIMIT_H
1458 +struct ipt_connlimit_data;
1460 +struct ipt_connlimit_info {
1464 + struct ipt_connlimit_data *data;
1466 +#endif /* _IPT_CONNLIMIT_H */
1467 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connmark.h
1468 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
1469 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connmark.h 2003-12-11 10:23:47.827667064 +0100
1471 +#ifndef _IPT_CONNMARK_H
1472 +#define _IPT_CONNMARK_H
1474 +struct ipt_connmark_info {
1475 + unsigned long mark, mask;
1479 +#endif /*_IPT_CONNMARK_H*/
1480 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_CONNMARK.h
1481 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
1482 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2003-12-11 10:23:47.828666912 +0100
1484 +#ifndef _IPT_CONNMARK_H_target
1485 +#define _IPT_CONNMARK_H_target
1488 + IPT_CONNMARK_SET = 0,
1489 + IPT_CONNMARK_SAVE,
1490 + IPT_CONNMARK_RESTORE
1493 +struct ipt_connmark_target_info {
1494 + unsigned long mark;
1498 +#endif /*_IPT_CONNMARK_H_target*/
1499 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_conntrack.h
1500 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-11-26 21:45:07.000000000 +0100
1501 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-12-11 10:23:17.222319784 +0100
1504 #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
1505 #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
1506 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
1508 /* flags, invflags: */
1509 #define IPT_CONNTRACK_STATE 0x01
1510 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_dstlimit.h
1511 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
1512 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_dstlimit.h 2003-12-11 10:23:20.526817424 +0100
1514 +#ifndef _IPT_DSTLIMIT_H
1515 +#define _IPT_DSTLIMIT_H
1517 +/* timings are in milliseconds. */
1518 +#define IPT_DSTLIMIT_SCALE 10000
1519 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
1520 + seconds, or one every 59 hours. */
1522 +/* details of this structure hidden by the implementation */
1523 +struct ipt_dstlimit_htable;
1525 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
1526 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
1527 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
1529 +struct ipt_dstlimit_info {
1530 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1531 + u_int32_t avg; /* Average secs between packets * scale */
1532 + u_int32_t burst; /* Period multiplier for upper limit. */
1534 + /* user specified */
1535 + unsigned int size; /* how many buckets */
1536 + unsigned int max; /* max number of entries */
1537 + unsigned int gc_interval; /* gc interval */
1538 + unsigned int expire; /* when do entries expire? */
1539 + char name [IFNAMSIZ]; /* name */
1541 + struct ipt_dstlimit_htable *hinfo;
1543 + /* Used internally by the kernel */
1546 + struct ipt_dstlimit_info *master;
1549 +#endif /*_IPT_DSTLIMIT_H*/
1550 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_fuzzy.h
1551 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1552 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_fuzzy.h 2003-12-11 10:23:22.734481808 +0100
1554 +#ifndef _IPT_FUZZY_H
1555 +#define _IPT_FUZZY_H
1557 +#include <linux/param.h>
1558 +#include <linux/types.h>
1560 +#define MAXFUZZYRATE 10000000
1561 +#define MINFUZZYRATE 3
1563 +struct ipt_fuzzy_info {
1564 + u_int32_t minimum_rate;
1565 + u_int32_t maximum_rate;
1566 + u_int32_t packets_total;
1567 + u_int32_t bytes_total;
1568 + u_int32_t previous_time;
1569 + u_int32_t present_time;
1570 + u_int32_t mean_rate;
1571 + u_int8_t acceptance_rate;
1574 +#endif /*_IPT_FUZZY_H*/
1575 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_IPMARK.h
1576 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
1577 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_IPMARK.h 2003-12-11 10:23:52.557947952 +0100
1579 +#ifndef _IPT_IPMARK_H_target
1580 +#define _IPT_IPMARK_H_target
1582 +struct ipt_ipmark_target_info {
1583 + unsigned long andmask;
1584 + unsigned long ormask;
1585 + unsigned int addr;
1588 +#define IPT_IPMARK_SRC 0
1589 +#define IPT_IPMARK_DST 1
1591 +#endif /*_IPT_IPMARK_H_target*/
1592 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipv4options.h
1593 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1594 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipv4options.h 2003-12-11 10:23:25.055129016 +0100
1596 +#ifndef __ipt_ipv4options_h_included__
1597 +#define __ipt_ipv4options_h_included__
1599 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1600 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1601 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1602 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1603 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1604 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1605 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1606 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1607 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1608 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1609 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1611 +struct ipt_ipv4options_info {
1612 + u_int16_t options;
1616 +#endif /* __ipt_ipv4options_h_included__ */
1617 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mark.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mark.h
1618 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mark.h 2003-11-26 21:45:46.000000000 +0100
1619 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mark.h 2003-12-11 10:24:14.940545280 +0100
1625 + IPT_MARK_BIT_OP_NONE,
1626 + IPT_MARK_BIT_OP_AND,
1627 + IPT_MARK_BIT_OP_OR
1630 struct ipt_mark_info {
1631 unsigned long mark, mask;
1636 #endif /*_IPT_MARK_H*/
1637 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mport.h
1638 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1639 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mport.h 2003-12-11 10:23:27.304787016 +0100
1641 +#ifndef _IPT_MPORT_H
1642 +#define _IPT_MPORT_H
1643 +#include <linux/netfilter_ipv4/ip_tables.h>
1645 +#define IPT_MPORT_SOURCE (1<<0)
1646 +#define IPT_MPORT_DESTINATION (1<<1)
1647 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1649 +#define IPT_MULTI_PORTS 15
1651 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1652 +/* every entry in ports[] except for the last one has one bit in pflags
1653 + * associated with it. If this bit is set, the port is the first port of
1654 + * a portrange, with the next entry being the last.
1655 + * End of list is marked with pflags bit set and port=65535.
1656 + * If 14 ports are used (last one does not have a pflag), the last port
1657 + * is repeated to fill the last entry in ports[] */
1660 + u_int8_t flags:2; /* Type of comparison */
1661 + u_int16_t pflags:14; /* Port flags */
1662 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1664 +#endif /*_IPT_MPORT_H*/
1665 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_NETLINK.h
1666 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
1667 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_NETLINK.h 2003-12-11 10:23:28.409619056 +0100
1669 +#ifndef _IPT_FWMON_H
1670 +#define _IPT_FWMON_H
1672 +/* Bitmask macros */
1673 +#define MASK(x,y) (x & y)
1674 +#define MASK_SET(x,y) x |= y
1675 +#define MASK_UNSET(x,y) x &= ~y
1677 +#define USE_MARK 0x00000001
1678 +#define USE_DROP 0x00000002
1679 +#define USE_SIZE 0x00000004
1683 + unsigned int flags;
1684 + unsigned int mark;
1685 + unsigned int size;
1691 + unsigned int mark;
1692 + char iface[IFNAMSIZ];
1695 +#endif /*_IPT_FWMON_H*/
1696 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_nth.h
1697 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1698 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_nth.h 2003-12-11 10:23:30.639280096 +0100
1703 +#include <linux/param.h>
1704 +#include <linux/types.h>
1706 +#ifndef IPT_NTH_NUM_COUNTERS
1707 +#define IPT_NTH_NUM_COUNTERS 16
1710 +struct ipt_nth_info {
1718 +#endif /*_IPT_NTH_H*/
1719 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_osf.h
1720 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1721 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_osf.h 2003-12-11 10:23:31.785105904 +0100
1726 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1729 + * This program is free software; you can redistribute it and/or modify
1730 + * it under the terms of the GNU General Public License as published by
1731 + * the Free Software Foundation; either version 2 of the License, or
1732 + * (at your option) any later version.
1734 + * This program is distributed in the hope that it will be useful,
1735 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1736 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1737 + * GNU General Public License for more details.
1739 + * You should have received a copy of the GNU General Public License
1740 + * along with this program; if not, write to the Free Software
1741 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1747 +#define MAXGENRELEN 32
1748 +#define MAXDETLEN 64
1750 +#include <linux/list.h>
1752 +struct ipt_osf_info
1754 + char genre[MAXGENRELEN];
1756 + int invert; /* UNSUPPORTED */
1762 + unsigned long val;
1765 +/* This struct represents IANA options
1766 + * http://www.iana.org/assignments/tcp-parameters
1770 + unsigned char kind;
1771 + unsigned char length;
1779 + struct list_head flist;
1780 + struct osf_wc wss;
1781 + unsigned char ttl;
1784 + char genre[MAXGENRELEN];
1785 + char version[MAXGENRELEN], subtype[MAXGENRELEN];
1787 + /* Not needed, but for consistency with original table from Michal Zalewski */
1788 + char details[MAXDETLEN];
1791 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1795 +/* Defines for IANA option kinds */
1797 +#define OSFOPT_EOL 0 /* End of options */
1798 +#define OSFOPT_NOP 1 /* NOP */
1799 +#define OSFOPT_MSS 2 /* Maximum segment size */
1800 +#define OSFOPT_WSO 3 /* Window scale option */
1801 +#define OSFOPT_SACKP 4 /* SACK permitted */
1802 +#define OSFOPT_SACK 5 /* SACK */
1803 +#define OSFOPT_ECHO 6
1804 +#define OSFOPT_ECHOREPLY 7
1805 +#define OSFOPT_TS 8 /* Timestamp option */
1806 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1807 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1808 +/* Others are not used in current OSF */
1810 +static struct osf_opt IANA_opts[] =
1817 + {5, 1 ,}, /* SACK length is not defined */
1823 + {11, 1,}, /* CC: Suppose 1 */
1824 + {12, 1,}, /* the same */
1825 + {13, 1,}, /* and here too */
1827 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1841 +#endif /* __KERNEL__ */
1843 +#endif /* _IPT_OSF_H */
1844 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_pool.h
1845 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1846 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_pool.h 2003-12-11 10:23:32.943929736 +0100
1848 +#ifndef _IPT_POOL_H
1849 +#define _IPT_POOL_H
1851 +#include <linux/netfilter_ipv4/ip_pool.h>
1853 +#define IPT_POOL_INV_SRC 0x00000001
1854 +#define IPT_POOL_INV_DST 0x00000002
1855 +#define IPT_POOL_DEL_SRC 0x00000004
1856 +#define IPT_POOL_DEL_DST 0x00000008
1857 +#define IPT_POOL_INV_MOD_SRC 0x00000010
1858 +#define IPT_POOL_INV_MOD_DST 0x00000020
1859 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1860 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1861 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
1862 +#define IPT_POOL_MOD_DST_DROP 0x00000200
1865 +struct ipt_pool_info
1872 +#endif /*_IPT_POOL_H*/
1873 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_psd.h
1874 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1875 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_psd.h 2003-12-11 10:23:34.085756152 +0100
1880 +#include <linux/param.h>
1881 +#include <linux/types.h>
1884 + * High port numbers have a lower weight to reduce the frequency of false
1885 + * positives, such as from passive mode FTP transfers.
1887 +#define PORT_WEIGHT_PRIV 3
1888 +#define PORT_WEIGHT_HIGH 1
1891 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1892 + * from the same source, with no longer than DELAY ticks between ports.
1894 +#define SCAN_MIN_COUNT 7
1895 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1896 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1897 +#define SCAN_DELAY_THRESHOLD (HZ * 3)
1900 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1901 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1902 + * HASH_MAX source addresses per the same hash value.
1904 +#define LIST_SIZE 0x100
1906 +#define HASH_SIZE (1 << HASH_LOG)
1907 +#define HASH_MAX 0x10
1909 +struct ipt_psd_info {
1910 + unsigned int weight_threshold;
1911 + unsigned int delay_threshold;
1912 + unsigned short lo_ports_weight;
1913 + unsigned short hi_ports_weight;
1916 +#endif /*_IPT_PSD_H*/
1917 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_quota.h
1918 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1919 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_quota.h 2003-12-11 10:23:35.183589256 +0100
1921 +#ifndef _IPT_QUOTA_H
1922 +#define _IPT_QUOTA_H
1924 +/* print debug info in both kernel/netfilter module & iptable library */
1925 +//#define DEBUG_IPT_QUOTA
1927 +struct ipt_quota_info {
1931 +#endif /*_IPT_QUOTA_H*/
1932 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_random.h
1933 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1934 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_random.h 2003-12-11 10:23:37.415249992 +0100
1936 +#ifndef _IPT_RAND_H
1937 +#define _IPT_RAND_H
1939 +#include <linux/param.h>
1940 +#include <linux/types.h>
1942 +struct ipt_rand_info {
1946 +#endif /*_IPT_RAND_H*/
1947 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_realm.h
1948 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1949 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_realm.h 2003-12-11 10:23:38.552077168 +0100
1951 +#ifndef _IPT_REALM_H
1952 +#define _IPT_REALM_H
1954 +struct ipt_realm_info {
1959 +#endif /*_IPT_REALM_H*/
1960 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_REJECT.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_REJECT.h
1961 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_REJECT.h 2003-11-26 21:45:21.000000000 +0100
1962 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_REJECT.h 2003-12-11 10:24:13.907702296 +0100
1965 struct ipt_reject_info {
1966 enum ipt_reject_with with; /* reject type */
1967 + u_int8_t fake_source_address; /* 1: fake src addr with original packet dest, 0: no fake */
1970 -#endif /*_IPT_REJECT_H*/
1971 +#endif /* _IPT_REJECT_H */
1972 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ROUTE.h
1973 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
1974 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ROUTE.h 2003-12-11 10:24:02.013510488 +0100
1976 +/* Header file for iptables ipt_ROUTE target
1978 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
1980 + * This software is distributed under GNU GPL v2, 1991
1982 +#ifndef _IPT_ROUTE_H_target
1983 +#define _IPT_ROUTE_H_target
1985 +#define IPT_ROUTE_IFNAMSIZ 16
1987 +struct ipt_route_target_info {
1988 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
1989 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
1990 + u_int32_t gw; /* IP address of gateway */
1994 +/* Values for "flags" field */
1995 +#define IPT_ROUTE_CONTINUE 0x01
1997 +#endif /*_IPT_ROUTE_H_target*/
1998 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_rpc.h
1999 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
2000 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_rpc.h 2003-12-11 10:24:04.354154656 +0100
2002 +/* RPC extension for IP netfilter matching, Version 2.2
2003 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2004 + * - original rpc tracking module
2005 + * - "recent" connection handling for kernel 2.3+ netfilter
2007 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2008 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2010 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2011 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
2012 + * - extended matching to support filtering on procedures
2014 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
2016 + * This program is free software; you can redistribute it and/or
2017 + * modify it under the terms of the GNU General Public License
2018 + * as published by the Free Software Foundation; either version
2019 + * 2 of the License, or (at your option) any later version.
2026 +struct ipt_rpc_data;
2028 +struct ipt_rpc_info {
2031 + const char c_procs[1408];
2033 + struct ipt_rpc_data *data;
2036 +#endif /* _IPT_RPC_H */
2037 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_sctp.h
2038 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
2039 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_sctp.h 2003-12-11 10:23:18.302155624 +0100
2041 +/* iptables module for matching the SCTP header
2043 + * (C) 2003 Harald Welte <laforge@gnumonks.org>
2045 + * This software is distributed under GNU GPL v2, 1991
2049 +#ifndef _IPT_SCTP_H
2050 +#define _IPT_SCTP_H
2052 +struct ipt_sctp_info {
2053 + u_int16_t spts[2]; /* Souce port range */
2054 + u_int16_t dpts[2]; /* Destination port range */
2055 + u_int32_t chunks; /* chunks to be matched */
2056 + u_int32_t chunk_mask; /* chunk mask to be matched */
2057 + u_int8_t invflags; /* Inverse flags */
2060 +#define IPT_SCTP_INV_SRCPT 0x01 /* Invert the sense of source ports */
2061 +#define IPT_SCTP_INV_DSTPT 0x02 /* Invert the sense of dest ports */
2062 +#define IPT_SCTP_INV_CHUNKS 0x03 /* Invert the sense of chunks */
2063 +#define IPT_SCTP_INV_MASK 0x03 /* All possible flags */
2065 +#endif /* _IPT_SCTP_H */
2066 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_state.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_state.h
2067 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_state.h 2003-11-26 21:45:27.000000000 +0100
2068 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_state.h 2003-12-11 10:23:17.223319632 +0100
2070 #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
2071 #define IPT_STATE_INVALID (1 << 0)
2073 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
2075 struct ipt_state_info
2077 unsigned int statemask;
2078 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_string.h
2079 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
2080 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_string.h 2003-12-11 10:24:08.051592560 +0100
2082 +#ifndef _IPT_STRING_H
2083 +#define _IPT_STRING_H
2085 +/* *** PERFORMANCE TWEAK ***
2086 + * Packet size and search string threshold,
2087 + * above which sublinear searches is used. */
2088 +#define IPT_STRING_HAYSTACK_THRESH 100
2089 +#define IPT_STRING_NEEDLE_THRESH 20
2091 +#define BM_MAX_NLEN 256
2092 +#define BM_MAX_HLEN 1024
2094 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
2096 +struct ipt_string_info {
2097 + char string[BM_MAX_NLEN];
2102 +#endif /* _IPT_STRING_H */
2103 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TCPLAG.h
2104 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h 1970-01-01 01:00:00.000000000 +0100
2105 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TCPLAG.h 2003-12-11 10:24:10.437229888 +0100
2107 +#ifndef _IPT_TCPLAG_H
2108 +#define _IPT_TCPLAG_H
2112 + unsigned char level;
2113 + unsigned char prefix[ 15 ];
2117 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_time.h
2118 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
2119 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_time.h 2003-12-11 10:23:40.871724528 +0100
2121 +#ifndef __ipt_time_h_included__
2122 +#define __ipt_time_h_included__
2125 +struct ipt_time_info {
2126 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
2127 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
2128 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
2129 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
2133 +#endif /* __ipt_time_h_included__ */
2134 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TTL.h
2135 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
2136 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TTL.h 2003-12-11 10:23:41.987554896 +0100
2138 +/* TTL modification module for IP tables
2139 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
2150 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
2152 +struct ipt_TTL_info {
2159 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_u32.h
2160 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
2161 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_u32.h 2003-12-11 10:23:43.131381008 +0100
2165 +#include <linux/netfilter_ipv4/ip_tables.h>
2175 +struct ipt_u32_location_element
2180 +struct ipt_u32_value_element
2185 +/* *** any way to allow for an arbitrary number of elements?
2186 + for now I settle for a limit of 10 of each */
2187 +#define U32MAXSIZE 10
2188 +struct ipt_u32_test
2191 + struct ipt_u32_location_element location[U32MAXSIZE+1];
2193 + struct ipt_u32_value_element value[U32MAXSIZE+1];
2199 + struct ipt_u32_test tests[U32MAXSIZE+1];
2202 +#endif /*_IPT_U32_H*/
2203 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ULOG.h
2204 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ULOG.h 2003-11-26 21:43:39.000000000 +0100
2205 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ULOG.h 2003-12-11 10:23:14.921669536 +0100
2207 #define NETLINK_NFLOG 5
2210 +#define NFLOG_DEFAULT_NLGROUP 1
2211 +#define NFLOG_DEFAULT_QTHRESHOLD 1
2213 #define ULOG_MAC_LEN 80
2214 #define ULOG_PREFIX_LEN 32
2216 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_XOR.h
2217 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
2218 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_XOR.h 2003-12-11 10:24:11.736032440 +0100
2223 +struct ipt_XOR_info {
2225 + u_int8_t block_size;
2228 +#endif /* _IPT_XOR_H */
2229 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h linux-2.6.0-test11/include/linux/netfilter_ipv4.h
2230 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h 2003-11-26 21:45:25.000000000 +0100
2231 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4.h 2003-12-11 10:23:17.223319632 +0100
2234 enum nf_ip_hook_priorities {
2235 NF_IP_PRI_FIRST = INT_MIN,
2236 + NF_IP_PRI_CONNTRACK_DEFRAG = -400,
2237 + NF_IP_PRI_RAW = -300,
2238 NF_IP_PRI_CONNTRACK = -200,
2239 NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
2240 NF_IP_PRI_MANGLE = -150,
2241 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6_tables.h
2242 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6_tables.h 2003-11-26 21:45:41.000000000 +0100
2243 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6_tables.h 2003-12-11 10:23:17.223319632 +0100
2244 @@ -140,6 +140,12 @@
2246 unsigned int comefrom;
2248 + /* Name of the chain */
2251 + /* Rule number in the chain. */
2252 + u_int32_t rulenum;
2254 /* Packet and byte counters. */
2255 struct ip6t_counters counters;
2257 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_condition.h
2258 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_condition.h 1970-01-01 01:00:00.000000000 +0100
2259 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_condition.h 2003-12-11 10:23:45.446029128 +0100
2261 +#ifndef __IP6T_CONDITION_MATCH__
2262 +#define __IP6T_CONDITION_MATCH__
2264 +#define CONDITION6_NAME_LEN 32
2266 +struct condition6_info {
2267 + char name[CONDITION6_NAME_LEN];
2272 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_fuzzy.h
2273 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
2274 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2003-12-11 10:23:21.621650984 +0100
2276 +#ifndef _IP6T_FUZZY_H
2277 +#define _IP6T_FUZZY_H
2279 +#include <linux/param.h>
2280 +#include <linux/types.h>
2282 +#define MAXFUZZYRATE 10000000
2283 +#define MINFUZZYRATE 3
2285 +struct ip6t_fuzzy_info {
2286 + u_int32_t minimum_rate;
2287 + u_int32_t maximum_rate;
2288 + u_int32_t packets_total;
2289 + u_int32_t bytes_total;
2290 + u_int32_t previous_time;
2291 + u_int32_t present_time;
2292 + u_int32_t mean_rate;
2293 + u_int8_t acceptance_rate;
2296 +#endif /*_IP6T_FUZZY_H*/
2297 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_HL.h
2298 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
2299 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_HL.h 2003-12-11 10:23:23.851312024 +0100
2301 +/* Hop Limit modification module for ip6tables
2302 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
2303 + * Based on HW's TTL module */
2314 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
2316 +struct ip6t_HL_info {
2318 + u_int8_t hop_limit;
2323 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_nth.h
2324 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
2325 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_nth.h 2003-12-11 10:23:29.532448360 +0100
2327 +#ifndef _IP6T_NTH_H
2328 +#define _IP6T_NTH_H
2330 +#include <linux/param.h>
2331 +#include <linux/types.h>
2333 +#ifndef IP6T_NTH_NUM_COUNTERS
2334 +#define IP6T_NTH_NUM_COUNTERS 16
2337 +struct ip6t_nth_info {
2345 +#endif /*_IP6T_NTH_H*/
2346 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_owner.h
2347 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_owner.h 2003-11-26 21:44:32.000000000 +0100
2348 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_owner.h 2003-12-11 10:23:58.199090368 +0100
2350 #define IP6T_OWNER_GID 0x02
2351 #define IP6T_OWNER_PID 0x04
2352 #define IP6T_OWNER_SID 0x08
2353 +#define IP6T_OWNER_COMM 0x10
2355 struct ip6t_owner_info {
2361 u_int8_t match, invert; /* flags */
2364 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_random.h
2365 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
2366 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_random.h 2003-12-11 10:23:36.320416432 +0100
2368 +#ifndef _IP6T_RAND_H
2369 +#define _IP6T_RAND_H
2371 +#include <linux/param.h>
2372 +#include <linux/types.h>
2374 +struct ip6t_rand_info {
2378 +#endif /*_IP6T_RAND_H*/
2379 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_REJECT.h
2380 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2003-11-26 21:42:47.000000000 +0100
2381 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_REJECT.h 2003-12-11 10:23:39.702902216 +0100
2383 #define _IP6T_REJECT_H
2385 enum ip6t_reject_with {
2386 - IP6T_ICMP_NET_UNREACHABLE,
2387 - IP6T_ICMP_HOST_UNREACHABLE,
2388 - IP6T_ICMP_PROT_UNREACHABLE,
2389 - IP6T_ICMP_PORT_UNREACHABLE,
2390 - IP6T_ICMP_ECHOREPLY
2391 + IP6T_ICMP6_NO_ROUTE,
2392 + IP6T_ICMP6_ADM_PROHIBITED,
2393 + IP6T_ICMP6_NOT_NEIGHBOUR,
2394 + IP6T_ICMP6_ADDR_UNREACH,
2395 + IP6T_ICMP6_PORT_UNREACH,
2396 + IP6T_ICMP6_ECHOREPLY,
2400 struct ip6t_reject_info {
2401 enum ip6t_reject_with with; /* reject type */
2404 -#endif /*_IPT_REJECT_H*/
2405 +#endif /*_IP6T_REJECT_H*/
2406 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_ROUTE.h
2407 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
2408 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2003-12-11 10:24:03.166335232 +0100
2410 +/* Header file for iptables ip6t_ROUTE target
2412 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
2414 + * This software is distributed under GNU GPL v2, 1991
2416 +#ifndef _IPT_ROUTE_H_target
2417 +#define _IPT_ROUTE_H_target
2419 +#define IP6T_ROUTE_IFNAMSIZ 16
2421 +struct ip6t_route_target_info {
2422 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
2423 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
2424 + u_int32_t gw[4]; /* IPv6 address of gateway */
2428 +/* Values for "flags" field */
2429 +#define IP6T_ROUTE_CONTINUE 0x01
2431 +#endif /*_IP6T_ROUTE_H_target*/
2432 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_mime.h linux-2.6.0-test11/include/linux/netfilter_mime.h
2433 --- linux-2.6.0-test11.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
2434 +++ linux-2.6.0-test11/include/linux/netfilter_mime.h 2003-12-11 10:24:06.855774352 +0100
2437 + * MIME functions for netfilter modules. This file provides implementations
2438 + * for basic MIME parsing. MIME headers are used in many protocols, such as
2439 + * HTTP, RTSP, SIP, etc.
2441 + * gcc will warn for defined but unused functions, so we only include the
2442 + * functions requested. The following macros are used:
2443 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
2445 +#ifndef _NETFILTER_MIME_H
2446 +#define _NETFILTER_MIME_H
2448 +/* Only include these functions for kernel code. */
2451 +#include <linux/ctype.h>
2454 + * Given a buffer and length, advance to the next line and mark the current
2455 + * line. If the current line is empty, *plinelen will be set to zero. If
2456 + * not, it will be set to the actual line length (including CRLF).
2458 + * 'line' in this context means logical line (includes LWS continuations).
2459 + * Returns 1 on success, 0 on failure.
2461 +#ifdef NF_NEED_MIME_NEXTLINE
2463 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2467 + int is_first_line = 1;
2476 + while (p[off] != '\n')
2487 + /* if we saw a crlf, physlen needs adjusted */
2488 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2493 + /* advance past the newline */
2496 + /* check for an empty line */
2502 + /* check for colon on the first physical line */
2503 + if (is_first_line)
2505 + is_first_line = 0;
2506 + if (memchr(p+(*poff), ':', physlen) == NULL)
2512 + while (p[off] == ' ' || p[off] == '\t');
2514 + *plineoff = *poff;
2515 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
2520 +#endif /* NF_NEED_MIME_NEXTLINE */
2522 +#endif /* __KERNEL__ */
2524 +#endif /* _NETFILTER_MIME_H */
2525 diff -Nur linux-2.6.0-test11.org/include/linux/smp.h linux-2.6.0-test11/include/linux/smp.h
2526 --- linux-2.6.0-test11.org/include/linux/smp.h 2003-11-26 21:44:20.000000000 +0100
2527 +++ linux-2.6.0-test11/include/linux/smp.h 2003-12-11 11:43:37.505525352 +0100
2530 extern int smp_threads_ready;
2532 +extern int smp_num_cpus;
2534 #define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
2535 #define MSG_ALL 0x8001
2537 diff -Nur linux-2.6.0-test11.org/net/core/netfilter.c linux-2.6.0-test11/net/core/netfilter.c
2538 --- linux-2.6.0-test11.org/net/core/netfilter.c 2003-11-26 21:43:56.000000000 +0100
2539 +++ linux-2.6.0-test11/net/core/netfilter.c 2003-12-11 10:23:57.175246016 +0100
2542 * February 2000: Modified by James Morris to have 1 queue per protocol.
2543 * 15-Mar-2000: Added NF_REPEAT --RR.
2544 + * 08-May-2003: Internal logging interface added by Jozsef Kadlecsik.
2546 #include <linux/config.h>
2547 +#include <linux/kernel.h>
2548 #include <linux/netfilter.h>
2549 #include <net/protocol.h>
2550 #include <linux/init.h>
2552 } queue_handler[NPROTO];
2553 static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
2556 + * nf_register_hook - Register with a netfilter hook
2557 + * @reg: Hook operations to be registered
2559 int nf_register_hook(struct nf_hook_ops *reg)
2561 struct list_head *i;
2567 + * nf_unregister_hook - Unregister from a netfilter hook
2568 + * @reg: hook operations to be unregistered
2570 void nf_unregister_hook(struct nf_hook_ops *reg)
2572 spin_lock_bh(&nf_hook_lock);
2573 @@ -389,6 +399,18 @@
2578 + * nf_register_queue_handler - Registere a queue handler with netfilter
2579 + * @pf: protocol family
2580 + * @outfn: function called by core to enqueue a packet
2581 + * @data: opaque parameter, passed through
2583 + * This function registers a queue handler with netfilter. There can only
2584 + * be one queue handler for every protocol family.
2586 + * A queue handler _must_ reinject every packet via nf_reinject, no
2589 int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
2592 @@ -406,7 +428,12 @@
2596 -/* The caller must flush their queue before this */
2598 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
2599 + * @pf: protocol family
2601 + * The caller must flush their queue before unregistering
2603 int nf_unregister_queue_handler(int pf)
2605 write_lock_bh(&queue_handler_lock);
2606 @@ -549,6 +576,15 @@
2611 + * nf_reinject - Reinject a packet from a queue handler
2612 + * @skb: the packet to be reinjected
2613 + * @info: info which was passed to the outfn() of the queue handler
2614 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
2616 + * This is the function called by a queue handler to reinject a
2619 void nf_reinject(struct sk_buff *skb, struct nf_info *info,
2620 unsigned int verdict)
2622 @@ -743,7 +779,70 @@
2623 EXPORT_SYMBOL(skb_ip_make_writable);
2624 #endif /*CONFIG_INET*/
2626 +/* Internal logging interface, which relies on the real
2627 + LOG target modules */
2629 +#define NF_LOG_PREFIXLEN 128
2631 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
2632 +static int reported = 0;
2633 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
2635 +int nf_log_register(int pf, nf_logfn *logfn)
2639 + /* Any setup of logging members must be done before
2640 + * substituting pointer. */
2642 + spin_lock(&nf_log_lock);
2643 + if (!nf_logging[pf]) {
2644 + nf_logging[pf] = logfn;
2647 + spin_unlock(&nf_log_lock);
2651 +void nf_log_unregister(int pf, nf_logfn *logfn)
2653 + spin_lock(&nf_log_lock);
2654 + if (nf_logging[pf] == logfn)
2655 + nf_logging[pf] = NULL;
2656 + spin_unlock(&nf_log_lock);
2658 + /* Give time to concurrent readers. */
2659 + synchronize_net();
2662 +void nf_log_packet(int pf,
2663 + unsigned int hooknum,
2664 + const struct sk_buff *skb,
2665 + const struct net_device *in,
2666 + const struct net_device *out,
2667 + const char *fmt, ...)
2670 + char prefix[NF_LOG_PREFIXLEN];
2674 + logfn = nf_logging[pf];
2676 + va_start(args, fmt);
2677 + vsnprintf(prefix, sizeof(prefix), fmt, args);
2679 + /* We must read logging before nf_logfn[pf] */
2680 + smp_read_barrier_depends();
2681 + logfn(hooknum, skb, in, out, prefix);
2682 + } else if (!reported) {
2683 + printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
2684 + "no backend logging module loaded in!\n");
2687 + rcu_read_unlock();
2690 /* This does not belong here, but ipt_REJECT needs it if connection
2691 tracking in use: without this, connection may not be in hash table,
2692 and hence manufactured ICMP or RST packets will not be associated
2694 EXPORT_SYMBOL(ip_ct_attach);
2695 EXPORT_SYMBOL(ip_route_me_harder);
2696 EXPORT_SYMBOL(nf_getsockopt);
2697 +EXPORT_SYMBOL(nf_log_register);
2698 +EXPORT_SYMBOL(nf_log_unregister);
2699 +EXPORT_SYMBOL(nf_log_packet);
2700 EXPORT_SYMBOL(nf_hook_slow);
2701 EXPORT_SYMBOL(nf_hooks);
2702 EXPORT_SYMBOL(nf_register_hook);
2703 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_core.c
2704 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_core.c 2003-11-26 21:42:40.000000000 +0100
2705 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_core.c 2003-12-11 10:24:15.987386136 +0100
2708 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
2710 + * (C) 2000-2003 by the netfilter core team <coreteam@netfilter.org>
2712 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
2713 * - new API and handling of conntrack/nat helpers
2715 * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
2716 * - add usage/reference counts to ip_conntrack_expect
2717 * - export ip_conntrack[_expect]_{find_get,put} functions
2718 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
2719 + * - added DocBook-style comments for public API
2722 #include <linux/config.h>
2724 #include <linux/slab.h>
2725 #include <linux/random.h>
2726 #include <linux/jhash.h>
2727 -/* For ERR_PTR(). Yeah, I know... --RR */
2728 -#include <linux/fs.h>
2729 +#include <linux/err.h>
2731 /* This rwlock protects the main hash table, protocol/helper/expected
2732 registrations, conntrack timers*/
2734 static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
2735 struct list_head *ip_conntrack_hash;
2736 static kmem_cache_t *ip_conntrack_cachep;
2737 +struct ip_conntrack ip_conntrack_untracked;
2739 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
2746 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
2747 + * @protocol: protocol number
2749 struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
2751 struct ip_conntrack_protocol *p;
2753 inverse->dst.ip = orig->src.ip;
2754 inverse->dst.protonum = orig->dst.protonum;
2756 + inverse->src.u.all = inverse->dst.u.all = 0;
2758 return protocol->invert_tuple(inverse, orig);
2762 atomic_dec(&ip_conntrack_count);
2765 -static void death_by_timeout(unsigned long ul_conntrack)
2766 +void ip_ct_death_by_timeout(unsigned long ul_conntrack)
2768 struct ip_conntrack *ct = (void *)ul_conntrack;
2770 @@ -377,7 +386,14 @@
2774 -/* Find a connection corresponding to a tuple. */
2776 + * ip_conntrack_find_get - find conntrack according to tuple
2777 + * @tuple: conntrack tuple for which we search conntrack
2778 + * @ignored_conntrack: ignore this conntrack during search
2780 + * This function increments the reference count of the found
2781 + * conntrack (if any).
2783 struct ip_conntrack_tuple_hash *
2784 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
2785 const struct ip_conntrack *ignored_conntrack)
2786 @@ -405,7 +421,14 @@
2790 -/* Return conntrack and conntrack_info given skb->nfct->master */
2792 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
2793 + * @skb: skb for which we want to find conntrack and conntrack_info
2794 + * @ctinfo: pointer to ctinfo, used as return value
2796 + * This function resolves the respective conntrack and conntrack_info
2797 + * structures for the connection this packet (skb) is part of.
2799 struct ip_conntrack *
2800 ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
2802 @@ -475,8 +498,14 @@
2806 -/* Returns true if a connection correspondings to the tuple (required
2809 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
2810 + * @tuple: tuple to be used for this test
2811 + * @ignored_conntrack: conntrack which is excluded from result
2813 + * This function is called by the NAT code in order to find out if
2814 + * a particular tuple is already in use by some connection.
2817 ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
2818 const struct ip_conntrack *ignored_conntrack)
2822 if (del_timer(&h->ctrack->timeout)) {
2823 - death_by_timeout((unsigned long)h->ctrack);
2824 + ip_ct_death_by_timeout((unsigned long)h->ctrack);
2827 ip_conntrack_put(h->ctrack);
2828 @@ -602,7 +631,13 @@
2830 return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
2834 + * ip_ct_find_helper - Find application helper according to tuple
2835 + * @tuple: tuple for which helper needs to be found
2837 + * This function is used to determine if any registered conntrack helper
2838 + * is to be used for the given tuple.
2840 struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
2842 return LIST_FIND(&helpers, helper_cmp,
2844 /* Don't set timer yet: wait for confirmation */
2845 init_timer(&conntrack->timeout);
2846 conntrack->timeout.data = (unsigned long)conntrack;
2847 - conntrack->timeout.function = death_by_timeout;
2848 + conntrack->timeout.function = ip_ct_death_by_timeout;
2850 INIT_LIST_HEAD(&conntrack->sibling_list);
2853 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2854 conntrack->master = expected;
2855 expected->sibling = conntrack;
2856 +#if CONFIG_IP_NF_CONNTRACK_MARK
2857 + conntrack->mark = expected->expectant->mark;
2859 LIST_DELETE(&ip_conntrack_expect_list, expected);
2860 expected->expectant->expecting--;
2861 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2862 @@ -790,6 +828,15 @@
2866 + /* Never happen */
2867 + if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
2868 + if (net_ratelimit()) {
2869 + printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
2870 + (*pskb)->nh.iph->protocol, hooknum);
2875 /* FIXME: Do this right please. --RR */
2876 (*pskb)->nfcache |= NFC_UNKNOWN;
2878 @@ -808,18 +855,10 @@
2882 - /* Previously seen (loopback)? Ignore. Do this before
2883 - fragment check. */
2884 + /* Previously seen (loopback or untracked)? Ignore. */
2888 - /* Gather fragments. */
2889 - if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
2890 - *pskb = ip_ct_gather_frags(*pskb);
2895 proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
2897 /* It may be an icmp error... */
2898 @@ -896,6 +935,14 @@
2899 return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
2903 + * ip_conntrack_unexpect_related - Unexpect a related connection
2904 + * @expect: expecattin to be removed
2906 + * This function removes an existing expectation, that has not yet been
2907 + * confirmed (i.e. expectation was issued, but expected connection didn't
2910 inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
2912 WRITE_LOCK(&ip_conntrack_lock);
2913 @@ -913,7 +960,20 @@
2914 WRITE_UNLOCK(&ip_conntrack_lock);
2917 -/* Add a related connection. */
2919 + * ip_conntrack_expect_related - Expect a related connection
2920 + * @related_to: master conntrack
2921 + * @expect: expectation with all values filled in
2923 + * This function is called by conntrack application helpers who
2924 + * have detected that the control (master) connection is just about
2925 + * to negotiate a related slave connection.
2927 + * Note: This function allocates it's own struct ip_conntrack_expect,
2928 + * copying the values from the 'expect' parameter. Thus, 'expect' can
2929 + * be allocated on the stack and does not need to be valid after this
2930 + * function returns.
2932 int ip_conntrack_expect_related(struct ip_conntrack *related_to,
2933 struct ip_conntrack_expect *expect)
2936 * so there is no need to use the tuple lock too */
2938 DEBUGP("ip_conntrack_expect_related %p\n", related_to);
2939 - DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
2940 - DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
2941 + DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
2942 + DEBUGP("mask: "); DUMP_TUPLE_RAW(&expect->mask);
2944 old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
2945 struct ip_conntrack_expect *, &expect->tuple,
2946 @@ -953,7 +1013,6 @@
2948 } else if (related_to->helper->max_expected &&
2949 related_to->expecting >= related_to->helper->max_expected) {
2950 - struct list_head *cur_item;
2952 if (!(related_to->helper->flags &
2953 IP_CT_HELPER_F_REUSE_EXPECT)) {
2954 @@ -978,21 +1037,14 @@
2955 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
2957 /* choose the the oldest expectation to evict */
2958 - list_for_each(cur_item, &related_to->sibling_list) {
2959 - struct ip_conntrack_expect *cur;
2961 - cur = list_entry(cur_item,
2962 - struct ip_conntrack_expect,
2964 - if (cur->sibling == NULL) {
2966 + list_for_each_entry(old, &related_to->sibling_list,
2968 + if (old->sibling == NULL)
2973 - /* (!old) cannot happen, since related_to->expecting is the
2974 - * number of unconfirmed expects */
2975 - IP_NF_ASSERT(old);
2976 + /* We cannot fail since related_to->expecting is the number
2977 + * of unconfirmed expectations */
2978 + IP_NF_ASSERT(old && old->sibling == NULL);
2980 /* newnat14 does not reuse the real allocated memory
2981 * structures but rather unexpects the old and
2982 @@ -1024,7 +1076,7 @@
2983 atomic_set(&new->use, 1);
2985 /* add to expected list for this connection */
2986 - list_add(&new->expected_list, &related_to->sibling_list);
2987 + list_add_tail(&new->expected_list, &related_to->sibling_list);
2988 /* add to global list of expectations */
2989 list_prepend(&ip_conntrack_expect_list, &new->list);
2990 /* add and start timer if required */
2991 @@ -1043,7 +1095,15 @@
2995 -/* Change tuple in an existing expectation */
2997 + * ip_conntrack_change_expect - Change tuple in existing expectation
2998 + * @expect: expectation which is to be changed
2999 + * @newtuple: new tuple for expect
3001 + * This function is mostly called by NAT application helpers, who want to
3002 + * change an expectation issued by their respective conntrack application
3003 + * helper counterpart.
3005 int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
3006 struct ip_conntrack_tuple *newtuple)
3008 @@ -1051,15 +1111,14 @@
3010 MUST_BE_READ_LOCKED(&ip_conntrack_lock);
3011 WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
3013 DEBUGP("change_expect:\n");
3014 - DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
3015 - DEBUGP("exp mask: "); DUMP_TUPLE(&expect->mask);
3016 - DEBUGP("newtuple: "); DUMP_TUPLE(newtuple);
3017 + DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
3018 + DEBUGP("exp mask: "); DUMP_TUPLE_RAW(&expect->mask);
3019 + DEBUGP("newtuple: "); DUMP_TUPLE_RAW(newtuple);
3020 if (expect->ct_tuple.dst.protonum == 0) {
3021 /* Never seen before */
3022 DEBUGP("change expect: never seen before\n");
3023 - if (!ip_ct_tuple_equal(&expect->tuple, newtuple)
3024 + if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
3025 && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
3026 struct ip_conntrack_expect *, newtuple, &expect->mask)) {
3027 /* Force NAT to find an unused tuple */
3028 @@ -1084,8 +1143,15 @@
3032 -/* Alter reply tuple (maybe alter helper). If it's already taken,
3033 - return 0 and don't do alteration. */
3035 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
3036 + * @conntrack: conntrack whose reply tuple we want to alter
3037 + * @newreply: designated reply tuple for this conntrack
3039 + * This function alters the reply tuple of a conntrack to the given
3040 + * newreply tuple. If this newreply tuple is already taken, return 0
3041 + * and don't do alteration
3043 int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
3044 const struct ip_conntrack_tuple *newreply)
3046 @@ -1110,6 +1176,13 @@
3051 + * ip_conntrack_helper_register - Register a conntrack application helper
3052 + * @me: structure describing the helper
3054 + * This function is called by conntrack application helpers to register
3055 + * themselves with the conntrack core.
3057 int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
3059 WRITE_LOCK(&ip_conntrack_lock);
3060 @@ -1131,6 +1204,13 @@
3065 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
3066 + * @me: structure describing the helper
3068 + * This function is called by conntrack application helpers to unregister
3069 + * themselvers from the conntrack core.
3071 void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
3074 @@ -1149,7 +1229,14 @@
3078 -/* Refresh conntrack for this many jiffies. */
3080 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
3081 + * @ct: conntrack which we want to refresh
3082 + * @extra_jiffies: number of jiffies to add
3084 + * This function is called by protocol helpers and application helpers in
3085 + * order to change the expiration timer of a conntrack entry.
3087 void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
3089 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
3090 @@ -1159,8 +1246,10 @@
3091 if (!is_confirmed(ct))
3092 ct->timeout.expires = extra_jiffies;
3094 - /* Need del_timer for race avoidance (may already be dying). */
3095 - if (del_timer(&ct->timeout)) {
3096 + /* Don't update timer for each packet, only if it's been >HZ
3097 + * ticks since last update.
3098 + * Need del_timer for race avoidance (may already be dying). */
3099 + if (abs(jiffies + extra_jiffies - ct->timeout.expires) >= HZ && del_timer(&ct->timeout)) {
3100 ct->timeout.expires = jiffies + extra_jiffies;
3101 add_timer(&ct->timeout);
3103 @@ -1168,7 +1257,16 @@
3104 WRITE_UNLOCK(&ip_conntrack_lock);
3107 -/* Returns new sk_buff, or NULL */
3110 + * ip_ct_gather_frags - Gather fragments of a particular skb
3111 + * @skb: pointer to sk_buff of fragmented IP packet
3113 + * This code is just a wrapper around the defragmentation code in the core IPv4
3114 + * stack. It also takes care of nonlinear skb's.
3116 + * Returns new sk_buff, or NULL
3119 ip_ct_gather_frags(struct sk_buff *skb)
3121 @@ -1253,6 +1351,16 @@
3126 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
3127 + * @kill: callback function selecting which entries to delete
3128 + * @data: opaque data pointer, becomes 2nd argument for kill function
3130 + * This function can be used to selectively delete elements of the conntrack
3131 + * hashtable. The function iterates over the list of conntrack entries and
3132 + * calls the 'kill' function for every entry. If the return value is true,
3133 + * the connection is deleted (death_by_timeout).
3136 ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
3138 @@ -1263,7 +1371,7 @@
3139 while ((h = get_next_corpse(kill, data)) != NULL) {
3140 /* Time to push up daises... */
3141 if (del_timer(&h->ctrack->timeout))
3142 - death_by_timeout((unsigned long)h->ctrack);
3143 + ip_ct_death_by_timeout((unsigned long)h->ctrack);
3144 /* ... else the timer will get him soon. */
3146 ip_conntrack_put(h->ctrack);
3147 @@ -1419,6 +1527,15 @@
3149 /* For use by ipt_REJECT */
3150 ip_ct_attach = ip_conntrack_attach;
3152 + /* Set up fake conntrack:
3153 + - to never be deleted, not in any hashes */
3154 + atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
3155 + /* - and look it like as a confirmed connection */
3156 + set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
3157 + /* - and prepare the ctinfo field for NAT. */
3158 + ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
3163 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_egg.c
3164 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3165 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_egg.c 2003-12-11 10:23:50.104320960 +0100
3167 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3168 + * based on ip_conntrack_irc.c
3170 + * This module only supports the share userfile-send command,
3171 + * used by eggdrops to share it's userfile.
3173 + * There are no support for NAT at the moment.
3175 + * This program is free software; you can redistribute it and/or
3176 + * modify it under the terms of the GNU General Public License
3177 + * as published by the Free Software Foundation; either version
3178 + * 2 of the License, or (at your option) any later version.
3180 + * Module load syntax:
3182 + * please give the ports of all Eggdrops You have running
3183 + * on your system, the default port is 3333.
3185 + * 2001-04-19: Security update. IP addresses are now compared
3186 + * to prevent unauthorized "related" access.
3188 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3189 + * Port to netfilter 'newnat' API.
3192 +#include <linux/module.h>
3193 +#include <linux/netfilter.h>
3194 +#include <linux/ip.h>
3195 +#include <net/checksum.h>
3196 +#include <net/tcp.h>
3198 +#include <linux/netfilter_ipv4/lockhelp.h>
3199 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3201 +#define MAX_PORTS 8
3202 +static int ports[MAX_PORTS];
3203 +static int ports_c = 0;
3204 +static unsigned int egg_timeout = 300;
3206 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3207 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3208 +MODULE_LICENSE("GPL");
3210 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3211 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3214 +DECLARE_LOCK(ip_egg_lock);
3215 +struct module *ip_conntrack_egg = THIS_MODULE;
3218 +#define DEBUGP printk
3220 +#define DEBUGP(format, args...)
3223 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3224 +/* tries to get the ip_addr and port out of a eggdrop command
3225 + return value: -1 on failure, 0 on success
3226 + data pointer to first byte of DCC command data
3227 + data_end pointer to last byte of dcc command data
3228 + ip returns parsed ip of dcc command
3229 + port returns parsed port of dcc command */
3231 + if (data > data_end)
3234 + *ip = simple_strtoul(data, &data, 10);
3236 + /* skip blanks between ip and port */
3237 + while (*data == ' ' && data < data_end)
3240 + *port = simple_strtoul(data, &data, 10);
3245 +static int help(const struct iphdr *iph, size_t len,
3246 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3248 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3249 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3250 + char *data = (char *) tcph + tcph->doff * 4;
3252 + u_int32_t tcplen = len - iph->ihl * 4;
3253 + u_int32_t datalen = tcplen - tcph->doff * 4;
3254 + int dir = CTINFO2DIR(ctinfo);
3255 + int bytes_scanned = 0;
3256 + struct ip_conntrack_expect exp;
3259 + u_int16_t egg_port;
3261 + DEBUGP("entered\n");
3263 + /* If packet is coming from IRC server */
3264 + if (dir != IP_CT_DIR_REPLY)
3267 + /* Until there's been traffic both ways, don't look in packets. */
3268 + if (ctinfo != IP_CT_ESTABLISHED
3269 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3270 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
3274 + /* Not whole TCP header? */
3275 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3276 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3280 + /* Checksum invalid? Ignore. */
3281 + /* FIXME: Source route IP option packets --RR */
3282 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3283 + csum_partial((char *) tcph, tcplen, 0))) {
3284 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3285 + tcph, tcplen, NIPQUAD(iph->saddr),
3286 + NIPQUAD(iph->daddr));
3290 + data_limit = (char *) data + datalen;
3291 + while (datalen > 5 && bytes_scanned < 128) {
3292 + if (memcmp(data, "s us ", 5)) {
3301 + DEBUGP("Userfile-share found in connection "
3302 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3303 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3305 + if (parse_command((char *) data, data_limit, &egg_ip,
3307 + DEBUGP("no data in userfile-share pkt\n");
3311 + memset(&exp, 0, sizeof(exp));
3313 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3314 + if (net_ratelimit())
3315 + printk("Forged Eggdrop command from "
3316 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3317 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3318 + HIPQUAD(egg_ip), egg_port);
3322 + exp.tuple.src.ip = iph->daddr;
3323 + exp.tuple.src.u.tcp.port = 0;
3324 + exp.tuple.dst.ip = htonl(egg_ip);
3325 + exp.tuple.dst.u.tcp.port = htons(egg_port);
3326 + exp.tuple.dst.protonum = IPPROTO_TCP;
3328 + exp.mask.dst.u.tcp.port = 0xffff;
3329 + exp.mask.dst.protonum = 0xffff;
3331 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3332 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3333 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3335 + ip_conntrack_expect_related(ct, &exp);
3341 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3342 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3344 +static void deregister_helpers(void) {
3347 + for (i = 0; i < ports_c; i++) {
3348 + DEBUGP("unregistering helper for port %d\n", ports[i]);
3349 + ip_conntrack_helper_unregister(&egg_helpers[i]);
3353 +static int __init init(void)
3358 + /* If no port given, default to standard eggdrop port */
3359 + if (ports[0] == 0)
3362 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3363 + memset(&egg_helpers[i], 0,
3364 + sizeof(struct ip_conntrack_helper));
3365 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3366 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3367 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3368 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
3369 + egg_helpers[i].max_expected = 1;
3370 + egg_helpers[i].timeout = egg_timeout;
3371 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3372 + egg_helpers[i].me = THIS_MODULE;
3373 + egg_helpers[i].help = help;
3375 + tmpname = &egg_names[i][0];
3376 + if (ports[i] == 3333)
3377 + sprintf(tmpname, "eggdrop");
3379 + sprintf(tmpname, "eggdrop-%d", ports[i]);
3380 + egg_helpers[i].name = tmpname;
3382 + DEBUGP("port #%d: %d\n", i, ports[i]);
3384 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
3387 + printk("ip_conntrack_egg: ERROR registering helper "
3388 + "for port %d\n", ports[i]);
3389 + deregister_helpers();
3397 +static void __exit fini(void)
3399 + deregister_helpers();
3404 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_h323.c
3405 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3406 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_h323.c 2003-12-11 10:23:51.335133848 +0100
3409 + * H.323 'brute force' extension for H.323 connection tracking.
3410 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3412 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3413 + * (http://www.coritel.it/projects/sofia/nat/)
3414 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3415 + * the unregistered helpers to the conntrack entries.
3419 +#include <linux/module.h>
3420 +#include <linux/netfilter.h>
3421 +#include <linux/ip.h>
3422 +#include <net/checksum.h>
3423 +#include <net/tcp.h>
3425 +#include <linux/netfilter_ipv4/lockhelp.h>
3426 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3427 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3428 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3429 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3430 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3432 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3433 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3434 +MODULE_LICENSE("GPL");
3436 +DECLARE_LOCK(ip_h323_lock);
3437 +struct module *ip_conntrack_h323 = THIS_MODULE;
3440 +#define DEBUGP printk
3442 +#define DEBUGP(format, args...)
3445 +/* FIXME: This should be in userspace. Later. */
3446 +static int h245_help(const struct iphdr *iph, size_t len,
3447 + struct ip_conntrack *ct,
3448 + enum ip_conntrack_info ctinfo)
3450 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3451 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3452 + unsigned char *data_limit;
3453 + u_int32_t tcplen = len - iph->ihl * 4;
3454 + u_int32_t datalen = tcplen - tcph->doff * 4;
3455 + int dir = CTINFO2DIR(ctinfo);
3456 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3457 + struct ip_conntrack_expect expect, *exp = &expect;
3458 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3459 + u_int16_t data_port;
3460 + u_int32_t data_ip;
3463 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3464 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3465 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3467 + /* Can't track connections formed before we registered */
3471 + /* Until there's been traffic both ways, don't look in packets. */
3472 + if (ctinfo != IP_CT_ESTABLISHED
3473 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3474 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3478 + /* Not whole TCP header or too short packet? */
3479 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3480 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3484 + /* Checksum invalid? Ignore. */
3485 + /* FIXME: Source route IP option packets --RR */
3486 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3487 + csum_partial((char *)tcph, tcplen, 0))) {
3488 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3489 + tcph, tcplen, NIPQUAD(iph->saddr),
3490 + NIPQUAD(iph->daddr));
3494 + data_limit = (unsigned char *) data + datalen;
3497 + for (i = 0; data < (data_limit - 5); data++, i++) {
3498 + data_ip = *((u_int32_t *)data);
3499 + if (data_ip == iph->saddr) {
3500 + data_port = *((u_int16_t *)(data + 4));
3501 + memset(&expect, 0, sizeof(expect));
3502 + /* update the H.225 info */
3503 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3504 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3505 + NIPQUAD(iph->saddr), ntohs(data_port));
3506 + LOCK_BH(&ip_h323_lock);
3507 + info->is_h225 = H225_PORT + 1;
3508 + exp_info->port = data_port;
3509 + exp_info->dir = dir;
3510 + exp_info->offset = i;
3512 + exp->seq = ntohl(tcph->seq) + i;
3514 + exp->tuple = ((struct ip_conntrack_tuple)
3515 + { { ct->tuplehash[!dir].tuple.src.ip,
3518 + { .tcp = { data_port } },
3520 + exp->mask = ((struct ip_conntrack_tuple)
3521 + { { 0xFFFFFFFF, { 0 } },
3522 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3524 + exp->expectfn = NULL;
3526 + /* Ignore failure; should only happen with NAT */
3527 + ip_conntrack_expect_related(ct, exp);
3529 + UNLOCK_BH(&ip_h323_lock);
3537 +/* H.245 helper is not registered! */
3538 +static struct ip_conntrack_helper h245 =
3540 + "H.245", /* name */
3541 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3542 + NULL, /* module */
3543 + 8, /* max_ expected */
3544 + 240, /* timeout */
3545 + { { 0, { 0 } }, /* tuple */
3546 + { 0, { 0 }, IPPROTO_TCP } },
3547 + { { 0, { 0xFFFF } }, /* mask */
3548 + { 0, { 0 }, 0xFFFF } },
3549 + h245_help /* helper */
3552 +static int h225_expect(struct ip_conntrack *ct)
3554 + WRITE_LOCK(&ip_conntrack_lock);
3555 + ct->helper = &h245;
3556 + DEBUGP("h225_expect: helper for %p added\n", ct);
3557 + WRITE_UNLOCK(&ip_conntrack_lock);
3559 + return NF_ACCEPT; /* unused */
3562 +/* FIXME: This should be in userspace. Later. */
3563 +static int h225_help(const struct iphdr *iph, size_t len,
3564 + struct ip_conntrack *ct,
3565 + enum ip_conntrack_info ctinfo)
3567 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3568 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3569 + unsigned char *data_limit;
3570 + u_int32_t tcplen = len - iph->ihl * 4;
3571 + u_int32_t datalen = tcplen - tcph->doff * 4;
3572 + int dir = CTINFO2DIR(ctinfo);
3573 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3574 + struct ip_conntrack_expect expect, *exp = &expect;
3575 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3576 + u_int16_t data_port;
3577 + u_int32_t data_ip;
3580 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3581 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3582 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3584 + /* Can't track connections formed before we registered */
3588 + /* Until there's been traffic both ways, don't look in packets. */
3589 + if (ctinfo != IP_CT_ESTABLISHED
3590 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3591 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3595 + /* Not whole TCP header or too short packet? */
3596 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3597 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3601 + /* Checksum invalid? Ignore. */
3602 + /* FIXME: Source route IP option packets --RR */
3603 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3604 + csum_partial((char *)tcph, tcplen, 0))) {
3605 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3606 + tcph, tcplen, NIPQUAD(iph->saddr),
3607 + NIPQUAD(iph->daddr));
3611 + data_limit = (unsigned char *) data + datalen;
3614 + for (i = 0; data < (data_limit - 5); data++, i++) {
3615 + data_ip = *((u_int32_t *)data);
3616 + if (data_ip == iph->saddr) {
3617 + data_port = *((u_int16_t *)(data + 4));
3618 + if (data_port == tcph->source) {
3619 + /* Signal address */
3620 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3621 + NIPQUAD(iph->saddr));
3622 + /* Update the H.225 info so that NAT can mangle the address/port
3623 + even when we have no expected connection! */
3624 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3625 + LOCK_BH(&ip_h323_lock);
3627 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3628 + info->offset[IP_CT_DIR_ORIGINAL] = i;
3629 + UNLOCK_BH(&ip_h323_lock);
3632 + memset(&expect, 0, sizeof(expect));
3634 + /* update the H.225 info */
3635 + LOCK_BH(&ip_h323_lock);
3636 + info->is_h225 = H225_PORT;
3637 + exp_info->port = data_port;
3638 + exp_info->dir = dir;
3639 + exp_info->offset = i;
3641 + exp->seq = ntohl(tcph->seq) + i;
3643 + exp->tuple = ((struct ip_conntrack_tuple)
3644 + { { ct->tuplehash[!dir].tuple.src.ip,
3647 + { .tcp = { data_port } },
3649 + exp->mask = ((struct ip_conntrack_tuple)
3650 + { { 0xFFFFFFFF, { 0 } },
3651 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3653 + exp->expectfn = h225_expect;
3655 + /* Ignore failure */
3656 + ip_conntrack_expect_related(ct, exp);
3658 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3659 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3660 + NIPQUAD(iph->saddr), ntohs(data_port));
3662 + UNLOCK_BH(&ip_h323_lock);
3664 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3665 + } else if (data_ip == iph->daddr) {
3666 + data_port = *((u_int16_t *)(data + 4));
3667 + if (data_port == tcph->dest) {
3668 + /* Signal address */
3669 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3670 + NIPQUAD(iph->daddr));
3671 + /* Update the H.225 info so that NAT can mangle the address/port
3672 + even when we have no expected connection! */
3673 + LOCK_BH(&ip_h323_lock);
3675 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3676 + info->offset[IP_CT_DIR_REPLY] = i;
3677 + UNLOCK_BH(&ip_h323_lock);
3687 +static struct ip_conntrack_helper h225 =
3689 + "H.225", /* name */
3690 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3691 + THIS_MODULE, /* module */
3692 + 2, /* max_expected */
3693 + 240, /* timeout */
3694 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
3695 + { 0, { 0 }, IPPROTO_TCP } },
3696 + { { 0, { 0xFFFF } }, /* mask */
3697 + { 0, { 0 }, 0xFFFF } },
3698 + h225_help /* helper */
3701 +static int __init init(void)
3703 + return ip_conntrack_helper_register(&h225);
3706 +static void __exit fini(void)
3708 + /* Unregister H.225 helper */
3709 + ip_conntrack_helper_unregister(&h225);
3712 +EXPORT_SYMBOL(ip_h323_lock);
3716 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_mms.c
3717 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
3718 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_mms.c 2003-12-11 10:23:55.933434800 +0100
3720 +/* MMS extension for IP connection tracking
3721 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3722 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3724 + * ip_conntrack_mms.c v0.3 2002-09-22
3726 + * This program is free software; you can redistribute it and/or
3727 + * modify it under the terms of the GNU General Public License
3728 + * as published by the Free Software Foundation; either version
3729 + * 2 of the License, or (at your option) any later version.
3731 + * Module load syntax:
3732 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3734 + * Please give the ports of all MMS servers You wish to connect to.
3735 + * If you don't specify ports, the default will be TCP port 1755.
3737 + * More info on MMS protocol, firewalls and NAT:
3738 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3739 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3741 + * The SDP project people are reverse-engineering MMS:
3742 + * http://get.to/sdp
3745 +#include <linux/config.h>
3746 +#include <linux/module.h>
3747 +#include <linux/netfilter.h>
3748 +#include <linux/ip.h>
3749 +#include <linux/ctype.h>
3750 +#include <net/checksum.h>
3751 +#include <net/tcp.h>
3753 +#include <linux/netfilter_ipv4/lockhelp.h>
3754 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3755 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3757 +DECLARE_LOCK(ip_mms_lock);
3758 +struct module *ip_conntrack_mms = THIS_MODULE;
3760 +#define MAX_PORTS 8
3761 +static int ports[MAX_PORTS];
3762 +static int ports_c;
3764 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3768 +#define DEBUGP printk
3770 +#define DEBUGP(format, args...)
3773 +EXPORT_SYMBOL(ip_mms_lock);
3775 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3776 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3777 +MODULE_LICENSE("GPL");
3779 +/* #define isdigit(c) (c >= '0' && c <= '9') */
3781 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3782 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3785 + for (i = 0; i < unicode_size; ++i) {
3786 + string[i] = (char)(unicode[i]);
3788 + string[unicode_size] = 0x00;
3791 +__inline static int atoi(char *s)
3794 + while (isdigit(*s)) {
3795 + i = i*10 + *(s++) - '0';
3800 +/* convert ip address string like "192.168.0.10" to unsigned int */
3801 +__inline static u_int32_t asciiiptoi(char *s)
3803 + unsigned int i, j, k;
3805 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
3807 + for(j=0; (*(++s) != '.') && (j<3); ++j)
3814 +int parse_mms(const char *data,
3815 + const unsigned int datalen,
3816 + u_int32_t *mms_ip,
3817 + u_int16_t *mms_proto,
3818 + u_int16_t *mms_port,
3819 + char **mms_string_b,
3820 + char **mms_string_e,
3821 + char **mms_padding_e)
3823 + int unicode_size, i;
3824 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
3825 + char getlengthstring[28];
3827 + for(unicode_size=0;
3828 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3830 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
3831 + return -1; /* out of bounds - incomplete packet */
3833 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3834 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3836 + /* IP address ? */
3837 + *mms_ip = asciiiptoi(tempstring+2);
3839 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3842 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
3843 + *mms_proto = IPPROTO_TCP;
3844 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3845 + *mms_proto = IPPROTO_UDP;
3848 + *mms_port = atoi(tempstring+7+i);
3850 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
3851 + unicode string, one to the end of the string, and one to the end
3852 + of the packet, since we must keep track of the number of bytes
3853 + between end of the unicode string and the end of packet (padding) */
3854 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3855 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3856 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3861 +/* FIXME: This should be in userspace. Later. */
3862 +static int help(const struct iphdr *iph, size_t len,
3863 + struct ip_conntrack *ct,
3864 + enum ip_conntrack_info ctinfo)
3866 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3867 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3868 + const char *data = (const char *)tcph + tcph->doff * 4;
3869 + unsigned int tcplen = len - iph->ihl * 4;
3870 + unsigned int datalen = tcplen - tcph->doff * 4;
3871 + int dir = CTINFO2DIR(ctinfo);
3872 + struct ip_conntrack_expect expect, *exp = &expect;
3873 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3876 + u_int16_t mms_proto;
3877 + char mms_proto_string[8];
3878 + u_int16_t mms_port;
3879 + char *mms_string_b, *mms_string_e, *mms_padding_e;
3881 + /* Until there's been traffic both ways, don't look in packets. */
3882 + if (ctinfo != IP_CT_ESTABLISHED
3883 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3884 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3888 + /* Not whole TCP header? */
3889 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3890 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3894 + /* Checksum invalid? Ignore. */
3895 + /* FIXME: Source route IP option packets --RR */
3896 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3897 + csum_partial((char *)tcph, tcplen, 0))) {
3898 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3899 + tcph, tcplen, NIPQUAD(iph->saddr),
3900 + NIPQUAD(iph->daddr));
3904 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3905 + /* FIXME: There is an issue with only looking at this packet: before this packet,
3906 + the client has already sent a packet to the server with the server's hostname
3907 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
3908 + server will break the connection if this doesn't correspond to its own host
3909 + header. The client can also connect to an IP address; if it's the server's IP
3910 + address, it will not break the connection. When doing DNAT on a connection
3911 + where the client uses a server's IP address, the nat module should detect
3912 + this and change this string accordingly to the DNATed address. This should
3913 + probably be done by checking for an IP address, then storing it as a member
3914 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3916 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
3917 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3918 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
3919 + (u8)*(data+36), (u8)*(data+37),
3920 + (u8)*(data+38), (u8)*(data+39),
3922 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3923 + &mms_string_b, &mms_string_e, &mms_padding_e))
3924 + if(net_ratelimit())
3925 + /* FIXME: more verbose debugging ? */
3926 + printk(KERN_WARNING
3927 + "ip_conntrack_mms: Unable to parse data payload\n");
3929 + memset(&expect, 0, sizeof(expect));
3931 + sprintf(mms_proto_string, "(%u)", mms_proto);
3932 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3933 + mms_proto == IPPROTO_TCP ? "TCP"
3934 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3935 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3939 + /* it's possible that the client will just ask the server to tunnel
3940 + the stream over the same TCP session (from port 1755): there's
3941 + shouldn't be a need to add an expectation in that case, but it
3942 + makes NAT packet mangling so much easier */
3943 + LOCK_BH(&ip_mms_lock);
3945 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3947 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3948 + exp_mms_info->len = (mms_string_e - mms_string_b);
3949 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
3950 + exp_mms_info->port = mms_port;
3952 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3953 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3955 + exp->tuple = ((struct ip_conntrack_tuple)
3956 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3958 + { .tcp = { (__u16) ntohs(mms_port) } },
3961 + exp->mask = ((struct ip_conntrack_tuple)
3962 + { { 0xFFFFFFFF, { 0 } },
3963 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3964 + exp->expectfn = NULL;
3965 + ip_conntrack_expect_related(ct, &expect);
3966 + UNLOCK_BH(&ip_mms_lock);
3972 +static struct ip_conntrack_helper mms[MAX_PORTS];
3973 +static char mms_names[MAX_PORTS][10];
3975 +/* Not __exit: called from init() */
3976 +static void fini(void)
3979 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3980 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3982 + ip_conntrack_helper_unregister(&mms[i]);
3986 +static int __init init(void)
3991 + if (ports[0] == 0)
3992 + ports[0] = MMS_PORT;
3994 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3995 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3996 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3997 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
3998 + mms[i].mask.src.u.tcp.port = 0xFFFF;
3999 + mms[i].mask.dst.protonum = 0xFFFF;
4000 + mms[i].max_expected = 1;
4001 + mms[i].timeout = 0;
4002 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4003 + mms[i].me = THIS_MODULE;
4004 + mms[i].help = help;
4006 + tmpname = &mms_names[i][0];
4007 + if (ports[i] == MMS_PORT)
4008 + sprintf(tmpname, "mms");
4010 + sprintf(tmpname, "mms-%d", ports[i]);
4011 + mms[i].name = tmpname;
4013 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
4015 + ret = ip_conntrack_helper_register(&mms[i]);
4028 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp.c
4029 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp.c 1970-01-01 01:00:00.000000000 +0100
4030 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp.c 2003-12-11 10:25:04.543004560 +0100
4033 + * ip_conntrack_pptp.c - Version 1.9
4035 + * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
4036 + * PPTP is a a protocol for creating virtual private networks.
4037 + * It is a specification defined by Microsoft and some vendors
4038 + * working with Microsoft. PPTP is built on top of a modified
4039 + * version of the Internet Generic Routing Encapsulation Protocol.
4040 + * GRE is defined in RFC 1701 and RFC 1702. Documentation of
4041 + * PPTP can be found in RFC 2637
4043 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4045 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4048 + * - We blindly assume that control connections are always
4049 + * established in PNS->PAC direction. This is a violation
4052 + * TODO: - finish support for multiple calls within one session
4053 + * (needs expect reservations in newnat)
4054 + * - testing of incoming PPTP calls
4057 + * 2002-02-05 - Version 1.3
4058 + * - Call ip_conntrack_unexpect_related() from
4059 + * pptp_timeout_related() to destroy expectations in case
4060 + * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
4061 + * (Philip Craig <philipc@snapgear.com>)
4062 + * - Add Version information at module loadtime
4063 + * 2002-02-10 - Version 1.6
4064 + * - move to C99 style initializers
4065 + * - remove second expectation if first arrives
4069 +#include <linux/config.h>
4070 +#include <linux/module.h>
4071 +#include <linux/netfilter.h>
4072 +#include <linux/ip.h>
4073 +#include <net/checksum.h>
4074 +#include <net/tcp.h>
4076 +#include <linux/netfilter_ipv4/lockhelp.h>
4077 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4078 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4079 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4081 +#define IP_CT_PPTP_VERSION "1.9"
4083 +MODULE_LICENSE("GPL");
4084 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4085 +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
4087 +DECLARE_LOCK(ip_pptp_lock);
4090 +#include "ip_conntrack_pptp_priv.h"
4091 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4092 + ": " format, ## args)
4094 +#define DEBUGP(format, args...)
4098 +#define MINS * 60 SECS
4099 +#define HOURS * 60 MINS
4100 +#define DAYS * 24 HOURS
4102 +#define PPTP_GRE_TIMEOUT (10 MINS)
4103 +#define PPTP_GRE_STREAM_TIMEOUT (5 DAYS)
4105 +static int pptp_expectfn(struct ip_conntrack *ct)
4107 + struct ip_conntrack *master;
4108 + struct ip_conntrack_expect *exp;
4110 + DEBUGP("increasing timeouts\n");
4111 + /* increase timeout of GRE data channel conntrack entry */
4112 + ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
4113 + ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
4115 + master = master_ct(ct);
4117 + DEBUGP(" no master!!!\n");
4123 + DEBUGP("no expectation!!\n");
4127 + DEBUGP("completing tuples with ct info\n");
4128 + /* we can do this, since we're unconfirmed */
4129 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
4130 + htonl(master->help.ct_pptp_info.pac_call_id)) {
4131 + /* assume PNS->PAC */
4132 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
4133 + htonl(master->help.ct_pptp_info.pns_call_id);
4134 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4135 + htonl(master->help.ct_pptp_info.pns_call_id);
4137 + /* assume PAC->PNS */
4138 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
4139 + htonl(master->help.ct_pptp_info.pac_call_id);
4140 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4141 + htonl(master->help.ct_pptp_info.pac_call_id);
4144 + /* delete other expectation */
4145 + if (exp->expected_list.next != &exp->expected_list) {
4146 + struct ip_conntrack_expect *other_exp;
4147 + struct list_head *cur_item, *next;
4149 + for (cur_item = master->sibling_list.next;
4150 + cur_item != &master->sibling_list; cur_item = next) {
4151 + next = cur_item->next;
4152 + other_exp = list_entry(cur_item,
4153 + struct ip_conntrack_expect,
4155 + /* remove only if occurred at same sequence number */
4156 + if (other_exp != exp && other_exp->seq == exp->seq) {
4157 + DEBUGP("unexpecting other direction\n");
4158 + ip_ct_gre_keymap_destroy(other_exp);
4159 + ip_conntrack_unexpect_related(other_exp);
4167 +/* timeout GRE data connections */
4168 +static int pptp_timeout_related(struct ip_conntrack *ct)
4170 + struct list_head *cur_item, *next;
4171 + struct ip_conntrack_expect *exp;
4173 + /* FIXME: do we have to lock something ? */
4174 + for (cur_item = ct->sibling_list.next;
4175 + cur_item != &ct->sibling_list; cur_item = next) {
4176 + next = cur_item->next;
4177 + exp = list_entry(cur_item, struct ip_conntrack_expect,
4180 + ip_ct_gre_keymap_destroy(exp);
4181 + if (!exp->sibling) {
4182 + ip_conntrack_unexpect_related(exp);
4186 + DEBUGP("killing conntrack %p\n",
4188 + exp->sibling->proto.gre.timeout = 0;
4189 + exp->sibling->proto.gre.stream_timeout = 0;
4191 + if (del_timer(&exp->sibling->timeout))
4192 + ip_ct_death_by_timeout((unsigned long)exp->sibling);
4198 +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
4200 +exp_gre(struct ip_conntrack *master,
4203 + u_int16_t peer_callid)
4205 + struct ip_conntrack_expect exp;
4206 + struct ip_conntrack_tuple inv_tuple;
4208 + memset(&exp, 0, sizeof(exp));
4209 + /* tuple in original direction, PNS->PAC */
4210 + exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4211 + exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
4212 + exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4213 + exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
4214 + exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
4215 + exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
4216 + exp.tuple.dst.protonum = IPPROTO_GRE;
4218 + exp.mask.src.ip = 0xffffffff;
4219 + exp.mask.src.u.all = 0;
4220 + exp.mask.dst.u.all = 0;
4221 + exp.mask.dst.u.gre.key = 0xffffffff;
4222 + exp.mask.dst.u.gre.version = 0xff;
4223 + exp.mask.dst.u.gre.protocol = 0xffff;
4224 + exp.mask.dst.ip = 0xffffffff;
4225 + exp.mask.dst.protonum = 0xffff;
4228 + exp.expectfn = pptp_expectfn;
4230 + exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
4231 + exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
4233 + DEBUGP("calling expect_related ");
4234 + DUMP_TUPLE_RAW(&exp.tuple);
4236 + /* Add GRE keymap entries */
4237 + if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
4240 + invert_tuplepr(&inv_tuple, &exp.tuple);
4241 + if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
4242 + ip_ct_gre_keymap_destroy(&exp);
4246 + if (ip_conntrack_expect_related(master, &exp) != 0) {
4247 + ip_ct_gre_keymap_destroy(&exp);
4248 + DEBUGP("cannot expect_related()\n");
4252 + /* tuple in reply direction, PAC->PNS */
4253 + exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4254 + exp.tuple.src.u.gre.key = htonl(ntohs(callid));
4255 + exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4256 + exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
4258 + DEBUGP("calling expect_related ");
4259 + DUMP_TUPLE_RAW(&exp.tuple);
4261 + /* Add GRE keymap entries */
4262 + ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
4263 + invert_tuplepr(&inv_tuple, &exp.tuple);
4264 + ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
4265 + /* FIXME: cannot handle error correctly, since we need to free
4266 + * the above keymap :( */
4268 + if (ip_conntrack_expect_related(master, &exp) != 0) {
4269 + /* free the second pair of keypmaps */
4270 + ip_ct_gre_keymap_destroy(&exp);
4271 + DEBUGP("cannot expect_related():\n");
4279 +pptp_inbound_pkt(struct tcphdr *tcph,
4280 + struct pptp_pkt_hdr *pptph,
4282 + struct ip_conntrack *ct,
4283 + enum ip_conntrack_info ctinfo)
4285 + struct PptpControlHeader *ctlh;
4286 + union pptp_ctrl_union pptpReq;
4288 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4289 + u_int16_t msg, *cid, *pcid;
4292 + ctlh = (struct PptpControlHeader *)
4293 + ((char *) pptph + sizeof(struct pptp_pkt_hdr));
4294 + pptpReq.rawreq = (void *)
4295 + ((char *) ctlh + sizeof(struct PptpControlHeader));
4297 + msg = ntohs(ctlh->messageType);
4298 + DEBUGP("inbound control message %s\n", strMName[msg]);
4301 + case PPTP_START_SESSION_REPLY:
4302 + /* server confirms new control session */
4303 + if (info->sstate < PPTP_SESSION_REQUESTED) {
4304 + DEBUGP("%s without START_SESS_REQUEST\n",
4308 + if (pptpReq.srep->resultCode == PPTP_START_OK)
4309 + info->sstate = PPTP_SESSION_CONFIRMED;
4311 + info->sstate = PPTP_SESSION_ERROR;
4314 + case PPTP_STOP_SESSION_REPLY:
4315 + /* server confirms end of control session */
4316 + if (info->sstate > PPTP_SESSION_STOPREQ) {
4317 + DEBUGP("%s without STOP_SESS_REQUEST\n",
4321 + if (pptpReq.strep->resultCode == PPTP_STOP_OK)
4322 + info->sstate = PPTP_SESSION_NONE;
4324 + info->sstate = PPTP_SESSION_ERROR;
4327 + case PPTP_OUT_CALL_REPLY:
4328 + /* server accepted call, we now expect GRE frames */
4329 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4330 + DEBUGP("%s but no session\n", strMName[msg]);
4333 + if (info->cstate != PPTP_CALL_OUT_REQ &&
4334 + info->cstate != PPTP_CALL_OUT_CONF) {
4335 + DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
4338 + if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
4339 + info->cstate = PPTP_CALL_NONE;
4343 + cid = &pptpReq.ocack->callID;
4344 + pcid = &pptpReq.ocack->peersCallID;
4346 + info->pac_call_id = ntohs(*cid);
4348 + if (htons(info->pns_call_id) != *pcid) {
4349 + DEBUGP("%s for unknown callid %u\n",
4350 + strMName[msg], ntohs(*pcid));
4354 + DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg],
4355 + ntohs(*cid), ntohs(*pcid));
4357 + info->cstate = PPTP_CALL_OUT_CONF;
4359 + seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4360 + if (exp_gre(ct, seq, *cid, *pcid) != 0)
4361 + printk("ip_conntrack_pptp: error during exp_gre\n");
4364 + case PPTP_IN_CALL_REQUEST:
4365 + /* server tells us about incoming call request */
4366 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4367 + DEBUGP("%s but no session\n", strMName[msg]);
4370 + pcid = &pptpReq.icack->peersCallID;
4371 + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4372 + info->cstate = PPTP_CALL_IN_REQ;
4373 + info->pac_call_id= ntohs(*pcid);
4376 + case PPTP_IN_CALL_CONNECT:
4377 + /* server tells us about incoming call established */
4378 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4379 + DEBUGP("%s but no session\n", strMName[msg]);
4382 + if (info->sstate != PPTP_CALL_IN_REP
4383 + && info->sstate != PPTP_CALL_IN_CONF) {
4384 + DEBUGP("%s but never sent IN_CALL_REPLY\n",
4389 + pcid = &pptpReq.iccon->peersCallID;
4390 + cid = &info->pac_call_id;
4392 + if (info->pns_call_id != ntohs(*pcid)) {
4393 + DEBUGP("%s for unknown CallID %u\n",
4394 + strMName[msg], ntohs(*cid));
4398 + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4399 + info->cstate = PPTP_CALL_IN_CONF;
4401 + /* we expect a GRE connection from PAC to PNS */
4402 + seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4403 + if (exp_gre(ct, seq, *cid, *pcid) != 0)
4404 + printk("ip_conntrack_pptp: error during exp_gre\n");
4408 + case PPTP_CALL_DISCONNECT_NOTIFY:
4409 + /* server confirms disconnect */
4410 + cid = &pptpReq.disc->callID;
4411 + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4412 + info->cstate = PPTP_CALL_NONE;
4414 + /* untrack this call id, unexpect GRE packets */
4415 + pptp_timeout_related(ct);
4418 + case PPTP_WAN_ERROR_NOTIFY:
4421 + case PPTP_ECHO_REQUEST:
4422 + case PPTP_ECHO_REPLY:
4423 + /* I don't have to explain these ;) */
4426 + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
4427 + ? strMName[msg]:strMName[0], msg);
4436 +pptp_outbound_pkt(struct tcphdr *tcph,
4437 + struct pptp_pkt_hdr *pptph,
4439 + struct ip_conntrack *ct,
4440 + enum ip_conntrack_info ctinfo)
4442 + struct PptpControlHeader *ctlh;
4443 + union pptp_ctrl_union pptpReq;
4444 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4445 + u_int16_t msg, *cid, *pcid;
4447 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
4448 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
4450 + msg = ntohs(ctlh->messageType);
4451 + DEBUGP("outbound control message %s\n", strMName[msg]);
4454 + case PPTP_START_SESSION_REQUEST:
4455 + /* client requests for new control session */
4456 + if (info->sstate != PPTP_SESSION_NONE) {
4457 + DEBUGP("%s but we already have one",
4460 + info->sstate = PPTP_SESSION_REQUESTED;
4462 + case PPTP_STOP_SESSION_REQUEST:
4463 + /* client requests end of control session */
4464 + info->sstate = PPTP_SESSION_STOPREQ;
4467 + case PPTP_OUT_CALL_REQUEST:
4468 + /* client initiating connection to server */
4469 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4470 + DEBUGP("%s but no session\n",
4474 + info->cstate = PPTP_CALL_OUT_REQ;
4475 + /* track PNS call id */
4476 + cid = &pptpReq.ocreq->callID;
4477 + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4478 + info->pns_call_id = ntohs(*cid);
4480 + case PPTP_IN_CALL_REPLY:
4481 + /* client answers incoming call */
4482 + if (info->cstate != PPTP_CALL_IN_REQ
4483 + && info->cstate != PPTP_CALL_IN_REP) {
4484 + DEBUGP("%s without incall_req\n",
4488 + if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
4489 + info->cstate = PPTP_CALL_NONE;
4492 + pcid = &pptpReq.icack->peersCallID;
4493 + if (info->pac_call_id != ntohs(*pcid)) {
4494 + DEBUGP("%s for unknown call %u\n",
4495 + strMName[msg], ntohs(*pcid));
4498 + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
4499 + /* part two of the three-way handshake */
4500 + info->cstate = PPTP_CALL_IN_REP;
4501 + info->pns_call_id = ntohs(pptpReq.icack->callID);
4504 + case PPTP_CALL_CLEAR_REQUEST:
4505 + /* client requests hangup of call */
4506 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4507 + DEBUGP("CLEAR_CALL but no session\n");
4510 + /* FUTURE: iterate over all calls and check if
4511 + * call ID is valid. We don't do this without newnat,
4512 + * because we only know about last call */
4513 + info->cstate = PPTP_CALL_CLEAR_REQ;
4515 + case PPTP_SET_LINK_INFO:
4517 + case PPTP_ECHO_REQUEST:
4518 + case PPTP_ECHO_REPLY:
4519 + /* I don't have to explain these ;) */
4522 + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?
4523 + strMName[msg]:strMName[0], msg);
4524 + /* unknown: no need to create GRE masq table entry */
4532 +/* track caller id inside control connection, call expect_related */
4534 +conntrack_pptp_help(const struct iphdr *iph, size_t len,
4535 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4538 + struct pptp_pkt_hdr *pptph;
4540 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4541 + u_int32_t tcplen = len - iph->ihl * 4;
4542 + u_int32_t datalen = tcplen - tcph->doff * 4;
4544 + int dir = CTINFO2DIR(ctinfo);
4545 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4547 + int oldsstate, oldcstate;
4550 + /* don't do any tracking before tcp handshake complete */
4551 + if (ctinfo != IP_CT_ESTABLISHED
4552 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4553 + DEBUGP("ctinfo = %u, skipping\n", ctinfo);
4557 + /* not a complete TCP header? */
4558 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4559 + DEBUGP("tcplen = %u\n", tcplen);
4563 + /* checksum invalid? */
4564 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4565 + csum_partial((char *) tcph, tcplen, 0))) {
4566 + printk(KERN_NOTICE __FILE__ ": bad csum\n");
4567 + /* W2K PPTP server sends TCP packets with wrong checksum :(( */
4568 + //return NF_ACCEPT;
4571 + if (tcph->fin || tcph->rst) {
4572 + DEBUGP("RST/FIN received, timeouting GRE\n");
4573 + /* can't do this after real newnat */
4574 + info->cstate = PPTP_CALL_NONE;
4576 + /* untrack this call id, unexpect GRE packets */
4577 + pptp_timeout_related(ct);
4581 + pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
4582 + datalimit = (void *) pptph + datalen;
4584 + /* not a full pptp packet header? */
4585 + if ((void *) pptph+sizeof(*pptph) >= datalimit) {
4586 + DEBUGP("no full PPTP header, can't track\n");
4590 + /* if it's not a control message we can't do anything with it */
4591 + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
4592 + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
4593 + DEBUGP("not a control packet\n");
4597 + oldsstate = info->sstate;
4598 + oldcstate = info->cstate;
4600 + LOCK_BH(&ip_pptp_lock);
4602 + /* FIXME: We just blindly assume that the control connection is always
4603 + * established from PNS->PAC. However, RFC makes no guarantee */
4604 + if (dir == IP_CT_DIR_ORIGINAL)
4605 + /* client -> server (PNS -> PAC) */
4606 + ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4608 + /* server -> client (PAC -> PNS) */
4609 + ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4610 + DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
4611 + oldsstate, info->sstate, oldcstate, info->cstate);
4612 + UNLOCK_BH(&ip_pptp_lock);
4617 +/* control protocol helper */
4618 +static struct ip_conntrack_helper pptp = {
4619 + .list = { NULL, NULL },
4621 + .flags = IP_CT_HELPER_F_REUSE_EXPECT,
4622 + .me = THIS_MODULE,
4623 + .max_expected = 2,
4625 + .tuple = { .src = { .ip = 0,
4626 + .u = { .tcp = { .port =
4627 + __constant_htons(PPTP_CONTROL_PORT) } }
4630 + .u = { .all = 0 },
4631 + .protonum = IPPROTO_TCP
4634 + .mask = { .src = { .ip = 0,
4635 + .u = { .tcp = { .port = 0xffff } }
4638 + .u = { .all = 0 },
4639 + .protonum = 0xffff
4642 + .help = conntrack_pptp_help
4645 +/* ip_conntrack_pptp initialization */
4646 +static int __init init(void)
4650 + DEBUGP(__FILE__ ": registering helper\n");
4651 + if ((retcode = ip_conntrack_helper_register(&pptp))) {
4652 + printk(KERN_ERR "Unable to register conntrack application "
4653 + "helper for pptp: %d\n", retcode);
4657 + printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
4661 +static void __exit fini(void)
4663 + ip_conntrack_helper_unregister(&pptp);
4664 + printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
4670 +EXPORT_SYMBOL(ip_pptp_lock);
4671 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp_priv.h
4672 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 1970-01-01 01:00:00.000000000 +0100
4673 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 2003-11-17 09:09:34.000000000 +0100
4675 +#ifndef _IP_CT_PPTP_PRIV_H
4676 +#define _IP_CT_PPTP_PRIV_H
4678 +/* PptpControlMessageType names */
4679 +static const char *strMName[] = {
4680 + "UNKNOWN_MESSAGE",
4681 + "START_SESSION_REQUEST",
4682 + "START_SESSION_REPLY",
4683 + "STOP_SESSION_REQUEST",
4684 + "STOP_SESSION_REPLY",
4687 + "OUT_CALL_REQUEST",
4689 + "IN_CALL_REQUEST",
4691 + "IN_CALL_CONNECT",
4692 + "CALL_CLEAR_REQUEST",
4693 + "CALL_DISCONNECT_NOTIFY",
4694 + "WAN_ERROR_NOTIFY",
4699 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_proto_gre.c
4700 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
4701 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2003-11-17 09:09:34.000000000 +0100
4704 + * ip_conntrack_proto_gre.c - Version 1.2
4706 + * Connection tracking protocol helper module for GRE.
4708 + * GRE is a generic encapsulation protocol, which is generally not very
4709 + * suited for NAT, as it has no protocol-specific part as port numbers.
4711 + * It has an optional key field, which may help us distinguishing two
4712 + * connections between the same two hosts.
4714 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
4716 + * PPTP is built on top of a modified version of GRE, and has a mandatory
4717 + * field called "CallID", which serves us for the same purpose as the key
4718 + * field in plain GRE.
4720 + * Documentation about PPTP can be found in RFC 2637
4722 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4724 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4728 +#include <linux/config.h>
4729 +#include <linux/module.h>
4730 +#include <linux/types.h>
4731 +#include <linux/timer.h>
4732 +#include <linux/netfilter.h>
4733 +#include <linux/ip.h>
4734 +#include <linux/in.h>
4735 +#include <linux/list.h>
4737 +#include <linux/netfilter_ipv4/lockhelp.h>
4739 +DECLARE_RWLOCK(ip_ct_gre_lock);
4740 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
4741 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
4743 +#include <linux/netfilter_ipv4/listhelp.h>
4744 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4745 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4746 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4748 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4749 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4751 +MODULE_LICENSE("GPL");
4752 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4753 +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
4755 +/* shamelessly stolen from ip_conntrack_proto_udp.c */
4756 +#define GRE_TIMEOUT (30*HZ)
4757 +#define GRE_STREAM_TIMEOUT (180*HZ)
4760 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4761 + ": " format, ## args)
4762 +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
4763 + NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
4764 + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
4765 + (x)->dst.u.gre.version, \
4766 + ntohs((x)->dst.u.gre.protocol))
4768 +#define DEBUGP(x, args...)
4769 +#define DUMP_TUPLE_GRE(x)
4772 +/* GRE KEYMAP HANDLING FUNCTIONS */
4773 +static LIST_HEAD(gre_keymap_list);
4775 +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
4776 + const struct ip_conntrack_tuple *t)
4778 + return ((km->tuple.src.ip == t->src.ip) &&
4779 + (km->tuple.dst.ip == t->dst.ip) &&
4780 + (km->tuple.dst.protonum == t->dst.protonum) &&
4781 + (km->tuple.dst.u.all == t->dst.u.all));
4784 +/* look up the source key for a given tuple */
4785 +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
4787 + struct ip_ct_gre_keymap *km;
4790 + READ_LOCK(&ip_ct_gre_lock);
4791 + km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
4792 + struct ip_ct_gre_keymap *, t);
4794 + READ_UNLOCK(&ip_ct_gre_lock);
4798 + key = km->tuple.src.u.gre.key;
4799 + READ_UNLOCK(&ip_ct_gre_lock);
4804 +/* add a single keymap entry, associate with specified expect */
4805 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
4806 + struct ip_conntrack_tuple *t, int reply)
4808 + struct ip_ct_gre_keymap *km;
4810 + km = kmalloc(sizeof(*km), GFP_ATOMIC);
4814 + /* initializing list head should be sufficient */
4815 + memset(km, 0, sizeof(*km));
4817 + memcpy(&km->tuple, t, sizeof(*t));
4820 + exp->proto.gre.keymap_orig = km;
4822 + exp->proto.gre.keymap_reply = km;
4824 + DEBUGP("adding new entry %p: ", km);
4825 + DUMP_TUPLE_GRE(&km->tuple);
4827 + WRITE_LOCK(&ip_ct_gre_lock);
4828 + list_append(&gre_keymap_list, km);
4829 + WRITE_UNLOCK(&ip_ct_gre_lock);
4834 +/* change the tuple of a keymap entry (used by nat helper) */
4835 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
4836 + struct ip_conntrack_tuple *t)
4838 + DEBUGP("changing entry %p to: ", km);
4839 + DUMP_TUPLE_GRE(t);
4841 + WRITE_LOCK(&ip_ct_gre_lock);
4842 + memcpy(&km->tuple, t, sizeof(km->tuple));
4843 + WRITE_UNLOCK(&ip_ct_gre_lock);
4846 +/* destroy the keymap entries associated with specified expect */
4847 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
4849 + DEBUGP("entering for exp %p\n", exp);
4850 + WRITE_LOCK(&ip_ct_gre_lock);
4851 + if (exp->proto.gre.keymap_orig) {
4852 + DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
4853 + list_del(&exp->proto.gre.keymap_orig->list);
4854 + kfree(exp->proto.gre.keymap_orig);
4855 + exp->proto.gre.keymap_orig = NULL;
4857 + if (exp->proto.gre.keymap_reply) {
4858 + DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
4859 + list_del(&exp->proto.gre.keymap_reply->list);
4860 + kfree(exp->proto.gre.keymap_reply);
4861 + exp->proto.gre.keymap_reply = NULL;
4863 + WRITE_UNLOCK(&ip_ct_gre_lock);
4867 +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
4869 +/* invert gre part of tuple */
4870 +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
4871 + const struct ip_conntrack_tuple *orig)
4873 + tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
4874 + tuple->dst.u.gre.version = orig->dst.u.gre.version;
4876 + tuple->dst.u.gre.key = orig->src.u.gre.key;
4877 + tuple->src.u.gre.key = orig->dst.u.gre.key;
4882 +/* gre hdr info to tuple */
4883 +static int gre_pkt_to_tuple(const void *datah, size_t datalen,
4884 + struct ip_conntrack_tuple *tuple)
4886 + struct gre_hdr *grehdr = (struct gre_hdr *) datah;
4887 + struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
4890 + /* core guarantees 8 protocol bytes, no need for size check */
4892 + tuple->dst.u.gre.version = grehdr->version;
4893 + tuple->dst.u.gre.protocol = grehdr->protocol;
4895 + switch (grehdr->version) {
4896 + case GRE_VERSION_1701:
4897 + if (!grehdr->key) {
4898 + DEBUGP("Can't track GRE without key\n");
4901 + tuple->dst.u.gre.key = *(gre_key(grehdr));
4904 + case GRE_VERSION_PPTP:
4905 + if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
4906 + DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
4909 + tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
4913 + printk(KERN_WARNING "unknown GRE version %hu\n",
4914 + tuple->dst.u.gre.version);
4918 + srckey = gre_keymap_lookup(tuple);
4921 + DEBUGP("found src key %x for tuple ", ntohl(srckey));
4922 + DUMP_TUPLE_GRE(tuple);
4924 + tuple->src.u.gre.key = srckey;
4929 +/* print gre part of tuple */
4930 +static unsigned int gre_print_tuple(char *buffer,
4931 + const struct ip_conntrack_tuple *tuple)
4933 + return sprintf(buffer, "version=%d protocol=0x%04x srckey=0x%x dstkey=0x%x ",
4934 + tuple->dst.u.gre.version,
4935 + ntohs(tuple->dst.u.gre.protocol),
4936 + ntohl(tuple->src.u.gre.key),
4937 + ntohl(tuple->dst.u.gre.key));
4940 +/* print private data for conntrack */
4941 +static unsigned int gre_print_conntrack(char *buffer,
4942 + const struct ip_conntrack *ct)
4944 + return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
4945 + (ct->proto.gre.timeout / HZ),
4946 + (ct->proto.gre.stream_timeout / HZ));
4949 +/* Returns verdict for packet, and may modify conntrack */
4950 +static int gre_packet(struct ip_conntrack *ct,
4951 + struct iphdr *iph, size_t len,
4952 + enum ip_conntrack_info conntrackinfo)
4954 + /* If we've seen traffic both ways, this is a GRE connection.
4955 + * Extend timeout. */
4956 + if (ct->status & IPS_SEEN_REPLY) {
4957 + ip_ct_refresh(ct, ct->proto.gre.stream_timeout);
4958 + /* Also, more likely to be important, and not a probe. */
4959 + set_bit(IPS_ASSURED_BIT, &ct->status);
4961 + ip_ct_refresh(ct, ct->proto.gre.timeout);
4966 +/* Called when a new connection for this protocol found. */
4967 +static int gre_new(struct ip_conntrack *ct,
4968 + struct iphdr *iph, size_t len)
4971 + DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4973 + /* initialize to sane value. Ideally a conntrack helper
4974 + * (e.g. in case of pptp) is increasing them */
4975 + ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
4976 + ct->proto.gre.timeout = GRE_TIMEOUT;
4981 +/* Called when a conntrack entry has already been removed from the hashes
4982 + * and is about to be deleted from memory */
4983 +static void gre_destroy(struct ip_conntrack *ct)
4985 + struct ip_conntrack_expect *master = ct->master;
4987 + DEBUGP(" entering\n");
4990 + DEBUGP("no master exp for ct %p\n", ct);
4994 + ip_ct_gre_keymap_destroy(master);
4997 +/* protocol helper struct */
4998 +static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
5003 + gre_print_conntrack,
5010 +/* ip_conntrack_proto_gre initialization */
5011 +static int __init init(void)
5015 + if ((retcode = ip_conntrack_protocol_register(&gre))) {
5016 + printk(KERN_ERR "Unable to register conntrack protocol "
5017 + "helper for gre: %d\n", retcode);
5024 +static void __exit fini(void)
5026 + struct list_head *pos, *n;
5028 + /* delete all keymap entries */
5029 + WRITE_LOCK(&ip_ct_gre_lock);
5030 + list_for_each_safe(pos, n, &gre_keymap_list) {
5031 + DEBUGP("deleting keymap %p at module unload time\n", pos);
5035 + WRITE_UNLOCK(&ip_ct_gre_lock);
5037 + ip_conntrack_protocol_unregister(&gre);
5040 +EXPORT_SYMBOL(ip_ct_gre_keymap_add);
5041 +EXPORT_SYMBOL(ip_ct_gre_keymap_change);
5042 +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
5046 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_quake3.c
5047 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
5048 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_quake3.c 2003-12-11 10:24:00.845688024 +0100
5050 +/* Quake3 extension for IP connection tracking
5051 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5052 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5054 + * ip_conntrack_quake3.c v0.04 2002-08-31
5056 + * This program is free software; you can redistribute it and/or
5057 + * modify it under the terms of the GNU General Public License
5058 + * as published by the Free Software Foundation; either version
5059 + * 2 of the License, or (at your option) any later version.
5061 + * Module load syntax:
5062 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5064 + * please give the ports of all Quake3 master servers You wish to
5065 + * connect to. If you don't specify ports, the default will be UDP
5068 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5071 +#include <linux/module.h>
5072 +#include <linux/ip.h>
5073 +#include <linux/udp.h>
5075 +#include <linux/netfilter.h>
5076 +#include <linux/netfilter_ipv4/ip_tables.h>
5077 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5078 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5080 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5082 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5083 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5084 +MODULE_LICENSE("GPL");
5086 +#define MAX_PORTS 8
5087 +static int ports[MAX_PORTS];
5088 +static int ports_c = 0;
5090 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5091 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5094 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5095 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5097 +#define DEBUGP printk
5099 +#define DEBUGP(format, args...)
5102 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5104 +static int quake3_help(const struct iphdr *iph, size_t len,
5105 + struct ip_conntrack *ct,
5106 + enum ip_conntrack_info ctinfo)
5108 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5109 + int dir = CTINFO2DIR(ctinfo);
5110 + struct ip_conntrack_expect exp;
5113 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5114 + if (ctinfo != IP_CT_ESTABLISHED
5115 + && ctinfo != IP_CT_IS_REPLY) {
5116 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5118 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5120 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5121 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5122 + i+6 < ntohs(udph->len);
5124 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5125 + i, ntohs(udph->len),
5126 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
5127 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5129 + memset(&exp, 0, sizeof(exp));
5131 + exp.tuple = ((struct ip_conntrack_tuple)
5132 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5133 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
5134 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
5137 + exp.mask = ((struct ip_conntrack_tuple)
5138 + { { 0xFFFFFFFF, { 0 } },
5139 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5140 + exp.expectfn = NULL;
5142 + ip_conntrack_expect_related(ct, &exp);
5147 + return(NF_ACCEPT);
5150 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5151 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
5153 +static void fini(void)
5157 + for(i = 0 ; (i < ports_c); i++) {
5158 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5160 + ip_conntrack_helper_unregister(&quake3[i]);
5164 +static int __init init(void)
5170 + ports[0]=QUAKE3_MASTER_PORT;
5172 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5173 + /* Create helper structure */
5174 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5176 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5177 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5178 + quake3[i].mask.dst.protonum = 0xFFFF;
5179 + quake3[i].mask.src.u.udp.port = 0xFFFF;
5180 + quake3[i].help = quake3_help;
5181 + quake3[i].me = THIS_MODULE;
5183 + tmpname = &quake3_names[i][0];
5184 + if (ports[i] == QUAKE3_MASTER_PORT)
5185 + sprintf(tmpname, "quake3");
5187 + sprintf(tmpname, "quake3-%d", i);
5188 + quake3[i].name = tmpname;
5190 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5193 + ret=ip_conntrack_helper_register(&quake3[i]);
5206 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
5207 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
5208 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2003-12-11 10:24:04.352154960 +0100
5210 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
5211 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5212 + * - original rpc tracking module
5213 + * - "recent" connection handling for kernel 2.3+ netfilter
5215 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5216 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5218 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5219 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
5220 + * - extended matching to support filtering on procedures
5222 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
5224 + * This program is free software; you can redistribute it and/or
5225 + * modify it under the terms of the GNU General Public License
5226 + * as published by the Free Software Foundation; either version
5227 + * 2 of the License, or (at your option) any later version.
5229 + * Module load syntax:
5230 + * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
5232 + * Please give the ports of all RPC servers you wish to connect to.
5233 + * If you don't specify ports, the default will be port 111.
5237 + * RPCs should not be exposed to the internet - ask the Pentagon;
5239 + * "The unidentified crackers pleaded guilty in July to charges
5240 + * of juvenile delinquency stemming from a string of Pentagon
5241 + * network intrusions in February.
5243 + * The youths, going by the names TooShort and Makaveli, used
5244 + * a common server security hole to break in, according to
5245 + * Dane Jasper, owner of the California Internet service
5246 + * provider, Sonic. They used the hole, known as the 'statd'
5247 + * exploit, to attempt more than 800 break-ins, Jasper said."
5249 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5250 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
5254 +#include <linux/module.h>
5255 +#include <linux/netfilter.h>
5256 +#include <linux/ip.h>
5257 +#include <net/checksum.h>
5258 +#include <net/tcp.h>
5260 +#include <asm/param.h>
5261 +#include <linux/sched.h>
5262 +#include <linux/timer.h>
5263 +#include <linux/stddef.h>
5264 +#include <linux/list.h>
5266 +#include <linux/netfilter_ipv4/lockhelp.h>
5267 +#include <linux/netfilter_ipv4/ip_tables.h>
5268 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5269 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5271 +#define MAX_PORTS 8
5272 +static int ports[MAX_PORTS];
5273 +static int ports_n_c = 0;
5276 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5277 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5280 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5281 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
5282 +MODULE_LICENSE("GPL");
5285 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
5288 +#define DEBUGP(format, args...)
5291 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
5292 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
5293 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
5294 +#include <linux/netfilter_ipv4/listhelp.h>
5296 +/* For future conections RPC, using client's cache bindings
5297 + * I'll use ip_conntrack_lock to lock these lists */
5299 +LIST_HEAD(request_p_list_tcp);
5302 +static void delete_request_p(unsigned long request_p_ul)
5304 + struct request_p *p = (void *)request_p_ul;
5306 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5307 + LIST_DELETE(&request_p_list_tcp, p);
5308 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5314 +static void req_cl(struct request_p * r)
5316 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5317 + del_timer(&r->timeout);
5318 + LIST_DELETE(&request_p_list_tcp, r);
5319 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5325 +static void clean_request(struct list_head *list)
5327 + struct list_head *first = list->prev;
5328 + struct list_head *temp = list->next;
5329 + struct list_head *aux;
5331 + if (list_empty(list))
5334 + while (first != temp) {
5336 + req_cl((struct request_p *)temp);
5339 + req_cl((struct request_p *)temp);
5344 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5347 + struct request_p *req_p;
5349 + /* Verifies if entry already exists */
5350 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5351 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5352 + struct request_p *, xid, ip, port);
5355 + /* Refresh timeout */
5356 + if (del_timer(&req_p->timeout)) {
5357 + req_p->timeout.expires = jiffies + EXP;
5358 + add_timer(&req_p->timeout);
5360 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5364 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5366 + /* Allocate new request_p */
5367 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5369 + DEBUGP("can't allocate request_p\n");
5372 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
5373 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5376 + /* Initialize timer */
5377 + init_timer(&req_p->timeout);
5378 + req_p->timeout.function = delete_request_p;
5379 + add_timer(&req_p->timeout);
5382 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5383 + list_prepend(&request_p_list_tcp, req_p);
5384 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5390 +static int check_rpc_packet(const u_int32_t *data,
5391 + int dir, struct ip_conntrack *ct,
5392 + struct list_head request_p_list)
5394 + struct request_p *req_p;
5396 + struct ip_conntrack_expect expect, *exp = &expect;
5398 + /* Translstion's buffer for XDR */
5399 + u_int16_t port_buf;
5405 + /* This does sanity checking on RPC payloads,
5406 + * and permits only the RPC "get port" (3)
5407 + * in authorised procedures in client
5408 + * communications with the portmapper.
5411 + /* perform direction dependant RPC work */
5412 + if (dir == IP_CT_DIR_ORIGINAL) {
5416 + /* Get RPC requestor */
5417 + if (IXDR_GET_INT32(data) != 3) {
5418 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5421 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5425 + /* Jump Credentials and Verfifier */
5426 + data += IXDR_GET_INT32(data) + 2;
5427 + data += IXDR_GET_INT32(data) + 2;
5429 + /* Get RPC procedure */
5430 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5431 + (unsigned int)IXDR_GET_INT32(data));
5433 + /* Get RPC protocol and store against client parameters */
5435 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5436 + ct->tuplehash[dir].tuple.src.u.all);
5438 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5439 + xid, IXDR_GET_INT32(data),
5440 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5441 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
5443 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
5444 + (unsigned int)IXDR_GET_INT32(data));
5448 + /* Check for returning packet's stored counterpart */
5449 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5450 + struct request_p *, xid,
5451 + ct->tuplehash[!dir].tuple.src.ip,
5452 + ct->tuplehash[!dir].tuple.src.u.all);
5454 + /* Drop unexpected packets */
5456 + DEBUGP("packet is not expected. [skip]\n");
5460 + /* Verifies if packet is really an RPC reply packet */
5462 + if (IXDR_GET_INT32(data) != 1) {
5463 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
5467 + /* Is status accept? */
5469 + if (IXDR_GET_INT32(data)) {
5470 + DEBUGP("packet is not an RPC accept. [skip]\n");
5474 + /* Get Verifier length. Jump verifier */
5476 + data = data + IXDR_GET_INT32(data) + 2;
5478 + /* Is accpet status "success"? */
5479 + if (IXDR_GET_INT32(data)) {
5480 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5484 + /* Get server port number */
5486 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
5488 + /* If a packet has made it this far then it deserves an
5489 + * expectation ... if port == 0, then this service is
5490 + * not going to be registered.
5493 + DEBUGP("port found: %u\n", port_buf);
5495 + memset(&expect, 0, sizeof(expect));
5497 + /* Watch out, Radioactive-Man! */
5498 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5499 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5500 + exp->mask.src.ip = 0xffffffff;
5501 + exp->mask.dst.ip = 0xffffffff;
5503 + switch (req_p->proto) {
5505 + exp->tuple.src.u.udp.port = 0;
5506 + exp->tuple.dst.u.udp.port = htons(port_buf);
5507 + exp->tuple.dst.protonum = IPPROTO_UDP;
5508 + exp->mask.src.u.udp.port = 0;
5509 + exp->mask.dst.u.udp.port = htons(0xffff);
5510 + exp->mask.dst.protonum = 0xffff;
5514 + exp->tuple.src.u.tcp.port = 0;
5515 + exp->tuple.dst.u.tcp.port = htons(port_buf);
5516 + exp->tuple.dst.protonum = IPPROTO_TCP;
5517 + exp->mask.src.u.tcp.port = 0;
5518 + exp->mask.dst.u.tcp.port = htons(0xffff);
5519 + exp->mask.dst.protonum = 0xffff;
5522 + exp->expectfn = NULL;
5524 + ip_conntrack_expect_related(ct, &expect);
5526 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
5527 + NIPQUAD(exp->tuple.src.ip),
5528 + NIPQUAD(exp->tuple.dst.ip),
5529 + port_buf, req_p->proto);
5531 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
5532 + NIPQUAD(exp->mask.src.ip),
5533 + NIPQUAD(exp->mask.dst.ip),
5534 + exp->mask.dst.protonum);
5540 + DEBUGP("packet evaluated. [expect]\n");
5549 +/* RPC TCP helper */
5550 +static int help(const struct iphdr *iph, size_t len,
5551 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5553 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5554 + const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
5555 + size_t tcplen = len - iph->ihl * 4;
5557 + int dir = CTINFO2DIR(ctinfo);
5561 + DEBUGP("new packet to evaluate ..\n");
5563 + /* This works for packets like handshake packets, ignore */
5564 + if (len == ((tcph->doff + iph->ihl) * 4)) {
5565 + DEBUGP("packet has no data (may still be handshaking). [skip]\n");
5569 + /* Until there's been traffic both ways, don't look in packets. */
5570 + if (ctinfo != IP_CT_ESTABLISHED
5571 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5572 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
5573 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
5574 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
5578 + /* Not whole TCP header? */
5579 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5580 + DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
5581 + DEBUGP("packet does not contain a complete TCP header. [skip]\n");
5585 + /* FIXME: Source route IP option packets --RR */
5586 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5587 + csum_partial((char *) tcph, tcplen, 0))) {
5588 + DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5589 + tcph, tcplen, NIPQUAD(iph->saddr),
5590 + NIPQUAD(iph->daddr));
5591 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
5592 + DEBUGP("packet contains a bad checksum. [skip]\n");
5596 + /* perform direction dependant protocol work */
5597 + if (dir == IP_CT_DIR_ORIGINAL) {
5599 + DEBUGP("packet is from the initiator. [cont]\n");
5601 + /* Tests if packet len is ok */
5602 + if ((tcplen - (tcph->doff * 4)) != 60) {
5603 + DEBUGP("packet length is not correct. [skip]\n");
5609 + DEBUGP("packet is from the receiver. [cont]\n");
5611 + /* Tests if packet len is ok */
5612 + if ((tcplen - (tcph->doff * 4)) != 32) {
5613 + DEBUGP("packet length is not correct. [skip]\n");
5618 + /* Get to the data */
5621 + /* Check the RPC data */
5622 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
5629 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
5631 +static void fini(void);
5634 +static int __init init(void)
5637 + static char name[10];
5640 + /* If no port given, default to standard RPC port */
5641 + if (ports[0] == 0)
5642 + ports[0] = RPC_PORT;
5644 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5645 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5647 + if (ports[port] == RPC_PORT)
5648 + sprintf(name, "rpc");
5650 + sprintf(name, "rpc-%d", port);
5652 + rpc_helpers[port].name = name;
5653 + rpc_helpers[port].me = THIS_MODULE;
5654 + rpc_helpers[port].max_expected = 1;
5655 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5656 + rpc_helpers[port].timeout = 0;
5658 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5659 + rpc_helpers[port].mask.dst.protonum = 0xffff;
5661 + /* RPC can come from ports 0:65535 to ports[port] (111) */
5662 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
5663 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
5664 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
5666 + rpc_helpers[port].help = help;
5668 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5669 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5670 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
5671 + ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
5672 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
5673 + ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
5674 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5675 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
5676 + ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
5677 + NIPQUAD(rpc_helpers[port].mask.src.ip),
5678 + ntohs(rpc_helpers[port].mask.src.u.tcp.port));
5680 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
5683 + printk("ERROR registering port %d\n",
5694 +/* This function is intentionally _NOT_ defined as __exit, because
5695 + * it is needed by the init function */
5696 +static void fini(void)
5700 + DEBUGP("cleaning request list\n");
5701 + clean_request(&request_p_list_tcp);
5703 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
5704 + DEBUGP("unregistering port %d\n", ports[port]);
5705 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
5713 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
5714 +EXPORT_SYMBOL(request_p_list_tcp);
5715 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
5716 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
5718 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
5719 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
5720 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2003-12-11 10:24:04.353154808 +0100
5722 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
5723 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5724 + * - original rpc tracking module
5725 + * - "recent" connection handling for kernel 2.3+ netfilter
5727 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5728 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5730 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5731 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
5732 + * - extended matching to support filtering on procedures
5734 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
5736 + * This program is free software; you can redistribute it and/or
5737 + * modify it under the terms of the GNU General Public License
5738 + * as published by the Free Software Foundation; either version
5739 + * 2 of the License, or (at your option) any later version.
5741 + * Module load syntax:
5742 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
5744 + * Please give the ports of all RPC servers you wish to connect to.
5745 + * If you don't specify ports, the default will be port 111.
5749 + * RPCs should not be exposed to the internet - ask the Pentagon;
5751 + * "The unidentified crackers pleaded guilty in July to charges
5752 + * of juvenile delinquency stemming from a string of Pentagon
5753 + * network intrusions in February.
5755 + * The youths, going by the names TooShort and Makaveli, used
5756 + * a common server security hole to break in, according to
5757 + * Dane Jasper, owner of the California Internet service
5758 + * provider, Sonic. They used the hole, known as the 'statd'
5759 + * exploit, to attempt more than 800 break-ins, Jasper said."
5761 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5762 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
5766 +#include <linux/module.h>
5767 +#include <linux/netfilter.h>
5768 +#include <linux/ip.h>
5769 +#include <net/checksum.h>
5770 +#include <net/udp.h>
5772 +#include <asm/param.h>
5773 +#include <linux/sched.h>
5774 +#include <linux/timer.h>
5775 +#include <linux/stddef.h>
5776 +#include <linux/list.h>
5778 +#include <linux/netfilter_ipv4/lockhelp.h>
5779 +#include <linux/netfilter_ipv4/ip_tables.h>
5780 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5781 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5783 +#define MAX_PORTS 8
5784 +static int ports[MAX_PORTS];
5785 +static int ports_n_c = 0;
5788 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5789 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5792 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5793 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
5794 +MODULE_LICENSE("GPL");
5797 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
5800 +#define DEBUGP(format, args...)
5803 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
5804 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
5805 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
5806 +#include <linux/netfilter_ipv4/listhelp.h>
5808 +/* For future conections RPC, using client's cache bindings
5809 + * I'll use ip_conntrack_lock to lock these lists */
5811 +LIST_HEAD(request_p_list_udp);
5814 +static void delete_request_p(unsigned long request_p_ul)
5816 + struct request_p *p = (void *)request_p_ul;
5818 + WRITE_LOCK(&ipct_rpc_udp_lock);
5819 + LIST_DELETE(&request_p_list_udp, p);
5820 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5826 +static void req_cl(struct request_p * r)
5828 + WRITE_LOCK(&ipct_rpc_udp_lock);
5829 + del_timer(&r->timeout);
5830 + LIST_DELETE(&request_p_list_udp, r);
5831 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5837 +static void clean_request(struct list_head *list)
5839 + struct list_head *first = list->prev;
5840 + struct list_head *temp = list->next;
5841 + struct list_head *aux;
5843 + if (list_empty(list))
5846 + while (first != temp) {
5848 + req_cl((struct request_p *)temp);
5851 + req_cl((struct request_p *)temp);
5856 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5859 + struct request_p *req_p;
5861 + /* Verifies if entry already exists */
5862 + WRITE_LOCK(&ipct_rpc_udp_lock);
5863 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5864 + struct request_p *, xid, ip, port);
5867 + /* Refresh timeout */
5868 + if (del_timer(&req_p->timeout)) {
5869 + req_p->timeout.expires = jiffies + EXP;
5870 + add_timer(&req_p->timeout);
5872 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5876 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5878 + /* Allocate new request_p */
5879 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5881 + DEBUGP("can't allocate request_p\n");
5884 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
5885 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5888 + /* Initialize timer */
5889 + init_timer(&req_p->timeout);
5890 + req_p->timeout.function = delete_request_p;
5891 + add_timer(&req_p->timeout);
5894 + WRITE_LOCK(&ipct_rpc_udp_lock);
5895 + list_prepend(&request_p_list_udp, req_p);
5896 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5902 +static int check_rpc_packet(const u_int32_t *data,
5903 + int dir, struct ip_conntrack *ct,
5904 + struct list_head request_p_list)
5906 + struct request_p *req_p;
5908 + struct ip_conntrack_expect expect, *exp = &expect;
5910 + /* Translstion's buffer for XDR */
5911 + u_int16_t port_buf;
5917 + /* This does sanity checking on RPC payloads,
5918 + * and permits only the RPC "get port" (3)
5919 + * in authorised procedures in client
5920 + * communications with the portmapper.
5923 + /* perform direction dependant RPC work */
5924 + if (dir == IP_CT_DIR_ORIGINAL) {
5928 + /* Get RPC requestor */
5929 + if (IXDR_GET_INT32(data) != 3) {
5930 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5933 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5937 + /* Jump Credentials and Verfifier */
5938 + data = data + IXDR_GET_INT32(data) + 2;
5939 + data = data + IXDR_GET_INT32(data) + 2;
5941 + /* Get RPC procedure */
5942 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5943 + (unsigned int)IXDR_GET_INT32(data));
5945 + /* Get RPC protocol and store against client parameters */
5947 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5948 + ct->tuplehash[dir].tuple.src.u.all);
5950 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5951 + xid, IXDR_GET_INT32(data),
5952 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5953 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
5955 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
5956 + (unsigned int)IXDR_GET_INT32(data));
5960 + /* Check for returning packet's stored counterpart */
5961 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5962 + struct request_p *, xid,
5963 + ct->tuplehash[!dir].tuple.src.ip,
5964 + ct->tuplehash[!dir].tuple.src.u.all);
5966 + /* Drop unexpected packets */
5968 + DEBUGP("packet is not expected. [skip]\n");
5972 + /* Verifies if packet is really an RPC reply packet */
5974 + if (IXDR_GET_INT32(data) != 1) {
5975 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
5979 + /* Is status accept? */
5981 + if (IXDR_GET_INT32(data)) {
5982 + DEBUGP("packet is not an RPC accept. [skip]\n");
5986 + /* Get Verifier length. Jump verifier */
5988 + data = data + IXDR_GET_INT32(data) + 2;
5990 + /* Is accpet status "success"? */
5991 + if (IXDR_GET_INT32(data)) {
5992 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5996 + /* Get server port number */
5998 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
6000 + /* If a packet has made it this far then it deserves an
6001 + * expectation ... if port == 0, then this service is
6002 + * not going to be registered.
6005 + DEBUGP("port found: %u\n", port_buf);
6007 + memset(&expect, 0, sizeof(expect));
6009 + /* Watch out, Radioactive-Man! */
6010 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6011 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
6012 + exp->mask.src.ip = 0xffffffff;
6013 + exp->mask.dst.ip = 0xffffffff;
6015 + switch (req_p->proto) {
6017 + exp->tuple.src.u.udp.port = 0;
6018 + exp->tuple.dst.u.udp.port = htons(port_buf);
6019 + exp->tuple.dst.protonum = IPPROTO_UDP;
6020 + exp->mask.src.u.udp.port = 0;
6021 + exp->mask.dst.u.udp.port = htons(0xffff);
6022 + exp->mask.dst.protonum = 0xffff;
6026 + exp->tuple.src.u.tcp.port = 0;
6027 + exp->tuple.dst.u.tcp.port = htons(port_buf);
6028 + exp->tuple.dst.protonum = IPPROTO_TCP;
6029 + exp->mask.src.u.tcp.port = 0;
6030 + exp->mask.dst.u.tcp.port = htons(0xffff);
6031 + exp->mask.dst.protonum = 0xffff;
6034 + exp->expectfn = NULL;
6036 + ip_conntrack_expect_related(ct, &expect);
6038 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
6039 + NIPQUAD(exp->tuple.src.ip),
6040 + NIPQUAD(exp->tuple.dst.ip),
6041 + port_buf, req_p->proto);
6043 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
6044 + NIPQUAD(exp->mask.src.ip),
6045 + NIPQUAD(exp->mask.dst.ip),
6046 + exp->mask.dst.protonum);
6052 + DEBUGP("packet evaluated. [expect]\n");
6061 +/* RPC UDP helper */
6062 +static int help(const struct iphdr *iph, size_t len,
6063 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6065 + struct udphdr *udph = (void *) iph + iph->ihl * 4;
6066 + const u_int32_t *data = (const u_int32_t *)udph + 2;
6067 + size_t udplen = len - iph->ihl * 4;
6068 + int dir = CTINFO2DIR(ctinfo);
6072 + const u_int16_t *chsm = (const u_int16_t *)udph + 3;
6075 + DEBUGP("new packet to evaluate ..\n");
6077 + /* Not whole UDP header? */
6078 + if (udplen < sizeof(struct udphdr)) {
6079 + DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
6080 + DEBUGP("packet does not contain a complete UDP header. [skip]\n");
6084 + /* FIXME: Source route IP option packets --RR */
6086 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6087 + csum_partial((char *)udph, udplen, 0))) {
6088 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
6089 + DEBUGP("packet contains a bad checksum. [skip]\n");
6094 + /* perform direction dependant protocol work */
6095 + if (dir == IP_CT_DIR_ORIGINAL) {
6097 + DEBUGP("packet is from the initiator. [cont]\n");
6099 + /* Tests if packet len is ok */
6100 + if ((udplen - sizeof(struct udphdr)) != 56) {
6101 + DEBUGP("packet length is not correct. [skip]\n");
6107 + DEBUGP("packet is from the receiver. [cont]\n");
6109 + /* Until there's been traffic both ways, don't look in packets. */
6110 + if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6111 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
6112 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
6113 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
6117 + /* Tests if packet len is ok */
6118 + if ((udplen - sizeof(struct udphdr)) != 28) {
6119 + DEBUGP("packet length is not correct. [skip]\n");
6125 + /* Get to the data */
6126 + /* udp *data == *correct */
6128 + /* Check the RPC data */
6129 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
6136 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
6138 +static void fini(void);
6141 +static int __init init(void)
6144 + static char name[10];
6147 + /* If no port given, default to standard RPC port */
6148 + if (ports[0] == 0)
6149 + ports[0] = RPC_PORT;
6151 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6152 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6154 + if (ports[port] == RPC_PORT)
6155 + sprintf(name, "rpc");
6157 + sprintf(name, "rpc-%d", port);
6159 + rpc_helpers[port].name = name;
6160 + rpc_helpers[port].me = THIS_MODULE;
6161 + rpc_helpers[port].max_expected = 1;
6162 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6163 + rpc_helpers[port].timeout = 0;
6165 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
6166 + rpc_helpers[port].mask.dst.protonum = 0xffff;
6168 + /* RPC can come from ports 0:65535 to ports[port] (111) */
6169 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
6170 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
6171 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
6173 + rpc_helpers[port].help = help;
6175 + DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
6176 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6177 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
6178 + ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
6179 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
6180 + ntohs(rpc_helpers[port].tuple.src.u.udp.port));
6181 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6182 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
6183 + ntohs(rpc_helpers[port].mask.dst.u.udp.port),
6184 + NIPQUAD(rpc_helpers[port].mask.src.ip),
6185 + ntohs(rpc_helpers[port].mask.src.u.udp.port));
6187 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
6190 + printk("ERROR registering port %d\n",
6201 +/* This function is intentionally _NOT_ defined as __exit, because
6202 + * it is needed by the init function */
6203 +static void fini(void)
6207 + DEBUGP("cleaning request list\n");
6208 + clean_request(&request_p_list_udp);
6210 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
6211 + DEBUGP("unregistering port %d\n", ports[port]);
6212 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
6220 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
6221 +EXPORT_SYMBOL(request_p_list_udp);
6222 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
6223 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
6225 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rsh.c
6226 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
6227 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rsh.c 2003-12-11 10:24:05.587967088 +0100
6229 +/* RSH extension for IP connection tracking, Version 1.0
6230 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
6231 + * based on HW's ip_conntrack_irc.c
6233 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
6235 + * This program is free software; you can redistribute it and/or
6236 + * modify it under the terms of the GNU General Public License
6237 + * as published by the Free Software Foundation; either version
6238 + * 2 of the License, or (at your option) any later version.
6240 + * Module load syntax:
6241 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
6243 + * please give the ports of all RSH servers You wish to connect to.
6244 + * If You don't specify ports, the default will be port 514
6247 + * RSH blows ... you should use SSH (openssh.org) to replace it,
6248 + * unfortunately I babysit some sysadmins that won't migrate
6249 + * their legacy crap, in our second tier.
6254 + * Some docco ripped from the net to teach me all there is to know about
6255 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
6258 + * I have no idea what "unix rshd man pages" these guys have .. but that
6259 + * is some pretty detailed docco!
6262 + * 4. Of the rsh protocol.
6263 + * -----------------------
6265 + * The rshd listens on TCP port #514. The following info is from the unix
6266 + * rshd man pages :
6268 + * "Service Request Protocol
6270 + * When the rshd daemon receives a service request, it initiates the
6271 + * following protocol:
6273 + * 1. The rshd daemon checks the source port number for the request.
6274 + * If the port number is not in the range 0 through 1023, the rshd daemon
6275 + * terminates the connection.
6277 + * 2. The rshd daemon reads characters from the socket up to a null byte.
6278 + * The string read is interpreted as an ASCII number (base 10). If this
6279 + * number is nonzero, the rshd daemon interprets it as the port number
6280 + * of a secondary stream to be used as standard error. A second connection
6281 + * is created to the specified port on the client host. The source port
6282 + * on the local host is in the range 0 through 1023.
6284 + * 3. The rshd daemon uses the source address of the initial connection
6285 + * request to determine the name of the client host. If the name cannot
6286 + * be determined, the rshd daemon uses the dotted decimal representation
6287 + * of the client host's address.
6289 + * 4. The rshd daemon retrieves the following information from the initial
6292 + * * A null-terminated string of at most 16 bytes interpreted as
6293 + * the user name of the user on the client host.
6295 + * * A null-terminated string of at most 16 bytes interpreted as
6296 + * the user name to be used on the local server host.
6298 + * * Another null-terminated string interpreted as a command line
6299 + * to be passed to a shell on the local server host.
6301 + * 5. The rshd daemon attempts to validate the user using the following steps:
6303 + * a. The rshd daemon looks up the local user name in the /etc/passwd
6304 + * file and tries to switch to the home directory (using the chdir
6305 + * subroutine). If either the lookup or the directory change fails,
6306 + * the rshd daemon terminates the connection.
6308 + * b. If the local user ID is a nonzero value, the rshd daemon searches
6309 + * the /etc/hosts.equiv file to see if the name of the client
6310 + * workstation is listed. If the client workstation is listed as an
6311 + * equivalent host, the rshd daemon validates the user.
6313 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
6314 + * authenticate the user by checking the .rhosts file.
6316 + * d. If either the $HOME/.rhosts authentication fails or the
6317 + * client host is not an equivalent host, the rshd daemon
6318 + * terminates the connection.
6320 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
6321 + * on the initial connection and passes the command line to the user's
6322 + * local login shell. The shell then inherits the network connections
6323 + * established by the rshd daemon."
6328 +#include <linux/module.h>
6329 +#include <linux/netfilter.h>
6330 +#include <linux/ip.h>
6331 +#include <net/checksum.h>
6332 +#include <net/tcp.h>
6334 +#include <linux/netfilter_ipv4/lockhelp.h>
6335 +#include <linux/netfilter_ipv4/ip_tables.h>
6336 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6337 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
6339 +#define MAX_PORTS 8
6340 +static int ports[MAX_PORTS];
6341 +static int ports_n_c = 0;
6343 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
6344 +MODULE_DESCRIPTION("RSH connection tracking module");
6345 +MODULE_LICENSE("GPL");
6347 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6348 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
6351 +DECLARE_LOCK(ip_rsh_lock);
6352 +struct module *ip_conntrack_rsh = THIS_MODULE;
6355 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
6358 +#define DEBUGP(format, args...)
6363 +/* FIXME: This should be in userspace. Later. */
6364 +static int help(const struct iphdr *iph, size_t len,
6365 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6367 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6368 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6369 + const char *data = (const char *) tcph + tcph->doff * 4;
6370 + u_int32_t tcplen = len - iph->ihl * 4;
6371 + int dir = CTINFO2DIR(ctinfo);
6372 + struct ip_conntrack_expect expect, *exp = &expect;
6373 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
6377 + /* note that "maxoctet" is used to maintain sanity (8 was the
6378 + * original array size used in rshd/glibc) -- is there a
6379 + * vulnerability in rshd.c in the looped port *= 10?
6383 + DEBUGP("entered\n");
6385 + /* bail if packet is not from RSH client */
6386 + if (dir == IP_CT_DIR_REPLY)
6389 + /* Until there's been traffic both ways, don't look in packets. */
6390 + if (ctinfo != IP_CT_ESTABLISHED
6391 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6392 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
6396 + /* Not whole TCP header? */
6397 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
6398 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
6402 + /* Checksum invalid? Ignore. */
6403 + /* FIXME: Source route IP option packets --RR */
6404 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6405 + csum_partial((char *) tcph, tcplen, 0))) {
6406 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6407 + tcph, tcplen, NIPQUAD(iph->saddr),
6408 + NIPQUAD(iph->daddr));
6412 + /* find the rsh stderr port */
6415 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
6420 + if (*data < 48 || *data > 57) {
6421 + DEBUGP("these aren't the packets you're looking for ..\n");
6424 + port = port * 10 + ( *data - 48 );
6427 + /* dont relate sessions that try to expose the client */
6428 + DEBUGP("found port %u\n", port);
6429 + if (port > 1023) {
6430 + DEBUGP("skipping, expected port size is greater than 1023!\n");
6435 + LOCK_BH(&ip_rsh_lock);
6437 + /* new(,related) connection is;
6438 + * reply + dst (uint)port + src port (0:1023)
6440 + memset(&expect, 0, sizeof(expect));
6442 + /* save some discovered data, in case someone ever wants to write
6443 + * a NAT module for this bastard ..
6445 + exp_rsh_info->port = port;
6447 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
6450 + /* Watch out, Radioactive-Man! */
6451 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6452 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
6453 + exp->tuple.src.u.tcp.port = 0;
6454 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
6455 + exp->tuple.dst.protonum = IPPROTO_TCP;
6457 + exp->mask.src.ip = 0xffffffff;
6458 + exp->mask.dst.ip = 0xffffffff;
6460 + exp->mask.src.u.tcp.port = htons(0xfc00);
6461 + exp->mask.dst.u.tcp.port = htons(0xfc00);
6462 + exp->mask.dst.protonum = 0xffff;
6464 + exp->expectfn = NULL;
6466 + ip_conntrack_expect_related(ct, &expect);
6468 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6469 + NIPQUAD(exp->tuple.src.ip),
6470 + ntohs(exp->tuple.src.u.tcp.port),
6471 + NIPQUAD(exp->tuple.dst.ip),
6472 + ntohs(exp->tuple.dst.u.tcp.port));
6474 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6475 + NIPQUAD(exp->mask.src.ip),
6476 + ntohs(exp->mask.src.u.tcp.port),
6477 + NIPQUAD(exp->mask.dst.ip),
6478 + ntohs(exp->mask.dst.u.tcp.port));
6479 + UNLOCK_BH(&ip_rsh_lock);
6484 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
6486 +static void fini(void);
6488 +static int __init init(void)
6491 + static char name[10];
6494 + /* If no port given, default to standard RSH port */
6495 + if (ports[0] == 0)
6496 + ports[0] = RSH_PORT;
6498 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6499 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6501 + if (ports[port] == RSH_PORT)
6502 + sprintf(name, "rsh");
6504 + sprintf(name, "rsh-%d", port);
6506 + rsh_helpers[port].name = name;
6507 + rsh_helpers[port].me = THIS_MODULE;
6508 + rsh_helpers[port].max_expected = 1;
6509 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6510 + rsh_helpers[port].timeout = 0;
6512 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
6513 + rsh_helpers[port].mask.dst.protonum = 0xffff;
6515 + /* RSH must come from ports 0:1023 to ports[port] (514) */
6516 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
6517 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
6518 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
6520 + rsh_helpers[port].help = help;
6522 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
6523 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6524 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
6525 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
6526 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
6527 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
6528 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6529 + NIPQUAD(rsh_helpers[port].mask.src.ip),
6530 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
6531 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
6532 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
6534 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
6537 + printk("ERROR registering port %d\n",
6547 +/* This function is intentionally _NOT_ defined as __exit, because
6548 + * it is needed by the init function */
6549 +static void fini(void)
6552 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6553 + DEBUGP("unregistering port %d\n", ports[port]);
6554 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
6560 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rtsp.c
6561 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
6562 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rtsp.c 2003-12-11 11:19:50.678436040 +0100
6565 + * RTSP extension for IP connection tracking
6566 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6567 + * based on ip_conntrack_irc.c
6569 + * This program is free software; you can redistribute it and/or
6570 + * modify it under the terms of the GNU General Public License
6571 + * as published by the Free Software Foundation; either version
6572 + * 2 of the License, or (at your option) any later version.
6574 + * Module load syntax:
6575 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6576 + * max_outstanding=n setup_timeout=secs
6578 + * If no ports are specified, the default will be port 554.
6580 + * With max_outstanding you can define the maximum number of not yet
6581 + * answered SETUP requests per RTSP session (default 8).
6582 + * With setup_timeout you can specify how long the system waits for
6583 + * an expected data channel (default 300 seconds).
6586 +#include <linux/config.h>
6587 +#include <linux/module.h>
6588 +#include <linux/netfilter.h>
6589 +#include <linux/ip.h>
6590 +#include <net/checksum.h>
6591 +#include <net/tcp.h>
6593 +#include <linux/netfilter_ipv4/lockhelp.h>
6594 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6595 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6597 +#include <linux/ctype.h>
6598 +#define NF_NEED_STRNCASECMP
6599 +#define NF_NEED_STRTOU16
6600 +#define NF_NEED_STRTOU32
6601 +#define NF_NEED_NEXTLINE
6602 +#include <linux/netfilter_helpers.h>
6603 +#define NF_NEED_MIME_NEXTLINE
6604 +#include <linux/netfilter_mime.h>
6606 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
6608 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
6609 +#ifdef IP_NF_RTSP_DEBUG
6610 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
6612 +#define DEBUGP(args...)
6615 +#define MAX_PORTS 8
6616 +static int ports[MAX_PORTS];
6617 +static int num_ports = 0;
6618 +static int max_outstanding = 8;
6619 +static unsigned int setup_timeout = 300;
6621 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6622 +MODULE_DESCRIPTION("RTSP connection tracking module");
6623 +MODULE_LICENSE("GPL");
6625 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6626 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6627 +MODULE_PARM(max_outstanding, "i");
6628 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
6629 +MODULE_PARM(setup_timeout, "i");
6630 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
6633 +DECLARE_LOCK(ip_rtsp_lock);
6634 +struct module* ip_conntrack_rtsp = THIS_MODULE;
6637 + * Max mappings we will allow for one RTSP connection (for RTP, the number
6638 + * of allocated ports is twice this value). Note that SMIL burns a lot of
6639 + * ports so keep this reasonably high. If this is too low, you will see a
6640 + * lot of "no free client map entries" messages.
6642 +#define MAX_PORT_MAPS 16
6644 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
6646 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6649 + * Parse an RTSP packet.
6651 + * Returns zero if parsing failed.
6654 + * IN ptcp tcp data pointer
6655 + * IN tcplen tcp data len
6656 + * IN/OUT ptcpoff points to current tcp offset
6657 + * OUT phdrsoff set to offset of rtsp headers
6658 + * OUT phdrslen set to length of rtsp headers
6659 + * OUT pcseqoff set to offset of CSeq header
6660 + * OUT pcseqlen set to length of CSeq header
6663 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
6664 + uint* phdrsoff, uint* phdrslen,
6665 + uint* pcseqoff, uint* pcseqlen)
6667 + uint entitylen = 0;
6671 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6676 + *phdrsoff = *ptcpoff;
6677 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6681 + if (entitylen > 0)
6683 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
6687 + if (lineoff+linelen > tcplen)
6689 +// INFOP("!! overrun !!\n");
6693 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
6695 + *pcseqoff = lineoff;
6696 + *pcseqlen = linelen;
6698 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
6700 + uint off = lineoff+15;
6701 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
6702 + nf_strtou32(ptcp+off, &entitylen);
6705 + *phdrslen = (*ptcpoff) - (*phdrsoff);
6711 + * Find lo/hi client ports (if any) in transport header
6713 + * ptcp, tcplen = packet
6714 + * tranoff, tranlen = buffer to search
6717 + * pport_lo, pport_hi = lo/hi ports (host endian)
6719 + * Returns nonzero if any client ports found
6721 + * Note: it is valid (and expected) for the client to request multiple
6722 + * transports, so we need to parse the entire line.
6725 +rtsp_parse_transport(char* ptran, uint tranlen,
6726 + struct ip_ct_rtsp_expect* prtspexp)
6731 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6732 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
6734 + //INFOP("sanity check failed\n");
6737 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
6739 + SKIP_WSPACE(ptran, tranlen, off);
6741 + /* Transport: tran;field;field=val,tran;field;field=val,... */
6742 + while (off < tranlen)
6744 + const char* pparamend;
6745 + uint nextparamoff;
6747 + pparamend = memchr(ptran+off, ',', tranlen-off);
6748 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
6749 + nextparamoff = pparamend-ptran;
6751 + while (off < nextparamoff)
6753 + const char* pfieldend;
6754 + uint nextfieldoff;
6756 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6757 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6759 + if (strncmp(ptran+off, "client_port=", 12) == 0)
6765 + numlen = nf_strtou16(ptran+off, &port);
6767 + if (prtspexp->loport != 0 && prtspexp->loport != port)
6769 + DEBUGP("multiple ports found, port %hu ignored\n", port);
6773 + prtspexp->loport = prtspexp->hiport = port;
6774 + if (ptran[off] == '-')
6777 + numlen = nf_strtou16(ptran+off, &port);
6779 + prtspexp->pbtype = pb_range;
6780 + prtspexp->hiport = port;
6782 + // If we have a range, assume rtp:
6783 + // loport must be even, hiport must be loport+1
6784 + if ((prtspexp->loport & 0x0001) != 0 ||
6785 + prtspexp->hiport != prtspexp->loport+1)
6787 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
6788 + prtspexp->loport, prtspexp->hiport);
6789 + prtspexp->loport &= 0xfffe;
6790 + prtspexp->hiport = prtspexp->loport+1;
6793 + else if (ptran[off] == '/')
6796 + numlen = nf_strtou16(ptran+off, &port);
6798 + prtspexp->pbtype = pb_discon;
6799 + prtspexp->hiport = port;
6806 + * Note we don't look for the destination parameter here.
6807 + * If we are using NAT, the NAT module will handle it. If not,
6808 + * and the client is sending packets elsewhere, the expectation
6809 + * will quietly time out.
6812 + off = nextfieldoff;
6815 + off = nextparamoff;
6821 +/*** conntrack functions ***/
6823 +/* outbound packet: client->server */
6825 +help_out(const struct iphdr* iph, size_t pktlen,
6826 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6828 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
6829 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6830 + uint tcplen = pktlen - iph->ihl * 4;
6831 + char* pdata = (char*)tcph + tcph->doff * 4;
6832 + uint datalen = tcplen - tcph->doff * 4;
6835 + struct ip_conntrack_expect exp;
6837 + while (dataoff < datalen)
6839 + uint cmdoff = dataoff;
6849 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
6850 + &hdrsoff, &hdrslen,
6851 + &cseqoff, &cseqlen))
6853 + break; /* not a valid message */
6856 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
6858 + continue; /* not a SETUP message */
6860 + DEBUGP("found a setup message\n");
6862 + memset(&exp, 0, sizeof(exp));
6865 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
6866 + &lineoff, &linelen))
6872 + if (off > hdrsoff+hdrslen)
6874 +// INFOP("!! overrun !!");
6878 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
6880 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
6881 + &exp.help.exp_rtsp_info);
6885 + if (exp.help.exp_rtsp_info.loport == 0)
6887 + DEBUGP("no udp transports found\n");
6888 + continue; /* no udp transports found */
6891 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
6892 + (int)exp.help.exp_rtsp_info.pbtype,
6893 + exp.help.exp_rtsp_info.loport,
6894 + exp.help.exp_rtsp_info.hiport);
6896 + LOCK_BH(&ip_rtsp_lock);
6897 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
6898 + exp.help.exp_rtsp_info.len = hdrslen;
6900 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6901 + exp.mask.src.ip = 0xffffffff;
6902 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
6903 + exp.mask.dst.ip = 0xffffffff;
6904 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
6905 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
6906 + exp.tuple.dst.protonum = IPPROTO_UDP;
6907 + exp.mask.dst.protonum = 0xffff;
6909 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6910 + NIPQUAD(exp.tuple.src.ip),
6911 + ntohs(exp.tuple.src.u.tcp.port),
6912 + NIPQUAD(exp.tuple.dst.ip),
6913 + ntohs(exp.tuple.dst.u.tcp.port));
6915 + /* pass the request off to the nat helper */
6916 + rc = ip_conntrack_expect_related(ct, &exp);
6917 + UNLOCK_BH(&ip_rtsp_lock);
6920 + DEBUGP("ip_conntrack_expect_related succeeded\n");
6924 +// INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
6931 +/* inbound packet: server->client */
6933 +help_in(const struct iphdr* iph, size_t pktlen,
6934 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6940 +help(const struct iphdr* iph, size_t pktlen,
6941 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6943 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6944 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6945 + u_int32_t tcplen = pktlen - iph->ihl * 4;
6947 + /* Until there's been traffic both ways, don't look in packets. */
6948 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
6950 + DEBUGP("conntrackinfo = %u\n", ctinfo);
6954 + /* Not whole TCP header? */
6955 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
6957 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
6961 + /* Checksum invalid? Ignore. */
6962 + /* FIXME: Source route IP option packets --RR */
6963 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6964 + csum_partial((char*)tcph, tcplen, 0)))
6966 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6967 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6971 + switch (CTINFO2DIR(ctinfo))
6973 + case IP_CT_DIR_ORIGINAL:
6974 + help_out(iph, pktlen, ct, ctinfo);
6976 + case IP_CT_DIR_REPLY:
6977 + help_in(iph, pktlen, ct, ctinfo);
6986 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
6987 +static char rtsp_names[MAX_PORTS][10];
6989 +/* This function is intentionally _NOT_ defined as __exit */
6994 + for (i = 0; i < num_ports; i++)
6996 + DEBUGP("unregistering port %d\n", ports[i]);
6997 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
7005 + struct ip_conntrack_helper *hlpr;
7008 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7010 + if (max_outstanding < 1)
7012 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
7015 + if (setup_timeout < 0)
7017 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
7021 + /* If no port given, default to standard rtsp port */
7022 + if (ports[0] == 0)
7024 + ports[0] = RTSP_PORT;
7027 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
7029 + hlpr = &rtsp_helpers[i];
7030 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
7031 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7032 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
7033 + hlpr->mask.src.u.tcp.port = 0xFFFF;
7034 + hlpr->mask.dst.protonum = 0xFFFF;
7035 + hlpr->max_expected = max_outstanding;
7036 + hlpr->timeout = setup_timeout;
7037 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
7038 + hlpr->me = ip_conntrack_rtsp;
7039 + hlpr->help = help;
7041 + tmpname = &rtsp_names[i][0];
7042 + if (ports[i] == RTSP_PORT)
7044 + sprintf(tmpname, "rtsp");
7048 + sprintf(tmpname, "rtsp-%d", i);
7050 + hlpr->name = tmpname;
7052 + DEBUGP("port #%d: %d\n", i, ports[i]);
7054 + ret = ip_conntrack_helper_register(hlpr);
7058 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
7067 +#ifdef CONFIG_IP_NF_NAT_NEEDED
7068 +EXPORT_SYMBOL(ip_rtsp_lock);
7073 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_standalone.c
7074 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-12-11 09:50:30.000000000 +0100
7075 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-12-11 10:24:15.986386288 +0100
7077 len += sprintf(buffer + len, "[ASSURED] ");
7078 len += sprintf(buffer + len, "use=%u ",
7079 atomic_read(&conntrack->ct_general.use));
7080 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
7081 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
7083 len += sprintf(buffer + len, "\n");
7086 @@ -186,6 +189,26 @@
7087 return ip_conntrack_confirm(*pskb);
7090 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
7091 + struct sk_buff **pskb,
7092 + const struct net_device *in,
7093 + const struct net_device *out,
7094 + int (*okfn)(struct sk_buff *))
7096 + /* Previously seen (loopback)? Ignore. Do this before
7097 + fragment check. */
7098 + if ((*pskb)->nfct)
7101 + /* Gather fragments. */
7102 + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
7103 + *pskb = ip_ct_gather_frags(*pskb);
7110 static unsigned int ip_refrag(unsigned int hooknum,
7111 struct sk_buff **pskb,
7112 const struct net_device *in,
7113 @@ -226,6 +249,15 @@
7114 return ip_conntrack_in(hooknum, pskb, in, out, okfn);
7117 +/* At the very first: defragment */
7118 +static struct nf_hook_ops ip_conntrack_defrag_ops = {
7119 + .hook = ip_conntrack_defrag,
7120 + .owner = THIS_MODULE,
7122 + .hooknum = NF_IP_PRE_ROUTING,
7123 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
7126 /* Connection tracking may drop packets, but never alters them, so
7127 make it the first hook. */
7128 static struct nf_hook_ops ip_conntrack_in_ops = {
7129 @@ -236,6 +268,14 @@
7130 .priority = NF_IP_PRI_CONNTRACK,
7133 +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
7134 + .hook = ip_conntrack_defrag,
7135 + .owner = THIS_MODULE,
7137 + .hooknum = NF_IP_LOCAL_OUT,
7138 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
7141 static struct nf_hook_ops ip_conntrack_local_out_ops = {
7142 .hook = ip_conntrack_local,
7143 .owner = THIS_MODULE,
7144 @@ -368,10 +408,20 @@
7145 if (!proc) goto cleanup_init;
7146 proc->owner = THIS_MODULE;
7148 + ret = nf_register_hook(&ip_conntrack_defrag_ops);
7150 + printk("ip_conntrack: can't register pre-routing defrag hook.\n");
7151 + goto cleanup_proc;
7153 + ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
7155 + printk("ip_conntrack: can't register local_out defrag hook.\n");
7156 + goto cleanup_defragops;
7158 ret = nf_register_hook(&ip_conntrack_in_ops);
7160 printk("ip_conntrack: can't register pre-routing hook.\n");
7161 - goto cleanup_proc;
7162 + goto cleanup_defraglocalops;
7164 ret = nf_register_hook(&ip_conntrack_local_out_ops);
7166 @@ -409,6 +459,10 @@
7167 nf_unregister_hook(&ip_conntrack_local_out_ops);
7169 nf_unregister_hook(&ip_conntrack_in_ops);
7170 + cleanup_defraglocalops:
7171 + nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
7172 + cleanup_defragops:
7173 + nf_unregister_hook(&ip_conntrack_defrag_ops);
7175 proc_net_remove("ip_conntrack");
7177 @@ -417,13 +471,20 @@
7181 -/* FIXME: Allow NULL functions and sub in pointers to generic for
7184 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
7185 + * @proto: structure describing this layer 4 protocol helper
7187 + * This function is called by layer 4 protocol helpers to register
7188 + * themselves with the conntrack core.
7190 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
7193 struct list_head *i;
7195 + /* FIXME: Allow NULL functions and sub in pointers to generic for
7197 WRITE_LOCK(&ip_conntrack_lock);
7198 list_for_each(i, &protocol_list) {
7199 if (((struct ip_conntrack_protocol *)i)->proto
7200 @@ -440,12 +501,20 @@
7205 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
7206 + * @proto: structure describing this layer 4 protocol helper
7208 + * This function is called byh layer 4 protocol helpers to unregister
7209 + * themselvers from the conntrack core. Please note that all conntrack
7210 + * entries for this protocol are deleted from the conntrack hash table.
7212 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
7214 WRITE_LOCK(&ip_conntrack_lock);
7216 - /* ip_ct_find_proto() returns proto_generic in case there is no protocol
7217 - * helper. So this should be enough - HW */
7218 + /* ip_ct_find_proto() returns proto_generic in case there is no
7219 + * protocol helper. So this should be enough - HW */
7220 LIST_DELETE(&protocol_list, proto);
7221 WRITE_UNLOCK(&ip_conntrack_lock);
7224 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
7225 EXPORT_SYMBOL(ip_ct_selective_cleanup);
7226 EXPORT_SYMBOL(ip_ct_refresh);
7227 +EXPORT_SYMBOL(ip_ct_death_by_timeout);
7228 EXPORT_SYMBOL(ip_ct_find_proto);
7229 EXPORT_SYMBOL(__ip_ct_find_proto);
7230 EXPORT_SYMBOL(ip_ct_find_helper);
7232 EXPORT_SYMBOL(ip_conntrack_expect_list);
7233 EXPORT_SYMBOL(ip_conntrack_lock);
7234 EXPORT_SYMBOL(ip_conntrack_hash);
7235 +EXPORT_SYMBOL(ip_conntrack_untracked);
7236 EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
7237 EXPORT_SYMBOL_GPL(ip_conntrack_put);
7238 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_talk.c
7239 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
7240 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_talk.c 2003-12-11 10:24:09.249410464 +0100
7243 + * talk extension for IP connection tracking.
7244 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7246 + * This program is free software; you can redistribute it and/or
7247 + * modify it under the terms of the GNU General Public License
7248 + * as published by the Free Software Foundation; either version
7249 + * 2 of the License, or (at your option) any later version.
7251 + * Module load syntax:
7252 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
7254 + * talk=[0|1] disable|enable old talk support
7255 + * ntalk=[0|1] disable|enable ntalk support
7256 + * ntalk2=[0|1] disable|enable ntalk2 support
7258 + * The default is talk=1 ntalk=1 ntalk2=1
7260 + * The helper does not support simultaneous talk requests.
7263 + * ASCII art on talk protocols
7266 + * caller server callee server
7273 + * caller client ----------- callee client
7276 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
7277 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
7278 + * 3. callee client <-> caller server: LOOK_UP invitation
7279 + * 4. callee client <-> caller client: talk data channel
7281 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
7282 + * draft-hunter-talk-00.txt
7283 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
7285 +#include <linux/config.h>
7286 +#include <linux/module.h>
7287 +#include <linux/netfilter.h>
7288 +#include <linux/ip.h>
7289 +#include <net/checksum.h>
7290 +#include <net/udp.h>
7292 +#include <linux/netfilter_ipv4/lockhelp.h>
7293 +#include <linux/netfilter_ipv4/ip_conntrack.h>
7294 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
7295 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7296 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7298 +/* Default all talk protocols are supported */
7299 +static int talk = 1;
7300 +static int ntalk = 1;
7301 +static int ntalk2 = 1;
7302 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7303 +MODULE_DESCRIPTION("talk connection tracking module");
7304 +MODULE_LICENSE("GPL");
7306 +MODULE_PARM(talk, "i");
7307 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7308 +MODULE_PARM(ntalk, "i");
7309 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7310 +MODULE_PARM(ntalk2, "i");
7311 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7314 +DECLARE_LOCK(ip_talk_lock);
7315 +struct module *ip_conntrack_talk = THIS_MODULE;
7318 +#define DEBUGP printk
7320 +#define DEBUGP(format, args...)
7323 +static int talk_expect(struct ip_conntrack *ct);
7324 +static int ntalk_expect(struct ip_conntrack *ct);
7326 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
7328 +static int talk_help_response(const struct iphdr *iph, size_t len,
7329 + struct ip_conntrack *ct,
7330 + enum ip_conntrack_info ctinfo,
7335 + struct talk_addr *addr)
7337 + int dir = CTINFO2DIR(ctinfo);
7338 + struct ip_conntrack_expect expect, *exp = &expect;
7339 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
7341 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
7342 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7345 + if (!(answer == SUCCESS && type == mode))
7348 + memset(&expect, 0, sizeof(expect));
7350 + if (type == ANNOUNCE) {
7352 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
7354 + /* update the talk info */
7355 + LOCK_BH(&ip_talk_lock);
7356 + exp_talk_info->port = htons(talk_port);
7358 + /* expect callee client -> caller server message */
7359 + exp->tuple = ((struct ip_conntrack_tuple)
7360 + { { ct->tuplehash[dir].tuple.src.ip,
7362 + { ct->tuplehash[dir].tuple.dst.ip,
7363 + { .tcp = { htons(talk_port) } },
7365 + exp->mask = ((struct ip_conntrack_tuple)
7366 + { { 0xFFFFFFFF, { 0 } },
7367 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
7369 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
7371 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
7372 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
7373 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
7375 + /* Ignore failure; should only happen with NAT */
7376 + ip_conntrack_expect_related(ct, &expect);
7377 + UNLOCK_BH(&ip_talk_lock);
7379 + if (type == LOOK_UP) {
7381 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
7383 + /* update the talk info */
7384 + LOCK_BH(&ip_talk_lock);
7385 + exp_talk_info->port = addr->ta_port;
7387 + /* expect callee client -> caller client connection */
7388 + exp->tuple = ((struct ip_conntrack_tuple)
7389 + { { ct->tuplehash[!dir].tuple.src.ip,
7392 + { addr->ta_port },
7394 + exp->mask = ((struct ip_conntrack_tuple)
7395 + { { 0xFFFFFFFF, { 0 } },
7396 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
7398 + exp->expectfn = NULL;
7400 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
7401 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
7402 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
7404 + /* Ignore failure; should only happen with NAT */
7405 + ip_conntrack_expect_related(ct, &expect);
7406 + UNLOCK_BH(&ip_talk_lock);
7412 +/* FIXME: This should be in userspace. Later. */
7413 +static int talk_help(const struct iphdr *iph, size_t len,
7414 + struct ip_conntrack *ct,
7415 + enum ip_conntrack_info ctinfo,
7419 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7420 + const char *data = (const char *)udph + sizeof(struct udphdr);
7421 + int dir = CTINFO2DIR(ctinfo);
7424 + DEBUGP("ip_ct_talk_help: help entered\n");
7426 + /* Until there's been traffic both ways, don't look in packets. */
7427 + if (ctinfo != IP_CT_ESTABLISHED
7428 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
7429 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
7433 + /* Not whole UDP header? */
7434 + udplen = len - iph->ihl * 4;
7435 + if (udplen < sizeof(struct udphdr)) {
7436 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
7440 + /* Checksum invalid? Ignore. */
7441 + /* FIXME: Source route IP option packets --RR */
7442 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7443 + csum_partial((char *)udph, udplen, 0))) {
7444 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
7445 + udph, udplen, NIPQUAD(iph->saddr),
7446 + NIPQUAD(iph->daddr));
7450 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7451 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
7453 + if (dir == IP_CT_DIR_ORIGINAL)
7456 + if (talk_port == TALK_PORT
7457 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7458 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7459 + ((struct talk_response *)data)->type,
7460 + ((struct talk_response *)data)->answer,
7461 + &(((struct talk_response *)data)->addr));
7462 + else if (talk_port == NTALK_PORT
7464 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7465 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7466 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7467 + ((struct ntalk_response *)data)->type,
7468 + ((struct ntalk_response *)data)->answer,
7469 + &(((struct ntalk_response *)data)->addr));
7470 + else if (talk_port == NTALK_PORT
7472 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7473 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7474 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7475 + ((struct ntalk2_response *)data)->type,
7476 + ((struct ntalk2_response *)data)->answer,
7477 + &(((struct ntalk2_response *)data)->addr));
7479 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
7480 + (unsigned)udplen - sizeof(struct udphdr),
7481 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7486 +static int lookup_help(const struct iphdr *iph, size_t len,
7487 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7489 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
7492 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
7493 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7495 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
7498 +static struct ip_conntrack_helper lookup_helpers[2] =
7499 + { { { NULL, NULL },
7500 + "talk", /* name */
7502 + NULL, /* module */
7503 + 1, /* max_expected */
7504 + 240, /* timeout */
7505 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
7506 + { 0, { 0 }, IPPROTO_UDP } },
7507 + { { 0, { 0xFFFF } }, /* mask */
7508 + { 0, { 0 }, 0xFFFF } },
7509 + lookup_help }, /* helper */
7511 + "ntalk", /* name */
7513 + NULL, /* module */
7514 + 1, /* max_expected */
7515 + 240, /* timeout */
7516 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
7517 + { 0, { 0 }, IPPROTO_UDP } },
7518 + { { 0, { 0xFFFF } }, /* mask */
7519 + { 0, { 0 }, 0xFFFF } },
7520 + lookup_nhelp } /* helper */
7523 +static int talk_expect(struct ip_conntrack *ct)
7525 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
7526 + WRITE_LOCK(&ip_conntrack_lock);
7527 + ct->helper = &lookup_helpers[0];
7528 + WRITE_UNLOCK(&ip_conntrack_lock);
7530 + return NF_ACCEPT; /* unused */
7533 +static int ntalk_expect(struct ip_conntrack *ct)
7535 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
7536 + WRITE_LOCK(&ip_conntrack_lock);
7537 + ct->helper = &lookup_helpers[1];
7538 + WRITE_UNLOCK(&ip_conntrack_lock);
7540 + return NF_ACCEPT; /* unused */
7543 +static int help(const struct iphdr *iph, size_t len,
7544 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7546 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
7549 +static int nhelp(const struct iphdr *iph, size_t len,
7550 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7552 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
7555 +static struct ip_conntrack_helper talk_helpers[2] =
7556 + { { { NULL, NULL },
7557 + "talk", /* name */
7559 + THIS_MODULE, /* module */
7560 + 1, /* max_expected */
7561 + 240, /* timeout */
7562 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
7563 + { 0, { 0 }, IPPROTO_UDP } },
7564 + { { 0, { 0xFFFF } }, /* mask */
7565 + { 0, { 0 }, 0xFFFF } },
7566 + help }, /* helper */
7568 + "ntalk", /* name */
7570 + THIS_MODULE, /* module */
7571 + 1, /* max_expected */
7572 + 240, /* timeout */
7573 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
7574 + { 0, { 0 }, IPPROTO_UDP } },
7575 + { { 0, { 0xFFFF } }, /* mask */
7576 + { 0, { 0 }, 0xFFFF } },
7577 + nhelp } /* helper */
7580 +static int __init init(void)
7583 + ip_conntrack_helper_register(&talk_helpers[0]);
7584 + if (ntalk > 0 || ntalk2 > 0)
7585 + ip_conntrack_helper_register(&talk_helpers[1]);
7590 +static void __exit fini(void)
7593 + ip_conntrack_helper_unregister(&talk_helpers[0]);
7594 + if (ntalk > 0 || ntalk2 > 0)
7595 + ip_conntrack_helper_unregister(&talk_helpers[1]);
7598 +EXPORT_SYMBOL(ip_talk_lock);
7602 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_tftp.c
7603 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_tftp.c 2003-11-26 21:43:31.000000000 +0100
7604 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_tftp.c 2003-12-11 10:23:13.893825792 +0100
7607 for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7608 /* Create helper structure */
7609 - memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
7611 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
7612 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
7613 tftp[i].mask.dst.protonum = 0xFFFF;
7614 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_amanda.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_amanda.c
7615 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_amanda.c 2003-11-26 21:43:24.000000000 +0100
7616 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_amanda.c 2003-12-11 10:23:13.893825792 +0100
7618 struct ip_nat_helper *hlpr;
7620 hlpr = &ip_nat_amanda_helper;
7621 - memset(hlpr, 0, sizeof(struct ip_nat_helper));
7623 hlpr->tuple.dst.protonum = IPPROTO_UDP;
7624 hlpr->tuple.src.u.udp.port = htons(10080);
7625 hlpr->mask.src.u.udp.port = 0xFFFF;
7626 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_core.c
7627 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_core.c 2003-11-26 21:43:07.000000000 +0100
7628 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_core.c 2003-12-11 10:23:59.482895200 +0100
7630 WRITE_UNLOCK(&ip_nat_lock);
7633 -/* We do checksum mangling, so if they were wrong before they're still
7634 - * wrong. Also works for incomplete packets (eg. ICMP dest
7635 - * unreachables.) */
7637 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
7638 + * @oldvalinv: bit-inverted old value of 32bit word
7639 + * @newval: new value of 32bit word
7640 + * @oldcheck: old checksum value
7642 + * This function implements incremental checksum mangling, so if a checksum
7643 + * was wrong it will still be wrong after mangling. Also works for incomplete
7644 + * packets (eg. ICMP dest unreachables). Return value is the new checksum.
7647 ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
7649 @@ -118,7 +125,14 @@
7653 -/* Is this tuple already taken? (not by us) */
7655 + * ip_nat_used_tuple - Is this tuple already in use?
7656 + * @tuple: tuple to be used for this check
7657 + * @ignored_conntrack: conntrack excluded from this check
7659 + * This function checks for the reply (inverted) tuple in the conntrack
7660 + * hash. This is necessarry with NAT, since there is no fixed mapping.
7663 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
7664 const struct ip_conntrack *ignored_conntrack)
7666 *tuple = *orig_tuple;
7667 while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
7669 - DEBUGP("Found best for "); DUMP_TUPLE(tuple);
7670 + DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
7671 /* 3) The per-protocol part of the manip is made to
7672 map into the range to make a unique tuple. */
7674 @@ -509,6 +523,19 @@
7679 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
7680 + * @conntrack: conntrack on which we operate
7681 + * @mr: address/port range which is valid for this NAT mapping
7682 + * @hooknum: hook at which this NAT mapping applies
7684 + * This function is called by NAT targets (SNAT,DNAT,...) and by
7685 + * the NAT application helper modules. It is called for the NEW packet
7686 + * of a connection in order to specify which NAT mappings shall apply to
7687 + * this connection at a given hook.
7689 + * Note: The reply mappings are created automagically by this function.
7692 ip_nat_setup_info(struct ip_conntrack *conntrack,
7693 const struct ip_nat_multi_range *mr,
7695 HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
7697 DEBUGP("Original: ");
7698 - DUMP_TUPLE(&orig_tp);
7699 + DUMP_TUPLE_RAW(&orig_tp);
7701 - DUMP_TUPLE(&new_tuple);
7702 + DUMP_TUPLE_RAW(&new_tuple);
7705 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
7708 /* Have to grab read lock before sibling_list traversal */
7709 READ_LOCK(&ip_conntrack_lock);
7710 - list_for_each(cur_item, &ct->sibling_list) {
7711 + list_for_each_prev(cur_item, &ct->sibling_list) {
7712 exp = list_entry(cur_item, struct ip_conntrack_expect,
7715 @@ -1010,7 +1037,11 @@
7716 /* FIXME: Man, this is a hack. <SIGH> */
7717 IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
7718 ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
7721 + /* Initialize fake conntrack so that NAT will skip it */
7722 + ip_conntrack_untracked.nat.info.initialized |=
7723 + (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
7728 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_cuseeme.c
7729 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_cuseeme.c 1970-01-01 01:00:00.000000000 +0100
7730 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_cuseeme.c 2003-12-11 10:23:48.970493328 +0100
7732 +/* CuSeeMe extension for UDP NAT alteration.
7733 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7734 + * based on ip_masq_cuseeme.c in 2.2 kernels
7736 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
7738 + * This program is free software; you can redistribute it and/or
7739 + * modify it under the terms of the GNU General Public License
7740 + * as published by the Free Software Foundation; either version
7741 + * 2 of the License, or (at your option) any later version.
7743 + * Module load syntax:
7744 + * insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
7746 + * Please give the ports of the CuSeeMe traffic you want to track.
7747 + * If you don't specify ports, the default will be UDP port 7648.
7749 + * CuSeeMe Protocol Documentation:
7750 + * http://cu-seeme.net/squeek/tech/contents.html
7754 +#include <linux/module.h>
7755 +#include <linux/netfilter_ipv4.h>
7756 +#include <linux/ip.h>
7757 +#include <linux/udp.h>
7759 +#include <linux/netfilter.h>
7760 +#include <linux/netfilter_ipv4/ip_tables.h>
7761 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7762 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
7763 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7764 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7766 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7767 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
7768 +MODULE_LICENSE("GPL");
7770 +#define MAX_PORTS 8
7772 +static int ports[MAX_PORTS];
7773 +static int ports_c = 0;
7775 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7776 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
7780 +#define DEBUGP printk
7782 +#define DEBUGP(format, args...)
7785 +/* process packet from client->reflector, possibly manipulate client IP in payload */
7786 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
7787 + struct ip_nat_info *info,
7788 + enum ip_conntrack_info ctinfo,
7789 + struct sk_buff **pskb,
7791 + unsigned int datalen)
7793 + char new_port_ip[6];
7794 + struct cu_header *cu_head=(struct cu_header *)data;
7796 + DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n",
7797 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7799 + /* At least check that the data at offset 10 is the client's port and IP address */
7800 + if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
7801 + (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
7802 + DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
7803 + NIPQUAD(cu_head->addr),
7804 + ntohs(cu_head->port),
7805 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7806 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
7807 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7808 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7809 + /* at offset 10, replace 6 bytes containing port + IP address */
7810 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7811 + 10, 6, (char *)(new_port_ip), 6);
7813 + DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7814 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7815 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
7816 + NIPQUAD(cu_head->addr),
7817 + ntohs(cu_head->port));
7820 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
7821 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
7822 + struct ip_nat_info *info,
7823 + enum ip_conntrack_info ctinfo,
7824 + struct sk_buff **pskb,
7826 + unsigned int datalen)
7828 + char new_port_ip[6];
7829 + struct cu_header *cu_head = (struct cu_header *)data;
7830 + struct oc_header *oc_head = (struct oc_header *)data;
7831 + struct client_info *ci;
7835 + DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n",
7836 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7838 + /* Check if we're really dealing with the client's port + IP address before rewriting */
7839 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
7840 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
7841 + DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
7842 + NIPQUAD(cu_head->dest_addr),
7843 + ntohs(cu_head->dest_port),
7844 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7845 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
7846 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
7847 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7848 + /* at offset 2, replace 6 bytes containing port + IP address */
7849 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7850 + 2, 6, (char *)(new_port_ip), 6);
7852 + DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7853 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7854 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
7855 + NIPQUAD(cu_head->dest_addr),
7856 + ntohs(cu_head->dest_port));
7858 + /* Check if we're really dealing with the server's port + IP address before rewriting.
7859 + In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
7860 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
7861 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
7862 + DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
7863 + NIPQUAD(cu_head->addr),
7864 + ntohs(cu_head->port),
7865 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
7866 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
7867 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
7868 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7869 + /* at offset 10, replace 6 bytes containing port + IP address */
7870 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7871 + 10, 6, (char *)(new_port_ip), 6);
7873 + /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
7874 + is not that important so we're not logging this unless we're debugging */
7875 + DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7876 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
7877 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
7878 + NIPQUAD(cu_head->addr),
7879 + ntohs(cu_head->port));
7881 + /* Spin through client_info structs until we find our own */
7882 + if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
7883 + DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
7884 + for(i=0, off=sizeof(struct oc_header);
7885 + (i < oc_head->client_count &&
7886 + off+sizeof(struct client_info) <= datalen);
7888 + ci=(struct client_info *)(data+off);
7889 + DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n",
7890 + NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7891 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7892 + if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
7893 + /* mangle this IP address */
7894 + DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
7895 + NIPQUAD(ci->address),
7896 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7897 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7898 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7899 + (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4,
7900 + (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
7903 + off+=sizeof(struct client_info);
7906 + DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n",
7907 + ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
7910 +static unsigned int
7911 +cuseeme_nat_help(struct ip_conntrack *ct,
7912 + struct ip_conntrack_expect *exp,
7913 + struct ip_nat_info *info,
7914 + enum ip_conntrack_info ctinfo,
7915 + unsigned int hooknum,
7916 + struct sk_buff **pskb)
7918 + struct iphdr *iph = (*pskb)->nh.iph;
7919 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7920 + int dir = CTINFO2DIR(ctinfo);
7921 + unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
7922 + char *data = (char *) &udph[1];
7924 + DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
7925 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7926 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7927 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7928 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7931 + /* Only mangle things once: original direction in POST_ROUTING
7932 + and reply direction on PRE_ROUTING. */
7933 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7934 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7935 + DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
7936 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7937 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7938 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7939 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7943 + if(datalen < sizeof(struct cu_header)) {
7944 + /* packet too small */
7945 + if (net_ratelimit())
7946 + printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n",
7947 + datalen, sizeof(struct cu_header));
7952 + /* In the debugging output, "outgoing" is from client to server, and
7953 + "incoming" is from server to client */
7954 + if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7955 + cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
7957 + cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
7962 +static struct ip_nat_helper cuseeme[MAX_PORTS];
7963 +static char cuseeme_names[MAX_PORTS][14]; /* cuseeme-65535 */
7965 +static void fini(void)
7969 + for (i = 0 ; i < ports_c; i++) {
7970 + DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
7971 + ip_nat_helper_unregister(&cuseeme[i]);
7975 +static int __init init(void)
7981 + ports[0] = CUSEEME_PORT;
7983 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7984 + memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
7986 + cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
7987 + cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
7988 + cuseeme[i].mask.dst.protonum = 0xFFFF;
7989 + cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
7990 + cuseeme[i].help = cuseeme_nat_help;
7991 + cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE +
7992 + IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
7993 + is stricly needed... */
7994 + cuseeme[i].me = THIS_MODULE;
7995 + cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
7997 + tmpname = &cuseeme_names[i][0];
7998 + if (ports[i] == CUSEEME_PORT)
7999 + sprintf(tmpname, "cuseeme");
8001 + sprintf(tmpname, "cuseeme-%d", ports[i]);
8002 + cuseeme[i].name = tmpname;
8004 + DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
8005 + ports[i], cuseeme[i].name);
8006 + ret = ip_nat_helper_register(&cuseeme[i]);
8009 + printk("ip_nat_cuseeme: unable to register helper for port %d\n",
8021 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_h323.c
8022 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
8023 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_h323.c 2003-12-11 10:23:51.336133696 +0100
8026 + * H.323 'brute force' extension for NAT alteration.
8027 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8029 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
8030 + * (http://www.coritel.it/projects/sofia/nat.html)
8031 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
8032 + * the unregistered helpers to the conntrack entries.
8036 +#include <linux/module.h>
8037 +#include <linux/netfilter.h>
8038 +#include <linux/ip.h>
8039 +#include <net/checksum.h>
8040 +#include <net/tcp.h>
8042 +#include <linux/netfilter_ipv4/lockhelp.h>
8043 +#include <linux/netfilter_ipv4/ip_nat.h>
8044 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8045 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8046 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
8047 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8048 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
8050 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8051 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
8052 +MODULE_LICENSE("GPL");
8054 +DECLARE_LOCK_EXTERN(ip_h323_lock);
8055 +struct module *ip_nat_h323 = THIS_MODULE;
8058 +#define DEBUGP printk
8060 +#define DEBUGP(format, args...)
8063 +/* FIXME: Time out? --RR */
8065 +static unsigned int
8066 +h225_nat_expected(struct sk_buff **pskb,
8067 + unsigned int hooknum,
8068 + struct ip_conntrack *ct,
8069 + struct ip_nat_info *info);
8071 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8072 + struct ip_conntrack_expect *exp,
8073 + struct ip_nat_info *info,
8074 + enum ip_conntrack_info ctinfo,
8075 + unsigned int hooknum,
8076 + struct sk_buff **pskb);
8078 +static struct ip_nat_helper h245 =
8080 + "H.245", /* name */
8082 + NULL, /* module */
8083 + { { 0, { 0 } }, /* tuple */
8084 + { 0, { 0 }, IPPROTO_TCP } },
8085 + { { 0, { 0xFFFF } }, /* mask */
8086 + { 0, { 0 }, 0xFFFF } },
8087 + h225_nat_help, /* helper */
8088 + h225_nat_expected /* expectfn */
8091 +static unsigned int
8092 +h225_nat_expected(struct sk_buff **pskb,
8093 + unsigned int hooknum,
8094 + struct ip_conntrack *ct,
8095 + struct ip_nat_info *info)
8097 + struct ip_nat_multi_range mr;
8098 + u_int32_t newdstip, newsrcip, newip;
8100 + struct ip_ct_h225_expect *exp_info;
8101 + struct ip_ct_h225_master *master_info;
8102 + struct ip_conntrack *master = master_ct(ct);
8103 + unsigned int is_h225, ret;
8105 + IP_NF_ASSERT(info);
8106 + IP_NF_ASSERT(master);
8108 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8110 + DEBUGP("h225_nat_expected: We have a connection!\n");
8111 + master_info = &ct->master->expectant->help.ct_h225_info;
8112 + exp_info = &ct->master->help.exp_h225_info;
8114 + LOCK_BH(&ip_h323_lock);
8116 + DEBUGP("master: ");
8117 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8118 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
8119 + DEBUGP("conntrack: ");
8120 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8121 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
8122 + /* Make connection go to the client. */
8123 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8124 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8125 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
8126 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8128 + /* Make the connection go to the server */
8129 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8130 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8131 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
8132 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8134 + port = exp_info->port;
8135 + is_h225 = master_info->is_h225 == H225_PORT;
8136 + UNLOCK_BH(&ip_h323_lock);
8138 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8143 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8146 + /* We don't want to manip the per-protocol, just the IPs... */
8147 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8148 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8150 + /* ... unless we're doing a MANIP_DST, in which case, make
8151 + sure we map to the correct port */
8152 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8153 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8154 + mr.range[0].min = mr.range[0].max
8155 + = ((union ip_conntrack_manip_proto)
8156 + { .tcp = { port } });
8159 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8162 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
8163 + /* NAT expectfn called with ip_nat_lock write-locked */
8164 + info->helper = &h245;
8169 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
8170 + struct sk_buff **pskb,
8171 + enum ip_conntrack_info ctinfo)
8173 + struct iphdr *iph = (*pskb)->nh.iph;
8174 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8175 + char *data = (char *) tcph + tcph->doff * 4;
8176 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8177 + u_int32_t datalen = tcplen - tcph->doff*4;
8178 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
8183 + MUST_BE_LOCKED(&ip_h323_lock);
8185 + DEBUGP("h323_signal_address_fixup: %s %s\n",
8186 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8188 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8190 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8191 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
8194 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
8195 + info->offset[IP_CT_DIR_ORIGINAL],
8196 + info->offset[IP_CT_DIR_REPLY],
8198 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8199 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8201 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
8202 + DEBUGP("h323_signal_address_fixup: %s %s\n",
8203 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
8204 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
8205 + if (!between(info->seq[i], ntohl(tcph->seq),
8206 + ntohl(tcph->seq) + datalen))
8208 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
8209 + ntohl(tcph->seq) + datalen)) {
8210 + /* Partial retransmisison. It's a cracker being funky. */
8211 + if (net_ratelimit()) {
8212 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8215 + ntohl(tcph->seq) + datalen);
8220 + /* Change address inside packet to match way we're mapping
8221 + this connection. */
8222 + if (i == IP_CT_DIR_ORIGINAL) {
8223 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
8224 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
8226 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
8227 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
8230 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
8231 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
8232 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
8233 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8235 + /* Modify the packet */
8236 + *(u_int32_t *)(data + info->offset[i]) = newip;
8237 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
8239 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
8240 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
8241 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
8242 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8245 + /* fix checksum information */
8247 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8251 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8252 + csum_partial((char *)tcph, tcph->doff*4,
8254 + ip_send_check(iph);
8259 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
8260 + struct ip_conntrack *ct,
8261 + struct sk_buff **pskb,
8262 + enum ip_conntrack_info ctinfo,
8263 + struct ip_conntrack_expect *expect)
8267 + struct ip_conntrack_tuple newtuple;
8268 + struct iphdr *iph = (*pskb)->nh.iph;
8269 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8270 + char *data = (char *) tcph + tcph->doff * 4;
8271 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8272 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
8275 + MUST_BE_LOCKED(&ip_h323_lock);
8276 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
8277 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8278 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8280 + if (!between(expect->seq + 6, ntohl(tcph->seq),
8281 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
8282 + /* Partial retransmisison. It's a cracker being funky. */
8283 + if (net_ratelimit()) {
8284 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8287 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
8292 + /* Change address inside packet to match way we're mapping
8293 + this connection. */
8294 + if (info->dir == IP_CT_DIR_REPLY) {
8295 + /* Must be where client thinks server is */
8296 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8297 + /* Expect something from client->server */
8298 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8299 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8301 + /* Must be where server thinks client is */
8302 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8303 + /* Expect something from server->client */
8304 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8305 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8308 + is_h225 = (master_info->is_h225 == H225_PORT);
8311 + newtuple.dst.protonum = IPPROTO_TCP;
8312 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
8314 + newtuple.dst.protonum = IPPROTO_UDP;
8315 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
8318 + /* Try to get same port: if not, try to change it. */
8319 + for (port = ntohs(info->port); port != 0; port++) {
8321 + newtuple.dst.u.tcp.port = htons(port);
8323 + newtuple.dst.u.udp.port = htons(port);
8325 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
8329 + DEBUGP("h323_data_fixup: no free port found!\n");
8333 + port = htons(port);
8335 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
8336 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
8337 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
8339 + /* Modify the packet */
8340 + *(u_int32_t *)(data + info->offset) = newip;
8341 + *(u_int16_t *)(data + info->offset + 4) = port;
8343 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
8344 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
8345 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
8347 + /* fix checksum information */
8348 + /* FIXME: usually repeated multiple times in the case of H.245! */
8350 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8351 + tcplen - tcph->doff*4, 0);
8354 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8355 + csum_partial((char *)tcph, tcph->doff*4,
8357 + ip_send_check(iph);
8362 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8363 + struct ip_conntrack_expect *exp,
8364 + struct ip_nat_info *info,
8365 + enum ip_conntrack_info ctinfo,
8366 + unsigned int hooknum,
8367 + struct sk_buff **pskb)
8370 + struct ip_ct_h225_expect *exp_info;
8372 + /* Only mangle things once: original direction in POST_ROUTING
8373 + and reply direction on PRE_ROUTING. */
8374 + dir = CTINFO2DIR(ctinfo);
8375 + DEBUGP("nat_h323: dir %s at hook %s\n",
8376 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8377 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8378 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8379 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8380 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8381 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8382 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
8383 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8384 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8385 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8386 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8391 + LOCK_BH(&ip_h323_lock);
8392 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
8393 + UNLOCK_BH(&ip_h323_lock);
8396 + UNLOCK_BH(&ip_h323_lock);
8400 + exp_info = &exp->help.exp_h225_info;
8402 + LOCK_BH(&ip_h323_lock);
8403 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
8404 + UNLOCK_BH(&ip_h323_lock);
8407 + UNLOCK_BH(&ip_h323_lock);
8412 +static struct ip_nat_helper h225 =
8414 + "H.225", /* name */
8415 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8416 + THIS_MODULE, /* module */
8417 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
8418 + { 0, { 0 }, IPPROTO_TCP } },
8419 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
8420 + { 0, { 0 }, 0xFFFF } },
8421 + h225_nat_help, /* helper */
8422 + h225_nat_expected /* expectfn */
8425 +static int __init init(void)
8429 + ret = ip_nat_helper_register(&h225);
8432 + printk("ip_nat_h323: cannot initialize the module!\n");
8437 +static void __exit fini(void)
8439 + ip_nat_helper_unregister(&h225);
8444 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_helper.c
8445 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_helper.c 2003-11-26 21:43:08.000000000 +0100
8446 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_helper.c 2003-12-11 10:23:57.173246320 +0100
8447 @@ -147,9 +147,19 @@
8451 -/* Generic function for mangling variable-length address changes inside
8452 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
8453 - * command in FTP).
8455 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
8456 + * @skb: pointer to skb of packet on which we operate
8457 + * @ct: conntrack of the connection to which this packet belongs
8458 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8459 + * @match_offset: offset in bytes where to-be-manipulated part starts
8460 + * @match_len: lenght of the to-be-manipulated part
8461 + * @rep_buffer: pointer to buffer containing replacement
8462 + * @rep_len: length of replacement
8464 + * Generic function for mangling fixed and variable-length changes inside
8465 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command
8468 * Takes care about all the nasty sequence number changes, checksumming,
8469 * skb enlargement, ...
8470 @@ -195,16 +205,27 @@
8474 -/* Generic function for mangling variable-length address changes inside
8475 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8476 - * command in the Amanda protocol)
8478 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
8479 + * @skb: pointer to skb of packet on which we operate
8480 + * @ct: conntrack of the connection to which this packet belongs
8481 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8482 + * @match_offset: offset in bytes where to-be-manipulated part starts
8483 + * @match_len: lenght of the to-be-manipulated part
8484 + * @rep_buffer: pointer to buffer containing replacement
8485 + * @rep_len: length of replacement
8487 + * Generic function for mangling fixed and variable-length changes inside
8488 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8489 + * commad in the Amanda protocol)
8491 * Takes care about all the nasty sequence number changes, checksumming,
8492 * skb enlargement, ...
8494 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
8495 - * should be fairly easy to do.
8497 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
8502 ip_nat_mangle_udp_packet(struct sk_buff **pskb,
8503 struct ip_conntrack *ct,
8504 @@ -402,6 +423,13 @@
8505 return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
8509 + * ip_nat_helper_register - Register NAT application helper
8510 + * @me: structure describing the helper
8512 + * This function is called by NAT application helpers to register
8513 + * themselves with the NAT core.
8515 int ip_nat_helper_register(struct ip_nat_helper *me)
8518 @@ -428,6 +456,13 @@
8523 + * ip_nat_helper_unregister - Unregister NAT application helper
8524 + * @me: structure describing the helper
8526 + * This function is called by NAT application helpers to unregister
8527 + * themselves from the NAT core.
8529 void ip_nat_helper_unregister(struct ip_nat_helper *me)
8531 WRITE_LOCK(&ip_nat_lock);
8532 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_mms.c
8533 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
8534 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_mms.c 2003-12-11 10:23:55.934434648 +0100
8536 +/* MMS extension for TCP NAT alteration.
8537 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
8538 + * based on ip_nat_ftp.c and ip_nat_irc.c
8540 + * ip_nat_mms.c v0.3 2002-09-22
8542 + * This program is free software; you can redistribute it and/or
8543 + * modify it under the terms of the GNU General Public License
8544 + * as published by the Free Software Foundation; either version
8545 + * 2 of the License, or (at your option) any later version.
8547 + * Module load syntax:
8548 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
8550 + * Please give the ports of all MMS servers You wish to connect to.
8551 + * If you don't specify ports, the default will be TCP port 1755.
8553 + * More info on MMS protocol, firewalls and NAT:
8554 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
8555 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
8557 + * The SDP project people are reverse-engineering MMS:
8558 + * http://get.to/sdp
8561 +/* FIXME: issue with UDP & fragmentation with this URL:
8562 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
8563 + may be related to out-of-order first packets:
8564 + basically the expectation is set up correctly, then the server sends
8565 + a first UDP packet which is fragmented plus arrives out-of-order.
8566 + the MASQUERADING firewall with ip_nat_mms loaded responds with
8567 + an ICMP unreachable back to the server */
8569 +#include <linux/module.h>
8570 +#include <linux/netfilter_ipv4.h>
8571 +#include <linux/ip.h>
8572 +#include <linux/tcp.h>
8573 +#include <net/tcp.h>
8574 +#include <linux/netfilter_ipv4/ip_nat.h>
8575 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8576 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8577 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
8578 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8581 +#define DEBUGP printk
8582 +#define DUMP_BYTES(address, counter) \
8584 + int temp_counter; \
8585 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
8586 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
8591 +#define DEBUGP(format, args...)
8592 +#define DUMP_BYTES(address, counter)
8595 +#define MAX_PORTS 8
8596 +static int ports[MAX_PORTS];
8597 +static int ports_c = 0;
8600 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8603 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
8604 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
8605 +MODULE_LICENSE("GPL");
8607 +DECLARE_LOCK_EXTERN(ip_mms_lock);
8609 +/* FIXME: Time out? --RR */
8611 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
8612 + struct ip_conntrack *ct,
8613 + struct sk_buff **pskb,
8614 + enum ip_conntrack_info ctinfo,
8615 + struct ip_conntrack_expect *expect)
8618 + struct ip_conntrack_tuple t;
8619 + struct iphdr *iph = (*pskb)->nh.iph;
8620 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8621 + char *data = (char *)tcph + tcph->doff * 4;
8622 + int i, j, k, port;
8623 + u_int16_t mms_proto;
8625 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
8626 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
8627 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
8631 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
8632 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
8633 + char proto_string[6];
8635 + MUST_BE_LOCKED(&ip_mms_lock);
8637 + /* what was the protocol again ? */
8638 + mms_proto = expect->tuple.dst.protonum;
8639 + sprintf(proto_string, "%u", mms_proto);
8641 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
8642 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
8643 + mms_proto == IPPROTO_UDP ? "UDP"
8644 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
8646 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8648 + /* Alter conntrack's expectations. */
8649 + t = expect->tuple;
8651 + for (port = ct_mms_info->port; port != 0; port++) {
8652 + t.dst.u.tcp.port = htons(port);
8653 + if (ip_conntrack_change_expect(expect, &t) == 0) {
8654 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
8662 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
8664 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
8665 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
8667 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
8669 + memset(unicode_buffer, 0, sizeof(char)*75);
8671 + for (i=0; i<strlen(buffer); ++i)
8672 + *(unicode_buffer+i*2)=*(buffer+i);
8674 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
8675 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
8676 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
8678 + /* add end of packet to it */
8679 + for (j=0; j<ct_mms_info->padding; ++j) {
8680 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
8681 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
8682 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
8685 + /* pad with zeroes at the end ? see explanation of weird math below */
8686 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
8687 + for (k=0; k<zero_padding; ++k)
8688 + *(unicode_buffer+i*2+j+k)= (char)0;
8690 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
8691 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8692 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8694 + /* explanation, before I forget what I did:
8695 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
8696 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
8697 + but note that things may have to be padded with zeroes to align by 8
8698 + bytes, hence we add 7 and divide by 8 to get the correct length */
8699 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
8700 + *mms_chunkLenLV = *mms_chunkLenLM+2;
8701 + *mms_messageLength = *mms_chunkLenLV*8;
8703 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8704 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8706 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
8707 + expect->seq - ntohl(tcph->seq),
8708 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
8709 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
8710 + DUMP_BYTES(unicode_buffer, 60);
8715 +static unsigned int
8716 +mms_nat_expected(struct sk_buff **pskb,
8717 + unsigned int hooknum,
8718 + struct ip_conntrack *ct,
8719 + struct ip_nat_info *info)
8721 + struct ip_nat_multi_range mr;
8722 + u_int32_t newdstip, newsrcip, newip;
8724 + struct ip_conntrack *master = master_ct(ct);
8726 + IP_NF_ASSERT(info);
8727 + IP_NF_ASSERT(master);
8729 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8731 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
8733 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8734 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8735 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
8736 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8737 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8738 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8739 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8741 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8746 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8749 + /* We don't want to manip the per-protocol, just the IPs. */
8750 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8751 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8753 + return ip_nat_setup_info(ct, &mr, hooknum);
8757 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
8758 + struct ip_conntrack_expect *exp,
8759 + struct ip_nat_info *info,
8760 + enum ip_conntrack_info ctinfo,
8761 + unsigned int hooknum,
8762 + struct sk_buff **pskb)
8764 + struct iphdr *iph = (*pskb)->nh.iph;
8765 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8766 + unsigned int datalen;
8768 + struct ip_ct_mms_expect *ct_mms_info;
8771 + DEBUGP("ip_nat_mms: no exp!!");
8773 + ct_mms_info = &exp->help.exp_mms_info;
8775 + /* Only mangle things once: original direction in POST_ROUTING
8776 + and reply direction on PRE_ROUTING. */
8777 + dir = CTINFO2DIR(ctinfo);
8778 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8779 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8780 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
8781 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8782 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8783 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8784 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8787 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
8788 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8789 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8790 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8791 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8793 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
8795 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
8796 + exp->seq + ct_mms_info->len,
8798 + ntohl(tcph->seq) + datalen);
8800 + LOCK_BH(&ip_mms_lock);
8801 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
8802 + if (between(exp->seq + ct_mms_info->len,
8804 + ntohl(tcph->seq) + datalen)) {
8805 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
8806 + UNLOCK_BH(&ip_mms_lock);
8810 + /* Half a match? This means a partial retransmisison.
8811 + It's a cracker being funky. */
8812 + if (net_ratelimit()) {
8813 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
8814 + exp->seq, ct_mms_info->len,
8816 + ntohl(tcph->seq) + datalen);
8818 + UNLOCK_BH(&ip_mms_lock);
8821 + UNLOCK_BH(&ip_mms_lock);
8826 +static struct ip_nat_helper mms[MAX_PORTS];
8827 +static char mms_names[MAX_PORTS][10];
8829 +/* Not __exit: called from init() */
8830 +static void fini(void)
8834 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8835 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
8836 + ip_nat_helper_unregister(&mms[i]);
8840 +static int __init init(void)
8845 + if (ports[0] == 0)
8846 + ports[0] = MMS_PORT;
8848 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8850 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
8852 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
8853 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
8854 + mms[i].mask.dst.protonum = 0xFFFF;
8855 + mms[i].mask.src.u.tcp.port = 0xFFFF;
8856 + mms[i].help = mms_nat_help;
8857 + mms[i].me = THIS_MODULE;
8859 + mms[i].expect = mms_nat_expected;
8861 + tmpname = &mms_names[i][0];
8862 + if (ports[i] == MMS_PORT)
8863 + sprintf(tmpname, "mms");
8865 + sprintf(tmpname, "mms-%d", i);
8866 + mms[i].name = tmpname;
8868 + DEBUGP("ip_nat_mms: register helper for port %d\n",
8870 + ret = ip_nat_helper_register(&mms[i]);
8873 + printk("ip_nat_mms: error registering "
8874 + "helper for port %d\n", ports[i]);
8886 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_pptp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_pptp.c
8887 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_pptp.c 1970-01-01 01:00:00.000000000 +0100
8888 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_pptp.c 2003-11-17 09:09:34.000000000 +0100
8891 + * ip_nat_pptp.c - Version 1.5
8893 + * NAT support for PPTP (Point to Point Tunneling Protocol).
8894 + * PPTP is a a protocol for creating virtual private networks.
8895 + * It is a specification defined by Microsoft and some vendors
8896 + * working with Microsoft. PPTP is built on top of a modified
8897 + * version of the Internet Generic Routing Encapsulation Protocol.
8898 + * GRE is defined in RFC 1701 and RFC 1702. Documentation of
8899 + * PPTP can be found in RFC 2637
8901 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
8903 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
8905 + * TODO: - Support for multiple calls within one session
8906 + * (needs netfilter newnat code)
8907 + * - NAT to a unique tuple, not to TCP source port
8908 + * (needs netfilter tuple reservation)
8911 + * 2002-02-10 - Version 1.3
8912 + * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
8913 + * in local connections (Philip Craig <philipc@snapgear.com>)
8914 + * - add checks for magicCookie and pptp version
8915 + * - make argument list of pptp_{out,in}bound_packet() shorter
8916 + * - move to C99 style initializers
8917 + * - print version number at module loadtime
8918 + * 2003-09-22 - Version 1.5
8919 + * - use SNATed tcp sourceport as callid, since we get called before
8920 + * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
8924 +#include <linux/config.h>
8925 +#include <linux/module.h>
8926 +#include <linux/ip.h>
8927 +#include <linux/tcp.h>
8928 +#include <net/tcp.h>
8929 +#include <linux/netfilter_ipv4/ip_nat.h>
8930 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8931 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8932 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
8933 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8934 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
8935 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
8937 +#define IP_NAT_PPTP_VERSION "1.5"
8939 +MODULE_LICENSE("GPL");
8940 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
8941 +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
8945 +#include "ip_conntrack_pptp_priv.h"
8946 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
8947 + ": " format, ## args)
8949 +#define DEBUGP(format, args...)
8952 +static unsigned int
8953 +pptp_nat_expected(struct sk_buff **pskb,
8954 + unsigned int hooknum,
8955 + struct ip_conntrack *ct,
8956 + struct ip_nat_info *info)
8958 + struct ip_conntrack *master = master_ct(ct);
8959 + struct ip_nat_multi_range mr;
8960 + struct ip_ct_pptp_master *ct_pptp_info;
8961 + struct ip_nat_pptp *nat_pptp_info;
8962 + u_int32_t newip, newcid;
8965 + IP_NF_ASSERT(info);
8966 + IP_NF_ASSERT(master);
8967 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8969 + DEBUGP("we have a connection!\n");
8971 + LOCK_BH(&ip_pptp_lock);
8972 + ct_pptp_info = &master->help.ct_pptp_info;
8973 + nat_pptp_info = &master->nat.help.nat_pptp_info;
8975 + /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
8976 + * (unmanipulated) values */
8977 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8978 + DEBUGP("completing tuples with NAT info \n");
8979 + /* we can do this, since we're unconfirmed */
8980 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
8981 + htonl(ct_pptp_info->pac_call_id)) {
8982 + /* assume PNS->PAC */
8983 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8984 + htonl(nat_pptp_info->pns_call_id);
8985 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8986 + htonl(nat_pptp_info->pns_call_id);
8987 + newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8988 + newcid = htonl(nat_pptp_info->pac_call_id);
8990 + /* assume PAC->PNS */
8991 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8992 + htonl(nat_pptp_info->pac_call_id);
8993 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8994 + htonl(nat_pptp_info->pac_call_id);
8995 + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8996 + newcid = htonl(nat_pptp_info->pns_call_id);
8999 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
9000 + htonl(ct_pptp_info->pac_call_id)) {
9001 + /* assume PNS->PAC */
9002 + newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9003 + newcid = htonl(ct_pptp_info->pns_call_id);
9006 + /* assume PAC->PNS */
9007 + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
9008 + newcid = htonl(ct_pptp_info->pac_call_id);
9013 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
9014 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
9015 + mr.range[0].min = mr.range[0].max =
9016 + ((union ip_conntrack_manip_proto ) { newcid });
9017 + DEBUGP("change ip to %u.%u.%u.%u\n",
9019 + DEBUGP("change key to 0x%x\n", ntohl(newcid));
9020 + ret = ip_nat_setup_info(ct, &mr, hooknum);
9022 + UNLOCK_BH(&ip_pptp_lock);
9028 +/* outbound packets == from PNS to PAC */
9029 +static inline unsigned int
9030 +pptp_outbound_pkt(struct sk_buff **pskb,
9031 + struct ip_conntrack *ct,
9032 + enum ip_conntrack_info ctinfo,
9033 + struct ip_conntrack_expect *exp)
9036 + struct iphdr *iph = (*pskb)->nh.iph;
9037 + struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9038 + struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
9039 + ((void *)tcph + tcph->doff*4);
9041 + struct PptpControlHeader *ctlh;
9042 + union pptp_ctrl_union pptpReq;
9043 + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9044 + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9046 + u_int16_t msg, *cid = NULL, new_callid;
9048 + /* FIXME: size checks !!! */
9049 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9050 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9052 + new_callid = htons(ct_pptp_info->pns_call_id);
9054 + switch (msg = ntohs(ctlh->messageType)) {
9055 + case PPTP_OUT_CALL_REQUEST:
9056 + cid = &pptpReq.ocreq->callID;
9057 + /* FIXME: ideally we would want to reserve a call ID
9058 + * here. current netfilter NAT core is not able to do
9059 + * this :( For now we use TCP source port. This breaks
9060 + * multiple calls within one control session */
9062 + /* save original call ID in nat_info */
9063 + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
9065 + /* don't use tcph->source since we are at a DSTmanip
9066 + * hook (e.g. PREROUTING) and pkt is not mangled yet */
9067 + new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
9069 + /* save new call ID in ct info */
9070 + ct_pptp_info->pns_call_id = ntohs(new_callid);
9072 + case PPTP_IN_CALL_REPLY:
9073 + cid = &pptpReq.icreq->callID;
9075 + case PPTP_CALL_CLEAR_REQUEST:
9076 + cid = &pptpReq.clrreq->callID;
9079 + DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
9080 + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9081 + /* fall through */
9083 + case PPTP_SET_LINK_INFO:
9084 + /* only need to NAT in case PAC is behind NAT box */
9085 + case PPTP_START_SESSION_REQUEST:
9086 + case PPTP_START_SESSION_REPLY:
9087 + case PPTP_STOP_SESSION_REQUEST:
9088 + case PPTP_STOP_SESSION_REPLY:
9089 + case PPTP_ECHO_REQUEST:
9090 + case PPTP_ECHO_REPLY:
9091 + /* no need to alter packet */
9095 + IP_NF_ASSERT(cid);
9097 + DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9098 + ntohs(*cid), ntohs(new_callid));
9100 + /* mangle packet */
9101 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
9102 + sizeof(new_callid), (char *)&new_callid,
9103 + sizeof(new_callid));
9108 +/* inbound packets == from PAC to PNS */
9109 +static inline unsigned int
9110 +pptp_inbound_pkt(struct sk_buff **pskb,
9111 + struct ip_conntrack *ct,
9112 + enum ip_conntrack_info ctinfo,
9113 + struct ip_conntrack_expect *oldexp)
9115 + struct iphdr *iph = (*pskb)->nh.iph;
9116 + struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9117 + struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
9118 + ((void *)tcph + tcph->doff*4);
9120 + struct PptpControlHeader *ctlh;
9121 + union pptp_ctrl_union pptpReq;
9122 + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9123 + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9125 + u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
9126 + u_int32_t old_dst_ip;
9128 + struct ip_conntrack_tuple t, inv_t;
9129 + struct ip_conntrack_tuple *orig_t, *reply_t;
9131 + /* FIXME: size checks !!! */
9132 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9133 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9135 + new_pcid = htons(nat_pptp_info->pns_call_id);
9137 + switch (msg = ntohs(ctlh->messageType)) {
9138 + case PPTP_OUT_CALL_REPLY:
9139 + pcid = &pptpReq.ocack->peersCallID;
9140 + cid = &pptpReq.ocack->callID;
9142 + DEBUGP("outcall but no expectation\n");
9145 + old_dst_ip = oldexp->tuple.dst.ip;
9146 + t = oldexp->tuple;
9147 + invert_tuplepr(&inv_t, &t);
9149 + /* save original PAC call ID in nat_info */
9150 + nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
9152 + /* alter expectation */
9153 + orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
9154 + reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
9155 + if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
9156 + /* expectation for PNS->PAC direction */
9157 + t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9158 + t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9159 + inv_t.src.ip = reply_t->src.ip;
9160 + inv_t.dst.ip = reply_t->dst.ip;
9161 + inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9162 + inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9164 + /* expectation for PAC->PNS direction */
9165 + t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9166 + t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9167 + inv_t.src.ip = orig_t->src.ip;
9168 + inv_t.dst.ip = orig_t->dst.ip;
9169 + inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9170 + inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9173 + if (!ip_conntrack_change_expect(oldexp, &t)) {
9174 + DEBUGP("successfully changed expect\n");
9176 + DEBUGP("can't change expect\n");
9178 + ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
9179 + ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
9181 + case PPTP_IN_CALL_CONNECT:
9182 + pcid = &pptpReq.iccon->peersCallID;
9185 + old_dst_ip = oldexp->tuple.dst.ip;
9186 + t = oldexp->tuple;
9188 + /* alter expectation, no need for callID */
9189 + if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
9190 + /* expectation for PNS->PAC direction */
9191 + t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9193 + /* expectation for PAC->PNS direction */
9194 + t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9197 + if (!ip_conntrack_change_expect(oldexp, &t)) {
9198 + DEBUGP("successfully changed expect\n");
9200 + DEBUGP("can't change expect\n");
9203 + case PPTP_IN_CALL_REQUEST:
9204 + /* only need to nat in case PAC is behind NAT box */
9206 + case PPTP_WAN_ERROR_NOTIFY:
9207 + pcid = &pptpReq.wanerr->peersCallID;
9209 + case PPTP_CALL_DISCONNECT_NOTIFY:
9210 + pcid = &pptpReq.disc->callID;
9214 + DEBUGP("unknown inbound packet %s\n",
9215 + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9216 + /* fall through */
9218 + case PPTP_START_SESSION_REQUEST:
9219 + case PPTP_START_SESSION_REPLY:
9220 + case PPTP_STOP_SESSION_REQUEST:
9221 + case PPTP_STOP_SESSION_REPLY:
9222 + case PPTP_ECHO_REQUEST:
9223 + case PPTP_ECHO_REPLY:
9224 + /* no need to alter packet */
9228 + /* mangle packet */
9229 + IP_NF_ASSERT(pcid);
9230 + DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
9231 + ntohs(*pcid), ntohs(new_pcid));
9232 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
9233 + sizeof(new_pcid), (char *)&new_pcid,
9234 + sizeof(new_pcid));
9237 + IP_NF_ASSERT(cid);
9238 + DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9239 + ntohs(*cid), ntohs(new_cid));
9240 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
9241 + (void *)cid - (void *)pptph,
9242 + sizeof(new_cid), (char *)&new_cid,
9246 + /* great, at least we don't need to resize packets */
9251 +static unsigned int tcp_help(struct ip_conntrack *ct,
9252 + struct ip_conntrack_expect *exp,
9253 + struct ip_nat_info *info,
9254 + enum ip_conntrack_info ctinfo,
9255 + unsigned int hooknum, struct sk_buff **pskb)
9257 + struct iphdr *iph = (*pskb)->nh.iph;
9258 + struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9259 + unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
9260 + struct pptp_pkt_hdr *pptph;
9264 + DEBUGP("entering\n");
9266 + /* Only mangle things once: DST for original direction
9267 + and SRC for reply direction. */
9268 + dir = CTINFO2DIR(ctinfo);
9269 + if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
9270 + && dir == IP_CT_DIR_ORIGINAL)
9271 + || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
9272 + && dir == IP_CT_DIR_REPLY))) {
9273 + DEBUGP("Not touching dir %s at hook %s\n",
9274 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9275 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9276 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9277 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
9278 + : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
9282 + /* if packet is too small, just skip it */
9283 + if (datalen < sizeof(struct pptp_pkt_hdr)+
9284 + sizeof(struct PptpControlHeader)) {
9285 + DEBUGP("pptp packet too short\n");
9289 + pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
9291 + /* if it's not a control message, we can't handle it */
9292 + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
9293 + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
9294 + DEBUGP("not a pptp control packet\n");
9298 + LOCK_BH(&ip_pptp_lock);
9300 + if (dir == IP_CT_DIR_ORIGINAL) {
9301 + /* reuqests sent by client to server (PNS->PAC) */
9302 + pptp_outbound_pkt(pskb, ct, ctinfo, exp);
9304 + /* response from the server to the client (PAC->PNS) */
9305 + pptp_inbound_pkt(pskb, ct, ctinfo, exp);
9308 + UNLOCK_BH(&ip_pptp_lock);
9313 +/* nat helper struct for control connection */
9314 +static struct ip_nat_helper pptp_tcp_helper = {
9315 + .list = { NULL, NULL },
9317 + .flags = IP_NAT_HELPER_F_ALWAYS,
9318 + .me = THIS_MODULE,
9319 + .tuple = { .src = { .ip = 0,
9320 + .u = { .tcp = { .port =
9321 + __constant_htons(PPTP_CONTROL_PORT) }
9325 + .u = { .all = 0 },
9326 + .protonum = IPPROTO_TCP
9330 + .mask = { .src = { .ip = 0,
9331 + .u = { .tcp = { .port = 0xFFFF } }
9334 + .u = { .all = 0 },
9335 + .protonum = 0xFFFF
9339 + .expect = pptp_nat_expected
9343 +static int __init init(void)
9345 + DEBUGP("%s: registering NAT helper\n", __FILE__);
9346 + if (ip_nat_helper_register(&pptp_tcp_helper)) {
9347 + printk(KERN_ERR "Unable to register NAT application helper "
9352 + printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
9356 +static void __exit fini(void)
9358 + DEBUGP("cleanup_module\n" );
9359 + ip_nat_helper_unregister(&pptp_tcp_helper);
9360 + printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
9365 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_proto_gre.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_proto_gre.c
9366 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
9367 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_proto_gre.c 2003-11-17 09:09:34.000000000 +0100
9370 + * ip_nat_proto_gre.c - Version 1.2
9372 + * NAT protocol helper module for GRE.
9374 + * GRE is a generic encapsulation protocol, which is generally not very
9375 + * suited for NAT, as it has no protocol-specific part as port numbers.
9377 + * It has an optional key field, which may help us distinguishing two
9378 + * connections between the same two hosts.
9380 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
9382 + * PPTP is built on top of a modified version of GRE, and has a mandatory
9383 + * field called "CallID", which serves us for the same purpose as the key
9384 + * field in plain GRE.
9386 + * Documentation about PPTP can be found in RFC 2637
9388 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
9390 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
9394 +#include <linux/config.h>
9395 +#include <linux/module.h>
9396 +#include <linux/ip.h>
9397 +#include <linux/netfilter_ipv4/ip_nat.h>
9398 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9399 +#include <linux/netfilter_ipv4/ip_nat_protocol.h>
9400 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
9402 +MODULE_LICENSE("GPL");
9403 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9404 +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
9407 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
9408 + ": " format, ## args)
9410 +#define DEBUGP(x, args...)
9413 +/* is key in given range between min and max */
9415 +gre_in_range(const struct ip_conntrack_tuple *tuple,
9416 + enum ip_nat_manip_type maniptype,
9417 + const union ip_conntrack_manip_proto *min,
9418 + const union ip_conntrack_manip_proto *max)
9422 + if (maniptype == IP_NAT_MANIP_SRC)
9423 + key = tuple->src.u.gre.key;
9425 + key = tuple->dst.u.gre.key;
9427 + return ntohl(key) >= ntohl(min->gre.key)
9428 + && ntohl(key) <= ntohl(max->gre.key);
9431 +/* generate unique tuple ... */
9433 +gre_unique_tuple(struct ip_conntrack_tuple *tuple,
9434 + const struct ip_nat_range *range,
9435 + enum ip_nat_manip_type maniptype,
9436 + const struct ip_conntrack *conntrack)
9438 + u_int32_t min, i, range_size;
9439 + u_int32_t key = 0, *keyptr;
9441 + if (maniptype == IP_NAT_MANIP_SRC)
9442 + keyptr = &tuple->src.u.gre.key;
9444 + keyptr = &tuple->dst.u.gre.key;
9446 + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
9448 + switch (tuple->dst.u.gre.version) {
9450 + DEBUGP("NATing GRE version 0 (ct=%p)\n",
9453 + range_size = 0xffffffff;
9455 + case GRE_VERSION_PPTP:
9456 + DEBUGP("%p: NATing GRE PPTP\n",
9459 + range_size = 0xffff;
9462 + printk(KERN_WARNING "nat_gre: unknown GRE version\n");
9468 + min = ntohl(range->min.gre.key);
9469 + range_size = ntohl(range->max.gre.key) - min + 1;
9472 + DEBUGP("min = %u, range_size = %u\n", min, range_size);
9474 + for (i = 0; i < range_size; i++, key++) {
9475 + *keyptr = htonl(min + key % range_size);
9476 + if (!ip_nat_used_tuple(tuple, conntrack))
9480 + DEBUGP("%p: no NAT mapping\n", conntrack);
9485 +/* manipulate a GRE packet according to maniptype */
9487 +gre_manip_pkt(struct iphdr *iph, size_t len,
9488 + const struct ip_conntrack_manip *manip,
9489 + enum ip_nat_manip_type maniptype)
9491 + struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
9492 + struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
9494 + /* we only have destination manip of a packet, since 'source key'
9495 + * is not present in the packet itself */
9496 + if (maniptype == IP_NAT_MANIP_DST) {
9497 + /* key manipulation is always dest */
9498 + switch (greh->version) {
9501 + DEBUGP("can't nat GRE w/o key\n");
9505 + /* FIXME: Never tested this code... */
9506 + *(gre_csum(greh)) =
9507 + ip_nat_cheat_check(~*(gre_key(greh)),
9509 + *(gre_csum(greh)));
9511 + *(gre_key(greh)) = manip->u.gre.key;
9513 + case GRE_VERSION_PPTP:
9514 + DEBUGP("call_id -> 0x%04x\n",
9515 + ntohl(manip->u.gre.key));
9516 + pgreh->call_id = htons(ntohl(manip->u.gre.key));
9519 + DEBUGP("can't nat unknown GRE version\n");
9525 +/* print out a nat tuple */
9526 +static unsigned int
9527 +gre_print(char *buffer,
9528 + const struct ip_conntrack_tuple *match,
9529 + const struct ip_conntrack_tuple *mask)
9531 + unsigned int len = 0;
9533 + if (mask->dst.u.gre.version)
9534 + len += sprintf(buffer + len, "version=%d ",
9535 + ntohs(match->dst.u.gre.version));
9537 + if (mask->dst.u.gre.protocol)
9538 + len += sprintf(buffer + len, "protocol=0x%x ",
9539 + ntohs(match->dst.u.gre.protocol));
9541 + if (mask->src.u.gre.key)
9542 + len += sprintf(buffer + len, "srckey=0x%x ",
9543 + ntohl(match->src.u.gre.key));
9545 + if (mask->dst.u.gre.key)
9546 + len += sprintf(buffer + len, "dstkey=0x%x ",
9547 + ntohl(match->src.u.gre.key));
9552 +/* print a range of keys */
9553 +static unsigned int
9554 +gre_print_range(char *buffer, const struct ip_nat_range *range)
9556 + if (range->min.gre.key != 0
9557 + || range->max.gre.key != 0xFFFF) {
9558 + if (range->min.gre.key == range->max.gre.key)
9559 + return sprintf(buffer, "key 0x%x ",
9560 + ntohl(range->min.gre.key));
9562 + return sprintf(buffer, "keys 0x%u-0x%u ",
9563 + ntohl(range->min.gre.key),
9564 + ntohl(range->max.gre.key));
9569 +/* nat helper struct */
9570 +static struct ip_nat_protocol gre =
9571 + { { NULL, NULL }, "GRE", IPPROTO_GRE,
9579 +static int __init init(void)
9581 + if (ip_nat_protocol_register(&gre))
9587 +static void __exit fini(void)
9589 + ip_nat_protocol_unregister(&gre);
9594 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_quake3.c
9595 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
9596 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_quake3.c 2003-12-11 10:24:00.845688024 +0100
9598 +/* Quake3 extension for UDP NAT alteration.
9599 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
9600 + * based on ip_nat_ftp.c and ip_nat_tftp.c
9602 + * ip_nat_quake3.c v0.0.3 2002-08-31
9604 + * This program is free software; you can redistribute it and/or
9605 + * modify it under the terms of the GNU General Public License
9606 + * as published by the Free Software Foundation; either version
9607 + * 2 of the License, or (at your option) any later version.
9609 + * Module load syntax:
9610 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
9612 + * please give the ports of all Quake3 master servers You wish to
9613 + * connect to. If you don't specify ports, the default will be UDP
9616 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
9619 + * - If you're one of those people who would try anything to lower
9620 + * latency while playing Quake (and who isn't :-) ), you may want to
9621 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
9622 + * outgoing UDP traffic.
9623 + * This will make ip_conntrack_quake3 add the necessary expectations,
9624 + * but there will be no overhead for client->server UDP streams. If
9625 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
9626 + * hook for every packet in the client->server UDP stream.
9627 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
9628 + * The IP addresses in the master connection payload (=IP addresses
9629 + * of Quake servers) have no relation with the master server so
9630 + * DNAT'ing the master connection to a server should not change the
9631 + * expected connections.
9632 + * - Not tested due to lack of equipment:
9633 + * - multiple Quake3 clients behind one MASQUERADE gateway
9634 + * - what if Quake3 client is running on router too
9637 +#include <linux/module.h>
9638 +#include <linux/netfilter_ipv4.h>
9639 +#include <linux/ip.h>
9640 +#include <linux/udp.h>
9642 +#include <linux/netfilter.h>
9643 +#include <linux/netfilter_ipv4/ip_tables.h>
9644 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9645 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
9646 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9647 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9649 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
9650 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
9651 +MODULE_LICENSE("GPL");
9653 +#define MAX_PORTS 8
9655 +static int ports[MAX_PORTS];
9656 +static int ports_c = 0;
9658 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
9659 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
9662 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
9663 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
9665 +#define DEBUGP printk
9667 +#define DEBUGP(format, args...)
9670 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
9672 +static unsigned int
9673 +quake3_nat_help(struct ip_conntrack *ct,
9674 + struct ip_conntrack_expect *exp,
9675 + struct ip_nat_info *info,
9676 + enum ip_conntrack_info ctinfo,
9677 + unsigned int hooknum,
9678 + struct sk_buff **pskb)
9680 + struct iphdr *iph = (*pskb)->nh.iph;
9681 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
9682 + struct ip_conntrack_tuple repl;
9683 + int dir = CTINFO2DIR(ctinfo);
9686 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
9687 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9688 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9689 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9690 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
9692 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9693 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
9695 + /* Only mangle things once: original direction in POST_ROUTING
9696 + and reply direction on PRE_ROUTING. */
9697 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
9698 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
9699 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
9700 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9701 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9702 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9703 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
9708 + DEBUGP("no conntrack expectation to modify\n");
9712 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
9713 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
9714 + i+6 < ntohs(udph->len);
9716 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
9717 + i, ntohs(udph->len),
9718 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
9719 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
9721 + memset(&repl, 0, sizeof(repl));
9723 + repl.dst.protonum = IPPROTO_UDP;
9724 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
9725 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
9726 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
9728 + ip_conntrack_change_expect(exp, &repl);
9734 +static unsigned int
9735 +quake3_nat_expected(struct sk_buff **pskb,
9736 + unsigned int hooknum,
9737 + struct ip_conntrack *ct,
9738 + struct ip_nat_info *info)
9740 + const struct ip_conntrack *master = ct->master->expectant;
9741 + struct ip_nat_multi_range mr;
9742 + u_int32_t newsrcip, newdstip, newip;
9744 + const struct ip_conntrack_tuple *repl =
9745 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
9746 + struct iphdr *iph = (*pskb)->nh.iph;
9747 + struct udphdr *udph = (void *)iph + iph->ihl*4;
9750 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
9751 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9753 + IP_NF_ASSERT(info);
9754 + IP_NF_ASSERT(master);
9755 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
9757 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
9758 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9760 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
9762 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9763 + "newsrc: %u.%u.%u.%u\n",
9764 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9765 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9766 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9767 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9768 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9773 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9774 + "newdst: %u.%u.%u.%u\n",
9775 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9776 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9777 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9778 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9779 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9784 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
9785 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
9787 + return ip_nat_setup_info(ct,&mr,hooknum);
9790 +static struct ip_nat_helper quake3[MAX_PORTS];
9791 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
9793 +static void fini(void)
9797 + for (i = 0 ; i < ports_c; i++) {
9798 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
9799 + ip_nat_helper_unregister(&quake3[i]);
9803 +static int __init init(void)
9809 + ports[0] = QUAKE3_MASTER_PORT;
9811 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
9812 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
9814 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
9815 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
9816 + quake3[i].mask.dst.protonum = 0xFFFF;
9817 + quake3[i].mask.src.u.udp.port = 0xFFFF;
9818 + quake3[i].help = quake3_nat_help;
9819 + quake3[i].flags = 0;
9820 + quake3[i].me = THIS_MODULE;
9821 + quake3[i].expect = quake3_nat_expected;
9823 + tmpname = &quake3_names[i][0];
9824 + if (ports[i] == QUAKE3_MASTER_PORT)
9825 + sprintf(tmpname, "quake3");
9827 + sprintf(tmpname, "quake3-%d", i);
9828 + quake3[i].name = tmpname;
9830 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
9831 + ports[i], quake3[i].name);
9832 + ret = ip_nat_helper_register(&quake3[i]);
9835 + printk("ip_nat_quake3: unable to register helper for port %d\n",
9847 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rtsp.c
9848 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
9849 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rtsp.c 2003-12-11 10:24:06.857774048 +0100
9852 + * RTSP extension for TCP NAT alteration
9853 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
9854 + * based on ip_nat_irc.c
9856 + * This program is free software; you can redistribute it and/or
9857 + * modify it under the terms of the GNU General Public License
9858 + * as published by the Free Software Foundation; either version
9859 + * 2 of the License, or (at your option) any later version.
9861 + * Module load syntax:
9862 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
9863 + * stunaddr=<address>
9864 + * destaction=[auto|strip|none]
9866 + * If no ports are specified, the default will be port 554 only.
9868 + * stunaddr specifies the address used to detect that a client is using STUN.
9869 + * If this address is seen in the destination parameter, it is assumed that
9870 + * the client has already punched a UDP hole in the firewall, so we don't
9871 + * mangle the client_port. If none is specified, it is autodetected. It
9872 + * only needs to be set if you have multiple levels of NAT. It should be
9873 + * set to the external address that the STUN clients detect. Note that in
9874 + * this case, it will not be possible for clients to use UDP with servers
9875 + * between the NATs.
9877 + * If no destaction is specified, auto is used.
9878 + * destaction=auto: strip destination parameter if it is not stunaddr.
9879 + * destaction=strip: always strip destination parameter (not recommended).
9880 + * destaction=none: do not touch destination parameter (not recommended).
9883 +#include <linux/module.h>
9884 +#include <linux/netfilter_ipv4.h>
9885 +#include <linux/ip.h>
9886 +#include <linux/tcp.h>
9887 +#include <linux/kernel.h>
9888 +#include <net/tcp.h>
9889 +#include <linux/netfilter_ipv4/ip_nat.h>
9890 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9891 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9892 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
9893 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9895 +#include <linux/inet.h>
9896 +#include <linux/ctype.h>
9897 +#define NF_NEED_STRNCASECMP
9898 +#define NF_NEED_STRTOU16
9899 +#include <linux/netfilter_helpers.h>
9900 +#define NF_NEED_MIME_NEXTLINE
9901 +#include <linux/netfilter_mime.h>
9903 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
9904 +#ifdef IP_NF_RTSP_DEBUG
9905 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
9907 +#define DEBUGP(args...)
9910 +#define MAX_PORTS 8
9911 +#define DSTACT_AUTO 0
9912 +#define DSTACT_STRIP 1
9913 +#define DSTACT_NONE 2
9915 +static int ports[MAX_PORTS];
9916 +static char* stunaddr = NULL;
9917 +static char* destaction = NULL;
9919 +static int num_ports = 0;
9920 +static u_int32_t extip = 0;
9921 +static int dstact = 0;
9923 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
9924 +MODULE_DESCRIPTION("RTSP network address translation module");
9925 +MODULE_LICENSE("GPL");
9927 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9928 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
9929 +MODULE_PARM(stunaddr, "s");
9930 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
9931 +MODULE_PARM(destaction, "s");
9932 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
9935 +/* protects rtsp part of conntracks */
9936 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
9938 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
9940 +/*** helper functions ***/
9943 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
9945 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
9946 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
9948 + *pptcpdata = (char*)tcph + tcph->doff*4;
9949 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
9952 +/*** nat functions ***/
9955 + * Mangle the "Transport:" header:
9956 + * - Replace all occurences of "client_port=<spec>"
9957 + * - Handle destination parameter
9960 + * ct, ctinfo = conntrack context
9962 + * tranoff = Transport header offset from TCP data
9963 + * tranlen = Transport header length (incl. CRLF)
9964 + * rport_lo = replacement low port (host endian)
9965 + * rport_hi = replacement high port (host endian)
9967 + * Returns packet size difference.
9969 + * Assumes that a complete transport header is present, ending with CR or LF
9972 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
9973 + struct ip_conntrack_expect* exp,
9974 + struct sk_buff** pskb, uint tranoff, uint tranlen)
9979 + char rbuf1[16]; /* Replacement buffer (one port) */
9980 + uint rbuf1len; /* Replacement len (one port) */
9981 + char rbufa[16]; /* Replacement buffer (all ports) */
9982 + uint rbufalen; /* Replacement len (all ports) */
9984 + u_int16_t loport, hiport;
9986 + uint diff; /* Number of bytes we removed */
9988 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
9989 + struct ip_conntrack_tuple t;
9991 + char szextaddr[15+1];
9995 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
9996 + ptran = ptcp+tranoff;
9998 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
9999 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
10000 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
10002 + INFOP("sanity check failed\n");
10006 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
10008 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10010 + t.dst.ip = newip;
10012 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
10013 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
10014 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
10016 + rbuf1len = rbufalen = 0;
10017 + switch (prtspexp->pbtype)
10020 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10022 + t.dst.u.udp.port = htons(loport);
10023 + if (ip_conntrack_change_expect(exp, &t) == 0)
10025 + DEBUGP("using port %hu\n", loport);
10031 + rbuf1len = sprintf(rbuf1, "%hu", loport);
10032 + rbufalen = sprintf(rbufa, "%hu", loport);
10036 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
10038 + t.dst.u.udp.port = htons(loport);
10039 + if (ip_conntrack_change_expect(exp, &t) == 0)
10041 + hiport = loport + ~exp->mask.dst.u.udp.port;
10042 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
10048 + rbuf1len = sprintf(rbuf1, "%hu", loport);
10049 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
10053 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10055 + t.dst.u.udp.port = htons(loport);
10056 + if (ip_conntrack_change_expect(exp, &t) == 0)
10058 + DEBUGP("using port %hu (1 of 2)\n", loport);
10062 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
10064 + t.dst.u.udp.port = htons(hiport);
10065 + if (ip_conntrack_change_expect(exp, &t) == 0)
10067 + DEBUGP("using port %hu (2 of 2)\n", hiport);
10071 + if (loport != 0 && hiport != 0)
10073 + rbuf1len = sprintf(rbuf1, "%hu", loport);
10074 + if (hiport == loport+1)
10076 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
10080 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
10088 + if (rbuf1len == 0)
10090 + return 0; /* cannot get replacement port(s) */
10093 + /* Transport: tran;field;field=val,tran;field;field=val,... */
10094 + while (off < tranlen)
10097 + const char* pparamend;
10098 + uint nextparamoff;
10100 + pparamend = memchr(ptran+off, ',', tranlen-off);
10101 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
10102 + nextparamoff = pparamend-ptcp;
10105 + * We pass over each param twice. On the first pass, we look for a
10106 + * destination= field. It is handled by the security policy. If it
10107 + * is present, allowed, and equal to our external address, we assume
10108 + * that STUN is being used and we leave the client_port= field alone.
10112 + while (off < nextparamoff)
10114 + const char* pfieldend;
10115 + uint nextfieldoff;
10117 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10118 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10120 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
10122 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
10126 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
10128 + diff = nextfieldoff-off;
10129 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10130 + off, diff, NULL, 0))
10132 + /* mangle failed, all we can do is bail */
10135 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10136 + ptran = ptcp+tranoff;
10138 + nextparamoff -= diff;
10139 + nextfieldoff -= diff;
10143 + off = nextfieldoff;
10150 + while (off < nextparamoff)
10152 + const char* pfieldend;
10153 + uint nextfieldoff;
10155 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10156 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10158 + if (strncmp(ptran+off, "client_port=", 12) == 0)
10164 + char* rbuf = rbuf1;
10165 + uint rbuflen = rbuf1len;
10168 + origoff = (ptran-ptcp)+off;
10170 + numlen = nf_strtou16(ptran+off, &port);
10172 + origlen += numlen;
10173 + if (port != prtspexp->loport)
10175 + DEBUGP("multiple ports found, port %hu ignored\n", port);
10179 + if (ptran[off] == '-' || ptran[off] == '/')
10183 + numlen = nf_strtou16(ptran+off, &port);
10185 + origlen += numlen;
10187 + rbuflen = rbufalen;
10191 + * note we cannot just memcpy() if the sizes are the same.
10192 + * the mangle function does skb resizing, checks for a
10193 + * cloned skb, and updates the checksums.
10195 + * parameter 4 below is offset from start of tcp data.
10197 + diff = origlen-rbuflen;
10198 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10199 + origoff, origlen, rbuf, rbuflen))
10201 + /* mangle failed, all we can do is bail */
10204 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10205 + ptran = ptcp+tranoff;
10207 + nextparamoff -= diff;
10208 + nextfieldoff -= diff;
10212 + off = nextfieldoff;
10215 + off = nextparamoff;
10221 +static unsigned int
10222 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
10224 + struct ip_nat_multi_range mr;
10225 + u_int32_t newdstip, newsrcip, newip;
10227 + struct ip_conntrack *master = master_ct(ct);
10229 + IP_NF_ASSERT(info);
10230 + IP_NF_ASSERT(master);
10232 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10234 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10235 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10236 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
10238 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
10239 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
10241 + mr.rangesize = 1;
10242 + /* We don't want to manip the per-protocol, just the IPs. */
10243 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10244 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
10246 + return ip_nat_setup_info(ct, &mr, hooknum);
10250 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10251 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10261 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
10262 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
10264 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
10266 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10268 + hdrsoff = exp->seq - ntohl(tcph->seq);
10269 + hdrslen = prtspexp->len;
10272 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
10274 + if (linelen == 0)
10278 + if (off > hdrsoff+hdrslen)
10280 + INFOP("!! overrun !!");
10283 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10285 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
10287 + uint oldtcplen = tcplen;
10288 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
10292 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10293 + hdrslen -= (oldtcplen-tcplen);
10294 + off -= (oldtcplen-tcplen);
10295 + lineoff -= (oldtcplen-tcplen);
10296 + linelen -= (oldtcplen-tcplen);
10297 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10301 + return NF_ACCEPT;
10305 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10306 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10308 + /* XXX: unmangle */
10309 + return NF_ACCEPT;
10313 +help(struct ip_conntrack* ct,
10314 + struct ip_conntrack_expect* exp,
10315 + struct ip_nat_info* info,
10316 + enum ip_conntrack_info ctinfo,
10317 + unsigned int hooknum,
10318 + struct sk_buff** pskb)
10320 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
10321 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
10324 + struct ip_ct_rtsp_expect* ct_rtsp_info;
10325 + int rc = NF_ACCEPT;
10327 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
10329 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
10330 + return NF_ACCEPT;
10333 + ct_rtsp_info = &exp->help.exp_rtsp_info;
10336 + * Only mangle things once: original direction in POST_ROUTING
10337 + * and reply direction on PRE_ROUTING.
10339 + dir = CTINFO2DIR(ctinfo);
10340 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10341 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
10343 + DEBUGP("Not touching dir %s at hook %s\n",
10344 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10345 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10346 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10347 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10348 + return NF_ACCEPT;
10350 + DEBUGP("got beyond not touching\n");
10352 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
10354 + LOCK_BH(&ip_rtsp_lock);
10355 + /* Ensure the packet contains all of the marked data */
10356 + if (!between(exp->seq + ct_rtsp_info->len,
10357 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
10359 + /* Partial retransmission? Probably a hacker. */
10360 + if (net_ratelimit())
10362 + INFOP("partial packet %u/%u in %u/%u\n",
10363 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
10365 + UNLOCK_BH(&ip_rtsp_lock);
10371 + case IP_CT_DIR_ORIGINAL:
10372 + rc = help_out(ct, ctinfo, exp, pskb);
10374 + case IP_CT_DIR_REPLY:
10375 + rc = help_in(ct, ctinfo, exp, pskb);
10380 + UNLOCK_BH(&ip_rtsp_lock);
10385 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
10386 +static char rtsp_names[MAX_PORTS][10];
10388 +/* This function is intentionally _NOT_ defined as __exit */
10394 + for (i = 0; i < num_ports; i++)
10396 + DEBUGP("unregistering helper for port %d\n", ports[i]);
10397 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
10406 + struct ip_nat_helper* hlpr;
10409 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
10411 + if (ports[0] == 0)
10413 + ports[0] = RTSP_PORT;
10416 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
10418 + hlpr = &ip_nat_rtsp_helpers[i];
10419 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
10421 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
10422 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
10423 + hlpr->mask.src.u.tcp.port = 0xFFFF;
10424 + hlpr->mask.dst.protonum = 0xFFFF;
10425 + hlpr->help = help;
10427 + hlpr->me = THIS_MODULE;
10428 + hlpr->expect = expected;
10430 + tmpname = &rtsp_names[i][0];
10431 + if (ports[i] == RTSP_PORT)
10433 + sprintf(tmpname, "rtsp");
10437 + sprintf(tmpname, "rtsp-%d", i);
10439 + hlpr->name = tmpname;
10441 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
10442 + ret = ip_nat_helper_register(hlpr);
10446 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
10452 + if (stunaddr != NULL)
10454 + extip = in_aton(stunaddr);
10456 + if (destaction != NULL)
10458 + if (strcmp(destaction, "auto") == 0)
10460 + dstact = DSTACT_AUTO;
10462 + if (strcmp(destaction, "strip") == 0)
10464 + dstact = DSTACT_STRIP;
10466 + if (strcmp(destaction, "none") == 0)
10468 + dstact = DSTACT_NONE;
10474 +module_init(init);
10475 +module_exit(fini);
10476 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rule.c
10477 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rule.c 2003-11-26 21:43:38.000000000 +0100
10478 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rule.c 2003-12-11 10:23:17.227319024 +0100
10481 sizeof(struct ipt_entry),
10482 sizeof(struct ipt_standard),
10483 - 0, { 0, 0 }, { } },
10484 + 0, NULL, 0, { 0, 0 }, { } },
10485 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10486 -NF_ACCEPT - 1 } },
10490 sizeof(struct ipt_entry),
10491 sizeof(struct ipt_standard),
10492 - 0, { 0, 0 }, { } },
10493 + 0, NULL, 0, { 0, 0 }, { } },
10494 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10495 -NF_ACCEPT - 1 } },
10499 sizeof(struct ipt_entry),
10500 sizeof(struct ipt_standard),
10501 - 0, { 0, 0 }, { } },
10502 + 0, NULL, 0, { 0, 0 }, { } },
10503 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10508 sizeof(struct ipt_entry),
10509 sizeof(struct ipt_error),
10510 - 0, { 0, 0 }, { } },
10511 + 0, NULL, 0, { 0, 0 }, { } },
10512 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10515 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_standalone.c
10516 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_standalone.c 2003-11-26 21:45:10.000000000 +0100
10517 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_standalone.c 2003-12-11 10:23:57.173246320 +0100
10518 @@ -260,7 +260,13 @@
10522 -/* Protocol registration. */
10524 + * ip_nat_protocol_register - Register a layer 4 protocol helper
10525 + * @proto: structure describing this helper
10527 + * This function is called by NAT layer 4 protocol helpers to register
10528 + * themselvers with the NAT core.
10530 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
10533 @@ -281,9 +287,16 @@
10537 -/* Noone stores the protocol anywhere; simply delete it. */
10539 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
10540 + * @proto: sturcture describing the helper
10542 + * This function is called by NAT layer 4 protocol helpers to
10543 + * unregister themselves from the NAT core.
10545 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
10547 + /* Noone stores the protocol anywhere; simply delete it. */
10548 WRITE_LOCK(&ip_nat_lock);
10549 LIST_DELETE(&protos, proto);
10550 WRITE_UNLOCK(&ip_nat_lock);
10551 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_talk.c
10552 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
10553 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_talk.c 2003-12-11 10:24:09.250410312 +0100
10556 + * talk extension for UDP NAT alteration.
10557 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10559 + * This program is free software; you can redistribute it and/or
10560 + * modify it under the terms of the GNU General Public License
10561 + * as published by the Free Software Foundation; either version
10562 + * 2 of the License, or (at your option) any later version.
10564 + * Module load syntax:
10565 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
10567 + * talk=[0|1] disable|enable old talk support
10568 + * ntalk=[0|1] disable|enable ntalk support
10569 + * ntalk2=[0|1] disable|enable ntalk2 support
10571 + * The default is talk=1 ntalk=1 ntalk2=1
10575 +#include <linux/module.h>
10576 +#include <linux/netfilter_ipv4.h>
10577 +#include <linux/ip.h>
10578 +#include <linux/udp.h>
10579 +#include <linux/kernel.h>
10580 +#include <net/tcp.h>
10581 +#include <net/udp.h>
10583 +#include <linux/netfilter_ipv4/ip_nat.h>
10584 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
10585 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
10586 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
10587 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10589 +/* Default all talk protocols are supported */
10590 +static int talk = 1;
10591 +static int ntalk = 1;
10592 +static int ntalk2 = 1;
10593 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
10594 +MODULE_DESCRIPTION("talk network address translation module");
10595 +#ifdef MODULE_PARM
10596 +MODULE_PARM(talk, "i");
10597 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
10598 +MODULE_PARM(ntalk, "i");
10599 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
10600 +MODULE_PARM(ntalk2, "i");
10601 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
10605 +#define DEBUGP printk
10606 +#define IP_NAT_TALK_DEBUG
10608 +#define DEBUGP(format, args...)
10611 +/* FIXME: Time out? --RR */
10614 +mangle_packet(struct sk_buff **pskb,
10615 + struct ip_conntrack *ct,
10618 + struct talk_addr *addr,
10619 + struct talk_addr *ctl_addr)
10621 + struct iphdr *iph = (*pskb)->nh.iph;
10622 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10623 + size_t udplen = (*pskb)->len - iph->ihl * 4;
10625 + /* Fortunately talk sends a structure with the address and
10626 + port in it. The size of the packet won't change. */
10628 + if (ctl_addr == NULL) {
10630 + if (addr->ta_addr == INADDR_ANY)
10632 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
10633 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10634 + NIPQUAD(newip), ntohs(port));
10635 + addr->ta_addr = newip;
10636 + addr->ta_port = port;
10639 + if (addr->ta_addr != INADDR_ANY) {
10640 + /* Change address inside packet to match way we're mapping
10641 + this connection. */
10642 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
10643 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10644 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
10645 + ntohs(addr->ta_port));
10646 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10648 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
10649 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10650 + NIPQUAD(newip), ntohs(port));
10651 + ctl_addr->ta_addr = newip;
10652 + ctl_addr->ta_port = port;
10655 + /* Fix checksums */
10656 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
10658 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
10659 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
10661 + ip_send_check(iph);
10665 +static int talk_help_msg(struct ip_conntrack *ct,
10666 + struct sk_buff **pskb,
10668 + struct talk_addr *addr,
10669 + struct talk_addr *ctl_addr)
10674 + unsigned int verdict = NF_ACCEPT;
10676 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
10677 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10678 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10681 + /* Change address inside packet to match way we're mapping
10682 + this connection. */
10683 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10684 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
10685 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
10686 + NIPQUAD(newip), ntohs(port));
10688 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
10689 + verdict = NF_DROP;
10694 +static int talk_help_response(struct ip_conntrack *ct,
10695 + struct ip_conntrack_expect *exp,
10696 + struct sk_buff **pskb,
10699 + struct talk_addr *addr)
10703 + struct ip_conntrack_tuple t;
10704 + struct ip_ct_talk_expect *ct_talk_info;
10706 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
10707 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10710 + LOCK_BH(&ip_talk_lock);
10711 + ct_talk_info = &exp->help.exp_talk_info;
10713 + if (!(answer == SUCCESS
10714 + && (type == LOOK_UP || type == ANNOUNCE)
10715 + && exp != NULL)) {
10716 + UNLOCK_BH(&ip_talk_lock);
10717 + return NF_ACCEPT;
10720 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
10721 + ntohs(ct_talk_info->port),
10722 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
10724 + /* Change address inside packet to match way we're mapping
10725 + this connection. */
10726 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
10727 + IP_CT_DIR_REPLY].tuple.dst.ip;
10728 + /* We can read expect here without conntrack lock, since it's
10729 + only set in ip_conntrack_talk , with ip_talk_lock held
10732 + t.dst.ip = newip;
10734 + /* Try to get same port: if not, try to change it. */
10735 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
10736 + if (type == LOOK_UP)
10737 + t.dst.u.tcp.port = htons(port);
10739 + t.dst.u.udp.port = htons(port);
10741 + if (ip_conntrack_change_expect(exp, &t) == 0) {
10742 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
10746 + UNLOCK_BH(&ip_talk_lock);
10748 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
10751 + return NF_ACCEPT;
10754 +static unsigned int talk_help(struct ip_conntrack *ct,
10755 + struct ip_conntrack_expect *exp,
10756 + struct ip_nat_info *info,
10757 + enum ip_conntrack_info ctinfo,
10758 + unsigned int hooknum,
10759 + struct sk_buff **pskb,
10762 + struct iphdr *iph = (*pskb)->nh.iph;
10763 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10764 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
10765 + char *data = (char *)udph + sizeof(struct udphdr);
10768 + /* Only mangle things once: original direction in POST_ROUTING
10769 + and reply direction on PRE_ROUTING. */
10770 + dir = CTINFO2DIR(ctinfo);
10771 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10772 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
10773 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
10774 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10775 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10776 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10777 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10778 + return NF_ACCEPT;
10780 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
10781 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10782 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10783 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10784 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10785 + NIPQUAD(iph->saddr), ntohs(udph->source),
10786 + NIPQUAD(iph->daddr), ntohs(udph->dest),
10789 + /* Because conntrack does not drop packets, checking must be repeated here... */
10790 + if (talk_port == TALK_PORT) {
10791 + if (dir == IP_CT_DIR_ORIGINAL
10792 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
10793 + return talk_help_msg(ct, pskb,
10794 + ((struct talk_msg *)data)->type,
10795 + &(((struct talk_msg *)data)->addr),
10796 + &(((struct talk_msg *)data)->ctl_addr));
10797 + else if (dir == IP_CT_DIR_REPLY
10798 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
10799 + return talk_help_response(ct, exp, pskb,
10800 + ((struct talk_response *)data)->type,
10801 + ((struct talk_response *)data)->answer,
10802 + &(((struct talk_response *)data)->addr));
10804 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
10805 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
10806 + (unsigned)udplen - sizeof(struct udphdr),
10807 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
10811 + if (dir == IP_CT_DIR_ORIGINAL) {
10813 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
10814 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
10815 + return talk_help_msg(ct, pskb,
10816 + ((struct ntalk_msg *)data)->type,
10817 + &(((struct ntalk_msg *)data)->addr),
10818 + &(((struct ntalk_msg *)data)->ctl_addr));
10820 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
10821 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
10822 + && udplen == sizeof(struct udphdr)
10823 + + sizeof(struct ntalk2_msg)
10824 + + ((struct ntalk2_msg *)data)->extended)
10825 + return talk_help_msg(ct, pskb,
10826 + ((struct ntalk2_msg *)data)->type,
10827 + &(((struct ntalk2_msg *)data)->addr),
10828 + &(((struct ntalk2_msg *)data)->ctl_addr));
10830 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
10831 + (unsigned)udplen - sizeof(struct udphdr),
10832 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
10837 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
10838 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
10839 + return talk_help_response(ct, exp, pskb,
10840 + ((struct ntalk_response *)data)->type,
10841 + ((struct ntalk_response *)data)->answer,
10842 + &(((struct ntalk_response *)data)->addr));
10844 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
10845 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
10846 + return talk_help_response(ct, exp, pskb,
10847 + ((struct ntalk2_response *)data)->type,
10848 + ((struct ntalk2_response *)data)->answer,
10849 + &(((struct ntalk2_response *)data)->addr));
10851 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
10852 + (unsigned)udplen - sizeof(struct udphdr),
10853 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
10860 +static unsigned int help(struct ip_conntrack *ct,
10861 + struct ip_conntrack_expect *exp,
10862 + struct ip_nat_info *info,
10863 + enum ip_conntrack_info ctinfo,
10864 + unsigned int hooknum,
10865 + struct sk_buff **pskb)
10867 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
10870 +static unsigned int nhelp(struct ip_conntrack *ct,
10871 + struct ip_conntrack_expect *exp,
10872 + struct ip_nat_info *info,
10873 + enum ip_conntrack_info ctinfo,
10874 + unsigned int hooknum,
10875 + struct sk_buff **pskb)
10877 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
10880 +static unsigned int
10881 +talk_nat_expected(struct sk_buff **pskb,
10882 + unsigned int hooknum,
10883 + struct ip_conntrack *ct,
10884 + struct ip_nat_info *info);
10886 +static struct ip_nat_helper talk_helpers[2] =
10887 + { { { NULL, NULL },
10888 + "talk", /* name */
10889 + IP_NAT_HELPER_F_ALWAYS, /* flags */
10890 + THIS_MODULE, /* module */
10891 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
10892 + { 0, { 0 }, IPPROTO_UDP } },
10893 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
10894 + { 0, { 0 }, 0xFFFF } },
10895 + help, /* helper */
10896 + talk_nat_expected }, /* expectfn */
10897 + { { NULL, NULL },
10898 + "ntalk", /* name */
10899 + IP_NAT_HELPER_F_ALWAYS, /* flags */
10900 + THIS_MODULE, /* module */
10901 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
10902 + { 0, { 0 }, IPPROTO_UDP } },
10903 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
10904 + { 0, { 0 }, 0xFFFF } },
10905 + nhelp, /* helper */
10906 + talk_nat_expected } /* expectfn */
10909 +static unsigned int
10910 +talk_nat_expected(struct sk_buff **pskb,
10911 + unsigned int hooknum,
10912 + struct ip_conntrack *ct,
10913 + struct ip_nat_info *info)
10915 + struct ip_nat_multi_range mr;
10916 + u_int32_t newdstip, newsrcip, newip;
10918 + unsigned int ret;
10920 + struct ip_conntrack *master = master_ct(ct);
10922 + IP_NF_ASSERT(info);
10923 + IP_NF_ASSERT(master);
10925 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
10927 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
10929 + LOCK_BH(&ip_talk_lock);
10930 + port = ct->master->help.exp_talk_info.port;
10931 + UNLOCK_BH(&ip_talk_lock);
10933 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
10934 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10935 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10936 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10937 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10940 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10941 + /* Callee client -> caller server */
10942 +#ifdef IP_NAT_TALK_DEBUG
10943 + struct iphdr *iph = (*pskb)->nh.iph;
10944 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10946 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10947 + NIPQUAD(iph->saddr), ntohs(udph->source),
10948 + NIPQUAD(iph->daddr), ntohs(udph->dest));
10950 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10951 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
10952 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10953 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
10955 + /* Callee client -> caller client */
10956 +#ifdef IP_NAT_TALK_DEBUG
10957 + struct iphdr *iph = (*pskb)->nh.iph;
10958 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
10960 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10961 + NIPQUAD(iph->saddr), ntohs(tcph->source),
10962 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
10964 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
10965 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10966 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10967 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
10969 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
10970 + newip = newsrcip;
10972 + newip = newdstip;
10974 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
10976 + mr.rangesize = 1;
10977 + /* We don't want to manip the per-protocol, just the IPs... */
10978 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10979 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
10981 + /* ... unless we're doing a MANIP_DST, in which case, make
10982 + sure we map to the correct port */
10983 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
10984 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
10985 + mr.range[0].min = mr.range[0].max
10986 + = ((union ip_conntrack_manip_proto)
10987 + { .udp = { port } });
10989 + ret = ip_nat_setup_info(ct, &mr, hooknum);
10991 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10992 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
10993 + /* NAT expectfn called with ip_nat_lock write-locked */
10994 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
10999 +static int __init init(void)
11004 + ret = ip_nat_helper_register(&talk_helpers[0]);
11009 + if (ntalk > 0 || ntalk2 > 0) {
11010 + ret = ip_nat_helper_register(&talk_helpers[1]);
11012 + if (ret != 0 && talk > 0)
11013 + ip_nat_helper_unregister(&talk_helpers[0]);
11018 +static void __exit fini(void)
11021 + ip_nat_helper_unregister(&talk_helpers[0]);
11022 + if (ntalk > 0 || ntalk2 > 0)
11023 + ip_nat_helper_unregister(&talk_helpers[1]);
11026 +module_init(init);
11027 +module_exit(fini);
11028 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_tftp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_tftp.c
11029 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_tftp.c 2003-11-26 21:43:31.000000000 +0100
11030 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_tftp.c 2003-12-11 10:23:13.893825792 +0100
11031 @@ -164,8 +164,6 @@
11032 ports[0] = TFTP_PORT;
11034 for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
11035 - memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
11037 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
11038 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
11039 tftp[i].mask.dst.protonum = 0xFFFF;
11040 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_pool.c linux-2.6.0-test11/net/ipv4/netfilter/ip_pool.c
11041 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
11042 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_pool.c 2003-12-11 10:23:32.944929584 +0100
11044 +/* Kernel module for IP pool management */
11046 +#include <linux/module.h>
11047 +#include <linux/ip.h>
11048 +#include <linux/skbuff.h>
11049 +#include <linux/netfilter_ipv4/ip_tables.h>
11050 +#include <linux/netfilter_ipv4/ip_pool.h>
11051 +#include <linux/errno.h>
11052 +#include <asm/uaccess.h>
11053 +#include <asm/bitops.h>
11054 +#include <linux/interrupt.h>
11055 +#include <linux/spinlock.h>
11060 +#define DP(format, args...)
11063 +MODULE_LICENSE("GPL");
11065 +#define NR_POOL 16
11066 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
11069 + u_int32_t first_ip; /* host byte order, included in range */
11070 + u_int32_t last_ip; /* host byte order, included in range */
11071 + void *members; /* the bitmap proper */
11072 + int nr_use; /* total nr. of tests through this */
11073 + int nr_match; /* total nr. of matches through this */
11077 +static struct ip_pool *POOL;
11079 +static inline struct ip_pool *lookup(ip_pool_t index)
11081 + if (index < 0 || index >= nr_pool) {
11082 + DP("ip_pool:lookup: bad index %d\n", index);
11085 + return POOL+index;
11088 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
11090 + struct ip_pool *pool = lookup(index);
11093 + if (!pool || !pool->members)
11095 + read_lock_bh(&pool->lock);
11096 + if (pool->members) {
11097 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
11098 + addr -= pool->first_ip;
11099 + if (test_bit(addr, pool->members)) {
11101 +#ifdef CONFIG_IP_POOL_STATISTICS
11102 + pool->nr_match++;
11106 +#ifdef CONFIG_IP_POOL_STATISTICS
11110 + read_unlock_bh(&pool->lock);
11114 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
11116 + struct ip_pool *pool;
11119 + pool = lookup(index);
11120 + if ( !pool || !pool->members
11121 + || addr < pool->first_ip || addr > pool->last_ip)
11123 + read_lock_bh(&pool->lock);
11124 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
11125 + addr -= pool->first_ip;
11127 + ? (0 != test_and_clear_bit(addr, pool->members))
11128 + : (0 != test_and_set_bit(addr, pool->members));
11130 + read_unlock_bh(&pool->lock);
11134 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
11136 + int res = pool_change(index,addr,isdel);
11138 + if (!isdel) res = !res;
11142 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
11144 + return 4*((((b-a+8)/8)+3)/4);
11147 +static inline int poolbytes(ip_pool_t index)
11149 + struct ip_pool *pool = lookup(index);
11151 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
11154 +static int setpool(
11160 + struct ip_pool_request req;
11162 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
11163 + if (!capable(CAP_NET_ADMIN))
11165 + if (optval != SO_IP_POOL)
11167 + if (len != sizeof(req))
11169 + if (copy_from_user(&req, user, sizeof(req)) != 0)
11171 + printk("obsolete op - upgrade your ippool(8) utility.\n");
11175 +static int getpool(
11181 + struct ip_pool_request req;
11182 + struct ip_pool *pool;
11185 + void *newmembers;
11188 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
11189 + if (!capable(CAP_NET_ADMIN))
11191 + if (optval != SO_IP_POOL)
11193 + if (*len != sizeof(req)) {
11196 + if (copy_from_user(&req, user, sizeof(req)) != 0)
11198 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
11199 + if (req.op < IP_POOL_BAD001) {
11200 + printk("obsolete op - upgrade your ippool(8) utility.\n");
11204 + case IP_POOL_HIGH_NR:
11205 + DP("ip_pool HIGH_NR\n");
11206 + req.index = IP_POOL_NONE;
11207 + for (i=0; i<nr_pool; i++)
11208 + if (POOL[i].members)
11210 + return copy_to_user(user, &req, sizeof(req));
11211 + case IP_POOL_LOOKUP:
11212 + DP("ip_pool LOOKUP\n");
11213 + pool = lookup(req.index);
11216 + if (!pool->members)
11218 + req.addr = htonl(pool->first_ip);
11219 + req.addr2 = htonl(pool->last_ip);
11220 + return copy_to_user(user, &req, sizeof(req));
11221 + case IP_POOL_USAGE:
11222 + DP("ip_pool USE\n");
11223 + pool = lookup(req.index);
11226 + if (!pool->members)
11228 + req.addr = pool->nr_use;
11229 + req.addr2 = pool->nr_match;
11230 + return copy_to_user(user, &req, sizeof(req));
11231 + case IP_POOL_TEST_ADDR:
11232 + DP("ip_pool TEST 0x%08x\n", req.addr);
11233 + pool = lookup(req.index);
11237 + read_lock_bh(&pool->lock);
11238 + if (!pool->members) {
11239 + DP("ip_pool TEST_ADDR no members in pool\n");
11241 + goto unlock_and_return_res;
11243 + req.addr = ntohl(req.addr);
11244 + if (req.addr < pool->first_ip) {
11245 + DP("ip_pool TEST_ADDR address < pool bounds\n");
11247 + goto unlock_and_return_res;
11249 + if (req.addr > pool->last_ip) {
11250 + DP("ip_pool TEST_ADDR address > pool bounds\n");
11252 + goto unlock_and_return_res;
11254 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
11256 + read_unlock_bh(&pool->lock);
11257 + return copy_to_user(user, &req, sizeof(req));
11258 + case IP_POOL_FLUSH:
11259 + DP("ip_pool FLUSH not yet implemented.\n");
11261 + case IP_POOL_DESTROY:
11262 + DP("ip_pool DESTROY not yet implemented.\n");
11264 + case IP_POOL_INIT:
11265 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
11266 + pool = lookup(req.index);
11269 + req.addr = ntohl(req.addr);
11270 + req.addr2 = ntohl(req.addr2);
11271 + if (req.addr > req.addr2) {
11272 + DP("ip_pool INIT bad ip range\n");
11275 + newbytes = bitmap_bytes(req.addr, req.addr2);
11276 + newmembers = kmalloc(newbytes, GFP_KERNEL);
11277 + if (!newmembers) {
11278 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
11281 + memset(newmembers, 0, newbytes);
11282 + write_lock_bh(&pool->lock);
11283 + if (pool->members) {
11284 + DP("ip_pool INIT pool %d exists\n", req.index);
11285 + kfree(newmembers);
11287 + goto unlock_and_return_res;
11289 + pool->first_ip = req.addr;
11290 + pool->last_ip = req.addr2;
11291 + pool->nr_use = 0;
11292 + pool->nr_match = 0;
11293 + pool->members = newmembers;
11294 + write_unlock_bh(&pool->lock);
11296 + case IP_POOL_ADD_ADDR:
11297 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
11298 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
11299 + return copy_to_user(user, &req, sizeof(req));
11300 + case IP_POOL_DEL_ADDR:
11301 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
11302 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
11303 + return copy_to_user(user, &req, sizeof(req));
11305 + DP("ip_pool:getpool bad op %d\n", req.op);
11310 +unlock_and_return_res:
11312 + read_unlock_bh(&pool->lock);
11316 +static struct nf_sockopt_ops so_pool
11317 += { { NULL, NULL }, PF_INET,
11318 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
11319 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
11322 +MODULE_PARM(nr_pool, "i");
11324 +static int __init init(void)
11329 + if (nr_pool < 1) {
11330 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
11333 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
11335 + printk("ip_pool module init: out of memory for nr_pool %d\n",
11339 + for (i=0; i<nr_pool; i++) {
11340 + POOL[i].first_ip = 0;
11341 + POOL[i].last_ip = 0;
11342 + POOL[i].members = 0;
11343 + POOL[i].nr_use = 0;
11344 + POOL[i].nr_match = 0;
11345 + POOL[i].lock = RW_LOCK_UNLOCKED;
11347 + res = nf_register_sockopt(&so_pool);
11348 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
11356 +static void __exit fini(void)
11360 + DP("ip_pool:fini BYEBYE\n");
11361 + nf_unregister_sockopt(&so_pool);
11362 + for (i=0; i<nr_pool; i++) {
11363 + if (POOL[i].members) {
11364 + kfree(POOL[i].members);
11365 + POOL[i].members = 0;
11370 + DP("ip_pool:fini these are the famous last words\n");
11374 +module_init(init);
11375 +module_exit(fini);
11376 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_queue.c linux-2.6.0-test11/net/ipv4/netfilter/ip_queue.c
11377 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_queue.c 2003-11-26 21:46:12.000000000 +0100
11378 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_queue.c 2003-12-11 10:24:12.845863720 +0100
11379 @@ -417,6 +417,33 @@
11383 +ipq_set_vwmark(struct ipq_vwmark_msg *vmsg, unsigned int len)
11385 + struct ipq_queue_entry *entry;
11387 + if (vmsg->value > NF_MAX_VERDICT)
11390 + entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
11391 + if (entry == NULL)
11394 + int verdict = vmsg->value;
11396 + if (vmsg->data_len && vmsg->data_len == len)
11397 + if (ipq_mangle_ipv4((ipq_verdict_msg_t *)vmsg, entry) < 0)
11398 + verdict = NF_DROP;
11400 + /* set mark of associated skb */
11401 + entry->skb->nfmark = vmsg->nfmark;
11403 + ipq_issue_verdict(entry, verdict);
11410 ipq_receive_peer(struct ipq_peer_msg *pmsg,
11411 unsigned char type, unsigned int len)
11413 @@ -438,6 +465,14 @@
11414 status = ipq_set_verdict(&pmsg->msg.verdict,
11415 len - sizeof(*pmsg));
11417 + case IPQM_VWMARK:
11418 + if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
11419 + status = -EINVAL;
11421 + status = ipq_set_vwmark(&pmsg->msg.vwmark,
11422 + len - sizeof(*pmsg));
11428 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.0-test11/net/ipv4/netfilter/iptable_filter.c
11429 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_filter.c 2003-11-26 21:43:35.000000000 +0100
11430 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_filter.c 2003-12-11 10:23:17.230318568 +0100
11433 sizeof(struct ipt_entry),
11434 sizeof(struct ipt_standard),
11435 - 0, { 0, 0 }, { } },
11436 + 0, NULL, 0, { 0, 0 }, { } },
11437 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11438 -NF_ACCEPT - 1 } },
11442 sizeof(struct ipt_entry),
11443 sizeof(struct ipt_standard),
11444 - 0, { 0, 0 }, { } },
11445 + 0, NULL, 0, { 0, 0 }, { } },
11446 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11447 -NF_ACCEPT - 1 } },
11451 sizeof(struct ipt_entry),
11452 sizeof(struct ipt_standard),
11453 - 0, { 0, 0 }, { } },
11454 + 0, NULL, 0, { 0, 0 }, { } },
11455 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11460 sizeof(struct ipt_entry),
11461 sizeof(struct ipt_error),
11462 - 0, { 0, 0 }, { } },
11463 + 0, NULL, 0, { 0, 0 }, { } },
11464 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11467 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.0-test11/net/ipv4/netfilter/iptable_mangle.c
11468 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_mangle.c 2003-11-26 21:45:28.000000000 +0100
11469 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_mangle.c 2003-12-11 10:23:17.230318568 +0100
11472 sizeof(struct ipt_entry),
11473 sizeof(struct ipt_standard),
11474 - 0, { 0, 0 }, { } },
11475 + 0, NULL, 0, { 0, 0 }, { } },
11476 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11477 -NF_ACCEPT - 1 } },
11481 sizeof(struct ipt_entry),
11482 sizeof(struct ipt_standard),
11483 - 0, { 0, 0 }, { } },
11484 + 0, NULL, 0, { 0, 0 }, { } },
11485 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11486 -NF_ACCEPT - 1 } },
11490 sizeof(struct ipt_entry),
11491 sizeof(struct ipt_standard),
11492 - 0, { 0, 0 }, { } },
11493 + 0, NULL, 0, { 0, 0 }, { } },
11494 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11495 -NF_ACCEPT - 1 } },
11499 sizeof(struct ipt_entry),
11500 sizeof(struct ipt_standard),
11501 - 0, { 0, 0 }, { } },
11502 + 0, NULL, 0, { 0, 0 }, { } },
11503 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11504 -NF_ACCEPT - 1 } },
11506 @@ -101,7 +101,7 @@
11508 sizeof(struct ipt_entry),
11509 sizeof(struct ipt_standard),
11510 - 0, { 0, 0 }, { } },
11511 + 0, NULL, 0, { 0, 0 }, { } },
11512 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11513 -NF_ACCEPT - 1 } },
11515 @@ -110,7 +110,7 @@
11517 sizeof(struct ipt_entry),
11518 sizeof(struct ipt_error),
11519 - 0, { 0, 0 }, { } },
11520 + 0, NULL, 0, { 0, 0 }, { } },
11521 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11524 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.0-test11/net/ipv4/netfilter/iptable_raw.c
11525 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_raw.c 1970-01-01 01:00:00.000000000 +0100
11526 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_raw.c 2003-12-11 10:23:17.231318416 +0100
11529 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
11531 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
11533 +#include <linux/module.h>
11534 +#include <linux/netfilter_ipv4/ip_tables.h>
11536 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
11538 +/* Standard entry. */
11539 +struct ipt_standard
11541 + struct ipt_entry entry;
11542 + struct ipt_standard_target target;
11545 +struct ipt_error_target
11547 + struct ipt_entry_target target;
11548 + char errorname[IPT_FUNCTION_MAXNAMELEN];
11553 + struct ipt_entry entry;
11554 + struct ipt_error_target target;
11559 + struct ipt_replace repl;
11560 + struct ipt_standard entries[2];
11561 + struct ipt_error term;
11562 +} initial_table __initdata
11563 += { { "raw", RAW_VALID_HOOKS, 3,
11564 + sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
11565 + { [NF_IP_PRE_ROUTING] 0,
11566 + [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11567 + { [NF_IP_PRE_ROUTING] 0,
11568 + [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11571 + /* PRE_ROUTING */
11572 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11574 + sizeof(struct ipt_entry),
11575 + sizeof(struct ipt_standard),
11576 + 0, NULL, 0, { 0, 0 }, { } },
11577 + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11578 + -NF_ACCEPT - 1 } },
11580 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11582 + sizeof(struct ipt_entry),
11583 + sizeof(struct ipt_standard),
11584 + 0, NULL, 0, { 0, 0 }, { } },
11585 + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11586 + -NF_ACCEPT - 1 } }
11589 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11591 + sizeof(struct ipt_entry),
11592 + sizeof(struct ipt_error),
11593 + 0, NULL, 0, { 0, 0 }, { } },
11594 + { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11601 +static struct ipt_table packet_raw = {
11603 + .table = &initial_table.repl,
11604 + .valid_hooks = RAW_VALID_HOOKS,
11605 + .lock = RW_LOCK_UNLOCKED,
11606 + .me = THIS_MODULE,
11609 +/* The work comes in here from netfilter.c. */
11610 +static unsigned int
11611 +ipt_hook(unsigned int hook,
11612 + struct sk_buff **pskb,
11613 + const struct net_device *in,
11614 + const struct net_device *out,
11615 + int (*okfn)(struct sk_buff *))
11617 + return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
11620 +/* 'raw' is the very first table. */
11621 +static struct nf_hook_ops ipt_ops[] = {
11622 + { /* PRE_ROUTING hook */
11623 + .hook = ipt_hook,
11624 + .owner = THIS_MODULE,
11626 + .hooknum = NF_IP_PRE_ROUTING,
11627 + .priority = NF_IP_PRI_RAW,
11629 + { /* LOCAL_OUT hook */
11630 + .hook = ipt_hook,
11631 + .owner = THIS_MODULE,
11633 + .hooknum = NF_IP_LOCAL_OUT,
11634 + .priority = NF_IP_PRI_RAW,
11638 +static int __init init(void)
11642 + /* Register table */
11643 + ret = ipt_register_table(&packet_raw);
11647 + /* Register hooks */
11648 + ret = nf_register_hook(&ipt_ops[0]);
11650 + goto cleanup_table;
11652 + ret = nf_register_hook(&ipt_ops[1]);
11654 + goto cleanup_hook0;
11659 + nf_unregister_hook(&ipt_ops[0]);
11661 + ipt_unregister_table(&packet_raw);
11666 +static void __exit fini(void)
11670 + for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
11671 + nf_unregister_hook(&ipt_ops[i]);
11673 + ipt_unregister_table(&packet_raw);
11676 +module_init(init);
11677 +module_exit(fini);
11678 +MODULE_LICENSE("GPL");
11679 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11680 +MODULE_DESCRIPTION("IPv4 raw table");
11681 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_tables.c linux-2.6.0-test11/net/ipv4/netfilter/ip_tables.c
11682 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_tables.c 2003-11-26 21:43:25.000000000 +0100
11683 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_tables.c 2003-12-11 10:23:53.624785768 +0100
11685 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11686 * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
11688 + * 6 Mar 2002 Robert Olsson <robban@robtex.com>
11689 + * 17 Apr 2003 Chris Wilson <chris@netservers.co.uk>
11690 + * - mark_source_chains speedup for complex chains
11692 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
11693 * - increase module usage count as soon as we have rules inside
11696 #include <linux/config.h>
11697 #include <linux/cache.h>
11698 #include <linux/skbuff.h>
11699 +#include <linux/socket.h>
11700 #include <linux/kmod.h>
11701 #include <linux/vmalloc.h>
11702 #include <linux/netdevice.h>
11704 #include <asm/semaphore.h>
11705 #include <linux/proc_fs.h>
11707 +#include <linux/netfilter.h>
11708 #include <linux/netfilter_ipv4/ip_tables.h>
11710 +static const char *hooknames[] = {
11711 + [NF_IP_PRE_ROUTING] "PREROUTING",
11712 + [NF_IP_LOCAL_IN] "INPUT",
11713 + [NF_IP_FORWARD] "FORWARD",
11714 + [NF_IP_LOCAL_OUT] "OUTPUT",
11715 + [NF_IP_POST_ROUTING] "POSTROUTING",
11718 MODULE_LICENSE("GPL");
11719 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11720 MODULE_DESCRIPTION("IPv4 packet filter");
11721 @@ -322,6 +336,12 @@
11723 t = ipt_get_target(e);
11724 IP_NF_ASSERT(t->u.kernel.target);
11726 + /* The packet traced and the rule isn't an unconditional return/END. */
11727 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
11728 + nf_log_packet(AF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11729 + table->name, e->chainname, e->rulenum);
11731 /* Standard target? */
11732 if (!t->u.kernel.target->target) {
11734 @@ -474,6 +494,29 @@
11735 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
11739 +find_error_target(struct ipt_entry *s,
11740 + struct ipt_entry *e,
11741 + char **chainname)
11743 + struct ipt_entry_target *t;
11744 + static struct ipt_entry *found = NULL;
11749 + t = ipt_get_target(found);
11750 + if (strcmp(t->u.user.name,
11751 + IPT_ERROR_TARGET) == 0) {
11752 + *chainname = t->data;
11761 /* All zeroes == unconditional rule. */
11763 unconditional(const struct ipt_ip *ip)
11764 @@ -493,6 +536,11 @@
11765 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
11768 + char *chainname = NULL;
11769 + u_int32_t rulenum;
11771 + /* keep track of where we have been: */
11772 + unsigned char *been = vmalloc(newinfo->size);
11774 /* No recursion; use packet counter to save back ptrs (reset
11775 to 0 as we leave), and comefrom to save source hook bitmask */
11776 @@ -506,6 +554,9 @@
11778 /* Set initial back pointer. */
11779 e->counters.pcnt = pos;
11780 + memset(been, 0, newinfo->size);
11782 + chainname = (char *) hooknames[hook];
11785 struct ipt_standard_target *t
11786 @@ -514,10 +565,13 @@
11787 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
11788 printk("iptables: loop hook %u pos %u %08X.\n",
11789 hook, pos, e->comefrom);
11794 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
11795 + e->rulenum = rulenum++;
11796 + e->chainname = chainname;
11798 /* Unconditional return/END. */
11799 if (e->target_offset == sizeof(struct ipt_entry)
11800 @@ -527,6 +581,10 @@
11801 && unconditional(&e->ip)) {
11802 unsigned int oldpos, size;
11804 + /* Set unconditional rulenum to zero. */
11806 + e->counters.bcnt = 0;
11808 /* Return: backtrack through the last
11811 @@ -552,6 +610,11 @@
11812 (newinfo->entries + pos);
11813 } while (oldpos == pos + e->next_offset);
11815 + /* Restore chainname, rulenum. */
11816 + chainname = e->chainname;
11817 + rulenum = e->counters.bcnt;
11818 + e->counters.bcnt = 0;
11820 /* Move along one */
11821 size = e->next_offset;
11822 e = (struct ipt_entry *)
11823 @@ -561,12 +624,27 @@
11825 int newpos = t->verdict;
11827 - if (strcmp(t->target.u.user.name,
11828 + if ( (pos < 0 || pos >= newinfo->size
11830 + && strcmp(t->target.u.user.name,
11831 IPT_STANDARD_TARGET) == 0
11833 /* This a jump; chase it. */
11834 + if (pos >= 0 && pos < newinfo->size)
11836 duprintf("Jump rule %u -> %u\n",
11838 + e->counters.bcnt = rulenum++;
11840 + e = (struct ipt_entry *)
11841 + (newinfo->entries + newpos);
11842 + if (IPT_ENTRY_ITERATE(newinfo->entries,
11844 + find_error_target,
11845 + e, &chainname) == 0) {
11846 + printk("ip_tables: table screwed up!\n");
11850 /* ... this is a fallthru */
11851 newpos = pos + e->next_offset;
11852 @@ -580,6 +658,7 @@
11854 duprintf("Finished chain %u\n", hook);
11860 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_addrtype.c
11861 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
11862 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_addrtype.c 2003-12-11 10:23:44.237212896 +0100
11865 + * iptables module to match inet_addr_type() of an ip.
11868 +#include <linux/module.h>
11869 +#include <linux/skbuff.h>
11870 +#include <linux/netdevice.h>
11871 +#include <net/route.h>
11873 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
11874 +#include <linux/netfilter_ipv4/ip_tables.h>
11876 +MODULE_LICENSE("GPL");
11878 +static inline int match_type(u_int32_t addr, u_int16_t mask)
11880 + return !!(mask & (1 << inet_addr_type(addr)));
11883 +static int match(const struct sk_buff *skb, const struct net_device *in,
11884 + const struct net_device *out, const void *matchinfo,
11885 + int offset, const void *hdr, u_int16_t datalen,
11888 + const struct ipt_addrtype_info *info = matchinfo;
11889 + const struct iphdr *iph = skb->nh.iph;
11892 + if (info->source)
11893 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
11895 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
11900 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
11901 + void *matchinfo, unsigned int matchsize,
11902 + unsigned int hook_mask)
11904 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
11905 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
11906 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
11913 +static struct ipt_match addrtype_match = { { NULL, NULL }, "addrtype", &match,
11914 + &checkentry, NULL, THIS_MODULE };
11916 +static int __init init(void)
11918 + return ipt_register_match(&addrtype_match);
11921 +static void __exit fini(void)
11923 + ipt_unregister_match(&addrtype_match);
11927 +module_init(init);
11928 +module_exit(fini);
11929 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_condition.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_condition.c
11930 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_condition.c 1970-01-01 01:00:00.000000000 +0100
11931 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_condition.c 2003-12-11 10:23:46.622850224 +0100
11933 +/*-------------------------------------------*\
11934 +| Netfilter Condition Module |
11936 +| Description: This module allows firewall |
11937 +| rules to match using condition variables |
11938 +| stored in /proc files. |
11940 +| Author: Stephane Ouellette 2002-10-22 |
11941 +| <ouellettes@videotron.ca> |
11944 +| 2003-02-10 Second version with improved |
11945 +| locking and simplified code. |
11947 +| This software is distributed under the |
11948 +| terms of the GNU GPL. |
11949 +\*-------------------------------------------*/
11951 +#include<linux/module.h>
11952 +#include<linux/proc_fs.h>
11953 +#include<linux/spinlock.h>
11954 +#include<linux/string.h>
11955 +#include<asm/atomic.h>
11956 +#include<linux/netfilter_ipv4/ip_tables.h>
11957 +#include<linux/netfilter_ipv4/ipt_condition.h>
11960 +#ifndef CONFIG_PROC_FS
11961 +#error "Proc file system support is required for this module"
11965 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
11966 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
11967 +MODULE_LICENSE("GPL");
11970 +struct condition_variable {
11971 + struct condition_variable *next;
11972 + struct proc_dir_entry *status_proc;
11973 + atomic_t refcount;
11974 + int enabled; /* TRUE == 1, FALSE == 0 */
11978 +static rwlock_t list_lock;
11979 +static struct condition_variable *head = NULL;
11980 +static struct proc_dir_entry *proc_net_condition = NULL;
11984 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
11985 + int length, int *eof, void *data)
11987 + struct condition_variable *var =
11988 + (struct condition_variable *) data;
11990 + if (offset == 0) {
11992 + buffer[0] = (var->enabled) ? '1' : '0';
11993 + buffer[1] = '\n';
12003 +ipt_condition_write_info(struct file *file, const char *buffer,
12004 + unsigned long length, void *data)
12006 + struct condition_variable *var =
12007 + (struct condition_variable *) data;
12010 + /* Match only on the first character */
12011 + switch (buffer[0]) {
12013 + var->enabled = 0;
12016 + var->enabled = 1;
12020 + return (int) length;
12025 +match(const struct sk_buff *skb, const struct net_device *in,
12026 + const struct net_device *out, const void *matchinfo, int offset,
12027 + const void *hdr, u_int16_t datalen, int *hotdrop)
12029 + const struct condition_info *info =
12030 + (const struct condition_info *) matchinfo;
12031 + struct condition_variable *var;
12032 + int condition_status = 0;
12034 + read_lock(&list_lock);
12036 + for (var = head; var; var = var->next) {
12037 + if (strcmp(info->name, var->status_proc->name) == 0) {
12038 + condition_status = var->enabled;
12043 + read_unlock(&list_lock);
12045 + return condition_status ^ info->invert;
12051 +checkentry(const char *tablename, const struct ipt_ip *ip,
12052 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
12054 + struct condition_info *info = (struct condition_info *) matchinfo;
12055 + struct condition_variable *var, *newvar;
12057 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12060 + /* The first step is to check if the condition variable already exists. */
12061 + /* Here, a read lock is sufficient because we won't change the list */
12062 + read_lock(&list_lock);
12064 + for (var = head; var; var = var->next) {
12065 + if (strcmp(info->name, var->status_proc->name) == 0) {
12066 + atomic_inc(&var->refcount);
12067 + read_unlock(&list_lock);
12072 + read_unlock(&list_lock);
12074 + /* At this point, we need to allocate a new condition variable */
12075 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
12080 + /* Create the condition variable's proc file entry */
12081 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
12083 + if (!newvar->status_proc) {
12085 + * There are two possibilities:
12086 + * 1- Another condition variable with the same name has been created, which is valid.
12087 + * 2- There was a memory allocation error.
12090 + read_lock(&list_lock);
12092 + for (var = head; var; var = var->next) {
12093 + if (strcmp(info->name, var->status_proc->name) == 0) {
12094 + atomic_inc(&var->refcount);
12095 + read_unlock(&list_lock);
12100 + read_unlock(&list_lock);
12104 + atomic_set(&newvar->refcount, 1);
12105 + newvar->enabled = 0;
12106 + newvar->status_proc->owner = THIS_MODULE;
12107 + newvar->status_proc->data = newvar;
12109 + newvar->status_proc->read_proc = ipt_condition_read_info;
12110 + newvar->status_proc->write_proc = ipt_condition_write_info;
12112 + write_lock(&list_lock);
12114 + newvar->next = head;
12117 + write_unlock(&list_lock);
12124 +destroy(void *matchinfo, unsigned int matchsize)
12126 + struct condition_info *info = (struct condition_info *) matchinfo;
12127 + struct condition_variable *var, *prev = NULL;
12129 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12132 + write_lock(&list_lock);
12134 + for (var = head; var && strcmp(info->name, var->status_proc->name);
12135 + prev = var, var = var->next);
12137 + if (var && atomic_dec_and_test(&var->refcount)) {
12139 + prev->next = var->next;
12141 + head = var->next;
12143 + write_unlock(&list_lock);
12144 + remove_proc_entry(var->status_proc->name, proc_net_condition);
12147 + write_unlock(&list_lock);
12151 +static struct ipt_match condition_match = {
12152 + .name = "condition",
12154 + .checkentry = &checkentry,
12155 + .destroy = &destroy,
12156 + .me = THIS_MODULE
12165 + rwlock_init(&list_lock);
12166 + proc_net_condition = proc_mkdir("ipt_condition", proc_net);
12168 + if (proc_net_condition) {
12169 + errorcode = ipt_register_match(&condition_match);
12172 + remove_proc_entry("ipt_condition", proc_net);
12174 + errorcode = -EACCES;
12176 + return errorcode;
12180 +static void __exit
12183 + ipt_unregister_match(&condition_match);
12184 + remove_proc_entry("ipt_condition", proc_net);
12187 +module_init(init);
12188 +module_exit(fini);
12189 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_connlimit.c
12190 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
12191 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connlimit.c 2003-12-11 12:50:01.556857488 +0100
12194 + * netfilter module to limit the number of parallel tcp
12195 + * connections per IP address.
12196 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
12197 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
12198 + * only ignore TIME_WAIT or gone connections
12202 + * Kernel module to match connection tracking information.
12203 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
12205 +#include <linux/module.h>
12206 +#include <linux/skbuff.h>
12207 +#include <linux/list.h>
12208 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12209 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
12210 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
12211 +#include <linux/netfilter_ipv4/ip_tables.h>
12212 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
12216 +MODULE_LICENSE("GPL");
12218 +/* we'll save the tuples of all connections we care about */
12219 +struct ipt_connlimit_conn
12221 + struct list_head list;
12222 + struct ip_conntrack_tuple tuple;
12225 +struct ipt_connlimit_data {
12227 + struct list_head iphash[256];
12230 +static int ipt_iphash(u_int32_t addr)
12234 + hash = addr & 0xff;
12235 + hash ^= (addr >> 8) & 0xff;
12236 + hash ^= (addr >> 16) & 0xff;
12237 + hash ^= (addr >> 24) & 0xff;
12241 +static int count_them(struct ipt_connlimit_data *data,
12242 + u_int32_t addr, u_int32_t mask,
12243 + struct ip_conntrack *ct)
12246 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
12247 + "fin_wait", "time_wait", "close", "close_wait",
12248 + "last_ack", "listen" };
12250 + int addit = 1, matches = 0;
12251 + struct ip_conntrack_tuple tuple;
12252 + struct ip_conntrack_tuple_hash *found;
12253 + struct ipt_connlimit_conn *conn;
12254 + struct list_head *hash,*lh;
12256 + spin_lock(&data->lock);
12257 + tuple = ct->tuplehash[0].tuple;
12258 + hash = &data->iphash[ipt_iphash(addr & mask)];
12260 + /* check the saved connections */
12261 + for (lh = hash->next; lh != hash; lh = lh->next) {
12262 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
12263 + found = ip_conntrack_find_get(&conn->tuple,ct);
12264 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
12266 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
12267 + /* Just to be sure we have it only once in the list.
12268 + We should'nt see tuples twice unless someone hooks this
12269 + into a table without "-p tcp --syn" */
12273 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
12274 + ipt_iphash(addr & mask),
12275 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
12276 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
12277 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
12279 + if (NULL == found) {
12280 + /* this one is gone */
12282 + list_del(lh->next);
12286 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
12287 + /* we don't care about connections which are
12288 + closed already -> ditch it */
12290 + list_del(lh->next);
12292 + nf_conntrack_put(&found->ctrack->infos[0]);
12295 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
12296 + /* same source IP address -> be counted! */
12299 + nf_conntrack_put(&found->ctrack->infos[0]);
12302 + /* save the new connection in our list */
12304 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
12305 + ipt_iphash(addr & mask),
12306 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
12307 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
12309 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
12310 + if (NULL == conn)
12312 + memset(conn,0,sizeof(*conn));
12313 + INIT_LIST_HEAD(&conn->list);
12314 + conn->tuple = tuple;
12315 + list_add(&conn->list,hash);
12318 + spin_unlock(&data->lock);
12323 +match(const struct sk_buff *skb,
12324 + const struct net_device *in,
12325 + const struct net_device *out,
12326 + const void *matchinfo,
12329 + u_int16_t datalen,
12332 + const struct ipt_connlimit_info *info = matchinfo;
12333 + int connections, match;
12334 + struct ip_conntrack *ct;
12335 + enum ip_conntrack_info ctinfo;
12337 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12338 + if (NULL == ct) {
12339 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
12343 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
12344 + if (-1 == connections) {
12345 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
12346 + *hotdrop = 1; /* let's free some memory :-) */
12349 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
12351 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
12352 + "connections=%d limit=%d match=%s\n",
12353 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
12354 + connections, info->limit, match ? "yes" : "no");
12360 +static int check(const char *tablename,
12361 + const struct ipt_ip *ip,
12363 + unsigned int matchsize,
12364 + unsigned int hook_mask)
12366 + struct ipt_connlimit_info *info = matchinfo;
12369 + /* verify size */
12370 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
12373 + /* refuse anything but tcp */
12374 + if (ip->proto != IPPROTO_TCP)
12377 + /* init private data */
12378 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
12379 + spin_lock_init(&(info->data->lock));
12380 + for (i = 0; i < 256; i++)
12381 + INIT_LIST_HEAD(&(info->data->iphash[i]));
12386 +static void destroy(void *matchinfo, unsigned int matchinfosize)
12388 + struct ipt_connlimit_info *info = matchinfo;
12389 + struct ipt_connlimit_conn *conn;
12390 + struct list_head *hash;
12394 + for (i = 0; i < 256; i++) {
12395 + hash = &(info->data->iphash[i]);
12396 + while (hash != hash->next) {
12397 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
12398 + list_del(hash->next);
12402 + kfree(info->data);
12405 +static struct ipt_match connlimit_match
12406 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
12408 +static int __init init(void)
12410 + return ipt_register_match(&connlimit_match);
12413 +static void __exit fini(void)
12415 + ipt_unregister_match(&connlimit_match);
12418 +module_init(init);
12419 +module_exit(fini);
12420 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_connmark.c
12421 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
12422 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connmark.c 2003-12-11 10:23:47.827667064 +0100
12424 +/* Kernel module to match connection mark values. */
12425 +#include <linux/module.h>
12426 +#include <linux/skbuff.h>
12428 +#include <linux/netfilter_ipv4/ip_tables.h>
12429 +#include <linux/netfilter_ipv4/ipt_connmark.h>
12430 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12433 +match(const struct sk_buff *skb,
12434 + const struct net_device *in,
12435 + const struct net_device *out,
12436 + const void *matchinfo,
12439 + u_int16_t datalen,
12442 + const struct ipt_connmark_info *info = matchinfo;
12443 + enum ip_conntrack_info ctinfo;
12444 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12448 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
12452 +checkentry(const char *tablename,
12453 + const struct ipt_ip *ip,
12455 + unsigned int matchsize,
12456 + unsigned int hook_mask)
12458 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
12464 +static struct ipt_match connmark_match
12465 += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE };
12467 +static int __init init(void)
12469 + return ipt_register_match(&connmark_match);
12472 +static void __exit fini(void)
12474 + ipt_unregister_match(&connmark_match);
12477 +module_init(init);
12478 +module_exit(fini);
12479 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_CONNMARK.c
12480 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
12481 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_CONNMARK.c 2003-12-11 10:23:47.828666912 +0100
12483 +/* This is a module which is used for setting/remembering the mark field of
12484 + * an connection, or optionally restore it to the skb
12486 +#include <linux/module.h>
12487 +#include <linux/skbuff.h>
12488 +#include <linux/ip.h>
12489 +#include <net/checksum.h>
12491 +#include <linux/netfilter_ipv4/ip_tables.h>
12492 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
12493 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12495 +static unsigned int
12496 +target(struct sk_buff **pskb,
12497 + unsigned int hooknum,
12498 + const struct net_device *in,
12499 + const struct net_device *out,
12500 + const void *targinfo,
12503 + const struct ipt_connmark_target_info *markinfo = targinfo;
12505 + enum ip_conntrack_info ctinfo;
12506 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
12508 + switch(markinfo->mode) {
12509 + case IPT_CONNMARK_SET:
12510 + ct->mark = markinfo->mark;
12512 + case IPT_CONNMARK_SAVE:
12513 + ct->mark = (*pskb)->nfmark;
12515 + case IPT_CONNMARK_RESTORE:
12516 + if (ct->mark != (*pskb)->nfmark) {
12517 + (*pskb)->nfmark = ct->mark;
12518 + (*pskb)->nfcache |= NFC_ALTERED;
12524 + return IPT_CONTINUE;
12528 +checkentry(const char *tablename,
12529 + const struct ipt_entry *e,
12531 + unsigned int targinfosize,
12532 + unsigned int hook_mask)
12534 + struct ipt_connmark_target_info *matchinfo = targinfo;
12535 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
12536 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
12538 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
12542 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
12543 + if (strcmp(tablename, "mangle") != 0) {
12544 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
12552 +static struct ipt_target ipt_connmark_reg
12553 += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE };
12555 +static int __init init(void)
12557 + if (ipt_register_target(&ipt_connmark_reg))
12563 +static void __exit fini(void)
12565 + ipt_unregister_target(&ipt_connmark_reg);
12568 +module_init(init);
12569 +module_exit(fini);
12570 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_conntrack.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_conntrack.c
12571 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_conntrack.c 2003-11-26 21:45:34.000000000 +0100
12572 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_conntrack.c 2003-12-11 10:23:17.229318720 +0100
12575 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
12578 + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
12579 + statebit = IPT_CONNTRACK_STATE_UNTRACKED;
12581 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
12583 statebit = IPT_CONNTRACK_STATE_INVALID;
12584 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_dstlimit.c
12585 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
12586 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_dstlimit.c 2003-12-11 10:23:20.528817120 +0100
12588 +/* iptables match extension to limit the number of packets per second
12589 + * seperately for each destination.
12591 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
12593 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
12595 + * based on ipt_limit.c by:
12596 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
12597 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
12598 + * Rusty Russell <rusty@rustcorp.com.au>
12600 + * The general idea is to create a hash table for every dstip and have a
12601 + * seperate limit counter per tuple. This way you can do something like 'limit
12602 + * the number of syn packets for each of my internal addresses.
12604 + * Ideally this would just be implemented as a general 'hash' match, which would
12605 + * allow us to attach any iptables target to it's hash buckets. But this is
12606 + * not possible in the current iptables architecture. As always, pkttables for
12607 + * 2.7.x will help ;)
12609 +#include <linux/module.h>
12610 +#include <linux/skbuff.h>
12611 +#include <linux/spinlock.h>
12612 +#include <linux/random.h>
12613 +#include <linux/jhash.h>
12614 +#include <linux/slab.h>
12615 +#include <linux/vmalloc.h>
12616 +#include <linux/tcp.h>
12617 +#include <linux/udp.h>
12618 +#include <linux/proc_fs.h>
12619 +#include <linux/seq_file.h>
12621 +#define ASSERT_READ_LOCK(x)
12622 +#define ASSERT_WRITE_LOCK(x)
12623 +#include <linux/netfilter_ipv4/lockhelp.h>
12624 +#include <linux/netfilter_ipv4/listhelp.h>
12626 +#include <linux/netfilter_ipv4/ip_tables.h>
12627 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
12629 +/* FIXME: this is just for IP_NF_ASSERRT */
12630 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12632 +#define MS2JIFFIES(x) ((x*HZ)/1000)
12634 +MODULE_LICENSE("GPL");
12635 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
12636 +MODULE_DESCRIPTION("iptables match for limiting per destination");
12638 +/* need to declare this at the top */
12639 +static struct proc_dir_entry *dstlimit_procdir;
12640 +static struct file_operations dl_file_ops;
12642 +/* hash table crap */
12644 +struct dsthash_dst {
12645 + u_int32_t src_ip;
12646 + u_int32_t dst_ip;
12650 +struct dsthash_ent {
12651 + /* static / read-only parts in the beginning */
12652 + struct list_head list;
12653 + struct dsthash_dst dst;
12655 + /* modified structure members in the end */
12656 + unsigned long expires; /* precalculated expiry time */
12658 + unsigned long prev; /* last modification */
12659 + u_int32_t credit;
12660 + u_int32_t credit_cap, cost;
12664 +struct ipt_dstlimit_htable {
12665 + struct ipt_dstlimit_info *minfo; /* public structure */
12667 + /* used internally */
12668 + spinlock_t lock; /* lock for list_head */
12669 + u_int32_t rnd; /* random seed for hash */
12670 + struct timer_list timer; /* timer for gc */
12671 + atomic_t count; /* number entries in table */
12673 + /* seq_file stuff */
12674 + struct proc_dir_entry *pde;
12676 + struct list_head hash[0]; /* hashtable itself */
12679 +static kmem_cache_t *dstlimit_cachep;
12681 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
12683 + return (ent->dst.dst_ip == b->dst_ip
12684 + && ent->dst.port == b->port
12685 + && ent->dst.src_ip == b->src_ip);
12688 +static inline u_int32_t
12689 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
12691 + return (jhash_3words(dst->dst_ip, dst->port,
12692 + dst->src_ip, ht->rnd) % ht->minfo->size);
12695 +static inline struct dsthash_ent *
12696 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12698 + struct dsthash_ent *ent;
12699 + u_int32_t hash = hash_dst(ht, dst);
12700 + MUST_BE_LOCKED(&ht->lock);
12701 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
12705 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
12706 +static struct dsthash_ent *
12707 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12709 + struct dsthash_ent *ent;
12711 + /* initialize hash with random val at the time we allocate
12712 + * the first hashtable entry */
12714 + get_random_bytes(&ht->rnd, 4);
12716 + if (ht->minfo->max &&
12717 + atomic_read(&ht->count) >= ht->minfo->max) {
12718 + /* FIXME: do something. question is what.. */
12719 + if (net_ratelimit())
12720 + printk("max count of %u reached\n", ht->minfo->max);
12724 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
12726 + if (net_ratelimit())
12727 + printk("Can't allocate dsthash_ent\n");
12731 + atomic_inc(&ht->count);
12733 + ent->dst.dst_ip = dst->dst_ip;
12734 + ent->dst.port = dst->port;
12735 + ent->dst.src_ip = dst->src_ip;
12737 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
12742 +static inline void
12743 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
12745 + MUST_BE_LOCKED(&ht->lock);
12747 + list_del(&ent->list);
12748 + kmem_cache_free(dstlimit_cachep, ent);
12749 + atomic_dec(&ht->count);
12752 +static void htable_gc(unsigned long htlong);
12754 +static int htable_create(struct ipt_dstlimit_info *minfo)
12757 + struct ipt_dstlimit_htable *hinfo;
12759 + if (!minfo->size) {
12760 + minfo->size = (((num_physpages << PAGE_SHIFT) / 16384)
12761 + / sizeof(struct list_head));
12762 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
12763 + minfo->size = 8192;
12764 + if (minfo->size < 16)
12765 + minfo->size = 16;
12768 + minfo->max = 8 * minfo->size;
12769 + else if (minfo->max < minfo->size)
12770 + minfo->max = minfo->size;
12772 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
12773 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
12774 + + (sizeof(struct list_head) * minfo->size));
12776 + printk(KERN_ERR "Unable to create ipt_dstlimit hash\n");
12780 + for (i = 0; i < minfo->size; i++)
12781 + INIT_LIST_HEAD(&hinfo->hash[i]);
12783 + minfo->hinfo = hinfo;
12785 + hinfo->minfo = minfo;
12786 + atomic_set(&hinfo->count, 0);
12789 + hinfo->lock = SPIN_LOCK_UNLOCKED;
12791 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
12792 + if (!hinfo->pde) {
12796 + hinfo->pde->proc_fops = &dl_file_ops;
12797 + hinfo->pde->data = hinfo;
12799 + init_timer(&hinfo->timer);
12800 + hinfo->timer.expires = jiffies + MS2JIFFIES(minfo->gc_interval);
12801 + hinfo->timer.data = (unsigned long )hinfo;
12802 + hinfo->timer.function = htable_gc;
12803 + add_timer(&hinfo->timer);
12808 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12813 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12815 + return (jiffies >= he->expires);
12818 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
12819 + int (*select)(struct ipt_dstlimit_htable *ht,
12820 + struct dsthash_ent *he))
12824 + IP_NF_ASSERT(ht->minfo->size && ht->minfo->max);
12826 + /* lock hash table and iterate over it */
12827 + LOCK_BH(&ht->lock);
12828 + for (i = 0; i < ht->minfo->size; i++) {
12829 + struct dsthash_ent *dh, *n;
12830 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
12831 + if ((*select)(ht, dh))
12832 + __dsthash_free(ht, dh);
12835 + UNLOCK_BH(&ht->lock);
12838 +/* hash table garbage collector, run by timer */
12839 +static void htable_gc(unsigned long htlong)
12841 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
12843 + htable_selective_cleanup(ht, select_gc);
12845 + /* re-add the timer accordingly */
12846 + ht->timer.expires = jiffies + MS2JIFFIES(ht->minfo->gc_interval);
12847 + add_timer(&ht->timer);
12850 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
12851 + * see net/sched/sch_tbf.c in the linux source tree
12854 +/* Rusty: This is my (non-mathematically-inclined) understanding of
12855 + this algorithm. The `average rate' in jiffies becomes your initial
12856 + amount of credit `credit' and the most credit you can ever have
12857 + `credit_cap'. The `peak rate' becomes the cost of passing the
12860 + `prev' tracks the last packet hit: you gain one credit per jiffy.
12861 + If you get credit balance more than this, the extra credit is
12862 + discarded. Every time the match passes, you lose `cost' credits;
12863 + if you don't have that many, the test fails.
12865 + See Alexey's formal explanation in net/sched/sch_tbf.c.
12867 + To get the maximum range, we multiply by this factor (ie. you get N
12868 + credits per jiffy). We want to allow a rate as low as 1 per day
12869 + (slowest userspace tool allows), which means
12870 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
12872 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
12874 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
12875 + * us the power of 2 below the theoretical max, so GCC simply does a
12877 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
12878 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
12879 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
12880 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
12881 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
12882 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
12884 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
12886 +/* Precision saver. */
12887 +static inline u_int32_t
12888 +user2credits(u_int32_t user)
12890 + /* If multiplying would overflow... */
12891 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
12892 + /* Divide first. */
12893 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
12895 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
12898 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
12900 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
12901 + * CREDITS_PER_JIFFY;
12902 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
12903 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
12907 +dstlimit_match(const struct sk_buff *skb,
12908 + const struct net_device *in,
12909 + const struct net_device *out,
12910 + const void *matchinfo,
12913 + u_int16_t datalen,
12916 + struct ipt_dstlimit_info *r =
12917 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
12918 + unsigned long now = jiffies;
12919 + struct dsthash_ent *dh;
12920 + struct dsthash_dst dst;
12922 + memset(&dst, 0, sizeof(dst));
12924 + /* dest ip is always in hash */
12925 + dst.dst_ip = skb->nh.iph->daddr;
12927 + /* source ip only if respective hashmode, otherwise set to
12929 + if (r->mode & IPT_DSTLIMIT_HASH_SIP)
12930 + dst.src_ip = skb->nh.iph->saddr;
12932 + /* dest port only if respective mode */
12933 + if (r->mode & IPT_DSTLIMIT_HASH_DPT) {
12934 + switch (skb->nh.iph->protocol) {
12935 + struct tcphdr *th;
12936 + struct udphdr *uh;
12937 + case IPPROTO_TCP:
12938 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12939 + dst.port = th->dest;
12941 + case IPPROTO_UDP:
12942 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12943 + dst.port = uh->dest;
12950 + LOCK_BH(&r->hinfo->lock);
12951 + dh = __dsthash_find(r->hinfo, &dst);
12953 + dh = __dsthash_alloc_init(r->hinfo, &dst);
12956 + /* enomem... don't match == DROP */
12957 + if (net_ratelimit())
12958 + printk("%s: ENOMEM\n", __FUNCTION__);
12959 + UNLOCK_BH(&r->hinfo->lock);
12963 + dh->expires = jiffies + MS2JIFFIES(r->expire);
12965 + dh->rateinfo.prev = jiffies;
12966 + dh->rateinfo.credit = user2credits(r->avg * r->burst);
12967 + dh->rateinfo.credit_cap = user2credits(r->avg * r->burst);
12968 + dh->rateinfo.cost = user2credits(r->avg);
12970 + UNLOCK_BH(&r->hinfo->lock);
12974 + /* update expiration timeout */
12975 + dh->expires = now + MS2JIFFIES(r->expire);
12977 + rateinfo_recalc(dh, now);
12978 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
12979 + /* We're underlimit. */
12980 + dh->rateinfo.credit -= dh->rateinfo.cost;
12981 + UNLOCK_BH(&r->hinfo->lock);
12985 + UNLOCK_BH(&r->hinfo->lock);
12987 + /* default case: we're overlimit, thus don't match */
12992 +dstlimit_checkentry(const char *tablename,
12993 + const struct ipt_ip *ip,
12995 + unsigned int matchsize,
12996 + unsigned int hook_mask)
12998 + struct ipt_dstlimit_info *r = matchinfo;
13000 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
13003 + /* Check for overflow. */
13004 + if (r->burst == 0
13005 + || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
13006 + printk("Overflow in ipt_dstlimit, try lower: %u/%u\n",
13007 + r->avg, r->burst);
13012 + || r->mode > (IPT_DSTLIMIT_HASH_DPT
13013 + |IPT_DSTLIMIT_HASH_DIP
13014 + |IPT_DSTLIMIT_HASH_SIP))
13017 + if (!r->gc_interval)
13023 + if (htable_create(r) != 0) {
13024 + printk("Unable to create dstlimit htable\n");
13028 + /* Ugly hack: For SMP, we only want to use one set */
13035 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
13037 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
13041 + /* remove timer, if it is pending */
13042 + if (timer_pending(&r->hinfo->timer))
13043 + del_timer(&r->hinfo->timer);
13045 + /* remove proc entry */
13046 + remove_proc_entry(r->name, dstlimit_procdir);
13048 + htable_selective_cleanup(r->hinfo, select_all);
13049 + vfree(&r->hinfo);
13052 +static struct ipt_match ipt_dstlimit = {
13053 + .list = { .prev = NULL, .next = NULL },
13054 + .name = "dstlimit",
13055 + .match = dstlimit_match,
13056 + .checkentry = dstlimit_checkentry,
13057 + .destroy = dstlimit_destroy,
13058 + .me = THIS_MODULE
13063 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
13065 + struct proc_dir_entry *pde = s->private;
13066 + struct ipt_dstlimit_htable *htable = pde->data;
13067 + unsigned int *bucket;
13069 + LOCK_BH(&htable->lock);
13070 + if (*pos >= htable->minfo->size)
13073 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
13075 + return ERR_PTR(-ENOMEM);
13081 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
13083 + struct proc_dir_entry *pde = s->private;
13084 + struct ipt_dstlimit_htable *htable = pde->data;
13085 + unsigned int *bucket = (unsigned int *)v;
13087 + *pos = ++(*bucket);
13088 + if (*pos >= htable->minfo->size) {
13095 +static void dl_seq_stop(struct seq_file *s, void *v)
13097 + struct proc_dir_entry *pde = s->private;
13098 + struct ipt_dstlimit_htable *htable = pde->data;
13100 + UNLOCK_BH(&htable->lock);
13103 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
13105 + /* recalculate to show accurate numbers */
13106 + rateinfo_recalc(ent, jiffies);
13108 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
13109 + (ent->expires - jiffies)/HZ,
13110 + NIPQUAD(ent->dst.src_ip),
13111 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
13112 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
13113 + ent->rateinfo.cost);
13116 +static int dl_seq_show(struct seq_file *s, void *v)
13118 + struct proc_dir_entry *pde = s->private;
13119 + struct ipt_dstlimit_htable *htable = pde->data;
13120 + unsigned int *bucket = (unsigned int *)v;
13122 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
13123 + struct dsthash_ent *, s)) {
13124 + /* buffer was filled and unable to print that tuple */
13130 +static struct seq_operations dl_seq_ops = {
13131 + .start = dl_seq_start,
13132 + .next = dl_seq_next,
13133 + .stop = dl_seq_stop,
13134 + .show = dl_seq_show
13137 +static int dl_proc_open(struct inode *inode, struct file *file)
13139 + int ret = seq_open(file, &dl_seq_ops);
13142 + struct seq_file *sf = file->private_data;
13143 + sf->private = PDE(inode);
13148 +static struct file_operations dl_file_ops = {
13149 + .owner = THIS_MODULE,
13150 + .open = dl_proc_open,
13151 + .read = seq_read,
13152 + .llseek = seq_lseek,
13153 + .release = seq_release
13156 +static int init_or_fini(int fini)
13163 + if (ipt_register_match(&ipt_dstlimit)) {
13165 + goto cleanup_nothing;
13168 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
13169 + * quite small ? */
13170 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
13171 + sizeof(struct dsthash_ent), 0,
13172 + SLAB_HWCACHE_ALIGN, NULL, NULL);
13173 + if (!dstlimit_cachep) {
13174 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
13176 + goto cleanup_unreg_match;
13179 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
13180 + if (!dstlimit_procdir) {
13181 + printk(KERN_ERR "Unable to create proc dir entry\n");
13183 + goto cleanup_free_slab;
13189 + remove_proc_entry("ipt_dstlimit", proc_net);
13190 +cleanup_free_slab:
13191 + kmem_cache_destroy(dstlimit_cachep);
13192 +cleanup_unreg_match:
13193 + ipt_unregister_match(&ipt_dstlimit);
13199 +static int __init init(void)
13201 + return init_or_fini(0);
13204 +static void __exit fini(void)
13209 +module_init(init);
13210 +module_exit(fini);
13211 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_fuzzy.c
13212 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
13213 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_fuzzy.c 2003-12-11 10:23:22.735481656 +0100
13216 + * This module implements a simple TSK FLC
13217 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
13218 + * to limit , in an adaptive and flexible way , the packet rate crossing
13219 + * a given stream . It serves as an initial and very simple (but effective)
13220 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
13221 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
13222 + * into our code in a precise , adaptive and efficient manner.
13223 + * The goal is very similar to that of "limit" match , but using techniques of
13224 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
13225 + * avoiding over and undershoots - and stuff like that .
13228 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
13229 + * 2002-08-17 : Changed to eliminate floating point operations .
13230 + * 2002-08-23 : Coding style changes .
13233 +#include <linux/module.h>
13234 +#include <linux/skbuff.h>
13235 +#include <linux/ip.h>
13236 +#include <linux/random.h>
13237 +#include <net/tcp.h>
13238 +#include <linux/spinlock.h>
13239 +#include <linux/netfilter_ipv4/ip_tables.h>
13240 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
13243 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
13244 + Expressed in percentage
13247 +#define PAR_LOW 1/100
13248 +#define PAR_HIGH 1
13250 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
13252 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
13253 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
13254 +MODULE_LICENSE("GPL");
13256 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13258 + if (tx >= maxi) return 100;
13260 + if (tx <= mini) return 0;
13262 + return ( (100*(tx-mini)) / (maxi-mini) ) ;
13265 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13267 + if (tx <= mini) return 100;
13269 + if (tx >= maxi) return 0;
13271 + return ( (100*( maxi - tx )) / ( maxi - mini ) ) ;
13276 +ipt_fuzzy_match(const struct sk_buff *pskb,
13277 + const struct net_device *in,
13278 + const struct net_device *out,
13279 + const void *matchinfo,
13282 + u_int16_t datalen,
13285 + /* From userspace */
13287 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
13289 + u_int8_t random_number;
13290 + unsigned long amount ;
13291 + u_int8_t howhigh , howlow ;
13294 + spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
13296 + info->bytes_total += pskb->len ;
13297 + info->packets_total++ ;
13299 + info->present_time = jiffies ;
13301 + if ( info->present_time >= info->previous_time )
13302 + amount = info->present_time - info->previous_time ;
13304 + /* There was a transition : I choose to re-sample
13305 + and keep the old acceptance rate...
13309 + info->previous_time = info->present_time ;
13310 + info->bytes_total = info->packets_total = 0;
13313 + if ( amount > HZ/10 ) /* More than 100 ms elapsed ... */
13316 + info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total ) \
13319 + info->previous_time = info->present_time ;
13320 + info->bytes_total = info->packets_total = 0 ;
13322 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
13323 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
13325 + info->acceptance_rate = (u_int8_t) \
13326 + ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
13328 + /* In fact , the above defuzzification would require a denominator
13329 + proportional to (howhigh+howlow) but , in this particular case ,
13330 + that expression is constant .
13331 + An imediate consequence is that it isn't necessary to call
13332 + both mf_high and mf_low - but to keep things understandable ,
13338 + spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
13341 + if ( info->acceptance_rate < 100 )
13343 + get_random_bytes((void *)(&random_number), 1);
13345 + /* If within the acceptance , it can pass => don't match */
13346 + if ( random_number <= (255 * info->acceptance_rate) / 100 )
13349 + return 1; /* It can't pass ( It matches ) */
13352 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
13357 +ipt_fuzzy_checkentry(const char *tablename,
13358 + const struct ipt_ip *e,
13360 + unsigned int matchsize,
13361 + unsigned int hook_mask)
13364 + const struct ipt_fuzzy_info *info = matchinfo;
13366 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
13367 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
13368 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
13372 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
13373 + || (info->minimum_rate >= info->maximum_rate ))
13375 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
13382 +static struct ipt_match ipt_fuzzy_reg = {
13386 + ipt_fuzzy_checkentry,
13390 +static int __init init(void)
13392 + if (ipt_register_match(&ipt_fuzzy_reg))
13398 +static void __exit fini(void)
13400 + ipt_unregister_match(&ipt_fuzzy_reg);
13403 +module_init(init);
13404 +module_exit(fini);
13405 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPMARK.c
13406 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
13407 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPMARK.c 2003-12-11 10:23:52.557947952 +0100
13409 +/* This is a module which is used for setting the NFMARK field of an skb. */
13410 +#include <linux/module.h>
13411 +#include <linux/skbuff.h>
13412 +#include <linux/ip.h>
13413 +#include <net/checksum.h>
13415 +#include <linux/netfilter_ipv4/ip_tables.h>
13416 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
13418 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
13419 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
13420 +MODULE_LICENSE("GPL");
13422 +static unsigned int
13423 +target(struct sk_buff **pskb,
13424 + unsigned int hooknum,
13425 + const struct net_device *in,
13426 + const struct net_device *out,
13427 + const void *targinfo,
13430 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
13432 + struct iphdr *iph = (*pskb)->nh.iph;
13434 + unsigned long mark;
13437 + if(ipmarkinfo->addr == IPT_IPMARK_SRC)
13438 + mark = (unsigned long) iph->saddr;
13440 + mark = (unsigned long) iph->daddr;
13442 +// mark has ip address in little indian, we have to change the byte order:
13443 + a = (char *) &mark;
13444 + t = *a; *a=*(a+3); *(a+3)=t;
13445 + t=*(a+1); *(a+1)=*(a+2); *(a+2)=t;
13447 + mark &= ipmarkinfo->andmask;
13448 + mark |= ipmarkinfo->ormask;
13450 + if((*pskb)->nfmark != mark) {
13451 + (*pskb)->nfmark = mark;
13452 + (*pskb)->nfcache |= NFC_ALTERED;
13454 + return IPT_CONTINUE;
13458 +checkentry(const char *tablename,
13459 + const struct ipt_entry *e,
13461 + unsigned int targinfosize,
13462 + unsigned int hook_mask)
13464 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
13465 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
13467 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
13471 + if (strcmp(tablename, "mangle") != 0) {
13472 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13479 +static struct ipt_target ipt_ipmark_reg
13480 += { { NULL, NULL }, "IPMARK", target, checkentry, NULL, THIS_MODULE };
13482 +static int __init init(void)
13484 + if (ipt_register_target(&ipt_ipmark_reg))
13490 +static void __exit fini(void)
13492 + ipt_unregister_target(&ipt_ipmark_reg);
13495 +module_init(init);
13496 +module_exit(fini);
13497 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipv4options.c
13498 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
13499 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipv4options.c 2003-12-11 10:23:25.055129016 +0100
13502 + This is a module which is used to match ipv4 options.
13503 + This file is distributed under the terms of the GNU General Public
13504 + License (GPL). Copies of the GPL can be obtained from:
13505 + ftp://prep.ai.mit.edu/pub/gnu/GPL
13507 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
13508 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
13509 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
13510 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
13513 +#include <linux/module.h>
13514 +#include <linux/skbuff.h>
13515 +#include <net/ip.h>
13517 +#include <linux/netfilter_ipv4/ip_tables.h>
13518 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
13520 +MODULE_LICENSE("GPL");
13523 +match(const struct sk_buff *skb,
13524 + const struct net_device *in,
13525 + const struct net_device *out,
13526 + const void *matchinfo,
13529 + u_int16_t datalen,
13532 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
13533 + const struct iphdr *iph = skb->nh.iph;
13534 + const struct ip_options *opt;
13536 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
13537 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
13539 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
13540 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13541 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13542 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13543 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13544 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
13549 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
13550 + /* there are options, and we don't need to care which one */
13553 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
13554 + /* there are options but we don't want any ! */
13559 + opt = &(IPCB(skb)->opt);
13561 + /* source routing */
13562 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
13563 + if (!((opt->srr) & (opt->is_strictroute)))
13566 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
13567 + if (!((opt->srr) & (!opt->is_strictroute)))
13570 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
13574 + /* record route */
13575 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
13579 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
13584 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
13588 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
13592 + /* router-alert option */
13593 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
13594 + if (!opt->router_alert)
13597 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
13598 + if (opt->router_alert)
13607 +checkentry(const char *tablename,
13608 + const struct ipt_ip *ip,
13610 + unsigned int matchsize,
13611 + unsigned int hook_mask)
13613 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
13614 + /* Check the size */
13615 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
13617 + /* Now check the coherence of the data ... */
13618 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
13619 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
13620 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
13621 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
13622 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
13623 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
13624 + return 0; /* opposites */
13625 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
13626 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13627 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13628 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13629 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13630 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
13631 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
13632 + return 0; /* opposites */
13633 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
13634 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
13635 + return 0; /* cannot match in the same time loose and strict source routing */
13636 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13637 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
13638 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
13639 + return 0; /* opposites */
13640 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
13641 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
13642 + return 0; /* opposites */
13643 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
13644 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
13645 + return 0; /* opposites */
13646 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
13647 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
13648 + return 0; /* opposites */
13650 + /* everything looks ok. */
13654 +static struct ipt_match ipv4options_match
13655 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
13657 +static int __init init(void)
13659 + printk("ipt_ipv4options loading\n");
13660 + return ipt_register_match(&ipv4options_match);
13663 +static void __exit fini(void)
13665 + ipt_unregister_match(&ipv4options_match);
13666 + printk("ipt_ipv4options unloaded\n");
13669 +module_init(init);
13670 +module_exit(fini);
13671 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
13672 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
13673 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2003-12-11 10:23:26.189956496 +0100
13676 + * Strip all IP options in the IP packet header.
13678 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
13679 + * This software is distributed under GNU GPL v2, 1991
13682 +#include <linux/module.h>
13683 +#include <linux/skbuff.h>
13684 +#include <linux/ip.h>
13685 +#include <net/checksum.h>
13687 +#include <linux/netfilter_ipv4/ip_tables.h>
13689 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
13690 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
13691 +MODULE_LICENSE("GPL");
13693 +static unsigned int
13694 +target(struct sk_buff **pskb,
13695 + unsigned int hooknum,
13696 + const struct net_device *in,
13697 + const struct net_device *out,
13698 + const void *targinfo,
13701 + struct iphdr *iph = (*pskb)->nh.iph;
13702 + struct sk_buff *skb = (*pskb);
13703 + struct ip_options * opt;
13704 + unsigned char * optiph = skb->nh.raw;
13705 + int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
13708 + /* if no options in packet then nothing to clear. */
13709 + if (iph->ihl * 4 == sizeof(struct iphdr))
13710 + return IPT_CONTINUE;
13712 + /* else clear all options */
13713 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
13714 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
13715 + opt = &(IPCB(skb)->opt);
13716 + opt->is_data = 0;
13719 + skb->nfcache |= NFC_ALTERED;
13721 + return IPT_CONTINUE;
13725 +checkentry(const char *tablename,
13726 + const struct ipt_entry *e,
13728 + unsigned int targinfosize,
13729 + unsigned int hook_mask)
13731 + if (strcmp(tablename, "mangle")) {
13732 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13735 + /* nothing else to check because no parameters */
13739 +static struct ipt_target ipt_ipv4optsstrip_reg
13740 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
13742 +static int __init init(void)
13744 + if (ipt_register_target(&ipt_ipv4optsstrip_reg))
13746 + printk("ipt_IPV4OPTSSTRIP loaded\n");
13751 +static void __exit fini(void)
13753 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
13754 + printk("ipt_IPV4OPTSSTRIP unloaded\n");
13757 +module_init(init);
13758 +module_exit(fini);
13759 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_LOG.c
13760 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_LOG.c 2003-11-26 21:45:28.000000000 +0100
13761 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_LOG.c 2003-12-11 10:23:14.922669384 +0100
13763 #include <linux/module.h>
13764 #include <linux/spinlock.h>
13765 #include <linux/skbuff.h>
13766 +#include <linux/socket.h>
13767 #include <linux/ip.h>
13768 #include <net/icmp.h>
13769 #include <net/udp.h>
13770 #include <net/tcp.h>
13771 #include <net/route.h>
13773 +#include <linux/netfilter.h>
13774 #include <linux/netfilter_ipv4/ip_tables.h>
13775 #include <linux/netfilter_ipv4/ipt_LOG.h>
13778 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
13779 MODULE_DESCRIPTION("iptables syslog logging module");
13781 +static unsigned int nflog = 1;
13782 +MODULE_PARM(nflog, "i");
13783 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
13786 #define DEBUGP printk
13788 @@ -315,28 +321,25 @@
13789 /* maxlen = 230+ 91 + 230 + 252 = 803 */
13792 -static unsigned int
13793 -ipt_log_target(struct sk_buff **pskb,
13795 +ipt_log_packet(unsigned int hooknum,
13796 + const struct sk_buff *skb,
13797 const struct net_device *in,
13798 const struct net_device *out,
13799 - unsigned int hooknum,
13800 - const void *targinfo,
13802 + const struct ipt_log_info *loginfo,
13803 + const char *level_string,
13804 + const char *prefix)
13806 - const struct ipt_log_info *loginfo = targinfo;
13807 - char level_string[4] = "< >";
13809 - level_string[1] = '0' + (loginfo->level % 8);
13810 spin_lock_bh(&log_lock);
13811 printk(level_string);
13812 printk("%sIN=%s OUT=%s ",
13814 + prefix == NULL ? loginfo->prefix : prefix,
13815 in ? in->name : "",
13816 out ? out->name : "");
13817 #ifdef CONFIG_BRIDGE_NETFILTER
13818 - if ((*pskb)->nf_bridge) {
13819 - struct net_device *physindev = (*pskb)->nf_bridge->physindev;
13820 - struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
13821 + if (skb->nf_bridge) {
13822 + struct net_device *physindev = skb->nf_bridge->physindev;
13823 + struct net_device *physoutdev = skb->nf_bridge->physoutdev;
13825 if (physindev && in != physindev)
13826 printk("PHYSIN=%s ", physindev->name);
13827 @@ -348,25 +351,56 @@
13829 /* MAC logging for input chain only. */
13831 - if ((*pskb)->dev && (*pskb)->dev->hard_header_len
13832 - && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
13833 + if (skb->dev && skb->dev->hard_header_len
13834 + && skb->mac.raw != (void*)skb->nh.iph) {
13836 - unsigned char *p = (*pskb)->mac.raw;
13837 - for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
13838 + unsigned char *p = skb->mac.raw;
13839 + for (i = 0; i < skb->dev->hard_header_len; i++,p++)
13840 printk("%02x%c", *p,
13841 - i==(*pskb)->dev->hard_header_len - 1
13842 + i==skb->dev->hard_header_len - 1
13848 - dump_packet(loginfo, *pskb, 0);
13849 + dump_packet(loginfo, skb, 0);
13851 spin_unlock_bh(&log_lock);
13854 +static unsigned int
13855 +ipt_log_target(struct sk_buff **pskb,
13856 + const struct net_device *in,
13857 + const struct net_device *out,
13858 + unsigned int hooknum,
13859 + const void *targinfo,
13862 + const struct ipt_log_info *loginfo = targinfo;
13863 + char level_string[4] = "< >";
13865 + level_string[1] = '0' + (loginfo->level % 8);
13866 + ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
13868 return IPT_CONTINUE;
13872 +ipt_logfn(unsigned int hooknum,
13873 + const struct sk_buff *skb,
13874 + const struct net_device *in,
13875 + const struct net_device *out,
13876 + const char *prefix)
13878 + struct ipt_log_info loginfo = {
13880 + .logflags = IPT_LOG_MASK,
13884 + ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
13887 static int ipt_log_checkentry(const char *tablename,
13888 const struct ipt_entry *e,
13890 @@ -406,12 +440,17 @@
13892 if (ipt_register_target(&ipt_log_reg))
13895 + nf_log_register(PF_INET, &ipt_logfn);
13900 static void __exit fini(void)
13903 + nf_log_unregister(PF_INET, &ipt_logfn);
13905 ipt_unregister_target(&ipt_log_reg);
13908 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mark.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_mark.c
13909 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mark.c 2003-11-26 21:46:13.000000000 +0100
13910 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mark.c 2003-12-11 10:24:14.940545280 +0100
13915 - const struct ipt_mark_info *info = matchinfo;
13916 + const struct ipt_mark_info *info = (struct ipt_mark_info *)matchinfo;
13918 - return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13919 + if (info->bit_op == IPT_MARK_BIT_OP_NONE)
13920 + return (skb->nfmark == info->mark) ^ info->invert;
13922 + if (info->bit_op == IPT_MARK_BIT_OP_AND)
13923 + return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13925 + return ((skb->nfmark | info->mask) == info->mark) ^ info->invert;
13929 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_mport.c
13930 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
13931 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mport.c 2003-12-11 10:23:27.304787016 +0100
13933 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
13934 + the same place so we can treat them as equal. */
13935 +#include <linux/module.h>
13936 +#include <linux/types.h>
13937 +#include <linux/udp.h>
13938 +#include <linux/skbuff.h>
13940 +#include <linux/netfilter_ipv4/ipt_mport.h>
13941 +#include <linux/netfilter_ipv4/ip_tables.h>
13943 +MODULE_LICENSE("GPL");
13946 +#define duprintf(format, args...) printk(format , ## args)
13948 +#define duprintf(format, args...)
13951 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
13953 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
13957 + u_int16_t pflags = minfo->pflags;
13958 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
13962 + && minfo->ports[i] == 65535)
13965 + s = minfo->ports[i];
13967 + if (pflags & m) {
13968 + e = minfo->ports[++i];
13973 + if (minfo->flags & IPT_MPORT_SOURCE
13974 + && src >= s && src <= e)
13977 + if (minfo->flags & IPT_MPORT_DESTINATION
13978 + && dst >= s && dst <= e)
13986 +match(const struct sk_buff *skb,
13987 + const struct net_device *in,
13988 + const struct net_device *out,
13989 + const void *matchinfo,
13992 + u_int16_t datalen,
13995 + const struct udphdr *udp = hdr;
13996 + const struct ipt_mport *minfo = matchinfo;
13998 + /* Must be big enough to read ports. */
13999 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
14000 + /* We've been asked to examine this packet, and we
14001 + can't. Hence, no choice but to drop. */
14002 + duprintf("ipt_mport:"
14003 + " Dropping evil offset=0 tinygram.\n");
14008 + /* Must not be a fragment. */
14010 + && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
14013 +/* Called when user tries to insert an entry of this type. */
14015 +checkentry(const char *tablename,
14016 + const struct ipt_ip *ip,
14018 + unsigned int matchsize,
14019 + unsigned int hook_mask)
14021 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
14024 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
14025 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
14026 + && !(ip->invflags & IPT_INV_PROTO)
14027 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
14030 +static struct ipt_match mport_match
14031 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
14033 +static int __init init(void)
14035 + return ipt_register_match(&mport_match);
14038 +static void __exit fini(void)
14040 + ipt_unregister_match(&mport_match);
14043 +module_init(init);
14044 +module_exit(fini);
14045 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NOTRACK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_NOTRACK.c
14046 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NOTRACK.c 1970-01-01 01:00:00.000000000 +0100
14047 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_NOTRACK.c 2003-12-11 10:23:17.229318720 +0100
14049 +/* This is a module which is used for setting up fake conntracks
14050 + * on packets so that they are not seen by the conntrack/NAT code.
14052 +#include <linux/module.h>
14053 +#include <linux/skbuff.h>
14055 +#include <linux/netfilter_ipv4/ip_tables.h>
14056 +#include <linux/netfilter_ipv4/ip_conntrack.h>
14058 +static unsigned int
14059 +target(struct sk_buff **pskb,
14060 + const struct net_device *in,
14061 + const struct net_device *out,
14062 + unsigned int hooknum,
14063 + const void *targinfo,
14066 + /* Previously seen (loopback)? Ignore. */
14067 + if ((*pskb)->nfct != NULL)
14068 + return IPT_CONTINUE;
14070 + /* Attach fake conntrack entry.
14071 + If there is a real ct entry correspondig to this packet,
14072 + it'll hang aroun till timing out. We don't deal with it
14073 + for performance reasons. JK */
14074 + (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
14075 + nf_conntrack_get((*pskb)->nfct);
14077 + return IPT_CONTINUE;
14081 +checkentry(const char *tablename,
14082 + const struct ipt_entry *e,
14084 + unsigned int targinfosize,
14085 + unsigned int hook_mask)
14087 + if (targinfosize != 0) {
14088 + printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
14093 + if (strcmp(tablename, "raw") != 0) {
14094 + printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
14101 +static struct ipt_target ipt_notrack_reg = {
14102 + .name = "NOTRACK",
14103 + .target = target,
14104 + .checkentry = checkentry,
14106 + .me = THIS_MODULE,
14109 +static int __init init(void)
14111 + if (ipt_register_target(&ipt_notrack_reg))
14117 +static void __exit fini(void)
14119 + ipt_unregister_target(&ipt_notrack_reg);
14122 +module_init(init);
14123 +module_exit(fini);
14125 +MODULE_LICENSE("GPL");
14126 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
14127 +MODULE_DESCRIPTION("IPv4 NOTRACK target");
14128 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_nth.c
14129 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
14130 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_nth.c 2003-12-11 10:23:30.640279944 +0100
14133 + This is a module which is used for match support for every Nth packet
14134 + This file is distributed under the terms of the GNU General Public
14135 + License (GPL). Copies of the GPL can be obtained from:
14136 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14138 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14139 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
14140 + * added support for multiple counters
14141 + * added support for matching on individual packets
14142 + in the counter cycle
14146 +#include <linux/module.h>
14147 +#include <linux/skbuff.h>
14148 +#include <linux/ip.h>
14149 +#include <net/tcp.h>
14150 +#include <linux/spinlock.h>
14151 +#include <linux/netfilter_ipv4/ip_tables.h>
14152 +#include <linux/netfilter_ipv4/ipt_nth.h>
14154 +MODULE_LICENSE("GPL");
14157 + * State information.
14161 + u_int16_t number;
14164 +static struct state states[IPT_NTH_NUM_COUNTERS];
14167 +ipt_nth_match(const struct sk_buff *pskb,
14168 + const struct net_device *in,
14169 + const struct net_device *out,
14170 + const void *matchinfo,
14173 + u_int16_t datalen,
14176 + /* Parameters from userspace */
14177 + const struct ipt_nth_info *info = matchinfo;
14178 + unsigned counter = info->counter;
14179 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
14181 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14185 + spin_lock(&states[counter].lock);
14187 + /* Are we matching every nth packet?*/
14188 + if (info->packet == 0xFF)
14190 + /* We're matching every nth packet and only every nth packet*/
14191 + /* Do we match or invert match? */
14192 + if (info->not == 0)
14194 + if (states[counter].number == 0)
14196 + ++states[counter].number;
14199 + if (states[counter].number >= info->every)
14200 + states[counter].number = 0; /* reset the counter */
14202 + ++states[counter].number;
14207 + if (states[counter].number == 0)
14209 + ++states[counter].number;
14212 + if (states[counter].number >= info->every)
14213 + states[counter].number = 0;
14215 + ++states[counter].number;
14221 + /* We're using the --packet, so there must be a rule for every value */
14222 + if (states[counter].number == info->packet)
14224 + /* only increment the counter when a match happens */
14225 + if (states[counter].number >= info->every)
14226 + states[counter].number = 0; /* reset the counter */
14228 + ++states[counter].number;
14236 + /* don't match */
14237 + spin_unlock(&states[counter].lock);
14241 + spin_unlock(&states[counter].lock);
14246 +ipt_nth_checkentry(const char *tablename,
14247 + const struct ipt_ip *e,
14249 + unsigned int matchsize,
14250 + unsigned int hook_mask)
14252 + /* Parameters from userspace */
14253 + const struct ipt_nth_info *info = matchinfo;
14254 + unsigned counter = info->counter;
14255 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
14257 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14261 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
14262 + printk("nth: matchsize %u != %u\n", matchsize,
14263 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
14267 + states[counter].number = info->startat;
14272 +static struct ipt_match ipt_nth_reg = {
14276 + ipt_nth_checkentry,
14280 +static int __init init(void)
14282 + unsigned counter;
14283 + memset(&states, 0, sizeof(states));
14284 + if (ipt_register_match(&ipt_nth_reg))
14287 + for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
14289 + spin_lock_init(&(states[counter].lock));
14292 + printk("ipt_nth match loaded\n");
14296 +static void __exit fini(void)
14298 + ipt_unregister_match(&ipt_nth_reg);
14299 + printk("ipt_nth match unloaded\n");
14302 +module_init(init);
14303 +module_exit(fini);
14304 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_osf.c
14305 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
14306 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_osf.c 2003-12-11 10:23:31.784106056 +0100
14311 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
14314 + * This program is free software; you can redistribute it and/or modify
14315 + * it under the terms of the GNU General Public License as published by
14316 + * the Free Software Foundation; either version 2 of the License, or
14317 + * (at your option) any later version.
14319 + * This program is distributed in the hope that it will be useful,
14320 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14321 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14322 + * GNU General Public License for more details.
14324 + * You should have received a copy of the GNU General Public License
14325 + * along with this program; if not, write to the Free Software
14326 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14330 + * OS fingerprint matching module.
14331 + * It simply compares various parameters from SYN packet with
14332 + * some hardcoded ones.
14334 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
14338 +#include <linux/smp.h>
14339 +#include <linux/module.h>
14340 +#include <linux/skbuff.h>
14341 +#include <linux/file.h>
14342 +#include <linux/ip.h>
14343 +#include <linux/proc_fs.h>
14344 +#include <linux/fs.h>
14345 +#include <linux/slab.h>
14346 +#include <linux/spinlock.h>
14347 +#include <linux/ctype.h>
14348 +#include <linux/list.h>
14350 +#include <net/sock.h>
14351 +#include <net/ip.h>
14353 +#include <linux/netfilter_ipv4/ip_tables.h>
14355 +#include <linux/netfilter_ipv4/ipt_osf.h>
14357 +//#define OSF_DEBUG
14360 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
14361 +#define loga(x...) printk(x)
14363 +#define log(x...) do {} while(0)
14364 +#define loga(x...) do {} while(0)
14367 +#define FMATCH_WRONG 0
14368 +#define FMATCH_OK 1
14369 +#define FMATCH_OPT_WRONG 2
14371 +#define OPTDEL ','
14372 +#define OSFPDEL ':'
14373 +#define MAXOPTSTRLEN 128
14374 +#define OSFFLUSH "FLUSH"
14376 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
14377 +static struct list_head finger_list;
14379 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
14380 + const void *, int, const void *, u_int16_t, int *);
14381 +static int checkentry(const char *, const struct ipt_ip *, void *,
14382 + unsigned int, unsigned int);
14384 +static struct ipt_match osf_match =
14395 +match(const struct sk_buff *skb,
14396 + const struct net_device *in,
14397 + const struct net_device *out,
14398 + const void *matchinfo,
14401 + u_int16_t datalen,
14404 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
14405 + struct iphdr *ip = skb->nh.iph;
14406 + struct tcphdr *tcp;
14407 + int fmatch = FMATCH_WRONG;
14408 + unsigned long totlen, optsize = 0, window;
14409 + unsigned char df, *optp = NULL, *_optp = NULL;
14410 + char check_WSS = 0;
14411 + struct list_head *ent;
14412 + struct osf_finger *f;
14414 + if (!ip || !info)
14417 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
14422 + totlen = ntohs(ip->tot_len);
14423 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
14424 + window = ntohs(tcp->window);
14426 + if (tcp->doff*4 > sizeof(struct tcphdr))
14428 + _optp = optp = (char *)(tcp+1);
14429 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
14433 + /* Actually we can create hash/table of all genres and search
14434 + * only in appropriate part, but here is initial variant,
14435 + * so will use slow path.
14437 + read_lock(&osf_lock);
14438 + list_for_each(ent, &finger_list)
14440 + f = list_entry(ent, struct osf_finger, flist);
14442 + if (strcmp(info->genre, f->genre))
14447 + if ( ip->ttl == f->ttl &&
14448 + totlen == f->ss &&
14451 + unsigned long foptsize;
14453 + unsigned short mss = 0;
14457 + switch (f->wss.wc)
14459 + case 0: check_WSS = 0; break;
14460 + case 'S': check_WSS = 1; break;
14461 + case 'T': check_WSS = 2; break;
14462 + case '%': check_WSS = 3; break;
14463 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
14464 + f->wss.wc, f->genre, f->details);
14468 + if (check_WSS == 4)
14471 + /* Check options */
14474 + for (optnum=0; optnum<f->opt_num; ++optnum)
14475 + foptsize += f->opt[optnum].length;
14478 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
14483 + fmatch = FMATCH_OK;
14484 + loga("\tYEP : matching without options.\n");
14489 + for (optnum=0; optnum<f->opt_num; ++optnum)
14491 + if (f->opt[optnum].kind == (*optp))
14493 + unsigned char len = f->opt[optnum].length;
14494 + unsigned char *optend = optp + len;
14496 + fmatch = FMATCH_OK;
14498 + if (*optp == OSFOPT_MSS) /* MSS */
14499 + mss = ntohs(*(unsigned short *)(optp+2));
14503 + /* Skip kind and length fields*/
14506 + if (f->opt[optnum].wc.wc != 0)
14508 + unsigned long tmp = 0;
14510 + /* Hmmm... It looks a bit ugly. :) */
14511 + memcpy(&tmp, &f->opt[optnum].wc.val,
14512 + (len > sizeof(unsigned long)?
14513 + sizeof(unsigned long):len));
14515 + tmp = ntohl(tmp);
14516 + if (tmp != f->opt[optnum].wc.val)
14517 + fmatch = FMATCH_OPT_WRONG;
14524 + fmatch = FMATCH_OPT_WRONG;
14526 + if (fmatch != FMATCH_OK)
14530 + if (fmatch != FMATCH_OPT_WRONG)
14532 + fmatch = FMATCH_WRONG;
14534 + switch (check_WSS)
14537 + if (window == f->wss.val)
14538 + fmatch = FMATCH_OK;
14540 + case 1: /* MSS */
14541 + if (window == f->wss.val*mss)
14542 + fmatch = FMATCH_OK;
14544 + case 2: /* MTU */
14545 + if (window == f->wss.val*(mss+40))
14546 + fmatch = FMATCH_OK;
14548 + case 3: /* MOD */
14549 + if (window % f->wss.val == 0)
14550 + fmatch = FMATCH_OK;
14556 + if (fmatch == FMATCH_OK)
14559 + log("genre %s[%25s]: ttl=%d, size=%lu, df=%d, "
14560 + "check_WSS=%d, win=%lu, optsize=%lu:\n",
14561 + f->genre, f->details,
14562 + ip->ttl, totlen, df,
14563 + check_WSS, window, optsize);
14568 + read_unlock(&osf_lock);
14570 + return (fmatch == FMATCH_OK)?1:0;
14574 +checkentry(const char *tablename,
14575 + const struct ipt_ip *ip,
14577 + unsigned int matchsize,
14578 + unsigned int hook_mask)
14580 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
14582 + if (ip->proto != IPPROTO_TCP)
14588 +static char * osf_strchr(char *ptr, char c)
14592 + tmp = strchr(ptr, c);
14594 + while (tmp && tmp+1 && isspace(*(tmp+1)))
14600 +static struct osf_finger * finger_alloc()
14602 + struct osf_finger *f;
14604 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
14606 + memset(f, 0, sizeof(struct osf_finger));
14611 +static void finger_free(struct osf_finger *f)
14613 + memset(f, 0, sizeof(struct osf_finger));
14618 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
14622 + unsigned long val;
14626 + while (ptr != NULL && i < olen)
14635 + ptr = osf_strchr(&obuf[i], OPTDEL);
14640 + i += (int)(ptr-&obuf[i]);
14647 + op = OSFOPT_SACKP;
14648 + ptr = osf_strchr(&obuf[i], OPTDEL);
14653 + i += (int)(ptr-&obuf[i]);
14661 + ptr = osf_strchr(&obuf[i], OPTDEL);
14666 + i += (int)(ptr-&obuf[i]);
14674 + ptr = osf_strchr(&obuf[i], OPTDEL);
14677 + switch (obuf[i+1])
14679 + case '%': wc = '%'; break;
14680 + case 'S': wc = 'S'; break;
14681 + case 'T': wc = 'T'; break;
14682 + default: wc = 0; break;
14688 + val = simple_strtoul(&obuf[i+2], NULL, 10);
14690 + val = simple_strtoul(&obuf[i+1], NULL, 10);
14691 + i += (int)(ptr-&obuf[i]);
14699 + ptr = osf_strchr(&obuf[i], OPTDEL);
14702 + if (obuf[i+1] == '%')
14707 + val = simple_strtoul(&obuf[i+2], NULL, 10);
14709 + val = simple_strtoul(&obuf[i+1], NULL, 10);
14710 + i += (int)(ptr-&obuf[i]);
14718 + ptr = osf_strchr(&obuf[i], OPTDEL);
14723 + i += (int)(ptr-&obuf[i]);
14730 + ptr = osf_strchr(&obuf[i], OPTDEL);
14734 + i += (int)(ptr-&obuf[i]);
14742 + opt[*optnum].kind = IANA_opts[op].kind;
14743 + opt[*optnum].length = IANA_opts[op].length;
14744 + opt[*optnum].wc.wc = wc;
14745 + opt[*optnum].wc.val = val;
14747 + log("opt %2d: kind=%2d, length=%2d, wc.wc=%d, wc.val=%5lu\n",
14748 + *optnum, opt[*optnum].kind, opt[*optnum].length,
14749 + opt[*optnum].wc.wc, opt[*optnum].wc.val);
14755 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
14757 + struct list_head *ent;
14758 + struct osf_finger *f = NULL;
14764 + read_lock_bh(&osf_lock);
14765 + list_for_each(ent, &finger_list)
14767 + f = list_entry(ent, struct osf_finger, flist);
14769 + log("%s - %s: ttl=%d, wss=%c%lu, df=%d, size=%lu",
14770 + f->genre, f->details, f->ttl, (f->wss.wc)?f->wss.wc:' ', f->wss.val, f->df, f->ss);
14772 + count += sprintf(buf+count, "%s - %s[%s] : %s",
14773 + f->genre, f->version,
14774 + f->subtype, f->details);
14779 + //count += sprintf(buf+count, " OPT: ");
14780 + for (i=0; i<f->opt_num; ++i)
14782 + //count += sprintf(buf+count, "%d.%c%lu; ",
14783 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14784 + loga("%d.%c%lu; ",
14785 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14789 + count += sprintf(buf+count, "\n");
14791 + read_unlock_bh(&osf_lock);
14796 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
14800 + char obuf[MAXOPTSTRLEN];
14801 + struct osf_finger *finger;
14802 + struct list_head *ent, *n;
14804 + char *pbeg, *pend;
14806 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
14809 + write_lock_bh(&osf_lock);
14810 + list_for_each_safe(ent, n, &finger_list)
14813 + finger = list_entry(ent, struct osf_finger, flist);
14814 + list_del(&finger->flist);
14815 + finger_free(finger);
14817 + write_unlock_bh(&osf_lock);
14819 + log("Flushed %d entries.\n", i);
14826 + for (i=0; i<count && buffer[i] != '\0'; ++i)
14827 + if (buffer[i] == ':')
14830 + if (cnt != 8 || i != count)
14832 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
14837 + memset(obuf, 0, sizeof(obuf));
14839 + finger = finger_alloc();
14842 + log("Failed to allocate new fingerprint entry.\n");
14846 + pbeg = (char *)buffer;
14847 + pend = osf_strchr(pbeg, OSFPDEL);
14851 + if (pbeg[0] == 'S')
14853 + finger->wss.wc = 'S';
14854 + if (pbeg[1] == '%')
14855 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14856 + else if (pbeg[1] == '*')
14857 + finger->wss.val = 0;
14859 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14861 + else if (pbeg[0] == 'T')
14863 + finger->wss.wc = 'T';
14864 + if (pbeg[1] == '%')
14865 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14866 + else if (pbeg[1] == '*')
14867 + finger->wss.val = 0;
14869 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14871 + if (isdigit(pbeg[0]))
14873 + finger->wss.wc = 0;
14874 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
14879 + pend = osf_strchr(pbeg, OSFPDEL);
14883 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
14886 + pend = osf_strchr(pbeg, OSFPDEL);
14890 + finger->df = simple_strtoul(pbeg, NULL, 10);
14893 + pend = osf_strchr(pbeg, OSFPDEL);
14897 + finger->ss = simple_strtoul(pbeg, NULL, 10);
14901 + pend = osf_strchr(pbeg, OSFPDEL);
14905 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
14909 + pend = osf_strchr(pbeg, OSFPDEL);
14913 + if (pbeg[0] == '@' || pbeg[0] == '*')
14914 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
14916 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
14920 + pend = osf_strchr(pbeg, OSFPDEL);
14924 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
14928 + pend = osf_strchr(pbeg, OSFPDEL);
14932 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
14936 + cnt = snprintf(finger->details,
14937 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
14940 + log("%s - %s[%s] : %s\n",
14941 + finger->genre, finger->version,
14942 + finger->subtype, finger->details);
14944 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
14947 + write_lock_bh(&osf_lock);
14948 + list_add(&finger->flist, &finger_list);
14949 + write_unlock_bh(&osf_lock);
14954 +static int __init osf_init(void)
14957 + struct proc_dir_entry *p;
14959 + log("Startng OS fingerprint matching module.\n");
14961 + INIT_LIST_HEAD(&finger_list);
14963 + err = ipt_register_match(&osf_match);
14966 + log("Failed to register OS fingerprint matching module.\n");
14970 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
14973 + ipt_unregister_match(&osf_match);
14977 + p->write_proc = osf_proc_write;
14978 + p->read_proc = osf_proc_read;
14983 +static void __exit osf_fini(void)
14985 + struct list_head *ent, *n;
14986 + struct osf_finger *f;
14988 + remove_proc_entry("sys/net/ipv4/osf", NULL);
14989 + ipt_unregister_match(&osf_match);
14991 + list_for_each_safe(ent, n, &finger_list)
14993 + f = list_entry(ent, struct osf_finger, flist);
14994 + list_del(&f->flist);
14998 + log("OS fingerprint matching module finished.\n");
15001 +module_init(osf_init);
15002 +module_exit(osf_fini);
15004 +MODULE_LICENSE("GPL");
15005 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
15006 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
15007 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_pool.c
15008 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
15009 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_pool.c 2003-12-11 10:23:32.944929584 +0100
15011 +/* Kernel module to match an IP address pool. */
15013 +#include <linux/module.h>
15014 +#include <linux/ip.h>
15015 +#include <linux/skbuff.h>
15017 +#include <linux/netfilter_ipv4/ip_tables.h>
15018 +#include <linux/netfilter_ipv4/ip_pool.h>
15019 +#include <linux/netfilter_ipv4/ipt_pool.h>
15021 +static inline int match_pool(
15026 + if (ip_pool_match(index, ntohl(addr)))
15032 + const struct sk_buff *skb,
15033 + const struct net_device *in,
15034 + const struct net_device *out,
15035 + const void *matchinfo,
15038 + u_int16_t datalen,
15041 + const struct ipt_pool_info *info = matchinfo;
15042 + const struct iphdr *iph = skb->nh.iph;
15044 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
15045 + info->flags&IPT_POOL_INV_SRC))
15048 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
15049 + info->flags&IPT_POOL_INV_DST))
15055 +static int checkentry(
15056 + const char *tablename,
15057 + const struct ipt_ip *ip,
15059 + unsigned int matchsize,
15060 + unsigned int hook_mask
15062 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
15067 +static struct ipt_match pool_match
15068 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
15070 +static int __init init(void)
15072 + return ipt_register_match(&pool_match);
15075 +static void __exit fini(void)
15077 + ipt_unregister_match(&pool_match);
15080 +module_init(init);
15081 +module_exit(fini);
15082 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_POOL.c
15083 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
15084 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_POOL.c 2003-12-11 10:23:32.945929432 +0100
15086 +/* ipt_POOL.c - netfilter target to manipulate IP pools
15088 + * This target can be used almost everywhere. It acts on some specified
15089 + * IP pool, adding or deleting some IP address in the pool. The address
15090 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
15091 + * of the packet under inspection.
15093 + * The target normally returns IPT_CONTINUE.
15096 +#include <linux/types.h>
15097 +#include <linux/ip.h>
15098 +#include <linux/timer.h>
15099 +#include <linux/module.h>
15100 +#include <linux/netfilter.h>
15101 +#include <linux/netdevice.h>
15102 +#include <linux/if.h>
15103 +#include <linux/inetdevice.h>
15104 +#include <net/protocol.h>
15105 +#include <net/checksum.h>
15106 +#include <linux/netfilter_ipv4.h>
15107 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
15108 +#include <linux/netfilter_ipv4/ipt_pool.h>
15111 +#define DEBUGP printk
15113 +#define DEBUGP(format, args...)
15116 +/*** NOTE NOTE NOTE NOTE ***
15118 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
15119 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
15120 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
15121 +** is modified for the source IP address of the packet under inspection.
15122 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
15124 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
15125 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
15127 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
15128 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
15129 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
15130 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
15134 +do_check(const char *tablename,
15135 + const struct ipt_entry *e,
15137 + unsigned int targinfosize,
15138 + unsigned int hook_mask)
15140 + const struct ipt_pool_info *ipi = targinfo;
15142 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
15143 + DEBUGP("POOL_check: size %u.\n", targinfosize);
15146 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
15150 +static unsigned int
15151 +do_target(struct sk_buff **pskb,
15152 + unsigned int hooknum,
15153 + const struct net_device *in,
15154 + const struct net_device *out,
15155 + const void *targinfo,
15158 + const struct ipt_pool_info *ipi = targinfo;
15160 + unsigned int verdict = IPT_CONTINUE;
15162 + if (ipi->src != IP_POOL_NONE) {
15163 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
15164 + ipi->flags & IPT_POOL_DEL_SRC);
15165 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
15166 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
15167 + verdict = NF_ACCEPT;
15168 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
15169 + verdict = NF_DROP;
15172 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
15173 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
15174 + ipi->flags & IPT_POOL_DEL_DST);
15175 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
15176 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
15177 + verdict = NF_ACCEPT;
15178 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
15179 + verdict = NF_DROP;
15185 +static struct ipt_target pool_reg
15186 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
15188 +static int __init init(void)
15190 + DEBUGP("init ipt_POOL\n");
15191 + return ipt_register_target(&pool_reg);
15194 +static void __exit fini(void)
15196 + DEBUGP("fini ipt_POOL\n");
15197 + ipt_unregister_target(&pool_reg);
15200 +module_init(init);
15201 +module_exit(fini);
15202 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_psd.c
15203 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
15204 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_psd.c 2003-12-11 10:23:34.086756000 +0100
15207 + This is a module which is used for PSD (portscan detection)
15208 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
15209 + and LOG target module.
15211 + Copyright (C) 2000,2001 astaro AG
15213 + This file is distributed under the terms of the GNU General Public
15214 + License (GPL). Copies of the GPL can be obtained from:
15215 + ftp://prep.ai.mit.edu/pub/gnu/GPL
15217 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
15218 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
15219 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
15220 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
15221 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
15224 +#include <linux/module.h>
15225 +#include <linux/skbuff.h>
15226 +#include <linux/ip.h>
15227 +#include <net/tcp.h>
15228 +#include <linux/spinlock.h>
15229 +#include <linux/netfilter_ipv4/ip_tables.h>
15230 +#include <linux/netfilter_ipv4/ipt_psd.h>
15233 +#define DEBUGP printk
15235 +#define DEBUGP(format, args...)
15238 +MODULE_LICENSE("GPL");
15239 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
15241 +#define HF_DADDR_CHANGING 0x01
15242 +#define HF_SPORT_CHANGING 0x02
15243 +#define HF_TOS_CHANGING 0x04
15244 +#define HF_TTL_CHANGING 0x08
15247 + * Information we keep per each target port
15250 + u_int16_t number; /* port number */
15251 + u_int8_t proto; /* protocol number */
15252 + u_int8_t and_flags; /* tcp ANDed flags */
15253 + u_int8_t or_flags; /* tcp ORed flags */
15257 + * Information we keep per each source address.
15260 + struct host *next; /* Next entry with the same hash */
15261 + clock_t timestamp; /* Last update time */
15262 + struct in_addr src_addr; /* Source address */
15263 + struct in_addr dest_addr; /* Destination address */
15264 + unsigned short src_port; /* Source port */
15265 + int count; /* Number of ports in the list */
15266 + int weight; /* Total weight of ports in the list */
15267 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
15268 + unsigned char tos; /* TOS */
15269 + unsigned char ttl; /* TTL */
15270 + unsigned char flags; /* HF_ flags bitmask */
15274 + * State information.
15278 + struct host list[LIST_SIZE]; /* List of source addresses */
15279 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
15280 + int index; /* Oldest entry to be replaced */
15284 + * Convert an IP address into a hash table index.
15286 +static inline int hashfunc(struct in_addr addr)
15288 + unsigned int value;
15291 + value = addr.s_addr;
15295 + } while ((value >>= HASH_LOG));
15297 + return hash & (HASH_SIZE - 1);
15301 +ipt_psd_match(const struct sk_buff *pskb,
15302 + const struct net_device *in,
15303 + const struct net_device *out,
15304 + const void *matchinfo,
15307 + u_int16_t datalen,
15310 + struct iphdr *ip_hdr;
15311 + struct tcphdr *tcp_hdr;
15312 + struct in_addr addr;
15313 + u_int16_t src_port,dest_port;
15314 + u_int8_t tcp_flags, proto;
15316 + struct host *curr, *last, **head;
15317 + int hash, index, count;
15319 + /* Parameters from userspace */
15320 + const struct ipt_psd_info *psdinfo = matchinfo;
15323 + ip_hdr = pskb->nh.iph;
15325 + /* Sanity check */
15326 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
15327 + DEBUGP("PSD: sanity check failed\n");
15331 + /* TCP or UDP ? */
15332 + proto = ip_hdr->protocol;
15334 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
15335 + DEBUGP("PSD: protocol not supported\n");
15339 + /* Get the source address, source & destination ports, and TCP flags */
15341 + addr.s_addr = ip_hdr->saddr;
15343 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
15345 + /* Yep, it´s dirty */
15346 + src_port = tcp_hdr->source;
15347 + dest_port = tcp_hdr->dest;
15349 + if (proto == IPPROTO_TCP) {
15350 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
15353 + tcp_flags = 0x00;
15356 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
15357 + * them spoof us. [DHCP needs this feature - HW] */
15358 + if (!addr.s_addr) {
15359 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
15363 + /* Use jiffies here not to depend on someone setting the time while we're
15364 + * running; we need to be careful with possible return value overflows. */
15367 + spin_lock(&state.lock);
15369 + /* Do we know this source address already? */
15372 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
15374 + if (curr->src_addr.s_addr == addr.s_addr) break;
15376 + if (curr->next) last = curr;
15377 + } while ((curr = curr->next));
15381 + /* We know this address, and the entry isn't too old. Update it. */
15382 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
15383 + time_after_eq(now, curr->timestamp)) {
15385 + /* Just update the appropriate list entry if we've seen this port already */
15386 + for (index = 0; index < curr->count; index++) {
15387 + if (curr->ports[index].number == dest_port) {
15388 + curr->ports[index].proto = proto;
15389 + curr->ports[index].and_flags &= tcp_flags;
15390 + curr->ports[index].or_flags |= tcp_flags;
15391 + goto out_no_match;
15395 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
15396 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
15397 + goto out_no_match;
15399 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
15400 + curr->timestamp = now;
15402 + /* Logged this scan already? Then drop the packet. */
15403 + if (curr->weight >= psdinfo->weight_threshold)
15406 + /* Specify if destination address, source port, TOS or TTL are not fixed */
15407 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
15408 + curr->flags |= HF_DADDR_CHANGING;
15409 + if (curr->src_port != src_port)
15410 + curr->flags |= HF_SPORT_CHANGING;
15411 + if (curr->tos != ip_hdr->tos)
15412 + curr->flags |= HF_TOS_CHANGING;
15413 + if (curr->ttl != ip_hdr->ttl)
15414 + curr->flags |= HF_TTL_CHANGING;
15416 + /* Update the total weight */
15417 + curr->weight += (ntohs(dest_port) < 1024) ?
15418 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15420 + /* Got enough destination ports to decide that this is a scan? */
15421 + /* Then log it and drop the packet. */
15422 + if (curr->weight >= psdinfo->weight_threshold)
15425 + /* Remember the new port */
15426 + if (curr->count < SCAN_MAX_COUNT) {
15427 + curr->ports[curr->count].number = dest_port;
15428 + curr->ports[curr->count].proto = proto;
15429 + curr->ports[curr->count].and_flags = tcp_flags;
15430 + curr->ports[curr->count].or_flags = tcp_flags;
15434 + goto out_no_match;
15437 + /* We know this address, but the entry is outdated. Mark it unused, and
15438 + * remove from the hash table. We'll allocate a new entry instead since
15439 + * this one might get re-used too soon. */
15440 + curr->src_addr.s_addr = 0;
15442 + last->next = last->next->next;
15444 + *head = (*head)->next;
15448 + /* We don't need an ACK from a new source address */
15449 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
15450 + goto out_no_match;
15452 + /* Got too many source addresses with the same hash value? Then remove the
15453 + * oldest one from the hash table, so that they can't take too much of our
15454 + * CPU time even with carefully chosen spoofed IP addresses. */
15455 + if (count >= HASH_MAX && last) last->next = NULL;
15457 + /* We're going to re-use the oldest list entry, so remove it from the hash
15458 + * table first (if it is really already in use, and isn't removed from the
15459 + * hash table already because of the HASH_MAX check above). */
15461 + /* First, find it */
15462 + if (state.list[state.index].src_addr.s_addr)
15463 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
15467 + if ((curr = *head))
15469 + if (curr == &state.list[state.index]) break;
15471 + } while ((curr = curr->next));
15473 + /* Then, remove it */
15476 + last->next = last->next->next;
15478 + *head = (*head)->next;
15481 + /* Get our list entry */
15482 + curr = &state.list[state.index++];
15483 + if (state.index >= LIST_SIZE) state.index = 0;
15485 + /* Link it into the hash table */
15486 + head = &state.hash[hash];
15487 + curr->next = *head;
15490 + /* And fill in the fields */
15491 + curr->timestamp = now;
15492 + curr->src_addr = addr;
15493 + curr->dest_addr.s_addr = ip_hdr->daddr;
15494 + curr->src_port = src_port;
15496 + curr->weight = (ntohs(dest_port) < 1024) ?
15497 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15498 + curr->ports[0].number = dest_port;
15499 + curr->ports[0].proto = proto;
15500 + curr->ports[0].and_flags = tcp_flags;
15501 + curr->ports[0].or_flags = tcp_flags;
15502 + curr->tos = ip_hdr->tos;
15503 + curr->ttl = ip_hdr->ttl;
15506 + spin_unlock(&state.lock);
15510 + spin_unlock(&state.lock);
15514 +static int ipt_psd_checkentry(const char *tablename,
15515 + const struct ipt_ip *e,
15517 + unsigned int matchsize,
15518 + unsigned int hook_mask)
15520 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
15522 + /* we accept TCP only */
15523 +/* if (e->ip.proto != IPPROTO_TCP) { */
15524 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
15528 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
15529 + DEBUGP("PSD: matchsize %u != %u\n",
15531 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
15538 +static struct ipt_match ipt_psd_reg = {
15542 + ipt_psd_checkentry,
15546 +static int __init init(void)
15548 + if (ipt_register_match(&ipt_psd_reg))
15551 + memset(&state, 0, sizeof(state));
15553 + spin_lock_init(&(state.lock));
15555 + printk("netfilter PSD loaded - (c) astaro AG\n");
15559 +static void __exit fini(void)
15561 + ipt_unregister_match(&ipt_psd_reg);
15562 + printk("netfilter PSD unloaded - (c) astaro AG\n");
15565 +module_init(init);
15566 +module_exit(fini);
15567 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_quota.c
15568 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
15569 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_quota.c 2003-12-11 10:23:35.183589256 +0100
15572 + * netfilter module to enforce network quotas
15574 + * Sam Johnston <samj@samj.net>
15576 +#include <linux/module.h>
15577 +#include <linux/skbuff.h>
15578 +#include <linux/spinlock.h>
15579 +#include <linux/interrupt.h>
15581 +#include <linux/netfilter_ipv4/ip_tables.h>
15582 +#include <linux/netfilter_ipv4/ipt_quota.h>
15584 +MODULE_LICENSE("GPL");
15586 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
15589 +match(const struct sk_buff *skb,
15590 + const struct net_device *in,
15591 + const struct net_device *out,
15592 + const void *matchinfo,
15593 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
15596 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
15598 + spin_lock_bh("a_lock);
15600 + if (q->quota >= datalen) {
15601 + /* we can afford this one */
15602 + q->quota -= datalen;
15603 + spin_unlock_bh("a_lock);
15605 +#ifdef DEBUG_IPT_QUOTA
15606 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
15611 + /* so we do not allow even small packets from now on */
15614 +#ifdef DEBUG_IPT_QUOTA
15615 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
15618 + spin_unlock_bh("a_lock);
15623 +checkentry(const char *tablename,
15624 + const struct ipt_ip *ip,
15625 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
15627 + /* TODO: spinlocks? sanity checks? */
15628 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
15634 +static struct ipt_match quota_match
15635 + = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
15640 + return ipt_register_match("a_match);
15643 +static void __exit
15646 + ipt_unregister_match("a_match);
15649 +module_init(init);
15650 +module_exit(fini);
15652 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_random.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_random.c
15653 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
15654 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_random.c 2003-12-11 10:23:37.415249992 +0100
15657 + This is a module which is used for a "random" match support.
15658 + This file is distributed under the terms of the GNU General Public
15659 + License (GPL). Copies of the GPL can be obtained from:
15660 + ftp://prep.ai.mit.edu/pub/gnu/GPL
15662 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
15665 +#include <linux/module.h>
15666 +#include <linux/skbuff.h>
15667 +#include <linux/ip.h>
15668 +#include <linux/random.h>
15669 +#include <net/tcp.h>
15670 +#include <linux/spinlock.h>
15671 +#include <linux/netfilter_ipv4/ip_tables.h>
15672 +#include <linux/netfilter_ipv4/ipt_random.h>
15674 +MODULE_LICENSE("GPL");
15677 +ipt_rand_match(const struct sk_buff *pskb,
15678 + const struct net_device *in,
15679 + const struct net_device *out,
15680 + const void *matchinfo,
15683 + u_int16_t datalen,
15686 + /* Parameters from userspace */
15687 + const struct ipt_rand_info *info = matchinfo;
15688 + u_int8_t random_number;
15690 + /* get 1 random number from the kernel random number generation routine */
15691 + get_random_bytes((void *)(&random_number), 1);
15693 + /* Do we match ? */
15694 + if (random_number <= info->average)
15701 +ipt_rand_checkentry(const char *tablename,
15702 + const struct ipt_ip *e,
15704 + unsigned int matchsize,
15705 + unsigned int hook_mask)
15707 + /* Parameters from userspace */
15708 + const struct ipt_rand_info *info = matchinfo;
15710 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
15711 + printk("ipt_random: matchsize %u != %u\n", matchsize,
15712 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
15716 + /* must be 1 <= average % <= 99 */
15717 + /* 1 x 2.55 = 2 */
15718 + /* 99 x 2.55 = 252 */
15719 + if ((info->average < 2) || (info->average > 252)) {
15720 + printk("ipt_random: invalid average %u\n", info->average);
15727 +static struct ipt_match ipt_rand_reg = {
15731 + ipt_rand_checkentry,
15735 +static int __init init(void)
15737 + if (ipt_register_match(&ipt_rand_reg))
15740 + printk("ipt_random match loaded\n");
15744 +static void __exit fini(void)
15746 + ipt_unregister_match(&ipt_rand_reg);
15747 + printk("ipt_random match unloaded\n");
15750 +module_init(init);
15751 +module_exit(fini);
15752 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_realm.c
15753 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
15754 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_realm.c 2003-12-11 10:23:38.553077016 +0100
15756 +/* Kernel module to match realm from routing. */
15757 +#include <linux/module.h>
15758 +#include <linux/skbuff.h>
15759 +#include <linux/netdevice.h>
15760 +#include <net/route.h>
15762 +#include <linux/netfilter_ipv4/ipt_realm.h>
15763 +#include <linux/netfilter_ipv4/ip_tables.h>
15765 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
15766 +MODULE_LICENSE("GPL");
15769 +match(const struct sk_buff *skb,
15770 + const struct net_device *in,
15771 + const struct net_device *out,
15772 + const void *matchinfo,
15775 + u_int16_t datalen,
15778 + const struct ipt_realm_info *info = matchinfo;
15779 + struct dst_entry *dst = skb->dst;
15784 + id = dst->tclassid;
15786 + return (info->id == (id & info->mask)) ^ info->invert;
15789 +static int check(const char *tablename,
15790 + const struct ipt_ip *ip,
15792 + unsigned int matchsize,
15793 + unsigned int hook_mask)
15796 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
15797 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
15798 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
15799 + "LOCAL_IN or FORWARD.\n");
15803 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
15809 +static struct ipt_match realm_match
15810 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
15812 +static int __init init(void)
15814 + return ipt_register_match(&realm_match);
15817 +static void __exit fini(void)
15819 + ipt_unregister_match(&realm_match);
15822 +module_init(init);
15823 +module_exit(fini);
15824 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_REJECT.c
15825 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_REJECT.c 2003-11-26 21:45:22.000000000 +0100
15826 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_REJECT.c 2003-12-11 10:24:13.908702144 +0100
15828 * This is a module which is used for rejecting packets.
15829 * Added support for customized reject packets (Jozsef Kadlecsik).
15830 * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812]
15831 + * Added support for fake source IP in icmp-unreach (Fabrice MARIE & Guillaume MORIN).
15833 #include <linux/config.h>
15834 #include <linux/module.h>
15835 @@ -204,13 +205,13 @@
15839 -static void send_unreach(struct sk_buff *skb_in, int code)
15840 +static void send_unreach(struct sk_buff *skb_in, int code, u_int8_t fake_source_address)
15843 struct udphdr *udph;
15844 struct icmphdr *icmph;
15845 struct sk_buff *nskb;
15847 + u32 saddr,packet_daddr;
15849 int hh_len, length;
15850 struct rtable *rt = (struct rtable*)skb_in->dst;
15851 @@ -274,7 +275,7 @@
15855 - saddr = iph->daddr;
15856 + packet_daddr = saddr = iph->daddr;
15857 if (!(rt->rt_flags & RTCF_LOCAL))
15860 @@ -322,7 +323,16 @@
15862 ip_select_ident(iph, &rt->u.dst, NULL);
15863 iph->protocol=IPPROTO_ICMP;
15864 - iph->saddr=rt->rt_src;
15866 + /* fake source IP if we have to
15867 + if fake_source_address == 1, we fake the source IP
15868 + from the packet destination address dynamically.
15870 + if (fake_source_address == 1)
15871 + iph->saddr = packet_daddr;
15873 + iph->saddr=rt->rt_src;
15875 iph->daddr=rt->rt_dst;
15877 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
15878 @@ -370,25 +380,25 @@
15879 must return an absolute verdict. --RR */
15880 switch (reject->with) {
15881 case IPT_ICMP_NET_UNREACHABLE:
15882 - send_unreach(*pskb, ICMP_NET_UNREACH);
15883 + send_unreach(*pskb, ICMP_NET_UNREACH, reject->fake_source_address);
15885 case IPT_ICMP_HOST_UNREACHABLE:
15886 - send_unreach(*pskb, ICMP_HOST_UNREACH);
15887 + send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
15889 case IPT_ICMP_PROT_UNREACHABLE:
15890 - send_unreach(*pskb, ICMP_PROT_UNREACH);
15891 + send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
15893 case IPT_ICMP_PORT_UNREACHABLE:
15894 - send_unreach(*pskb, ICMP_PORT_UNREACH);
15895 + send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
15897 case IPT_ICMP_NET_PROHIBITED:
15898 - send_unreach(*pskb, ICMP_NET_ANO);
15899 + send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
15901 case IPT_ICMP_HOST_PROHIBITED:
15902 - send_unreach(*pskb, ICMP_HOST_ANO);
15903 + send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
15905 case IPT_ICMP_ADMIN_PROHIBITED:
15906 - send_unreach(*pskb, ICMP_PKT_FILTERED);
15907 + send_unreach(*pskb, ICMP_PKT_FILTERED, reject->fake_source_address);
15909 case IPT_TCP_RESET:
15910 send_reset(*pskb, hooknum);
15911 @@ -435,6 +445,11 @@
15912 DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
15915 + /* cannot fake source address */
15916 + if (rejinfo->fake_source_address != 0) {
15917 + DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
15923 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_rpc.c
15924 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
15925 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_rpc.c 2003-12-11 10:24:04.354154656 +0100
15927 +/* RPC extension for IP connection matching, Version 2.2
15928 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
15929 + * - original rpc tracking module
15930 + * - "recent" connection handling for kernel 2.3+ netfilter
15932 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
15933 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
15935 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
15936 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
15937 + * - extended matching to support filtering on procedures
15939 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
15941 + * This program is free software; you can redistribute it and/or
15942 + * modify it under the terms of the GNU General Public License
15943 + * as published by the Free Software Foundation; either version
15944 + * 2 of the License, or (at your option) any later version.
15946 + * Module load syntax:
15947 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
15949 + * Please give the ports of all RPC servers you wish to connect to.
15950 + * If you don't specify ports, the default will be port 111.
15954 + * RPCs should not be exposed to the internet - ask the Pentagon;
15956 + * "The unidentified crackers pleaded guilty in July to charges
15957 + * of juvenile delinquency stemming from a string of Pentagon
15958 + * network intrusions in February.
15960 + * The youths, going by the names TooShort and Makaveli, used
15961 + * a common server security hole to break in, according to
15962 + * Dane Jasper, owner of the California Internet service
15963 + * provider, Sonic. They used the hole, known as the 'statd'
15964 + * exploit, to attempt more than 800 break-ins, Jasper said."
15966 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
15967 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
15971 +#include <linux/module.h>
15972 +#include <linux/skbuff.h>
15973 +#include <linux/list.h>
15974 +#include <linux/udp.h>
15975 +#include <linux/tcp.h>
15976 +#include <linux/netfilter_ipv4/ip_conntrack.h>
15977 +#include <linux/netfilter_ipv4/ip_tables.h>
15978 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
15979 +#include <linux/netfilter_ipv4/lockhelp.h>
15980 +#include <linux/netfilter_ipv4/ipt_rpc.h>
15982 +#define MAX_PORTS 8
15983 +static int ports[MAX_PORTS];
15984 +static int ports_n_c = 0;
15986 +#ifdef MODULE_PARM
15987 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
15988 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
15991 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
15992 +MODULE_DESCRIPTION("RPC connection matching module");
15993 +MODULE_LICENSE("GPL");
15996 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
15999 +#define DEBUGP(format, args...)
16002 +EXPORT_NO_SYMBOLS;
16004 +/* vars from ip_conntrack_rpc_tcp */
16005 +extern struct list_head request_p_list_tcp;
16006 +extern struct module *ip_conntrack_rpc_tcp;
16008 +/* vars from ip_conntrack_rpc_udp */
16009 +extern struct list_head request_p_list_udp;
16010 +extern struct module *ip_conntrack_rpc_udp;
16012 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
16013 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
16015 +#define ASSERT_READ_LOCK(x) \
16017 + if (x == &request_p_list_udp) \
16018 + MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
16019 + else if (x == &request_p_list_tcp) \
16020 + MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
16023 +#define ASSERT_WRITE_LOCK(x) \
16025 + if (x == &request_p_list_udp) \
16026 + MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
16027 + else if (x == &request_p_list_tcp) \
16028 + MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
16031 +#include <linux/netfilter_ipv4/listhelp.h>
16033 +const int IPT_RPC_CHAR_LEN = 11;
16036 +static int k_atoi(char *string)
16038 + unsigned int result = 0;
16039 + int maxoctet = IPT_RPC_CHAR_LEN;
16041 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
16044 + if (*string == 0)
16046 + if (*string < 48 || *string > 57) {
16049 + result = result * 10 + ( *string - 48 );
16055 +static int match_rpcs(char *c_procs, int i_procs, int proc)
16059 + unsigned int proc_num;
16061 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
16063 + if (i_procs == -1)
16066 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
16068 + proc_ptr = c_procs;
16069 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
16070 + proc_num = k_atoi(proc_ptr);
16072 + if (proc_num == proc)
16080 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
16081 + int *hotdrop, int dir, struct ip_conntrack *ct,
16082 + int offset, struct list_head request_p_list)
16084 + const struct ipt_rpc_info *rpcinfo = matchinfo;
16085 + struct request_p *req_p;
16092 + /* This does sanity checking on RPC payloads,
16093 + * and permits only the RPC "get port" (3)
16094 + * in authorised procedures in client
16095 + * communications with the portmapper.
16100 + /* Get RPC requestor */
16101 + if (IXDR_GET_INT32(data) != 3) {
16102 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
16103 + if(rpcinfo->strict == 1)
16107 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
16111 + /* Jump Credentials and Verfifier */
16112 + data = data + IXDR_GET_INT32(data) + 2;
16113 + data = data + IXDR_GET_INT32(data) + 2;
16115 + /* Get RPC procedure */
16116 + if (match_rpcs((char *)&rpcinfo->c_procs,
16117 + rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
16118 + DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
16119 + (unsigned int)IXDR_GET_INT32(data));
16121 + /* If the RPC conntrack half entry already exists .. */
16123 + switch (ct->tuplehash[0].tuple.dst.protonum) {
16124 + case IPPROTO_UDP:
16125 + WRITE_LOCK(&ipct_rpc_udp_lock);
16126 + case IPPROTO_TCP:
16127 + WRITE_LOCK(&ipct_rpc_tcp_lock);
16129 + req_p = LIST_FIND(&request_p_list, request_p_cmp,
16130 + struct request_p *, xid,
16131 + ct->tuplehash[dir].tuple.src.ip,
16132 + ct->tuplehash[dir].tuple.src.u.all);
16135 + DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16136 + xid, ct->tuplehash[dir].tuple.dst.protonum,
16137 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16138 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
16140 + /* .. remove it */
16141 + if (del_timer(&req_p->timeout))
16142 + req_p->timeout.expires = 0;
16144 + LIST_DELETE(&request_p_list, req_p);
16145 + DEBUGP("RPC req_p removed. [done]\n");
16148 + DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16149 + xid, ct->tuplehash[dir].tuple.dst.protonum,
16150 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16151 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
16154 + switch (ct->tuplehash[0].tuple.dst.protonum) {
16155 + case IPPROTO_UDP:
16156 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
16157 + case IPPROTO_TCP:
16158 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
16161 + if(rpcinfo->strict == 1)
16166 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
16167 + (unsigned int)IXDR_GET_INT32(data));
16168 + return (1 && (!offset));
16172 +static int match(const struct sk_buff *skb, const struct net_device *in,
16173 + const struct net_device *out, const void *matchinfo,
16174 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
16176 + struct ip_conntrack *ct;
16177 + enum ip_conntrack_info ctinfo;
16178 + const u_int32_t *data;
16179 + enum ip_conntrack_dir dir;
16180 + const struct tcphdr *tcp;
16181 + const struct ipt_rpc_info *rpcinfo = matchinfo;
16182 + int port, portsok;
16186 + DEBUGP("new packet to evaluate ..\n");
16188 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
16190 + DEBUGP("no ct available [skip]\n");
16194 + DEBUGP("ct detected. [cont]\n");
16195 + dir = CTINFO2DIR(ctinfo);
16197 + /* we only want the client to server packets for matching */
16198 + if (dir != IP_CT_DIR_ORIGINAL)
16201 + /* This does sanity checking on UDP or TCP packets,
16202 + * like their respective modules.
16205 + switch (ct->tuplehash[0].tuple.dst.protonum) {
16207 + case IPPROTO_UDP:
16208 + DEBUGP("PROTO_UDP [cont]\n");
16209 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
16210 + DEBUGP("packet does not contain a complete header. [drop]\n");
16214 + for (port=0,portsok=0; port <= ports_n_c; port++) {
16215 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16220 + if (portsok == 0) {
16221 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16222 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16226 + if ((datalen - sizeof(struct udphdr)) != 56) {
16227 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
16228 + if (rpcinfo->strict == 1)
16232 + DEBUGP("packet length is correct. [cont]\n");
16234 + /* Get to the data */
16235 + data = (const u_int32_t *)hdr + 2;
16237 + /* Check the RPC data */
16238 + tval = check_rpc_packet(data, matchinfo, hotdrop,
16240 + request_p_list_udp);
16245 + case IPPROTO_TCP:
16246 + DEBUGP("PROTO_TCP [cont]\n");
16247 + if (offset == 0 && datalen < sizeof(struct tcphdr)) {
16248 + DEBUGP("packet does not contain a complete header. [drop]\n");
16252 + for (port=0,portsok=0; port <= ports_n_c; port++) {
16253 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16258 + if (portsok == 0) {
16259 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16260 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16265 + if (datalen == (tcp->doff * 4)) {
16266 + DEBUGP("packet does not contain any data. [match]\n");
16267 + return (1 && (!offset));
16270 + /* Tests if packet len is ok */
16271 + if ((datalen - (tcp->doff * 4)) != 60) {
16272 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
16273 + if(rpcinfo->strict == 1)
16277 + DEBUGP("packet length is correct. [cont]\n");
16279 + /* Get to the data */
16280 + data = (const u_int32_t *)tcp + tcp->doff + 1;
16282 + /* Check the RPC data */
16283 + tval = check_rpc_packet(data, matchinfo, hotdrop,
16285 + request_p_list_tcp);
16291 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
16292 + ct->tuplehash[0].tuple.dst.protonum);
16297 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
16298 + unsigned int matchsize, unsigned int hook_mask)
16301 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
16302 + | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
16303 + printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
16307 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
16314 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
16315 + &match, &checkentry, NULL,
16319 +static int __init init(void)
16323 + DEBUGP("incrementing usage counts\n");
16324 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
16325 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
16327 + /* If no port given, default to standard RPC port */
16328 + if (ports[0] == 0)
16329 + ports[0] = RPC_PORT;
16331 + DEBUGP("registering match [%s] for;\n", rpc_match.name);
16332 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
16333 + DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
16337 + return ipt_register_match(&rpc_match);
16341 +static void fini(void)
16343 + DEBUGP("unregistering match\n");
16344 + ipt_unregister_match(&rpc_match);
16346 + DEBUGP("decrementing usage counts\n");
16347 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
16348 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
16352 +module_init(init);
16353 +module_exit(fini);
16355 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_sctp.c
16356 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
16357 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_sctp.c 2003-12-11 10:23:18.303155472 +0100
16359 +/* IP tables module for matching the SCTP header
16361 + * $ipt_sctp.c,v 1.3 2002/05/29 15:09:00 laforge Exp$
16363 + * (C) 2003 by Harald Welte <laforge@gnumonks.org>
16365 + * This software is distributed under the terms GNU GPL v2
16368 +#include <linux/module.h>
16369 +#include <linux/skbuff.h>
16370 +#include <linux/sctp.h>
16372 +#include <linux/netfilter_ipv4/ip_tables.h>
16373 +#include <linux/netfilter_ipv4/ipt_sctp.h>
16375 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
16376 +MODULE_DESCRIPTION("IP tables SCTP matching module");
16377 +MODULE_LICENSE("GPL");
16379 +/* Returns 1 if the port is matched by the range, 0 otherwise */
16381 +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
16385 + ret = (port >= min && port <= max) ^ invert;
16389 +static int chunk_match(const struct sk_buff *skb, u_int32_t chunks, u_int32_t chunk_mask)
16391 + sctp_chunkhdr_t *ch = (sctp_chunkhdr_t *) skb->data;
16393 + u_int32_t chunks_present = 0;
16396 + u_int8_t *ch_end;
16397 + ch_end = ((u_int8_t *) ch) + WORD_ROUND(ntohs(ch->length));
16399 + if (ch->type < 32)
16400 + chunks_present |= (1 << ch_type);
16401 + else if (ch->type == SCTP_CID_ASCONF)
16402 + chunks_present |= (1 << 31);
16403 + else if (ch->type == SCTP_CID_ASCONF_ACK)
16404 + chunks_present |= (1 << 30);
16406 + ch = (sctp_chunkhdr_t *) ch_end;
16407 + } while (ch_end < skb->tail);
16409 + return ((chunks_present& chunk_mask) == chunks);
16412 +static int match(const struct sk_buff *skb, const struct net_device *in,
16413 + const struct net_device *out, const void *matchinfo,
16414 + int offset, const void *hdr, u_int16_t datalen,
16417 + const struct ipt_sctp_info *info = matchinfo;
16418 + const struct iphdr *iph = skb->nh.iph;
16419 + const struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
16421 + if (iph->protocol != IPPROTO_SCTP)
16424 + if (offset == 1) {
16425 + duprintf("Dropping evil SCTP offset=1 frag.\n");
16428 + } else if (offset == 0 && datalen < sizeof(struct sctphdr)) {
16429 + /* We've been askd o examine this packet, and we can't.
16430 + * Hence, no choice but to drop. */
16431 + duprintf("Dropping evil SCTP offset=0 tinygram.\n");
16437 + && port_match(info->spts[0], info->spts[1],
16438 + ntohs(sh->source),
16439 + !!(info->invflags & IPT_SCTP_INV_SRCPT))
16440 + && port_match(info->dpts[0], info->dpts[1],
16442 + !!(info->invflags & IPT_SCTP_INV_DSTPT))
16443 + && chunk_match(skb, info->chunks, info->chunk_mask)
16447 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
16448 + void *matchinfo, unsigned int matchsize,
16449 + unsigned int hook_mask)
16451 + const struct ipt_sctp_info *info = matchinfo;
16453 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_sctp_info)))
16456 + if (ip->proto != IPPROTO_SCTP && !(ip->invflags & IPT_INV_PROTO))
16459 + if !(info->invflags & ~IPT_SCTP_INV_MASK)
16465 +static struct ipt_match sctp_match = {
16468 + .checkentry = &checkentry,
16469 + .me = THIS_MODULE,
16472 +static int __init init(void)
16474 + return ipt_register_match(&sctp_match);
16477 +static void __exit fini(void)
16479 + ipt_unregister_match(&sctp_match);
16482 +module_init(init);
16483 +module_exit(fini);
16484 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_state.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_state.c
16485 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_state.c 2003-11-26 21:46:07.000000000 +0100
16486 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_state.c 2003-12-11 10:23:17.230318568 +0100
16487 @@ -23,10 +23,12 @@
16488 enum ip_conntrack_info ctinfo;
16489 unsigned int statebit;
16491 - if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16492 - statebit = IPT_STATE_INVALID;
16494 + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
16495 + statebit = IPT_STATE_UNTRACKED;
16496 + else if (ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16497 statebit = IPT_STATE_BIT(ctinfo);
16499 + statebit = IPT_STATE_INVALID;
16501 return (sinfo->statemask & statebit);
16503 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TCPLAG.c
16504 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
16505 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TCPLAG.c 2003-12-11 10:24:10.438229736 +0100
16507 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
16508 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
16510 + * This program is free software; you can redistribute it and/or modify
16511 + * it under the terms of the GNU General Public License as published by
16512 + * the Free Software Foundation; either version 2 of the License, or
16513 + * (at your option) any later version.
16515 + * This program is distributed in the hope that it will be useful,
16516 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16517 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16518 + * GNU General Public License for more details.
16520 + * You should have received a copy of the GNU General Public License
16521 + * along with this program; if not, write to the Free Software
16522 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16526 + * This collects packets and attempts to make them into pairs
16527 + * based on its own knowledge of how typical network conversations
16528 + * operate. Once it has a pair, it logs the time between them.
16530 +#include <linux/module.h>
16531 +#include <linux/skbuff.h>
16532 +#include <linux/ip.h>
16533 +#include <linux/spinlock.h>
16534 +#include <net/icmp.h>
16535 +#include <net/udp.h>
16536 +#include <net/tcp.h>
16537 +#include <linux/netfilter_ipv4/ip_tables.h>
16539 +#include <net/route.h>
16540 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
16543 +#define DEBUGP printk
16545 +#define DEBUGP(format, args...)
16549 + * We need one spinlock for the hash table.
16551 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
16553 +typedef struct timeval timeval_T;
16556 + * Linked lists of events in the connection,
16557 + * these store the SEQ numbers and the newest is always
16558 + * at the start of the linked list, then they get older
16559 + * down to the end of the linked list (this is not perfect
16560 + * if packets get out of order but we don't worry about fine
16561 + * details like that).
16563 + * Matching any event wipes out that event and also all other
16564 + * events down the chain (i.e. all older events).
16565 + * This keeps the linked list as short as possible.
16567 +typedef struct tcplag_event_S
16569 + struct tcplag_event_S *next;
16572 + u32 expected_ACK;
16573 + struct timeval stamp;
16577 + * This stores the connection statistics
16578 + * We define connections more loosely than TCP/IP does,
16579 + * because we only consider the two hosts, not the ports
16580 + * Also, we list the host-pairs in low,high order which
16581 + * means that we don't care who originated the connection.
16583 +typedef struct tcplag_hash_S
16587 + struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
16588 + struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
16589 + tcplag_event_T *h_ACK_list; /* Try to match ACK packets coming from h in this list */
16590 + tcplag_event_T *l_ACK_list; /* Try to match ACK packets coming from l in this list */
16591 + time_t stamp; /* When this bucket got added to the table */
16592 + u16 count_l_SEQ_h_ACK; /* Increment for each event */
16593 + u16 count_h_SEQ_l_ACK; /* Increment for each event */
16596 +static tcplag_hash_T **hashtab = 0;
16597 +static u32 hashsize = 0;
16598 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
16599 +static u32 reaper_ix = 0;
16601 +static void divide_down( timeval_T *T, int c )
16606 + remainder = T->tv_sec % c; /* Only works properly with positive numbers */
16607 + remainder *= 1000000;
16608 + T->tv_usec == remainder;
16612 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
16616 + x = tv1->tv_sec - tv2->tv_sec;
16617 + if( x ) return( x );
16618 + x = tv1->tv_usec - tv2->tv_usec;
16622 +void sprint_timeval( char *buf, timeval_T *tv )
16625 + sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
16627 + sprintf( buf, "%lu", tv->tv_usec );
16631 + * This generates the log messages through printk()
16633 + * There is really no particular interest in the port numbers at this stage,
16634 + * they are only useful for matching up the request with the reply.
16635 + * The IP numbers are useful because some sites may be slower than others
16636 + * or may travel different routes, etc (OK, in theory changing the port number
16637 + * could also change the route but I don't like that sort of theory).
16641 + * LIP= The IP number of the side with the lowest lag
16642 + * RIP= The IP number of the side with the highest lag
16643 + * LLAG= The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
16644 + * RLAG= The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
16646 +static void output( tcplag_hash_T *H, int level, const char *prefix )
16648 + struct timeval ltm, rtm;
16649 + u32 local_ip, remote_ip;
16650 + char r_buf[ 20 ], l_buf[ 20 ];
16652 + * We can't make sense of a connection that only passes data one way,
16653 + * In principle, at least the SYN and FIN should go both ways so we
16654 + * should get a few hits for every connection.
16656 + if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
16658 + * Calculate average times by dividing down
16660 + divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
16661 + divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
16663 + * Sort these two by the lag so the the local is always the short lag
16665 + if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
16667 + local_ip = H->low_ip;
16668 + remote_ip = H->high_ip;
16669 + rtm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
16670 + rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
16671 + ltm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
16672 + ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
16676 + local_ip = H->high_ip;
16677 + remote_ip = H->low_ip;
16678 + ltm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
16679 + ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
16680 + rtm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
16681 + rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
16684 + * Don't use a spinlock on the output,
16685 + * it is not guaranteed safe because some OTHER printk could
16686 + * split our log message so we want only one single printk.
16688 + * We use sprintf() to partially pre-digest the output
16690 + * Actually, neither this not the main netfilter LOG target is
16691 + * really safe from printk() overlap, basically syslog cannot
16692 + * be regarded as a guaranteed data output channel. It is good
16693 + * enough for most purposes.
16695 + sprint_timeval( l_buf, <m );
16696 + sprint_timeval( r_buf, &rtm );
16697 + printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
16698 + level & 7, prefix,
16699 + NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
16704 + * The reaper rolls through the hash table looking for old.
16705 + * Log entries are only generated at the reaping time
16706 + * (which means all log entries are out-of-date)
16708 +static void reaper( time_t now, int level, const char *prefix )
16712 + now -= max_seconds;
16713 + if( !hashsize ) return;
16714 + if( !hashtab ) return;
16715 + for( i = 0; i < 10; i++ )
16717 + if( ++reaper_ix >= hashsize ) reaper_ix = 0;
16719 +// DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
16721 + if( hashtab[ reaper_ix ])
16723 + tcplag_hash_T *found = 0;
16725 + spin_lock_bh( &hash_lock );
16726 + if( hashtab[ reaper_ix ])
16728 + if( now > hashtab[ reaper_ix ]->stamp )
16730 + DEBUGP( KERN_WARNING "reaper found expired entry\n" );
16731 + found = hashtab[ reaper_ix ];
16732 + hashtab[ reaper_ix ] = 0;
16735 + spin_unlock_bh( &hash_lock );
16739 + output( found, level, prefix );
16747 + * Convert the connection characteristics into a number
16748 + * (not including the timestamp) FIXME: this is a sucky hash function
16750 +static u32 make_hash( tcplag_hash_T *connection )
16754 + r = connection->low_ip;
16755 + r += connection->high_ip;
16759 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
16763 + x = con1->low_ip - con2->low_ip; if( x ) return( x );
16764 + x = con1->high_ip - con2->high_ip;
16768 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
16772 + DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
16773 + x = ev1->expected_ACK - ev2->expected_ACK;
16774 + if( x ) return( x );
16775 + DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
16776 + x = ev1->source_port - ev2->source_port;
16777 + if( x ) return( x );
16778 + DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
16779 + x = ev1->dest_port - ev2->dest_port;
16784 + * Go to the hash table and either find an existing connection that
16785 + * matches correctly or inject a new connection into the table.
16786 + * Once the connection is OK, chain the event onto the linked list.
16788 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
16792 + if( !event ) return; /* Just to be safe */
16793 + if( !hashsize ) return;
16794 + if( !hashtab ) return;
16796 + h = make_hash( connection );
16799 + DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
16801 + spin_lock_bh( &hash_lock );
16802 + for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
16804 + tcplag_hash_T *co_new = 0;
16806 + * Consider existing entry
16808 + if( hashtab[ h ])
16810 + if( compare_connections( hashtab[ h ], connection )) continue;
16811 + co_new = hashtab[ h ];
16812 + DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
16816 + * Use empty slot for new entry
16818 + if( !hashtab[ h ])
16820 + co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
16821 + memset( co_new, 0, sizeof( tcplag_hash_T ));
16822 + co_new->low_ip = connection->low_ip;
16823 + co_new->high_ip = connection->high_ip;
16824 + co_new->stamp = event->stamp.tv_sec;
16825 + hashtab[ h ] = co_new;
16826 + DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
16829 + tcplag_event_T *ev_new;
16831 + ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
16832 + memcpy( ev_new, event, sizeof( tcplag_event_T ));
16835 + ev_new->next = co_new->h_ACK_list;
16836 + co_new->h_ACK_list = ev_new;
16837 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
16841 + ev_new->next = co_new->l_ACK_list;
16842 + co_new->l_ACK_list = ev_new;
16843 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
16850 + spin_unlock_bh( &hash_lock );
16854 + * Search the hash table for a matching connection,
16855 + * if we can't find one of those then we are stuffed.
16857 + * Once a connection has been found, scan along the list for
16858 + * a matching SEQ number and if that is found then calculate
16859 + * the lag, update the counters and cut the chain at the
16860 + * point where the matching SEQ is found.
16862 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
16866 + if( !event ) return( 0 );
16867 + if( !hashsize ) return( 0 );
16868 + if( !hashtab ) return( 0 );
16869 + h = make_hash( connection );
16872 + DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
16874 + for( i = 0; i < hashsize; i++ )
16876 + tcplag_hash_T *found = 0;
16878 + if( !hashtab[ h ]) return( 0 );
16880 + spin_lock_bh( &hash_lock );
16881 + if( hashtab[ h ])
16883 + if( !compare_connections( hashtab[ h ], connection ))
16885 + tcplag_event_T *ev, **evroot;
16889 + found = hashtab[ h ];
16892 + evroot = &found->h_ACK_list;
16893 + tv = &found->lag_l_SEQ_h_ACK;
16894 + cn = &found->count_l_SEQ_h_ACK;
16895 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
16899 + evroot = &found->l_ACK_list;
16900 + tv = &found->lag_h_SEQ_l_ACK;
16901 + cn = &found->count_h_SEQ_l_ACK;
16902 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
16904 + for( ev = *evroot; ev; ev = ev->next )
16906 + if( !compare_events( ev, event ))
16909 + * Calculate the lag (in two parts) and add that to the collection
16911 + event->stamp.tv_sec -= ev->stamp.tv_sec;
16912 + event->stamp.tv_usec -= ev->stamp.tv_usec;
16913 + if( event->stamp.tv_usec < 0 )
16915 + event->stamp.tv_usec += 1000000;
16916 + event->stamp.tv_sec++;
16918 + if( event->stamp.tv_sec < 0 )
16920 + DEBUGP( KERN_WARNING "Negative lag detected\n" );
16924 + tv->tv_sec += event->stamp.tv_sec;
16925 + tv->tv_usec += event->stamp.tv_usec;
16927 + DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
16928 + " (accumulator is up to %lu.%06lu, %u events)\n",
16929 + event->stamp.tv_sec,
16930 + event->stamp.tv_usec,
16931 + tv->tv_sec, tv->tv_usec, *cn );
16934 + * Truncate the linked list.
16936 + * Visit each event in the list and return the memory to the pool.
16938 + * If a host is making multiple connections to the same remote host
16939 + * then this truncation will result in some requests not being
16940 + * monitored. Statistically we will still get some reasonable number
16941 + * of measurements and multiple simultaneous connections between host
16942 + * pairs don't happen all that often.
16947 + tcplag_event_T *ev_next = ev->next;
16948 + DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
16953 + * TODO: overflow limit for *cn, force premature output() if necessary
16954 + * (and drop this connection from the hash table)
16963 + spin_unlock_bh( &hash_lock );
16965 + if( found ) return( 1 );
16966 + if( ++h >= hashsize ) h = 0;
16972 + * Here is our target data:
16974 + * pskb -- The packet itself (see linux/skbuff.h for breakdown)
16978 + * in -- The device that this packet came in on
16979 + * (depending on the chain this may or may not exist)
16981 + * out -- The device that this packet is just about to go
16982 + * out onto (again existance depends on the chain)
16984 + * targinfo -- Our private data (handed through from iptables command util)
16986 + * userinfo -- Some more data
16990 +static unsigned int target( struct sk_buff **pskb,
16991 + unsigned int hooknum,
16992 + const struct net_device *in,
16993 + const struct net_device *out,
16994 + const void *targinfo,
16997 + struct iphdr *iph = ( *pskb )->nh.iph;
16998 + const struct ipt_tcplag *el = targinfo;
16999 + tcplag_hash_T connection;
17000 + tcplag_event_T event;
17003 + * We know we are dealing with IP here
17004 + * Fill in all the obvious fields
17006 + if( iph->saddr > iph->daddr )
17009 + connection.high_ip = iph->saddr;
17010 + connection.low_ip = iph->daddr;
17015 + connection.low_ip = iph->saddr;
17016 + connection.high_ip = iph->daddr;
17018 + do_gettimeofday( &event.stamp );
17020 + * Do a bit of cleaning
17022 + reaper( event.stamp.tv_sec, el->level, el->prefix );
17024 + DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
17025 + event.stamp.tv_sec,
17026 + event.stamp.tv_usec,
17027 + in ? in->name : "none", out ? out->name : "none" );
17029 + * Now start looking at the details
17031 + * First step is to identify this packet to see if it is
17032 + * the sort of packet that we are interested in.
17033 + * Don't hold any locks while we are doing this because often
17034 + * we will just let the packet go without any further consideration.
17036 + switch( iph->protocol )
17038 + case IPPROTO_TCP:
17040 + struct tcphdr *tcp;
17042 + if( ntohs( iph->frag_off ) & IP_OFFSET )
17044 + DEBUGP( KERN_WARNING "ignoring fragment\n" );
17047 + tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
17048 + event.source_port = ntohs( tcp->source );
17049 + event.dest_port = ntohs( tcp->dest );
17051 + * Every packet should have a valid SEQ number so use this to
17052 + * generate an ACK number. This works along the formula:
17053 + * -- Start with the SEQ number
17054 + * -- For SYN or FIN add 1 to that number
17055 + * -- For data packet, add the data length to that number
17059 + * Data length requires a bit of fiddling around
17062 + unsigned int data_len;
17063 + if( tcp->syn || tcp->fin )
17065 + data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
17069 + data_len = ntohs( iph->tot_len );
17070 + data_len -= 4 * iph->ihl; /* Subtract away IP header & options */
17071 + data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
17074 + DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
17076 + if( data_len ) /* Only track events that demand an ACK */
17078 + event.expected_ACK = ntohl( tcp->seq ) + data_len;
17079 + hash_insert( &connection, &event, direction );
17083 + DEBUGP( "Don't bother to insert this, ACK not required\n" );
17090 + * Now we consider the matching of an existing event.
17091 + * Reverse the port numbers and change the ACK number to the actual ACK number
17092 + * Note that the direction is reversed because the reply will be going
17093 + * the opposite way to the request.
17095 + event.expected_ACK = ntohl( tcp->ack_seq );
17096 + event.dest_port = ntohs( tcp->source );
17097 + event.source_port = ntohs( tcp->dest );
17098 + request_complete( &connection, &event, !direction );
17102 + DEBUGP( "Don't bother to check this, ACK not valid\n" );
17106 + return( IPT_CONTINUE );
17110 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
17111 + * return( 1 ) if the entry is suitable
17117 + * targinfo -- Our private data block (handed to us from iptables plug-in)
17119 + * targinfosize -- The size of our private data block
17124 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
17125 + * all possible flag combos make sense. All we check for is correct data size.
17127 +static int checkentry( const char *tablename,
17128 + const struct ipt_entry *e,
17130 + unsigned int targinfosize,
17131 + unsigned int hook_mask )
17133 + const struct ipt_tcplag *el = targinfo;
17135 + if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
17137 + DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
17138 + IPT_ALIGN( sizeof( struct ipt_tcplag )));
17141 + if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
17145 +static struct ipt_target reg =
17155 +static int __init init( void )
17157 + if( ipt_register_target( ® )) return( -EINVAL );
17158 + hashsize = 123; /* should be configurable */
17159 + hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
17160 + memset( hashtab, 0, sizeof( void * ) * hashsize );
17165 + * This should not need locks (in theory)
17166 + * because it can only get punted after it is no longer
17167 + * chained into any of the netfilter lists.
17169 +static void __exit fini( void )
17173 + ipt_unregister_target( ® );
17175 + * Put back kernel memory
17177 + for( i = 0; i < hashsize; i++ )
17179 + tcplag_hash_T *p;
17181 + if(( p = hashtab[ i ]))
17183 + tcplag_event_T *ev, *evn;
17185 + hashtab[ i ] = 0;
17186 + for( ev = p->h_ACK_list; ev; ev = evn )
17191 + for( ev = p->l_ACK_list; ev; ev = evn )
17199 + kfree( hashtab );
17202 +module_init(init);
17203 +module_exit(fini);
17204 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_time.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_time.c
17205 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
17206 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_time.c 2003-12-11 10:23:40.871724528 +0100
17209 + This is a module which is used for time matching
17210 + It is using some modified code from dietlibc (localtime() function)
17211 + that you can find at http://www.fefe.de/dietlibc/
17212 + This file is distributed under the terms of the GNU General Public
17213 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
17214 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
17215 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
17216 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
17217 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
17218 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
17219 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
17222 +#include <linux/module.h>
17223 +#include <linux/skbuff.h>
17224 +#include <linux/netfilter_ipv4/ip_tables.h>
17225 +#include <linux/netfilter_ipv4/ipt_time.h>
17226 +#include <linux/time.h>
17228 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
17229 +MODULE_DESCRIPTION("Match arrival timestamp");
17230 +MODULE_LICENSE("GPL");
17234 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
17235 + int tm_min; /* Minutes. [0-59] */
17236 + int tm_hour; /* Hours. [0-23] */
17237 + int tm_mday; /* Day. [1-31] */
17238 + int tm_mon; /* Month. [0-11] */
17239 + int tm_year; /* Year - 1900. */
17240 + int tm_wday; /* Day of week. [0-6] */
17241 + int tm_yday; /* Days in year.[0-365] */
17242 + int tm_isdst; /* DST. [-1/0/1]*/
17244 + long int tm_gmtoff; /* we don't care, we count from GMT */
17245 + const char *tm_zone; /* we don't care, we count from GMT */
17249 +localtime(const time_t *timepr, struct tm *r);
17252 +match(const struct sk_buff *skb,
17253 + const struct net_device *in,
17254 + const struct net_device *out,
17255 + const void *matchinfo,
17258 + u_int16_t datalen,
17261 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
17262 + struct tm currenttime; /* time human readable */
17263 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
17264 + u_int16_t packet_time;
17265 + struct timeval kerneltimeval;
17266 + time_t packet_local_time;
17268 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
17269 + if (info->kerneltime)
17271 + do_gettimeofday(&kerneltimeval);
17272 + packet_local_time = kerneltimeval.tv_sec;
17275 + packet_local_time = skb->stamp.tv_sec;
17277 + /* Transform the timestamp of the packet, in a human readable form */
17278 + localtime(&packet_local_time, ¤ttime);
17280 + /* check if we match this timestamp, we start by the days... */
17281 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
17282 + return 0; /* the day doesn't match */
17284 + /* ... check the time now */
17285 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
17286 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
17289 + /* here we match ! */
17294 +checkentry(const char *tablename,
17295 + const struct ipt_ip *ip,
17297 + unsigned int matchsize,
17298 + unsigned int hook_mask)
17300 + struct ipt_time_info *info = matchinfo; /* match info for rule */
17302 + /* First, check that we are in the correct hook */
17303 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
17305 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
17307 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
17310 + /* we use the kerneltime if we are in forward or output */
17311 + info->kerneltime = 1;
17312 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
17313 + /* if not, we use the skb time */
17314 + info->kerneltime = 0;
17316 + /* Check the size */
17317 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
17319 + /* Now check the coherence of the data ... */
17320 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
17321 + (info->time_stop > 1439))
17323 + printk(KERN_WARNING "ipt_time: invalid argument\n");
17330 +static struct ipt_match time_match
17331 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
17333 +static int __init init(void)
17335 + printk("ipt_time loading\n");
17336 + return ipt_register_match(&time_match);
17339 +static void __exit fini(void)
17341 + ipt_unregister_match(&time_match);
17342 + printk("ipt_time unloaded\n");
17345 +module_init(init);
17346 +module_exit(fini);
17349 +/* The part below is borowed and modified from dietlibc */
17351 +/* seconds per day */
17352 +#define SPD 24*60*60
17355 +localtime(const time_t *timepr, struct tm *r) {
17358 + extern struct timezone sys_tz;
17359 + const unsigned int __spm[12] =
17365 + (31+28+31+30+31),
17366 + (31+28+31+30+31+30),
17367 + (31+28+31+30+31+30+31),
17368 + (31+28+31+30+31+30+31+31),
17369 + (31+28+31+30+31+30+31+31+30),
17370 + (31+28+31+30+31+30+31+31+30+31),
17371 + (31+28+31+30+31+30+31+31+30+31+30),
17373 + register time_t work;
17375 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
17376 + work=timep%(SPD);
17377 + r->tm_sec=work%60; work/=60;
17378 + r->tm_min=work%60; r->tm_hour=work/60;
17379 + work=timep/(SPD);
17380 + r->tm_wday=(4+work)%7;
17381 + for (i=1970; ; ++i) {
17382 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
17388 + r->tm_year=i-1900;
17389 + for (i=11; i && __spm[i]>work; --i) ;
17391 + r->tm_mday=work-__spm[i]+1;
17393 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TRACE.c
17394 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
17395 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TRACE.c 2003-12-11 10:23:17.229318720 +0100
17397 +/* This is a module which is used for setting
17398 + * the NFC_TRACE flag in the nfcache field of an skb.
17400 +#include <linux/module.h>
17401 +#include <linux/skbuff.h>
17403 +#include <linux/netfilter_ipv4/ip_tables.h>
17405 +static unsigned int
17406 +target(struct sk_buff **pskb,
17407 + const struct net_device *in,
17408 + const struct net_device *out,
17409 + unsigned int hooknum,
17410 + const void *targinfo,
17413 + (*pskb)->nfcache |= NFC_TRACE;
17414 + return IPT_CONTINUE;
17418 +checkentry(const char *tablename,
17419 + const struct ipt_entry *e,
17421 + unsigned int targinfosize,
17422 + unsigned int hook_mask)
17424 + if (targinfosize != 0) {
17425 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17430 + if (strcmp(tablename, "raw") != 0) {
17431 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17438 +static struct ipt_target ipt_trace_reg = {
17440 + .target = target,
17441 + .checkentry = checkentry,
17443 + .me = THIS_MODULE,
17446 +static int __init init(void)
17448 + if (ipt_register_target(&ipt_trace_reg))
17454 +static void __exit fini(void)
17456 + ipt_unregister_target(&ipt_trace_reg);
17459 +module_init(init);
17460 +module_exit(fini);
17461 +MODULE_LICENSE("GPL");
17462 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
17463 +MODULE_DESCRIPTION("IPv4 TRACE target");
17464 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TTL.c
17465 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
17466 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TTL.c 2003-12-11 10:23:41.987554896 +0100
17468 +/* TTL modification target for IP tables
17469 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
17473 + * This software is distributed under the terms of GNU GPL
17476 +#include <linux/module.h>
17477 +#include <linux/skbuff.h>
17478 +#include <linux/ip.h>
17479 +#include <net/checksum.h>
17481 +#include <linux/netfilter_ipv4/ip_tables.h>
17482 +#include <linux/netfilter_ipv4/ipt_TTL.h>
17484 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
17485 +MODULE_DESCRIPTION("IP tables TTL modification module");
17486 +MODULE_LICENSE("GPL");
17488 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
17489 + const struct net_device *in, const struct net_device *out,
17490 + const void *targinfo, void *userinfo)
17492 + struct iphdr *iph = (*pskb)->nh.iph;
17493 + const struct ipt_TTL_info *info = targinfo;
17494 + u_int16_t diffs[2];
17497 + switch (info->mode) {
17498 + case IPT_TTL_SET:
17499 + new_ttl = info->ttl;
17501 + case IPT_TTL_INC:
17502 + new_ttl = iph->ttl + info->ttl;
17503 + if (new_ttl > 255)
17506 + case IPT_TTL_DEC:
17507 + new_ttl = iph->ttl + info->ttl;
17512 + new_ttl = iph->ttl;
17516 + if (new_ttl != iph->ttl) {
17517 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
17518 + iph->ttl = new_ttl;
17519 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
17520 + iph->check = csum_fold(csum_partial((char *)diffs,
17522 + iph->check^0xFFFF));
17523 + (*pskb)->nfcache |= NFC_ALTERED;
17526 + return IPT_CONTINUE;
17529 +static int ipt_ttl_checkentry(const char *tablename,
17530 + const struct ipt_entry *e,
17532 + unsigned int targinfosize,
17533 + unsigned int hook_mask)
17535 + struct ipt_TTL_info *info = targinfo;
17537 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
17538 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
17540 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
17544 + if (strcmp(tablename, "mangle")) {
17545 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
17549 + if (info->mode > IPT_TTL_MAXMODE) {
17550 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
17555 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
17556 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
17563 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
17564 + ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
17566 +static int __init init(void)
17568 + return ipt_register_target(&ipt_TTL);
17571 +static void __exit fini(void)
17573 + ipt_unregister_target(&ipt_TTL);
17576 +module_init(init);
17577 +module_exit(fini);
17578 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_u32.c
17579 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
17580 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_u32.c 2003-12-11 10:23:43.131381008 +0100
17582 +/* Kernel module to match u32 packet content. */
17585 +U32 tests whether quantities of up to 4 bytes extracted from a packet
17586 +have specified values. The specification of what to extract is general
17587 +enough to find data at given offsets from tcp headers or payloads.
17590 + The argument amounts to a program in a small language described below.
17591 + tests := location = value | tests && location = value
17592 + value := range | value , range
17593 + range := number | number : number
17594 + a single number, n, is interpreted the same as n:n
17595 + n:m is interpreted as the range of numbers >=n and <=m
17596 + location := number | location operator number
17597 + operator := & | << | >> | @
17599 + The operators &, <<, >>, && mean the same as in c. The = is really a set
17600 + membership operator and the value syntax describes a set. The @ operator
17601 + is what allows moving to the next header and is described further below.
17603 + *** Until I can find out how to avoid it, there are some artificial limits
17604 + on the size of the tests:
17605 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
17606 + - no more than 10 ranges (and 9 commas) per value
17607 + - no more than 10 numbers (and 9 operators) per location
17609 + To describe the meaning of location, imagine the following machine that
17610 + interprets it. There are three registers:
17611 + A is of type char*, initially the address of the IP header
17612 + B and C are unsigned 32 bit integers, initially zero
17614 + The instructions are:
17615 + number B = number;
17616 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
17617 + &number C = C&number
17618 + <<number C = C<<number
17619 + >>number C = C>>number
17620 + @number A = A+C; then do the instruction number
17621 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
17622 + Otherwise the result of the computation is the final value of C.
17624 + Whitespace is allowed but not required in the tests.
17625 + However the characters that do occur there are likely to require
17626 + shell quoting, so it's a good idea to enclose the arguments in quotes.
17629 + match IP packets with total length >= 256
17630 + The IP header contains a total length field in bytes 2-3.
17631 + --u32 "0&0xFFFF=0x100:0xFFFF"
17633 + AND that with FFFF (giving bytes 2-3),
17634 + and test whether that's in the range [0x100:0xFFFF]
17636 +Example: (more realistic, hence more complicated)
17637 + match icmp packets with icmp type 0
17638 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
17639 + --u32 "6&0xFF=1 && ...
17640 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
17641 + Next test that it's not a fragment.
17642 + (If so it might be part of such a packet but we can't always tell.)
17643 + n.b. This test is generally needed if you want to match anything
17644 + beyond the IP header.
17645 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
17646 + packet (not a fragment). Alternatively, you can allow first fragments
17647 + by only testing the last 5 bits of byte 6.
17648 + ... 4&0x3FFF=0 && ...
17649 + Last test: the first byte past the IP header (the type) is 0
17650 + This is where we have to use the @syntax. The length of the IP header
17651 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
17652 + IP header itself.
17653 + ... 0>>22&0x3C@0>>24=0"
17654 + The first 0 means read bytes 0-3,
17655 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
17656 + the first byte, so only 22 bits is four times that plus a few more bits.
17657 + &3C then eliminates the two extra bits on the right and the first four
17658 + bits of the first byte.
17659 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
17660 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
17661 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
17662 + @ means to use this number as a new offset into the packet, and read
17663 + four bytes starting from there. This is the first 4 bytes of the icmp
17664 + payload, of which byte 0 is the icmp type. Therefore we simply shift
17665 + the value 24 to the right to throw out all but the first byte and compare
17666 + the result with 0.
17669 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
17670 + First we test that the packet is a tcp packet (similar to icmp).
17671 + --u32 "6&0xFF=6 && ...
17672 + Next, test that it's not a fragment (same as above).
17673 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
17674 + 0>>22&3C as above computes the number of bytes in the IP header.
17675 + @ makes this the new offset into the packet, which is the start of the
17676 + tcp header. The length of the tcp header (again in 32 bit words) is
17677 + the left half of byte 12 of the tcp header. The 12>>26&3C
17678 + computes this length in bytes (similar to the IP header before).
17679 + @ makes this the new offset, which is the start of the tcp payload.
17680 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
17681 + result is any of 1, 2, 5 or 8
17684 +#include <linux/module.h>
17685 +#include <linux/skbuff.h>
17687 +#include <linux/netfilter_ipv4/ipt_u32.h>
17688 +#include <linux/netfilter_ipv4/ip_tables.h>
17690 +/* #include <asm-i386/timex.h> for timing */
17692 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
17693 +MODULE_DESCRIPTION("IP tables u32 matching module");
17694 +MODULE_LICENSE("GPL");
17697 +match(const struct sk_buff *skb,
17698 + const struct net_device *in,
17699 + const struct net_device *out,
17700 + const void *matchinfo,
17703 + u_int16_t datalen,
17706 + const struct ipt_u32 *data = matchinfo;
17708 + unsigned char* origbase = (char*)skb->nh.iph;
17709 + unsigned char* base = origbase;
17710 + unsigned char* head = skb->head;
17711 + unsigned char* end = skb->end;
17712 + int nnums, nvals;
17713 + u_int32_t pos, val;
17714 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
17715 + cycles1 = get_cycles(); */
17717 + for (testind=0; testind < data->ntests; testind++) {
17718 + base = origbase; /* reset for each test */
17719 + pos = data->tests[testind].location[0].number;
17720 + if (base+pos+3 > end || base+pos < head)
17722 + val = (base[pos]<<24) + (base[pos+1]<<16) +
17723 + (base[pos+2]<<8) + base[pos+3];
17724 + nnums = data->tests[testind].nnums;
17725 + for (i=1; i < nnums; i++) {
17726 + u_int32_t number = data->tests[testind].location[i].number;
17727 + switch (data->tests[testind].location[i].nextop) {
17728 + case IPT_U32_AND:
17729 + val = val & number;
17731 + case IPT_U32_LEFTSH:
17732 + val = val << number;
17734 + case IPT_U32_RIGHTSH:
17735 + val = val >> number;
17738 + base = base + val;
17740 + if (base+pos+3 > end || base+pos < head)
17742 + val = (base[pos]<<24) + (base[pos+1]<<16) +
17743 + (base[pos+2]<<8) + base[pos+3];
17747 + nvals = data->tests[testind].nvalues;
17748 + for (i=0; i < nvals; i++) {
17749 + if ((data->tests[testind].value[i].min <= val) &&
17750 + (val <= data->tests[testind].value[i].max)) {
17754 + if (i >= data->tests[testind].nvalues) {
17755 + /* cycles2 = get_cycles();
17756 + printk("failed %d in %d cycles\n", testind,
17757 + cycles2-cycles1); */
17761 + /* cycles2 = get_cycles();
17762 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
17767 +checkentry(const char *tablename,
17768 + const struct ipt_ip *ip,
17770 + unsigned int matchsize,
17771 + unsigned int hook_mask)
17773 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
17778 +static struct ipt_match u32_match
17779 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
17781 +static int __init init(void)
17783 + return ipt_register_match(&u32_match);
17786 +static void __exit fini(void)
17788 + ipt_unregister_match(&u32_match);
17791 +module_init(init);
17792 +module_exit(fini);
17793 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ULOG.c
17794 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ULOG.c 2003-11-26 21:43:34.000000000 +0100
17795 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ULOG.c 2003-12-11 10:23:14.923669232 +0100
17797 #include <linux/netlink.h>
17798 #include <linux/netdevice.h>
17799 #include <linux/mm.h>
17800 +#include <linux/netfilter.h>
17801 #include <linux/netfilter_ipv4/ip_tables.h>
17802 #include <linux/netfilter_ipv4/ipt_ULOG.h>
17803 #include <linux/netfilter_ipv4/lockhelp.h>
17805 MODULE_PARM(flushtimeout, "i");
17806 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
17808 +static unsigned int nflog = 1;
17809 +MODULE_PARM(nflog, "i");
17810 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
17812 /* global data structures */
17815 @@ -152,17 +157,17 @@
17819 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
17820 - const struct net_device *in,
17821 - const struct net_device *out,
17822 - unsigned int hooknum,
17823 - const void *targinfo, void *userinfo)
17824 +static void ipt_ulog_packet(unsigned int hooknum,
17825 + const struct sk_buff *skb,
17826 + const struct net_device *in,
17827 + const struct net_device *out,
17828 + const struct ipt_ulog_info *loginfo,
17829 + const char *prefix)
17832 ulog_packet_msg_t *pm;
17833 size_t size, copy_len;
17834 struct nlmsghdr *nlh;
17835 - struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
17837 /* ffs == find first bit set, necessary because userspace
17838 * is already shifting groupnumber, but we need unshifted.
17839 @@ -171,8 +176,8 @@
17841 /* calculate the size of the skb needed */
17842 if ((loginfo->copy_range == 0) ||
17843 - (loginfo->copy_range > (*pskb)->len)) {
17844 - copy_len = (*pskb)->len;
17845 + (loginfo->copy_range > skb->len)) {
17846 + copy_len = skb->len;
17848 copy_len = loginfo->copy_range;
17850 @@ -209,19 +214,21 @@
17852 /* copy hook, prefix, timestamp, payload, etc. */
17853 pm->data_len = copy_len;
17854 - pm->timestamp_sec = (*pskb)->stamp.tv_sec;
17855 - pm->timestamp_usec = (*pskb)->stamp.tv_usec;
17856 - pm->mark = (*pskb)->nfmark;
17857 + pm->timestamp_sec = skb->stamp.tv_sec;
17858 + pm->timestamp_usec = skb->stamp.tv_usec;
17859 + pm->mark = skb->nfmark;
17860 pm->hook = hooknum;
17861 - if (loginfo->prefix[0] != '\0')
17862 + if (prefix != NULL)
17863 + strncpy(pm->prefix, prefix, sizeof(pm->prefix));
17864 + else if (loginfo->prefix[0] != '\0')
17865 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
17867 *(pm->prefix) = '\0';
17869 if (in && in->hard_header_len > 0
17870 - && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
17871 + && skb->mac.raw != (void *) skb->nh.iph
17872 && in->hard_header_len <= ULOG_MAC_LEN) {
17873 - memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
17874 + memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
17875 pm->mac_len = in->hard_header_len;
17878 @@ -236,8 +243,8 @@
17880 pm->outdev_name[0] = '\0';
17882 - /* copy_len <= (*pskb)->len, so can't fail. */
17883 - if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
17884 + /* copy_len <= skb->len, so can't fail. */
17885 + if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
17888 /* check if we are building multi-part messages */
17889 @@ -261,8 +268,7 @@
17891 UNLOCK_BH(&ulog_lock);
17893 - return IPT_CONTINUE;
17898 PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
17899 @@ -271,8 +277,35 @@
17900 PRINTR("ipt_ULOG: Error building netlink message\n");
17902 UNLOCK_BH(&ulog_lock);
17905 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
17906 + const struct net_device *in,
17907 + const struct net_device *out,
17908 + unsigned int hooknum,
17909 + const void *targinfo, void *userinfo)
17911 + struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
17913 - return IPT_CONTINUE;
17914 + ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
17916 + return IPT_CONTINUE;
17919 +static void ipt_logfn(unsigned int hooknum,
17920 + const struct sk_buff *skb,
17921 + const struct net_device *in,
17922 + const struct net_device *out,
17923 + const char *prefix)
17925 + struct ipt_ulog_info loginfo = {
17926 + .nl_group = NFLOG_DEFAULT_NLGROUP,
17928 + .qthreshold = NFLOG_DEFAULT_QTHRESHOLD,
17932 + ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
17935 static int ipt_ulog_checkentry(const char *tablename,
17936 @@ -337,6 +370,9 @@
17941 + nf_log_register(PF_INET, &ipt_logfn);
17946 @@ -347,6 +383,9 @@
17948 DEBUGP("ipt_ULOG: cleanup_module\n");
17951 + nf_log_unregister(PF_INET, &ipt_logfn);
17953 ipt_unregister_target(&ipt_ulog_reg);
17954 sock_release(nflognl->sk_socket);
17956 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_XOR.c
17957 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
17958 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_XOR.c 2003-12-11 10:24:11.736032440 +0100
17960 +/* XOR target for IP tables
17961 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
17962 + * Based on ipt_TTL.c
17966 + * This software is distributed under the terms of GNU GPL
17969 +#include <linux/module.h>
17970 +#include <linux/skbuff.h>
17971 +#include <linux/ip.h>
17972 +#include <linux/tcp.h>
17973 +#include <linux/udp.h>
17975 +#include <linux/netfilter_ipv4/ip_tables.h>
17976 +#include <linux/netfilter_ipv4/ipt_XOR.h>
17978 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
17979 +MODULE_DESCRIPTION("IP tables XOR module");
17980 +MODULE_LICENSE("GPL");
17982 +static unsigned int ipt_xor_target(struct sk_buff **pskb, unsigned int hooknum,
17983 + const struct net_device *in, const struct net_device *out,
17984 + const void *targinfo, void *userinfo)
17986 + struct ipt_XOR_info *info = (void *) targinfo;
17987 + struct iphdr *iph = (*pskb)->nh.iph;
17988 + struct tcphdr *tcph;
17989 + struct udphdr *udph;
17992 + if (iph->protocol == IPPROTO_TCP) {
17993 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
17994 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
17995 + for (k=0; k<=info->block_size; k++) {
17996 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
18001 + if (info->key[j] == 0x00)
18004 + } else if (iph->protocol == IPPROTO_UDP) {
18005 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
18006 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
18007 + for (k=0; k<=info->block_size; k++) {
18008 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
18013 + if (info->key[j] == 0x00)
18018 + return IPT_CONTINUE;
18021 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
18022 + void *targinfo, unsigned int targinfosize,
18023 + unsigned int hook_mask)
18025 + struct ipt_XOR_info *info = targinfo;
18027 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
18028 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
18029 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
18033 + if (strcmp(tablename, "mangle")) {
18034 + printk(KERN_WARNING "XOR: can only be called from"
18035 + "\"mangle\" table, not \"%s\"\n", tablename);
18039 + if (!strcmp(info->key, "")) {
18040 + printk(KERN_WARNING "XOR: You must specify a key");
18044 + if (info->block_size == 0) {
18045 + printk(KERN_WARNING "XOR: You must specify a block-size");
18052 +static struct ipt_target ipt_XOR = { { NULL, NULL }, "XOR",
18053 + ipt_xor_target, ipt_xor_checkentry, NULL, THIS_MODULE };
18055 +static int __init init(void)
18057 + return ipt_register_target(&ipt_XOR);
18060 +static void __exit fini(void)
18062 + ipt_unregister_target(&ipt_XOR);
18065 +module_init(init);
18066 +module_exit(fini);
18067 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig linux-2.6.0-test11/net/ipv4/netfilter/Kconfig
18068 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig 2003-11-26 21:45:21.000000000 +0100
18069 +++ linux-2.6.0-test11/net/ipv4/netfilter/Kconfig 2003-12-11 12:57:13.875135120 +0100
18071 menu "IP: Netfilter Configuration"
18072 depends on INET && NETFILTER
18074 +config IP_NF_TARGET_XOR
18075 + tristate ' XOR target support'
18076 + depends on IP_NF_IPTABLES
18078 + XOR target support
18079 + CONFIG_IP_NF_TARGET_XOR
18080 + This option adds a `XOR' target, which can encrypt TCP and
18081 + UDP traffic using a simple XOR encryption.
18083 + If you want to compile it as a module, say M here and read
18084 + Documentation/modules.txt. If unsure, say `N'.
18088 +config IP_NF_TARGET_TCPLAG
18089 + tristate ' TCPLAG target support'
18090 + depends on IP_NF_IPTABLES
18092 + TCPLAG target support
18093 + CONFIG_IP_NF_TARGET_TCPLAG
18094 + This option adds a `TCPLAG' target, intended for INPUT, OUTPUT and
18097 + This target has no effect on packets but will passively monitor TCP/IP
18098 + connections and send lag estimates to syslog. Lag estimates are
18099 + generated by considering the time delay between SEQ and matching ACK,
18100 + which does not map precisely to any particular network property.
18101 + We can say that a fast network will typically give smaller lag values
18102 + than a slow network.
18104 + Safest option is to choose `M' here and compile as a module,
18105 + the module will do nothing until activated using the `iptables' utility.
18111 + tristate ' talk protocol support'
18112 + depends on IP_NF_CONNTRACK
18114 + Talk protocol support
18115 + CONFIG_IP_NF_TALK
18116 + The talk protocols (both otalk/talk - or talk/ntalk, to confuse
18117 + you by the different namings about which is old or which is new :-)
18118 + use an additional channel to setup the talk session and a separated
18119 + data channel for the actual conversation (like in FTP). Both the
18120 + initiating and the setup channels are over UDP, while the data channel
18121 + is over TCP, on a random port. The conntrack part of this extension
18122 + will enable you to let in/out talk sessions easily by matching these
18123 + connections as RELATED by the state match, while the NAT part helps
18124 + you to let talk sessions trough a NAT machine.
18126 + If you want to compile it as a module, say 'M' here and read
18127 + Documentation/modules.txt. If unsure, say 'N'.
18132 + tristate ' RTSP protocol support'
18133 + depends on IP_NF_CONNTRACK
18135 + RTSP protocol support
18136 + CONFIG_IP_NF_RTSP
18137 + Support the RTSP protocol. This allows UDP transports to be setup
18138 + properly, including RTP and RDT.
18140 + If you want to compile it as a module, say 'M' here and read
18141 + Documentation/modules.txt. If unsure, say 'Y'.
18147 + tristate ' RSH protocol support'
18148 + depends on IP_NF_CONNTRACK
18150 + RSH protocol support
18152 + The RSH connection tracker is required if the dynamic
18153 + stderr "Server to Client" connection is to occur during a
18154 + normal RSH session. This typically operates as follows;
18156 + Client 0:1023 --> Server 514 (stream 1 - stdin/stdout)
18157 + Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
18159 + This connection tracker will identify new RSH sessions,
18160 + extract the outbound session details, and notify netfilter
18161 + of pending "related" sessions.
18163 + Warning: This module could be dangerous. It is not "best
18164 + practice" to use RSH, use SSH in all instances.
18165 + (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
18168 + If you want to compile it as a module, say M here and read
18169 + <file:Documentation/modules.txt>. If unsure, say `N'.
18173 +config IP_NF_MATCH_RPC
18174 + tristate ' RPC match support'
18175 + depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
18177 + RPC match support
18178 + CONFIG_IP_NF_MATCH_RPC
18179 + This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
18180 + matcher and tracker.
18182 + This option supplies two connection tracking modules;
18183 + ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
18184 + portmapper requests using UDP and TCP respectively.
18186 + This option also adds an RPC match module for iptables, which
18187 + matches both via the old "record match" method and a new
18188 + "procedure match" method. The older method matches all RPC
18189 + procedure packets that relate to previously recorded packets
18190 + seen querying a portmapper. The newer method matches only
18191 + those RPC procedure packets explicitly specified by the user,
18192 + and that can then be related to previously recorded packets
18193 + seen querying a portmapper.
18195 + These three modules are required if RPCs are to be filtered
18196 + accurately; as RPCs are allocated pseudo-randomly to UDP and
18197 + TCP ports as they register with the portmapper.
18199 + Up to 8 portmapper ports per module, and up to 128 RPC
18200 + procedures per iptables rule, may be specified by the user,
18201 + to enable effective RPC management.
18204 + If you want to compile it as a module, say M here and read
18205 + <file:Documentation/modules.txt>. If unsure, say `N'.
18209 +config IP_NF_QUAKE3
18210 + tristate ' Quake III protocol support'
18211 + depends on IP_NF_CONNTRACK
18213 + Quake III Arena protocol support
18214 + CONFIG_IP_NF_QUAKE3
18215 + Quake III Arena connection tracking helper. This module allows for a
18216 + stricter firewall rulebase if one only allows traffic to a master
18217 + server. Connections to Quake III server IP addresses and ports returned
18218 + by the master server will be tracked automatically.
18220 + If you want to compile it as a module, say M here and read
18221 + <file:Documentation/modules.txt>. If unsure, say `Y'.
18225 +config IP_NF_CT_PROTO_GRE
18226 + tristate ' GRE protocol support'
18227 + depends on IP_NF_CONNTRACK
18229 + tristate ' PPTP protocol support'
18230 + depends on IP_NF_CT_PROTO_GRE
18232 + PPTP conntrack and NAT support
18233 + CONFIG_IP_NF_PPTP
18234 + This module adds support for PPTP (Point to Point Tunnelling Protocol,
18235 + RFC2637) conncection tracking and NAT.
18237 + If you are running PPTP sessions over a stateful firewall or NAT box,
18238 + you may want to enable this feature.
18240 + Please note that not all PPTP modes of operation are supported yet.
18241 + For more info, read top of the file net/ipv4/netfilter/ip_conntrack_pptp.c
18243 + If you want to compile it as a module, say M here and read
18244 + Documentation/modules.txt. If unsure, say `N'.
18246 + GRE protocol conntrack and NAT support
18247 + CONFIG_IP_NF_CT_PROTO_GRE
18248 + This module adds generic support for connection tracking and NAT of the
18249 + GRE protocol (RFC1701, RFC2784). Please note that this will only work
18250 + with GRE connections using the key field of the GRE header.
18252 + You will need GRE support to enable PPTP support.
18254 + If you want to compile it as a module, say `M' here and read
18255 + Documentation/modules.txt. If unsire, say `N'.
18260 + tristate ' MMS protocol support'
18261 + depends on IP_NF_CONNTRACK
18263 + MMS protocol support
18265 + Tracking MMS (Microsoft Windows Media Services) connections
18266 + could be problematic if random ports are used to send the
18267 + streaming content. This option allows users to track streaming
18268 + connections over random UDP or TCP ports.
18270 + If you want to compile it as a module, say M here and read
18271 + <file:Documentation/modules.txt>. If unsure, say `Y'.
18275 +config IP_NF_TARGET_IPMARK
18276 + tristate ' IPMARK target support'
18277 + depends on IP_NF_MANGLE
18279 + IPMARK target support
18280 + CONFIG_IP_NF_TARGET_IPMARK
18281 + This option adds a `IPMARK' target, which allows you to create rules
18282 + in the `mangle' table which alter the netfilter mark (nfmark) field
18283 + basing on the source or destination ip address of the packet.
18284 + This is very useful for very fast massive mangling and marking.
18286 + If you want to compile it as a module, say M here and read
18287 + <file:Documentation/modules.txt>. If unsure, say `N'.
18294 + tristate ' H.323 (netmeeting) support'
18295 + depends on IP_NF_CONNTRACK
18297 + H.323 (netmeeting) support
18298 + CONFIG_IP_NF_H323
18299 + H.323 is a standard signalling protocol used by teleconferencing
18300 + softwares like netmeeting. With the ip_conntrack_h323 and
18301 + the ip_nat_h323 modules you can support the protocol on a connection
18302 + tracking/NATing firewall.
18304 + If you want to compile it as a module, say 'M' here and read
18305 + Documentation/modules.txt. If unsure, say 'N'.
18310 + tristate ' Eggdrop bot support'
18311 + depends on IP_NF_CONNTRACK
18313 + Eggdrop bot support
18315 + If you are running an eggdrop hub bot on this machine, then you
18316 + may want to enable this feature. This enables eggdrop bots to share
18317 + their user file to other eggdrop bots.
18319 + If you want to compile it as a module, say M here and read
18320 + Documentation/modules.txt. If unsure, say `N'.
18324 +config IP_NF_CUSEEME
18325 + tristate ' CuSeeMe protocol support'
18326 + depends on IP_NF_CONNTRACK
18328 + CuSeeMe protocol support
18329 + CONFIG_IP_NF_CUSEEME
18330 + The CuSeeMe conferencing protocol is problematic when used in
18331 + conjunction with NAT; even though there are no random ports used for
18332 + extra connections, the messages contain IP addresses inside them.
18333 + This NAT helper mangles the IP address inside packets so both
18334 + parties don't get confused.
18336 + If you want to compile it as a module, say M here and read
18337 + <file:Documentation/modules.txt>. If unsure, say `Y'.
18343 +config IP_NF_CONNTRACK_MARK
18344 + bool ' Connection mark tracking support'
18345 +config IP_NF_TARGET_CONNMARK
18346 + tristate ' CONNMARK target support'
18347 + depends on IP_NF_IPTABLES
18348 +config IP_NF_MATCH_CONNMARK
18349 + tristate ' Connection mark match support'
18350 + depends on IP_NF_IPTABLES
18352 + Per connection mark support
18353 + CONFIG_IP_NF_CONNTRACK_MARK
18354 + This option enables support for connection marks, used by the
18355 + `CONNMARK' target and `connmark' match. Similar to the mark value
18356 + of packets, but this mark value is kept in the conntrack session
18357 + instead of the individual packets.
18359 + CONNMARK target support
18360 + CONFIG_IP_NF_TARGET_CONNMARK
18361 + This option adds a `CONNMARK' target, which allows one to manipulate
18362 + the connection mark value. Similar to the MARK target, but
18363 + affects the connection mark value rather than the packet mark value.
18365 + If you want to compile it as a module, say M here and read
18366 + Documentation/modules.txt. The module will be called
18367 + ipt_CONNMARK.o. If unsure, say `N'.
18369 + connmark match support
18370 + CONFIP_IP_NF_MATCH_CONNMARK
18371 + This option adds a `connmark' match, which allows you to match the
18372 + connection mark value previously set for the session by `CONNMARK'.
18376 +config IP_NF_MATCH_CONDITION
18377 + tristate ' condition match support'
18378 + depends on IP_NF_IPTABLES
18380 + Condition variable match support
18381 + CONFIG_IP_NF_MATCH_CONDITION
18382 + This option allows you to match firewall rules against condition
18383 + variables stored in the /proc/net/ipt_condition directory.
18385 + If you want to compile it as a module, say M here and read
18386 + Documentation/modules.txt. If unsure, say `N'.
18390 +config IP_NF_MATCH_ADDRTYPE
18391 + tristate ' address type match support'
18392 + depends on IP_NF_IPTABLES
18394 + addrtype match support
18395 + CONFIG_IP_NF_MATCH_ADDRTYPE
18396 + This option allows you to match what routing thinks of an address,
18397 + eg. UNICAST, LOCAL, BROADCAST, ...
18399 + If you want to compile it as a module, say M here and read
18400 + Documentation/modules.txt. If unsure, say `N'.
18404 +config IP_NF_MATCH_U32
18405 + tristate ' U32 match support'
18406 + depends on IP_NF_U32
18408 + U32 patch support
18409 + CONFIG_IP_NF_MATCH_U32
18410 + U32 allows you to extract quantities of up to 4 bytes from a packet,
18411 + AND them with specified masks, shift them by specified amounts and
18412 + test whether the results are in any of a set of specified ranges.
18413 + The specification of what to extract is general enough to skip over
18414 + headers with lengths stored in the packet, as in IP or TCP header
18417 + Details and examples are in the kernel module source.
18422 +config IP_NF_TARGET_TTL
18423 + tristate ' TTL target support'
18424 + depends on IP_NF_IPTABLES
18426 + TTL target support
18427 + CONFIG_IP_NF_TARGET_TTL
18428 + This option adds a `TTL' target, which enables the user to set
18429 + the TTL value or increment / decrement the TTL value by a given
18432 + If you want to compile it as a module, say M here and read
18433 + Documentation/modules.txt. If unsure, say `N'.
18437 +config IP_NF_MATCH_TIME
18438 + tristate ' TIME match support (EXPERIMENTAL)'
18439 + depends on IP_NF_IPTABLES
18441 + TIME patch support
18442 + CONFIG_IP_NF_MATCH_TIME
18443 + This option adds a `time' match, which allows you
18444 + to matchbased on the packet arrival time
18445 + (arrival time at the machine which the netfilter is running on) or
18446 + departure time (for locally generated packets).
18448 + If you say Y here, try iptables -m time --help for more information.
18450 + If you want to compile it as a module, say M here and read
18451 + Documentation/modules.txt. If unsure, say `N'.
18456 +config IP_NF_MATCH_REALM
18457 + tristate ' realm match support'
18458 + depends on IP_NF_IPTABLES
18460 + REALM match support
18461 + CONFIG_IP_NF_MATCH_REALM
18462 + This option adds a `realm' match, which allows you to use the realm
18463 + key from the routing subsytem inside iptables.
18465 + This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
18468 + If you want to compile it as a module, say M here and read
18469 + Documentation/modules.txt. If unsure, say `N'.
18474 +config IP_NF_MATCH_RANDOM
18475 + tristate ' random match support'
18476 + depends on IP_NF_IPTABLES
18478 + Random match support
18479 + CONFIG_IP_NF_MATCH_RANDOM
18480 + This option adds a `random' match,
18481 + which allow you to match packets randomly
18482 + following a given probability.
18484 + If you want to compile it as a module, say M here and read
18485 + Documentation/modules.txt. If unsure, say `N'.
18490 +config IP_NF_MATCH_QUOTA
18491 + tristate ' quota match support'
18492 + depends on IP_NF_IPTABLES
18494 + quota match support
18495 + CONFIG_IP_NF_MATCH_QUOTA
18496 + This match implements network quotas.
18498 + If you want to compile it as a module, say M here and read
18499 + Documentation/modules.txt. If unsure, say `N'.
18504 +config IP_NF_MATCH_PSD
18505 + tristate ' psd match support'
18506 + depends on IP_NF_IPTABLES
18508 + psd match support
18509 + CONFIG_IP_NF_MATCH_PSD
18510 + This option adds a `psd' match, which allows you to create rules in
18511 + any iptables table wich will detect TCP and UDP port scans.
18513 + If you want to compile it as a module, say M here and read
18514 + Documentation/modules.txt. If unsure, say `N'.
18520 + tristate ' IP address pool support'
18521 + depends on IP_NF_IPTABLES
18522 +config IP_POOL_STATISTICS
18523 + bool ' enable statistics on pool usage'
18525 + pool match and target support
18526 + CONFIG_IP_NF_MATCH_POOL
18527 + Pool matching lets you use bitmaps with one bit per address from some
18528 + range of IP addresses; the match depends on whether a checked source
18529 + or destination address has its bit set in the pool.
18531 + There is also a POOL netfilter target, which can be used to set or remove
18532 + the addresses of a packet from a pool.
18534 + To define and use pools, you need userlevel utilities: a patched iptables,
18535 + and the program ippool(8), which defines the pools and their bounds.
18536 + The current release of pool matching is ippool-0.0.2, and can be found
18537 + in the archives of the netfilter mailing list at
18538 + http://lists.samba.org/netfilter/.
18540 + If you want to compile it as a module, say M here and read
18541 + Documentation/modules.txt. If unsure, say `N'.
18543 + pool match and target statistics gathering
18544 + CONFIG_IP_POOL_STATISTICS
18545 + This option controls whether usage gathering code is compiled into the
18546 + ip_pool module. Disabling statistics may be substantially faster.
18550 +config IP_NF_MATCH_OSF
18551 + tristate ' OSF match support (EXPERIMENTAL)'
18552 + depends on IP_NF_IPTABLES
18554 + OSF match support
18555 + CONFIG_IP_NF_MATCH_OSF
18557 + The idea of passive OS fingerprint matching exists for quite a long time,
18558 + but was created as extension fo OpenBSD pf only some weeks ago.
18559 + Original idea was lurked in some OpenBSD mailing list (thanks
18560 + grange@open...) and than adopted for Linux netfilter in form of this code.
18562 + Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
18563 + his excellent p0f and than changed a bit for more convenience.
18565 + This module compares some data(WS, MSS, options and it's order, ttl,
18566 + df and others) from first SYN packet (actually from packets with SYN
18567 + bit set) with hardcoded in fingers[] table ones.
18569 + If you say Y here, try iptables -m osf --help for more information.
18571 + If you want to compile it as a module, say M here and read
18572 + Documentation/modules.txt. If unsure, say `N'.
18576 +config IP_NF_MATCH_NTH
18577 + tristate ' Nth match support'
18578 + depends on IP_NF_IPTABLES
18580 + Nth match support
18581 + CONFIG_IP_NF_MATCH_NTH
18582 + This option adds a `Nth' match, which allow you to make
18583 + rules that match every Nth packet. By default there are
18584 + 16 different counters.
18587 + --every Nth Match every Nth packet
18588 + [--counter] num Use counter 0-15 (default:0)
18589 + [--start] num Initialize the counter at the number 'num'
18590 + instead of 0. Must be between 0 and Nth-1
18591 + [--packet] num Match on 'num' packet. Must be between 0
18594 + If --packet is used for a counter than
18595 + there must be Nth number of --packet
18596 + rules, covering all values between 0 and
18597 + Nth-1 inclusively.
18599 + If you want to compile it as a module, say M here and read
18600 + Documentation/modules.txt. If unsure, say `N'.
18605 +config IP_NF_MATCH_MPORT
18606 + tristate ' Multiple port with ranges match support'
18607 + depends on IP_NF_IPTABLES
18609 + Multiple port with ranges match support
18610 + CONFIG_IP_NF_MATCH_MPORT
18611 + This is an enhanced multiport match which supports port
18612 + ranges as well as single ports.
18614 + If you want to compile it as a module, say M here and read
18615 + Documentation/modules.txt. If unsure, say `N'.
18619 +config IP_NF_TARGET_IPV4OPTSSTRIP
18620 + tristate ' IPV4OPTSSTRIP target support'
18621 + depends on IP_NF_FILTER
18623 + IPV4OPTSSTRIP target support
18624 + CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP
18625 + This option adds an IPV4OPTSSTRIP target.
18626 + This target allows you to strip all IP options in a packet.
18628 + If you want to compile it as a module, say M here and read
18629 + Documentation/modules.txt. If unsure, say `N'.
18634 +config IP_NF_MATCH_IPV4OPTIONS
18635 + tristate ' IPV4OPTIONS match support (EXPERIMENTAL)'
18636 + depends on IP_NF_IPTABLES
18638 + IPV4OPTIONS patch support
18639 + CONFIG_IP_NF_MATCH_IPV4OPTIONS
18640 + This option adds a IPV4OPTIONS match.
18641 + It allows you to filter options like source routing,
18642 + record route, timestamp and router-altert.
18644 + If you say Y here, try iptables -m ipv4options --help for more information.
18646 + If you want to compile it as a module, say M here and read
18647 + Documentation/modules.txt. If unsure, say `N'.
18652 +config IP_NF_MATCH_FUZZY
18653 + tristate ' fuzzy match support'
18654 + depends on IP_NF_IPTABLES
18656 + Fuzzy Logic Controller match support
18657 + CONFIG_IP_NF_MATCH_FUZZY
18658 + This option adds a `fuzzy' match,
18659 + which allows you to match packets according to a fuzzy logic
18662 + If you want to compile it as a module, say M here and read
18663 + Documentation/modules.txt. If unsure, say `N'.
18668 +config IP_NF_MATCH_DSTLIMIT
18669 + tristate ' dstlimit match support'
18670 + depends on IP_NF_IPTABLES
18674 +config IP_NF_MATCH_CONNLIMIT
18675 + tristate ' Connections/IP limit match support'
18676 + depends on IP_NF_IPTABLES
18678 + Connections/IP limit match support
18679 + CONFIG_IP_NF_MATCH_CONNLIMIT
18680 + This match allows you to restrict the number of parallel TCP
18681 + connections to a server per client IP address (or address block).
18683 + If you want to compile it as a module, say M here and read
18684 + Documentation/modules.txt. If unsure, say `N'.
18688 config IP_NF_CONNTRACK
18689 tristate "Connection tracking (required for masq/NAT)"
18691 @@ -197,6 +811,15 @@
18693 To compile it as a module, choose M here. If unsure, say N.
18695 +config IP_NF_MATCH_SCTP
18696 + tristate "SCTP match support"
18697 + depends on IP_NF_IPTABLES
18699 + This match allows iptables to match on the SCTP header.
18701 + If you want to compile it as a module, say M here and read
18702 + <file:Documentation/modules.txt>. If unsure, say `N'.
18704 config IP_NF_MATCH_LENGTH
18705 tristate "LENGTH match support"
18706 depends on IP_NF_IPTABLES
18707 @@ -527,6 +1150,42 @@
18709 To compile it as a module, choose M here. If unsure, say N.
18712 + tristate "Raw table"
18713 + depends on IP_NF_IPTABLES
18715 + This option adds a `raw' table to iptables: see the man page for
18716 + iptables(8). This table is the very first in the netfilter
18717 + framework and hooks in at the PREROUTING and OUTPUT chains.
18718 + The TRACE and NOTRACK targets can be used in this table only.
18720 + To compile it as a module, choose M here. If unsure, say N.
18722 +config IP_NF_TARGET_TRACE
18723 + tristate "TRACE target support"
18724 + depends on IP_NF_RAW
18726 + The TRACE target allows packets to be traced as those matches
18727 + any subsequent rule in any table/rule. The matched rule and
18728 + the packet is logged with the prefix
18730 + TRACE: tablename/chainname/rulenum
18732 + if the ipt_LOG or ipt_ULOG targets are loaded in.
18734 + To compile it as a module, choose M here. If unsure, say N.
18736 +config IP_NF_TARGET_NOTRACK
18737 + tristate "NOTRACK target support"
18738 + depends on IP_NF_RAW
18740 + The NOTRACK target allows a select rule to specify which
18741 + packets *not* to enter the conntrack/NAT subsystems
18742 + with all the consequences (no ICMP error tracking,
18743 + no protocol helpers for the selected packets).
18745 + To compile it as a module, choose M here. If unsure, say N.
18747 config IP_NF_ARPTABLES
18748 tristate "ARP tables support"
18750 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile linux-2.6.0-test11/net/ipv4/netfilter/Makefile
18751 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile 2003-11-26 21:43:25.000000000 +0100
18752 +++ linux-2.6.0-test11/net/ipv4/netfilter/Makefile 2003-12-11 12:56:51.470541136 +0100
18753 @@ -19,37 +19,91 @@
18754 # connection tracking
18755 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
18757 +# talk protocol support
18758 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
18759 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
18763 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
18764 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
18767 # connection tracking helpers
18769 +# rtsp protocol support
18770 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
18771 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
18773 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
18774 +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
18775 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
18776 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
18777 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
18778 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
18779 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
18781 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
18783 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
18786 +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
18787 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
18788 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
18789 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
18790 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
18791 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
18792 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
18793 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
18795 # generic IP tables
18796 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
18798 -# the three instances of ip_tables
18799 +# the four instances of ip_tables
18800 obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
18801 obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
18802 obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
18803 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
18806 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
18808 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
18809 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
18810 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
18811 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
18812 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
18813 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
18814 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
18815 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
18816 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
18818 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
18819 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
18821 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
18823 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
18824 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
18825 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
18827 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
18830 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
18832 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
18834 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
18837 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
18839 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
18842 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
18844 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
18846 @@ -59,10 +113,17 @@
18848 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
18850 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
18853 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
18854 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
18855 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
18856 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
18857 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
18858 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
18859 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
18860 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
18862 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
18865 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
18866 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
18867 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
18868 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
18869 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
18870 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
18871 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
18872 @@ -79,8 +141,16 @@
18873 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
18874 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
18875 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
18876 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
18877 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
18878 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
18879 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
18881 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
18882 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
18883 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
18884 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
18885 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
18887 # generic ARP tables
18888 obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
18889 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.0-test11/net/ipv6/netfilter/ip6table_filter.c
18890 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_filter.c 2003-11-26 21:42:56.000000000 +0100
18891 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_filter.c 2003-12-11 10:23:17.233318112 +0100
18894 sizeof(struct ip6t_entry),
18895 sizeof(struct ip6t_standard),
18896 - 0, { 0, 0 }, { } },
18897 + 0, NULL, 0, { 0, 0 }, { } },
18898 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18899 -NF_ACCEPT - 1 } },
18903 sizeof(struct ip6t_entry),
18904 sizeof(struct ip6t_standard),
18905 - 0, { 0, 0 }, { } },
18906 + 0, NULL, 0, { 0, 0 }, { } },
18907 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18908 -NF_ACCEPT - 1 } },
18912 sizeof(struct ip6t_entry),
18913 sizeof(struct ip6t_standard),
18914 - 0, { 0, 0 }, { } },
18915 + 0, NULL, 0, { 0, 0 }, { } },
18916 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18921 sizeof(struct ip6t_entry),
18922 sizeof(struct ip6t_error),
18923 - 0, { 0, 0 }, { } },
18924 + 0, NULL, 0, { 0, 0 }, { } },
18925 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18928 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.0-test11/net/ipv6/netfilter/ip6table_mangle.c
18929 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_mangle.c 2003-11-26 21:43:36.000000000 +0100
18930 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_mangle.c 2003-12-11 10:23:17.234317960 +0100
18933 sizeof(struct ip6t_entry),
18934 sizeof(struct ip6t_standard),
18935 - 0, { 0, 0 }, { } },
18936 + 0, NULL, 0, { 0, 0 }, { } },
18937 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18938 -NF_ACCEPT - 1 } },
18942 sizeof(struct ip6t_entry),
18943 sizeof(struct ip6t_standard),
18944 - 0, { 0, 0 }, { } },
18945 + 0, NULL, 0, { 0, 0 }, { } },
18946 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18947 -NF_ACCEPT - 1 } },
18951 sizeof(struct ip6t_entry),
18952 sizeof(struct ip6t_standard),
18953 - 0, { 0, 0 }, { } },
18954 + 0, NULL, 0, { 0, 0 }, { } },
18955 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18956 -NF_ACCEPT - 1 } },
18960 sizeof(struct ip6t_entry),
18961 sizeof(struct ip6t_standard),
18962 - 0, { 0, 0 }, { } },
18963 + 0, NULL, 0, { 0, 0 }, { } },
18964 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18965 -NF_ACCEPT - 1 } },
18969 sizeof(struct ip6t_entry),
18970 sizeof(struct ip6t_standard),
18971 - 0, { 0, 0 }, { } },
18972 + 0, NULL, 0, { 0, 0 }, { } },
18973 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18976 @@ -107,7 +107,7 @@
18978 sizeof(struct ip6t_entry),
18979 sizeof(struct ip6t_error),
18980 - 0, { 0, 0 }, { } },
18981 + 0, NULL, 0, { 0, 0 }, { } },
18982 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18985 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.0-test11/net/ipv6/netfilter/ip6table_raw.c
18986 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_raw.c 1970-01-01 01:00:00.000000000 +0100
18987 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_raw.c 2003-12-11 10:23:17.234317960 +0100
18990 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
18992 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
18994 +#include <linux/module.h>
18995 +#include <linux/netfilter_ipv6/ip6_tables.h>
18997 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
19000 +#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
19002 +#define DEBUGP(x, args...)
19005 +/* Standard entry. */
19006 +struct ip6t_standard
19008 + struct ip6t_entry entry;
19009 + struct ip6t_standard_target target;
19012 +struct ip6t_error_target
19014 + struct ip6t_entry_target target;
19015 + char errorname[IP6T_FUNCTION_MAXNAMELEN];
19020 + struct ip6t_entry entry;
19021 + struct ip6t_error_target target;
19026 + struct ip6t_replace repl;
19027 + struct ip6t_standard entries[2];
19028 + struct ip6t_error term;
19029 +} initial_table __initdata
19030 += { { "raw", RAW_VALID_HOOKS, 3,
19031 + sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
19032 + { [NF_IP6_PRE_ROUTING] 0,
19033 + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
19034 + { [NF_IP6_PRE_ROUTING] 0,
19035 + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
19038 + /* PRE_ROUTING */
19039 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19041 + sizeof(struct ip6t_entry),
19042 + sizeof(struct ip6t_standard),
19043 + 0, NULL, 0, { 0, 0 }, { } },
19044 + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19045 + -NF_ACCEPT - 1 } },
19047 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19049 + sizeof(struct ip6t_entry),
19050 + sizeof(struct ip6t_standard),
19051 + 0, NULL, 0, { 0, 0 }, { } },
19052 + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19053 + -NF_ACCEPT - 1 } },
19056 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19058 + sizeof(struct ip6t_entry),
19059 + sizeof(struct ip6t_error),
19060 + 0, NULL, 0, { 0, 0 }, { } },
19061 + { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19068 +static struct ip6t_table packet_raw = {
19070 + .table = &initial_table.repl,
19071 + .valid_hooks = RAW_VALID_HOOKS,
19072 + .lock = RW_LOCK_UNLOCKED,
19073 + .me = THIS_MODULE
19076 +/* The work comes in here from netfilter.c. */
19077 +static unsigned int
19078 +ip6t_hook(unsigned int hook,
19079 + struct sk_buff **pskb,
19080 + const struct net_device *in,
19081 + const struct net_device *out,
19082 + int (*okfn)(struct sk_buff *))
19084 + return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
19087 +static struct nf_hook_ops ip6t_ops[] = {
19088 + { /* PRE_ROUTING */
19089 + .hook = ip6t_hook,
19090 + .owner = THIS_MODULE,
19092 + .hooknum = NF_IP6_PRE_ROUTING,
19093 + .priority = NF_IP6_PRI_FIRST,
19095 + { /* LOCAL_OUT */
19096 + .hook = ip6t_hook,
19097 + .owner = THIS_MODULE,
19099 + .hooknum = NF_IP6_LOCAL_OUT,
19100 + .priority = NF_IP6_PRI_FIRST,
19104 +static int __init init(void)
19108 + /* Register table */
19109 + ret = ip6t_register_table(&packet_raw);
19113 + /* Register hooks */
19114 + ret = nf_register_hook(&ip6t_ops[0]);
19116 + goto cleanup_table;
19118 + ret = nf_register_hook(&ip6t_ops[1]);
19120 + goto cleanup_hook0;
19125 + nf_unregister_hook(&ip6t_ops[0]);
19127 + ip6t_unregister_table(&packet_raw);
19132 +static void __exit fini(void)
19136 + for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
19137 + nf_unregister_hook(&ip6t_ops[i]);
19139 + ip6t_unregister_table(&packet_raw);
19142 +module_init(init);
19143 +module_exit(fini);
19144 +MODULE_LICENSE("GPL");
19145 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19146 +MODULE_DESCRIPTION("IPv6 raw table");
19147 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.0-test11/net/ipv6/netfilter/ip6_tables.c
19148 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6_tables.c 2003-11-26 21:45:30.000000000 +0100
19149 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6_tables.c 2003-12-11 10:23:17.233318112 +0100
19152 #include <linux/config.h>
19153 #include <linux/skbuff.h>
19154 +#include <linux/socket.h>
19155 #include <linux/kmod.h>
19156 #include <linux/vmalloc.h>
19157 #include <linux/netdevice.h>
19159 #include <asm/semaphore.h>
19160 #include <linux/proc_fs.h>
19162 +#include <linux/netfilter.h>
19163 #include <linux/netfilter_ipv6/ip6_tables.h>
19165 +static const char *hook6names[] = {
19166 + [NF_IP6_PRE_ROUTING] "PREROUTING",
19167 + [NF_IP6_LOCAL_IN] "INPUT",
19168 + [NF_IP6_FORWARD] "FORWARD",
19169 + [NF_IP6_LOCAL_OUT] "OUTPUT",
19170 + [NF_IP6_POST_ROUTING] "POSTROUTING",
19173 MODULE_LICENSE("GPL");
19174 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19175 MODULE_DESCRIPTION("IPv6 packet filter");
19176 @@ -403,6 +413,12 @@
19178 t = ip6t_get_target(e);
19179 IP_NF_ASSERT(t->u.kernel.target);
19181 + /* The packet traced and the rule isn't an unconditional return/END. */
19182 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
19183 + nf_log_packet(AF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
19184 + table->name, e->chainname, e->rulenum);
19186 /* Standard target? */
19187 if (!t->u.kernel.target->target) {
19189 @@ -556,6 +572,29 @@
19190 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
19194 +find_error_target(struct ip6t_entry *s,
19195 + struct ip6t_entry *e,
19196 + char **chainname)
19198 + struct ip6t_entry_target *t;
19199 + static struct ip6t_entry *found = NULL;
19204 + t = ip6t_get_target(found);
19205 + if (strcmp(t->u.user.name,
19206 + IP6T_ERROR_TARGET) == 0) {
19207 + *chainname = t->data;
19216 /* All zeroes == unconditional rule. */
19218 unconditional(const struct ip6t_ip6 *ipv6)
19219 @@ -575,6 +614,8 @@
19220 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
19223 + char *chainname = NULL;
19224 + u_int32_t rulenum;
19226 /* No recursion; use packet counter to save back ptrs (reset
19227 to 0 as we leave), and comefrom to save source hook bitmask */
19228 @@ -588,6 +629,8 @@
19230 /* Set initial back pointer. */
19231 e->counters.pcnt = pos;
19233 + chainname = (char *) hook6names[hook];
19236 struct ip6t_standard_target *t
19237 @@ -600,6 +643,8 @@
19240 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
19241 + e->rulenum = rulenum++;
19242 + e->chainname = chainname;
19244 /* Unconditional return/END. */
19245 if (e->target_offset == sizeof(struct ip6t_entry)
19246 @@ -609,6 +654,10 @@
19247 && unconditional(&e->ipv6)) {
19248 unsigned int oldpos, size;
19250 + /* Set unconditional rulenum to zero. */
19252 + e->counters.bcnt = 0;
19254 /* Return: backtrack through the last
19257 @@ -634,6 +683,11 @@
19258 (newinfo->entries + pos);
19259 } while (oldpos == pos + e->next_offset);
19261 + /* Restore chainname, rulenum. */
19262 + chainname = e->chainname;
19263 + rulenum = e->counters.bcnt;
19264 + e->counters.bcnt = 0;
19266 /* Move along one */
19267 size = e->next_offset;
19268 e = (struct ip6t_entry *)
19269 @@ -649,6 +703,17 @@
19270 /* This a jump; chase it. */
19271 duprintf("Jump rule %u -> %u\n",
19273 + e->counters.bcnt = rulenum++;
19275 + e = (struct ip6t_entry *)
19276 + (newinfo->entries + newpos);
19277 + if (IP6T_ENTRY_ITERATE(newinfo->entries,
19279 + find_error_target,
19280 + e, &chainname) == 0) {
19281 + printk("ip6_tables: table screwed up!\n");
19285 /* ... this is a fallthru */
19286 newpos = pos + e->next_offset;
19287 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_condition.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_condition.c
19288 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_condition.c 1970-01-01 01:00:00.000000000 +0100
19289 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_condition.c 2003-12-11 10:23:45.446029128 +0100
19291 +/*-------------------------------------------*\
19292 +| Netfilter Condition Module for IPv6 |
19294 +| Description: This module allows firewall |
19295 +| rules to match using condition variables |
19296 +| stored in /proc files. |
19298 +| Author: Stephane Ouellette 2003-02-10 |
19299 +| <ouellettes@videotron.ca> |
19301 +| This software is distributed under the |
19302 +| terms of the GNU GPL. |
19303 +\*-------------------------------------------*/
19305 +#include<linux/module.h>
19306 +#include<linux/proc_fs.h>
19307 +#include<linux/spinlock.h>
19308 +#include<linux/string.h>
19309 +#include<asm/atomic.h>
19310 +#include<linux/netfilter_ipv6/ip6_tables.h>
19311 +#include<linux/netfilter_ipv6/ip6t_condition.h>
19314 +#ifndef CONFIG_PROC_FS
19315 +#error "Proc file system support is required for this module"
19319 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
19320 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
19321 +MODULE_LICENSE("GPL");
19324 +struct condition_variable {
19325 + struct condition_variable *next;
19326 + struct proc_dir_entry *status_proc;
19327 + atomic_t refcount;
19328 + int enabled; /* TRUE == 1, FALSE == 0 */
19332 +static rwlock_t list_lock;
19333 +static struct condition_variable *head = NULL;
19334 +static struct proc_dir_entry *proc_net_condition = NULL;
19338 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
19339 + int length, int *eof, void *data)
19341 + struct condition_variable *var =
19342 + (struct condition_variable *) data;
19344 + if (offset == 0) {
19346 + buffer[0] = (var->enabled) ? '1' : '0';
19347 + buffer[1] = '\n';
19357 +ipt_condition_write_info(struct file *file, const char *buffer,
19358 + unsigned long length, void *data)
19360 + struct condition_variable *var =
19361 + (struct condition_variable *) data;
19364 + /* Match only on the first character */
19365 + switch (buffer[0]) {
19367 + var->enabled = 0;
19370 + var->enabled = 1;
19374 + return (int) length;
19379 +match(const struct sk_buff *skb, const struct net_device *in,
19380 + const struct net_device *out, const void *matchinfo, int offset,
19381 + const void *hdr, u_int16_t datalen, int *hotdrop)
19383 + const struct condition6_info *info =
19384 + (const struct condition6_info *) matchinfo;
19385 + struct condition_variable *var;
19386 + int condition_status = 0;
19388 + read_lock(&list_lock);
19390 + for (var = head; var; var = var->next) {
19391 + if (strcmp(info->name, var->status_proc->name) == 0) {
19392 + condition_status = var->enabled;
19397 + read_unlock(&list_lock);
19399 + return condition_status ^ info->invert;
19405 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
19406 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
19408 + struct condition6_info *info =
19409 + (struct condition6_info *) matchinfo;
19410 + struct condition_variable *var, *newvar;
19412 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19415 + /* The first step is to check if the condition variable already exists. */
19416 + /* Here, a read lock is sufficient because we won't change the list */
19417 + read_lock(&list_lock);
19419 + for (var = head; var; var = var->next) {
19420 + if (strcmp(info->name, var->status_proc->name) == 0) {
19421 + atomic_inc(&var->refcount);
19422 + read_unlock(&list_lock);
19427 + read_unlock(&list_lock);
19429 + /* At this point, we need to allocate a new condition variable */
19430 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
19435 + /* Create the condition variable's proc file entry */
19436 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
19438 + if (!newvar->status_proc) {
19440 + * There are two possibilities:
19441 + * 1- Another condition variable with the same name has been created, which is valid.
19442 + * 2- There was a memory allocation error.
19445 + read_lock(&list_lock);
19447 + for (var = head; var; var = var->next) {
19448 + if (strcmp(info->name, var->status_proc->name) == 0) {
19449 + atomic_inc(&var->refcount);
19450 + read_unlock(&list_lock);
19455 + read_unlock(&list_lock);
19459 + atomic_set(&newvar->refcount, 1);
19460 + newvar->enabled = 0;
19461 + newvar->status_proc->owner = THIS_MODULE;
19462 + newvar->status_proc->data = newvar;
19464 + newvar->status_proc->read_proc = ipt_condition_read_info;
19465 + newvar->status_proc->write_proc = ipt_condition_write_info;
19467 + write_lock(&list_lock);
19469 + newvar->next = head;
19472 + write_unlock(&list_lock);
19479 +destroy(void *matchinfo, unsigned int matchsize)
19481 + struct condition6_info *info =
19482 + (struct condition6_info *) matchinfo;
19483 + struct condition_variable *var, *prev = NULL;
19485 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19488 + write_lock(&list_lock);
19490 + for (var = head; var && strcmp(info->name, var->status_proc->name);
19491 + prev = var, var = var->next);
19493 + if (var && atomic_dec_and_test(&var->refcount)) {
19495 + prev->next = var->next;
19497 + head = var->next;
19499 + write_unlock(&list_lock);
19500 + remove_proc_entry(var->status_proc->name, proc_net_condition);
19503 + write_unlock(&list_lock);
19507 +static struct ip6t_match condition_match = {
19508 + .name = "condition",
19510 + .checkentry = &checkentry,
19511 + .destroy = &destroy,
19512 + .me = THIS_MODULE
19521 + rwlock_init(&list_lock);
19522 + proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
19524 + if (proc_net_condition) {
19525 + errorcode = ipt_register_match(&condition_match);
19528 + remove_proc_entry("ip6t_condition", proc_net);
19530 + errorcode = -EACCES;
19532 + return errorcode;
19536 +static void __exit
19539 + ipt_unregister_match(&condition_match);
19540 + remove_proc_entry("ip6t_condition", proc_net);
19543 +module_init(init);
19544 +module_exit(fini);
19545 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_fuzzy.c
19546 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
19547 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_fuzzy.c 2003-12-11 10:23:21.621650984 +0100
19550 + * This module implements a simple TSK FLC
19551 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
19552 + * to limit , in an adaptive and flexible way , the packet rate crossing
19553 + * a given stream . It serves as an initial and very simple (but effective)
19554 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
19555 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
19556 + * into our code in a precise , adaptive and efficient manner.
19557 + * The goal is very similar to that of "limit" match , but using techniques of
19558 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
19559 + * avoiding over and undershoots - and stuff like that .
19562 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
19563 + * 2002-08-17 : Changed to eliminate floating point operations .
19564 + * 2002-08-23 : Coding style changes .
19565 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
19568 +#include <linux/module.h>
19569 +#include <linux/skbuff.h>
19570 +#include <linux/ipv6.h>
19571 +#include <linux/random.h>
19572 +#include <net/tcp.h>
19573 +#include <linux/spinlock.h>
19574 +#include <linux/netfilter_ipv6/ip6_tables.h>
19575 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
19578 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
19579 + Expressed in percentage
19582 +#define PAR_LOW 1/100
19583 +#define PAR_HIGH 1
19585 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
19587 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
19588 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
19589 +MODULE_LICENSE("GPL");
19591 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19593 + if (tx >= maxi) return 100;
19595 + if (tx <= mini) return 0;
19597 + return ((100 * (tx-mini)) / (maxi-mini));
19600 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19602 + if (tx <= mini) return 100;
19604 + if (tx >= maxi) return 0;
19606 + return ((100 * (maxi - tx)) / (maxi - mini));
19611 +ip6t_fuzzy_match(const struct sk_buff *pskb,
19612 + const struct net_device *in,
19613 + const struct net_device *out,
19614 + const void *matchinfo,
19617 + u_int16_t datalen,
19620 + /* From userspace */
19622 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
19624 + u_int8_t random_number;
19625 + unsigned long amount;
19626 + u_int8_t howhigh, howlow;
19629 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
19631 + info->bytes_total += pskb->len;
19632 + info->packets_total++;
19634 + info->present_time = jiffies;
19636 + if (info->present_time >= info->previous_time)
19637 + amount = info->present_time - info->previous_time;
19639 + /* There was a transition : I choose to re-sample
19640 + and keep the old acceptance rate...
19644 + info->previous_time = info->present_time;
19645 + info->bytes_total = info->packets_total = 0;
19648 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
19650 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
19653 + info->previous_time = info->present_time;
19654 + info->bytes_total = info->packets_total = 0;
19656 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
19657 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
19659 + info->acceptance_rate = (u_int8_t) \
19660 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
19662 + /* In fact, the above defuzzification would require a denominator
19663 + * proportional to (howhigh+howlow) but, in this particular case,
19664 + * that expression is constant.
19665 + * An imediate consequence is that it is not necessary to call
19666 + * both mf_high and mf_low - but to keep things understandable,
19672 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
19675 + if (info->acceptance_rate < 100)
19677 + get_random_bytes((void *)(&random_number), 1);
19679 + /* If within the acceptance , it can pass => don't match */
19680 + if (random_number <= (255 * info->acceptance_rate) / 100)
19683 + return 1; /* It can't pass (It matches) */
19686 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
19691 +ip6t_fuzzy_checkentry(const char *tablename,
19692 + const struct ip6t_ip6 *ip,
19694 + unsigned int matchsize,
19695 + unsigned int hook_mask)
19698 + const struct ip6t_fuzzy_info *info = matchinfo;
19700 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
19701 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
19702 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
19706 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
19707 + || (info->minimum_rate >= info->maximum_rate)) {
19708 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
19715 +static struct ip6t_match ip6t_fuzzy_reg = {
19718 + ip6t_fuzzy_match,
19719 + ip6t_fuzzy_checkentry,
19723 +static int __init init(void)
19725 + if (ip6t_register_match(&ip6t_fuzzy_reg))
19731 +static void __exit fini(void)
19733 + ip6t_unregister_match(&ip6t_fuzzy_reg);
19736 +module_init(init);
19737 +module_exit(fini);
19738 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_HL.c
19739 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
19740 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_HL.c 2003-12-11 10:23:23.851312024 +0100
19743 + * Hop Limit modification target for ip6tables
19744 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
19745 + * Based on HW's TTL module
19747 + * This software is distributed under the terms of GNU GPL
19750 +#include <linux/module.h>
19751 +#include <linux/skbuff.h>
19752 +#include <linux/ip.h>
19754 +#include <linux/netfilter_ipv6/ip6_tables.h>
19755 +#include <linux/netfilter_ipv6/ip6t_HL.h>
19757 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
19758 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
19759 +MODULE_LICENSE("GPL");
19761 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
19762 + const struct net_device *in, const struct net_device *out,
19763 + const void *targinfo, void *userinfo)
19765 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
19766 + const struct ip6t_HL_info *info = targinfo;
19767 + u_int16_t diffs[2];
19770 + switch (info->mode) {
19771 + case IP6T_HL_SET:
19772 + new_hl = info->hop_limit;
19774 + case IP6T_HL_INC:
19775 + new_hl = ip6h->hop_limit + info->hop_limit;
19776 + if (new_hl > 255)
19779 + case IP6T_HL_DEC:
19780 + new_hl = ip6h->hop_limit + info->hop_limit;
19785 + new_hl = ip6h->hop_limit;
19789 + if (new_hl != ip6h->hop_limit) {
19790 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
19791 + ip6h->hop_limit = new_hl;
19792 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
19795 + return IP6T_CONTINUE;
19798 +static int ip6t_hl_checkentry(const char *tablename,
19799 + const struct ip6t_entry *e,
19801 + unsigned int targinfosize,
19802 + unsigned int hook_mask)
19804 + struct ip6t_HL_info *info = targinfo;
19806 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
19807 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
19809 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
19813 + if (strcmp(tablename, "mangle")) {
19814 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
19818 + if (info->mode > IP6T_HL_MAXMODE) {
19819 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
19824 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
19825 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
19832 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
19833 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
19835 +static int __init init(void)
19837 + return ip6t_register_target(&ip6t_HL);
19840 +static void __exit fini(void)
19842 + ip6t_unregister_target(&ip6t_HL);
19845 +module_init(init);
19846 +module_exit(fini);
19847 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_LOG.c
19848 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_LOG.c 2003-11-26 21:43:30.000000000 +0100
19849 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_LOG.c 2003-12-11 10:23:14.924669080 +0100
19852 #include <linux/module.h>
19853 #include <linux/skbuff.h>
19854 +#include <linux/socket.h>
19855 #include <linux/ip.h>
19856 #include <linux/spinlock.h>
19857 #include <linux/icmpv6.h>
19858 #include <net/udp.h>
19859 #include <net/tcp.h>
19860 #include <net/ipv6.h>
19861 +#include <linux/netfilter.h>
19862 #include <linux/netfilter_ipv6/ip6_tables.h>
19864 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
19865 MODULE_DESCRIPTION("IP6 tables LOG target module");
19866 MODULE_LICENSE("GPL");
19868 +static unsigned int nflog = 1;
19869 +MODULE_PARM(nflog, "i");
19870 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
19873 #include <net/route.h>
19874 #include <linux/netfilter_ipv6/ip6t_LOG.h>
19875 @@ -256,40 +262,38 @@
19879 -static unsigned int
19880 -ip6t_log_target(struct sk_buff **pskb,
19881 - unsigned int hooknum,
19882 - const struct net_device *in,
19883 - const struct net_device *out,
19884 - const void *targinfo,
19887 +ip6t_log_packet(unsigned int hooknum,
19888 + const struct sk_buff *skb,
19889 + const struct net_device *in,
19890 + const struct net_device *out,
19891 + const struct ip6t_log_info *loginfo,
19892 + const char *level_string,
19893 + const char *prefix)
19895 - struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
19896 - const struct ip6t_log_info *loginfo = targinfo;
19897 - char level_string[4] = "< >";
19898 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
19900 - level_string[1] = '0' + (loginfo->level % 8);
19901 spin_lock_bh(&log_lock);
19902 printk(level_string);
19903 printk("%sIN=%s OUT=%s ",
19905 + prefix == NULL ? loginfo->prefix : prefix,
19906 in ? in->name : "",
19907 out ? out->name : "");
19909 /* MAC logging for input chain only. */
19911 - if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
19912 - if ((*pskb)->dev->type != ARPHRD_SIT){
19913 + if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
19914 + if (skb->dev->type != ARPHRD_SIT){
19916 - unsigned char *p = (*pskb)->mac.raw;
19917 - for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
19918 + unsigned char *p = skb->mac.raw;
19919 + for (i = 0; i < skb->dev->hard_header_len; i++,p++)
19920 printk("%02x%c", *p,
19921 - i==(*pskb)->dev->hard_header_len - 1
19922 + i==skb->dev->hard_header_len - 1
19926 - unsigned char *p = (*pskb)->mac.raw;
19927 - if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
19928 + unsigned char *p = skb->mac.raw;
19929 + if ( p - (ETH_ALEN*2+2) > skb->head ){
19931 for (i = 0; i < (ETH_ALEN); i++,p++)
19932 printk("%02x%s", *p,
19933 @@ -300,10 +304,10 @@
19934 i == ETH_ALEN-1 ? ' ' : ':');
19937 - if (((*pskb)->dev->addr_len == 4) &&
19938 - (*pskb)->dev->hard_header_len > 20){
19939 + if ((skb->dev->addr_len == 4) &&
19940 + skb->dev->hard_header_len > 20){
19942 - p = (*pskb)->mac.raw + 12;
19943 + p = skb->mac.raw + 12;
19944 for (i = 0; i < 4; i++,p++)
19945 printk("%3d%s", *p,
19946 i == 3 ? "->" : ".");
19947 @@ -319,10 +323,41 @@
19948 dump_packet(loginfo, ipv6h, 1);
19950 spin_unlock_bh(&log_lock);
19953 +static unsigned int
19954 +ip6t_log_target(struct sk_buff **pskb,
19955 + unsigned int hooknum,
19956 + const struct net_device *in,
19957 + const struct net_device *out,
19958 + const void *targinfo,
19961 + const struct ip6t_log_info *loginfo = targinfo;
19962 + char level_string[4] = "< >";
19964 + level_string[1] = '0' + (loginfo->level % 8);
19965 + ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
19967 return IP6T_CONTINUE;
19971 +ip6t_logfn(unsigned int hooknum,
19972 + const struct sk_buff *skb,
19973 + const struct net_device *in,
19974 + const struct net_device *out,
19975 + const char *prefix)
19977 + struct ip6t_log_info loginfo = {
19979 + .logflags = IP6T_LOG_MASK,
19983 + ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
19986 static int ip6t_log_checkentry(const char *tablename,
19987 const struct ip6t_entry *e,
19989 @@ -359,12 +394,17 @@
19991 if (ip6t_register_target(&ip6t_log_reg))
19994 + nf_log_register(PF_INET6, &ip6t_logfn);
19999 static void __exit fini(void)
20002 + nf_log_register(PF_INET6, &ip6t_logfn);
20004 ip6t_unregister_target(&ip6t_log_reg);
20007 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_nth.c
20008 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
20009 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_nth.c 2003-12-11 10:23:29.533448208 +0100
20012 + This is a module which is used for match support for every Nth packet
20013 + This file is distributed under the terms of the GNU General Public
20014 + License (GPL). Copies of the GPL can be obtained from:
20015 + ftp://prep.ai.mit.edu/pub/gnu/GPL
20017 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20018 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
20019 + * added support for multiple counters
20020 + * added support for matching on individual packets
20021 + in the counter cycle
20022 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20026 +#include <linux/module.h>
20027 +#include <linux/skbuff.h>
20028 +#include <linux/ip.h>
20029 +#include <net/tcp.h>
20030 +#include <linux/spinlock.h>
20031 +#include <linux/netfilter_ipv6/ip6_tables.h>
20032 +#include <linux/netfilter_ipv6/ip6t_nth.h>
20034 +MODULE_LICENSE("GPL");
20037 + * State information.
20041 + u_int16_t number;
20044 +static struct state states[IP6T_NTH_NUM_COUNTERS];
20047 +ip6t_nth_match(const struct sk_buff *pskb,
20048 + const struct net_device *in,
20049 + const struct net_device *out,
20050 + const void *matchinfo,
20053 + u_int16_t datalen,
20056 + /* Parameters from userspace */
20057 + const struct ip6t_nth_info *info = matchinfo;
20058 + unsigned counter = info->counter;
20059 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
20061 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20065 + spin_lock(&states[counter].lock);
20067 + /* Are we matching every nth packet?*/
20068 + if (info->packet == 0xFF)
20070 + /* We're matching every nth packet and only every nth packet*/
20071 + /* Do we match or invert match? */
20072 + if (info->not == 0)
20074 + if (states[counter].number == 0)
20076 + ++states[counter].number;
20079 + if (states[counter].number >= info->every)
20080 + states[counter].number = 0; /* reset the counter */
20082 + ++states[counter].number;
20087 + if (states[counter].number == 0)
20089 + ++states[counter].number;
20092 + if (states[counter].number >= info->every)
20093 + states[counter].number = 0;
20095 + ++states[counter].number;
20101 + /* We're using the --packet, so there must be a rule for every value */
20102 + if (states[counter].number == info->packet)
20104 + /* only increment the counter when a match happens */
20105 + if (states[counter].number >= info->every)
20106 + states[counter].number = 0; /* reset the counter */
20108 + ++states[counter].number;
20116 + /* don't match */
20117 + spin_unlock(&states[counter].lock);
20121 + spin_unlock(&states[counter].lock);
20126 +ip6t_nth_checkentry(const char *tablename,
20127 + const struct ip6t_ip6 *e,
20129 + unsigned int matchsize,
20130 + unsigned int hook_mask)
20132 + /* Parameters from userspace */
20133 + const struct ip6t_nth_info *info = matchinfo;
20134 + unsigned counter = info->counter;
20135 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
20137 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20141 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
20142 + printk("nth: matchsize %u != %u\n", matchsize,
20143 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
20147 + states[counter].number = info->startat;
20152 +static struct ip6t_match ip6t_nth_reg = {
20156 + ip6t_nth_checkentry,
20160 +static int __init init(void)
20162 + unsigned counter;
20163 + memset(&states, 0, sizeof(states));
20164 + if (ip6t_register_match(&ip6t_nth_reg))
20167 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
20169 + spin_lock_init(&(states[counter].lock));
20172 + printk("ip6t_nth match loaded\n");
20176 +static void __exit fini(void)
20178 + ip6t_unregister_match(&ip6t_nth_reg);
20179 + printk("ip6t_nth match unloaded\n");
20182 +module_init(init);
20183 +module_exit(fini);
20184 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_owner.c
20185 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_owner.c 2003-11-26 21:45:19.000000000 +0100
20186 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_owner.c 1970-01-01 01:00:00.000000000 +0100
20188 -/* Kernel module to match various things tied to sockets associated with
20189 - locally generated outgoing packets.
20191 - Copyright (C) 2000,2001 Marc Boucher
20193 -#include <linux/module.h>
20194 -#include <linux/skbuff.h>
20195 -#include <linux/file.h>
20196 -#include <net/sock.h>
20198 -#include <linux/netfilter_ipv6/ip6t_owner.h>
20199 -#include <linux/netfilter_ipv6/ip6_tables.h>
20201 -MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20202 -MODULE_DESCRIPTION("IP6 tables owner matching module");
20203 -MODULE_LICENSE("GPL");
20206 -match_pid(const struct sk_buff *skb, pid_t pid)
20208 - struct task_struct *p;
20209 - struct files_struct *files;
20212 - read_lock(&tasklist_lock);
20213 - p = find_task_by_pid(pid);
20217 - files = p->files;
20219 - spin_lock(&files->file_lock);
20220 - for (i=0; i < files->max_fds; i++) {
20221 - if (fcheck_files(files, i) == skb->sk->sk_socket->file) {
20222 - spin_unlock(&files->file_lock);
20224 - read_unlock(&tasklist_lock);
20228 - spin_unlock(&files->file_lock);
20232 - read_unlock(&tasklist_lock);
20237 -match_sid(const struct sk_buff *skb, pid_t sid)
20239 - struct task_struct *g, *p;
20240 - struct file *file = skb->sk->sk_socket->file;
20243 - read_lock(&tasklist_lock);
20244 - do_each_thread(g, p) {
20245 - struct files_struct *files;
20246 - if (p->session != sid)
20250 - files = p->files;
20252 - spin_lock(&files->file_lock);
20253 - for (i=0; i < files->max_fds; i++) {
20254 - if (fcheck_files(files, i) == file) {
20259 - spin_unlock(&files->file_lock);
20264 - } while_each_thread(g, p);
20266 - read_unlock(&tasklist_lock);
20272 -match(const struct sk_buff *skb,
20273 - const struct net_device *in,
20274 - const struct net_device *out,
20275 - const void *matchinfo,
20278 - u_int16_t datalen,
20281 - const struct ip6t_owner_info *info = matchinfo;
20283 - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
20286 - if(info->match & IP6T_OWNER_UID) {
20287 - if((skb->sk->sk_socket->file->f_uid != info->uid) ^
20288 - !!(info->invert & IP6T_OWNER_UID))
20292 - if(info->match & IP6T_OWNER_GID) {
20293 - if((skb->sk->sk_socket->file->f_gid != info->gid) ^
20294 - !!(info->invert & IP6T_OWNER_GID))
20298 - if(info->match & IP6T_OWNER_PID) {
20299 - if (!match_pid(skb, info->pid) ^
20300 - !!(info->invert & IP6T_OWNER_PID))
20304 - if(info->match & IP6T_OWNER_SID) {
20305 - if (!match_sid(skb, info->sid) ^
20306 - !!(info->invert & IP6T_OWNER_SID))
20314 -checkentry(const char *tablename,
20315 - const struct ip6t_ip6 *ip,
20317 - unsigned int matchsize,
20318 - unsigned int hook_mask)
20321 - & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) {
20322 - printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
20326 - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
20332 -static struct ip6t_match owner_match = {
20335 - .checkentry = &checkentry,
20336 - .me = THIS_MODULE,
20339 -static int __init init(void)
20341 - return ip6t_register_match(&owner_match);
20344 -static void __exit fini(void)
20346 - ip6t_unregister_match(&owner_match);
20349 -module_init(init);
20350 -module_exit(fini);
20351 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_random.c
20352 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
20353 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_random.c 2003-12-11 10:23:36.320416432 +0100
20356 + This is a module which is used for a "random" match support.
20357 + This file is distributed under the terms of the GNU General Public
20358 + License (GPL). Copies of the GPL can be obtained from:
20359 + ftp://prep.ai.mit.edu/pub/gnu/GPL
20361 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20362 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20365 +#include <linux/module.h>
20366 +#include <linux/skbuff.h>
20367 +#include <linux/ip.h>
20368 +#include <linux/random.h>
20369 +#include <net/tcp.h>
20370 +#include <linux/spinlock.h>
20371 +#include <linux/netfilter_ipv6/ip6_tables.h>
20372 +#include <linux/netfilter_ipv6/ip6t_random.h>
20374 +MODULE_LICENSE("GPL");
20377 +ip6t_rand_match(const struct sk_buff *pskb,
20378 + const struct net_device *in,
20379 + const struct net_device *out,
20380 + const void *matchinfo,
20383 + u_int16_t datalen,
20386 + /* Parameters from userspace */
20387 + const struct ip6t_rand_info *info = matchinfo;
20388 + u_int8_t random_number;
20390 + /* get 1 random number from the kernel random number generation routine */
20391 + get_random_bytes((void *)(&random_number), 1);
20393 + /* Do we match ? */
20394 + if (random_number <= info->average)
20401 +ip6t_rand_checkentry(const char *tablename,
20402 + const struct ip6t_ip6 *e,
20404 + unsigned int matchsize,
20405 + unsigned int hook_mask)
20407 + /* Parameters from userspace */
20408 + const struct ip6t_rand_info *info = matchinfo;
20410 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
20411 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
20412 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
20416 + /* must be 1 <= average % <= 99 */
20417 + /* 1 x 2.55 = 2 */
20418 + /* 99 x 2.55 = 252 */
20419 + if ((info->average < 2) || (info->average > 252)) {
20420 + printk("ip6t_random: invalid average %u\n", info->average);
20427 +static struct ip6t_match ip6t_rand_reg = {
20431 + ip6t_rand_checkentry,
20435 +static int __init init(void)
20437 + if (ip6t_register_match(&ip6t_rand_reg))
20440 + printk("ip6t_random match loaded\n");
20444 +static void __exit fini(void)
20446 + ip6t_unregister_match(&ip6t_rand_reg);
20447 + printk("ip6t_random match unloaded\n");
20450 +module_init(init);
20451 +module_exit(fini);
20452 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_REJECT.c
20453 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
20454 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_REJECT.c 2003-12-11 10:23:39.703902064 +0100
20457 + * This is a module which is used for rejecting packets.
20458 + * Added support for customized reject packets (Jozsef Kadlecsik).
20459 + * Sun 12 Nov 2000
20460 + * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
20462 +#include <linux/config.h>
20463 +#include <linux/module.h>
20464 +#include <linux/skbuff.h>
20465 +#include <linux/icmpv6.h>
20466 +#include <net/tcp.h>
20467 +#include <linux/netfilter_ipv6/ip6_tables.h>
20468 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
20471 +#define DEBUGP printk
20473 +#define DEBUGP(format, args...)
20477 +/* Send RST reply */
20478 +static void send_reset(struct sk_buff *oldskb)
20480 + struct sk_buff *nskb;
20481 + struct tcphdr *otcph, *tcph;
20482 + struct rtable *rt;
20483 + unsigned int otcplen;
20486 + /* IP header checks: fragment, too short. */
20487 + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
20488 + || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
20491 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
20492 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
20494 + /* No RST for RST. */
20498 + /* Check checksum. */
20499 + if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
20500 + oldskb->nh.iph->daddr,
20501 + csum_partial((char *)otcph, otcplen, 0)) != 0)
20504 + /* Copy skb (even if skb is about to be dropped, we can't just
20505 + clone it because there may be other things, such as tcpdump,
20506 + interested in it) */
20507 + nskb = skb_copy(oldskb, GFP_ATOMIC);
20511 + /* This packet will not be the same as the other: clear nf fields */
20512 + nf_conntrack_put(nskb->nfct);
20513 + nskb->nfct = NULL;
20514 + nskb->nfcache = 0;
20515 +#ifdef CONFIG_NETFILTER_DEBUG
20516 + nskb->nf_debug = 0;
20519 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
20521 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
20522 + tcph->source = xchg(&tcph->dest, tcph->source);
20524 + /* Truncate to length (no data) */
20525 + tcph->doff = sizeof(struct tcphdr)/4;
20526 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
20527 + nskb->nh.iph->tot_len = htons(nskb->len);
20531 + tcph->seq = otcph->ack_seq;
20532 + tcph->ack_seq = 0;
20535 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
20536 + + otcplen - (otcph->doff<<2));
20540 + /* Reset flags */
20541 + ((u_int8_t *)tcph)[13] = 0;
20543 + tcph->ack = needs_ack;
20545 + tcph->window = 0;
20546 + tcph->urg_ptr = 0;
20548 + /* Adjust TCP checksum */
20550 + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
20551 + nskb->nh.iph->saddr,
20552 + nskb->nh.iph->daddr,
20553 + csum_partial((char *)tcph,
20554 + sizeof(struct tcphdr), 0));
20556 + /* Adjust IP TTL, DF */
20557 + nskb->nh.iph->ttl = MAXTTL;
20558 + /* Set DF, id = 0 */
20559 + nskb->nh.iph->frag_off = htons(IP_DF);
20560 + nskb->nh.iph->id = 0;
20562 + /* Adjust IP checksum */
20563 + nskb->nh.iph->check = 0;
20564 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
20565 + nskb->nh.iph->ihl);
20568 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
20569 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
20573 + dst_release(nskb->dst);
20574 + nskb->dst = &rt->u.dst;
20576 + /* "Never happens" */
20577 + if (nskb->len > nskb->dst->pmtu)
20580 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
20581 + ip_finish_output);
20589 +static unsigned int reject6_target(struct sk_buff **pskb,
20590 + unsigned int hooknum,
20591 + const struct net_device *in,
20592 + const struct net_device *out,
20593 + const void *targinfo,
20596 + const struct ip6t_reject_info *reject = targinfo;
20598 + /* WARNING: This code causes reentry within ip6tables.
20599 + This means that the ip6tables jump stack is now crap. We
20600 + must return an absolute verdict. --RR */
20601 + DEBUGP("REJECTv6: calling icmpv6_send\n");
20602 + switch (reject->with) {
20603 + case IP6T_ICMP6_NO_ROUTE:
20604 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
20606 + case IP6T_ICMP6_ADM_PROHIBITED:
20607 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
20609 + case IP6T_ICMP6_NOT_NEIGHBOUR:
20610 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
20612 + case IP6T_ICMP6_ADDR_UNREACH:
20613 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
20615 + case IP6T_ICMP6_PORT_UNREACH:
20616 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
20619 + case IPT_ICMP_ECHOREPLY: {
20620 + struct icmp6hdr *icmph = (struct icmphdr *)
20621 + ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
20622 + unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
20624 + /* Not non-head frags, or truncated */
20625 + if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
20626 + && datalen >= 4) {
20627 + /* Usually I don't like cut & pasting code,
20628 + but dammit, my party is starting in 45
20630 + struct icmp_bxm icmp_param;
20632 + icmp_param.icmph=*icmph;
20633 + icmp_param.icmph.type=ICMP_ECHOREPLY;
20634 + icmp_param.data_ptr=(icmph+1);
20635 + icmp_param.data_len=datalen;
20636 + icmp_reply(&icmp_param, *pskb);
20640 + case IPT_TCP_RESET:
20641 + send_reset(*pskb);
20645 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
20652 +static inline int find_ping_match(const struct ip6t_entry_match *m)
20654 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
20656 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
20657 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
20658 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
20664 +static int check(const char *tablename,
20665 + const struct ip6t_entry *e,
20667 + unsigned int targinfosize,
20668 + unsigned int hook_mask)
20670 + const struct ip6t_reject_info *rejinfo = targinfo;
20672 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
20673 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
20677 + /* Only allow these for packet filtering. */
20678 + if (strcmp(tablename, "filter") != 0) {
20679 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
20682 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
20683 + | (1 << NF_IP6_FORWARD)
20684 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
20685 + DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
20689 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
20690 + /* Must specify that it's an ICMP ping packet. */
20691 + if (e->ipv6.proto != IPPROTO_ICMPV6
20692 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20693 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
20696 + /* Must contain ICMP match. */
20697 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
20698 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
20701 + } else if (rejinfo->with == IP6T_TCP_RESET) {
20702 + /* Must specify that it's a TCP packet */
20703 + if (e->ipv6.proto != IPPROTO_TCP
20704 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20705 + DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
20713 +static struct ip6t_target ip6t_reject_reg
20714 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
20716 +static int __init init(void)
20718 + if (ip6t_register_target(&ip6t_reject_reg))
20723 +static void __exit fini(void)
20725 + ip6t_unregister_target(&ip6t_reject_reg);
20728 +module_init(init);
20729 +module_exit(fini);
20730 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_ROUTE.c
20731 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
20732 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_ROUTE.c 2003-12-11 10:24:03.166335232 +0100
20735 + * This implements the ROUTE v6 target, which enables you to setup unusual
20736 + * routes not supported by the standard kernel routing table.
20738 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
20740 + * v 1.0 2003/08/05
20742 + * This software is distributed under GNU GPL v2, 1991
20745 +#include <linux/module.h>
20746 +#include <linux/skbuff.h>
20747 +#include <linux/ipv6.h>
20748 +#include <linux/netfilter_ipv6/ip6_tables.h>
20749 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
20750 +#include <linux/netdevice.h>
20751 +#include <net/ipv6.h>
20752 +#include <net/ndisc.h>
20753 +#include <net/ip6_route.h>
20754 +#include <linux/icmpv6.h>
20757 +#define DEBUGP printk
20759 +#define DEBUGP(format, args...)
20762 +#define NIP6(addr) \
20763 + ntohs((addr).s6_addr16[0]), \
20764 + ntohs((addr).s6_addr16[1]), \
20765 + ntohs((addr).s6_addr16[2]), \
20766 + ntohs((addr).s6_addr16[3]), \
20767 + ntohs((addr).s6_addr16[4]), \
20768 + ntohs((addr).s6_addr16[5]), \
20769 + ntohs((addr).s6_addr16[6]), \
20770 + ntohs((addr).s6_addr16[7])
20772 +/* Route the packet according to the routing keys specified in
20773 + * route_info. Keys are :
20775 + * 0 if no oif preferred,
20776 + * otherwise set to the index of the desired oif
20777 + * - route_info->gw :
20778 + * 0 if no gateway specified,
20779 + * otherwise set to the next host to which the pkt must be routed
20780 + * If success, skb->dev is the output device to which the packet must
20781 + * be sent and skb->dst is not NULL
20783 + * RETURN: 1 if the packet was succesfully routed to the
20784 + * destination desired
20785 + * 0 if the kernel routing table could not route the packet
20786 + * according to the keys specified
20789 +route6(struct sk_buff *skb,
20790 + unsigned int ifindex,
20791 + const struct ip6t_route_target_info *route_info)
20793 + struct rt6_info *rt = NULL;
20794 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
20795 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
20797 + DEBUGP("ip6t_ROUTE: called with: ");
20798 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
20799 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
20800 + DEBUGP("OUT=%s\n", route_info->oif);
20802 + if (ipv6_addr_any(gw))
20803 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
20805 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
20810 + DEBUGP("ip6t_ROUTE: routing gives: ");
20811 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
20812 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
20813 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
20815 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
20816 + goto wrong_route;
20818 + if (!rt->rt6i_nexthop) {
20819 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
20820 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
20823 + /* Drop old route. */
20824 + dst_release(skb->dst);
20825 + skb->dst = &rt->u.dst;
20826 + skb->dev = rt->rt6i_dev;
20830 + dst_release(&rt->u.dst);
20832 + if (!net_ratelimit())
20835 + printk("ip6t_ROUTE: no explicit route found ");
20837 + printk("via interface %s ", route_info->oif);
20838 + if (!ipv6_addr_any(gw))
20839 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
20845 +/* Stolen from ip6_output_finish
20846 + * PRE : skb->dev is set to the device we are leaving by
20847 + * skb->dst is not NULL
20848 + * POST: the packet is sent with the link layer header pushed
20849 + * the packet is destroyed
20851 +static void ip_direct_send(struct sk_buff *skb)
20853 + struct dst_entry *dst = skb->dst;
20854 + struct hh_cache *hh = dst->hh;
20857 + read_lock_bh(&hh->hh_lock);
20858 + memcpy(skb->data - 16, hh->hh_data, 16);
20859 + read_unlock_bh(&hh->hh_lock);
20860 + skb_push(skb, hh->hh_len);
20861 + hh->hh_output(skb);
20862 + } else if (dst->neighbour)
20863 + dst->neighbour->output(skb);
20865 + if (net_ratelimit())
20866 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
20872 +static unsigned int
20873 +route6_oif(const struct ip6t_route_target_info *route_info,
20874 + struct sk_buff *skb)
20876 + unsigned int ifindex = 0;
20877 + struct net_device *dev_out = NULL;
20879 + /* The user set the interface name to use.
20880 + * Getting the current interface index.
20882 + if ((dev_out = dev_get_by_name(route_info->oif))) {
20883 + ifindex = dev_out->ifindex;
20885 + /* Unknown interface name : packet dropped */
20886 + if (net_ratelimit())
20887 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
20889 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
20890 + return IP6T_CONTINUE;
20895 + /* Trying the standard way of routing packets */
20896 + if (route6(skb, ifindex, route_info)) {
20897 + dev_put(dev_out);
20898 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
20899 + return IP6T_CONTINUE;
20901 + ip_direct_send(skb);
20902 + return NF_STOLEN;
20908 +static unsigned int
20909 +route6_gw(const struct ip6t_route_target_info *route_info,
20910 + struct sk_buff *skb)
20912 + if (route6(skb, 0, route_info)) {
20913 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
20914 + return IP6T_CONTINUE;
20916 + ip_direct_send(skb);
20917 + return NF_STOLEN;
20923 +static unsigned int
20924 +ip6t_route_target(struct sk_buff **pskb,
20925 + unsigned int hooknum,
20926 + const struct net_device *in,
20927 + const struct net_device *out,
20928 + const void *targinfo,
20931 + const struct ip6t_route_target_info *route_info = targinfo;
20932 + struct sk_buff *skb = *pskb;
20933 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
20935 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
20938 + /* If we are at PREROUTING or INPUT hook
20939 + * the TTL isn't decreased by the IP stack
20941 + if (hooknum == NF_IP6_PRE_ROUTING ||
20942 + hooknum == NF_IP6_LOCAL_IN) {
20944 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
20946 + if (ipv6h->hop_limit <= 1) {
20947 + /* Force OUTPUT device used as source address */
20948 + skb->dev = skb->dst->dev;
20950 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
20951 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
20956 + ipv6h->hop_limit--;
20961 + if (route_info->oif[0])
20962 + return route6_oif(route_info, *pskb);
20964 + if (!ipv6_addr_any(gw))
20965 + return route6_gw(route_info, *pskb);
20967 + if (net_ratelimit())
20968 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
20970 + return IP6T_CONTINUE;
20975 +ip6t_route_checkentry(const char *tablename,
20976 + const struct ip6t_entry *e,
20978 + unsigned int targinfosize,
20979 + unsigned int hook_mask)
20981 + if (strcmp(tablename, "mangle") != 0) {
20982 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
20986 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
20987 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
20989 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
20997 +static struct ip6t_target ip6t_route_reg = {
20999 + .target = ip6t_route_target,
21000 + .checkentry = ip6t_route_checkentry,
21001 + .me = THIS_MODULE
21005 +static int __init init(void)
21007 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
21008 + if (ip6t_register_target(&ip6t_route_reg))
21015 +static void __exit fini(void)
21017 + ip6t_unregister_target(&ip6t_route_reg);
21020 +module_init(init);
21021 +module_exit(fini);
21022 +MODULE_LICENSE("GPL");
21023 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_TRACE.c
21024 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
21025 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_TRACE.c 2003-12-11 10:23:17.233318112 +0100
21027 +/* This is a module which is used for setting
21028 + * the NFC_TRACE flag in the nfcache field of an skb.
21030 +#include <linux/module.h>
21031 +#include <linux/skbuff.h>
21033 +#include <linux/netfilter_ipv6/ip6_tables.h>
21035 +static unsigned int
21036 +target(struct sk_buff **pskb,
21037 + unsigned int hooknum,
21038 + const struct net_device *in,
21039 + const struct net_device *out,
21040 + const void *targinfo,
21043 + (*pskb)->nfcache |= NFC_TRACE;
21044 + return IP6T_CONTINUE;
21048 +checkentry(const char *tablename,
21049 + const struct ip6t_entry *e,
21051 + unsigned int targinfosize,
21052 + unsigned int hook_mask)
21054 + if (targinfosize != 0) {
21055 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
21060 + if (strcmp(tablename, "raw") != 0) {
21061 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
21068 +static struct ip6t_target ip6t_trace_reg = {
21070 + .target = target,
21071 + .checkentry = checkentry,
21073 + .me = THIS_MODULE,
21076 +static int __init init(void)
21078 + if (ip6t_register_target(&ip6t_trace_reg))
21084 +static void __exit fini(void)
21086 + ip6t_unregister_target(&ip6t_trace_reg);
21089 +module_init(init);
21090 +module_exit(fini);
21092 +MODULE_LICENSE("GPL");
21093 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21094 +MODULE_DESCRIPTION("IPv6 TRACE target");
21096 \ Brak znaku nowej linii na koñcu pliku
21097 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig linux-2.6.0-test11/net/ipv6/netfilter/Kconfig
21098 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig 2003-11-26 21:45:28.000000000 +0100
21099 +++ linux-2.6.0-test11/net/ipv6/netfilter/Kconfig 2003-12-11 12:59:02.951552984 +0100
21101 menu "IPv6: Netfilter Configuration"
21102 depends on INET && IPV6!=n && NETFILTER
21104 +config IP6_NF_TARGET_ROUTE
21105 + bool ' ROUTE target support'
21107 + CONFIG_IP6_NF_TARGET_ROUTE
21108 + This option adds a `ROUTE' target, which enables you to setup unusual
21109 + routes. The ROUTE target is also able to change the incoming interface
21112 + The target can be or not a final target. It has to be used inside the
21115 + Not working as a module.
21117 +config IP6_NF_MATCH_CONDITION
21118 + tristate ' Condition variable match support'
21119 + depends on IP6_NF_IPTABLES
21121 + Condition variable match support
21122 + CONFIG_IP6_NF_MATCH_CONDITION
21123 + This option allows you to match firewall rules against condition
21124 + variables stored in the /proc/net/ipt_condition directory.
21126 + If you want to compile it as a module, say M here and read
21127 + Documentation/modules.txt. If unsure, say `N'.
21131 +config IP6_NF_TARGET_REJECT
21132 + tristate ' REJECT target support'
21133 + depends on IP6_NF_FILTER
21135 + REJECT target support
21136 + CONFIG_IP6_NF_TARGET_REJECT
21137 + The REJECT target allows a filtering rule to specify that an ICMPv6
21138 + error should be issued in response to an incoming packet, rather
21139 + than silently being dropped.
21141 + If you want to compile it as a module, say M here and read
21142 + Documentation/modules.txt. If unsure, say `N'.
21146 +config IP6_NF_MATCH_RANDOM
21147 + tristate ' Random match support'
21148 + depends on IP6_NF_IPTABLES
21150 + Random match support
21151 + CONFIG_IP6_NF_MATCH_RANDOM
21152 + This option adds a `random' match,
21153 + which allow you to match packets randomly
21154 + following a given probability.
21156 + If you want to compile it as a module, say M here and read
21157 + Documentation/modules.txt. If unsure, say `N'.
21162 +config IP6_NF_MATCH_NTH
21163 + tristate ' Nth match support'
21164 + depends on IP6_NF_IPTABLES
21166 + Nth match support
21167 + CONFIG_IP6_NF_MATCH_NTH
21168 + This option adds a `Nth' match, which allow you to make
21169 + rules that match every Nth packet. By default there are
21170 + 16 different counters.
21173 + --every Nth Match every Nth packet
21174 + [--counter] num Use counter 0-15 (default:0)
21175 + [--start] num Initialize the counter at the number 'num'
21176 + instead of 0. Must be between 0 and Nth-1
21177 + [--packet] num Match on 'num' packet. Must be between 0
21180 + If --packet is used for a counter than
21181 + there must be Nth number of --packet
21182 + rules, covering all values between 0 and
21183 + Nth-1 inclusively.
21185 + If you want to compile it as a module, say M here and read
21186 + Documentation/modules.txt. If unsure, say `N'.
21191 +config IP6_NF_TARGET_HL
21192 + tristate ' HL target support'
21193 + depends on IP6_NF_FILTER
21195 + HL target support
21196 + CONFIG_IP6_NF_TARGET_HL
21197 + This option adds a `HL' target, which allows you to modify the value of
21198 + IPv6 Hop Limit field.
21200 + If you want to compile it as a module, say M here and read
21201 + <file:Documentation/modules.txt>. If unsure, say `N'.
21205 +config IP6_NF_MATCH_FUZZY
21206 + tristate ' Fuzzy match support'
21207 + depends on IP6_NF_FILTER
21209 + Fuzzy Logic Controller match support
21210 + CONFIG_IP6_NF_MATCH_FUZZY
21211 + This option adds a `fuzzy' match, which allows you to match
21212 + packets according to a fuzzy logic based law.
21214 + If you want to compile it as a module, say M here and read
21215 + Documentation/modules.txt. If unsure, say `N'.
21220 #tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
21221 #if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
21222 # dep_tristate ' FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK
21223 @@ -102,15 +218,6 @@
21225 To compile it as a module, choose M here. If unsure, say N.
21227 -config IP6_NF_MATCH_OWNER
21228 - tristate "Owner match support"
21229 - depends on IP6_NF_IPTABLES
21231 - Packet owner matching allows you to match locally-generated packets
21232 - based on who created them: the user, group, process or session.
21234 - To compile it as a module, choose M here. If unsure, say N.
21236 # dep_tristate ' MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
21237 config IP6_NF_MATCH_MARK
21238 tristate "netfilter MARK match support"
21239 @@ -217,6 +324,31 @@
21241 To compile it as a module, choose M here. If unsure, say N.
21244 + tristate "Raw table"
21245 + depends on IP6_NF_IPTABLES
21247 + This option adds a `raw' table to iptables: see the man page for
21248 + iptables(8). This table is the very first in the netfilter
21249 + framework and hooks in at the PREROUTING and OUTPUT chains.
21250 + The TRACE target can be used in this table only.
21252 + To compile it as a module, choose M here. If unsure, say N.
21254 +config IP6_NF_TARGET_TRACE
21255 + tristate "TRACE target support"
21256 + depends on IP6_NF_RAW
21258 + The TRACE target allows packets to be traced as those matches
21259 + any subsequent rule in any IPv6 netfilter table/rule. The matched
21260 + rule and the packet is logged with the prefix
21262 + TRACE: tablename/chainname/rulenum
21264 + if the ip6t_LOG target is loaded in.
21266 + To compile it as a module, choose M here. If unsure, say N.
21268 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
21271 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile linux-2.6.0-test11/net/ipv6/netfilter/Makefile
21272 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile 2003-11-26 21:44:26.000000000 +0100
21273 +++ linux-2.6.0-test11/net/ipv6/netfilter/Makefile 2003-12-11 12:59:09.998481688 +0100
21275 obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
21276 obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
21277 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
21278 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
21279 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
21280 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
21281 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
21282 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
21283 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
21284 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
21285 @@ -15,10 +17,18 @@
21286 obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
21287 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
21288 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
21289 -obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
21290 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
21291 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
21292 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
21293 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
21294 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
21295 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
21296 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
21297 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
21299 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
21301 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
21302 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
21303 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
21304 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
21305 diff -Nur linux-2.6.0-test11.org/netfilter-patch-o-matic/patches linux-2.6.0-test11/netfilter-patch-o-matic/patches
21306 --- linux-2.6.0-test11.org/netfilter-patch-o-matic/patches 1970-01-01 01:00:00.000000000 +0100
21307 +++ linux-2.6.0-test11/netfilter-patch-o-matic/patches 2003-12-11 12:58:41.483816576 +0100
21309 +./base/01_sctp_match.patch
21310 +./base/connlimit.patch
21311 +./base/dstlimit.patch
21312 +./base/fuzzy6.patch.ipv6
21313 +./base/fuzzy.patch
21314 +./base/HL.patch.ipv6
21315 +./base/iprange.patch
21316 +./base/ipv4options.patch
21317 +./base/IPV4OPTSSTRIP.patch
21318 +./base/mport.patch
21319 +./base/NETLINK.patch
21320 +./base/nth6.patch.ipv6
21325 +./base/quota.patch
21326 +./base/random6.patch.ipv6
21327 +./base/random.patch
21328 +./base/realm.patch
21329 +./base/REJECT.patch.ipv6
21334 +./extra/addrtype.patch
21335 +./extra/CLASSIFY.patch
21336 +./extra/condition6.patch.ipv6
21337 +./extra/condition.patch
21338 +./extra/CONNMARK.patch
21339 +./extra/cuseeme-nat.patch
21340 +./extra/eggdrop-conntrack.patch
21341 +./extra/h323-conntrack-nat.patch
21342 +./extra/IPMARK.patch
21343 +./extra/iptables-loopcheck-speedup.patch
21344 +./extra/mms-conntrack-nat.patch
21345 +./extra/netfilter-docbook.patch manual change
21346 +./extra/pptp-conntrack-nat.patch manual change
21347 +./extra/quake3-conntrack.patch
21348 +./extra/ROUTE.patch.ipv6
21351 +./extra/rtsp-conntrack.patch
21352 +./extra/talk-conntrack-nat.patch
21353 +./extra/TCPLAG.patch
21354 +./extra/TRACE.patch
21355 +./extra/TRACE.patch.ipv6
21357 +./optimizations/ip_ct_refresh_optimization.patch
21358 +./optimizations/ip_ct_refresh_optimization_pptp.patch
21359 +./pending/23_REJECT-headroom-tcprst.patch
21360 +./pending/24_rcu.patch
21361 +./pending/25-err-ptr.patch
21362 +./pending/26-memsets.patch
21363 +./pending/40_nf-log.patch
21364 +./pending/70_expect-evict-order.patch
21365 +./pending/71_raw.patch
21366 +./submited/02_REJECT-headroom-tcprst.patch
21367 +./submited/03_260t4-mirror-remove.patch
21368 +./submited/03_physdev_bridged.patch
21369 +./submited/04_260t4-unclean-remove.patch
21370 +./submited/05_260t4-unexperimental.patch
21371 +./submited/06_260t4-cosmetic.patch
21372 +./submited/07_260t4-newmodules_iprange_SAME_NETMAP_CLASSIFY.patch
21373 +./submited/07_nonlinear_skb.patch
21374 +./submited/08_260t4_ipt-helper-kconfig.patch
21375 +./submited/09_260t4-cosmetic-physdev-author.patch
21376 +./submited/75_nathelper-udp-csum.patch
21377 +./submited/76_mangle_udp-sizecheck.patch
21378 +./submited/77_destroy-conntrack.patch
21379 +./submited/78_reject-localout.patch
21380 +./submited/80_ip_conntrack-proc.patch
21381 +./submited/82_irc-conntrack-mirc-serverlookup.patch
21382 +./submited/83_nolocalout.patch
21383 +./submited/84_local-nullbinding.patch
21384 +./submited/85_ipv6header.patch
21385 +./submited/86_getorigdst-tuple-zero.patch
21386 +./submited/87_compat-nat_setup_info.patch
21387 +./submited/89_ip_queue-maxlen.patch
21388 +./userspace/ip_queue_vwmark.patch
21389 +./userspace/ipt_REJECT-fake-source.patch
21390 +./userspace/mark-bitwise-ops.patch