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-10 23:13:24.656327752 +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-10 23:14:12.889995120 +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-10 23:13:55.776596752 +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-10 23:22:29.227540344 +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_expect gre;
261 + struct ip_ct_gre gre;
262 struct ip_ct_tcp tcp;
263 struct ip_ct_icmp icmp;
268 /* Add protocol helper include file here */
269 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
270 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
271 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
272 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
273 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
274 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
276 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
277 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
278 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
280 /* per expectation: application helper private data */
281 union ip_conntrack_expect_help {
282 /* insert conntrack helper private data (expect) here */
283 + struct ip_ct_pptp_expect exp_pptp_info;
284 + struct ip_ct_talk_expect exp_talk_info;
285 + struct ip_ct_rtsp_master ct_rtsp_info;
286 + struct ip_ct_rtsp_expect exp_rtsp_info;
287 + struct ip_ct_rsh_expect exp_rsh_info;
288 + struct ip_ct_mms_expect exp_mms_info;
289 + struct ip_ct_h225_expect exp_h225_info;
290 struct ip_ct_amanda_expect exp_amanda_info;
291 struct ip_ct_ftp_expect exp_ftp_info;
292 struct ip_ct_irc_expect exp_irc_info;
294 /* per conntrack: application helper private data */
295 union ip_conntrack_help {
296 /* insert conntrack helper private data (master) here */
297 + struct ip_ct_pptp_master ct_pptp_info;
298 + struct ip_ct_talk_master ct_talk_info;
299 + struct ip_ct_rsh_master ct_rsh_info;
300 + struct ip_ct_mms_master ct_mms_info;
301 + struct ip_ct_h225_master ct_h225_info;
302 struct ip_ct_ftp_master ct_ftp_info;
303 struct ip_ct_irc_master ct_irc_info;
306 #ifdef CONFIG_IP_NF_NAT_NEEDED
307 #include <linux/netfilter_ipv4/ip_nat.h>
308 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
310 /* per conntrack: nat application helper private data */
311 union ip_conntrack_nat_help {
312 /* insert nat helper private data here */
313 + struct ip_nat_pptp nat_pptp_info;
319 #endif /* CONFIG_IP_NF_NAT_NEEDED */
321 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
322 + unsigned long mark;
326 /* get master conntrack via master expectation */
328 extern void ip_ct_refresh(struct ip_conntrack *ct,
329 unsigned long extra_jiffies);
331 +/* Kill conntrack */
332 +extern void ip_ct_death_by_timeout(unsigned long ul_conntrack);
334 /* These are for NAT. Icky. */
335 /* Call me when a conntrack is destroyed. */
336 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
339 extern unsigned int ip_conntrack_htable_size;
341 +/* A fake conntrack entry which never vanishes. */
342 +extern struct ip_conntrack ip_conntrack_untracked;
344 /* eg. PROVIDES_CONNTRACK(ftp); */
345 #define PROVIDES_CONNTRACK(name) \
346 int needs_ip_conntrack_##name; \
347 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
348 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
349 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2003-12-10 23:13:58.176231952 +0100
351 +#ifndef _IP_CONNTRACK_H323_H
352 +#define _IP_CONNTRACK_H323_H
353 +/* H.323 connection tracking. */
356 +/* Protects H.323 related data */
357 +DECLARE_LOCK_EXTERN(ip_h323_lock);
360 +/* Default H.225 port */
361 +#define H225_PORT 1720
363 +/* This structure is per expected connection */
364 +struct ip_ct_h225_expect {
365 + u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
366 + enum ip_conntrack_dir dir; /* Direction of the original connection */
367 + unsigned int offset; /* offset of the address in the payload */
370 +/* This structure exists only once per master */
371 +struct ip_ct_h225_master {
372 + int is_h225; /* H.225 or H.245 connection */
373 +#ifdef CONFIG_IP_NF_NAT_NEEDED
374 + enum ip_conntrack_dir dir; /* Direction of the original connection */
375 + u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
376 + unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
380 +#endif /* _IP_CONNTRACK_H323_H */
381 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
382 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
383 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2003-12-10 23:14:02.755535792 +0100
385 +#ifndef _IP_CONNTRACK_MMS_H
386 +#define _IP_CONNTRACK_MMS_H
390 +#include <linux/netfilter_ipv4/lockhelp.h>
392 +DECLARE_LOCK_EXTERN(ip_mms_lock);
394 +#define MMS_PORT 1755
395 +#define MMS_SRV_MSG_ID 196610
397 +#define MMS_SRV_MSG_OFFSET 36
398 +#define MMS_SRV_UNICODE_STRING_OFFSET 60
399 +#define MMS_SRV_CHUNKLENLV_OFFSET 16
400 +#define MMS_SRV_CHUNKLENLM_OFFSET 32
401 +#define MMS_SRV_MESSAGELENGTH_OFFSET 8
404 +/* This structure is per expected connection */
405 +struct ip_ct_mms_expect {
411 +/* This structure exists only once per master */
412 +struct ip_ct_mms_master {
415 +#endif /* _IP_CONNTRACK_MMS_H */
416 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
417 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 1970-01-01 01:00:00.000000000 +0100
418 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2003-11-17 09:09:34.000000000 +0100
420 +/* PPTP constants and structs */
421 +#ifndef _CONNTRACK_PPTP_H
422 +#define _CONNTRACK_PPTP_H
424 +/* state of the control session */
425 +enum pptp_ctrlsess_state {
426 + PPTP_SESSION_NONE, /* no session present */
427 + PPTP_SESSION_ERROR, /* some session error */
428 + PPTP_SESSION_STOPREQ, /* stop_sess request seen */
429 + PPTP_SESSION_REQUESTED, /* start_sess request seen */
430 + PPTP_SESSION_CONFIRMED, /* session established */
433 +/* state of the call inside the control session */
434 +enum pptp_ctrlcall_state {
438 + PPTP_CALL_OUT_CONF,
442 + PPTP_CALL_CLEAR_REQ,
446 +/* conntrack private data */
447 +struct ip_ct_pptp_master {
448 + enum pptp_ctrlsess_state sstate; /* session state */
450 + /* everything below is going to be per-expectation in newnat,
451 + * since there could be more than one call within one session */
452 + enum pptp_ctrlcall_state cstate; /* call state */
453 + u_int16_t pac_call_id; /* call id of PAC, host byte order */
454 + u_int16_t pns_call_id; /* call id of PNS, host byte order */
457 +/* conntrack_expect private member */
458 +struct ip_ct_pptp_expect {
459 + enum pptp_ctrlcall_state cstate; /* call state */
460 + u_int16_t pac_call_id; /* call id of PAC */
461 + u_int16_t pns_call_id; /* call id of PNS */
467 +#include <linux/netfilter_ipv4/lockhelp.h>
468 +DECLARE_LOCK_EXTERN(ip_pptp_lock);
470 +#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
472 +union pptp_ctrl_union {
474 + struct PptpStartSessionRequest *sreq;
475 + struct PptpStartSessionReply *srep;
476 + struct PptpStopSessionReqest *streq;
477 + struct PptpStopSessionReply *strep;
478 + struct PptpOutCallRequest *ocreq;
479 + struct PptpOutCallReply *ocack;
480 + struct PptpInCallRequest *icreq;
481 + struct PptpInCallReply *icack;
482 + struct PptpInCallConnected *iccon;
483 + struct PptpClearCallRequest *clrreq;
484 + struct PptpCallDisconnectNotify *disc;
485 + struct PptpWanErrorNotify *wanerr;
486 + struct PptpSetLinkInfo *setlink;
491 +#define PPTP_CONTROL_PORT 1723
493 +#define PPTP_PACKET_CONTROL 1
494 +#define PPTP_PACKET_MGMT 2
496 +#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
498 +struct pptp_pkt_hdr {
499 + __u16 packetLength;
504 +/* PptpControlMessageType values */
505 +#define PPTP_START_SESSION_REQUEST 1
506 +#define PPTP_START_SESSION_REPLY 2
507 +#define PPTP_STOP_SESSION_REQUEST 3
508 +#define PPTP_STOP_SESSION_REPLY 4
509 +#define PPTP_ECHO_REQUEST 5
510 +#define PPTP_ECHO_REPLY 6
511 +#define PPTP_OUT_CALL_REQUEST 7
512 +#define PPTP_OUT_CALL_REPLY 8
513 +#define PPTP_IN_CALL_REQUEST 9
514 +#define PPTP_IN_CALL_REPLY 10
515 +#define PPTP_IN_CALL_CONNECT 11
516 +#define PPTP_CALL_CLEAR_REQUEST 12
517 +#define PPTP_CALL_DISCONNECT_NOTIFY 13
518 +#define PPTP_WAN_ERROR_NOTIFY 14
519 +#define PPTP_SET_LINK_INFO 15
521 +#define PPTP_MSG_MAX 15
523 +/* PptpGeneralError values */
524 +#define PPTP_ERROR_CODE_NONE 0
525 +#define PPTP_NOT_CONNECTED 1
526 +#define PPTP_BAD_FORMAT 2
527 +#define PPTP_BAD_VALUE 3
528 +#define PPTP_NO_RESOURCE 4
529 +#define PPTP_BAD_CALLID 5
530 +#define PPTP_REMOVE_DEVICE_ERROR 6
532 +struct PptpControlHeader {
537 +/* FramingCapability Bitmap Values */
538 +#define PPTP_FRAME_CAP_ASYNC 0x1
539 +#define PPTP_FRAME_CAP_SYNC 0x2
541 +/* BearerCapability Bitmap Values */
542 +#define PPTP_BEARER_CAP_ANALOG 0x1
543 +#define PPTP_BEARER_CAP_DIGITAL 0x2
545 +struct PptpStartSessionRequest {
546 + __u16 protocolVersion;
549 + __u32 framingCapability;
550 + __u32 bearerCapability;
552 + __u16 firmwareRevision;
554 + __u8 vendorString[64];
557 +/* PptpStartSessionResultCode Values */
558 +#define PPTP_START_OK 1
559 +#define PPTP_START_GENERAL_ERROR 2
560 +#define PPTP_START_ALREADY_CONNECTED 3
561 +#define PPTP_START_NOT_AUTHORIZED 4
562 +#define PPTP_START_UNKNOWN_PROTOCOL 5
564 +struct PptpStartSessionReply {
565 + __u16 protocolVersion;
567 + __u8 generalErrorCode;
568 + __u32 framingCapability;
569 + __u32 bearerCapability;
571 + __u16 firmwareRevision;
573 + __u8 vendorString[64];
576 +/* PptpStopReasons */
577 +#define PPTP_STOP_NONE 1
578 +#define PPTP_STOP_PROTOCOL 2
579 +#define PPTP_STOP_LOCAL_SHUTDOWN 3
581 +struct PptpStopSessionRequest {
585 +/* PptpStopSessionResultCode */
586 +#define PPTP_STOP_OK 1
587 +#define PPTP_STOP_GENERAL_ERROR 2
589 +struct PptpStopSessionReply {
591 + __u8 generalErrorCode;
594 +struct PptpEchoRequest {
598 +/* PptpEchoReplyResultCode */
599 +#define PPTP_ECHO_OK 1
600 +#define PPTP_ECHO_GENERAL_ERROR 2
602 +struct PptpEchoReply {
605 + __u8 generalErrorCode;
609 +/* PptpFramingType */
610 +#define PPTP_ASYNC_FRAMING 1
611 +#define PPTP_SYNC_FRAMING 2
612 +#define PPTP_DONT_CARE_FRAMING 3
614 +/* PptpCallBearerType */
615 +#define PPTP_ANALOG_TYPE 1
616 +#define PPTP_DIGITAL_TYPE 2
617 +#define PPTP_DONT_CARE_BEARER_TYPE 3
619 +struct PptpOutCallRequest {
621 + __u16 callSerialNumber;
626 + __u16 packetWindow;
627 + __u16 packetProcDelay;
629 + __u16 phoneNumberLength;
631 + __u8 phoneNumber[64];
632 + __u8 subAddress[64];
635 +/* PptpCallResultCode */
636 +#define PPTP_OUTCALL_CONNECT 1
637 +#define PPTP_OUTCALL_GENERAL_ERROR 2
638 +#define PPTP_OUTCALL_NO_CARRIER 3
639 +#define PPTP_OUTCALL_BUSY 4
640 +#define PPTP_OUTCALL_NO_DIAL_TONE 5
641 +#define PPTP_OUTCALL_TIMEOUT 6
642 +#define PPTP_OUTCALL_DONT_ACCEPT 7
644 +struct PptpOutCallReply {
648 + __u8 generalErrorCode;
650 + __u32 connectSpeed;
651 + __u16 packetWindow;
652 + __u16 packetProcDelay;
653 + __u32 physChannelID;
656 +struct PptpInCallRequest {
658 + __u16 callSerialNumber;
659 + __u32 callBearerType;
660 + __u32 physChannelID;
661 + __u16 dialedNumberLength;
662 + __u16 dialingNumberLength;
663 + __u8 dialedNumber[64];
664 + __u8 dialingNumber[64];
665 + __u8 subAddress[64];
668 +/* PptpInCallResultCode */
669 +#define PPTP_INCALL_ACCEPT 1
670 +#define PPTP_INCALL_GENERAL_ERROR 2
671 +#define PPTP_INCALL_DONT_ACCEPT 3
673 +struct PptpInCallReply {
677 + __u8 generalErrorCode;
678 + __u16 packetWindow;
679 + __u16 packetProcDelay;
683 +struct PptpInCallConnected {
686 + __u32 connectSpeed;
687 + __u16 packetWindow;
688 + __u16 packetProcDelay;
689 + __u32 callFramingType;
692 +struct PptpClearCallRequest {
697 +struct PptpCallDisconnectNotify {
700 + __u8 generalErrorCode;
703 + __u8 callStatistics[128];
706 +struct PptpWanErrorNotify {
710 + __u32 framingErrors;
711 + __u32 hardwareOverRuns;
712 + __u32 bufferOverRuns;
713 + __u32 timeoutErrors;
714 + __u32 alignmentErrors;
717 +struct PptpSetLinkInfo {
725 +struct pptp_priv_data {
731 +#endif /* __KERNEL__ */
732 +#endif /* _CONNTRACK_PPTP_H */
733 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
734 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 1970-01-01 01:00:00.000000000 +0100
735 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h 2003-11-17 09:09:34.000000000 +0100
737 +#ifndef _CONNTRACK_PROTO_GRE_H
738 +#define _CONNTRACK_PROTO_GRE_H
739 +#include <asm/byteorder.h>
741 +/* GRE PROTOCOL HEADER */
743 +/* GRE Version field */
744 +#define GRE_VERSION_1701 0x0
745 +#define GRE_VERSION_PPTP 0x1
747 +/* GRE Protocol field */
748 +#define GRE_PROTOCOL_PPTP 0x880B
751 +#define GRE_FLAG_C 0x80
752 +#define GRE_FLAG_R 0x40
753 +#define GRE_FLAG_K 0x20
754 +#define GRE_FLAG_S 0x10
755 +#define GRE_FLAG_A 0x80
757 +#define GRE_IS_C(f) ((f)&GRE_FLAG_C)
758 +#define GRE_IS_R(f) ((f)&GRE_FLAG_R)
759 +#define GRE_IS_K(f) ((f)&GRE_FLAG_K)
760 +#define GRE_IS_S(f) ((f)&GRE_FLAG_S)
761 +#define GRE_IS_A(f) ((f)&GRE_FLAG_A)
763 +/* GRE is a mess: Four different standards */
765 +#if defined(__LITTLE_ENDIAN_BITFIELD)
775 +#elif defined(__BIG_ENDIAN_BITFIELD)
786 +#error "Adjust your <asm/byteorder.h> defines"
791 +/* modified GRE header for PPTP */
792 +struct gre_hdr_pptp {
793 + __u8 flags; /* bitfield */
794 + __u8 version; /* should be GRE_VERSION_PPTP */
795 + __u16 protocol; /* should be GRE_PROTOCOL_PPTP */
796 + __u16 payload_len; /* size of ppp payload, not inc. gre header */
797 + __u16 call_id; /* peer's call_id for this session */
798 + __u32 seq; /* sequence number. Present if S==1 */
799 + __u32 ack; /* seq number of highest packet recieved by */
800 + /* sender in this session */
804 +/* this is part of ip_conntrack */
806 + unsigned int stream_timeout;
807 + unsigned int timeout;
810 +/* this is part of ip_conntrack_expect */
811 +struct ip_ct_gre_expect {
812 + struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
816 +struct ip_conntrack_expect;
818 +/* structure for original <-> reply keymap */
819 +struct ip_ct_gre_keymap {
820 + struct list_head list;
822 + struct ip_conntrack_tuple tuple;
826 +/* add new tuple->key_reply pair to keymap */
827 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
828 + struct ip_conntrack_tuple *t,
831 +/* change an existing keymap entry */
832 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
833 + struct ip_conntrack_tuple *t);
835 +/* delete keymap entries */
836 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
839 +/* get pointer to gre key, if present */
840 +static inline u_int32_t *gre_key(struct gre_hdr *greh)
844 + if (greh->csum || greh->routing)
845 + return (u_int32_t *) (greh+sizeof(*greh)+4);
846 + return (u_int32_t *) (greh+sizeof(*greh));
849 +/* get pointer ot gre csum, if present */
850 +static inline u_int16_t *gre_csum(struct gre_hdr *greh)
854 + return (u_int16_t *) (greh+sizeof(*greh));
857 +#endif /* __KERNEL__ */
859 +#endif /* _CONNTRACK_PROTO_GRE_H */
860 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
861 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
862 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2003-12-10 23:14:06.243005616 +0100
864 +#ifndef _IP_CT_QUAKE3
865 +#define _IP_CT_QUAKE3
867 +/* Don't confuse with 27960, often used as the Server Port */
868 +#define QUAKE3_MASTER_PORT 27950
870 +struct quake3_search {
871 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
872 + const char *pattern;
876 +/* This structure is per expected connection */
877 +struct ip_ct_quake3_expect {
880 +/* This structure exists only once per master */
881 +struct ip_ct_quake3_master {
884 +#endif /* _IP_CT_QUAKE3 */
885 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
886 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
887 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2003-12-10 23:14:10.155410840 +0100
889 +/* RPC extension for IP connection tracking, Version 2.2
890 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
891 + * - original rpc tracking module
892 + * - "recent" connection handling for kernel 2.3+ netfilter
894 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
895 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
897 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
898 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
899 + * - extended matching to support filtering on procedures
901 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
903 + * This program is free software; you can redistribute it and/or
904 + * modify it under the terms of the GNU General Public License
905 + * as published by the Free Software Foundation; either version
906 + * 2 of the License, or (at your option) any later version.
910 +#include <asm/param.h>
911 +#include <linux/sched.h>
912 +#include <linux/timer.h>
913 +#include <linux/stddef.h>
914 +#include <linux/list.h>
916 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
918 +#ifndef _IP_CONNTRACK_RPC_H
919 +#define _IP_CONNTRACK_RPC_H
921 +#define RPC_PORT 111
924 +/* Datum in RPC packets are encoded in XDR */
925 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
927 +/* Fast timeout, to deny DoS atacks */
928 +#define EXP (60 * HZ)
930 +/* Normal timeouts */
931 +#define EXPIRES (180 * HZ)
933 +/* For future conections RPC, using client's cache bindings
934 + * I'll use ip_conntrack_lock to lock these lists */
936 +/* This identifies each request and stores protocol */
938 + struct list_head list;
947 + struct timer_list timeout;
950 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
951 + u_int32_t ip, u_int32_t port) {
952 + return (p->xid == xid && p->ip == ip && p->port);
956 +#endif /* _IP_CONNTRACK_RPC_H */
957 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
958 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
959 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2003-12-10 23:14:11.556197888 +0100
961 +/* RSH extension for IP connection tracking, Version 1.0
962 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
963 + * based on HW's ip_conntrack_irc.c
965 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
967 + * This program is free software; you can redistribute it and/or
968 + * modify it under the terms of the GNU General Public License
969 + * as published by the Free Software Foundation; either version
970 + * 2 of the License, or (at your option) any later version.
972 +#ifndef _IP_CONNTRACK_RSH_H
973 +#define _IP_CONNTRACK_RSH_H
976 +#include <linux/netfilter_ipv4/lockhelp.h>
978 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
982 +#define RSH_PORT 514
984 +/* This structure is per expected connection */
985 +struct ip_ct_rsh_expect
990 +/* This structure exists only once per master */
991 +struct ip_ct_rsh_master {
994 +#endif /* _IP_CONNTRACK_RSH_H */
996 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
997 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
998 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2003-12-10 23:14:12.890994968 +0100
1001 + * RTSP extension for IP connection tracking.
1002 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
1003 + * based on ip_conntrack_irc.h
1005 + * This program is free software; you can redistribute it and/or
1006 + * modify it under the terms of the GNU General Public License
1007 + * as published by the Free Software Foundation; either version
1008 + * 2 of the License, or (at your option) any later version.
1010 +#ifndef _IP_CONNTRACK_RTSP_H
1011 +#define _IP_CONNTRACK_RTSP_H
1013 +/* #define IP_NF_RTSP_DEBUG */
1014 +#define IP_NF_RTSP_VERSION "0.01"
1016 +/* port block types */
1018 + pb_single, /* client_port=x */
1019 + pb_range, /* client_port=x-y */
1020 + pb_discon /* client_port=x/y (rtspbis) */
1023 +/* We record seq number and length of rtsp headers here, all in host order. */
1026 + * This structure is per expected connection. It is a member of struct
1027 + * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
1028 + * there and we are expected to only store the length of the data which
1029 + * needs replaced. If a packet contains multiple RTSP messages, we create
1030 + * one expected connection per message.
1032 + * We use these variables to mark the entire header block. This may seem
1033 + * like overkill, but the nature of RTSP requires it. A header may appear
1034 + * multiple times in a message. We must treat two Transport headers the
1035 + * same as one Transport header with two entries.
1037 +struct ip_ct_rtsp_expect
1039 + u_int32_t len; /* length of header block */
1040 + portblock_t pbtype; /* Type of port block that was requested */
1041 + u_int16_t loport; /* Port that was requested, low or first */
1042 + u_int16_t hiport; /* Port that was requested, high or second */
1044 + uint method; /* RTSP method */
1045 + uint cseq; /* CSeq from request */
1049 +/* This structure exists only once per master */
1050 +struct ip_ct_rtsp_master
1058 +#include <linux/netfilter_ipv4/lockhelp.h>
1060 +#define RTSP_PORT 554
1062 +/* Protects rtsp part of conntracks */
1063 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
1065 +#endif /* __KERNEL__ */
1067 +#endif /* _IP_CONNTRACK_RTSP_H */
1068 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
1069 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
1070 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2003-12-10 23:14:15.479601440 +0100
1072 +#ifndef _IP_CONNTRACK_TALK_H
1073 +#define _IP_CONNTRACK_TALK_H
1074 +/* TALK tracking. */
1077 +#include <linux/in.h>
1078 +#include <linux/netfilter_ipv4/lockhelp.h>
1080 +/* Protects talk part of conntracks */
1081 +DECLARE_LOCK_EXTERN(ip_talk_lock);
1085 +#define TALK_PORT 517
1086 +#define NTALK_PORT 518
1088 +/* talk structures and constants from <protocols/talkd.h> */
1091 + * 4.3BSD struct sockaddr
1094 + u_int16_t ta_family;
1095 + u_int16_t ta_port;
1096 + u_int32_t ta_addr;
1097 + u_int32_t ta_junk1;
1098 + u_int32_t ta_junk2;
1101 +#define TALK_OLD_NSIZE 9
1102 +#define TALK_NSIZE 12
1103 +#define TALK_TTY_NSIZE 16
1106 + * Client->server request message formats.
1109 + u_char type; /* request type, see below */
1110 + char l_name[TALK_OLD_NSIZE];/* caller's name */
1111 + char r_name[TALK_OLD_NSIZE];/* callee's name */
1113 + u_int32_t id_num; /* message id */
1114 + int32_t pid; /* caller's process id */
1115 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1116 + struct talk_addr addr; /* old (4.3) style */
1117 + struct talk_addr ctl_addr; /* old (4.3) style */
1121 + u_char vers; /* protocol version */
1122 + u_char type; /* request type, see below */
1123 + u_char answer; /* not used */
1125 + u_int32_t id_num; /* message id */
1126 + struct talk_addr addr; /* old (4.3) style */
1127 + struct talk_addr ctl_addr; /* old (4.3) style */
1128 + int32_t pid; /* caller's process id */
1129 + char l_name[TALK_NSIZE];/* caller's name */
1130 + char r_name[TALK_NSIZE];/* callee's name */
1131 + char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1134 +struct ntalk2_msg {
1135 + u_char vers; /* talk protocol version */
1136 + u_char type; /* request type */
1137 + u_char answer; /* */
1138 + u_char extended; /* !0 if additional parts */
1139 + u_int32_t id_num; /* message id number (dels) */
1140 + struct talk_addr addr; /* target address */
1141 + struct talk_addr ctl_addr; /* reply to address */
1142 + int32_t pid; /* caller's process id */
1143 + char l_name[TALK_NSIZE]; /* caller's name */
1144 + char r_name[TALK_NSIZE]; /* callee's name */
1145 + char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
1149 + * Server->client response message formats.
1151 +struct talk_response {
1152 + u_char type; /* type of request message, see below */
1153 + u_char answer; /* response to request message, see below */
1155 + u_int32_t id_num; /* message id */
1156 + struct talk_addr addr; /* address for establishing conversation */
1159 +struct ntalk_response {
1160 + u_char vers; /* protocol version */
1161 + u_char type; /* type of request message, see below */
1162 + u_char answer; /* response to request message, see below */
1164 + u_int32_t id_num; /* message id */
1165 + struct talk_addr addr; /* address for establishing conversation */
1168 +struct ntalk2_response {
1169 + u_char vers; /* protocol version */
1170 + u_char type; /* type of request message */
1171 + u_char answer; /* response to request */
1172 + u_char rvers; /* Version of answering vers*/
1173 + u_int32_t id_num; /* message id number */
1174 + struct talk_addr addr; /* address for connection */
1175 + /* This is at the end to compatiblize this with NTALK version. */
1176 + char r_name[TALK_NSIZE]; /* callee's name */
1179 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
1180 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
1181 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
1183 +#define TALK_VERSION 0 /* protocol versions */
1184 +#define NTALK_VERSION 1
1185 +#define NTALK2_VERSION 2
1187 +/* message type values */
1188 +#define LEAVE_INVITE 0 /* leave invitation with server */
1189 +#define LOOK_UP 1 /* check for invitation by callee */
1190 +#define DELETE 2 /* delete invitation by caller */
1191 +#define ANNOUNCE 3 /* announce invitation by caller */
1193 +#define REPLY_QUERY 4 /* request reply data from local daemon */
1195 +/* answer values */
1196 +#define SUCCESS 0 /* operation completed properly */
1197 +#define NOT_HERE 1 /* callee not logged in */
1198 +#define FAILED 2 /* operation failed for unexplained reason */
1199 +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
1200 +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
1201 +#define UNKNOWN_REQUEST 5 /* request has invalid type value */
1202 +#define BADVERSION 6 /* request has invalid protocol version */
1203 +#define BADADDR 7 /* request has invalid addr value */
1204 +#define BADCTLADDR 8 /* request has invalid ctl_addr value */
1206 +#define NO_CALLER 9 /* no-one calling answer from REPLY */
1207 +#define TRY_HERE 10 /* Not on this machine, try this */
1208 +#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
1209 +#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
1211 +/* We don't really need much for talk */
1212 +struct ip_ct_talk_expect
1214 + /* Port that was to be used */
1218 +/* This structure exists only once per master */
1219 +struct ip_ct_talk_master
1223 +#endif /* _IP_CONNTRACK_TALK_H */
1224 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
1225 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-11-26 21:44:58.000000000 +0100
1226 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-12-10 23:13:04.122449376 +0100
1228 union ip_conntrack_manip_proto
1230 /* Add other protocols here. */
1245 /* The manipulable part of the tuple. */
1249 /* Add other protocols here. */
1257 u_int8_t type, code;
1260 + u_int16_t protocol;
1270 #define DUMP_TUPLE(tp) \
1271 -DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
1272 +DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", \
1273 (tp), (tp)->dst.protonum, \
1274 - NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \
1275 - NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
1276 + NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all), \
1277 + NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
1279 +#define DUMP_TUPLE_RAW(x) \
1280 + DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
1281 + (x), (x)->dst.protonum, \
1282 + NIPQUAD((x)->src.ip), ntohl((x)->src.u.all), \
1283 + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
1285 #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
1287 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
1288 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_nat_pptp.h 1970-01-01 01:00:00.000000000 +0100
1289 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_nat_pptp.h 2003-11-17 09:09:34.000000000 +0100
1291 +/* PPTP constants and structs */
1292 +#ifndef _NAT_PPTP_H
1293 +#define _NAT_PPTP_H
1295 +/* conntrack private data */
1296 +struct ip_nat_pptp {
1297 + u_int16_t pns_call_id; /* NAT'ed PNS call id */
1298 + u_int16_t pac_call_id; /* NAT'ed PAC call id */
1301 +#endif /* _NAT_PPTP_H */
1302 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
1303 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
1304 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_pool.h 2003-12-10 23:13:39.981997896 +0100
1309 +/***************************************************************************/
1310 +/* This program is free software; you can redistribute it and/or modify */
1311 +/* it under the terms of the GNU General Public License as published by */
1312 +/* the Free Software Foundation; either version 2 of the License, or */
1313 +/* (at your option) any later version. */
1315 +/* This program is distributed in the hope that it will be useful, */
1316 +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
1317 +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
1318 +/* GNU General Public License for more details. */
1320 +/* You should have received a copy of the GNU General Public License */
1321 +/* along with this program; if not, write to the Free Software */
1322 +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
1323 +/***************************************************************************/
1325 +/* A sockopt of such quality has hardly ever been seen before on the open
1326 + * market! This little beauty, hardly ever used: above 64, so it's
1327 + * traditionally used for firewalling, not touched (even once!) by the
1328 + * 2.0, 2.2 and 2.4 kernels!
1330 + * Comes with its own certificate of authenticity, valid anywhere in the
1333 + * Rusty, 19.4.2000
1335 +#define SO_IP_POOL 81
1337 +typedef int ip_pool_t; /* pool index */
1338 +#define IP_POOL_NONE ((ip_pool_t)-1)
1340 +struct ip_pool_request {
1347 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
1349 +#define IP_POOL_BAD001 0x00000010
1351 +#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
1352 +#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
1353 +#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
1354 +#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
1355 +#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
1356 +#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
1357 +#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
1358 +#define IP_POOL_USAGE 0x00000018 /* result in addr */
1359 +#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
1363 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
1364 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
1365 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
1369 +#endif /*_IP_POOL_H*/
1370 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
1371 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_queue.h 2003-11-26 21:45:32.000000000 +0100
1372 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_queue.h 2003-12-10 23:14:19.439999368 +0100
1374 unsigned char payload[0]; /* Optional replacement packet */
1375 } ipq_verdict_msg_t;
1377 +typedef struct ipq_vwmark_msg {
1378 + unsigned int value; /* Verdict to hand to netfilter */
1379 + unsigned long id; /* Packet ID for this verdict */
1380 + size_t data_len; /* Length of replacement data */
1381 + unsigned char payload[0]; /* Optional replacement packet */
1382 + unsigned long nfmark; /* Mark for the Packet */
1383 +} ipq_vwmark_msg_t;
1386 typedef struct ipq_peer_msg {
1388 ipq_verdict_msg_t verdict;
1389 ipq_mode_msg_t mode;
1390 + ipq_vwmark_msg_t vwmark;
1395 #define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */
1396 #define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */
1397 #define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */
1398 -#define IPQM_MAX (IPQM_BASE + 4)
1399 +#define IPQM_VWMARK (IPQM_BASE + 4) /* Verdict and mark from peer */
1400 +#define IPQM_MAX (IPQM_BASE + 5)
1402 #endif /*_IP_QUEUE_H*/
1403 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
1404 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_tables.h 2003-11-26 21:44:17.000000000 +0100
1405 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_tables.h 2003-12-10 23:13:24.656327752 +0100
1406 @@ -134,6 +134,12 @@
1408 unsigned int comefrom;
1410 + /* Name of the chain */
1413 + /* Rule number in the chain. */
1414 + u_int32_t rulenum;
1416 /* Packet and byte counters. */
1417 struct ipt_counters counters;
1419 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
1420 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
1421 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_addrtype.h 2003-12-10 23:13:51.091309024 +0100
1423 +#ifndef _IPT_ADDRTYPE_H
1424 +#define _IPT_ADDRTYPE_H
1426 +struct ipt_addrtype_info {
1427 + u_int16_t source; /* source-type mask */
1428 + u_int16_t dest; /* dest-type mask */
1429 + int invert_source;
1434 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
1435 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_condition.h 1970-01-01 01:00:00.000000000 +0100
1436 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_condition.h 2003-12-10 23:13:53.355964744 +0100
1438 +#ifndef __IPT_CONDITION_MATCH__
1439 +#define __IPT_CONDITION_MATCH__
1441 +#define CONDITION_NAME_LEN 32
1443 +struct condition_info {
1444 + char name[CONDITION_NAME_LEN];
1449 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
1450 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
1451 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connlimit.h 2003-12-10 23:13:26.810000344 +0100
1453 +#ifndef _IPT_CONNLIMIT_H
1454 +#define _IPT_CONNLIMIT_H
1456 +struct ipt_connlimit_data;
1458 +struct ipt_connlimit_info {
1462 + struct ipt_connlimit_data *data;
1464 +#endif /* _IPT_CONNLIMIT_H */
1465 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
1466 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
1467 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connmark.h 2003-12-10 23:13:54.582778240 +0100
1469 +#ifndef _IPT_CONNMARK_H
1470 +#define _IPT_CONNMARK_H
1472 +struct ipt_connmark_info {
1473 + unsigned long mark, mask;
1477 +#endif /*_IPT_CONNMARK_H*/
1478 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
1479 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
1480 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2003-12-10 23:13:54.582778240 +0100
1482 +#ifndef _IPT_CONNMARK_H_target
1483 +#define _IPT_CONNMARK_H_target
1486 + IPT_CONNMARK_SET = 0,
1487 + IPT_CONNMARK_SAVE,
1488 + IPT_CONNMARK_RESTORE
1491 +struct ipt_connmark_target_info {
1492 + unsigned long mark;
1496 +#endif /*_IPT_CONNMARK_H_target*/
1497 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
1498 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-11-26 21:45:07.000000000 +0100
1499 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-12-10 23:13:24.657327600 +0100
1502 #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
1503 #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
1504 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
1506 /* flags, invflags: */
1507 #define IPT_CONNTRACK_STATE 0x01
1508 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
1509 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
1510 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_dstlimit.h 2003-12-10 23:13:27.868839376 +0100
1512 +#ifndef _IPT_DSTLIMIT_H
1513 +#define _IPT_DSTLIMIT_H
1515 +/* timings are in milliseconds. */
1516 +#define IPT_DSTLIMIT_SCALE 10000
1517 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
1518 + seconds, or one every 59 hours. */
1520 +/* details of this structure hidden by the implementation */
1521 +struct ipt_dstlimit_htable;
1523 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
1524 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
1525 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
1527 +struct ipt_dstlimit_info {
1528 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1529 + u_int32_t avg; /* Average secs between packets * scale */
1530 + u_int32_t burst; /* Period multiplier for upper limit. */
1532 + /* user specified */
1533 + unsigned int size; /* how many buckets */
1534 + unsigned int max; /* max number of entries */
1535 + unsigned int gc_interval; /* gc interval */
1536 + unsigned int expire; /* when do entries expire? */
1537 + char name [IFNAMSIZ]; /* name */
1539 + struct ipt_dstlimit_htable *hinfo;
1541 + /* Used internally by the kernel */
1544 + struct ipt_dstlimit_info *master;
1547 +#endif /*_IPT_DSTLIMIT_H*/
1548 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
1549 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1550 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_fuzzy.h 2003-12-10 23:13:30.016512880 +0100
1552 +#ifndef _IPT_FUZZY_H
1553 +#define _IPT_FUZZY_H
1555 +#include <linux/param.h>
1556 +#include <linux/types.h>
1558 +#define MAXFUZZYRATE 10000000
1559 +#define MINFUZZYRATE 3
1561 +struct ipt_fuzzy_info {
1562 + u_int32_t minimum_rate;
1563 + u_int32_t maximum_rate;
1564 + u_int32_t packets_total;
1565 + u_int32_t bytes_total;
1566 + u_int32_t previous_time;
1567 + u_int32_t present_time;
1568 + u_int32_t mean_rate;
1569 + u_int8_t acceptance_rate;
1572 +#endif /*_IPT_FUZZY_H*/
1573 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
1574 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
1575 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_IPMARK.h 2003-12-10 23:13:59.369050616 +0100
1577 +#ifndef _IPT_IPMARK_H_target
1578 +#define _IPT_IPMARK_H_target
1580 +struct ipt_ipmark_target_info {
1581 + unsigned long andmask;
1582 + unsigned long ormask;
1583 + unsigned int addr;
1586 +#define IPT_IPMARK_SRC 0
1587 +#define IPT_IPMARK_DST 1
1589 +#endif /*_IPT_IPMARK_H_target*/
1590 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
1591 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1592 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipv4options.h 2003-12-10 23:13:32.270170272 +0100
1594 +#ifndef __ipt_ipv4options_h_included__
1595 +#define __ipt_ipv4options_h_included__
1597 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1598 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1599 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1600 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1601 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1602 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1603 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1604 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1605 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1606 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1607 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1609 +struct ipt_ipv4options_info {
1610 + u_int16_t options;
1614 +#endif /* __ipt_ipv4options_h_included__ */
1615 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
1616 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mark.h 2003-11-26 21:45:46.000000000 +0100
1617 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mark.h 2003-12-10 23:14:21.806639584 +0100
1623 + IPT_MARK_BIT_OP_NONE,
1624 + IPT_MARK_BIT_OP_AND,
1625 + IPT_MARK_BIT_OP_OR
1628 struct ipt_mark_info {
1629 unsigned long mark, mask;
1634 #endif /*_IPT_MARK_H*/
1635 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
1636 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1637 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mport.h 2003-12-10 23:13:34.440840280 +0100
1639 +#ifndef _IPT_MPORT_H
1640 +#define _IPT_MPORT_H
1641 +#include <linux/netfilter_ipv4/ip_tables.h>
1643 +#define IPT_MPORT_SOURCE (1<<0)
1644 +#define IPT_MPORT_DESTINATION (1<<1)
1645 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1647 +#define IPT_MULTI_PORTS 15
1649 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1650 +/* every entry in ports[] except for the last one has one bit in pflags
1651 + * associated with it. If this bit is set, the port is the first port of
1652 + * a portrange, with the next entry being the last.
1653 + * End of list is marked with pflags bit set and port=65535.
1654 + * If 14 ports are used (last one does not have a pflag), the last port
1655 + * is repeated to fill the last entry in ports[] */
1658 + u_int8_t flags:2; /* Type of comparison */
1659 + u_int16_t pflags:14; /* Port flags */
1660 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1662 +#endif /*_IPT_MPORT_H*/
1663 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
1664 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
1665 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_NETLINK.h 2003-12-10 23:13:35.507678096 +0100
1667 +#ifndef _IPT_FWMON_H
1668 +#define _IPT_FWMON_H
1670 +/* Bitmask macros */
1671 +#define MASK(x,y) (x & y)
1672 +#define MASK_SET(x,y) x |= y
1673 +#define MASK_UNSET(x,y) x &= ~y
1675 +#define USE_MARK 0x00000001
1676 +#define USE_DROP 0x00000002
1677 +#define USE_SIZE 0x00000004
1681 + unsigned int flags;
1682 + unsigned int mark;
1683 + unsigned int size;
1689 + unsigned int mark;
1690 + char iface[IFNAMSIZ];
1693 +#endif /*_IPT_FWMON_H*/
1694 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
1695 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1696 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_nth.h 2003-12-10 23:13:37.748337464 +0100
1701 +#include <linux/param.h>
1702 +#include <linux/types.h>
1704 +#ifndef IPT_NTH_NUM_COUNTERS
1705 +#define IPT_NTH_NUM_COUNTERS 16
1708 +struct ipt_nth_info {
1716 +#endif /*_IPT_NTH_H*/
1717 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
1718 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1719 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_osf.h 2003-12-10 23:13:38.897162816 +0100
1724 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1727 + * This program is free software; you can redistribute it and/or modify
1728 + * it under the terms of the GNU General Public License as published by
1729 + * the Free Software Foundation; either version 2 of the License, or
1730 + * (at your option) any later version.
1732 + * This program is distributed in the hope that it will be useful,
1733 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1734 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1735 + * GNU General Public License for more details.
1737 + * You should have received a copy of the GNU General Public License
1738 + * along with this program; if not, write to the Free Software
1739 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1745 +#define MAXGENRELEN 32
1746 +#define MAXDETLEN 64
1748 +#include <linux/list.h>
1750 +struct ipt_osf_info
1752 + char genre[MAXGENRELEN];
1754 + int invert; /* UNSUPPORTED */
1760 + unsigned long val;
1763 +/* This struct represents IANA options
1764 + * http://www.iana.org/assignments/tcp-parameters
1768 + unsigned char kind;
1769 + unsigned char length;
1777 + struct list_head flist;
1778 + struct osf_wc wss;
1779 + unsigned char ttl;
1782 + char genre[MAXGENRELEN];
1783 + char version[MAXGENRELEN], subtype[MAXGENRELEN];
1785 + /* Not needed, but for consistency with original table from Michal Zalewski */
1786 + char details[MAXDETLEN];
1789 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1793 +/* Defines for IANA option kinds */
1795 +#define OSFOPT_EOL 0 /* End of options */
1796 +#define OSFOPT_NOP 1 /* NOP */
1797 +#define OSFOPT_MSS 2 /* Maximum segment size */
1798 +#define OSFOPT_WSO 3 /* Window scale option */
1799 +#define OSFOPT_SACKP 4 /* SACK permitted */
1800 +#define OSFOPT_SACK 5 /* SACK */
1801 +#define OSFOPT_ECHO 6
1802 +#define OSFOPT_ECHOREPLY 7
1803 +#define OSFOPT_TS 8 /* Timestamp option */
1804 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1805 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1806 +/* Others are not used in current OSF */
1808 +static struct osf_opt IANA_opts[] =
1815 + {5, 1 ,}, /* SACK length is not defined */
1821 + {11, 1,}, /* CC: Suppose 1 */
1822 + {12, 1,}, /* the same */
1823 + {13, 1,}, /* and here too */
1825 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1839 +#endif /* __KERNEL__ */
1841 +#endif /* _IPT_OSF_H */
1842 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
1843 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1844 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_pool.h 2003-12-10 23:13:39.981997896 +0100
1846 +#ifndef _IPT_POOL_H
1847 +#define _IPT_POOL_H
1849 +#include <linux/netfilter_ipv4/ip_pool.h>
1851 +#define IPT_POOL_INV_SRC 0x00000001
1852 +#define IPT_POOL_INV_DST 0x00000002
1853 +#define IPT_POOL_DEL_SRC 0x00000004
1854 +#define IPT_POOL_DEL_DST 0x00000008
1855 +#define IPT_POOL_INV_MOD_SRC 0x00000010
1856 +#define IPT_POOL_INV_MOD_DST 0x00000020
1857 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1858 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1859 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
1860 +#define IPT_POOL_MOD_DST_DROP 0x00000200
1863 +struct ipt_pool_info
1870 +#endif /*_IPT_POOL_H*/
1871 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
1872 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1873 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_psd.h 2003-12-10 23:13:41.104827200 +0100
1878 +#include <linux/param.h>
1879 +#include <linux/types.h>
1882 + * High port numbers have a lower weight to reduce the frequency of false
1883 + * positives, such as from passive mode FTP transfers.
1885 +#define PORT_WEIGHT_PRIV 3
1886 +#define PORT_WEIGHT_HIGH 1
1889 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1890 + * from the same source, with no longer than DELAY ticks between ports.
1892 +#define SCAN_MIN_COUNT 7
1893 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1894 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1895 +#define SCAN_DELAY_THRESHOLD (HZ * 3)
1898 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1899 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1900 + * HASH_MAX source addresses per the same hash value.
1902 +#define LIST_SIZE 0x100
1904 +#define HASH_SIZE (1 << HASH_LOG)
1905 +#define HASH_MAX 0x10
1907 +struct ipt_psd_info {
1908 + unsigned int weight_threshold;
1909 + unsigned int delay_threshold;
1910 + unsigned short lo_ports_weight;
1911 + unsigned short hi_ports_weight;
1914 +#endif /*_IPT_PSD_H*/
1915 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
1916 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1917 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_quota.h 2003-12-10 23:13:42.203660152 +0100
1919 +#ifndef _IPT_QUOTA_H
1920 +#define _IPT_QUOTA_H
1922 +/* print debug info in both kernel/netfilter module & iptable library */
1923 +//#define DEBUG_IPT_QUOTA
1925 +struct ipt_quota_info {
1929 +#endif /*_IPT_QUOTA_H*/
1930 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
1931 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1932 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_random.h 2003-12-10 23:13:44.404325600 +0100
1934 +#ifndef _IPT_RAND_H
1935 +#define _IPT_RAND_H
1937 +#include <linux/param.h>
1938 +#include <linux/types.h>
1940 +struct ipt_rand_info {
1944 +#endif /*_IPT_RAND_H*/
1945 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
1946 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1947 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_realm.h 2003-12-10 23:13:45.528154752 +0100
1949 +#ifndef _IPT_REALM_H
1950 +#define _IPT_REALM_H
1952 +struct ipt_realm_info {
1957 +#endif /*_IPT_REALM_H*/
1958 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
1959 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_REJECT.h 2003-11-26 21:45:21.000000000 +0100
1960 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_REJECT.h 2003-12-10 23:14:20.642816512 +0100
1963 struct ipt_reject_info {
1964 enum ipt_reject_with with; /* reject type */
1965 + u_int8_t fake_source_address; /* 1: fake src addr with original packet dest, 0: no fake */
1968 -#endif /*_IPT_REJECT_H*/
1969 +#endif /* _IPT_REJECT_H */
1970 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
1971 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
1972 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ROUTE.h 2003-12-10 23:14:07.501814248 +0100
1974 +/* Header file for iptables ipt_ROUTE target
1976 + * (C) 2002 by CĆ©dric de Launois <delaunois@info.ucl.ac.be>
1978 + * This software is distributed under GNU GPL v2, 1991
1980 +#ifndef _IPT_ROUTE_H_target
1981 +#define _IPT_ROUTE_H_target
1983 +#define IPT_ROUTE_IFNAMSIZ 16
1985 +struct ipt_route_target_info {
1986 + char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
1987 + char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
1988 + u_int32_t gw; /* IP address of gateway */
1992 +/* Values for "flags" field */
1993 +#define IPT_ROUTE_CONTINUE 0x01
1995 +#endif /*_IPT_ROUTE_H_target*/
1996 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
1997 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
1998 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_rpc.h 2003-12-10 23:14:10.155410840 +0100
2000 +/* RPC extension for IP netfilter matching, Version 2.2
2001 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2002 + * - original rpc tracking module
2003 + * - "recent" connection handling for kernel 2.3+ netfilter
2005 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2006 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2008 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2009 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
2010 + * - extended matching to support filtering on procedures
2012 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
2014 + * This program is free software; you can redistribute it and/or
2015 + * modify it under the terms of the GNU General Public License
2016 + * as published by the Free Software Foundation; either version
2017 + * 2 of the License, or (at your option) any later version.
2024 +struct ipt_rpc_data;
2026 +struct ipt_rpc_info {
2029 + const char c_procs[1408];
2031 + struct ipt_rpc_data *data;
2034 +#endif /* _IPT_RPC_H */
2035 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
2036 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
2037 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_sctp.h 2003-12-10 23:13:25.744162376 +0100
2039 +/* iptables module for matching the SCTP header
2041 + * (C) 2003 Harald Welte <laforge@gnumonks.org>
2043 + * This software is distributed under GNU GPL v2, 1991
2047 +#ifndef _IPT_SCTP_H
2048 +#define _IPT_SCTP_H
2050 +struct ipt_sctp_info {
2051 + u_int16_t spts[2]; /* Souce port range */
2052 + u_int16_t dpts[2]; /* Destination port range */
2053 + u_int32_t chunks; /* chunks to be matched */
2054 + u_int32_t chunk_mask; /* chunk mask to be matched */
2055 + u_int8_t invflags; /* Inverse flags */
2058 +#define IPT_SCTP_INV_SRCPT 0x01 /* Invert the sense of source ports */
2059 +#define IPT_SCTP_INV_DSTPT 0x02 /* Invert the sense of dest ports */
2060 +#define IPT_SCTP_INV_CHUNKS 0x03 /* Invert the sense of chunks */
2061 +#define IPT_SCTP_INV_MASK 0x03 /* All possible flags */
2063 +#endif /* _IPT_SCTP_H */
2064 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
2065 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_state.h 2003-11-26 21:45:27.000000000 +0100
2066 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_state.h 2003-12-10 23:13:24.657327600 +0100
2068 #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
2069 #define IPT_STATE_INVALID (1 << 0)
2071 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
2073 struct ipt_state_info
2075 unsigned int statemask;
2076 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
2077 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
2078 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_string.h 2003-12-10 23:14:14.164801320 +0100
2080 +#ifndef _IPT_STRING_H
2081 +#define _IPT_STRING_H
2083 +/* *** PERFORMANCE TWEAK ***
2084 + * Packet size and search string threshold,
2085 + * above which sublinear searches is used. */
2086 +#define IPT_STRING_HAYSTACK_THRESH 100
2087 +#define IPT_STRING_NEEDLE_THRESH 20
2089 +#define BM_MAX_NLEN 256
2090 +#define BM_MAX_HLEN 1024
2092 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
2094 +struct ipt_string_info {
2095 + char string[BM_MAX_NLEN];
2100 +#endif /* _IPT_STRING_H */
2101 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
2102 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h 1970-01-01 01:00:00.000000000 +0100
2103 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TCPLAG.h 2003-12-10 23:14:16.739409920 +0100
2105 +#ifndef _IPT_TCPLAG_H
2106 +#define _IPT_TCPLAG_H
2110 + unsigned char level;
2111 + unsigned char prefix[ 15 ];
2115 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
2116 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
2117 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_time.h 2003-12-10 23:13:47.814807128 +0100
2119 +#ifndef __ipt_time_h_included__
2120 +#define __ipt_time_h_included__
2123 +struct ipt_time_info {
2124 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
2125 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
2126 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
2127 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
2131 +#endif /* __ipt_time_h_included__ */
2132 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
2133 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
2134 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TTL.h 2003-12-10 23:13:48.933637040 +0100
2136 +/* TTL modification module for IP tables
2137 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
2148 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
2150 +struct ipt_TTL_info {
2157 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
2158 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
2159 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_u32.h 2003-12-10 23:13:50.005474096 +0100
2163 +#include <linux/netfilter_ipv4/ip_tables.h>
2173 +struct ipt_u32_location_element
2178 +struct ipt_u32_value_element
2183 +/* *** any way to allow for an arbitrary number of elements?
2184 + for now I settle for a limit of 10 of each */
2185 +#define U32MAXSIZE 10
2186 +struct ipt_u32_test
2189 + struct ipt_u32_location_element location[U32MAXSIZE+1];
2191 + struct ipt_u32_value_element value[U32MAXSIZE+1];
2197 + struct ipt_u32_test tests[U32MAXSIZE+1];
2200 +#endif /*_IPT_U32_H*/
2201 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
2202 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ULOG.h 2003-11-26 21:43:39.000000000 +0100
2203 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ULOG.h 2003-12-10 23:13:22.344679176 +0100
2205 #define NETLINK_NFLOG 5
2208 +#define NFLOG_DEFAULT_NLGROUP 1
2209 +#define NFLOG_DEFAULT_QTHRESHOLD 1
2211 #define ULOG_MAC_LEN 80
2212 #define ULOG_PREFIX_LEN 32
2214 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
2215 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
2216 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_XOR.h 2003-12-10 23:14:18.223184352 +0100
2221 +struct ipt_XOR_info {
2223 + u_int8_t block_size;
2226 +#endif /* _IPT_XOR_H */
2227 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h linux-2.6.0-test11/include/linux/netfilter_ipv4.h
2228 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h 2003-11-26 21:45:25.000000000 +0100
2229 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4.h 2003-12-10 23:13:24.657327600 +0100
2232 enum nf_ip_hook_priorities {
2233 NF_IP_PRI_FIRST = INT_MIN,
2234 + NF_IP_PRI_CONNTRACK_DEFRAG = -400,
2235 + NF_IP_PRI_RAW = -300,
2236 NF_IP_PRI_CONNTRACK = -200,
2237 NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
2238 NF_IP_PRI_MANGLE = -150,
2239 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
2240 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6_tables.h 2003-11-26 21:45:41.000000000 +0100
2241 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6_tables.h 2003-12-10 23:13:24.657327600 +0100
2242 @@ -140,6 +140,12 @@
2244 unsigned int comefrom;
2246 + /* Name of the chain */
2249 + /* Rule number in the chain. */
2250 + u_int32_t rulenum;
2252 /* Packet and byte counters. */
2253 struct ip6t_counters counters;
2255 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
2256 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_condition.h 1970-01-01 01:00:00.000000000 +0100
2257 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_condition.h 2003-12-10 23:13:52.255132096 +0100
2259 +#ifndef __IP6T_CONDITION_MATCH__
2260 +#define __IP6T_CONDITION_MATCH__
2262 +#define CONDITION6_NAME_LEN 32
2264 +struct condition6_info {
2265 + char name[CONDITION6_NAME_LEN];
2270 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
2271 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
2272 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2003-12-10 23:13:28.962673088 +0100
2274 +#ifndef _IP6T_FUZZY_H
2275 +#define _IP6T_FUZZY_H
2277 +#include <linux/param.h>
2278 +#include <linux/types.h>
2280 +#define MAXFUZZYRATE 10000000
2281 +#define MINFUZZYRATE 3
2283 +struct ip6t_fuzzy_info {
2284 + u_int32_t minimum_rate;
2285 + u_int32_t maximum_rate;
2286 + u_int32_t packets_total;
2287 + u_int32_t bytes_total;
2288 + u_int32_t previous_time;
2289 + u_int32_t present_time;
2290 + u_int32_t mean_rate;
2291 + u_int8_t acceptance_rate;
2294 +#endif /*_IP6T_FUZZY_H*/
2295 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
2296 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
2297 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_HL.h 2003-12-10 23:13:31.107347048 +0100
2299 +/* Hop Limit modification module for ip6tables
2300 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
2301 + * Based on HW's TTL module */
2312 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
2314 +struct ip6t_HL_info {
2316 + u_int8_t hop_limit;
2321 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
2322 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
2323 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_nth.h 2003-12-10 23:13:36.622508616 +0100
2325 +#ifndef _IP6T_NTH_H
2326 +#define _IP6T_NTH_H
2328 +#include <linux/param.h>
2329 +#include <linux/types.h>
2331 +#ifndef IP6T_NTH_NUM_COUNTERS
2332 +#define IP6T_NTH_NUM_COUNTERS 16
2335 +struct ip6t_nth_info {
2343 +#endif /*_IP6T_NTH_H*/
2344 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
2345 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_owner.h 2003-11-26 21:44:32.000000000 +0100
2346 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_owner.h 2003-12-10 23:14:05.028190296 +0100
2348 #define IP6T_OWNER_GID 0x02
2349 #define IP6T_OWNER_PID 0x04
2350 #define IP6T_OWNER_SID 0x08
2351 +#define IP6T_OWNER_COMM 0x10
2353 struct ip6t_owner_info {
2359 u_int8_t match, invert; /* flags */
2362 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
2363 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
2364 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_random.h 2003-12-10 23:13:43.304492800 +0100
2366 +#ifndef _IP6T_RAND_H
2367 +#define _IP6T_RAND_H
2369 +#include <linux/param.h>
2370 +#include <linux/types.h>
2372 +struct ip6t_rand_info {
2376 +#endif /*_IP6T_RAND_H*/
2377 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
2378 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2003-11-26 21:42:47.000000000 +0100
2379 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_REJECT.h 2003-12-10 23:13:46.679979648 +0100
2381 #define _IP6T_REJECT_H
2383 enum ip6t_reject_with {
2384 - IP6T_ICMP_NET_UNREACHABLE,
2385 - IP6T_ICMP_HOST_UNREACHABLE,
2386 - IP6T_ICMP_PROT_UNREACHABLE,
2387 - IP6T_ICMP_PORT_UNREACHABLE,
2388 - IP6T_ICMP_ECHOREPLY
2389 + IP6T_ICMP6_NO_ROUTE,
2390 + IP6T_ICMP6_ADM_PROHIBITED,
2391 + IP6T_ICMP6_NOT_NEIGHBOUR,
2392 + IP6T_ICMP6_ADDR_UNREACH,
2393 + IP6T_ICMP6_PORT_UNREACH,
2394 + IP6T_ICMP6_ECHOREPLY,
2398 struct ip6t_reject_info {
2399 enum ip6t_reject_with with; /* reject type */
2402 -#endif /*_IPT_REJECT_H*/
2403 +#endif /*_IP6T_REJECT_H*/
2404 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
2405 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h 1970-01-01 01:00:00.000000000 +0100
2406 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_ROUTE.h 2003-12-10 23:14:08.745625160 +0100
2408 +/* Header file for iptables ip6t_ROUTE target
2410 + * (C) 2003 by CĆ©dric de Launois <delaunois@info.ucl.ac.be>
2412 + * This software is distributed under GNU GPL v2, 1991
2414 +#ifndef _IPT_ROUTE_H_target
2415 +#define _IPT_ROUTE_H_target
2417 +#define IP6T_ROUTE_IFNAMSIZ 16
2419 +struct ip6t_route_target_info {
2420 + char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
2421 + char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
2422 + u_int32_t gw[4]; /* IPv6 address of gateway */
2426 +/* Values for "flags" field */
2427 +#define IP6T_ROUTE_CONTINUE 0x01
2429 +#endif /*_IP6T_ROUTE_H_target*/
2430 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_mime.h linux-2.6.0-test11/include/linux/netfilter_mime.h
2431 --- linux-2.6.0-test11.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
2432 +++ linux-2.6.0-test11/include/linux/netfilter_mime.h 2003-12-10 23:14:12.890994968 +0100
2435 + * MIME functions for netfilter modules. This file provides implementations
2436 + * for basic MIME parsing. MIME headers are used in many protocols, such as
2437 + * HTTP, RTSP, SIP, etc.
2439 + * gcc will warn for defined but unused functions, so we only include the
2440 + * functions requested. The following macros are used:
2441 + * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
2443 +#ifndef _NETFILTER_MIME_H
2444 +#define _NETFILTER_MIME_H
2446 +/* Only include these functions for kernel code. */
2449 +#include <linux/ctype.h>
2452 + * Given a buffer and length, advance to the next line and mark the current
2453 + * line. If the current line is empty, *plinelen will be set to zero. If
2454 + * not, it will be set to the actual line length (including CRLF).
2456 + * 'line' in this context means logical line (includes LWS continuations).
2457 + * Returns 1 on success, 0 on failure.
2459 +#ifdef NF_NEED_MIME_NEXTLINE
2461 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2465 + int is_first_line = 1;
2474 + while (p[off] != '\n')
2485 + /* if we saw a crlf, physlen needs adjusted */
2486 + if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2491 + /* advance past the newline */
2494 + /* check for an empty line */
2500 + /* check for colon on the first physical line */
2501 + if (is_first_line)
2503 + is_first_line = 0;
2504 + if (memchr(p+(*poff), ':', physlen) == NULL)
2510 + while (p[off] == ' ' || p[off] == '\t');
2512 + *plineoff = *poff;
2513 + *plinelen = (physlen == 0) ? 0 : (off - *poff);
2518 +#endif /* NF_NEED_MIME_NEXTLINE */
2520 +#endif /* __KERNEL__ */
2522 +#endif /* _NETFILTER_MIME_H */
2523 diff -Nur linux-2.6.0-test11.org/net/core/netfilter.c linux-2.6.0-test11/net/core/netfilter.c
2524 --- linux-2.6.0-test11.org/net/core/netfilter.c 2003-11-26 21:43:56.000000000 +0100
2525 +++ linux-2.6.0-test11/net/core/netfilter.c 2003-12-10 23:14:03.998346856 +0100
2528 * February 2000: Modified by James Morris to have 1 queue per protocol.
2529 * 15-Mar-2000: Added NF_REPEAT --RR.
2530 + * 08-May-2003: Internal logging interface added by Jozsef Kadlecsik.
2532 #include <linux/config.h>
2533 +#include <linux/kernel.h>
2534 #include <linux/netfilter.h>
2535 #include <net/protocol.h>
2536 #include <linux/init.h>
2538 } queue_handler[NPROTO];
2539 static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
2542 + * nf_register_hook - Register with a netfilter hook
2543 + * @reg: Hook operations to be registered
2545 int nf_register_hook(struct nf_hook_ops *reg)
2547 struct list_head *i;
2553 + * nf_unregister_hook - Unregister from a netfilter hook
2554 + * @reg: hook operations to be unregistered
2556 void nf_unregister_hook(struct nf_hook_ops *reg)
2558 spin_lock_bh(&nf_hook_lock);
2559 @@ -389,6 +399,18 @@
2564 + * nf_register_queue_handler - Registere a queue handler with netfilter
2565 + * @pf: protocol family
2566 + * @outfn: function called by core to enqueue a packet
2567 + * @data: opaque parameter, passed through
2569 + * This function registers a queue handler with netfilter. There can only
2570 + * be one queue handler for every protocol family.
2572 + * A queue handler _must_ reinject every packet via nf_reinject, no
2575 int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
2578 @@ -406,7 +428,12 @@
2582 -/* The caller must flush their queue before this */
2584 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
2585 + * @pf: protocol family
2587 + * The caller must flush their queue before unregistering
2589 int nf_unregister_queue_handler(int pf)
2591 write_lock_bh(&queue_handler_lock);
2592 @@ -549,6 +576,15 @@
2597 + * nf_reinject - Reinject a packet from a queue handler
2598 + * @skb: the packet to be reinjected
2599 + * @info: info which was passed to the outfn() of the queue handler
2600 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
2602 + * This is the function called by a queue handler to reinject a
2605 void nf_reinject(struct sk_buff *skb, struct nf_info *info,
2606 unsigned int verdict)
2608 @@ -743,7 +779,70 @@
2609 EXPORT_SYMBOL(skb_ip_make_writable);
2610 #endif /*CONFIG_INET*/
2612 +/* Internal logging interface, which relies on the real
2613 + LOG target modules */
2615 +#define NF_LOG_PREFIXLEN 128
2617 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
2618 +static int reported = 0;
2619 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
2621 +int nf_log_register(int pf, nf_logfn *logfn)
2625 + /* Any setup of logging members must be done before
2626 + * substituting pointer. */
2628 + spin_lock(&nf_log_lock);
2629 + if (!nf_logging[pf]) {
2630 + nf_logging[pf] = logfn;
2633 + spin_unlock(&nf_log_lock);
2637 +void nf_log_unregister(int pf, nf_logfn *logfn)
2639 + spin_lock(&nf_log_lock);
2640 + if (nf_logging[pf] == logfn)
2641 + nf_logging[pf] = NULL;
2642 + spin_unlock(&nf_log_lock);
2644 + /* Give time to concurrent readers. */
2645 + synchronize_net();
2648 +void nf_log_packet(int pf,
2649 + unsigned int hooknum,
2650 + const struct sk_buff *skb,
2651 + const struct net_device *in,
2652 + const struct net_device *out,
2653 + const char *fmt, ...)
2656 + char prefix[NF_LOG_PREFIXLEN];
2660 + logfn = nf_logging[pf];
2662 + va_start(args, fmt);
2663 + vsnprintf(prefix, sizeof(prefix), fmt, args);
2665 + /* We must read logging before nf_logfn[pf] */
2666 + smp_read_barrier_depends();
2667 + logfn(hooknum, skb, in, out, prefix);
2668 + } else if (!reported) {
2669 + printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
2670 + "no backend logging module loaded in!\n");
2673 + rcu_read_unlock();
2676 /* This does not belong here, but ipt_REJECT needs it if connection
2677 tracking in use: without this, connection may not be in hash table,
2678 and hence manufactured ICMP or RST packets will not be associated
2680 EXPORT_SYMBOL(ip_ct_attach);
2681 EXPORT_SYMBOL(ip_route_me_harder);
2682 EXPORT_SYMBOL(nf_getsockopt);
2683 +EXPORT_SYMBOL(nf_log_register);
2684 +EXPORT_SYMBOL(nf_log_unregister);
2685 +EXPORT_SYMBOL(nf_log_packet);
2686 EXPORT_SYMBOL(nf_hook_slow);
2687 EXPORT_SYMBOL(nf_hooks);
2688 EXPORT_SYMBOL(nf_register_hook);
2689 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
2690 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_core.c 2003-11-26 21:42:40.000000000 +0100
2691 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_core.c 2003-12-10 23:14:22.975461896 +0100
2694 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
2696 + * (C) 2000-2003 by the netfilter core team <coreteam@netfilter.org>
2698 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
2699 * - new API and handling of conntrack/nat helpers
2701 * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
2702 * - add usage/reference counts to ip_conntrack_expect
2703 * - export ip_conntrack[_expect]_{find_get,put} functions
2704 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
2705 + * - added DocBook-style comments for public API
2708 #include <linux/config.h>
2710 #include <linux/slab.h>
2711 #include <linux/random.h>
2712 #include <linux/jhash.h>
2713 -/* For ERR_PTR(). Yeah, I know... --RR */
2714 -#include <linux/fs.h>
2715 +#include <linux/err.h>
2717 /* This rwlock protects the main hash table, protocol/helper/expected
2718 registrations, conntrack timers*/
2720 static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
2721 struct list_head *ip_conntrack_hash;
2722 static kmem_cache_t *ip_conntrack_cachep;
2723 +struct ip_conntrack ip_conntrack_untracked;
2725 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
2732 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
2733 + * @protocol: protocol number
2735 struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
2737 struct ip_conntrack_protocol *p;
2739 inverse->dst.ip = orig->src.ip;
2740 inverse->dst.protonum = orig->dst.protonum;
2742 + inverse->src.u.all = inverse->dst.u.all = 0;
2744 return protocol->invert_tuple(inverse, orig);
2748 atomic_dec(&ip_conntrack_count);
2751 -static void death_by_timeout(unsigned long ul_conntrack)
2752 +void ip_ct_death_by_timeout(unsigned long ul_conntrack)
2754 struct ip_conntrack *ct = (void *)ul_conntrack;
2756 @@ -377,7 +386,14 @@
2760 -/* Find a connection corresponding to a tuple. */
2762 + * ip_conntrack_find_get - find conntrack according to tuple
2763 + * @tuple: conntrack tuple for which we search conntrack
2764 + * @ignored_conntrack: ignore this conntrack during search
2766 + * This function increments the reference count of the found
2767 + * conntrack (if any).
2769 struct ip_conntrack_tuple_hash *
2770 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
2771 const struct ip_conntrack *ignored_conntrack)
2772 @@ -405,7 +421,14 @@
2776 -/* Return conntrack and conntrack_info given skb->nfct->master */
2778 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
2779 + * @skb: skb for which we want to find conntrack and conntrack_info
2780 + * @ctinfo: pointer to ctinfo, used as return value
2782 + * This function resolves the respective conntrack and conntrack_info
2783 + * structures for the connection this packet (skb) is part of.
2785 struct ip_conntrack *
2786 ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
2788 @@ -475,8 +498,14 @@
2792 -/* Returns true if a connection correspondings to the tuple (required
2795 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
2796 + * @tuple: tuple to be used for this test
2797 + * @ignored_conntrack: conntrack which is excluded from result
2799 + * This function is called by the NAT code in order to find out if
2800 + * a particular tuple is already in use by some connection.
2803 ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
2804 const struct ip_conntrack *ignored_conntrack)
2808 if (del_timer(&h->ctrack->timeout)) {
2809 - death_by_timeout((unsigned long)h->ctrack);
2810 + ip_ct_death_by_timeout((unsigned long)h->ctrack);
2813 ip_conntrack_put(h->ctrack);
2814 @@ -602,7 +631,13 @@
2816 return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
2820 + * ip_ct_find_helper - Find application helper according to tuple
2821 + * @tuple: tuple for which helper needs to be found
2823 + * This function is used to determine if any registered conntrack helper
2824 + * is to be used for the given tuple.
2826 struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
2828 return LIST_FIND(&helpers, helper_cmp,
2830 /* Don't set timer yet: wait for confirmation */
2831 init_timer(&conntrack->timeout);
2832 conntrack->timeout.data = (unsigned long)conntrack;
2833 - conntrack->timeout.function = death_by_timeout;
2834 + conntrack->timeout.function = ip_ct_death_by_timeout;
2836 INIT_LIST_HEAD(&conntrack->sibling_list);
2839 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2840 conntrack->master = expected;
2841 expected->sibling = conntrack;
2842 +#if CONFIG_IP_NF_CONNTRACK_MARK
2843 + conntrack->mark = expected->expectant->mark;
2845 LIST_DELETE(&ip_conntrack_expect_list, expected);
2846 expected->expectant->expecting--;
2847 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2848 @@ -790,6 +828,15 @@
2852 + /* Never happen */
2853 + if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
2854 + if (net_ratelimit()) {
2855 + printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
2856 + (*pskb)->nh.iph->protocol, hooknum);
2861 /* FIXME: Do this right please. --RR */
2862 (*pskb)->nfcache |= NFC_UNKNOWN;
2864 @@ -808,18 +855,10 @@
2868 - /* Previously seen (loopback)? Ignore. Do this before
2869 - fragment check. */
2870 + /* Previously seen (loopback or untracked)? Ignore. */
2874 - /* Gather fragments. */
2875 - if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
2876 - *pskb = ip_ct_gather_frags(*pskb);
2881 proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
2883 /* It may be an icmp error... */
2884 @@ -896,6 +935,14 @@
2885 return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
2889 + * ip_conntrack_unexpect_related - Unexpect a related connection
2890 + * @expect: expecattin to be removed
2892 + * This function removes an existing expectation, that has not yet been
2893 + * confirmed (i.e. expectation was issued, but expected connection didn't
2896 inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
2898 WRITE_LOCK(&ip_conntrack_lock);
2899 @@ -913,7 +960,20 @@
2900 WRITE_UNLOCK(&ip_conntrack_lock);
2903 -/* Add a related connection. */
2905 + * ip_conntrack_expect_related - Expect a related connection
2906 + * @related_to: master conntrack
2907 + * @expect: expectation with all values filled in
2909 + * This function is called by conntrack application helpers who
2910 + * have detected that the control (master) connection is just about
2911 + * to negotiate a related slave connection.
2913 + * Note: This function allocates it's own struct ip_conntrack_expect,
2914 + * copying the values from the 'expect' parameter. Thus, 'expect' can
2915 + * be allocated on the stack and does not need to be valid after this
2916 + * function returns.
2918 int ip_conntrack_expect_related(struct ip_conntrack *related_to,
2919 struct ip_conntrack_expect *expect)
2922 * so there is no need to use the tuple lock too */
2924 DEBUGP("ip_conntrack_expect_related %p\n", related_to);
2925 - DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
2926 - DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
2927 + DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
2928 + DEBUGP("mask: "); DUMP_TUPLE_RAW(&expect->mask);
2930 old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
2931 struct ip_conntrack_expect *, &expect->tuple,
2932 @@ -953,7 +1013,6 @@
2934 } else if (related_to->helper->max_expected &&
2935 related_to->expecting >= related_to->helper->max_expected) {
2936 - struct list_head *cur_item;
2938 if (!(related_to->helper->flags &
2939 IP_CT_HELPER_F_REUSE_EXPECT)) {
2940 @@ -978,21 +1037,14 @@
2941 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
2943 /* choose the the oldest expectation to evict */
2944 - list_for_each(cur_item, &related_to->sibling_list) {
2945 - struct ip_conntrack_expect *cur;
2947 - cur = list_entry(cur_item,
2948 - struct ip_conntrack_expect,
2950 - if (cur->sibling == NULL) {
2952 + list_for_each_entry(old, &related_to->sibling_list,
2954 + if (old->sibling == NULL)
2959 - /* (!old) cannot happen, since related_to->expecting is the
2960 - * number of unconfirmed expects */
2961 - IP_NF_ASSERT(old);
2962 + /* We cannot fail since related_to->expecting is the number
2963 + * of unconfirmed expectations */
2964 + IP_NF_ASSERT(old && old->sibling == NULL);
2966 /* newnat14 does not reuse the real allocated memory
2967 * structures but rather unexpects the old and
2968 @@ -1024,7 +1076,7 @@
2969 atomic_set(&new->use, 1);
2971 /* add to expected list for this connection */
2972 - list_add(&new->expected_list, &related_to->sibling_list);
2973 + list_add_tail(&new->expected_list, &related_to->sibling_list);
2974 /* add to global list of expectations */
2975 list_prepend(&ip_conntrack_expect_list, &new->list);
2976 /* add and start timer if required */
2977 @@ -1043,7 +1095,15 @@
2981 -/* Change tuple in an existing expectation */
2983 + * ip_conntrack_change_expect - Change tuple in existing expectation
2984 + * @expect: expectation which is to be changed
2985 + * @newtuple: new tuple for expect
2987 + * This function is mostly called by NAT application helpers, who want to
2988 + * change an expectation issued by their respective conntrack application
2989 + * helper counterpart.
2991 int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
2992 struct ip_conntrack_tuple *newtuple)
2994 @@ -1051,15 +1111,14 @@
2996 MUST_BE_READ_LOCKED(&ip_conntrack_lock);
2997 WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
2999 DEBUGP("change_expect:\n");
3000 - DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
3001 - DEBUGP("exp mask: "); DUMP_TUPLE(&expect->mask);
3002 - DEBUGP("newtuple: "); DUMP_TUPLE(newtuple);
3003 + DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
3004 + DEBUGP("exp mask: "); DUMP_TUPLE_RAW(&expect->mask);
3005 + DEBUGP("newtuple: "); DUMP_TUPLE_RAW(newtuple);
3006 if (expect->ct_tuple.dst.protonum == 0) {
3007 /* Never seen before */
3008 DEBUGP("change expect: never seen before\n");
3009 - if (!ip_ct_tuple_equal(&expect->tuple, newtuple)
3010 + if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
3011 && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
3012 struct ip_conntrack_expect *, newtuple, &expect->mask)) {
3013 /* Force NAT to find an unused tuple */
3014 @@ -1084,8 +1143,15 @@
3018 -/* Alter reply tuple (maybe alter helper). If it's already taken,
3019 - return 0 and don't do alteration. */
3021 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
3022 + * @conntrack: conntrack whose reply tuple we want to alter
3023 + * @newreply: designated reply tuple for this conntrack
3025 + * This function alters the reply tuple of a conntrack to the given
3026 + * newreply tuple. If this newreply tuple is already taken, return 0
3027 + * and don't do alteration
3029 int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
3030 const struct ip_conntrack_tuple *newreply)
3032 @@ -1110,6 +1176,13 @@
3037 + * ip_conntrack_helper_register - Register a conntrack application helper
3038 + * @me: structure describing the helper
3040 + * This function is called by conntrack application helpers to register
3041 + * themselves with the conntrack core.
3043 int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
3045 WRITE_LOCK(&ip_conntrack_lock);
3046 @@ -1131,6 +1204,13 @@
3051 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
3052 + * @me: structure describing the helper
3054 + * This function is called by conntrack application helpers to unregister
3055 + * themselvers from the conntrack core.
3057 void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
3060 @@ -1149,7 +1229,14 @@
3064 -/* Refresh conntrack for this many jiffies. */
3066 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
3067 + * @ct: conntrack which we want to refresh
3068 + * @extra_jiffies: number of jiffies to add
3070 + * This function is called by protocol helpers and application helpers in
3071 + * order to change the expiration timer of a conntrack entry.
3073 void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
3075 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
3076 @@ -1159,8 +1246,10 @@
3077 if (!is_confirmed(ct))
3078 ct->timeout.expires = extra_jiffies;
3080 - /* Need del_timer for race avoidance (may already be dying). */
3081 - if (del_timer(&ct->timeout)) {
3082 + /* Don't update timer for each packet, only if it's been >HZ
3083 + * ticks since last update.
3084 + * Need del_timer for race avoidance (may already be dying). */
3085 + if (abs(jiffies + extra_jiffies - ct->timeout.expires) >= HZ && del_timer(&ct->timeout)) {
3086 ct->timeout.expires = jiffies + extra_jiffies;
3087 add_timer(&ct->timeout);
3089 @@ -1168,7 +1257,16 @@
3090 WRITE_UNLOCK(&ip_conntrack_lock);
3093 -/* Returns new sk_buff, or NULL */
3096 + * ip_ct_gather_frags - Gather fragments of a particular skb
3097 + * @skb: pointer to sk_buff of fragmented IP packet
3099 + * This code is just a wrapper around the defragmentation code in the core IPv4
3100 + * stack. It also takes care of nonlinear skb's.
3102 + * Returns new sk_buff, or NULL
3105 ip_ct_gather_frags(struct sk_buff *skb)
3107 @@ -1253,6 +1351,16 @@
3112 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
3113 + * @kill: callback function selecting which entries to delete
3114 + * @data: opaque data pointer, becomes 2nd argument for kill function
3116 + * This function can be used to selectively delete elements of the conntrack
3117 + * hashtable. The function iterates over the list of conntrack entries and
3118 + * calls the 'kill' function for every entry. If the return value is true,
3119 + * the connection is deleted (death_by_timeout).
3122 ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
3124 @@ -1263,7 +1371,7 @@
3125 while ((h = get_next_corpse(kill, data)) != NULL) {
3126 /* Time to push up daises... */
3127 if (del_timer(&h->ctrack->timeout))
3128 - death_by_timeout((unsigned long)h->ctrack);
3129 + ip_ct_death_by_timeout((unsigned long)h->ctrack);
3130 /* ... else the timer will get him soon. */
3132 ip_conntrack_put(h->ctrack);
3133 @@ -1419,6 +1527,15 @@
3135 /* For use by ipt_REJECT */
3136 ip_ct_attach = ip_conntrack_attach;
3138 + /* Set up fake conntrack:
3139 + - to never be deleted, not in any hashes */
3140 + atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
3141 + /* - and look it like as a confirmed connection */
3142 + set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
3143 + /* - and prepare the ctinfo field for NAT. */
3144 + ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
3149 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
3150 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3151 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_egg.c 2003-12-10 23:13:56.912424080 +0100
3153 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3154 + * based on ip_conntrack_irc.c
3156 + * This module only supports the share userfile-send command,
3157 + * used by eggdrops to share it's userfile.
3159 + * There are no support for NAT at the moment.
3161 + * This program is free software; you can redistribute it and/or
3162 + * modify it under the terms of the GNU General Public License
3163 + * as published by the Free Software Foundation; either version
3164 + * 2 of the License, or (at your option) any later version.
3166 + * Module load syntax:
3168 + * please give the ports of all Eggdrops You have running
3169 + * on your system, the default port is 3333.
3171 + * 2001-04-19: Security update. IP addresses are now compared
3172 + * to prevent unauthorized "related" access.
3174 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3175 + * Port to netfilter 'newnat' API.
3178 +#include <linux/module.h>
3179 +#include <linux/netfilter.h>
3180 +#include <linux/ip.h>
3181 +#include <net/checksum.h>
3182 +#include <net/tcp.h>
3184 +#include <linux/netfilter_ipv4/lockhelp.h>
3185 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3187 +#define MAX_PORTS 8
3188 +static int ports[MAX_PORTS];
3189 +static int ports_c = 0;
3190 +static unsigned int egg_timeout = 300;
3192 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3193 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3194 +MODULE_LICENSE("GPL");
3196 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3197 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3200 +DECLARE_LOCK(ip_egg_lock);
3201 +struct module *ip_conntrack_egg = THIS_MODULE;
3204 +#define DEBUGP printk
3206 +#define DEBUGP(format, args...)
3209 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3210 +/* tries to get the ip_addr and port out of a eggdrop command
3211 + return value: -1 on failure, 0 on success
3212 + data pointer to first byte of DCC command data
3213 + data_end pointer to last byte of dcc command data
3214 + ip returns parsed ip of dcc command
3215 + port returns parsed port of dcc command */
3217 + if (data > data_end)
3220 + *ip = simple_strtoul(data, &data, 10);
3222 + /* skip blanks between ip and port */
3223 + while (*data == ' ' && data < data_end)
3226 + *port = simple_strtoul(data, &data, 10);
3231 +static int help(const struct iphdr *iph, size_t len,
3232 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3234 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3235 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3236 + char *data = (char *) tcph + tcph->doff * 4;
3238 + u_int32_t tcplen = len - iph->ihl * 4;
3239 + u_int32_t datalen = tcplen - tcph->doff * 4;
3240 + int dir = CTINFO2DIR(ctinfo);
3241 + int bytes_scanned = 0;
3242 + struct ip_conntrack_expect exp;
3245 + u_int16_t egg_port;
3247 + DEBUGP("entered\n");
3249 + /* If packet is coming from IRC server */
3250 + if (dir != IP_CT_DIR_REPLY)
3253 + /* Until there's been traffic both ways, don't look in packets. */
3254 + if (ctinfo != IP_CT_ESTABLISHED
3255 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3256 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
3260 + /* Not whole TCP header? */
3261 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3262 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3266 + /* Checksum invalid? Ignore. */
3267 + /* FIXME: Source route IP option packets --RR */
3268 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3269 + csum_partial((char *) tcph, tcplen, 0))) {
3270 + DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3271 + tcph, tcplen, NIPQUAD(iph->saddr),
3272 + NIPQUAD(iph->daddr));
3276 + data_limit = (char *) data + datalen;
3277 + while (datalen > 5 && bytes_scanned < 128) {
3278 + if (memcmp(data, "s us ", 5)) {
3287 + DEBUGP("Userfile-share found in connection "
3288 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3289 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3291 + if (parse_command((char *) data, data_limit, &egg_ip,
3293 + DEBUGP("no data in userfile-share pkt\n");
3297 + memset(&exp, 0, sizeof(exp));
3299 + if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3300 + if (net_ratelimit())
3301 + printk("Forged Eggdrop command from "
3302 + "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3303 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3304 + HIPQUAD(egg_ip), egg_port);
3308 + exp.tuple.src.ip = iph->daddr;
3309 + exp.tuple.src.u.tcp.port = 0;
3310 + exp.tuple.dst.ip = htonl(egg_ip);
3311 + exp.tuple.dst.u.tcp.port = htons(egg_port);
3312 + exp.tuple.dst.protonum = IPPROTO_TCP;
3314 + exp.mask.dst.u.tcp.port = 0xffff;
3315 + exp.mask.dst.protonum = 0xffff;
3317 + DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3318 + NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3319 + NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3321 + ip_conntrack_expect_related(ct, &exp);
3327 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3328 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3330 +static void deregister_helpers(void) {
3333 + for (i = 0; i < ports_c; i++) {
3334 + DEBUGP("unregistering helper for port %d\n", ports[i]);
3335 + ip_conntrack_helper_unregister(&egg_helpers[i]);
3339 +static int __init init(void)
3344 + /* If no port given, default to standard eggdrop port */
3345 + if (ports[0] == 0)
3348 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3349 + memset(&egg_helpers[i], 0,
3350 + sizeof(struct ip_conntrack_helper));
3351 + egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3352 + egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3353 + egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3354 + egg_helpers[i].mask.dst.protonum = 0xFFFF;
3355 + egg_helpers[i].max_expected = 1;
3356 + egg_helpers[i].timeout = egg_timeout;
3357 + egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3358 + egg_helpers[i].me = THIS_MODULE;
3359 + egg_helpers[i].help = help;
3361 + tmpname = &egg_names[i][0];
3362 + if (ports[i] == 3333)
3363 + sprintf(tmpname, "eggdrop");
3365 + sprintf(tmpname, "eggdrop-%d", ports[i]);
3366 + egg_helpers[i].name = tmpname;
3368 + DEBUGP("port #%d: %d\n", i, ports[i]);
3370 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
3373 + printk("ip_conntrack_egg: ERROR registering helper "
3374 + "for port %d\n", ports[i]);
3375 + deregister_helpers();
3383 +static void __exit fini(void)
3385 + deregister_helpers();
3390 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
3391 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3392 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_h323.c 2003-12-10 23:13:58.177231800 +0100
3395 + * H.323 'brute force' extension for H.323 connection tracking.
3396 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3398 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3399 + * (http://www.coritel.it/projects/sofia/nat/)
3400 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3401 + * the unregistered helpers to the conntrack entries.
3405 +#include <linux/module.h>
3406 +#include <linux/netfilter.h>
3407 +#include <linux/ip.h>
3408 +#include <net/checksum.h>
3409 +#include <net/tcp.h>
3411 +#include <linux/netfilter_ipv4/lockhelp.h>
3412 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3413 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3414 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3415 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3416 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3418 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3419 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3420 +MODULE_LICENSE("GPL");
3422 +DECLARE_LOCK(ip_h323_lock);
3423 +struct module *ip_conntrack_h323 = THIS_MODULE;
3426 +#define DEBUGP printk
3428 +#define DEBUGP(format, args...)
3431 +/* FIXME: This should be in userspace. Later. */
3432 +static int h245_help(const struct iphdr *iph, size_t len,
3433 + struct ip_conntrack *ct,
3434 + enum ip_conntrack_info ctinfo)
3436 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3437 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3438 + unsigned char *data_limit;
3439 + u_int32_t tcplen = len - iph->ihl * 4;
3440 + u_int32_t datalen = tcplen - tcph->doff * 4;
3441 + int dir = CTINFO2DIR(ctinfo);
3442 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3443 + struct ip_conntrack_expect expect, *exp = &expect;
3444 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3445 + u_int16_t data_port;
3446 + u_int32_t data_ip;
3449 + DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3450 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3451 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3453 + /* Can't track connections formed before we registered */
3457 + /* Until there's been traffic both ways, don't look in packets. */
3458 + if (ctinfo != IP_CT_ESTABLISHED
3459 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3460 + DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3464 + /* Not whole TCP header or too short packet? */
3465 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3466 + DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3470 + /* Checksum invalid? Ignore. */
3471 + /* FIXME: Source route IP option packets --RR */
3472 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3473 + csum_partial((char *)tcph, tcplen, 0))) {
3474 + DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3475 + tcph, tcplen, NIPQUAD(iph->saddr),
3476 + NIPQUAD(iph->daddr));
3480 + data_limit = (unsigned char *) data + datalen;
3483 + for (i = 0; data < (data_limit - 5); data++, i++) {
3484 + data_ip = *((u_int32_t *)data);
3485 + if (data_ip == iph->saddr) {
3486 + data_port = *((u_int16_t *)(data + 4));
3487 + memset(&expect, 0, sizeof(expect));
3488 + /* update the H.225 info */
3489 + DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3490 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3491 + NIPQUAD(iph->saddr), ntohs(data_port));
3492 + LOCK_BH(&ip_h323_lock);
3493 + info->is_h225 = H225_PORT + 1;
3494 + exp_info->port = data_port;
3495 + exp_info->dir = dir;
3496 + exp_info->offset = i;
3498 + exp->seq = ntohl(tcph->seq) + i;
3500 + exp->tuple = ((struct ip_conntrack_tuple)
3501 + { { ct->tuplehash[!dir].tuple.src.ip,
3504 + { .tcp = { data_port } },
3506 + exp->mask = ((struct ip_conntrack_tuple)
3507 + { { 0xFFFFFFFF, { 0 } },
3508 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3510 + exp->expectfn = NULL;
3512 + /* Ignore failure; should only happen with NAT */
3513 + ip_conntrack_expect_related(ct, exp);
3515 + UNLOCK_BH(&ip_h323_lock);
3523 +/* H.245 helper is not registered! */
3524 +static struct ip_conntrack_helper h245 =
3526 + "H.245", /* name */
3527 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3528 + NULL, /* module */
3529 + 8, /* max_ expected */
3530 + 240, /* timeout */
3531 + { { 0, { 0 } }, /* tuple */
3532 + { 0, { 0 }, IPPROTO_TCP } },
3533 + { { 0, { 0xFFFF } }, /* mask */
3534 + { 0, { 0 }, 0xFFFF } },
3535 + h245_help /* helper */
3538 +static int h225_expect(struct ip_conntrack *ct)
3540 + WRITE_LOCK(&ip_conntrack_lock);
3541 + ct->helper = &h245;
3542 + DEBUGP("h225_expect: helper for %p added\n", ct);
3543 + WRITE_UNLOCK(&ip_conntrack_lock);
3545 + return NF_ACCEPT; /* unused */
3548 +/* FIXME: This should be in userspace. Later. */
3549 +static int h225_help(const struct iphdr *iph, size_t len,
3550 + struct ip_conntrack *ct,
3551 + enum ip_conntrack_info ctinfo)
3553 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3554 + unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3555 + unsigned char *data_limit;
3556 + u_int32_t tcplen = len - iph->ihl * 4;
3557 + u_int32_t datalen = tcplen - tcph->doff * 4;
3558 + int dir = CTINFO2DIR(ctinfo);
3559 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3560 + struct ip_conntrack_expect expect, *exp = &expect;
3561 + struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3562 + u_int16_t data_port;
3563 + u_int32_t data_ip;
3566 + DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3567 + NIPQUAD(iph->saddr), ntohs(tcph->source),
3568 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
3570 + /* Can't track connections formed before we registered */
3574 + /* Until there's been traffic both ways, don't look in packets. */
3575 + if (ctinfo != IP_CT_ESTABLISHED
3576 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3577 + DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3581 + /* Not whole TCP header or too short packet? */
3582 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3583 + DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3587 + /* Checksum invalid? Ignore. */
3588 + /* FIXME: Source route IP option packets --RR */
3589 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3590 + csum_partial((char *)tcph, tcplen, 0))) {
3591 + DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3592 + tcph, tcplen, NIPQUAD(iph->saddr),
3593 + NIPQUAD(iph->daddr));
3597 + data_limit = (unsigned char *) data + datalen;
3600 + for (i = 0; data < (data_limit - 5); data++, i++) {
3601 + data_ip = *((u_int32_t *)data);
3602 + if (data_ip == iph->saddr) {
3603 + data_port = *((u_int16_t *)(data + 4));
3604 + if (data_port == tcph->source) {
3605 + /* Signal address */
3606 + DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3607 + NIPQUAD(iph->saddr));
3608 + /* Update the H.225 info so that NAT can mangle the address/port
3609 + even when we have no expected connection! */
3610 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3611 + LOCK_BH(&ip_h323_lock);
3613 + info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3614 + info->offset[IP_CT_DIR_ORIGINAL] = i;
3615 + UNLOCK_BH(&ip_h323_lock);
3618 + memset(&expect, 0, sizeof(expect));
3620 + /* update the H.225 info */
3621 + LOCK_BH(&ip_h323_lock);
3622 + info->is_h225 = H225_PORT;
3623 + exp_info->port = data_port;
3624 + exp_info->dir = dir;
3625 + exp_info->offset = i;
3627 + exp->seq = ntohl(tcph->seq) + i;
3629 + exp->tuple = ((struct ip_conntrack_tuple)
3630 + { { ct->tuplehash[!dir].tuple.src.ip,
3633 + { .tcp = { data_port } },
3635 + exp->mask = ((struct ip_conntrack_tuple)
3636 + { { 0xFFFFFFFF, { 0 } },
3637 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3639 + exp->expectfn = h225_expect;
3641 + /* Ignore failure */
3642 + ip_conntrack_expect_related(ct, exp);
3644 + DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3645 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3646 + NIPQUAD(iph->saddr), ntohs(data_port));
3648 + UNLOCK_BH(&ip_h323_lock);
3650 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3651 + } else if (data_ip == iph->daddr) {
3652 + data_port = *((u_int16_t *)(data + 4));
3653 + if (data_port == tcph->dest) {
3654 + /* Signal address */
3655 + DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3656 + NIPQUAD(iph->daddr));
3657 + /* Update the H.225 info so that NAT can mangle the address/port
3658 + even when we have no expected connection! */
3659 + LOCK_BH(&ip_h323_lock);
3661 + info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3662 + info->offset[IP_CT_DIR_REPLY] = i;
3663 + UNLOCK_BH(&ip_h323_lock);
3673 +static struct ip_conntrack_helper h225 =
3675 + "H.225", /* name */
3676 + IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3677 + THIS_MODULE, /* module */
3678 + 2, /* max_expected */
3679 + 240, /* timeout */
3680 + { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
3681 + { 0, { 0 }, IPPROTO_TCP } },
3682 + { { 0, { 0xFFFF } }, /* mask */
3683 + { 0, { 0 }, 0xFFFF } },
3684 + h225_help /* helper */
3687 +static int __init init(void)
3689 + return ip_conntrack_helper_register(&h225);
3692 +static void __exit fini(void)
3694 + /* Unregister H.225 helper */
3695 + ip_conntrack_helper_unregister(&h225);
3698 +EXPORT_SYMBOL(ip_h323_lock);
3702 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
3703 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
3704 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_mms.c 2003-12-10 23:14:02.756535640 +0100
3706 +/* MMS extension for IP connection tracking
3707 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3708 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3710 + * ip_conntrack_mms.c v0.3 2002-09-22
3712 + * This program is free software; you can redistribute it and/or
3713 + * modify it under the terms of the GNU General Public License
3714 + * as published by the Free Software Foundation; either version
3715 + * 2 of the License, or (at your option) any later version.
3717 + * Module load syntax:
3718 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3720 + * Please give the ports of all MMS servers You wish to connect to.
3721 + * If you don't specify ports, the default will be TCP port 1755.
3723 + * More info on MMS protocol, firewalls and NAT:
3724 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3725 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3727 + * The SDP project people are reverse-engineering MMS:
3728 + * http://get.to/sdp
3731 +#include <linux/config.h>
3732 +#include <linux/module.h>
3733 +#include <linux/netfilter.h>
3734 +#include <linux/ip.h>
3735 +#include <linux/ctype.h>
3736 +#include <net/checksum.h>
3737 +#include <net/tcp.h>
3739 +#include <linux/netfilter_ipv4/lockhelp.h>
3740 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3741 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3743 +DECLARE_LOCK(ip_mms_lock);
3744 +struct module *ip_conntrack_mms = THIS_MODULE;
3746 +#define MAX_PORTS 8
3747 +static int ports[MAX_PORTS];
3748 +static int ports_c;
3750 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3754 +#define DEBUGP printk
3756 +#define DEBUGP(format, args...)
3759 +EXPORT_SYMBOL(ip_mms_lock);
3761 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3762 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3763 +MODULE_LICENSE("GPL");
3765 +/* #define isdigit(c) (c >= '0' && c <= '9') */
3767 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3768 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3771 + for (i = 0; i < unicode_size; ++i) {
3772 + string[i] = (char)(unicode[i]);
3774 + string[unicode_size] = 0x00;
3777 +__inline static int atoi(char *s)
3780 + while (isdigit(*s)) {
3781 + i = i*10 + *(s++) - '0';
3786 +/* convert ip address string like "192.168.0.10" to unsigned int */
3787 +__inline static u_int32_t asciiiptoi(char *s)
3789 + unsigned int i, j, k;
3791 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
3793 + for(j=0; (*(++s) != '.') && (j<3); ++j)
3800 +int parse_mms(const char *data,
3801 + const unsigned int datalen,
3802 + u_int32_t *mms_ip,
3803 + u_int16_t *mms_proto,
3804 + u_int16_t *mms_port,
3805 + char **mms_string_b,
3806 + char **mms_string_e,
3807 + char **mms_padding_e)
3809 + int unicode_size, i;
3810 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
3811 + char getlengthstring[28];
3813 + for(unicode_size=0;
3814 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3816 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
3817 + return -1; /* out of bounds - incomplete packet */
3819 + unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3820 + DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3822 + /* IP address ? */
3823 + *mms_ip = asciiiptoi(tempstring+2);
3825 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3828 + if(strncmp(tempstring+3+i, "TCP", 3)==0)
3829 + *mms_proto = IPPROTO_TCP;
3830 + else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3831 + *mms_proto = IPPROTO_UDP;
3834 + *mms_port = atoi(tempstring+7+i);
3836 + /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
3837 + unicode string, one to the end of the string, and one to the end
3838 + of the packet, since we must keep track of the number of bytes
3839 + between end of the unicode string and the end of packet (padding) */
3840 + *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3841 + *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3842 + *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3847 +/* FIXME: This should be in userspace. Later. */
3848 +static int help(const struct iphdr *iph, size_t len,
3849 + struct ip_conntrack *ct,
3850 + enum ip_conntrack_info ctinfo)
3852 + /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3853 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3854 + const char *data = (const char *)tcph + tcph->doff * 4;
3855 + unsigned int tcplen = len - iph->ihl * 4;
3856 + unsigned int datalen = tcplen - tcph->doff * 4;
3857 + int dir = CTINFO2DIR(ctinfo);
3858 + struct ip_conntrack_expect expect, *exp = &expect;
3859 + struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3862 + u_int16_t mms_proto;
3863 + char mms_proto_string[8];
3864 + u_int16_t mms_port;
3865 + char *mms_string_b, *mms_string_e, *mms_padding_e;
3867 + /* Until there's been traffic both ways, don't look in packets. */
3868 + if (ctinfo != IP_CT_ESTABLISHED
3869 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3870 + DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3874 + /* Not whole TCP header? */
3875 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3876 + DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3880 + /* Checksum invalid? Ignore. */
3881 + /* FIXME: Source route IP option packets --RR */
3882 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3883 + csum_partial((char *)tcph, tcplen, 0))) {
3884 + DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3885 + tcph, tcplen, NIPQUAD(iph->saddr),
3886 + NIPQUAD(iph->daddr));
3890 + /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3891 + /* FIXME: There is an issue with only looking at this packet: before this packet,
3892 + the client has already sent a packet to the server with the server's hostname
3893 + according to the client (think of it as the "Host: " header in HTTP/1.1). The
3894 + server will break the connection if this doesn't correspond to its own host
3895 + header. The client can also connect to an IP address; if it's the server's IP
3896 + address, it will not break the connection. When doing DNAT on a connection
3897 + where the client uses a server's IP address, the nat module should detect
3898 + this and change this string accordingly to the DNATed address. This should
3899 + probably be done by checking for an IP address, then storing it as a member
3900 + of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3902 + if( (MMS_SRV_MSG_OFFSET < datalen) &&
3903 + ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3904 + DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
3905 + (u8)*(data+36), (u8)*(data+37),
3906 + (u8)*(data+38), (u8)*(data+39),
3908 + if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3909 + &mms_string_b, &mms_string_e, &mms_padding_e))
3910 + if(net_ratelimit())
3911 + /* FIXME: more verbose debugging ? */
3912 + printk(KERN_WARNING
3913 + "ip_conntrack_mms: Unable to parse data payload\n");
3915 + memset(&expect, 0, sizeof(expect));
3917 + sprintf(mms_proto_string, "(%u)", mms_proto);
3918 + DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3919 + mms_proto == IPPROTO_TCP ? "TCP"
3920 + : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3921 + NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3925 + /* it's possible that the client will just ask the server to tunnel
3926 + the stream over the same TCP session (from port 1755): there's
3927 + shouldn't be a need to add an expectation in that case, but it
3928 + makes NAT packet mangling so much easier */
3929 + LOCK_BH(&ip_mms_lock);
3931 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3933 + exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3934 + exp_mms_info->len = (mms_string_e - mms_string_b);
3935 + exp_mms_info->padding = (mms_padding_e - mms_string_e);
3936 + exp_mms_info->port = mms_port;
3938 + DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3939 + exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3941 + exp->tuple = ((struct ip_conntrack_tuple)
3942 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3944 + { .tcp = { (__u16) ntohs(mms_port) } },
3947 + exp->mask = ((struct ip_conntrack_tuple)
3948 + { { 0xFFFFFFFF, { 0 } },
3949 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3950 + exp->expectfn = NULL;
3951 + ip_conntrack_expect_related(ct, &expect);
3952 + UNLOCK_BH(&ip_mms_lock);
3958 +static struct ip_conntrack_helper mms[MAX_PORTS];
3959 +static char mms_names[MAX_PORTS][10];
3961 +/* Not __exit: called from init() */
3962 +static void fini(void)
3965 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3966 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3968 + ip_conntrack_helper_unregister(&mms[i]);
3972 +static int __init init(void)
3977 + if (ports[0] == 0)
3978 + ports[0] = MMS_PORT;
3980 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3981 + memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3982 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3983 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
3984 + mms[i].mask.src.u.tcp.port = 0xFFFF;
3985 + mms[i].mask.dst.protonum = 0xFFFF;
3986 + mms[i].max_expected = 1;
3987 + mms[i].timeout = 0;
3988 + mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3989 + mms[i].me = THIS_MODULE;
3990 + mms[i].help = help;
3992 + tmpname = &mms_names[i][0];
3993 + if (ports[i] == MMS_PORT)
3994 + sprintf(tmpname, "mms");
3996 + sprintf(tmpname, "mms-%d", ports[i]);
3997 + mms[i].name = tmpname;
3999 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
4001 + ret = ip_conntrack_helper_register(&mms[i]);
4014 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
4015 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp.c 1970-01-01 01:00:00.000000000 +0100
4016 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp.c 2003-12-10 23:14:24.102290592 +0100
4019 + * ip_conntrack_pptp.c - Version 1.9
4021 + * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
4022 + * PPTP is a a protocol for creating virtual private networks.
4023 + * It is a specification defined by Microsoft and some vendors
4024 + * working with Microsoft. PPTP is built on top of a modified
4025 + * version of the Internet Generic Routing Encapsulation Protocol.
4026 + * GRE is defined in RFC 1701 and RFC 1702. Documentation of
4027 + * PPTP can be found in RFC 2637
4029 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4031 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4034 + * - We blindly assume that control connections are always
4035 + * established in PNS->PAC direction. This is a violation
4038 + * TODO: - finish support for multiple calls within one session
4039 + * (needs expect reservations in newnat)
4040 + * - testing of incoming PPTP calls
4043 + * 2002-02-05 - Version 1.3
4044 + * - Call ip_conntrack_unexpect_related() from
4045 + * pptp_timeout_related() to destroy expectations in case
4046 + * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
4047 + * (Philip Craig <philipc@snapgear.com>)
4048 + * - Add Version information at module loadtime
4049 + * 2002-02-10 - Version 1.6
4050 + * - move to C99 style initializers
4051 + * - remove second expectation if first arrives
4055 +#include <linux/config.h>
4056 +#include <linux/module.h>
4057 +#include <linux/netfilter.h>
4058 +#include <linux/ip.h>
4059 +#include <net/checksum.h>
4060 +#include <net/tcp.h>
4062 +#include <linux/netfilter_ipv4/lockhelp.h>
4063 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4064 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4065 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4067 +#define IP_CT_PPTP_VERSION "1.9"
4069 +MODULE_LICENSE("GPL");
4070 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4071 +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
4073 +DECLARE_LOCK(ip_pptp_lock);
4076 +#include "ip_conntrack_pptp_priv.h"
4077 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4078 + ": " format, ## args)
4080 +#define DEBUGP(format, args...)
4084 +#define MINS * 60 SECS
4085 +#define HOURS * 60 MINS
4086 +#define DAYS * 24 HOURS
4088 +#define PPTP_GRE_TIMEOUT (10 MINS)
4089 +#define PPTP_GRE_STREAM_TIMEOUT (5 DAYS)
4091 +static int pptp_expectfn(struct ip_conntrack *ct)
4093 + struct ip_conntrack *master;
4094 + struct ip_conntrack_expect *exp;
4096 + DEBUGP("increasing timeouts\n");
4097 + /* increase timeout of GRE data channel conntrack entry */
4098 + ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
4099 + ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
4101 + master = master_ct(ct);
4103 + DEBUGP(" no master!!!\n");
4109 + DEBUGP("no expectation!!\n");
4113 + DEBUGP("completing tuples with ct info\n");
4114 + /* we can do this, since we're unconfirmed */
4115 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
4116 + htonl(master->help.ct_pptp_info.pac_call_id)) {
4117 + /* assume PNS->PAC */
4118 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
4119 + htonl(master->help.ct_pptp_info.pns_call_id);
4120 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4121 + htonl(master->help.ct_pptp_info.pns_call_id);
4123 + /* assume PAC->PNS */
4124 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
4125 + htonl(master->help.ct_pptp_info.pac_call_id);
4126 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4127 + htonl(master->help.ct_pptp_info.pac_call_id);
4130 + /* delete other expectation */
4131 + if (exp->expected_list.next != &exp->expected_list) {
4132 + struct ip_conntrack_expect *other_exp;
4133 + struct list_head *cur_item, *next;
4135 + for (cur_item = master->sibling_list.next;
4136 + cur_item != &master->sibling_list; cur_item = next) {
4137 + next = cur_item->next;
4138 + other_exp = list_entry(cur_item,
4139 + struct ip_conntrack_expect,
4141 + /* remove only if occurred at same sequence number */
4142 + if (other_exp != exp && other_exp->seq == exp->seq) {
4143 + DEBUGP("unexpecting other direction\n");
4144 + ip_ct_gre_keymap_destroy(other_exp);
4145 + ip_conntrack_unexpect_related(other_exp);
4153 +/* timeout GRE data connections */
4154 +static int pptp_timeout_related(struct ip_conntrack *ct)
4156 + struct list_head *cur_item, *next;
4157 + struct ip_conntrack_expect *exp;
4159 + /* FIXME: do we have to lock something ? */
4160 + for (cur_item = ct->sibling_list.next;
4161 + cur_item != &ct->sibling_list; cur_item = next) {
4162 + next = cur_item->next;
4163 + exp = list_entry(cur_item, struct ip_conntrack_expect,
4166 + ip_ct_gre_keymap_destroy(exp);
4167 + if (!exp->sibling) {
4168 + ip_conntrack_unexpect_related(exp);
4172 + DEBUGP("killing conntrack %p\n",
4174 + exp->sibling->proto.gre.timeout = 0;
4175 + exp->sibling->proto.gre.stream_timeout = 0;
4177 + if (del_timer(&exp->sibling->timeout))
4178 + ip_ct_death_by_timeout((unsigned long)exp->sibling);
4184 +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
4186 +exp_gre(struct ip_conntrack *master,
4189 + u_int16_t peer_callid)
4191 + struct ip_conntrack_expect exp;
4192 + struct ip_conntrack_tuple inv_tuple;
4194 + memset(&exp, 0, sizeof(exp));
4195 + /* tuple in original direction, PNS->PAC */
4196 + exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4197 + exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
4198 + exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4199 + exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
4200 + exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
4201 + exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
4202 + exp.tuple.dst.protonum = IPPROTO_GRE;
4204 + exp.mask.src.ip = 0xffffffff;
4205 + exp.mask.src.u.all = 0;
4206 + exp.mask.dst.u.all = 0;
4207 + exp.mask.dst.u.gre.key = 0xffffffff;
4208 + exp.mask.dst.u.gre.version = 0xff;
4209 + exp.mask.dst.u.gre.protocol = 0xffff;
4210 + exp.mask.dst.ip = 0xffffffff;
4211 + exp.mask.dst.protonum = 0xffff;
4214 + exp.expectfn = pptp_expectfn;
4216 + exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
4217 + exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
4219 + DEBUGP("calling expect_related ");
4220 + DUMP_TUPLE_RAW(&exp.tuple);
4222 + /* Add GRE keymap entries */
4223 + if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
4226 + invert_tuplepr(&inv_tuple, &exp.tuple);
4227 + if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
4228 + ip_ct_gre_keymap_destroy(&exp);
4232 + if (ip_conntrack_expect_related(master, &exp) != 0) {
4233 + ip_ct_gre_keymap_destroy(&exp);
4234 + DEBUGP("cannot expect_related()\n");
4238 + /* tuple in reply direction, PAC->PNS */
4239 + exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4240 + exp.tuple.src.u.gre.key = htonl(ntohs(callid));
4241 + exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4242 + exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
4244 + DEBUGP("calling expect_related ");
4245 + DUMP_TUPLE_RAW(&exp.tuple);
4247 + /* Add GRE keymap entries */
4248 + ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
4249 + invert_tuplepr(&inv_tuple, &exp.tuple);
4250 + ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
4251 + /* FIXME: cannot handle error correctly, since we need to free
4252 + * the above keymap :( */
4254 + if (ip_conntrack_expect_related(master, &exp) != 0) {
4255 + /* free the second pair of keypmaps */
4256 + ip_ct_gre_keymap_destroy(&exp);
4257 + DEBUGP("cannot expect_related():\n");
4265 +pptp_inbound_pkt(struct tcphdr *tcph,
4266 + struct pptp_pkt_hdr *pptph,
4268 + struct ip_conntrack *ct,
4269 + enum ip_conntrack_info ctinfo)
4271 + struct PptpControlHeader *ctlh;
4272 + union pptp_ctrl_union pptpReq;
4274 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4275 + u_int16_t msg, *cid, *pcid;
4278 + ctlh = (struct PptpControlHeader *)
4279 + ((char *) pptph + sizeof(struct pptp_pkt_hdr));
4280 + pptpReq.rawreq = (void *)
4281 + ((char *) ctlh + sizeof(struct PptpControlHeader));
4283 + msg = ntohs(ctlh->messageType);
4284 + DEBUGP("inbound control message %s\n", strMName[msg]);
4287 + case PPTP_START_SESSION_REPLY:
4288 + /* server confirms new control session */
4289 + if (info->sstate < PPTP_SESSION_REQUESTED) {
4290 + DEBUGP("%s without START_SESS_REQUEST\n",
4294 + if (pptpReq.srep->resultCode == PPTP_START_OK)
4295 + info->sstate = PPTP_SESSION_CONFIRMED;
4297 + info->sstate = PPTP_SESSION_ERROR;
4300 + case PPTP_STOP_SESSION_REPLY:
4301 + /* server confirms end of control session */
4302 + if (info->sstate > PPTP_SESSION_STOPREQ) {
4303 + DEBUGP("%s without STOP_SESS_REQUEST\n",
4307 + if (pptpReq.strep->resultCode == PPTP_STOP_OK)
4308 + info->sstate = PPTP_SESSION_NONE;
4310 + info->sstate = PPTP_SESSION_ERROR;
4313 + case PPTP_OUT_CALL_REPLY:
4314 + /* server accepted call, we now expect GRE frames */
4315 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4316 + DEBUGP("%s but no session\n", strMName[msg]);
4319 + if (info->cstate != PPTP_CALL_OUT_REQ &&
4320 + info->cstate != PPTP_CALL_OUT_CONF) {
4321 + DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
4324 + if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
4325 + info->cstate = PPTP_CALL_NONE;
4329 + cid = &pptpReq.ocack->callID;
4330 + pcid = &pptpReq.ocack->peersCallID;
4332 + info->pac_call_id = ntohs(*cid);
4334 + if (htons(info->pns_call_id) != *pcid) {
4335 + DEBUGP("%s for unknown callid %u\n",
4336 + strMName[msg], ntohs(*pcid));
4340 + DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg],
4341 + ntohs(*cid), ntohs(*pcid));
4343 + info->cstate = PPTP_CALL_OUT_CONF;
4345 + seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4346 + if (exp_gre(ct, seq, *cid, *pcid) != 0)
4347 + printk("ip_conntrack_pptp: error during exp_gre\n");
4350 + case PPTP_IN_CALL_REQUEST:
4351 + /* server tells us about incoming call request */
4352 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4353 + DEBUGP("%s but no session\n", strMName[msg]);
4356 + pcid = &pptpReq.icack->peersCallID;
4357 + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4358 + info->cstate = PPTP_CALL_IN_REQ;
4359 + info->pac_call_id= ntohs(*pcid);
4362 + case PPTP_IN_CALL_CONNECT:
4363 + /* server tells us about incoming call established */
4364 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4365 + DEBUGP("%s but no session\n", strMName[msg]);
4368 + if (info->sstate != PPTP_CALL_IN_REP
4369 + && info->sstate != PPTP_CALL_IN_CONF) {
4370 + DEBUGP("%s but never sent IN_CALL_REPLY\n",
4375 + pcid = &pptpReq.iccon->peersCallID;
4376 + cid = &info->pac_call_id;
4378 + if (info->pns_call_id != ntohs(*pcid)) {
4379 + DEBUGP("%s for unknown CallID %u\n",
4380 + strMName[msg], ntohs(*cid));
4384 + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4385 + info->cstate = PPTP_CALL_IN_CONF;
4387 + /* we expect a GRE connection from PAC to PNS */
4388 + seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4389 + if (exp_gre(ct, seq, *cid, *pcid) != 0)
4390 + printk("ip_conntrack_pptp: error during exp_gre\n");
4394 + case PPTP_CALL_DISCONNECT_NOTIFY:
4395 + /* server confirms disconnect */
4396 + cid = &pptpReq.disc->callID;
4397 + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4398 + info->cstate = PPTP_CALL_NONE;
4400 + /* untrack this call id, unexpect GRE packets */
4401 + pptp_timeout_related(ct);
4404 + case PPTP_WAN_ERROR_NOTIFY:
4407 + case PPTP_ECHO_REQUEST:
4408 + case PPTP_ECHO_REPLY:
4409 + /* I don't have to explain these ;) */
4412 + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
4413 + ? strMName[msg]:strMName[0], msg);
4422 +pptp_outbound_pkt(struct tcphdr *tcph,
4423 + struct pptp_pkt_hdr *pptph,
4425 + struct ip_conntrack *ct,
4426 + enum ip_conntrack_info ctinfo)
4428 + struct PptpControlHeader *ctlh;
4429 + union pptp_ctrl_union pptpReq;
4430 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4431 + u_int16_t msg, *cid, *pcid;
4433 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
4434 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
4436 + msg = ntohs(ctlh->messageType);
4437 + DEBUGP("outbound control message %s\n", strMName[msg]);
4440 + case PPTP_START_SESSION_REQUEST:
4441 + /* client requests for new control session */
4442 + if (info->sstate != PPTP_SESSION_NONE) {
4443 + DEBUGP("%s but we already have one",
4446 + info->sstate = PPTP_SESSION_REQUESTED;
4448 + case PPTP_STOP_SESSION_REQUEST:
4449 + /* client requests end of control session */
4450 + info->sstate = PPTP_SESSION_STOPREQ;
4453 + case PPTP_OUT_CALL_REQUEST:
4454 + /* client initiating connection to server */
4455 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4456 + DEBUGP("%s but no session\n",
4460 + info->cstate = PPTP_CALL_OUT_REQ;
4461 + /* track PNS call id */
4462 + cid = &pptpReq.ocreq->callID;
4463 + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4464 + info->pns_call_id = ntohs(*cid);
4466 + case PPTP_IN_CALL_REPLY:
4467 + /* client answers incoming call */
4468 + if (info->cstate != PPTP_CALL_IN_REQ
4469 + && info->cstate != PPTP_CALL_IN_REP) {
4470 + DEBUGP("%s without incall_req\n",
4474 + if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
4475 + info->cstate = PPTP_CALL_NONE;
4478 + pcid = &pptpReq.icack->peersCallID;
4479 + if (info->pac_call_id != ntohs(*pcid)) {
4480 + DEBUGP("%s for unknown call %u\n",
4481 + strMName[msg], ntohs(*pcid));
4484 + DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
4485 + /* part two of the three-way handshake */
4486 + info->cstate = PPTP_CALL_IN_REP;
4487 + info->pns_call_id = ntohs(pptpReq.icack->callID);
4490 + case PPTP_CALL_CLEAR_REQUEST:
4491 + /* client requests hangup of call */
4492 + if (info->sstate != PPTP_SESSION_CONFIRMED) {
4493 + DEBUGP("CLEAR_CALL but no session\n");
4496 + /* FUTURE: iterate over all calls and check if
4497 + * call ID is valid. We don't do this without newnat,
4498 + * because we only know about last call */
4499 + info->cstate = PPTP_CALL_CLEAR_REQ;
4501 + case PPTP_SET_LINK_INFO:
4503 + case PPTP_ECHO_REQUEST:
4504 + case PPTP_ECHO_REPLY:
4505 + /* I don't have to explain these ;) */
4508 + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?
4509 + strMName[msg]:strMName[0], msg);
4510 + /* unknown: no need to create GRE masq table entry */
4518 +/* track caller id inside control connection, call expect_related */
4520 +conntrack_pptp_help(const struct iphdr *iph, size_t len,
4521 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4524 + struct pptp_pkt_hdr *pptph;
4526 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4527 + u_int32_t tcplen = len - iph->ihl * 4;
4528 + u_int32_t datalen = tcplen - tcph->doff * 4;
4530 + int dir = CTINFO2DIR(ctinfo);
4531 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4533 + int oldsstate, oldcstate;
4536 + /* don't do any tracking before tcp handshake complete */
4537 + if (ctinfo != IP_CT_ESTABLISHED
4538 + && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4539 + DEBUGP("ctinfo = %u, skipping\n", ctinfo);
4543 + /* not a complete TCP header? */
4544 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4545 + DEBUGP("tcplen = %u\n", tcplen);
4549 + /* checksum invalid? */
4550 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4551 + csum_partial((char *) tcph, tcplen, 0))) {
4552 + printk(KERN_NOTICE __FILE__ ": bad csum\n");
4553 + /* W2K PPTP server sends TCP packets with wrong checksum :(( */
4554 + //return NF_ACCEPT;
4557 + if (tcph->fin || tcph->rst) {
4558 + DEBUGP("RST/FIN received, timeouting GRE\n");
4559 + /* can't do this after real newnat */
4560 + info->cstate = PPTP_CALL_NONE;
4562 + /* untrack this call id, unexpect GRE packets */
4563 + pptp_timeout_related(ct);
4567 + pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
4568 + datalimit = (void *) pptph + datalen;
4570 + /* not a full pptp packet header? */
4571 + if ((void *) pptph+sizeof(*pptph) >= datalimit) {
4572 + DEBUGP("no full PPTP header, can't track\n");
4576 + /* if it's not a control message we can't do anything with it */
4577 + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
4578 + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
4579 + DEBUGP("not a control packet\n");
4583 + oldsstate = info->sstate;
4584 + oldcstate = info->cstate;
4586 + LOCK_BH(&ip_pptp_lock);
4588 + /* FIXME: We just blindly assume that the control connection is always
4589 + * established from PNS->PAC. However, RFC makes no guarantee */
4590 + if (dir == IP_CT_DIR_ORIGINAL)
4591 + /* client -> server (PNS -> PAC) */
4592 + ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4594 + /* server -> client (PAC -> PNS) */
4595 + ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4596 + DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
4597 + oldsstate, info->sstate, oldcstate, info->cstate);
4598 + UNLOCK_BH(&ip_pptp_lock);
4603 +/* control protocol helper */
4604 +static struct ip_conntrack_helper pptp = {
4605 + .list = { NULL, NULL },
4607 + .flags = IP_CT_HELPER_F_REUSE_EXPECT,
4608 + .me = THIS_MODULE,
4609 + .max_expected = 2,
4611 + .tuple = { .src = { .ip = 0,
4612 + .u = { .tcp = { .port =
4613 + __constant_htons(PPTP_CONTROL_PORT) } }
4616 + .u = { .all = 0 },
4617 + .protonum = IPPROTO_TCP
4620 + .mask = { .src = { .ip = 0,
4621 + .u = { .tcp = { .port = 0xffff } }
4624 + .u = { .all = 0 },
4625 + .protonum = 0xffff
4628 + .help = conntrack_pptp_help
4631 +/* ip_conntrack_pptp initialization */
4632 +static int __init init(void)
4636 + DEBUGP(__FILE__ ": registering helper\n");
4637 + if ((retcode = ip_conntrack_helper_register(&pptp))) {
4638 + printk(KERN_ERR "Unable to register conntrack application "
4639 + "helper for pptp: %d\n", retcode);
4643 + printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
4647 +static void __exit fini(void)
4649 + ip_conntrack_helper_unregister(&pptp);
4650 + printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
4656 +EXPORT_SYMBOL(ip_pptp_lock);
4657 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
4658 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 1970-01-01 01:00:00.000000000 +0100
4659 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp_priv.h 2003-11-17 09:09:34.000000000 +0100
4661 +#ifndef _IP_CT_PPTP_PRIV_H
4662 +#define _IP_CT_PPTP_PRIV_H
4664 +/* PptpControlMessageType names */
4665 +static const char *strMName[] = {
4666 + "UNKNOWN_MESSAGE",
4667 + "START_SESSION_REQUEST",
4668 + "START_SESSION_REPLY",
4669 + "STOP_SESSION_REQUEST",
4670 + "STOP_SESSION_REPLY",
4673 + "OUT_CALL_REQUEST",
4675 + "IN_CALL_REQUEST",
4677 + "IN_CALL_CONNECT",
4678 + "CALL_CLEAR_REQUEST",
4679 + "CALL_DISCONNECT_NOTIFY",
4680 + "WAN_ERROR_NOTIFY",
4685 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
4686 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
4687 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_proto_gre.c 2003-11-17 09:09:34.000000000 +0100
4690 + * ip_conntrack_proto_gre.c - Version 1.2
4692 + * Connection tracking protocol helper module for GRE.
4694 + * GRE is a generic encapsulation protocol, which is generally not very
4695 + * suited for NAT, as it has no protocol-specific part as port numbers.
4697 + * It has an optional key field, which may help us distinguishing two
4698 + * connections between the same two hosts.
4700 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
4702 + * PPTP is built on top of a modified version of GRE, and has a mandatory
4703 + * field called "CallID", which serves us for the same purpose as the key
4704 + * field in plain GRE.
4706 + * Documentation about PPTP can be found in RFC 2637
4708 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4710 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4714 +#include <linux/config.h>
4715 +#include <linux/module.h>
4716 +#include <linux/types.h>
4717 +#include <linux/timer.h>
4718 +#include <linux/netfilter.h>
4719 +#include <linux/ip.h>
4720 +#include <linux/in.h>
4721 +#include <linux/list.h>
4723 +#include <linux/netfilter_ipv4/lockhelp.h>
4725 +DECLARE_RWLOCK(ip_ct_gre_lock);
4726 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
4727 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
4729 +#include <linux/netfilter_ipv4/listhelp.h>
4730 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4731 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4732 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4734 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4735 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4737 +MODULE_LICENSE("GPL");
4738 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4739 +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
4741 +/* shamelessly stolen from ip_conntrack_proto_udp.c */
4742 +#define GRE_TIMEOUT (30*HZ)
4743 +#define GRE_STREAM_TIMEOUT (180*HZ)
4746 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4747 + ": " format, ## args)
4748 +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
4749 + NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
4750 + NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
4751 + (x)->dst.u.gre.version, \
4752 + ntohs((x)->dst.u.gre.protocol))
4754 +#define DEBUGP(x, args...)
4755 +#define DUMP_TUPLE_GRE(x)
4758 +/* GRE KEYMAP HANDLING FUNCTIONS */
4759 +static LIST_HEAD(gre_keymap_list);
4761 +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
4762 + const struct ip_conntrack_tuple *t)
4764 + return ((km->tuple.src.ip == t->src.ip) &&
4765 + (km->tuple.dst.ip == t->dst.ip) &&
4766 + (km->tuple.dst.protonum == t->dst.protonum) &&
4767 + (km->tuple.dst.u.all == t->dst.u.all));
4770 +/* look up the source key for a given tuple */
4771 +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
4773 + struct ip_ct_gre_keymap *km;
4776 + READ_LOCK(&ip_ct_gre_lock);
4777 + km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
4778 + struct ip_ct_gre_keymap *, t);
4780 + READ_UNLOCK(&ip_ct_gre_lock);
4784 + key = km->tuple.src.u.gre.key;
4785 + READ_UNLOCK(&ip_ct_gre_lock);
4790 +/* add a single keymap entry, associate with specified expect */
4791 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
4792 + struct ip_conntrack_tuple *t, int reply)
4794 + struct ip_ct_gre_keymap *km;
4796 + km = kmalloc(sizeof(*km), GFP_ATOMIC);
4800 + /* initializing list head should be sufficient */
4801 + memset(km, 0, sizeof(*km));
4803 + memcpy(&km->tuple, t, sizeof(*t));
4806 + exp->proto.gre.keymap_orig = km;
4808 + exp->proto.gre.keymap_reply = km;
4810 + DEBUGP("adding new entry %p: ", km);
4811 + DUMP_TUPLE_GRE(&km->tuple);
4813 + WRITE_LOCK(&ip_ct_gre_lock);
4814 + list_append(&gre_keymap_list, km);
4815 + WRITE_UNLOCK(&ip_ct_gre_lock);
4820 +/* change the tuple of a keymap entry (used by nat helper) */
4821 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
4822 + struct ip_conntrack_tuple *t)
4824 + DEBUGP("changing entry %p to: ", km);
4825 + DUMP_TUPLE_GRE(t);
4827 + WRITE_LOCK(&ip_ct_gre_lock);
4828 + memcpy(&km->tuple, t, sizeof(km->tuple));
4829 + WRITE_UNLOCK(&ip_ct_gre_lock);
4832 +/* destroy the keymap entries associated with specified expect */
4833 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
4835 + DEBUGP("entering for exp %p\n", exp);
4836 + WRITE_LOCK(&ip_ct_gre_lock);
4837 + if (exp->proto.gre.keymap_orig) {
4838 + DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
4839 + list_del(&exp->proto.gre.keymap_orig->list);
4840 + kfree(exp->proto.gre.keymap_orig);
4841 + exp->proto.gre.keymap_orig = NULL;
4843 + if (exp->proto.gre.keymap_reply) {
4844 + DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
4845 + list_del(&exp->proto.gre.keymap_reply->list);
4846 + kfree(exp->proto.gre.keymap_reply);
4847 + exp->proto.gre.keymap_reply = NULL;
4849 + WRITE_UNLOCK(&ip_ct_gre_lock);
4853 +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
4855 +/* invert gre part of tuple */
4856 +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
4857 + const struct ip_conntrack_tuple *orig)
4859 + tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
4860 + tuple->dst.u.gre.version = orig->dst.u.gre.version;
4862 + tuple->dst.u.gre.key = orig->src.u.gre.key;
4863 + tuple->src.u.gre.key = orig->dst.u.gre.key;
4868 +/* gre hdr info to tuple */
4869 +static int gre_pkt_to_tuple(const void *datah, size_t datalen,
4870 + struct ip_conntrack_tuple *tuple)
4872 + struct gre_hdr *grehdr = (struct gre_hdr *) datah;
4873 + struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
4876 + /* core guarantees 8 protocol bytes, no need for size check */
4878 + tuple->dst.u.gre.version = grehdr->version;
4879 + tuple->dst.u.gre.protocol = grehdr->protocol;
4881 + switch (grehdr->version) {
4882 + case GRE_VERSION_1701:
4883 + if (!grehdr->key) {
4884 + DEBUGP("Can't track GRE without key\n");
4887 + tuple->dst.u.gre.key = *(gre_key(grehdr));
4890 + case GRE_VERSION_PPTP:
4891 + if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
4892 + DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
4895 + tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
4899 + printk(KERN_WARNING "unknown GRE version %hu\n",
4900 + tuple->dst.u.gre.version);
4904 + srckey = gre_keymap_lookup(tuple);
4907 + DEBUGP("found src key %x for tuple ", ntohl(srckey));
4908 + DUMP_TUPLE_GRE(tuple);
4910 + tuple->src.u.gre.key = srckey;
4915 +/* print gre part of tuple */
4916 +static unsigned int gre_print_tuple(char *buffer,
4917 + const struct ip_conntrack_tuple *tuple)
4919 + return sprintf(buffer, "version=%d protocol=0x%04x srckey=0x%x dstkey=0x%x ",
4920 + tuple->dst.u.gre.version,
4921 + ntohs(tuple->dst.u.gre.protocol),
4922 + ntohl(tuple->src.u.gre.key),
4923 + ntohl(tuple->dst.u.gre.key));
4926 +/* print private data for conntrack */
4927 +static unsigned int gre_print_conntrack(char *buffer,
4928 + const struct ip_conntrack *ct)
4930 + return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
4931 + (ct->proto.gre.timeout / HZ),
4932 + (ct->proto.gre.stream_timeout / HZ));
4935 +/* Returns verdict for packet, and may modify conntrack */
4936 +static int gre_packet(struct ip_conntrack *ct,
4937 + struct iphdr *iph, size_t len,
4938 + enum ip_conntrack_info conntrackinfo)
4940 + /* If we've seen traffic both ways, this is a GRE connection.
4941 + * Extend timeout. */
4942 + if (ct->status & IPS_SEEN_REPLY) {
4943 + ip_ct_refresh(ct, ct->proto.gre.stream_timeout);
4944 + /* Also, more likely to be important, and not a probe. */
4945 + set_bit(IPS_ASSURED_BIT, &ct->status);
4947 + ip_ct_refresh(ct, ct->proto.gre.timeout);
4952 +/* Called when a new connection for this protocol found. */
4953 +static int gre_new(struct ip_conntrack *ct,
4954 + struct iphdr *iph, size_t len)
4957 + DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4959 + /* initialize to sane value. Ideally a conntrack helper
4960 + * (e.g. in case of pptp) is increasing them */
4961 + ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
4962 + ct->proto.gre.timeout = GRE_TIMEOUT;
4967 +/* Called when a conntrack entry has already been removed from the hashes
4968 + * and is about to be deleted from memory */
4969 +static void gre_destroy(struct ip_conntrack *ct)
4971 + struct ip_conntrack_expect *master = ct->master;
4973 + DEBUGP(" entering\n");
4976 + DEBUGP("no master exp for ct %p\n", ct);
4980 + ip_ct_gre_keymap_destroy(master);
4983 +/* protocol helper struct */
4984 +static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
4989 + gre_print_conntrack,
4996 +/* ip_conntrack_proto_gre initialization */
4997 +static int __init init(void)
5001 + if ((retcode = ip_conntrack_protocol_register(&gre))) {
5002 + printk(KERN_ERR "Unable to register conntrack protocol "
5003 + "helper for gre: %d\n", retcode);
5010 +static void __exit fini(void)
5012 + struct list_head *pos, *n;
5014 + /* delete all keymap entries */
5015 + WRITE_LOCK(&ip_ct_gre_lock);
5016 + list_for_each_safe(pos, n, &gre_keymap_list) {
5017 + DEBUGP("deleting keymap %p at module unload time\n", pos);
5021 + WRITE_UNLOCK(&ip_ct_gre_lock);
5023 + ip_conntrack_protocol_unregister(&gre);
5026 +EXPORT_SYMBOL(ip_ct_gre_keymap_add);
5027 +EXPORT_SYMBOL(ip_ct_gre_keymap_change);
5028 +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
5032 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
5033 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
5034 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_quake3.c 2003-12-10 23:14:06.244005464 +0100
5036 +/* Quake3 extension for IP connection tracking
5037 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5038 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5040 + * ip_conntrack_quake3.c v0.04 2002-08-31
5042 + * This program is free software; you can redistribute it and/or
5043 + * modify it under the terms of the GNU General Public License
5044 + * as published by the Free Software Foundation; either version
5045 + * 2 of the License, or (at your option) any later version.
5047 + * Module load syntax:
5048 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5050 + * please give the ports of all Quake3 master servers You wish to
5051 + * connect to. If you don't specify ports, the default will be UDP
5054 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5057 +#include <linux/module.h>
5058 +#include <linux/ip.h>
5059 +#include <linux/udp.h>
5061 +#include <linux/netfilter.h>
5062 +#include <linux/netfilter_ipv4/ip_tables.h>
5063 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5064 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5066 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5068 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5069 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5070 +MODULE_LICENSE("GPL");
5072 +#define MAX_PORTS 8
5073 +static int ports[MAX_PORTS];
5074 +static int ports_c = 0;
5076 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5077 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5080 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5081 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5083 +#define DEBUGP printk
5085 +#define DEBUGP(format, args...)
5088 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5090 +static int quake3_help(const struct iphdr *iph, size_t len,
5091 + struct ip_conntrack *ct,
5092 + enum ip_conntrack_info ctinfo)
5094 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
5095 + int dir = CTINFO2DIR(ctinfo);
5096 + struct ip_conntrack_expect exp;
5099 + /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5100 + if (ctinfo != IP_CT_ESTABLISHED
5101 + && ctinfo != IP_CT_IS_REPLY) {
5102 + DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5104 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5106 + if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5107 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5108 + i+6 < ntohs(udph->len);
5110 + DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5111 + i, ntohs(udph->len),
5112 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
5113 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5115 + memset(&exp, 0, sizeof(exp));
5117 + exp.tuple = ((struct ip_conntrack_tuple)
5118 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5119 + { (u_int32_t) *((u_int32_t *)((int)udph + i)),
5120 + { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
5123 + exp.mask = ((struct ip_conntrack_tuple)
5124 + { { 0xFFFFFFFF, { 0 } },
5125 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5126 + exp.expectfn = NULL;
5128 + ip_conntrack_expect_related(ct, &exp);
5133 + return(NF_ACCEPT);
5136 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5137 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
5139 +static void fini(void)
5143 + for(i = 0 ; (i < ports_c); i++) {
5144 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5146 + ip_conntrack_helper_unregister(&quake3[i]);
5150 +static int __init init(void)
5156 + ports[0]=QUAKE3_MASTER_PORT;
5158 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5159 + /* Create helper structure */
5160 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5162 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5163 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5164 + quake3[i].mask.dst.protonum = 0xFFFF;
5165 + quake3[i].mask.src.u.udp.port = 0xFFFF;
5166 + quake3[i].help = quake3_help;
5167 + quake3[i].me = THIS_MODULE;
5169 + tmpname = &quake3_names[i][0];
5170 + if (ports[i] == QUAKE3_MASTER_PORT)
5171 + sprintf(tmpname, "quake3");
5173 + sprintf(tmpname, "quake3-%d", i);
5174 + quake3[i].name = tmpname;
5176 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5179 + ret=ip_conntrack_helper_register(&quake3[i]);
5192 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
5193 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
5194 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2003-12-10 23:14:10.153411144 +0100
5196 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
5197 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5198 + * - original rpc tracking module
5199 + * - "recent" connection handling for kernel 2.3+ netfilter
5201 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5202 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5204 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5205 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
5206 + * - extended matching to support filtering on procedures
5208 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
5210 + * This program is free software; you can redistribute it and/or
5211 + * modify it under the terms of the GNU General Public License
5212 + * as published by the Free Software Foundation; either version
5213 + * 2 of the License, or (at your option) any later version.
5215 + * Module load syntax:
5216 + * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
5218 + * Please give the ports of all RPC servers you wish to connect to.
5219 + * If you don't specify ports, the default will be port 111.
5223 + * RPCs should not be exposed to the internet - ask the Pentagon;
5225 + * "The unidentified crackers pleaded guilty in July to charges
5226 + * of juvenile delinquency stemming from a string of Pentagon
5227 + * network intrusions in February.
5229 + * The youths, going by the names TooShort and Makaveli, used
5230 + * a common server security hole to break in, according to
5231 + * Dane Jasper, owner of the California Internet service
5232 + * provider, Sonic. They used the hole, known as the 'statd'
5233 + * exploit, to attempt more than 800 break-ins, Jasper said."
5235 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5236 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
5240 +#include <linux/module.h>
5241 +#include <linux/netfilter.h>
5242 +#include <linux/ip.h>
5243 +#include <net/checksum.h>
5244 +#include <net/tcp.h>
5246 +#include <asm/param.h>
5247 +#include <linux/sched.h>
5248 +#include <linux/timer.h>
5249 +#include <linux/stddef.h>
5250 +#include <linux/list.h>
5252 +#include <linux/netfilter_ipv4/lockhelp.h>
5253 +#include <linux/netfilter_ipv4/ip_tables.h>
5254 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5255 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5257 +#define MAX_PORTS 8
5258 +static int ports[MAX_PORTS];
5259 +static int ports_n_c = 0;
5262 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5263 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5266 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5267 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
5268 +MODULE_LICENSE("GPL");
5271 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
5274 +#define DEBUGP(format, args...)
5277 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
5278 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
5279 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
5280 +#include <linux/netfilter_ipv4/listhelp.h>
5282 +/* For future conections RPC, using client's cache bindings
5283 + * I'll use ip_conntrack_lock to lock these lists */
5285 +LIST_HEAD(request_p_list_tcp);
5288 +static void delete_request_p(unsigned long request_p_ul)
5290 + struct request_p *p = (void *)request_p_ul;
5292 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5293 + LIST_DELETE(&request_p_list_tcp, p);
5294 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5300 +static void req_cl(struct request_p * r)
5302 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5303 + del_timer(&r->timeout);
5304 + LIST_DELETE(&request_p_list_tcp, r);
5305 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5311 +static void clean_request(struct list_head *list)
5313 + struct list_head *first = list->prev;
5314 + struct list_head *temp = list->next;
5315 + struct list_head *aux;
5317 + if (list_empty(list))
5320 + while (first != temp) {
5322 + req_cl((struct request_p *)temp);
5325 + req_cl((struct request_p *)temp);
5330 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5333 + struct request_p *req_p;
5335 + /* Verifies if entry already exists */
5336 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5337 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5338 + struct request_p *, xid, ip, port);
5341 + /* Refresh timeout */
5342 + if (del_timer(&req_p->timeout)) {
5343 + req_p->timeout.expires = jiffies + EXP;
5344 + add_timer(&req_p->timeout);
5346 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5350 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5352 + /* Allocate new request_p */
5353 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5355 + DEBUGP("can't allocate request_p\n");
5358 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
5359 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5362 + /* Initialize timer */
5363 + init_timer(&req_p->timeout);
5364 + req_p->timeout.function = delete_request_p;
5365 + add_timer(&req_p->timeout);
5368 + WRITE_LOCK(&ipct_rpc_tcp_lock);
5369 + list_prepend(&request_p_list_tcp, req_p);
5370 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5376 +static int check_rpc_packet(const u_int32_t *data,
5377 + int dir, struct ip_conntrack *ct,
5378 + struct list_head request_p_list)
5380 + struct request_p *req_p;
5382 + struct ip_conntrack_expect expect, *exp = &expect;
5384 + /* Translstion's buffer for XDR */
5385 + u_int16_t port_buf;
5391 + /* This does sanity checking on RPC payloads,
5392 + * and permits only the RPC "get port" (3)
5393 + * in authorised procedures in client
5394 + * communications with the portmapper.
5397 + /* perform direction dependant RPC work */
5398 + if (dir == IP_CT_DIR_ORIGINAL) {
5402 + /* Get RPC requestor */
5403 + if (IXDR_GET_INT32(data) != 3) {
5404 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5407 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5411 + /* Jump Credentials and Verfifier */
5412 + data += IXDR_GET_INT32(data) + 2;
5413 + data += IXDR_GET_INT32(data) + 2;
5415 + /* Get RPC procedure */
5416 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5417 + (unsigned int)IXDR_GET_INT32(data));
5419 + /* Get RPC protocol and store against client parameters */
5421 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5422 + ct->tuplehash[dir].tuple.src.u.all);
5424 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5425 + xid, IXDR_GET_INT32(data),
5426 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5427 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
5429 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
5430 + (unsigned int)IXDR_GET_INT32(data));
5434 + /* Check for returning packet's stored counterpart */
5435 + req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5436 + struct request_p *, xid,
5437 + ct->tuplehash[!dir].tuple.src.ip,
5438 + ct->tuplehash[!dir].tuple.src.u.all);
5440 + /* Drop unexpected packets */
5442 + DEBUGP("packet is not expected. [skip]\n");
5446 + /* Verifies if packet is really an RPC reply packet */
5448 + if (IXDR_GET_INT32(data) != 1) {
5449 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
5453 + /* Is status accept? */
5455 + if (IXDR_GET_INT32(data)) {
5456 + DEBUGP("packet is not an RPC accept. [skip]\n");
5460 + /* Get Verifier length. Jump verifier */
5462 + data = data + IXDR_GET_INT32(data) + 2;
5464 + /* Is accpet status "success"? */
5465 + if (IXDR_GET_INT32(data)) {
5466 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5470 + /* Get server port number */
5472 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
5474 + /* If a packet has made it this far then it deserves an
5475 + * expectation ... if port == 0, then this service is
5476 + * not going to be registered.
5479 + DEBUGP("port found: %u\n", port_buf);
5481 + memset(&expect, 0, sizeof(expect));
5483 + /* Watch out, Radioactive-Man! */
5484 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5485 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5486 + exp->mask.src.ip = 0xffffffff;
5487 + exp->mask.dst.ip = 0xffffffff;
5489 + switch (req_p->proto) {
5491 + exp->tuple.src.u.udp.port = 0;
5492 + exp->tuple.dst.u.udp.port = htons(port_buf);
5493 + exp->tuple.dst.protonum = IPPROTO_UDP;
5494 + exp->mask.src.u.udp.port = 0;
5495 + exp->mask.dst.u.udp.port = htons(0xffff);
5496 + exp->mask.dst.protonum = 0xffff;
5500 + exp->tuple.src.u.tcp.port = 0;
5501 + exp->tuple.dst.u.tcp.port = htons(port_buf);
5502 + exp->tuple.dst.protonum = IPPROTO_TCP;
5503 + exp->mask.src.u.tcp.port = 0;
5504 + exp->mask.dst.u.tcp.port = htons(0xffff);
5505 + exp->mask.dst.protonum = 0xffff;
5508 + exp->expectfn = NULL;
5510 + ip_conntrack_expect_related(ct, &expect);
5512 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
5513 + NIPQUAD(exp->tuple.src.ip),
5514 + NIPQUAD(exp->tuple.dst.ip),
5515 + port_buf, req_p->proto);
5517 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
5518 + NIPQUAD(exp->mask.src.ip),
5519 + NIPQUAD(exp->mask.dst.ip),
5520 + exp->mask.dst.protonum);
5526 + DEBUGP("packet evaluated. [expect]\n");
5535 +/* RPC TCP helper */
5536 +static int help(const struct iphdr *iph, size_t len,
5537 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5539 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5540 + const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
5541 + size_t tcplen = len - iph->ihl * 4;
5543 + int dir = CTINFO2DIR(ctinfo);
5547 + DEBUGP("new packet to evaluate ..\n");
5549 + /* This works for packets like handshake packets, ignore */
5550 + if (len == ((tcph->doff + iph->ihl) * 4)) {
5551 + DEBUGP("packet has no data (may still be handshaking). [skip]\n");
5555 + /* Until there's been traffic both ways, don't look in packets. */
5556 + if (ctinfo != IP_CT_ESTABLISHED
5557 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5558 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
5559 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
5560 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
5564 + /* Not whole TCP header? */
5565 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5566 + DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
5567 + DEBUGP("packet does not contain a complete TCP header. [skip]\n");
5571 + /* FIXME: Source route IP option packets --RR */
5572 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5573 + csum_partial((char *) tcph, tcplen, 0))) {
5574 + DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5575 + tcph, tcplen, NIPQUAD(iph->saddr),
5576 + NIPQUAD(iph->daddr));
5577 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
5578 + DEBUGP("packet contains a bad checksum. [skip]\n");
5582 + /* perform direction dependant protocol work */
5583 + if (dir == IP_CT_DIR_ORIGINAL) {
5585 + DEBUGP("packet is from the initiator. [cont]\n");
5587 + /* Tests if packet len is ok */
5588 + if ((tcplen - (tcph->doff * 4)) != 60) {
5589 + DEBUGP("packet length is not correct. [skip]\n");
5595 + DEBUGP("packet is from the receiver. [cont]\n");
5597 + /* Tests if packet len is ok */
5598 + if ((tcplen - (tcph->doff * 4)) != 32) {
5599 + DEBUGP("packet length is not correct. [skip]\n");
5604 + /* Get to the data */
5607 + /* Check the RPC data */
5608 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
5615 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
5617 +static void fini(void);
5620 +static int __init init(void)
5623 + static char name[10];
5626 + /* If no port given, default to standard RPC port */
5627 + if (ports[0] == 0)
5628 + ports[0] = RPC_PORT;
5630 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5631 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5633 + if (ports[port] == RPC_PORT)
5634 + sprintf(name, "rpc");
5636 + sprintf(name, "rpc-%d", port);
5638 + rpc_helpers[port].name = name;
5639 + rpc_helpers[port].me = THIS_MODULE;
5640 + rpc_helpers[port].max_expected = 1;
5641 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5642 + rpc_helpers[port].timeout = 0;
5644 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5645 + rpc_helpers[port].mask.dst.protonum = 0xffff;
5647 + /* RPC can come from ports 0:65535 to ports[port] (111) */
5648 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
5649 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
5650 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
5652 + rpc_helpers[port].help = help;
5654 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5655 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5656 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
5657 + ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
5658 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
5659 + ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
5660 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5661 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
5662 + ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
5663 + NIPQUAD(rpc_helpers[port].mask.src.ip),
5664 + ntohs(rpc_helpers[port].mask.src.u.tcp.port));
5666 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
5669 + printk("ERROR registering port %d\n",
5680 +/* This function is intentionally _NOT_ defined as __exit, because
5681 + * it is needed by the init function */
5682 +static void fini(void)
5686 + DEBUGP("cleaning request list\n");
5687 + clean_request(&request_p_list_tcp);
5689 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
5690 + DEBUGP("unregistering port %d\n", ports[port]);
5691 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
5699 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
5700 +EXPORT_SYMBOL(request_p_list_tcp);
5701 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
5702 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
5704 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
5705 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
5706 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2003-12-10 23:14:10.154410992 +0100
5708 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
5709 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5710 + * - original rpc tracking module
5711 + * - "recent" connection handling for kernel 2.3+ netfilter
5713 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5714 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5716 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5717 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
5718 + * - extended matching to support filtering on procedures
5720 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
5722 + * This program is free software; you can redistribute it and/or
5723 + * modify it under the terms of the GNU General Public License
5724 + * as published by the Free Software Foundation; either version
5725 + * 2 of the License, or (at your option) any later version.
5727 + * Module load syntax:
5728 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
5730 + * Please give the ports of all RPC servers you wish to connect to.
5731 + * If you don't specify ports, the default will be port 111.
5735 + * RPCs should not be exposed to the internet - ask the Pentagon;
5737 + * "The unidentified crackers pleaded guilty in July to charges
5738 + * of juvenile delinquency stemming from a string of Pentagon
5739 + * network intrusions in February.
5741 + * The youths, going by the names TooShort and Makaveli, used
5742 + * a common server security hole to break in, according to
5743 + * Dane Jasper, owner of the California Internet service
5744 + * provider, Sonic. They used the hole, known as the 'statd'
5745 + * exploit, to attempt more than 800 break-ins, Jasper said."
5747 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5748 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
5752 +#include <linux/module.h>
5753 +#include <linux/netfilter.h>
5754 +#include <linux/ip.h>
5755 +#include <net/checksum.h>
5756 +#include <net/udp.h>
5758 +#include <asm/param.h>
5759 +#include <linux/sched.h>
5760 +#include <linux/timer.h>
5761 +#include <linux/stddef.h>
5762 +#include <linux/list.h>
5764 +#include <linux/netfilter_ipv4/lockhelp.h>
5765 +#include <linux/netfilter_ipv4/ip_tables.h>
5766 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5767 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5769 +#define MAX_PORTS 8
5770 +static int ports[MAX_PORTS];
5771 +static int ports_n_c = 0;
5774 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5775 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5778 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5779 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
5780 +MODULE_LICENSE("GPL");
5783 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
5786 +#define DEBUGP(format, args...)
5789 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
5790 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
5791 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
5792 +#include <linux/netfilter_ipv4/listhelp.h>
5794 +/* For future conections RPC, using client's cache bindings
5795 + * I'll use ip_conntrack_lock to lock these lists */
5797 +LIST_HEAD(request_p_list_udp);
5800 +static void delete_request_p(unsigned long request_p_ul)
5802 + struct request_p *p = (void *)request_p_ul;
5804 + WRITE_LOCK(&ipct_rpc_udp_lock);
5805 + LIST_DELETE(&request_p_list_udp, p);
5806 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5812 +static void req_cl(struct request_p * r)
5814 + WRITE_LOCK(&ipct_rpc_udp_lock);
5815 + del_timer(&r->timeout);
5816 + LIST_DELETE(&request_p_list_udp, r);
5817 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5823 +static void clean_request(struct list_head *list)
5825 + struct list_head *first = list->prev;
5826 + struct list_head *temp = list->next;
5827 + struct list_head *aux;
5829 + if (list_empty(list))
5832 + while (first != temp) {
5834 + req_cl((struct request_p *)temp);
5837 + req_cl((struct request_p *)temp);
5842 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5845 + struct request_p *req_p;
5847 + /* Verifies if entry already exists */
5848 + WRITE_LOCK(&ipct_rpc_udp_lock);
5849 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5850 + struct request_p *, xid, ip, port);
5853 + /* Refresh timeout */
5854 + if (del_timer(&req_p->timeout)) {
5855 + req_p->timeout.expires = jiffies + EXP;
5856 + add_timer(&req_p->timeout);
5858 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5862 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5864 + /* Allocate new request_p */
5865 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5867 + DEBUGP("can't allocate request_p\n");
5870 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
5871 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5874 + /* Initialize timer */
5875 + init_timer(&req_p->timeout);
5876 + req_p->timeout.function = delete_request_p;
5877 + add_timer(&req_p->timeout);
5880 + WRITE_LOCK(&ipct_rpc_udp_lock);
5881 + list_prepend(&request_p_list_udp, req_p);
5882 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
5888 +static int check_rpc_packet(const u_int32_t *data,
5889 + int dir, struct ip_conntrack *ct,
5890 + struct list_head request_p_list)
5892 + struct request_p *req_p;
5894 + struct ip_conntrack_expect expect, *exp = &expect;
5896 + /* Translstion's buffer for XDR */
5897 + u_int16_t port_buf;
5903 + /* This does sanity checking on RPC payloads,
5904 + * and permits only the RPC "get port" (3)
5905 + * in authorised procedures in client
5906 + * communications with the portmapper.
5909 + /* perform direction dependant RPC work */
5910 + if (dir == IP_CT_DIR_ORIGINAL) {
5914 + /* Get RPC requestor */
5915 + if (IXDR_GET_INT32(data) != 3) {
5916 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5919 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5923 + /* Jump Credentials and Verfifier */
5924 + data = data + IXDR_GET_INT32(data) + 2;
5925 + data = data + IXDR_GET_INT32(data) + 2;
5927 + /* Get RPC procedure */
5928 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5929 + (unsigned int)IXDR_GET_INT32(data));
5931 + /* Get RPC protocol and store against client parameters */
5933 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5934 + ct->tuplehash[dir].tuple.src.u.all);
5936 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5937 + xid, IXDR_GET_INT32(data),
5938 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5939 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
5941 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
5942 + (unsigned int)IXDR_GET_INT32(data));
5946 + /* Check for returning packet's stored counterpart */
5947 + req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5948 + struct request_p *, xid,
5949 + ct->tuplehash[!dir].tuple.src.ip,
5950 + ct->tuplehash[!dir].tuple.src.u.all);
5952 + /* Drop unexpected packets */
5954 + DEBUGP("packet is not expected. [skip]\n");
5958 + /* Verifies if packet is really an RPC reply packet */
5960 + if (IXDR_GET_INT32(data) != 1) {
5961 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
5965 + /* Is status accept? */
5967 + if (IXDR_GET_INT32(data)) {
5968 + DEBUGP("packet is not an RPC accept. [skip]\n");
5972 + /* Get Verifier length. Jump verifier */
5974 + data = data + IXDR_GET_INT32(data) + 2;
5976 + /* Is accpet status "success"? */
5977 + if (IXDR_GET_INT32(data)) {
5978 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5982 + /* Get server port number */
5984 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
5986 + /* If a packet has made it this far then it deserves an
5987 + * expectation ... if port == 0, then this service is
5988 + * not going to be registered.
5991 + DEBUGP("port found: %u\n", port_buf);
5993 + memset(&expect, 0, sizeof(expect));
5995 + /* Watch out, Radioactive-Man! */
5996 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5997 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5998 + exp->mask.src.ip = 0xffffffff;
5999 + exp->mask.dst.ip = 0xffffffff;
6001 + switch (req_p->proto) {
6003 + exp->tuple.src.u.udp.port = 0;
6004 + exp->tuple.dst.u.udp.port = htons(port_buf);
6005 + exp->tuple.dst.protonum = IPPROTO_UDP;
6006 + exp->mask.src.u.udp.port = 0;
6007 + exp->mask.dst.u.udp.port = htons(0xffff);
6008 + exp->mask.dst.protonum = 0xffff;
6012 + exp->tuple.src.u.tcp.port = 0;
6013 + exp->tuple.dst.u.tcp.port = htons(port_buf);
6014 + exp->tuple.dst.protonum = IPPROTO_TCP;
6015 + exp->mask.src.u.tcp.port = 0;
6016 + exp->mask.dst.u.tcp.port = htons(0xffff);
6017 + exp->mask.dst.protonum = 0xffff;
6020 + exp->expectfn = NULL;
6022 + ip_conntrack_expect_related(ct, &expect);
6024 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
6025 + NIPQUAD(exp->tuple.src.ip),
6026 + NIPQUAD(exp->tuple.dst.ip),
6027 + port_buf, req_p->proto);
6029 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
6030 + NIPQUAD(exp->mask.src.ip),
6031 + NIPQUAD(exp->mask.dst.ip),
6032 + exp->mask.dst.protonum);
6038 + DEBUGP("packet evaluated. [expect]\n");
6047 +/* RPC UDP helper */
6048 +static int help(const struct iphdr *iph, size_t len,
6049 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6051 + struct udphdr *udph = (void *) iph + iph->ihl * 4;
6052 + const u_int32_t *data = (const u_int32_t *)udph + 2;
6053 + size_t udplen = len - iph->ihl * 4;
6054 + int dir = CTINFO2DIR(ctinfo);
6058 + const u_int16_t *chsm = (const u_int16_t *)udph + 3;
6061 + DEBUGP("new packet to evaluate ..\n");
6063 + /* Not whole UDP header? */
6064 + if (udplen < sizeof(struct udphdr)) {
6065 + DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
6066 + DEBUGP("packet does not contain a complete UDP header. [skip]\n");
6070 + /* FIXME: Source route IP option packets --RR */
6072 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6073 + csum_partial((char *)udph, udplen, 0))) {
6074 + DEBUGP("[note: failure to get past this error may indicate source routing]\n");
6075 + DEBUGP("packet contains a bad checksum. [skip]\n");
6080 + /* perform direction dependant protocol work */
6081 + if (dir == IP_CT_DIR_ORIGINAL) {
6083 + DEBUGP("packet is from the initiator. [cont]\n");
6085 + /* Tests if packet len is ok */
6086 + if ((udplen - sizeof(struct udphdr)) != 56) {
6087 + DEBUGP("packet length is not correct. [skip]\n");
6093 + DEBUGP("packet is from the receiver. [cont]\n");
6095 + /* Until there's been traffic both ways, don't look in packets. */
6096 + if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6097 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
6098 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
6099 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
6103 + /* Tests if packet len is ok */
6104 + if ((udplen - sizeof(struct udphdr)) != 28) {
6105 + DEBUGP("packet length is not correct. [skip]\n");
6111 + /* Get to the data */
6112 + /* udp *data == *correct */
6114 + /* Check the RPC data */
6115 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
6122 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
6124 +static void fini(void);
6127 +static int __init init(void)
6130 + static char name[10];
6133 + /* If no port given, default to standard RPC port */
6134 + if (ports[0] == 0)
6135 + ports[0] = RPC_PORT;
6137 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6138 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6140 + if (ports[port] == RPC_PORT)
6141 + sprintf(name, "rpc");
6143 + sprintf(name, "rpc-%d", port);
6145 + rpc_helpers[port].name = name;
6146 + rpc_helpers[port].me = THIS_MODULE;
6147 + rpc_helpers[port].max_expected = 1;
6148 + rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6149 + rpc_helpers[port].timeout = 0;
6151 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
6152 + rpc_helpers[port].mask.dst.protonum = 0xffff;
6154 + /* RPC can come from ports 0:65535 to ports[port] (111) */
6155 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
6156 + rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
6157 + rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
6159 + rpc_helpers[port].help = help;
6161 + DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
6162 + DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6163 + NIPQUAD(rpc_helpers[port].tuple.dst.ip),
6164 + ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
6165 + NIPQUAD(rpc_helpers[port].tuple.src.ip),
6166 + ntohs(rpc_helpers[port].tuple.src.u.udp.port));
6167 + DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6168 + NIPQUAD(rpc_helpers[port].mask.dst.ip),
6169 + ntohs(rpc_helpers[port].mask.dst.u.udp.port),
6170 + NIPQUAD(rpc_helpers[port].mask.src.ip),
6171 + ntohs(rpc_helpers[port].mask.src.u.udp.port));
6173 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
6176 + printk("ERROR registering port %d\n",
6187 +/* This function is intentionally _NOT_ defined as __exit, because
6188 + * it is needed by the init function */
6189 +static void fini(void)
6193 + DEBUGP("cleaning request list\n");
6194 + clean_request(&request_p_list_udp);
6196 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
6197 + DEBUGP("unregistering port %d\n", ports[port]);
6198 + ip_conntrack_helper_unregister(&rpc_helpers[port]);
6206 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
6207 +EXPORT_SYMBOL(request_p_list_udp);
6208 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
6209 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
6211 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
6212 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
6213 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rsh.c 2003-12-10 23:14:11.557197736 +0100
6215 +/* RSH extension for IP connection tracking, Version 1.0
6216 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
6217 + * based on HW's ip_conntrack_irc.c
6219 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
6221 + * This program is free software; you can redistribute it and/or
6222 + * modify it under the terms of the GNU General Public License
6223 + * as published by the Free Software Foundation; either version
6224 + * 2 of the License, or (at your option) any later version.
6226 + * Module load syntax:
6227 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
6229 + * please give the ports of all RSH servers You wish to connect to.
6230 + * If You don't specify ports, the default will be port 514
6233 + * RSH blows ... you should use SSH (openssh.org) to replace it,
6234 + * unfortunately I babysit some sysadmins that won't migrate
6235 + * their legacy crap, in our second tier.
6240 + * Some docco ripped from the net to teach me all there is to know about
6241 + * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
6244 + * I have no idea what "unix rshd man pages" these guys have .. but that
6245 + * is some pretty detailed docco!
6248 + * 4. Of the rsh protocol.
6249 + * -----------------------
6251 + * The rshd listens on TCP port #514. The following info is from the unix
6252 + * rshd man pages :
6254 + * "Service Request Protocol
6256 + * When the rshd daemon receives a service request, it initiates the
6257 + * following protocol:
6259 + * 1. The rshd daemon checks the source port number for the request.
6260 + * If the port number is not in the range 0 through 1023, the rshd daemon
6261 + * terminates the connection.
6263 + * 2. The rshd daemon reads characters from the socket up to a null byte.
6264 + * The string read is interpreted as an ASCII number (base 10). If this
6265 + * number is nonzero, the rshd daemon interprets it as the port number
6266 + * of a secondary stream to be used as standard error. A second connection
6267 + * is created to the specified port on the client host. The source port
6268 + * on the local host is in the range 0 through 1023.
6270 + * 3. The rshd daemon uses the source address of the initial connection
6271 + * request to determine the name of the client host. If the name cannot
6272 + * be determined, the rshd daemon uses the dotted decimal representation
6273 + * of the client host's address.
6275 + * 4. The rshd daemon retrieves the following information from the initial
6278 + * * A null-terminated string of at most 16 bytes interpreted as
6279 + * the user name of the user on the client host.
6281 + * * A null-terminated string of at most 16 bytes interpreted as
6282 + * the user name to be used on the local server host.
6284 + * * Another null-terminated string interpreted as a command line
6285 + * to be passed to a shell on the local server host.
6287 + * 5. The rshd daemon attempts to validate the user using the following steps:
6289 + * a. The rshd daemon looks up the local user name in the /etc/passwd
6290 + * file and tries to switch to the home directory (using the chdir
6291 + * subroutine). If either the lookup or the directory change fails,
6292 + * the rshd daemon terminates the connection.
6294 + * b. If the local user ID is a nonzero value, the rshd daemon searches
6295 + * the /etc/hosts.equiv file to see if the name of the client
6296 + * workstation is listed. If the client workstation is listed as an
6297 + * equivalent host, the rshd daemon validates the user.
6299 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
6300 + * authenticate the user by checking the .rhosts file.
6302 + * d. If either the $HOME/.rhosts authentication fails or the
6303 + * client host is not an equivalent host, the rshd daemon
6304 + * terminates the connection.
6306 + * 6. Once rshd validates the user, the rshd daemon returns a null byte
6307 + * on the initial connection and passes the command line to the user's
6308 + * local login shell. The shell then inherits the network connections
6309 + * established by the rshd daemon."
6314 +#include <linux/module.h>
6315 +#include <linux/netfilter.h>
6316 +#include <linux/ip.h>
6317 +#include <net/checksum.h>
6318 +#include <net/tcp.h>
6320 +#include <linux/netfilter_ipv4/lockhelp.h>
6321 +#include <linux/netfilter_ipv4/ip_tables.h>
6322 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6323 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
6325 +#define MAX_PORTS 8
6326 +static int ports[MAX_PORTS];
6327 +static int ports_n_c = 0;
6329 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
6330 +MODULE_DESCRIPTION("RSH connection tracking module");
6331 +MODULE_LICENSE("GPL");
6333 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6334 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
6337 +DECLARE_LOCK(ip_rsh_lock);
6338 +struct module *ip_conntrack_rsh = THIS_MODULE;
6341 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
6344 +#define DEBUGP(format, args...)
6349 +/* FIXME: This should be in userspace. Later. */
6350 +static int help(const struct iphdr *iph, size_t len,
6351 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6353 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6354 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6355 + const char *data = (const char *) tcph + tcph->doff * 4;
6356 + u_int32_t tcplen = len - iph->ihl * 4;
6357 + int dir = CTINFO2DIR(ctinfo);
6358 + struct ip_conntrack_expect expect, *exp = &expect;
6359 + struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
6363 + /* note that "maxoctet" is used to maintain sanity (8 was the
6364 + * original array size used in rshd/glibc) -- is there a
6365 + * vulnerability in rshd.c in the looped port *= 10?
6369 + DEBUGP("entered\n");
6371 + /* bail if packet is not from RSH client */
6372 + if (dir == IP_CT_DIR_REPLY)
6375 + /* Until there's been traffic both ways, don't look in packets. */
6376 + if (ctinfo != IP_CT_ESTABLISHED
6377 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6378 + DEBUGP("Conntrackinfo = %u\n", ctinfo);
6382 + /* Not whole TCP header? */
6383 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
6384 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
6388 + /* Checksum invalid? Ignore. */
6389 + /* FIXME: Source route IP option packets --RR */
6390 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6391 + csum_partial((char *) tcph, tcplen, 0))) {
6392 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6393 + tcph, tcplen, NIPQUAD(iph->saddr),
6394 + NIPQUAD(iph->daddr));
6398 + /* find the rsh stderr port */
6401 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
6406 + if (*data < 48 || *data > 57) {
6407 + DEBUGP("these aren't the packets you're looking for ..\n");
6410 + port = port * 10 + ( *data - 48 );
6413 + /* dont relate sessions that try to expose the client */
6414 + DEBUGP("found port %u\n", port);
6415 + if (port > 1023) {
6416 + DEBUGP("skipping, expected port size is greater than 1023!\n");
6421 + LOCK_BH(&ip_rsh_lock);
6423 + /* new(,related) connection is;
6424 + * reply + dst (uint)port + src port (0:1023)
6426 + memset(&expect, 0, sizeof(expect));
6428 + /* save some discovered data, in case someone ever wants to write
6429 + * a NAT module for this bastard ..
6431 + exp_rsh_info->port = port;
6433 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
6436 + /* Watch out, Radioactive-Man! */
6437 + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6438 + exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
6439 + exp->tuple.src.u.tcp.port = 0;
6440 + exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
6441 + exp->tuple.dst.protonum = IPPROTO_TCP;
6443 + exp->mask.src.ip = 0xffffffff;
6444 + exp->mask.dst.ip = 0xffffffff;
6446 + exp->mask.src.u.tcp.port = htons(0xfc00);
6447 + exp->mask.dst.u.tcp.port = htons(0xfc00);
6448 + exp->mask.dst.protonum = 0xffff;
6450 + exp->expectfn = NULL;
6452 + ip_conntrack_expect_related(ct, &expect);
6454 + DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6455 + NIPQUAD(exp->tuple.src.ip),
6456 + ntohs(exp->tuple.src.u.tcp.port),
6457 + NIPQUAD(exp->tuple.dst.ip),
6458 + ntohs(exp->tuple.dst.u.tcp.port));
6460 + DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6461 + NIPQUAD(exp->mask.src.ip),
6462 + ntohs(exp->mask.src.u.tcp.port),
6463 + NIPQUAD(exp->mask.dst.ip),
6464 + ntohs(exp->mask.dst.u.tcp.port));
6465 + UNLOCK_BH(&ip_rsh_lock);
6470 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
6472 +static void fini(void);
6474 +static int __init init(void)
6477 + static char name[10];
6480 + /* If no port given, default to standard RSH port */
6481 + if (ports[0] == 0)
6482 + ports[0] = RSH_PORT;
6484 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6485 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6487 + if (ports[port] == RSH_PORT)
6488 + sprintf(name, "rsh");
6490 + sprintf(name, "rsh-%d", port);
6492 + rsh_helpers[port].name = name;
6493 + rsh_helpers[port].me = THIS_MODULE;
6494 + rsh_helpers[port].max_expected = 1;
6495 + rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6496 + rsh_helpers[port].timeout = 0;
6498 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
6499 + rsh_helpers[port].mask.dst.protonum = 0xffff;
6501 + /* RSH must come from ports 0:1023 to ports[port] (514) */
6502 + rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
6503 + rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
6504 + rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
6506 + rsh_helpers[port].help = help;
6508 + DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
6509 + DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6510 + NIPQUAD(rsh_helpers[port].tuple.src.ip),
6511 + ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
6512 + NIPQUAD(rsh_helpers[port].tuple.dst.ip),
6513 + ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
6514 + DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6515 + NIPQUAD(rsh_helpers[port].mask.src.ip),
6516 + ntohs(rsh_helpers[port].mask.src.u.tcp.port),
6517 + NIPQUAD(rsh_helpers[port].mask.dst.ip),
6518 + ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
6520 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
6523 + printk("ERROR registering port %d\n",
6533 +/* This function is intentionally _NOT_ defined as __exit, because
6534 + * it is needed by the init function */
6535 +static void fini(void)
6538 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6539 + DEBUGP("unregistering port %d\n", ports[port]);
6540 + ip_conntrack_helper_unregister(&rsh_helpers[port]);
6546 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
6547 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
6548 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rtsp.c 2003-12-10 23:14:12.891994816 +0100
6551 + * RTSP extension for IP connection tracking
6552 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6553 + * based on ip_conntrack_irc.c
6555 + * This program is free software; you can redistribute it and/or
6556 + * modify it under the terms of the GNU General Public License
6557 + * as published by the Free Software Foundation; either version
6558 + * 2 of the License, or (at your option) any later version.
6560 + * Module load syntax:
6561 + * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6562 + * max_outstanding=n setup_timeout=secs
6564 + * If no ports are specified, the default will be port 554.
6566 + * With max_outstanding you can define the maximum number of not yet
6567 + * answered SETUP requests per RTSP session (default 8).
6568 + * With setup_timeout you can specify how long the system waits for
6569 + * an expected data channel (default 300 seconds).
6572 +#include <linux/config.h>
6573 +#include <linux/module.h>
6574 +#include <linux/netfilter.h>
6575 +#include <linux/ip.h>
6576 +#include <net/checksum.h>
6577 +#include <net/tcp.h>
6579 +#include <linux/netfilter_ipv4/lockhelp.h>
6580 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6581 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6583 +#include <linux/ctype.h>
6584 +#define NF_NEED_STRNCASECMP
6585 +#define NF_NEED_STRTOU16
6586 +#define NF_NEED_STRTOU32
6587 +#define NF_NEED_NEXTLINE
6588 +#include <linux/netfilter_helpers.h>
6589 +#define NF_NEED_MIME_NEXTLINE
6590 +#include <linux/netfilter_mime.h>
6592 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
6594 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
6595 +#ifdef IP_NF_RTSP_DEBUG
6596 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
6598 +#define DEBUGP(args...)
6601 +#define MAX_PORTS 8
6602 +static int ports[MAX_PORTS];
6603 +static int num_ports = 0;
6604 +static int max_outstanding = 8;
6605 +static unsigned int setup_timeout = 300;
6607 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6608 +MODULE_DESCRIPTION("RTSP connection tracking module");
6609 +MODULE_LICENSE("GPL");
6611 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6612 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6613 +MODULE_PARM(max_outstanding, "i");
6614 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
6615 +MODULE_PARM(setup_timeout, "i");
6616 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
6619 +DECLARE_LOCK(ip_rtsp_lock);
6620 +struct module* ip_conntrack_rtsp = THIS_MODULE;
6623 + * Max mappings we will allow for one RTSP connection (for RTP, the number
6624 + * of allocated ports is twice this value). Note that SMIL burns a lot of
6625 + * ports so keep this reasonably high. If this is too low, you will see a
6626 + * lot of "no free client map entries" messages.
6628 +#define MAX_PORT_MAPS 16
6630 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
6632 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6635 + * Parse an RTSP packet.
6637 + * Returns zero if parsing failed.
6640 + * IN ptcp tcp data pointer
6641 + * IN tcplen tcp data len
6642 + * IN/OUT ptcpoff points to current tcp offset
6643 + * OUT phdrsoff set to offset of rtsp headers
6644 + * OUT phdrslen set to length of rtsp headers
6645 + * OUT pcseqoff set to offset of CSeq header
6646 + * OUT pcseqlen set to length of CSeq header
6649 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
6650 + uint* phdrsoff, uint* phdrslen,
6651 + uint* pcseqoff, uint* pcseqlen)
6653 + uint entitylen = 0;
6657 + if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6662 + *phdrsoff = *ptcpoff;
6663 + while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6667 + if (entitylen > 0)
6669 + *ptcpoff += min(entitylen, tcplen - *ptcpoff);
6673 + if (lineoff+linelen > tcplen)
6675 + INFOP("!! overrun !!\n");
6679 + if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
6681 + *pcseqoff = lineoff;
6682 + *pcseqlen = linelen;
6684 + if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
6686 + uint off = lineoff+15;
6687 + SKIP_WSPACE(ptcp+lineoff, linelen, off);
6688 + nf_strtou32(ptcp+off, &entitylen);
6691 + *phdrslen = (*ptcpoff) - (*phdrsoff);
6697 + * Find lo/hi client ports (if any) in transport header
6699 + * ptcp, tcplen = packet
6700 + * tranoff, tranlen = buffer to search
6703 + * pport_lo, pport_hi = lo/hi ports (host endian)
6705 + * Returns nonzero if any client ports found
6707 + * Note: it is valid (and expected) for the client to request multiple
6708 + * transports, so we need to parse the entire line.
6711 +rtsp_parse_transport(char* ptran, uint tranlen,
6712 + struct ip_ct_rtsp_expect* prtspexp)
6717 + if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6718 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
6720 + INFOP("sanity check failed\n");
6723 + DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
6725 + SKIP_WSPACE(ptran, tranlen, off);
6727 + /* Transport: tran;field;field=val,tran;field;field=val,... */
6728 + while (off < tranlen)
6730 + const char* pparamend;
6731 + uint nextparamoff;
6733 + pparamend = memchr(ptran+off, ',', tranlen-off);
6734 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
6735 + nextparamoff = pparamend-ptran;
6737 + while (off < nextparamoff)
6739 + const char* pfieldend;
6740 + uint nextfieldoff;
6742 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6743 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6745 + if (strncmp(ptran+off, "client_port=", 12) == 0)
6751 + numlen = nf_strtou16(ptran+off, &port);
6753 + if (prtspexp->loport != 0 && prtspexp->loport != port)
6755 + DEBUGP("multiple ports found, port %hu ignored\n", port);
6759 + prtspexp->loport = prtspexp->hiport = port;
6760 + if (ptran[off] == '-')
6763 + numlen = nf_strtou16(ptran+off, &port);
6765 + prtspexp->pbtype = pb_range;
6766 + prtspexp->hiport = port;
6768 + // If we have a range, assume rtp:
6769 + // loport must be even, hiport must be loport+1
6770 + if ((prtspexp->loport & 0x0001) != 0 ||
6771 + prtspexp->hiport != prtspexp->loport+1)
6773 + DEBUGP("incorrect range: %hu-%hu, correcting\n",
6774 + prtspexp->loport, prtspexp->hiport);
6775 + prtspexp->loport &= 0xfffe;
6776 + prtspexp->hiport = prtspexp->loport+1;
6779 + else if (ptran[off] == '/')
6782 + numlen = nf_strtou16(ptran+off, &port);
6784 + prtspexp->pbtype = pb_discon;
6785 + prtspexp->hiport = port;
6792 + * Note we don't look for the destination parameter here.
6793 + * If we are using NAT, the NAT module will handle it. If not,
6794 + * and the client is sending packets elsewhere, the expectation
6795 + * will quietly time out.
6798 + off = nextfieldoff;
6801 + off = nextparamoff;
6807 +/*** conntrack functions ***/
6809 +/* outbound packet: client->server */
6811 +help_out(const struct iphdr* iph, size_t pktlen,
6812 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6814 + int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
6815 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6816 + uint tcplen = pktlen - iph->ihl * 4;
6817 + char* pdata = (char*)tcph + tcph->doff * 4;
6818 + uint datalen = tcplen - tcph->doff * 4;
6821 + struct ip_conntrack_expect exp;
6823 + while (dataoff < datalen)
6825 + uint cmdoff = dataoff;
6835 + if (!rtsp_parse_message(pdata, datalen, &dataoff,
6836 + &hdrsoff, &hdrslen,
6837 + &cseqoff, &cseqlen))
6839 + break; /* not a valid message */
6842 + if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
6844 + continue; /* not a SETUP message */
6846 + DEBUGP("found a setup message\n");
6848 + memset(&exp, 0, sizeof(exp));
6851 + while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
6852 + &lineoff, &linelen))
6858 + if (off > hdrsoff+hdrslen)
6860 + INFOP("!! overrun !!");
6864 + if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
6866 + rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
6867 + &exp.help.exp_rtsp_info);
6871 + if (exp.help.exp_rtsp_info.loport == 0)
6873 + DEBUGP("no udp transports found\n");
6874 + continue; /* no udp transports found */
6877 + DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
6878 + (int)exp.help.exp_rtsp_info.pbtype,
6879 + exp.help.exp_rtsp_info.loport,
6880 + exp.help.exp_rtsp_info.hiport);
6882 + LOCK_BH(&ip_rtsp_lock);
6883 + exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
6884 + exp.help.exp_rtsp_info.len = hdrslen;
6886 + exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6887 + exp.mask.src.ip = 0xffffffff;
6888 + exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
6889 + exp.mask.dst.ip = 0xffffffff;
6890 + exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
6891 + exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
6892 + exp.tuple.dst.protonum = IPPROTO_UDP;
6893 + exp.mask.dst.protonum = 0xffff;
6895 + DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6896 + NIPQUAD(exp.tuple.src.ip),
6897 + ntohs(exp.tuple.src.u.tcp.port),
6898 + NIPQUAD(exp.tuple.dst.ip),
6899 + ntohs(exp.tuple.dst.u.tcp.port));
6901 + /* pass the request off to the nat helper */
6902 + rc = ip_conntrack_expect_related(ct, &exp);
6903 + UNLOCK_BH(&ip_rtsp_lock);
6906 + DEBUGP("ip_conntrack_expect_related succeeded\n");
6910 + INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
6917 +/* inbound packet: server->client */
6919 +help_in(const struct iphdr* iph, size_t pktlen,
6920 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6926 +help(const struct iphdr* iph, size_t pktlen,
6927 + struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6929 + /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6930 + struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6931 + u_int32_t tcplen = pktlen - iph->ihl * 4;
6933 + /* Until there's been traffic both ways, don't look in packets. */
6934 + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
6936 + DEBUGP("conntrackinfo = %u\n", ctinfo);
6940 + /* Not whole TCP header? */
6941 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
6943 + DEBUGP("tcplen = %u\n", (unsigned)tcplen);
6947 + /* Checksum invalid? Ignore. */
6948 + /* FIXME: Source route IP option packets --RR */
6949 + if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6950 + csum_partial((char*)tcph, tcplen, 0)))
6952 + DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6953 + tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6957 + switch (CTINFO2DIR(ctinfo))
6959 + case IP_CT_DIR_ORIGINAL:
6960 + help_out(iph, pktlen, ct, ctinfo);
6962 + case IP_CT_DIR_REPLY:
6963 + help_in(iph, pktlen, ct, ctinfo);
6972 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
6973 +static char rtsp_names[MAX_PORTS][10];
6975 +/* This function is intentionally _NOT_ defined as __exit */
6980 + for (i = 0; i < num_ports; i++)
6982 + DEBUGP("unregistering port %d\n", ports[i]);
6983 + ip_conntrack_helper_unregister(&rtsp_helpers[i]);
6991 + struct ip_conntrack_helper *hlpr;
6994 + printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
6996 + if (max_outstanding < 1)
6998 + printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
7001 + if (setup_timeout < 0)
7003 + printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
7007 + /* If no port given, default to standard rtsp port */
7008 + if (ports[0] == 0)
7010 + ports[0] = RTSP_PORT;
7013 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
7015 + hlpr = &rtsp_helpers[i];
7016 + memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
7017 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7018 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
7019 + hlpr->mask.src.u.tcp.port = 0xFFFF;
7020 + hlpr->mask.dst.protonum = 0xFFFF;
7021 + hlpr->max_expected = max_outstanding;
7022 + hlpr->timeout = setup_timeout;
7023 + hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
7024 + hlpr->me = ip_conntrack_rtsp;
7025 + hlpr->help = help;
7027 + tmpname = &rtsp_names[i][0];
7028 + if (ports[i] == RTSP_PORT)
7030 + sprintf(tmpname, "rtsp");
7034 + sprintf(tmpname, "rtsp-%d", i);
7036 + hlpr->name = tmpname;
7038 + DEBUGP("port #%d: %d\n", i, ports[i]);
7040 + ret = ip_conntrack_helper_register(hlpr);
7044 + printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
7053 +#ifdef CONFIG_IP_NF_NAT_NEEDED
7054 +EXPORT_SYMBOL(ip_rtsp_lock);
7059 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
7060 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-12-10 20:50:26.980332712 +0100
7061 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-12-10 23:14:22.974462048 +0100
7063 len += sprintf(buffer + len, "[ASSURED] ");
7064 len += sprintf(buffer + len, "use=%u ",
7065 atomic_read(&conntrack->ct_general.use));
7066 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
7067 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
7069 len += sprintf(buffer + len, "\n");
7072 @@ -186,6 +189,26 @@
7073 return ip_conntrack_confirm(*pskb);
7076 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
7077 + struct sk_buff **pskb,
7078 + const struct net_device *in,
7079 + const struct net_device *out,
7080 + int (*okfn)(struct sk_buff *))
7082 + /* Previously seen (loopback)? Ignore. Do this before
7083 + fragment check. */
7084 + if ((*pskb)->nfct)
7087 + /* Gather fragments. */
7088 + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
7089 + *pskb = ip_ct_gather_frags(*pskb);
7096 static unsigned int ip_refrag(unsigned int hooknum,
7097 struct sk_buff **pskb,
7098 const struct net_device *in,
7099 @@ -226,6 +249,15 @@
7100 return ip_conntrack_in(hooknum, pskb, in, out, okfn);
7103 +/* At the very first: defragment */
7104 +static struct nf_hook_ops ip_conntrack_defrag_ops = {
7105 + .hook = ip_conntrack_defrag,
7106 + .owner = THIS_MODULE,
7108 + .hooknum = NF_IP_PRE_ROUTING,
7109 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
7112 /* Connection tracking may drop packets, but never alters them, so
7113 make it the first hook. */
7114 static struct nf_hook_ops ip_conntrack_in_ops = {
7115 @@ -236,6 +268,14 @@
7116 .priority = NF_IP_PRI_CONNTRACK,
7119 +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
7120 + .hook = ip_conntrack_defrag,
7121 + .owner = THIS_MODULE,
7123 + .hooknum = NF_IP_LOCAL_OUT,
7124 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
7127 static struct nf_hook_ops ip_conntrack_local_out_ops = {
7128 .hook = ip_conntrack_local,
7129 .owner = THIS_MODULE,
7130 @@ -368,10 +408,20 @@
7131 if (!proc) goto cleanup_init;
7132 proc->owner = THIS_MODULE;
7134 + ret = nf_register_hook(&ip_conntrack_defrag_ops);
7136 + printk("ip_conntrack: can't register pre-routing defrag hook.\n");
7137 + goto cleanup_proc;
7139 + ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
7141 + printk("ip_conntrack: can't register local_out defrag hook.\n");
7142 + goto cleanup_defragops;
7144 ret = nf_register_hook(&ip_conntrack_in_ops);
7146 printk("ip_conntrack: can't register pre-routing hook.\n");
7147 - goto cleanup_proc;
7148 + goto cleanup_defraglocalops;
7150 ret = nf_register_hook(&ip_conntrack_local_out_ops);
7152 @@ -409,6 +459,10 @@
7153 nf_unregister_hook(&ip_conntrack_local_out_ops);
7155 nf_unregister_hook(&ip_conntrack_in_ops);
7156 + cleanup_defraglocalops:
7157 + nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
7158 + cleanup_defragops:
7159 + nf_unregister_hook(&ip_conntrack_defrag_ops);
7161 proc_net_remove("ip_conntrack");
7163 @@ -417,13 +471,20 @@
7167 -/* FIXME: Allow NULL functions and sub in pointers to generic for
7170 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
7171 + * @proto: structure describing this layer 4 protocol helper
7173 + * This function is called by layer 4 protocol helpers to register
7174 + * themselves with the conntrack core.
7176 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
7179 struct list_head *i;
7181 + /* FIXME: Allow NULL functions and sub in pointers to generic for
7183 WRITE_LOCK(&ip_conntrack_lock);
7184 list_for_each(i, &protocol_list) {
7185 if (((struct ip_conntrack_protocol *)i)->proto
7186 @@ -440,12 +501,20 @@
7191 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
7192 + * @proto: structure describing this layer 4 protocol helper
7194 + * This function is called byh layer 4 protocol helpers to unregister
7195 + * themselvers from the conntrack core. Please note that all conntrack
7196 + * entries for this protocol are deleted from the conntrack hash table.
7198 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
7200 WRITE_LOCK(&ip_conntrack_lock);
7202 - /* ip_ct_find_proto() returns proto_generic in case there is no protocol
7203 - * helper. So this should be enough - HW */
7204 + /* ip_ct_find_proto() returns proto_generic in case there is no
7205 + * protocol helper. So this should be enough - HW */
7206 LIST_DELETE(&protocol_list, proto);
7207 WRITE_UNLOCK(&ip_conntrack_lock);
7210 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
7211 EXPORT_SYMBOL(ip_ct_selective_cleanup);
7212 EXPORT_SYMBOL(ip_ct_refresh);
7213 +EXPORT_SYMBOL(ip_ct_death_by_timeout);
7214 EXPORT_SYMBOL(ip_ct_find_proto);
7215 EXPORT_SYMBOL(__ip_ct_find_proto);
7216 EXPORT_SYMBOL(ip_ct_find_helper);
7218 EXPORT_SYMBOL(ip_conntrack_expect_list);
7219 EXPORT_SYMBOL(ip_conntrack_lock);
7220 EXPORT_SYMBOL(ip_conntrack_hash);
7221 +EXPORT_SYMBOL(ip_conntrack_untracked);
7222 EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
7223 EXPORT_SYMBOL_GPL(ip_conntrack_put);
7224 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
7225 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
7226 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_talk.c 2003-12-10 23:14:15.480601288 +0100
7229 + * talk extension for IP connection tracking.
7230 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7232 + * This program is free software; you can redistribute it and/or
7233 + * modify it under the terms of the GNU General Public License
7234 + * as published by the Free Software Foundation; either version
7235 + * 2 of the License, or (at your option) any later version.
7237 + * Module load syntax:
7238 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
7240 + * talk=[0|1] disable|enable old talk support
7241 + * ntalk=[0|1] disable|enable ntalk support
7242 + * ntalk2=[0|1] disable|enable ntalk2 support
7244 + * The default is talk=1 ntalk=1 ntalk2=1
7246 + * The helper does not support simultaneous talk requests.
7249 + * ASCII art on talk protocols
7252 + * caller server callee server
7259 + * caller client ----------- callee client
7262 + * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
7263 + * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
7264 + * 3. callee client <-> caller server: LOOK_UP invitation
7265 + * 4. callee client <-> caller client: talk data channel
7267 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
7268 + * draft-hunter-talk-00.txt
7269 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
7271 +#include <linux/config.h>
7272 +#include <linux/module.h>
7273 +#include <linux/netfilter.h>
7274 +#include <linux/ip.h>
7275 +#include <net/checksum.h>
7276 +#include <net/udp.h>
7278 +#include <linux/netfilter_ipv4/lockhelp.h>
7279 +#include <linux/netfilter_ipv4/ip_conntrack.h>
7280 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
7281 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7282 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7284 +/* Default all talk protocols are supported */
7285 +static int talk = 1;
7286 +static int ntalk = 1;
7287 +static int ntalk2 = 1;
7288 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7289 +MODULE_DESCRIPTION("talk connection tracking module");
7290 +MODULE_LICENSE("GPL");
7292 +MODULE_PARM(talk, "i");
7293 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7294 +MODULE_PARM(ntalk, "i");
7295 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7296 +MODULE_PARM(ntalk2, "i");
7297 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7300 +DECLARE_LOCK(ip_talk_lock);
7301 +struct module *ip_conntrack_talk = THIS_MODULE;
7304 +#define DEBUGP printk
7306 +#define DEBUGP(format, args...)
7309 +static int talk_expect(struct ip_conntrack *ct);
7310 +static int ntalk_expect(struct ip_conntrack *ct);
7312 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
7314 +static int talk_help_response(const struct iphdr *iph, size_t len,
7315 + struct ip_conntrack *ct,
7316 + enum ip_conntrack_info ctinfo,
7321 + struct talk_addr *addr)
7323 + int dir = CTINFO2DIR(ctinfo);
7324 + struct ip_conntrack_expect expect, *exp = &expect;
7325 + struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
7327 + DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
7328 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7331 + if (!(answer == SUCCESS && type == mode))
7334 + memset(&expect, 0, sizeof(expect));
7336 + if (type == ANNOUNCE) {
7338 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
7340 + /* update the talk info */
7341 + LOCK_BH(&ip_talk_lock);
7342 + exp_talk_info->port = htons(talk_port);
7344 + /* expect callee client -> caller server message */
7345 + exp->tuple = ((struct ip_conntrack_tuple)
7346 + { { ct->tuplehash[dir].tuple.src.ip,
7348 + { ct->tuplehash[dir].tuple.dst.ip,
7349 + { .tcp = { htons(talk_port) } },
7351 + exp->mask = ((struct ip_conntrack_tuple)
7352 + { { 0xFFFFFFFF, { 0 } },
7353 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
7355 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
7357 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
7358 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
7359 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
7361 + /* Ignore failure; should only happen with NAT */
7362 + ip_conntrack_expect_related(ct, &expect);
7363 + UNLOCK_BH(&ip_talk_lock);
7365 + if (type == LOOK_UP) {
7367 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
7369 + /* update the talk info */
7370 + LOCK_BH(&ip_talk_lock);
7371 + exp_talk_info->port = addr->ta_port;
7373 + /* expect callee client -> caller client connection */
7374 + exp->tuple = ((struct ip_conntrack_tuple)
7375 + { { ct->tuplehash[!dir].tuple.src.ip,
7378 + { addr->ta_port },
7380 + exp->mask = ((struct ip_conntrack_tuple)
7381 + { { 0xFFFFFFFF, { 0 } },
7382 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
7384 + exp->expectfn = NULL;
7386 + DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
7387 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
7388 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
7390 + /* Ignore failure; should only happen with NAT */
7391 + ip_conntrack_expect_related(ct, &expect);
7392 + UNLOCK_BH(&ip_talk_lock);
7398 +/* FIXME: This should be in userspace. Later. */
7399 +static int talk_help(const struct iphdr *iph, size_t len,
7400 + struct ip_conntrack *ct,
7401 + enum ip_conntrack_info ctinfo,
7405 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7406 + const char *data = (const char *)udph + sizeof(struct udphdr);
7407 + int dir = CTINFO2DIR(ctinfo);
7410 + DEBUGP("ip_ct_talk_help: help entered\n");
7412 + /* Until there's been traffic both ways, don't look in packets. */
7413 + if (ctinfo != IP_CT_ESTABLISHED
7414 + && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
7415 + DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
7419 + /* Not whole UDP header? */
7420 + udplen = len - iph->ihl * 4;
7421 + if (udplen < sizeof(struct udphdr)) {
7422 + DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
7426 + /* Checksum invalid? Ignore. */
7427 + /* FIXME: Source route IP option packets --RR */
7428 + if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7429 + csum_partial((char *)udph, udplen, 0))) {
7430 + DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
7431 + udph, udplen, NIPQUAD(iph->saddr),
7432 + NIPQUAD(iph->daddr));
7436 + DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7437 + NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
7439 + if (dir == IP_CT_DIR_ORIGINAL)
7442 + if (talk_port == TALK_PORT
7443 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7444 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7445 + ((struct talk_response *)data)->type,
7446 + ((struct talk_response *)data)->answer,
7447 + &(((struct talk_response *)data)->addr));
7448 + else if (talk_port == NTALK_PORT
7450 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7451 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7452 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7453 + ((struct ntalk_response *)data)->type,
7454 + ((struct ntalk_response *)data)->answer,
7455 + &(((struct ntalk_response *)data)->addr));
7456 + else if (talk_port == NTALK_PORT
7458 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7459 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7460 + return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7461 + ((struct ntalk2_response *)data)->type,
7462 + ((struct ntalk2_response *)data)->answer,
7463 + &(((struct ntalk2_response *)data)->addr));
7465 + DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
7466 + (unsigned)udplen - sizeof(struct udphdr),
7467 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7472 +static int lookup_help(const struct iphdr *iph, size_t len,
7473 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7475 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
7478 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
7479 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7481 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
7484 +static struct ip_conntrack_helper lookup_helpers[2] =
7485 + { { { NULL, NULL },
7486 + "talk", /* name */
7488 + NULL, /* module */
7489 + 1, /* max_expected */
7490 + 240, /* timeout */
7491 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
7492 + { 0, { 0 }, IPPROTO_UDP } },
7493 + { { 0, { 0xFFFF } }, /* mask */
7494 + { 0, { 0 }, 0xFFFF } },
7495 + lookup_help }, /* helper */
7497 + "ntalk", /* name */
7499 + NULL, /* module */
7500 + 1, /* max_expected */
7501 + 240, /* timeout */
7502 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
7503 + { 0, { 0 }, IPPROTO_UDP } },
7504 + { { 0, { 0xFFFF } }, /* mask */
7505 + { 0, { 0 }, 0xFFFF } },
7506 + lookup_nhelp } /* helper */
7509 +static int talk_expect(struct ip_conntrack *ct)
7511 + DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
7512 + WRITE_LOCK(&ip_conntrack_lock);
7513 + ct->helper = &lookup_helpers[0];
7514 + WRITE_UNLOCK(&ip_conntrack_lock);
7516 + return NF_ACCEPT; /* unused */
7519 +static int ntalk_expect(struct ip_conntrack *ct)
7521 + DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
7522 + WRITE_LOCK(&ip_conntrack_lock);
7523 + ct->helper = &lookup_helpers[1];
7524 + WRITE_UNLOCK(&ip_conntrack_lock);
7526 + return NF_ACCEPT; /* unused */
7529 +static int help(const struct iphdr *iph, size_t len,
7530 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7532 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
7535 +static int nhelp(const struct iphdr *iph, size_t len,
7536 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7538 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
7541 +static struct ip_conntrack_helper talk_helpers[2] =
7542 + { { { NULL, NULL },
7543 + "talk", /* name */
7545 + THIS_MODULE, /* module */
7546 + 1, /* max_expected */
7547 + 240, /* timeout */
7548 + { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
7549 + { 0, { 0 }, IPPROTO_UDP } },
7550 + { { 0, { 0xFFFF } }, /* mask */
7551 + { 0, { 0 }, 0xFFFF } },
7552 + help }, /* helper */
7554 + "ntalk", /* name */
7556 + THIS_MODULE, /* module */
7557 + 1, /* max_expected */
7558 + 240, /* timeout */
7559 + { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
7560 + { 0, { 0 }, IPPROTO_UDP } },
7561 + { { 0, { 0xFFFF } }, /* mask */
7562 + { 0, { 0 }, 0xFFFF } },
7563 + nhelp } /* helper */
7566 +static int __init init(void)
7569 + ip_conntrack_helper_register(&talk_helpers[0]);
7570 + if (ntalk > 0 || ntalk2 > 0)
7571 + ip_conntrack_helper_register(&talk_helpers[1]);
7576 +static void __exit fini(void)
7579 + ip_conntrack_helper_unregister(&talk_helpers[0]);
7580 + if (ntalk > 0 || ntalk2 > 0)
7581 + ip_conntrack_helper_unregister(&talk_helpers[1]);
7584 +EXPORT_SYMBOL(ip_talk_lock);
7588 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
7589 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_tftp.c 2003-11-26 21:43:31.000000000 +0100
7590 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_tftp.c 2003-12-10 23:13:21.271842272 +0100
7593 for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7594 /* Create helper structure */
7595 - memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
7597 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
7598 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
7599 tftp[i].mask.dst.protonum = 0xFFFF;
7600 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
7601 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_amanda.c 2003-11-26 21:43:24.000000000 +0100
7602 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_amanda.c 2003-12-10 23:13:21.271842272 +0100
7604 struct ip_nat_helper *hlpr;
7606 hlpr = &ip_nat_amanda_helper;
7607 - memset(hlpr, 0, sizeof(struct ip_nat_helper));
7609 hlpr->tuple.dst.protonum = IPPROTO_UDP;
7610 hlpr->tuple.src.u.udp.port = htons(10080);
7611 hlpr->mask.src.u.udp.port = 0xFFFF;
7612 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
7613 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_core.c 2003-11-26 21:43:07.000000000 +0100
7614 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_core.c 2003-12-10 23:14:03.995347312 +0100
7616 WRITE_UNLOCK(&ip_nat_lock);
7619 -/* We do checksum mangling, so if they were wrong before they're still
7620 - * wrong. Also works for incomplete packets (eg. ICMP dest
7621 - * unreachables.) */
7623 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
7624 + * @oldvalinv: bit-inverted old value of 32bit word
7625 + * @newval: new value of 32bit word
7626 + * @oldcheck: old checksum value
7628 + * This function implements incremental checksum mangling, so if a checksum
7629 + * was wrong it will still be wrong after mangling. Also works for incomplete
7630 + * packets (eg. ICMP dest unreachables). Return value is the new checksum.
7633 ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
7635 @@ -118,7 +125,14 @@
7639 -/* Is this tuple already taken? (not by us) */
7641 + * ip_nat_used_tuple - Is this tuple already in use?
7642 + * @tuple: tuple to be used for this check
7643 + * @ignored_conntrack: conntrack excluded from this check
7645 + * This function checks for the reply (inverted) tuple in the conntrack
7646 + * hash. This is necessarry with NAT, since there is no fixed mapping.
7649 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
7650 const struct ip_conntrack *ignored_conntrack)
7652 *tuple = *orig_tuple;
7653 while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
7655 - DEBUGP("Found best for "); DUMP_TUPLE(tuple);
7656 + DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
7657 /* 3) The per-protocol part of the manip is made to
7658 map into the range to make a unique tuple. */
7660 @@ -509,6 +523,19 @@
7665 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
7666 + * @conntrack: conntrack on which we operate
7667 + * @mr: address/port range which is valid for this NAT mapping
7668 + * @hooknum: hook at which this NAT mapping applies
7670 + * This function is called by NAT targets (SNAT,DNAT,...) and by
7671 + * the NAT application helper modules. It is called for the NEW packet
7672 + * of a connection in order to specify which NAT mappings shall apply to
7673 + * this connection at a given hook.
7675 + * Note: The reply mappings are created automagically by this function.
7678 ip_nat_setup_info(struct ip_conntrack *conntrack,
7679 const struct ip_nat_multi_range *mr,
7681 HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
7683 DEBUGP("Original: ");
7684 - DUMP_TUPLE(&orig_tp);
7685 + DUMP_TUPLE_RAW(&orig_tp);
7687 - DUMP_TUPLE(&new_tuple);
7688 + DUMP_TUPLE_RAW(&new_tuple);
7691 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
7694 /* Have to grab read lock before sibling_list traversal */
7695 READ_LOCK(&ip_conntrack_lock);
7696 - list_for_each(cur_item, &ct->sibling_list) {
7697 + list_for_each_prev(cur_item, &ct->sibling_list) {
7698 exp = list_entry(cur_item, struct ip_conntrack_expect,
7701 @@ -1010,7 +1037,11 @@
7702 /* FIXME: Man, this is a hack. <SIGH> */
7703 IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
7704 ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
7707 + /* Initialize fake conntrack so that NAT will skip it */
7708 + ip_conntrack_untracked.nat.info.initialized |=
7709 + (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
7714 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
7715 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_cuseeme.c 1970-01-01 01:00:00.000000000 +0100
7716 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_cuseeme.c 2003-12-10 23:13:55.777596600 +0100
7718 +/* CuSeeMe extension for UDP NAT alteration.
7719 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7720 + * based on ip_masq_cuseeme.c in 2.2 kernels
7722 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
7724 + * This program is free software; you can redistribute it and/or
7725 + * modify it under the terms of the GNU General Public License
7726 + * as published by the Free Software Foundation; either version
7727 + * 2 of the License, or (at your option) any later version.
7729 + * Module load syntax:
7730 + * insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
7732 + * Please give the ports of the CuSeeMe traffic you want to track.
7733 + * If you don't specify ports, the default will be UDP port 7648.
7735 + * CuSeeMe Protocol Documentation:
7736 + * http://cu-seeme.net/squeek/tech/contents.html
7740 +#include <linux/module.h>
7741 +#include <linux/netfilter_ipv4.h>
7742 +#include <linux/ip.h>
7743 +#include <linux/udp.h>
7745 +#include <linux/netfilter.h>
7746 +#include <linux/netfilter_ipv4/ip_tables.h>
7747 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7748 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
7749 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7750 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7752 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7753 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
7754 +MODULE_LICENSE("GPL");
7756 +#define MAX_PORTS 8
7758 +static int ports[MAX_PORTS];
7759 +static int ports_c = 0;
7761 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7762 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
7766 +#define DEBUGP printk
7768 +#define DEBUGP(format, args...)
7771 +/* process packet from client->reflector, possibly manipulate client IP in payload */
7772 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
7773 + struct ip_nat_info *info,
7774 + enum ip_conntrack_info ctinfo,
7775 + struct sk_buff **pskb,
7777 + unsigned int datalen)
7779 + char new_port_ip[6];
7780 + struct cu_header *cu_head=(struct cu_header *)data;
7782 + DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n",
7783 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7785 + /* At least check that the data at offset 10 is the client's port and IP address */
7786 + if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
7787 + (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
7788 + DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
7789 + NIPQUAD(cu_head->addr),
7790 + ntohs(cu_head->port),
7791 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7792 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
7793 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7794 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7795 + /* at offset 10, replace 6 bytes containing port + IP address */
7796 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7797 + 10, 6, (char *)(new_port_ip), 6);
7799 + DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7800 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7801 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
7802 + NIPQUAD(cu_head->addr),
7803 + ntohs(cu_head->port));
7806 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
7807 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
7808 + struct ip_nat_info *info,
7809 + enum ip_conntrack_info ctinfo,
7810 + struct sk_buff **pskb,
7812 + unsigned int datalen)
7814 + char new_port_ip[6];
7815 + struct cu_header *cu_head = (struct cu_header *)data;
7816 + struct oc_header *oc_head = (struct oc_header *)data;
7817 + struct client_info *ci;
7821 + DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n",
7822 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7824 + /* Check if we're really dealing with the client's port + IP address before rewriting */
7825 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
7826 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
7827 + DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
7828 + NIPQUAD(cu_head->dest_addr),
7829 + ntohs(cu_head->dest_port),
7830 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7831 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
7832 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
7833 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7834 + /* at offset 2, replace 6 bytes containing port + IP address */
7835 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7836 + 2, 6, (char *)(new_port_ip), 6);
7838 + DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7839 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7840 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
7841 + NIPQUAD(cu_head->dest_addr),
7842 + ntohs(cu_head->dest_port));
7844 + /* Check if we're really dealing with the server's port + IP address before rewriting.
7845 + In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
7846 + if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
7847 + (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
7848 + DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
7849 + NIPQUAD(cu_head->addr),
7850 + ntohs(cu_head->port),
7851 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
7852 + ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
7853 + *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
7854 + *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7855 + /* at offset 10, replace 6 bytes containing port + IP address */
7856 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7857 + 10, 6, (char *)(new_port_ip), 6);
7859 + /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
7860 + is not that important so we're not logging this unless we're debugging */
7861 + DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7862 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
7863 + ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
7864 + NIPQUAD(cu_head->addr),
7865 + ntohs(cu_head->port));
7867 + /* Spin through client_info structs until we find our own */
7868 + if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
7869 + DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
7870 + for(i=0, off=sizeof(struct oc_header);
7871 + (i < oc_head->client_count &&
7872 + off+sizeof(struct client_info) <= datalen);
7874 + ci=(struct client_info *)(data+off);
7875 + DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n",
7876 + NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7877 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7878 + if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
7879 + /* mangle this IP address */
7880 + DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
7881 + NIPQUAD(ci->address),
7882 + NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7883 + (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7884 + ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7885 + (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4,
7886 + (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
7889 + off+=sizeof(struct client_info);
7892 + DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n",
7893 + ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
7896 +static unsigned int
7897 +cuseeme_nat_help(struct ip_conntrack *ct,
7898 + struct ip_conntrack_expect *exp,
7899 + struct ip_nat_info *info,
7900 + enum ip_conntrack_info ctinfo,
7901 + unsigned int hooknum,
7902 + struct sk_buff **pskb)
7904 + struct iphdr *iph = (*pskb)->nh.iph;
7905 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
7906 + int dir = CTINFO2DIR(ctinfo);
7907 + unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
7908 + char *data = (char *) &udph[1];
7910 + DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
7911 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7912 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7913 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7914 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7917 + /* Only mangle things once: original direction in POST_ROUTING
7918 + and reply direction on PRE_ROUTING. */
7919 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7920 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7921 + DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
7922 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7923 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7924 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7925 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7929 + if(datalen < sizeof(struct cu_header)) {
7930 + /* packet too small */
7931 + if (net_ratelimit())
7932 + printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n",
7933 + datalen, sizeof(struct cu_header));
7938 + /* In the debugging output, "outgoing" is from client to server, and
7939 + "incoming" is from server to client */
7940 + if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7941 + cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
7943 + cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
7948 +static struct ip_nat_helper cuseeme[MAX_PORTS];
7949 +static char cuseeme_names[MAX_PORTS][14]; /* cuseeme-65535 */
7951 +static void fini(void)
7955 + for (i = 0 ; i < ports_c; i++) {
7956 + DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
7957 + ip_nat_helper_unregister(&cuseeme[i]);
7961 +static int __init init(void)
7967 + ports[0] = CUSEEME_PORT;
7969 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7970 + memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
7972 + cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
7973 + cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
7974 + cuseeme[i].mask.dst.protonum = 0xFFFF;
7975 + cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
7976 + cuseeme[i].help = cuseeme_nat_help;
7977 + cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE +
7978 + IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
7979 + is stricly needed... */
7980 + cuseeme[i].me = THIS_MODULE;
7981 + cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
7983 + tmpname = &cuseeme_names[i][0];
7984 + if (ports[i] == CUSEEME_PORT)
7985 + sprintf(tmpname, "cuseeme");
7987 + sprintf(tmpname, "cuseeme-%d", ports[i]);
7988 + cuseeme[i].name = tmpname;
7990 + DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
7991 + ports[i], cuseeme[i].name);
7992 + ret = ip_nat_helper_register(&cuseeme[i]);
7995 + printk("ip_nat_cuseeme: unable to register helper for port %d\n",
8007 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
8008 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
8009 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_h323.c 2003-12-10 23:13:58.178231648 +0100
8012 + * H.323 'brute force' extension for NAT alteration.
8013 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8015 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
8016 + * (http://www.coritel.it/projects/sofia/nat.html)
8017 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
8018 + * the unregistered helpers to the conntrack entries.
8022 +#include <linux/module.h>
8023 +#include <linux/netfilter.h>
8024 +#include <linux/ip.h>
8025 +#include <net/checksum.h>
8026 +#include <net/tcp.h>
8028 +#include <linux/netfilter_ipv4/lockhelp.h>
8029 +#include <linux/netfilter_ipv4/ip_nat.h>
8030 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8031 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8032 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
8033 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8034 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
8036 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8037 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
8038 +MODULE_LICENSE("GPL");
8040 +DECLARE_LOCK_EXTERN(ip_h323_lock);
8041 +struct module *ip_nat_h323 = THIS_MODULE;
8044 +#define DEBUGP printk
8046 +#define DEBUGP(format, args...)
8049 +/* FIXME: Time out? --RR */
8051 +static unsigned int
8052 +h225_nat_expected(struct sk_buff **pskb,
8053 + unsigned int hooknum,
8054 + struct ip_conntrack *ct,
8055 + struct ip_nat_info *info);
8057 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8058 + struct ip_conntrack_expect *exp,
8059 + struct ip_nat_info *info,
8060 + enum ip_conntrack_info ctinfo,
8061 + unsigned int hooknum,
8062 + struct sk_buff **pskb);
8064 +static struct ip_nat_helper h245 =
8066 + "H.245", /* name */
8068 + NULL, /* module */
8069 + { { 0, { 0 } }, /* tuple */
8070 + { 0, { 0 }, IPPROTO_TCP } },
8071 + { { 0, { 0xFFFF } }, /* mask */
8072 + { 0, { 0 }, 0xFFFF } },
8073 + h225_nat_help, /* helper */
8074 + h225_nat_expected /* expectfn */
8077 +static unsigned int
8078 +h225_nat_expected(struct sk_buff **pskb,
8079 + unsigned int hooknum,
8080 + struct ip_conntrack *ct,
8081 + struct ip_nat_info *info)
8083 + struct ip_nat_multi_range mr;
8084 + u_int32_t newdstip, newsrcip, newip;
8086 + struct ip_ct_h225_expect *exp_info;
8087 + struct ip_ct_h225_master *master_info;
8088 + struct ip_conntrack *master = master_ct(ct);
8089 + unsigned int is_h225, ret;
8091 + IP_NF_ASSERT(info);
8092 + IP_NF_ASSERT(master);
8094 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8096 + DEBUGP("h225_nat_expected: We have a connection!\n");
8097 + master_info = &ct->master->expectant->help.ct_h225_info;
8098 + exp_info = &ct->master->help.exp_h225_info;
8100 + LOCK_BH(&ip_h323_lock);
8102 + DEBUGP("master: ");
8103 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8104 + DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
8105 + DEBUGP("conntrack: ");
8106 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8107 + if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
8108 + /* Make connection go to the client. */
8109 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8110 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8111 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
8112 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8114 + /* Make the connection go to the server */
8115 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8116 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8117 + DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
8118 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8120 + port = exp_info->port;
8121 + is_h225 = master_info->is_h225 == H225_PORT;
8122 + UNLOCK_BH(&ip_h323_lock);
8124 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8129 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8132 + /* We don't want to manip the per-protocol, just the IPs... */
8133 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8134 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8136 + /* ... unless we're doing a MANIP_DST, in which case, make
8137 + sure we map to the correct port */
8138 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8139 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8140 + mr.range[0].min = mr.range[0].max
8141 + = ((union ip_conntrack_manip_proto)
8142 + { .tcp = { port } });
8145 + ret = ip_nat_setup_info(ct, &mr, hooknum);
8148 + DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
8149 + /* NAT expectfn called with ip_nat_lock write-locked */
8150 + info->helper = &h245;
8155 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
8156 + struct sk_buff **pskb,
8157 + enum ip_conntrack_info ctinfo)
8159 + struct iphdr *iph = (*pskb)->nh.iph;
8160 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8161 + char *data = (char *) tcph + tcph->doff * 4;
8162 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8163 + u_int32_t datalen = tcplen - tcph->doff*4;
8164 + struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
8169 + MUST_BE_LOCKED(&ip_h323_lock);
8171 + DEBUGP("h323_signal_address_fixup: %s %s\n",
8172 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8174 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8176 + if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8177 + || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
8180 + DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
8181 + info->offset[IP_CT_DIR_ORIGINAL],
8182 + info->offset[IP_CT_DIR_REPLY],
8184 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8185 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8187 + for (i = 0; i < IP_CT_DIR_MAX; i++) {
8188 + DEBUGP("h323_signal_address_fixup: %s %s\n",
8189 + info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
8190 + i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
8191 + if (!between(info->seq[i], ntohl(tcph->seq),
8192 + ntohl(tcph->seq) + datalen))
8194 + if (!between(info->seq[i] + 6, ntohl(tcph->seq),
8195 + ntohl(tcph->seq) + datalen)) {
8196 + /* Partial retransmisison. It's a cracker being funky. */
8197 + if (net_ratelimit()) {
8198 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8201 + ntohl(tcph->seq) + datalen);
8206 + /* Change address inside packet to match way we're mapping
8207 + this connection. */
8208 + if (i == IP_CT_DIR_ORIGINAL) {
8209 + newip = ct->tuplehash[!info->dir].tuple.dst.ip;
8210 + port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
8212 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
8213 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
8216 + DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
8217 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
8218 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
8219 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8221 + /* Modify the packet */
8222 + *(u_int32_t *)(data + info->offset[i]) = newip;
8223 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
8225 + DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
8226 + i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
8227 + NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
8228 + ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8231 + /* fix checksum information */
8233 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8237 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8238 + csum_partial((char *)tcph, tcph->doff*4,
8240 + ip_send_check(iph);
8245 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
8246 + struct ip_conntrack *ct,
8247 + struct sk_buff **pskb,
8248 + enum ip_conntrack_info ctinfo,
8249 + struct ip_conntrack_expect *expect)
8253 + struct ip_conntrack_tuple newtuple;
8254 + struct iphdr *iph = (*pskb)->nh.iph;
8255 + struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8256 + char *data = (char *) tcph + tcph->doff * 4;
8257 + u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8258 + struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
8261 + MUST_BE_LOCKED(&ip_h323_lock);
8262 + DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
8263 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8264 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8266 + if (!between(expect->seq + 6, ntohl(tcph->seq),
8267 + ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
8268 + /* Partial retransmisison. It's a cracker being funky. */
8269 + if (net_ratelimit()) {
8270 + printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8273 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
8278 + /* Change address inside packet to match way we're mapping
8279 + this connection. */
8280 + if (info->dir == IP_CT_DIR_REPLY) {
8281 + /* Must be where client thinks server is */
8282 + newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8283 + /* Expect something from client->server */
8284 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8285 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8287 + /* Must be where server thinks client is */
8288 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8289 + /* Expect something from server->client */
8290 + newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8291 + newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8294 + is_h225 = (master_info->is_h225 == H225_PORT);
8297 + newtuple.dst.protonum = IPPROTO_TCP;
8298 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
8300 + newtuple.dst.protonum = IPPROTO_UDP;
8301 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
8304 + /* Try to get same port: if not, try to change it. */
8305 + for (port = ntohs(info->port); port != 0; port++) {
8307 + newtuple.dst.u.tcp.port = htons(port);
8309 + newtuple.dst.u.udp.port = htons(port);
8311 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
8315 + DEBUGP("h323_data_fixup: no free port found!\n");
8319 + port = htons(port);
8321 + DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
8322 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
8323 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
8325 + /* Modify the packet */
8326 + *(u_int32_t *)(data + info->offset) = newip;
8327 + *(u_int16_t *)(data + info->offset + 4) = port;
8329 + DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
8330 + NIPQUAD(*((u_int32_t *)(data + info->offset))),
8331 + ntohs(*((u_int16_t *)(data + info->offset + 4))));
8333 + /* fix checksum information */
8334 + /* FIXME: usually repeated multiple times in the case of H.245! */
8336 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8337 + tcplen - tcph->doff*4, 0);
8340 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8341 + csum_partial((char *)tcph, tcph->doff*4,
8343 + ip_send_check(iph);
8348 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8349 + struct ip_conntrack_expect *exp,
8350 + struct ip_nat_info *info,
8351 + enum ip_conntrack_info ctinfo,
8352 + unsigned int hooknum,
8353 + struct sk_buff **pskb)
8356 + struct ip_ct_h225_expect *exp_info;
8358 + /* Only mangle things once: original direction in POST_ROUTING
8359 + and reply direction on PRE_ROUTING. */
8360 + dir = CTINFO2DIR(ctinfo);
8361 + DEBUGP("nat_h323: dir %s at hook %s\n",
8362 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8363 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8364 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8365 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8366 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8367 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8368 + DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
8369 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8370 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8371 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8372 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8377 + LOCK_BH(&ip_h323_lock);
8378 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
8379 + UNLOCK_BH(&ip_h323_lock);
8382 + UNLOCK_BH(&ip_h323_lock);
8386 + exp_info = &exp->help.exp_h225_info;
8388 + LOCK_BH(&ip_h323_lock);
8389 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
8390 + UNLOCK_BH(&ip_h323_lock);
8393 + UNLOCK_BH(&ip_h323_lock);
8398 +static struct ip_nat_helper h225 =
8400 + "H.225", /* name */
8401 + IP_NAT_HELPER_F_ALWAYS, /* flags */
8402 + THIS_MODULE, /* module */
8403 + { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
8404 + { 0, { 0 }, IPPROTO_TCP } },
8405 + { { 0, { .tcp = { 0xFFFF } } }, /* mask */
8406 + { 0, { 0 }, 0xFFFF } },
8407 + h225_nat_help, /* helper */
8408 + h225_nat_expected /* expectfn */
8411 +static int __init init(void)
8415 + ret = ip_nat_helper_register(&h225);
8418 + printk("ip_nat_h323: cannot initialize the module!\n");
8423 +static void __exit fini(void)
8425 + ip_nat_helper_unregister(&h225);
8430 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
8431 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_helper.c 2003-11-26 21:43:08.000000000 +0100
8432 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_helper.c 2003-12-10 23:14:03.996347160 +0100
8433 @@ -147,9 +147,19 @@
8437 -/* Generic function for mangling variable-length address changes inside
8438 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
8439 - * command in FTP).
8441 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
8442 + * @skb: pointer to skb of packet on which we operate
8443 + * @ct: conntrack of the connection to which this packet belongs
8444 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8445 + * @match_offset: offset in bytes where to-be-manipulated part starts
8446 + * @match_len: lenght of the to-be-manipulated part
8447 + * @rep_buffer: pointer to buffer containing replacement
8448 + * @rep_len: length of replacement
8450 + * Generic function for mangling fixed and variable-length changes inside
8451 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command
8454 * Takes care about all the nasty sequence number changes, checksumming,
8455 * skb enlargement, ...
8456 @@ -195,16 +205,27 @@
8460 -/* Generic function for mangling variable-length address changes inside
8461 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8462 - * command in the Amanda protocol)
8464 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
8465 + * @skb: pointer to skb of packet on which we operate
8466 + * @ct: conntrack of the connection to which this packet belongs
8467 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8468 + * @match_offset: offset in bytes where to-be-manipulated part starts
8469 + * @match_len: lenght of the to-be-manipulated part
8470 + * @rep_buffer: pointer to buffer containing replacement
8471 + * @rep_len: length of replacement
8473 + * Generic function for mangling fixed and variable-length changes inside
8474 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8475 + * commad in the Amanda protocol)
8477 * Takes care about all the nasty sequence number changes, checksumming,
8478 * skb enlargement, ...
8480 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
8481 - * should be fairly easy to do.
8483 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
8488 ip_nat_mangle_udp_packet(struct sk_buff **pskb,
8489 struct ip_conntrack *ct,
8490 @@ -402,6 +423,13 @@
8491 return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
8495 + * ip_nat_helper_register - Register NAT application helper
8496 + * @me: structure describing the helper
8498 + * This function is called by NAT application helpers to register
8499 + * themselves with the NAT core.
8501 int ip_nat_helper_register(struct ip_nat_helper *me)
8504 @@ -428,6 +456,13 @@
8509 + * ip_nat_helper_unregister - Unregister NAT application helper
8510 + * @me: structure describing the helper
8512 + * This function is called by NAT application helpers to unregister
8513 + * themselves from the NAT core.
8515 void ip_nat_helper_unregister(struct ip_nat_helper *me)
8517 WRITE_LOCK(&ip_nat_lock);
8518 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
8519 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
8520 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_mms.c 2003-12-10 23:14:02.757535488 +0100
8522 +/* MMS extension for TCP NAT alteration.
8523 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
8524 + * based on ip_nat_ftp.c and ip_nat_irc.c
8526 + * ip_nat_mms.c v0.3 2002-09-22
8528 + * This program is free software; you can redistribute it and/or
8529 + * modify it under the terms of the GNU General Public License
8530 + * as published by the Free Software Foundation; either version
8531 + * 2 of the License, or (at your option) any later version.
8533 + * Module load syntax:
8534 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
8536 + * Please give the ports of all MMS servers You wish to connect to.
8537 + * If you don't specify ports, the default will be TCP port 1755.
8539 + * More info on MMS protocol, firewalls and NAT:
8540 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
8541 + * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
8543 + * The SDP project people are reverse-engineering MMS:
8544 + * http://get.to/sdp
8547 +/* FIXME: issue with UDP & fragmentation with this URL:
8548 + http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
8549 + may be related to out-of-order first packets:
8550 + basically the expectation is set up correctly, then the server sends
8551 + a first UDP packet which is fragmented plus arrives out-of-order.
8552 + the MASQUERADING firewall with ip_nat_mms loaded responds with
8553 + an ICMP unreachable back to the server */
8555 +#include <linux/module.h>
8556 +#include <linux/netfilter_ipv4.h>
8557 +#include <linux/ip.h>
8558 +#include <linux/tcp.h>
8559 +#include <net/tcp.h>
8560 +#include <linux/netfilter_ipv4/ip_nat.h>
8561 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8562 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8563 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
8564 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8567 +#define DEBUGP printk
8568 +#define DUMP_BYTES(address, counter) \
8570 + int temp_counter; \
8571 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
8572 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
8577 +#define DEBUGP(format, args...)
8578 +#define DUMP_BYTES(address, counter)
8581 +#define MAX_PORTS 8
8582 +static int ports[MAX_PORTS];
8583 +static int ports_c = 0;
8586 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8589 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
8590 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
8591 +MODULE_LICENSE("GPL");
8593 +DECLARE_LOCK_EXTERN(ip_mms_lock);
8595 +/* FIXME: Time out? --RR */
8597 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
8598 + struct ip_conntrack *ct,
8599 + struct sk_buff **pskb,
8600 + enum ip_conntrack_info ctinfo,
8601 + struct ip_conntrack_expect *expect)
8604 + struct ip_conntrack_tuple t;
8605 + struct iphdr *iph = (*pskb)->nh.iph;
8606 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8607 + char *data = (char *)tcph + tcph->doff * 4;
8608 + int i, j, k, port;
8609 + u_int16_t mms_proto;
8611 + u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
8612 + u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
8613 + u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
8617 + char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
8618 + char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
8619 + char proto_string[6];
8621 + MUST_BE_LOCKED(&ip_mms_lock);
8623 + /* what was the protocol again ? */
8624 + mms_proto = expect->tuple.dst.protonum;
8625 + sprintf(proto_string, "%u", mms_proto);
8627 + DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
8628 + expect->seq, ct_mms_info->len, ntohl(tcph->seq),
8629 + mms_proto == IPPROTO_UDP ? "UDP"
8630 + : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
8632 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8634 + /* Alter conntrack's expectations. */
8635 + t = expect->tuple;
8637 + for (port = ct_mms_info->port; port != 0; port++) {
8638 + t.dst.u.tcp.port = htons(port);
8639 + if (ip_conntrack_change_expect(expect, &t) == 0) {
8640 + DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
8648 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
8650 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
8651 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
8653 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
8655 + memset(unicode_buffer, 0, sizeof(char)*75);
8657 + for (i=0; i<strlen(buffer); ++i)
8658 + *(unicode_buffer+i*2)=*(buffer+i);
8660 + DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
8661 + DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
8662 + DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
8664 + /* add end of packet to it */
8665 + for (j=0; j<ct_mms_info->padding; ++j) {
8666 + DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
8667 + i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
8668 + *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
8671 + /* pad with zeroes at the end ? see explanation of weird math below */
8672 + zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
8673 + for (k=0; k<zero_padding; ++k)
8674 + *(unicode_buffer+i*2+j+k)= (char)0;
8676 + DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
8677 + DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8678 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8680 + /* explanation, before I forget what I did:
8681 + strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
8682 + divide by 8 and add 3 to compute the mms_chunkLenLM field,
8683 + but note that things may have to be padded with zeroes to align by 8
8684 + bytes, hence we add 7 and divide by 8 to get the correct length */
8685 + *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
8686 + *mms_chunkLenLV = *mms_chunkLenLM+2;
8687 + *mms_messageLength = *mms_chunkLenLV*8;
8689 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8690 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8692 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
8693 + expect->seq - ntohl(tcph->seq),
8694 + ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
8695 + strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
8696 + DUMP_BYTES(unicode_buffer, 60);
8701 +static unsigned int
8702 +mms_nat_expected(struct sk_buff **pskb,
8703 + unsigned int hooknum,
8704 + struct ip_conntrack *ct,
8705 + struct ip_nat_info *info)
8707 + struct ip_nat_multi_range mr;
8708 + u_int32_t newdstip, newsrcip, newip;
8710 + struct ip_conntrack *master = master_ct(ct);
8712 + IP_NF_ASSERT(info);
8713 + IP_NF_ASSERT(master);
8715 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8717 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
8719 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8720 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8721 + DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
8722 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8723 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8724 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8725 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
8727 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8732 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8735 + /* We don't want to manip the per-protocol, just the IPs. */
8736 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8737 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
8739 + return ip_nat_setup_info(ct, &mr, hooknum);
8743 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
8744 + struct ip_conntrack_expect *exp,
8745 + struct ip_nat_info *info,
8746 + enum ip_conntrack_info ctinfo,
8747 + unsigned int hooknum,
8748 + struct sk_buff **pskb)
8750 + struct iphdr *iph = (*pskb)->nh.iph;
8751 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8752 + unsigned int datalen;
8754 + struct ip_ct_mms_expect *ct_mms_info;
8757 + DEBUGP("ip_nat_mms: no exp!!");
8759 + ct_mms_info = &exp->help.exp_mms_info;
8761 + /* Only mangle things once: original direction in POST_ROUTING
8762 + and reply direction on PRE_ROUTING. */
8763 + dir = CTINFO2DIR(ctinfo);
8764 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8765 + ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8766 + DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
8767 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8768 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8769 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8770 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8773 + DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
8774 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8775 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8776 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8777 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8779 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
8781 + DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
8782 + exp->seq + ct_mms_info->len,
8784 + ntohl(tcph->seq) + datalen);
8786 + LOCK_BH(&ip_mms_lock);
8787 + /* Check wether the whole IP/proto/port pattern is carried in the payload */
8788 + if (between(exp->seq + ct_mms_info->len,
8790 + ntohl(tcph->seq) + datalen)) {
8791 + if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
8792 + UNLOCK_BH(&ip_mms_lock);
8796 + /* Half a match? This means a partial retransmisison.
8797 + It's a cracker being funky. */
8798 + if (net_ratelimit()) {
8799 + printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
8800 + exp->seq, ct_mms_info->len,
8802 + ntohl(tcph->seq) + datalen);
8804 + UNLOCK_BH(&ip_mms_lock);
8807 + UNLOCK_BH(&ip_mms_lock);
8812 +static struct ip_nat_helper mms[MAX_PORTS];
8813 +static char mms_names[MAX_PORTS][10];
8815 +/* Not __exit: called from init() */
8816 +static void fini(void)
8820 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8821 + DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
8822 + ip_nat_helper_unregister(&mms[i]);
8826 +static int __init init(void)
8831 + if (ports[0] == 0)
8832 + ports[0] = MMS_PORT;
8834 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8836 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
8838 + mms[i].tuple.dst.protonum = IPPROTO_TCP;
8839 + mms[i].tuple.src.u.tcp.port = htons(ports[i]);
8840 + mms[i].mask.dst.protonum = 0xFFFF;
8841 + mms[i].mask.src.u.tcp.port = 0xFFFF;
8842 + mms[i].help = mms_nat_help;
8843 + mms[i].me = THIS_MODULE;
8845 + mms[i].expect = mms_nat_expected;
8847 + tmpname = &mms_names[i][0];
8848 + if (ports[i] == MMS_PORT)
8849 + sprintf(tmpname, "mms");
8851 + sprintf(tmpname, "mms-%d", i);
8852 + mms[i].name = tmpname;
8854 + DEBUGP("ip_nat_mms: register helper for port %d\n",
8856 + ret = ip_nat_helper_register(&mms[i]);
8859 + printk("ip_nat_mms: error registering "
8860 + "helper for port %d\n", ports[i]);
8872 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
8873 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_pptp.c 1970-01-01 01:00:00.000000000 +0100
8874 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_pptp.c 2003-11-17 09:09:34.000000000 +0100
8877 + * ip_nat_pptp.c - Version 1.5
8879 + * NAT support for PPTP (Point to Point Tunneling Protocol).
8880 + * PPTP is a a protocol for creating virtual private networks.
8881 + * It is a specification defined by Microsoft and some vendors
8882 + * working with Microsoft. PPTP is built on top of a modified
8883 + * version of the Internet Generic Routing Encapsulation Protocol.
8884 + * GRE is defined in RFC 1701 and RFC 1702. Documentation of
8885 + * PPTP can be found in RFC 2637
8887 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
8889 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
8891 + * TODO: - Support for multiple calls within one session
8892 + * (needs netfilter newnat code)
8893 + * - NAT to a unique tuple, not to TCP source port
8894 + * (needs netfilter tuple reservation)
8897 + * 2002-02-10 - Version 1.3
8898 + * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
8899 + * in local connections (Philip Craig <philipc@snapgear.com>)
8900 + * - add checks for magicCookie and pptp version
8901 + * - make argument list of pptp_{out,in}bound_packet() shorter
8902 + * - move to C99 style initializers
8903 + * - print version number at module loadtime
8904 + * 2003-09-22 - Version 1.5
8905 + * - use SNATed tcp sourceport as callid, since we get called before
8906 + * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
8910 +#include <linux/config.h>
8911 +#include <linux/module.h>
8912 +#include <linux/ip.h>
8913 +#include <linux/tcp.h>
8914 +#include <net/tcp.h>
8915 +#include <linux/netfilter_ipv4/ip_nat.h>
8916 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8917 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8918 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
8919 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8920 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
8921 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
8923 +#define IP_NAT_PPTP_VERSION "1.5"
8925 +MODULE_LICENSE("GPL");
8926 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
8927 +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
8931 +#include "ip_conntrack_pptp_priv.h"
8932 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
8933 + ": " format, ## args)
8935 +#define DEBUGP(format, args...)
8938 +static unsigned int
8939 +pptp_nat_expected(struct sk_buff **pskb,
8940 + unsigned int hooknum,
8941 + struct ip_conntrack *ct,
8942 + struct ip_nat_info *info)
8944 + struct ip_conntrack *master = master_ct(ct);
8945 + struct ip_nat_multi_range mr;
8946 + struct ip_ct_pptp_master *ct_pptp_info;
8947 + struct ip_nat_pptp *nat_pptp_info;
8948 + u_int32_t newip, newcid;
8951 + IP_NF_ASSERT(info);
8952 + IP_NF_ASSERT(master);
8953 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8955 + DEBUGP("we have a connection!\n");
8957 + LOCK_BH(&ip_pptp_lock);
8958 + ct_pptp_info = &master->help.ct_pptp_info;
8959 + nat_pptp_info = &master->nat.help.nat_pptp_info;
8961 + /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
8962 + * (unmanipulated) values */
8963 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8964 + DEBUGP("completing tuples with NAT info \n");
8965 + /* we can do this, since we're unconfirmed */
8966 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
8967 + htonl(ct_pptp_info->pac_call_id)) {
8968 + /* assume PNS->PAC */
8969 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8970 + htonl(nat_pptp_info->pns_call_id);
8971 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8972 + htonl(nat_pptp_info->pns_call_id);
8973 + newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8974 + newcid = htonl(nat_pptp_info->pac_call_id);
8976 + /* assume PAC->PNS */
8977 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8978 + htonl(nat_pptp_info->pac_call_id);
8979 + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8980 + htonl(nat_pptp_info->pac_call_id);
8981 + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8982 + newcid = htonl(nat_pptp_info->pns_call_id);
8985 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
8986 + htonl(ct_pptp_info->pac_call_id)) {
8987 + /* assume PNS->PAC */
8988 + newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8989 + newcid = htonl(ct_pptp_info->pns_call_id);
8992 + /* assume PAC->PNS */
8993 + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8994 + newcid = htonl(ct_pptp_info->pac_call_id);
8999 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
9000 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
9001 + mr.range[0].min = mr.range[0].max =
9002 + ((union ip_conntrack_manip_proto ) { newcid });
9003 + DEBUGP("change ip to %u.%u.%u.%u\n",
9005 + DEBUGP("change key to 0x%x\n", ntohl(newcid));
9006 + ret = ip_nat_setup_info(ct, &mr, hooknum);
9008 + UNLOCK_BH(&ip_pptp_lock);
9014 +/* outbound packets == from PNS to PAC */
9015 +static inline unsigned int
9016 +pptp_outbound_pkt(struct sk_buff **pskb,
9017 + struct ip_conntrack *ct,
9018 + enum ip_conntrack_info ctinfo,
9019 + struct ip_conntrack_expect *exp)
9022 + struct iphdr *iph = (*pskb)->nh.iph;
9023 + struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9024 + struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
9025 + ((void *)tcph + tcph->doff*4);
9027 + struct PptpControlHeader *ctlh;
9028 + union pptp_ctrl_union pptpReq;
9029 + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9030 + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9032 + u_int16_t msg, *cid = NULL, new_callid;
9034 + /* FIXME: size checks !!! */
9035 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9036 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9038 + new_callid = htons(ct_pptp_info->pns_call_id);
9040 + switch (msg = ntohs(ctlh->messageType)) {
9041 + case PPTP_OUT_CALL_REQUEST:
9042 + cid = &pptpReq.ocreq->callID;
9043 + /* FIXME: ideally we would want to reserve a call ID
9044 + * here. current netfilter NAT core is not able to do
9045 + * this :( For now we use TCP source port. This breaks
9046 + * multiple calls within one control session */
9048 + /* save original call ID in nat_info */
9049 + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
9051 + /* don't use tcph->source since we are at a DSTmanip
9052 + * hook (e.g. PREROUTING) and pkt is not mangled yet */
9053 + new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
9055 + /* save new call ID in ct info */
9056 + ct_pptp_info->pns_call_id = ntohs(new_callid);
9058 + case PPTP_IN_CALL_REPLY:
9059 + cid = &pptpReq.icreq->callID;
9061 + case PPTP_CALL_CLEAR_REQUEST:
9062 + cid = &pptpReq.clrreq->callID;
9065 + DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
9066 + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9067 + /* fall through */
9069 + case PPTP_SET_LINK_INFO:
9070 + /* only need to NAT in case PAC is behind NAT box */
9071 + case PPTP_START_SESSION_REQUEST:
9072 + case PPTP_START_SESSION_REPLY:
9073 + case PPTP_STOP_SESSION_REQUEST:
9074 + case PPTP_STOP_SESSION_REPLY:
9075 + case PPTP_ECHO_REQUEST:
9076 + case PPTP_ECHO_REPLY:
9077 + /* no need to alter packet */
9081 + IP_NF_ASSERT(cid);
9083 + DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9084 + ntohs(*cid), ntohs(new_callid));
9086 + /* mangle packet */
9087 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
9088 + sizeof(new_callid), (char *)&new_callid,
9089 + sizeof(new_callid));
9094 +/* inbound packets == from PAC to PNS */
9095 +static inline unsigned int
9096 +pptp_inbound_pkt(struct sk_buff **pskb,
9097 + struct ip_conntrack *ct,
9098 + enum ip_conntrack_info ctinfo,
9099 + struct ip_conntrack_expect *oldexp)
9101 + struct iphdr *iph = (*pskb)->nh.iph;
9102 + struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9103 + struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *)
9104 + ((void *)tcph + tcph->doff*4);
9106 + struct PptpControlHeader *ctlh;
9107 + union pptp_ctrl_union pptpReq;
9108 + struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9109 + struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9111 + u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
9112 + u_int32_t old_dst_ip;
9114 + struct ip_conntrack_tuple t, inv_t;
9115 + struct ip_conntrack_tuple *orig_t, *reply_t;
9117 + /* FIXME: size checks !!! */
9118 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9119 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9121 + new_pcid = htons(nat_pptp_info->pns_call_id);
9123 + switch (msg = ntohs(ctlh->messageType)) {
9124 + case PPTP_OUT_CALL_REPLY:
9125 + pcid = &pptpReq.ocack->peersCallID;
9126 + cid = &pptpReq.ocack->callID;
9128 + DEBUGP("outcall but no expectation\n");
9131 + old_dst_ip = oldexp->tuple.dst.ip;
9132 + t = oldexp->tuple;
9133 + invert_tuplepr(&inv_t, &t);
9135 + /* save original PAC call ID in nat_info */
9136 + nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
9138 + /* alter expectation */
9139 + orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
9140 + reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
9141 + if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
9142 + /* expectation for PNS->PAC direction */
9143 + t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9144 + t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9145 + inv_t.src.ip = reply_t->src.ip;
9146 + inv_t.dst.ip = reply_t->dst.ip;
9147 + inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9148 + inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9150 + /* expectation for PAC->PNS direction */
9151 + t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9152 + t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9153 + inv_t.src.ip = orig_t->src.ip;
9154 + inv_t.dst.ip = orig_t->dst.ip;
9155 + inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9156 + inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9159 + if (!ip_conntrack_change_expect(oldexp, &t)) {
9160 + DEBUGP("successfully changed expect\n");
9162 + DEBUGP("can't change expect\n");
9164 + ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
9165 + ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
9167 + case PPTP_IN_CALL_CONNECT:
9168 + pcid = &pptpReq.iccon->peersCallID;
9171 + old_dst_ip = oldexp->tuple.dst.ip;
9172 + t = oldexp->tuple;
9174 + /* alter expectation, no need for callID */
9175 + if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
9176 + /* expectation for PNS->PAC direction */
9177 + t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9179 + /* expectation for PAC->PNS direction */
9180 + t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9183 + if (!ip_conntrack_change_expect(oldexp, &t)) {
9184 + DEBUGP("successfully changed expect\n");
9186 + DEBUGP("can't change expect\n");
9189 + case PPTP_IN_CALL_REQUEST:
9190 + /* only need to nat in case PAC is behind NAT box */
9192 + case PPTP_WAN_ERROR_NOTIFY:
9193 + pcid = &pptpReq.wanerr->peersCallID;
9195 + case PPTP_CALL_DISCONNECT_NOTIFY:
9196 + pcid = &pptpReq.disc->callID;
9200 + DEBUGP("unknown inbound packet %s\n",
9201 + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9202 + /* fall through */
9204 + case PPTP_START_SESSION_REQUEST:
9205 + case PPTP_START_SESSION_REPLY:
9206 + case PPTP_STOP_SESSION_REQUEST:
9207 + case PPTP_STOP_SESSION_REPLY:
9208 + case PPTP_ECHO_REQUEST:
9209 + case PPTP_ECHO_REPLY:
9210 + /* no need to alter packet */
9214 + /* mangle packet */
9215 + IP_NF_ASSERT(pcid);
9216 + DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
9217 + ntohs(*pcid), ntohs(new_pcid));
9218 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
9219 + sizeof(new_pcid), (char *)&new_pcid,
9220 + sizeof(new_pcid));
9223 + IP_NF_ASSERT(cid);
9224 + DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9225 + ntohs(*cid), ntohs(new_cid));
9226 + ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
9227 + (void *)cid - (void *)pptph,
9228 + sizeof(new_cid), (char *)&new_cid,
9232 + /* great, at least we don't need to resize packets */
9237 +static unsigned int tcp_help(struct ip_conntrack *ct,
9238 + struct ip_conntrack_expect *exp,
9239 + struct ip_nat_info *info,
9240 + enum ip_conntrack_info ctinfo,
9241 + unsigned int hooknum, struct sk_buff **pskb)
9243 + struct iphdr *iph = (*pskb)->nh.iph;
9244 + struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9245 + unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
9246 + struct pptp_pkt_hdr *pptph;
9250 + DEBUGP("entering\n");
9252 + /* Only mangle things once: DST for original direction
9253 + and SRC for reply direction. */
9254 + dir = CTINFO2DIR(ctinfo);
9255 + if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
9256 + && dir == IP_CT_DIR_ORIGINAL)
9257 + || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
9258 + && dir == IP_CT_DIR_REPLY))) {
9259 + DEBUGP("Not touching dir %s at hook %s\n",
9260 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9261 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9262 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9263 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
9264 + : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
9268 + /* if packet is too small, just skip it */
9269 + if (datalen < sizeof(struct pptp_pkt_hdr)+
9270 + sizeof(struct PptpControlHeader)) {
9271 + DEBUGP("pptp packet too short\n");
9275 + pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
9277 + /* if it's not a control message, we can't handle it */
9278 + if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
9279 + ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
9280 + DEBUGP("not a pptp control packet\n");
9284 + LOCK_BH(&ip_pptp_lock);
9286 + if (dir == IP_CT_DIR_ORIGINAL) {
9287 + /* reuqests sent by client to server (PNS->PAC) */
9288 + pptp_outbound_pkt(pskb, ct, ctinfo, exp);
9290 + /* response from the server to the client (PAC->PNS) */
9291 + pptp_inbound_pkt(pskb, ct, ctinfo, exp);
9294 + UNLOCK_BH(&ip_pptp_lock);
9299 +/* nat helper struct for control connection */
9300 +static struct ip_nat_helper pptp_tcp_helper = {
9301 + .list = { NULL, NULL },
9303 + .flags = IP_NAT_HELPER_F_ALWAYS,
9304 + .me = THIS_MODULE,
9305 + .tuple = { .src = { .ip = 0,
9306 + .u = { .tcp = { .port =
9307 + __constant_htons(PPTP_CONTROL_PORT) }
9311 + .u = { .all = 0 },
9312 + .protonum = IPPROTO_TCP
9316 + .mask = { .src = { .ip = 0,
9317 + .u = { .tcp = { .port = 0xFFFF } }
9320 + .u = { .all = 0 },
9321 + .protonum = 0xFFFF
9325 + .expect = pptp_nat_expected
9329 +static int __init init(void)
9331 + DEBUGP("%s: registering NAT helper\n", __FILE__);
9332 + if (ip_nat_helper_register(&pptp_tcp_helper)) {
9333 + printk(KERN_ERR "Unable to register NAT application helper "
9338 + printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
9342 +static void __exit fini(void)
9344 + DEBUGP("cleanup_module\n" );
9345 + ip_nat_helper_unregister(&pptp_tcp_helper);
9346 + printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
9351 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
9352 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_proto_gre.c 1970-01-01 01:00:00.000000000 +0100
9353 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_proto_gre.c 2003-11-17 09:09:34.000000000 +0100
9356 + * ip_nat_proto_gre.c - Version 1.2
9358 + * NAT protocol helper module for GRE.
9360 + * GRE is a generic encapsulation protocol, which is generally not very
9361 + * suited for NAT, as it has no protocol-specific part as port numbers.
9363 + * It has an optional key field, which may help us distinguishing two
9364 + * connections between the same two hosts.
9366 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
9368 + * PPTP is built on top of a modified version of GRE, and has a mandatory
9369 + * field called "CallID", which serves us for the same purpose as the key
9370 + * field in plain GRE.
9372 + * Documentation about PPTP can be found in RFC 2637
9374 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
9376 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
9380 +#include <linux/config.h>
9381 +#include <linux/module.h>
9382 +#include <linux/ip.h>
9383 +#include <linux/netfilter_ipv4/ip_nat.h>
9384 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9385 +#include <linux/netfilter_ipv4/ip_nat_protocol.h>
9386 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
9388 +MODULE_LICENSE("GPL");
9389 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9390 +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
9393 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
9394 + ": " format, ## args)
9396 +#define DEBUGP(x, args...)
9399 +/* is key in given range between min and max */
9401 +gre_in_range(const struct ip_conntrack_tuple *tuple,
9402 + enum ip_nat_manip_type maniptype,
9403 + const union ip_conntrack_manip_proto *min,
9404 + const union ip_conntrack_manip_proto *max)
9408 + if (maniptype == IP_NAT_MANIP_SRC)
9409 + key = tuple->src.u.gre.key;
9411 + key = tuple->dst.u.gre.key;
9413 + return ntohl(key) >= ntohl(min->gre.key)
9414 + && ntohl(key) <= ntohl(max->gre.key);
9417 +/* generate unique tuple ... */
9419 +gre_unique_tuple(struct ip_conntrack_tuple *tuple,
9420 + const struct ip_nat_range *range,
9421 + enum ip_nat_manip_type maniptype,
9422 + const struct ip_conntrack *conntrack)
9424 + u_int32_t min, i, range_size;
9425 + u_int32_t key = 0, *keyptr;
9427 + if (maniptype == IP_NAT_MANIP_SRC)
9428 + keyptr = &tuple->src.u.gre.key;
9430 + keyptr = &tuple->dst.u.gre.key;
9432 + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
9434 + switch (tuple->dst.u.gre.version) {
9436 + DEBUGP("NATing GRE version 0 (ct=%p)\n",
9439 + range_size = 0xffffffff;
9441 + case GRE_VERSION_PPTP:
9442 + DEBUGP("%p: NATing GRE PPTP\n",
9445 + range_size = 0xffff;
9448 + printk(KERN_WARNING "nat_gre: unknown GRE version\n");
9454 + min = ntohl(range->min.gre.key);
9455 + range_size = ntohl(range->max.gre.key) - min + 1;
9458 + DEBUGP("min = %u, range_size = %u\n", min, range_size);
9460 + for (i = 0; i < range_size; i++, key++) {
9461 + *keyptr = htonl(min + key % range_size);
9462 + if (!ip_nat_used_tuple(tuple, conntrack))
9466 + DEBUGP("%p: no NAT mapping\n", conntrack);
9471 +/* manipulate a GRE packet according to maniptype */
9473 +gre_manip_pkt(struct iphdr *iph, size_t len,
9474 + const struct ip_conntrack_manip *manip,
9475 + enum ip_nat_manip_type maniptype)
9477 + struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
9478 + struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
9480 + /* we only have destination manip of a packet, since 'source key'
9481 + * is not present in the packet itself */
9482 + if (maniptype == IP_NAT_MANIP_DST) {
9483 + /* key manipulation is always dest */
9484 + switch (greh->version) {
9487 + DEBUGP("can't nat GRE w/o key\n");
9491 + /* FIXME: Never tested this code... */
9492 + *(gre_csum(greh)) =
9493 + ip_nat_cheat_check(~*(gre_key(greh)),
9495 + *(gre_csum(greh)));
9497 + *(gre_key(greh)) = manip->u.gre.key;
9499 + case GRE_VERSION_PPTP:
9500 + DEBUGP("call_id -> 0x%04x\n",
9501 + ntohl(manip->u.gre.key));
9502 + pgreh->call_id = htons(ntohl(manip->u.gre.key));
9505 + DEBUGP("can't nat unknown GRE version\n");
9511 +/* print out a nat tuple */
9512 +static unsigned int
9513 +gre_print(char *buffer,
9514 + const struct ip_conntrack_tuple *match,
9515 + const struct ip_conntrack_tuple *mask)
9517 + unsigned int len = 0;
9519 + if (mask->dst.u.gre.version)
9520 + len += sprintf(buffer + len, "version=%d ",
9521 + ntohs(match->dst.u.gre.version));
9523 + if (mask->dst.u.gre.protocol)
9524 + len += sprintf(buffer + len, "protocol=0x%x ",
9525 + ntohs(match->dst.u.gre.protocol));
9527 + if (mask->src.u.gre.key)
9528 + len += sprintf(buffer + len, "srckey=0x%x ",
9529 + ntohl(match->src.u.gre.key));
9531 + if (mask->dst.u.gre.key)
9532 + len += sprintf(buffer + len, "dstkey=0x%x ",
9533 + ntohl(match->src.u.gre.key));
9538 +/* print a range of keys */
9539 +static unsigned int
9540 +gre_print_range(char *buffer, const struct ip_nat_range *range)
9542 + if (range->min.gre.key != 0
9543 + || range->max.gre.key != 0xFFFF) {
9544 + if (range->min.gre.key == range->max.gre.key)
9545 + return sprintf(buffer, "key 0x%x ",
9546 + ntohl(range->min.gre.key));
9548 + return sprintf(buffer, "keys 0x%u-0x%u ",
9549 + ntohl(range->min.gre.key),
9550 + ntohl(range->max.gre.key));
9555 +/* nat helper struct */
9556 +static struct ip_nat_protocol gre =
9557 + { { NULL, NULL }, "GRE", IPPROTO_GRE,
9565 +static int __init init(void)
9567 + if (ip_nat_protocol_register(&gre))
9573 +static void __exit fini(void)
9575 + ip_nat_protocol_unregister(&gre);
9580 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
9581 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
9582 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_quake3.c 2003-12-10 23:14:06.244005464 +0100
9584 +/* Quake3 extension for UDP NAT alteration.
9585 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
9586 + * based on ip_nat_ftp.c and ip_nat_tftp.c
9588 + * ip_nat_quake3.c v0.0.3 2002-08-31
9590 + * This program is free software; you can redistribute it and/or
9591 + * modify it under the terms of the GNU General Public License
9592 + * as published by the Free Software Foundation; either version
9593 + * 2 of the License, or (at your option) any later version.
9595 + * Module load syntax:
9596 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
9598 + * please give the ports of all Quake3 master servers You wish to
9599 + * connect to. If you don't specify ports, the default will be UDP
9602 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
9605 + * - If you're one of those people who would try anything to lower
9606 + * latency while playing Quake (and who isn't :-) ), you may want to
9607 + * consider not loading ip_nat_quake3 at all and just MASQUERADE all
9608 + * outgoing UDP traffic.
9609 + * This will make ip_conntrack_quake3 add the necessary expectations,
9610 + * but there will be no overhead for client->server UDP streams. If
9611 + * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
9612 + * hook for every packet in the client->server UDP stream.
9613 + * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
9614 + * The IP addresses in the master connection payload (=IP addresses
9615 + * of Quake servers) have no relation with the master server so
9616 + * DNAT'ing the master connection to a server should not change the
9617 + * expected connections.
9618 + * - Not tested due to lack of equipment:
9619 + * - multiple Quake3 clients behind one MASQUERADE gateway
9620 + * - what if Quake3 client is running on router too
9623 +#include <linux/module.h>
9624 +#include <linux/netfilter_ipv4.h>
9625 +#include <linux/ip.h>
9626 +#include <linux/udp.h>
9628 +#include <linux/netfilter.h>
9629 +#include <linux/netfilter_ipv4/ip_tables.h>
9630 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9631 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
9632 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9633 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9635 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
9636 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
9637 +MODULE_LICENSE("GPL");
9639 +#define MAX_PORTS 8
9641 +static int ports[MAX_PORTS];
9642 +static int ports_c = 0;
9644 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
9645 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
9648 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
9649 + doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
9651 +#define DEBUGP printk
9653 +#define DEBUGP(format, args...)
9656 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
9658 +static unsigned int
9659 +quake3_nat_help(struct ip_conntrack *ct,
9660 + struct ip_conntrack_expect *exp,
9661 + struct ip_nat_info *info,
9662 + enum ip_conntrack_info ctinfo,
9663 + unsigned int hooknum,
9664 + struct sk_buff **pskb)
9666 + struct iphdr *iph = (*pskb)->nh.iph;
9667 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
9668 + struct ip_conntrack_tuple repl;
9669 + int dir = CTINFO2DIR(ctinfo);
9672 + DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
9673 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9674 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9675 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9676 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
9678 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9679 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
9681 + /* Only mangle things once: original direction in POST_ROUTING
9682 + and reply direction on PRE_ROUTING. */
9683 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
9684 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
9685 + DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
9686 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9687 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9688 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9689 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
9694 + DEBUGP("no conntrack expectation to modify\n");
9698 + if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
9699 + for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
9700 + i+6 < ntohs(udph->len);
9702 + DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
9703 + i, ntohs(udph->len),
9704 + NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
9705 + ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
9707 + memset(&repl, 0, sizeof(repl));
9709 + repl.dst.protonum = IPPROTO_UDP;
9710 + repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
9711 + repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
9712 + repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
9714 + ip_conntrack_change_expect(exp, &repl);
9720 +static unsigned int
9721 +quake3_nat_expected(struct sk_buff **pskb,
9722 + unsigned int hooknum,
9723 + struct ip_conntrack *ct,
9724 + struct ip_nat_info *info)
9726 + const struct ip_conntrack *master = ct->master->expectant;
9727 + struct ip_nat_multi_range mr;
9728 + u_int32_t newsrcip, newdstip, newip;
9730 + const struct ip_conntrack_tuple *repl =
9731 + &master->tuplehash[IP_CT_DIR_REPLY].tuple;
9732 + struct iphdr *iph = (*pskb)->nh.iph;
9733 + struct udphdr *udph = (void *)iph + iph->ihl*4;
9736 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
9737 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9739 + IP_NF_ASSERT(info);
9740 + IP_NF_ASSERT(master);
9741 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
9743 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
9744 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9746 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
9748 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9749 + "newsrc: %u.%u.%u.%u\n",
9750 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9751 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9752 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9753 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9754 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9759 + DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9760 + "newdst: %u.%u.%u.%u\n",
9761 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9762 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9763 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9764 + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9765 + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9770 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
9771 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
9773 + return ip_nat_setup_info(ct,&mr,hooknum);
9776 +static struct ip_nat_helper quake3[MAX_PORTS];
9777 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
9779 +static void fini(void)
9783 + for (i = 0 ; i < ports_c; i++) {
9784 + DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
9785 + ip_nat_helper_unregister(&quake3[i]);
9789 +static int __init init(void)
9795 + ports[0] = QUAKE3_MASTER_PORT;
9797 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
9798 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
9800 + quake3[i].tuple.dst.protonum = IPPROTO_UDP;
9801 + quake3[i].tuple.src.u.udp.port = htons(ports[i]);
9802 + quake3[i].mask.dst.protonum = 0xFFFF;
9803 + quake3[i].mask.src.u.udp.port = 0xFFFF;
9804 + quake3[i].help = quake3_nat_help;
9805 + quake3[i].flags = 0;
9806 + quake3[i].me = THIS_MODULE;
9807 + quake3[i].expect = quake3_nat_expected;
9809 + tmpname = &quake3_names[i][0];
9810 + if (ports[i] == QUAKE3_MASTER_PORT)
9811 + sprintf(tmpname, "quake3");
9813 + sprintf(tmpname, "quake3-%d", i);
9814 + quake3[i].name = tmpname;
9816 + DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
9817 + ports[i], quake3[i].name);
9818 + ret = ip_nat_helper_register(&quake3[i]);
9821 + printk("ip_nat_quake3: unable to register helper for port %d\n",
9833 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
9834 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
9835 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rtsp.c 2003-12-10 23:14:12.892994664 +0100
9838 + * RTSP extension for TCP NAT alteration
9839 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
9840 + * based on ip_nat_irc.c
9842 + * This program is free software; you can redistribute it and/or
9843 + * modify it under the terms of the GNU General Public License
9844 + * as published by the Free Software Foundation; either version
9845 + * 2 of the License, or (at your option) any later version.
9847 + * Module load syntax:
9848 + * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
9849 + * stunaddr=<address>
9850 + * destaction=[auto|strip|none]
9852 + * If no ports are specified, the default will be port 554 only.
9854 + * stunaddr specifies the address used to detect that a client is using STUN.
9855 + * If this address is seen in the destination parameter, it is assumed that
9856 + * the client has already punched a UDP hole in the firewall, so we don't
9857 + * mangle the client_port. If none is specified, it is autodetected. It
9858 + * only needs to be set if you have multiple levels of NAT. It should be
9859 + * set to the external address that the STUN clients detect. Note that in
9860 + * this case, it will not be possible for clients to use UDP with servers
9861 + * between the NATs.
9863 + * If no destaction is specified, auto is used.
9864 + * destaction=auto: strip destination parameter if it is not stunaddr.
9865 + * destaction=strip: always strip destination parameter (not recommended).
9866 + * destaction=none: do not touch destination parameter (not recommended).
9869 +#include <linux/module.h>
9870 +#include <linux/netfilter_ipv4.h>
9871 +#include <linux/ip.h>
9872 +#include <linux/tcp.h>
9873 +#include <linux/kernel.h>
9874 +#include <net/tcp.h>
9875 +#include <linux/netfilter_ipv4/ip_nat.h>
9876 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9877 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9878 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
9879 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9881 +#include <linux/inet.h>
9882 +#include <linux/ctype.h>
9883 +#define NF_NEED_STRNCASECMP
9884 +#define NF_NEED_STRTOU16
9885 +#include <linux/netfilter_helpers.h>
9886 +#define NF_NEED_MIME_NEXTLINE
9887 +#include <linux/netfilter_mime.h>
9889 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
9890 +#ifdef IP_NF_RTSP_DEBUG
9891 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
9893 +#define DEBUGP(args...)
9896 +#define MAX_PORTS 8
9897 +#define DSTACT_AUTO 0
9898 +#define DSTACT_STRIP 1
9899 +#define DSTACT_NONE 2
9901 +static int ports[MAX_PORTS];
9902 +static char* stunaddr = NULL;
9903 +static char* destaction = NULL;
9905 +static int num_ports = 0;
9906 +static u_int32_t extip = 0;
9907 +static int dstact = 0;
9909 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
9910 +MODULE_DESCRIPTION("RTSP network address translation module");
9911 +MODULE_LICENSE("GPL");
9913 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9914 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
9915 +MODULE_PARM(stunaddr, "s");
9916 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
9917 +MODULE_PARM(destaction, "s");
9918 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
9921 +/* protects rtsp part of conntracks */
9922 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
9924 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
9926 +/*** helper functions ***/
9929 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
9931 + struct iphdr* iph = (struct iphdr*)skb->nh.iph;
9932 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
9934 + *pptcpdata = (char*)tcph + tcph->doff*4;
9935 + *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
9938 +/*** nat functions ***/
9941 + * Mangle the "Transport:" header:
9942 + * - Replace all occurences of "client_port=<spec>"
9943 + * - Handle destination parameter
9946 + * ct, ctinfo = conntrack context
9948 + * tranoff = Transport header offset from TCP data
9949 + * tranlen = Transport header length (incl. CRLF)
9950 + * rport_lo = replacement low port (host endian)
9951 + * rport_hi = replacement high port (host endian)
9953 + * Returns packet size difference.
9955 + * Assumes that a complete transport header is present, ending with CR or LF
9958 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
9959 + struct ip_conntrack_expect* exp,
9960 + struct sk_buff** pskb, uint tranoff, uint tranlen)
9965 + char rbuf1[16]; /* Replacement buffer (one port) */
9966 + uint rbuf1len; /* Replacement len (one port) */
9967 + char rbufa[16]; /* Replacement buffer (all ports) */
9968 + uint rbufalen; /* Replacement len (all ports) */
9970 + u_int16_t loport, hiport;
9972 + uint diff; /* Number of bytes we removed */
9974 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
9975 + struct ip_conntrack_tuple t;
9977 + char szextaddr[15+1];
9981 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
9982 + ptran = ptcp+tranoff;
9984 + if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
9985 + tranlen < 10 || !iseol(ptran[tranlen-1]) ||
9986 + nf_strncasecmp(ptran, "Transport:", 10) != 0)
9988 + INFOP("sanity check failed\n");
9992 + SKIP_WSPACE(ptcp+tranoff, tranlen, off);
9994 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9998 + extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
9999 + : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
10000 + DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
10002 + rbuf1len = rbufalen = 0;
10003 + switch (prtspexp->pbtype)
10006 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10008 + t.dst.u.udp.port = htons(loport);
10009 + if (ip_conntrack_change_expect(exp, &t) == 0)
10011 + DEBUGP("using port %hu\n", loport);
10017 + rbuf1len = sprintf(rbuf1, "%hu", loport);
10018 + rbufalen = sprintf(rbufa, "%hu", loport);
10022 + for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
10024 + t.dst.u.udp.port = htons(loport);
10025 + if (ip_conntrack_change_expect(exp, &t) == 0)
10027 + hiport = loport + ~exp->mask.dst.u.udp.port;
10028 + DEBUGP("using ports %hu-%hu\n", loport, hiport);
10034 + rbuf1len = sprintf(rbuf1, "%hu", loport);
10035 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
10039 + for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10041 + t.dst.u.udp.port = htons(loport);
10042 + if (ip_conntrack_change_expect(exp, &t) == 0)
10044 + DEBUGP("using port %hu (1 of 2)\n", loport);
10048 + for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
10050 + t.dst.u.udp.port = htons(hiport);
10051 + if (ip_conntrack_change_expect(exp, &t) == 0)
10053 + DEBUGP("using port %hu (2 of 2)\n", hiport);
10057 + if (loport != 0 && hiport != 0)
10059 + rbuf1len = sprintf(rbuf1, "%hu", loport);
10060 + if (hiport == loport+1)
10062 + rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
10066 + rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
10074 + if (rbuf1len == 0)
10076 + return 0; /* cannot get replacement port(s) */
10079 + /* Transport: tran;field;field=val,tran;field;field=val,... */
10080 + while (off < tranlen)
10083 + const char* pparamend;
10084 + uint nextparamoff;
10086 + pparamend = memchr(ptran+off, ',', tranlen-off);
10087 + pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
10088 + nextparamoff = pparamend-ptcp;
10091 + * We pass over each param twice. On the first pass, we look for a
10092 + * destination= field. It is handled by the security policy. If it
10093 + * is present, allowed, and equal to our external address, we assume
10094 + * that STUN is being used and we leave the client_port= field alone.
10098 + while (off < nextparamoff)
10100 + const char* pfieldend;
10101 + uint nextfieldoff;
10103 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10104 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10106 + if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
10108 + if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
10112 + if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
10114 + diff = nextfieldoff-off;
10115 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10116 + off, diff, NULL, 0))
10118 + /* mangle failed, all we can do is bail */
10121 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10122 + ptran = ptcp+tranoff;
10124 + nextparamoff -= diff;
10125 + nextfieldoff -= diff;
10129 + off = nextfieldoff;
10136 + while (off < nextparamoff)
10138 + const char* pfieldend;
10139 + uint nextfieldoff;
10141 + pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10142 + nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10144 + if (strncmp(ptran+off, "client_port=", 12) == 0)
10150 + char* rbuf = rbuf1;
10151 + uint rbuflen = rbuf1len;
10154 + origoff = (ptran-ptcp)+off;
10156 + numlen = nf_strtou16(ptran+off, &port);
10158 + origlen += numlen;
10159 + if (port != prtspexp->loport)
10161 + DEBUGP("multiple ports found, port %hu ignored\n", port);
10165 + if (ptran[off] == '-' || ptran[off] == '/')
10169 + numlen = nf_strtou16(ptran+off, &port);
10171 + origlen += numlen;
10173 + rbuflen = rbufalen;
10177 + * note we cannot just memcpy() if the sizes are the same.
10178 + * the mangle function does skb resizing, checks for a
10179 + * cloned skb, and updates the checksums.
10181 + * parameter 4 below is offset from start of tcp data.
10183 + diff = origlen-rbuflen;
10184 + if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10185 + origoff, origlen, rbuf, rbuflen))
10187 + /* mangle failed, all we can do is bail */
10190 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10191 + ptran = ptcp+tranoff;
10193 + nextparamoff -= diff;
10194 + nextfieldoff -= diff;
10198 + off = nextfieldoff;
10201 + off = nextparamoff;
10207 +static unsigned int
10208 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
10210 + struct ip_nat_multi_range mr;
10211 + u_int32_t newdstip, newsrcip, newip;
10213 + struct ip_conntrack *master = master_ct(ct);
10215 + IP_NF_ASSERT(info);
10216 + IP_NF_ASSERT(master);
10218 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10220 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10221 + newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10222 + newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
10224 + DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
10225 + NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
10227 + mr.rangesize = 1;
10228 + /* We don't want to manip the per-protocol, just the IPs. */
10229 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10230 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
10232 + return ip_nat_setup_info(ct, &mr, hooknum);
10236 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10237 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10247 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
10248 + struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
10250 + struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
10252 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10254 + hdrsoff = exp->seq - ntohl(tcph->seq);
10255 + hdrslen = prtspexp->len;
10258 + while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
10260 + if (linelen == 0)
10264 + if (off > hdrsoff+hdrslen)
10266 + INFOP("!! overrun !!");
10269 + DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10271 + if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
10273 + uint oldtcplen = tcplen;
10274 + if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
10278 + get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10279 + hdrslen -= (oldtcplen-tcplen);
10280 + off -= (oldtcplen-tcplen);
10281 + lineoff -= (oldtcplen-tcplen);
10282 + linelen -= (oldtcplen-tcplen);
10283 + DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10287 + return NF_ACCEPT;
10291 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10292 + struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10294 + /* XXX: unmangle */
10295 + return NF_ACCEPT;
10299 +help(struct ip_conntrack* ct,
10300 + struct ip_conntrack_expect* exp,
10301 + struct ip_nat_info* info,
10302 + enum ip_conntrack_info ctinfo,
10303 + unsigned int hooknum,
10304 + struct sk_buff** pskb)
10306 + struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
10307 + struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
10310 + struct ip_ct_rtsp_expect* ct_rtsp_info;
10311 + int rc = NF_ACCEPT;
10313 + if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
10315 + DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
10316 + return NF_ACCEPT;
10319 + ct_rtsp_info = &exp->help.exp_rtsp_info;
10322 + * Only mangle things once: original direction in POST_ROUTING
10323 + * and reply direction on PRE_ROUTING.
10325 + dir = CTINFO2DIR(ctinfo);
10326 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10327 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
10329 + DEBUGP("Not touching dir %s at hook %s\n",
10330 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10331 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10332 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10333 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10334 + return NF_ACCEPT;
10336 + DEBUGP("got beyond not touching\n");
10338 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
10340 + LOCK_BH(&ip_rtsp_lock);
10341 + /* Ensure the packet contains all of the marked data */
10342 + if (!between(exp->seq + ct_rtsp_info->len,
10343 + ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
10345 + /* Partial retransmission? Probably a hacker. */
10346 + if (net_ratelimit())
10348 + INFOP("partial packet %u/%u in %u/%u\n",
10349 + exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
10351 + UNLOCK_BH(&ip_rtsp_lock);
10357 + case IP_CT_DIR_ORIGINAL:
10358 + rc = help_out(ct, ctinfo, exp, pskb);
10360 + case IP_CT_DIR_REPLY:
10361 + rc = help_in(ct, ctinfo, exp, pskb);
10366 + UNLOCK_BH(&ip_rtsp_lock);
10371 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
10372 +static char rtsp_names[MAX_PORTS][10];
10374 +/* This function is intentionally _NOT_ defined as __exit */
10380 + for (i = 0; i < num_ports; i++)
10382 + DEBUGP("unregistering helper for port %d\n", ports[i]);
10383 + ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
10392 + struct ip_nat_helper* hlpr;
10395 + printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
10397 + if (ports[0] == 0)
10399 + ports[0] = RTSP_PORT;
10402 + for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
10404 + hlpr = &ip_nat_rtsp_helpers[i];
10405 + memset(hlpr, 0, sizeof(struct ip_nat_helper));
10407 + hlpr->tuple.dst.protonum = IPPROTO_TCP;
10408 + hlpr->tuple.src.u.tcp.port = htons(ports[i]);
10409 + hlpr->mask.src.u.tcp.port = 0xFFFF;
10410 + hlpr->mask.dst.protonum = 0xFFFF;
10411 + hlpr->help = help;
10413 + hlpr->me = THIS_MODULE;
10414 + hlpr->expect = expected;
10416 + tmpname = &rtsp_names[i][0];
10417 + if (ports[i] == RTSP_PORT)
10419 + sprintf(tmpname, "rtsp");
10423 + sprintf(tmpname, "rtsp-%d", i);
10425 + hlpr->name = tmpname;
10427 + DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
10428 + ret = ip_nat_helper_register(hlpr);
10432 + printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
10438 + if (stunaddr != NULL)
10440 + extip = in_aton(stunaddr);
10442 + if (destaction != NULL)
10444 + if (strcmp(destaction, "auto") == 0)
10446 + dstact = DSTACT_AUTO;
10448 + if (strcmp(destaction, "strip") == 0)
10450 + dstact = DSTACT_STRIP;
10452 + if (strcmp(destaction, "none") == 0)
10454 + dstact = DSTACT_NONE;
10460 +module_init(init);
10461 +module_exit(fini);
10462 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
10463 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rule.c 2003-11-26 21:43:38.000000000 +0100
10464 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rule.c 2003-12-10 23:13:24.662326840 +0100
10467 sizeof(struct ipt_entry),
10468 sizeof(struct ipt_standard),
10469 - 0, { 0, 0 }, { } },
10470 + 0, NULL, 0, { 0, 0 }, { } },
10471 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10472 -NF_ACCEPT - 1 } },
10476 sizeof(struct ipt_entry),
10477 sizeof(struct ipt_standard),
10478 - 0, { 0, 0 }, { } },
10479 + 0, NULL, 0, { 0, 0 }, { } },
10480 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10481 -NF_ACCEPT - 1 } },
10485 sizeof(struct ipt_entry),
10486 sizeof(struct ipt_standard),
10487 - 0, { 0, 0 }, { } },
10488 + 0, NULL, 0, { 0, 0 }, { } },
10489 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10494 sizeof(struct ipt_entry),
10495 sizeof(struct ipt_error),
10496 - 0, { 0, 0 }, { } },
10497 + 0, NULL, 0, { 0, 0 }, { } },
10498 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10501 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
10502 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_standalone.c 2003-11-26 21:45:10.000000000 +0100
10503 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_standalone.c 2003-12-10 23:14:03.996347160 +0100
10504 @@ -260,7 +260,13 @@
10508 -/* Protocol registration. */
10510 + * ip_nat_protocol_register - Register a layer 4 protocol helper
10511 + * @proto: structure describing this helper
10513 + * This function is called by NAT layer 4 protocol helpers to register
10514 + * themselvers with the NAT core.
10516 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
10519 @@ -281,9 +287,16 @@
10523 -/* Noone stores the protocol anywhere; simply delete it. */
10525 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
10526 + * @proto: sturcture describing the helper
10528 + * This function is called by NAT layer 4 protocol helpers to
10529 + * unregister themselves from the NAT core.
10531 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
10533 + /* Noone stores the protocol anywhere; simply delete it. */
10534 WRITE_LOCK(&ip_nat_lock);
10535 LIST_DELETE(&protos, proto);
10536 WRITE_UNLOCK(&ip_nat_lock);
10537 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
10538 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
10539 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_talk.c 2003-12-10 23:14:15.481601136 +0100
10542 + * talk extension for UDP NAT alteration.
10543 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10545 + * This program is free software; you can redistribute it and/or
10546 + * modify it under the terms of the GNU General Public License
10547 + * as published by the Free Software Foundation; either version
10548 + * 2 of the License, or (at your option) any later version.
10550 + * Module load syntax:
10551 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
10553 + * talk=[0|1] disable|enable old talk support
10554 + * ntalk=[0|1] disable|enable ntalk support
10555 + * ntalk2=[0|1] disable|enable ntalk2 support
10557 + * The default is talk=1 ntalk=1 ntalk2=1
10561 +#include <linux/module.h>
10562 +#include <linux/netfilter_ipv4.h>
10563 +#include <linux/ip.h>
10564 +#include <linux/udp.h>
10565 +#include <linux/kernel.h>
10566 +#include <net/tcp.h>
10567 +#include <net/udp.h>
10569 +#include <linux/netfilter_ipv4/ip_nat.h>
10570 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
10571 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
10572 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
10573 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10575 +/* Default all talk protocols are supported */
10576 +static int talk = 1;
10577 +static int ntalk = 1;
10578 +static int ntalk2 = 1;
10579 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
10580 +MODULE_DESCRIPTION("talk network address translation module");
10581 +#ifdef MODULE_PARM
10582 +MODULE_PARM(talk, "i");
10583 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
10584 +MODULE_PARM(ntalk, "i");
10585 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
10586 +MODULE_PARM(ntalk2, "i");
10587 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
10591 +#define DEBUGP printk
10592 +#define IP_NAT_TALK_DEBUG
10594 +#define DEBUGP(format, args...)
10597 +/* FIXME: Time out? --RR */
10600 +mangle_packet(struct sk_buff **pskb,
10601 + struct ip_conntrack *ct,
10604 + struct talk_addr *addr,
10605 + struct talk_addr *ctl_addr)
10607 + struct iphdr *iph = (*pskb)->nh.iph;
10608 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10609 + size_t udplen = (*pskb)->len - iph->ihl * 4;
10611 + /* Fortunately talk sends a structure with the address and
10612 + port in it. The size of the packet won't change. */
10614 + if (ctl_addr == NULL) {
10616 + if (addr->ta_addr == INADDR_ANY)
10618 + DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
10619 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10620 + NIPQUAD(newip), ntohs(port));
10621 + addr->ta_addr = newip;
10622 + addr->ta_port = port;
10625 + if (addr->ta_addr != INADDR_ANY) {
10626 + /* Change address inside packet to match way we're mapping
10627 + this connection. */
10628 + DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
10629 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10630 + NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
10631 + ntohs(addr->ta_port));
10632 + addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10634 + DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
10635 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10636 + NIPQUAD(newip), ntohs(port));
10637 + ctl_addr->ta_addr = newip;
10638 + ctl_addr->ta_port = port;
10641 + /* Fix checksums */
10642 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
10644 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
10645 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
10647 + ip_send_check(iph);
10651 +static int talk_help_msg(struct ip_conntrack *ct,
10652 + struct sk_buff **pskb,
10654 + struct talk_addr *addr,
10655 + struct talk_addr *ctl_addr)
10660 + unsigned int verdict = NF_ACCEPT;
10662 + DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
10663 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10664 + NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10667 + /* Change address inside packet to match way we're mapping
10668 + this connection. */
10669 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10670 + port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
10671 + DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
10672 + NIPQUAD(newip), ntohs(port));
10674 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
10675 + verdict = NF_DROP;
10680 +static int talk_help_response(struct ip_conntrack *ct,
10681 + struct ip_conntrack_expect *exp,
10682 + struct sk_buff **pskb,
10685 + struct talk_addr *addr)
10689 + struct ip_conntrack_tuple t;
10690 + struct ip_ct_talk_expect *ct_talk_info;
10692 + DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
10693 + NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10696 + LOCK_BH(&ip_talk_lock);
10697 + ct_talk_info = &exp->help.exp_talk_info;
10699 + if (!(answer == SUCCESS
10700 + && (type == LOOK_UP || type == ANNOUNCE)
10701 + && exp != NULL)) {
10702 + UNLOCK_BH(&ip_talk_lock);
10703 + return NF_ACCEPT;
10706 + DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
10707 + ntohs(ct_talk_info->port),
10708 + type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
10710 + /* Change address inside packet to match way we're mapping
10711 + this connection. */
10712 + newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
10713 + IP_CT_DIR_REPLY].tuple.dst.ip;
10714 + /* We can read expect here without conntrack lock, since it's
10715 + only set in ip_conntrack_talk , with ip_talk_lock held
10718 + t.dst.ip = newip;
10720 + /* Try to get same port: if not, try to change it. */
10721 + for (port = ntohs(ct_talk_info->port); port != 0; port++) {
10722 + if (type == LOOK_UP)
10723 + t.dst.u.tcp.port = htons(port);
10725 + t.dst.u.udp.port = htons(port);
10727 + if (ip_conntrack_change_expect(exp, &t) == 0) {
10728 + DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
10732 + UNLOCK_BH(&ip_talk_lock);
10734 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
10737 + return NF_ACCEPT;
10740 +static unsigned int talk_help(struct ip_conntrack *ct,
10741 + struct ip_conntrack_expect *exp,
10742 + struct ip_nat_info *info,
10743 + enum ip_conntrack_info ctinfo,
10744 + unsigned int hooknum,
10745 + struct sk_buff **pskb,
10748 + struct iphdr *iph = (*pskb)->nh.iph;
10749 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10750 + unsigned int udplen = (*pskb)->len - iph->ihl * 4;
10751 + char *data = (char *)udph + sizeof(struct udphdr);
10754 + /* Only mangle things once: original direction in POST_ROUTING
10755 + and reply direction on PRE_ROUTING. */
10756 + dir = CTINFO2DIR(ctinfo);
10757 + if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10758 + || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
10759 + DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
10760 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10761 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10762 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10763 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10764 + return NF_ACCEPT;
10766 + DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
10767 + dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10768 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10769 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10770 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10771 + NIPQUAD(iph->saddr), ntohs(udph->source),
10772 + NIPQUAD(iph->daddr), ntohs(udph->dest),
10775 + /* Because conntrack does not drop packets, checking must be repeated here... */
10776 + if (talk_port == TALK_PORT) {
10777 + if (dir == IP_CT_DIR_ORIGINAL
10778 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
10779 + return talk_help_msg(ct, pskb,
10780 + ((struct talk_msg *)data)->type,
10781 + &(((struct talk_msg *)data)->addr),
10782 + &(((struct talk_msg *)data)->ctl_addr));
10783 + else if (dir == IP_CT_DIR_REPLY
10784 + && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
10785 + return talk_help_response(ct, exp, pskb,
10786 + ((struct talk_response *)data)->type,
10787 + ((struct talk_response *)data)->answer,
10788 + &(((struct talk_response *)data)->addr));
10790 + DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
10791 + dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
10792 + (unsigned)udplen - sizeof(struct udphdr),
10793 + dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
10797 + if (dir == IP_CT_DIR_ORIGINAL) {
10799 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
10800 + && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
10801 + return talk_help_msg(ct, pskb,
10802 + ((struct ntalk_msg *)data)->type,
10803 + &(((struct ntalk_msg *)data)->addr),
10804 + &(((struct ntalk_msg *)data)->ctl_addr));
10806 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
10807 + && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
10808 + && udplen == sizeof(struct udphdr)
10809 + + sizeof(struct ntalk2_msg)
10810 + + ((struct ntalk2_msg *)data)->extended)
10811 + return talk_help_msg(ct, pskb,
10812 + ((struct ntalk2_msg *)data)->type,
10813 + &(((struct ntalk2_msg *)data)->addr),
10814 + &(((struct ntalk2_msg *)data)->ctl_addr));
10816 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
10817 + (unsigned)udplen - sizeof(struct udphdr),
10818 + sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
10823 + && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
10824 + && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
10825 + return talk_help_response(ct, exp, pskb,
10826 + ((struct ntalk_response *)data)->type,
10827 + ((struct ntalk_response *)data)->answer,
10828 + &(((struct ntalk_response *)data)->addr));
10830 + && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
10831 + && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
10832 + return talk_help_response(ct, exp, pskb,
10833 + ((struct ntalk2_response *)data)->type,
10834 + ((struct ntalk2_response *)data)->answer,
10835 + &(((struct ntalk2_response *)data)->addr));
10837 + DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
10838 + (unsigned)udplen - sizeof(struct udphdr),
10839 + sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
10846 +static unsigned int help(struct ip_conntrack *ct,
10847 + struct ip_conntrack_expect *exp,
10848 + struct ip_nat_info *info,
10849 + enum ip_conntrack_info ctinfo,
10850 + unsigned int hooknum,
10851 + struct sk_buff **pskb)
10853 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
10856 +static unsigned int nhelp(struct ip_conntrack *ct,
10857 + struct ip_conntrack_expect *exp,
10858 + struct ip_nat_info *info,
10859 + enum ip_conntrack_info ctinfo,
10860 + unsigned int hooknum,
10861 + struct sk_buff **pskb)
10863 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
10866 +static unsigned int
10867 +talk_nat_expected(struct sk_buff **pskb,
10868 + unsigned int hooknum,
10869 + struct ip_conntrack *ct,
10870 + struct ip_nat_info *info);
10872 +static struct ip_nat_helper talk_helpers[2] =
10873 + { { { NULL, NULL },
10874 + "talk", /* name */
10875 + IP_NAT_HELPER_F_ALWAYS, /* flags */
10876 + THIS_MODULE, /* module */
10877 + { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
10878 + { 0, { 0 }, IPPROTO_UDP } },
10879 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
10880 + { 0, { 0 }, 0xFFFF } },
10881 + help, /* helper */
10882 + talk_nat_expected }, /* expectfn */
10883 + { { NULL, NULL },
10884 + "ntalk", /* name */
10885 + IP_NAT_HELPER_F_ALWAYS, /* flags */
10886 + THIS_MODULE, /* module */
10887 + { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
10888 + { 0, { 0 }, IPPROTO_UDP } },
10889 + { { 0, { .udp = { 0xFFFF } } }, /* mask */
10890 + { 0, { 0 }, 0xFFFF } },
10891 + nhelp, /* helper */
10892 + talk_nat_expected } /* expectfn */
10895 +static unsigned int
10896 +talk_nat_expected(struct sk_buff **pskb,
10897 + unsigned int hooknum,
10898 + struct ip_conntrack *ct,
10899 + struct ip_nat_info *info)
10901 + struct ip_nat_multi_range mr;
10902 + u_int32_t newdstip, newsrcip, newip;
10904 + unsigned int ret;
10906 + struct ip_conntrack *master = master_ct(ct);
10908 + IP_NF_ASSERT(info);
10909 + IP_NF_ASSERT(master);
10911 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
10913 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
10915 + LOCK_BH(&ip_talk_lock);
10916 + port = ct->master->help.exp_talk_info.port;
10917 + UNLOCK_BH(&ip_talk_lock);
10919 + DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
10920 + CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10921 + hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10922 + : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10923 + : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10926 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10927 + /* Callee client -> caller server */
10928 +#ifdef IP_NAT_TALK_DEBUG
10929 + struct iphdr *iph = (*pskb)->nh.iph;
10930 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10932 + DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10933 + NIPQUAD(iph->saddr), ntohs(udph->source),
10934 + NIPQUAD(iph->daddr), ntohs(udph->dest));
10936 + newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10937 + newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
10938 + DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10939 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
10941 + /* Callee client -> caller client */
10942 +#ifdef IP_NAT_TALK_DEBUG
10943 + struct iphdr *iph = (*pskb)->nh.iph;
10944 + struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
10946 + DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10947 + NIPQUAD(iph->saddr), ntohs(tcph->source),
10948 + NIPQUAD(iph->daddr), ntohs(tcph->dest));
10950 + newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
10951 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10952 + DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10953 + NIPQUAD(newsrcip), NIPQUAD(newdstip));
10955 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
10956 + newip = newsrcip;
10958 + newip = newdstip;
10960 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
10962 + mr.rangesize = 1;
10963 + /* We don't want to manip the per-protocol, just the IPs... */
10964 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10965 + mr.range[0].min_ip = mr.range[0].max_ip = newip;
10967 + /* ... unless we're doing a MANIP_DST, in which case, make
10968 + sure we map to the correct port */
10969 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
10970 + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
10971 + mr.range[0].min = mr.range[0].max
10972 + = ((union ip_conntrack_manip_proto)
10973 + { .udp = { port } });
10975 + ret = ip_nat_setup_info(ct, &mr, hooknum);
10977 + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10978 + DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
10979 + /* NAT expectfn called with ip_nat_lock write-locked */
10980 + info->helper = &talk_helpers[htons(port) - TALK_PORT];
10985 +static int __init init(void)
10990 + ret = ip_nat_helper_register(&talk_helpers[0]);
10995 + if (ntalk > 0 || ntalk2 > 0) {
10996 + ret = ip_nat_helper_register(&talk_helpers[1]);
10998 + if (ret != 0 && talk > 0)
10999 + ip_nat_helper_unregister(&talk_helpers[0]);
11004 +static void __exit fini(void)
11007 + ip_nat_helper_unregister(&talk_helpers[0]);
11008 + if (ntalk > 0 || ntalk2 > 0)
11009 + ip_nat_helper_unregister(&talk_helpers[1]);
11012 +module_init(init);
11013 +module_exit(fini);
11014 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
11015 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_tftp.c 2003-11-26 21:43:31.000000000 +0100
11016 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_tftp.c 2003-12-10 23:13:21.271842272 +0100
11017 @@ -164,8 +164,6 @@
11018 ports[0] = TFTP_PORT;
11020 for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
11021 - memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
11023 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
11024 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
11025 tftp[i].mask.dst.protonum = 0xFFFF;
11026 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
11027 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
11028 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_pool.c 2003-12-10 23:13:39.982997744 +0100
11030 +/* Kernel module for IP pool management */
11032 +#include <linux/module.h>
11033 +#include <linux/ip.h>
11034 +#include <linux/skbuff.h>
11035 +#include <linux/netfilter_ipv4/ip_tables.h>
11036 +#include <linux/netfilter_ipv4/ip_pool.h>
11037 +#include <linux/errno.h>
11038 +#include <asm/uaccess.h>
11039 +#include <asm/bitops.h>
11040 +#include <linux/interrupt.h>
11041 +#include <linux/spinlock.h>
11046 +#define DP(format, args...)
11049 +MODULE_LICENSE("GPL");
11051 +#define NR_POOL 16
11052 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
11055 + u_int32_t first_ip; /* host byte order, included in range */
11056 + u_int32_t last_ip; /* host byte order, included in range */
11057 + void *members; /* the bitmap proper */
11058 + int nr_use; /* total nr. of tests through this */
11059 + int nr_match; /* total nr. of matches through this */
11063 +static struct ip_pool *POOL;
11065 +static inline struct ip_pool *lookup(ip_pool_t index)
11067 + if (index < 0 || index >= nr_pool) {
11068 + DP("ip_pool:lookup: bad index %d\n", index);
11071 + return POOL+index;
11074 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
11076 + struct ip_pool *pool = lookup(index);
11079 + if (!pool || !pool->members)
11081 + read_lock_bh(&pool->lock);
11082 + if (pool->members) {
11083 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
11084 + addr -= pool->first_ip;
11085 + if (test_bit(addr, pool->members)) {
11087 +#ifdef CONFIG_IP_POOL_STATISTICS
11088 + pool->nr_match++;
11092 +#ifdef CONFIG_IP_POOL_STATISTICS
11096 + read_unlock_bh(&pool->lock);
11100 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
11102 + struct ip_pool *pool;
11105 + pool = lookup(index);
11106 + if ( !pool || !pool->members
11107 + || addr < pool->first_ip || addr > pool->last_ip)
11109 + read_lock_bh(&pool->lock);
11110 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
11111 + addr -= pool->first_ip;
11113 + ? (0 != test_and_clear_bit(addr, pool->members))
11114 + : (0 != test_and_set_bit(addr, pool->members));
11116 + read_unlock_bh(&pool->lock);
11120 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
11122 + int res = pool_change(index,addr,isdel);
11124 + if (!isdel) res = !res;
11128 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
11130 + return 4*((((b-a+8)/8)+3)/4);
11133 +static inline int poolbytes(ip_pool_t index)
11135 + struct ip_pool *pool = lookup(index);
11137 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
11140 +static int setpool(
11146 + struct ip_pool_request req;
11148 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
11149 + if (!capable(CAP_NET_ADMIN))
11151 + if (optval != SO_IP_POOL)
11153 + if (len != sizeof(req))
11155 + if (copy_from_user(&req, user, sizeof(req)) != 0)
11157 + printk("obsolete op - upgrade your ippool(8) utility.\n");
11161 +static int getpool(
11167 + struct ip_pool_request req;
11168 + struct ip_pool *pool;
11171 + void *newmembers;
11174 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
11175 + if (!capable(CAP_NET_ADMIN))
11177 + if (optval != SO_IP_POOL)
11179 + if (*len != sizeof(req)) {
11182 + if (copy_from_user(&req, user, sizeof(req)) != 0)
11184 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
11185 + if (req.op < IP_POOL_BAD001) {
11186 + printk("obsolete op - upgrade your ippool(8) utility.\n");
11190 + case IP_POOL_HIGH_NR:
11191 + DP("ip_pool HIGH_NR\n");
11192 + req.index = IP_POOL_NONE;
11193 + for (i=0; i<nr_pool; i++)
11194 + if (POOL[i].members)
11196 + return copy_to_user(user, &req, sizeof(req));
11197 + case IP_POOL_LOOKUP:
11198 + DP("ip_pool LOOKUP\n");
11199 + pool = lookup(req.index);
11202 + if (!pool->members)
11204 + req.addr = htonl(pool->first_ip);
11205 + req.addr2 = htonl(pool->last_ip);
11206 + return copy_to_user(user, &req, sizeof(req));
11207 + case IP_POOL_USAGE:
11208 + DP("ip_pool USE\n");
11209 + pool = lookup(req.index);
11212 + if (!pool->members)
11214 + req.addr = pool->nr_use;
11215 + req.addr2 = pool->nr_match;
11216 + return copy_to_user(user, &req, sizeof(req));
11217 + case IP_POOL_TEST_ADDR:
11218 + DP("ip_pool TEST 0x%08x\n", req.addr);
11219 + pool = lookup(req.index);
11223 + read_lock_bh(&pool->lock);
11224 + if (!pool->members) {
11225 + DP("ip_pool TEST_ADDR no members in pool\n");
11227 + goto unlock_and_return_res;
11229 + req.addr = ntohl(req.addr);
11230 + if (req.addr < pool->first_ip) {
11231 + DP("ip_pool TEST_ADDR address < pool bounds\n");
11233 + goto unlock_and_return_res;
11235 + if (req.addr > pool->last_ip) {
11236 + DP("ip_pool TEST_ADDR address > pool bounds\n");
11238 + goto unlock_and_return_res;
11240 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
11242 + read_unlock_bh(&pool->lock);
11243 + return copy_to_user(user, &req, sizeof(req));
11244 + case IP_POOL_FLUSH:
11245 + DP("ip_pool FLUSH not yet implemented.\n");
11247 + case IP_POOL_DESTROY:
11248 + DP("ip_pool DESTROY not yet implemented.\n");
11250 + case IP_POOL_INIT:
11251 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
11252 + pool = lookup(req.index);
11255 + req.addr = ntohl(req.addr);
11256 + req.addr2 = ntohl(req.addr2);
11257 + if (req.addr > req.addr2) {
11258 + DP("ip_pool INIT bad ip range\n");
11261 + newbytes = bitmap_bytes(req.addr, req.addr2);
11262 + newmembers = kmalloc(newbytes, GFP_KERNEL);
11263 + if (!newmembers) {
11264 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
11267 + memset(newmembers, 0, newbytes);
11268 + write_lock_bh(&pool->lock);
11269 + if (pool->members) {
11270 + DP("ip_pool INIT pool %d exists\n", req.index);
11271 + kfree(newmembers);
11273 + goto unlock_and_return_res;
11275 + pool->first_ip = req.addr;
11276 + pool->last_ip = req.addr2;
11277 + pool->nr_use = 0;
11278 + pool->nr_match = 0;
11279 + pool->members = newmembers;
11280 + write_unlock_bh(&pool->lock);
11282 + case IP_POOL_ADD_ADDR:
11283 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
11284 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
11285 + return copy_to_user(user, &req, sizeof(req));
11286 + case IP_POOL_DEL_ADDR:
11287 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
11288 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
11289 + return copy_to_user(user, &req, sizeof(req));
11291 + DP("ip_pool:getpool bad op %d\n", req.op);
11296 +unlock_and_return_res:
11298 + read_unlock_bh(&pool->lock);
11302 +static struct nf_sockopt_ops so_pool
11303 += { { NULL, NULL }, PF_INET,
11304 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
11305 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
11308 +MODULE_PARM(nr_pool, "i");
11310 +static int __init init(void)
11315 + if (nr_pool < 1) {
11316 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
11319 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
11321 + printk("ip_pool module init: out of memory for nr_pool %d\n",
11325 + for (i=0; i<nr_pool; i++) {
11326 + POOL[i].first_ip = 0;
11327 + POOL[i].last_ip = 0;
11328 + POOL[i].members = 0;
11329 + POOL[i].nr_use = 0;
11330 + POOL[i].nr_match = 0;
11331 + POOL[i].lock = RW_LOCK_UNLOCKED;
11333 + res = nf_register_sockopt(&so_pool);
11334 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
11342 +static void __exit fini(void)
11346 + DP("ip_pool:fini BYEBYE\n");
11347 + nf_unregister_sockopt(&so_pool);
11348 + for (i=0; i<nr_pool; i++) {
11349 + if (POOL[i].members) {
11350 + kfree(POOL[i].members);
11351 + POOL[i].members = 0;
11356 + DP("ip_pool:fini these are the famous last words\n");
11360 +module_init(init);
11361 +module_exit(fini);
11362 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
11363 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_queue.c 2003-11-26 21:46:12.000000000 +0100
11364 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_queue.c 2003-12-10 23:14:19.440999216 +0100
11365 @@ -417,6 +417,33 @@
11369 +ipq_set_vwmark(struct ipq_vwmark_msg *vmsg, unsigned int len)
11371 + struct ipq_queue_entry *entry;
11373 + if (vmsg->value > NF_MAX_VERDICT)
11376 + entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
11377 + if (entry == NULL)
11380 + int verdict = vmsg->value;
11382 + if (vmsg->data_len && vmsg->data_len == len)
11383 + if (ipq_mangle_ipv4((ipq_verdict_msg_t *)vmsg, entry) < 0)
11384 + verdict = NF_DROP;
11386 + /* set mark of associated skb */
11387 + entry->skb->nfmark = vmsg->nfmark;
11389 + ipq_issue_verdict(entry, verdict);
11396 ipq_receive_peer(struct ipq_peer_msg *pmsg,
11397 unsigned char type, unsigned int len)
11399 @@ -438,6 +465,14 @@
11400 status = ipq_set_verdict(&pmsg->msg.verdict,
11401 len - sizeof(*pmsg));
11403 + case IPQM_VWMARK:
11404 + if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
11405 + status = -EINVAL;
11407 + status = ipq_set_vwmark(&pmsg->msg.vwmark,
11408 + len - sizeof(*pmsg));
11414 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
11415 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_filter.c 2003-11-26 21:43:35.000000000 +0100
11416 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_filter.c 2003-12-10 23:13:24.664326536 +0100
11419 sizeof(struct ipt_entry),
11420 sizeof(struct ipt_standard),
11421 - 0, { 0, 0 }, { } },
11422 + 0, NULL, 0, { 0, 0 }, { } },
11423 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11424 -NF_ACCEPT - 1 } },
11428 sizeof(struct ipt_entry),
11429 sizeof(struct ipt_standard),
11430 - 0, { 0, 0 }, { } },
11431 + 0, NULL, 0, { 0, 0 }, { } },
11432 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11433 -NF_ACCEPT - 1 } },
11437 sizeof(struct ipt_entry),
11438 sizeof(struct ipt_standard),
11439 - 0, { 0, 0 }, { } },
11440 + 0, NULL, 0, { 0, 0 }, { } },
11441 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11446 sizeof(struct ipt_entry),
11447 sizeof(struct ipt_error),
11448 - 0, { 0, 0 }, { } },
11449 + 0, NULL, 0, { 0, 0 }, { } },
11450 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11453 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
11454 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_mangle.c 2003-11-26 21:45:28.000000000 +0100
11455 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_mangle.c 2003-12-10 23:13:24.665326384 +0100
11458 sizeof(struct ipt_entry),
11459 sizeof(struct ipt_standard),
11460 - 0, { 0, 0 }, { } },
11461 + 0, NULL, 0, { 0, 0 }, { } },
11462 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11463 -NF_ACCEPT - 1 } },
11467 sizeof(struct ipt_entry),
11468 sizeof(struct ipt_standard),
11469 - 0, { 0, 0 }, { } },
11470 + 0, NULL, 0, { 0, 0 }, { } },
11471 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11472 -NF_ACCEPT - 1 } },
11476 sizeof(struct ipt_entry),
11477 sizeof(struct ipt_standard),
11478 - 0, { 0, 0 }, { } },
11479 + 0, NULL, 0, { 0, 0 }, { } },
11480 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11481 -NF_ACCEPT - 1 } },
11485 sizeof(struct ipt_entry),
11486 sizeof(struct ipt_standard),
11487 - 0, { 0, 0 }, { } },
11488 + 0, NULL, 0, { 0, 0 }, { } },
11489 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11490 -NF_ACCEPT - 1 } },
11492 @@ -101,7 +101,7 @@
11494 sizeof(struct ipt_entry),
11495 sizeof(struct ipt_standard),
11496 - 0, { 0, 0 }, { } },
11497 + 0, NULL, 0, { 0, 0 }, { } },
11498 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11499 -NF_ACCEPT - 1 } },
11501 @@ -110,7 +110,7 @@
11503 sizeof(struct ipt_entry),
11504 sizeof(struct ipt_error),
11505 - 0, { 0, 0 }, { } },
11506 + 0, NULL, 0, { 0, 0 }, { } },
11507 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11510 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
11511 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_raw.c 1970-01-01 01:00:00.000000000 +0100
11512 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_raw.c 2003-12-10 23:13:24.665326384 +0100
11515 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
11517 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
11519 +#include <linux/module.h>
11520 +#include <linux/netfilter_ipv4/ip_tables.h>
11522 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
11524 +/* Standard entry. */
11525 +struct ipt_standard
11527 + struct ipt_entry entry;
11528 + struct ipt_standard_target target;
11531 +struct ipt_error_target
11533 + struct ipt_entry_target target;
11534 + char errorname[IPT_FUNCTION_MAXNAMELEN];
11539 + struct ipt_entry entry;
11540 + struct ipt_error_target target;
11545 + struct ipt_replace repl;
11546 + struct ipt_standard entries[2];
11547 + struct ipt_error term;
11548 +} initial_table __initdata
11549 += { { "raw", RAW_VALID_HOOKS, 3,
11550 + sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
11551 + { [NF_IP_PRE_ROUTING] 0,
11552 + [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11553 + { [NF_IP_PRE_ROUTING] 0,
11554 + [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11557 + /* PRE_ROUTING */
11558 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11560 + sizeof(struct ipt_entry),
11561 + sizeof(struct ipt_standard),
11562 + 0, NULL, 0, { 0, 0 }, { } },
11563 + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11564 + -NF_ACCEPT - 1 } },
11566 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11568 + sizeof(struct ipt_entry),
11569 + sizeof(struct ipt_standard),
11570 + 0, NULL, 0, { 0, 0 }, { } },
11571 + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11572 + -NF_ACCEPT - 1 } }
11575 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11577 + sizeof(struct ipt_entry),
11578 + sizeof(struct ipt_error),
11579 + 0, NULL, 0, { 0, 0 }, { } },
11580 + { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11587 +static struct ipt_table packet_raw = {
11589 + .table = &initial_table.repl,
11590 + .valid_hooks = RAW_VALID_HOOKS,
11591 + .lock = RW_LOCK_UNLOCKED,
11592 + .me = THIS_MODULE,
11595 +/* The work comes in here from netfilter.c. */
11596 +static unsigned int
11597 +ipt_hook(unsigned int hook,
11598 + struct sk_buff **pskb,
11599 + const struct net_device *in,
11600 + const struct net_device *out,
11601 + int (*okfn)(struct sk_buff *))
11603 + return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
11606 +/* 'raw' is the very first table. */
11607 +static struct nf_hook_ops ipt_ops[] = {
11608 + { /* PRE_ROUTING hook */
11609 + .hook = ipt_hook,
11610 + .owner = THIS_MODULE,
11612 + .hooknum = NF_IP_PRE_ROUTING,
11613 + .priority = NF_IP_PRI_RAW,
11615 + { /* LOCAL_OUT hook */
11616 + .hook = ipt_hook,
11617 + .owner = THIS_MODULE,
11619 + .hooknum = NF_IP_LOCAL_OUT,
11620 + .priority = NF_IP_PRI_RAW,
11624 +static int __init init(void)
11628 + /* Register table */
11629 + ret = ipt_register_table(&packet_raw);
11633 + /* Register hooks */
11634 + ret = nf_register_hook(&ipt_ops[0]);
11636 + goto cleanup_table;
11638 + ret = nf_register_hook(&ipt_ops[1]);
11640 + goto cleanup_hook0;
11645 + nf_unregister_hook(&ipt_ops[0]);
11647 + ipt_unregister_table(&packet_raw);
11652 +static void __exit fini(void)
11656 + for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
11657 + nf_unregister_hook(&ipt_ops[i]);
11659 + ipt_unregister_table(&packet_raw);
11662 +module_init(init);
11663 +module_exit(fini);
11664 +MODULE_LICENSE("GPL");
11665 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11666 +MODULE_DESCRIPTION("IPv4 raw table");
11667 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
11668 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_tables.c 2003-11-26 21:43:25.000000000 +0100
11669 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_tables.c 2003-12-10 23:14:00.453885696 +0100
11671 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11672 * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
11674 + * 6 Mar 2002 Robert Olsson <robban@robtex.com>
11675 + * 17 Apr 2003 Chris Wilson <chris@netservers.co.uk>
11676 + * - mark_source_chains speedup for complex chains
11678 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
11679 * - increase module usage count as soon as we have rules inside
11682 #include <linux/config.h>
11683 #include <linux/cache.h>
11684 #include <linux/skbuff.h>
11685 +#include <linux/socket.h>
11686 #include <linux/kmod.h>
11687 #include <linux/vmalloc.h>
11688 #include <linux/netdevice.h>
11690 #include <asm/semaphore.h>
11691 #include <linux/proc_fs.h>
11693 +#include <linux/netfilter.h>
11694 #include <linux/netfilter_ipv4/ip_tables.h>
11696 +static const char *hooknames[] = {
11697 + [NF_IP_PRE_ROUTING] "PREROUTING",
11698 + [NF_IP_LOCAL_IN] "INPUT",
11699 + [NF_IP_FORWARD] "FORWARD",
11700 + [NF_IP_LOCAL_OUT] "OUTPUT",
11701 + [NF_IP_POST_ROUTING] "POSTROUTING",
11704 MODULE_LICENSE("GPL");
11705 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11706 MODULE_DESCRIPTION("IPv4 packet filter");
11707 @@ -322,6 +336,12 @@
11709 t = ipt_get_target(e);
11710 IP_NF_ASSERT(t->u.kernel.target);
11712 + /* The packet traced and the rule isn't an unconditional return/END. */
11713 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
11714 + nf_log_packet(AF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11715 + table->name, e->chainname, e->rulenum);
11717 /* Standard target? */
11718 if (!t->u.kernel.target->target) {
11720 @@ -474,6 +494,29 @@
11721 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
11725 +find_error_target(struct ipt_entry *s,
11726 + struct ipt_entry *e,
11727 + char **chainname)
11729 + struct ipt_entry_target *t;
11730 + static struct ipt_entry *found = NULL;
11735 + t = ipt_get_target(found);
11736 + if (strcmp(t->u.user.name,
11737 + IPT_ERROR_TARGET) == 0) {
11738 + *chainname = t->data;
11747 /* All zeroes == unconditional rule. */
11749 unconditional(const struct ipt_ip *ip)
11750 @@ -493,6 +536,11 @@
11751 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
11754 + char *chainname = NULL;
11755 + u_int32_t rulenum;
11757 + /* keep track of where we have been: */
11758 + unsigned char *been = vmalloc(newinfo->size);
11760 /* No recursion; use packet counter to save back ptrs (reset
11761 to 0 as we leave), and comefrom to save source hook bitmask */
11762 @@ -506,6 +554,9 @@
11764 /* Set initial back pointer. */
11765 e->counters.pcnt = pos;
11766 + memset(been, 0, newinfo->size);
11768 + chainname = (char *) hooknames[hook];
11771 struct ipt_standard_target *t
11772 @@ -514,10 +565,13 @@
11773 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
11774 printk("iptables: loop hook %u pos %u %08X.\n",
11775 hook, pos, e->comefrom);
11780 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
11781 + e->rulenum = rulenum++;
11782 + e->chainname = chainname;
11784 /* Unconditional return/END. */
11785 if (e->target_offset == sizeof(struct ipt_entry)
11786 @@ -527,6 +581,10 @@
11787 && unconditional(&e->ip)) {
11788 unsigned int oldpos, size;
11790 + /* Set unconditional rulenum to zero. */
11792 + e->counters.bcnt = 0;
11794 /* Return: backtrack through the last
11797 @@ -552,6 +610,11 @@
11798 (newinfo->entries + pos);
11799 } while (oldpos == pos + e->next_offset);
11801 + /* Restore chainname, rulenum. */
11802 + chainname = e->chainname;
11803 + rulenum = e->counters.bcnt;
11804 + e->counters.bcnt = 0;
11806 /* Move along one */
11807 size = e->next_offset;
11808 e = (struct ipt_entry *)
11809 @@ -561,12 +624,27 @@
11811 int newpos = t->verdict;
11813 - if (strcmp(t->target.u.user.name,
11814 + if ( (pos < 0 || pos >= newinfo->size
11816 + && strcmp(t->target.u.user.name,
11817 IPT_STANDARD_TARGET) == 0
11819 /* This a jump; chase it. */
11820 + if (pos >= 0 && pos < newinfo->size)
11822 duprintf("Jump rule %u -> %u\n",
11824 + e->counters.bcnt = rulenum++;
11826 + e = (struct ipt_entry *)
11827 + (newinfo->entries + newpos);
11828 + if (IPT_ENTRY_ITERATE(newinfo->entries,
11830 + find_error_target,
11831 + e, &chainname) == 0) {
11832 + printk("ip_tables: table screwed up!\n");
11836 /* ... this is a fallthru */
11837 newpos = pos + e->next_offset;
11838 @@ -580,6 +658,7 @@
11840 duprintf("Finished chain %u\n", hook);
11846 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
11847 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
11848 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_addrtype.c 2003-12-10 23:13:51.092308872 +0100
11851 + * iptables module to match inet_addr_type() of an ip.
11854 +#include <linux/module.h>
11855 +#include <linux/skbuff.h>
11856 +#include <linux/netdevice.h>
11857 +#include <net/route.h>
11859 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
11860 +#include <linux/netfilter_ipv4/ip_tables.h>
11862 +MODULE_LICENSE("GPL");
11864 +static inline int match_type(u_int32_t addr, u_int16_t mask)
11866 + return !!(mask & (1 << inet_addr_type(addr)));
11869 +static int match(const struct sk_buff *skb, const struct net_device *in,
11870 + const struct net_device *out, const void *matchinfo,
11871 + int offset, const void *hdr, u_int16_t datalen,
11874 + const struct ipt_addrtype_info *info = matchinfo;
11875 + const struct iphdr *iph = skb->nh.iph;
11878 + if (info->source)
11879 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
11881 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
11886 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
11887 + void *matchinfo, unsigned int matchsize,
11888 + unsigned int hook_mask)
11890 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
11891 + printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
11892 + matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
11899 +static struct ipt_match addrtype_match = { { NULL, NULL }, "addrtype", &match,
11900 + &checkentry, NULL, THIS_MODULE };
11902 +static int __init init(void)
11904 + return ipt_register_match(&addrtype_match);
11907 +static void __exit fini(void)
11909 + ipt_unregister_match(&addrtype_match);
11913 +module_init(init);
11914 +module_exit(fini);
11915 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
11916 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_condition.c 1970-01-01 01:00:00.000000000 +0100
11917 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_condition.c 2003-12-10 23:13:53.356964592 +0100
11919 +/*-------------------------------------------*\
11920 +| Netfilter Condition Module |
11922 +| Description: This module allows firewall |
11923 +| rules to match using condition variables |
11924 +| stored in /proc files. |
11926 +| Author: Stephane Ouellette 2002-10-22 |
11927 +| <ouellettes@videotron.ca> |
11930 +| 2003-02-10 Second version with improved |
11931 +| locking and simplified code. |
11933 +| This software is distributed under the |
11934 +| terms of the GNU GPL. |
11935 +\*-------------------------------------------*/
11937 +#include<linux/module.h>
11938 +#include<linux/proc_fs.h>
11939 +#include<linux/spinlock.h>
11940 +#include<linux/string.h>
11941 +#include<asm/atomic.h>
11942 +#include<linux/netfilter_ipv4/ip_tables.h>
11943 +#include<linux/netfilter_ipv4/ipt_condition.h>
11946 +#ifndef CONFIG_PROC_FS
11947 +#error "Proc file system support is required for this module"
11951 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
11952 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
11953 +MODULE_LICENSE("GPL");
11956 +struct condition_variable {
11957 + struct condition_variable *next;
11958 + struct proc_dir_entry *status_proc;
11959 + atomic_t refcount;
11960 + int enabled; /* TRUE == 1, FALSE == 0 */
11964 +static rwlock_t list_lock;
11965 +static struct condition_variable *head = NULL;
11966 +static struct proc_dir_entry *proc_net_condition = NULL;
11970 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
11971 + int length, int *eof, void *data)
11973 + struct condition_variable *var =
11974 + (struct condition_variable *) data;
11976 + if (offset == 0) {
11978 + buffer[0] = (var->enabled) ? '1' : '0';
11979 + buffer[1] = '\n';
11989 +ipt_condition_write_info(struct file *file, const char *buffer,
11990 + unsigned long length, void *data)
11992 + struct condition_variable *var =
11993 + (struct condition_variable *) data;
11996 + /* Match only on the first character */
11997 + switch (buffer[0]) {
11999 + var->enabled = 0;
12002 + var->enabled = 1;
12006 + return (int) length;
12011 +match(const struct sk_buff *skb, const struct net_device *in,
12012 + const struct net_device *out, const void *matchinfo, int offset,
12013 + const void *hdr, u_int16_t datalen, int *hotdrop)
12015 + const struct condition_info *info =
12016 + (const struct condition_info *) matchinfo;
12017 + struct condition_variable *var;
12018 + int condition_status = 0;
12020 + read_lock(&list_lock);
12022 + for (var = head; var; var = var->next) {
12023 + if (strcmp(info->name, var->status_proc->name) == 0) {
12024 + condition_status = var->enabled;
12029 + read_unlock(&list_lock);
12031 + return condition_status ^ info->invert;
12037 +checkentry(const char *tablename, const struct ipt_ip *ip,
12038 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
12040 + struct condition_info *info = (struct condition_info *) matchinfo;
12041 + struct condition_variable *var, *newvar;
12043 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12046 + /* The first step is to check if the condition variable already exists. */
12047 + /* Here, a read lock is sufficient because we won't change the list */
12048 + read_lock(&list_lock);
12050 + for (var = head; var; var = var->next) {
12051 + if (strcmp(info->name, var->status_proc->name) == 0) {
12052 + atomic_inc(&var->refcount);
12053 + read_unlock(&list_lock);
12058 + read_unlock(&list_lock);
12060 + /* At this point, we need to allocate a new condition variable */
12061 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
12066 + /* Create the condition variable's proc file entry */
12067 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
12069 + if (!newvar->status_proc) {
12071 + * There are two possibilities:
12072 + * 1- Another condition variable with the same name has been created, which is valid.
12073 + * 2- There was a memory allocation error.
12076 + read_lock(&list_lock);
12078 + for (var = head; var; var = var->next) {
12079 + if (strcmp(info->name, var->status_proc->name) == 0) {
12080 + atomic_inc(&var->refcount);
12081 + read_unlock(&list_lock);
12086 + read_unlock(&list_lock);
12090 + atomic_set(&newvar->refcount, 1);
12091 + newvar->enabled = 0;
12092 + newvar->status_proc->owner = THIS_MODULE;
12093 + newvar->status_proc->data = newvar;
12095 + newvar->status_proc->read_proc = ipt_condition_read_info;
12096 + newvar->status_proc->write_proc = ipt_condition_write_info;
12098 + write_lock(&list_lock);
12100 + newvar->next = head;
12103 + write_unlock(&list_lock);
12110 +destroy(void *matchinfo, unsigned int matchsize)
12112 + struct condition_info *info = (struct condition_info *) matchinfo;
12113 + struct condition_variable *var, *prev = NULL;
12115 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12118 + write_lock(&list_lock);
12120 + for (var = head; var && strcmp(info->name, var->status_proc->name);
12121 + prev = var, var = var->next);
12123 + if (var && atomic_dec_and_test(&var->refcount)) {
12125 + prev->next = var->next;
12127 + head = var->next;
12129 + write_unlock(&list_lock);
12130 + remove_proc_entry(var->status_proc->name, proc_net_condition);
12133 + write_unlock(&list_lock);
12137 +static struct ipt_match condition_match = {
12138 + .name = "condition",
12140 + .checkentry = &checkentry,
12141 + .destroy = &destroy,
12142 + .me = THIS_MODULE
12151 + rwlock_init(&list_lock);
12152 + proc_net_condition = proc_mkdir("ipt_condition", proc_net);
12154 + if (proc_net_condition) {
12155 + errorcode = ipt_register_match(&condition_match);
12158 + remove_proc_entry("ipt_condition", proc_net);
12160 + errorcode = -EACCES;
12162 + return errorcode;
12166 +static void __exit
12169 + ipt_unregister_match(&condition_match);
12170 + remove_proc_entry("ipt_condition", proc_net);
12173 +module_init(init);
12174 +module_exit(fini);
12175 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
12176 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
12177 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connlimit.c 2003-12-10 23:13:26.811000192 +0100
12180 + * netfilter module to limit the number of parallel tcp
12181 + * connections per IP address.
12182 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
12183 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
12184 + * only ignore TIME_WAIT or gone connections
12188 + * Kernel module to match connection tracking information.
12189 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
12191 +#include <linux/module.h>
12192 +#include <linux/skbuff.h>
12193 +#include <linux/list.h>
12194 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12195 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
12196 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
12197 +#include <linux/netfilter_ipv4/ip_tables.h>
12198 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
12202 +MODULE_LICENSE("GPL");
12204 +/* we'll save the tuples of all connections we care about */
12205 +struct ipt_connlimit_conn
12207 + struct list_head list;
12208 + struct ip_conntrack_tuple tuple;
12211 +struct ipt_connlimit_data {
12213 + struct list_head iphash[256];
12216 +static int ipt_iphash(u_int32_t addr)
12220 + hash = addr & 0xff;
12221 + hash ^= (addr >> 8) & 0xff;
12222 + hash ^= (addr >> 16) & 0xff;
12223 + hash ^= (addr >> 24) & 0xff;
12227 +static int count_them(struct ipt_connlimit_data *data,
12228 + u_int32_t addr, u_int32_t mask,
12229 + struct ip_conntrack *ct)
12232 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
12233 + "fin_wait", "time_wait", "close", "close_wait",
12234 + "last_ack", "listen" };
12236 + int addit = 1, matches = 0;
12237 + struct ip_conntrack_tuple tuple;
12238 + struct ip_conntrack_tuple_hash *found;
12239 + struct ipt_connlimit_conn *conn;
12240 + struct list_head *hash,*lh;
12242 + spin_lock(&data->lock);
12243 + tuple = ct->tuplehash[0].tuple;
12244 + hash = &data->iphash[ipt_iphash(addr & mask)];
12246 + /* check the saved connections */
12247 + for (lh = hash->next; lh != hash; lh = lh->next) {
12248 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
12249 + found = ip_conntrack_find_get(&conn->tuple,ct);
12250 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
12252 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
12253 + /* Just to be sure we have it only once in the list.
12254 + We should'nt see tuples twice unless someone hooks this
12255 + into a table without "-p tcp --syn" */
12259 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
12260 + ipt_iphash(addr & mask),
12261 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
12262 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
12263 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
12265 + if (NULL == found) {
12266 + /* this one is gone */
12268 + list_del(lh->next);
12272 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
12273 + /* we don't care about connections which are
12274 + closed already -> ditch it */
12276 + list_del(lh->next);
12278 + nf_conntrack_put(&found->ctrack->infos[0]);
12281 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
12282 + /* same source IP address -> be counted! */
12285 + nf_conntrack_put(&found->ctrack->infos[0]);
12288 + /* save the new connection in our list */
12290 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
12291 + ipt_iphash(addr & mask),
12292 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
12293 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
12295 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
12296 + if (NULL == conn)
12298 + memset(conn,0,sizeof(*conn));
12299 + INIT_LIST_HEAD(&conn->list);
12300 + conn->tuple = tuple;
12301 + list_add(&conn->list,hash);
12304 + spin_unlock(&data->lock);
12309 +match(const struct sk_buff *skb,
12310 + const struct net_device *in,
12311 + const struct net_device *out,
12312 + const void *matchinfo,
12315 + u_int16_t datalen,
12318 + const struct ipt_connlimit_info *info = matchinfo;
12319 + int connections, match;
12320 + struct ip_conntrack *ct;
12321 + enum ip_conntrack_info ctinfo;
12323 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12324 + if (NULL == ct) {
12325 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
12329 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
12330 + if (-1 == connections) {
12331 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
12332 + *hotdrop = 1; /* let's free some memory :-) */
12335 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
12337 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
12338 + "connections=%d limit=%d match=%s\n",
12339 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
12340 + connections, info->limit, match ? "yes" : "no");
12346 +static int check(const char *tablename,
12347 + const struct ipt_ip *ip,
12349 + unsigned int matchsize,
12350 + unsigned int hook_mask)
12352 + struct ipt_connlimit_info *info = matchinfo;
12355 + /* verify size */
12356 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
12359 + /* refuse anything but tcp */
12360 + if (ip->proto != IPPROTO_TCP)
12363 + /* init private data */
12364 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
12365 + spin_lock_init(&(info->data->lock));
12366 + for (i = 0; i < 256; i++)
12367 + INIT_LIST_HEAD(&(info->data->iphash[i]));
12372 +static void destroy(void *matchinfo, unsigned int matchinfosize)
12374 + struct ipt_connlimit_info *info = matchinfo;
12375 + struct ipt_connlimit_conn *conn;
12376 + struct list_head *hash;
12380 + for (i = 0; i < 256; i++) {
12381 + hash = &(info->data->iphash[i]);
12382 + while (hash != hash->next) {
12383 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
12384 + list_del(hash->next);
12388 + kfree(info->data);
12391 +static struct ipt_match connlimit_match
12392 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
12394 +static int __init init(void)
12396 + /* NULL if ip_conntrack not a module */
12397 + if (ip_conntrack_module)
12398 + __MOD_INC_USE_COUNT(ip_conntrack_module);
12399 + return ipt_register_match(&connlimit_match);
12402 +static void __exit fini(void)
12404 + ipt_unregister_match(&connlimit_match);
12405 + if (ip_conntrack_module)
12406 + __MOD_DEC_USE_COUNT(ip_conntrack_module);
12409 +module_init(init);
12410 +module_exit(fini);
12411 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
12412 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
12413 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connmark.c 2003-12-10 23:13:54.582778240 +0100
12415 +/* Kernel module to match connection mark values. */
12416 +#include <linux/module.h>
12417 +#include <linux/skbuff.h>
12419 +#include <linux/netfilter_ipv4/ip_tables.h>
12420 +#include <linux/netfilter_ipv4/ipt_connmark.h>
12421 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12424 +match(const struct sk_buff *skb,
12425 + const struct net_device *in,
12426 + const struct net_device *out,
12427 + const void *matchinfo,
12430 + u_int16_t datalen,
12433 + const struct ipt_connmark_info *info = matchinfo;
12434 + enum ip_conntrack_info ctinfo;
12435 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12439 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
12443 +checkentry(const char *tablename,
12444 + const struct ipt_ip *ip,
12446 + unsigned int matchsize,
12447 + unsigned int hook_mask)
12449 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
12455 +static struct ipt_match connmark_match
12456 += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE };
12458 +static int __init init(void)
12460 + return ipt_register_match(&connmark_match);
12463 +static void __exit fini(void)
12465 + ipt_unregister_match(&connmark_match);
12468 +module_init(init);
12469 +module_exit(fini);
12470 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
12471 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
12472 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_CONNMARK.c 2003-12-10 23:13:54.583778088 +0100
12474 +/* This is a module which is used for setting/remembering the mark field of
12475 + * an connection, or optionally restore it to the skb
12477 +#include <linux/module.h>
12478 +#include <linux/skbuff.h>
12479 +#include <linux/ip.h>
12480 +#include <net/checksum.h>
12482 +#include <linux/netfilter_ipv4/ip_tables.h>
12483 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
12484 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12486 +static unsigned int
12487 +target(struct sk_buff **pskb,
12488 + unsigned int hooknum,
12489 + const struct net_device *in,
12490 + const struct net_device *out,
12491 + const void *targinfo,
12494 + const struct ipt_connmark_target_info *markinfo = targinfo;
12496 + enum ip_conntrack_info ctinfo;
12497 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
12499 + switch(markinfo->mode) {
12500 + case IPT_CONNMARK_SET:
12501 + ct->mark = markinfo->mark;
12503 + case IPT_CONNMARK_SAVE:
12504 + ct->mark = (*pskb)->nfmark;
12506 + case IPT_CONNMARK_RESTORE:
12507 + if (ct->mark != (*pskb)->nfmark) {
12508 + (*pskb)->nfmark = ct->mark;
12509 + (*pskb)->nfcache |= NFC_ALTERED;
12515 + return IPT_CONTINUE;
12519 +checkentry(const char *tablename,
12520 + const struct ipt_entry *e,
12522 + unsigned int targinfosize,
12523 + unsigned int hook_mask)
12525 + struct ipt_connmark_target_info *matchinfo = targinfo;
12526 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
12527 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
12529 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
12533 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
12534 + if (strcmp(tablename, "mangle") != 0) {
12535 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
12543 +static struct ipt_target ipt_connmark_reg
12544 += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE };
12546 +static int __init init(void)
12548 + if (ipt_register_target(&ipt_connmark_reg))
12554 +static void __exit fini(void)
12556 + ipt_unregister_target(&ipt_connmark_reg);
12559 +module_init(init);
12560 +module_exit(fini);
12561 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
12562 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_conntrack.c 2003-11-26 21:45:34.000000000 +0100
12563 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_conntrack.c 2003-12-10 23:13:24.664326536 +0100
12566 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
12569 + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
12570 + statebit = IPT_CONNTRACK_STATE_UNTRACKED;
12572 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
12574 statebit = IPT_CONNTRACK_STATE_INVALID;
12575 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
12576 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
12577 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_dstlimit.c 2003-12-10 23:13:27.869839224 +0100
12579 +/* iptables match extension to limit the number of packets per second
12580 + * seperately for each destination.
12582 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
12584 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
12586 + * based on ipt_limit.c by:
12587 + * JƩrƓme de Vivie <devivie@info.enserb.u-bordeaux.fr>
12588 + * HervƩ Eychenne <eychenne@info.enserb.u-bordeaux.fr>
12589 + * Rusty Russell <rusty@rustcorp.com.au>
12591 + * The general idea is to create a hash table for every dstip and have a
12592 + * seperate limit counter per tuple. This way you can do something like 'limit
12593 + * the number of syn packets for each of my internal addresses.
12595 + * Ideally this would just be implemented as a general 'hash' match, which would
12596 + * allow us to attach any iptables target to it's hash buckets. But this is
12597 + * not possible in the current iptables architecture. As always, pkttables for
12598 + * 2.7.x will help ;)
12600 +#include <linux/module.h>
12601 +#include <linux/skbuff.h>
12602 +#include <linux/spinlock.h>
12603 +#include <linux/random.h>
12604 +#include <linux/jhash.h>
12605 +#include <linux/slab.h>
12606 +#include <linux/vmalloc.h>
12607 +#include <linux/tcp.h>
12608 +#include <linux/udp.h>
12609 +#include <linux/proc_fs.h>
12610 +#include <linux/seq_file.h>
12612 +#define ASSERT_READ_LOCK(x)
12613 +#define ASSERT_WRITE_LOCK(x)
12614 +#include <linux/netfilter_ipv4/lockhelp.h>
12615 +#include <linux/netfilter_ipv4/listhelp.h>
12617 +#include <linux/netfilter_ipv4/ip_tables.h>
12618 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
12620 +/* FIXME: this is just for IP_NF_ASSERRT */
12621 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12623 +#define MS2JIFFIES(x) ((x*HZ)/1000)
12625 +MODULE_LICENSE("GPL");
12626 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
12627 +MODULE_DESCRIPTION("iptables match for limiting per destination");
12629 +/* need to declare this at the top */
12630 +static struct proc_dir_entry *dstlimit_procdir;
12631 +static struct file_operations dl_file_ops;
12633 +/* hash table crap */
12635 +struct dsthash_dst {
12636 + u_int32_t src_ip;
12637 + u_int32_t dst_ip;
12641 +struct dsthash_ent {
12642 + /* static / read-only parts in the beginning */
12643 + struct list_head list;
12644 + struct dsthash_dst dst;
12646 + /* modified structure members in the end */
12647 + unsigned long expires; /* precalculated expiry time */
12649 + unsigned long prev; /* last modification */
12650 + u_int32_t credit;
12651 + u_int32_t credit_cap, cost;
12655 +struct ipt_dstlimit_htable {
12656 + struct ipt_dstlimit_info *minfo; /* public structure */
12658 + /* used internally */
12659 + spinlock_t lock; /* lock for list_head */
12660 + u_int32_t rnd; /* random seed for hash */
12661 + struct timer_list timer; /* timer for gc */
12662 + atomic_t count; /* number entries in table */
12664 + /* seq_file stuff */
12665 + struct proc_dir_entry *pde;
12667 + struct list_head hash[0]; /* hashtable itself */
12670 +static kmem_cache_t *dstlimit_cachep;
12672 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
12674 + return (ent->dst.dst_ip == b->dst_ip
12675 + && ent->dst.port == b->port
12676 + && ent->dst.src_ip == b->src_ip);
12679 +static inline u_int32_t
12680 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
12682 + return (jhash_3words(dst->dst_ip, dst->port,
12683 + dst->src_ip, ht->rnd) % ht->minfo->size);
12686 +static inline struct dsthash_ent *
12687 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12689 + struct dsthash_ent *ent;
12690 + u_int32_t hash = hash_dst(ht, dst);
12691 + MUST_BE_LOCKED(&ht->lock);
12692 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
12696 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
12697 +static struct dsthash_ent *
12698 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12700 + struct dsthash_ent *ent;
12702 + /* initialize hash with random val at the time we allocate
12703 + * the first hashtable entry */
12705 + get_random_bytes(&ht->rnd, 4);
12707 + if (ht->minfo->max &&
12708 + atomic_read(&ht->count) >= ht->minfo->max) {
12709 + /* FIXME: do something. question is what.. */
12710 + if (net_ratelimit())
12711 + printk("max count of %u reached\n", ht->minfo->max);
12715 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
12717 + if (net_ratelimit())
12718 + printk("Can't allocate dsthash_ent\n");
12722 + atomic_inc(&ht->count);
12724 + ent->dst.dst_ip = dst->dst_ip;
12725 + ent->dst.port = dst->port;
12726 + ent->dst.src_ip = dst->src_ip;
12728 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
12733 +static inline void
12734 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
12736 + MUST_BE_LOCKED(&ht->lock);
12738 + list_del(&ent->list);
12739 + kmem_cache_free(dstlimit_cachep, ent);
12740 + atomic_dec(&ht->count);
12743 +static void htable_gc(unsigned long htlong);
12745 +static int htable_create(struct ipt_dstlimit_info *minfo)
12748 + struct ipt_dstlimit_htable *hinfo;
12750 + if (!minfo->size) {
12751 + minfo->size = (((num_physpages << PAGE_SHIFT) / 16384)
12752 + / sizeof(struct list_head));
12753 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
12754 + minfo->size = 8192;
12755 + if (minfo->size < 16)
12756 + minfo->size = 16;
12759 + minfo->max = 8 * minfo->size;
12760 + else if (minfo->max < minfo->size)
12761 + minfo->max = minfo->size;
12763 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
12764 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
12765 + + (sizeof(struct list_head) * minfo->size));
12767 + printk(KERN_ERR "Unable to create ipt_dstlimit hash\n");
12771 + for (i = 0; i < minfo->size; i++)
12772 + INIT_LIST_HEAD(&hinfo->hash[i]);
12774 + minfo->hinfo = hinfo;
12776 + hinfo->minfo = minfo;
12777 + atomic_set(&hinfo->count, 0);
12780 + hinfo->lock = SPIN_LOCK_UNLOCKED;
12782 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
12783 + if (!hinfo->pde) {
12787 + hinfo->pde->proc_fops = &dl_file_ops;
12788 + hinfo->pde->data = hinfo;
12790 + init_timer(&hinfo->timer);
12791 + hinfo->timer.expires = jiffies + MS2JIFFIES(minfo->gc_interval);
12792 + hinfo->timer.data = (unsigned long )hinfo;
12793 + hinfo->timer.function = htable_gc;
12794 + add_timer(&hinfo->timer);
12799 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12804 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12806 + return (jiffies >= he->expires);
12809 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
12810 + int (*select)(struct ipt_dstlimit_htable *ht,
12811 + struct dsthash_ent *he))
12815 + IP_NF_ASSERT(ht->minfo->size && ht->minfo->max);
12817 + /* lock hash table and iterate over it */
12818 + LOCK_BH(&ht->lock);
12819 + for (i = 0; i < ht->minfo->size; i++) {
12820 + struct dsthash_ent *dh, *n;
12821 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
12822 + if ((*select)(ht, dh))
12823 + __dsthash_free(ht, dh);
12826 + UNLOCK_BH(&ht->lock);
12829 +/* hash table garbage collector, run by timer */
12830 +static void htable_gc(unsigned long htlong)
12832 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
12834 + htable_selective_cleanup(ht, select_gc);
12836 + /* re-add the timer accordingly */
12837 + ht->timer.expires = jiffies + MS2JIFFIES(ht->minfo->gc_interval);
12838 + add_timer(&ht->timer);
12841 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
12842 + * see net/sched/sch_tbf.c in the linux source tree
12845 +/* Rusty: This is my (non-mathematically-inclined) understanding of
12846 + this algorithm. The `average rate' in jiffies becomes your initial
12847 + amount of credit `credit' and the most credit you can ever have
12848 + `credit_cap'. The `peak rate' becomes the cost of passing the
12851 + `prev' tracks the last packet hit: you gain one credit per jiffy.
12852 + If you get credit balance more than this, the extra credit is
12853 + discarded. Every time the match passes, you lose `cost' credits;
12854 + if you don't have that many, the test fails.
12856 + See Alexey's formal explanation in net/sched/sch_tbf.c.
12858 + To get the maximum range, we multiply by this factor (ie. you get N
12859 + credits per jiffy). We want to allow a rate as low as 1 per day
12860 + (slowest userspace tool allows), which means
12861 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
12863 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
12865 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
12866 + * us the power of 2 below the theoretical max, so GCC simply does a
12868 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
12869 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
12870 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
12871 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
12872 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
12873 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
12875 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
12877 +/* Precision saver. */
12878 +static inline u_int32_t
12879 +user2credits(u_int32_t user)
12881 + /* If multiplying would overflow... */
12882 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
12883 + /* Divide first. */
12884 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
12886 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
12889 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
12891 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
12892 + * CREDITS_PER_JIFFY;
12893 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
12894 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
12898 +dstlimit_match(const struct sk_buff *skb,
12899 + const struct net_device *in,
12900 + const struct net_device *out,
12901 + const void *matchinfo,
12904 + u_int16_t datalen,
12907 + struct ipt_dstlimit_info *r =
12908 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
12909 + unsigned long now = jiffies;
12910 + struct dsthash_ent *dh;
12911 + struct dsthash_dst dst;
12913 + memset(&dst, 0, sizeof(dst));
12915 + /* dest ip is always in hash */
12916 + dst.dst_ip = skb->nh.iph->daddr;
12918 + /* source ip only if respective hashmode, otherwise set to
12920 + if (r->mode & IPT_DSTLIMIT_HASH_SIP)
12921 + dst.src_ip = skb->nh.iph->saddr;
12923 + /* dest port only if respective mode */
12924 + if (r->mode & IPT_DSTLIMIT_HASH_DPT) {
12925 + switch (skb->nh.iph->protocol) {
12926 + struct tcphdr *th;
12927 + struct udphdr *uh;
12928 + case IPPROTO_TCP:
12929 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12930 + dst.port = th->dest;
12932 + case IPPROTO_UDP:
12933 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12934 + dst.port = uh->dest;
12941 + LOCK_BH(&r->hinfo->lock);
12942 + dh = __dsthash_find(r->hinfo, &dst);
12944 + dh = __dsthash_alloc_init(r->hinfo, &dst);
12947 + /* enomem... don't match == DROP */
12948 + if (net_ratelimit())
12949 + printk("%s: ENOMEM\n", __FUNCTION__);
12950 + UNLOCK_BH(&r->hinfo->lock);
12954 + dh->expires = jiffies + MS2JIFFIES(r->expire);
12956 + dh->rateinfo.prev = jiffies;
12957 + dh->rateinfo.credit = user2credits(r->avg * r->burst);
12958 + dh->rateinfo.credit_cap = user2credits(r->avg * r->burst);
12959 + dh->rateinfo.cost = user2credits(r->avg);
12961 + UNLOCK_BH(&r->hinfo->lock);
12965 + /* update expiration timeout */
12966 + dh->expires = now + MS2JIFFIES(r->expire);
12968 + rateinfo_recalc(dh, now);
12969 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
12970 + /* We're underlimit. */
12971 + dh->rateinfo.credit -= dh->rateinfo.cost;
12972 + UNLOCK_BH(&r->hinfo->lock);
12976 + UNLOCK_BH(&r->hinfo->lock);
12978 + /* default case: we're overlimit, thus don't match */
12983 +dstlimit_checkentry(const char *tablename,
12984 + const struct ipt_ip *ip,
12986 + unsigned int matchsize,
12987 + unsigned int hook_mask)
12989 + struct ipt_dstlimit_info *r = matchinfo;
12991 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
12994 + /* Check for overflow. */
12995 + if (r->burst == 0
12996 + || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
12997 + printk("Overflow in ipt_dstlimit, try lower: %u/%u\n",
12998 + r->avg, r->burst);
13003 + || r->mode > (IPT_DSTLIMIT_HASH_DPT
13004 + |IPT_DSTLIMIT_HASH_DIP
13005 + |IPT_DSTLIMIT_HASH_SIP))
13008 + if (!r->gc_interval)
13014 + if (htable_create(r) != 0) {
13015 + printk("Unable to create dstlimit htable\n");
13019 + /* Ugly hack: For SMP, we only want to use one set */
13026 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
13028 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
13032 + /* remove timer, if it is pending */
13033 + if (timer_pending(&r->hinfo->timer))
13034 + del_timer(&r->hinfo->timer);
13036 + /* remove proc entry */
13037 + remove_proc_entry(r->name, dstlimit_procdir);
13039 + htable_selective_cleanup(r->hinfo, select_all);
13040 + vfree(&r->hinfo);
13043 +static struct ipt_match ipt_dstlimit = {
13044 + .list = { .prev = NULL, .next = NULL },
13045 + .name = "dstlimit",
13046 + .match = dstlimit_match,
13047 + .checkentry = dstlimit_checkentry,
13048 + .destroy = dstlimit_destroy,
13049 + .me = THIS_MODULE
13054 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
13056 + struct proc_dir_entry *pde = s->private;
13057 + struct ipt_dstlimit_htable *htable = pde->data;
13058 + unsigned int *bucket;
13060 + LOCK_BH(&htable->lock);
13061 + if (*pos >= htable->minfo->size)
13064 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
13066 + return ERR_PTR(-ENOMEM);
13072 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
13074 + struct proc_dir_entry *pde = s->private;
13075 + struct ipt_dstlimit_htable *htable = pde->data;
13076 + unsigned int *bucket = (unsigned int *)v;
13078 + *pos = ++(*bucket);
13079 + if (*pos >= htable->minfo->size) {
13086 +static void dl_seq_stop(struct seq_file *s, void *v)
13088 + struct proc_dir_entry *pde = s->private;
13089 + struct ipt_dstlimit_htable *htable = pde->data;
13091 + UNLOCK_BH(&htable->lock);
13094 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
13096 + /* recalculate to show accurate numbers */
13097 + rateinfo_recalc(ent, jiffies);
13099 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
13100 + (ent->expires - jiffies)/HZ,
13101 + NIPQUAD(ent->dst.src_ip),
13102 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
13103 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
13104 + ent->rateinfo.cost);
13107 +static int dl_seq_show(struct seq_file *s, void *v)
13109 + struct proc_dir_entry *pde = s->private;
13110 + struct ipt_dstlimit_htable *htable = pde->data;
13111 + unsigned int *bucket = (unsigned int *)v;
13113 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
13114 + struct dsthash_ent *, s)) {
13115 + /* buffer was filled and unable to print that tuple */
13121 +static struct seq_operations dl_seq_ops = {
13122 + .start = dl_seq_start,
13123 + .next = dl_seq_next,
13124 + .stop = dl_seq_stop,
13125 + .show = dl_seq_show
13128 +static int dl_proc_open(struct inode *inode, struct file *file)
13130 + int ret = seq_open(file, &dl_seq_ops);
13133 + struct seq_file *sf = file->private_data;
13134 + sf->private = PDE(inode);
13139 +static struct file_operations dl_file_ops = {
13140 + .owner = THIS_MODULE,
13141 + .open = dl_proc_open,
13142 + .read = seq_read,
13143 + .llseek = seq_lseek,
13144 + .release = seq_release
13147 +static int init_or_fini(int fini)
13154 + if (ipt_register_match(&ipt_dstlimit)) {
13156 + goto cleanup_nothing;
13159 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
13160 + * quite small ? */
13161 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
13162 + sizeof(struct dsthash_ent), 0,
13163 + SLAB_HWCACHE_ALIGN, NULL, NULL);
13164 + if (!dstlimit_cachep) {
13165 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
13167 + goto cleanup_unreg_match;
13170 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
13171 + if (!dstlimit_procdir) {
13172 + printk(KERN_ERR "Unable to create proc dir entry\n");
13174 + goto cleanup_free_slab;
13180 + remove_proc_entry("ipt_dstlimit", proc_net);
13181 +cleanup_free_slab:
13182 + kmem_cache_destroy(dstlimit_cachep);
13183 +cleanup_unreg_match:
13184 + ipt_unregister_match(&ipt_dstlimit);
13190 +static int __init init(void)
13192 + return init_or_fini(0);
13195 +static void __exit fini(void)
13200 +module_init(init);
13201 +module_exit(fini);
13202 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
13203 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
13204 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_fuzzy.c 2003-12-10 23:13:30.017512728 +0100
13207 + * This module implements a simple TSK FLC
13208 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
13209 + * to limit , in an adaptive and flexible way , the packet rate crossing
13210 + * a given stream . It serves as an initial and very simple (but effective)
13211 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
13212 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
13213 + * into our code in a precise , adaptive and efficient manner.
13214 + * The goal is very similar to that of "limit" match , but using techniques of
13215 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
13216 + * avoiding over and undershoots - and stuff like that .
13219 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
13220 + * 2002-08-17 : Changed to eliminate floating point operations .
13221 + * 2002-08-23 : Coding style changes .
13224 +#include <linux/module.h>
13225 +#include <linux/skbuff.h>
13226 +#include <linux/ip.h>
13227 +#include <linux/random.h>
13228 +#include <net/tcp.h>
13229 +#include <linux/spinlock.h>
13230 +#include <linux/netfilter_ipv4/ip_tables.h>
13231 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
13234 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
13235 + Expressed in percentage
13238 +#define PAR_LOW 1/100
13239 +#define PAR_HIGH 1
13241 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
13243 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
13244 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
13245 +MODULE_LICENSE("GPL");
13247 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13249 + if (tx >= maxi) return 100;
13251 + if (tx <= mini) return 0;
13253 + return ( (100*(tx-mini)) / (maxi-mini) ) ;
13256 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13258 + if (tx <= mini) return 100;
13260 + if (tx >= maxi) return 0;
13262 + return ( (100*( maxi - tx )) / ( maxi - mini ) ) ;
13267 +ipt_fuzzy_match(const struct sk_buff *pskb,
13268 + const struct net_device *in,
13269 + const struct net_device *out,
13270 + const void *matchinfo,
13273 + u_int16_t datalen,
13276 + /* From userspace */
13278 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
13280 + u_int8_t random_number;
13281 + unsigned long amount ;
13282 + u_int8_t howhigh , howlow ;
13285 + spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
13287 + info->bytes_total += pskb->len ;
13288 + info->packets_total++ ;
13290 + info->present_time = jiffies ;
13292 + if ( info->present_time >= info->previous_time )
13293 + amount = info->present_time - info->previous_time ;
13295 + /* There was a transition : I choose to re-sample
13296 + and keep the old acceptance rate...
13300 + info->previous_time = info->present_time ;
13301 + info->bytes_total = info->packets_total = 0;
13304 + if ( amount > HZ/10 ) /* More than 100 ms elapsed ... */
13307 + info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total ) \
13310 + info->previous_time = info->present_time ;
13311 + info->bytes_total = info->packets_total = 0 ;
13313 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
13314 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
13316 + info->acceptance_rate = (u_int8_t) \
13317 + ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
13319 + /* In fact , the above defuzzification would require a denominator
13320 + proportional to (howhigh+howlow) but , in this particular case ,
13321 + that expression is constant .
13322 + An imediate consequence is that it isn't necessary to call
13323 + both mf_high and mf_low - but to keep things understandable ,
13329 + spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
13332 + if ( info->acceptance_rate < 100 )
13334 + get_random_bytes((void *)(&random_number), 1);
13336 + /* If within the acceptance , it can pass => don't match */
13337 + if ( random_number <= (255 * info->acceptance_rate) / 100 )
13340 + return 1; /* It can't pass ( It matches ) */
13343 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
13348 +ipt_fuzzy_checkentry(const char *tablename,
13349 + const struct ipt_ip *e,
13351 + unsigned int matchsize,
13352 + unsigned int hook_mask)
13355 + const struct ipt_fuzzy_info *info = matchinfo;
13357 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
13358 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
13359 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
13363 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
13364 + || (info->minimum_rate >= info->maximum_rate ))
13366 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
13373 +static struct ipt_match ipt_fuzzy_reg = {
13377 + ipt_fuzzy_checkentry,
13381 +static int __init init(void)
13383 + if (ipt_register_match(&ipt_fuzzy_reg))
13389 +static void __exit fini(void)
13391 + ipt_unregister_match(&ipt_fuzzy_reg);
13394 +module_init(init);
13395 +module_exit(fini);
13396 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
13397 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
13398 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPMARK.c 2003-12-10 23:13:59.369050616 +0100
13400 +/* This is a module which is used for setting the NFMARK field of an skb. */
13401 +#include <linux/module.h>
13402 +#include <linux/skbuff.h>
13403 +#include <linux/ip.h>
13404 +#include <net/checksum.h>
13406 +#include <linux/netfilter_ipv4/ip_tables.h>
13407 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
13409 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
13410 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
13411 +MODULE_LICENSE("GPL");
13413 +static unsigned int
13414 +target(struct sk_buff **pskb,
13415 + unsigned int hooknum,
13416 + const struct net_device *in,
13417 + const struct net_device *out,
13418 + const void *targinfo,
13421 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
13423 + struct iphdr *iph = (*pskb)->nh.iph;
13425 + unsigned long mark;
13428 + if(ipmarkinfo->addr == IPT_IPMARK_SRC)
13429 + mark = (unsigned long) iph->saddr;
13431 + mark = (unsigned long) iph->daddr;
13433 +// mark has ip address in little indian, we have to change the byte order:
13434 + a = (char *) &mark;
13435 + t = *a; *a=*(a+3); *(a+3)=t;
13436 + t=*(a+1); *(a+1)=*(a+2); *(a+2)=t;
13438 + mark &= ipmarkinfo->andmask;
13439 + mark |= ipmarkinfo->ormask;
13441 + if((*pskb)->nfmark != mark) {
13442 + (*pskb)->nfmark = mark;
13443 + (*pskb)->nfcache |= NFC_ALTERED;
13445 + return IPT_CONTINUE;
13449 +checkentry(const char *tablename,
13450 + const struct ipt_entry *e,
13452 + unsigned int targinfosize,
13453 + unsigned int hook_mask)
13455 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
13456 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
13458 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
13462 + if (strcmp(tablename, "mangle") != 0) {
13463 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13470 +static struct ipt_target ipt_ipmark_reg
13471 += { { NULL, NULL }, "IPMARK", target, checkentry, NULL, THIS_MODULE };
13473 +static int __init init(void)
13475 + if (ipt_register_target(&ipt_ipmark_reg))
13481 +static void __exit fini(void)
13483 + ipt_unregister_target(&ipt_ipmark_reg);
13486 +module_init(init);
13487 +module_exit(fini);
13488 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
13489 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
13490 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipv4options.c 2003-12-10 23:13:32.270170272 +0100
13493 + This is a module which is used to match ipv4 options.
13494 + This file is distributed under the terms of the GNU General Public
13495 + License (GPL). Copies of the GPL can be obtained from:
13496 + ftp://prep.ai.mit.edu/pub/gnu/GPL
13498 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
13499 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
13500 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
13501 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
13504 +#include <linux/module.h>
13505 +#include <linux/skbuff.h>
13506 +#include <net/ip.h>
13508 +#include <linux/netfilter_ipv4/ip_tables.h>
13509 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
13511 +MODULE_LICENSE("GPL");
13514 +match(const struct sk_buff *skb,
13515 + const struct net_device *in,
13516 + const struct net_device *out,
13517 + const void *matchinfo,
13520 + u_int16_t datalen,
13523 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
13524 + const struct iphdr *iph = skb->nh.iph;
13525 + const struct ip_options *opt;
13527 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
13528 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
13530 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
13531 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13532 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13533 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13534 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13535 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
13540 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
13541 + /* there are options, and we don't need to care which one */
13544 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
13545 + /* there are options but we don't want any ! */
13550 + opt = &(IPCB(skb)->opt);
13552 + /* source routing */
13553 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
13554 + if (!((opt->srr) & (opt->is_strictroute)))
13557 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
13558 + if (!((opt->srr) & (!opt->is_strictroute)))
13561 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
13565 + /* record route */
13566 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
13570 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
13575 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
13579 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
13583 + /* router-alert option */
13584 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
13585 + if (!opt->router_alert)
13588 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
13589 + if (opt->router_alert)
13598 +checkentry(const char *tablename,
13599 + const struct ipt_ip *ip,
13601 + unsigned int matchsize,
13602 + unsigned int hook_mask)
13604 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
13605 + /* Check the size */
13606 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
13608 + /* Now check the coherence of the data ... */
13609 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
13610 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
13611 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
13612 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
13613 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
13614 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
13615 + return 0; /* opposites */
13616 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
13617 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13618 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13619 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13620 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13621 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
13622 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
13623 + return 0; /* opposites */
13624 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
13625 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
13626 + return 0; /* cannot match in the same time loose and strict source routing */
13627 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13628 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
13629 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
13630 + return 0; /* opposites */
13631 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
13632 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
13633 + return 0; /* opposites */
13634 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
13635 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
13636 + return 0; /* opposites */
13637 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
13638 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
13639 + return 0; /* opposites */
13641 + /* everything looks ok. */
13645 +static struct ipt_match ipv4options_match
13646 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
13648 +static int __init init(void)
13650 + printk("ipt_ipv4options loading\n");
13651 + return ipt_register_match(&ipv4options_match);
13654 +static void __exit fini(void)
13656 + ipt_unregister_match(&ipv4options_match);
13657 + printk("ipt_ipv4options unloaded\n");
13660 +module_init(init);
13661 +module_exit(fini);
13662 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
13663 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
13664 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2003-12-10 23:13:33.336008240 +0100
13667 + * Strip all IP options in the IP packet header.
13669 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
13670 + * This software is distributed under GNU GPL v2, 1991
13673 +#include <linux/module.h>
13674 +#include <linux/skbuff.h>
13675 +#include <linux/ip.h>
13676 +#include <net/checksum.h>
13678 +#include <linux/netfilter_ipv4/ip_tables.h>
13680 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
13681 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
13682 +MODULE_LICENSE("GPL");
13684 +static unsigned int
13685 +target(struct sk_buff **pskb,
13686 + unsigned int hooknum,
13687 + const struct net_device *in,
13688 + const struct net_device *out,
13689 + const void *targinfo,
13692 + struct iphdr *iph = (*pskb)->nh.iph;
13693 + struct sk_buff *skb = (*pskb);
13694 + struct ip_options * opt;
13695 + unsigned char * optiph = skb->nh.raw;
13696 + int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
13699 + /* if no options in packet then nothing to clear. */
13700 + if (iph->ihl * 4 == sizeof(struct iphdr))
13701 + return IPT_CONTINUE;
13703 + /* else clear all options */
13704 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
13705 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
13706 + opt = &(IPCB(skb)->opt);
13707 + opt->is_data = 0;
13710 + skb->nfcache |= NFC_ALTERED;
13712 + return IPT_CONTINUE;
13716 +checkentry(const char *tablename,
13717 + const struct ipt_entry *e,
13719 + unsigned int targinfosize,
13720 + unsigned int hook_mask)
13722 + if (strcmp(tablename, "mangle")) {
13723 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13726 + /* nothing else to check because no parameters */
13730 +static struct ipt_target ipt_ipv4optsstrip_reg
13731 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
13733 +static int __init init(void)
13735 + if (ipt_register_target(&ipt_ipv4optsstrip_reg))
13737 + printk("ipt_IPV4OPTSSTRIP loaded\n");
13742 +static void __exit fini(void)
13744 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
13745 + printk("ipt_IPV4OPTSSTRIP unloaded\n");
13748 +module_init(init);
13749 +module_exit(fini);
13750 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
13751 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_LOG.c 2003-11-26 21:45:28.000000000 +0100
13752 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_LOG.c 2003-12-10 23:13:22.346678872 +0100
13754 #include <linux/module.h>
13755 #include <linux/spinlock.h>
13756 #include <linux/skbuff.h>
13757 +#include <linux/socket.h>
13758 #include <linux/ip.h>
13759 #include <net/icmp.h>
13760 #include <net/udp.h>
13761 #include <net/tcp.h>
13762 #include <net/route.h>
13764 +#include <linux/netfilter.h>
13765 #include <linux/netfilter_ipv4/ip_tables.h>
13766 #include <linux/netfilter_ipv4/ipt_LOG.h>
13769 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
13770 MODULE_DESCRIPTION("iptables syslog logging module");
13772 +static unsigned int nflog = 1;
13773 +MODULE_PARM(nflog, "i");
13774 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
13777 #define DEBUGP printk
13779 @@ -315,28 +321,25 @@
13780 /* maxlen = 230+ 91 + 230 + 252 = 803 */
13783 -static unsigned int
13784 -ipt_log_target(struct sk_buff **pskb,
13786 +ipt_log_packet(unsigned int hooknum,
13787 + const struct sk_buff *skb,
13788 const struct net_device *in,
13789 const struct net_device *out,
13790 - unsigned int hooknum,
13791 - const void *targinfo,
13793 + const struct ipt_log_info *loginfo,
13794 + const char *level_string,
13795 + const char *prefix)
13797 - const struct ipt_log_info *loginfo = targinfo;
13798 - char level_string[4] = "< >";
13800 - level_string[1] = '0' + (loginfo->level % 8);
13801 spin_lock_bh(&log_lock);
13802 printk(level_string);
13803 printk("%sIN=%s OUT=%s ",
13805 + prefix == NULL ? loginfo->prefix : prefix,
13806 in ? in->name : "",
13807 out ? out->name : "");
13808 #ifdef CONFIG_BRIDGE_NETFILTER
13809 - if ((*pskb)->nf_bridge) {
13810 - struct net_device *physindev = (*pskb)->nf_bridge->physindev;
13811 - struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
13812 + if (skb->nf_bridge) {
13813 + struct net_device *physindev = skb->nf_bridge->physindev;
13814 + struct net_device *physoutdev = skb->nf_bridge->physoutdev;
13816 if (physindev && in != physindev)
13817 printk("PHYSIN=%s ", physindev->name);
13818 @@ -348,25 +351,56 @@
13820 /* MAC logging for input chain only. */
13822 - if ((*pskb)->dev && (*pskb)->dev->hard_header_len
13823 - && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
13824 + if (skb->dev && skb->dev->hard_header_len
13825 + && skb->mac.raw != (void*)skb->nh.iph) {
13827 - unsigned char *p = (*pskb)->mac.raw;
13828 - for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
13829 + unsigned char *p = skb->mac.raw;
13830 + for (i = 0; i < skb->dev->hard_header_len; i++,p++)
13831 printk("%02x%c", *p,
13832 - i==(*pskb)->dev->hard_header_len - 1
13833 + i==skb->dev->hard_header_len - 1
13839 - dump_packet(loginfo, *pskb, 0);
13840 + dump_packet(loginfo, skb, 0);
13842 spin_unlock_bh(&log_lock);
13845 +static unsigned int
13846 +ipt_log_target(struct sk_buff **pskb,
13847 + const struct net_device *in,
13848 + const struct net_device *out,
13849 + unsigned int hooknum,
13850 + const void *targinfo,
13853 + const struct ipt_log_info *loginfo = targinfo;
13854 + char level_string[4] = "< >";
13856 + level_string[1] = '0' + (loginfo->level % 8);
13857 + ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
13859 return IPT_CONTINUE;
13863 +ipt_logfn(unsigned int hooknum,
13864 + const struct sk_buff *skb,
13865 + const struct net_device *in,
13866 + const struct net_device *out,
13867 + const char *prefix)
13869 + struct ipt_log_info loginfo = {
13871 + .logflags = IPT_LOG_MASK,
13875 + ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
13878 static int ipt_log_checkentry(const char *tablename,
13879 const struct ipt_entry *e,
13881 @@ -406,12 +440,17 @@
13883 if (ipt_register_target(&ipt_log_reg))
13886 + nf_log_register(PF_INET, &ipt_logfn);
13891 static void __exit fini(void)
13894 + nf_log_unregister(PF_INET, &ipt_logfn);
13896 ipt_unregister_target(&ipt_log_reg);
13899 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
13900 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mark.c 2003-11-26 21:46:13.000000000 +0100
13901 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mark.c 2003-12-10 23:14:21.807639432 +0100
13906 - const struct ipt_mark_info *info = matchinfo;
13907 + const struct ipt_mark_info *info = (struct ipt_mark_info *)matchinfo;
13909 - return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13910 + if (info->bit_op == IPT_MARK_BIT_OP_NONE)
13911 + return (skb->nfmark == info->mark) ^ info->invert;
13913 + if (info->bit_op == IPT_MARK_BIT_OP_AND)
13914 + return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13916 + return ((skb->nfmark | info->mask) == info->mark) ^ info->invert;
13920 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
13921 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
13922 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mport.c 2003-12-10 23:13:34.441840128 +0100
13924 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
13925 + the same place so we can treat them as equal. */
13926 +#include <linux/module.h>
13927 +#include <linux/types.h>
13928 +#include <linux/udp.h>
13929 +#include <linux/skbuff.h>
13931 +#include <linux/netfilter_ipv4/ipt_mport.h>
13932 +#include <linux/netfilter_ipv4/ip_tables.h>
13934 +MODULE_LICENSE("GPL");
13937 +#define duprintf(format, args...) printk(format , ## args)
13939 +#define duprintf(format, args...)
13942 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
13944 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
13948 + u_int16_t pflags = minfo->pflags;
13949 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
13953 + && minfo->ports[i] == 65535)
13956 + s = minfo->ports[i];
13958 + if (pflags & m) {
13959 + e = minfo->ports[++i];
13964 + if (minfo->flags & IPT_MPORT_SOURCE
13965 + && src >= s && src <= e)
13968 + if (minfo->flags & IPT_MPORT_DESTINATION
13969 + && dst >= s && dst <= e)
13977 +match(const struct sk_buff *skb,
13978 + const struct net_device *in,
13979 + const struct net_device *out,
13980 + const void *matchinfo,
13983 + u_int16_t datalen,
13986 + const struct udphdr *udp = hdr;
13987 + const struct ipt_mport *minfo = matchinfo;
13989 + /* Must be big enough to read ports. */
13990 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
13991 + /* We've been asked to examine this packet, and we
13992 + can't. Hence, no choice but to drop. */
13993 + duprintf("ipt_mport:"
13994 + " Dropping evil offset=0 tinygram.\n");
13999 + /* Must not be a fragment. */
14001 + && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
14004 +/* Called when user tries to insert an entry of this type. */
14006 +checkentry(const char *tablename,
14007 + const struct ipt_ip *ip,
14009 + unsigned int matchsize,
14010 + unsigned int hook_mask)
14012 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
14015 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
14016 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
14017 + && !(ip->invflags & IPT_INV_PROTO)
14018 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
14021 +static struct ipt_match mport_match
14022 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
14024 +static int __init init(void)
14026 + return ipt_register_match(&mport_match);
14029 +static void __exit fini(void)
14031 + ipt_unregister_match(&mport_match);
14034 +module_init(init);
14035 +module_exit(fini);
14036 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_NETLINK.c
14037 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
14038 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_NETLINK.c 2003-12-10 23:13:35.507678096 +0100
14040 +#include <linux/module.h>
14041 +#include <linux/version.h>
14042 +#include <linux/config.h>
14043 +#include <linux/socket.h>
14044 +#include <linux/skbuff.h>
14045 +#include <linux/kernel.h>
14046 +#include <linux/netlink.h>
14047 +#include <linux/netdevice.h>
14048 +#include <linux/mm.h>
14049 +#include <linux/socket.h>
14050 +#include <linux/netfilter_ipv4/ip_tables.h>
14051 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
14052 +#include <net/sock.h>
14054 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
14055 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
14056 +MODULE_LICENSE("GPL");
14059 +#define DEBUGP printk
14061 +#define DEBUGP(format, args...)
14064 +static struct sock *ipfwsk;
14066 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
14067 + unsigned int hooknum,
14068 + const struct net_device *in,
14069 + const struct net_device *out,
14070 + const void *targinfo, void *userinfo)
14072 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
14073 + struct iphdr *ip = (*pskb)->nh.iph;
14074 + struct sk_buff *outskb;
14075 + struct netlink_t nlhdr;
14078 + /* Allocate a socket buffer */
14079 + if ( MASK(nld->flags, USE_SIZE) )
14080 + len = nld->size+sizeof(nlhdr);
14082 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
14084 + outskb=alloc_skb(len, GFP_ATOMIC);
14089 + if ( MASK(nld->flags, USE_MARK) )
14090 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
14092 + nlhdr.mark=(*pskb)->nfmark;
14094 + if ( in && in->name ) {
14095 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
14096 + }else if ( out && out->name ){
14097 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
14100 + skb_put(outskb, len);
14101 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
14102 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
14103 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
14105 + if (net_ratelimit())
14106 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
14109 + if ( MASK(nld->flags, USE_DROP) )
14112 + return IPT_CONTINUE;
14115 +static int ipt_netlink_checkentry(const char *tablename,
14116 + const struct ipt_entry *e,
14118 + unsigned int targinfosize,
14119 + unsigned int hookmask)
14121 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
14126 +static struct ipt_target ipt_netlink_reg = {
14129 + ipt_netlink_target,
14130 + ipt_netlink_checkentry,
14135 +static int __init init(void)
14137 + DEBUGP("ipt_NETLINK: init module\n");
14139 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
14143 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
14150 +static void __exit fini(void)
14152 + DEBUGP("ipt_NETLINK: cleanup_module\n");
14153 + ipt_unregister_target(&ipt_netlink_reg);
14154 + if(ipfwsk->socket) sock_release(ipfwsk->socket);
14157 +module_init(init);
14158 +module_exit(fini);
14159 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
14160 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NOTRACK.c 1970-01-01 01:00:00.000000000 +0100
14161 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_NOTRACK.c 2003-12-10 23:13:24.663326688 +0100
14163 +/* This is a module which is used for setting up fake conntracks
14164 + * on packets so that they are not seen by the conntrack/NAT code.
14166 +#include <linux/module.h>
14167 +#include <linux/skbuff.h>
14169 +#include <linux/netfilter_ipv4/ip_tables.h>
14170 +#include <linux/netfilter_ipv4/ip_conntrack.h>
14172 +static unsigned int
14173 +target(struct sk_buff **pskb,
14174 + const struct net_device *in,
14175 + const struct net_device *out,
14176 + unsigned int hooknum,
14177 + const void *targinfo,
14180 + /* Previously seen (loopback)? Ignore. */
14181 + if ((*pskb)->nfct != NULL)
14182 + return IPT_CONTINUE;
14184 + /* Attach fake conntrack entry.
14185 + If there is a real ct entry correspondig to this packet,
14186 + it'll hang aroun till timing out. We don't deal with it
14187 + for performance reasons. JK */
14188 + (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
14189 + nf_conntrack_get((*pskb)->nfct);
14191 + return IPT_CONTINUE;
14195 +checkentry(const char *tablename,
14196 + const struct ipt_entry *e,
14198 + unsigned int targinfosize,
14199 + unsigned int hook_mask)
14201 + if (targinfosize != 0) {
14202 + printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
14207 + if (strcmp(tablename, "raw") != 0) {
14208 + printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
14215 +static struct ipt_target ipt_notrack_reg = {
14216 + .name = "NOTRACK",
14217 + .target = target,
14218 + .checkentry = checkentry,
14220 + .me = THIS_MODULE,
14223 +static int __init init(void)
14225 + if (ipt_register_target(&ipt_notrack_reg))
14231 +static void __exit fini(void)
14233 + ipt_unregister_target(&ipt_notrack_reg);
14236 +module_init(init);
14237 +module_exit(fini);
14239 +MODULE_LICENSE("GPL");
14240 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
14241 +MODULE_DESCRIPTION("IPv4 NOTRACK target");
14242 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
14243 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
14244 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_nth.c 2003-12-10 23:13:37.748337464 +0100
14247 + This is a module which is used for match support for every Nth packet
14248 + This file is distributed under the terms of the GNU General Public
14249 + License (GPL). Copies of the GPL can be obtained from:
14250 + ftp://prep.ai.mit.edu/pub/gnu/GPL
14252 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14253 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
14254 + * added support for multiple counters
14255 + * added support for matching on individual packets
14256 + in the counter cycle
14260 +#include <linux/module.h>
14261 +#include <linux/skbuff.h>
14262 +#include <linux/ip.h>
14263 +#include <net/tcp.h>
14264 +#include <linux/spinlock.h>
14265 +#include <linux/netfilter_ipv4/ip_tables.h>
14266 +#include <linux/netfilter_ipv4/ipt_nth.h>
14268 +MODULE_LICENSE("GPL");
14271 + * State information.
14275 + u_int16_t number;
14278 +static struct state states[IPT_NTH_NUM_COUNTERS];
14281 +ipt_nth_match(const struct sk_buff *pskb,
14282 + const struct net_device *in,
14283 + const struct net_device *out,
14284 + const void *matchinfo,
14287 + u_int16_t datalen,
14290 + /* Parameters from userspace */
14291 + const struct ipt_nth_info *info = matchinfo;
14292 + unsigned counter = info->counter;
14293 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
14295 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14299 + spin_lock(&states[counter].lock);
14301 + /* Are we matching every nth packet?*/
14302 + if (info->packet == 0xFF)
14304 + /* We're matching every nth packet and only every nth packet*/
14305 + /* Do we match or invert match? */
14306 + if (info->not == 0)
14308 + if (states[counter].number == 0)
14310 + ++states[counter].number;
14313 + if (states[counter].number >= info->every)
14314 + states[counter].number = 0; /* reset the counter */
14316 + ++states[counter].number;
14321 + if (states[counter].number == 0)
14323 + ++states[counter].number;
14326 + if (states[counter].number >= info->every)
14327 + states[counter].number = 0;
14329 + ++states[counter].number;
14335 + /* We're using the --packet, so there must be a rule for every value */
14336 + if (states[counter].number == info->packet)
14338 + /* only increment the counter when a match happens */
14339 + if (states[counter].number >= info->every)
14340 + states[counter].number = 0; /* reset the counter */
14342 + ++states[counter].number;
14350 + /* don't match */
14351 + spin_unlock(&states[counter].lock);
14355 + spin_unlock(&states[counter].lock);
14360 +ipt_nth_checkentry(const char *tablename,
14361 + const struct ipt_ip *e,
14363 + unsigned int matchsize,
14364 + unsigned int hook_mask)
14366 + /* Parameters from userspace */
14367 + const struct ipt_nth_info *info = matchinfo;
14368 + unsigned counter = info->counter;
14369 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
14371 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14375 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
14376 + printk("nth: matchsize %u != %u\n", matchsize,
14377 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
14381 + states[counter].number = info->startat;
14386 +static struct ipt_match ipt_nth_reg = {
14390 + ipt_nth_checkentry,
14394 +static int __init init(void)
14396 + unsigned counter;
14397 + memset(&states, 0, sizeof(states));
14398 + if (ipt_register_match(&ipt_nth_reg))
14401 + for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
14403 + spin_lock_init(&(states[counter].lock));
14406 + printk("ipt_nth match loaded\n");
14410 +static void __exit fini(void)
14412 + ipt_unregister_match(&ipt_nth_reg);
14413 + printk("ipt_nth match unloaded\n");
14416 +module_init(init);
14417 +module_exit(fini);
14418 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
14419 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
14420 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_osf.c 2003-12-10 23:13:38.896162968 +0100
14425 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
14428 + * This program is free software; you can redistribute it and/or modify
14429 + * it under the terms of the GNU General Public License as published by
14430 + * the Free Software Foundation; either version 2 of the License, or
14431 + * (at your option) any later version.
14433 + * This program is distributed in the hope that it will be useful,
14434 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14435 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14436 + * GNU General Public License for more details.
14438 + * You should have received a copy of the GNU General Public License
14439 + * along with this program; if not, write to the Free Software
14440 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14444 + * OS fingerprint matching module.
14445 + * It simply compares various parameters from SYN packet with
14446 + * some hardcoded ones.
14448 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
14452 +#include <linux/smp.h>
14453 +#include <linux/module.h>
14454 +#include <linux/skbuff.h>
14455 +#include <linux/file.h>
14456 +#include <linux/ip.h>
14457 +#include <linux/proc_fs.h>
14458 +#include <linux/fs.h>
14459 +#include <linux/slab.h>
14460 +#include <linux/spinlock.h>
14461 +#include <linux/ctype.h>
14462 +#include <linux/list.h>
14464 +#include <net/sock.h>
14465 +#include <net/ip.h>
14467 +#include <linux/netfilter_ipv4/ip_tables.h>
14469 +#include <linux/netfilter_ipv4/ipt_osf.h>
14471 +//#define OSF_DEBUG
14474 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
14475 +#define loga(x...) printk(x)
14477 +#define log(x...) do {} while(0)
14478 +#define loga(x...) do {} while(0)
14481 +#define FMATCH_WRONG 0
14482 +#define FMATCH_OK 1
14483 +#define FMATCH_OPT_WRONG 2
14485 +#define OPTDEL ','
14486 +#define OSFPDEL ':'
14487 +#define MAXOPTSTRLEN 128
14488 +#define OSFFLUSH "FLUSH"
14490 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
14491 +static struct list_head finger_list;
14493 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
14494 + const void *, int, const void *, u_int16_t, int *);
14495 +static int checkentry(const char *, const struct ipt_ip *, void *,
14496 + unsigned int, unsigned int);
14498 +static struct ipt_match osf_match =
14509 +match(const struct sk_buff *skb,
14510 + const struct net_device *in,
14511 + const struct net_device *out,
14512 + const void *matchinfo,
14515 + u_int16_t datalen,
14518 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
14519 + struct iphdr *ip = skb->nh.iph;
14520 + struct tcphdr *tcp;
14521 + int fmatch = FMATCH_WRONG;
14522 + unsigned long totlen, optsize = 0, window;
14523 + unsigned char df, *optp = NULL, *_optp = NULL;
14524 + char check_WSS = 0;
14525 + struct list_head *ent;
14526 + struct osf_finger *f;
14528 + if (!ip || !info)
14531 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
14536 + totlen = ntohs(ip->tot_len);
14537 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
14538 + window = ntohs(tcp->window);
14540 + if (tcp->doff*4 > sizeof(struct tcphdr))
14542 + _optp = optp = (char *)(tcp+1);
14543 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
14547 + /* Actually we can create hash/table of all genres and search
14548 + * only in appropriate part, but here is initial variant,
14549 + * so will use slow path.
14551 + read_lock(&osf_lock);
14552 + list_for_each(ent, &finger_list)
14554 + f = list_entry(ent, struct osf_finger, flist);
14556 + if (strcmp(info->genre, f->genre))
14561 + if ( ip->ttl == f->ttl &&
14562 + totlen == f->ss &&
14565 + unsigned long foptsize;
14567 + unsigned short mss = 0;
14571 + switch (f->wss.wc)
14573 + case 0: check_WSS = 0; break;
14574 + case 'S': check_WSS = 1; break;
14575 + case 'T': check_WSS = 2; break;
14576 + case '%': check_WSS = 3; break;
14577 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
14578 + f->wss.wc, f->genre, f->details);
14582 + if (check_WSS == 4)
14585 + /* Check options */
14588 + for (optnum=0; optnum<f->opt_num; ++optnum)
14589 + foptsize += f->opt[optnum].length;
14592 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
14597 + fmatch = FMATCH_OK;
14598 + loga("\tYEP : matching without options.\n");
14603 + for (optnum=0; optnum<f->opt_num; ++optnum)
14605 + if (f->opt[optnum].kind == (*optp))
14607 + unsigned char len = f->opt[optnum].length;
14608 + unsigned char *optend = optp + len;
14610 + fmatch = FMATCH_OK;
14612 + if (*optp == OSFOPT_MSS) /* MSS */
14613 + mss = ntohs(*(unsigned short *)(optp+2));
14617 + /* Skip kind and length fields*/
14620 + if (f->opt[optnum].wc.wc != 0)
14622 + unsigned long tmp = 0;
14624 + /* Hmmm... It looks a bit ugly. :) */
14625 + memcpy(&tmp, &f->opt[optnum].wc.val,
14626 + (len > sizeof(unsigned long)?
14627 + sizeof(unsigned long):len));
14629 + tmp = ntohl(tmp);
14630 + if (tmp != f->opt[optnum].wc.val)
14631 + fmatch = FMATCH_OPT_WRONG;
14638 + fmatch = FMATCH_OPT_WRONG;
14640 + if (fmatch != FMATCH_OK)
14644 + if (fmatch != FMATCH_OPT_WRONG)
14646 + fmatch = FMATCH_WRONG;
14648 + switch (check_WSS)
14651 + if (window == f->wss.val)
14652 + fmatch = FMATCH_OK;
14654 + case 1: /* MSS */
14655 + if (window == f->wss.val*mss)
14656 + fmatch = FMATCH_OK;
14658 + case 2: /* MTU */
14659 + if (window == f->wss.val*(mss+40))
14660 + fmatch = FMATCH_OK;
14662 + case 3: /* MOD */
14663 + if (window % f->wss.val == 0)
14664 + fmatch = FMATCH_OK;
14670 + if (fmatch == FMATCH_OK)
14673 + log("genre %s[%25s]: ttl=%d, size=%lu, df=%d, "
14674 + "check_WSS=%d, win=%lu, optsize=%lu:\n",
14675 + f->genre, f->details,
14676 + ip->ttl, totlen, df,
14677 + check_WSS, window, optsize);
14682 + read_unlock(&osf_lock);
14684 + return (fmatch == FMATCH_OK)?1:0;
14688 +checkentry(const char *tablename,
14689 + const struct ipt_ip *ip,
14691 + unsigned int matchsize,
14692 + unsigned int hook_mask)
14694 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
14696 + if (ip->proto != IPPROTO_TCP)
14702 +static char * osf_strchr(char *ptr, char c)
14706 + tmp = strchr(ptr, c);
14708 + while (tmp && tmp+1 && isspace(*(tmp+1)))
14714 +static struct osf_finger * finger_alloc()
14716 + struct osf_finger *f;
14718 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
14720 + memset(f, 0, sizeof(struct osf_finger));
14725 +static void finger_free(struct osf_finger *f)
14727 + memset(f, 0, sizeof(struct osf_finger));
14732 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
14736 + unsigned long val;
14740 + while (ptr != NULL && i < olen)
14749 + ptr = osf_strchr(&obuf[i], OPTDEL);
14754 + i += (int)(ptr-&obuf[i]);
14761 + op = OSFOPT_SACKP;
14762 + ptr = osf_strchr(&obuf[i], OPTDEL);
14767 + i += (int)(ptr-&obuf[i]);
14775 + ptr = osf_strchr(&obuf[i], OPTDEL);
14780 + i += (int)(ptr-&obuf[i]);
14788 + ptr = osf_strchr(&obuf[i], OPTDEL);
14791 + switch (obuf[i+1])
14793 + case '%': wc = '%'; break;
14794 + case 'S': wc = 'S'; break;
14795 + case 'T': wc = 'T'; break;
14796 + default: wc = 0; break;
14802 + val = simple_strtoul(&obuf[i+2], NULL, 10);
14804 + val = simple_strtoul(&obuf[i+1], NULL, 10);
14805 + i += (int)(ptr-&obuf[i]);
14813 + ptr = osf_strchr(&obuf[i], OPTDEL);
14816 + if (obuf[i+1] == '%')
14821 + val = simple_strtoul(&obuf[i+2], NULL, 10);
14823 + val = simple_strtoul(&obuf[i+1], NULL, 10);
14824 + i += (int)(ptr-&obuf[i]);
14832 + ptr = osf_strchr(&obuf[i], OPTDEL);
14837 + i += (int)(ptr-&obuf[i]);
14844 + ptr = osf_strchr(&obuf[i], OPTDEL);
14848 + i += (int)(ptr-&obuf[i]);
14856 + opt[*optnum].kind = IANA_opts[op].kind;
14857 + opt[*optnum].length = IANA_opts[op].length;
14858 + opt[*optnum].wc.wc = wc;
14859 + opt[*optnum].wc.val = val;
14861 + log("opt %2d: kind=%2d, length=%2d, wc.wc=%d, wc.val=%5lu\n",
14862 + *optnum, opt[*optnum].kind, opt[*optnum].length,
14863 + opt[*optnum].wc.wc, opt[*optnum].wc.val);
14869 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
14871 + struct list_head *ent;
14872 + struct osf_finger *f = NULL;
14878 + read_lock_bh(&osf_lock);
14879 + list_for_each(ent, &finger_list)
14881 + f = list_entry(ent, struct osf_finger, flist);
14883 + log("%s - %s: ttl=%d, wss=%c%lu, df=%d, size=%lu",
14884 + f->genre, f->details, f->ttl, (f->wss.wc)?f->wss.wc:' ', f->wss.val, f->df, f->ss);
14886 + count += sprintf(buf+count, "%s - %s[%s] : %s",
14887 + f->genre, f->version,
14888 + f->subtype, f->details);
14893 + //count += sprintf(buf+count, " OPT: ");
14894 + for (i=0; i<f->opt_num; ++i)
14896 + //count += sprintf(buf+count, "%d.%c%lu; ",
14897 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14898 + loga("%d.%c%lu; ",
14899 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14903 + count += sprintf(buf+count, "\n");
14905 + read_unlock_bh(&osf_lock);
14910 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
14914 + char obuf[MAXOPTSTRLEN];
14915 + struct osf_finger *finger;
14916 + struct list_head *ent, *n;
14918 + char *pbeg, *pend;
14920 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
14923 + write_lock_bh(&osf_lock);
14924 + list_for_each_safe(ent, n, &finger_list)
14927 + finger = list_entry(ent, struct osf_finger, flist);
14928 + list_del(&finger->flist);
14929 + finger_free(finger);
14931 + write_unlock_bh(&osf_lock);
14933 + log("Flushed %d entries.\n", i);
14940 + for (i=0; i<count && buffer[i] != '\0'; ++i)
14941 + if (buffer[i] == ':')
14944 + if (cnt != 8 || i != count)
14946 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
14951 + memset(obuf, 0, sizeof(obuf));
14953 + finger = finger_alloc();
14956 + log("Failed to allocate new fingerprint entry.\n");
14960 + pbeg = (char *)buffer;
14961 + pend = osf_strchr(pbeg, OSFPDEL);
14965 + if (pbeg[0] == 'S')
14967 + finger->wss.wc = 'S';
14968 + if (pbeg[1] == '%')
14969 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14970 + else if (pbeg[1] == '*')
14971 + finger->wss.val = 0;
14973 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14975 + else if (pbeg[0] == 'T')
14977 + finger->wss.wc = 'T';
14978 + if (pbeg[1] == '%')
14979 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14980 + else if (pbeg[1] == '*')
14981 + finger->wss.val = 0;
14983 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14985 + if (isdigit(pbeg[0]))
14987 + finger->wss.wc = 0;
14988 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
14993 + pend = osf_strchr(pbeg, OSFPDEL);
14997 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
15000 + pend = osf_strchr(pbeg, OSFPDEL);
15004 + finger->df = simple_strtoul(pbeg, NULL, 10);
15007 + pend = osf_strchr(pbeg, OSFPDEL);
15011 + finger->ss = simple_strtoul(pbeg, NULL, 10);
15015 + pend = osf_strchr(pbeg, OSFPDEL);
15019 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
15023 + pend = osf_strchr(pbeg, OSFPDEL);
15027 + if (pbeg[0] == '@' || pbeg[0] == '*')
15028 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
15030 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
15034 + pend = osf_strchr(pbeg, OSFPDEL);
15038 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
15042 + pend = osf_strchr(pbeg, OSFPDEL);
15046 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
15050 + cnt = snprintf(finger->details,
15051 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
15054 + log("%s - %s[%s] : %s\n",
15055 + finger->genre, finger->version,
15056 + finger->subtype, finger->details);
15058 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
15061 + write_lock_bh(&osf_lock);
15062 + list_add(&finger->flist, &finger_list);
15063 + write_unlock_bh(&osf_lock);
15068 +static int __init osf_init(void)
15071 + struct proc_dir_entry *p;
15073 + log("Startng OS fingerprint matching module.\n");
15075 + INIT_LIST_HEAD(&finger_list);
15077 + err = ipt_register_match(&osf_match);
15080 + log("Failed to register OS fingerprint matching module.\n");
15084 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
15087 + ipt_unregister_match(&osf_match);
15091 + p->write_proc = osf_proc_write;
15092 + p->read_proc = osf_proc_read;
15097 +static void __exit osf_fini(void)
15099 + struct list_head *ent, *n;
15100 + struct osf_finger *f;
15102 + remove_proc_entry("sys/net/ipv4/osf", NULL);
15103 + ipt_unregister_match(&osf_match);
15105 + list_for_each_safe(ent, n, &finger_list)
15107 + f = list_entry(ent, struct osf_finger, flist);
15108 + list_del(&f->flist);
15112 + log("OS fingerprint matching module finished.\n");
15115 +module_init(osf_init);
15116 +module_exit(osf_fini);
15118 +MODULE_LICENSE("GPL");
15119 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
15120 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
15121 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
15122 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
15123 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_pool.c 2003-12-10 23:13:39.982997744 +0100
15125 +/* Kernel module to match an IP address pool. */
15127 +#include <linux/module.h>
15128 +#include <linux/ip.h>
15129 +#include <linux/skbuff.h>
15131 +#include <linux/netfilter_ipv4/ip_tables.h>
15132 +#include <linux/netfilter_ipv4/ip_pool.h>
15133 +#include <linux/netfilter_ipv4/ipt_pool.h>
15135 +static inline int match_pool(
15140 + if (ip_pool_match(index, ntohl(addr)))
15146 + const struct sk_buff *skb,
15147 + const struct net_device *in,
15148 + const struct net_device *out,
15149 + const void *matchinfo,
15152 + u_int16_t datalen,
15155 + const struct ipt_pool_info *info = matchinfo;
15156 + const struct iphdr *iph = skb->nh.iph;
15158 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
15159 + info->flags&IPT_POOL_INV_SRC))
15162 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
15163 + info->flags&IPT_POOL_INV_DST))
15169 +static int checkentry(
15170 + const char *tablename,
15171 + const struct ipt_ip *ip,
15173 + unsigned int matchsize,
15174 + unsigned int hook_mask
15176 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
15181 +static struct ipt_match pool_match
15182 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
15184 +static int __init init(void)
15186 + return ipt_register_match(&pool_match);
15189 +static void __exit fini(void)
15191 + ipt_unregister_match(&pool_match);
15194 +module_init(init);
15195 +module_exit(fini);
15196 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
15197 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
15198 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_POOL.c 2003-12-10 23:13:39.982997744 +0100
15200 +/* ipt_POOL.c - netfilter target to manipulate IP pools
15202 + * This target can be used almost everywhere. It acts on some specified
15203 + * IP pool, adding or deleting some IP address in the pool. The address
15204 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
15205 + * of the packet under inspection.
15207 + * The target normally returns IPT_CONTINUE.
15210 +#include <linux/types.h>
15211 +#include <linux/ip.h>
15212 +#include <linux/timer.h>
15213 +#include <linux/module.h>
15214 +#include <linux/netfilter.h>
15215 +#include <linux/netdevice.h>
15216 +#include <linux/if.h>
15217 +#include <linux/inetdevice.h>
15218 +#include <net/protocol.h>
15219 +#include <net/checksum.h>
15220 +#include <linux/netfilter_ipv4.h>
15221 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
15222 +#include <linux/netfilter_ipv4/ipt_pool.h>
15225 +#define DEBUGP printk
15227 +#define DEBUGP(format, args...)
15230 +/*** NOTE NOTE NOTE NOTE ***
15232 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
15233 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
15234 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
15235 +** is modified for the source IP address of the packet under inspection.
15236 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
15238 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
15239 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
15241 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
15242 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
15243 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
15244 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
15248 +do_check(const char *tablename,
15249 + const struct ipt_entry *e,
15251 + unsigned int targinfosize,
15252 + unsigned int hook_mask)
15254 + const struct ipt_pool_info *ipi = targinfo;
15256 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
15257 + DEBUGP("POOL_check: size %u.\n", targinfosize);
15260 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
15264 +static unsigned int
15265 +do_target(struct sk_buff **pskb,
15266 + unsigned int hooknum,
15267 + const struct net_device *in,
15268 + const struct net_device *out,
15269 + const void *targinfo,
15272 + const struct ipt_pool_info *ipi = targinfo;
15274 + unsigned int verdict = IPT_CONTINUE;
15276 + if (ipi->src != IP_POOL_NONE) {
15277 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
15278 + ipi->flags & IPT_POOL_DEL_SRC);
15279 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
15280 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
15281 + verdict = NF_ACCEPT;
15282 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
15283 + verdict = NF_DROP;
15286 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
15287 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
15288 + ipi->flags & IPT_POOL_DEL_DST);
15289 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
15290 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
15291 + verdict = NF_ACCEPT;
15292 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
15293 + verdict = NF_DROP;
15299 +static struct ipt_target pool_reg
15300 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
15302 +static int __init init(void)
15304 + DEBUGP("init ipt_POOL\n");
15305 + return ipt_register_target(&pool_reg);
15308 +static void __exit fini(void)
15310 + DEBUGP("fini ipt_POOL\n");
15311 + ipt_unregister_target(&pool_reg);
15314 +module_init(init);
15315 +module_exit(fini);
15316 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
15317 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
15318 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_psd.c 2003-12-10 23:13:41.104827200 +0100
15321 + This is a module which is used for PSD (portscan detection)
15322 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
15323 + and LOG target module.
15325 + Copyright (C) 2000,2001 astaro AG
15327 + This file is distributed under the terms of the GNU General Public
15328 + License (GPL). Copies of the GPL can be obtained from:
15329 + ftp://prep.ai.mit.edu/pub/gnu/GPL
15331 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
15332 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
15333 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
15334 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
15335 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
15338 +#include <linux/module.h>
15339 +#include <linux/skbuff.h>
15340 +#include <linux/ip.h>
15341 +#include <net/tcp.h>
15342 +#include <linux/spinlock.h>
15343 +#include <linux/netfilter_ipv4/ip_tables.h>
15344 +#include <linux/netfilter_ipv4/ipt_psd.h>
15347 +#define DEBUGP printk
15349 +#define DEBUGP(format, args...)
15352 +MODULE_LICENSE("GPL");
15353 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
15355 +#define HF_DADDR_CHANGING 0x01
15356 +#define HF_SPORT_CHANGING 0x02
15357 +#define HF_TOS_CHANGING 0x04
15358 +#define HF_TTL_CHANGING 0x08
15361 + * Information we keep per each target port
15364 + u_int16_t number; /* port number */
15365 + u_int8_t proto; /* protocol number */
15366 + u_int8_t and_flags; /* tcp ANDed flags */
15367 + u_int8_t or_flags; /* tcp ORed flags */
15371 + * Information we keep per each source address.
15374 + struct host *next; /* Next entry with the same hash */
15375 + clock_t timestamp; /* Last update time */
15376 + struct in_addr src_addr; /* Source address */
15377 + struct in_addr dest_addr; /* Destination address */
15378 + unsigned short src_port; /* Source port */
15379 + int count; /* Number of ports in the list */
15380 + int weight; /* Total weight of ports in the list */
15381 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
15382 + unsigned char tos; /* TOS */
15383 + unsigned char ttl; /* TTL */
15384 + unsigned char flags; /* HF_ flags bitmask */
15388 + * State information.
15392 + struct host list[LIST_SIZE]; /* List of source addresses */
15393 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
15394 + int index; /* Oldest entry to be replaced */
15398 + * Convert an IP address into a hash table index.
15400 +static inline int hashfunc(struct in_addr addr)
15402 + unsigned int value;
15405 + value = addr.s_addr;
15409 + } while ((value >>= HASH_LOG));
15411 + return hash & (HASH_SIZE - 1);
15415 +ipt_psd_match(const struct sk_buff *pskb,
15416 + const struct net_device *in,
15417 + const struct net_device *out,
15418 + const void *matchinfo,
15421 + u_int16_t datalen,
15424 + struct iphdr *ip_hdr;
15425 + struct tcphdr *tcp_hdr;
15426 + struct in_addr addr;
15427 + u_int16_t src_port,dest_port;
15428 + u_int8_t tcp_flags, proto;
15430 + struct host *curr, *last, **head;
15431 + int hash, index, count;
15433 + /* Parameters from userspace */
15434 + const struct ipt_psd_info *psdinfo = matchinfo;
15437 + ip_hdr = pskb->nh.iph;
15439 + /* Sanity check */
15440 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
15441 + DEBUGP("PSD: sanity check failed\n");
15445 + /* TCP or UDP ? */
15446 + proto = ip_hdr->protocol;
15448 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
15449 + DEBUGP("PSD: protocol not supported\n");
15453 + /* Get the source address, source & destination ports, and TCP flags */
15455 + addr.s_addr = ip_hdr->saddr;
15457 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
15459 + /* Yep, itĀ“s dirty */
15460 + src_port = tcp_hdr->source;
15461 + dest_port = tcp_hdr->dest;
15463 + if (proto == IPPROTO_TCP) {
15464 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
15467 + tcp_flags = 0x00;
15470 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
15471 + * them spoof us. [DHCP needs this feature - HW] */
15472 + if (!addr.s_addr) {
15473 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
15477 + /* Use jiffies here not to depend on someone setting the time while we're
15478 + * running; we need to be careful with possible return value overflows. */
15481 + spin_lock(&state.lock);
15483 + /* Do we know this source address already? */
15486 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
15488 + if (curr->src_addr.s_addr == addr.s_addr) break;
15490 + if (curr->next) last = curr;
15491 + } while ((curr = curr->next));
15495 + /* We know this address, and the entry isn't too old. Update it. */
15496 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
15497 + time_after_eq(now, curr->timestamp)) {
15499 + /* Just update the appropriate list entry if we've seen this port already */
15500 + for (index = 0; index < curr->count; index++) {
15501 + if (curr->ports[index].number == dest_port) {
15502 + curr->ports[index].proto = proto;
15503 + curr->ports[index].and_flags &= tcp_flags;
15504 + curr->ports[index].or_flags |= tcp_flags;
15505 + goto out_no_match;
15509 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
15510 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
15511 + goto out_no_match;
15513 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
15514 + curr->timestamp = now;
15516 + /* Logged this scan already? Then drop the packet. */
15517 + if (curr->weight >= psdinfo->weight_threshold)
15520 + /* Specify if destination address, source port, TOS or TTL are not fixed */
15521 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
15522 + curr->flags |= HF_DADDR_CHANGING;
15523 + if (curr->src_port != src_port)
15524 + curr->flags |= HF_SPORT_CHANGING;
15525 + if (curr->tos != ip_hdr->tos)
15526 + curr->flags |= HF_TOS_CHANGING;
15527 + if (curr->ttl != ip_hdr->ttl)
15528 + curr->flags |= HF_TTL_CHANGING;
15530 + /* Update the total weight */
15531 + curr->weight += (ntohs(dest_port) < 1024) ?
15532 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15534 + /* Got enough destination ports to decide that this is a scan? */
15535 + /* Then log it and drop the packet. */
15536 + if (curr->weight >= psdinfo->weight_threshold)
15539 + /* Remember the new port */
15540 + if (curr->count < SCAN_MAX_COUNT) {
15541 + curr->ports[curr->count].number = dest_port;
15542 + curr->ports[curr->count].proto = proto;
15543 + curr->ports[curr->count].and_flags = tcp_flags;
15544 + curr->ports[curr->count].or_flags = tcp_flags;
15548 + goto out_no_match;
15551 + /* We know this address, but the entry is outdated. Mark it unused, and
15552 + * remove from the hash table. We'll allocate a new entry instead since
15553 + * this one might get re-used too soon. */
15554 + curr->src_addr.s_addr = 0;
15556 + last->next = last->next->next;
15558 + *head = (*head)->next;
15562 + /* We don't need an ACK from a new source address */
15563 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
15564 + goto out_no_match;
15566 + /* Got too many source addresses with the same hash value? Then remove the
15567 + * oldest one from the hash table, so that they can't take too much of our
15568 + * CPU time even with carefully chosen spoofed IP addresses. */
15569 + if (count >= HASH_MAX && last) last->next = NULL;
15571 + /* We're going to re-use the oldest list entry, so remove it from the hash
15572 + * table first (if it is really already in use, and isn't removed from the
15573 + * hash table already because of the HASH_MAX check above). */
15575 + /* First, find it */
15576 + if (state.list[state.index].src_addr.s_addr)
15577 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
15581 + if ((curr = *head))
15583 + if (curr == &state.list[state.index]) break;
15585 + } while ((curr = curr->next));
15587 + /* Then, remove it */
15590 + last->next = last->next->next;
15592 + *head = (*head)->next;
15595 + /* Get our list entry */
15596 + curr = &state.list[state.index++];
15597 + if (state.index >= LIST_SIZE) state.index = 0;
15599 + /* Link it into the hash table */
15600 + head = &state.hash[hash];
15601 + curr->next = *head;
15604 + /* And fill in the fields */
15605 + curr->timestamp = now;
15606 + curr->src_addr = addr;
15607 + curr->dest_addr.s_addr = ip_hdr->daddr;
15608 + curr->src_port = src_port;
15610 + curr->weight = (ntohs(dest_port) < 1024) ?
15611 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15612 + curr->ports[0].number = dest_port;
15613 + curr->ports[0].proto = proto;
15614 + curr->ports[0].and_flags = tcp_flags;
15615 + curr->ports[0].or_flags = tcp_flags;
15616 + curr->tos = ip_hdr->tos;
15617 + curr->ttl = ip_hdr->ttl;
15620 + spin_unlock(&state.lock);
15624 + spin_unlock(&state.lock);
15628 +static int ipt_psd_checkentry(const char *tablename,
15629 + const struct ipt_ip *e,
15631 + unsigned int matchsize,
15632 + unsigned int hook_mask)
15634 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
15636 + /* we accept TCP only */
15637 +/* if (e->ip.proto != IPPROTO_TCP) { */
15638 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
15642 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
15643 + DEBUGP("PSD: matchsize %u != %u\n",
15645 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
15652 +static struct ipt_match ipt_psd_reg = {
15656 + ipt_psd_checkentry,
15660 +static int __init init(void)
15662 + if (ipt_register_match(&ipt_psd_reg))
15665 + memset(&state, 0, sizeof(state));
15667 + spin_lock_init(&(state.lock));
15669 + printk("netfilter PSD loaded - (c) astaro AG\n");
15673 +static void __exit fini(void)
15675 + ipt_unregister_match(&ipt_psd_reg);
15676 + printk("netfilter PSD unloaded - (c) astaro AG\n");
15679 +module_init(init);
15680 +module_exit(fini);
15681 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
15682 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
15683 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_quota.c 2003-12-10 23:13:42.204660000 +0100
15686 + * netfilter module to enforce network quotas
15688 + * Sam Johnston <samj@samj.net>
15690 +#include <linux/module.h>
15691 +#include <linux/skbuff.h>
15692 +#include <linux/spinlock.h>
15693 +#include <linux/interrupt.h>
15695 +#include <linux/netfilter_ipv4/ip_tables.h>
15696 +#include <linux/netfilter_ipv4/ipt_quota.h>
15698 +MODULE_LICENSE("GPL");
15700 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
15703 +match(const struct sk_buff *skb,
15704 + const struct net_device *in,
15705 + const struct net_device *out,
15706 + const void *matchinfo,
15707 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
15710 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
15712 + spin_lock_bh("a_lock);
15714 + if (q->quota >= datalen) {
15715 + /* we can afford this one */
15716 + q->quota -= datalen;
15717 + spin_unlock_bh("a_lock);
15719 +#ifdef DEBUG_IPT_QUOTA
15720 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
15725 + /* so we do not allow even small packets from now on */
15728 +#ifdef DEBUG_IPT_QUOTA
15729 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
15732 + spin_unlock_bh("a_lock);
15737 +checkentry(const char *tablename,
15738 + const struct ipt_ip *ip,
15739 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
15741 + /* TODO: spinlocks? sanity checks? */
15742 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
15748 +static struct ipt_match quota_match
15749 + = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
15754 + return ipt_register_match("a_match);
15757 +static void __exit
15760 + ipt_unregister_match("a_match);
15763 +module_init(init);
15764 +module_exit(fini);
15766 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
15767 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
15768 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_random.c 2003-12-10 23:13:44.404325600 +0100
15771 + This is a module which is used for a "random" match support.
15772 + This file is distributed under the terms of the GNU General Public
15773 + License (GPL). Copies of the GPL can be obtained from:
15774 + ftp://prep.ai.mit.edu/pub/gnu/GPL
15776 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
15779 +#include <linux/module.h>
15780 +#include <linux/skbuff.h>
15781 +#include <linux/ip.h>
15782 +#include <linux/random.h>
15783 +#include <net/tcp.h>
15784 +#include <linux/spinlock.h>
15785 +#include <linux/netfilter_ipv4/ip_tables.h>
15786 +#include <linux/netfilter_ipv4/ipt_random.h>
15788 +MODULE_LICENSE("GPL");
15791 +ipt_rand_match(const struct sk_buff *pskb,
15792 + const struct net_device *in,
15793 + const struct net_device *out,
15794 + const void *matchinfo,
15797 + u_int16_t datalen,
15800 + /* Parameters from userspace */
15801 + const struct ipt_rand_info *info = matchinfo;
15802 + u_int8_t random_number;
15804 + /* get 1 random number from the kernel random number generation routine */
15805 + get_random_bytes((void *)(&random_number), 1);
15807 + /* Do we match ? */
15808 + if (random_number <= info->average)
15815 +ipt_rand_checkentry(const char *tablename,
15816 + const struct ipt_ip *e,
15818 + unsigned int matchsize,
15819 + unsigned int hook_mask)
15821 + /* Parameters from userspace */
15822 + const struct ipt_rand_info *info = matchinfo;
15824 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
15825 + printk("ipt_random: matchsize %u != %u\n", matchsize,
15826 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
15830 + /* must be 1 <= average % <= 99 */
15831 + /* 1 x 2.55 = 2 */
15832 + /* 99 x 2.55 = 252 */
15833 + if ((info->average < 2) || (info->average > 252)) {
15834 + printk("ipt_random: invalid average %u\n", info->average);
15841 +static struct ipt_match ipt_rand_reg = {
15845 + ipt_rand_checkentry,
15849 +static int __init init(void)
15851 + if (ipt_register_match(&ipt_rand_reg))
15854 + printk("ipt_random match loaded\n");
15858 +static void __exit fini(void)
15860 + ipt_unregister_match(&ipt_rand_reg);
15861 + printk("ipt_random match unloaded\n");
15864 +module_init(init);
15865 +module_exit(fini);
15866 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
15867 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
15868 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_realm.c 2003-12-10 23:13:45.528154752 +0100
15870 +/* Kernel module to match realm from routing. */
15871 +#include <linux/module.h>
15872 +#include <linux/skbuff.h>
15873 +#include <linux/netdevice.h>
15874 +#include <net/route.h>
15876 +#include <linux/netfilter_ipv4/ipt_realm.h>
15877 +#include <linux/netfilter_ipv4/ip_tables.h>
15879 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
15880 +MODULE_LICENSE("GPL");
15883 +match(const struct sk_buff *skb,
15884 + const struct net_device *in,
15885 + const struct net_device *out,
15886 + const void *matchinfo,
15889 + u_int16_t datalen,
15892 + const struct ipt_realm_info *info = matchinfo;
15893 + struct dst_entry *dst = skb->dst;
15898 + id = dst->tclassid;
15900 + return (info->id == (id & info->mask)) ^ info->invert;
15903 +static int check(const char *tablename,
15904 + const struct ipt_ip *ip,
15906 + unsigned int matchsize,
15907 + unsigned int hook_mask)
15910 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
15911 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
15912 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
15913 + "LOCAL_IN or FORWARD.\n");
15917 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
15923 +static struct ipt_match realm_match
15924 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
15926 +static int __init init(void)
15928 + return ipt_register_match(&realm_match);
15931 +static void __exit fini(void)
15933 + ipt_unregister_match(&realm_match);
15936 +module_init(init);
15937 +module_exit(fini);
15938 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
15939 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_REJECT.c 2003-11-26 21:45:22.000000000 +0100
15940 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_REJECT.c 2003-12-10 23:14:20.643816360 +0100
15942 * This is a module which is used for rejecting packets.
15943 * Added support for customized reject packets (Jozsef Kadlecsik).
15944 * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812]
15945 + * Added support for fake source IP in icmp-unreach (Fabrice MARIE & Guillaume MORIN).
15947 #include <linux/config.h>
15948 #include <linux/module.h>
15949 @@ -204,13 +205,13 @@
15953 -static void send_unreach(struct sk_buff *skb_in, int code)
15954 +static void send_unreach(struct sk_buff *skb_in, int code, u_int8_t fake_source_address)
15957 struct udphdr *udph;
15958 struct icmphdr *icmph;
15959 struct sk_buff *nskb;
15961 + u32 saddr,packet_daddr;
15963 int hh_len, length;
15964 struct rtable *rt = (struct rtable*)skb_in->dst;
15965 @@ -274,7 +275,7 @@
15969 - saddr = iph->daddr;
15970 + packet_daddr = saddr = iph->daddr;
15971 if (!(rt->rt_flags & RTCF_LOCAL))
15974 @@ -322,7 +323,16 @@
15976 ip_select_ident(iph, &rt->u.dst, NULL);
15977 iph->protocol=IPPROTO_ICMP;
15978 - iph->saddr=rt->rt_src;
15980 + /* fake source IP if we have to
15981 + if fake_source_address == 1, we fake the source IP
15982 + from the packet destination address dynamically.
15984 + if (fake_source_address == 1)
15985 + iph->saddr = packet_daddr;
15987 + iph->saddr=rt->rt_src;
15989 iph->daddr=rt->rt_dst;
15991 iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
15992 @@ -370,25 +380,25 @@
15993 must return an absolute verdict. --RR */
15994 switch (reject->with) {
15995 case IPT_ICMP_NET_UNREACHABLE:
15996 - send_unreach(*pskb, ICMP_NET_UNREACH);
15997 + send_unreach(*pskb, ICMP_NET_UNREACH, reject->fake_source_address);
15999 case IPT_ICMP_HOST_UNREACHABLE:
16000 - send_unreach(*pskb, ICMP_HOST_UNREACH);
16001 + send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
16003 case IPT_ICMP_PROT_UNREACHABLE:
16004 - send_unreach(*pskb, ICMP_PROT_UNREACH);
16005 + send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
16007 case IPT_ICMP_PORT_UNREACHABLE:
16008 - send_unreach(*pskb, ICMP_PORT_UNREACH);
16009 + send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
16011 case IPT_ICMP_NET_PROHIBITED:
16012 - send_unreach(*pskb, ICMP_NET_ANO);
16013 + send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
16015 case IPT_ICMP_HOST_PROHIBITED:
16016 - send_unreach(*pskb, ICMP_HOST_ANO);
16017 + send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
16019 case IPT_ICMP_ADMIN_PROHIBITED:
16020 - send_unreach(*pskb, ICMP_PKT_FILTERED);
16021 + send_unreach(*pskb, ICMP_PKT_FILTERED, reject->fake_source_address);
16023 case IPT_TCP_RESET:
16024 send_reset(*pskb, hooknum);
16025 @@ -435,6 +445,11 @@
16026 DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
16029 + /* cannot fake source address */
16030 + if (rejinfo->fake_source_address != 0) {
16031 + DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
16037 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ROUTE.c
16038 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
16039 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ROUTE.c 2003-12-10 23:14:07.502814096 +0100
16042 + * This implements the ROUTE target, which enables you to setup unusual
16043 + * routes not supported by the standard kernel routing table.
16045 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
16047 + * v 1.8 2003/07/25
16049 + * This software is distributed under GNU GPL v2, 1991
16052 +#include <linux/module.h>
16053 +#include <linux/skbuff.h>
16054 +#include <linux/ip.h>
16055 +#include <linux/netfilter_ipv4/ip_tables.h>
16056 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
16057 +#include <linux/netdevice.h>
16058 +#include <linux/route.h>
16059 +#include <net/ip.h>
16060 +#include <net/route.h>
16061 +#include <net/icmp.h>
16064 +#define DEBUGP printk
16066 +#define DEBUGP(format, args...)
16070 +/* Try to route the packet according to the routing keys specified in
16071 + * route_info. Keys are :
16073 + * 0 if no oif preferred,
16074 + * otherwise set to the index of the desired oif
16075 + * - route_info->gw :
16076 + * 0 if no gateway specified,
16077 + * otherwise set to the next host to which the pkt must be routed
16078 + * If success, skb->dev is the output device to which the packet must
16079 + * be sent and skb->dst is not NULL
16081 + * RETURN: -1 if an error occured
16082 + * 1 if the packet was succesfully routed to the
16083 + * destination desired
16084 + * 0 if the kernel routing table could not route the packet
16085 + * according to the keys specified
16087 +static int route(struct sk_buff *skb,
16088 + unsigned int ifindex,
16089 + const struct ipt_route_target_info *route_info)
16092 + struct rtable *rt;
16093 + struct iphdr *iph = skb->nh.iph;
16094 + struct rt_key key = {
16098 + tos:RT_TOS(iph->tos)
16101 + /* The destination address may be overloaded by the target */
16102 + if (route_info->gw)
16103 + key.dst = route_info->gw;
16105 + /* Trying to route the packet using the standard routing table. */
16106 + if ((err = ip_route_output_key(&rt, &key))) {
16107 + if (net_ratelimit())
16108 + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
16112 + /* Drop old route. */
16113 + dst_release(skb->dst);
16116 + /* Success if no oif specified or if the oif correspond to the
16118 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
16119 + skb->dst = &rt->u.dst;
16120 + skb->dev = skb->dst->dev;
16124 + /* The interface selected by the routing table is not the one
16125 + * specified by the user. This may happen because the dst address
16126 + * is one of our own addresses.
16128 + if (net_ratelimit())
16129 + DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
16130 + NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
16136 +/* Stolen from ip_finish_output2
16137 + * PRE : skb->dev is set to the device we are leaving by
16138 + * skb->dst is not NULL
16139 + * POST: the packet is sent with the link layer header pushed
16140 + * the packet is destroyed
16142 +static void ip_direct_send(struct sk_buff *skb)
16144 + struct dst_entry *dst = skb->dst;
16145 + struct hh_cache *hh = dst->hh;
16148 + read_lock_bh(&hh->hh_lock);
16149 + memcpy(skb->data - 16, hh->hh_data, 16);
16150 + read_unlock_bh(&hh->hh_lock);
16151 + skb_push(skb, hh->hh_len);
16152 + hh->hh_output(skb);
16153 + } else if (dst->neighbour)
16154 + dst->neighbour->output(skb);
16156 + if (net_ratelimit())
16157 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
16163 +/* PRE : skb->dev is set to the device we are leaving by
16164 + * POST: - the packet is directly sent to the skb->dev device, without
16165 + * pushing the link layer header.
16166 + * - the packet is destroyed
16168 +static inline int dev_direct_send(struct sk_buff *skb)
16170 + return dev_queue_xmit(skb);
16174 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
16175 + struct sk_buff *skb)
16177 + unsigned int ifindex = 0;
16178 + struct net_device *dev_out = NULL;
16180 + /* The user set the interface name to use.
16181 + * Getting the current interface index.
16183 + if ((dev_out = dev_get_by_name(route_info->oif))) {
16184 + ifindex = dev_out->ifindex;
16186 + /* Unknown interface name : packet dropped */
16187 + if (net_ratelimit())
16188 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
16192 + /* Trying the standard way of routing packets */
16193 + switch (route(skb, ifindex, route_info)) {
16195 + dev_put(dev_out);
16196 + if (route_info->flags & IPT_ROUTE_CONTINUE)
16197 + return IPT_CONTINUE;
16199 + ip_direct_send(skb);
16200 + return NF_STOLEN;
16203 + /* Failed to send to oif. Trying the hard way */
16204 + if (route_info->flags & IPT_ROUTE_CONTINUE)
16207 + if (net_ratelimit())
16208 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
16211 + /* We have to force the use of an interface.
16212 + * This interface must be a tunnel interface since
16213 + * otherwise we can't guess the hw address for
16214 + * the packet. For a tunnel interface, no hw address
16217 + if ((dev_out->type != ARPHRD_TUNNEL)
16218 + && (dev_out->type != ARPHRD_IPGRE)) {
16219 + if (net_ratelimit())
16220 + DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
16221 + dev_put(dev_out);
16225 + /* Send the packet. This will also free skb
16226 + * Do not go through the POST_ROUTING hook because
16227 + * skb->dst is not set and because it will probably
16228 + * get confused by the destination IP address.
16230 + skb->dev = dev_out;
16231 + dev_direct_send(skb);
16232 + dev_put(dev_out);
16233 + return NF_STOLEN;
16236 + /* Unexpected error */
16237 + dev_put(dev_out);
16243 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
16244 + struct sk_buff *skb)
16246 + struct net_device *dev_out = NULL;
16247 + unsigned int ifindex = 0;
16249 + /* Getting the current interface index. */
16250 + if ((dev_out = dev_get_by_name(route_info->iif)))
16251 + ifindex = dev_out->ifindex;
16253 + /* Unknown interface name : packet dropped */
16254 + if (net_ratelimit())
16255 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
16259 + skb->dev = dev_out;
16260 + dst_release(skb->dst);
16265 + return NF_STOLEN;
16269 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
16270 + struct sk_buff *skb)
16272 + if (route(skb, 0, route_info)!=1)
16275 + if (route_info->flags & IPT_ROUTE_CONTINUE)
16276 + return IPT_CONTINUE;
16278 + ip_direct_send(skb);
16279 + return NF_STOLEN;
16283 +static unsigned int ipt_route_target(struct sk_buff **pskb,
16284 + unsigned int hooknum,
16285 + const struct net_device *in,
16286 + const struct net_device *out,
16287 + const void *targinfo,
16290 + const struct ipt_route_target_info *route_info = targinfo;
16291 + struct sk_buff *skb = *pskb;
16293 + /* If we are at PREROUTING or INPUT hook
16294 + * the TTL isn't decreased by the IP stack
16296 + if (hooknum == NF_IP_PRE_ROUTING ||
16297 + hooknum == NF_IP_LOCAL_IN) {
16299 + struct iphdr *iph = skb->nh.iph;
16301 + if (iph->ttl <= 1) {
16302 + struct rtable *rt;
16304 + if (ip_route_output(&rt, iph->saddr, iph->daddr,
16305 + RT_TOS(iph->tos) | RTO_CONN,
16310 + if (skb->dev == rt->u.dst.dev) {
16311 + /* Drop old route. */
16312 + dst_release(skb->dst);
16313 + skb->dst = &rt->u.dst;
16315 + /* this will traverse normal stack, and
16316 + * thus call conntrack on the icmp packet */
16317 + icmp_send(skb, ICMP_TIME_EXCEEDED,
16318 + ICMP_EXC_TTL, 0);
16324 + ip_decrease_ttl(iph);
16327 + /* Tell conntrack to forget this packet since it may get confused
16328 + * when a packet is leaving with dst address == our address.
16329 + * Good idea ? Dunno. Need advice.
16331 + if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
16332 + nf_conntrack_put(skb->nfct);
16333 + skb->nfct = NULL;
16334 + skb->nfcache = 0;
16335 +#ifdef CONFIG_NETFILTER_DEBUG
16336 + skb->nf_debug = 0;
16340 + if (route_info->oif[0])
16341 + return route_oif(route_info, *pskb);
16343 + if (route_info->iif[0])
16344 + return route_iif(route_info, *pskb);
16346 + if (route_info->gw)
16347 + return route_gw(route_info, *pskb);
16349 + if (net_ratelimit())
16350 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
16352 + return IPT_CONTINUE;
16356 +static int ipt_route_checkentry(const char *tablename,
16357 + const struct ipt_entry *e,
16359 + unsigned int targinfosize,
16360 + unsigned int hook_mask)
16362 + if (strcmp(tablename, "mangle") != 0) {
16363 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
16368 + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
16369 + | (1 << NF_IP_LOCAL_IN)
16370 + | (1 << NF_IP_FORWARD)
16371 + | (1 << NF_IP_LOCAL_OUT)
16372 + | (1 << NF_IP_POST_ROUTING))) {
16373 + printk("ipt_ROUTE: bad hook\n");
16377 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
16378 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
16380 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
16388 +static struct ipt_target ipt_route_reg
16389 += { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
16393 +static int __init init(void)
16395 + if (ipt_register_target(&ipt_route_reg))
16402 +static void __exit fini(void)
16404 + ipt_unregister_target(&ipt_route_reg);
16407 +module_init(init);
16408 +module_exit(fini);
16409 +MODULE_LICENSE("GPL");
16410 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
16411 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
16412 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_rpc.c 2003-12-10 23:14:10.155410840 +0100
16414 +/* RPC extension for IP connection matching, Version 2.2
16415 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
16416 + * - original rpc tracking module
16417 + * - "recent" connection handling for kernel 2.3+ netfilter
16419 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
16420 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
16422 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
16423 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
16424 + * - extended matching to support filtering on procedures
16426 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
16428 + * This program is free software; you can redistribute it and/or
16429 + * modify it under the terms of the GNU General Public License
16430 + * as published by the Free Software Foundation; either version
16431 + * 2 of the License, or (at your option) any later version.
16433 + * Module load syntax:
16434 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
16436 + * Please give the ports of all RPC servers you wish to connect to.
16437 + * If you don't specify ports, the default will be port 111.
16441 + * RPCs should not be exposed to the internet - ask the Pentagon;
16443 + * "The unidentified crackers pleaded guilty in July to charges
16444 + * of juvenile delinquency stemming from a string of Pentagon
16445 + * network intrusions in February.
16447 + * The youths, going by the names TooShort and Makaveli, used
16448 + * a common server security hole to break in, according to
16449 + * Dane Jasper, owner of the California Internet service
16450 + * provider, Sonic. They used the hole, known as the 'statd'
16451 + * exploit, to attempt more than 800 break-ins, Jasper said."
16453 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
16454 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
16458 +#include <linux/module.h>
16459 +#include <linux/skbuff.h>
16460 +#include <linux/list.h>
16461 +#include <linux/udp.h>
16462 +#include <linux/tcp.h>
16463 +#include <linux/netfilter_ipv4/ip_conntrack.h>
16464 +#include <linux/netfilter_ipv4/ip_tables.h>
16465 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
16466 +#include <linux/netfilter_ipv4/lockhelp.h>
16467 +#include <linux/netfilter_ipv4/ipt_rpc.h>
16469 +#define MAX_PORTS 8
16470 +static int ports[MAX_PORTS];
16471 +static int ports_n_c = 0;
16473 +#ifdef MODULE_PARM
16474 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
16475 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
16478 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
16479 +MODULE_DESCRIPTION("RPC connection matching module");
16480 +MODULE_LICENSE("GPL");
16483 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
16486 +#define DEBUGP(format, args...)
16489 +EXPORT_NO_SYMBOLS;
16491 +/* vars from ip_conntrack_rpc_tcp */
16492 +extern struct list_head request_p_list_tcp;
16493 +extern struct module *ip_conntrack_rpc_tcp;
16495 +/* vars from ip_conntrack_rpc_udp */
16496 +extern struct list_head request_p_list_udp;
16497 +extern struct module *ip_conntrack_rpc_udp;
16499 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
16500 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
16502 +#define ASSERT_READ_LOCK(x) \
16504 + if (x == &request_p_list_udp) \
16505 + MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
16506 + else if (x == &request_p_list_tcp) \
16507 + MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
16510 +#define ASSERT_WRITE_LOCK(x) \
16512 + if (x == &request_p_list_udp) \
16513 + MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
16514 + else if (x == &request_p_list_tcp) \
16515 + MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
16518 +#include <linux/netfilter_ipv4/listhelp.h>
16520 +const int IPT_RPC_CHAR_LEN = 11;
16523 +static int k_atoi(char *string)
16525 + unsigned int result = 0;
16526 + int maxoctet = IPT_RPC_CHAR_LEN;
16528 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
16531 + if (*string == 0)
16533 + if (*string < 48 || *string > 57) {
16536 + result = result * 10 + ( *string - 48 );
16542 +static int match_rpcs(char *c_procs, int i_procs, int proc)
16546 + unsigned int proc_num;
16548 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
16550 + if (i_procs == -1)
16553 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
16555 + proc_ptr = c_procs;
16556 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
16557 + proc_num = k_atoi(proc_ptr);
16559 + if (proc_num == proc)
16567 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
16568 + int *hotdrop, int dir, struct ip_conntrack *ct,
16569 + int offset, struct list_head request_p_list)
16571 + const struct ipt_rpc_info *rpcinfo = matchinfo;
16572 + struct request_p *req_p;
16579 + /* This does sanity checking on RPC payloads,
16580 + * and permits only the RPC "get port" (3)
16581 + * in authorised procedures in client
16582 + * communications with the portmapper.
16587 + /* Get RPC requestor */
16588 + if (IXDR_GET_INT32(data) != 3) {
16589 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
16590 + if(rpcinfo->strict == 1)
16594 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
16598 + /* Jump Credentials and Verfifier */
16599 + data = data + IXDR_GET_INT32(data) + 2;
16600 + data = data + IXDR_GET_INT32(data) + 2;
16602 + /* Get RPC procedure */
16603 + if (match_rpcs((char *)&rpcinfo->c_procs,
16604 + rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
16605 + DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
16606 + (unsigned int)IXDR_GET_INT32(data));
16608 + /* If the RPC conntrack half entry already exists .. */
16610 + switch (ct->tuplehash[0].tuple.dst.protonum) {
16611 + case IPPROTO_UDP:
16612 + WRITE_LOCK(&ipct_rpc_udp_lock);
16613 + case IPPROTO_TCP:
16614 + WRITE_LOCK(&ipct_rpc_tcp_lock);
16616 + req_p = LIST_FIND(&request_p_list, request_p_cmp,
16617 + struct request_p *, xid,
16618 + ct->tuplehash[dir].tuple.src.ip,
16619 + ct->tuplehash[dir].tuple.src.u.all);
16622 + DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16623 + xid, ct->tuplehash[dir].tuple.dst.protonum,
16624 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16625 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
16627 + /* .. remove it */
16628 + if (del_timer(&req_p->timeout))
16629 + req_p->timeout.expires = 0;
16631 + LIST_DELETE(&request_p_list, req_p);
16632 + DEBUGP("RPC req_p removed. [done]\n");
16635 + DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16636 + xid, ct->tuplehash[dir].tuple.dst.protonum,
16637 + NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16638 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
16641 + switch (ct->tuplehash[0].tuple.dst.protonum) {
16642 + case IPPROTO_UDP:
16643 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
16644 + case IPPROTO_TCP:
16645 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
16648 + if(rpcinfo->strict == 1)
16653 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
16654 + (unsigned int)IXDR_GET_INT32(data));
16655 + return (1 && (!offset));
16659 +static int match(const struct sk_buff *skb, const struct net_device *in,
16660 + const struct net_device *out, const void *matchinfo,
16661 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
16663 + struct ip_conntrack *ct;
16664 + enum ip_conntrack_info ctinfo;
16665 + const u_int32_t *data;
16666 + enum ip_conntrack_dir dir;
16667 + const struct tcphdr *tcp;
16668 + const struct ipt_rpc_info *rpcinfo = matchinfo;
16669 + int port, portsok;
16673 + DEBUGP("new packet to evaluate ..\n");
16675 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
16677 + DEBUGP("no ct available [skip]\n");
16681 + DEBUGP("ct detected. [cont]\n");
16682 + dir = CTINFO2DIR(ctinfo);
16684 + /* we only want the client to server packets for matching */
16685 + if (dir != IP_CT_DIR_ORIGINAL)
16688 + /* This does sanity checking on UDP or TCP packets,
16689 + * like their respective modules.
16692 + switch (ct->tuplehash[0].tuple.dst.protonum) {
16694 + case IPPROTO_UDP:
16695 + DEBUGP("PROTO_UDP [cont]\n");
16696 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
16697 + DEBUGP("packet does not contain a complete header. [drop]\n");
16701 + for (port=0,portsok=0; port <= ports_n_c; port++) {
16702 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16707 + if (portsok == 0) {
16708 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16709 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16713 + if ((datalen - sizeof(struct udphdr)) != 56) {
16714 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
16715 + if (rpcinfo->strict == 1)
16719 + DEBUGP("packet length is correct. [cont]\n");
16721 + /* Get to the data */
16722 + data = (const u_int32_t *)hdr + 2;
16724 + /* Check the RPC data */
16725 + tval = check_rpc_packet(data, matchinfo, hotdrop,
16727 + request_p_list_udp);
16732 + case IPPROTO_TCP:
16733 + DEBUGP("PROTO_TCP [cont]\n");
16734 + if (offset == 0 && datalen < sizeof(struct tcphdr)) {
16735 + DEBUGP("packet does not contain a complete header. [drop]\n");
16739 + for (port=0,portsok=0; port <= ports_n_c; port++) {
16740 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16745 + if (portsok == 0) {
16746 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16747 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16752 + if (datalen == (tcp->doff * 4)) {
16753 + DEBUGP("packet does not contain any data. [match]\n");
16754 + return (1 && (!offset));
16757 + /* Tests if packet len is ok */
16758 + if ((datalen - (tcp->doff * 4)) != 60) {
16759 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
16760 + if(rpcinfo->strict == 1)
16764 + DEBUGP("packet length is correct. [cont]\n");
16766 + /* Get to the data */
16767 + data = (const u_int32_t *)tcp + tcp->doff + 1;
16769 + /* Check the RPC data */
16770 + tval = check_rpc_packet(data, matchinfo, hotdrop,
16772 + request_p_list_tcp);
16778 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
16779 + ct->tuplehash[0].tuple.dst.protonum);
16784 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
16785 + unsigned int matchsize, unsigned int hook_mask)
16788 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
16789 + | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
16790 + printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
16794 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
16801 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
16802 + &match, &checkentry, NULL,
16806 +static int __init init(void)
16810 + DEBUGP("incrementing usage counts\n");
16811 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
16812 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
16814 + /* If no port given, default to standard RPC port */
16815 + if (ports[0] == 0)
16816 + ports[0] = RPC_PORT;
16818 + DEBUGP("registering match [%s] for;\n", rpc_match.name);
16819 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
16820 + DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
16824 + return ipt_register_match(&rpc_match);
16828 +static void fini(void)
16830 + DEBUGP("unregistering match\n");
16831 + ipt_unregister_match(&rpc_match);
16833 + DEBUGP("decrementing usage counts\n");
16834 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
16835 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
16839 +module_init(init);
16840 +module_exit(fini);
16842 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
16843 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
16844 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_sctp.c 2003-12-10 23:13:25.745162224 +0100
16846 +/* IP tables module for matching the SCTP header
16848 + * $ipt_sctp.c,v 1.3 2002/05/29 15:09:00 laforge Exp$
16850 + * (C) 2003 by Harald Welte <laforge@gnumonks.org>
16852 + * This software is distributed under the terms GNU GPL v2
16855 +#include <linux/module.h>
16856 +#include <linux/skbuff.h>
16857 +#include <linux/sctp.h>
16859 +#include <linux/netfilter_ipv4/ip_tables.h>
16860 +#include <linux/netfilter_ipv4/ipt_sctp.h>
16862 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
16863 +MODULE_DESCRIPTION("IP tables SCTP matching module");
16864 +MODULE_LICENSE("GPL");
16866 +/* Returns 1 if the port is matched by the range, 0 otherwise */
16868 +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
16872 + ret = (port >= min && port <= max) ^ invert;
16876 +static int chunk_match(const struct sk_buff *skb, u_int32_t chunks, u_int32_t chunk_mask)
16878 + sctp_chunkhdr_t *ch = (sctp_chunkhdr_t *) skb->data;
16880 + u_int32_t chunks_present = 0;
16883 + u_int8_t *ch_end;
16884 + ch_end = ((u_int8_t *) ch) + WORD_ROUND(ntohs(ch->length));
16886 + if (ch->type < 32)
16887 + chunks_present |= (1 << ch_type);
16888 + else if (ch->type == SCTP_CID_ASCONF)
16889 + chunks_present |= (1 << 31);
16890 + else if (ch->type == SCTP_CID_ASCONF_ACK)
16891 + chunks_present |= (1 << 30);
16893 + ch = (sctp_chunkhdr_t *) ch_end;
16894 + } while (ch_end < skb->tail);
16896 + return ((chunks_present& chunk_mask) == chunks);
16899 +static int match(const struct sk_buff *skb, const struct net_device *in,
16900 + const struct net_device *out, const void *matchinfo,
16901 + int offset, const void *hdr, u_int16_t datalen,
16904 + const struct ipt_sctp_info *info = matchinfo;
16905 + const struct iphdr *iph = skb->nh.iph;
16906 + const struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
16908 + if (iph->protocol != IPPROTO_SCTP)
16911 + if (offset == 1) {
16912 + duprintf("Dropping evil SCTP offset=1 frag.\n");
16915 + } else if (offset == 0 && datalen < sizeof(struct sctphdr)) {
16916 + /* We've been askd o examine this packet, and we can't.
16917 + * Hence, no choice but to drop. */
16918 + duprintf("Dropping evil SCTP offset=0 tinygram.\n");
16924 + && port_match(info->spts[0], info->spts[1],
16925 + ntohs(sh->source),
16926 + !!(info->invflags & IPT_SCTP_INV_SRCPT))
16927 + && port_match(info->dpts[0], info->dpts[1],
16929 + !!(info->invflags & IPT_SCTP_INV_DSTPT))
16930 + && chunk_match(skb, info->chunks, info->chunk_mask)
16934 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
16935 + void *matchinfo, unsigned int matchsize,
16936 + unsigned int hook_mask)
16938 + const struct ipt_sctp_info *info = matchinfo;
16940 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_sctp_info)))
16943 + if (ip->proto != IPPROTO_SCTP && !(ip->invflags & IPT_INV_PROTO))
16946 + if !(info->invflags & ~IPT_SCTP_INV_MASK)
16952 +static struct ipt_match sctp_match = {
16955 + .checkentry = &checkentry,
16956 + .me = THIS_MODULE,
16959 +static int __init init(void)
16961 + return ipt_register_match(&sctp_match);
16964 +static void __exit fini(void)
16966 + ipt_unregister_match(&sctp_match);
16969 +module_init(init);
16970 +module_exit(fini);
16971 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
16972 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_state.c 2003-11-26 21:46:07.000000000 +0100
16973 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_state.c 2003-12-10 23:13:24.664326536 +0100
16974 @@ -23,10 +23,12 @@
16975 enum ip_conntrack_info ctinfo;
16976 unsigned int statebit;
16978 - if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16979 - statebit = IPT_STATE_INVALID;
16981 + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
16982 + statebit = IPT_STATE_UNTRACKED;
16983 + else if (ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16984 statebit = IPT_STATE_BIT(ctinfo);
16986 + statebit = IPT_STATE_INVALID;
16988 return (sinfo->statemask & statebit);
16990 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_string.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_string.c
16991 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
16992 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_string.c 2003-12-10 23:14:14.165801168 +0100
16994 +/* Kernel module to match a string into a packet.
16996 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
16999 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
17000 + * Fixed SMP re-entrancy problem using per-cpu data areas
17001 + * for the skip/shift tables.
17002 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
17003 + * Fixed kernel panic, due to overrunning boyer moore string
17004 + * tables. Also slightly tweaked heuristic for deciding what
17005 + * search algo to use.
17006 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
17007 + * Implemented Boyer Moore Sublinear search algorithm
17008 + * alongside the existing linear search based on memcmp().
17009 + * Also a quick check to decide which method to use on a per
17013 +#include <linux/smp.h>
17014 +#include <linux/module.h>
17015 +#include <linux/skbuff.h>
17016 +#include <linux/file.h>
17017 +#include <net/sock.h>
17019 +#include <linux/netfilter_ipv4/ip_tables.h>
17020 +#include <linux/netfilter_ipv4/ipt_string.h>
17022 +MODULE_LICENSE("GPL");
17024 +struct string_per_cpu {
17030 +struct string_per_cpu *bm_string_data=NULL;
17032 +/* Boyer Moore Sublinear string search - VERY FAST */
17033 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
17035 + int M1, right_end, sk, sh;
17038 + int *skip, *shift, *len;
17040 + /* use data suitable for this CPU */
17041 + shift=bm_string_data[smp_processor_id()].shift;
17042 + skip=bm_string_data[smp_processor_id()].skip;
17043 + len=bm_string_data[smp_processor_id()].len;
17045 + /* Setup skip/shift tables */
17046 + M1 = right_end = needle_len-1;
17047 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
17048 + for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
17050 + for (i = 1; i < needle_len; i++) {
17051 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
17056 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
17057 + for (i = M1; i > 0; i--) shift[len[i]] = i;
17060 + for (i = 0; i < needle_len; i++) {
17061 + if (len[i] == M1 - i) ended = i;
17062 + if (ended) shift[i] = ended;
17065 + /* Do the search*/
17066 + while (right_end < haystack_len)
17068 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
17069 + if (i == needle_len) {
17070 + return haystack+(right_end - M1);
17073 + sk = skip[haystack[right_end - i]];
17075 + right_end = max(right_end - i + sk, right_end + sh);
17081 +/* Linear string search based on memcmp() */
17082 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
17084 + char *k = haystack + (haystack_len-needle_len);
17085 + char *t = haystack;
17087 + while ( t <= k ) {
17088 + if (memcmp(t, needle, needle_len) == 0)
17098 +match(const struct sk_buff *skb,
17099 + const struct net_device *in,
17100 + const struct net_device *out,
17101 + const void *matchinfo,
17104 + u_int16_t datalen,
17107 + const struct ipt_string_info *info = matchinfo;
17108 + struct iphdr *ip = skb->nh.iph;
17110 + char *needle, *haystack;
17111 + proc_ipt_search search=search_linear;
17113 + if ( !ip ) return 0;
17115 + /* get lenghts, and validate them */
17117 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
17118 + if ( nlen > hlen ) return 0;
17120 + needle=(char *)&info->string;
17121 + haystack=(char *)ip+(ip->ihl*4);
17123 + /* The sublinear search comes in to its own
17124 + * on the larger packets */
17125 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
17126 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
17127 + if ( hlen < BM_MAX_HLEN ) {
17128 + search=search_sublinear;
17130 + if (net_ratelimit())
17131 + printk(KERN_INFO "ipt_string: Packet too big "
17132 + "to attempt sublinear string search "
17133 + "(%d bytes)\n", hlen );
17137 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
17141 +checkentry(const char *tablename,
17142 + const struct ipt_ip *ip,
17144 + unsigned int matchsize,
17145 + unsigned int hook_mask)
17148 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
17154 +void string_freeup_data(void)
17158 + if ( bm_string_data ) {
17159 + for(c=0; c<smp_num_cpus; c++) {
17160 + if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
17161 + if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
17162 + if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
17164 + kfree(bm_string_data);
17168 +static struct ipt_match string_match
17169 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
17171 +static int __init init(void)
17177 + tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
17178 + alen=sizeof(int)*BM_MAX_HLEN;
17180 + /* allocate array of structures */
17181 + if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
17185 + memset(bm_string_data, 0, tlen);
17187 + /* allocate our skip/shift tables */
17188 + for(c=0; c<smp_num_cpus; c++) {
17189 + if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
17191 + if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
17193 + if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
17197 + return ipt_register_match(&string_match);
17200 + string_freeup_data();
17204 +static void __exit fini(void)
17206 + ipt_unregister_match(&string_match);
17207 + string_freeup_data();
17210 +module_init(init);
17211 +module_exit(fini);
17212 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TARPIT.c
17213 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
17214 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TARPIT.c 2003-12-10 23:14:01.536721080 +0100
17217 + * Kernel module to capture and hold incoming TCP connections using
17218 + * no local per-connection resources.
17220 + * Based on ipt_REJECT.c and offering functionality similar to
17221 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
17223 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
17225 + * This program is free software; you can redistribute it and/or modify
17226 + * it under the terms of the GNU General Public License as published by
17227 + * the Free Software Foundation; either version 2 of the License, or
17228 + * (at your option) any later version.
17230 + * This program is distributed in the hope that it will be useful,
17231 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17232 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17233 + * GNU General Public License for more details.
17235 + * You should have received a copy of the GNU General Public License
17236 + * along with this program; if not, write to the Free Software
17237 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17240 + * - Allow incoming TCP connections to be established.
17241 + * - Passing data should result in the connection being switched to the
17242 + * persist state (0 byte window), in which the remote side stops sending
17243 + * data and asks to continue every 60 seconds.
17244 + * - Attempts to shut down the connection should be ignored completely, so
17245 + * the remote side ends up having to time it out.
17248 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
17249 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
17250 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
17253 +#include <linux/config.h>
17254 +#include <linux/module.h>
17255 +#include <linux/skbuff.h>
17256 +#include <linux/ip.h>
17257 +#include <net/ip.h>
17258 +#include <net/tcp.h>
17259 +#include <net/icmp.h>
17261 +#include <net/route.h>
17262 +#include <linux/random.h>
17263 +#include <linux/netfilter_ipv4/ip_tables.h>
17266 +#define DEBUGP printk
17268 +#define DEBUGP(format, args...)
17272 +/* Stolen from ip_finish_output2 */
17273 +static int ip_direct_send(struct sk_buff *skb)
17275 + struct dst_entry *dst = skb->dst;
17276 + struct hh_cache *hh = dst->hh;
17279 + read_lock_bh(&hh->hh_lock);
17280 + memcpy(skb->data - 16, hh->hh_data, 16);
17281 + read_unlock_bh(&hh->hh_lock);
17282 + skb_push(skb, hh->hh_len);
17283 + return hh->hh_output(skb);
17284 + } else if (dst->neighbour)
17285 + return dst->neighbour->output(skb);
17287 + if (net_ratelimit())
17288 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
17295 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
17297 + struct sk_buff *nskb;
17298 + struct rtable *nrt;
17299 + struct tcphdr *otcph, *ntcph;
17300 + unsigned int otcplen;
17303 + /* A truncated TCP header isn't going to be useful */
17304 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
17307 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
17308 + + oskb->nh.iph->ihl);
17309 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
17311 + /* No replies for RST or FIN */
17312 + if (otcph->rst || otcph->fin)
17315 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
17316 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
17319 + /* Check checksum. */
17320 + if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
17321 + oskb->nh.iph->daddr,
17322 + csum_partial((char *)otcph, otcplen, 0)) != 0)
17325 + /* Copy skb (even if skb is about to be dropped, we can't just
17326 + clone it because there may be other things, such as tcpdump,
17327 + interested in it) */
17328 + nskb = skb_copy(oskb, GFP_ATOMIC);
17332 + /* This packet will not be the same as the other: clear nf fields */
17333 + nf_conntrack_put(nskb->nfct);
17334 + nskb->nfct = NULL;
17335 + nskb->nfcache = 0;
17336 +#ifdef CONFIG_NETFILTER_DEBUG
17337 + nskb->nf_debug = 0;
17340 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
17342 + /* Truncate to length (no data) */
17343 + ntcph->doff = sizeof(struct tcphdr)/4;
17344 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
17345 + nskb->nh.iph->tot_len = htons(nskb->len);
17347 + /* Swap source and dest */
17348 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
17349 + tmp = ntcph->source;
17350 + ntcph->source = ntcph->dest;
17351 + ntcph->dest = tmp;
17353 + /* Use supplied sequence number or make a new one */
17354 + ntcph->seq = otcph->ack ? otcph->ack_seq
17355 + : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
17356 + nskb->nh.iph->daddr,
17360 + /* Our SYN-ACKs must have a >0 window */
17361 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
17363 + ntcph->urg_ptr = 0;
17365 + /* Reset flags */
17366 + ((u_int8_t *)ntcph)[13] = 0;
17368 + if (otcph->syn && otcph->ack) {
17370 + ntcph->ack_seq = 0;
17372 + ntcph->syn = otcph->syn;
17374 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
17377 + /* Adjust TCP checksum */
17378 + ntcph->check = 0;
17379 + ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
17380 + nskb->nh.iph->saddr,
17381 + nskb->nh.iph->daddr,
17382 + csum_partial((char *)ntcph,
17383 + sizeof(struct tcphdr), 0));
17385 + /* Adjust IP TTL */
17386 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
17388 + /* Set DF, id = 0 */
17389 + nskb->nh.iph->frag_off = htons(IP_DF);
17390 + nskb->nh.iph->id = 0;
17392 + /* Adjust IP checksum */
17393 + nskb->nh.iph->check = 0;
17394 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
17395 + nskb->nh.iph->ihl);
17397 + if (ip_route_output(&nrt, nskb->nh.iph->daddr,
17398 + local ? nskb->nh.iph->saddr : 0,
17399 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
17403 + dst_release(nskb->dst);
17404 + nskb->dst = &nrt->u.dst;
17406 + /* "Never happens" */
17407 + if (nskb->len > nskb->dst->pmtu)
17410 + ip_direct_send (nskb);
17419 +static unsigned int tarpit(struct sk_buff **pskb,
17420 + unsigned int hooknum,
17421 + const struct net_device *in,
17422 + const struct net_device *out,
17423 + const void *targinfo,
17426 + struct sk_buff *skb = *pskb;
17427 + struct rtable *rt = (struct rtable*)skb->dst;
17429 + /* Do we have an input route cache entry? */
17433 + /* No replies to physical multicast/broadcast */
17434 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
17437 + /* Now check at the protocol level */
17438 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
17441 + /* Our naive response construction doesn't deal with IP
17442 + options, and probably shouldn't try. */
17443 + if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
17446 + /* We aren't interested in fragments */
17447 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
17450 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
17456 +static int check(const char *tablename,
17457 + const struct ipt_entry *e,
17459 + unsigned int targinfosize,
17460 + unsigned int hook_mask)
17462 + /* Only allow these for input/forward packet filtering. */
17463 + if (strcmp(tablename, "filter") != 0) {
17464 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
17467 + if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
17468 + | (1 << NF_IP_FORWARD))) != 0) {
17469 + DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
17473 + /* Must specify that it's a TCP packet */
17474 + if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
17475 + DEBUGP("TARPIT: not valid for non-tcp\n");
17482 +static struct ipt_target ipt_tarpit_reg
17483 += { { NULL, NULL }, "TARPIT", tarpit, check, NULL, THIS_MODULE };
17485 +static int __init init(void)
17487 + if (ipt_register_target(&ipt_tarpit_reg))
17492 +static void __exit fini(void)
17494 + ipt_unregister_target(&ipt_tarpit_reg);
17497 +module_init(init);
17498 +module_exit(fini);
17499 +MODULE_LICENSE("GPL");
17500 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
17501 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
17502 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TCPLAG.c 2003-12-10 23:14:16.741409616 +0100
17504 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
17505 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
17507 + * This program is free software; you can redistribute it and/or modify
17508 + * it under the terms of the GNU General Public License as published by
17509 + * the Free Software Foundation; either version 2 of the License, or
17510 + * (at your option) any later version.
17512 + * This program is distributed in the hope that it will be useful,
17513 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17514 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17515 + * GNU General Public License for more details.
17517 + * You should have received a copy of the GNU General Public License
17518 + * along with this program; if not, write to the Free Software
17519 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17523 + * This collects packets and attempts to make them into pairs
17524 + * based on its own knowledge of how typical network conversations
17525 + * operate. Once it has a pair, it logs the time between them.
17527 +#include <linux/module.h>
17528 +#include <linux/skbuff.h>
17529 +#include <linux/ip.h>
17530 +#include <linux/spinlock.h>
17531 +#include <net/icmp.h>
17532 +#include <net/udp.h>
17533 +#include <net/tcp.h>
17534 +#include <linux/netfilter_ipv4/ip_tables.h>
17536 +#include <net/route.h>
17537 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
17540 +#define DEBUGP printk
17542 +#define DEBUGP(format, args...)
17546 + * We need one spinlock for the hash table.
17548 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
17550 +typedef struct timeval timeval_T;
17553 + * Linked lists of events in the connection,
17554 + * these store the SEQ numbers and the newest is always
17555 + * at the start of the linked list, then they get older
17556 + * down to the end of the linked list (this is not perfect
17557 + * if packets get out of order but we don't worry about fine
17558 + * details like that).
17560 + * Matching any event wipes out that event and also all other
17561 + * events down the chain (i.e. all older events).
17562 + * This keeps the linked list as short as possible.
17564 +typedef struct tcplag_event_S
17566 + struct tcplag_event_S *next;
17569 + u32 expected_ACK;
17570 + struct timeval stamp;
17574 + * This stores the connection statistics
17575 + * We define connections more loosely than TCP/IP does,
17576 + * because we only consider the two hosts, not the ports
17577 + * Also, we list the host-pairs in low,high order which
17578 + * means that we don't care who originated the connection.
17580 +typedef struct tcplag_hash_S
17584 + struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
17585 + struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
17586 + tcplag_event_T *h_ACK_list; /* Try to match ACK packets coming from h in this list */
17587 + tcplag_event_T *l_ACK_list; /* Try to match ACK packets coming from l in this list */
17588 + time_t stamp; /* When this bucket got added to the table */
17589 + u16 count_l_SEQ_h_ACK; /* Increment for each event */
17590 + u16 count_h_SEQ_l_ACK; /* Increment for each event */
17593 +static tcplag_hash_T **hashtab = 0;
17594 +static u32 hashsize = 0;
17595 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
17596 +static u32 reaper_ix = 0;
17598 +static void divide_down( timeval_T *T, int c )
17603 + remainder = T->tv_sec % c; /* Only works properly with positive numbers */
17604 + remainder *= 1000000;
17605 + T->tv_usec == remainder;
17609 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
17613 + x = tv1->tv_sec - tv2->tv_sec;
17614 + if( x ) return( x );
17615 + x = tv1->tv_usec - tv2->tv_usec;
17619 +void sprint_timeval( char *buf, timeval_T *tv )
17622 + sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
17624 + sprintf( buf, "%lu", tv->tv_usec );
17628 + * This generates the log messages through printk()
17630 + * There is really no particular interest in the port numbers at this stage,
17631 + * they are only useful for matching up the request with the reply.
17632 + * The IP numbers are useful because some sites may be slower than others
17633 + * or may travel different routes, etc (OK, in theory changing the port number
17634 + * could also change the route but I don't like that sort of theory).
17638 + * LIP= The IP number of the side with the lowest lag
17639 + * RIP= The IP number of the side with the highest lag
17640 + * LLAG= The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
17641 + * RLAG= The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
17643 +static void output( tcplag_hash_T *H, int level, const char *prefix )
17645 + struct timeval ltm, rtm;
17646 + u32 local_ip, remote_ip;
17647 + char r_buf[ 20 ], l_buf[ 20 ];
17649 + * We can't make sense of a connection that only passes data one way,
17650 + * In principle, at least the SYN and FIN should go both ways so we
17651 + * should get a few hits for every connection.
17653 + if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
17655 + * Calculate average times by dividing down
17657 + divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
17658 + divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
17660 + * Sort these two by the lag so the the local is always the short lag
17662 + if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
17664 + local_ip = H->low_ip;
17665 + remote_ip = H->high_ip;
17666 + rtm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
17667 + rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
17668 + ltm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
17669 + ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
17673 + local_ip = H->high_ip;
17674 + remote_ip = H->low_ip;
17675 + ltm.tv_sec = H->lag_l_SEQ_h_ACK.tv_sec;
17676 + ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
17677 + rtm.tv_sec = H->lag_h_SEQ_l_ACK.tv_sec;
17678 + rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
17681 + * Don't use a spinlock on the output,
17682 + * it is not guaranteed safe because some OTHER printk could
17683 + * split our log message so we want only one single printk.
17685 + * We use sprintf() to partially pre-digest the output
17687 + * Actually, neither this not the main netfilter LOG target is
17688 + * really safe from printk() overlap, basically syslog cannot
17689 + * be regarded as a guaranteed data output channel. It is good
17690 + * enough for most purposes.
17692 + sprint_timeval( l_buf, <m );
17693 + sprint_timeval( r_buf, &rtm );
17694 + printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
17695 + level & 7, prefix,
17696 + NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
17701 + * The reaper rolls through the hash table looking for old.
17702 + * Log entries are only generated at the reaping time
17703 + * (which means all log entries are out-of-date)
17705 +static void reaper( time_t now, int level, const char *prefix )
17709 + now -= max_seconds;
17710 + if( !hashsize ) return;
17711 + if( !hashtab ) return;
17712 + for( i = 0; i < 10; i++ )
17714 + if( ++reaper_ix >= hashsize ) reaper_ix = 0;
17716 +// DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
17718 + if( hashtab[ reaper_ix ])
17720 + tcplag_hash_T *found = 0;
17722 + spin_lock_bh( &hash_lock );
17723 + if( hashtab[ reaper_ix ])
17725 + if( now > hashtab[ reaper_ix ]->stamp )
17727 + DEBUGP( KERN_WARNING "reaper found expired entry\n" );
17728 + found = hashtab[ reaper_ix ];
17729 + hashtab[ reaper_ix ] = 0;
17732 + spin_unlock_bh( &hash_lock );
17736 + output( found, level, prefix );
17744 + * Convert the connection characteristics into a number
17745 + * (not including the timestamp) FIXME: this is a sucky hash function
17747 +static u32 make_hash( tcplag_hash_T *connection )
17751 + r = connection->low_ip;
17752 + r += connection->high_ip;
17756 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
17760 + x = con1->low_ip - con2->low_ip; if( x ) return( x );
17761 + x = con1->high_ip - con2->high_ip;
17765 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
17769 + DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
17770 + x = ev1->expected_ACK - ev2->expected_ACK;
17771 + if( x ) return( x );
17772 + DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
17773 + x = ev1->source_port - ev2->source_port;
17774 + if( x ) return( x );
17775 + DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
17776 + x = ev1->dest_port - ev2->dest_port;
17781 + * Go to the hash table and either find an existing connection that
17782 + * matches correctly or inject a new connection into the table.
17783 + * Once the connection is OK, chain the event onto the linked list.
17785 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17789 + if( !event ) return; /* Just to be safe */
17790 + if( !hashsize ) return;
17791 + if( !hashtab ) return;
17793 + h = make_hash( connection );
17796 + DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
17798 + spin_lock_bh( &hash_lock );
17799 + for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
17801 + tcplag_hash_T *co_new = 0;
17803 + * Consider existing entry
17805 + if( hashtab[ h ])
17807 + if( compare_connections( hashtab[ h ], connection )) continue;
17808 + co_new = hashtab[ h ];
17809 + DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
17813 + * Use empty slot for new entry
17815 + if( !hashtab[ h ])
17817 + co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
17818 + memset( co_new, 0, sizeof( tcplag_hash_T ));
17819 + co_new->low_ip = connection->low_ip;
17820 + co_new->high_ip = connection->high_ip;
17821 + co_new->stamp = event->stamp.tv_sec;
17822 + hashtab[ h ] = co_new;
17823 + DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
17826 + tcplag_event_T *ev_new;
17828 + ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
17829 + memcpy( ev_new, event, sizeof( tcplag_event_T ));
17832 + ev_new->next = co_new->h_ACK_list;
17833 + co_new->h_ACK_list = ev_new;
17834 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
17838 + ev_new->next = co_new->l_ACK_list;
17839 + co_new->l_ACK_list = ev_new;
17840 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
17847 + spin_unlock_bh( &hash_lock );
17851 + * Search the hash table for a matching connection,
17852 + * if we can't find one of those then we are stuffed.
17854 + * Once a connection has been found, scan along the list for
17855 + * a matching SEQ number and if that is found then calculate
17856 + * the lag, update the counters and cut the chain at the
17857 + * point where the matching SEQ is found.
17859 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17863 + if( !event ) return( 0 );
17864 + if( !hashsize ) return( 0 );
17865 + if( !hashtab ) return( 0 );
17866 + h = make_hash( connection );
17869 + DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
17871 + for( i = 0; i < hashsize; i++ )
17873 + tcplag_hash_T *found = 0;
17875 + if( !hashtab[ h ]) return( 0 );
17877 + spin_lock_bh( &hash_lock );
17878 + if( hashtab[ h ])
17880 + if( !compare_connections( hashtab[ h ], connection ))
17882 + tcplag_event_T *ev, **evroot;
17886 + found = hashtab[ h ];
17889 + evroot = &found->h_ACK_list;
17890 + tv = &found->lag_l_SEQ_h_ACK;
17891 + cn = &found->count_l_SEQ_h_ACK;
17892 + DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
17896 + evroot = &found->l_ACK_list;
17897 + tv = &found->lag_h_SEQ_l_ACK;
17898 + cn = &found->count_h_SEQ_l_ACK;
17899 + DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
17901 + for( ev = *evroot; ev; ev = ev->next )
17903 + if( !compare_events( ev, event ))
17906 + * Calculate the lag (in two parts) and add that to the collection
17908 + event->stamp.tv_sec -= ev->stamp.tv_sec;
17909 + event->stamp.tv_usec -= ev->stamp.tv_usec;
17910 + if( event->stamp.tv_usec < 0 )
17912 + event->stamp.tv_usec += 1000000;
17913 + event->stamp.tv_sec++;
17915 + if( event->stamp.tv_sec < 0 )
17917 + DEBUGP( KERN_WARNING "Negative lag detected\n" );
17921 + tv->tv_sec += event->stamp.tv_sec;
17922 + tv->tv_usec += event->stamp.tv_usec;
17924 + DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
17925 + " (accumulator is up to %lu.%06lu, %u events)\n",
17926 + event->stamp.tv_sec,
17927 + event->stamp.tv_usec,
17928 + tv->tv_sec, tv->tv_usec, *cn );
17931 + * Truncate the linked list.
17933 + * Visit each event in the list and return the memory to the pool.
17935 + * If a host is making multiple connections to the same remote host
17936 + * then this truncation will result in some requests not being
17937 + * monitored. Statistically we will still get some reasonable number
17938 + * of measurements and multiple simultaneous connections between host
17939 + * pairs don't happen all that often.
17944 + tcplag_event_T *ev_next = ev->next;
17945 + DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
17950 + * TODO: overflow limit for *cn, force premature output() if necessary
17951 + * (and drop this connection from the hash table)
17960 + spin_unlock_bh( &hash_lock );
17962 + if( found ) return( 1 );
17963 + if( ++h >= hashsize ) h = 0;
17969 + * Here is our target data:
17971 + * pskb -- The packet itself (see linux/skbuff.h for breakdown)
17975 + * in -- The device that this packet came in on
17976 + * (depending on the chain this may or may not exist)
17978 + * out -- The device that this packet is just about to go
17979 + * out onto (again existance depends on the chain)
17981 + * targinfo -- Our private data (handed through from iptables command util)
17983 + * userinfo -- Some more data
17987 +static unsigned int target( struct sk_buff **pskb,
17988 + unsigned int hooknum,
17989 + const struct net_device *in,
17990 + const struct net_device *out,
17991 + const void *targinfo,
17994 + struct iphdr *iph = ( *pskb )->nh.iph;
17995 + const struct ipt_tcplag *el = targinfo;
17996 + tcplag_hash_T connection;
17997 + tcplag_event_T event;
18000 + * We know we are dealing with IP here
18001 + * Fill in all the obvious fields
18003 + if( iph->saddr > iph->daddr )
18006 + connection.high_ip = iph->saddr;
18007 + connection.low_ip = iph->daddr;
18012 + connection.low_ip = iph->saddr;
18013 + connection.high_ip = iph->daddr;
18015 + do_gettimeofday( &event.stamp );
18017 + * Do a bit of cleaning
18019 + reaper( event.stamp.tv_sec, el->level, el->prefix );
18021 + DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
18022 + event.stamp.tv_sec,
18023 + event.stamp.tv_usec,
18024 + in ? in->name : "none", out ? out->name : "none" );
18026 + * Now start looking at the details
18028 + * First step is to identify this packet to see if it is
18029 + * the sort of packet that we are interested in.
18030 + * Don't hold any locks while we are doing this because often
18031 + * we will just let the packet go without any further consideration.
18033 + switch( iph->protocol )
18035 + case IPPROTO_TCP:
18037 + struct tcphdr *tcp;
18039 + if( ntohs( iph->frag_off ) & IP_OFFSET )
18041 + DEBUGP( KERN_WARNING "ignoring fragment\n" );
18044 + tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
18045 + event.source_port = ntohs( tcp->source );
18046 + event.dest_port = ntohs( tcp->dest );
18048 + * Every packet should have a valid SEQ number so use this to
18049 + * generate an ACK number. This works along the formula:
18050 + * -- Start with the SEQ number
18051 + * -- For SYN or FIN add 1 to that number
18052 + * -- For data packet, add the data length to that number
18056 + * Data length requires a bit of fiddling around
18059 + unsigned int data_len;
18060 + if( tcp->syn || tcp->fin )
18062 + data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
18066 + data_len = ntohs( iph->tot_len );
18067 + data_len -= 4 * iph->ihl; /* Subtract away IP header & options */
18068 + data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
18071 + DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
18073 + if( data_len ) /* Only track events that demand an ACK */
18075 + event.expected_ACK = ntohl( tcp->seq ) + data_len;
18076 + hash_insert( &connection, &event, direction );
18080 + DEBUGP( "Don't bother to insert this, ACK not required\n" );
18087 + * Now we consider the matching of an existing event.
18088 + * Reverse the port numbers and change the ACK number to the actual ACK number
18089 + * Note that the direction is reversed because the reply will be going
18090 + * the opposite way to the request.
18092 + event.expected_ACK = ntohl( tcp->ack_seq );
18093 + event.dest_port = ntohs( tcp->source );
18094 + event.source_port = ntohs( tcp->dest );
18095 + request_complete( &connection, &event, !direction );
18099 + DEBUGP( "Don't bother to check this, ACK not valid\n" );
18103 + return( IPT_CONTINUE );
18107 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
18108 + * return( 1 ) if the entry is suitable
18114 + * targinfo -- Our private data block (handed to us from iptables plug-in)
18116 + * targinfosize -- The size of our private data block
18121 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
18122 + * all possible flag combos make sense. All we check for is correct data size.
18124 +static int checkentry( const char *tablename,
18125 + const struct ipt_entry *e,
18127 + unsigned int targinfosize,
18128 + unsigned int hook_mask )
18130 + const struct ipt_tcplag *el = targinfo;
18132 + if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
18134 + DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
18135 + IPT_ALIGN( sizeof( struct ipt_tcplag )));
18138 + if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
18142 +static struct ipt_target reg =
18152 +static int __init init( void )
18154 + if( ipt_register_target( ® )) return( -EINVAL );
18155 + hashsize = 123; /* should be configurable */
18156 + hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
18157 + memset( hashtab, 0, sizeof( void * ) * hashsize );
18162 + * This should not need locks (in theory)
18163 + * because it can only get punted after it is no longer
18164 + * chained into any of the netfilter lists.
18166 +static void __exit fini( void )
18170 + ipt_unregister_target( ® );
18172 + * Put back kernel memory
18174 + for( i = 0; i < hashsize; i++ )
18176 + tcplag_hash_T *p;
18178 + if(( p = hashtab[ i ]))
18180 + tcplag_event_T *ev, *evn;
18182 + hashtab[ i ] = 0;
18183 + for( ev = p->h_ACK_list; ev; ev = evn )
18188 + for( ev = p->l_ACK_list; ev; ev = evn )
18196 + kfree( hashtab );
18199 +module_init(init);
18200 +module_exit(fini);
18201 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
18202 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
18203 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_time.c 2003-12-10 23:13:47.815806976 +0100
18206 + This is a module which is used for time matching
18207 + It is using some modified code from dietlibc (localtime() function)
18208 + that you can find at http://www.fefe.de/dietlibc/
18209 + This file is distributed under the terms of the GNU General Public
18210 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
18211 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
18212 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
18213 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
18214 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
18215 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
18216 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
18219 +#include <linux/module.h>
18220 +#include <linux/skbuff.h>
18221 +#include <linux/netfilter_ipv4/ip_tables.h>
18222 +#include <linux/netfilter_ipv4/ipt_time.h>
18223 +#include <linux/time.h>
18225 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
18226 +MODULE_DESCRIPTION("Match arrival timestamp");
18227 +MODULE_LICENSE("GPL");
18231 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
18232 + int tm_min; /* Minutes. [0-59] */
18233 + int tm_hour; /* Hours. [0-23] */
18234 + int tm_mday; /* Day. [1-31] */
18235 + int tm_mon; /* Month. [0-11] */
18236 + int tm_year; /* Year - 1900. */
18237 + int tm_wday; /* Day of week. [0-6] */
18238 + int tm_yday; /* Days in year.[0-365] */
18239 + int tm_isdst; /* DST. [-1/0/1]*/
18241 + long int tm_gmtoff; /* we don't care, we count from GMT */
18242 + const char *tm_zone; /* we don't care, we count from GMT */
18246 +localtime(const time_t *timepr, struct tm *r);
18249 +match(const struct sk_buff *skb,
18250 + const struct net_device *in,
18251 + const struct net_device *out,
18252 + const void *matchinfo,
18255 + u_int16_t datalen,
18258 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
18259 + struct tm currenttime; /* time human readable */
18260 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
18261 + u_int16_t packet_time;
18262 + struct timeval kerneltimeval;
18263 + time_t packet_local_time;
18265 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
18266 + if (info->kerneltime)
18268 + do_gettimeofday(&kerneltimeval);
18269 + packet_local_time = kerneltimeval.tv_sec;
18272 + packet_local_time = skb->stamp.tv_sec;
18274 + /* Transform the timestamp of the packet, in a human readable form */
18275 + localtime(&packet_local_time, ¤ttime);
18277 + /* check if we match this timestamp, we start by the days... */
18278 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
18279 + return 0; /* the day doesn't match */
18281 + /* ... check the time now */
18282 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
18283 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
18286 + /* here we match ! */
18291 +checkentry(const char *tablename,
18292 + const struct ipt_ip *ip,
18294 + unsigned int matchsize,
18295 + unsigned int hook_mask)
18297 + struct ipt_time_info *info = matchinfo; /* match info for rule */
18299 + /* First, check that we are in the correct hook */
18300 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
18302 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
18304 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
18307 + /* we use the kerneltime if we are in forward or output */
18308 + info->kerneltime = 1;
18309 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
18310 + /* if not, we use the skb time */
18311 + info->kerneltime = 0;
18313 + /* Check the size */
18314 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
18316 + /* Now check the coherence of the data ... */
18317 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
18318 + (info->time_stop > 1439))
18320 + printk(KERN_WARNING "ipt_time: invalid argument\n");
18327 +static struct ipt_match time_match
18328 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
18330 +static int __init init(void)
18332 + printk("ipt_time loading\n");
18333 + return ipt_register_match(&time_match);
18336 +static void __exit fini(void)
18338 + ipt_unregister_match(&time_match);
18339 + printk("ipt_time unloaded\n");
18342 +module_init(init);
18343 +module_exit(fini);
18346 +/* The part below is borowed and modified from dietlibc */
18348 +/* seconds per day */
18349 +#define SPD 24*60*60
18352 +localtime(const time_t *timepr, struct tm *r) {
18355 + extern struct timezone sys_tz;
18356 + const unsigned int __spm[12] =
18362 + (31+28+31+30+31),
18363 + (31+28+31+30+31+30),
18364 + (31+28+31+30+31+30+31),
18365 + (31+28+31+30+31+30+31+31),
18366 + (31+28+31+30+31+30+31+31+30),
18367 + (31+28+31+30+31+30+31+31+30+31),
18368 + (31+28+31+30+31+30+31+31+30+31+30),
18370 + register time_t work;
18372 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
18373 + work=timep%(SPD);
18374 + r->tm_sec=work%60; work/=60;
18375 + r->tm_min=work%60; r->tm_hour=work/60;
18376 + work=timep/(SPD);
18377 + r->tm_wday=(4+work)%7;
18378 + for (i=1970; ; ++i) {
18379 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
18385 + r->tm_year=i-1900;
18386 + for (i=11; i && __spm[i]>work; --i) ;
18388 + r->tm_mday=work-__spm[i]+1;
18390 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
18391 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
18392 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TRACE.c 2003-12-10 23:13:24.663326688 +0100
18394 +/* This is a module which is used for setting
18395 + * the NFC_TRACE flag in the nfcache field of an skb.
18397 +#include <linux/module.h>
18398 +#include <linux/skbuff.h>
18400 +#include <linux/netfilter_ipv4/ip_tables.h>
18402 +static unsigned int
18403 +target(struct sk_buff **pskb,
18404 + const struct net_device *in,
18405 + const struct net_device *out,
18406 + unsigned int hooknum,
18407 + const void *targinfo,
18410 + (*pskb)->nfcache |= NFC_TRACE;
18411 + return IPT_CONTINUE;
18415 +checkentry(const char *tablename,
18416 + const struct ipt_entry *e,
18418 + unsigned int targinfosize,
18419 + unsigned int hook_mask)
18421 + if (targinfosize != 0) {
18422 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
18427 + if (strcmp(tablename, "raw") != 0) {
18428 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
18435 +static struct ipt_target ipt_trace_reg = {
18437 + .target = target,
18438 + .checkentry = checkentry,
18440 + .me = THIS_MODULE,
18443 +static int __init init(void)
18445 + if (ipt_register_target(&ipt_trace_reg))
18451 +static void __exit fini(void)
18453 + ipt_unregister_target(&ipt_trace_reg);
18456 +module_init(init);
18457 +module_exit(fini);
18458 +MODULE_LICENSE("GPL");
18459 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
18460 +MODULE_DESCRIPTION("IPv4 TRACE target");
18461 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
18462 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
18463 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TTL.c 2003-12-10 23:13:48.933637040 +0100
18465 +/* TTL modification target for IP tables
18466 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
18470 + * This software is distributed under the terms of GNU GPL
18473 +#include <linux/module.h>
18474 +#include <linux/skbuff.h>
18475 +#include <linux/ip.h>
18476 +#include <net/checksum.h>
18478 +#include <linux/netfilter_ipv4/ip_tables.h>
18479 +#include <linux/netfilter_ipv4/ipt_TTL.h>
18481 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
18482 +MODULE_DESCRIPTION("IP tables TTL modification module");
18483 +MODULE_LICENSE("GPL");
18485 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
18486 + const struct net_device *in, const struct net_device *out,
18487 + const void *targinfo, void *userinfo)
18489 + struct iphdr *iph = (*pskb)->nh.iph;
18490 + const struct ipt_TTL_info *info = targinfo;
18491 + u_int16_t diffs[2];
18494 + switch (info->mode) {
18495 + case IPT_TTL_SET:
18496 + new_ttl = info->ttl;
18498 + case IPT_TTL_INC:
18499 + new_ttl = iph->ttl + info->ttl;
18500 + if (new_ttl > 255)
18503 + case IPT_TTL_DEC:
18504 + new_ttl = iph->ttl + info->ttl;
18509 + new_ttl = iph->ttl;
18513 + if (new_ttl != iph->ttl) {
18514 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
18515 + iph->ttl = new_ttl;
18516 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
18517 + iph->check = csum_fold(csum_partial((char *)diffs,
18519 + iph->check^0xFFFF));
18520 + (*pskb)->nfcache |= NFC_ALTERED;
18523 + return IPT_CONTINUE;
18526 +static int ipt_ttl_checkentry(const char *tablename,
18527 + const struct ipt_entry *e,
18529 + unsigned int targinfosize,
18530 + unsigned int hook_mask)
18532 + struct ipt_TTL_info *info = targinfo;
18534 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
18535 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
18537 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
18541 + if (strcmp(tablename, "mangle")) {
18542 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
18546 + if (info->mode > IPT_TTL_MAXMODE) {
18547 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
18552 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
18553 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
18560 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
18561 + ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
18563 +static int __init init(void)
18565 + return ipt_register_target(&ipt_TTL);
18568 +static void __exit fini(void)
18570 + ipt_unregister_target(&ipt_TTL);
18573 +module_init(init);
18574 +module_exit(fini);
18575 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
18576 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
18577 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_u32.c 2003-12-10 23:13:50.006473944 +0100
18579 +/* Kernel module to match u32 packet content. */
18582 +U32 tests whether quantities of up to 4 bytes extracted from a packet
18583 +have specified values. The specification of what to extract is general
18584 +enough to find data at given offsets from tcp headers or payloads.
18587 + The argument amounts to a program in a small language described below.
18588 + tests := location = value | tests && location = value
18589 + value := range | value , range
18590 + range := number | number : number
18591 + a single number, n, is interpreted the same as n:n
18592 + n:m is interpreted as the range of numbers >=n and <=m
18593 + location := number | location operator number
18594 + operator := & | << | >> | @
18596 + The operators &, <<, >>, && mean the same as in c. The = is really a set
18597 + membership operator and the value syntax describes a set. The @ operator
18598 + is what allows moving to the next header and is described further below.
18600 + *** Until I can find out how to avoid it, there are some artificial limits
18601 + on the size of the tests:
18602 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
18603 + - no more than 10 ranges (and 9 commas) per value
18604 + - no more than 10 numbers (and 9 operators) per location
18606 + To describe the meaning of location, imagine the following machine that
18607 + interprets it. There are three registers:
18608 + A is of type char*, initially the address of the IP header
18609 + B and C are unsigned 32 bit integers, initially zero
18611 + The instructions are:
18612 + number B = number;
18613 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
18614 + &number C = C&number
18615 + <<number C = C<<number
18616 + >>number C = C>>number
18617 + @number A = A+C; then do the instruction number
18618 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
18619 + Otherwise the result of the computation is the final value of C.
18621 + Whitespace is allowed but not required in the tests.
18622 + However the characters that do occur there are likely to require
18623 + shell quoting, so it's a good idea to enclose the arguments in quotes.
18626 + match IP packets with total length >= 256
18627 + The IP header contains a total length field in bytes 2-3.
18628 + --u32 "0&0xFFFF=0x100:0xFFFF"
18630 + AND that with FFFF (giving bytes 2-3),
18631 + and test whether that's in the range [0x100:0xFFFF]
18633 +Example: (more realistic, hence more complicated)
18634 + match icmp packets with icmp type 0
18635 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
18636 + --u32 "6&0xFF=1 && ...
18637 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
18638 + Next test that it's not a fragment.
18639 + (If so it might be part of such a packet but we can't always tell.)
18640 + n.b. This test is generally needed if you want to match anything
18641 + beyond the IP header.
18642 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
18643 + packet (not a fragment). Alternatively, you can allow first fragments
18644 + by only testing the last 5 bits of byte 6.
18645 + ... 4&0x3FFF=0 && ...
18646 + Last test: the first byte past the IP header (the type) is 0
18647 + This is where we have to use the @syntax. The length of the IP header
18648 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
18649 + IP header itself.
18650 + ... 0>>22&0x3C@0>>24=0"
18651 + The first 0 means read bytes 0-3,
18652 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
18653 + the first byte, so only 22 bits is four times that plus a few more bits.
18654 + &3C then eliminates the two extra bits on the right and the first four
18655 + bits of the first byte.
18656 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
18657 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
18658 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
18659 + @ means to use this number as a new offset into the packet, and read
18660 + four bytes starting from there. This is the first 4 bytes of the icmp
18661 + payload, of which byte 0 is the icmp type. Therefore we simply shift
18662 + the value 24 to the right to throw out all but the first byte and compare
18663 + the result with 0.
18666 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
18667 + First we test that the packet is a tcp packet (similar to icmp).
18668 + --u32 "6&0xFF=6 && ...
18669 + Next, test that it's not a fragment (same as above).
18670 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
18671 + 0>>22&3C as above computes the number of bytes in the IP header.
18672 + @ makes this the new offset into the packet, which is the start of the
18673 + tcp header. The length of the tcp header (again in 32 bit words) is
18674 + the left half of byte 12 of the tcp header. The 12>>26&3C
18675 + computes this length in bytes (similar to the IP header before).
18676 + @ makes this the new offset, which is the start of the tcp payload.
18677 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
18678 + result is any of 1, 2, 5 or 8
18681 +#include <linux/module.h>
18682 +#include <linux/skbuff.h>
18684 +#include <linux/netfilter_ipv4/ipt_u32.h>
18685 +#include <linux/netfilter_ipv4/ip_tables.h>
18687 +/* #include <asm-i386/timex.h> for timing */
18689 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
18690 +MODULE_DESCRIPTION("IP tables u32 matching module");
18691 +MODULE_LICENSE("GPL");
18694 +match(const struct sk_buff *skb,
18695 + const struct net_device *in,
18696 + const struct net_device *out,
18697 + const void *matchinfo,
18700 + u_int16_t datalen,
18703 + const struct ipt_u32 *data = matchinfo;
18705 + unsigned char* origbase = (char*)skb->nh.iph;
18706 + unsigned char* base = origbase;
18707 + unsigned char* head = skb->head;
18708 + unsigned char* end = skb->end;
18709 + int nnums, nvals;
18710 + u_int32_t pos, val;
18711 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
18712 + cycles1 = get_cycles(); */
18714 + for (testind=0; testind < data->ntests; testind++) {
18715 + base = origbase; /* reset for each test */
18716 + pos = data->tests[testind].location[0].number;
18717 + if (base+pos+3 > end || base+pos < head)
18719 + val = (base[pos]<<24) + (base[pos+1]<<16) +
18720 + (base[pos+2]<<8) + base[pos+3];
18721 + nnums = data->tests[testind].nnums;
18722 + for (i=1; i < nnums; i++) {
18723 + u_int32_t number = data->tests[testind].location[i].number;
18724 + switch (data->tests[testind].location[i].nextop) {
18725 + case IPT_U32_AND:
18726 + val = val & number;
18728 + case IPT_U32_LEFTSH:
18729 + val = val << number;
18731 + case IPT_U32_RIGHTSH:
18732 + val = val >> number;
18735 + base = base + val;
18737 + if (base+pos+3 > end || base+pos < head)
18739 + val = (base[pos]<<24) + (base[pos+1]<<16) +
18740 + (base[pos+2]<<8) + base[pos+3];
18744 + nvals = data->tests[testind].nvalues;
18745 + for (i=0; i < nvals; i++) {
18746 + if ((data->tests[testind].value[i].min <= val) &&
18747 + (val <= data->tests[testind].value[i].max)) {
18751 + if (i >= data->tests[testind].nvalues) {
18752 + /* cycles2 = get_cycles();
18753 + printk("failed %d in %d cycles\n", testind,
18754 + cycles2-cycles1); */
18758 + /* cycles2 = get_cycles();
18759 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
18764 +checkentry(const char *tablename,
18765 + const struct ipt_ip *ip,
18767 + unsigned int matchsize,
18768 + unsigned int hook_mask)
18770 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
18775 +static struct ipt_match u32_match
18776 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
18778 +static int __init init(void)
18780 + return ipt_register_match(&u32_match);
18783 +static void __exit fini(void)
18785 + ipt_unregister_match(&u32_match);
18788 +module_init(init);
18789 +module_exit(fini);
18790 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
18791 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ULOG.c 2003-11-26 21:43:34.000000000 +0100
18792 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ULOG.c 2003-12-10 23:13:22.346678872 +0100
18794 #include <linux/netlink.h>
18795 #include <linux/netdevice.h>
18796 #include <linux/mm.h>
18797 +#include <linux/netfilter.h>
18798 #include <linux/netfilter_ipv4/ip_tables.h>
18799 #include <linux/netfilter_ipv4/ipt_ULOG.h>
18800 #include <linux/netfilter_ipv4/lockhelp.h>
18802 MODULE_PARM(flushtimeout, "i");
18803 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
18805 +static unsigned int nflog = 1;
18806 +MODULE_PARM(nflog, "i");
18807 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
18809 /* global data structures */
18812 @@ -152,17 +157,17 @@
18816 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
18817 - const struct net_device *in,
18818 - const struct net_device *out,
18819 - unsigned int hooknum,
18820 - const void *targinfo, void *userinfo)
18821 +static void ipt_ulog_packet(unsigned int hooknum,
18822 + const struct sk_buff *skb,
18823 + const struct net_device *in,
18824 + const struct net_device *out,
18825 + const struct ipt_ulog_info *loginfo,
18826 + const char *prefix)
18829 ulog_packet_msg_t *pm;
18830 size_t size, copy_len;
18831 struct nlmsghdr *nlh;
18832 - struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18834 /* ffs == find first bit set, necessary because userspace
18835 * is already shifting groupnumber, but we need unshifted.
18836 @@ -171,8 +176,8 @@
18838 /* calculate the size of the skb needed */
18839 if ((loginfo->copy_range == 0) ||
18840 - (loginfo->copy_range > (*pskb)->len)) {
18841 - copy_len = (*pskb)->len;
18842 + (loginfo->copy_range > skb->len)) {
18843 + copy_len = skb->len;
18845 copy_len = loginfo->copy_range;
18847 @@ -209,19 +214,21 @@
18849 /* copy hook, prefix, timestamp, payload, etc. */
18850 pm->data_len = copy_len;
18851 - pm->timestamp_sec = (*pskb)->stamp.tv_sec;
18852 - pm->timestamp_usec = (*pskb)->stamp.tv_usec;
18853 - pm->mark = (*pskb)->nfmark;
18854 + pm->timestamp_sec = skb->stamp.tv_sec;
18855 + pm->timestamp_usec = skb->stamp.tv_usec;
18856 + pm->mark = skb->nfmark;
18857 pm->hook = hooknum;
18858 - if (loginfo->prefix[0] != '\0')
18859 + if (prefix != NULL)
18860 + strncpy(pm->prefix, prefix, sizeof(pm->prefix));
18861 + else if (loginfo->prefix[0] != '\0')
18862 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
18864 *(pm->prefix) = '\0';
18866 if (in && in->hard_header_len > 0
18867 - && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
18868 + && skb->mac.raw != (void *) skb->nh.iph
18869 && in->hard_header_len <= ULOG_MAC_LEN) {
18870 - memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
18871 + memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
18872 pm->mac_len = in->hard_header_len;
18875 @@ -236,8 +243,8 @@
18877 pm->outdev_name[0] = '\0';
18879 - /* copy_len <= (*pskb)->len, so can't fail. */
18880 - if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
18881 + /* copy_len <= skb->len, so can't fail. */
18882 + if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
18885 /* check if we are building multi-part messages */
18886 @@ -261,8 +268,7 @@
18888 UNLOCK_BH(&ulog_lock);
18890 - return IPT_CONTINUE;
18895 PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
18896 @@ -271,8 +277,35 @@
18897 PRINTR("ipt_ULOG: Error building netlink message\n");
18899 UNLOCK_BH(&ulog_lock);
18902 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
18903 + const struct net_device *in,
18904 + const struct net_device *out,
18905 + unsigned int hooknum,
18906 + const void *targinfo, void *userinfo)
18908 + struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18910 - return IPT_CONTINUE;
18911 + ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
18913 + return IPT_CONTINUE;
18916 +static void ipt_logfn(unsigned int hooknum,
18917 + const struct sk_buff *skb,
18918 + const struct net_device *in,
18919 + const struct net_device *out,
18920 + const char *prefix)
18922 + struct ipt_ulog_info loginfo = {
18923 + .nl_group = NFLOG_DEFAULT_NLGROUP,
18925 + .qthreshold = NFLOG_DEFAULT_QTHRESHOLD,
18929 + ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
18932 static int ipt_ulog_checkentry(const char *tablename,
18933 @@ -337,6 +370,9 @@
18938 + nf_log_register(PF_INET, &ipt_logfn);
18943 @@ -347,6 +383,9 @@
18945 DEBUGP("ipt_ULOG: cleanup_module\n");
18948 + nf_log_unregister(PF_INET, &ipt_logfn);
18950 ipt_unregister_target(&ipt_ulog_reg);
18951 sock_release(nflognl->sk_socket);
18953 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
18954 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
18955 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_XOR.c 2003-12-10 23:14:18.224184200 +0100
18957 +/* XOR target for IP tables
18958 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
18959 + * Based on ipt_TTL.c
18963 + * This software is distributed under the terms of GNU GPL
18966 +#include <linux/module.h>
18967 +#include <linux/skbuff.h>
18968 +#include <linux/ip.h>
18969 +#include <linux/tcp.h>
18970 +#include <linux/udp.h>
18972 +#include <linux/netfilter_ipv4/ip_tables.h>
18973 +#include <linux/netfilter_ipv4/ipt_XOR.h>
18975 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
18976 +MODULE_DESCRIPTION("IP tables XOR module");
18977 +MODULE_LICENSE("GPL");
18979 +static unsigned int ipt_xor_target(struct sk_buff **pskb, unsigned int hooknum,
18980 + const struct net_device *in, const struct net_device *out,
18981 + const void *targinfo, void *userinfo)
18983 + struct ipt_XOR_info *info = (void *) targinfo;
18984 + struct iphdr *iph = (*pskb)->nh.iph;
18985 + struct tcphdr *tcph;
18986 + struct udphdr *udph;
18989 + if (iph->protocol == IPPROTO_TCP) {
18990 + tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
18991 + for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
18992 + for (k=0; k<=info->block_size; k++) {
18993 + (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
18998 + if (info->key[j] == 0x00)
19001 + } else if (iph->protocol == IPPROTO_UDP) {
19002 + udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
19003 + for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
19004 + for (k=0; k<=info->block_size; k++) {
19005 + (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
19010 + if (info->key[j] == 0x00)
19015 + return IPT_CONTINUE;
19018 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
19019 + void *targinfo, unsigned int targinfosize,
19020 + unsigned int hook_mask)
19022 + struct ipt_XOR_info *info = targinfo;
19024 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
19025 + printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
19026 + targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
19030 + if (strcmp(tablename, "mangle")) {
19031 + printk(KERN_WARNING "XOR: can only be called from"
19032 + "\"mangle\" table, not \"%s\"\n", tablename);
19036 + if (!strcmp(info->key, "")) {
19037 + printk(KERN_WARNING "XOR: You must specify a key");
19041 + if (info->block_size == 0) {
19042 + printk(KERN_WARNING "XOR: You must specify a block-size");
19049 +static struct ipt_target ipt_XOR = { { NULL, NULL }, "XOR",
19050 + ipt_xor_target, ipt_xor_checkentry, NULL, THIS_MODULE };
19052 +static int __init init(void)
19054 + return ipt_register_target(&ipt_XOR);
19057 +static void __exit fini(void)
19059 + ipt_unregister_target(&ipt_XOR);
19062 +module_init(init);
19063 +module_exit(fini);
19064 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig linux-2.6.0-test11/net/ipv4/netfilter/Kconfig
19065 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig 2003-11-26 21:45:21.000000000 +0100
19066 +++ linux-2.6.0-test11/net/ipv4/netfilter/Kconfig 2003-12-10 23:13:25.745162224 +0100
19067 @@ -197,6 +197,15 @@
19069 To compile it as a module, choose M here. If unsure, say N.
19071 +config IP_NF_MATCH_SCTP
19072 + tristate "SCTP match support"
19073 + depends on IP_NF_IPTABLES
19075 + This match allows iptables to match on the SCTP header.
19077 + If you want to compile it as a module, say M here and read
19078 + <file:Documentation/modules.txt>. If unsure, say `N'.
19080 config IP_NF_MATCH_LENGTH
19081 tristate "LENGTH match support"
19082 depends on IP_NF_IPTABLES
19083 @@ -527,6 +536,42 @@
19085 To compile it as a module, choose M here. If unsure, say N.
19088 + tristate "Raw table"
19089 + depends on IP_NF_IPTABLES
19091 + This option adds a `raw' table to iptables: see the man page for
19092 + iptables(8). This table is the very first in the netfilter
19093 + framework and hooks in at the PREROUTING and OUTPUT chains.
19094 + The TRACE and NOTRACK targets can be used in this table only.
19096 + To compile it as a module, choose M here. If unsure, say N.
19098 +config IP_NF_TARGET_TRACE
19099 + tristate "TRACE target support"
19100 + depends on IP_NF_RAW
19102 + The TRACE target allows packets to be traced as those matches
19103 + any subsequent rule in any table/rule. The matched rule and
19104 + the packet is logged with the prefix
19106 + TRACE: tablename/chainname/rulenum
19108 + if the ipt_LOG or ipt_ULOG targets are loaded in.
19110 + To compile it as a module, choose M here. If unsure, say N.
19112 +config IP_NF_TARGET_NOTRACK
19113 + tristate "NOTRACK target support"
19114 + depends on IP_NF_RAW
19116 + The NOTRACK target allows a select rule to specify which
19117 + packets *not* to enter the conntrack/NAT subsystems
19118 + with all the consequences (no ICMP error tracking,
19119 + no protocol helpers for the selected packets).
19121 + To compile it as a module, choose M here. If unsure, say N.
19123 config IP_NF_ARPTABLES
19124 tristate "ARP tables support"
19126 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile linux-2.6.0-test11/net/ipv4/netfilter/Makefile
19127 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile 2003-11-26 21:43:25.000000000 +0100
19128 +++ linux-2.6.0-test11/net/ipv4/netfilter/Makefile 2003-12-10 23:24:46.646649464 +0100
19129 @@ -19,37 +19,91 @@
19130 # connection tracking
19131 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
19133 +# talk protocol support
19134 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
19135 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
19139 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
19140 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
19143 # connection tracking helpers
19144 +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
19146 +# rtsp protocol support
19147 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
19148 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
19150 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
19151 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
19152 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
19153 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
19154 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
19155 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
19157 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
19159 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
19162 +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
19163 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
19164 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
19165 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
19166 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
19167 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
19168 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
19169 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
19171 # generic IP tables
19172 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
19174 -# the three instances of ip_tables
19175 +# the four instances of ip_tables
19176 obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
19177 obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
19178 obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
19179 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
19182 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
19184 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
19185 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
19186 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
19187 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
19188 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
19189 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
19190 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
19191 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
19192 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
19194 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
19195 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
19197 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
19199 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
19200 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
19201 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
19203 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
19206 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
19208 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
19210 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
19213 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
19215 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
19218 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
19220 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
19222 @@ -59,10 +113,18 @@
19224 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
19226 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
19229 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
19230 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
19231 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
19232 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
19233 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
19234 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
19235 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
19236 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
19237 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
19239 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
19241 @@ -72,15 +134,28 @@
19242 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
19243 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
19244 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
19245 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
19246 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
19247 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
19248 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
19249 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
19250 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
19251 obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
19252 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
19253 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
19254 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
19255 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
19256 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
19257 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
19258 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
19260 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
19262 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
19263 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
19264 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
19265 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
19266 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
19268 # generic ARP tables
19269 obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
19270 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
19271 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_filter.c 2003-11-26 21:42:56.000000000 +0100
19272 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_filter.c 2003-12-10 23:13:24.668325928 +0100
19275 sizeof(struct ip6t_entry),
19276 sizeof(struct ip6t_standard),
19277 - 0, { 0, 0 }, { } },
19278 + 0, NULL, 0, { 0, 0 }, { } },
19279 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19280 -NF_ACCEPT - 1 } },
19284 sizeof(struct ip6t_entry),
19285 sizeof(struct ip6t_standard),
19286 - 0, { 0, 0 }, { } },
19287 + 0, NULL, 0, { 0, 0 }, { } },
19288 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19289 -NF_ACCEPT - 1 } },
19293 sizeof(struct ip6t_entry),
19294 sizeof(struct ip6t_standard),
19295 - 0, { 0, 0 }, { } },
19296 + 0, NULL, 0, { 0, 0 }, { } },
19297 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19302 sizeof(struct ip6t_entry),
19303 sizeof(struct ip6t_error),
19304 - 0, { 0, 0 }, { } },
19305 + 0, NULL, 0, { 0, 0 }, { } },
19306 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19309 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
19310 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_mangle.c 2003-11-26 21:43:36.000000000 +0100
19311 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_mangle.c 2003-12-10 23:13:24.668325928 +0100
19314 sizeof(struct ip6t_entry),
19315 sizeof(struct ip6t_standard),
19316 - 0, { 0, 0 }, { } },
19317 + 0, NULL, 0, { 0, 0 }, { } },
19318 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19319 -NF_ACCEPT - 1 } },
19323 sizeof(struct ip6t_entry),
19324 sizeof(struct ip6t_standard),
19325 - 0, { 0, 0 }, { } },
19326 + 0, NULL, 0, { 0, 0 }, { } },
19327 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19328 -NF_ACCEPT - 1 } },
19332 sizeof(struct ip6t_entry),
19333 sizeof(struct ip6t_standard),
19334 - 0, { 0, 0 }, { } },
19335 + 0, NULL, 0, { 0, 0 }, { } },
19336 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19337 -NF_ACCEPT - 1 } },
19341 sizeof(struct ip6t_entry),
19342 sizeof(struct ip6t_standard),
19343 - 0, { 0, 0 }, { } },
19344 + 0, NULL, 0, { 0, 0 }, { } },
19345 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19346 -NF_ACCEPT - 1 } },
19350 sizeof(struct ip6t_entry),
19351 sizeof(struct ip6t_standard),
19352 - 0, { 0, 0 }, { } },
19353 + 0, NULL, 0, { 0, 0 }, { } },
19354 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19357 @@ -107,7 +107,7 @@
19359 sizeof(struct ip6t_entry),
19360 sizeof(struct ip6t_error),
19361 - 0, { 0, 0 }, { } },
19362 + 0, NULL, 0, { 0, 0 }, { } },
19363 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19366 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
19367 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_raw.c 1970-01-01 01:00:00.000000000 +0100
19368 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_raw.c 2003-12-10 23:13:24.668325928 +0100
19371 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
19373 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
19375 +#include <linux/module.h>
19376 +#include <linux/netfilter_ipv6/ip6_tables.h>
19378 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
19381 +#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
19383 +#define DEBUGP(x, args...)
19386 +/* Standard entry. */
19387 +struct ip6t_standard
19389 + struct ip6t_entry entry;
19390 + struct ip6t_standard_target target;
19393 +struct ip6t_error_target
19395 + struct ip6t_entry_target target;
19396 + char errorname[IP6T_FUNCTION_MAXNAMELEN];
19401 + struct ip6t_entry entry;
19402 + struct ip6t_error_target target;
19407 + struct ip6t_replace repl;
19408 + struct ip6t_standard entries[2];
19409 + struct ip6t_error term;
19410 +} initial_table __initdata
19411 += { { "raw", RAW_VALID_HOOKS, 3,
19412 + sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
19413 + { [NF_IP6_PRE_ROUTING] 0,
19414 + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
19415 + { [NF_IP6_PRE_ROUTING] 0,
19416 + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
19419 + /* PRE_ROUTING */
19420 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19422 + sizeof(struct ip6t_entry),
19423 + sizeof(struct ip6t_standard),
19424 + 0, NULL, 0, { 0, 0 }, { } },
19425 + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19426 + -NF_ACCEPT - 1 } },
19428 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19430 + sizeof(struct ip6t_entry),
19431 + sizeof(struct ip6t_standard),
19432 + 0, NULL, 0, { 0, 0 }, { } },
19433 + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19434 + -NF_ACCEPT - 1 } },
19437 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19439 + sizeof(struct ip6t_entry),
19440 + sizeof(struct ip6t_error),
19441 + 0, NULL, 0, { 0, 0 }, { } },
19442 + { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19449 +static struct ip6t_table packet_raw = {
19451 + .table = &initial_table.repl,
19452 + .valid_hooks = RAW_VALID_HOOKS,
19453 + .lock = RW_LOCK_UNLOCKED,
19454 + .me = THIS_MODULE
19457 +/* The work comes in here from netfilter.c. */
19458 +static unsigned int
19459 +ip6t_hook(unsigned int hook,
19460 + struct sk_buff **pskb,
19461 + const struct net_device *in,
19462 + const struct net_device *out,
19463 + int (*okfn)(struct sk_buff *))
19465 + return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
19468 +static struct nf_hook_ops ip6t_ops[] = {
19469 + { /* PRE_ROUTING */
19470 + .hook = ip6t_hook,
19471 + .owner = THIS_MODULE,
19473 + .hooknum = NF_IP6_PRE_ROUTING,
19474 + .priority = NF_IP6_PRI_FIRST,
19476 + { /* LOCAL_OUT */
19477 + .hook = ip6t_hook,
19478 + .owner = THIS_MODULE,
19480 + .hooknum = NF_IP6_LOCAL_OUT,
19481 + .priority = NF_IP6_PRI_FIRST,
19485 +static int __init init(void)
19489 + /* Register table */
19490 + ret = ip6t_register_table(&packet_raw);
19494 + /* Register hooks */
19495 + ret = nf_register_hook(&ip6t_ops[0]);
19497 + goto cleanup_table;
19499 + ret = nf_register_hook(&ip6t_ops[1]);
19501 + goto cleanup_hook0;
19506 + nf_unregister_hook(&ip6t_ops[0]);
19508 + ip6t_unregister_table(&packet_raw);
19513 +static void __exit fini(void)
19517 + for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
19518 + nf_unregister_hook(&ip6t_ops[i]);
19520 + ip6t_unregister_table(&packet_raw);
19523 +module_init(init);
19524 +module_exit(fini);
19525 +MODULE_LICENSE("GPL");
19526 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19527 +MODULE_DESCRIPTION("IPv6 raw table");
19528 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
19529 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6_tables.c 2003-11-26 21:45:30.000000000 +0100
19530 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6_tables.c 2003-12-10 23:13:24.667326080 +0100
19533 #include <linux/config.h>
19534 #include <linux/skbuff.h>
19535 +#include <linux/socket.h>
19536 #include <linux/kmod.h>
19537 #include <linux/vmalloc.h>
19538 #include <linux/netdevice.h>
19540 #include <asm/semaphore.h>
19541 #include <linux/proc_fs.h>
19543 +#include <linux/netfilter.h>
19544 #include <linux/netfilter_ipv6/ip6_tables.h>
19546 +static const char *hook6names[] = {
19547 + [NF_IP6_PRE_ROUTING] "PREROUTING",
19548 + [NF_IP6_LOCAL_IN] "INPUT",
19549 + [NF_IP6_FORWARD] "FORWARD",
19550 + [NF_IP6_LOCAL_OUT] "OUTPUT",
19551 + [NF_IP6_POST_ROUTING] "POSTROUTING",
19554 MODULE_LICENSE("GPL");
19555 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19556 MODULE_DESCRIPTION("IPv6 packet filter");
19557 @@ -403,6 +413,12 @@
19559 t = ip6t_get_target(e);
19560 IP_NF_ASSERT(t->u.kernel.target);
19562 + /* The packet traced and the rule isn't an unconditional return/END. */
19563 + if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
19564 + nf_log_packet(AF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
19565 + table->name, e->chainname, e->rulenum);
19567 /* Standard target? */
19568 if (!t->u.kernel.target->target) {
19570 @@ -556,6 +572,29 @@
19571 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
19575 +find_error_target(struct ip6t_entry *s,
19576 + struct ip6t_entry *e,
19577 + char **chainname)
19579 + struct ip6t_entry_target *t;
19580 + static struct ip6t_entry *found = NULL;
19585 + t = ip6t_get_target(found);
19586 + if (strcmp(t->u.user.name,
19587 + IP6T_ERROR_TARGET) == 0) {
19588 + *chainname = t->data;
19597 /* All zeroes == unconditional rule. */
19599 unconditional(const struct ip6t_ip6 *ipv6)
19600 @@ -575,6 +614,8 @@
19601 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
19604 + char *chainname = NULL;
19605 + u_int32_t rulenum;
19607 /* No recursion; use packet counter to save back ptrs (reset
19608 to 0 as we leave), and comefrom to save source hook bitmask */
19609 @@ -588,6 +629,8 @@
19611 /* Set initial back pointer. */
19612 e->counters.pcnt = pos;
19614 + chainname = (char *) hook6names[hook];
19617 struct ip6t_standard_target *t
19618 @@ -600,6 +643,8 @@
19621 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
19622 + e->rulenum = rulenum++;
19623 + e->chainname = chainname;
19625 /* Unconditional return/END. */
19626 if (e->target_offset == sizeof(struct ip6t_entry)
19627 @@ -609,6 +654,10 @@
19628 && unconditional(&e->ipv6)) {
19629 unsigned int oldpos, size;
19631 + /* Set unconditional rulenum to zero. */
19633 + e->counters.bcnt = 0;
19635 /* Return: backtrack through the last
19638 @@ -634,6 +683,11 @@
19639 (newinfo->entries + pos);
19640 } while (oldpos == pos + e->next_offset);
19642 + /* Restore chainname, rulenum. */
19643 + chainname = e->chainname;
19644 + rulenum = e->counters.bcnt;
19645 + e->counters.bcnt = 0;
19647 /* Move along one */
19648 size = e->next_offset;
19649 e = (struct ip6t_entry *)
19650 @@ -649,6 +703,17 @@
19651 /* This a jump; chase it. */
19652 duprintf("Jump rule %u -> %u\n",
19654 + e->counters.bcnt = rulenum++;
19656 + e = (struct ip6t_entry *)
19657 + (newinfo->entries + newpos);
19658 + if (IP6T_ENTRY_ITERATE(newinfo->entries,
19660 + find_error_target,
19661 + e, &chainname) == 0) {
19662 + printk("ip6_tables: table screwed up!\n");
19666 /* ... this is a fallthru */
19667 newpos = pos + e->next_offset;
19668 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
19669 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_condition.c 1970-01-01 01:00:00.000000000 +0100
19670 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_condition.c 2003-12-10 23:13:52.256131944 +0100
19672 +/*-------------------------------------------*\
19673 +| Netfilter Condition Module for IPv6 |
19675 +| Description: This module allows firewall |
19676 +| rules to match using condition variables |
19677 +| stored in /proc files. |
19679 +| Author: Stephane Ouellette 2003-02-10 |
19680 +| <ouellettes@videotron.ca> |
19682 +| This software is distributed under the |
19683 +| terms of the GNU GPL. |
19684 +\*-------------------------------------------*/
19686 +#include<linux/module.h>
19687 +#include<linux/proc_fs.h>
19688 +#include<linux/spinlock.h>
19689 +#include<linux/string.h>
19690 +#include<asm/atomic.h>
19691 +#include<linux/netfilter_ipv6/ip6_tables.h>
19692 +#include<linux/netfilter_ipv6/ip6t_condition.h>
19695 +#ifndef CONFIG_PROC_FS
19696 +#error "Proc file system support is required for this module"
19700 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
19701 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
19702 +MODULE_LICENSE("GPL");
19705 +struct condition_variable {
19706 + struct condition_variable *next;
19707 + struct proc_dir_entry *status_proc;
19708 + atomic_t refcount;
19709 + int enabled; /* TRUE == 1, FALSE == 0 */
19713 +static rwlock_t list_lock;
19714 +static struct condition_variable *head = NULL;
19715 +static struct proc_dir_entry *proc_net_condition = NULL;
19719 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
19720 + int length, int *eof, void *data)
19722 + struct condition_variable *var =
19723 + (struct condition_variable *) data;
19725 + if (offset == 0) {
19727 + buffer[0] = (var->enabled) ? '1' : '0';
19728 + buffer[1] = '\n';
19738 +ipt_condition_write_info(struct file *file, const char *buffer,
19739 + unsigned long length, void *data)
19741 + struct condition_variable *var =
19742 + (struct condition_variable *) data;
19745 + /* Match only on the first character */
19746 + switch (buffer[0]) {
19748 + var->enabled = 0;
19751 + var->enabled = 1;
19755 + return (int) length;
19760 +match(const struct sk_buff *skb, const struct net_device *in,
19761 + const struct net_device *out, const void *matchinfo, int offset,
19762 + const void *hdr, u_int16_t datalen, int *hotdrop)
19764 + const struct condition6_info *info =
19765 + (const struct condition6_info *) matchinfo;
19766 + struct condition_variable *var;
19767 + int condition_status = 0;
19769 + read_lock(&list_lock);
19771 + for (var = head; var; var = var->next) {
19772 + if (strcmp(info->name, var->status_proc->name) == 0) {
19773 + condition_status = var->enabled;
19778 + read_unlock(&list_lock);
19780 + return condition_status ^ info->invert;
19786 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
19787 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
19789 + struct condition6_info *info =
19790 + (struct condition6_info *) matchinfo;
19791 + struct condition_variable *var, *newvar;
19793 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19796 + /* The first step is to check if the condition variable already exists. */
19797 + /* Here, a read lock is sufficient because we won't change the list */
19798 + read_lock(&list_lock);
19800 + for (var = head; var; var = var->next) {
19801 + if (strcmp(info->name, var->status_proc->name) == 0) {
19802 + atomic_inc(&var->refcount);
19803 + read_unlock(&list_lock);
19808 + read_unlock(&list_lock);
19810 + /* At this point, we need to allocate a new condition variable */
19811 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
19816 + /* Create the condition variable's proc file entry */
19817 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
19819 + if (!newvar->status_proc) {
19821 + * There are two possibilities:
19822 + * 1- Another condition variable with the same name has been created, which is valid.
19823 + * 2- There was a memory allocation error.
19826 + read_lock(&list_lock);
19828 + for (var = head; var; var = var->next) {
19829 + if (strcmp(info->name, var->status_proc->name) == 0) {
19830 + atomic_inc(&var->refcount);
19831 + read_unlock(&list_lock);
19836 + read_unlock(&list_lock);
19840 + atomic_set(&newvar->refcount, 1);
19841 + newvar->enabled = 0;
19842 + newvar->status_proc->owner = THIS_MODULE;
19843 + newvar->status_proc->data = newvar;
19845 + newvar->status_proc->read_proc = ipt_condition_read_info;
19846 + newvar->status_proc->write_proc = ipt_condition_write_info;
19848 + write_lock(&list_lock);
19850 + newvar->next = head;
19853 + write_unlock(&list_lock);
19860 +destroy(void *matchinfo, unsigned int matchsize)
19862 + struct condition6_info *info =
19863 + (struct condition6_info *) matchinfo;
19864 + struct condition_variable *var, *prev = NULL;
19866 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19869 + write_lock(&list_lock);
19871 + for (var = head; var && strcmp(info->name, var->status_proc->name);
19872 + prev = var, var = var->next);
19874 + if (var && atomic_dec_and_test(&var->refcount)) {
19876 + prev->next = var->next;
19878 + head = var->next;
19880 + write_unlock(&list_lock);
19881 + remove_proc_entry(var->status_proc->name, proc_net_condition);
19884 + write_unlock(&list_lock);
19888 +static struct ip6t_match condition_match = {
19889 + .name = "condition",
19891 + .checkentry = &checkentry,
19892 + .destroy = &destroy,
19893 + .me = THIS_MODULE
19902 + rwlock_init(&list_lock);
19903 + proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
19905 + if (proc_net_condition) {
19906 + errorcode = ipt_register_match(&condition_match);
19909 + remove_proc_entry("ip6t_condition", proc_net);
19911 + errorcode = -EACCES;
19913 + return errorcode;
19917 +static void __exit
19920 + ipt_unregister_match(&condition_match);
19921 + remove_proc_entry("ip6t_condition", proc_net);
19924 +module_init(init);
19925 +module_exit(fini);
19926 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
19927 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
19928 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_fuzzy.c 2003-12-10 23:13:28.963672936 +0100
19931 + * This module implements a simple TSK FLC
19932 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
19933 + * to limit , in an adaptive and flexible way , the packet rate crossing
19934 + * a given stream . It serves as an initial and very simple (but effective)
19935 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
19936 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
19937 + * into our code in a precise , adaptive and efficient manner.
19938 + * The goal is very similar to that of "limit" match , but using techniques of
19939 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
19940 + * avoiding over and undershoots - and stuff like that .
19943 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
19944 + * 2002-08-17 : Changed to eliminate floating point operations .
19945 + * 2002-08-23 : Coding style changes .
19946 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
19949 +#include <linux/module.h>
19950 +#include <linux/skbuff.h>
19951 +#include <linux/ipv6.h>
19952 +#include <linux/random.h>
19953 +#include <net/tcp.h>
19954 +#include <linux/spinlock.h>
19955 +#include <linux/netfilter_ipv6/ip6_tables.h>
19956 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
19959 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
19960 + Expressed in percentage
19963 +#define PAR_LOW 1/100
19964 +#define PAR_HIGH 1
19966 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
19968 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
19969 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
19970 +MODULE_LICENSE("GPL");
19972 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19974 + if (tx >= maxi) return 100;
19976 + if (tx <= mini) return 0;
19978 + return ((100 * (tx-mini)) / (maxi-mini));
19981 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19983 + if (tx <= mini) return 100;
19985 + if (tx >= maxi) return 0;
19987 + return ((100 * (maxi - tx)) / (maxi - mini));
19992 +ip6t_fuzzy_match(const struct sk_buff *pskb,
19993 + const struct net_device *in,
19994 + const struct net_device *out,
19995 + const void *matchinfo,
19998 + u_int16_t datalen,
20001 + /* From userspace */
20003 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
20005 + u_int8_t random_number;
20006 + unsigned long amount;
20007 + u_int8_t howhigh, howlow;
20010 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
20012 + info->bytes_total += pskb->len;
20013 + info->packets_total++;
20015 + info->present_time = jiffies;
20017 + if (info->present_time >= info->previous_time)
20018 + amount = info->present_time - info->previous_time;
20020 + /* There was a transition : I choose to re-sample
20021 + and keep the old acceptance rate...
20025 + info->previous_time = info->present_time;
20026 + info->bytes_total = info->packets_total = 0;
20029 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
20031 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
20034 + info->previous_time = info->present_time;
20035 + info->bytes_total = info->packets_total = 0;
20037 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
20038 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
20040 + info->acceptance_rate = (u_int8_t) \
20041 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
20043 + /* In fact, the above defuzzification would require a denominator
20044 + * proportional to (howhigh+howlow) but, in this particular case,
20045 + * that expression is constant.
20046 + * An imediate consequence is that it is not necessary to call
20047 + * both mf_high and mf_low - but to keep things understandable,
20053 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
20056 + if (info->acceptance_rate < 100)
20058 + get_random_bytes((void *)(&random_number), 1);
20060 + /* If within the acceptance , it can pass => don't match */
20061 + if (random_number <= (255 * info->acceptance_rate) / 100)
20064 + return 1; /* It can't pass (It matches) */
20067 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
20072 +ip6t_fuzzy_checkentry(const char *tablename,
20073 + const struct ip6t_ip6 *ip,
20075 + unsigned int matchsize,
20076 + unsigned int hook_mask)
20079 + const struct ip6t_fuzzy_info *info = matchinfo;
20081 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
20082 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
20083 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
20087 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
20088 + || (info->minimum_rate >= info->maximum_rate)) {
20089 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
20096 +static struct ip6t_match ip6t_fuzzy_reg = {
20099 + ip6t_fuzzy_match,
20100 + ip6t_fuzzy_checkentry,
20104 +static int __init init(void)
20106 + if (ip6t_register_match(&ip6t_fuzzy_reg))
20112 +static void __exit fini(void)
20114 + ip6t_unregister_match(&ip6t_fuzzy_reg);
20117 +module_init(init);
20118 +module_exit(fini);
20119 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
20120 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
20121 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_HL.c 2003-12-10 23:13:31.108346896 +0100
20124 + * Hop Limit modification target for ip6tables
20125 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
20126 + * Based on HW's TTL module
20128 + * This software is distributed under the terms of GNU GPL
20131 +#include <linux/module.h>
20132 +#include <linux/skbuff.h>
20133 +#include <linux/ip.h>
20135 +#include <linux/netfilter_ipv6/ip6_tables.h>
20136 +#include <linux/netfilter_ipv6/ip6t_HL.h>
20138 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
20139 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
20140 +MODULE_LICENSE("GPL");
20142 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
20143 + const struct net_device *in, const struct net_device *out,
20144 + const void *targinfo, void *userinfo)
20146 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
20147 + const struct ip6t_HL_info *info = targinfo;
20148 + u_int16_t diffs[2];
20151 + switch (info->mode) {
20152 + case IP6T_HL_SET:
20153 + new_hl = info->hop_limit;
20155 + case IP6T_HL_INC:
20156 + new_hl = ip6h->hop_limit + info->hop_limit;
20157 + if (new_hl > 255)
20160 + case IP6T_HL_DEC:
20161 + new_hl = ip6h->hop_limit + info->hop_limit;
20166 + new_hl = ip6h->hop_limit;
20170 + if (new_hl != ip6h->hop_limit) {
20171 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
20172 + ip6h->hop_limit = new_hl;
20173 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
20176 + return IP6T_CONTINUE;
20179 +static int ip6t_hl_checkentry(const char *tablename,
20180 + const struct ip6t_entry *e,
20182 + unsigned int targinfosize,
20183 + unsigned int hook_mask)
20185 + struct ip6t_HL_info *info = targinfo;
20187 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
20188 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
20190 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
20194 + if (strcmp(tablename, "mangle")) {
20195 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
20199 + if (info->mode > IP6T_HL_MAXMODE) {
20200 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
20205 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
20206 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
20213 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
20214 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
20216 +static int __init init(void)
20218 + return ip6t_register_target(&ip6t_HL);
20221 +static void __exit fini(void)
20223 + ip6t_unregister_target(&ip6t_HL);
20226 +module_init(init);
20227 +module_exit(fini);
20228 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
20229 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_LOG.c 2003-11-26 21:43:30.000000000 +0100
20230 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_LOG.c 2003-12-10 23:13:22.347678720 +0100
20233 #include <linux/module.h>
20234 #include <linux/skbuff.h>
20235 +#include <linux/socket.h>
20236 #include <linux/ip.h>
20237 #include <linux/spinlock.h>
20238 #include <linux/icmpv6.h>
20239 #include <net/udp.h>
20240 #include <net/tcp.h>
20241 #include <net/ipv6.h>
20242 +#include <linux/netfilter.h>
20243 #include <linux/netfilter_ipv6/ip6_tables.h>
20245 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
20246 MODULE_DESCRIPTION("IP6 tables LOG target module");
20247 MODULE_LICENSE("GPL");
20249 +static unsigned int nflog = 1;
20250 +MODULE_PARM(nflog, "i");
20251 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
20254 #include <net/route.h>
20255 #include <linux/netfilter_ipv6/ip6t_LOG.h>
20256 @@ -256,40 +262,38 @@
20260 -static unsigned int
20261 -ip6t_log_target(struct sk_buff **pskb,
20262 - unsigned int hooknum,
20263 - const struct net_device *in,
20264 - const struct net_device *out,
20265 - const void *targinfo,
20268 +ip6t_log_packet(unsigned int hooknum,
20269 + const struct sk_buff *skb,
20270 + const struct net_device *in,
20271 + const struct net_device *out,
20272 + const struct ip6t_log_info *loginfo,
20273 + const char *level_string,
20274 + const char *prefix)
20276 - struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
20277 - const struct ip6t_log_info *loginfo = targinfo;
20278 - char level_string[4] = "< >";
20279 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
20281 - level_string[1] = '0' + (loginfo->level % 8);
20282 spin_lock_bh(&log_lock);
20283 printk(level_string);
20284 printk("%sIN=%s OUT=%s ",
20286 + prefix == NULL ? loginfo->prefix : prefix,
20287 in ? in->name : "",
20288 out ? out->name : "");
20290 /* MAC logging for input chain only. */
20292 - if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
20293 - if ((*pskb)->dev->type != ARPHRD_SIT){
20294 + if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
20295 + if (skb->dev->type != ARPHRD_SIT){
20297 - unsigned char *p = (*pskb)->mac.raw;
20298 - for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
20299 + unsigned char *p = skb->mac.raw;
20300 + for (i = 0; i < skb->dev->hard_header_len; i++,p++)
20301 printk("%02x%c", *p,
20302 - i==(*pskb)->dev->hard_header_len - 1
20303 + i==skb->dev->hard_header_len - 1
20307 - unsigned char *p = (*pskb)->mac.raw;
20308 - if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
20309 + unsigned char *p = skb->mac.raw;
20310 + if ( p - (ETH_ALEN*2+2) > skb->head ){
20312 for (i = 0; i < (ETH_ALEN); i++,p++)
20313 printk("%02x%s", *p,
20314 @@ -300,10 +304,10 @@
20315 i == ETH_ALEN-1 ? ' ' : ':');
20318 - if (((*pskb)->dev->addr_len == 4) &&
20319 - (*pskb)->dev->hard_header_len > 20){
20320 + if ((skb->dev->addr_len == 4) &&
20321 + skb->dev->hard_header_len > 20){
20323 - p = (*pskb)->mac.raw + 12;
20324 + p = skb->mac.raw + 12;
20325 for (i = 0; i < 4; i++,p++)
20326 printk("%3d%s", *p,
20327 i == 3 ? "->" : ".");
20328 @@ -319,10 +323,41 @@
20329 dump_packet(loginfo, ipv6h, 1);
20331 spin_unlock_bh(&log_lock);
20334 +static unsigned int
20335 +ip6t_log_target(struct sk_buff **pskb,
20336 + unsigned int hooknum,
20337 + const struct net_device *in,
20338 + const struct net_device *out,
20339 + const void *targinfo,
20342 + const struct ip6t_log_info *loginfo = targinfo;
20343 + char level_string[4] = "< >";
20345 + level_string[1] = '0' + (loginfo->level % 8);
20346 + ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
20348 return IP6T_CONTINUE;
20352 +ip6t_logfn(unsigned int hooknum,
20353 + const struct sk_buff *skb,
20354 + const struct net_device *in,
20355 + const struct net_device *out,
20356 + const char *prefix)
20358 + struct ip6t_log_info loginfo = {
20360 + .logflags = IP6T_LOG_MASK,
20364 + ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
20367 static int ip6t_log_checkentry(const char *tablename,
20368 const struct ip6t_entry *e,
20370 @@ -359,12 +394,17 @@
20372 if (ip6t_register_target(&ip6t_log_reg))
20375 + nf_log_register(PF_INET6, &ip6t_logfn);
20380 static void __exit fini(void)
20383 + nf_log_register(PF_INET6, &ip6t_logfn);
20385 ip6t_unregister_target(&ip6t_log_reg);
20388 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
20389 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
20390 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_nth.c 2003-12-10 23:13:36.623508464 +0100
20393 + This is a module which is used for match support for every Nth packet
20394 + This file is distributed under the terms of the GNU General Public
20395 + License (GPL). Copies of the GPL can be obtained from:
20396 + ftp://prep.ai.mit.edu/pub/gnu/GPL
20398 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20399 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
20400 + * added support for multiple counters
20401 + * added support for matching on individual packets
20402 + in the counter cycle
20403 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20407 +#include <linux/module.h>
20408 +#include <linux/skbuff.h>
20409 +#include <linux/ip.h>
20410 +#include <net/tcp.h>
20411 +#include <linux/spinlock.h>
20412 +#include <linux/netfilter_ipv6/ip6_tables.h>
20413 +#include <linux/netfilter_ipv6/ip6t_nth.h>
20415 +MODULE_LICENSE("GPL");
20418 + * State information.
20422 + u_int16_t number;
20425 +static struct state states[IP6T_NTH_NUM_COUNTERS];
20428 +ip6t_nth_match(const struct sk_buff *pskb,
20429 + const struct net_device *in,
20430 + const struct net_device *out,
20431 + const void *matchinfo,
20434 + u_int16_t datalen,
20437 + /* Parameters from userspace */
20438 + const struct ip6t_nth_info *info = matchinfo;
20439 + unsigned counter = info->counter;
20440 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
20442 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20446 + spin_lock(&states[counter].lock);
20448 + /* Are we matching every nth packet?*/
20449 + if (info->packet == 0xFF)
20451 + /* We're matching every nth packet and only every nth packet*/
20452 + /* Do we match or invert match? */
20453 + if (info->not == 0)
20455 + if (states[counter].number == 0)
20457 + ++states[counter].number;
20460 + if (states[counter].number >= info->every)
20461 + states[counter].number = 0; /* reset the counter */
20463 + ++states[counter].number;
20468 + if (states[counter].number == 0)
20470 + ++states[counter].number;
20473 + if (states[counter].number >= info->every)
20474 + states[counter].number = 0;
20476 + ++states[counter].number;
20482 + /* We're using the --packet, so there must be a rule for every value */
20483 + if (states[counter].number == info->packet)
20485 + /* only increment the counter when a match happens */
20486 + if (states[counter].number >= info->every)
20487 + states[counter].number = 0; /* reset the counter */
20489 + ++states[counter].number;
20497 + /* don't match */
20498 + spin_unlock(&states[counter].lock);
20502 + spin_unlock(&states[counter].lock);
20507 +ip6t_nth_checkentry(const char *tablename,
20508 + const struct ip6t_ip6 *e,
20510 + unsigned int matchsize,
20511 + unsigned int hook_mask)
20513 + /* Parameters from userspace */
20514 + const struct ip6t_nth_info *info = matchinfo;
20515 + unsigned counter = info->counter;
20516 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
20518 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20522 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
20523 + printk("nth: matchsize %u != %u\n", matchsize,
20524 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
20528 + states[counter].number = info->startat;
20533 +static struct ip6t_match ip6t_nth_reg = {
20537 + ip6t_nth_checkentry,
20541 +static int __init init(void)
20543 + unsigned counter;
20544 + memset(&states, 0, sizeof(states));
20545 + if (ip6t_register_match(&ip6t_nth_reg))
20548 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
20550 + spin_lock_init(&(states[counter].lock));
20553 + printk("ip6t_nth match loaded\n");
20557 +static void __exit fini(void)
20559 + ip6t_unregister_match(&ip6t_nth_reg);
20560 + printk("ip6t_nth match unloaded\n");
20563 +module_init(init);
20564 +module_exit(fini);
20565 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
20566 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_owner.c 2003-11-26 21:45:19.000000000 +0100
20567 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_owner.c 2003-12-10 23:14:05.029190144 +0100
20569 MODULE_LICENSE("GPL");
20572 +match_comm(const struct sk_buff *skb, const char *comm)
20574 + struct task_struct *p;
20575 + struct files_struct *files;
20578 + read_lock(&tasklist_lock);
20579 + for_each_task(p) {
20580 + if(strncmp(p->comm, comm, sizeof(p->comm)))
20584 + files = p->files;
20586 + read_lock(&files->file_lock);
20587 + for (i=0; i < files->max_fds; i++) {
20588 + if (fcheck_files(files, i) == skb->sk->socket->file) {
20589 + read_unlock(&files->file_lock);
20591 + read_unlock(&tasklist_lock);
20595 + read_unlock(&files->file_lock);
20599 + read_unlock(&tasklist_lock);
20604 match_pid(const struct sk_buff *skb, pid_t pid)
20606 struct task_struct *p;
20607 @@ -120,6 +152,12 @@
20611 + if(info->match & IP6T_OWNER_COMM) {
20612 + if (!match_comm(skb, info->comm) ^
20613 + !!(info->invert & IP6T_OWNER_COMM))
20620 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
20621 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
20622 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_random.c 2003-12-10 23:13:43.304492800 +0100
20625 + This is a module which is used for a "random" match support.
20626 + This file is distributed under the terms of the GNU General Public
20627 + License (GPL). Copies of the GPL can be obtained from:
20628 + ftp://prep.ai.mit.edu/pub/gnu/GPL
20630 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20631 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20634 +#include <linux/module.h>
20635 +#include <linux/skbuff.h>
20636 +#include <linux/ip.h>
20637 +#include <linux/random.h>
20638 +#include <net/tcp.h>
20639 +#include <linux/spinlock.h>
20640 +#include <linux/netfilter_ipv6/ip6_tables.h>
20641 +#include <linux/netfilter_ipv6/ip6t_random.h>
20643 +MODULE_LICENSE("GPL");
20646 +ip6t_rand_match(const struct sk_buff *pskb,
20647 + const struct net_device *in,
20648 + const struct net_device *out,
20649 + const void *matchinfo,
20652 + u_int16_t datalen,
20655 + /* Parameters from userspace */
20656 + const struct ip6t_rand_info *info = matchinfo;
20657 + u_int8_t random_number;
20659 + /* get 1 random number from the kernel random number generation routine */
20660 + get_random_bytes((void *)(&random_number), 1);
20662 + /* Do we match ? */
20663 + if (random_number <= info->average)
20670 +ip6t_rand_checkentry(const char *tablename,
20671 + const struct ip6t_ip6 *e,
20673 + unsigned int matchsize,
20674 + unsigned int hook_mask)
20676 + /* Parameters from userspace */
20677 + const struct ip6t_rand_info *info = matchinfo;
20679 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
20680 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
20681 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
20685 + /* must be 1 <= average % <= 99 */
20686 + /* 1 x 2.55 = 2 */
20687 + /* 99 x 2.55 = 252 */
20688 + if ((info->average < 2) || (info->average > 252)) {
20689 + printk("ip6t_random: invalid average %u\n", info->average);
20696 +static struct ip6t_match ip6t_rand_reg = {
20700 + ip6t_rand_checkentry,
20704 +static int __init init(void)
20706 + if (ip6t_register_match(&ip6t_rand_reg))
20709 + printk("ip6t_random match loaded\n");
20713 +static void __exit fini(void)
20715 + ip6t_unregister_match(&ip6t_rand_reg);
20716 + printk("ip6t_random match unloaded\n");
20719 +module_init(init);
20720 +module_exit(fini);
20721 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
20722 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
20723 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_REJECT.c 2003-12-10 23:13:46.680979496 +0100
20726 + * This is a module which is used for rejecting packets.
20727 + * Added support for customized reject packets (Jozsef Kadlecsik).
20728 + * Sun 12 Nov 2000
20729 + * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
20731 +#include <linux/config.h>
20732 +#include <linux/module.h>
20733 +#include <linux/skbuff.h>
20734 +#include <linux/icmpv6.h>
20735 +#include <net/tcp.h>
20736 +#include <linux/netfilter_ipv6/ip6_tables.h>
20737 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
20740 +#define DEBUGP printk
20742 +#define DEBUGP(format, args...)
20746 +/* Send RST reply */
20747 +static void send_reset(struct sk_buff *oldskb)
20749 + struct sk_buff *nskb;
20750 + struct tcphdr *otcph, *tcph;
20751 + struct rtable *rt;
20752 + unsigned int otcplen;
20755 + /* IP header checks: fragment, too short. */
20756 + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
20757 + || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
20760 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
20761 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
20763 + /* No RST for RST. */
20767 + /* Check checksum. */
20768 + if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
20769 + oldskb->nh.iph->daddr,
20770 + csum_partial((char *)otcph, otcplen, 0)) != 0)
20773 + /* Copy skb (even if skb is about to be dropped, we can't just
20774 + clone it because there may be other things, such as tcpdump,
20775 + interested in it) */
20776 + nskb = skb_copy(oldskb, GFP_ATOMIC);
20780 + /* This packet will not be the same as the other: clear nf fields */
20781 + nf_conntrack_put(nskb->nfct);
20782 + nskb->nfct = NULL;
20783 + nskb->nfcache = 0;
20784 +#ifdef CONFIG_NETFILTER_DEBUG
20785 + nskb->nf_debug = 0;
20788 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
20790 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
20791 + tcph->source = xchg(&tcph->dest, tcph->source);
20793 + /* Truncate to length (no data) */
20794 + tcph->doff = sizeof(struct tcphdr)/4;
20795 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
20796 + nskb->nh.iph->tot_len = htons(nskb->len);
20800 + tcph->seq = otcph->ack_seq;
20801 + tcph->ack_seq = 0;
20804 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
20805 + + otcplen - (otcph->doff<<2));
20809 + /* Reset flags */
20810 + ((u_int8_t *)tcph)[13] = 0;
20812 + tcph->ack = needs_ack;
20814 + tcph->window = 0;
20815 + tcph->urg_ptr = 0;
20817 + /* Adjust TCP checksum */
20819 + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
20820 + nskb->nh.iph->saddr,
20821 + nskb->nh.iph->daddr,
20822 + csum_partial((char *)tcph,
20823 + sizeof(struct tcphdr), 0));
20825 + /* Adjust IP TTL, DF */
20826 + nskb->nh.iph->ttl = MAXTTL;
20827 + /* Set DF, id = 0 */
20828 + nskb->nh.iph->frag_off = htons(IP_DF);
20829 + nskb->nh.iph->id = 0;
20831 + /* Adjust IP checksum */
20832 + nskb->nh.iph->check = 0;
20833 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
20834 + nskb->nh.iph->ihl);
20837 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
20838 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
20842 + dst_release(nskb->dst);
20843 + nskb->dst = &rt->u.dst;
20845 + /* "Never happens" */
20846 + if (nskb->len > nskb->dst->pmtu)
20849 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
20850 + ip_finish_output);
20858 +static unsigned int reject6_target(struct sk_buff **pskb,
20859 + unsigned int hooknum,
20860 + const struct net_device *in,
20861 + const struct net_device *out,
20862 + const void *targinfo,
20865 + const struct ip6t_reject_info *reject = targinfo;
20867 + /* WARNING: This code causes reentry within ip6tables.
20868 + This means that the ip6tables jump stack is now crap. We
20869 + must return an absolute verdict. --RR */
20870 + DEBUGP("REJECTv6: calling icmpv6_send\n");
20871 + switch (reject->with) {
20872 + case IP6T_ICMP6_NO_ROUTE:
20873 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
20875 + case IP6T_ICMP6_ADM_PROHIBITED:
20876 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
20878 + case IP6T_ICMP6_NOT_NEIGHBOUR:
20879 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
20881 + case IP6T_ICMP6_ADDR_UNREACH:
20882 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
20884 + case IP6T_ICMP6_PORT_UNREACH:
20885 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
20888 + case IPT_ICMP_ECHOREPLY: {
20889 + struct icmp6hdr *icmph = (struct icmphdr *)
20890 + ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
20891 + unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
20893 + /* Not non-head frags, or truncated */
20894 + if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
20895 + && datalen >= 4) {
20896 + /* Usually I don't like cut & pasting code,
20897 + but dammit, my party is starting in 45
20899 + struct icmp_bxm icmp_param;
20901 + icmp_param.icmph=*icmph;
20902 + icmp_param.icmph.type=ICMP_ECHOREPLY;
20903 + icmp_param.data_ptr=(icmph+1);
20904 + icmp_param.data_len=datalen;
20905 + icmp_reply(&icmp_param, *pskb);
20909 + case IPT_TCP_RESET:
20910 + send_reset(*pskb);
20914 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
20921 +static inline int find_ping_match(const struct ip6t_entry_match *m)
20923 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
20925 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
20926 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
20927 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
20933 +static int check(const char *tablename,
20934 + const struct ip6t_entry *e,
20936 + unsigned int targinfosize,
20937 + unsigned int hook_mask)
20939 + const struct ip6t_reject_info *rejinfo = targinfo;
20941 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
20942 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
20946 + /* Only allow these for packet filtering. */
20947 + if (strcmp(tablename, "filter") != 0) {
20948 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
20951 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
20952 + | (1 << NF_IP6_FORWARD)
20953 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
20954 + DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
20958 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
20959 + /* Must specify that it's an ICMP ping packet. */
20960 + if (e->ipv6.proto != IPPROTO_ICMPV6
20961 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20962 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
20965 + /* Must contain ICMP match. */
20966 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
20967 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
20970 + } else if (rejinfo->with == IP6T_TCP_RESET) {
20971 + /* Must specify that it's a TCP packet */
20972 + if (e->ipv6.proto != IPPROTO_TCP
20973 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20974 + DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
20982 +static struct ip6t_target ip6t_reject_reg
20983 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
20985 +static int __init init(void)
20987 + if (ip6t_register_target(&ip6t_reject_reg))
20992 +static void __exit fini(void)
20994 + ip6t_unregister_target(&ip6t_reject_reg);
20997 +module_init(init);
20998 +module_exit(fini);
20999 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
21000 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
21001 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_ROUTE.c 2003-12-10 23:14:08.745625160 +0100
21004 + * This implements the ROUTE v6 target, which enables you to setup unusual
21005 + * routes not supported by the standard kernel routing table.
21007 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
21009 + * v 1.0 2003/08/05
21011 + * This software is distributed under GNU GPL v2, 1991
21014 +#include <linux/module.h>
21015 +#include <linux/skbuff.h>
21016 +#include <linux/ipv6.h>
21017 +#include <linux/netfilter_ipv6/ip6_tables.h>
21018 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
21019 +#include <linux/netdevice.h>
21020 +#include <net/ipv6.h>
21021 +#include <net/ndisc.h>
21022 +#include <net/ip6_route.h>
21023 +#include <linux/icmpv6.h>
21026 +#define DEBUGP printk
21028 +#define DEBUGP(format, args...)
21031 +#define NIP6(addr) \
21032 + ntohs((addr).s6_addr16[0]), \
21033 + ntohs((addr).s6_addr16[1]), \
21034 + ntohs((addr).s6_addr16[2]), \
21035 + ntohs((addr).s6_addr16[3]), \
21036 + ntohs((addr).s6_addr16[4]), \
21037 + ntohs((addr).s6_addr16[5]), \
21038 + ntohs((addr).s6_addr16[6]), \
21039 + ntohs((addr).s6_addr16[7])
21041 +/* Route the packet according to the routing keys specified in
21042 + * route_info. Keys are :
21044 + * 0 if no oif preferred,
21045 + * otherwise set to the index of the desired oif
21046 + * - route_info->gw :
21047 + * 0 if no gateway specified,
21048 + * otherwise set to the next host to which the pkt must be routed
21049 + * If success, skb->dev is the output device to which the packet must
21050 + * be sent and skb->dst is not NULL
21052 + * RETURN: 1 if the packet was succesfully routed to the
21053 + * destination desired
21054 + * 0 if the kernel routing table could not route the packet
21055 + * according to the keys specified
21058 +route6(struct sk_buff *skb,
21059 + unsigned int ifindex,
21060 + const struct ip6t_route_target_info *route_info)
21062 + struct rt6_info *rt = NULL;
21063 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
21064 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
21066 + DEBUGP("ip6t_ROUTE: called with: ");
21067 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
21068 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
21069 + DEBUGP("OUT=%s\n", route_info->oif);
21071 + if (ipv6_addr_any(gw))
21072 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
21074 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
21079 + DEBUGP("ip6t_ROUTE: routing gives: ");
21080 + DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
21081 + DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
21082 + DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
21084 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
21085 + goto wrong_route;
21087 + if (!rt->rt6i_nexthop) {
21088 + DEBUGP("ip6t_ROUTE: discovering neighbour\n");
21089 + rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
21092 + /* Drop old route. */
21093 + dst_release(skb->dst);
21094 + skb->dst = &rt->u.dst;
21095 + skb->dev = rt->rt6i_dev;
21099 + dst_release(&rt->u.dst);
21101 + if (!net_ratelimit())
21104 + printk("ip6t_ROUTE: no explicit route found ");
21106 + printk("via interface %s ", route_info->oif);
21107 + if (!ipv6_addr_any(gw))
21108 + printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
21114 +/* Stolen from ip6_output_finish
21115 + * PRE : skb->dev is set to the device we are leaving by
21116 + * skb->dst is not NULL
21117 + * POST: the packet is sent with the link layer header pushed
21118 + * the packet is destroyed
21120 +static void ip_direct_send(struct sk_buff *skb)
21122 + struct dst_entry *dst = skb->dst;
21123 + struct hh_cache *hh = dst->hh;
21126 + read_lock_bh(&hh->hh_lock);
21127 + memcpy(skb->data - 16, hh->hh_data, 16);
21128 + read_unlock_bh(&hh->hh_lock);
21129 + skb_push(skb, hh->hh_len);
21130 + hh->hh_output(skb);
21131 + } else if (dst->neighbour)
21132 + dst->neighbour->output(skb);
21134 + if (net_ratelimit())
21135 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
21141 +static unsigned int
21142 +route6_oif(const struct ip6t_route_target_info *route_info,
21143 + struct sk_buff *skb)
21145 + unsigned int ifindex = 0;
21146 + struct net_device *dev_out = NULL;
21148 + /* The user set the interface name to use.
21149 + * Getting the current interface index.
21151 + if ((dev_out = dev_get_by_name(route_info->oif))) {
21152 + ifindex = dev_out->ifindex;
21154 + /* Unknown interface name : packet dropped */
21155 + if (net_ratelimit())
21156 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
21158 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
21159 + return IP6T_CONTINUE;
21164 + /* Trying the standard way of routing packets */
21165 + if (route6(skb, ifindex, route_info)) {
21166 + dev_put(dev_out);
21167 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
21168 + return IP6T_CONTINUE;
21170 + ip_direct_send(skb);
21171 + return NF_STOLEN;
21177 +static unsigned int
21178 +route6_gw(const struct ip6t_route_target_info *route_info,
21179 + struct sk_buff *skb)
21181 + if (route6(skb, 0, route_info)) {
21182 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
21183 + return IP6T_CONTINUE;
21185 + ip_direct_send(skb);
21186 + return NF_STOLEN;
21192 +static unsigned int
21193 +ip6t_route_target(struct sk_buff **pskb,
21194 + unsigned int hooknum,
21195 + const struct net_device *in,
21196 + const struct net_device *out,
21197 + const void *targinfo,
21200 + const struct ip6t_route_target_info *route_info = targinfo;
21201 + struct sk_buff *skb = *pskb;
21202 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
21204 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
21207 + /* If we are at PREROUTING or INPUT hook
21208 + * the TTL isn't decreased by the IP stack
21210 + if (hooknum == NF_IP6_PRE_ROUTING ||
21211 + hooknum == NF_IP6_LOCAL_IN) {
21213 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
21215 + if (ipv6h->hop_limit <= 1) {
21216 + /* Force OUTPUT device used as source address */
21217 + skb->dev = skb->dst->dev;
21219 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
21220 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
21225 + ipv6h->hop_limit--;
21230 + if (route_info->oif[0])
21231 + return route6_oif(route_info, *pskb);
21233 + if (!ipv6_addr_any(gw))
21234 + return route6_gw(route_info, *pskb);
21236 + if (net_ratelimit())
21237 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
21239 + return IP6T_CONTINUE;
21244 +ip6t_route_checkentry(const char *tablename,
21245 + const struct ip6t_entry *e,
21247 + unsigned int targinfosize,
21248 + unsigned int hook_mask)
21250 + if (strcmp(tablename, "mangle") != 0) {
21251 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
21255 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
21256 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
21258 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
21266 +static struct ip6t_target ip6t_route_reg = {
21268 + .target = ip6t_route_target,
21269 + .checkentry = ip6t_route_checkentry,
21270 + .me = THIS_MODULE
21274 +static int __init init(void)
21276 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
21277 + if (ip6t_register_target(&ip6t_route_reg))
21284 +static void __exit fini(void)
21286 + ip6t_unregister_target(&ip6t_route_reg);
21289 +module_init(init);
21290 +module_exit(fini);
21291 +MODULE_LICENSE("GPL");
21292 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
21293 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
21294 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_TRACE.c 2003-12-10 23:13:24.667326080 +0100
21296 +/* This is a module which is used for setting
21297 + * the NFC_TRACE flag in the nfcache field of an skb.
21299 +#include <linux/module.h>
21300 +#include <linux/skbuff.h>
21302 +#include <linux/netfilter_ipv6/ip6_tables.h>
21304 +static unsigned int
21305 +target(struct sk_buff **pskb,
21306 + unsigned int hooknum,
21307 + const struct net_device *in,
21308 + const struct net_device *out,
21309 + const void *targinfo,
21312 + (*pskb)->nfcache |= NFC_TRACE;
21313 + return IP6T_CONTINUE;
21317 +checkentry(const char *tablename,
21318 + const struct ip6t_entry *e,
21320 + unsigned int targinfosize,
21321 + unsigned int hook_mask)
21323 + if (targinfosize != 0) {
21324 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
21329 + if (strcmp(tablename, "raw") != 0) {
21330 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
21337 +static struct ip6t_target ip6t_trace_reg = {
21339 + .target = target,
21340 + .checkentry = checkentry,
21342 + .me = THIS_MODULE,
21345 +static int __init init(void)
21347 + if (ip6t_register_target(&ip6t_trace_reg))
21353 +static void __exit fini(void)
21355 + ip6t_unregister_target(&ip6t_trace_reg);
21358 +module_init(init);
21359 +module_exit(fini);
21361 +MODULE_LICENSE("GPL");
21362 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21363 +MODULE_DESCRIPTION("IPv6 TRACE target");
21365 \ Brak znaku nowej linii na koƱcu pliku
21366 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig linux-2.6.0-test11/net/ipv6/netfilter/Kconfig
21367 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig 2003-11-26 21:45:28.000000000 +0100
21368 +++ linux-2.6.0-test11/net/ipv6/netfilter/Kconfig 2003-12-10 23:13:24.665326384 +0100
21369 @@ -217,6 +217,31 @@
21371 To compile it as a module, choose M here. If unsure, say N.
21374 + tristate "Raw table"
21375 + depends on IP6_NF_IPTABLES
21377 + This option adds a `raw' table to iptables: see the man page for
21378 + iptables(8). This table is the very first in the netfilter
21379 + framework and hooks in at the PREROUTING and OUTPUT chains.
21380 + The TRACE target can be used in this table only.
21382 + To compile it as a module, choose M here. If unsure, say N.
21384 +config IP6_NF_TARGET_TRACE
21385 + tristate "TRACE target support"
21386 + depends on IP6_NF_RAW
21388 + The TRACE target allows packets to be traced as those matches
21389 + any subsequent rule in any IPv6 netfilter table/rule. The matched
21390 + rule and the packet is logged with the prefix
21392 + TRACE: tablename/chainname/rulenum
21394 + if the ip6t_LOG target is loaded in.
21396 + To compile it as a module, choose M here. If unsure, say N.
21398 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
21401 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile linux-2.6.0-test11/net/ipv6/netfilter/Makefile
21402 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile 2003-11-26 21:44:26.000000000 +0100
21403 +++ linux-2.6.0-test11/net/ipv6/netfilter/Makefile 2003-12-10 23:14:08.816614368 +0100
21405 obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
21406 obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
21407 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
21408 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
21409 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
21410 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
21411 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
21412 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
21413 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
21414 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
21416 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
21417 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
21418 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
21419 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
21420 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
21421 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
21422 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
21423 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
21424 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
21426 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
21428 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
21429 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
21430 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
21431 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
21432 diff -Nur linux-2.6.0-test11.org/netfilter-patch-o-matic/patches linux-2.6.0-test11/netfilter-patch-o-matic/patches
21433 --- linux-2.6.0-test11.org/netfilter-patch-o-matic/patches 1970-01-01 01:00:00.000000000 +0100
21434 +++ linux-2.6.0-test11/netfilter-patch-o-matic/patches 2003-12-10 23:38:25.000000000 +0100
21436 +./base/01_sctp_match.patch
21437 +./base/connlimit.patch
21438 +./base/dstlimit.patch
21439 +./base/fuzzy6.patch.ipv6
21440 +./base/fuzzy.patch
21441 +./base/HL.patch.ipv6
21442 +./base/iprange.patch
21443 +./base/ipv4options.patch
21444 +./base/IPV4OPTSSTRIP.patch
21445 +./base/mport.patch
21446 +./base/NETLINK.patch
21447 +./base/nth6.patch.ipv6
21452 +./base/quota.patch
21453 +./base/random6.patch.ipv6
21454 +./base/random.patch
21455 +./base/realm.patch
21456 +./base/REJECT.patch.ipv6
21461 +./extra/addrtype.patch
21462 +./extra/CLASSIFY.patch
21463 +./extra/condition6.patch.ipv6
21464 +./extra/condition.patch
21465 +./extra/CONNMARK.patch
21466 +./extra/cuseeme-nat.patch
21467 +./extra/eggdrop-conntrack.patch
21468 +./extra/h323-conntrack-nat.patch
21469 +./extra/IPMARK.patch
21470 +./extra/iptables-loopcheck-speedup.patch
21471 +./extra/ipt_TARPIT.patch manual change .makefile
21472 +./extra/mms-conntrack-nat.patch
21473 +./extra/netfilter-docbook.patch manual change
21474 +./extra/ownercmd.patch.ipv6
21475 +./extra/pptp-conntrack-nat.patch
21476 +./extra/quake3-conntrack.patch
21477 +./extra/ROUTE.patch
21478 +./extra/ROUTE.patch.ipv6
21481 +./extra/rtsp-conntrack.patch
21482 +./extra/string.patch manual change .makefile
21483 +./extra/talk-conntrack-nat.patch
21484 +./extra/TCPLAG.patch
21485 +./extra/TRACE.patch
21486 +./extra/TRACE.patch.ipv6
21488 +./optimizations/ip_ct_refresh_optimization.patch
21489 +./optimizations/ip_ct_refresh_optimization_pptp.patch
21490 +./pending/23_REJECT-headroom-tcprst.patch
21491 +./pending/24_rcu.patch
21492 +./pending/25-err-ptr.patch
21493 +./pending/26-memsets.patch
21494 +./pending/40_nf-log.patch
21495 +./pending/70_expect-evict-order.patch
21496 +./pending/71_raw.patch
21497 +./submited/02_REJECT-headroom-tcprst.patch
21498 +./submited/03_260t4-mirror-remove.patch
21499 +./submited/03_physdev_bridged.patch
21500 +./submited/04_260t4-unclean-remove.patch
21501 +./submited/05_260t4-unexperimental.patch
21502 +./submited/06_260t4-cosmetic.patch
21503 +./submited/07_260t4-newmodules_iprange_SAME_NETMAP_CLASSIFY.patch
21504 +./submited/07_nonlinear_skb.patch
21505 +./submited/08_260t4_ipt-helper-kconfig.patch
21506 +./submited/09_260t4-cosmetic-physdev-author.patch
21507 +./submited/75_nathelper-udp-csum.patch
21508 +./submited/76_mangle_udp-sizecheck.patch
21509 +./submited/77_destroy-conntrack.patch
21510 +./submited/78_reject-localout.patch
21511 +./submited/80_ip_conntrack-proc.patch
21512 +./submited/82_irc-conntrack-mirc-serverlookup.patch
21513 +./submited/83_nolocalout.patch
21514 +./submited/84_local-nullbinding.patch
21515 +./submited/85_ipv6header.patch
21516 +./submited/86_getorigdst-tuple-zero.patch
21517 +./submited/87_compat-nat_setup_info.patch
21518 +./submited/89_ip_queue-maxlen.patch
21519 +./userspace/ip_queue_vwmark.patch
21520 +./userspace/ipt_REJECT-fake-source.patch
21521 +./userspace/mark-bitwise-ops.patch