1diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack.h linux/include/linux/netfilter_ipv4/ip_conntrack.h 2--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack.h Fri Apr 27 14:15:01 2001 3+++ linux/include/linux/netfilter_ipv4/ip_conntrack.h Fri Jun 1 06:47:50 2001 4@@ -23,8 +23,26 @@ 5 /* >= this indicates reply direction */ 6 IP_CT_IS_REPLY, 7 8- /* Number of distinct IP_CT types (no NEW in reply dirn). */ 9- IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 10+ /* For ctnetlink only, when connection gets deleted. */ 11+ IP_CT_DELETE, 12+ 13+ /* Number of distinct IP_CT types (no NEW in reply dirn, no DELETE). */ 14+ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1 15+}; 16+ 17+/* Bitset representing status of connection. */ 18+enum ip_conntrack_status { 19+ /* It's an expected connection: bit 0 set. This bit never changed */ 20+ IPS_EXPECTED_BIT = 0, 21+ IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), 22+ 23+ /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ 24+ IPS_SEEN_REPLY_BIT = 1, 25+ IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), 26+ 27+ /* Conntrack should never be early-expired. */ 28+ IPS_ASSURED_BIT = 2, 29+ IPS_ASSURED = (1 << IPS_ASSURED_BIT), 30 }; 31 32 #ifdef __KERNEL__ 33@@ -47,21 +65,6 @@ 34 #define IP_NF_ASSERT(x) 35 #endif 36 37-/* Bitset representing status of connection. */ 38-enum ip_conntrack_status { 39- /* It's an expected connection: bit 0 set. This bit never changed */ 40- IPS_EXPECTED_BIT = 0, 41- IPS_EXPECTED = (1 << IPS_EXPECTED_BIT), 42- 43- /* We've seen packets both ways: bit 1 set. Can be set, not unset. */ 44- IPS_SEEN_REPLY_BIT = 1, 45- IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT), 46- 47- /* Conntrack should never be early-expired. */ 48- IPS_ASSURED_BIT = 2, 49- IPS_ASSURED = (1 << IPS_ASSURED_BIT), 50-}; 51- 52 struct ip_conntrack_expect 53 { 54 /* Internal linked list */ 55@@ -163,9 +166,24 @@ 56 extern void ip_ct_refresh(struct ip_conntrack *ct, 57 unsigned long extra_jiffies); 58 59-/* These are for NAT. Icky. */ 60-/* Call me when a conntrack is destroyed. */ 61-extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); 62+/* This is for the ip_conntrack_notify facilities. */ 63+struct ip_conntrack_notify 64+{ 65+ /* Internal use. */ 66+ struct list_head list; 67+ 68+ void (*destroyed)(struct ip_conntrack *conntrack); 69+ void (*created)(struct ip_conntrack *conntrack, 70+ enum ip_conntrack_info info, 71+ const struct net_device *in, 72+ const struct net_device *out); 73+}; 74+ 75+extern int ip_conntrack_notify_register(struct ip_conntrack_notify *nb); 76+extern int ip_conntrack_notify_unregister(struct ip_conntrack_notify *nb); 77+ 78+/* For ctnetlink. */ 79+extern void ip_conntrack_put(struct ip_conntrack *ct); 80 81 /* Returns new sk_buff, or NULL */ 82 struct sk_buff * 83diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_core.h linux/include/linux/netfilter_ipv4/ip_conntrack_core.h 84--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_core.h Fri Apr 27 14:15:01 2001 85+++ linux/include/linux/netfilter_ipv4/ip_conntrack_core.h Fri Jun 1 06:47:50 2001 86@@ -29,7 +29,7 @@ 87 struct ip_conntrack_protocol *protocol); 88 89 /* Find a connection corresponding to a tuple. */ 90-struct ip_conntrack_tuple_hash * 91+extern struct ip_conntrack_tuple_hash * 92 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple, 93 const struct ip_conntrack *ignored_conntrack); 94 95@@ -44,6 +44,7 @@ 96 return NF_ACCEPT; 97 } 98 99+extern unsigned int ip_conntrack_htable_size; 100 extern struct list_head *ip_conntrack_hash; 101 extern struct list_head expect_list; 102 DECLARE_RWLOCK_EXTERN(ip_conntrack_lock); 103diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_ftp.h linux/include/linux/netfilter_ipv4/ip_conntrack_ftp.h 104--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_ftp.h Wed Apr 25 15:00:28 2001 105+++ linux/include/linux/netfilter_ipv4/ip_conntrack_ftp.h Fri Jun 1 06:47:50 2001 106@@ -2,15 +2,6 @@ 107 #define _IP_CONNTRACK_FTP_H 108 /* FTP tracking. */ 109 110-#ifndef __KERNEL__ 111-#error Only in kernel. 112-#endif 113- 114-#include <linux/netfilter_ipv4/lockhelp.h> 115- 116-/* Protects ftp part of conntracks */ 117-DECLARE_LOCK_EXTERN(ip_ftp_lock); 118- 119 enum ip_ct_ftp_type 120 { 121 /* PORT command from client */ 122@@ -41,4 +32,10 @@ 123 int seq_aft_nl_set[IP_CT_DIR_MAX]; 124 }; 125 126+#ifdef __KERNEL__ 127+#include <linux/netfilter_ipv4/lockhelp.h> 128+ 129+/* Protects ftp part of conntracks */ 130+DECLARE_LOCK_EXTERN(ip_ftp_lock); 131+#endif /* __KERNEL__ */ 132 #endif /* _IP_CONNTRACK_FTP_H */ 133diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_netlink.h linux/include/linux/netfilter_ipv4/ip_conntrack_netlink.h 134--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_netlink.h Wed Dec 31 16:00:00 1969 135+++ linux/include/linux/netfilter_ipv4/ip_conntrack_netlink.h Fri Jun 1 05:55:25 2001 136@@ -0,0 +1,119 @@ 137+#ifndef _IP_CONNTRACK_NETLINK_H 138+#define _IP_CONNTRACK_NETLINK_H 139+ 140+/* ip_conntrack_netlink.h: structures and definitions for ctnetlink. 141+ */ 142+ 143+/* ctnetlink message types. 144+ */ 145+#define CTM_BASE 0x10 146+#define CTM_GETCONNTRACK (CTM_BASE + 0) 147+#define CTM_DELCONNTRACK (CTM_BASE + 1) 148+#define CTM_NEWCONNTRACK (CTM_BASE + 2) 149+#define CTM_MAX (CTM_BASE + 3) 150+ 151+/* ctnetlink attribute types. 152+ */ 153+enum ctattr_type_t 154+{ 155+ CTA_UNSPEC, /* [none] I don't know (unspecified). */ 156+ CTA_ORIG, /* [ip_conntrack_tuple] Original tuple. */ 157+ CTA_RPLY, /* [ip_conntrack_tuple] Reply tuple. */ 158+ CTA_IIF, /* [char] Input interface name (ie eth0). */ 159+ CTA_OIF, /* [char] Output interface name (ie eth1). */ 160+ CTA_STATUS, /* [unsigned long] Status of connection. */ 161+ CTA_INFO, /* [unsigned long] Information (ctinfo). */ 162+ CTA_PROTOINFO, /* [rta_proto] Protocol specific ct information. */ 163+ CTA_HELPINFO, /* [rta_help] Helper specific information. */ 164+ CTA_NATINFO, /* [rta_nat] Any NAT transformations. */ 165+ CTA_MAX = CTA_NATINFO 166+}; 167+ 168+/* Generic structure for encapsulation optional conntrack information. 169+ * It is reminiscent of sockaddr, but with sa_family replaced 170+ * with attribute type. 171+ * ! This should someday be put somewhere generic as now rtnetlink and 172+ * ! ctnetlink use the same attributes methods. - JSchulist. 173+ */ 174+ 175+struct ctattr 176+{ 177+ unsigned short cta_len; 178+ unsigned short cta_type; 179+}; 180+ 181+#define CTA_ALIGNTO 4 182+#define CTA_ALIGN(len) (((len) + CTA_ALIGNTO - 1) & ~(CTA_ALIGNTO - 1)) 183+#define CTA_OK(cta,len) ((len) > 0 && (cta)->cta_len >= sizeof(struct ctattr) \ 184+ && (cta)->cta_len <= (len)) 185+#define CTA_NEXT(cta,attrlen) ((attrlen) -= CTA_ALIGN((cta)->cta_len), \ 186+ (struct ctattr *)(((char *)(cta)) + CTA_ALIGN((cta)->cta_len))) 187+#define CTA_LENGTH(len) (CTA_ALIGN(sizeof(struct ctattr)) + (len)) 188+#define CTA_SPACE(len) CTA_ALIGN(CTA_LENGTH(len)) 189+#define CTA_DATA(cta) ((void *)(((char *)(cta)) + CTA_LENGTH(0))) 190+#define CTA_PAYLOAD(cta) ((int)((cta)->cta_len) - CTA_LENGTH(0)) 191+ 192+/* Generic ctnetlink message header. 193+ */ 194+struct ctmsg { 195+ unsigned char ctm_family; 196+ unsigned char ctm_orig_len; 197+ unsigned char ctm_rply_len; 198+}; 199+ 200+#define CTM_CTA(c) ((struct ctattr *)(((char *)(c)) \ 201+ + NLMSG_ALIGN(sizeof(struct ctmsg)))) 202+#define CTM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct ctmsg)) 203+ 204+/* General form of address family dependent message. 205+ */ 206+struct ctgenmsg { 207+ unsigned char ctgen_family; 208+}; 209+ 210+/* Attribute specific data structures. 211+ */ 212+ 213+#ifdef CONFIG_IP_NF_NAT_NEEDED 214+struct cta_nat { 215+ unsigned int num_manips; 216+ struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS]; 217+}; 218+#endif /* CONFIG_IP_NF_NAT_NEEDED */ 219+ 220+struct cta_proto { 221+ unsigned char num_proto; /* Protocol number IPPROTO_X */ 222+ union { 223+ struct ip_ct_tcp tcp; 224+ struct ip_ct_icmp icmp; 225+ } proto; 226+}; 227+ 228+struct cta_help { 229+ struct ip_conntrack_tuple tuple; 230+ struct ip_conntrack_tuple mask; 231+ 232+ union { 233+ struct ip_ct_ftp ct_ftp_info; 234+ } help; 235+}; 236+ 237+/* ctnetlink multicast groups: reports any change of ctinfo, 238+ * ctstatus, or protocol state change. 239+ */ 240+#define CTGRP_IPV4_CT_TCP 0x01 241+#define CTGRP_IPV4_CT_UDP 0x02 242+#define CTGRP_IPV4_CT_ICMP 0x04 243+ 244+#define CTGRP_IPV6_CT_TCP 0x10 245+#define CTGRP_IPV6_CT_UDP 0x20 246+#define CTGRP_IPV6_CT_ICMP 0x40 247+ 248+#ifdef __KERNEL__ 249+extern void __cta_fill(struct sk_buff *skb, int attrtype, 250+ int attrlen, const void *data); 251+#define CTA_PUT(skb, attrtype, attrlen, data) \ 252+({ if (skb_tailroom(skb) < (int)CTA_SPACE(attrlen)) goto ctattr_failure; \ 253+ __cta_fill(skb, attrtype, attrlen, data); }) 254+#endif /* __KERNEL__ */ 255+#endif /* _IP_CONNTRACK_NETLINK_H */ 256diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 257--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_protocol.h Fri Apr 27 14:15:01 2001 258+++ linux/include/linux/netfilter_ipv4/ip_conntrack_protocol.h Fri Jun 1 06:47:50 2001 259@@ -35,7 +35,7 @@ 260 /* Returns verdict for packet, or -1 for invalid. */ 261 int (*packet)(struct ip_conntrack *conntrack, 262 struct iphdr *iph, size_t len, 263- enum ip_conntrack_info ctinfo); 264+ enum ip_conntrack_info ctinfo, int *set_notify); 265 266 /* Called when a new connection for this protocol found; 267 * returns TRUE if it's OK. If so, packet() called next. */ 268diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_tcp.h linux/include/linux/netfilter_ipv4/ip_conntrack_tcp.h 269--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_tcp.h Fri Aug 4 13:07:24 2000 270+++ linux/include/linux/netfilter_ipv4/ip_conntrack_tcp.h Fri Jun 1 00:31:00 2001 271@@ -2,10 +2,6 @@ 272 #define _IP_CONNTRACK_TCP_H 273 /* TCP tracking. */ 274 275-#ifndef __KERNEL__ 276-#error Only in kernel. 277-#endif 278- 279 enum tcp_conntrack { 280 TCP_CONNTRACK_NONE, 281 TCP_CONNTRACK_ESTABLISHED, 282diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 283--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_conntrack_tuple.h Thu Aug 10 12:35:15 2000 284+++ linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h Fri Jun 1 00:31:00 2001 285@@ -62,8 +62,6 @@ 286 } dst; 287 }; 288 289-#ifdef __KERNEL__ 290- 291 #define DUMP_TUPLE(tp) \ 292 DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \ 293 (tp), (tp)->dst.protonum, \ 294@@ -114,6 +112,8 @@ 295 || ((t->dst.protonum ^ tuple->dst.protonum) 296 & mask->dst.protonum)); 297 } 298+ 299+#ifdef __KERNEL__ 300 301 /* Connections have two entries in the hash table: one for each way */ 302 struct ip_conntrack_tuple_hash 303diff -ruN linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_nat.h linux/include/linux/netfilter_ipv4/ip_nat.h 304--- linux-2.4.5-ac5/include/linux/netfilter_ipv4/ip_nat.h Wed Apr 25 15:00:28 2001 305+++ linux/include/linux/netfilter_ipv4/ip_nat.h Fri Jun 1 06:47:50 2001 306@@ -55,22 +55,6 @@ 307 struct ip_nat_range range[1]; 308 }; 309 310-#ifdef __KERNEL__ 311-#include <linux/list.h> 312-#include <linux/netfilter_ipv4/lockhelp.h> 313- 314-/* Protects NAT hash tables, and NAT-private part of conntracks. */ 315-DECLARE_RWLOCK_EXTERN(ip_nat_lock); 316- 317-/* Hashes for by-source and IP/protocol. */ 318-struct ip_nat_hash 319-{ 320- struct list_head list; 321- 322- /* conntrack we're embedded in: NULL if not in hash. */ 323- struct ip_conntrack *conntrack; 324-}; 325- 326 /* Worst case: local-out manip + 1 post-routing, and reverse dirn. */ 327 #define IP_NAT_MAX_MANIPS (2*3) 328 329@@ -88,6 +72,19 @@ 330 /* Manipulations to occur at each conntrack in this dirn. */ 331 struct ip_conntrack_manip manip; 332 }; 333+ 334+#ifdef __KERNEL__ 335+#include <linux/netfilter_ipv4/lockhelp.h> 336+#include <linux/list.h> 337+ 338+/* Hashes for by-source and IP/protocol. */ 339+struct ip_nat_hash 340+{ 341+ struct list_head list; 342+ 343+ /* conntrack we're embedded in: NULL if not in hash. */ 344+ struct ip_conntrack *conntrack; 345+}; 346 347 /* The structure embedded in the conntrack structure. */ 348 struct ip_nat_info 349@@ -110,6 +107,9 @@ 350 351 struct ip_nat_seq seq[IP_CT_DIR_MAX]; 352 }; 353+ 354+/* Protects NAT hash tables, and NAT-private part of conntracks. */ 355+DECLARE_RWLOCK_EXTERN(ip_nat_lock); 356 357 /* Set up the info structure to map into this range. */ 358 extern unsigned int ip_nat_setup_info(struct ip_conntrack *conntrack, 359diff -ruN linux-2.4.5-ac5/include/linux/netlink.h linux/include/linux/netlink.h 360--- linux-2.4.5-ac5/include/linux/netlink.h Sun Nov 12 20:37:17 2000 361+++ linux/include/linux/netlink.h Fri Jun 1 00:31:00 2001 362@@ -5,6 +5,7 @@ 363 #define NETLINK_SKIP 1 /* Reserved for ENskip */ 364 #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ 365 #define NETLINK_FIREWALL 3 /* Firewalling hook */ 366+#define NETLINK_CONNTRACK 5 /* Netfilter connection tracking */ 367 #define NETLINK_ARPD 8 368 #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ 369 #define NETLINK_IP6_FW 13 370diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_core.c linux/net/ipv4/netfilter/ip_conntrack_core.c 371--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_core.c Fri Apr 27 14:15:01 2001 372+++ linux/net/ipv4/netfilter/ip_conntrack_core.c Fri Jun 1 00:31:00 2001 373@@ -45,10 +45,10 @@ 374 375 DECLARE_RWLOCK(ip_conntrack_lock); 376 377-void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL; 378 LIST_HEAD(expect_list); 379 LIST_HEAD(protocol_list); 380 static LIST_HEAD(helpers); 381+static LIST_HEAD(notify_list); 382 unsigned int ip_conntrack_htable_size = 0; 383 static int ip_conntrack_max = 0; 384 static atomic_t ip_conntrack_count = ATOMIC_INIT(0); 385@@ -86,7 +86,7 @@ 386 return p; 387 } 388 389-static inline void ip_conntrack_put(struct ip_conntrack *ct) 390+inline void ip_conntrack_put(struct ip_conntrack *ct) 391 { 392 IP_NF_ASSERT(ct); 393 IP_NF_ASSERT(ct->infos[0].master); 394@@ -150,6 +150,55 @@ 395 return protocol->invert_tuple(inverse, orig); 396 } 397 398+static inline void 399+ip_conntrack_destroyed(struct ip_conntrack *ct) 400+{ 401+ struct list_head *i; 402+ 403+ for (i = notify_list.next; i != ¬ify_list; i = i->next) 404+ if (((struct ip_conntrack_notify *)i)->destroyed) 405+ ((struct ip_conntrack_notify *)i)->destroyed(ct); 406+ return; 407+} 408+ 409+static inline void 410+ip_conntrack_created(struct ip_conntrack *ct, 411+ enum ip_conntrack_info info, const struct net_device *in, 412+ const struct net_device *out) 413+{ 414+ struct list_head *i; 415+ 416+ for (i = notify_list.next; i != ¬ify_list; i = i->next) 417+ if (((struct ip_conntrack_notify *)i)->created) 418+ ((struct ip_conntrack_notify *)i)->created(ct, 419+ info, in, out); 420+ return; 421+} 422+ 423+int 424+ip_conntrack_notify_register(struct ip_conntrack_notify *nb) 425+{ 426+ MOD_INC_USE_COUNT; 427+ 428+ WRITE_LOCK(&ip_conntrack_lock); 429+ list_prepend(¬ify_list, nb); 430+ WRITE_UNLOCK(&ip_conntrack_lock); 431+ 432+ return 0; 433+} 434+ 435+int 436+ip_conntrack_notify_unregister(struct ip_conntrack_notify *nb) 437+{ 438+ WRITE_LOCK(&ip_conntrack_lock); 439+ LIST_DELETE(¬ify_list, nb); 440+ WRITE_UNLOCK(&ip_conntrack_lock); 441+ 442+ MOD_DEC_USE_COUNT; 443+ 444+ return 0; 445+} 446+ 447 static void 448 clean_from_lists(struct ip_conntrack *ct) 449 { 450@@ -182,8 +231,7 @@ 451 if (ct->master.master) 452 nf_conntrack_put(&ct->master); 453 454- if (ip_conntrack_destroyed) 455- ip_conntrack_destroyed(ct); 456+ ip_conntrack_destroyed(ct); 457 kmem_cache_free(ip_conntrack_cachep, ct); 458 atomic_dec(&ip_conntrack_count); 459 } 460@@ -570,7 +618,7 @@ 461 static inline struct ip_conntrack * 462 resolve_normal_ct(struct sk_buff *skb, 463 struct ip_conntrack_protocol *proto, 464- int *set_reply, 465+ int *set_reply, int *set_notify, 466 unsigned int hooknum, 467 enum ip_conntrack_info *ctinfo) 468 { 469@@ -611,6 +659,7 @@ 470 DEBUGP("ip_conntrack_in: new packet for %p\n", 471 h->ctrack); 472 *ctinfo = IP_CT_NEW; 473+ *set_notify = 1; 474 } 475 *set_reply = 0; 476 } 477@@ -628,7 +677,7 @@ 478 struct ip_conntrack *ct; 479 enum ip_conntrack_info ctinfo; 480 struct ip_conntrack_protocol *proto; 481- int set_reply; 482+ int set_reply, set_notify = 0; 483 int ret; 484 485@@ -668,7 +717,8 @@ 486 && icmp_error_track(*pskb, &ctinfo, hooknum)) 487 return NF_ACCEPT; 488 489- if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) 490+ if (!(ct = resolve_normal_ct(*pskb, proto, &set_reply, &set_notify, 491+ hooknum,&ctinfo))) 492 /* Not valid part of a connection */ 493 return NF_ACCEPT; 494 495@@ -678,7 +728,8 @@ 496 497 IP_NF_ASSERT((*pskb)->nfct); 498 499- ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo); 500+ ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo, 501+ &set_notify); 502 if (ret == -1) { 503 /* Invalid */ 504 nf_conntrack_put((*pskb)->nfct); 505@@ -698,7 +749,8 @@ 506 } 507 if (set_reply) 508 set_bit(IPS_SEEN_REPLY_BIT, &ct->status); 509- 510+ if (set_notify) 511+ ip_conntrack_created(ct, ctinfo, in, out); 512 return ret; 513 } 514 515@@ -1050,6 +1102,7 @@ 516 #ifdef CONFIG_SYSCTL 517 unregister_sysctl_table(ip_conntrack_sysctl_header); 518 #endif 519+ 520 ip_ct_attach = NULL; 521 /* This makes sure all current packets have passed through 522 netfilter framework. Roll on, two-stage module 523diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_netlink.c linux/net/ipv4/netfilter/ip_conntrack_netlink.c 524--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_netlink.c Wed Dec 31 16:00:00 1969 525+++ linux/net/ipv4/netfilter/ip_conntrack_netlink.c Fri Jun 1 00:31:00 2001 526@@ -0,0 +1,523 @@ 527+/* Connection tracking via netlink socket. Allows for user space 528+ * protocol helpers and general trouble making from userspace. 529+ * 530+ * Jay Schulist <jschlst@samba.org>, Copyright (c) 2001. 531+ * 532+ * Initial connection tracking via netlink development funded and 533+ * generally made possible by Network Robots, Inc. (www.networkrobots.com) 534+ * 535+ * This software may be used and distributed according to the terms 536+ * of the GNU General Public License, incorporated herein by reference. 537+ */ 538+ 539+#include <linux/config.h> 540+#include <linux/module.h> 541+#include <linux/types.h> 542+#include <linux/socket.h> 543+#include <linux/kernel.h> 544+#include <linux/major.h> 545+#include <linux/sched.h> 546+#include <linux/timer.h> 547+#include <linux/string.h> 548+#include <linux/sockios.h> 549+#include <linux/net.h> 550+#include <linux/fcntl.h> 551+#include <linux/skbuff.h> 552+#include <asm/uaccess.h> 553+#include <asm/system.h> 554+#include <net/sock.h> 555+#include <linux/init.h> 556+#include <linux/netlink.h> 557+#include <linux/spinlock.h> 558+#include <linux/rtnetlink.h> 559+ 560+#include <linux/netfilter_ipv4/ip_conntrack.h> 561+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 562+#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 563+#include <linux/netfilter_ipv4/ip_conntrack_core.h> 564+#include <linux/netfilter_ipv4/ip_conntrack_netlink.h> 565+ 566+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) 567+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock) 568+#include <linux/netfilter_ipv4/listhelp.h> 569+ 570+char ctversion[] = "1.00"; 571+int ct_debug_level = 1; 572+#define ct_debug(level, format, arg...) \ 573+ if(ct_debug_level > level) \ 574+ printk(__FILE__ ": " format, ## arg) 575+ 576+static struct sock *ctnl = NULL; 577+ 578+void __cta_fill(struct sk_buff *skb, int attrtype, int attrlen, 579+ const void *data) 580+{ 581+ struct ctattr *cta; 582+ int size = CTA_LENGTH(attrlen); 583+ 584+ cta = (struct ctattr *)skb_put(skb, CTA_ALIGN(size)); 585+ cta->cta_type = attrtype; 586+ cta->cta_len = size; 587+ memcpy(CTA_DATA(cta), data, attrlen); 588+} 589+ 590+static int ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, 591+ int event, int nowait, const struct ip_conntrack *ct, 592+ const enum ip_conntrack_info *ctinfo, unsigned char proto, 593+ const struct net_device *in, const struct net_device *out) 594+{ 595+ struct nlmsghdr *nlh; 596+ struct ctmsg *msg; 597+ unsigned long s; 598+ unsigned char *b; 599+ 600+ b = skb->tail; 601+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ctmsg)); 602+ msg = NLMSG_DATA(nlh); 603+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0; 604+ msg->ctm_family = AF_INET; 605+ msg->ctm_orig_len = sizeof(struct ip_conntrack_tuple); 606+ msg->ctm_rply_len = sizeof(struct ip_conntrack_tuple); 607+ CTA_PUT(skb, CTA_ORIG, sizeof(struct ip_conntrack_tuple), 608+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 609+ CTA_PUT(skb, CTA_RPLY, sizeof(struct ip_conntrack_tuple), 610+ &ct->tuplehash[IP_CT_DIR_REPLY].tuple); 611+ s = ct->status; 612+ CTA_PUT(skb, CTA_STATUS, sizeof(unsigned long), &s); 613+ if(in) 614+ CTA_PUT(skb, CTA_IIF, IFNAMSIZ, in->name); 615+ if(out) 616+ CTA_PUT(skb, CTA_OIF, IFNAMSIZ, out->name); 617+ if(ctinfo) 618+ CTA_PUT(skb, CTA_INFO, sizeof(unsigned long), ctinfo); 619+#ifdef CONFIG_IP_NF_NAT_NEEDED 620+ if(ct->nat.info.initialized && ct->nat.info.num_manips) 621+ { 622+ const struct ip_nat_info *nat = &ct->nat.info; 623+ struct cta_nat cn; 624+ 625+ cn.num_manips = nat->num_manips; 626+ memcpy(&cn.manips, &nat->manips, (nat->num_manips 627+ * sizeof(struct ip_nat_info_manip))); 628+ CTA_PUT(skb, CTA_NATINFO, sizeof(struct cta_nat), &cn); 629+ } 630+#endif /* CONFIG_IP_NF_NAT_NEEDED */ 631+ if(ct->helper) 632+ { 633+ struct cta_help ch; 634+ 635+ memcpy(&ch.tuple, &ct->helper->tuple, 636+ sizeof(struct ip_conntrack_tuple)); 637+ memcpy(&ch.mask, &ct->helper->mask, 638+ sizeof(struct ip_conntrack_tuple)); 639+ memcpy(&ch.help.ct_ftp_info, &ct->help.ct_ftp_info, 640+ sizeof(struct ip_ct_ftp)); 641+ CTA_PUT(skb, CTA_HELPINFO, sizeof(struct cta_help), &ch); 642+ } 643+ if(proto == IPPROTO_TCP || proto == IPPROTO_UDP 644+ || proto == IPPROTO_ICMP) 645+ { 646+ struct cta_proto cp; 647+ 648+ cp.num_proto = proto; 649+ if(proto == IPPROTO_TCP) 650+ memcpy(&cp.proto.tcp, &ct->proto.tcp, 651+ sizeof(struct ip_ct_tcp)); 652+ if(proto == IPPROTO_ICMP) 653+ memcpy(&cp.proto.icmp, &ct->proto.icmp, 654+ sizeof(struct ip_ct_icmp)); 655+ CTA_PUT(skb, CTA_PROTOINFO, sizeof(struct cta_proto), &cp); 656+ } 657+ 658+ nlh->nlmsg_len = skb->tail - b; 659+ return (skb->len); 660+ 661+nlmsg_failure: 662+ctattr_failure: 663+ skb_trim(skb, b - skb->data); 664+ return (-1); 665+} 666+ 667+static inline void ctnetlink_send(struct sk_buff *skb, u32 pid, unsigned group) 668+{ 669+ NETLINK_CB(skb).dst_groups = group; 670+ netlink_broadcast(ctnl, skb, pid, group, GFP_ATOMIC); 671+ return; 672+} 673+ 674+inline struct sk_buff *ctnetlink_event_build_msg(const struct ip_conntrack *ct, 675+ const enum ip_conntrack_info ctinfo, const unsigned char proto, 676+ const struct net_device *in, const struct net_device *out) 677+{ 678+ struct sk_buff *skb; 679+ int err; 680+ 681+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 682+ if(!skb) 683+ return (NULL); 684+ 685+ err = ctnetlink_fill_info(skb, 0, 0, CTM_NEWCONNTRACK, 1, 686+ ct, &ctinfo, proto, in, out); 687+ if(err <= 0) 688+ goto nlmsg_failure; 689+ return (skb); 690+ 691+nlmsg_failure: 692+ if(skb) 693+ kfree_skb(skb); 694+ return (NULL); 695+} 696+ 697+void ctnetlink_create(struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, 698+ const struct net_device *in, const struct net_device *out) 699+{ 700+ u16 proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; 701+ struct sk_buff *skb; 702+ 703+ skb = ctnetlink_event_build_msg(ct, ctinfo, proto, in, out); 704+ if(!skb) 705+ return; 706+ 707+ if (proto == IPPROTO_TCP) { 708+ ctnetlink_send(skb, 0, CTGRP_IPV4_CT_TCP); 709+ return; 710+ } 711+ if (proto == IPPROTO_UDP) { 712+ ctnetlink_send(skb, 0, CTGRP_IPV4_CT_UDP); 713+ return; 714+ } 715+ if (proto == IPPROTO_ICMP) { 716+ ctnetlink_send(skb, 0, CTGRP_IPV4_CT_ICMP); 717+ return; 718+ } 719+ 720+ kfree_skb(skb); 721+ return; 722+} 723+ 724+void ctnetlink_destroy(struct ip_conntrack *ct) 725+{ 726+ ctnetlink_create(ct, IP_CT_DELETE, NULL, NULL); 727+} 728+ 729+inline int ctnetlink_kill(const struct ip_conntrack *i, void *data) 730+{ 731+ struct ip_conntrack *t = (struct ip_conntrack *)data; 732+ 733+ if(!memcmp(&i->tuplehash[IP_CT_DIR_ORIGINAL], 734+ &t->tuplehash[IP_CT_DIR_ORIGINAL], 735+ sizeof(struct ip_conntrack_tuple_hash))) 736+ { 737+ ip_conntrack_put(t); 738+ return (1); 739+ } 740+ 741+ return (0); 742+} 743+ 744+int ctnetlink_delete_conntrack(struct sk_buff *skb, struct nlmsghdr *nlh, 745+ void *arg) 746+{ 747+ struct ip_conntrack_tuple_hash *h; 748+ struct ip_conntrack_tuple *tuple; 749+ struct ctattr **cda = arg; 750+ 751+ if(cda[CTA_ORIG-1]) 752+ tuple = CTA_DATA(cda[CTA_ORIG-1]); 753+ else 754+ { 755+ if(cda[CTA_RPLY-1]) 756+ tuple = CTA_DATA(cda[CTA_RPLY-1]); 757+ else 758+ return (-EINVAL); 759+ } 760+ 761+ h = ip_conntrack_find_get(tuple, NULL); 762+ if(!h) 763+ return (-ENOENT); 764+ ip_ct_selective_cleanup(ctnetlink_kill, h->ctrack); 765+ 766+ return (0); 767+} 768+ 769+int ctnetlink_get_conntrack(struct sk_buff *skb, struct nlmsghdr *nlh, 770+ void *arg) 771+{ 772+ struct ip_conntrack_tuple_hash *h; 773+ struct ip_conntrack_tuple *tuple; 774+ struct ctattr **cda = arg; 775+ struct ip_conntrack *ct; 776+ struct sk_buff *skb2 = NULL; 777+ int err, proto; 778+ 779+ if(cda[CTA_ORIG-1]) 780+ tuple = CTA_DATA(cda[CTA_ORIG-1]); 781+ else 782+ { 783+ if(cda[CTA_RPLY-1]) 784+ tuple = CTA_DATA(cda[CTA_RPLY-1]); 785+ else 786+ return (-EINVAL); 787+ } 788+ 789+ h = ip_conntrack_find_get(tuple, NULL); 790+ if(!h) 791+ return (-ENOENT); 792+ 793+ ct = h->ctrack; 794+ if(!ct) 795+ goto nlmsg_failure; 796+ 797+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 798+ if(!skb2) 799+ return (-ENOMEM); 800+ NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid; 801+ 802+ proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; 803+ err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 804+ CTM_NEWCONNTRACK, 1, ct, NULL, proto, NULL, NULL); 805+ if(err <= 0) 806+ goto nlmsg_failure; 807+ 808+ err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); 809+ if(err < 0) 810+ return (err); 811+ return (0); 812+ 813+nlmsg_failure: 814+ if(skb2) 815+ kfree_skb(skb2); 816+ return (-1); 817+} 818+ 819+/* Finish me: should support NLM_F_CREATE and NLM_F_REPLACE. */ 820+int ctnetlink_new_conntrack(struct sk_buff *skb, struct nlmsghdr *nlh, 821+ void *arg) 822+{ 823+ return (-EOPNOTSUPP); 824+} 825+ 826+int ctnetlink_done(struct netlink_callback *cb) 827+{ 828+ return (0); 829+} 830+ 831+int ctnetlink_dump_build_msg(const struct ip_conntrack_tuple_hash *hash, 832+ struct sk_buff *skb, u32 pid, u32 seq) 833+{ 834+ struct ip_conntrack *ct; 835+ int err, proto; 836+ 837+ /* Only count originals */ 838+ if (DIRECTION(hash)) 839+ return (0); 840+ 841+ ct = hash->ctrack; 842+ if(!ct) 843+ goto nlmsg_failure; 844+ 845+ proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; 846+ err = ctnetlink_fill_info(skb, pid, seq, CTM_NEWCONNTRACK, 1, 847+ ct, NULL, proto, NULL, NULL); 848+ if(err <= 0) 849+ goto nlmsg_failure; 850+ return (0); 851+ 852+nlmsg_failure: 853+ if(skb) 854+ kfree_skb(skb); 855+ return (-1); 856+} 857+ 858+int ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) 859+{ 860+ int i; 861+ int idx; 862+ int s_idx = cb->args[0]; 863+ 864+ /* Traverse hash; send originals then reply. */ 865+ READ_LOCK(&ip_conntrack_lock); 866+ for(i = 0, idx = 0; i < ip_conntrack_htable_size; i++, idx++) 867+ { 868+ if(idx < s_idx) 869+ continue; 870+ if(LIST_FIND(&ip_conntrack_hash[i], ctnetlink_dump_build_msg, 871+ struct ip_conntrack_tuple_hash *, skb, 872+ NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq)) 873+ continue; 874+ } 875+ READ_UNLOCK(&ip_conntrack_lock); 876+ 877+ cb->args[0] = idx; 878+ return (skb->len); 879+} 880+ 881+/* Process one complete ctlink message. */ 882+static inline int ctnetlink_rcv_msg(struct sk_buff *skb, 883+ struct nlmsghdr *nlh, int *errp) 884+{ 885+ struct ctattr *cta[CTA_MAX]; 886+ int type, min_len, err = 0; 887+ 888+ /* Only requests are handled by kernel now. */ 889+ if(!(nlh->nlmsg_flags & NLM_F_REQUEST)) 890+ return (0); 891+ 892+ /* Unknown message: reply with EINVAL */ 893+ type = nlh->nlmsg_type; 894+ if(type > CTM_MAX) 895+ goto err_inval; 896+ 897+ /* All the messages must have at least 1 byte length */ 898+ if(nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct ctgenmsg))) 899+ return (0); 900+ 901+ if(type == CTM_GETCONNTRACK && nlh->nlmsg_flags & NLM_F_DUMP) 902+ { 903+ struct ctgenmsg *msg = NLMSG_DATA(nlh); 904+ u32 rlen; 905+ 906+ if(msg->ctgen_family != AF_INET) 907+ return (-EAFNOSUPPORT); 908+ 909+ if((*errp = netlink_dump_start(ctnl, skb, nlh, 910+ ctnetlink_dump_table, ctnetlink_done)) != 0) 911+ goto err_inval; 912+ rlen = NLMSG_ALIGN(nlh->nlmsg_len); 913+ if(rlen > skb->len) 914+ rlen = skb->len; 915+ skb_pull(skb, rlen); 916+ goto done; 917+ } 918+ 919+ /* check attribute lengths. */ 920+ min_len = sizeof(struct ctmsg); 921+ if(nlh->nlmsg_len < min_len) 922+ goto err_inval; 923+ 924+ if(nlh->nlmsg_len > min_len) 925+ { 926+ struct ctattr *attr = CTM_CTA(NLMSG_DATA(nlh)); 927+ int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); 928+ 929+ while(CTA_OK(attr, attrlen)) 930+ { 931+ unsigned flavor = attr->cta_type; 932+ if(flavor) 933+ { 934+ if(flavor > RTA_MAX) 935+ goto err_inval; 936+ cta[flavor - 1] = attr; 937+ } 938+ attr = CTA_NEXT(attr, attrlen); 939+ } 940+ } 941+ 942+ switch(type) { 943+ case (CTM_DELCONNTRACK): 944+ err = ctnetlink_delete_conntrack(skb,nlh,(void *)&cta); 945+ break; 946+ 947+ case (CTM_GETCONNTRACK): 948+ err = ctnetlink_get_conntrack(skb,nlh,(void *)&cta); 949+ break; 950+ 951+ case (CTM_NEWCONNTRACK): 952+ ctnetlink_new_conntrack(skb, nlh, (void *)&cta); 953+ break; 954+ 955+ default: 956+ goto err_inval; 957+ } 958+ 959+done: 960+ *errp = err; 961+ return (err); 962+ 963+err_inval: 964+ *errp = -EINVAL; 965+ return (-1); 966+} 967+ 968+/* Process one packet of messages. */ 969+static inline int ctnetlink_rcv_skb(struct sk_buff *skb) 970+{ 971+ int err; 972+ struct nlmsghdr *nlh; 973+ 974+ while(skb->len >= NLMSG_SPACE(0)) 975+ { 976+ u32 rlen; 977+ 978+ nlh = (struct nlmsghdr *)skb->data; 979+ if(nlh->nlmsg_len < sizeof(struct nlmsghdr) 980+ || skb->len < nlh->nlmsg_len) 981+ return (0); 982+ rlen = NLMSG_ALIGN(nlh->nlmsg_len); 983+ if(rlen > skb->len) 984+ rlen = skb->len; 985+ if(ctnetlink_rcv_msg(skb, nlh, &err)) 986+ { 987+ if(err == 0) 988+ return (-1); 989+ netlink_ack(skb, nlh, err); 990+ } 991+ else 992+ if(nlh->nlmsg_flags & NLM_F_ACK) 993+ netlink_ack(skb, nlh, 0); 994+ skb_pull(skb, rlen); 995+ } 996+ 997+ return (0); 998+} 999+ 1000+static void ctnetlink_rcv(struct sock *sk, int len) 1001+{ 1002+ do { 1003+ struct sk_buff *skb; 1004+ 1005+ if(rtnl_shlock_nowait()) 1006+ return; 1007+ 1008+ while((skb = skb_dequeue(&sk->receive_queue)) != NULL) 1009+ { 1010+ if(ctnetlink_rcv_skb(skb)) 1011+ { 1012+ if(skb->len) 1013+ skb_queue_head(&sk->receive_queue, skb); else 1014+ kfree_skb(skb); 1015+ break; 1016+ } 1017+ kfree_skb(skb); 1018+ } 1019+ 1020+ up(&rtnl_sem); 1021+ } while (ctnl && ctnl->receive_queue.qlen); 1022+} 1023+ 1024+static struct ip_conntrack_notify ctnl_notify = { { NULL, NULL }, 1025+ ctnetlink_destroy, 1026+ ctnetlink_create }; 1027+ 1028+void __exit ctnetlink_exit(void) 1029+{ 1030+ printk("CTnetlink: removing netlink socket.\n"); 1031+ ip_conntrack_notify_unregister(&ctnl_notify); 1032+ sock_release(ctnl->socket); 1033+ return; 1034+} 1035+ 1036+int __init ctnetlink_init(void) 1037+{ 1038+ printk("CTnetlink: initializing netlink socket v%s.\n", ctversion); 1039+ ctnl = netlink_kernel_create(NETLINK_CONNTRACK, ctnetlink_rcv); 1040+ if(!ctnl) 1041+ panic("ctnetlink_init: cannot initialize ctnetlink.\n"); 1042+ if(ip_conntrack_notify_register(&ctnl_notify) < 0) 1043+ panic("ctnetlink_init: cannot register notifier.\n"); 1044+ 1045+ return (0); 1046+} 1047+ 1048+module_init(ctnetlink_init); 1049+module_exit(ctnetlink_exit); 1050diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c 1051--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_generic.c Fri Apr 27 14:15:01 2001 1052+++ linux/net/ipv4/netfilter/ip_conntrack_proto_generic.c Fri Jun 1 00:31:00 2001 1053@@ -41,7 +41,7 @@ 1054 /* Returns verdict for packet, or -1 for invalid. */ 1055 static int established(struct ip_conntrack *conntrack, 1056 struct iphdr *iph, size_t len, 1057- enum ip_conntrack_info conntrackinfo) 1058+ enum ip_conntrack_info conntrackinfo, int *set_notify) 1059 { 1060 ip_ct_refresh(conntrack, GENERIC_TIMEOUT); 1061 return NF_ACCEPT; 1062diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 1063--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Fri Apr 27 14:15:01 2001 1064+++ linux/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Fri Jun 1 00:31:00 2001 1065@@ -70,7 +70,7 @@ 1066 /* Returns verdict for packet, or -1 for invalid. */ 1067 static int icmp_packet(struct ip_conntrack *ct, 1068 struct iphdr *iph, size_t len, 1069- enum ip_conntrack_info ctinfo) 1070+ enum ip_conntrack_info ctinfo, int *set_notify) 1071 { 1072 /* Try to delete connection immediately after all replies: 1073 won't actually vanish as we still have skb, and del_timer 1074diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 1075--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Fri Apr 27 14:15:01 2001 1076+++ linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Fri Jun 1 00:31:00 2001 1077@@ -146,7 +146,7 @@ 1078 /* Returns verdict for packet, or -1 for invalid. */ 1079 static int tcp_packet(struct ip_conntrack *conntrack, 1080 struct iphdr *iph, size_t len, 1081- enum ip_conntrack_info ctinfo) 1082+ enum ip_conntrack_info ctinfo, int *set_notify) 1083 { 1084 enum tcp_conntrack newconntrack, oldtcpstate; 1085 struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl); 1086@@ -174,6 +174,9 @@ 1087 return -1; 1088 } 1089 1090+ if (oldtcpstate != newconntrack) 1091+ *set_notify = 1; 1092+ 1093 conntrack->proto.tcp.state = newconntrack; 1094 1095 /* Poor man's window tracking: record SYN/ACK for handshake check */ 1096@@ -196,8 +199,10 @@ 1097 if (oldtcpstate == TCP_CONNTRACK_SYN_RECV 1098 && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL 1099 && tcph->ack && !tcph->syn 1100- && tcph->ack_seq == conntrack->proto.tcp.handshake_ack) 1101+ && tcph->ack_seq == conntrack->proto.tcp.handshake_ack) { 1102 set_bit(IPS_ASSURED_BIT, &conntrack->status); 1103+ *set_notify = 1; 1104+ } 1105 1106 ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]); 1107 } 1108diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c 1109--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_proto_udp.c Fri Apr 27 14:15:01 2001 1110+++ linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c Fri Jun 1 00:31:00 2001 1111@@ -47,14 +47,17 @@ 1112 /* Returns verdict for packet, and may modify conntracktype */ 1113 static int udp_packet(struct ip_conntrack *conntrack, 1114 struct iphdr *iph, size_t len, 1115- enum ip_conntrack_info conntrackinfo) 1116+ enum ip_conntrack_info conntrackinfo, int *set_notify) 1117 { 1118 /* If we've seen traffic both ways, this is some kind of UDP 1119 stream. Extend timeout. */ 1120 if (conntrack->status & IPS_SEEN_REPLY) { 1121+ unsigned long oldstatus = conntrack->status; 1122 ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT); 1123 /* Also, more likely to be important, and not a probe */ 1124 set_bit(IPS_ASSURED_BIT, &conntrack->status); 1125+ if(oldstatus != conntrack->status) 1126+ *set_notify = 1; 1127 } else 1128 ip_ct_refresh(conntrack, UDP_TIMEOUT); 1129 1130diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_standalone.c linux/net/ipv4/netfilter/ip_conntrack_standalone.c 1131--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Apr 27 14:15:01 2001 1132+++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c Fri Jun 1 00:31:00 2001 1133@@ -320,14 +320,19 @@ 1134 EXPORT_SYMBOL(ip_conntrack_protocol_register); 1135 EXPORT_SYMBOL(invert_tuplepr); 1136 EXPORT_SYMBOL(ip_conntrack_alter_reply); 1137-EXPORT_SYMBOL(ip_conntrack_destroyed); 1138 EXPORT_SYMBOL(ip_conntrack_get); 1139 EXPORT_SYMBOL(ip_conntrack_module); 1140 EXPORT_SYMBOL(ip_conntrack_helper_register); 1141 EXPORT_SYMBOL(ip_conntrack_helper_unregister); 1142+EXPORT_SYMBOL(ip_conntrack_notify_register); 1143+EXPORT_SYMBOL(ip_conntrack_notify_unregister); 1144 EXPORT_SYMBOL(ip_ct_selective_cleanup); 1145 EXPORT_SYMBOL(ip_ct_refresh); 1146 EXPORT_SYMBOL(ip_conntrack_expect_related); 1147 EXPORT_SYMBOL(ip_conntrack_tuple_taken); 1148 EXPORT_SYMBOL(ip_ct_gather_frags); 1149 EXPORT_SYMBOL(ip_conntrack_htable_size); 1150+EXPORT_SYMBOL(ip_conntrack_hash); 1151+EXPORT_SYMBOL(ip_conntrack_lock); 1152+EXPORT_SYMBOL(ip_conntrack_put); 1153+EXPORT_SYMBOL(ip_conntrack_find_get); 1154diff -ruN linux-2.4.5-ac5/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c 1155--- linux-2.4.5-ac5/net/ipv4/netfilter/ip_nat_core.c Wed May 16 10:31:27 2001 1156+++ linux/net/ipv4/netfilter/ip_nat_core.c Fri Jun 1 00:31:00 2001 1157@@ -856,6 +856,10 @@ 1158 return NF_ACCEPT; 1159 } 1160 1161+static struct ip_conntrack_notify nat_notify = { { NULL, NULL }, 1162+ ip_nat_cleanup_conntrack, 1163+ NULL }; 1164+ 1165 int __init ip_nat_init(void) 1166 { 1167 size_t i; 1168@@ -882,9 +886,8 @@ 1169 INIT_LIST_HEAD(&byipsproto[i]); 1170 } 1171 1172- 1173- IP_NF_ASSERT(ip_conntrack_destroyed == NULL); 1174- ip_conntrack_destroyed = &ip_nat_cleanup_conntrack; 1175+ if (ip_conntrack_notify_register(&nat_notify) < 0) 1176+ panic("ip_nat_init: cannot register notifier.\n"); 1177 1178 return 0; 1179 } 1180@@ -900,5 +903,5 @@ 1181 void ip_nat_cleanup(void) 1182 { 1183 ip_ct_selective_cleanup(&clean_nat, NULL); 1184- ip_conntrack_destroyed = NULL; 1185+ ip_conntrack_notify_unregister(&nat_notify); 1186 } 1187diff -ruN linux-2.4.5-ac5/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c 1188--- linux-2.4.5-ac5/net/netlink/netlink_dev.c Fri Feb 9 11:29:44 2001 1189+++ linux/net/netlink/netlink_dev.c Fri Jun 1 00:31:00 2001 1190@@ -200,6 +200,7 @@ 1191 make_devfs_entries ("skip", 1); 1192 make_devfs_entries ("USERSOCK", 2); 1193 make_devfs_entries ("fwmonitor", 3); 1194+ make_devfs_entries ("conntrack", 5); 1195 make_devfs_entries ("ARPD", 8); 1196 make_devfs_entries ("ROUTE6", 11); 1197 make_devfs_entries ("IP6_FW", 13); 1198