1diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack.h 2--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack.h Sat Aug 3 02:39:45 2002 3+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack.h Fri Nov 29 00:53:15 2002 4@@ -6,6 +6,7 @@ 5 6 #include <linux/config.h> 7 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h> 8+#include <asm/atomic.h> 9 10 enum ip_conntrack_info 11 { 12@@ -42,12 +43,57 @@ 13 IPS_ASSURED = (1 << IPS_ASSURED_BIT), 14 }; 15 16+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h> 17+#include <linux/netfilter_ipv4/ip_conntrack_icmp.h> 18+ 19+/* per conntrack: protocol private data */ 20+union ip_conntrack_proto { 21+ /* insert conntrack proto private data here */ 22+ struct ip_ct_tcp tcp; 23+ struct ip_ct_icmp icmp; 24+}; 25+ 26+union ip_conntrack_expect_proto { 27+ /* insert expect proto private data here */ 28+}; 29+ 30+/* Add protocol helper include file here */ 31+#include <linux/netfilter_ipv4/ip_conntrack_ftp.h> 32+#include <linux/netfilter_ipv4/ip_conntrack_irc.h> 33+ 34+/* per expectation: application helper private data */ 35+union ip_conntrack_expect_help { 36+ /* insert conntrack helper private data (expect) here */ 37+ struct ip_ct_ftp_expect exp_ftp_info; 38+ struct ip_ct_irc_expect exp_irc_info; 39+ 40+#ifdef CONFIG_IP_NF_NAT_NEEDED 41+ union { 42+ /* insert nat helper private data (expect) here */ 43+ } nat; 44+#endif 45+}; 46+ 47+/* per conntrack: application helper private data */ 48+union ip_conntrack_help { 49+ /* insert conntrack helper private data (master) here */ 50+ struct ip_ct_ftp_master ct_ftp_info; 51+ struct ip_ct_irc_master ct_irc_info; 52+}; 53+ 54+#ifdef CONFIG_IP_NF_NAT_NEEDED 55+#include <linux/netfilter_ipv4/ip_nat.h> 56+ 57+/* per conntrack: nat application helper private data */ 58+union ip_conntrack_nat_help { 59+ /* insert nat helper private data here */ 60+}; 61+#endif 62+ 63 #ifdef __KERNEL__ 64 65 #include <linux/types.h> 66 #include <linux/skbuff.h> 67-#include <linux/netfilter_ipv4/ip_conntrack_tcp.h> 68-#include <linux/netfilter_ipv4/ip_conntrack_icmp.h> 69 70 #ifdef CONFIG_NF_DEBUG 71 #define IP_NF_ASSERT(x) \ 72@@ -64,26 +110,45 @@ 73 74 struct ip_conntrack_expect 75 { 76- /* Internal linked list */ 77+ /* Internal linked list (global expectation list) */ 78 struct list_head list; 79 80+ /* reference count */ 81+ atomic_t use; 82+ 83+ /* expectation list for this master */ 84+ struct list_head expected_list; 85+ 86+ /* The conntrack of the master connection */ 87+ struct ip_conntrack *expectant; 88+ 89+ /* The conntrack of the sibling connection, set after 90+ * expectation arrived */ 91+ struct ip_conntrack *sibling; 92+ 93+ /* Tuple saved for conntrack */ 94+ struct ip_conntrack_tuple ct_tuple; 95+ 96+ /* Timer function; deletes the expectation. */ 97+ struct timer_list timeout; 98+ 99+ /* Data filled out by the conntrack helpers follow: */ 100+ 101 /* We expect this tuple, with the following mask */ 102 struct ip_conntrack_tuple tuple, mask; 103 104 /* Function to call after setup and insertion */ 105 int (*expectfn)(struct ip_conntrack *new); 106 107- /* The conntrack we are part of (set iff we're live) */ 108- struct ip_conntrack *expectant; 109-}; 110+ /* At which sequence number did this expectation occur */ 111+ u_int32_t seq; 112+ 113+ union ip_conntrack_expect_proto proto; 114 115-#ifdef CONFIG_IP_NF_NAT_NEEDED 116-#include <linux/netfilter_ipv4/ip_nat.h> 117-#endif 118- 119-#include <linux/netfilter_ipv4/ip_conntrack_ftp.h> 120-#include <linux/netfilter_ipv4/ip_conntrack_irc.h> 121+ union ip_conntrack_expect_help help; 122+}; 123 124+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 125 struct ip_conntrack 126 { 127 /* Usage count in here is 1 for hash table/destruct timer, 1 per skb, 128@@ -101,10 +166,13 @@ 129 130 /* If we're expecting another related connection, this will be 131 in expected linked list */ 132- struct ip_conntrack_expect expected; 133+ struct list_head sibling_list; 134+ 135+ /* Current number of expected connections */ 136+ unsigned int expecting; 137 138- /* If we were expected by another connection, this will be it */ 139- struct nf_ct_info master; 140+ /* If we were expected by an expectation, this will be it */ 141+ struct ip_conntrack_expect *master; 142 143 /* Helper, if any. */ 144 struct ip_conntrack_helper *helper; 145@@ -115,22 +183,14 @@ 146 147 /* Storage reserved for other modules: */ 148 149- union { 150- struct ip_ct_tcp tcp; 151- struct ip_ct_icmp icmp; 152- } proto; 153+ union ip_conntrack_proto proto; 154 155- union { 156- struct ip_ct_ftp ct_ftp_info; 157- struct ip_ct_irc ct_irc_info; 158- } help; 159+ union ip_conntrack_help help; 160 161 #ifdef CONFIG_IP_NF_NAT_NEEDED 162 struct { 163 struct ip_nat_info info; 164- union { 165- /* insert nat helper private data here */ 166- } help; 167+ union ip_conntrack_nat_help help; 168 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ 169 defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) 170 int masq_index; 171@@ -140,6 +200,9 @@ 172 173 }; 174 175+/* get master conntrack via master expectation */ 176+#define master_ct(conntr) (conntr->master ? conntr->master->expectant : NULL) 177+ 178 /* Alter reply tuple (maybe alter helper). If it's already taken, 179 return 0 and don't do alteration. */ 180 extern int 181@@ -155,6 +218,16 @@ 182 /* Return conntrack_info and tuple hash for given skb. */ 183 extern struct ip_conntrack * 184 ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo); 185+ 186+/* decrement reference count on a conntrack */ 187+extern inline void ip_conntrack_put(struct ip_conntrack *ct); 188+ 189+/* find unconfirmed expectation based on tuple */ 190+struct ip_conntrack_expect * 191+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple); 192+ 193+/* decrement reference count on an expectation */ 194+void ip_conntrack_expect_put(struct ip_conntrack_expect *exp); 195 196 extern struct module *ip_conntrack_module; 197 198diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_core.h 199--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_core.h Fri Apr 27 23:15:01 2001 200+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_core.h Fri Nov 29 00:53:15 2002 201@@ -15,9 +15,9 @@ 202 extern void ip_conntrack_cleanup(void); 203 204 struct ip_conntrack_protocol; 205-extern struct ip_conntrack_protocol *find_proto(u_int8_t protocol); 206+extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol); 207 /* Like above, but you already have conntrack read lock. */ 208-extern struct ip_conntrack_protocol *__find_proto(u_int8_t protocol); 209+extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol); 210 extern struct list_head protocol_list; 211 212 /* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */ 213@@ -45,7 +45,7 @@ 214 } 215 216 extern struct list_head *ip_conntrack_hash; 217-extern struct list_head expect_list; 218+extern struct list_head ip_conntrack_expect_list; 219 DECLARE_RWLOCK_EXTERN(ip_conntrack_lock); 220 #endif /* _IP_CONNTRACK_CORE_H */ 221 222diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_ftp.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_ftp.h 223--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_ftp.h Thu Apr 26 00:00:28 2001 224+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_ftp.h Fri Nov 29 00:53:15 2002 225@@ -2,15 +2,17 @@ 226 #define _IP_CONNTRACK_FTP_H 227 /* FTP tracking. */ 228 229-#ifndef __KERNEL__ 230-#error Only in kernel. 231-#endif 232+#ifdef __KERNEL__ 233 234 #include <linux/netfilter_ipv4/lockhelp.h> 235 236 /* Protects ftp part of conntracks */ 237 DECLARE_LOCK_EXTERN(ip_ftp_lock); 238 239+#define FTP_PORT 21 240+ 241+#endif /* __KERNEL__ */ 242+ 243 enum ip_ct_ftp_type 244 { 245 /* PORT command from client */ 246@@ -23,18 +25,20 @@ 247 IP_CT_FTP_EPSV, 248 }; 249 250-/* We record seq number and length of ftp ip/port text here: all in 251- host order. */ 252-struct ip_ct_ftp 253+/* This structure is per expected connection */ 254+struct ip_ct_ftp_expect 255 { 256- /* This tells NAT that this is an ftp connection */ 257- int is_ftp; 258- u_int32_t seq; 259- /* 0 means not found yet */ 260- u_int32_t len; 261- enum ip_ct_ftp_type ftptype; 262- /* Port that was to be used */ 263- u_int16_t port; 264+ /* We record seq number and length of ftp ip/port text here: all in 265+ * host order. */ 266+ 267+ /* sequence number of IP address in packet is in ip_conntrack_expect */ 268+ u_int32_t len; /* length of IP address */ 269+ enum ip_ct_ftp_type ftptype; /* PORT or PASV ? */ 270+ u_int16_t port; /* TCP port that was to be used */ 271+}; 272+ 273+/* This structure exists only once per master */ 274+struct ip_ct_ftp_master { 275 /* Next valid seq position for cmd matching after newline */ 276 u_int32_t seq_aft_nl[IP_CT_DIR_MAX]; 277 /* 0 means seq_match_aft_nl not set */ 278diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_helper.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_helper.h 279--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_helper.h Mon Dec 11 22:31:23 2000 280+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_helper.h Fri Nov 29 00:53:15 2002 281@@ -5,10 +5,19 @@ 282 283 struct module; 284 285+/* Reuse expectation when max_expected reached */ 286+#define IP_CT_HELPER_F_REUSE_EXPECT 0x01 287+ 288 struct ip_conntrack_helper 289 { 290- /* Internal use. */ 291- struct list_head list; 292+ struct list_head list; /* Internal use. */ 293+ 294+ const char *name; /* name of the module */ 295+ unsigned char flags; /* Flags (see above) */ 296+ struct module *me; /* pointer to self */ 297+ unsigned int max_expected; /* Maximum number of concurrent 298+ * expected connections */ 299+ unsigned int timeout; /* timeout for expecteds */ 300 301 /* Mask of things we will help (compared against server response) */ 302 struct ip_conntrack_tuple tuple; 303@@ -24,11 +33,13 @@ 304 extern int ip_conntrack_helper_register(struct ip_conntrack_helper *); 305 extern void ip_conntrack_helper_unregister(struct ip_conntrack_helper *); 306 307-/* Add an expected connection: can only have one per connection */ 308+extern struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple); 309+ 310+/* Add an expected connection: can have more than one per connection */ 311 extern int ip_conntrack_expect_related(struct ip_conntrack *related_to, 312- const struct ip_conntrack_tuple *tuple, 313- const struct ip_conntrack_tuple *mask, 314- int (*expectfn)(struct ip_conntrack *)); 315-extern void ip_conntrack_unexpect_related(struct ip_conntrack *related_to); 316+ struct ip_conntrack_expect *exp); 317+extern int ip_conntrack_change_expect(struct ip_conntrack_expect *expect, 318+ struct ip_conntrack_tuple *newtuple); 319+extern void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp); 320 321 #endif /*_IP_CONNTRACK_HELPER_H*/ 322diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_irc.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_irc.h 323--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_irc.h Wed Oct 31 00:08:12 2001 324+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_irc.h Fri Nov 29 00:53:15 2002 325@@ -14,13 +14,28 @@ 326 #ifndef _IP_CONNTRACK_IRC_H 327 #define _IP_CONNTRACK_IRC_H 328 329-#ifndef __KERNEL__ 330-#error Only in kernel. 331-#endif 332+/* We record seq number and length of irc ip/port text here: all in 333+ host order. */ 334+ 335+/* This structure is per expected connection */ 336+struct ip_ct_irc_expect 337+{ 338+ /* length of IP address */ 339+ u_int32_t len; 340+ /* Port that was to be used */ 341+ u_int16_t port; 342+}; 343+ 344+/* This structure exists only once per master */ 345+struct ip_ct_irc_master { 346+}; 347+ 348+ 349+#ifdef __KERNEL__ 350 351 #include <linux/netfilter_ipv4/lockhelp.h> 352 353-#define IP_CONNTR_IRC 2 354+#define IRC_PORT 6667 355 356 struct dccproto { 357 char* match; 358@@ -30,18 +45,6 @@ 359 /* Protects irc part of conntracks */ 360 DECLARE_LOCK_EXTERN(ip_irc_lock); 361 362-/* We record seq number and length of irc ip/port text here: all in 363- host order. */ 364-struct ip_ct_irc 365-{ 366- /* This tells NAT that this is an IRC connection */ 367- int is_irc; 368- /* sequence number where address part of DCC command begins */ 369- u_int32_t seq; 370- /* 0 means not found yet */ 371- u_int32_t len; 372- /* Port that was to be used */ 373- u_int16_t port; 374-}; 375+#endif /* __KERNEL__ */ 376 377 #endif /* _IP_CONNTRACK_IRC_H */ 378diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 379--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h Sat Aug 3 02:39:45 2002 380+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_protocol.h Fri Nov 29 00:53:15 2002 381@@ -45,6 +45,10 @@ 382 /* Called when a conntrack entry is destroyed */ 383 void (*destroy)(struct ip_conntrack *conntrack); 384 385+ /* Has to decide if a expectation matches one packet or not */ 386+ int (*exp_matches_pkt)(struct ip_conntrack_expect *exp, 387+ struct sk_buff **pskb); 388+ 389 /* Module (if any) which this is connected to. */ 390 struct module *me; 391 }; 392diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_tcp.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_tcp.h 393--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_conntrack_tcp.h Fri Aug 4 22:07:24 2000 394+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_conntrack_tcp.h Fri Nov 29 00:53:15 2002 395@@ -2,10 +2,6 @@ 396 #define _IP_CONNTRACK_TCP_H 397 /* TCP tracking. */ 398 399-#ifndef __KERNEL__ 400-#error Only in kernel. 401-#endif 402- 403 enum tcp_conntrack { 404 TCP_CONNTRACK_NONE, 405 TCP_CONNTRACK_ESTABLISHED, 406diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_nat.h 407--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat.h Sat Aug 3 02:39:45 2002 408+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_nat.h Fri Nov 29 00:53:15 2002 409@@ -60,22 +60,6 @@ 410 struct ip_nat_range range[1]; 411 }; 412 413-#ifdef __KERNEL__ 414-#include <linux/list.h> 415-#include <linux/netfilter_ipv4/lockhelp.h> 416- 417-/* Protects NAT hash tables, and NAT-private part of conntracks. */ 418-DECLARE_RWLOCK_EXTERN(ip_nat_lock); 419- 420-/* Hashes for by-source and IP/protocol. */ 421-struct ip_nat_hash 422-{ 423- struct list_head list; 424- 425- /* conntrack we're embedded in: NULL if not in hash. */ 426- struct ip_conntrack *conntrack; 427-}; 428- 429 /* Worst case: local-out manip + 1 post-routing, and reverse dirn. */ 430 #define IP_NAT_MAX_MANIPS (2*3) 431 432@@ -93,7 +77,23 @@ 433 /* Manipulations to occur at each conntrack in this dirn. */ 434 struct ip_conntrack_manip manip; 435 }; 436- 437+ 438+#ifdef __KERNEL__ 439+#include <linux/list.h> 440+#include <linux/netfilter_ipv4/lockhelp.h> 441+ 442+/* Protects NAT hash tables, and NAT-private part of conntracks. */ 443+DECLARE_RWLOCK_EXTERN(ip_nat_lock); 444+ 445+/* Hashes for by-source and IP/protocol. */ 446+struct ip_nat_hash 447+{ 448+ struct list_head list; 449+ 450+ /* conntrack we're embedded in: NULL if not in hash. */ 451+ struct ip_conntrack *conntrack; 452+}; 453+ 454 /* The structure embedded in the conntrack structure. */ 455 struct ip_nat_info 456 { 457diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_nat_helper.h 458--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat_helper.h Thu Apr 26 00:00:28 2001 459+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_nat_helper.h Fri Nov 29 00:53:15 2002 460@@ -6,23 +6,37 @@ 461 462 struct sk_buff; 463 464+/* Flags */ 465+/* NAT helper must be called on every packet (for TCP) */ 466+#define IP_NAT_HELPER_F_ALWAYS 0x01 467+/* Standalone NAT helper, without a conntrack part */ 468+#define IP_NAT_HELPER_F_STANDALONE 0x02 469+ 470 struct ip_nat_helper 471 { 472- /* Internal use */ 473- struct list_head list; 474+ struct list_head list; /* Internal use */ 475 476+ const char *name; /* name of the module */ 477+ unsigned char flags; /* Flags (see above) */ 478+ struct module *me; /* pointer to self */ 479+ 480 /* Mask of things we will help: vs. tuple from server */ 481 struct ip_conntrack_tuple tuple; 482 struct ip_conntrack_tuple mask; 483 484 /* Helper function: returns verdict */ 485 unsigned int (*help)(struct ip_conntrack *ct, 486+ struct ip_conntrack_expect *exp, 487 struct ip_nat_info *info, 488 enum ip_conntrack_info ctinfo, 489 unsigned int hooknum, 490 struct sk_buff **pskb); 491 492- const char *name; 493+ /* Returns verdict and sets up NAT for this connection */ 494+ unsigned int (*expect)(struct sk_buff **pskb, 495+ unsigned int hooknum, 496+ struct ip_conntrack *ct, 497+ struct ip_nat_info *info); 498 }; 499 500 extern struct list_head helpers; 501@@ -39,5 +53,5 @@ 502 extern int ip_nat_seq_adjust(struct sk_buff *skb, 503 struct ip_conntrack *ct, 504 enum ip_conntrack_info ctinfo); 505-extern void ip_nat_delete_sack(struct sk_buff *skb, struct tcphdr *tcph); 506+extern void ip_nat_delete_sack(struct sk_buff *skb); 507 #endif 508diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat_rule.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_nat_rule.h 509--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ip_nat_rule.h Mon Dec 11 22:31:32 2000 510+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ip_nat_rule.h Fri Nov 29 00:53:15 2002 511@@ -5,24 +5,7 @@ 512 #include <linux/netfilter_ipv4/ip_nat.h> 513 514 #ifdef __KERNEL__ 515-/* Want to be told when we first NAT an expected packet for a conntrack? */ 516-struct ip_nat_expect 517-{ 518- struct list_head list; 519 520- /* Returns 1 (and sets verdict) if it has setup NAT for this 521- connection */ 522- int (*expect)(struct sk_buff **pskb, 523- unsigned int hooknum, 524- struct ip_conntrack *ct, 525- struct ip_nat_info *info, 526- struct ip_conntrack *master, 527- struct ip_nat_info *masterinfo, 528- unsigned int *verdict); 529-}; 530- 531-extern int ip_nat_expect_register(struct ip_nat_expect *expect); 532-extern void ip_nat_expect_unregister(struct ip_nat_expect *expect); 533 extern int ip_nat_rule_init(void) __init; 534 extern void ip_nat_rule_cleanup(void); 535 extern int ip_nat_rule_find(struct sk_buff **pskb, 536diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_DSCP.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_DSCP.h 537--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_DSCP.h Thu Jan 1 01:00:00 1970 538+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_DSCP.h Fri Nov 29 00:53:15 2002 539@@ -0,0 +1,20 @@ 540+/* iptables module for setting the IPv4 DSCP field 541+ * 542+ * (C) 2002 Harald Welte <laforge@gnumonks.org> 543+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com> 544+ * This software is distributed under GNU GPL v2, 1991 545+ * 546+ * See RFC2474 for a description of the DSCP field within the IP Header. 547+ * 548+ * ipt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp 549+*/ 550+#ifndef _IPT_DSCP_TARGET_H 551+#define _IPT_DSCP_TARGET_H 552+#include <linux/netfilter_ipv4/ipt_dscp.h> 553+ 554+/* target info */ 555+struct ipt_DSCP_info { 556+ u_int8_t dscp; 557+}; 558+ 559+#endif /* _IPT_DSCP_TARGET_H */ 560diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_ECN.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_ECN.h 561--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_ECN.h Thu Jan 1 01:00:00 1970 562+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_ECN.h Fri Nov 29 00:53:15 2002 563@@ -0,0 +1,31 @@ 564+/* Header file for iptables ipt_ECN target 565+ * 566+ * (C) 2002 by Harald Welte <laforge@gnumonks.org> 567+ * 568+ * This software is distributed under GNU GPL v2, 1991 569+ * 570+ * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp 571+*/ 572+#ifndef _IPT_ECN_TARGET_H 573+#define _IPT_ECN_TARGET_H 574+#include <linux/netfilter_ipv4/ipt_DSCP.h> 575+ 576+#define IPT_ECN_IP_MASK (~IPT_DSCP_MASK) 577+ 578+#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ 579+#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ 580+#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ 581+ 582+#define IPT_ECN_OP_MASK 0xce 583+ 584+struct ipt_ECN_info { 585+ u_int8_t operation; /* bitset of operations */ 586+ u_int8_t ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ 587+ union { 588+ struct { 589+ u_int8_t ece:1, cwr:1; /* TCP ECT bits */ 590+ } tcp; 591+ } proto; 592+}; 593+ 594+#endif /* _IPT_ECN_TARGET_H */ 595diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_conntrack.h 596--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_conntrack.h Thu Jan 1 01:00:00 1970 597+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_conntrack.h Fri Nov 29 00:53:15 2002 598@@ -0,0 +1,38 @@ 599+/* Header file for kernel module to match connection tracking information. 600+ * GPL (C) 2001 Marc Boucher (marc@mbsi.ca). 601+ */ 602+ 603+#ifndef _IPT_CONNTRACK_H 604+#define _IPT_CONNTRACK_H 605+ 606+#define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) 607+#define IPT_CONNTRACK_STATE_INVALID (1 << 0) 608+ 609+#define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) 610+#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) 611+ 612+/* flags, invflags: */ 613+#define IPT_CONNTRACK_STATE 0x01 614+#define IPT_CONNTRACK_PROTO 0x02 615+#define IPT_CONNTRACK_ORIGSRC 0x04 616+#define IPT_CONNTRACK_ORIGDST 0x08 617+#define IPT_CONNTRACK_REPLSRC 0x10 618+#define IPT_CONNTRACK_REPLDST 0x20 619+#define IPT_CONNTRACK_STATUS 0x40 620+#define IPT_CONNTRACK_EXPIRES 0x80 621+ 622+struct ipt_conntrack_info 623+{ 624+ unsigned int statemask, statusmask; 625+ 626+ struct ip_conntrack_tuple tuple[IP_CT_DIR_MAX]; 627+ struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; 628+ 629+ unsigned long expires_min, expires_max; 630+ 631+ /* Flags word */ 632+ u_int8_t flags; 633+ /* Inverse flags */ 634+ u_int8_t invflags; 635+}; 636+#endif /*_IPT_CONNTRACK_H*/ 637diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_dscp.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_dscp.h 638--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_dscp.h Thu Jan 1 01:00:00 1970 639+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_dscp.h Fri Nov 29 00:53:15 2002 640@@ -0,0 +1,23 @@ 641+/* iptables module for matching the IPv4 DSCP field 642+ * 643+ * (C) 2002 Harald Welte <laforge@gnumonks.org> 644+ * This software is distributed under GNU GPL v2, 1991 645+ * 646+ * See RFC2474 for a description of the DSCP field within the IP Header. 647+ * 648+ * ipt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp 649+*/ 650+#ifndef _IPT_DSCP_H 651+#define _IPT_DSCP_H 652+ 653+#define IPT_DSCP_MASK 0xfc /* 11111100 */ 654+#define IPT_DSCP_SHIFT 2 655+#define IPT_DSCP_MAX 0x3f /* 00111111 */ 656+ 657+/* match info */ 658+struct ipt_dscp_info { 659+ u_int8_t dscp; 660+ u_int8_t invert; 661+}; 662+ 663+#endif /* _IPT_DSCP_H */ 664diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_ecn.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_ecn.h 665--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_ecn.h Thu Jan 1 01:00:00 1970 666+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_ecn.h Fri Nov 29 00:53:15 2002 667@@ -0,0 +1,33 @@ 668+/* iptables module for matching the ECN header in IPv4 and TCP header 669+ * 670+ * (C) 2002 Harald Welte <laforge@gnumonks.org> 671+ * 672+ * This software is distributed under GNU GPL v2, 1991 673+ * 674+ * ipt_ecn.h,v 1.4 2002/08/05 19:39:00 laforge Exp 675+*/ 676+#ifndef _IPT_ECN_H 677+#define _IPT_ECN_H 678+#include <linux/netfilter_ipv4/ipt_dscp.h> 679+ 680+#define IPT_ECN_IP_MASK (~IPT_DSCP_MASK) 681+ 682+#define IPT_ECN_OP_MATCH_IP 0x01 683+#define IPT_ECN_OP_MATCH_ECE 0x10 684+#define IPT_ECN_OP_MATCH_CWR 0x20 685+ 686+#define IPT_ECN_OP_MATCH_MASK 0xce 687+ 688+/* match info */ 689+struct ipt_ecn_info { 690+ u_int8_t operation; 691+ u_int8_t invert; 692+ u_int8_t ip_ect; 693+ union { 694+ struct { 695+ u_int8_t ect; 696+ } tcp; 697+ } proto; 698+}; 699+ 700+#endif /* _IPT_ECN_H */ 701diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_helper.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_helper.h 702--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_helper.h Thu Jan 1 01:00:00 1970 703+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_helper.h Fri Nov 29 00:53:15 2002 704@@ -0,0 +1,8 @@ 705+#ifndef _IPT_HELPER_H 706+#define _IPT_HELPER_H 707+ 708+struct ipt_helper_info { 709+ int invert; 710+ char name[30]; 711+}; 712+#endif /* _IPT_HELPER_H */ 713diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_owner.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_owner.h 714--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_owner.h Fri Mar 17 19:56:20 2000 715+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_owner.h Fri Nov 29 00:53:15 2002 716@@ -6,12 +6,14 @@ 717 #define IPT_OWNER_GID 0x02 718 #define IPT_OWNER_PID 0x04 719 #define IPT_OWNER_SID 0x08 720+#define IPT_OWNER_COMM 0x10 721 722 struct ipt_owner_info { 723 uid_t uid; 724 gid_t gid; 725 pid_t pid; 726 pid_t sid; 727+ char comm[16]; 728 u_int8_t match, invert; /* flags */ 729 }; 730 731diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_pkttype.h linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_pkttype.h 732--- linux-2.4.19-plain/include/linux/netfilter_ipv4/ipt_pkttype.h Thu Jan 1 01:00:00 1970 733+++ linux-2.4.20-plain/include/linux/netfilter_ipv4/ipt_pkttype.h Fri Nov 29 00:53:15 2002 734@@ -0,0 +1,8 @@ 735+#ifndef _IPT_PKTTYPE_H 736+#define _IPT_PKTTYPE_H 737+ 738+struct ipt_pkttype_info { 739+ int pkttype; 740+ int invert; 741+}; 742+#endif /*_IPT_PKTTYPE_H*/ 743diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/include/linux/netfilter_ipv6/ip6t_length.h linux-2.4.20-plain/include/linux/netfilter_ipv6/ip6t_length.h 744--- linux-2.4.19-plain/include/linux/netfilter_ipv6/ip6t_length.h Thu Jan 1 01:00:00 1970 745+++ linux-2.4.20-plain/include/linux/netfilter_ipv6/ip6t_length.h Fri Nov 29 00:53:15 2002 746@@ -0,0 +1,10 @@ 747+#ifndef _IP6T_LENGTH_H 748+#define _IP6T_LENGTH_H 749+ 750+struct ip6t_length_info { 751+ u_int16_t min, max; 752+ u_int8_t invert; 753+}; 754+ 755+#endif /*_IP6T_LENGTH_H*/ 756+ 757diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/Config.in linux-2.4.20-plain/net/ipv4/netfilter/Config.in 758--- linux-2.4.19-plain/net/ipv4/netfilter/Config.in Sat Aug 3 02:39:46 2002 759+++ linux-2.4.20-plain/net/ipv4/netfilter/Config.in Fri Nov 29 00:53:15 2002 760@@ -18,15 +18,24 @@ 761 # The simple matches. 762 dep_tristate ' limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES 763 dep_tristate ' MAC address match support' CONFIG_IP_NF_MATCH_MAC $CONFIG_IP_NF_IPTABLES 764+ dep_tristate ' Packet type match support' CONFIG_IP_NF_MATCH_PKTTYPE $CONFIG_IP_NF_IPTABLES 765 dep_tristate ' netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES 766 dep_tristate ' Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES 767 dep_tristate ' TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES 768+ dep_tristate ' ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES 769+ 770+ dep_tristate ' DSCP match support' CONFIG_IP_NF_MATCH_DSCP $CONFIG_IP_NF_IPTABLES 771+ 772 dep_tristate ' AH/ESP match support' CONFIG_IP_NF_MATCH_AH_ESP $CONFIG_IP_NF_IPTABLES 773 dep_tristate ' LENGTH match support' CONFIG_IP_NF_MATCH_LENGTH $CONFIG_IP_NF_IPTABLES 774 dep_tristate ' TTL match support' CONFIG_IP_NF_MATCH_TTL $CONFIG_IP_NF_IPTABLES 775 dep_tristate ' tcpmss match support' CONFIG_IP_NF_MATCH_TCPMSS $CONFIG_IP_NF_IPTABLES 776 if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then 777+ dep_tristate ' Helper match support' CONFIG_IP_NF_MATCH_HELPER $CONFIG_IP_NF_IPTABLES 778+ fi 779+ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then 780 dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES 781+ dep_tristate ' Connection tracking match support' CONFIG_IP_NF_MATCH_CONNTRACK $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES 782 fi 783 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 784 dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES 785@@ -73,6 +82,10 @@ 786 dep_tristate ' Packet mangling' CONFIG_IP_NF_MANGLE $CONFIG_IP_NF_IPTABLES 787 if [ "$CONFIG_IP_NF_MANGLE" != "n" ]; then 788 dep_tristate ' TOS target support' CONFIG_IP_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE 789+ dep_tristate ' ECN target support' CONFIG_IP_NF_TARGET_ECN $CONFIG_IP_NF_MANGLE 790+ 791+ dep_tristate ' DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE 792+ 793 dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE 794 fi 795 dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES 796diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/Makefile linux-2.4.20-plain/net/ipv4/netfilter/Makefile 797--- linux-2.4.19-plain/net/ipv4/netfilter/Makefile Sat Aug 3 02:39:46 2002 798+++ linux-2.4.20-plain/net/ipv4/netfilter/Makefile Fri Nov 29 00:53:15 2002 799@@ -9,18 +9,18 @@ 800 801 O_TARGET := netfilter.o 802 803-export-objs = ip_conntrack_standalone.o ip_conntrack_ftp.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o arp_tables.o 804+export-objs = ip_conntrack_standalone.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o arp_tables.o 805 806 # Multipart objects. 807 list-multi := ip_conntrack.o iptable_nat.o ipfwadm.o ipchains.o 808 809 # objects for the conntrack and NAT core (used by standalone and backw. compat) 810 ip_nf_conntrack-objs := ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o 811-ip_nf_nat-objs := ip_nat_core.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o 812+ip_nf_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o 813 814 # objects for the standalone - connection tracking / NAT 815 ip_conntrack-objs := ip_conntrack_standalone.o $(ip_nf_conntrack-objs) 816-iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_helper.o $(ip_nf_nat-objs) 817+iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o $(ip_nf_nat-objs) 818 819 # objects for backwards compatibility mode 820 ip_nf_compat-objs := ip_fw_compat.o ip_fw_compat_redir.o ip_fw_compat_masq.o $(ip_nf_conntrack-objs) $(ip_nf_nat-objs) 821@@ -33,7 +33,14 @@ 822 823 # connection tracking helpers 824 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o 825+ifdef CONFIG_IP_NF_NAT_FTP 826+ export-objs += ip_conntrack_ftp.o 827+endif 828+ 829 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o 830+ifdef CONFIG_IP_NF_NAT_IRC 831+ export-objs += ip_conntrack_irc.o 832+endif 833 834 # NAT helpers 835 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o 836@@ -48,18 +55,24 @@ 837 obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o 838 839 # matches 840+obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o 841 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o 842 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o 843 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o 844+ 845+obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o 846 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o 847 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o 848 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o 849+obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 850+obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o 851 obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 852 853 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o 854 855 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 856 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o 857+obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o 858 obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o 859 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o 860 861@@ -67,6 +80,8 @@ 862 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 863 obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o 864 obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o 865+obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 866+obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o 867 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o 868 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 869 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 870diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_core.c 871--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_core.c Sat Aug 3 02:39:46 2002 872+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_core.c Fri Nov 29 00:53:15 2002 873@@ -3,7 +3,15 @@ 874 extension. */ 875 876 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General 877- Public Licence. */ 878+ * Public Licence. 879+ * 880+ * 23 Apr 2001: Harald Welte <laforge@gnumonks.org> 881+ * - new API and handling of conntrack/nat helpers 882+ * - now capable of multiple expectations for one master 883+ * 16 Jul 2002: Harald Welte <laforge@gnumonks.org> 884+ * - add usage/reference counts to ip_conntrack_expect 885+ * - export ip_conntrack[_expect]_{find_get,put} functions 886+ * */ 887 888 #ifdef MODULE 889 #define __NO_VERSION__ 890@@ -37,6 +45,8 @@ 891 #include <linux/netfilter_ipv4/ip_conntrack_core.h> 892 #include <linux/netfilter_ipv4/listhelp.h> 893 894+#define IP_CONNTRACK_VERSION "2.1" 895+ 896 #if 0 897 #define DEBUGP printk 898 #else 899@@ -44,9 +54,10 @@ 900 #endif 901 902 DECLARE_RWLOCK(ip_conntrack_lock); 903+DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock); 904 905 void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL; 906-LIST_HEAD(expect_list); 907+LIST_HEAD(ip_conntrack_expect_list); 908 LIST_HEAD(protocol_list); 909 static LIST_HEAD(helpers); 910 unsigned int ip_conntrack_htable_size = 0; 911@@ -63,7 +74,7 @@ 912 return protocol == curr->proto; 913 } 914 915-struct ip_conntrack_protocol *__find_proto(u_int8_t protocol) 916+struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol) 917 { 918 struct ip_conntrack_protocol *p; 919 920@@ -76,17 +87,18 @@ 921 return p; 922 } 923 924-struct ip_conntrack_protocol *find_proto(u_int8_t protocol) 925+struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol) 926 { 927 struct ip_conntrack_protocol *p; 928 929 READ_LOCK(&ip_conntrack_lock); 930- p = __find_proto(protocol); 931+ p = __ip_ct_find_proto(protocol); 932 READ_UNLOCK(&ip_conntrack_lock); 933 return p; 934 } 935 936-static inline void ip_conntrack_put(struct ip_conntrack *ct) 937+inline void 938+ip_conntrack_put(struct ip_conntrack *ct) 939 { 940 IP_NF_ASSERT(ct); 941 IP_NF_ASSERT(ct->infos[0].master); 942@@ -150,9 +162,135 @@ 943 return protocol->invert_tuple(inverse, orig); 944 } 945 946+ 947+/* ip_conntrack_expect helper functions */ 948+ 949+/* Compare tuple parts depending on mask. */ 950+static inline int expect_cmp(const struct ip_conntrack_expect *i, 951+ const struct ip_conntrack_tuple *tuple) 952+{ 953+ MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock); 954+ return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask); 955+} 956+ 957+static void 958+destroy_expect(struct ip_conntrack_expect *exp) 959+{ 960+ DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(exp->use)); 961+ IP_NF_ASSERT(atomic_read(exp->use)); 962+ IP_NF_ASSERT(!timer_pending(&exp->timeout)); 963+ 964+ kfree(exp); 965+} 966+ 967+ 968+inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp) 969+{ 970+ IP_NF_ASSERT(exp); 971+ 972+ if (atomic_dec_and_test(&exp->use)) { 973+ /* usage count dropped to zero */ 974+ destroy_expect(exp); 975+ } 976+} 977+ 978+static inline struct ip_conntrack_expect * 979+__ip_ct_expect_find(const struct ip_conntrack_tuple *tuple) 980+{ 981+ MUST_BE_READ_LOCKED(&ip_conntrack_lock); 982+ MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock); 983+ return LIST_FIND(&ip_conntrack_expect_list, expect_cmp, 984+ struct ip_conntrack_expect *, tuple); 985+} 986+ 987+/* Find a expectation corresponding to a tuple. */ 988+struct ip_conntrack_expect * 989+ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple) 990+{ 991+ struct ip_conntrack_expect *exp; 992+ 993+ READ_LOCK(&ip_conntrack_lock); 994+ READ_LOCK(&ip_conntrack_expect_tuple_lock); 995+ exp = __ip_ct_expect_find(tuple); 996+ if (exp) 997+ atomic_inc(&exp->use); 998+ READ_UNLOCK(&ip_conntrack_expect_tuple_lock); 999+ READ_UNLOCK(&ip_conntrack_lock); 1000+ 1001+ return exp; 1002+} 1003+ 1004+/* remove one specific expectation from all lists and drop refcount, 1005+ * does _NOT_ delete the timer. */ 1006+static void __unexpect_related(struct ip_conntrack_expect *expect) 1007+{ 1008+ DEBUGP("unexpect_related(%p)\n", expect); 1009+ MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); 1010+ 1011+ /* we're not allowed to unexpect a confirmed expectation! */ 1012+ IP_NF_ASSERT(!expect->sibling); 1013+ 1014+ /* delete from global and local lists */ 1015+ list_del(&expect->list); 1016+ list_del(&expect->expected_list); 1017+ 1018+ /* decrement expect-count of master conntrack */ 1019+ if (expect->expectant) 1020+ expect->expectant->expecting--; 1021+ 1022+ ip_conntrack_expect_put(expect); 1023+} 1024+ 1025+/* remove one specific expecatation from all lists, drop refcount 1026+ * and expire timer. 1027+ * This function can _NOT_ be called for confirmed expects! */ 1028+static void unexpect_related(struct ip_conntrack_expect *expect) 1029+{ 1030+ IP_NF_ASSERT(expect->expectant); 1031+ IP_NF_ASSERT(expect->expectant->helper); 1032+ /* if we are supposed to have a timer, but we can't delete 1033+ * it: race condition. __unexpect_related will 1034+ * be calledd by timeout function */ 1035+ if (expect->expectant->helper->timeout 1036+ && !del_timer(&expect->timeout)) 1037+ return; 1038+ 1039+ __unexpect_related(expect); 1040+} 1041+ 1042+/* delete all unconfirmed expectations for this conntrack */ 1043+static void remove_expectations(struct ip_conntrack *ct) 1044+{ 1045+ struct list_head *exp_entry, *next; 1046+ struct ip_conntrack_expect *exp; 1047+ 1048+ DEBUGP("remove_expectations(%p)\n", ct); 1049+ 1050+ for (exp_entry = ct->sibling_list.next; 1051+ exp_entry != &ct->sibling_list; exp_entry = next) { 1052+ next = exp_entry->next; 1053+ exp = list_entry(exp_entry, struct ip_conntrack_expect, 1054+ expected_list); 1055+ 1056+ /* we skip established expectations, as we want to delete 1057+ * the un-established ones only */ 1058+ if (exp->sibling) { 1059+ DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct); 1060+ continue; 1061+ } 1062+ 1063+ IP_NF_ASSERT(list_inlist(&ip_conntrack_expect_list, exp)); 1064+ IP_NF_ASSERT(exp->expectant == ct); 1065+ 1066+ /* delete expectation from global and private lists */ 1067+ unexpect_related(exp); 1068+ } 1069+} 1070+ 1071 static void 1072 clean_from_lists(struct ip_conntrack *ct) 1073 { 1074+ DEBUGP("clean_from_lists(%p)\n", ct); 1075 MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); 1076 /* Remove from both hash lists: must not NULL out next ptrs, 1077 otherwise we'll look unconfirmed. Fortunately, LIST_DELETE 1078@@ -163,12 +301,9 @@ 1079 LIST_DELETE(&ip_conntrack_hash 1080 [hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple)], 1081 &ct->tuplehash[IP_CT_DIR_REPLY]); 1082- /* If our expected is in the list, take it out. */ 1083- if (ct->expected.expectant) { 1084- IP_NF_ASSERT(list_inlist(&expect_list, &ct->expected)); 1085- IP_NF_ASSERT(ct->expected.expectant == ct); 1086- LIST_DELETE(&expect_list, &ct->expected); 1087- } 1088+ 1089+ /* Destroy all un-established, pending expectations */ 1090+ remove_expectations(ct); 1091 } 1092 1093 static void 1094@@ -177,21 +312,34 @@ 1095 struct ip_conntrack *ct = (struct ip_conntrack *)nfct; 1096 struct ip_conntrack_protocol *proto; 1097 1098+ DEBUGP("destroy_conntrack(%p)\n", ct); 1099 IP_NF_ASSERT(atomic_read(&nfct->use) == 0); 1100 IP_NF_ASSERT(!timer_pending(&ct->timeout)); 1101 1102- if (ct->master.master) 1103- nf_conntrack_put(&ct->master); 1104+ if (ct->master && master_ct(ct)) 1105+ ip_conntrack_put(master_ct(ct)); 1106 1107 /* To make sure we don't get any weird locking issues here: 1108 * destroy_conntrack() MUST NOT be called with a write lock 1109 * to ip_conntrack_lock!!! -HW */ 1110- proto = find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); 1111+ proto = ip_ct_find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); 1112 if (proto && proto->destroy) 1113 proto->destroy(ct); 1114 1115 if (ip_conntrack_destroyed) 1116 ip_conntrack_destroyed(ct); 1117+ 1118+ WRITE_LOCK(&ip_conntrack_lock); 1119+ /* Delete our master expectation */ 1120+ if (ct->master) { 1121+ /* can't call __unexpect_related here, 1122+ * since it would screw up expect_list */ 1123+ list_del(&ct->master->expected_list); 1124+ kfree(ct->master); 1125+ } 1126+ WRITE_UNLOCK(&ip_conntrack_lock); 1127+ 1128+ DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct); 1129 kmem_cache_free(ip_conntrack_cachep, ct); 1130 atomic_dec(&ip_conntrack_count); 1131 } 1132@@ -315,7 +463,7 @@ 1133 &ct->tuplehash[IP_CT_DIR_REPLY]); 1134 /* Timer relative to confirmation time, not original 1135 setting time, otherwise we'd get timer wrap in 1136- wierd delay cases. */ 1137+ weird delay cases. */ 1138 ct->timeout.expires += jiffies; 1139 add_timer(&ct->timeout); 1140 atomic_inc(&ct->ct_general.use); 1141@@ -389,7 +537,7 @@ 1142 return NULL; 1143 } 1144 1145- innerproto = find_proto(inner->protocol); 1146+ innerproto = ip_ct_find_proto(inner->protocol); 1147 /* Are they talking about one of our connections? */ 1148 if (inner->ihl * 4 + 8 > datalen 1149 || !get_tuple(inner, datalen, &origtuple, innerproto)) { 1150@@ -469,11 +617,11 @@ 1151 return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask); 1152 } 1153 1154-/* Compare parts depending on mask. */ 1155-static inline int expect_cmp(const struct ip_conntrack_expect *i, 1156- const struct ip_conntrack_tuple *tuple) 1157+struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple) 1158 { 1159- return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask); 1160+ return LIST_FIND(&helpers, helper_cmp, 1161+ struct ip_conntrack_helper *, 1162+ tuple); 1163 } 1164 1165 /* Allocate a new conntrack: we return -ENOMEM if classification 1166@@ -521,7 +669,7 @@ 1167 return ERR_PTR(-ENOMEM); 1168 } 1169 1170- memset(conntrack, 0, sizeof(struct ip_conntrack)); 1171+ memset(conntrack, 0, sizeof(*conntrack)); 1172 atomic_set(&conntrack->ct_general.use, 1); 1173 conntrack->ct_general.destroy = destroy_conntrack; 1174 conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple; 1175@@ -540,31 +688,44 @@ 1176 conntrack->timeout.data = (unsigned long)conntrack; 1177 conntrack->timeout.function = death_by_timeout; 1178 1179+ INIT_LIST_HEAD(&conntrack->sibling_list); 1180+ 1181 /* Mark clearly that it's not in the hash table. */ 1182 conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list.next = NULL; 1183 1184- /* Write lock required for deletion of expected. Without 1185- this, a read-lock would do. */ 1186 WRITE_LOCK(&ip_conntrack_lock); 1187- conntrack->helper = LIST_FIND(&helpers, helper_cmp, 1188- struct ip_conntrack_helper *, 1189- &repl_tuple); 1190 /* Need finding and deleting of expected ONLY if we win race */ 1191- expected = LIST_FIND(&expect_list, expect_cmp, 1192+ READ_LOCK(&ip_conntrack_expect_tuple_lock); 1193+ expected = LIST_FIND(&ip_conntrack_expect_list, expect_cmp, 1194 struct ip_conntrack_expect *, tuple); 1195+ READ_UNLOCK(&ip_conntrack_expect_tuple_lock); 1196+ 1197+ /* Look up the conntrack helper for master connections only */ 1198+ if (!expected) 1199+ conntrack->helper = ip_ct_find_helper(&repl_tuple); 1200+ 1201+ /* If the expectation is dying, then this is a looser. */ 1202+ if (expected 1203+ && expected->expectant->helper->timeout 1204+ && ! del_timer(&expected->timeout)) 1205+ expected = NULL; 1206+ 1207 /* If master is not in hash table yet (ie. packet hasn't left 1208 this machine yet), how can other end know about expected? 1209 Hence these are not the droids you are looking for (if 1210 master ct never got confirmed, we'd hold a reference to it 1211 and weird things would happen to future packets). */ 1212 if (expected && is_confirmed(expected->expectant)) { 1213+ DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n", 1214+ conntrack, expected); 1215 /* Welcome, Mr. Bond. We've been expecting you... */ 1216+ IP_NF_ASSERT(master_ct(conntrack)); 1217 conntrack->status = IPS_EXPECTED; 1218- conntrack->master.master = &expected->expectant->ct_general; 1219- IP_NF_ASSERT(conntrack->master.master); 1220- LIST_DELETE(&expect_list, expected); 1221- expected->expectant = NULL; 1222- nf_conntrack_get(&conntrack->master); 1223+ conntrack->master = expected; 1224+ expected->sibling = conntrack; 1225+ LIST_DELETE(&ip_conntrack_expect_list, expected); 1226+ expected->expectant->expecting--; 1227+ nf_conntrack_get(&master_ct(conntrack)->infos[0]); 1228 } 1229 atomic_inc(&ip_conntrack_count); 1230 WRITE_UNLOCK(&ip_conntrack_lock); 1231@@ -669,7 +830,7 @@ 1232 return NF_STOLEN; 1233 } 1234 1235- proto = find_proto((*pskb)->nh.iph->protocol); 1236+ proto = ip_ct_find_proto((*pskb)->nh.iph->protocol); 1237 1238 /* It may be an icmp error... */ 1239 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 1240@@ -713,66 +874,229 @@ 1241 int invert_tuplepr(struct ip_conntrack_tuple *inverse, 1242 const struct ip_conntrack_tuple *orig) 1243 { 1244- return invert_tuple(inverse, orig, find_proto(orig->dst.protonum)); 1245+ return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum)); 1246 } 1247 1248-static void unexpect_related(struct ip_conntrack *related_to) 1249-{ 1250- MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); 1251- list_del(&related_to->expected.list); 1252- related_to->expected.expectant = NULL; 1253+static inline int resent_expect(const struct ip_conntrack_expect *i, 1254+ const struct ip_conntrack_tuple *tuple, 1255+ const struct ip_conntrack_tuple *mask) 1256+{ 1257+ DEBUGP("resent_expect\n"); 1258+ DEBUGP(" tuple: "); DUMP_TUPLE(&i->tuple); 1259+ DEBUGP("ct_tuple: "); DUMP_TUPLE(&i->ct_tuple); 1260+ DEBUGP("test tuple: "); DUMP_TUPLE(tuple); 1261+ return (((i->ct_tuple.dst.protonum == 0 && ip_ct_tuple_equal(&i->tuple, tuple)) 1262+ || (i->ct_tuple.dst.protonum && ip_ct_tuple_equal(&i->ct_tuple, tuple))) 1263+ && ip_ct_tuple_equal(&i->mask, mask)); 1264 } 1265 1266 /* Would two expected things clash? */ 1267 static inline int expect_clash(const struct ip_conntrack_expect *i, 1268- const struct ip_conntrack_expect *new) 1269+ const struct ip_conntrack_tuple *tuple, 1270+ const struct ip_conntrack_tuple *mask) 1271 { 1272 /* Part covered by intersection of masks must be unequal, 1273 otherwise they clash */ 1274 struct ip_conntrack_tuple intersect_mask 1275- = { { i->mask.src.ip & new->mask.src.ip, 1276- { i->mask.src.u.all & new->mask.src.u.all } }, 1277- { i->mask.dst.ip & new->mask.dst.ip, 1278- { i->mask.dst.u.all & new->mask.dst.u.all }, 1279- i->mask.dst.protonum & new->mask.dst.protonum } }; 1280+ = { { i->mask.src.ip & mask->src.ip, 1281+ { i->mask.src.u.all & mask->src.u.all } }, 1282+ { i->mask.dst.ip & mask->dst.ip, 1283+ { i->mask.dst.u.all & mask->dst.u.all }, 1284+ i->mask.dst.protonum & mask->dst.protonum } }; 1285+ 1286+ return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask); 1287+} 1288+ 1289+inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect) 1290+{ 1291+ WRITE_LOCK(&ip_conntrack_lock); 1292+ unexpect_related(expect); 1293+ WRITE_UNLOCK(&ip_conntrack_lock); 1294+} 1295+ 1296+static void expectation_timed_out(unsigned long ul_expect) 1297+{ 1298+ struct ip_conntrack_expect *expect = (void *) ul_expect; 1299 1300- return ip_ct_tuple_mask_cmp(&i->tuple, &new->tuple, &intersect_mask); 1301+ DEBUGP("expectation %p timed out\n", expect); 1302+ WRITE_LOCK(&ip_conntrack_lock); 1303+ __unexpect_related(expect); 1304+ WRITE_UNLOCK(&ip_conntrack_lock); 1305 } 1306 1307 /* Add a related connection. */ 1308 int ip_conntrack_expect_related(struct ip_conntrack *related_to, 1309- const struct ip_conntrack_tuple *tuple, 1310- const struct ip_conntrack_tuple *mask, 1311- int (*expectfn)(struct ip_conntrack *)) 1312+ struct ip_conntrack_expect *expect) 1313 { 1314+ struct ip_conntrack_expect *old, *new; 1315+ int ret = 0; 1316+ 1317 WRITE_LOCK(&ip_conntrack_lock); 1318- if (related_to->expected.expectant) 1319- unexpect_related(related_to); 1320+ /* Because of the write lock, no reader can walk the lists, 1321+ * so there is no need to use the tuple lock too */ 1322+ 1323+ DEBUGP("ip_conntrack_expect_related %p\n", related_to); 1324+ DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple); 1325+ DEBUGP("mask: "); DUMP_TUPLE(&expect->mask); 1326+ 1327+ old = LIST_FIND(&ip_conntrack_expect_list, resent_expect, 1328+ struct ip_conntrack_expect *, &expect->tuple, 1329+ &expect->mask); 1330+ if (old) { 1331+ /* Helper private data may contain offsets but no pointers 1332+ pointing into the payload - otherwise we should have to copy 1333+ the data filled out by the helper over the old one */ 1334+ DEBUGP("expect_related: resent packet\n"); 1335+ if (related_to->helper->timeout) { 1336+ if (!del_timer(&old->timeout)) { 1337+ /* expectation is dying. Fall through */ 1338+ old = NULL; 1339+ } else { 1340+ old->timeout.expires = jiffies + 1341+ related_to->helper->timeout * HZ; 1342+ add_timer(&old->timeout); 1343+ } 1344+ } 1345+ 1346+ if (old) { 1347+ WRITE_UNLOCK(&ip_conntrack_lock); 1348+ return -EEXIST; 1349+ } 1350+ } else if (related_to->helper->max_expected && 1351+ related_to->expecting >= related_to->helper->max_expected) { 1352+ struct list_head *cur_item; 1353+ /* old == NULL */ 1354+ if (net_ratelimit()) 1355+ printk(KERN_WARNING 1356+ "ip_conntrack: max number of expected " 1357+ "connections %i of %s reached for " 1358+ "%u.%u.%u.%u->%u.%u.%u.%u%s\n", 1359+ related_to->helper->max_expected, 1360+ related_to->helper->name, 1361+ NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip), 1362+ NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip), 1363+ related_to->helper->flags & IP_CT_HELPER_F_REUSE_EXPECT ? 1364+ ", reusing" : ""); 1365+ if (!(related_to->helper->flags & 1366+ IP_CT_HELPER_F_REUSE_EXPECT)) { 1367+ WRITE_UNLOCK(&ip_conntrack_lock); 1368+ return -EPERM; 1369+ } 1370 1371- related_to->expected.tuple = *tuple; 1372- related_to->expected.mask = *mask; 1373- related_to->expected.expectfn = expectfn; 1374+ /* choose the the oldest expectation to evict */ 1375+ list_for_each(cur_item, &related_to->sibling_list) { 1376+ struct ip_conntrack_expect *cur; 1377+ 1378+ cur = list_entry(cur_item, 1379+ struct ip_conntrack_expect, 1380+ expected_list); 1381+ if (cur->sibling == NULL) { 1382+ old = cur; 1383+ break; 1384+ } 1385+ } 1386 1387- if (LIST_FIND(&expect_list, expect_clash, 1388- struct ip_conntrack_expect *, &related_to->expected)) { 1389+ /* (!old) cannot happen, since related_to->expecting is the 1390+ * number of unconfirmed expects */ 1391+ IP_NF_ASSERT(old); 1392+ 1393+ /* newnat14 does not reuse the real allocated memory 1394+ * structures but rather unexpects the old and 1395+ * allocates a new. unexpect_related will decrement 1396+ * related_to->expecting. 1397+ */ 1398+ unexpect_related(old); 1399+ ret = -EPERM; 1400+ } else if (LIST_FIND(&ip_conntrack_expect_list, expect_clash, 1401+ struct ip_conntrack_expect *, &expect->tuple, 1402+ &expect->mask)) { 1403 WRITE_UNLOCK(&ip_conntrack_lock); 1404+ DEBUGP("expect_related: busy!\n"); 1405 return -EBUSY; 1406 } 1407+ 1408+ new = (struct ip_conntrack_expect *) 1409+ kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC); 1410+ if (!new) { 1411+ WRITE_UNLOCK(&ip_conntrack_lock); 1412+ DEBUGP("expect_relaed: OOM allocating expect\n"); 1413+ return -ENOMEM; 1414+ } 1415+ 1416+ /* Zero out the new structure, then fill out it with the data */ 1417+ DEBUGP("new expectation %p of conntrack %p\n", new, related_to); 1418+ memset(new, 0, sizeof(*expect)); 1419+ INIT_LIST_HEAD(&new->list); 1420+ INIT_LIST_HEAD(&new->expected_list); 1421+ memcpy(new, expect, sizeof(*expect)); 1422+ new->expectant = related_to; 1423+ new->sibling = NULL; 1424+ /* increase usage count. This sucks. The memset above overwrites 1425+ * old usage count [if still present] and we increase to one. Only 1426+ * works because everything is done under ip_conntrack_lock() */ 1427+ atomic_inc(&new->use); 1428+ 1429+ /* add to expected list for this connection */ 1430+ list_add(&new->expected_list, &related_to->sibling_list); 1431+ /* add to global list of expectations */ 1432+ list_prepend(&ip_conntrack_expect_list, &new->list); 1433+ /* add and start timer if required */ 1434+ if (related_to->helper->timeout) { 1435+ init_timer(&new->timeout); 1436+ new->timeout.data = (unsigned long)new; 1437+ new->timeout.function = expectation_timed_out; 1438+ new->timeout.expires = jiffies + 1439+ related_to->helper->timeout * HZ; 1440+ add_timer(&new->timeout); 1441+ } 1442+ related_to->expecting++; 1443 1444- list_prepend(&expect_list, &related_to->expected); 1445- related_to->expected.expectant = related_to; 1446 WRITE_UNLOCK(&ip_conntrack_lock); 1447 1448- return 0; 1449+ return ret; 1450 } 1451 1452-void ip_conntrack_unexpect_related(struct ip_conntrack *related_to) 1453+/* Change tuple in an existing expectation */ 1454+int ip_conntrack_change_expect(struct ip_conntrack_expect *expect, 1455+ struct ip_conntrack_tuple *newtuple) 1456 { 1457- WRITE_LOCK(&ip_conntrack_lock); 1458- unexpect_related(related_to); 1459- WRITE_UNLOCK(&ip_conntrack_lock); 1460-} 1461+ int ret; 1462+ 1463+ MUST_BE_READ_LOCKED(&ip_conntrack_lock); 1464+ WRITE_LOCK(&ip_conntrack_expect_tuple_lock); 1465+ 1466+ DEBUGP("change_expect:\n"); 1467+ DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple); 1468+ DEBUGP("exp mask: "); DUMP_TUPLE(&expect->mask); 1469+ DEBUGP("newtuple: "); DUMP_TUPLE(newtuple); 1470+ if (expect->ct_tuple.dst.protonum == 0) { 1471+ /* Never seen before */ 1472+ DEBUGP("change expect: never seen before\n"); 1473+ if (!ip_ct_tuple_equal(&expect->tuple, newtuple) 1474+ && LIST_FIND(&ip_conntrack_expect_list, expect_clash, 1475+ struct ip_conntrack_expect *, newtuple, &expect->mask)) { 1476+ /* Force NAT to find an unused tuple */ 1477+ ret = -1; 1478+ } else { 1479+ memcpy(&expect->ct_tuple, &expect->tuple, sizeof(expect->tuple)); 1480+ memcpy(&expect->tuple, newtuple, sizeof(expect->tuple)); 1481+ ret = 0; 1482+ } 1483+ } else { 1484+ /* Resent packet */ 1485+ DEBUGP("change expect: resent packet\n"); 1486+ if (ip_ct_tuple_equal(&expect->tuple, newtuple)) { 1487+ ret = 0; 1488+ } else { 1489+ /* Force NAT to choose again the same port */ 1490+ ret = -1; 1491+ } 1492+ } 1493+ WRITE_UNLOCK(&ip_conntrack_expect_tuple_lock); 1494 1495+ return ret; 1496+} 1497+ 1498 /* Alter reply tuple (maybe alter helper). If it's already taken, 1499 return 0 and don't do alteration. */ 1500 int ip_conntrack_alter_reply(struct ip_conntrack *conntrack, 1501@@ -790,10 +1114,12 @@ 1502 DUMP_TUPLE(newreply); 1503 1504 conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; 1505- conntrack->helper = LIST_FIND(&helpers, helper_cmp, 1506- struct ip_conntrack_helper *, 1507- newreply); 1508+ if (!conntrack->master) 1509+ conntrack->helper = LIST_FIND(&helpers, helper_cmp, 1510+ struct ip_conntrack_helper *, 1511+ newreply); 1512 WRITE_UNLOCK(&ip_conntrack_lock); 1513+ 1514 return 1; 1515 } 1516 1517@@ -812,14 +1138,10 @@ 1518 const struct ip_conntrack_helper *me) 1519 { 1520 if (i->ctrack->helper == me) { 1521- i->ctrack->helper = NULL; 1522 /* Get rid of any expected. */ 1523- if (i->ctrack->expected.expectant) { 1524- IP_NF_ASSERT(i->ctrack->expected.expectant 1525- == i->ctrack); 1526- LIST_DELETE(&expect_list, &i->ctrack->expected); 1527- i->ctrack->expected.expectant = NULL; 1528- } 1529+ remove_expectations(i->ctrack); 1530+ /* And *then* set helper to NULL */ 1531+ i->ctrack->helper = NULL; 1532 } 1533 return 0; 1534 } 1535@@ -1100,18 +1422,22 @@ 1536 } 1537 ip_conntrack_max = 8 * ip_conntrack_htable_size; 1538 1539- printk("ip_conntrack (%u buckets, %d max)\n", 1540- ip_conntrack_htable_size, ip_conntrack_max); 1541+ printk("ip_conntrack version %s (%u buckets, %d max)" 1542+ " - %d bytes per conntrack\n", IP_CONNTRACK_VERSION, 1543+ ip_conntrack_htable_size, ip_conntrack_max, 1544+ sizeof(struct ip_conntrack)); 1545 1546 ret = nf_register_sockopt(&so_getorigdst); 1547- if (ret != 0) 1548+ if (ret != 0) { 1549+ printk(KERN_ERR "Unable to register netfilter socket option\n"); 1550 return ret; 1551+ } 1552 1553 ip_conntrack_hash = vmalloc(sizeof(struct list_head) 1554 * ip_conntrack_htable_size); 1555 if (!ip_conntrack_hash) { 1556- nf_unregister_sockopt(&so_getorigdst); 1557- return -ENOMEM; 1558+ printk(KERN_ERR "Unable to create ip_conntrack_hash\n"); 1559+ goto err_unreg_sockopt; 1560 } 1561 1562 ip_conntrack_cachep = kmem_cache_create("ip_conntrack", 1563@@ -1119,11 +1445,8 @@ 1564 SLAB_HWCACHE_ALIGN, NULL, NULL); 1565 if (!ip_conntrack_cachep) { 1566 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n"); 1567- vfree(ip_conntrack_hash); 1568- nf_unregister_sockopt(&so_getorigdst); 1569- return -ENOMEM; 1570+ goto err_free_hash; 1571 } 1572- 1573 /* Don't NEED lock here, but good form anyway. */ 1574 WRITE_LOCK(&ip_conntrack_lock); 1575 /* Sew in builtin protocols. */ 1576@@ -1142,14 +1465,20 @@ 1577 ip_conntrack_sysctl_header 1578 = register_sysctl_table(ip_conntrack_root_table, 0); 1579 if (ip_conntrack_sysctl_header == NULL) { 1580- kmem_cache_destroy(ip_conntrack_cachep); 1581- vfree(ip_conntrack_hash); 1582- nf_unregister_sockopt(&so_getorigdst); 1583- return -ENOMEM; 1584+ goto err_free_ct_cachep; 1585 } 1586 #endif /*CONFIG_SYSCTL*/ 1587 1588 /* For use by ipt_REJECT */ 1589 ip_ct_attach = ip_conntrack_attach; 1590 return ret; 1591+ 1592+err_free_ct_cachep: 1593+ kmem_cache_destroy(ip_conntrack_cachep); 1594+err_free_hash: 1595+ vfree(ip_conntrack_hash); 1596+err_unreg_sockopt: 1597+ nf_unregister_sockopt(&so_getorigdst); 1598+ 1599+ return -ENOMEM; 1600 } 1601diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_ftp.c 1602--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_ftp.c Wed Oct 31 00:08:12 2001 1603+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_ftp.c Fri Nov 29 00:53:15 2002 1604@@ -1,4 +1,5 @@ 1605 /* FTP extension for IP connection tracking. */ 1606+#include <linux/config.h> 1607 #include <linux/module.h> 1608 #include <linux/netfilter.h> 1609 #include <linux/ip.h> 1610@@ -15,7 +16,7 @@ 1611 1612 #define MAX_PORTS 8 1613 static int ports[MAX_PORTS]; 1614-static int ports_c; 1615+static int ports_c = 0; 1616 #ifdef MODULE_PARM 1617 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); 1618 #endif 1619@@ -242,8 +243,10 @@ 1620 u_int32_t array[6] = { 0 }; 1621 int dir = CTINFO2DIR(ctinfo); 1622 unsigned int matchlen, matchoff; 1623- struct ip_conntrack_tuple t, mask; 1624- struct ip_ct_ftp *info = &ct->help.ct_ftp_info; 1625+ struct ip_ct_ftp_master *ct_ftp_info = &ct->help.ct_ftp_info; 1626+ struct ip_conntrack_expect expect, *exp = &expect; 1627+ struct ip_ct_ftp_expect *exp_ftp_info = &exp->help.exp_ftp_info; 1628+ 1629 unsigned int i; 1630 int found = 0; 1631 1632@@ -271,8 +274,8 @@ 1633 } 1634 1635 LOCK_BH(&ip_ftp_lock); 1636- old_seq_aft_nl_set = info->seq_aft_nl_set[dir]; 1637- old_seq_aft_nl = info->seq_aft_nl[dir]; 1638+ old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir]; 1639+ old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir]; 1640 1641 DEBUGP("conntrack_ftp: datalen %u\n", datalen); 1642 if ((datalen > 0) && (data[datalen-1] == '\n')) { 1643@@ -281,8 +284,9 @@ 1644 || after(ntohl(tcph->seq) + datalen, old_seq_aft_nl)) { 1645 DEBUGP("conntrack_ftp: updating nl to %u\n", 1646 ntohl(tcph->seq) + datalen); 1647- info->seq_aft_nl[dir] = ntohl(tcph->seq) + datalen; 1648- info->seq_aft_nl_set[dir] = 1; 1649+ ct_ftp_info->seq_aft_nl[dir] = 1650+ ntohl(tcph->seq) + datalen; 1651+ ct_ftp_info->seq_aft_nl_set[dir] = 1; 1652 } 1653 } 1654 UNLOCK_BH(&ip_ftp_lock); 1655@@ -330,16 +334,17 @@ 1656 DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", 1657 (int)matchlen, data + matchoff, 1658 matchlen, ntohl(tcph->seq) + matchoff); 1659+ 1660+ memset(&expect, 0, sizeof(expect)); 1661 1662 /* Update the ftp info */ 1663 LOCK_BH(&ip_ftp_lock); 1664 if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]) 1665 == ct->tuplehash[dir].tuple.src.ip) { 1666- info->is_ftp = 21; 1667- info->seq = ntohl(tcph->seq) + matchoff; 1668- info->len = matchlen; 1669- info->ftptype = search[i].ftptype; 1670- info->port = array[4] << 8 | array[5]; 1671+ exp->seq = ntohl(tcph->seq) + matchoff; 1672+ exp_ftp_info->len = matchlen; 1673+ exp_ftp_info->ftptype = search[i].ftptype; 1674+ exp_ftp_info->port = array[4] << 8 | array[5]; 1675 } else { 1676 /* Enrico Scholz's passive FTP to partially RNAT'd ftp 1677 server: it really wants us to connect to a 1678@@ -356,18 +361,21 @@ 1679 if (!loose) goto out; 1680 } 1681 1682- t = ((struct ip_conntrack_tuple) 1683+ exp->tuple = ((struct ip_conntrack_tuple) 1684 { { ct->tuplehash[!dir].tuple.src.ip, 1685 { 0 } }, 1686 { htonl((array[0] << 24) | (array[1] << 16) 1687 | (array[2] << 8) | array[3]), 1688 { htons(array[4] << 8 | array[5]) }, 1689 IPPROTO_TCP }}); 1690- mask = ((struct ip_conntrack_tuple) 1691+ exp->mask = ((struct ip_conntrack_tuple) 1692 { { 0xFFFFFFFF, { 0 } }, 1693 { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); 1694+ 1695+ exp->expectfn = NULL; 1696+ 1697 /* Ignore failure; should only happen with NAT */ 1698- ip_conntrack_expect_related(ct, &t, &mask, NULL); 1699+ ip_conntrack_expect_related(ct, &expect); 1700 out: 1701 UNLOCK_BH(&ip_ftp_lock); 1702 1703@@ -375,12 +383,13 @@ 1704 } 1705 1706 static struct ip_conntrack_helper ftp[MAX_PORTS]; 1707+static char ftp_names[MAX_PORTS][10]; 1708 1709 /* Not __exit: called from init() */ 1710 static void fini(void) 1711 { 1712 int i; 1713- for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 1714+ for (i = 0; i < ports_c; i++) { 1715 DEBUGP("ip_ct_ftp: unregistering helper for port %d\n", 1716 ports[i]); 1717 ip_conntrack_helper_unregister(&ftp[i]); 1718@@ -390,9 +399,10 @@ 1719 static int __init init(void) 1720 { 1721 int i, ret; 1722+ char *tmpname; 1723 1724 if (ports[0] == 0) 1725- ports[0] = 21; 1726+ ports[0] = FTP_PORT; 1727 1728 for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 1729 memset(&ftp[i], 0, sizeof(struct ip_conntrack_helper)); 1730@@ -400,7 +410,19 @@ 1731 ftp[i].tuple.dst.protonum = IPPROTO_TCP; 1732 ftp[i].mask.src.u.tcp.port = 0xFFFF; 1733 ftp[i].mask.dst.protonum = 0xFFFF; 1734+ ftp[i].max_expected = 1; 1735+ ftp[i].timeout = 0; 1736+ ftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT; 1737+ ftp[i].me = ip_conntrack_ftp; 1738 ftp[i].help = help; 1739+ 1740+ tmpname = &ftp_names[i][0]; 1741+ if (ports[i] == FTP_PORT) 1742+ sprintf(tmpname, "ftp"); 1743+ else 1744+ sprintf(tmpname, "ftp-%d", ports[i]); 1745+ ftp[i].name = tmpname; 1746+ 1747 DEBUGP("ip_ct_ftp: registering helper for port %d\n", 1748 ports[i]); 1749 ret = ip_conntrack_helper_register(&ftp[i]); 1750@@ -414,10 +436,10 @@ 1751 return 0; 1752 } 1753 1754- 1755+#ifdef CONFIG_IP_NF_NAT_NEEDED 1756 EXPORT_SYMBOL(ip_ftp_lock); 1757-EXPORT_SYMBOL(ip_conntrack_ftp); 1758-MODULE_LICENSE("GPL"); 1759+#endif 1760 1761+MODULE_LICENSE("GPL"); 1762 module_init(init); 1763 module_exit(fini); 1764diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_irc.c 1765--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_irc.c Mon Feb 25 20:38:14 2002 1766+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_irc.c Fri Nov 29 00:53:15 2002 1767@@ -11,12 +11,18 @@ 1768 ** 1769 * Module load syntax: 1770 * insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS> 1771+ * max_dcc_channels=n dcc_timeout=secs 1772 * 1773 * please give the ports of all IRC servers You wish to connect to. 1774- * If You don't specify ports, the default will be port 6667 1775+ * If You don't specify ports, the default will be port 6667. 1776+ * With max_dcc_channels you can define the maximum number of not 1777+ * yet answered DCC channels per IRC session (default 8). 1778+ * With dcc_timeout you can specify how long the system waits for 1779+ * an expected DCC channel (default 300 seconds). 1780 * 1781 */ 1782 1783+#include <linux/config.h> 1784 #include <linux/module.h> 1785 #include <linux/netfilter.h> 1786 #include <linux/ip.h> 1787@@ -29,7 +35,9 @@ 1788 1789 #define MAX_PORTS 8 1790 static int ports[MAX_PORTS]; 1791-static int ports_n_c = 0; 1792+static int ports_c = 0; 1793+static int max_dcc_channels = 8; 1794+static unsigned int dcc_timeout = 300; 1795 1796 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 1797 MODULE_DESCRIPTION("IRC (DCC) connection tracking module"); 1798@@ -37,6 +45,10 @@ 1799 #ifdef MODULE_PARM 1800 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); 1801 MODULE_PARM_DESC(ports, "port numbers of IRC servers"); 1802+MODULE_PARM(max_dcc_channels, "i"); 1803+MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); 1804+MODULE_PARM(dcc_timeout, "i"); 1805+MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); 1806 #endif 1807 1808 #define NUM_DCCPROTO 5 1809@@ -103,23 +115,15 @@ 1810 u_int32_t tcplen = len - iph->ihl * 4; 1811 u_int32_t datalen = tcplen - tcph->doff * 4; 1812 int dir = CTINFO2DIR(ctinfo); 1813- struct ip_conntrack_tuple t, mask; 1814+ struct ip_conntrack_expect expect, *exp = &expect; 1815+ struct ip_ct_irc_expect *exp_irc_info = &exp->help.exp_irc_info; 1816 1817 u_int32_t dcc_ip; 1818 u_int16_t dcc_port; 1819 int i; 1820 char *addr_beg_p, *addr_end_p; 1821 1822- struct ip_ct_irc *info = &ct->help.ct_irc_info; 1823- 1824- mask = ((struct ip_conntrack_tuple) 1825- { { 0, { 0 } }, 1826- { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); 1827- 1828 DEBUGP("entered\n"); 1829- /* Can't track connections formed before we registered */ 1830- if (!info) 1831- return NF_ACCEPT; 1832 1833 /* If packet is coming from IRC server */ 1834 if (dir == IP_CT_DIR_REPLY) 1835@@ -189,33 +193,37 @@ 1836 1837 continue; 1838 } 1839+ 1840+ memset(&expect, 0, sizeof(expect)); 1841 1842 LOCK_BH(&ip_irc_lock); 1843 1844 /* save position of address in dcc string, 1845 * neccessary for NAT */ 1846- info->is_irc = IP_CONNTR_IRC; 1847 DEBUGP("tcph->seq = %u\n", tcph->seq); 1848- info->seq = ntohl(tcph->seq) + (addr_beg_p - _data); 1849- info->len = (addr_end_p - addr_beg_p); 1850- info->port = dcc_port; 1851+ exp->seq = ntohl(tcph->seq) + (addr_beg_p - _data); 1852+ exp_irc_info->len = (addr_end_p - addr_beg_p); 1853+ exp_irc_info->port = dcc_port; 1854 DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n", 1855- info->seq, (addr_end_p - _data), info->len); 1856+ exp->seq, (addr_end_p - _data), exp_irc_info->len); 1857 1858- memset(&t, 0, sizeof(t)); 1859- t.src.ip = 0; 1860- t.src.u.tcp.port = 0; 1861- t.dst.ip = htonl(dcc_ip); 1862- t.dst.u.tcp.port = htons(info->port); 1863- t.dst.protonum = IPPROTO_TCP; 1864+ exp->tuple = ((struct ip_conntrack_tuple) 1865+ { { 0, { 0 } }, 1866+ { htonl(dcc_ip), { htons(dcc_port) }, 1867+ IPPROTO_TCP }}); 1868+ exp->mask = ((struct ip_conntrack_tuple) 1869+ { { 0, { 0 } }, 1870+ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); 1871+ 1872+ exp->expectfn = NULL; 1873 1874 DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n", 1875- NIPQUAD(t.src.ip), 1876- ntohs(t.src.u.tcp.port), 1877- NIPQUAD(t.dst.ip), 1878- ntohs(t.dst.u.tcp.port)); 1879+ NIPQUAD(exp->tuple.src.ip), 1880+ ntohs(exp->tuple.src.u.tcp.port), 1881+ NIPQUAD(exp->tuple.dst.ip), 1882+ ntohs(exp->tuple.dst.u.tcp.port)); 1883 1884- ip_conntrack_expect_related(ct, &t, &mask, NULL); 1885+ ip_conntrack_expect_related(ct, &expect); 1886 UNLOCK_BH(&ip_irc_lock); 1887 1888 return NF_ACCEPT; 1889@@ -226,29 +234,53 @@ 1890 } 1891 1892 static struct ip_conntrack_helper irc_helpers[MAX_PORTS]; 1893+static char irc_names[MAX_PORTS][10]; 1894 1895 static void fini(void); 1896 1897 static int __init init(void) 1898 { 1899 int i, ret; 1900+ struct ip_conntrack_helper *hlpr; 1901+ char *tmpname; 1902 1903+ if (max_dcc_channels < 1) { 1904+ printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n"); 1905+ return -EBUSY; 1906+ } 1907+ if (dcc_timeout < 0) { 1908+ printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n"); 1909+ return -EBUSY; 1910+ } 1911+ 1912 /* If no port given, default to standard irc port */ 1913 if (ports[0] == 0) 1914- ports[0] = 6667; 1915+ ports[0] = IRC_PORT; 1916 1917 for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 1918- memset(&irc_helpers[i], 0, 1919+ hlpr = &irc_helpers[i]; 1920+ memset(hlpr, 0, 1921 sizeof(struct ip_conntrack_helper)); 1922- irc_helpers[i].tuple.src.u.tcp.port = htons(ports[i]); 1923- irc_helpers[i].tuple.dst.protonum = IPPROTO_TCP; 1924- irc_helpers[i].mask.src.u.tcp.port = 0xFFFF; 1925- irc_helpers[i].mask.dst.protonum = 0xFFFF; 1926- irc_helpers[i].help = help; 1927+ hlpr->tuple.src.u.tcp.port = htons(ports[i]); 1928+ hlpr->tuple.dst.protonum = IPPROTO_TCP; 1929+ hlpr->mask.src.u.tcp.port = 0xFFFF; 1930+ hlpr->mask.dst.protonum = 0xFFFF; 1931+ hlpr->max_expected = max_dcc_channels; 1932+ hlpr->timeout = dcc_timeout; 1933+ hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT; 1934+ hlpr->me = ip_conntrack_irc; 1935+ hlpr->help = help; 1936+ 1937+ tmpname = &irc_names[i][0]; 1938+ if (ports[i] == IRC_PORT) 1939+ sprintf(tmpname, "irc"); 1940+ else 1941+ sprintf(tmpname, "irc-%d", i); 1942+ hlpr->name = tmpname; 1943 1944 DEBUGP("port #%d: %d\n", i, ports[i]); 1945 1946- ret = ip_conntrack_helper_register(&irc_helpers[i]); 1947+ ret = ip_conntrack_helper_register(hlpr); 1948 1949 if (ret) { 1950 printk("ip_conntrack_irc: ERROR registering port %d\n", 1951@@ -256,7 +288,7 @@ 1952 fini(); 1953 return -EBUSY; 1954 } 1955- ports_n_c++; 1956+ ports_c++; 1957 } 1958 return 0; 1959 } 1960@@ -266,12 +298,16 @@ 1961 static void fini(void) 1962 { 1963 int i; 1964- for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 1965+ for (i = 0; i < ports_c; i++) { 1966 DEBUGP("unregistering port %d\n", 1967 ports[i]); 1968 ip_conntrack_helper_unregister(&irc_helpers[i]); 1969 } 1970 } 1971+ 1972+#ifdef CONFIG_IP_NF_NAT_NEEDED 1973+EXPORT_SYMBOL(ip_irc_lock); 1974+#endif 1975 1976 module_init(init); 1977 module_exit(fini); 1978diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c 1979--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c Sat Aug 3 02:39:46 2002 1980+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_generic.c Fri Nov 29 00:53:15 2002 1981@@ -57,5 +57,5 @@ 1982 struct ip_conntrack_protocol ip_conntrack_generic_protocol 1983 = { { NULL, NULL }, 0, "unknown", 1984 generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple, 1985- generic_print_conntrack, established, new, NULL, NULL }; 1986+ generic_print_conntrack, established, new, NULL, NULL, NULL }; 1987 1988diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 1989--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Sat Aug 3 02:39:46 2002 1990+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Fri Nov 29 00:53:15 2002 1991@@ -113,4 +113,4 @@ 1992 struct ip_conntrack_protocol ip_conntrack_protocol_icmp 1993 = { { NULL, NULL }, IPPROTO_ICMP, "icmp", 1994 icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple, 1995- icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL }; 1996+ icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL }; 1997diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 1998--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Sat Aug 3 02:39:46 2002 1999+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Fri Nov 29 00:53:15 2002 2000@@ -7,6 +7,10 @@ 2001 #include <linux/in.h> 2002 #include <linux/ip.h> 2003 #include <linux/tcp.h> 2004+#include <linux/string.h> 2005+ 2006+#include <net/tcp.h> 2007+ 2008 #include <linux/netfilter_ipv4/ip_conntrack.h> 2009 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 2010 #include <linux/netfilter_ipv4/lockhelp.h> 2011@@ -227,7 +231,19 @@ 2012 return 1; 2013 } 2014 2015+static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp, 2016+ struct sk_buff **pskb) 2017+{ 2018+ struct iphdr *iph = (*pskb)->nh.iph; 2019+ struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl); 2020+ unsigned int datalen; 2021+ 2022+ datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4; 2023+ 2024+ return between(exp->seq, ntohl(tcph->seq), ntohl(tcph->seq) + datalen); 2025+} 2026+ 2027 struct ip_conntrack_protocol ip_conntrack_protocol_tcp 2028 = { { NULL, NULL }, IPPROTO_TCP, "tcp", 2029 tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack, 2030- tcp_packet, tcp_new, NULL, NULL }; 2031+ tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL }; 2032diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2033--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c Sat Aug 3 02:39:46 2002 2034+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_proto_udp.c Fri Nov 29 00:53:15 2002 2035@@ -71,4 +71,4 @@ 2036 struct ip_conntrack_protocol ip_conntrack_protocol_udp 2037 = { { NULL, NULL }, IPPROTO_UDP, "udp", 2038 udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack, 2039- udp_packet, udp_new, NULL, NULL }; 2040+ udp_packet, udp_new, NULL, NULL, NULL }; 2041diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_standalone.c 2042--- linux-2.4.19-plain/net/ipv4/netfilter/ip_conntrack_standalone.c Sat Aug 3 02:39:46 2002 2043+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Nov 29 00:53:15 2002 2044@@ -62,10 +62,16 @@ 2045 { 2046 unsigned int len; 2047 2048- len = sprintf(buffer, "EXPECTING: proto=%u ", 2049- expect->tuple.dst.protonum); 2050+ if (expect->expectant->helper->timeout) 2051+ len = sprintf(buffer, "EXPECTING: %lu ", 2052+ timer_pending(&expect->timeout) 2053+ ? (expect->timeout.expires - jiffies)/HZ : 0); 2054+ else 2055+ len = sprintf(buffer, "EXPECTING: - "); 2056+ len += sprintf(buffer + len, "use=%u proto=%u ", 2057+ atomic_read(&expect->use), expect->tuple.dst.protonum); 2058 len += print_tuple(buffer + len, &expect->tuple, 2059- __find_proto(expect->tuple.dst.protonum)); 2060+ __ip_ct_find_proto(expect->tuple.dst.protonum)); 2061 len += sprintf(buffer + len, "\n"); 2062 return len; 2063 } 2064@@ -75,7 +81,7 @@ 2065 { 2066 unsigned int len; 2067 struct ip_conntrack_protocol *proto 2068- = __find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] 2069+ = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] 2070 .tuple.dst.protonum); 2071 2072 len = sprintf(buffer, "%-8s %u %lu ", 2073@@ -147,7 +153,8 @@ 2074 } 2075 2076 /* Now iterate through expecteds. */ 2077- for (e = expect_list.next; e != &expect_list; e = e->next) { 2078+ for (e = ip_conntrack_expect_list.next; 2079+ e != &ip_conntrack_expect_list; e = e->next) { 2080 unsigned int last_len; 2081 struct ip_conntrack_expect *expect 2082 = (struct ip_conntrack_expect *)e; 2083@@ -314,7 +321,7 @@ 2084 { 2085 WRITE_LOCK(&ip_conntrack_lock); 2086 2087- /* find_proto() returns proto_generic in case there is no protocol 2088+ /* ip_ct_find_proto() returns proto_generic in case there is no protocol 2089 * helper. So this should be enough - HW */ 2090 LIST_DELETE(&protocol_list, proto); 2091 WRITE_UNLOCK(&ip_conntrack_lock); 2092@@ -353,8 +360,19 @@ 2093 EXPORT_SYMBOL(ip_conntrack_helper_unregister); 2094 EXPORT_SYMBOL(ip_ct_selective_cleanup); 2095 EXPORT_SYMBOL(ip_ct_refresh); 2096+EXPORT_SYMBOL(ip_ct_find_proto); 2097+EXPORT_SYMBOL(__ip_ct_find_proto); 2098+EXPORT_SYMBOL(ip_ct_find_helper); 2099 EXPORT_SYMBOL(ip_conntrack_expect_related); 2100+EXPORT_SYMBOL(ip_conntrack_change_expect); 2101 EXPORT_SYMBOL(ip_conntrack_unexpect_related); 2102+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get); 2103+EXPORT_SYMBOL_GPL(ip_conntrack_expect_put); 2104 EXPORT_SYMBOL(ip_conntrack_tuple_taken); 2105 EXPORT_SYMBOL(ip_ct_gather_frags); 2106 EXPORT_SYMBOL(ip_conntrack_htable_size); 2107+EXPORT_SYMBOL(ip_conntrack_expect_list); 2108+EXPORT_SYMBOL(ip_conntrack_lock); 2109+EXPORT_SYMBOL(ip_conntrack_hash); 2110+EXPORT_SYMBOL_GPL(ip_conntrack_find_get); 2111+EXPORT_SYMBOL_GPL(ip_conntrack_put); 2112diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.4.20-plain/net/ipv4/netfilter/ip_fw_compat_masq.c 2113--- linux-2.4.19-plain/net/ipv4/netfilter/ip_fw_compat_masq.c Mon Feb 25 20:38:14 2002 2114+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_fw_compat_masq.c Fri Nov 29 00:53:15 2002 2115@@ -130,7 +130,7 @@ 2116 struct ip_conntrack *ct; 2117 int ret; 2118 2119- protocol = find_proto(iph->protocol); 2120+ protocol = ip_ct_find_proto(iph->protocol); 2121 2122 /* We don't feed packets to conntrack system unless we know 2123 they're part of an connection already established by an 2124diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_core.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_core.c 2125--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_core.c Sat Aug 3 02:39:46 2002 2126+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_core.c Fri Nov 29 00:53:15 2002 2127@@ -21,10 +21,14 @@ 2128 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) 2129 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) 2130 2131+#include <linux/netfilter_ipv4/ip_conntrack.h> 2132+#include <linux/netfilter_ipv4/ip_conntrack_core.h> 2133+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 2134 #include <linux/netfilter_ipv4/ip_nat.h> 2135 #include <linux/netfilter_ipv4/ip_nat_protocol.h> 2136 #include <linux/netfilter_ipv4/ip_nat_core.h> 2137 #include <linux/netfilter_ipv4/ip_nat_helper.h> 2138+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 2139 #include <linux/netfilter_ipv4/listhelp.h> 2140 2141 #if 0 2142@@ -34,6 +38,7 @@ 2143 #endif 2144 2145 DECLARE_RWLOCK(ip_nat_lock); 2146+DECLARE_RWLOCK_EXTERN(ip_conntrack_lock); 2147 2148 /* Calculated at init based on memory size */ 2149 static unsigned int ip_nat_htable_size; 2150@@ -198,6 +203,7 @@ 2151 return NULL; 2152 } 2153 2154+#ifdef CONFIG_IP_NF_NAT_LOCAL 2155 /* If it's really a local destination manip, it may need to do a 2156 source manip too. */ 2157 static int 2158@@ -216,6 +222,7 @@ 2159 ip_rt_put(rt); 2160 return 1; 2161 } 2162+#endif 2163 2164 /* Simple way to iterate through all. */ 2165 static inline int fake_cmp(const struct ip_nat_hash *i, 2166@@ -628,8 +635,9 @@ 2167 } 2168 2169 /* If there's a helper, assign it; based on new tuple. */ 2170- info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, 2171- &reply); 2172+ if (!conntrack->master) 2173+ info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, 2174+ &reply); 2175 2176 /* It's done. */ 2177 info->initialized |= (1 << HOOK2MANIP(hooknum)); 2178@@ -724,6 +732,20 @@ 2179 #endif 2180 } 2181 2182+static inline int exp_for_packet(struct ip_conntrack_expect *exp, 2183+ struct sk_buff **pskb) 2184+{ 2185+ struct ip_conntrack_protocol *proto; 2186+ int ret = 1; 2187+ 2188+ MUST_BE_READ_LOCKED(&ip_conntrack_lock); 2189+ proto = __ip_ct_find_proto((*pskb)->nh.iph->protocol); 2190+ if (proto->exp_matches_pkt) 2191+ ret = proto->exp_matches_pkt(exp, pskb); 2192+ 2193+ return ret; 2194+} 2195+ 2196 /* Do packet manipulations according to binding. */ 2197 unsigned int 2198 do_bindings(struct ip_conntrack *ct, 2199@@ -735,6 +757,7 @@ 2200 unsigned int i; 2201 struct ip_nat_helper *helper; 2202 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 2203+ int is_tcp = (*pskb)->nh.iph->protocol == IPPROTO_TCP; 2204 2205 /* Need nat lock to protect against modification, but neither 2206 conntrack (referenced) and helper (deleted with 2207@@ -773,11 +796,66 @@ 2208 READ_UNLOCK(&ip_nat_lock); 2209 2210 if (helper) { 2211+ struct ip_conntrack_expect *exp = NULL; 2212+ struct list_head *cur_item; 2213+ int ret = NF_ACCEPT; 2214+ 2215+ DEBUGP("do_bindings: helper existing for (%p)\n", ct); 2216+ 2217 /* Always defragged for helpers */ 2218 IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off 2219- & __constant_htons(IP_MF|IP_OFFSET))); 2220- return helper->help(ct, info, ctinfo, hooknum, pskb); 2221- } else return NF_ACCEPT; 2222+ & htons(IP_MF|IP_OFFSET))); 2223+ 2224+ /* Have to grab read lock before sibling_list traversal */ 2225+ READ_LOCK(&ip_conntrack_lock); 2226+ list_for_each(cur_item, &ct->sibling_list) { 2227+ exp = list_entry(cur_item, struct ip_conntrack_expect, 2228+ expected_list); 2229+ 2230+ /* if this expectation is already established, skip */ 2231+ if (exp->sibling) 2232+ continue; 2233+ 2234+ if (exp_for_packet(exp, pskb)) { 2235+ 2236+ DEBUGP("calling nat helper (exp=%p) for packet\n", 2237+ exp); 2238+ ret = helper->help(ct, exp, info, ctinfo, 2239+ hooknum, pskb); 2240+ if (ret != NF_ACCEPT) { 2241+ READ_UNLOCK(&ip_conntrack_lock); 2242+ return ret; 2243+ } 2244+ } 2245+ } 2246+ /* Helper might want to manip the packet even when there is no expectation */ 2247+ if (!exp && helper->flags & IP_NAT_HELPER_F_ALWAYS) { 2248+ DEBUGP("calling nat helper for packet without expectation\n"); 2249+ ret = helper->help(ct, NULL, info, ctinfo, 2250+ hooknum, pskb); 2251+ if (ret != NF_ACCEPT) { 2252+ READ_UNLOCK(&ip_conntrack_lock); 2253+ return ret; 2254+ } 2255+ } 2256+ READ_UNLOCK(&ip_conntrack_lock); 2257+ 2258+ /* Adjust sequence number only once per packet 2259+ * (helper is called at all hooks) */ 2260+ if (is_tcp && (hooknum == NF_IP_POST_ROUTING 2261+ || hooknum == NF_IP_LOCAL_IN)) { 2262+ DEBUGP("ip_nat_core: adjusting sequence number\n"); 2263+ /* future: put this in a l4-proto specific function, 2264+ * and call this function here. */ 2265+ ip_nat_seq_adjust(*pskb, ct, ctinfo); 2266+ } 2267+ 2268+ return ret; 2269+ 2270+ } else 2271+ return NF_ACCEPT; 2272+ 2273+ /* not reached */ 2274 } 2275 2276 unsigned int 2277@@ -816,7 +894,7 @@ 2278 2279-static int 2280+static unsigned int 2281 ftp_nat_expected(struct sk_buff **pskb, 2282 unsigned int hooknum, 2283 struct ip_conntrack *ct, 2284- struct ip_nat_info *info, 2285- struct ip_conntrack *master, 2286- struct ip_nat_info *masterinfo, 2287- unsigned int *verdict) 2288+ struct ip_nat_info *info) 2289 { 2290 struct ip_nat_multi_range mr; 2291 u_int32_t newdstip, newsrcip, newip; 2292- struct ip_ct_ftp *ftpinfo; 2293+ struct ip_ct_ftp_expect *exp_ftp_info; 2294 2295+ struct ip_conntrack *master = master_ct(ct); 2296+ 2297 IP_NF_ASSERT(info); 2298 IP_NF_ASSERT(master); 2299- IP_NF_ASSERT(masterinfo); 2300 2301 IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum)))); 2302 2303 DEBUGP("nat_expected: We have a connection!\n"); 2304- /* Master must be an ftp connection */ 2305- ftpinfo = &master->help.ct_ftp_info; 2306+ exp_ftp_info = &ct->master->help.exp_ftp_info; 2307 2308 LOCK_BH(&ip_ftp_lock); 2309- if (ftpinfo->is_ftp != 21) { 2310- UNLOCK_BH(&ip_ftp_lock); 2311- DEBUGP("nat_expected: master not ftp\n"); 2312- return 0; 2313- } 2314 2315- if (ftpinfo->ftptype == IP_CT_FTP_PORT 2316- || ftpinfo->ftptype == IP_CT_FTP_EPRT) { 2317+ if (exp_ftp_info->ftptype == IP_CT_FTP_PORT 2318+ || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) { 2319 /* PORT command: make connection go to the client. */ 2320 newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 2321 newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; 2322@@ -92,11 +84,9 @@ 2323 mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; 2324 mr.range[0].min = mr.range[0].max 2325 = ((union ip_conntrack_manip_proto) 2326- { htons(ftpinfo->port) }); 2327+ { htons(exp_ftp_info->port) }); 2328 } 2329- *verdict = ip_nat_setup_info(ct, &mr, hooknum); 2330- 2331- return 1; 2332+ return ip_nat_setup_info(ct, &mr, hooknum); 2333 } 2334 2335 static int 2336@@ -176,27 +166,22 @@ 2337 [IP_CT_FTP_EPSV] mangle_epsv_packet 2338 }; 2339 2340-static int ftp_data_fixup(const struct ip_ct_ftp *ct_ftp_info, 2341+static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info, 2342 struct ip_conntrack *ct, 2343- unsigned int datalen, 2344 struct sk_buff **pskb, 2345- enum ip_conntrack_info ctinfo) 2346+ enum ip_conntrack_info ctinfo, 2347+ struct ip_conntrack_expect *expect) 2348 { 2349 u_int32_t newip; 2350 struct iphdr *iph = (*pskb)->nh.iph; 2351 struct tcphdr *tcph = (void *)iph + iph->ihl*4; 2352 u_int16_t port; 2353- struct ip_conntrack_tuple tuple; 2354- /* Don't care about source port */ 2355- const struct ip_conntrack_tuple mask 2356- = { { 0xFFFFFFFF, { 0 } }, 2357- { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF } }; 2358+ struct ip_conntrack_tuple newtuple; 2359 2360- memset(&tuple, 0, sizeof(tuple)); 2361 MUST_BE_LOCKED(&ip_ftp_lock); 2362- DEBUGP("FTP_NAT: seq %u + %u in %u + %u\n", 2363- ct_ftp_info->seq, ct_ftp_info->len, 2364- ntohl(tcph->seq), datalen); 2365+ DEBUGP("FTP_NAT: seq %u + %u in %u\n", 2366+ expect->seq, ct_ftp_info->len, 2367+ ntohl(tcph->seq)); 2368 2369 /* Change address inside packet to match way we're mapping 2370 this connection. */ 2371@@ -206,29 +191,34 @@ 2372 is */ 2373 newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; 2374 /* Expect something from client->server */ 2375- tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 2376- tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; 2377+ newtuple.src.ip = 2378+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 2379+ newtuple.dst.ip = 2380+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; 2381 } else { 2382 /* PORT command: must be where server thinks client is */ 2383 newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; 2384 /* Expect something from server->client */ 2385- tuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; 2386- tuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; 2387+ newtuple.src.ip = 2388+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; 2389+ newtuple.dst.ip = 2390+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; 2391 } 2392- tuple.dst.protonum = IPPROTO_TCP; 2393+ newtuple.dst.protonum = IPPROTO_TCP; 2394+ newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port; 2395 2396 /* Try to get same port: if not, try to change it. */ 2397 for (port = ct_ftp_info->port; port != 0; port++) { 2398- tuple.dst.u.tcp.port = htons(port); 2399+ newtuple.dst.u.tcp.port = htons(port); 2400 2401- if (ip_conntrack_expect_related(ct, &tuple, &mask, NULL) == 0) 2402+ if (ip_conntrack_change_expect(expect, &newtuple) == 0) 2403 break; 2404 } 2405 if (port == 0) 2406 return 0; 2407 2408 if (!mangle[ct_ftp_info->ftptype](pskb, newip, port, 2409- ct_ftp_info->seq - ntohl(tcph->seq), 2410+ expect->seq - ntohl(tcph->seq), 2411 ct_ftp_info->len, ct, ctinfo)) 2412 return 0; 2413 2414@@ -236,6 +226,7 @@ 2415 } 2416 2417 static unsigned int help(struct ip_conntrack *ct, 2418+ struct ip_conntrack_expect *exp, 2419 struct ip_nat_info *info, 2420 enum ip_conntrack_info ctinfo, 2421 unsigned int hooknum, 2422@@ -245,13 +236,12 @@ 2423 struct tcphdr *tcph = (void *)iph + iph->ihl*4; 2424 unsigned int datalen; 2425 int dir; 2426- int score; 2427- struct ip_ct_ftp *ct_ftp_info 2428- = &ct->help.ct_ftp_info; 2429- 2430- /* Delete SACK_OK on initial TCP SYNs. */ 2431- if (tcph->syn && !tcph->ack) 2432- ip_nat_delete_sack(*pskb, tcph); 2433+ struct ip_ct_ftp_expect *ct_ftp_info; 2434+ 2435+ if (!exp) 2436+ DEBUGP("ip_nat_ftp: no exp!!"); 2437+ 2438+ ct_ftp_info = &exp->help.exp_ftp_info; 2439 2440 /* Only mangle things once: original direction in POST_ROUTING 2441 and reply direction on PRE_ROUTING. */ 2442@@ -267,103 +257,87 @@ 2443 } 2444 2445 datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; 2446- score = 0; 2447 LOCK_BH(&ip_ftp_lock); 2448- if (ct_ftp_info->len) { 2449- /* If it's in the right range... */ 2450- score += between(ct_ftp_info->seq, ntohl(tcph->seq), 2451- ntohl(tcph->seq) + datalen); 2452- score += between(ct_ftp_info->seq + ct_ftp_info->len, 2453- ntohl(tcph->seq), 2454- ntohl(tcph->seq) + datalen); 2455- if (score == 1) { 2456- /* Half a match? This means a partial retransmisison. 2457- It's a cracker being funky. */ 2458- if (net_ratelimit()) { 2459- printk("FTP_NAT: partial packet %u/%u in %u/%u\n", 2460- ct_ftp_info->seq, ct_ftp_info->len, 2461- ntohl(tcph->seq), 2462- ntohl(tcph->seq) + datalen); 2463- } 2464+ /* If it's in the right range... */ 2465+ if (between(exp->seq + ct_ftp_info->len, 2466+ ntohl(tcph->seq), 2467+ ntohl(tcph->seq) + datalen)) { 2468+ if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) { 2469 UNLOCK_BH(&ip_ftp_lock); 2470 return NF_DROP; 2471- } else if (score == 2) { 2472- if (!ftp_data_fixup(ct_ftp_info, ct, datalen, 2473- pskb, ctinfo)) { 2474- UNLOCK_BH(&ip_ftp_lock); 2475- return NF_DROP; 2476- } 2477- /* skb may have been reallocated */ 2478- iph = (*pskb)->nh.iph; 2479- tcph = (void *)iph + iph->ihl*4; 2480 } 2481+ } else { 2482+ /* Half a match? This means a partial retransmisison. 2483+ It's a cracker being funky. */ 2484+ if (net_ratelimit()) { 2485+ printk("FTP_NAT: partial packet %u/%u in %u/%u\n", 2486+ exp->seq, ct_ftp_info->len, 2487+ ntohl(tcph->seq), 2488+ ntohl(tcph->seq) + datalen); 2489+ } 2490+ UNLOCK_BH(&ip_ftp_lock); 2491+ return NF_DROP; 2492 } 2493- 2494 UNLOCK_BH(&ip_ftp_lock); 2495 2496- ip_nat_seq_adjust(*pskb, ct, ctinfo); 2497- 2498 return NF_ACCEPT; 2499 } 2500 2501 static struct ip_nat_helper ftp[MAX_PORTS]; 2502-static char ftp_names[MAX_PORTS][6]; 2503- 2504-static struct ip_nat_expect ftp_expect 2505-= { { NULL, NULL }, ftp_nat_expected }; 2506+static char ftp_names[MAX_PORTS][10]; 2507 2508 /* Not __exit: called from init() */ 2509 static void fini(void) 2510 { 2511 int i; 2512 2513- for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 2514+ for (i = 0; i < ports_c; i++) { 2515 DEBUGP("ip_nat_ftp: unregistering port %d\n", ports[i]); 2516 ip_nat_helper_unregister(&ftp[i]); 2517 } 2518- 2519- ip_nat_expect_unregister(&ftp_expect); 2520 } 2521 2522 static int __init init(void) 2523 { 2524- int i, ret; 2525+ int i, ret = 0; 2526 char *tmpname; 2527 2528- ret = ip_nat_expect_register(&ftp_expect); 2529- if (ret == 0) { 2530- if (ports[0] == 0) 2531- ports[0] = 21; 2532- 2533- for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 2534- 2535- memset(&ftp[i], 0, sizeof(struct ip_nat_helper)); 2536- 2537- ftp[i].tuple.dst.protonum = IPPROTO_TCP; 2538- ftp[i].tuple.src.u.tcp.port = htons(ports[i]); 2539- ftp[i].mask.dst.protonum = 0xFFFF; 2540- ftp[i].mask.src.u.tcp.port = 0xFFFF; 2541- ftp[i].help = help; 2542- 2543- tmpname = &ftp_names[i][0]; 2544- sprintf(tmpname, "ftp%2.2d", i); 2545- ftp[i].name = tmpname; 2546- 2547- DEBUGP("ip_nat_ftp: Trying to register for port %d\n", 2548- ports[i]); 2549- ret = ip_nat_helper_register(&ftp[i]); 2550- 2551- if (ret) { 2552- printk("ip_nat_ftp: error registering helper for port %d\n", ports[i]); 2553- fini(); 2554- return ret; 2555- } 2556- ports_c++; 2557- } 2558+ if (ports[0] == 0) 2559+ ports[0] = FTP_PORT; 2560 2561- } else { 2562- ip_nat_expect_unregister(&ftp_expect); 2563+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { 2564+ 2565+ memset(&ftp[i], 0, sizeof(struct ip_nat_helper)); 2566+ 2567+ ftp[i].tuple.dst.protonum = IPPROTO_TCP; 2568+ ftp[i].tuple.src.u.tcp.port = htons(ports[i]); 2569+ ftp[i].mask.dst.protonum = 0xFFFF; 2570+ ftp[i].mask.src.u.tcp.port = 0xFFFF; 2571+ ftp[i].help = help; 2572+ ftp[i].me = THIS_MODULE; 2573+ ftp[i].flags = 0; 2574+ ftp[i].expect = ftp_nat_expected; 2575+ 2576+ tmpname = &ftp_names[i][0]; 2577+ if (ports[i] == FTP_PORT) 2578+ sprintf(tmpname, "ftp"); 2579+ else 2580+ sprintf(tmpname, "ftp-%d", i); 2581+ ftp[i].name = tmpname; 2582+ 2583+ DEBUGP("ip_nat_ftp: Trying to register for port %d\n", 2584+ ports[i]); 2585+ ret = ip_nat_helper_register(&ftp[i]); 2586+ 2587+ if (ret) { 2588+ printk("ip_nat_ftp: error registering " 2589+ "helper for port %d\n", ports[i]); 2590+ fini(); 2591+ return ret; 2592+ } 2593+ ports_c++; 2594 } 2595+ 2596 return ret; 2597 } 2598 2599diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_helper.c 2600--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_helper.c Fri Dec 21 18:42:05 2001 2601+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_helper.c Fri Nov 29 00:53:15 2002 2602@@ -1,11 +1,18 @@ 2603 /* ip_nat_mangle.c - generic support functions for NAT helpers 2604 * 2605- * (C) 2000 by Harald Welte <laforge@gnumonks.org> 2606+ * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org> 2607 * 2608 * distributed under the terms of GNU GPL 2609+ * 2610+ * 14 Jan 2002 Harald Welte <laforge@gnumonks.org>: 2611+ * - add support for SACK adjustment 2612+ * 14 Mar 2002 Harald Welte <laforge@gnumonks.org>: 2613+ * - merge SACK support into newnat API 2614 */ 2615 #include <linux/version.h> 2616+#include <linux/config.h> 2617 #include <linux/module.h> 2618+#include <linux/kmod.h> 2619 #include <linux/types.h> 2620 #include <linux/timer.h> 2621 #include <linux/skbuff.h> 2622@@ -19,6 +26,8 @@ 2623 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) 2624 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) 2625 2626+#include <linux/netfilter_ipv4/ip_conntrack.h> 2627+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 2628 #include <linux/netfilter_ipv4/ip_nat.h> 2629 #include <linux/netfilter_ipv4/ip_nat_protocol.h> 2630 #include <linux/netfilter_ipv4/ip_nat_core.h> 2631@@ -32,7 +41,7 @@ 2632 #define DEBUGP(format, args...) 2633 #define DUMP_OFFSET(x) 2634 #endif 2635- 2636+ 2637 DECLARE_LOCK(ip_nat_seqofs_lock); 2638 2639 static inline int 2640@@ -199,6 +208,103 @@ 2641 return 1; 2642 } 2643 2644+/* Adjust one found SACK option including checksum correction */ 2645+static void 2646+sack_adjust(struct tcphdr *tcph, 2647+ unsigned char *ptr, 2648+ struct ip_nat_seq *natseq) 2649+{ 2650+ struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2); 2651+ int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; 2652+ int i; 2653+ 2654+ for (i = 0; i < num_sacks; i++, sp++) { 2655+ u_int32_t new_start_seq, new_end_seq; 2656+ 2657+ if (after(ntohl(sp->start_seq) - natseq->offset_before, 2658+ natseq->correction_pos)) 2659+ new_start_seq = ntohl(sp->start_seq) 2660+ - natseq->offset_after; 2661+ else 2662+ new_start_seq = ntohl(sp->start_seq) 2663+ - natseq->offset_before; 2664+ new_start_seq = htonl(new_start_seq); 2665+ 2666+ if (after(ntohl(sp->end_seq) - natseq->offset_before, 2667+ natseq->correction_pos)) 2668+ new_end_seq = ntohl(sp->end_seq) 2669+ - natseq->offset_after; 2670+ else 2671+ new_end_seq = ntohl(sp->end_seq) 2672+ - natseq->offset_before; 2673+ new_end_seq = htonl(new_end_seq); 2674+ 2675+ DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", 2676+ ntohl(sp->start_seq), new_start_seq, 2677+ ntohl(sp->end_seq), new_end_seq); 2678+ 2679+ tcph->check = 2680+ ip_nat_cheat_check(~sp->start_seq, new_start_seq, 2681+ ip_nat_cheat_check(~sp->end_seq, 2682+ new_end_seq, 2683+ tcph->check)); 2684+ 2685+ sp->start_seq = new_start_seq; 2686+ sp->end_seq = new_end_seq; 2687+ } 2688+} 2689+ 2690+ 2691+/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */ 2692+static inline int 2693+ip_nat_sack_adjust(struct sk_buff *skb, 2694+ struct ip_conntrack *ct, 2695+ enum ip_conntrack_info ctinfo) 2696+{ 2697+ struct iphdr *iph; 2698+ struct tcphdr *tcph; 2699+ unsigned char *ptr; 2700+ int length, dir, sack_adjusted = 0; 2701+ 2702+ iph = skb->nh.iph; 2703+ tcph = (void *)iph + iph->ihl*4; 2704+ length = (tcph->doff*4)-sizeof(struct tcphdr); 2705+ ptr = (unsigned char *)(tcph+1); 2706+ 2707+ dir = CTINFO2DIR(ctinfo); 2708+ 2709+ while (length > 0) { 2710+ int opcode = *ptr++; 2711+ int opsize; 2712+ 2713+ switch (opcode) { 2714+ case TCPOPT_EOL: 2715+ return !sack_adjusted; 2716+ case TCPOPT_NOP: 2717+ length--; 2718+ continue; 2719+ default: 2720+ opsize = *ptr++; 2721+ if (opsize > length) /* no partial opts */ 2722+ return !sack_adjusted; 2723+ if (opcode == TCPOPT_SACK) { 2724+ /* found SACK */ 2725+ if((opsize >= (TCPOLEN_SACK_BASE 2726+ +TCPOLEN_SACK_PERBLOCK)) && 2727+ !((opsize - TCPOLEN_SACK_BASE) 2728+ % TCPOLEN_SACK_PERBLOCK)) 2729+ sack_adjust(tcph, ptr-2, 2730+ &ct->nat.info.seq[!dir]); 2731+ 2732+ sack_adjusted = 1; 2733+ } 2734+ ptr += opsize-2; 2735+ length -= opsize; 2736+ } 2737+ } 2738+ return !sack_adjusted; 2739+} 2740+ 2741 /* TCP sequence number adjustment */ 2742 int 2743 ip_nat_seq_adjust(struct sk_buff *skb, 2744@@ -243,51 +349,9 @@ 2745 tcph->seq = newseq; 2746 tcph->ack_seq = newack; 2747 2748- return 0; 2749-} 2750- 2751-/* Grrr... SACK. Fuck me even harder. Don't want to fix it on the 2752- fly, so blow it away. */ 2753-void 2754-ip_nat_delete_sack(struct sk_buff *skb, struct tcphdr *tcph) 2755-{ 2756- unsigned int i; 2757- u_int8_t *opt = (u_int8_t *)tcph; 2758- 2759- DEBUGP("Seeking SACKPERM in SYN packet (doff = %u).\n", 2760- tcph->doff * 4); 2761- for (i = sizeof(struct tcphdr); i < tcph->doff * 4;) { 2762- DEBUGP("%u ", opt[i]); 2763- switch (opt[i]) { 2764- case TCPOPT_NOP: 2765- case TCPOPT_EOL: 2766- i++; 2767- break; 2768+ ip_nat_sack_adjust(skb, ct, ctinfo); 2769 2770- case TCPOPT_SACK_PERM: 2771- goto found_opt; 2772- 2773- default: 2774- /* Worst that can happen: it will take us over. */ 2775- i += opt[i+1] ?: 1; 2776- } 2777- } 2778- DEBUGP("\n"); 2779- return; 2780- 2781- found_opt: 2782- DEBUGP("\n"); 2783- DEBUGP("Found SACKPERM at offset %u.\n", i); 2784- 2785- /* Must be within TCP header, and valid SACK perm. */ 2786- if (i + opt[i+1] <= tcph->doff*4 && opt[i+1] == 2) { 2787- /* Replace with NOPs. */ 2788- tcph->check 2789- = ip_nat_cheat_check(*((u_int16_t *)(opt + i))^0xFFFF, 2790- (TCPOPT_NOP<<8)|TCPOPT_NOP, tcph->check); 2791- opt[i] = opt[i+1] = TCPOPT_NOP; 2792- } 2793- else DEBUGP("Something wrong with SACK_PERM.\n"); 2794+ return 0; 2795 } 2796 2797 static inline int 2798@@ -297,10 +361,51 @@ 2799 return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask); 2800 } 2801 2802+#define MODULE_MAX_NAMELEN 32 2803+ 2804 int ip_nat_helper_register(struct ip_nat_helper *me) 2805 { 2806 int ret = 0; 2807 2808+ if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) { 2809+ struct ip_conntrack_helper *ct_helper; 2810+ 2811+ if ((ct_helper = ip_ct_find_helper(&me->tuple)) 2812+ && ct_helper->me) { 2813+ __MOD_INC_USE_COUNT(ct_helper->me); 2814+ } else { 2815+ 2816+ /* We are a NAT helper for protocol X. If we need 2817+ * respective conntrack helper for protoccol X, compute 2818+ * conntrack helper name and try to load module */ 2819+ char name[MODULE_MAX_NAMELEN]; 2820+ const char *tmp = me->me->name; 2821+ 2822+ if (strlen(tmp) + 6 > MODULE_MAX_NAMELEN) { 2823+ printk(__FUNCTION__ ": unable to " 2824+ "compute conntrack helper name " 2825+ "from %s\n", tmp); 2826+ return -EBUSY; 2827+ } 2828+ tmp += 6; 2829+ sprintf(name, "ip_conntrack%s", tmp); 2830+#ifdef CONFIG_KMOD 2831+ if (!request_module(name) 2832+ && (ct_helper = ip_ct_find_helper(&me->tuple)) 2833+ && ct_helper->me) { 2834+ __MOD_INC_USE_COUNT(ct_helper->me); 2835+ } else { 2836+ printk("unable to load module %s\n", name); 2837+ return -EBUSY; 2838+ } 2839+#else 2840+ printk("unable to load module %s automatically " 2841+ "because kernel was compiled without kernel " 2842+ "module loader support\n", name); 2843+ return -EBUSY; 2844+#endif 2845+ } 2846+ } 2847 WRITE_LOCK(&ip_nat_lock); 2848 if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) 2849 ret = -EBUSY; 2850@@ -327,8 +432,14 @@ 2851 2852 void ip_nat_helper_unregister(struct ip_nat_helper *me) 2853 { 2854+ int found = 0; 2855+ 2856 WRITE_LOCK(&ip_nat_lock); 2857- LIST_DELETE(&helpers, me); 2858+ /* Autoloading conntrack helper might have failed */ 2859+ if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) { 2860+ LIST_DELETE(&helpers, me); 2861+ found = 1; 2862+ } 2863 WRITE_UNLOCK(&ip_nat_lock); 2864 2865 /* Someone could be still looking at the helper in a bh. */ 2866@@ -344,5 +455,19 @@ 2867 worse. --RR */ 2868 ip_ct_selective_cleanup(kill_helper, me); 2869 2870- MOD_DEC_USE_COUNT; 2871+ if (found) 2872+ MOD_DEC_USE_COUNT; 2873+ 2874+ /* If we are no standalone NAT helper, we need to decrement usage count 2875+ * on our conntrack helper */ 2876+ if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) { 2877+ struct ip_conntrack_helper *ct_helper; 2878+ 2879+ if ((ct_helper = ip_ct_find_helper(&me->tuple)) 2880+ && ct_helper->me) { 2881+ __MOD_DEC_USE_COUNT(ct_helper->me); 2882+ } else 2883+ printk(__FUNCTION__ ": unable to decrement usage count" 2884+ " of conntrack helper %s\n", me->me->name); 2885+ } 2886 } 2887diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_irc.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_irc.c 2888--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_irc.c Fri Dec 21 18:42:05 2001 2889+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_irc.c Fri Nov 29 00:53:15 2002 2890@@ -51,42 +51,29 @@ 2891 2892 2893-static int 2894+static unsigned int 2895 irc_nat_expected(struct sk_buff **pskb, 2896 unsigned int hooknum, 2897 struct ip_conntrack *ct, 2898- struct ip_nat_info *info, 2899- struct ip_conntrack *master, 2900- struct ip_nat_info *masterinfo, unsigned int *verdict) 2901+ struct ip_nat_info *info) 2902 { 2903 struct ip_nat_multi_range mr; 2904 u_int32_t newdstip, newsrcip, newip; 2905- struct ip_ct_irc *ircinfo; 2906+ 2907+ struct ip_conntrack *master = master_ct(ct); 2908 2909 IP_NF_ASSERT(info); 2910 IP_NF_ASSERT(master); 2911- IP_NF_ASSERT(masterinfo); 2912 2913 IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); 2914 2915 DEBUGP("nat_expected: We have a connection!\n"); 2916 2917- /* Master must be an irc connection */ 2918- ircinfo = &master->help.ct_irc_info; 2919- LOCK_BH(&ip_irc_lock); 2920- if (ircinfo->is_irc != IP_CONNTR_IRC) { 2921- UNLOCK_BH(&ip_irc_lock); 2922- DEBUGP("nat_expected: master not irc\n"); 2923- return 0; 2924- } 2925- 2926 newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 2927 newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; 2928 DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n", 2929 NIPQUAD(newsrcip), NIPQUAD(newdstip)); 2930 2931- UNLOCK_BH(&ip_irc_lock); 2932- 2933 if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 2934 newip = newsrcip; 2935 else 2936@@ -99,16 +86,14 @@ 2937 mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; 2938 mr.range[0].min_ip = mr.range[0].max_ip = newip; 2939 2940- *verdict = ip_nat_setup_info(ct, &mr, hooknum); 2941- 2942- return 1; 2943+ return ip_nat_setup_info(ct, &mr, hooknum); 2944 } 2945 2946-static int irc_data_fixup(const struct ip_ct_irc *ct_irc_info, 2947+static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info, 2948 struct ip_conntrack *ct, 2949- unsigned int datalen, 2950 struct sk_buff **pskb, 2951- enum ip_conntrack_info ctinfo) 2952+ enum ip_conntrack_info ctinfo, 2953+ struct ip_conntrack_expect *expect) 2954 { 2955 u_int32_t newip; 2956 struct ip_conntrack_tuple t; 2957@@ -121,9 +106,9 @@ 2958 2959 MUST_BE_LOCKED(&ip_irc_lock); 2960 2961- DEBUGP("IRC_NAT: info (seq %u + %u) packet(seq %u + %u)\n", 2962- ct_irc_info->seq, ct_irc_info->len, 2963- ntohl(tcph->seq), datalen); 2964+ DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n", 2965+ expect->seq, ct_irc_info->len, 2966+ ntohl(tcph->seq)); 2967 2968 newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; 2969 2970@@ -133,13 +118,11 @@ 2971 only set in ip_conntrack_irc, with ip_irc_lock held 2972 writable */ 2973 2974- t = ct->expected.tuple; 2975+ t = expect->tuple; 2976 t.dst.ip = newip; 2977 for (port = ct_irc_info->port; port != 0; port++) { 2978 t.dst.u.tcp.port = htons(port); 2979- if (ip_conntrack_expect_related(ct, &t, 2980- &ct->expected.mask, 2981- NULL) == 0) { 2982+ if (ip_conntrack_change_expect(expect, &t) == 0) { 2983 DEBUGP("using port %d", port); 2984 break; 2985 } 2986@@ -166,26 +149,28 @@ 2987 buffer, NIPQUAD(newip), port); 2988 2989 return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 2990- ct_irc_info->seq - ntohl(tcph->seq), 2991+ expect->seq - ntohl(tcph->seq), 2992 ct_irc_info->len, buffer, 2993 strlen(buffer)); 2994 } 2995 2996 static unsigned int help(struct ip_conntrack *ct, 2997+ struct ip_conntrack_expect *exp, 2998 struct ip_nat_info *info, 2999 enum ip_conntrack_info ctinfo, 3000- unsigned int hooknum, struct sk_buff **pskb) 3001+ unsigned int hooknum, 3002+ struct sk_buff **pskb) 3003 { 3004 struct iphdr *iph = (*pskb)->nh.iph; 3005 struct tcphdr *tcph = (void *) iph + iph->ihl * 4; 3006 unsigned int datalen; 3007 int dir; 3008- int score; 3009- struct ip_ct_irc *ct_irc_info = &ct->help.ct_irc_info; 3010+ struct ip_ct_irc_expect *ct_irc_info; 3011 3012- /* Delete SACK_OK on initial TCP SYNs. */ 3013- if (tcph->syn && !tcph->ack) 3014- ip_nat_delete_sack(*pskb, tcph); 3015+ if (!exp) 3016+ DEBUGP("ip_nat_irc: no exp!!"); 3017+ 3018+ ct_irc_info = &exp->help.exp_irc_info; 3019 3020 /* Only mangle things once: original direction in POST_ROUTING 3021 and reply direction on PRE_ROUTING. */ 3022@@ -202,55 +187,35 @@ 3023 DEBUGP("got beyond not touching\n"); 3024 3025 datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4; 3026- score = 0; 3027 LOCK_BH(&ip_irc_lock); 3028- if (ct_irc_info->len) { 3029- DEBUGP("got beyond ct_irc_info->len\n"); 3030- 3031- /* If it's in the right range... */ 3032- score += between(ct_irc_info->seq, ntohl(tcph->seq), 3033- ntohl(tcph->seq) + datalen); 3034- score += between(ct_irc_info->seq + ct_irc_info->len, 3035- ntohl(tcph->seq), 3036- ntohl(tcph->seq) + datalen); 3037- if (score == 1) { 3038- /* Half a match? This means a partial retransmisison. 3039- It's a cracker being funky. */ 3040- if (net_ratelimit()) { 3041- printk 3042- ("IRC_NAT: partial packet %u/%u in %u/%u\n", 3043- ct_irc_info->seq, ct_irc_info->len, 3044- ntohl(tcph->seq), 3045- ntohl(tcph->seq) + datalen); 3046- } 3047+ /* Check wether the whole IP/address pattern is carried in the payload */ 3048+ if (between(exp->seq + ct_irc_info->len, 3049+ ntohl(tcph->seq), 3050+ ntohl(tcph->seq) + datalen)) { 3051+ if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) { 3052 UNLOCK_BH(&ip_irc_lock); 3053 return NF_DROP; 3054- } else if (score == 2) { 3055- DEBUGP("IRC_NAT: score=2, calling fixup\n"); 3056- if (!irc_data_fixup(ct_irc_info, ct, datalen, 3057- pskb, ctinfo)) { 3058- UNLOCK_BH(&ip_irc_lock); 3059- return NF_DROP; 3060- } 3061- /* skb may have been reallocated */ 3062- iph = (*pskb)->nh.iph; 3063- tcph = (void *) iph + iph->ihl * 4; 3064 } 3065+ } else { 3066+ /* Half a match? This means a partial retransmisison. 3067+ It's a cracker being funky. */ 3068+ if (net_ratelimit()) { 3069+ printk 3070+ ("IRC_NAT: partial packet %u/%u in %u/%u\n", 3071+ exp->seq, ct_irc_info->len, 3072+ ntohl(tcph->seq), 3073+ ntohl(tcph->seq) + datalen); 3074+ } 3075+ UNLOCK_BH(&ip_irc_lock); 3076+ return NF_DROP; 3077 } 3078- 3079 UNLOCK_BH(&ip_irc_lock); 3080 3081- ip_nat_seq_adjust(*pskb, ct, ctinfo); 3082- 3083 return NF_ACCEPT; 3084 } 3085 3086 static struct ip_nat_helper ip_nat_irc_helpers[MAX_PORTS]; 3087-static char ip_nih_names[MAX_PORTS][6]; 3088- 3089-static struct ip_nat_expect irc_expect 3090- = { {NULL, NULL}, irc_nat_expected }; 3091- 3092+static char irc_names[MAX_PORTS][10]; 3093 3094 /* This function is intentionally _NOT_ defined as __exit, because 3095 * it is needed by init() */ 3096@@ -262,52 +227,54 @@ 3097 DEBUGP("ip_nat_irc: unregistering helper for port %d\n", 3098 ports[i]); 3099 ip_nat_helper_unregister(&ip_nat_irc_helpers[i]); 3100- } 3101- ip_nat_expect_unregister(&irc_expect); 3102+ } 3103 } 3104+ 3105 static int __init init(void) 3106 { 3107- int ret; 3108+ int ret = 0; 3109 int i; 3110 struct ip_nat_helper *hlpr; 3111 char *tmpname; 3112 3113- ret = ip_nat_expect_register(&irc_expect); 3114- if (ret == 0) { 3115- 3116- if (ports[0] == 0) { 3117- ports[0] = 6667; 3118- } 3119+ if (ports[0] == 0) { 3120+ ports[0] = IRC_PORT; 3121+ } 3122 3123- for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) { 3124- hlpr = &ip_nat_irc_helpers[i]; 3125- memset(hlpr, 0, 3126- sizeof(struct ip_nat_helper)); 3127- 3128- hlpr->tuple.dst.protonum = IPPROTO_TCP; 3129- hlpr->tuple.src.u.tcp.port = htons(ports[i]); 3130- hlpr->mask.src.u.tcp.port = 0xFFFF; 3131- hlpr->mask.dst.protonum = 0xFFFF; 3132- hlpr->help = help; 3133- 3134- tmpname = &ip_nih_names[i][0]; 3135- sprintf(tmpname, "irc%2.2d", i); 3136- 3137- hlpr->name = tmpname; 3138- DEBUGP 3139- ("ip_nat_irc: Trying to register helper for port %d: name %s\n", 3140- ports[i], hlpr->name); 3141- ret = ip_nat_helper_register(hlpr); 3142- 3143- if (ret) { 3144- printk 3145- ("ip_nat_irc: error registering helper for port %d\n", 3146- ports[i]); 3147- fini(); 3148- return 1; 3149- } 3150- ports_c++; 3151+ for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) { 3152+ hlpr = &ip_nat_irc_helpers[i]; 3153+ memset(hlpr, 0, 3154+ sizeof(struct ip_nat_helper)); 3155+ 3156+ hlpr->tuple.dst.protonum = IPPROTO_TCP; 3157+ hlpr->tuple.src.u.tcp.port = htons(ports[i]); 3158+ hlpr->mask.src.u.tcp.port = 0xFFFF; 3159+ hlpr->mask.dst.protonum = 0xFFFF; 3160+ hlpr->help = help; 3161+ hlpr->flags = 0; 3162+ hlpr->me = THIS_MODULE; 3163+ hlpr->expect = irc_nat_expected; 3164+ 3165+ tmpname = &irc_names[i][0]; 3166+ if (ports[i] == IRC_PORT) 3167+ sprintf(tmpname, "irc"); 3168+ else 3169+ sprintf(tmpname, "irc-%d", i); 3170+ hlpr->name = tmpname; 3171+ 3172+ DEBUGP 3173+ ("ip_nat_irc: Trying to register helper for port %d: name %s\n", 3174+ ports[i], hlpr->name); 3175+ ret = ip_nat_helper_register(hlpr); 3176+ 3177+ if (ret) { 3178+ printk 3179+ ("ip_nat_irc: error registering helper for port %d\n", 3180+ ports[i]); 3181+ fini(); 3182+ return 1; 3183 } 3184+ ports_c++; 3185 } 3186 return ret; 3187 } 3188diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_proto_tcp.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_proto_tcp.c 3189--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_proto_tcp.c Tue Aug 7 17:30:50 2001 3190+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_proto_tcp.c Fri Nov 29 00:53:15 2002 3191@@ -4,7 +4,6 @@ 3192 #include <linux/ip.h> 3193 #include <linux/tcp.h> 3194 #include <linux/if.h> 3195- 3196 #include <linux/netfilter_ipv4/ip_nat.h> 3197 #include <linux/netfilter_ipv4/ip_nat_rule.h> 3198 #include <linux/netfilter_ipv4/ip_nat_protocol.h> 3199diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_proto_unknown.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_proto_unknown.c 3200--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_proto_unknown.c Fri Mar 17 19:56:20 2000 3201+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_proto_unknown.c Fri Nov 29 00:53:15 2002 3202@@ -1,5 +1,5 @@ 3203 /* The "unknown" protocol. This is what is used for protocols we 3204- * don't understand. It's returned by find_proto(). 3205+ * don't understand. It's returned by ip_ct_find_proto(). 3206 */ 3207 3208 #include <linux/types.h> 3209diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_rule.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_rule.c 3210--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_rule.c Sat Aug 3 02:39:46 2002 3211+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_rule.c Fri Nov 29 00:53:15 2002 3212@@ -106,8 +106,6 @@ 3213 = { { NULL, NULL }, "nat", &nat_initial_table.repl, 3214 NAT_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE }; 3215 3216-LIST_HEAD(nat_expect_list); 3217- 3218 /* Source NAT */ 3219 static unsigned int ipt_snat_target(struct sk_buff **pskb, 3220 unsigned int hooknum, 3221@@ -254,19 +252,6 @@ 3222 return ip_nat_setup_info(conntrack, &mr, hooknum); 3223 } 3224 3225-static inline int call_expect(const struct ip_nat_expect *i, 3226- struct sk_buff **pskb, 3227- unsigned int hooknum, 3228- struct ip_conntrack *ct, 3229- struct ip_nat_info *info, 3230- struct ip_conntrack *master, 3231- struct ip_nat_info *masterinfo, 3232- unsigned int *verdict) 3233-{ 3234- return i->expect(pskb, hooknum, ct, info, master, masterinfo, 3235- verdict); 3236-} 3237- 3238 int ip_nat_rule_find(struct sk_buff **pskb, 3239 unsigned int hooknum, 3240 const struct net_device *in, 3241@@ -276,41 +261,14 @@ 3242 { 3243 int ret; 3244 3245- /* Master won't vanish while this ctrack still alive */ 3246- if (ct->master.master) { 3247- struct ip_conntrack *master; 3248- 3249- master = (struct ip_conntrack *)ct->master.master; 3250- if (LIST_FIND(&nat_expect_list, 3251- call_expect, 3252- struct ip_nat_expect *, 3253- pskb, hooknum, ct, info, 3254- master, &master->nat.info, &ret)) 3255- return ret; 3256- } 3257 ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL); 3258+ 3259 if (ret == NF_ACCEPT) { 3260 if (!(info->initialized & (1 << HOOK2MANIP(hooknum)))) 3261 /* NUL mapping */ 3262 ret = alloc_null_binding(ct, info, hooknum); 3263 } 3264 return ret; 3265-} 3266- 3267-int ip_nat_expect_register(struct ip_nat_expect *expect) 3268-{ 3269- WRITE_LOCK(&ip_nat_lock); 3270- list_prepend(&nat_expect_list, expect); 3271- WRITE_UNLOCK(&ip_nat_lock); 3272- 3273- return 0; 3274-} 3275- 3276-void ip_nat_expect_unregister(struct ip_nat_expect *expect) 3277-{ 3278- WRITE_LOCK(&ip_nat_lock); 3279- LIST_DELETE(&nat_expect_list, expect); 3280- WRITE_UNLOCK(&ip_nat_lock); 3281 } 3282 3283 static struct ipt_target ipt_snat_reg 3284diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_snmp_basic.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_snmp_basic.c 3285--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_snmp_basic.c Wed Oct 31 00:08:12 2001 3286+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_snmp_basic.c Fri Nov 29 00:53:15 2002 3287@@ -1243,6 +1243,7 @@ 3288 * NAT helper function, packets arrive here from NAT code. 3289 */ 3290 static unsigned int nat_help(struct ip_conntrack *ct, 3291+ struct ip_conntrack_expect *exp, 3292 struct ip_nat_info *info, 3293 enum ip_conntrack_info ctinfo, 3294 unsigned int hooknum, 3295@@ -1259,9 +1260,9 @@ 3296 * on post routing (SNAT). 3297 */ 3298 if (!((dir == IP_CT_DIR_REPLY && hooknum == NF_IP_PRE_ROUTING && 3299- udph->source == __constant_ntohs(SNMP_PORT)) || 3300+ udph->source == ntohs(SNMP_PORT)) || 3301 (dir == IP_CT_DIR_ORIGINAL && hooknum == NF_IP_POST_ROUTING && 3302- udph->dest == __constant_ntohs(SNMP_TRAP_PORT)))) { 3303+ udph->dest == ntohs(SNMP_TRAP_PORT)))) { 3304 spin_unlock_bh(&snmp_lock); 3305 return NF_ACCEPT; 3306 } 3307@@ -1303,19 +1304,27 @@ 3308 return NF_DROP; 3309 } 3310 3311-static struct ip_nat_helper snmp = { { NULL, NULL }, 3312+static struct ip_nat_helper snmp = { 3313+ { NULL, NULL }, 3314+ "snmp", 3315+ IP_NAT_HELPER_F_STANDALONE, 3316+ THIS_MODULE, 3317 { { 0, { __constant_htons(SNMP_PORT) } }, 3318 { 0, { 0 }, IPPROTO_UDP } }, 3319 { { 0, { 0xFFFF } }, 3320 { 0, { 0 }, 0xFFFF } }, 3321- nat_help, "snmp" }; 3322+ nat_help, NULL }; 3323 3324-static struct ip_nat_helper snmp_trap = { { NULL, NULL }, 3325+static struct ip_nat_helper snmp_trap = { 3326+ { NULL, NULL }, 3327+ "snmp_trap", 3328+ IP_NAT_HELPER_F_STANDALONE, 3329+ THIS_MODULE, 3330 { { 0, { __constant_htons(SNMP_TRAP_PORT) } }, 3331 { 0, { 0 }, IPPROTO_UDP } }, 3332 { { 0, { 0xFFFF } }, 3333 { 0, { 0 }, 0xFFFF } }, 3334- nat_help, "snmp_trap" }; 3335+ nat_help, NULL }; 3336 3337 /***************************************************************************** 3338 * 3339diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_standalone.c 3340--- linux-2.4.19-plain/net/ipv4/netfilter/ip_nat_standalone.c Sat Aug 3 02:39:46 2002 3341+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_nat_standalone.c Fri Nov 29 00:53:15 2002 3342@@ -5,7 +5,12 @@ 3343 */ 3344 3345 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General 3346- Public Licence. */ 3347+ * Public Licence. 3348+ * 3349+ * 23 Apr 2001: Harald Welte <laforge@gnumonks.org> 3350+ * - new API and handling of conntrack/nat helpers 3351+ * - now capable of multiple expectations for one master 3352+ * */ 3353 3354 #include <linux/config.h> 3355 #include <linux/types.h> 3356@@ -44,6 +49,15 @@ 3357 : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ 3358 : "*ERROR*"))) 3359 3360+static inline int call_expect(struct ip_conntrack *master, 3361+ struct sk_buff **pskb, 3362+ unsigned int hooknum, 3363+ struct ip_conntrack *ct, 3364+ struct ip_nat_info *info) 3365+{ 3366+ return master->nat.info.helper->expect(pskb, hooknum, ct, info); 3367+} 3368+ 3369 static unsigned int 3370 ip_nat_fn(unsigned int hooknum, 3371 struct sk_buff **pskb, 3372@@ -60,7 +74,7 @@ 3373 /* We never see fragments: conntrack defrags on pre-routing 3374 and local-out, and ip_nat_out protects post-routing. */ 3375 IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off 3376- & __constant_htons(IP_MF|IP_OFFSET))); 3377+ & htons(IP_MF|IP_OFFSET))); 3378 3379 (*pskb)->nfcache |= NFC_UNKNOWN; 3380 3381@@ -110,8 +124,16 @@ 3382 int in_hashes = info->initialized; 3383 unsigned int ret; 3384 3385- ret = ip_nat_rule_find(pskb, hooknum, in, out, 3386- ct, info); 3387+ if (ct->master 3388+ && master_ct(ct)->nat.info.helper 3389+ && master_ct(ct)->nat.info.helper->expect) { 3390+ ret = call_expect(master_ct(ct), pskb, 3391+ hooknum, ct, info); 3392+ } else { 3393+ ret = ip_nat_rule_find(pskb, hooknum, in, out, 3394+ ct, info); 3395+ } 3396+ 3397 if (ret != NF_ACCEPT) { 3398 WRITE_UNLOCK(&ip_nat_lock); 3399 return ret; 3400@@ -163,7 +185,7 @@ 3401 3402 I'm starting to have nightmares about fragments. */ 3403 3404- if ((*pskb)->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) { 3405+ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { 3406 *pskb = ip_ct_gather_frags(*pskb); 3407 3408 if (!*pskb) 3409@@ -334,11 +356,7 @@ 3410 EXPORT_SYMBOL(ip_nat_protocol_unregister); 3411 EXPORT_SYMBOL(ip_nat_helper_register); 3412 EXPORT_SYMBOL(ip_nat_helper_unregister); 3413-EXPORT_SYMBOL(ip_nat_expect_register); 3414-EXPORT_SYMBOL(ip_nat_expect_unregister); 3415 EXPORT_SYMBOL(ip_nat_cheat_check); 3416 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); 3417-EXPORT_SYMBOL(ip_nat_seq_adjust); 3418-EXPORT_SYMBOL(ip_nat_delete_sack); 3419 EXPORT_SYMBOL(ip_nat_used_tuple); 3420 MODULE_LICENSE("GPL"); 3421diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_queue.c linux-2.4.20-plain/net/ipv4/netfilter/ip_queue.c 3422--- linux-2.4.19-plain/net/ipv4/netfilter/ip_queue.c Sat Aug 3 02:39:46 2002 3423+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_queue.c Fri Nov 29 00:53:15 2002 3424@@ -2,13 +2,14 @@ 3425 * This is a module which is used for queueing IPv4 packets and 3426 * communicating with userspace via netlink. 3427 * 3428- * (C) 2000 James Morris, this code is GPL. 3429+ * (C) 2000-2002 James Morris, this code is GPL. 3430 * 3431 * 2000-03-27: Simplified code (thanks to Andi Kleen for clues). 3432 * 2000-05-20: Fixed notifier problems (following Miguel Freitas' report). 3433 * 2000-06-19: Fixed so nfmark is copied to metadata (reported by Sebastian 3434 * Zander). 3435 * 2000-08-01: Added Nick Williams' MAC support. 3436+ * 2002-06-25: Code cleanup. 3437 * 3438 */ 3439 #include <linux/module.h> 3440@@ -18,205 +19,310 @@ 3441 #include <linux/notifier.h> 3442 #include <linux/netdevice.h> 3443 #include <linux/netfilter.h> 3444+#include <linux/netfilter_ipv4/ip_queue.h> 3445+#include <linux/netfilter_ipv4/ip_tables.h> 3446 #include <linux/netlink.h> 3447 #include <linux/spinlock.h> 3448-#include <linux/rtnetlink.h> 3449+#include <linux/brlock.h> 3450 #include <linux/sysctl.h> 3451 #include <linux/proc_fs.h> 3452 #include <net/sock.h> 3453 #include <net/route.h> 3454 3455-#include <linux/netfilter_ipv4/ip_queue.h> 3456-#include <linux/netfilter_ipv4/ip_tables.h> 3457- 3458 #define IPQ_QMAX_DEFAULT 1024 3459 #define IPQ_PROC_FS_NAME "ip_queue" 3460 #define NET_IPQ_QMAX 2088 3461 #define NET_IPQ_QMAX_NAME "ip_queue_maxlen" 3462 3463-typedef struct ipq_rt_info { 3464+struct ipq_rt_info { 3465 __u8 tos; 3466 __u32 daddr; 3467 __u32 saddr; 3468-} ipq_rt_info_t; 3469+}; 3470 3471-typedef struct ipq_queue_element { 3472- struct list_head list; /* Links element into queue */ 3473- int verdict; /* Current verdict */ 3474- struct nf_info *info; /* Extra info from netfilter */ 3475- struct sk_buff *skb; /* Packet inside */ 3476- ipq_rt_info_t rt_info; /* May need post-mangle routing */ 3477-} ipq_queue_element_t; 3478- 3479-typedef int (*ipq_send_cb_t)(ipq_queue_element_t *e); 3480- 3481-typedef struct ipq_peer { 3482- pid_t pid; /* PID of userland peer */ 3483- unsigned char died; /* We think the peer died */ 3484- unsigned char copy_mode; /* Copy packet as well as metadata? */ 3485- size_t copy_range; /* Range past metadata to copy */ 3486- ipq_send_cb_t send; /* Callback for sending data to peer */ 3487-} ipq_peer_t; 3488- 3489-typedef struct ipq_queue { 3490- int len; /* Current queue len */ 3491- int *maxlen; /* Maximum queue len, via sysctl */ 3492- unsigned char flushing; /* If queue is being flushed */ 3493- unsigned char terminate; /* If the queue is being terminated */ 3494- struct list_head list; /* Head of packet queue */ 3495- spinlock_t lock; /* Queue spinlock */ 3496- ipq_peer_t peer; /* Userland peer */ 3497-} ipq_queue_t; 3498+struct ipq_queue_entry { 3499+ struct list_head list; 3500+ struct nf_info *info; 3501+ struct sk_buff *skb; 3502+ struct ipq_rt_info rt_info; 3503+}; 3504 3505-/**************************************************************************** 3506- * 3507- * Packet queue 3508- * 3509- ****************************************************************************/ 3510-/* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */ 3511-static ipq_queue_element_t * 3512-ipq_dequeue(ipq_queue_t *q, 3513- int (*cmp)(ipq_queue_element_t *, unsigned long), 3514- unsigned long data) 3515-{ 3516- struct list_head *i; 3517- 3518- spin_lock_bh(&q->lock); 3519- for (i = q->list.prev; i != &q->list; i = i->prev) { 3520- ipq_queue_element_t *e = (ipq_queue_element_t *)i; 3521- 3522- if (!cmp || cmp(e, data)) { 3523- list_del(&e->list); 3524- q->len--; 3525- spin_unlock_bh(&q->lock); 3526- return e; 3527- } 3528+typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); 3529+ 3530+static unsigned char copy_mode = IPQ_COPY_NONE; 3531+static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT; 3532+static rwlock_t queue_lock = RW_LOCK_UNLOCKED; 3533+static int peer_pid; 3534+static unsigned int copy_range; 3535+static unsigned int queue_total; 3536+static struct sock *ipqnl; 3537+static LIST_HEAD(queue_list); 3538+static DECLARE_MUTEX(ipqnl_sem); 3539+ 3540+static void 3541+ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) 3542+{ 3543+ nf_reinject(entry->skb, entry->info, verdict); 3544+ kfree(entry); 3545+} 3546+ 3547+static inline int 3548+__ipq_enqueue_entry(struct ipq_queue_entry *entry) 3549+{ 3550+ if (queue_total >= queue_maxlen) { 3551+ if (net_ratelimit()) 3552+ printk(KERN_WARNING "ip_queue: full at %d entries, " 3553+ "dropping packet(s).\n", queue_total); 3554+ return -ENOSPC; 3555+ } 3556+ list_add(&entry->list, &queue_list); 3557+ queue_total++; 3558+ return 0; 3559+} 3560+ 3561+/* 3562+ * Find and return a queued entry matched by cmpfn, or return the last 3563+ * entry if cmpfn is NULL. 3564+ */ 3565+static inline struct ipq_queue_entry * 3566+__ipq_find_entry(ipq_cmpfn cmpfn, unsigned long data) 3567+{ 3568+ struct list_head *p; 3569+ 3570+ list_for_each_prev(p, &queue_list) { 3571+ struct ipq_queue_entry *entry = (struct ipq_queue_entry *)p; 3572+ 3573+ if (!cmpfn || cmpfn(entry, data)) 3574+ return entry; 3575 } 3576- spin_unlock_bh(&q->lock); 3577 return NULL; 3578 } 3579 3580-/* Flush all packets */ 3581-static void ipq_flush(ipq_queue_t *q) 3582+static inline void 3583+__ipq_dequeue_entry(struct ipq_queue_entry *entry) 3584 { 3585- ipq_queue_element_t *e; 3586- 3587- spin_lock_bh(&q->lock); 3588- q->flushing = 1; 3589- spin_unlock_bh(&q->lock); 3590- while ((e = ipq_dequeue(q, NULL, 0))) { 3591- e->verdict = NF_DROP; 3592- nf_reinject(e->skb, e->info, e->verdict); 3593- kfree(e); 3594- } 3595- spin_lock_bh(&q->lock); 3596- q->flushing = 0; 3597- spin_unlock_bh(&q->lock); 3598-} 3599- 3600-static ipq_queue_t *ipq_create_queue(nf_queue_outfn_t outfn, 3601- ipq_send_cb_t send_cb, 3602- int *errp, int *sysctl_qmax) 3603+ list_del(&entry->list); 3604+ queue_total--; 3605+} 3606+ 3607+static inline struct ipq_queue_entry * 3608+__ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data) 3609 { 3610- int status; 3611- ipq_queue_t *q; 3612+ struct ipq_queue_entry *entry; 3613 3614- *errp = 0; 3615- q = kmalloc(sizeof(ipq_queue_t), GFP_KERNEL); 3616- if (q == NULL) { 3617- *errp = -ENOMEM; 3618+ entry = __ipq_find_entry(cmpfn, data); 3619+ if (entry == NULL) 3620 return NULL; 3621+ 3622+ __ipq_dequeue_entry(entry); 3623+ return entry; 3624+} 3625+ 3626+ 3627+static inline void 3628+__ipq_flush(int verdict) 3629+{ 3630+ struct ipq_queue_entry *entry; 3631+ 3632+ while ((entry = __ipq_find_dequeue_entry(NULL, 0))) 3633+ ipq_issue_verdict(entry, verdict); 3634+} 3635+ 3636+static inline int 3637+__ipq_set_mode(unsigned char mode, unsigned int range) 3638+{ 3639+ int status = 0; 3640+ 3641+ switch(mode) { 3642+ case IPQ_COPY_NONE: 3643+ case IPQ_COPY_META: 3644+ copy_mode = mode; 3645+ copy_range = 0; 3646+ break; 3647+ 3648+ case IPQ_COPY_PACKET: 3649+ copy_mode = mode; 3650+ copy_range = range; 3651+ if (copy_range > 0xFFFF) 3652+ copy_range = 0xFFFF; 3653+ break; 3654+ 3655+ default: 3656+ status = -EINVAL; 3657+ 3658 } 3659- q->peer.pid = 0; 3660- q->peer.died = 0; 3661- q->peer.copy_mode = IPQ_COPY_NONE; 3662- q->peer.copy_range = 0; 3663- q->peer.send = send_cb; 3664- q->len = 0; 3665- q->maxlen = sysctl_qmax; 3666- q->flushing = 0; 3667- q->terminate = 0; 3668- INIT_LIST_HEAD(&q->list); 3669- spin_lock_init(&q->lock); 3670- status = nf_register_queue_handler(PF_INET, outfn, q); 3671- if (status < 0) { 3672- *errp = -EBUSY; 3673- kfree(q); 3674+ return status; 3675+} 3676+ 3677+static inline void 3678+__ipq_reset(void) 3679+{ 3680+ peer_pid = 0; 3681+ __ipq_set_mode(IPQ_COPY_NONE, 0); 3682+ __ipq_flush(NF_DROP); 3683+} 3684+ 3685+static struct ipq_queue_entry * 3686+ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data) 3687+{ 3688+ struct ipq_queue_entry *entry; 3689+ 3690+ write_lock_bh(&queue_lock); 3691+ entry = __ipq_find_dequeue_entry(cmpfn, data); 3692+ write_unlock_bh(&queue_lock); 3693+ return entry; 3694+} 3695+ 3696+static void 3697+ipq_flush(int verdict) 3698+{ 3699+ write_lock_bh(&queue_lock); 3700+ __ipq_flush(verdict); 3701+ write_unlock_bh(&queue_lock); 3702+} 3703+ 3704+static struct sk_buff * 3705+ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) 3706+{ 3707+ unsigned char *old_tail; 3708+ size_t size = 0; 3709+ size_t data_len = 0; 3710+ struct sk_buff *skb; 3711+ struct ipq_packet_msg *pmsg; 3712+ struct nlmsghdr *nlh; 3713+ 3714+ read_lock_bh(&queue_lock); 3715+ 3716+ switch (copy_mode) { 3717+ case IPQ_COPY_META: 3718+ case IPQ_COPY_NONE: 3719+ size = NLMSG_SPACE(sizeof(*pmsg)); 3720+ data_len = 0; 3721+ break; 3722+ 3723+ case IPQ_COPY_PACKET: 3724+ if (copy_range == 0 || copy_range > entry->skb->len) 3725+ data_len = entry->skb->len; 3726+ else 3727+ data_len = copy_range; 3728+ 3729+ size = NLMSG_SPACE(sizeof(*pmsg) + data_len); 3730+ break; 3731+ 3732+ default: 3733+ *errp = -EINVAL; 3734+ read_unlock_bh(&queue_lock); 3735 return NULL; 3736 } 3737- return q; 3738+ 3739+ read_unlock_bh(&queue_lock); 3740+ 3741+ skb = alloc_skb(size, GFP_ATOMIC); 3742+ if (!skb) 3743+ goto nlmsg_failure; 3744+ 3745+ old_tail= skb->tail; 3746+ nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); 3747+ pmsg = NLMSG_DATA(nlh); 3748+ memset(pmsg, 0, sizeof(*pmsg)); 3749+ 3750+ pmsg->packet_id = (unsigned long )entry; 3751+ pmsg->data_len = data_len; 3752+ pmsg->timestamp_sec = entry->skb->stamp.tv_sec; 3753+ pmsg->timestamp_usec = entry->skb->stamp.tv_usec; 3754+ pmsg->mark = entry->skb->nfmark; 3755+ pmsg->hook = entry->info->hook; 3756+ pmsg->hw_protocol = entry->skb->protocol; 3757+ 3758+ if (entry->info->indev) 3759+ strcpy(pmsg->indev_name, entry->info->indev->name); 3760+ else 3761+ pmsg->indev_name[0] = '\0'; 3762+ 3763+ if (entry->info->outdev) 3764+ strcpy(pmsg->outdev_name, entry->info->outdev->name); 3765+ else 3766+ pmsg->outdev_name[0] = '\0'; 3767+ 3768+ if (entry->info->indev && entry->skb->dev) { 3769+ pmsg->hw_type = entry->skb->dev->type; 3770+ if (entry->skb->dev->hard_header_parse) 3771+ pmsg->hw_addrlen = 3772+ entry->skb->dev->hard_header_parse(entry->skb, 3773+ pmsg->hw_addr); 3774+ } 3775+ 3776+ if (data_len) 3777+ memcpy(pmsg->payload, entry->skb->data, data_len); 3778+ 3779+ nlh->nlmsg_len = skb->tail - old_tail; 3780+ return skb; 3781+ 3782+nlmsg_failure: 3783+ if (skb) 3784+ kfree_skb(skb); 3785+ *errp = -EINVAL; 3786+ printk(KERN_ERR "ip_queue: error creating packet message\n"); 3787+ return NULL; 3788 } 3789 3790-static int ipq_enqueue(ipq_queue_t *q, 3791- struct sk_buff *skb, struct nf_info *info) 3792+static int 3793+ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) 3794 { 3795- ipq_queue_element_t *e; 3796- int status; 3797- 3798- e = kmalloc(sizeof(*e), GFP_ATOMIC); 3799- if (e == NULL) { 3800- printk(KERN_ERR "ip_queue: OOM in enqueue\n"); 3801+ int status = -EINVAL; 3802+ struct sk_buff *nskb; 3803+ struct ipq_queue_entry *entry; 3804+ 3805+ if (copy_mode == IPQ_COPY_NONE) 3806+ return -EAGAIN; 3807+ 3808+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 3809+ if (entry == NULL) { 3810+ printk(KERN_ERR "ip_queue: OOM in ipq_enqueue_packet()\n"); 3811 return -ENOMEM; 3812 } 3813 3814- e->verdict = NF_DROP; 3815- e->info = info; 3816- e->skb = skb; 3817+ entry->info = info; 3818+ entry->skb = skb; 3819 3820- if (e->info->hook == NF_IP_LOCAL_OUT) { 3821+ if (entry->info->hook == NF_IP_LOCAL_OUT) { 3822 struct iphdr *iph = skb->nh.iph; 3823 3824- e->rt_info.tos = iph->tos; 3825- e->rt_info.daddr = iph->daddr; 3826- e->rt_info.saddr = iph->saddr; 3827- } 3828- 3829- spin_lock_bh(&q->lock); 3830- if (q->len >= *q->maxlen) { 3831- spin_unlock_bh(&q->lock); 3832- if (net_ratelimit()) 3833- printk(KERN_WARNING "ip_queue: full at %d entries, " 3834- "dropping packet(s).\n", q->len); 3835- goto free_drop; 3836- } 3837- if (q->flushing || q->peer.copy_mode == IPQ_COPY_NONE 3838- || q->peer.pid == 0 || q->peer.died || q->terminate) { 3839- spin_unlock_bh(&q->lock); 3840- goto free_drop; 3841- } 3842- status = q->peer.send(e); 3843- if (status > 0) { 3844- list_add(&e->list, &q->list); 3845- q->len++; 3846- spin_unlock_bh(&q->lock); 3847- return status; 3848- } 3849- spin_unlock_bh(&q->lock); 3850- if (status == -ECONNREFUSED) { 3851- printk(KERN_INFO "ip_queue: peer %d died, " 3852- "resetting state and flushing queue\n", q->peer.pid); 3853- q->peer.died = 1; 3854- q->peer.pid = 0; 3855- q->peer.copy_mode = IPQ_COPY_NONE; 3856- q->peer.copy_range = 0; 3857- ipq_flush(q); 3858- } 3859-free_drop: 3860- kfree(e); 3861- return -EBUSY; 3862-} 3863+ entry->rt_info.tos = iph->tos; 3864+ entry->rt_info.daddr = iph->daddr; 3865+ entry->rt_info.saddr = iph->saddr; 3866+ } 3867 3868-static void ipq_destroy_queue(ipq_queue_t *q) 3869-{ 3870- nf_unregister_queue_handler(PF_INET); 3871- spin_lock_bh(&q->lock); 3872- q->terminate = 1; 3873- spin_unlock_bh(&q->lock); 3874- ipq_flush(q); 3875- kfree(q); 3876+ nskb = ipq_build_packet_message(entry, &status); 3877+ if (nskb == NULL) 3878+ goto err_out_free; 3879+ 3880+ write_lock_bh(&queue_lock); 3881+ 3882+ if (!peer_pid) 3883+ goto err_out_unlock; 3884+ 3885+ status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT); 3886+ if (status < 0) 3887+ goto err_out_unlock; 3888+ 3889+ status = __ipq_enqueue_entry(entry); 3890+ if (status < 0) 3891+ goto err_out_unlock; 3892+ 3893+ write_unlock_bh(&queue_lock); 3894+ return status; 3895+ 3896+err_out_unlock: 3897+ write_unlock_bh(&queue_lock); 3898+ 3899+err_out_free: 3900+ kfree(entry); 3901+ return status; 3902 } 3903 3904-static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e) 3905+static int 3906+ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) 3907 { 3908 int diff; 3909 struct iphdr *user_iph = (struct iphdr *)v->payload; 3910@@ -266,296 +372,216 @@ 3911 return 0; 3912 } 3913 3914-static inline int id_cmp(ipq_queue_element_t *e, unsigned long id) 3915+static inline int 3916+id_cmp(struct ipq_queue_entry *e, unsigned long id) 3917 { 3918 return (id == (unsigned long )e); 3919 } 3920 3921-static int ipq_set_verdict(ipq_queue_t *q, 3922- ipq_verdict_msg_t *v, unsigned int len) 3923+static int 3924+ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) 3925 { 3926- ipq_queue_element_t *e; 3927+ struct ipq_queue_entry *entry; 3928 3929- if (v->value > NF_MAX_VERDICT) 3930+ if (vmsg->value > NF_MAX_VERDICT) 3931 return -EINVAL; 3932- e = ipq_dequeue(q, id_cmp, v->id); 3933- if (e == NULL) 3934+ 3935+ entry = ipq_find_dequeue_entry(id_cmp, vmsg->id); 3936+ if (entry == NULL) 3937 return -ENOENT; 3938 else { 3939- e->verdict = v->value; 3940- if (v->data_len && v->data_len == len) 3941- if (ipq_mangle_ipv4(v, e) < 0) 3942- e->verdict = NF_DROP; 3943- nf_reinject(e->skb, e->info, e->verdict); 3944- kfree(e); 3945+ int verdict = vmsg->value; 3946+ 3947+ if (vmsg->data_len && vmsg->data_len == len) 3948+ if (ipq_mangle_ipv4(vmsg, entry) < 0) 3949+ verdict = NF_DROP; 3950+ 3951+ ipq_issue_verdict(entry, verdict); 3952 return 0; 3953 } 3954 } 3955 3956-static int ipq_receive_peer(ipq_queue_t *q, ipq_peer_msg_t *m, 3957- unsigned char type, unsigned int len) 3958+static int 3959+ipq_set_mode(unsigned char mode, unsigned int range) 3960 { 3961+ int status; 3962+ 3963+ write_lock_bh(&queue_lock); 3964+ status = __ipq_set_mode(mode, range); 3965+ write_unlock_bh(&queue_lock); 3966+ return status; 3967+} 3968 3969+static int 3970+ipq_receive_peer(struct ipq_peer_msg *pmsg, 3971+ unsigned char type, unsigned int len) 3972+{ 3973 int status = 0; 3974- int busy; 3975- 3976- spin_lock_bh(&q->lock); 3977- busy = (q->terminate || q->flushing); 3978- spin_unlock_bh(&q->lock); 3979- if (busy) 3980- return -EBUSY; 3981- if (len < sizeof(ipq_peer_msg_t)) 3982+ 3983+ if (len < sizeof(*pmsg)) 3984 return -EINVAL; 3985+ 3986 switch (type) { 3987- case IPQM_MODE: 3988- switch (m->msg.mode.value) { 3989- case IPQ_COPY_META: 3990- q->peer.copy_mode = IPQ_COPY_META; 3991- q->peer.copy_range = 0; 3992- break; 3993- case IPQ_COPY_PACKET: 3994- q->peer.copy_mode = IPQ_COPY_PACKET; 3995- q->peer.copy_range = m->msg.mode.range; 3996- if (q->peer.copy_range > 0xFFFF) 3997- q->peer.copy_range = 0xFFFF; 3998- break; 3999- default: 4000- status = -EINVAL; 4001- } 4002- break; 4003- case IPQM_VERDICT: 4004- if (m->msg.verdict.value > NF_MAX_VERDICT) 4005- status = -EINVAL; 4006- else 4007- status = ipq_set_verdict(q, 4008- &m->msg.verdict, 4009- len - sizeof(*m)); 4010+ case IPQM_MODE: 4011+ status = ipq_set_mode(pmsg->msg.mode.value, 4012+ pmsg->msg.mode.range); 4013+ break; 4014+ 4015+ case IPQM_VERDICT: 4016+ if (pmsg->msg.verdict.value > NF_MAX_VERDICT) 4017+ status = -EINVAL; 4018+ else 4019+ status = ipq_set_verdict(&pmsg->msg.verdict, 4020+ len - sizeof(*pmsg)); 4021 break; 4022- default: 4023- status = -EINVAL; 4024+ default: 4025+ status = -EINVAL; 4026 } 4027 return status; 4028 } 4029 4030-static inline int dev_cmp(ipq_queue_element_t *e, unsigned long ifindex) 4031+static int 4032+dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex) 4033 { 4034- if (e->info->indev) 4035- if (e->info->indev->ifindex == ifindex) 4036+ if (entry->info->indev) 4037+ if (entry->info->indev->ifindex == ifindex) 4038 return 1; 4039- if (e->info->outdev) 4040- if (e->info->outdev->ifindex == ifindex) 4041+ 4042+ if (entry->info->outdev) 4043+ if (entry->info->outdev->ifindex == ifindex) 4044 return 1; 4045+ 4046 return 0; 4047 } 4048 4049-/* Drop any queued packets associated with device ifindex */ 4050-static void ipq_dev_drop(ipq_queue_t *q, int ifindex) 4051+static void 4052+ipq_dev_drop(int ifindex) 4053 { 4054- ipq_queue_element_t *e; 4055+ struct ipq_queue_entry *entry; 4056 4057- while ((e = ipq_dequeue(q, dev_cmp, ifindex))) { 4058- e->verdict = NF_DROP; 4059- nf_reinject(e->skb, e->info, e->verdict); 4060- kfree(e); 4061- } 4062-} 4063- 4064-/**************************************************************************** 4065- * 4066- * Netfilter interface 4067- * 4068- ****************************************************************************/ 4069- 4070-/* 4071- * Packets arrive here from netfilter for queuing to userspace. 4072- * All of them must be fed back via nf_reinject() or Alexey will kill Rusty. 4073- */ 4074-static int netfilter_receive(struct sk_buff *skb, 4075- struct nf_info *info, void *data) 4076-{ 4077- return ipq_enqueue((ipq_queue_t *)data, skb, info); 4078-} 4079- 4080-/**************************************************************************** 4081- * 4082- * Netlink interface. 4083- * 4084- ****************************************************************************/ 4085- 4086-static struct sock *nfnl = NULL; 4087-ipq_queue_t *nlq = NULL; 4088- 4089-static struct sk_buff *netlink_build_message(ipq_queue_element_t *e, int *errp) 4090-{ 4091- unsigned char *old_tail; 4092- size_t size = 0; 4093- size_t data_len = 0; 4094- struct sk_buff *skb; 4095- ipq_packet_msg_t *pm; 4096- struct nlmsghdr *nlh; 4097- 4098- switch (nlq->peer.copy_mode) { 4099- size_t copy_range; 4100- 4101- case IPQ_COPY_META: 4102- size = NLMSG_SPACE(sizeof(*pm)); 4103- data_len = 0; 4104- break; 4105- case IPQ_COPY_PACKET: 4106- copy_range = nlq->peer.copy_range; 4107- if (copy_range == 0 || copy_range > e->skb->len) 4108- data_len = e->skb->len; 4109- else 4110- data_len = copy_range; 4111- size = NLMSG_SPACE(sizeof(*pm) + data_len); 4112- 4113- break; 4114- case IPQ_COPY_NONE: 4115- default: 4116- *errp = -EINVAL; 4117- return NULL; 4118- } 4119- skb = alloc_skb(size, GFP_ATOMIC); 4120- if (!skb) 4121- goto nlmsg_failure; 4122- old_tail = skb->tail; 4123- nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); 4124- pm = NLMSG_DATA(nlh); 4125- memset(pm, 0, sizeof(*pm)); 4126- pm->packet_id = (unsigned long )e; 4127- pm->data_len = data_len; 4128- pm->timestamp_sec = e->skb->stamp.tv_sec; 4129- pm->timestamp_usec = e->skb->stamp.tv_usec; 4130- pm->mark = e->skb->nfmark; 4131- pm->hook = e->info->hook; 4132- if (e->info->indev) strcpy(pm->indev_name, e->info->indev->name); 4133- else pm->indev_name[0] = '\0'; 4134- if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name); 4135- else pm->outdev_name[0] = '\0'; 4136- pm->hw_protocol = e->skb->protocol; 4137- if (e->info->indev && e->skb->dev) { 4138- pm->hw_type = e->skb->dev->type; 4139- if (e->skb->dev->hard_header_parse) 4140- pm->hw_addrlen = 4141- e->skb->dev->hard_header_parse(e->skb, 4142- pm->hw_addr); 4143- } 4144- if (data_len) 4145- memcpy(pm->payload, e->skb->data, data_len); 4146- nlh->nlmsg_len = skb->tail - old_tail; 4147- NETLINK_CB(skb).dst_groups = 0; 4148- return skb; 4149-nlmsg_failure: 4150- if (skb) 4151- kfree_skb(skb); 4152- *errp = 0; 4153- printk(KERN_ERR "ip_queue: error creating netlink message\n"); 4154- return NULL; 4155-} 4156- 4157-static int netlink_send_peer(ipq_queue_element_t *e) 4158-{ 4159- int status = 0; 4160- struct sk_buff *skb; 4161- 4162- skb = netlink_build_message(e, &status); 4163- if (skb == NULL) 4164- return status; 4165- return netlink_unicast(nfnl, skb, nlq->peer.pid, MSG_DONTWAIT); 4166+ while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL) 4167+ ipq_issue_verdict(entry, NF_DROP); 4168 } 4169 4170 #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) 4171 4172-static __inline__ void netlink_receive_user_skb(struct sk_buff *skb) 4173+static inline void 4174+ipq_rcv_skb(struct sk_buff *skb) 4175 { 4176- int status, type; 4177+ int status, type, pid, flags, nlmsglen, skblen; 4178 struct nlmsghdr *nlh; 4179 4180- if (skb->len < sizeof(struct nlmsghdr)) 4181+ skblen = skb->len; 4182+ if (skblen < sizeof(*nlh)) 4183 return; 4184 4185 nlh = (struct nlmsghdr *)skb->data; 4186- if (nlh->nlmsg_len < sizeof(struct nlmsghdr) 4187- || skb->len < nlh->nlmsg_len) 4188- return; 4189- 4190- if(nlh->nlmsg_pid <= 0 4191- || !(nlh->nlmsg_flags & NLM_F_REQUEST) 4192- || nlh->nlmsg_flags & NLM_F_MULTI) 4193+ nlmsglen = nlh->nlmsg_len; 4194+ if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) 4195+ return; 4196+ 4197+ pid = nlh->nlmsg_pid; 4198+ flags = nlh->nlmsg_flags; 4199+ 4200+ if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI) 4201 RCV_SKB_FAIL(-EINVAL); 4202- if (nlh->nlmsg_flags & MSG_TRUNC) 4203+ 4204+ if (flags & MSG_TRUNC) 4205 RCV_SKB_FAIL(-ECOMM); 4206+ 4207 type = nlh->nlmsg_type; 4208 if (type < NLMSG_NOOP || type >= IPQM_MAX) 4209 RCV_SKB_FAIL(-EINVAL); 4210+ 4211 if (type <= IPQM_BASE) 4212 return; 4213+ 4214 if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) 4215 RCV_SKB_FAIL(-EPERM); 4216- if (nlq->peer.pid && !nlq->peer.died 4217- && (nlq->peer.pid != nlh->nlmsg_pid)) { 4218- printk(KERN_WARNING "ip_queue: peer pid changed from %d to " 4219- "%d, flushing queue\n", nlq->peer.pid, nlh->nlmsg_pid); 4220- ipq_flush(nlq); 4221- } 4222- nlq->peer.pid = nlh->nlmsg_pid; 4223- nlq->peer.died = 0; 4224- status = ipq_receive_peer(nlq, NLMSG_DATA(nlh), 4225- type, skb->len - NLMSG_LENGTH(0)); 4226+ 4227+ write_lock_bh(&queue_lock); 4228+ 4229+ if (peer_pid) { 4230+ if (peer_pid != pid) { 4231+ write_unlock_bh(&queue_lock); 4232+ RCV_SKB_FAIL(-EBUSY); 4233+ } 4234+ } 4235+ else 4236+ peer_pid = pid; 4237+ 4238+ write_unlock_bh(&queue_lock); 4239+ 4240+ status = ipq_receive_peer(NLMSG_DATA(nlh), type, 4241+ skblen - NLMSG_LENGTH(0)); 4242 if (status < 0) 4243 RCV_SKB_FAIL(status); 4244- if (nlh->nlmsg_flags & NLM_F_ACK) 4245+ 4246+ if (flags & NLM_F_ACK) 4247 netlink_ack(skb, nlh, 0); 4248 return; 4249 } 4250 4251-/* Note: we are only dealing with single part messages at the moment. */ 4252-static void netlink_receive_user_sk(struct sock *sk, int len) 4253+static void 4254+ipq_rcv_sk(struct sock *sk, int len) 4255 { 4256 do { 4257 struct sk_buff *skb; 4258 4259- if (rtnl_shlock_nowait()) 4260+ if (down_trylock(&ipqnl_sem)) 4261 return; 4262+ 4263 while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { 4264- netlink_receive_user_skb(skb); 4265+ ipq_rcv_skb(skb); 4266 kfree_skb(skb); 4267 } 4268- up(&rtnl_sem); 4269- } while (nfnl && nfnl->receive_queue.qlen); 4270-} 4271+ 4272+ up(&ipqnl_sem); 4273 4274-/**************************************************************************** 4275- * 4276- * System events 4277- * 4278- ****************************************************************************/ 4279+ } while (ipqnl && ipqnl->receive_queue.qlen); 4280+} 4281 4282-static int receive_event(struct notifier_block *this, 4283- unsigned long event, void *ptr) 4284+static int 4285+ipq_rcv_dev_event(struct notifier_block *this, 4286+ unsigned long event, void *ptr) 4287 { 4288 struct net_device *dev = ptr; 4289 4290 /* Drop any packets associated with the downed device */ 4291 if (event == NETDEV_DOWN) 4292- ipq_dev_drop(nlq, dev->ifindex); 4293+ ipq_dev_drop(dev->ifindex); 4294 return NOTIFY_DONE; 4295 } 4296 4297-struct notifier_block ipq_dev_notifier = { 4298- receive_event, 4299+static struct notifier_block ipq_dev_notifier = { 4300+ ipq_rcv_dev_event, 4301 NULL, 4302 0 4303 }; 4304 4305-/**************************************************************************** 4306- * 4307- * Sysctl - queue tuning. 4308- * 4309- ****************************************************************************/ 4310+static int 4311+ipq_rcv_nl_event(struct notifier_block *this, 4312+ unsigned long event, void *ptr) 4313+{ 4314+ struct netlink_notify *n = ptr; 4315+ 4316+ if (event == NETLINK_URELEASE && 4317+ n->protocol == NETLINK_FIREWALL && n->pid) { 4318+ write_lock_bh(&queue_lock); 4319+ if (n->pid == peer_pid) 4320+ __ipq_reset(); 4321+ write_unlock_bh(&queue_lock); 4322+ } 4323+ return NOTIFY_DONE; 4324+} 4325 4326-static int sysctl_maxlen = IPQ_QMAX_DEFAULT; 4327+static struct notifier_block ipq_nl_notifier = { 4328+ ipq_rcv_nl_event, 4329+ NULL, 4330+ 0 4331+}; 4332 4333+static int sysctl_maxlen = IPQ_QMAX_DEFAULT; 4334 static struct ctl_table_header *ipq_sysctl_header; 4335 4336 static ctl_table ipq_table[] = { 4337@@ -574,35 +600,27 @@ 4338 { 0 } 4339 }; 4340 4341-/**************************************************************************** 4342- * 4343- * Procfs - debugging info. 4344- * 4345- ****************************************************************************/ 4346- 4347-static int ipq_get_info(char *buffer, char **start, off_t offset, int length) 4348+static int 4349+ipq_get_info(char *buffer, char **start, off_t offset, int length) 4350 { 4351 int len; 4352 4353- spin_lock_bh(&nlq->lock); 4354+ read_lock_bh(&queue_lock); 4355+ 4356 len = sprintf(buffer, 4357- "Peer pid : %d\n" 4358- "Peer died : %d\n" 4359- "Peer copy mode : %d\n" 4360- "Peer copy range : %Zu\n" 4361- "Queue length : %d\n" 4362- "Queue max. length : %d\n" 4363- "Queue flushing : %d\n" 4364- "Queue terminate : %d\n", 4365- nlq->peer.pid, 4366- nlq->peer.died, 4367- nlq->peer.copy_mode, 4368- nlq->peer.copy_range, 4369- nlq->len, 4370- *nlq->maxlen, 4371- nlq->flushing, 4372- nlq->terminate); 4373- spin_unlock_bh(&nlq->lock); 4374+ "Peer PID : %d\n" 4375+ "Copy mode : %hu\n" 4376+ "Copy range : %u\n" 4377+ "Queue length : %u\n" 4378+ "Queue max. length : %u\n", 4379+ peer_pid, 4380+ copy_mode, 4381+ copy_range, 4382+ queue_total, 4383+ queue_maxlen); 4384+ 4385+ read_unlock_bh(&queue_lock); 4386+ 4387 *start = buffer + offset; 4388 len -= offset; 4389 if (len > length) 4390@@ -612,53 +630,74 @@ 4391 return len; 4392 } 4393 4394-/**************************************************************************** 4395- * 4396- * Module stuff. 4397- * 4398- ****************************************************************************/ 4399- 4400-static int __init init(void) 4401+static int 4402+init_or_cleanup(int init) 4403 { 4404- int status = 0; 4405+ int status = -ENOMEM; 4406 struct proc_dir_entry *proc; 4407 4408- nfnl = netlink_kernel_create(NETLINK_FIREWALL, netlink_receive_user_sk); 4409- if (nfnl == NULL) { 4410- printk(KERN_ERR "ip_queue: initialisation failed: unable to " 4411- "create kernel netlink socket\n"); 4412- return -ENOMEM; 4413- } 4414- nlq = ipq_create_queue(netfilter_receive, 4415- netlink_send_peer, &status, &sysctl_maxlen); 4416- if (nlq == NULL) { 4417- printk(KERN_ERR "ip_queue: initialisation failed: unable to " 4418- "create queue\n"); 4419- sock_release(nfnl->socket); 4420- return status; 4421+ if (!init) 4422+ goto cleanup; 4423+ 4424+ netlink_register_notifier(&ipq_nl_notifier); 4425+ ipqnl = netlink_kernel_create(NETLINK_FIREWALL, ipq_rcv_sk); 4426+ if (ipqnl == NULL) { 4427+ printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); 4428+ goto cleanup_netlink_notifier; 4429 } 4430+ 4431 proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info); 4432- if (proc) proc->owner = THIS_MODULE; 4433+ if (proc) 4434+ proc->owner = THIS_MODULE; 4435 else { 4436- ipq_destroy_queue(nlq); 4437- sock_release(nfnl->socket); 4438- return -ENOMEM; 4439+ printk(KERN_ERR "ip_queue: failed to create proc entry\n"); 4440+ goto cleanup_ipqnl; 4441 } 4442+ 4443 register_netdevice_notifier(&ipq_dev_notifier); 4444 ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0); 4445+ 4446+ status = nf_register_queue_handler(PF_INET, ipq_enqueue_packet, NULL); 4447+ if (status < 0) { 4448+ printk(KERN_ERR "ip_queue: failed to register queue handler\n"); 4449+ goto cleanup_sysctl; 4450+ } 4451+ return status; 4452+ 4453+cleanup: 4454+ nf_unregister_queue_handler(PF_INET); 4455+ br_write_lock_bh(BR_NETPROTO_LOCK); 4456+ br_write_unlock_bh(BR_NETPROTO_LOCK); 4457+ ipq_flush(NF_DROP); 4458+ 4459+cleanup_sysctl: 4460+ unregister_sysctl_table(ipq_sysctl_header); 4461+ unregister_netdevice_notifier(&ipq_dev_notifier); 4462+ proc_net_remove(IPQ_PROC_FS_NAME); 4463+ 4464+cleanup_ipqnl: 4465+ sock_release(ipqnl->socket); 4466+ down(&ipqnl_sem); 4467+ up(&ipqnl_sem); 4468+ 4469+cleanup_netlink_notifier: 4470+ netlink_unregister_notifier(&ipq_nl_notifier); 4471 return status; 4472 } 4473 4474+static int __init init(void) 4475+{ 4476+ 4477+ return init_or_cleanup(1); 4478+} 4479+ 4480 static void __exit fini(void) 4481 { 4482- unregister_sysctl_table(ipq_sysctl_header); 4483- proc_net_remove(IPQ_PROC_FS_NAME); 4484- unregister_netdevice_notifier(&ipq_dev_notifier); 4485- ipq_destroy_queue(nlq); 4486- sock_release(nfnl->socket); 4487+ init_or_cleanup(0); 4488 } 4489 4490 MODULE_DESCRIPTION("IPv4 packet queue handler"); 4491+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 4492 MODULE_LICENSE("GPL"); 4493 4494 module_init(init); 4495diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ip_tables.c linux-2.4.20-plain/net/ipv4/netfilter/ip_tables.c 4496--- linux-2.4.19-plain/net/ipv4/netfilter/ip_tables.c Mon Feb 25 20:38:14 2002 4497+++ linux-2.4.20-plain/net/ipv4/netfilter/ip_tables.c Fri Nov 29 00:53:15 2002 4498@@ -9,6 +9,7 @@ 4499 * a table 4500 */ 4501 #include <linux/config.h> 4502+#include <linux/cache.h> 4503 #include <linux/skbuff.h> 4504 #include <linux/kmod.h> 4505 #include <linux/vmalloc.h> 4506@@ -97,7 +98,7 @@ 4507 unsigned int underflow[NF_IP_NUMHOOKS]; 4508 4509 /* ipt_entry tables: one per CPU */ 4510- char entries[0] __attribute__((aligned(SMP_CACHE_BYTES))); 4511+ char entries[0] ____cacheline_aligned; 4512 }; 4513 4514 static LIST_HEAD(ipt_target); 4515diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipchains_core.c linux-2.4.20-plain/net/ipv4/netfilter/ipchains_core.c 4516--- linux-2.4.19-plain/net/ipv4/netfilter/ipchains_core.c Sat Aug 3 02:39:46 2002 4517+++ linux-2.4.20-plain/net/ipv4/netfilter/ipchains_core.c Fri Nov 29 00:53:15 2002 4518@@ -1252,7 +1252,7 @@ 4519 return NULL; 4520 } 4521 4522- fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_KERNEL); 4523+ fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_ATOMIC); 4524 if (!fwkern) { 4525 duprintf("convert_ipfw: kmalloc failed!\n"); 4526 *errno = ENOMEM; 4527@@ -1779,4 +1779,4 @@ 4528 #endif 4529 return ret; 4530 } 4531-MODULE_LICENSE("BSD without advertisement clause"); 4532+MODULE_LICENSE("Dual BSD/GPL"); 4533diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_DSCP.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_DSCP.c 4534--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_DSCP.c Thu Jan 1 01:00:00 1970 4535+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_DSCP.c Fri Nov 29 00:53:15 2002 4536@@ -0,0 +1,108 @@ 4537+/* iptables module for setting the IPv4 DSCP field, Version 1.8 4538+ * 4539+ * (C) 2002 by Harald Welte <laforge@gnumonks.org> 4540+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com> 4541+ * This software is distributed under GNU GPL v2, 1991 4542+ * 4543+ * See RFC2474 for a description of the DSCP field within the IP Header. 4544+ * 4545+ * ipt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp 4546+*/ 4547+ 4548+#include <linux/module.h> 4549+#include <linux/skbuff.h> 4550+#include <linux/ip.h> 4551+#include <net/checksum.h> 4552+ 4553+#include <linux/netfilter_ipv4/ip_tables.h> 4554+#include <linux/netfilter_ipv4/ipt_DSCP.h> 4555+ 4556+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 4557+MODULE_DESCRIPTION("IP tables DSCP modification module"); 4558+MODULE_LICENSE("GPL"); 4559+ 4560+static unsigned int 4561+target(struct sk_buff **pskb, 4562+ unsigned int hooknum, 4563+ const struct net_device *in, 4564+ const struct net_device *out, 4565+ const void *targinfo, 4566+ void *userinfo) 4567+{ 4568+ struct iphdr *iph = (*pskb)->nh.iph; 4569+ const struct ipt_DSCP_info *dinfo = targinfo; 4570+ u_int8_t sh_dscp = ((dinfo->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK); 4571+ 4572+ 4573+ if ((iph->tos & IPT_DSCP_MASK) != sh_dscp) { 4574+ u_int16_t diffs[2]; 4575+ 4576+ /* raw socket (tcpdump) may have clone of incoming 4577+ * skb: don't disturb it --RR */ 4578+ if (skb_cloned(*pskb) && !(*pskb)->sk) { 4579+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); 4580+ if (!nskb) 4581+ return NF_DROP; 4582+ kfree_skb(*pskb); 4583+ *pskb = nskb; 4584+ iph = (*pskb)->nh.iph; 4585+ } 4586+ 4587+ diffs[0] = htons(iph->tos) ^ 0xFFFF; 4588+ iph->tos = (iph->tos & ~IPT_DSCP_MASK) | sh_dscp; 4589+ diffs[1] = htons(iph->tos); 4590+ iph->check = csum_fold(csum_partial((char *)diffs, 4591+ sizeof(diffs), 4592+ iph->check^0xFFFF)); 4593+ (*pskb)->nfcache |= NFC_ALTERED; 4594+ } 4595+ return IPT_CONTINUE; 4596+} 4597+ 4598+static int 4599+checkentry(const char *tablename, 4600+ const struct ipt_entry *e, 4601+ void *targinfo, 4602+ unsigned int targinfosize, 4603+ unsigned int hook_mask) 4604+{ 4605+ const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp; 4606+ 4607+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) { 4608+ printk(KERN_WARNING "DSCP: targinfosize %u != %Zu\n", 4609+ targinfosize, 4610+ IPT_ALIGN(sizeof(struct ipt_DSCP_info))); 4611+ return 0; 4612+ } 4613+ 4614+ if (strcmp(tablename, "mangle") != 0) { 4615+ printk(KERN_WARNING "DSCP: can only be called from \"mangle\" table, not \"%s\"\n", tablename); 4616+ return 0; 4617+ } 4618+ 4619+ if ((dscp > IPT_DSCP_MAX)) { 4620+ printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); 4621+ return 0; 4622+ } 4623+ 4624+ return 1; 4625+} 4626+ 4627+static struct ipt_target ipt_dscp_reg 4628+= { { NULL, NULL }, "DSCP", target, checkentry, NULL, THIS_MODULE }; 4629+ 4630+static int __init init(void) 4631+{ 4632+ if (ipt_register_target(&ipt_dscp_reg)) 4633+ return -EINVAL; 4634+ 4635+ return 0; 4636+} 4637+ 4638+static void __exit fini(void) 4639+{ 4640+ ipt_unregister_target(&ipt_dscp_reg); 4641+} 4642+ 4643+module_init(init); 4644+module_exit(fini); 4645diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_ECN.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_ECN.c 4646--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_ECN.c Thu Jan 1 01:00:00 1970 4647+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_ECN.c Fri Nov 29 00:53:15 2002 4648@@ -0,0 +1,183 @@ 4649+/* iptables module for the IPv4 and TCP ECN bits, Version 1.2 4650+ * 4651+ * (C) 2002 by Harald Welte <laforge@gnumonks.org> 4652+ * 4653+ * This software is distributed under GNU GPL v2, 1991 4654+ * 4655+ * ipt_ECN.c,v 1.4 2002/08/05 19:36:51 laforge Exp 4656+*/ 4657+ 4658+#include <linux/module.h> 4659+#include <linux/skbuff.h> 4660+#include <linux/ip.h> 4661+#include <net/checksum.h> 4662+ 4663+#include <linux/netfilter_ipv4/ip_tables.h> 4664+#include <linux/netfilter_ipv4/ipt_ECN.h> 4665+ 4666+MODULE_LICENSE("GPL"); 4667+ 4668+/* set ECT codepoint from IP header. 4669+ * return 0 in case there was no ECT codepoint 4670+ * return 1 in case ECT codepoint has been overwritten 4671+ * return < 0 in case there was error */ 4672+static int inline 4673+set_ect_ip(struct sk_buff **pskb, struct iphdr *iph, 4674+ const struct ipt_ECN_info *einfo) 4675+{ 4676+ if ((iph->tos & IPT_ECN_IP_MASK) 4677+ != (einfo->ip_ect & IPT_ECN_IP_MASK)) { 4678+ u_int16_t diffs[2]; 4679+ 4680+ /* raw socket (tcpdump) may have clone of incoming 4681+ * skb: don't disturb it --RR */ 4682+ if (skb_cloned(*pskb) && !(*pskb)->sk) { 4683+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); 4684+ if (!nskb) 4685+ return NF_DROP; 4686+ kfree_skb(*pskb); 4687+ *pskb = nskb; 4688+ iph = (*pskb)->nh.iph; 4689+ } 4690+ 4691+ diffs[0] = htons(iph->tos) ^ 0xFFFF; 4692+ iph->tos = iph->tos & ~IPT_ECN_IP_MASK; 4693+ iph->tos = iph->tos | (einfo->ip_ect & IPT_ECN_IP_MASK); 4694+ diffs[1] = htons(iph->tos); 4695+ iph->check = csum_fold(csum_partial((char *)diffs, 4696+ sizeof(diffs), 4697+ iph->check^0xFFFF)); 4698+ (*pskb)->nfcache |= NFC_ALTERED; 4699+ 4700+ return 1; 4701+ } 4702+ return 0; 4703+} 4704+ 4705+static int inline 4706+set_ect_tcp(struct sk_buff **pskb, struct iphdr *iph, 4707+ const struct ipt_ECN_info *einfo) 4708+{ 4709+ 4710+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4; 4711+ u_int16_t *tcpflags = (u_int16_t *)tcph + 6; 4712+ u_int16_t diffs[2]; 4713+ 4714+ /* raw socket (tcpdump) may have clone of incoming 4715+ * skb: don't disturb it --RR */ 4716+ if (skb_cloned(*pskb) && !(*pskb)->sk) { 4717+ struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); 4718+ if (!nskb) 4719+ return NF_DROP; 4720+ kfree_skb(*pskb); 4721+ *pskb = nskb; 4722+ iph = (*pskb)->nh.iph; 4723+ } 4724+ 4725+ diffs[0] = *tcpflags; 4726+ 4727+ if (einfo->operation & IPT_ECN_OP_SET_ECE 4728+ && tcph->ece != einfo->proto.tcp.ece) { 4729+ tcph->ece = einfo->proto.tcp.ece; 4730+ } 4731+ 4732+ if (einfo->operation & IPT_ECN_OP_SET_CWR 4733+ && tcph->cwr != einfo->proto.tcp.cwr) { 4734+ tcph->cwr = einfo->proto.tcp.cwr; 4735+ } 4736+ 4737+ if (diffs[0] != *tcpflags) { 4738+ diffs[0] = htons(diffs[0]) ^ 0xFFFF; 4739+ diffs[1] = htons(*tcpflags); 4740+ tcph->check = csum_fold(csum_partial((char *)diffs, 4741+ sizeof(diffs), 4742+ tcph->check^0xFFFF)); 4743+ (*pskb)->nfcache |= NFC_ALTERED; 4744+ 4745+ return 1; 4746+ } 4747+ 4748+ return 0; 4749+} 4750+ 4751+static unsigned int 4752+target(struct sk_buff **pskb, 4753+ unsigned int hooknum, 4754+ const struct net_device *in, 4755+ const struct net_device *out, 4756+ const void *targinfo, 4757+ void *userinfo) 4758+{ 4759+ struct iphdr *iph = (*pskb)->nh.iph; 4760+ const struct ipt_ECN_info *einfo = targinfo; 4761+ 4762+ if (einfo->operation & IPT_ECN_OP_SET_IP) 4763+ set_ect_ip(pskb, iph, einfo); 4764+ 4765+ if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) 4766+ && iph->protocol == IPPROTO_TCP) 4767+ set_ect_tcp(pskb, iph, einfo); 4768+ 4769+ return IPT_CONTINUE; 4770+} 4771+ 4772+static int 4773+checkentry(const char *tablename, 4774+ const struct ipt_entry *e, 4775+ void *targinfo, 4776+ unsigned int targinfosize, 4777+ unsigned int hook_mask) 4778+{ 4779+ const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; 4780+ 4781+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { 4782+ printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", 4783+ targinfosize, 4784+ IPT_ALIGN(sizeof(struct ipt_ECN_info))); 4785+ return 0; 4786+ } 4787+ 4788+ if (strcmp(tablename, "mangle") != 0) { 4789+ printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename); 4790+ return 0; 4791+ } 4792+ 4793+ if (einfo->operation & IPT_ECN_OP_MASK) { 4794+ printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", 4795+ einfo->operation); 4796+ return 0; 4797+ } 4798+ if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { 4799+ printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", 4800+ einfo->ip_ect); 4801+ return 0; 4802+ } 4803+ 4804+ if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) 4805+ && e->ip.proto != IPPROTO_TCP) { 4806+ printk(KERN_WARNING "ECN: cannot use TCP operations on a " 4807+ "non-tcp rule\n"); 4808+ return 0; 4809+ } 4810+ 4811+ return 1; 4812+} 4813+ 4814+static struct ipt_target ipt_ecn_reg 4815+= { { NULL, NULL }, "ECN", target, checkentry, NULL, THIS_MODULE }; 4816+ 4817+static int __init init(void) 4818+{ 4819+ if (ipt_register_target(&ipt_ecn_reg)) 4820+ return -EINVAL; 4821+ 4822+ return 0; 4823+} 4824+ 4825+static void __exit fini(void) 4826+{ 4827+ ipt_unregister_target(&ipt_ecn_reg); 4828+} 4829+ 4830+module_init(init); 4831+module_exit(fini); 4832diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_REJECT.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_REJECT.c 4833--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_REJECT.c Sat Aug 3 02:39:46 2002 4834+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_REJECT.c Fri Nov 29 00:53:15 2002 4835@@ -75,6 +75,7 @@ 4836 #ifdef CONFIG_NETFILTER_DEBUG 4837 nskb->nf_debug = 0; 4838 #endif 4839+ nskb->nfmark = 0; 4840 4841 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); 4842 4843diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_ULOG.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_ULOG.c 4844--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_ULOG.c Sat Aug 3 02:39:46 2002 4845+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_ULOG.c Fri Nov 29 00:53:15 2002 4846@@ -10,6 +10,8 @@ 4847 * nlgroup now global (sysctl) 4848 * 2001/04/19 ulog-queue reworked, now fixed buffer size specified at 4849 * module loadtime -HW 4850+ * 2002/07/07 remove broken nflog_rcv() function -HW 4851+ * 2002/08/29 fix shifted/unshifted nlgroup bug -HW 4852 * 4853 * Released under the terms of the GPL 4854 * 4855@@ -29,7 +31,7 @@ 4856 * Specify, after how many clock ticks (intel: 100 per second) the queue 4857 * should be flushed even if it is not full yet. 4858 * 4859- * ipt_ULOG.c,v 1.18 2002/04/16 07:33:00 laforge Exp 4860+ * ipt_ULOG.c,v 1.21 2002/08/29 10:54:34 laforge Exp 4861 */ 4862 4863 #include <linux/module.h> 4864@@ -48,8 +50,11 @@ 4865 #include <linux/netfilter_ipv4/ipt_ULOG.h> 4866 #include <linux/netfilter_ipv4/lockhelp.h> 4867 #include <net/sock.h> 4868+#include <linux/bitops.h> 4869 4870 MODULE_LICENSE("GPL"); 4871+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 4872+MODULE_DESCRIPTION("IP tables userspace logging module"); 4873 4874 #define ULOG_NL_EVENT 111 /* Harald's favorite number */ 4875 #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ 4876@@ -63,10 +68,6 @@ 4877 4878 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0) 4879 4880-MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 4881-MODULE_DESCRIPTION("IP tables userspace logging module"); 4882- 4883- 4884 static unsigned int nlbufsiz = 4096; 4885 MODULE_PARM(nlbufsiz, "i"); 4886 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); 4887@@ -91,9 +92,9 @@ 4888 DECLARE_LOCK(ulog_lock); /* spinlock */ 4889 4890 /* send one ulog_buff_t to userspace */ 4891-static void ulog_send(unsigned int nlgroup) 4892+static void ulog_send(unsigned int nlgroupnum) 4893 { 4894- ulog_buff_t *ub = &ulog_buffers[nlgroup]; 4895+ ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; 4896 4897 if (timer_pending(&ub->timer)) { 4898 DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n"); 4899@@ -104,10 +105,10 @@ 4900 if (ub->qlen > 1) 4901 ub->lastnlh->nlmsg_type = NLMSG_DONE; 4902 4903- NETLINK_CB(ub->skb).dst_groups = nlgroup; 4904+ NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum); 4905 DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n", 4906 ub->qlen, nlgroup); 4907- netlink_broadcast(nflognl, ub->skb, 0, nlgroup, GFP_ATOMIC); 4908+ netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC); 4909 4910 ub->qlen = 0; 4911 ub->skb = NULL; 4912@@ -128,11 +129,6 @@ 4913 UNLOCK_BH(&ulog_lock); 4914 } 4915 4916-static void nflog_rcv(struct sock *sk, int len) 4917-{ 4918- printk("ipt_ULOG:nflog_rcv() did receive netlink message ?!?\n"); 4919-} 4920- 4921 struct sk_buff *ulog_alloc_skb(unsigned int size) 4922 { 4923 struct sk_buff *skb; 4924@@ -169,6 +165,11 @@ 4925 struct nlmsghdr *nlh; 4926 struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; 4927 4928+ /* ffs == find first bit set, necessary because userspace 4929+ * is already shifting groupnumber, but we need unshifted. 4930+ * ffs() returns [1..32], we need [0..31] */ 4931+ unsigned int groupnum = ffs(loginfo->nl_group) - 1; 4932+ 4933 /* calculate the size of the skb needed */ 4934 if ((loginfo->copy_range == 0) || 4935 (loginfo->copy_range > (*pskb)->len)) { 4936@@ -179,7 +180,7 @@ 4937 4938 size = NLMSG_SPACE(sizeof(*pm) + copy_len); 4939 4940- ub = &ulog_buffers[loginfo->nl_group]; 4941+ ub = &ulog_buffers[groupnum]; 4942 4943 LOCK_BH(&ulog_lock); 4944 4945@@ -191,7 +192,7 @@ 4946 /* either the queue len is too high or we don't have 4947 * enough room in nlskb left. send it to userspace. */ 4948 4949- ulog_send(loginfo->nl_group); 4950+ ulog_send(groupnum); 4951 4952 if (!(ub->skb = ulog_alloc_skb(size))) 4953 goto alloc_failure; 4954@@ -325,7 +326,7 @@ 4955 ulog_buffers[i].timer.data = i; 4956 } 4957 4958- nflognl = netlink_kernel_create(NETLINK_NFLOG, nflog_rcv); 4959+ nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL); 4960 if (!nflognl) 4961 return -ENOMEM; 4962 4963diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_ah.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_ah.c 4964--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_ah.c Mon Feb 25 20:38:14 2002 4965+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_ah.c Fri Nov 29 00:53:15 2002 4966@@ -91,12 +91,12 @@ 4967 static struct ipt_match ah_match 4968 = { { NULL, NULL }, "ah", &match, &checkentry, NULL, THIS_MODULE }; 4969 4970-int __init init(void) 4971+static int __init init(void) 4972 { 4973 return ipt_register_match(&ah_match); 4974 } 4975 4976-void __exit cleanup(void) 4977+static void __exit cleanup(void) 4978 { 4979 ipt_unregister_match(&ah_match); 4980 } 4981diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_conntrack.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_conntrack.c 4982--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_conntrack.c Thu Jan 1 01:00:00 1970 4983+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_conntrack.c Fri Nov 29 00:53:15 2002 4984@@ -0,0 +1,123 @@ 4985+/* Kernel module to match connection tracking information. 4986+ * Superset of Rusty's minimalistic state match. 4987+ * GPL (C) 2001 Marc Boucher (marc@mbsi.ca). 4988+ */ 4989+#include <linux/module.h> 4990+#include <linux/skbuff.h> 4991+#include <linux/netfilter_ipv4/ip_conntrack.h> 4992+#include <linux/netfilter_ipv4/ip_tables.h> 4993+#include <linux/netfilter_ipv4/ipt_conntrack.h> 4994+ 4995+static int 4996+match(const struct sk_buff *skb, 4997+ const struct net_device *in, 4998+ const struct net_device *out, 4999+ const void *matchinfo, 5000+ int offset, 5001+ const void *hdr, 5002+ u_int16_t datalen, 5003+ int *hotdrop) 5004+{ 5005+ const struct ipt_conntrack_info *sinfo = matchinfo; 5006+ struct ip_conntrack *ct; 5007+ enum ip_conntrack_info ctinfo; 5008+ unsigned int statebit; 5009+ 5010+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); 5011+ 5012+#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) 5013+ 5014+ statebit = ct ? IPT_CONNTRACK_STATE_INVALID : IPT_CONNTRACK_STATE_BIT(ctinfo); 5015+ if(sinfo->flags & IPT_CONNTRACK_STATE) { 5016+ if (ct) { 5017+ if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != 5018+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) 5019+ statebit |= IPT_CONNTRACK_STATE_SNAT; 5020+ 5021+ if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != 5022+ ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) 5023+ statebit |= IPT_CONNTRACK_STATE_DNAT; 5024+ } 5025+ 5026+ if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) 5027+ return 0; 5028+ } 5029+ 5030+ if(sinfo->flags & IPT_CONNTRACK_PROTO) { 5031+ if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) 5032+ return 0; 5033+ } 5034+ 5035+ if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { 5036+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) 5037+ return 0; 5038+ } 5039+ 5040+ if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { 5041+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) 5042+ return 0; 5043+ } 5044+ 5045+ if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { 5046+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) 5047+ return 0; 5048+ } 5049+ 5050+ if(sinfo->flags & IPT_CONNTRACK_REPLDST) { 5051+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) 5052+ return 0; 5053+ } 5054+ 5055+ if(sinfo->flags & IPT_CONNTRACK_STATUS) { 5056+ if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) 5057+ return 0; 5058+ } 5059+ 5060+ if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { 5061+ unsigned long expires; 5062+ 5063+ if(!ct) 5064+ return 0; 5065+ 5066+ expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; 5067+ 5068+ if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) 5069+ return 0; 5070+ } 5071+ 5072+ return 1; 5073+} 5074+ 5075+static int check(const char *tablename, 5076+ const struct ipt_ip *ip, 5077+ void *matchinfo, 5078+ unsigned int matchsize, 5079+ unsigned int hook_mask) 5080+{ 5081+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) 5082+ return 0; 5083+ 5084+ return 1; 5085+} 5086+ 5087+static struct ipt_match conntrack_match 5088+= { { NULL, NULL }, "conntrack", &match, &check, NULL, THIS_MODULE }; 5089+ 5090+static int __init init(void) 5091+{ 5092+ /* NULL if ip_conntrack not a module */ 5093+ if (ip_conntrack_module) 5094+ __MOD_INC_USE_COUNT(ip_conntrack_module); 5095+ return ipt_register_match(&conntrack_match); 5096+} 5097+ 5098+static void __exit fini(void) 5099+{ 5100+ ipt_unregister_match(&conntrack_match); 5101+ if (ip_conntrack_module) 5102+ __MOD_DEC_USE_COUNT(ip_conntrack_module); 5103+} 5104+ 5105+module_init(init); 5106+module_exit(fini); 5107+MODULE_LICENSE("GPL"); 5108diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_dscp.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_dscp.c 5109--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_dscp.c Thu Jan 1 01:00:00 1970 5110+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_dscp.c Fri Nov 29 00:53:15 2002 5111@@ -0,0 +1,58 @@ 5112+/* IP tables module for matching the value of the IPv4 DSCP field 5113+ * 5114+ * ipt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp 5115+ * 5116+ * (C) 2002 by Harald Welte <laforge@gnumonks.org> 5117+ * 5118+ * This software is distributed under the terms GNU GPL 5119+ */ 5120+ 5121+#include <linux/module.h> 5122+#include <linux/skbuff.h> 5123+ 5124+#include <linux/netfilter_ipv4/ipt_dscp.h> 5125+#include <linux/netfilter_ipv4/ip_tables.h> 5126+ 5127+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 5128+MODULE_DESCRIPTION("IP tables DSCP matching module"); 5129+MODULE_LICENSE("GPL"); 5130+ 5131+static int match(const struct sk_buff *skb, const struct net_device *in, 5132+ const struct net_device *out, const void *matchinfo, 5133+ int offset, const void *hdr, u_int16_t datalen, 5134+ int *hotdrop) 5135+{ 5136+ const struct ipt_dscp_info *info = matchinfo; 5137+ const struct iphdr *iph = skb->nh.iph; 5138+ 5139+ u_int8_t sh_dscp = ((info->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK); 5140+ 5141+ return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; 5142+} 5143+ 5144+static int checkentry(const char *tablename, const struct ipt_ip *ip, 5145+ void *matchinfo, unsigned int matchsize, 5146+ unsigned int hook_mask) 5147+{ 5148+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_dscp_info))) 5149+ return 0; 5150+ 5151+ return 1; 5152+} 5153+ 5154+static struct ipt_match dscp_match = { { NULL, NULL }, "dscp", &match, 5155+ &checkentry, NULL, THIS_MODULE }; 5156+ 5157+static int __init init(void) 5158+{ 5159+ return ipt_register_match(&dscp_match); 5160+} 5161+ 5162+static void __exit fini(void) 5163+{ 5164+ ipt_unregister_match(&dscp_match); 5165+ 5166+} 5167+ 5168+module_init(init); 5169+module_exit(fini); 5170diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_ecn.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_ecn.c 5171--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_ecn.c Thu Jan 1 01:00:00 1970 5172+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_ecn.c Fri Nov 29 00:53:15 2002 5173@@ -0,0 +1,118 @@ 5174+/* IP tables module for matching the value of the IPv4 and TCP ECN bits 5175+ * 5176+ * ipt_ecn.c,v 1.3 2002/05/29 15:09:00 laforge Exp 5177+ * 5178+ * (C) 2002 by Harald Welte <laforge@gnumonks.org> 5179+ * 5180+ * This software is distributed under the terms GNU GPL v2 5181+ */ 5182+ 5183+#include <linux/module.h> 5184+#include <linux/skbuff.h> 5185+#include <linux/tcp.h> 5186+ 5187+#include <linux/netfilter_ipv4/ip_tables.h> 5188+#include <linux/netfilter_ipv4/ipt_ecn.h> 5189+ 5190+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 5191+MODULE_DESCRIPTION("IP tables ECN matching module"); 5192+MODULE_LICENSE("GPL"); 5193+ 5194+static inline int match_ip(const struct sk_buff *skb, 5195+ const struct iphdr *iph, 5196+ const struct ipt_ecn_info *einfo) 5197+{ 5198+ return ((iph->tos&IPT_ECN_IP_MASK) == einfo->ip_ect); 5199+} 5200+ 5201+static inline int match_tcp(const struct sk_buff *skb, 5202+ const struct iphdr *iph, 5203+ const struct ipt_ecn_info *einfo) 5204+{ 5205+ struct tcphdr *tcph = (void *)iph + iph->ihl*4; 5206+ 5207+ if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { 5208+ if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { 5209+ if (tcph->ece == 1) 5210+ return 0; 5211+ } else { 5212+ if (tcph->ece == 0) 5213+ return 0; 5214+ } 5215+ } 5216+ 5217+ if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { 5218+ if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { 5219+ if (tcph->cwr == 1) 5220+ return 0; 5221+ } else { 5222+ if (tcph->cwr == 0) 5223+ return 0; 5224+ } 5225+ } 5226+ 5227+ return 1; 5228+} 5229+ 5230+static int match(const struct sk_buff *skb, const struct net_device *in, 5231+ const struct net_device *out, const void *matchinfo, 5232+ int offset, const void *hdr, u_int16_t datalen, 5233+ int *hotdrop) 5234+{ 5235+ const struct ipt_ecn_info *info = matchinfo; 5236+ const struct iphdr *iph = skb->nh.iph; 5237+ 5238+ if (info->operation & IPT_ECN_OP_MATCH_IP) 5239+ if (!match_ip(skb, iph, info)) 5240+ return 0; 5241+ 5242+ if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { 5243+ if (iph->protocol != IPPROTO_TCP) 5244+ return 0; 5245+ if (!match_tcp(skb, iph, info)) 5246+ return 0; 5247+ } 5248+ 5249+ return 1; 5250+} 5251+ 5252+static int checkentry(const char *tablename, const struct ipt_ip *ip, 5253+ void *matchinfo, unsigned int matchsize, 5254+ unsigned int hook_mask) 5255+{ 5256+ const struct ipt_ecn_info *info = matchinfo; 5257+ 5258+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) 5259+ return 0; 5260+ 5261+ if (info->operation & IPT_ECN_OP_MATCH_MASK) 5262+ return 0; 5263+ 5264+ if (info->invert & IPT_ECN_OP_MATCH_MASK) 5265+ return 0; 5266+ 5267+ if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) 5268+ && ip->proto != IPPROTO_TCP) { 5269+ printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" 5270+ " non-tcp packets\n"); 5271+ return 0; 5272+ } 5273+ 5274+ return 1; 5275+} 5276+ 5277+static struct ipt_match ecn_match = { { NULL, NULL }, "ecn", &match, 5278+ &checkentry, NULL, THIS_MODULE }; 5279+ 5280+static int __init init(void) 5281+{ 5282+ return ipt_register_match(&ecn_match); 5283+} 5284+ 5285+static void __exit fini(void) 5286+{ 5287+ ipt_unregister_match(&ecn_match); 5288+} 5289+ 5290+module_init(init); 5291+module_exit(fini); 5292diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_helper.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_helper.c 5293--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_helper.c Thu Jan 1 01:00:00 1970 5294+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_helper.c Fri Nov 29 00:53:15 2002 5295@@ -0,0 +1,112 @@ 5296+/* 5297+ * iptables module to match on related connections 5298+ * (c) 2001 Martin Josefsson <gandalf@wlug.westbo.se> 5299+ * 5300+ * Released under the terms of GNU GPLv2. 5301+ * 5302+ * 19 Mar 2002 Harald Welte <laforge@gnumonks.org>: 5303+ * - Port to newnat infrastructure 5304+ */ 5305+#include <linux/module.h> 5306+#include <linux/skbuff.h> 5307+#include <linux/netfilter_ipv4/ip_conntrack.h> 5308+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 5309+#include <linux/netfilter_ipv4/ip_tables.h> 5310+#include <linux/netfilter_ipv4/ipt_helper.h> 5311+ 5312+MODULE_LICENSE("GPL"); 5313+ 5314+#if 0 5315+#define DEBUGP printk 5316+#else 5317+#define DEBUGP(format, args...) 5318+#endif 5319+ 5320+static int 5321+match(const struct sk_buff *skb, 5322+ const struct net_device *in, 5323+ const struct net_device *out, 5324+ const void *matchinfo, 5325+ int offset, 5326+ const void *hdr, 5327+ u_int16_t datalen, 5328+ int *hotdrop) 5329+{ 5330+ const struct ipt_helper_info *info = matchinfo; 5331+ struct ip_conntrack_expect *exp; 5332+ struct ip_conntrack *ct; 5333+ enum ip_conntrack_info ctinfo; 5334+ 5335+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); 5336+ if (!ct) { 5337+ DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); 5338+ return 0; 5339+ } 5340+ 5341+ if (!ct->master) { 5342+ DEBUGP("ipt_helper: conntrack %p has no master\n", ct); 5343+ return 0; 5344+ } 5345+ 5346+ exp = ct->master; 5347+ if (!exp->expectant) { 5348+ DEBUGP("ipt_helper: expectation %p without expectant !?!\n", 5349+ exp); 5350+ return 0; 5351+ } 5352+ 5353+ if (!exp->expectant->helper) { 5354+ DEBUGP("ipt_helper: master ct %p has no helper\n", 5355+ exp->expectant); 5356+ return 0; 5357+ } 5358+ 5359+ DEBUGP("master's name = %s , info->name = %s\n", 5360+ exp->expectant->helper->name, info->name); 5361+ 5362+ return !strncmp(exp->expectant->helper->name, info->name, 5363+ strlen(exp->expectant->helper->name)) ^ info->invert; 5364+} 5365+ 5366+static int check(const char *tablename, 5367+ const struct ipt_ip *ip, 5368+ void *matchinfo, 5369+ unsigned int matchsize, 5370+ unsigned int hook_mask) 5371+{ 5372+ struct ipt_helper_info *info = matchinfo; 5373+ 5374+ info->name[29] = '\0'; 5375+ 5376+ /* verify size */ 5377+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) 5378+ return 0; 5379+ 5380+ /* verify that we actually should match anything */ 5381+ if ( strlen(info->name) == 0 ) 5382+ return 0; 5383+ 5384+ return 1; 5385+} 5386+ 5387+static struct ipt_match helper_match 5388+= { { NULL, NULL }, "helper", &match, &check, NULL, THIS_MODULE }; 5389+ 5390+static int __init init(void) 5391+{ 5392+ /* NULL if ip_conntrack not a module */ 5393+ if (ip_conntrack_module) 5394+ __MOD_INC_USE_COUNT(ip_conntrack_module); 5395+ return ipt_register_match(&helper_match); 5396+} 5397+ 5398+static void __exit fini(void) 5399+{ 5400+ ipt_unregister_match(&helper_match); 5401+ if (ip_conntrack_module) 5402+ __MOD_DEC_USE_COUNT(ip_conntrack_module); 5403+} 5404+ 5405+module_init(init); 5406+module_exit(fini); 5407+ 5408diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_owner.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_owner.c 5409--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_owner.c Sun Sep 30 21:26:08 2001 5410+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_owner.c Fri Nov 29 00:53:15 2002 5411@@ -12,6 +12,38 @@ 5412 #include <linux/netfilter_ipv4/ip_tables.h> 5413 5414 static int 5415+match_comm(const struct sk_buff *skb, const char *comm) 5416+{ 5417+ struct task_struct *p; 5418+ struct files_struct *files; 5419+ int i; 5420+ 5421+ read_lock(&tasklist_lock); 5422+ for_each_task(p) { 5423+ if(strncmp(p->comm, comm, sizeof(p->comm))) 5424+ continue; 5425+ 5426+ task_lock(p); 5427+ files = p->files; 5428+ if(files) { 5429+ read_lock(&files->file_lock); 5430+ for (i=0; i < files->max_fds; i++) { 5431+ if (fcheck_files(files, i) == skb->sk->socket->file) { 5432+ read_unlock(&files->file_lock); 5433+ task_unlock(p); 5434+ read_unlock(&tasklist_lock); 5435+ return 1; 5436+ } 5437+ } 5438+ read_unlock(&files->file_lock); 5439+ } 5440+ task_unlock(p); 5441+ } 5442+ read_unlock(&tasklist_lock); 5443+ return 0; 5444+} 5445+ 5446+static int 5447 match_pid(const struct sk_buff *skb, pid_t pid) 5448 { 5449 struct task_struct *p; 5450@@ -112,6 +144,12 @@ 5451 if(info->match & IPT_OWNER_SID) { 5452 if (!match_sid(skb, info->sid) ^ 5453 !!(info->invert & IPT_OWNER_SID)) 5454+ return 0; 5455+ } 5456+ 5457+ if(info->match & IPT_OWNER_COMM) { 5458+ if (!match_comm(skb, info->comm) ^ 5459+ !!(info->invert & IPT_OWNER_COMM)) 5460 return 0; 5461 } 5462 5463diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_pkttype.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_pkttype.c 5464--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_pkttype.c Thu Jan 1 01:00:00 1970 5465+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_pkttype.c Fri Nov 29 00:53:15 2002 5466@@ -0,0 +1,59 @@ 5467+#include <linux/module.h> 5468+#include <linux/skbuff.h> 5469+#include <linux/if_ether.h> 5470+#include <linux/if_packet.h> 5471+ 5472+#include <linux/netfilter_ipv4/ipt_pkttype.h> 5473+#include <linux/netfilter_ipv4/ip_tables.h> 5474+ 5475+MODULE_LICENSE("GPL"); 5476+ 5477+static int match(const struct sk_buff *skb, 5478+ const struct net_device *in, 5479+ const struct net_device *out, 5480+ const void *matchinfo, 5481+ int offset, 5482+ const void *hdr, 5483+ u_int16_t datalen, 5484+ int *hotdrop) 5485+{ 5486+ const struct ipt_pkttype_info *info = matchinfo; 5487+ 5488+ return (skb->pkt_type == info->pkttype) ^ info->invert; 5489+} 5490+ 5491+static int checkentry(const char *tablename, 5492+ const struct ipt_ip *ip, 5493+ void *matchinfo, 5494+ unsigned int matchsize, 5495+ unsigned int hook_mask) 5496+{ 5497+/* 5498+ if (hook_mask 5499+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) 5500+ | (1 << NF_IP_FORWARD))) { 5501+ printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); 5502+ return 0; 5503+ } 5504+*/ 5505+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info))) 5506+ return 0; 5507+ 5508+ return 1; 5509+} 5510+ 5511+static struct ipt_match pkttype_match 5512+= { { NULL, NULL }, "pkttype", &match, &checkentry, NULL, THIS_MODULE }; 5513+ 5514+static int __init init(void) 5515+{ 5516+ return ipt_register_match(&pkttype_match); 5517+} 5518+ 5519+static void __exit fini(void) 5520+{ 5521+ ipt_unregister_match(&pkttype_match); 5522+} 5523+ 5524+module_init(init); 5525+module_exit(fini); 5526diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv4/netfilter/ipt_unclean.c linux-2.4.20-plain/net/ipv4/netfilter/ipt_unclean.c 5527--- linux-2.4.19-plain/net/ipv4/netfilter/ipt_unclean.c Fri Dec 21 18:42:05 2001 5528+++ linux-2.4.20-plain/net/ipv4/netfilter/ipt_unclean.c Fri Nov 29 00:53:15 2002 5529@@ -211,15 +211,14 @@ 5530 5531 /* Bad checksum? Don't print, just say it's unclean. */ 5532- if (!more_frags && !embedded 5533+ if (!more_frags && !embedded && udph->check 5534 && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, 5535 csum_partial((char *)udph, datalen, 0)) != 0) 5536 return 0; 5537 5538- /* CHECK: Ports can't be zero. */ 5539- if (!udph->source || !udph->dest) { 5540- limpk("UDP zero ports %u/%u\n", 5541- ntohs(udph->source), ntohs(udph->dest)); 5542+ /* CHECK: Destination port can't be zero. */ 5543+ if (!udph->dest) { 5544+ limpk("UDP zero destination port\n"); 5545 return 0; 5546 } 5547 5548diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/Config.in linux-2.4.20-plain/net/ipv6/netfilter/Config.in 5549--- linux-2.4.19-plain/net/ipv6/netfilter/Config.in Mon Feb 25 20:38:14 2002 5550+++ linux-2.4.20-plain/net/ipv6/netfilter/Config.in Fri Nov 29 00:53:15 2002 5551@@ -24,6 +24,10 @@ 5552 fi 5553 # dep_tristate ' MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES 5554 dep_tristate ' netfilter MARK match support' CONFIG_IP6_NF_MATCH_MARK $CONFIG_IP6_NF_IPTABLES 5555+ dep_tristate ' Packet Length match support' CONFIG_IP6_NF_MATCH_LENGTH $CONFIG_IP6_NF_IPTABLES 5556+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 5557+ dep_tristate ' EUI64 address check (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_EUI64 $CONFIG_IP6_NF_IPTABLES 5558+ fi 5559 # dep_tristate ' Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES 5560 # dep_tristate ' TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES 5561 # if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then 5562diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/Makefile linux-2.4.20-plain/net/ipv6/netfilter/Makefile 5563--- linux-2.4.19-plain/net/ipv6/netfilter/Makefile Mon Feb 25 20:38:14 2002 5564+++ linux-2.4.20-plain/net/ipv6/netfilter/Makefile Fri Nov 29 00:53:15 2002 5565@@ -15,7 +15,9 @@ 5566 obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 5567 obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o 5568 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o 5569+obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o 5570 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o 5571+obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 5572 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o 5573 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 5574 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 5575diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/ip6_queue.c linux-2.4.20-plain/net/ipv6/netfilter/ip6_queue.c 5576--- linux-2.4.19-plain/net/ipv6/netfilter/ip6_queue.c Sat Aug 3 02:39:46 2002 5577+++ linux-2.4.20-plain/net/ipv6/netfilter/ip6_queue.c Fri Nov 29 00:53:15 2002 5578@@ -15,7 +15,7 @@ 5579 * real coder of this. 5580 * Few changes needed, mainly the hard_routing code and 5581 * the netlink socket protocol (we're NETLINK_IP6_FW). 5582- * 5583+ * 2002-06-25: Code cleanup. [JM: ported cleanup over from ip_queue.c] 5584 */ 5585 #include <linux/module.h> 5586 #include <linux/skbuff.h> 5587@@ -26,18 +26,12 @@ 5588 #include <linux/netfilter.h> 5589 #include <linux/netlink.h> 5590 #include <linux/spinlock.h> 5591-#include <linux/rtnetlink.h> 5592+#include <linux/brlock.h> 5593 #include <linux/sysctl.h> 5594 #include <linux/proc_fs.h> 5595 #include <net/sock.h> 5596 #include <net/ipv6.h> 5597 #include <net/ip6_route.h> 5598- 5599-/* We're still usign the following structs. No need to change them: */ 5600-/* ipq_packet_msg */ 5601-/* ipq_mode_msg */ 5602-/* ipq_verdict_msg */ 5603-/* ipq_peer_msg */ 5604 #include <linux/netfilter_ipv4/ip_queue.h> 5605 #include <linux/netfilter_ipv4/ip_tables.h> 5606 #include <linux/netfilter_ipv6/ip6_tables.h> 5607@@ -47,184 +41,289 @@ 5608 #define NET_IPQ_QMAX 2088 5609 #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" 5610 5611-typedef struct ip6q_rt_info { 5612+struct ipq_rt_info { 5613 struct in6_addr daddr; 5614 struct in6_addr saddr; 5615-} ip6q_rt_info_t; 5616+}; 5617 5618-typedef struct ip6q_queue_element { 5619- struct list_head list; /* Links element into queue */ 5620- int verdict; /* Current verdict */ 5621- struct nf_info *info; /* Extra info from netfilter */ 5622- struct sk_buff *skb; /* Packet inside */ 5623- ip6q_rt_info_t rt_info; /* May need post-mangle routing */ 5624-} ip6q_queue_element_t; 5625- 5626-typedef int (*ip6q_send_cb_t)(ip6q_queue_element_t *e); 5627- 5628-typedef struct ip6q_peer { 5629- pid_t pid; /* PID of userland peer */ 5630- unsigned char died; /* We think the peer died */ 5631- unsigned char copy_mode; /* Copy packet as well as metadata? */ 5632- size_t copy_range; /* Range past metadata to copy */ 5633- ip6q_send_cb_t send; /* Callback for sending data to peer */ 5634-} ip6q_peer_t; 5635- 5636-typedef struct ip6q_queue { 5637- int len; /* Current queue len */ 5638- int *maxlen; /* Maximum queue len, via sysctl */ 5639- unsigned char flushing; /* If queue is being flushed */ 5640- unsigned char terminate; /* If the queue is being terminated */ 5641- struct list_head list; /* Head of packet queue */ 5642- spinlock_t lock; /* Queue spinlock */ 5643- ip6q_peer_t peer; /* Userland peer */ 5644-} ip6q_queue_t; 5645+struct ipq_queue_entry { 5646+ struct list_head list; 5647+ struct nf_info *info; 5648+ struct sk_buff *skb; 5649+ struct ipq_rt_info rt_info; 5650+}; 5651 5652-/**************************************************************************** 5653- * 5654- * Packet queue 5655- * 5656- ****************************************************************************/ 5657-/* Dequeue a packet if matched by cmp, or the next available if cmp is NULL */ 5658-static ip6q_queue_element_t * 5659-ip6q_dequeue(ip6q_queue_t *q, 5660- int (*cmp)(ip6q_queue_element_t *, unsigned long), 5661- unsigned long data) 5662-{ 5663- struct list_head *i; 5664- 5665- spin_lock_bh(&q->lock); 5666- for (i = q->list.prev; i != &q->list; i = i->prev) { 5667- ip6q_queue_element_t *e = (ip6q_queue_element_t *)i; 5668- 5669- if (!cmp || cmp(e, data)) { 5670- list_del(&e->list); 5671- q->len--; 5672- spin_unlock_bh(&q->lock); 5673- return e; 5674- } 5675+typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); 5676+ 5677+static unsigned char copy_mode = IPQ_COPY_NONE; 5678+static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT; 5679+static rwlock_t queue_lock = RW_LOCK_UNLOCKED; 5680+static int peer_pid; 5681+static unsigned int copy_range; 5682+static unsigned int queue_total; 5683+static struct sock *ipqnl; 5684+static LIST_HEAD(queue_list); 5685+static DECLARE_MUTEX(ipqnl_sem); 5686+ 5687+static void 5688+ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict) 5689+{ 5690+ nf_reinject(entry->skb, entry->info, verdict); 5691+ kfree(entry); 5692+} 5693+ 5694+static inline int 5695+__ipq_enqueue_entry(struct ipq_queue_entry *entry) 5696+{ 5697+ if (queue_total >= queue_maxlen) { 5698+ if (net_ratelimit()) 5699+ printk(KERN_WARNING "ip6_queue: full at %d entries, " 5700+ "dropping packet(s).\n", queue_total); 5701+ return -ENOSPC; 5702+ } 5703+ list_add(&entry->list, &queue_list); 5704+ queue_total++; 5705+ return 0; 5706+} 5707+ 5708+/* 5709+ * Find and return a queued entry matched by cmpfn, or return the last 5710+ * entry if cmpfn is NULL. 5711+ */ 5712+static inline struct ipq_queue_entry * 5713+__ipq_find_entry(ipq_cmpfn cmpfn, unsigned long data) 5714+{ 5715+ struct list_head *p; 5716+ 5717+ list_for_each_prev(p, &queue_list) { 5718+ struct ipq_queue_entry *entry = (struct ipq_queue_entry *)p; 5719+ 5720+ if (!cmpfn || cmpfn(entry, data)) 5721+ return entry; 5722 } 5723- spin_unlock_bh(&q->lock); 5724 return NULL; 5725 } 5726 5727-/* Flush all packets */ 5728-static void ip6q_flush(ip6q_queue_t *q) 5729+static inline void 5730+__ipq_dequeue_entry(struct ipq_queue_entry *entry) 5731 { 5732- ip6q_queue_element_t *e; 5733- 5734- spin_lock_bh(&q->lock); 5735- q->flushing = 1; 5736- spin_unlock_bh(&q->lock); 5737- while ((e = ip6q_dequeue(q, NULL, 0))) { 5738- e->verdict = NF_DROP; 5739- nf_reinject(e->skb, e->info, e->verdict); 5740- kfree(e); 5741- } 5742- spin_lock_bh(&q->lock); 5743- q->flushing = 0; 5744- spin_unlock_bh(&q->lock); 5745-} 5746- 5747-static ip6q_queue_t *ip6q_create_queue(nf_queue_outfn_t outfn, 5748- ip6q_send_cb_t send_cb, 5749- int *errp, int *sysctl_qmax) 5750+ list_del(&entry->list); 5751+ queue_total--; 5752+} 5753+ 5754+static inline struct ipq_queue_entry * 5755+__ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data) 5756 { 5757- int status; 5758- ip6q_queue_t *q; 5759+ struct ipq_queue_entry *entry; 5760 5761- *errp = 0; 5762- q = kmalloc(sizeof(ip6q_queue_t), GFP_KERNEL); 5763- if (q == NULL) { 5764- *errp = -ENOMEM; 5765+ entry = __ipq_find_entry(cmpfn, data); 5766+ if (entry == NULL) 5767 return NULL; 5768+ 5769+ __ipq_dequeue_entry(entry); 5770+ return entry; 5771+} 5772+ 5773+ 5774+static inline void 5775+__ipq_flush(int verdict) 5776+{ 5777+ struct ipq_queue_entry *entry; 5778+ 5779+ while ((entry = __ipq_find_dequeue_entry(NULL, 0))) 5780+ ipq_issue_verdict(entry, verdict); 5781+} 5782+ 5783+static inline int 5784+__ipq_set_mode(unsigned char mode, unsigned int range) 5785+{ 5786+ int status = 0; 5787+ 5788+ switch(mode) { 5789+ case IPQ_COPY_NONE: 5790+ case IPQ_COPY_META: 5791+ copy_mode = mode; 5792+ copy_range = 0; 5793+ break; 5794+ 5795+ case IPQ_COPY_PACKET: 5796+ copy_mode = mode; 5797+ copy_range = range; 5798+ if (copy_range > 0xFFFF) 5799+ copy_range = 0xFFFF; 5800+ break; 5801+ 5802+ default: 5803+ status = -EINVAL; 5804+ 5805 } 5806- q->peer.pid = 0; 5807- q->peer.died = 0; 5808- q->peer.copy_mode = IPQ_COPY_NONE; 5809- q->peer.copy_range = 0; 5810- q->peer.send = send_cb; 5811- q->len = 0; 5812- q->maxlen = sysctl_qmax; 5813- q->flushing = 0; 5814- q->terminate = 0; 5815- INIT_LIST_HEAD(&q->list); 5816- spin_lock_init(&q->lock); 5817- status = nf_register_queue_handler(PF_INET6, outfn, q); 5818- if (status < 0) { 5819- *errp = -EBUSY; 5820- kfree(q); 5821+ return status; 5822+} 5823+ 5824+static inline void 5825+__ipq_reset(void) 5826+{ 5827+ peer_pid = 0; 5828+ __ipq_set_mode(IPQ_COPY_NONE, 0); 5829+ __ipq_flush(NF_DROP); 5830+} 5831+ 5832+static struct ipq_queue_entry * 5833+ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data) 5834+{ 5835+ struct ipq_queue_entry *entry; 5836+ 5837+ write_lock_bh(&queue_lock); 5838+ entry = __ipq_find_dequeue_entry(cmpfn, data); 5839+ write_unlock_bh(&queue_lock); 5840+ return entry; 5841+} 5842+ 5843+static void 5844+ipq_flush(int verdict) 5845+{ 5846+ write_lock_bh(&queue_lock); 5847+ __ipq_flush(verdict); 5848+ write_unlock_bh(&queue_lock); 5849+} 5850+ 5851+static struct sk_buff * 5852+ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) 5853+{ 5854+ unsigned char *old_tail; 5855+ size_t size = 0; 5856+ size_t data_len = 0; 5857+ struct sk_buff *skb; 5858+ struct ipq_packet_msg *pmsg; 5859+ struct nlmsghdr *nlh; 5860+ 5861+ read_lock_bh(&queue_lock); 5862+ 5863+ switch (copy_mode) { 5864+ case IPQ_COPY_META: 5865+ case IPQ_COPY_NONE: 5866+ size = NLMSG_SPACE(sizeof(*pmsg)); 5867+ data_len = 0; 5868+ break; 5869+ 5870+ case IPQ_COPY_PACKET: 5871+ if (copy_range == 0 || copy_range > entry->skb->len) 5872+ data_len = entry->skb->len; 5873+ else 5874+ data_len = copy_range; 5875+ 5876+ size = NLMSG_SPACE(sizeof(*pmsg) + data_len); 5877+ break; 5878+ 5879+ default: 5880+ *errp = -EINVAL; 5881+ read_unlock_bh(&queue_lock); 5882 return NULL; 5883 } 5884- return q; 5885+ 5886+ read_unlock_bh(&queue_lock); 5887+ 5888+ skb = alloc_skb(size, GFP_ATOMIC); 5889+ if (!skb) 5890+ goto nlmsg_failure; 5891+ 5892+ old_tail= skb->tail; 5893+ nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); 5894+ pmsg = NLMSG_DATA(nlh); 5895+ memset(pmsg, 0, sizeof(*pmsg)); 5896+ 5897+ pmsg->packet_id = (unsigned long )entry; 5898+ pmsg->data_len = data_len; 5899+ pmsg->timestamp_sec = entry->skb->stamp.tv_sec; 5900+ pmsg->timestamp_usec = entry->skb->stamp.tv_usec; 5901+ pmsg->mark = entry->skb->nfmark; 5902+ pmsg->hook = entry->info->hook; 5903+ pmsg->hw_protocol = entry->skb->protocol; 5904+ 5905+ if (entry->info->indev) 5906+ strcpy(pmsg->indev_name, entry->info->indev->name); 5907+ else 5908+ pmsg->indev_name[0] = '\0'; 5909+ 5910+ if (entry->info->outdev) 5911+ strcpy(pmsg->outdev_name, entry->info->outdev->name); 5912+ else 5913+ pmsg->outdev_name[0] = '\0'; 5914+ 5915+ if (entry->info->indev && entry->skb->dev) { 5916+ pmsg->hw_type = entry->skb->dev->type; 5917+ if (entry->skb->dev->hard_header_parse) 5918+ pmsg->hw_addrlen = 5919+ entry->skb->dev->hard_header_parse(entry->skb, 5920+ pmsg->hw_addr); 5921+ } 5922+ 5923+ if (data_len) 5924+ memcpy(pmsg->payload, entry->skb->data, data_len); 5925+ 5926+ nlh->nlmsg_len = skb->tail - old_tail; 5927+ return skb; 5928+ 5929+nlmsg_failure: 5930+ if (skb) 5931+ kfree_skb(skb); 5932+ *errp = -EINVAL; 5933+ printk(KERN_ERR "ip6_queue: error creating packet message\n"); 5934+ return NULL; 5935 } 5936 5937-static int ip6q_enqueue(ip6q_queue_t *q, 5938- struct sk_buff *skb, struct nf_info *info) 5939+static int 5940+ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) 5941 { 5942- ip6q_queue_element_t *e; 5943- int status; 5944- 5945- e = kmalloc(sizeof(*e), GFP_ATOMIC); 5946- if (e == NULL) { 5947- printk(KERN_ERR "ip6_queue: OOM in enqueue\n"); 5948+ int status = -EINVAL; 5949+ struct sk_buff *nskb; 5950+ struct ipq_queue_entry *entry; 5951+ 5952+ if (copy_mode == IPQ_COPY_NONE) 5953+ return -EAGAIN; 5954+ 5955+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 5956+ if (entry == NULL) { 5957+ printk(KERN_ERR "ip6_queue: OOM in ipq_enqueue_packet()\n"); 5958 return -ENOMEM; 5959 } 5960 5961- e->verdict = NF_DROP; 5962- e->info = info; 5963- e->skb = skb; 5964+ entry->info = info; 5965+ entry->skb = skb; 5966 5967- if (e->info->hook == NF_IP_LOCAL_OUT) { 5968+ if (entry->info->hook == NF_IP_LOCAL_OUT) { 5969 struct ipv6hdr *iph = skb->nh.ipv6h; 5970 5971- e->rt_info.daddr = iph->daddr; 5972- e->rt_info.saddr = iph->saddr; 5973+ entry->rt_info.daddr = iph->daddr; 5974+ entry->rt_info.saddr = iph->saddr; 5975 } 5976 5977- spin_lock_bh(&q->lock); 5978- if (q->len >= *q->maxlen) { 5979- spin_unlock_bh(&q->lock); 5980- if (net_ratelimit()) 5981- printk(KERN_WARNING "ip6_queue: full at %d entries, " 5982- "dropping packet(s).\n", q->len); 5983- goto free_drop; 5984- } 5985- if (q->flushing || q->peer.copy_mode == IPQ_COPY_NONE 5986- || q->peer.pid == 0 || q->peer.died || q->terminate) { 5987- spin_unlock_bh(&q->lock); 5988- goto free_drop; 5989- } 5990- status = q->peer.send(e); 5991- if (status > 0) { 5992- list_add(&e->list, &q->list); 5993- q->len++; 5994- spin_unlock_bh(&q->lock); 5995- return status; 5996- } 5997- spin_unlock_bh(&q->lock); 5998- if (status == -ECONNREFUSED) { 5999- printk(KERN_INFO "ip6_queue: peer %d died, " 6000- "resetting state and flushing queue\n", q->peer.pid); 6001- q->peer.died = 1; 6002- q->peer.pid = 0; 6003- q->peer.copy_mode = IPQ_COPY_NONE; 6004- q->peer.copy_range = 0; 6005- ip6q_flush(q); 6006- } 6007-free_drop: 6008- kfree(e); 6009- return -EBUSY; 6010-} 6011+ nskb = ipq_build_packet_message(entry, &status); 6012+ if (nskb == NULL) 6013+ goto err_out_free; 6014+ 6015+ write_lock_bh(&queue_lock); 6016+ 6017+ if (!peer_pid) 6018+ goto err_out_unlock; 6019 6020-static void ip6q_destroy_queue(ip6q_queue_t *q) 6021-{ 6022- nf_unregister_queue_handler(PF_INET6); 6023- spin_lock_bh(&q->lock); 6024- q->terminate = 1; 6025- spin_unlock_bh(&q->lock); 6026- ip6q_flush(q); 6027- kfree(q); 6028+ status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT); 6029+ if (status < 0) 6030+ goto err_out_unlock; 6031+ 6032+ status = __ipq_enqueue_entry(entry); 6033+ if (status < 0) 6034+ goto err_out_unlock; 6035+ 6036+ write_unlock_bh(&queue_lock); 6037+ return status; 6038+ 6039+err_out_unlock: 6040+ write_unlock_bh(&queue_lock); 6041+ 6042+err_out_free: 6043+ kfree(entry); 6044+ return status; 6045 } 6046 6047 /* 6048@@ -236,7 +335,8 @@ 6049 * 6050 * If that one is modified, this one should be modified too. 6051 */ 6052-static int route6_me_harder(struct sk_buff *skb) 6053+static int 6054+route6_me_harder(struct sk_buff *skb) 6055 { 6056 struct ipv6hdr *iph = skb->nh.ipv6h; 6057 struct dst_entry *dst; 6058@@ -264,7 +364,9 @@ 6059 skb->dst = dst; 6060 return 0; 6061 } 6062-static int ip6q_mangle_ipv6(ipq_verdict_msg_t *v, ip6q_queue_element_t *e) 6063+ 6064+static int 6065+ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) 6066 { 6067 int diff; 6068 struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; 6069@@ -306,357 +408,262 @@ 6070 */ 6071 if (e->info->hook == NF_IP_LOCAL_OUT) { 6072 struct ipv6hdr *iph = e->skb->nh.ipv6h; 6073- if (!( iph->daddr.in6_u.u6_addr32[0] == e->rt_info.daddr.in6_u.u6_addr32[0] 6074- && iph->daddr.in6_u.u6_addr32[1] == e->rt_info.daddr.in6_u.u6_addr32[1] 6075- && iph->daddr.in6_u.u6_addr32[2] == e->rt_info.daddr.in6_u.u6_addr32[2] 6076- && iph->daddr.in6_u.u6_addr32[3] == e->rt_info.daddr.in6_u.u6_addr32[3] 6077- && iph->saddr.in6_u.u6_addr32[0] == e->rt_info.saddr.in6_u.u6_addr32[0] 6078- && iph->saddr.in6_u.u6_addr32[1] == e->rt_info.saddr.in6_u.u6_addr32[1] 6079- && iph->saddr.in6_u.u6_addr32[2] == e->rt_info.saddr.in6_u.u6_addr32[2] 6080- && iph->saddr.in6_u.u6_addr32[3] == e->rt_info.saddr.in6_u.u6_addr32[3])) 6081+ if (ipv6_addr_cmp(&iph->daddr, &e->rt_info.daddr) || 6082+ ipv6_addr_cmp(&iph->saddr, &e->rt_info.saddr)) 6083 return route6_me_harder(e->skb); 6084 } 6085 return 0; 6086 } 6087 6088-static inline int id_cmp(ip6q_queue_element_t *e, unsigned long id) 6089+static inline int 6090+id_cmp(struct ipq_queue_entry *e, unsigned long id) 6091 { 6092 return (id == (unsigned long )e); 6093 } 6094 6095-static int ip6q_set_verdict(ip6q_queue_t *q, 6096- ipq_verdict_msg_t *v, unsigned int len) 6097+static int 6098+ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) 6099 { 6100- ip6q_queue_element_t *e; 6101+ struct ipq_queue_entry *entry; 6102 6103- if (v->value > NF_MAX_VERDICT) 6104+ if (vmsg->value > NF_MAX_VERDICT) 6105 return -EINVAL; 6106- e = ip6q_dequeue(q, id_cmp, v->id); 6107- if (e == NULL) 6108+ 6109+ entry = ipq_find_dequeue_entry(id_cmp, vmsg->id); 6110+ if (entry == NULL) 6111 return -ENOENT; 6112 else { 6113- e->verdict = v->value; 6114- if (v->data_len && v->data_len == len) 6115- if (ip6q_mangle_ipv6(v, e) < 0) 6116- e->verdict = NF_DROP; 6117- nf_reinject(e->skb, e->info, e->verdict); 6118- kfree(e); 6119+ int verdict = vmsg->value; 6120+ 6121+ if (vmsg->data_len && vmsg->data_len == len) 6122+ if (ipq_mangle_ipv6(vmsg, entry) < 0) 6123+ verdict = NF_DROP; 6124+ 6125+ ipq_issue_verdict(entry, verdict); 6126 return 0; 6127 } 6128 } 6129 6130-static int ip6q_receive_peer(ip6q_queue_t* q, ipq_peer_msg_t *m, 6131- unsigned char type, unsigned int len) 6132+static int 6133+ipq_set_mode(unsigned char mode, unsigned int range) 6134 { 6135+ int status; 6136+ 6137+ write_lock_bh(&queue_lock); 6138+ status = __ipq_set_mode(mode, range); 6139+ write_unlock_bh(&queue_lock); 6140+ return status; 6141+} 6142 6143+static int 6144+ipq_receive_peer(struct ipq_peer_msg *pmsg, 6145+ unsigned char type, unsigned int len) 6146+{ 6147 int status = 0; 6148- int busy; 6149- 6150- spin_lock_bh(&q->lock); 6151- busy = (q->terminate || q->flushing); 6152- spin_unlock_bh(&q->lock); 6153- if (busy) 6154- return -EBUSY; 6155- if (len < sizeof(ipq_peer_msg_t)) 6156+ 6157+ if (len < sizeof(*pmsg)) 6158 return -EINVAL; 6159+ 6160 switch (type) { 6161- case IPQM_MODE: 6162- switch (m->msg.mode.value) { 6163- case IPQ_COPY_META: 6164- q->peer.copy_mode = IPQ_COPY_META; 6165- q->peer.copy_range = 0; 6166- break; 6167- case IPQ_COPY_PACKET: 6168- q->peer.copy_mode = IPQ_COPY_PACKET; 6169- q->peer.copy_range = m->msg.mode.range; 6170- if (q->peer.copy_range > 0xFFFF) 6171- q->peer.copy_range = 0xFFFF; 6172- break; 6173- default: 6174- status = -EINVAL; 6175- } 6176- break; 6177- case IPQM_VERDICT: 6178- if (m->msg.verdict.value > NF_MAX_VERDICT) 6179- status = -EINVAL; 6180- else 6181- status = ip6q_set_verdict(q, 6182- &m->msg.verdict, 6183- len - sizeof(*m)); 6184+ case IPQM_MODE: 6185+ status = ipq_set_mode(pmsg->msg.mode.value, 6186+ pmsg->msg.mode.range); 6187+ break; 6188+ 6189+ case IPQM_VERDICT: 6190+ if (pmsg->msg.verdict.value > NF_MAX_VERDICT) 6191+ status = -EINVAL; 6192+ else 6193+ status = ipq_set_verdict(&pmsg->msg.verdict, 6194+ len - sizeof(*pmsg)); 6195 break; 6196- default: 6197- status = -EINVAL; 6198+ default: 6199+ status = -EINVAL; 6200 } 6201 return status; 6202 } 6203 6204-static inline int dev_cmp(ip6q_queue_element_t *e, unsigned long ifindex) 6205+static int 6206+dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex) 6207 { 6208- if (e->info->indev) 6209- if (e->info->indev->ifindex == ifindex) 6210+ if (entry->info->indev) 6211+ if (entry->info->indev->ifindex == ifindex) 6212 return 1; 6213- if (e->info->outdev) 6214- if (e->info->outdev->ifindex == ifindex) 6215+ 6216+ if (entry->info->outdev) 6217+ if (entry->info->outdev->ifindex == ifindex) 6218 return 1; 6219+ 6220 return 0; 6221 } 6222 6223-/* Drop any queued packets associated with device ifindex */ 6224-static void ip6q_dev_drop(ip6q_queue_t *q, int ifindex) 6225+static void 6226+ipq_dev_drop(int ifindex) 6227 { 6228- ip6q_queue_element_t *e; 6229+ struct ipq_queue_entry *entry; 6230 6231- while ((e = ip6q_dequeue(q, dev_cmp, ifindex))) { 6232- e->verdict = NF_DROP; 6233- nf_reinject(e->skb, e->info, e->verdict); 6234- kfree(e); 6235- } 6236-} 6237- 6238-/**************************************************************************** 6239- * 6240- * Netfilter interface 6241- * 6242- ****************************************************************************/ 6243- 6244-/* 6245- * Packets arrive here from netfilter for queuing to userspace. 6246- * All of them must be fed back via nf_reinject() or Alexey will kill Rusty. 6247- */ 6248-static int netfilter6_receive(struct sk_buff *skb, 6249- struct nf_info *info, void *data) 6250-{ 6251- return ip6q_enqueue((ip6q_queue_t *)data, skb, info); 6252-} 6253- 6254-/**************************************************************************** 6255- * 6256- * Netlink interface. 6257- * 6258- ****************************************************************************/ 6259- 6260-static struct sock *nfnl = NULL; 6261-/* This is not a static one, so we should not repeat its name */ 6262-ip6q_queue_t *nlq6 = NULL; 6263- 6264-static struct sk_buff *netlink_build_message(ip6q_queue_element_t *e, int *errp) 6265-{ 6266- unsigned char *old_tail; 6267- size_t size = 0; 6268- size_t data_len = 0; 6269- struct sk_buff *skb; 6270- ipq_packet_msg_t *pm; 6271- struct nlmsghdr *nlh; 6272- 6273- switch (nlq6->peer.copy_mode) { 6274- size_t copy_range; 6275- 6276- case IPQ_COPY_META: 6277- size = NLMSG_SPACE(sizeof(*pm)); 6278- data_len = 0; 6279- break; 6280- case IPQ_COPY_PACKET: 6281- copy_range = nlq6->peer.copy_range; 6282- if (copy_range == 0 || copy_range > e->skb->len) 6283- data_len = e->skb->len; 6284- else 6285- data_len = copy_range; 6286- size = NLMSG_SPACE(sizeof(*pm) + data_len); 6287- 6288- break; 6289- case IPQ_COPY_NONE: 6290- default: 6291- *errp = -EINVAL; 6292- return NULL; 6293- } 6294- skb = alloc_skb(size, GFP_ATOMIC); 6295- if (!skb) 6296- goto nlmsg_failure; 6297- old_tail = skb->tail; 6298- nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh)); 6299- pm = NLMSG_DATA(nlh); 6300- memset(pm, 0, sizeof(*pm)); 6301- pm->packet_id = (unsigned long )e; 6302- pm->data_len = data_len; 6303- pm->timestamp_sec = e->skb->stamp.tv_sec; 6304- pm->timestamp_usec = e->skb->stamp.tv_usec; 6305- pm->mark = e->skb->nfmark; 6306- pm->hook = e->info->hook; 6307- if (e->info->indev) strcpy(pm->indev_name, e->info->indev->name); 6308- else pm->indev_name[0] = '\0'; 6309- if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name); 6310- else pm->outdev_name[0] = '\0'; 6311- pm->hw_protocol = e->skb->protocol; 6312- if (e->info->indev && e->skb->dev) { 6313- pm->hw_type = e->skb->dev->type; 6314- if (e->skb->dev->hard_header_parse) 6315- pm->hw_addrlen = 6316- e->skb->dev->hard_header_parse(e->skb, 6317- pm->hw_addr); 6318- } 6319- if (data_len) 6320- memcpy(pm->payload, e->skb->data, data_len); 6321- nlh->nlmsg_len = skb->tail - old_tail; 6322- NETLINK_CB(skb).dst_groups = 0; 6323- return skb; 6324-nlmsg_failure: 6325- if (skb) 6326- kfree_skb(skb); 6327- *errp = 0; 6328- printk(KERN_ERR "ip6_queue: error creating netlink message\n"); 6329- return NULL; 6330-} 6331- 6332-static int netlink_send_peer(ip6q_queue_element_t *e) 6333-{ 6334- int status = 0; 6335- struct sk_buff *skb; 6336- 6337- skb = netlink_build_message(e, &status); 6338- if (skb == NULL) 6339- return status; 6340- return netlink_unicast(nfnl, skb, nlq6->peer.pid, MSG_DONTWAIT); 6341+ while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL) 6342+ ipq_issue_verdict(entry, NF_DROP); 6343 } 6344 6345 #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) 6346 6347-static __inline__ void netlink_receive_user_skb(struct sk_buff *skb) 6348+static inline void 6349+ipq_rcv_skb(struct sk_buff *skb) 6350 { 6351- int status, type; 6352+ int status, type, pid, flags, nlmsglen, skblen; 6353 struct nlmsghdr *nlh; 6354 6355- if (skb->len < sizeof(struct nlmsghdr)) 6356+ skblen = skb->len; 6357+ if (skblen < sizeof(*nlh)) 6358 return; 6359 6360 nlh = (struct nlmsghdr *)skb->data; 6361- if (nlh->nlmsg_len < sizeof(struct nlmsghdr) 6362- || skb->len < nlh->nlmsg_len) 6363- return; 6364- 6365- if(nlh->nlmsg_pid <= 0 6366- || !(nlh->nlmsg_flags & NLM_F_REQUEST) 6367- || nlh->nlmsg_flags & NLM_F_MULTI) 6368+ nlmsglen = nlh->nlmsg_len; 6369+ if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen) 6370+ return; 6371+ 6372+ pid = nlh->nlmsg_pid; 6373+ flags = nlh->nlmsg_flags; 6374+ 6375+ if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI) 6376 RCV_SKB_FAIL(-EINVAL); 6377- if (nlh->nlmsg_flags & MSG_TRUNC) 6378+ 6379+ if (flags & MSG_TRUNC) 6380 RCV_SKB_FAIL(-ECOMM); 6381+ 6382 type = nlh->nlmsg_type; 6383 if (type < NLMSG_NOOP || type >= IPQM_MAX) 6384 RCV_SKB_FAIL(-EINVAL); 6385+ 6386 if (type <= IPQM_BASE) 6387 return; 6388+ 6389 if(!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) 6390 RCV_SKB_FAIL(-EPERM); 6391- if (nlq6->peer.pid && !nlq6->peer.died 6392- && (nlq6->peer.pid != nlh->nlmsg_pid)) { 6393- printk(KERN_WARNING "ip6_queue: peer pid changed from %d to " 6394- "%d, flushing queue\n", nlq6->peer.pid, nlh->nlmsg_pid); 6395- ip6q_flush(nlq6); 6396- } 6397- nlq6->peer.pid = nlh->nlmsg_pid; 6398- nlq6->peer.died = 0; 6399- status = ip6q_receive_peer(nlq6, NLMSG_DATA(nlh), 6400- type, skb->len - NLMSG_LENGTH(0)); 6401+ 6402+ write_lock_bh(&queue_lock); 6403+ 6404+ if (peer_pid) { 6405+ if (peer_pid != pid) { 6406+ write_unlock_bh(&queue_lock); 6407+ RCV_SKB_FAIL(-EBUSY); 6408+ } 6409+ } 6410+ else 6411+ peer_pid = pid; 6412+ 6413+ write_unlock_bh(&queue_lock); 6414+ 6415+ status = ipq_receive_peer(NLMSG_DATA(nlh), type, 6416+ skblen - NLMSG_LENGTH(0)); 6417 if (status < 0) 6418 RCV_SKB_FAIL(status); 6419- if (nlh->nlmsg_flags & NLM_F_ACK) 6420+ 6421+ if (flags & NLM_F_ACK) 6422 netlink_ack(skb, nlh, 0); 6423 return; 6424 } 6425 6426-/* Note: we are only dealing with single part messages at the moment. */ 6427-static void netlink_receive_user_sk(struct sock *sk, int len) 6428+static void 6429+ipq_rcv_sk(struct sock *sk, int len) 6430 { 6431 do { 6432 struct sk_buff *skb; 6433 6434- if (rtnl_shlock_nowait()) 6435+ if (down_trylock(&ipqnl_sem)) 6436 return; 6437+ 6438 while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { 6439- netlink_receive_user_skb(skb); 6440+ ipq_rcv_skb(skb); 6441 kfree_skb(skb); 6442 } 6443- up(&rtnl_sem); 6444- } while (nfnl && nfnl->receive_queue.qlen); 6445-} 6446+ 6447+ up(&ipqnl_sem); 6448 6449-/**************************************************************************** 6450- * 6451- * System events 6452- * 6453- ****************************************************************************/ 6454+ } while (ipqnl && ipqnl->receive_queue.qlen); 6455+} 6456 6457-static int receive_event(struct notifier_block *this, 6458- unsigned long event, void *ptr) 6459+static int 6460+ipq_rcv_dev_event(struct notifier_block *this, 6461+ unsigned long event, void *ptr) 6462 { 6463 struct net_device *dev = ptr; 6464 6465 /* Drop any packets associated with the downed device */ 6466 if (event == NETDEV_DOWN) 6467- ip6q_dev_drop(nlq6, dev->ifindex); 6468+ ipq_dev_drop(dev->ifindex); 6469 return NOTIFY_DONE; 6470 } 6471 6472-struct notifier_block ip6q_dev_notifier = { 6473- receive_event, 6474+static struct notifier_block ipq_dev_notifier = { 6475+ ipq_rcv_dev_event, 6476 NULL, 6477 0 6478 }; 6479 6480-/**************************************************************************** 6481- * 6482- * Sysctl - queue tuning. 6483- * 6484- ****************************************************************************/ 6485+static int 6486+ipq_rcv_nl_event(struct notifier_block *this, 6487+ unsigned long event, void *ptr) 6488+{ 6489+ struct netlink_notify *n = ptr; 6490+ 6491+ if (event == NETLINK_URELEASE && 6492+ n->protocol == NETLINK_IP6_FW && n->pid) { 6493+ write_lock_bh(&queue_lock); 6494+ if (n->pid == peer_pid) 6495+ __ipq_reset(); 6496+ write_unlock_bh(&queue_lock); 6497+ } 6498+ return NOTIFY_DONE; 6499+} 6500 6501-static int sysctl_maxlen = IPQ_QMAX_DEFAULT; 6502+static struct notifier_block ipq_nl_notifier = { 6503+ ipq_rcv_nl_event, 6504+ NULL, 6505+ 0 6506+}; 6507 6508-static struct ctl_table_header *ip6q_sysctl_header; 6509+static int sysctl_maxlen = IPQ_QMAX_DEFAULT; 6510+static struct ctl_table_header *ipq_sysctl_header; 6511 6512-static ctl_table ip6q_table[] = { 6513+static ctl_table ipq_table[] = { 6514 { NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen, 6515 sizeof(sysctl_maxlen), 0644, NULL, proc_dointvec }, 6516 { 0 } 6517 }; 6518 6519-static ctl_table ip6q_dir_table[] = { 6520- {NET_IPV6, "ipv6", NULL, 0, 0555, ip6q_table, 0, 0, 0, 0, 0}, 6521+static ctl_table ipq_dir_table[] = { 6522+ {NET_IPV6, "ipv6", NULL, 0, 0555, ipq_table, 0, 0, 0, 0, 0}, 6523 { 0 } 6524 }; 6525 6526-static ctl_table ip6q_root_table[] = { 6527- {CTL_NET, "net", NULL, 0, 0555, ip6q_dir_table, 0, 0, 0, 0, 0}, 6528+static ctl_table ipq_root_table[] = { 6529+ {CTL_NET, "net", NULL, 0, 0555, ipq_dir_table, 0, 0, 0, 0, 0}, 6530 { 0 } 6531 }; 6532 6533-/**************************************************************************** 6534- * 6535- * Procfs - debugging info. 6536- * 6537- ****************************************************************************/ 6538- 6539-static int ip6q_get_info(char *buffer, char **start, off_t offset, int length) 6540+static int 6541+ipq_get_info(char *buffer, char **start, off_t offset, int length) 6542 { 6543 int len; 6544 6545- spin_lock_bh(&nlq6->lock); 6546+ read_lock_bh(&queue_lock); 6547+ 6548 len = sprintf(buffer, 6549- "Peer pid : %d\n" 6550- "Peer died : %d\n" 6551- "Peer copy mode : %d\n" 6552- "Peer copy range : %Zu\n" 6553- "Queue length : %d\n" 6554- "Queue max. length : %d\n" 6555- "Queue flushing : %d\n" 6556- "Queue terminate : %d\n", 6557- nlq6->peer.pid, 6558- nlq6->peer.died, 6559- nlq6->peer.copy_mode, 6560- nlq6->peer.copy_range, 6561- nlq6->len, 6562- *nlq6->maxlen, 6563- nlq6->flushing, 6564- nlq6->terminate); 6565- spin_unlock_bh(&nlq6->lock); 6566+ "Peer PID : %d\n" 6567+ "Copy mode : %hu\n" 6568+ "Copy range : %u\n" 6569+ "Queue length : %u\n" 6570+ "Queue max. length : %u\n", 6571+ peer_pid, 6572+ copy_mode, 6573+ copy_range, 6574+ queue_total, 6575+ queue_maxlen); 6576+ 6577+ read_unlock_bh(&queue_lock); 6578+ 6579 *start = buffer + offset; 6580 len -= offset; 6581 if (len > length) 6582@@ -666,52 +673,70 @@ 6583 return len; 6584 } 6585 6586-/**************************************************************************** 6587- * 6588- * Module stuff. 6589- * 6590- ****************************************************************************/ 6591- 6592-static int __init init(void) 6593+static int 6594+init_or_cleanup(int init) 6595 { 6596- int status = 0; 6597+ int status = -ENOMEM; 6598 struct proc_dir_entry *proc; 6599 6600- /* We must create the NETLINK_IP6_FW protocol service */ 6601- nfnl = netlink_kernel_create(NETLINK_IP6_FW, netlink_receive_user_sk); 6602- if (nfnl == NULL) { 6603- printk(KERN_ERR "ip6_queue: initialisation failed: unable to " 6604- "create kernel netlink socket\n"); 6605- return -ENOMEM; 6606+ if (!init) 6607+ goto cleanup; 6608+ 6609+ netlink_register_notifier(&ipq_nl_notifier); 6610+ ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk); 6611+ if (ipqnl == NULL) { 6612+ printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); 6613+ goto cleanup_netlink_notifier; 6614 } 6615- nlq6 = ip6q_create_queue(netfilter6_receive, 6616- netlink_send_peer, &status, &sysctl_maxlen); 6617- if (nlq6 == NULL) { 6618- printk(KERN_ERR "ip6_queue: initialisation failed: unable to " 6619- "create queue\n"); 6620- sock_release(nfnl->socket); 6621- return status; 6622- } 6623- /* The file will be /proc/net/ip6_queue */ 6624- proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ip6q_get_info); 6625- if (proc) proc->owner = THIS_MODULE; 6626+ 6627+ proc = proc_net_create(IPQ_PROC_FS_NAME, 0, ipq_get_info); 6628+ if (proc) 6629+ proc->owner = THIS_MODULE; 6630 else { 6631- ip6q_destroy_queue(nlq6); 6632- sock_release(nfnl->socket); 6633- return -ENOMEM; 6634+ printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); 6635+ goto cleanup_ipqnl; 6636+ } 6637+ 6638+ register_netdevice_notifier(&ipq_dev_notifier); 6639+ ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0); 6640+ 6641+ status = nf_register_queue_handler(PF_INET6, ipq_enqueue_packet, NULL); 6642+ if (status < 0) { 6643+ printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); 6644+ goto cleanup_sysctl; 6645 } 6646- register_netdevice_notifier(&ip6q_dev_notifier); 6647- ip6q_sysctl_header = register_sysctl_table(ip6q_root_table, 0); 6648+ return status; 6649+ 6650+cleanup: 6651+ nf_unregister_queue_handler(PF_INET6); 6652+ br_write_lock_bh(BR_NETPROTO_LOCK); 6653+ br_write_unlock_bh(BR_NETPROTO_LOCK); 6654+ ipq_flush(NF_DROP); 6655+ 6656+cleanup_sysctl: 6657+ unregister_sysctl_table(ipq_sysctl_header); 6658+ unregister_netdevice_notifier(&ipq_dev_notifier); 6659+ proc_net_remove(IPQ_PROC_FS_NAME); 6660+ 6661+cleanup_ipqnl: 6662+ sock_release(ipqnl->socket); 6663+ down(&ipqnl_sem); 6664+ up(&ipqnl_sem); 6665+ 6666+cleanup_netlink_notifier: 6667+ netlink_unregister_notifier(&ipq_nl_notifier); 6668 return status; 6669 } 6670 6671+static int __init init(void) 6672+{ 6673+ 6674+ return init_or_cleanup(1); 6675+} 6676+ 6677 static void __exit fini(void) 6678 { 6679- unregister_sysctl_table(ip6q_sysctl_header); 6680- proc_net_remove(IPQ_PROC_FS_NAME); 6681- unregister_netdevice_notifier(&ip6q_dev_notifier); 6682- ip6q_destroy_queue(nlq6); 6683- sock_release(nfnl->socket); 6684+ init_or_cleanup(0); 6685 } 6686 6687 MODULE_DESCRIPTION("IPv6 packet queue handler"); 6688diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/ip6_tables.c linux-2.4.20-plain/net/ipv6/netfilter/ip6_tables.c 6689--- linux-2.4.19-plain/net/ipv6/netfilter/ip6_tables.c Sat Aug 3 02:39:46 2002 6690+++ linux-2.4.20-plain/net/ipv6/netfilter/ip6_tables.c Fri Nov 29 00:53:15 2002 6691@@ -7,6 +7,8 @@ 6692 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> 6693 * - increase module usage count as soon as we have rules inside 6694 * a table 6695+ * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> 6696+ * - new extension header parser code 6697 */ 6698 #include <linux/config.h> 6699 #include <linux/skbuff.h> 6700@@ -25,6 +27,7 @@ 6701 #include <linux/netfilter_ipv6/ip6_tables.h> 6702 6703 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr)) 6704+#define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr)) 6705 6706 /*#define DEBUG_IP_FIREWALL*/ 6707 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */ 6708@@ -133,43 +136,23 @@ 6709 return 0; 6710 } 6711 6712-/* takes in current header and pointer to the header */ 6713-/* if another header exists, sets hdrptr to the next header 6714- and returns the new header value, else returns 0 */ 6715-static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t *hdrptr) 6716-{ 6717- int i; 6718- u_int8_t hdrlen, nexthdr = 0; 6719- switch(currenthdr){ 6720- case IPPROTO_AH: 6721- /* whoever decided to do the length of AUTH for ipv6 6722- in 32bit units unlike other headers should be beaten... 6723- repeatedly...with a large stick...no, an even LARGER 6724- stick...no, you're still not thinking big enough */ 6725- nexthdr = *hdrptr; 6726- hdrlen = hdrptr[i] * 4 + 8; 6727- hdrptr = hdrptr + hdrlen; 6728- break; 6729- /*stupid rfc2402 */ 6730- case IPPROTO_DSTOPTS: 6731- case IPPROTO_ROUTING: 6732- case IPPROTO_HOPOPTS: 6733- nexthdr = *hdrptr; 6734- hdrlen = hdrptr[1] * 8 + 8; 6735- hdrptr = hdrptr + hdrlen; 6736- break; 6737- case IPPROTO_FRAGMENT: 6738- nexthdr = *hdrptr; 6739- hdrptr = hdrptr + 8; 6740- break; 6741- } 6742- return nexthdr; 6743- 6744+/* Check for an extension */ 6745+int 6746+ip6t_ext_hdr(u8 nexthdr) 6747+{ 6748+ return ( (nexthdr == IPPROTO_HOPOPTS) || 6749+ (nexthdr == IPPROTO_ROUTING) || 6750+ (nexthdr == IPPROTO_FRAGMENT) || 6751+ (nexthdr == IPPROTO_ESP) || 6752+ (nexthdr == IPPROTO_AH) || 6753+ (nexthdr == IPPROTO_NONE) || 6754+ (nexthdr == IPPROTO_DSTOPTS) ); 6755 } 6756 6757 /* Returns whether matches rule or not. */ 6758 static inline int 6759-ip6_packet_match(const struct ipv6hdr *ipv6, 6760+ip6_packet_match(const struct sk_buff *skb, 6761+ const struct ipv6hdr *ipv6, 6762 const char *indev, 6763 const char *outdev, 6764 const struct ip6t_ip6 *ip6info, 6765@@ -227,17 +210,58 @@ 6766 /* look for the desired protocol header */ 6767 if((ip6info->flags & IP6T_F_PROTO)) { 6768 u_int8_t currenthdr = ipv6->nexthdr; 6769- u_int8_t *hdrptr; 6770- hdrptr = (u_int8_t *)(ipv6 + 1); 6771- do { 6772- if (ip6info->proto == currenthdr) { 6773- if(ip6info->invflags & IP6T_INV_PROTO) 6774- return 0; 6775- return 1; 6776+ struct ipv6_opt_hdr *hdrptr; 6777+ u_int16_t ptr; /* Header offset in skb */ 6778+ u_int16_t hdrlen; /* Header */ 6779+ 6780+ ptr = IPV6_HDR_LEN; 6781+ 6782+ while (ip6t_ext_hdr(currenthdr)) { 6783+ /* Is there enough space for the next ext header? */ 6784+ if (skb->len - ptr < IPV6_OPTHDR_LEN) 6785+ return 0; 6786+ 6787+ /* NONE or ESP: there isn't protocol part */ 6788+ /* If we want to count these packets in '-p all', 6789+ * we will change the return 0 to 1*/ 6790+ if ((currenthdr == IPPROTO_NONE) || 6791+ (currenthdr == IPPROTO_ESP)) 6792+ return 0; 6793+ 6794+ hdrptr = (struct ipv6_opt_hdr *)(skb->data + ptr); 6795+ 6796+ /* Size calculation */ 6797+ if (currenthdr == IPPROTO_FRAGMENT) { 6798+ hdrlen = 8; 6799+ } else if (currenthdr == IPPROTO_AH) 6800+ hdrlen = (hdrptr->hdrlen+2)<<2; 6801+ else 6802+ hdrlen = ipv6_optlen(hdrptr); 6803+ 6804+ currenthdr = hdrptr->nexthdr; 6805+ ptr += hdrlen; 6806+ /* ptr is too large */ 6807+ if ( ptr > skb->len ) 6808+ return 0; 6809+ } 6810+ 6811+ /* currenthdr contains the protocol header */ 6812+ 6813+ dprintf("Packet protocol %hi ?= %s%hi.\n", 6814+ currenthdr, 6815+ ip6info->invflags & IP6T_INV_PROTO ? "!":"", 6816+ ip6info->proto); 6817+ 6818+ if (ip6info->proto == currenthdr) { 6819+ if(ip6info->invflags & IP6T_INV_PROTO) { 6820+ return 0; 6821 } 6822- currenthdr = ip6_nexthdr(currenthdr, hdrptr); 6823- } while(currenthdr); 6824- if (!(ip6info->invflags & IP6T_INV_PROTO)) 6825+ return 1; 6826+ } 6827+ 6828+ /* We need match for the '-p all', too! */ 6829+ if ((ip6info->proto != 0) && 6830+ !(ip6info->invflags & IP6T_INV_PROTO)) 6831 return 0; 6832 } 6833 return 1; 6834@@ -360,7 +384,8 @@ 6835 IP_NF_ASSERT(e); 6836 IP_NF_ASSERT(back); 6837 (*pskb)->nfcache |= e->nfcache; 6838- if (ip6_packet_match(ipv6, indev, outdev, &e->ipv6, offset)) { 6839+ if (ip6_packet_match(*pskb, ipv6, indev, outdev, 6840+ &e->ipv6, offset)) { 6841 struct ip6t_entry_target *t; 6842 6843 if (IP6T_MATCH_ITERATE(e, do_match, 6844@@ -743,7 +768,7 @@ 6845 t = ip6t_get_target(e); 6846 target = find_target_lock(t->u.user.name, &ret, &ip6t_mutex); 6847 if (!target) { 6848- // duprintf("check_entry: `%s' not found\n", t->u.name); 6849+ duprintf("check_entry: `%s' not found\n", t->u.user.name); 6850 goto cleanup_matches; 6851 } 6852 if (target->me) 6853@@ -1469,6 +1494,9 @@ 6854 duprintf("table->private->number = %u\n", 6855 table->private->number); 6856 6857+ /* save number of initial entries */ 6858+ table->private->initial_entries = table->private->number; 6859+ 6860 table->lock = RW_LOCK_UNLOCKED; 6861 list_prepend(&ip6t_tables, table); 6862 6863@@ -1827,6 +1855,7 @@ 6864 EXPORT_SYMBOL(ip6t_unregister_match); 6865 EXPORT_SYMBOL(ip6t_register_target); 6866 EXPORT_SYMBOL(ip6t_unregister_target); 6867+EXPORT_SYMBOL(ip6t_ext_hdr); 6868 6869 module_init(init); 6870 module_exit(fini); 6871diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.20-plain/net/ipv6/netfilter/ip6t_LOG.c 6872--- linux-2.4.19-plain/net/ipv6/netfilter/ip6t_LOG.c Mon Nov 5 18:53:07 2001 6873+++ linux-2.4.20-plain/net/ipv6/netfilter/ip6t_LOG.c Fri Nov 29 00:53:15 2002 6874@@ -112,7 +112,7 @@ 6875 printk("FRAG:%u ", ntohs(fhdr->frag_off) & 0xFFF8); 6876 6877 /* Max length: 11 "INCOMPLETE " */ 6878- if (fhdr->frag_off & __constant_htons(0x0001)) 6879+ if (fhdr->frag_off & htons(0x0001)) 6880 printk("INCOMPLETE "); 6881 6882 printk("ID:%08x ", fhdr->identification); 6883@@ -289,12 +289,39 @@ 6884 /* MAC logging for input chain only. */ 6885 printk("MAC="); 6886 if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) { 6887- int i; 6888- unsigned char *p = (*pskb)->mac.raw; 6889- for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++) 6890+ if ((*pskb)->dev->type != ARPHRD_SIT){ 6891+ int i; 6892+ unsigned char *p = (*pskb)->mac.raw; 6893+ for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++) 6894 printk("%02x%c", *p, 6895- i==(*pskb)->dev->hard_header_len - 1 6896- ? ' ':':'); 6897+ i==(*pskb)->dev->hard_header_len - 1 6898+ ? ' ':':'); 6899+ } else { 6900+ int i; 6901+ unsigned char *p = (*pskb)->mac.raw; 6902+ if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){ 6903+ p -= (ETH_ALEN+2); 6904+ for (i = 0; i < (ETH_ALEN); i++,p++) 6905+ printk("%02x%s", *p, 6906+ i == ETH_ALEN-1 ? "->" : ":"); 6907+ p -= (ETH_ALEN*2); 6908+ for (i = 0; i < (ETH_ALEN); i++,p++) 6909+ printk("%02x%c", *p, 6910+ i == ETH_ALEN-1 ? ' ' : ':'); 6911+ } 6912+ 6913+ if (((*pskb)->dev->addr_len == 4) && 6914+ (*pskb)->dev->hard_header_len > 20){ 6915+ printk("TUNNEL="); 6916+ p = (*pskb)->mac.raw + 12; 6917+ for (i = 0; i < 4; i++,p++) 6918+ printk("%3d%s", *p, 6919+ i == 3 ? "->" : "."); 6920+ for (i = 0; i < 4; i++,p++) 6921+ printk("%3d%c", *p, 6922+ i == 3 ? ' ' : '.'); 6923+ } 6924+ } 6925 } else 6926 printk(" "); 6927 } 6928diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/ip6t_eui64.c linux-2.4.20-plain/net/ipv6/netfilter/ip6t_eui64.c 6929--- linux-2.4.19-plain/net/ipv6/netfilter/ip6t_eui64.c Thu Jan 1 01:00:00 1970 6930+++ linux-2.4.20-plain/net/ipv6/netfilter/ip6t_eui64.c Fri Nov 29 00:53:15 2002 6931@@ -0,0 +1,89 @@ 6932+/* Kernel module to match EUI64 address parameters. */ 6933+#include <linux/module.h> 6934+#include <linux/skbuff.h> 6935+#include <linux/ipv6.h> 6936+#include <linux/if_ether.h> 6937+ 6938+#include <linux/netfilter_ipv6/ip6_tables.h> 6939+ 6940+static int 6941+match(const struct sk_buff *skb, 6942+ const struct net_device *in, 6943+ const struct net_device *out, 6944+ const void *matchinfo, 6945+ int offset, 6946+ const void *hdr, 6947+ u_int16_t datalen, 6948+ int *hotdrop) 6949+{ 6950+ 6951+ unsigned char eui64[8]; 6952+ int i=0; 6953+ 6954+ if ( !(skb->mac.raw >= skb->head 6955+ && (skb->mac.raw + ETH_HLEN) <= skb->data) 6956+ && offset != 0) { 6957+ *hotdrop = 1; 6958+ return 0; 6959+ } 6960+ 6961+ memset(eui64, 0, sizeof(eui64)); 6962+ 6963+ if (skb->mac.ethernet->h_proto == ntohs(ETH_P_IPV6)) { 6964+ if (skb->nh.ipv6h->version == 0x6) { 6965+ memcpy(eui64, skb->mac.ethernet->h_source, 3); 6966+ memcpy(eui64 + 5, skb->mac.ethernet->h_source + 3, 3); 6967+ eui64[3]=0xff; 6968+ eui64[4]=0xfe; 6969+ eui64[0] |= 0x02; 6970+ 6971+ i=0; 6972+ while ((skb->nh.ipv6h->saddr.in6_u.u6_addr8[8+i] == 6973+ eui64[i]) && (i<8)) i++; 6974+ 6975+ if ( i == 8 ) 6976+ return 1; 6977+ } 6978+ } 6979+ 6980+ return 0; 6981+} 6982+ 6983+static int 6984+ip6t_eui64_checkentry(const char *tablename, 6985+ const struct ip6t_ip6 *ip, 6986+ void *matchinfo, 6987+ unsigned int matchsize, 6988+ unsigned int hook_mask) 6989+{ 6990+ if (hook_mask 6991+ & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) | 6992+ (1 << NF_IP6_PRE_ROUTING) )) { 6993+ printk("ip6t_eui64: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); 6994+ return 0; 6995+ } 6996+ 6997+ if (matchsize != IP6T_ALIGN(sizeof(int))) 6998+ return 0; 6999+ 7000+ return 1; 7001+} 7002+ 7003+static struct ip6t_match eui64_match 7004+= { { NULL, NULL }, "eui64", &match, &ip6t_eui64_checkentry, NULL, THIS_MODULE }; 7005+ 7006+static int __init init(void) 7007+{ 7008+ return ip6t_register_match(&eui64_match); 7009+} 7010+ 7011+static void __exit fini(void) 7012+{ 7013+ ip6t_unregister_match(&eui64_match); 7014+} 7015+ 7016+module_init(init); 7017+module_exit(fini); 7018+MODULE_DESCRIPTION("IPv6 EUI64 address checking match"); 7019+MODULE_LICENSE("GPL"); 7020+MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); 7021diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude *.orig --exclude *.rej --exclude *~ linux-2.4.19-plain/net/ipv6/netfilter/ip6t_length.c linux-2.4.20-plain/net/ipv6/netfilter/ip6t_length.c 7022--- linux-2.4.19-plain/net/ipv6/netfilter/ip6t_length.c Thu Jan 1 01:00:00 1970 7023+++ linux-2.4.20-plain/net/ipv6/netfilter/ip6t_length.c Fri Nov 29 00:53:15 2002 7024@@ -0,0 +1,51 @@ 7025+/* Length Match - IPv6 Port */ 7026+ 7027+#include <linux/module.h> 7028+#include <linux/skbuff.h> 7029+#include <linux/netfilter_ipv6/ip6t_length.h> 7030+#include <linux/netfilter_ipv6/ip6_tables.h> 7031+ 7032+static int 7033+match(const struct sk_buff *skb, 7034+ const struct net_device *in, 7035+ const struct net_device *out, 7036+ const void *matchinfo, 7037+ int offset, 7038+ const void *hdr, 7039+ u_int16_t datalen, 7040+ int *hotdrop) 7041+{ 7042+ const struct ip6t_length_info *info = matchinfo; 7043+ u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); 7044+ 7045+ return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; 7046+} 7047+ 7048+static int 7049+checkentry(const char *tablename, 7050+ const struct ip6t_ip6 *ip, 7051+ void *matchinfo, 7052+ unsigned int matchsize, 7053+ unsigned int hook_mask) 7054+{ 7055+ if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info))) 7056+ return 0; 7057+ 7058+ return 1; 7059+} 7060+ 7061+static struct ip6t_match length_match 7062+= { { NULL, NULL }, "length", &match, &checkentry, NULL, THIS_MODULE }; 7063+ 7064+static int __init init(void) 7065+{ 7066+ return ip6t_register_match(&length_match); 7067+} 7068+ 7069+static void __exit fini(void) 7070+{ 7071+ ip6t_unregister_match(&length_match); 7072+} 7073+ 7074+module_init(init); 7075+module_exit(fini); 7076