[netfilter-cvslog] r3551 - in branches/netfilter-ha/linux-2.6:
ct_sync patches
hidden at netfilter.org
hidden at netfilter.org
Mon Jan 3 00:13:27 CET 2005
Author: hidden at netfilter.org
Date: 2005-01-03 00:13:27 +0100 (Mon, 03 Jan 2005)
New Revision: 3551
Added:
branches/netfilter-ha/linux-2.6/patches/conntrack_alloc.patch
branches/netfilter-ha/linux-2.6/patches/conntrack_hash_manip.patch
branches/netfilter-ha/linux-2.6/patches/ct_notifier_pkt.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_clean_from_lists.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock_and_hash.patch
Removed:
branches/netfilter-ha/linux-2.6/ct_sync/Makefile
branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.h
branches/netfilter-ha/linux-2.6/patches/export_ct_id.patch
branches/netfilter-ha/linux-2.6/patches/export_hash_conntrack.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_nat_hash.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock.patch
branches/netfilter-ha/linux-2.6/patches/kgdb-1.9.patch
branches/netfilter-ha/linux-2.6/patches/nfnetlink-ctnetlink.patch
branches/netfilter-ha/linux-2.6/patches/proc_net_stat.patch
branches/netfilter-ha/linux-2.6/patches/raw.patch
branches/netfilter-ha/linux-2.6/patches/seq_file-seq_start_token.patch
Modified:
branches/netfilter-ha/linux-2.6/ct_sync/ct_sync.h
branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.c
branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.c
branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.h
branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_sock.c
branches/netfilter-ha/linux-2.6/patches/connmark.patch
branches/netfilter-ha/linux-2.6/patches/ct_sync_config_and_makefile.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_find.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_helpers.patch
branches/netfilter-ha/linux-2.6/patches/export_ip_nat_helpers.patch
branches/netfilter-ha/linux-2.6/patches/pf_packet.patch
branches/netfilter-ha/linux-2.6/patches/pf_packet_remove_warning.patch
branches/netfilter-ha/linux-2.6/patches/series
Log:
Initial port of the netfilter-ha code to Linux 2.6, along with some
enhancements and cleanups.
hidden at sch.bme.hu--2005-public/netfilter-ha--mainline--1.0--patch-3
* ct_sync/ct_sync_proto.c (cts_proto_request_recovery): use a variable
instead of that ugly constant value
* ct_sync/ct_sync_main.c: export cts_proto_recovery_threshold through
sysctl
hidden at sch.bme.hu--2005-public/netfilter-ha--mainline--1.0--patch-2
* ct_sync/ct_sync_proto.c (cts_proto_initsync_follows): add missing
fourth argument to csb_hdr_fill() which was removed by accident
hidden at sch.bme.hu--2005-public/netfilter-ha--mainline--1.0--patch-1
* ct_sync/ct_sync_proto.c (cts_proto_request_recovery): set active flag
before touching other recovery parameters
hidden at sch.bme.hu--2004-public/netfilter-ha--mainline--1.0--patch-4
* ct_sync/ct_sync_proto.c (cts_proto_init): removed group ID and state
parameters, use transition_callback() instead of became_slave()
* ct_sync/ct_sync_main.c (ct_sync_state_transition): new transition
callback, called on every protocol state transition
* ct_sync/ct_sync_main.c (_send_empty_initsync): use specified flags for
sending
* ct_sync/ct_sync_main.c (ct_sync_initsync_thread_main): send empty update
message with the new CTS_UPD_F_INITSYNC_DONE flag after completing the
initsync run
* ct_sync/ct_sync_main.c: more sysctl controllable parameters (maxage,
send_burst, recv_burst)
hidden at sch.bme.hu--2004-public/netfilter-ha--mainline--1.0--patch-3
* ct_sync/ct_sync_proto.c: removed cts_proto_recv_running()
* ct_sync/ct_sync.h: added some comments, removed lots of includes,
removed ct_thread_startup structure
* ct_sync/*.{c,h}: a bit more consistent indentation
hidden at sch.bme.hu--2004-public/netfilter-ha--mainline--1.0--patch-2
* ct_sync/ct_sync_main.c: use kthread_ helper functions
instead of own startup code
* ct_sync/ct_sync_main.h: removed, was junk anyway
* ct_sync/ct_sync_main.c, ct_sync/ct_sync_proto.c, ct_syncct_sync_sock.c:
removed remnants of the CVS ID
hidden at sch.bme.hu--2004-public/netfilter-ha--mainline--1.0--patch-1
* ct_sync/ct_sync_main.c(notrack_hook): when assigning conntrack to the skb,
initialize nfctinfo to IP_CT_NEW
Deleted: branches/netfilter-ha/linux-2.6/ct_sync/Makefile
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/Makefile 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/Makefile 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,35 +0,0 @@
-# set to your kernel tree
-KERNEL = /usr/src/linux-ctsync
-
-# get the Linux architecture. Needed to find proper include file for CFLAGS
-ARCH=$(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-# set default flags to compile module
-#CFLAGS = -DARCH=um -DCTSYNC_DEBUG -D__KERNEL__ -DMODULE -I$(KERNEL)/include -I$(KERNEL)/arch/um/include -I$(KERNEL)/arch/um/kernel/tt/include -I$(KERNEL)/arch/um/kernel/skas/include
-CFLAGS = -DCTSYNC_DEBUG -D__KERNEL__ -DMODULE -I$(KERNEL)/include
-CFLAGS+= -Wall -Wstrict-prototypes -g -fomit-frame-pointer -fno-strict-aliasing
-
-CT_SYNC_MOD = ct_sync.o
-CT_SYNC_OBJS = ct_sync_main.o ct_sync_sock.o ct_sync_proto.o
-
-all: $(CT_SYNC_MOD)
-
-# get configuration of kernel
-include $(KERNEL)/.config
-# modify CFLAGS with architecture specific flags
-include $(KERNEL)/arch/${ARCH}/Makefile
-
-# enable the module versions, if configured in kernel source tree
-ifdef CONFIG_MODVERSIONS
-CFLAGS+= -DMODVERSIONS -include $(KERNEL)/include/linux/modversions.h
-endif
-# enable SMP, if configured in kernel source tree
-ifdef CONFIG_SMP
-CFLAGS+= -D__SMP__
-endif
-
-$(CT_SYNC_MOD): $(CT_SYNC_OBJS)
- $(LD) -r $^ -o $@
-
-clean:
- rm -f *.o
-
Modified: branches/netfilter-ha/linux-2.6/ct_sync/ct_sync.h
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/ct_sync.h 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/ct_sync.h 2005-01-02 23:13:27 UTC (rev 3551)
@@ -8,40 +8,17 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * $Id$
- *
*/
#ifndef _CT_SYNC_H
#define _CT_SYNC_H
-#if 0
-#include <linux/config.h>
-#include <linux/version.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/tqueue.h>
-#include <linux/wait.h>
-
-#include <asm/semaphore.h>
-#include <linux/if_ether.h>
-#endif
-
#include <linux/list.h>
#include <linux/types.h>
#include <linux/if_ether.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
-#if 0
-#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-#include <linux/netfilter_ipv4/ip_conntrack_core.h>
-#include <linux/netfilter_ipv4/ip_nat.h>
-#include <linux/netfilter_ipv4/ip_nat_helper.h>
-#endif
+#define CTSYNC_DEBUG 8
-#define CTSYNC_DEBUG 0
-
/* debugging macros */
#if (CTSYNC_DEBUG > 0)
#define CT_SYNC_DEBUG(x, args...) printk (KERN_DEBUG "ct_sync: %s " x, __FUNCTION__ , ## args)
@@ -80,21 +57,21 @@
{
__u8 version; /* version number */
__u8 pkttype; /* type of packet: sync/NACK */
- __u8 node_id; /* id of the sender node */
+ __u8 __reserved1; /* id of the sender node */
__u8 count; /* number of msgs in packet */
__u16 pktseq; /* packet sequence number */
__u16 minseq; /* min seqno master has */
__u8 flags; /* flags: 1 == recover */
- __u8 __reserved; /* placeholder :) */
- __u16 __reserved2; /* placeholder :) */
+ __u8 __reserved2; /* placeholder :) */
+ __u16 __reserved3; /* placeholder :) */
};
/* packet types */
enum ct_sync_pkttype_t
{
CT_SYNC_PKT_UNKNOWN = 0x00, /* not defined, illegal */
- CT_SYNC_PKT_MASTER_ANNOUNCE = 0x01,
- CT_SYNC_PKT_SLAVE_INITSYNC = 0x02,
+ CT_SYNC_PKT_MASTER_ANNOUNCE = 0x01, /* master announcement (carrying seqno) */
+ CT_SYNC_PKT_SLAVE_INITSYNC = 0x02, /* slave requests a full re-sync */
CT_SYNC_PKT_SYNC = 0x03, /* normal sync packet */
CT_SYNC_PKT_NACK = 0x04, /* negative ack packet */
CT_SYNC_PKT_INITSYNC_FOLLOWS = 0x05, /* a full re-sync follows */
@@ -102,17 +79,17 @@
enum ct_sync_pkt_flag_t
{
- CT_SYNC_PKT_F_RECOVER = 0x01,
+ CT_SYNC_PKT_F_RECOVER = 0x01, /* recovery packet */
};
-/* CT_SYNC_PKT_MASTER_ANNOUNCE */
+/* CT_SYNC_PKT_MASTER_ANNOUNCE payload */
struct ct_sync_master_announce
{
__u32 upsince; /* master up since */
__u8 flags; /* flags */
};
-/* CT_SYNC_PKT_SLAVE_INITSYNC */
+/* CT_SYNC_PKT_SLAVE_INITSYNC payload */
struct ct_sync_slave_initsync
{
__u32 master;
@@ -146,7 +123,7 @@
CT_SYNC_MSG_DELETE = 0x02, /* delete conntrack entry */
};
-/* CT_SYNC_PKT_SYNC: ressources */
+/* CT_SYNC_PKT_SYNC: resources */
enum ct_sync_resource_t
{
CT_SYNC_RES_CONNTRACK = 0x01,
@@ -157,6 +134,7 @@
{
CTS_UPD_F_NEW = 0x01, /* creates new conntrack */
CTS_UPD_F_INITSYNC = 0x02, /* part of initial sync */
+ CTS_UPD_F_INITSYNC_DONE = 0x04, /* sent after an initsync session is complete */
};
/* linearized conntrack data */
@@ -210,13 +188,6 @@
#ifdef __KERNEL__
-/* thread startup structure */
-struct ct_thread_startup
-{
- struct completion *completion; /* signalling init of new thread */
- int (*function)(void *); /* function to run in the new thread */
-};
-
/* statistics */
struct ct_sync_st
{
@@ -250,16 +221,14 @@
unsigned long slave2master; /* slave->master transitions */
unsigned long master2slave; /* master->slave transitions */
unsigned long master2slave_auto;
-
- unsigned long initsyncs; /* master: started initsyncs */
+ unsigned long initsyncs; /* master: started initsyncs */
};
-extern struct ct_sync_stat ct_sync_stats[NR_CPUS];
+DECLARE_PER_CPU(struct ct_sync_stat, ct_sync_stats);
-#define CTS_STAT_INC(field) (ct_sync_stats[smp_processor_id()].field++)
+#define CTS_STAT_INC(field) (__get_cpu_var(ct_sync_stats).field++)
#endif /* _KERNEL_ */
#endif
-
Modified: branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.c
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.c 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.c 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,7 +1,7 @@
/*
* Connection tracking state replication for Netfilter
*
- * (C) 2002-2003, KOVACS Krisztian <hidden at sch.bme.hu>
+ * (C) 2002-2004, KOVACS Krisztian <hidden at sch.bme.hu>
* (C) 2003-2004, Harald Welte <laforge at netfilter.org>
* (C) 2004, BalaBit IT Ltd. <www.balabit.com>
*
@@ -9,8 +9,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * $Id$
- *
*/
#define __KERNEL_SYSCALLS__
@@ -18,6 +16,7 @@
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/sched.h>
@@ -30,12 +29,14 @@
#include <linux/notifier.h>
#include <linux/sysctl.h>
#include <linux/seq_file.h>
+#include <linux/percpu.h>
+#include <linux/kthread.h>
#include <net/sock.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
-#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_packet.h>
+#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -50,7 +51,7 @@
#include <linux/netfilter_ipv4/ct_sync.h>
#include <linux/netfilter_ipv4/ct_sync_proto.h>
-#define DEBUGP printk
+#define DEBUGP printk
#if (CTSYNC_DEBUG > 0)
#define CT_SYNC_DUMP_TUPLE(x) DUMP_TUPLE(x)
@@ -62,7 +63,7 @@
#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
#include <linux/netfilter_ipv4/listhelp.h>
-#define CT_SYNC_VERSION "0.18"
+#define CT_SYNC_VERSION "0.19"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KOVACS Krisztian <hidden at sch.bme.hu>, Harald Welte <laforge at netfilter.org>");
@@ -70,37 +71,21 @@
/* module parameters */
static char *syncdev = "";
-static int state = -1;
-static int id = -1;
+module_param(syncdev, charp, 0000);
static int l2drop = 0;
+module_param(l2drop, int, 0000);
static int cmarkbit = sizeof(unsigned long) * 8 - 1;
+module_param(cmarkbit, int, 0000);
-MODULE_PARM(syncdev, "s");
-MODULE_PARM_DESC(syncdev, "Interface used for sync messages");
-MODULE_PARM(state, "i");
-MODULE_PARM_DESC(state, "Initial state: 0=slave 1=master");
-MODULE_PARM(id, "i");
-MODULE_PARM_DESC(id, "unique Node ID (0..255) of local node");
-MODULE_PARM(l2drop, "i");
-MODULE_PARM_DESC(l2drop, "drop all packets at layer 2 if slave");
-MODULE_PARM(cmarkbit, "i");
-MODULE_PARM_DESC(cmarkbit, "bit in the connection mark to use as sync mark");
-
-/* used to stop ct_sync threads */
+/* thread wait queue heads */
static DECLARE_WAIT_QUEUE_HEAD(ct_sync_rcv_wait);
-static DECLARE_WAIT_QUEUE_HEAD(stop_ct_rcv_thread_wait);
-static atomic_t stop_ct_rcv_thread = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(ct_sync_send_wait);
-static DECLARE_WAIT_QUEUE_HEAD(stop_ct_send_thread_wait);
-static atomic_t stop_ct_send_thread = ATOMIC_INIT(0);
static atomic_t ct_sync_initsync_active = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(ct_sync_initsync_wait);
-static DECLARE_WAIT_QUEUE_HEAD(stop_ct_initsync_thread_wait);
-static atomic_t stop_ct_initsync_thread = ATOMIC_INIT(0);
-struct ct_sync_stat ct_sync_stats[NR_CPUS];
+DEFINE_PER_CPU(struct ct_sync_stat, ct_sync_stats);
/* configuration data */
static struct ct_sync_cfg
@@ -109,13 +94,13 @@
char devname[IFNAMSIZ]; /* dedicated sync network device */
int ifindex; /* ifindex of the network device */
struct cts_protoh *protoh; /* protocol handle */
- u8 nodeid; /* node id in cluster */
} cts_cfg;
/***********************************************************************
* FILLING CTSYNC MESSAGES WITH DATA
***********************************************************************/
+#if 0
static int
fill_expectmsg(void *buff, __u8 event,
struct ip_conntrack *master,
@@ -155,6 +140,7 @@
return 0;
}
+#endif
static int
fill_ctmsg(void *buff, __u8 event, struct ip_conntrack *ct, __u8 flags)
@@ -206,7 +192,6 @@
memcpy(&sct->proto, &ct->proto, sizeof(sct->proto));
#ifdef CONFIG_IP_NF_NAT_NEEDED
- //if (likely(ct->nat.info.initialized && ct->nat.info.num_manips)) {
if (likely(ct->nat.info.initialized)) {
const struct ip_nat_info *nat = &ct->nat.info;
@@ -248,19 +233,6 @@
* BACKEND FOR CONNTRACK MODIFICATION
***********************************************************************/
-static inline int
-_helper_name_cmp(const struct ip_conntrack_helper *i,
- const char *name)
-{
- return strncmp(i->name, name, CT_SYNC_CTHELPERSIZE - 1);
-}
-
-static inline int
-_nat_helper_name_cmp(const struct ip_nat_helper *i, const char *name)
-{
- return strncmp(i->name, name, CT_SYNC_NATHELPERSIZE - 1);
-}
-
/*
* update data in the conntrack entry
*/
@@ -295,10 +267,6 @@
//CT_SYNC_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
//CT_SYNC_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- /* optimization: done by conntrack_alloc */
- //ct->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = ct;
- //ct->tuplehash[IP_CT_DIR_REPLY].ctrack = ct;
-
/* timeout */
if (!timer_pending(&ct->timeout)) {
ct->timeout.expires = sct->expires;
@@ -337,11 +305,9 @@
/* conntrack helper */
if (unlikely(sct->helper[0] != '\0')) {
+ sct->helper[CT_SYNC_CTHELPERSIZE - 1] = '\0';
READ_LOCK(&ip_conntrack_lock);
- helper = LIST_FIND(&ip_conntrack_helpers,
- _helper_name_cmp,
- struct ip_conntrack_helper *,
- sct->helper);
+ helper = __ip_ct_find_helper_by_name(sct->helper);
if (unlikely(!helper)) {
CT_SYNC_ERR("Unknown conntrack helper `%s', "
"ignoring.\n", sct->helper);
@@ -353,8 +319,6 @@
READ_UNLOCK(&ip_conntrack_lock);
}
- /* nf_ct_infos filled in by conntrack_alloc */
-
/* protocol data */
memcpy(&ct->proto, &sct->proto, sizeof(ct->proto));
@@ -364,8 +328,8 @@
{
struct ip_nat_info *nat = &ct->nat.info;
/* DEBUG: initialize list heads to avoid oops */
- INIT_LIST_HEAD(&nat->bysource.list);
- INIT_LIST_HEAD(&nat->byipsproto.list);
+ INIT_LIST_HEAD(&nat->bysource);
+ INIT_LIST_HEAD(&nat->byipsproto);
}
//if (likely(sct->nat_initialized && sct->nat_num_manips)) {
@@ -388,10 +352,9 @@
if (unlikely(sct->nat_helper[0] != '\0')) {
struct ip_nat_helper *helper;
/* look up nat helper */
+ sct->nat_helper[CT_SYNC_NATHELPERSIZE - 1] = '\0';
READ_LOCK(&ip_nat_lock);
- helper = LIST_FIND(&ip_nat_helpers, _nat_helper_name_cmp,
- struct ip_nat_helper *,
- sct->nat_helper);
+ helper = __ip_nat_find_helper_by_name(sct->nat_helper);
if (unlikely(!helper)) {
CT_SYNC_ERR("Unknown NAT helper `%s', ignoring\n", sct->nat_helper);
nat->helper = NULL;
@@ -426,16 +389,15 @@
WRITE_LOCK(&ip_conntrack_lock);
if (!__ip_conntrack_find(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL)
&& !__ip_conntrack_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) {
- u_int32_t hash, repl_hash;
- hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
- repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+#if 0
/* place in ordered list */
ct->id = ip_conntrack_next_id++;
list_add_tail(&ct->olist, &ip_conntrack_ordered_list);
+#endif
/* put in conntrack hash */
- list_prepend(&ip_conntrack_hash[hash], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
- list_prepend(&ip_conntrack_hash[repl_hash], &ct->tuplehash[IP_CT_DIR_REPLY]);
- atomic_inc(&ct->ct_general.use);
+ __ip_conntrack_hash_insert(ct);
+ atomic_inc(&ct->ct_general.use);
+
/* put in NAT hashes if necessary */
if (sct->nat_initialized) {
CT_SYNC_ASSERT(previous_nat_initialized == 0);
@@ -456,90 +418,16 @@
return 0;
}
-static inline void
-__ct_sync_unexpect_related(struct ip_conntrack_expect *expect)
-{
- if (unlikely(expect->sibling != NULL)) {
- CT_SYNC_ERR("Cannot delete a confirmed expectation!\n");
- return;
- }
-
- list_del(&expect->list);
- list_del(&expect->expected_list);
-
- if (likely(expect->expectant != NULL))
- expect->expectant->expecting--;
-
- ip_conntrack_expect_put(expect);
-}
-
-static inline void
-_ct_sync_unexpect_related(struct ip_conntrack_expect *expect)
-{
- if (unlikely(!expect->expectant || !expect->expectant->helper))
- return;
- if (unlikely(expect->expectant->helper->timeout
- && !del_timer(&expect->timeout)))
- return;
-
- __ct_sync_unexpect_related(expect);
-}
-
-static inline void
-_ct_sync_conntrack_remove_expectations(struct ip_conntrack *ct)
-{
- struct list_head *exp_entry, *next;
- struct ip_conntrack_expect *exp;
-
- CT_SYNC_ENTER();
-
- for (exp_entry = ct->sibling_list.next;
- exp_entry != &ct->sibling_list; exp_entry = next) {
- next = exp_entry->next;
- exp = list_entry(exp_entry, struct ip_conntrack_expect,
- expected_list);
-
- if (exp->sibling)
- continue;
-
- _ct_sync_unexpect_related(exp);
- }
-
- CT_SYNC_LEAVE();
-}
-
-static inline void
-_ct_sync_conntrack_clean_lists(struct ip_conntrack *ct)
-{
- u_int32_t hash, repl_hash;
-
- CT_SYNC_ENTER();
-
- WRITE_LOCK(&ip_conntrack_lock);
-
- hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
- repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- LIST_DELETE(&ip_conntrack_hash[hash],
- &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
- LIST_DELETE(&ip_conntrack_hash[repl_hash],
- &ct->tuplehash[IP_CT_DIR_REPLY]);
- LIST_DELETE(&ip_conntrack_ordered_list, &ct->olist);
-
- WRITE_UNLOCK(&ip_conntrack_lock);
-
- _ct_sync_conntrack_remove_expectations(ct);
-
- CT_SYNC_LEAVE();
-}
-
-/* delete conntrack entry */
+/* delete conntrack entry, but do not generate an event */
static inline int
_ct_sync_remove_conntrack(struct ip_conntrack *ct)
{
CT_SYNC_ENTER();
del_timer(&ct->timeout);
- _ct_sync_conntrack_clean_lists(ct);
+ WRITE_LOCK(&ip_conntrack_lock);
+ ip_conntrack_clean_from_lists(ct);
+ WRITE_UNLOCK(&ip_conntrack_lock);
ip_conntrack_put(ct);
CT_SYNC_LEAVE();
@@ -645,12 +533,7 @@
CT_SYNC_LEAVE();
}
-static int kill_all(const struct ip_conntrack *i, void *data)
-{
- return 1;
-}
-
/***********************************************************************
* MESSAGE PROCESSING FUNCTIONS
***********************************************************************/
@@ -859,7 +742,6 @@
{
int ret;
u16 pktseq = ntohs(pkthdr->pktseq);
- //u16 minseq = ntohs(pkthdr->minseq);
CT_SYNC_ENTER();
@@ -891,12 +773,6 @@
if (cts_proto_is_master(cts_cfg.protoh) &&
!atomic_read(&ct_sync_initsync_active)) {
CTS_STAT_INC(initsyncs);
- /* signal that an initsync is to follow */
- if (cts_proto_initsync_follows(cph) < 0) {
- CT_SYNC_LEAVE();
- return -1;
- }
- /* wake up initsync thread */
wake_up(&ct_sync_initsync_wait);
} else
CT_SYNC_INFO("not master, or initsync already in progress\n");
@@ -907,33 +783,251 @@
}
/***********************************************************************
+ * SYSCTL HANDLING
+ ***********************************************************************/
+
+/* sysctl variables */
+static int cts_sysctl_state;
+static int cts_sysctl_maxage;
+static int cts_sysctl_send_burst = 100;
+static int cts_sysctl_recv_burst = 400;
+
+#define CTS_SYSCTL_STATE_NONE 0
+#define CTS_SYSCTL_STATE_SLAVE 1
+#define CTS_SYSCTL_STATE_MASTER 2
+
+static int
+cts_sysctl_change_state(int state)
+{
+ CT_SYNC_ENTER();
+
+ switch (state) {
+ case CTS_SYSCTL_STATE_NONE:
+ /* cannot set state to NONE */
+ CT_SYNC_ERR("cannot switch to state none!\n");
+ CT_SYNC_LEAVE();
+ return -EINVAL;
+ break;
+
+ case CTS_SYSCTL_STATE_SLAVE:
+ if (cts_proto_is_master(cts_cfg.protoh)) {
+ CTS_STAT_INC(master2slave);
+ CT_SYNC_ERR("cannot switch active master to client!\n");
+ CT_SYNC_LEAVE();
+ return -EINVAL;
+ } else if (cts_proto_get_state(cts_cfg.protoh) == CT_SYNC_PSTATE_NONE) {
+ cts_proto_become_slave(cts_cfg.protoh);
+ }
+ break;
+
+ case CTS_SYSCTL_STATE_MASTER:
+ if (!cts_proto_is_master(cts_cfg.protoh)) {
+ if (cts_proto_become_master(cts_cfg.protoh) < 0) {
+ CT_SYNC_ERR("proto said we cannot become master\n");
+ CT_SYNC_LEAVE();
+ return -EINVAL;
+ }
+ } else {
+ CT_SYNC_INFO("we already are master; staying cool");
+ }
+ break;
+
+ default:
+ /* unknown state */
+ CT_SYNC_ERR("cannot switch to unknown state!\n");
+ CT_SYNC_LEAVE();
+ return -EINVAL;
+ break;
+ break;
+ }
+
+ CT_SYNC_LEAVE();
+
+ return 0;
+}
+
+static void
+cts_sysctl_update_state(void)
+{
+ CT_SYNC_ENTER();
+
+ switch (cts_proto_get_state(cts_cfg.protoh)) {
+ case CT_SYNC_PSTATE_NONE:
+ cts_sysctl_state = CTS_SYSCTL_STATE_NONE;
+ break;
+ case CT_SYNC_PSTATE_SLAVE_INIT:
+ case CT_SYNC_PSTATE_SLAVE_SYNSENT:
+ case CT_SYNC_PSTATE_SLAVE_SYNRECV:
+ case CT_SYNC_PSTATE_SLAVE_RUNNING:
+ cts_sysctl_state = CTS_SYSCTL_STATE_SLAVE;
+ break;
+ case CT_SYNC_PSTATE_MASTER_INIT:
+ case CT_SYNC_PSTATE_MASTER_ADVSENT:
+ case CT_SYNC_PSTATE_MASTER_RUNNING:
+ cts_sysctl_state = CTS_SYSCTL_STATE_MASTER;
+ break;
+ default:
+ CT_SYNC_ERR("invalid state\n");
+ break;
+ }
+
+ CT_SYNC_LEAVE();
+}
+
+static int
+cts_sysctl_state_handler(ctl_table *table, int write,
+ struct file *filp, void *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ int res;
+
+ if (write) {
+ res = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if (res < 0)
+ return res;
+ return cts_sysctl_change_state(cts_sysctl_state);
+ } else {
+ cts_sysctl_update_state();
+ return proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ }
+}
+
+static int
+cts_sysctl_maxage_handler(ctl_table *table, int write,
+ struct file *filp, void *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ int res;
+
+ if (write) {
+ res = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if (res < 0)
+ return res;
+ return cts_proto_set_max_age(cts_sysctl_maxage);
+ } else {
+ cts_sysctl_maxage = cts_proto_get_max_age();
+ return proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ }
+}
+
+/* FIXME: define this in sysctl.h */
+#define NET_IPV4_NF_CONNTRACK_SYNC 20
+
+enum {
+ CTS_SYSCTL_STATE = 1,
+ CTS_SYSCTL_MAXAGE = 2,
+ CTS_SYSCTL_SEND_BURST = 3,
+ CTS_SYSCTL_RECV_BURST = 4,
+ CTS_SYSCTL_RECOVERY_THRESHOLD = 5,
+};
+
+static ctl_table ct_sync_sysctl_table[] = {
+ {
+ .ctl_name = CTS_SYSCTL_STATE,
+ .procname = "state",
+ .mode = 0644,
+ .data = &cts_sysctl_state,
+ .maxlen = sizeof(int),
+ .proc_handler = &cts_sysctl_state_handler,
+ },
+ {
+ .ctl_name = CTS_SYSCTL_MAXAGE,
+ .procname = "maxage",
+ .mode = 0644,
+ .data = &cts_sysctl_maxage,
+ .maxlen = sizeof(int),
+ .proc_handler = &cts_sysctl_maxage_handler,
+ },
+ {
+ .ctl_name = CTS_SYSCTL_SEND_BURST,
+ .procname = "send_burst",
+ .mode = 0644,
+ .data = &cts_sysctl_send_burst,
+ .maxlen = sizeof(int),
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = CTS_SYSCTL_RECV_BURST,
+ .procname = "recv_burst",
+ .mode = 0644,
+ .data = &cts_sysctl_recv_burst,
+ .maxlen = sizeof(int),
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = CTS_SYSCTL_RECOVERY_THRESHOLD,
+ .procname = "recovery_threshold",
+ .mode = 0644,
+ .data = &cts_proto_recovery_threshold,
+ .maxlen = sizeof(int),
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = 0,
+ .extra2 = 32767,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ct_sync_cts_table[] = {
+ {
+ .ctl_name = NET_IPV4_NF_CONNTRACK_SYNC,
+ .procname = "ct_sync",
+ .mode = 0555,
+ .child = ct_sync_sysctl_table,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ct_sync_netfilter_table[] = {
+ {
+ .ctl_name = NET_IPV4_NETFILTER,
+ .procname = "netfilter",
+ .mode = 0555,
+ .child = ct_sync_cts_table,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ct_sync_net_table[] = {
+ {
+ .ctl_name = NET_IPV4,
+ .procname = "ipv4",
+ .mode = 0555,
+ .child = ct_sync_netfilter_table,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ct_sync_root_table[] = {
+ {
+ .ctl_name = CTL_NET,
+ .procname = "net",
+ .mode = 0555,
+ .child = ct_sync_net_table,
+ },
+ { .ctl_name = 0 }
+};
+
+static struct ctl_table_header *ct_sync_sysctl_header;
+
+/***********************************************************************
* KERNEL THREADS
***********************************************************************/
-#define CT_SYNC_SEND_BURST 100
/* sync kernel thread: sender */
static int
-ct_sync_send_thread_main(void *ct_thread_startup)
+ct_sync_send_thread_main(void *data)
{
- mm_segment_t oldmm;
unsigned long remaining;
DECLARE_WAITQUEUE(wait, current);
CT_SYNC_ENTER();
- /* daemonize kernel thread, set values */
- daemonize();
- oldmm = get_fs();
- set_fs(KERNEL_DS);
- sigfillset(¤t->blocked);
- sprintf(current->comm, "ct_sync_send");
-
- complete((struct completion *) ct_thread_startup);
-
for (;;) {
int i = 0;
- if (unlikely(atomic_read(&stop_ct_send_thread))) {
- CT_SYNC_DEBUG("stop_ct_send_thread == 1\n");
+
+ /* check if we should stop */
+ if (kthread_should_stop()) {
+ CT_SYNC_DEBUG("send thread stopping\n");
break;
}
@@ -941,12 +1035,13 @@
* all of them */
while (cts_proto_send_pending(cts_cfg.protoh)) {
cts_proto_send_dequeue(cts_cfg.protoh);
- i++;
- if (i >= CT_SYNC_SEND_BURST)
+
+ if (++i >= cts_sysctl_send_burst)
break;
}
- cts_proto_initsync_retransmit(cts_cfg.protoh);
+ /* send an initsync request if necessary */
+ cts_proto_initsync_request(cts_cfg.protoh);
__set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&ct_sync_send_wait, &wait);
@@ -964,39 +1059,19 @@
CT_SYNC_DEBUG2("woken up after schedule_timeout() because we had an event\n");
}
- set_fs(oldmm);
-
- atomic_set(&stop_ct_send_thread, 0);
- wake_up(&stop_ct_send_thread_wait);
-
CT_SYNC_LEAVE();
return 0;
}
-/* FIXME: these should be configurable */
-#define CT_SYNC_RECV_BURST 200
-//#define CT_SYNC_INITSYNC_RATE 20
/* sync kernel thread: receiver */
static int
-ct_sync_rcv_thread_main(void *ct_thread_startup)
+ct_sync_rcv_thread_main(void *data)
{
- mm_segment_t oldmm;
DECLARE_WAITQUEUE(wait, current);
CT_SYNC_ENTER();
- /* daemonize kernel thread, set values */
- daemonize();
- oldmm = get_fs();
- set_fs(KERNEL_DS);
- sigfillset(¤t->blocked);
- sprintf(current->comm, "ct_sync_rcv");
-
- complete((struct completion *) ct_thread_startup);
-
- CT_SYNC_DEBUG("ct_sync_rcv: entering main loop\n");
-
for (;;) {
int pkts_enqueued = 0;
int pkts_received = 0;
@@ -1004,8 +1079,8 @@
struct ct_sync_msghdr *msghdr;
struct ct_sync_pkthdr *pkthdr;
- if (unlikely(atomic_read(&stop_ct_rcv_thread)))
- break;
+ if (kthread_should_stop())
+ break;
/* wait for a new packet to arrive */
if (!cts_proto_recv_pending(cts_cfg.protoh)) {
@@ -1015,7 +1090,7 @@
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
if (cts_proto_recv_pending(cts_cfg.protoh) ||
- unlikely(atomic_read(&stop_ct_rcv_thread)))
+ kthread_should_stop())
break;
CT_SYNC_DEBUG2("falling asleep\n");
@@ -1049,10 +1124,10 @@
and dropped the packet */
break;
}
-
+
pkts_received++;
CTS_STAT_INC(rx.pkts_tot);
- if (pkts_received >= CT_SYNC_RECV_BURST)
+ if (pkts_received >= cts_sysctl_recv_burst)
break;
}
@@ -1072,7 +1147,7 @@
}
/* give chance for other processes to run */
- if (pkts_received >= CT_SYNC_RECV_BURST)
+ if (pkts_received >= cts_sysctl_recv_burst)
cond_resched();
/* FIXME: implement another way to detect end of initsync,
@@ -1092,11 +1167,6 @@
}
error:
- set_fs(oldmm);
-
- atomic_set(&stop_ct_rcv_thread, 0);
- wake_up(&stop_ct_rcv_thread_wait);
-
CT_SYNC_LEAVE();
return 0;
@@ -1112,7 +1182,7 @@
if (likely(is_confirmed(ct)
#ifdef CONFIG_IP_NF_CONNTRACK_MARK
- /* stop timer only if this is a synchronized connection */
+ /* send only if this is a synchronized connection */
&& test_bit(cmarkbit, &ct->mark)
#endif
)) {
@@ -1132,7 +1202,8 @@
return 0;
}
-static int _send_empty_initsync(void)
+static int
+_send_empty_initsync(u8 flags)
{
struct cts_buff *csb;
struct ct_sync_msghdr *hdr;
@@ -1149,7 +1220,7 @@
hdr->type = CT_SYNC_MSG_UPDATE;
hdr->resource = CT_SYNC_RES_CONNTRACK;
hdr->len = 0;
- hdr->flags = CTS_UPD_F_INITSYNC;
+ hdr->flags = flags;
csb_use_dec(cts_cfg.protoh, csb);
@@ -1158,24 +1229,12 @@
/* sync kernel thread: recover */
static int
-ct_sync_initsync_thread_main(void *ct_thread_startup)
+ct_sync_initsync_thread_main(void *data)
{
DECLARE_WAITQUEUE(wait, current);
- mm_segment_t oldmm;
CT_SYNC_ENTER();
- /* daemonize kernel thread, set values */
- daemonize();
- oldmm = get_fs();
- set_fs(KERNEL_DS);
- sigfillset(¤t->blocked);
- sprintf(current->comm, "ct_sync_initsync");
-
- complete((struct completion *) ct_thread_startup);
-
- CT_SYNC_DEBUG("ct_sync_initsync: entering main loop\n");
-
for (;;) {
int i;
int num_sent_total;
@@ -1187,29 +1246,32 @@
__set_current_state(TASK_RUNNING);
/* somebody woke us. either initsync or thread termination
- request */
+ * request */
- if (unlikely(atomic_read(&stop_ct_initsync_thread)))
+ if (kthread_should_stop())
break;
CT_SYNC_INFO("starting initsync dump\n");
- /* Send master announce in order to assure slave(s)
- * learn about current (correct) seqno */
- cts_proto_master_announce(cts_cfg.protoh);
+ atomic_set(&ct_sync_initsync_active, 1);
+ /* Send an INITSYNC_FOLLOWS packet indicating that a full
+ * re-sync follows and all nodes waiting for re-sent
+ * packets should go to SLAVE_INIT state and forget
+ * current receiver state */
+ cts_proto_initsync_follows(cts_cfg.protoh);
+
/* speed: 40 conntracks per schedule, 100 schedules per
- second: 4000 conntracks per second. This makes about
- 25 seconds for 100,000 connections. Please note that
- we have four conntracks per packet, so the wire would
- see something like 1000 packets per second, or in
- other words: 1.5mbits */
+ * second: 4000 conntracks per second. This makes about
+ * 25 seconds for 100,000 connections. Please note that
+ * we have four conntracks per packet, so the wire would
+ * see something like 1000 packets per second, or in
+ * other words: 1.5mbits */
num_sent_total = 0;
- atomic_set(&ct_sync_initsync_active, 1);
for (i = 0; i < ip_conntrack_htable_size; i++) {
unsigned int num_sent = 0;
- if (unlikely(atomic_read(&stop_ct_initsync_thread)))
+ if (kthread_should_stop())
break;
READ_LOCK(&ip_conntrack_lock);
@@ -1237,45 +1299,27 @@
__set_current_state(TASK_RUNNING);
CT_SYNC_DEBUG2("woken up\n");
}
+
if (!num_sent_total) {
/* need to send an empty PKT_SYCN/UPD_F_INITSYNC
* packet in order to provoke state transition
* in slave */
- _send_empty_initsync();
+ _send_empty_initsync(CTS_UPD_F_INITSYNC);
}
+
+ /* signal that the initsync is over */
+ _send_empty_initsync(CTS_UPD_F_INITSYNC_DONE);
+
atomic_set(&ct_sync_initsync_active, 0);
CT_SYNC_INFO("finished initsync dump\n");
}
- set_fs(oldmm);
-
- atomic_set(&stop_ct_initsync_thread, 0);
- wake_up(&stop_ct_initsync_thread_wait);
-
CT_SYNC_LEAVE();
return 0;
}
-/* thread startup helper: double fork to reparent to init */
-static int
-fork_ct_thread(void *p)
-{
- struct ct_thread_startup *c = (struct ct_thread_startup *)p;
- CT_SYNC_ENTER();
-
- if (kernel_thread(c->function, c->completion, 0) < 0) {
- CT_SYNC_ERR("Failed to fork ct_sync thread.\n");
- CT_SYNC_LEAVE();
- return -1;
- }
-
- CT_SYNC_LEAVE();
-
- return 0;
-}
-
/***********************************************************************
* NOTIFIER HANDLERS
***********************************************************************/
@@ -1309,7 +1353,7 @@
CT_SYNC_LEAVE();
return;
}
- fill_ctmsg(buff, CT_SYNC_MSG_UPDATE, ct, new ? CTS_UPD_F_NEW:0);
+ fill_ctmsg(buff, CT_SYNC_MSG_UPDATE, ct, new ? CTS_UPD_F_NEW : 0);
csb_use_dec(cts_cfg.protoh, csb);
}
@@ -1361,6 +1405,7 @@
CT_SYNC_LEAVE();
}
+#if 0
/* conntrack expectation created notification */
static void
ct_sync_expect_create(struct ip_conntrack_expect *exp)
@@ -1418,10 +1463,8 @@
return;
}
+#endif
-/* event processing macros */
-#define EVENT(e) (1 << (e))
-
static int
ct_sync_notify(struct notifier_block *this,
unsigned long events, void *ct)
@@ -1429,14 +1472,14 @@
if ((struct ip_conntrack *)ct == &ip_conntrack_untracked)
return NOTIFY_DONE;
- if (events & EVENT(IPCT_NEW)) {
+ if (events & IPCT_NEW) {
ct_sync_create((struct ip_conntrack *)ct, 1);
- } else if (events & (EVENT(IPCT_STATUS) | EVENT(IPCT_PROTOINFO) |
- EVENT(IPCT_HELPINFO) | EVENT(IPCT_NATINFO))) {
+ } else if (events & (IPCT_STATUS | IPCT_PROTOINFO |
+ IPCT_HELPINFO | IPCT_NATINFO)) {
ct_sync_create((struct ip_conntrack *)ct, 0);
- } else if (events & EVENT(IPCT_DESTROY)) {
+ } else if (events & IPCT_DESTROY) {
ct_sync_destroy((struct ip_conntrack *)ct);
}
@@ -1451,7 +1494,7 @@
};
/***********************************************************************
- * conntrack exemptions
+ * NOTRACK (conntrack exemptions)
***********************************************************************/
static unsigned int
@@ -1467,7 +1510,6 @@
/* all traffic coming in or going out sync interface is not
to be tracked. Also, loopback traffic is ignored */
- /* FIXME: implement this based on ifindex matching */
if ((hook == NF_IP_PRE_ROUTING && indev &&
indev->ifindex == cts_cfg.ifindex) ||
(hook == NF_IP_LOCAL_OUT && outdev &&
@@ -1476,7 +1518,8 @@
(outdev && outdev == &loopback_dev)) {
/* Attach fake conntrack entry */
- (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
+ (*pskb)->nfct = &ip_conntrack_untracked.ct_general;
+ (*pskb)->nfctinfo = IP_CT_NEW;
nf_conntrack_get((*pskb)->nfct);
}
@@ -1510,7 +1553,6 @@
return NF_ACCEPT;
}
-
static struct nf_hook_ops cts_hook_ops[] = {
{ .hook = notrack_hook,
.pf = PF_INET,
@@ -1531,182 +1573,96 @@
};
/***********************************************************************
- * SYSCTL HANDLING
+ * CT_SYNC_PROTO CALLBACK
***********************************************************************/
-/* sysctl variables */
-static int cts_sysctl_state;
-
-static int
-cts_sysctl_change_state(int state)
+/* This could be converted to notifiers ... */
+static void
+ct_sync_state_transition(struct cts_protoh *cph,
+ enum cts_proto_state oldstate,
+ enum cts_proto_state newstate,
+ void *data)
{
CT_SYNC_ENTER();
- if ((state == 0) && cts_proto_is_master(cts_cfg.protoh)) {
- CTS_STAT_INC(master2slave);
- CT_SYNC_ERR("cannot switch active master to client!\n");
- CT_SYNC_LEAVE();
- return -EINVAL;
- } else if (state == 1) {
- if (!cts_proto_is_master(cts_cfg.protoh)) {
+ switch (newstate) {
+ case CT_SYNC_PSTATE_NONE:
+ break;
- ct_sync_start_timers();
+ case CT_SYNC_PSTATE_SLAVE_INIT:
+ case CT_SYNC_PSTATE_SLAVE_SYNRECV:
+ if (oldstate == CT_SYNC_PSTATE_NONE) {
+ /* initial slave synchronization: we don't stop
+ * conntrack timers when being initialized to
+ * slave: this could cause connections left in
+ * the conntrack hash for an indefinite amount
+ * of time... */
+ } else if (oldstate >= CT_SYNC_PSTATE_MASTER_INIT) {
+ /* transition from master to slave */
+ ip_conntrack_unregister_notifier(&ct_sync_notifier);
+ ct_sync_stop_timers();
+ }
+ break;
- if (ip_conntrack_notify_register(&ct_sync_notifier) < 0) {
+ case CT_SYNC_PSTATE_MASTER_INIT:
+ if (oldstate < CT_SYNC_PSTATE_MASTER_INIT) {
+ /* transition from none/slave to master */
+ ct_sync_start_timers();
+ if (ip_conntrack_register_notifier(&ct_sync_notifier) < 0) {
CT_SYNC_ERR("cannot register notifier\n");
- CT_SYNC_LEAVE();
- return -EINVAL;
}
-
- if (cts_proto_become_master(cts_cfg.protoh) < 0) {
- CT_SYNC_ERR("proto said we cannot become master\n");
- CT_SYNC_LEAVE();
- return -EINVAL;
- }
- } else {
- CT_SYNC_INFO("we already are master; staying cool");
}
+ break;
+
+ default:
+ break;
}
CT_SYNC_LEAVE();
-
- return 0;
}
-static void
-cts_sysctl_update_state(void)
-{
- cts_sysctl_state = cts_proto_is_master(cts_cfg.protoh);
-}
-
-static int
-cts_sysctl_state_handler(ctl_table *table, int write,
- struct file *filp, void *buffer,
- size_t *lenp)
-{
- int res;
-
- if (write) {
- res = proc_dointvec(table, write, filp, buffer, lenp);
- if (res < 0)
- return res;
- return cts_sysctl_change_state(cts_sysctl_state);
- } else {
- cts_sysctl_update_state();
- return proc_dointvec(table, write, filp, buffer, lenp);
- }
-}
-
-/* FIXME: define this in sysctl.h */
-#define NET_IPV4_NF_CONNTRACK_SYNC 20
-
-enum {
- CTS_SYSCTL_STATE = 1,
-};
-
-static ctl_table ct_sync_sysctl_table[] = {
- {
- .ctl_name = CTS_SYSCTL_STATE,
- .procname = "state",
- .mode = 0644,
- .data = &cts_sysctl_state,
- .maxlen = sizeof(int),
- .proc_handler = &cts_sysctl_state_handler
- },
- { .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_cts_table[] = {
- {
- .ctl_name = NET_IPV4_NF_CONNTRACK_SYNC,
- .procname = "ct_sync",
- .mode = 0555,
- .child = ct_sync_sysctl_table,
- },
- { .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_netfilter_table[] = {
- {
- .ctl_name = NET_IPV4_NETFILTER,
- .procname = "netfilter",
- .mode = 0555,
- .child = ct_sync_cts_table,
- },
- { .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_net_table[] = {
- {
- .ctl_name = NET_IPV4,
- .procname = "ipv4",
- .mode = 0555,
- .child = ct_sync_netfilter_table,
- },
- { .ctl_name = 0 }
-};
-
-static ctl_table ct_sync_root_table[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .mode = 0555,
- .child = ct_sync_net_table,
- },
- { .ctl_name = 0 }
-};
-
-static struct ctl_table_header *ct_sync_sysctl_header;
-
/***********************************************************************
- * CT_SYNC_PROTO CALLBACK
- ***********************************************************************/
-
-/* This could be converted to notifiers ... */
-
-static void
-ct_sync_became_slave(struct cts_protoh *cph, void *data)
-{
- ip_conntrack_notify_unregister(&ct_sync_notifier);
- ct_sync_stop_timers();
-}
-
-/***********************************************************************
* STATISTICS
***********************************************************************/
-static void *cts_stat_seq_start(struct seq_file *seq, loff_t *pos)
+static void *
+cts_stat_seq_start(struct seq_file *seq, loff_t *pos)
{
- int lcpu;
+ int cpu;
if (*pos == 0)
return SEQ_START_TOKEN;
- for (lcpu = *pos-1; lcpu < smp_num_cpus; ++lcpu) {
- int i = cpu_logical_map(lcpu);
- *pos = lcpu+1;
- return &ct_sync_stats[i];
+ for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+ if (!cpu_possible(cpu))
+ continue;
+ *pos = cpu+1;
+ return &per_cpu(ct_sync_stats, cpu);
}
return NULL;
}
-static void *cts_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *
+cts_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- int lcpu;
+ int cpu;
- for (lcpu = *pos; lcpu < smp_num_cpus; ++lcpu) {
- int i = cpu_logical_map(lcpu);
- *pos = lcpu+1;
- return &ct_sync_stats[i];
+ for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+ if (!cpu_possible(cpu))
+ continue;
+ *pos = cpu+1;
+ return &per_cpu(ct_sync_stats, cpu);
}
return NULL;
}
-static void cts_stat_seq_stop(struct seq_file *seq, void *v)
+static void
+cts_stat_seq_stop(struct seq_file *seq, void *v)
{
}
-static void cts_stat_seq_show_st(struct seq_file *seq, struct ct_sync_st *s)
+static void
+cts_stat_seq_show_st(struct seq_file *seq, struct ct_sync_st *s)
{
seq_printf(seq, "%lu %lu %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu %lu %lu %lu ",
@@ -1718,14 +1674,24 @@
s->exp_upd_tot, s->exp_del_tot);
}
-static int cts_stat_seq_show(struct seq_file *seq, void *v)
+static int
+cts_stat_seq_show(struct seq_file *seq, void *v)
{
struct ct_sync_stat *stats = v;
if (v == SEQ_START_TOKEN) {
- seq_printf(seq, "tx_pkts_tot tx_pkts_ooseq tx_pkts_recover tx_msgs tx_error tx_upd_tot tx_upd_new tx_upd_initial tx_upd_newbutexist tx_upd_nothere tx_del_tot tx_del_nothere tx_exp_upd_tot tx_exp_del_tot ");
- seq_printf(seq, "rx_pkts_tot rx_pkts_ooseq rx_pkts_recover rx_msgs rx_error rx_upd_tot rx_upd_new rx_upd_initial rx_upd_newbutexist rx_upd_nothere rx_del_tot rx_del_nothere rx_exp_upd_tot rx_exp_del_tot ");
- seq_printf(seq, "slave2master master2slave master2slave_auto initsyncs\n");
+ seq_printf(seq, "tx_pkts_tot tx_pkts_ooseq tx_pkts_recover "
+ "tx_msgs tx_error tx_upd_tot tx_upd_new "
+ "tx_upd_initial tx_upd_newbutexist tx_upd_nothere "
+ "tx_del_tot tx_del_nothere tx_exp_upd_tot "
+ "tx_exp_del_tot ");
+ seq_printf(seq, "rx_pkts_tot rx_pkts_ooseq rx_pkts_recover "
+ "rx_msgs rx_error rx_upd_tot rx_upd_new "
+ "rx_upd_initial rx_upd_newbutexist rx_upd_nothere "
+ "rx_del_tot rx_del_nothere rx_exp_upd_tot "
+ "rx_exp_del_tot ");
+ seq_printf(seq, "slave2master master2slave master2slave_auto "
+ "initsyncs\n");
return 0;
}
@@ -1762,15 +1728,20 @@
* MODULE INITIALIZATION
***********************************************************************/
+static int
+kill_all(const struct ip_conntrack *i, void *data)
+{
+ return 1;
+}
+
+static struct task_struct *rcv_thread, *send_thread, *initsync_thread;
+
/* DO NOT declare this as __init!! */
-int init_or_cleanup(int fini)
+static int
+init_or_cleanup(int fini)
{
- int ret = -1;
- pid_t pid;
- struct ct_thread_startup startup;
- DECLARE_WAITQUEUE(wait, current);
- DECLARE_COMPLETION(ct_thread_comp);
- struct net_device *sync_netdev;
+ int err, ret = -1;
+ struct net_device *sync_netdev;
struct proc_dir_entry *ct_sync_stat;
if (fini)
@@ -1788,25 +1759,12 @@
CT_SYNC_DEBUG("ct_sync_msghdr: %d bytes\n",
sizeof(struct ct_sync_msghdr));
CT_SYNC_DEBUG("cmarkbit: %d\n", cmarkbit);
- if (id == -1) {
- CT_SYNC_ERR("Required parameter id is missing.\n");
- return -1;
- }
+
if (strcmp(syncdev, "") == 0) {
CT_SYNC_ERR("Required parameter syncdev is missing.\n");
return -1;
}
- if (state == -1) {
- CT_SYNC_ERR("Required parameter state is missing; "
- " give 1 for master and 0 for slave.\n");
- return -1;
- }
- if (state != 0 && state != 1) {
- CT_SYNC_ERR("State has to be either 0 or 1\n");
- return -1;
- }
- cts_cfg.nodeid = id;
strcpy(cts_cfg.devname, syncdev);
cts_cfg.addr.sin_family = AF_INET;
cts_cfg.addr.sin_port = __constant_htons(1999);
@@ -1824,8 +1782,8 @@
}
/* init protocol layer */
- cts_cfg.protoh = cts_proto_init(cts_cfg.devname, &cts_cfg.addr, id,
- state, &ct_sync_became_slave, NULL,
+ cts_cfg.protoh = cts_proto_init(cts_cfg.devname, &cts_cfg.addr,
+ &ct_sync_state_transition, NULL,
&ct_sync_send_wait, &ct_sync_rcv_wait);
if (!cts_cfg.protoh) {
CT_SYNC_ERR("Failed to initialize protocol.\n");
@@ -1859,9 +1817,11 @@
goto error_sysctl;
ct_sync_stat->proc_fops = &cts_stat_seq_fops;
+#if 0
+ /* FIXME: should use the unified state change functions */
if (state) {
/* master: register notify callbacks */
- ret = ip_conntrack_notify_register(&ct_sync_notifier);
+ ret = ip_conntrack_register_notifier(&ct_sync_notifier);
if (ret < 0) {
CT_SYNC_ERR("unable to register notifier\n");
goto error_stat;
@@ -1880,102 +1840,59 @@
/* initsync request is handled by kernel thread */
}
+#endif
/* start threads */
- startup.completion = &ct_thread_comp;
- startup.function = ct_sync_send_thread_main;
- if ((pid = kernel_thread(fork_ct_thread, &startup, 0)) < 0)
- {
- CT_SYNC_ERR("Failed to start fork thread.\n");
- ret = pid;
- if (state)
- goto error_notify;
- else
- goto error_stat;
+ rcv_thread = kthread_run(ct_sync_rcv_thread_main, NULL,
+ "ct_sync_rcv");
+ if (IS_ERR(rcv_thread)) {
+ ret = PTR_ERR(rcv_thread);
+ goto error_notify;
}
- if ((ret = waitpid(pid, NULL, __WCLONE)) != pid)
- {
- CT_SYNC_ERR("Fork thread exit problem.\n");
- if (state)
- goto error_notify;
- else
- goto error_stat;
+
+ send_thread = kthread_run(ct_sync_send_thread_main, NULL,
+ "ct_sync_send");
+ if (IS_ERR(send_thread)) {
+ ret = PTR_ERR(send_thread);
+ goto error_rthread;
}
- wait_for_completion(&ct_thread_comp);
- init_completion(&ct_thread_comp);
- startup.completion = &ct_thread_comp;
- startup.function = ct_sync_rcv_thread_main;
- if ((pid = kernel_thread(fork_ct_thread, &startup, 0)) < 0)
- {
- CT_SYNC_ERR("Failed to start fork thread.\n");
- ret = pid;
+ initsync_thread = kthread_run(ct_sync_initsync_thread_main, NULL,
+ "ct_sync_initsync");
+ if (IS_ERR(initsync_thread)) {
+ ret = PTR_ERR(initsync_thread);
goto error_sthread;
}
- if ((ret = waitpid(pid, NULL, __WCLONE)) != pid)
- {
- CT_SYNC_ERR("Fork thread exit problem.\n");
- goto error_sthread;
- }
- wait_for_completion(&ct_thread_comp);
- init_completion(&ct_thread_comp);
- startup.completion = &ct_thread_comp;
- startup.function = ct_sync_initsync_thread_main;
- if ((pid = kernel_thread(fork_ct_thread, &startup, 0)) < 0)
- {
- CT_SYNC_ERR("Failed to start fork thread.\n");
- ret = pid;
- goto error_rthread;
- }
- if ((ret = waitpid(pid, NULL, __WCLONE)) != pid)
- {
- CT_SYNC_ERR("Fork thread exit problem.\n");
- goto error_rthread;
- }
- wait_for_completion(&ct_thread_comp);
-
/* Now we have all of our infrastructure up and running */
+ printk(KERN_NOTICE "netfilter conntrack_sync version %s loaded\n",
+ CT_SYNC_VERSION);
+ CT_SYNC_INFO("parameters: 'syncdev=%s l2drop=%u'\n",
+ syncdev, l2drop);
-
- printk(KERN_NOTICE "netfilter conntrack_sync Version %s loaded\n",
- CT_SYNC_VERSION);
- CT_SYNC_INFO("parameters: 'id=%u state=%u syncdev=%s l2drop=%u'\n",
- id, state, syncdev, l2drop);
-
return 0;
cleanup:
-error_ithread:
CT_SYNC_DEBUG("stopping initsync thread\n");
- __set_current_state(TASK_INTERRUPTIBLE);
- wake_up(&ct_sync_initsync_wait);
- atomic_set(&stop_ct_initsync_thread, 1);
- add_wait_queue(&stop_ct_initsync_thread_wait, &wait);
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&stop_ct_initsync_thread_wait, &wait);
-error_rthread:
- CT_SYNC_DEBUG("stopping receive thread\n");
- __set_current_state(TASK_INTERRUPTIBLE);
- atomic_set(&stop_ct_rcv_thread, 1);
- add_wait_queue(&stop_ct_rcv_thread_wait, &wait);
- wake_up(&ct_sync_rcv_wait);
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&stop_ct_rcv_thread_wait, &wait);
+ err = kthread_stop(initsync_thread);
+ if (err < 0) {
+ CT_SYNC_INFO("unable to stop initsync thread\n");
+ }
error_sthread:
CT_SYNC_DEBUG("stopping send thread\n");
- __set_current_state(TASK_INTERRUPTIBLE);
- atomic_set(&stop_ct_send_thread, 1);
- add_wait_queue(&stop_ct_send_thread_wait, &wait);
- wake_up(&ct_sync_send_wait);
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&stop_ct_send_thread_wait, &wait);
+ err = kthread_stop(send_thread);
+ if (err < 0) {
+ CT_SYNC_INFO("unable to stop send thread\n");
+ }
+error_rthread:
+ CT_SYNC_DEBUG("stopping receive thread\n");
+ err = kthread_stop(rcv_thread);
+ if (err < 0) {
+ CT_SYNC_INFO("unable to stop receive thread\n");
+ }
error_notify:
CT_SYNC_DEBUG("unregistering conntrack notifier\n");
- ip_conntrack_notify_unregister(&ct_sync_notifier);
+ ip_conntrack_unregister_notifier(&ct_sync_notifier);
error_stat:
remove_proc_entry("ct_sync_stat", proc_net_stat);
error_sysctl:
@@ -2009,10 +1926,9 @@
void __exit fini(void)
{
init_or_cleanup(1);
- printk(KERN_NOTICE "netfilter conntrack_sync Version %s unloaded\n",
+ printk(KERN_NOTICE "netfilter conntrack_sync version %s unloaded\n",
CT_SYNC_VERSION);
}
module_init(init);
module_exit(fini);
-
Deleted: branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.h
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.h 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_main.h 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,6 +0,0 @@
-#ifndef _CT_SYNC_MAIN_H
-#define _CT_SYNC_MAIN_H
-
-extern atomic_t stop_ct_send_thread;
-
-#endif /* _CT_SYNC_MAIN_H */
Modified: branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.c
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.c 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.c 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,7 +1,7 @@
/*
* Connection tracking state replication for Netfilter
*
- * (C) 2002-2003, KOVACS Krisztian <hidden at sch.bme.hu>
+ * (C) 2002-2004, KOVACS Krisztian <hidden at sch.bme.hu>
* (C) 2003-2004, Harald Welte <laforge at netfilter.org>
* (C) 2004, BalaBit IT Ltd. <www.balabit.com>
*
@@ -9,8 +9,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * $Id$
- *
*/
#include <linux/config.h>
@@ -53,8 +51,6 @@
-sizeof(struct ct_sync_pkthdr))
#define CT_SYNC_SEND_BACKLOG 32
-#define CT_SYNC_MAX_MSG_AGE (2 * HZ)
-
struct cts_proto_sock {
struct csb_ring ring;
struct socket *socket;
@@ -62,12 +58,20 @@
};
struct cts_protoh {
+ /* tx and rx sockets */
struct cts_proto_sock send;
struct cts_proto_sock recv;
+ /* node state */
atomic_t state;
- u8 nodeid;
- void (*became_slave)(struct cts_protoh *, void *);
- void *became_slave_arg;
+ /* callback function to call on state transitions */
+ void (*transition_callback)(struct cts_protoh *,
+ enum cts_proto_state,
+ enum cts_proto_state,
+ void *);
+ void *transition_callback_data;
+ /* timestamp of last initsync request */
+ unsigned long last_initsync;
+ /* recovery state of the node */
struct {
atomic_t active;
__u16 seq;
@@ -75,19 +79,6 @@
} recovery_request;
};
-/* node status */
-enum cts_proto_state
-{
- CT_SYNC_PSTATE_NONE = 0x00, /* unknown, illegal */
- CT_SYNC_PSTATE_SLAVE_INIT = 0x01, /* has just started */
- CT_SYNC_PSTATE_SLAVE_SYNSENT = 0x02, /* has requested initial sync */
- CT_SYNC_PSTATE_SLAVE_SYNRECV = 0x03, /* is receiving initial sync */
- CT_SYNC_PSTATE_SLAVE_RUNNING = 0x04, /* slave, fully synced */
- CT_SYNC_PSTATE_MASTER_INIT = 0x11, /* master has just started */
- CT_SYNC_PSTATE_MASTER_ADVSENT= 0x12, /* master has announced */
- CT_SYNC_PSTATE_MASTER_RUNNING= 0x14, /* master, running */
-};
-
static const char *cts_proto_statenames[0x15] = {
[CT_SYNC_PSTATE_NONE] = "NONE",
[CT_SYNC_PSTATE_SLAVE_INIT] = "SLAVE_INIT",
@@ -105,16 +96,52 @@
unsigned int oldstate = atomic_read(&cph->state);
atomic_set(&cph->state, state);
CT_SYNC_INFO("changed state: %s -> %s\n",
- cts_proto_statenames[oldstate],
- cts_proto_statenames[state]);
+ cts_proto_statenames[oldstate],
+ cts_proto_statenames[state]);
+ if (oldstate != state
+ && cph->transition_callback != NULL)
+ cph->transition_callback(cph, oldstate, state,
+ cph->transition_callback_data);
}
-const char *cts_proto_get_state_name(struct cts_protoh *cph)
+int
+cts_proto_is_master(struct cts_protoh *cph)
{
- return cts_proto_statenames[atomic_read(&cph->state)];
+ return (atomic_read(&cph->state) >= CT_SYNC_PSTATE_MASTER_INIT);
}
+int
+cts_proto_get_state(struct cts_protoh *cph)
+{
+ return atomic_read(&cph->state);
+}
+
/***********************************************************************
+ * SYSCTL functions
+ ***********************************************************************/
+
+/* upper limit is one minute */
+#define MSG_AGE_LIMIT 60000
+static unsigned long max_msg_age = 2 * HZ;
+
+unsigned int
+cts_proto_get_max_age(void)
+{
+ return jiffies_to_msecs(max_msg_age);
+}
+
+int
+cts_proto_set_max_age(unsigned int msecs)
+{
+ if (msecs > MSG_AGE_LIMIT)
+ return -EINVAL;
+
+ max_msg_age = msecs_to_jiffies(msecs);
+
+ return 0;
+}
+
+/***********************************************************************
* CTS_BUFF / CSB_RING util functions
***********************************************************************/
static inline void
@@ -124,7 +151,6 @@
hdr->version = 2;
hdr->pkttype = type;
hdr->pktseq = htons(seq);
- hdr->node_id = cph->nodeid;
hdr->count = 0;
}
@@ -288,8 +314,9 @@
* after advancing to the next buffer, while the receiver code handles the seqno
* of the ring specially (it is the sequence number of the last successfully
* received packet). */
-static struct cts_buff * __csb_ring_advance_alloc(struct cts_protoh *cph,
- struct csb_ring *csr)
+static struct cts_buff *
+__csb_ring_advance_alloc(struct cts_protoh *cph,
+ struct csb_ring *csr)
{
struct cts_buff *csb;
@@ -330,13 +357,6 @@
* CONTROL MESSAGES
***********************************************************************/
-int
-cts_proto_is_master(struct cts_protoh *cph)
-{
- return (atomic_read(&cph->state) >= CT_SYNC_PSTATE_MASTER_INIT);
-}
-
-
/* we have just been told to become master; tell other nodes */
int
cts_proto_master_announce(struct cts_protoh *cph)
@@ -352,6 +372,7 @@
CT_SYNC_DEBUG("sending master_announce with seqno=%u\n",
cph->send.ring.seqno);
+ memset(&pkt, 0, sizeof(pkt));
csb_hdr_fill(cph, &pkt.hdr, CT_SYNC_PKT_MASTER_ANNOUNCE,
cph->send.ring.seqno);
@@ -396,6 +417,19 @@
return 0;
}
+/* externally triggered: we become slave */
+int
+cts_proto_become_slave(struct cts_protoh *cph)
+{
+ CT_SYNC_ENTER();
+
+ set_state(cph, CT_SYNC_PSTATE_SLAVE_INIT);
+
+ CT_SYNC_LEAVE();
+
+ return 0;
+}
+
/* externally triggered: we're signalling a full re-sync */
int
cts_proto_initsync_follows(struct cts_protoh *cph)
@@ -407,6 +441,7 @@
CT_SYNC_ENTER();
+ memset(&pkt, 0, sizeof(pkt));
csb_hdr_fill(cph, &pkt.hdr, CT_SYNC_PKT_INITSYNC_FOLLOWS, 0);
len = cts_sock_send(cph->send.socket, (unsigned char *)&pkt, sizeof(pkt));
@@ -421,8 +456,9 @@
return 0;
}
-int
-cts_proto_request_initsync(struct cts_protoh *cph)
+/* send an initsync request */
+static int
+cts_proto_send_initsync_request(struct cts_protoh *cph)
{
size_t len;
struct {
@@ -432,18 +468,12 @@
CT_SYNC_ENTER();
- if (atomic_read(&cph->state) != CT_SYNC_PSTATE_SLAVE_INIT) {
- CT_SYNC_DEBUG("not sending initsync request from wrong state\n");
- CT_SYNC_LEAVE();
- return 0;
- }
-
CTS_STAT_INC(initsyncs);
CT_SYNC_DEBUG("sending INITSYNC request\n");
+ memset(&pkt, 0, sizeof(pkt));
csb_hdr_fill(cph, &pkt.hdr, CT_SYNC_PKT_SLAVE_INITSYNC, 0);
- pkt.is.master = 0;
len = cts_sock_send(cph->send.socket, (unsigned char*)&pkt, sizeof(pkt));
if (unlikely(len < sizeof(pkt))) {
@@ -458,41 +488,25 @@
return 0;
}
+/* externally triggered: transmit an initsync request if necessary:
+ * - we're in state CT_SYNC_PSTATE_SLAVE_INIT
+ * - we're in state CT_SYNC_PSTATE_SLAVE_SYNSENT but at least five seconds
+ * have elapsed since the last request
+ */
int
-cts_proto_initsync_retransmit(struct cts_protoh *cph)
+cts_proto_initsync_request(struct cts_protoh *cph)
{
- static unsigned long last_initsync;
+ if ((atomic_read(&cph->state) == CT_SYNC_PSTATE_SLAVE_INIT)
+ || (atomic_read(&cph->state) == CT_SYNC_PSTATE_SLAVE_SYNSENT
+ && jiffies >= cph->last_initsync + 5 * HZ)) {
+ cts_proto_send_initsync_request(cph);
+ cph->last_initsync = jiffies;
+ set_state(cph, CT_SYNC_PSTATE_SLAVE_SYNSENT);
+ }
- if (atomic_read(&cph->state) == CT_SYNC_PSTATE_NONE)
- atomic_set(&cph->state, CT_SYNC_PSTATE_SLAVE_INIT);
-
- /* if we are waiting for a reply to an initial sync,
- * retransmit request */
- if (atomic_read(&cph->state) == CT_SYNC_PSTATE_SLAVE_INIT
- && jiffies >= last_initsync + 5*HZ) {
- cts_proto_request_initsync(cph);
- last_initsync = jiffies;
- }
return 0;
}
-/* protocol has detected another master. we have to tell our user
- * that we just became slave */
-static void
-cts_proto_become_slave(struct cts_protoh *cph)
-{
- CT_SYNC_ENTER();
-
- CTS_STAT_INC(master2slave_auto);
-
- set_state(cph, CT_SYNC_PSTATE_SLAVE_RUNNING);
- if (likely(cph->became_slave != NULL))
- cph->became_slave(cph, cph->became_slave_arg);
-
- CT_SYNC_LEAVE();
-}
-
-
/***********************************************************************
* SENDER
***********************************************************************/
@@ -528,7 +542,8 @@
}
/* decrement usage count and advance csb->cur if we hit zero */
-void csb_use_dec(struct cts_protoh *cph, struct cts_buff *csb)
+void
+csb_use_dec(struct cts_protoh *cph, struct cts_buff *csb)
{
CT_SYNC_ENTER();
DUMP_CTS_BUFF(csb);
@@ -577,7 +592,7 @@
*/
if (!csb_used(tmp)
&& (tmp != (struct cts_buff *)csr->cur)
- && tmp->firstuse && (jiffies - tmp->firstuse > CT_SYNC_MAX_MSG_AGE)) {
+ && tmp->firstuse && (jiffies - tmp->firstuse > max_msg_age)) {
tmp = __csb_ring_advance_alloc(cph, csr);
if (unlikely(tmp == NULL)) {
spin_unlock_bh(&csr->lock);
@@ -600,7 +615,6 @@
return 0;
}
-
/* caller wants to enqueue `size' bytes. we have to return pointer to csb that
* is capable of that many bytes */
@@ -628,7 +642,7 @@
* 3. not enough space, need to advance/allocate new csb
*/
if (tmp == (struct cts_buff *)csr->cur
- || (tmp->firstuse && (jiffies - tmp->firstuse >= CT_SYNC_MAX_MSG_AGE))
+ || (tmp->firstuse && (jiffies - tmp->firstuse >= max_msg_age))
|| !(retbuf = csb_put(tmp, size))) {
tmp = __csb_ring_advance_alloc(cph, csr);
if (unlikely(!tmp)) {
@@ -643,7 +657,7 @@
CT_SYNC_ASSERT(retbuf);
csb_use_inc(tmp);
-
+
CT_SYNC_DEBUG2("using buffer %p: ", tmp);
DUMP_CTS_BUFF(tmp);
@@ -847,7 +861,6 @@
return 0;
}
-
/***********************************************************************
* RECEIVER
***********************************************************************/
@@ -863,7 +876,8 @@
cph->recovery_request.diff = 0;
}
-#define CTS_RECOVERY_THRESHOLD 8
+unsigned int cts_proto_recovery_threshold = 8;
+
/*
* request recovery, last seen packet is seq
*/
@@ -877,18 +891,19 @@
/* check if we already have a pending request */
if (atomic_read(&cph->recovery_request.active)) {
- /* if there are at least CTS_RECOVERY_THRESHOLD lost messages
+ /* if there are at least recovery_threshold lost messages
* since the last request, repeat; return immediately otherwise */
- if (diff < cph->recovery_request.diff + CTS_RECOVERY_THRESHOLD) {
+ if (diff < cph->recovery_request.diff + cts_proto_recovery_threshold) {
CT_SYNC_LEAVE();
return 0;
}
}
+ atomic_set(&cph->recovery_request.active, 1);
cph->recovery_request.seq = seq;
cph->recovery_request.diff = diff;
- atomic_set(&cph->recovery_request.active, 1);
+ memset(&hdr, 0, sizeof(hdr));
csb_hdr_fill(cph, &hdr, CT_SYNC_PKT_NACK, seq);
len = cts_sock_send(cph->send.socket, (char *)&hdr,
@@ -942,7 +957,6 @@
return ret;
}
-
/* Receive packet, process packet header info. That is:
* - For invalid packets, discard the packet.
* Return value: CTS_PROTO_RCV_DISCARDED
@@ -971,7 +985,7 @@
CT_SYNC_ENTER();
- /* FIXME: do we need spinlock here? Only called from kthread,
+ /* FIXME: do we need a spinlock here? Only called from kthread,
* which is serialized. Seems that the receive ring is accessed
* only from the receiver thread, so locking shouldn't be a problem.
*/
@@ -1019,7 +1033,6 @@
/* do we really want to accept sync pkts before we
* requested them? For now, fallthrough */
case CT_SYNC_PSTATE_SLAVE_SYNSENT:
- break;
/* set initial seqno */
csr->seqno = ntohs(csb->pkt.hdr.pktseq) - 1;
printk(KERN_DEBUG "setting initial seqno to %u\n",
@@ -1074,8 +1087,7 @@
goto done_ignore;
}
recover_seq = ntohs(csb->pkt.hdr.pktseq);
- CT_SYNC_DEBUG("node %u requested recovery of seq %u\n",
- csb->pkt.hdr.node_id, recover_seq);
+ CT_SYNC_DEBUG("requested recovery of seq %u\n", recover_seq);
/* need to go back one in order to overwrite this one */
csr->alloc = csr->alloc->prev;
/* free spinlock early to avoid deadlock with send lock */
@@ -1094,7 +1106,8 @@
case CT_SYNC_PSTATE_MASTER_ADVSENT:
case CT_SYNC_PSTATE_MASTER_RUNNING:
CT_SYNC_INFO("new master, degrading to client\n");
- cts_proto_become_slave(cph);
+ CTS_STAT_INC(master2slave_auto);
+ set_state(cph, CT_SYNC_PSTATE_SLAVE_SYNSENT);
/* fall thru */
default:
/* we have a new master, we have to update our receiver's
@@ -1131,7 +1144,6 @@
break;
case CT_SYNC_PKT_INITSYNC_FOLLOWS:
-#if 0
switch (atomic_read(&cph->state)) {
case CT_SYNC_PSTATE_MASTER_INIT:
case CT_SYNC_PSTATE_MASTER_ADVSENT:
@@ -1146,10 +1158,9 @@
case CT_SYNC_PSTATE_SLAVE_RUNNING:
CT_SYNC_DEBUG("received initsync announcement while being slave, reinit\n");
cts_proto_recovery_init(cph);
- set_state(cph, CT_SYNC_PSTATE_SLAVE_INIT);
+ set_state(cph, CT_SYNC_PSTATE_SLAVE_SYNSENT);
break;
}
-#endif
goto done_ignore;
break;
@@ -1179,17 +1190,9 @@
int
cts_proto_recv_pending(struct cts_protoh *cph)
{
- return (!skb_queue_empty(&cph->recv.socket->sk->receive_queue));
+ return (!skb_queue_empty(&cph->recv.socket->sk->sk_receive_queue));
}
-/* Set receiver to running state if it's in SYNRECV state. */
-void
-cts_proto_recv_running(struct cts_protoh *cph)
-{
- if (atomic_read(&cph->state) == CT_SYNC_PSTATE_SLAVE_SYNRECV)
- set_state(cph, CT_SYNC_PSTATE_SLAVE_RUNNING);
-}
-
/* get a pointer to the next to-be-processed message */
struct ct_sync_msghdr *
cts_proto_recvmsg(struct cts_protoh *cph, struct ct_sync_pkthdr **hdr)
@@ -1263,11 +1266,18 @@
csr_print(csr);
//spin_unlock(&csr->lock);
+ /* upon receiving a message with the INITSYNC flag set, we
+ * transition from SLAVE_INIT to SLAVE_SYNRECV */
if (unlikely(msghdr->type == CT_SYNC_MSG_UPDATE
&& msghdr->flags & CTS_UPD_F_INITSYNC
&& atomic_read(&cph->state) == CT_SYNC_PSTATE_SLAVE_INIT))
set_state(cph, CT_SYNC_PSTATE_SLAVE_SYNRECV);
+ if (unlikely(msghdr->type == CT_SYNC_MSG_UPDATE
+ && msghdr->flags & CTS_UPD_F_INITSYNC_DONE
+ && atomic_read(&cph->state) == CT_SYNC_PSTATE_SLAVE_SYNRECV))
+ set_state(cph, CT_SYNC_PSTATE_SLAVE_RUNNING);
+
CT_SYNC_LEAVE();
return msghdr;
@@ -1275,31 +1285,31 @@
/* data ready callback: wake up rcv thread */
static void
-cts_data_ready(struct sock *sk, int count)
+cts_proto_data_ready(struct sock *sk, int count)
{
struct cts_protoh *cph;
CT_SYNC_ENTER();
- cph = (struct cts_protoh *)sk->user_data;
+ cph = (struct cts_protoh *)sk->sk_user_data;
if (cph && cph->recv.wait && waitqueue_active(cph->recv.wait))
wake_up_interruptible(cph->recv.wait);
- if (sk->sleep && waitqueue_active(sk->sleep))
- wake_up_interruptible(sk->sleep);
+ if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+ wake_up_interruptible(sk->sk_sleep);
CT_SYNC_LEAVE();
}
-
/* initialize protocol */
struct cts_protoh *
cts_proto_init(char *devname,
const struct sockaddr_in *addr,
- u8 nodeid,
- int master,
- void (*became_slave)(struct cts_protoh*, void*),
- void *became_slave_arg,
+ void (*transition_callback)(struct cts_protoh*,
+ enum cts_proto_state,
+ enum cts_proto_state,
+ void*),
+ void *transition_callback_data,
wait_queue_head_t *send_wait,
wait_queue_head_t *rcv_wait)
{
@@ -1315,11 +1325,12 @@
goto error;
}
+ memset(cph, 0, sizeof(*cph));
+
/* don't call set_state since cph->state is not initialized yet */
atomic_set(&cph->state, CT_SYNC_PSTATE_NONE);
- cph->nodeid = nodeid;
- cph->became_slave = became_slave;
- cph->became_slave_arg = became_slave_arg;
+ cph->transition_callback = transition_callback;
+ cph->transition_callback_data = transition_callback_data;
/* init recovery structure */
cts_proto_recovery_init(cph);
@@ -1356,10 +1367,11 @@
CT_SYNC_ERR("Failed to create rcv socket.\n");
goto error_ssock;
}
- /* setup data_ready callback of receive socket */
- cph->recv.socket->sk->user_data = cph;
- cph->recv.socket->sk->data_ready = cts_data_ready;
+ /* setup sk_data_ready callback of receive socket */
+ cph->recv.socket->sk->sk_user_data = cph;
+ cph->recv.socket->sk->sk_data_ready = cts_proto_data_ready;
+
if (ret < 0)
goto error_rsock;
@@ -1396,4 +1408,3 @@
CT_SYNC_LEAVE();
}
-
Modified: branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.h
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.h 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_proto.h 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,17 +1,36 @@
#ifndef _CT_SYNC_PROTO_H
#define _CT_SYNC_PROTO_H
+#include <linux/in.h>
+
/* no need for a public declaration of cts_buff structure */
struct cts_buff;
struct cts_protoh;
-/* protocol intialization functions */
+/* protocol state machine */
+/* node status */
+enum cts_proto_state
+{
+ CT_SYNC_PSTATE_NONE = 0x00, /* unknown, illegal */
+ CT_SYNC_PSTATE_SLAVE_INIT = 0x01, /* has just started */
+ CT_SYNC_PSTATE_SLAVE_SYNSENT = 0x02, /* has requested initial sync */
+ CT_SYNC_PSTATE_SLAVE_SYNRECV = 0x03, /* is receiving initial sync */
+ CT_SYNC_PSTATE_SLAVE_RUNNING = 0x04, /* slave, fully synced */
+ CT_SYNC_PSTATE_MASTER_INIT = 0x11, /* master has just started */
+ CT_SYNC_PSTATE_MASTER_ADVSENT= 0x12, /* master has announced */
+ CT_SYNC_PSTATE_MASTER_RUNNING= 0x14, /* master, running */
+};
+
+/* GENERAL PROTOCOL LAYER FUNCTIONS */
+
+/* protocol intialization function */
struct cts_protoh *cts_proto_init(char *devname,
const struct sockaddr_in *addr,
- u8 nodeid, int master,
- void (*became_slave)(struct cts_protoh*,
- void *),
- void *became_slave_arg,
+ void (*transition_callback)(struct cts_protoh*,
+ enum cts_proto_state oldstate,
+ enum cts_proto_state newstate,
+ void *),
+ void *transition_callback_data,
wait_queue_head_t *send_wait,
wait_queue_head_t *rcv_wait);
@@ -21,18 +40,30 @@
/* is protocol state currently 'master' ? */
int cts_proto_is_master(struct cts_protoh *cph);
+/* return protocol state */
+int cts_proto_get_state(struct cts_protoh *cph);
+
/* tell protocol to make local node master */
int cts_proto_become_master(struct cts_protoh *cph);
+/* tell protocol to make local node slave (only from NONE!) */
+int cts_proto_become_slave(struct cts_protoh *cph);
+
+/* send a master announcement */
int cts_proto_master_announce(struct cts_protoh *cph);
/* signal that an initsync is to follow */
int cts_proto_initsync_follows(struct cts_protoh *cph);
-/* request initial re-sync from master */
-int cts_proto_request_initsync(struct cts_protoh *cph);
-int cts_proto_initsync_retransmit(struct cts_protoh *cph);
+/* request initial re-sync from master if necessary */
+int cts_proto_initsync_request(struct cts_protoh *cph);
+/* PARAMETERS */
+unsigned int cts_proto_get_max_age(void);
+int cts_proto_set_max_age(unsigned int msecs);
+
+extern unsigned int cts_proto_recovery_threshold;
+
/* SENDER */
/* advance current buffer of send ring if it's old enough,
@@ -49,8 +80,6 @@
/* dequeue a to-be-send cts_buff, otherwise put current task to sleep */
int cts_proto_send_dequeue(struct cts_protoh *cph);
-
-
/* RECEIVER */
/* possible return values of cts_proto_rcv_pkt() */
@@ -61,13 +90,12 @@
#define CTS_PROTO_RCV_MASTERANN 3
#define CTS_PROTO_RCV_INITSYNC 4
-/* check if we have pending packets in the receive buffer */
+/* check if we have pending packets in the receive queue of the rcv socket */
int cts_proto_recv_pending(struct cts_protoh *cph);
+
/* receive a packet, and enqueue it in the ring buffer if needed */
int cts_proto_recv_pkt(struct cts_protoh *cph);
-void cts_proto_recv_running(struct cts_protoh *cph);
-
/* get next message out of packet receiver queue */
struct ct_sync_msghdr *cts_proto_recvmsg(struct cts_protoh *cph, struct ct_sync_pkthdr **hdr);
Modified: branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_sock.c
===================================================================
--- branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_sock.c 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/ct_sync/ct_sync_sock.c 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,7 +1,7 @@
/*
* Connection tracking state replication for Netfilter
*
- * (C) 2002-2003, KOVACS Krisztian <hidden at sch.bme.hu>
+ * (C) 2002-2004, KOVACS Krisztian <hidden at sch.bme.hu>
* (C) 2003-2004, Harald Welte <laforge at netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -11,8 +11,6 @@
* Based on previous work from the LVS project
* (C) Wensong Zwang <wensong at linuxvirtualserver.org>
*
- * $Id$
- *
*/
#define __KERNEL_SYSCALLS__
@@ -35,6 +33,7 @@
#include <linux/rtnetlink.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
+#include <linux/ip.h>
#include <asm/uaccess.h>
@@ -48,7 +47,7 @@
{
/* setsockopt(sock, SOL_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); */
lock_sock(sk);
- sk->protinfo.af_inet.mc_loop = loop ? 1 : 0;
+ inet_sk(sk)->mc_loop = loop ? 1 : 0;
release_sock(sk);
}
@@ -60,7 +59,7 @@
{
/* setsockopt(sock, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); */
lock_sock(sk);
- sk->protinfo.af_inet.mc_ttl = ttl;
+ inet_sk(sk)->mc_ttl = ttl;
release_sock(sk);
}
@@ -73,12 +72,12 @@
if ((dev = __dev_get_by_name(ifname)) == NULL)
return -ENODEV;
- if (sk->bound_dev_if && dev->ifindex != sk->bound_dev_if)
+ if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
return -EINVAL;
lock_sock(sk);
- sk->protinfo.af_inet.mc_index = dev->ifindex;
- /* sk->protinfo.af_inet.mc_addr = 0; */
+ inet_sk(sk)->mc_index = dev->ifindex;
+ /* inet_sk(sk)->mc_addr = 0; */
release_sock(sk);
return 0;
@@ -127,7 +126,7 @@
if ((dev = __dev_get_by_name(ifname)) == NULL)
return -ENODEV;
- if (sk->bound_dev_if && dev->ifindex != sk->bound_dev_if)
+ if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
return -EINVAL;
mreq.imr_ifindex = dev->ifindex;
@@ -185,7 +184,7 @@
return NULL;
}
- sock->sk->reuse = 1;
+ sock->sk->sk_reuse = 1;
if (sock->ops->bind(sock, (struct sockaddr *)addr, sizeof(struct sockaddr)) < 0) {
CT_SYNC_ERR("Error binding to the multicast addr.\n");
Modified: branches/netfilter-ha/linux-2.6/patches/connmark.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/connmark.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/connmark.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,10 +1,22 @@
-Netfilter CONNMARK patch
-
-%patch
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_CONNMARK.h
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack.h
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-06-28 12:58:18.000000000 +0200
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-11-27 00:29:34.768960072 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack.h 2004-11-27 00:44:47.467208848 +0100
+@@ -264,6 +264,10 @@
+ } nat;
+ #endif /* CONFIG_IP_NF_NAT_NEEDED */
+
++#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
++ unsigned long mark;
++#endif
++
+ /* Traversed often, so hopefully in different cacheline to top */
+ /* These are my tuples; original and reply */
+ struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ipt_CONNMARK.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.9/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-11-27 00:44:47.469208544 +0100
@@ -0,0 +1,25 @@
+#ifndef _IPT_CONNMARK_H_target
+#define _IPT_CONNMARK_H_target
@@ -31,10 +43,10 @@
+};
+
+#endif /*_IPT_CONNMARK_H_target*/
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_connmark.h
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ipt_connmark.h
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ipt_connmark.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_connmark.h 2004-06-28 12:58:18.000000000 +0200
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.9/include/linux/netfilter_ipv4/ipt_connmark.h 2004-11-27 00:44:47.470208392 +0100
@@ -0,0 +1,18 @@
+#ifndef _IPT_CONNMARK_H
+#define _IPT_CONNMARK_H
@@ -54,25 +66,116 @@
+};
+
+#endif /*_IPT_CONNMARK_H*/
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack.h
+Index: linux-2.6.9/net/ipv4/netfilter/Kconfig
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-28 12:58:18.000000000 +0200
-@@ -207,6 +207,10 @@
- } nat;
- #endif /* CONFIG_IP_NF_NAT_NEEDED */
+--- linux-2.6.9.orig/net/ipv4/netfilter/Kconfig 2004-11-27 00:29:34.775959008 +0100
++++ linux-2.6.9/net/ipv4/netfilter/Kconfig 2004-11-27 00:44:47.475207632 +0100
+@@ -32,6 +32,14 @@
+ If unsure, say `N'.
+
++config IP_NF_CONNTRACK_MARK
++ bool 'Connection mark tracking support'
++ help
++ This option enables support for connection marks, used by the
++ `CONNMARK' target and `connmark' match. Similar to the mark value
++ of packets, but this mark value is kept in the conntrack session
++ instead of the individual packets.
++
+ config IP_NF_CT_PROTO_SCTP
+ tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
+ depends on IP_NF_CONNTRACK && EXPERIMENTAL
+@@ -342,6 +350,17 @@
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
+
++config IP_NF_MATCH_CONNMARK
++ tristate 'Connection mark match support'
++ depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
++ help
++ This option adds a `connmark' match, which allows you to match the
++ connection mark value previously set for the session by `CONNMARK'.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. The module will be called
++ ipt_connmark.o. If unsure, say `N'.
++
+ # `filter', generic and specific targets
+ config IP_NF_FILTER
+ tristate "Packet filtering"
+@@ -597,6 +616,18 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_TARGET_CONNMARK
++ tristate 'CONNMARK target support'
++ depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
++ help
++ This option adds a `CONNMARK' target, which allows one to manipulate
++ the connection mark value. Similar to the MARK target, but
++ affects the connection mark value rather than the packet mark value.
++
++ If you want to compile it as a module, say M here and read
++ Documentation/modules.txt. The module will be called
++ ipt_CONNMARK.o. If unsure, say `N'.
++
+ # raw + specific targets
+ config IP_NF_RAW
+ tristate 'raw table support (required for NOTRACK/TRACE)'
+Index: linux-2.6.9/net/ipv4/netfilter/Makefile
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/Makefile 2004-11-27 00:25:43.826068728 +0100
++++ linux-2.6.9/net/ipv4/netfilter/Makefile 2004-11-27 00:44:47.476207480 +0100
+@@ -61,6 +61,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
+ obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
+ obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
++obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
+ obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
+ obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
+@@ -81,6 +82,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
+ obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
+ obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
++obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
+ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
+ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
+ obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-27 00:30:59.285111664 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-27 00:44:47.481206720 +0100
+@@ -611,6 +611,9 @@
+ __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
+ conntrack->master = expected;
+ expected->sibling = conntrack;
++#if CONFIG_IP_NF_CONNTRACK_MARK
++ conntrack->mark = expected->expectant->mark;
++#endif
+ LIST_DELETE(&ip_conntrack_expect_list, expected);
+ expected->expectant->expecting--;
+ nf_conntrack_get(&master_ct(conntrack)->ct_general);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-11-27 00:29:34.796955816 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-11-27 00:44:47.485206112 +0100
+@@ -146,6 +146,11 @@
+ if (seq_printf(s, "[ASSURED] "))
+ return 1;
+
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
-+ unsigned long mark;
++ if (seq_printf(s, "mark=%ld ", conntrack->mark))
++ return 1;
+#endif
+
- };
+ if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
+ return 1;
- /* get master conntrack via master expectation */
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_CONNMARK.c
+Index: linux-2.6.9/net/ipv4/netfilter/ipt_CONNMARK.c
===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ipt_CONNMARK.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_CONNMARK.c 2004-06-28 12:58:18.000000000 +0200
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.9/net/ipv4/netfilter/ipt_CONNMARK.c 2004-11-27 00:44:47.487205808 +0100
@@ -0,0 +1,118 @@
+/* This kernel module is used to modify the connection mark values, or
+ * to optionally restore the skb nfmark from the connection mark
@@ -109,9 +212,9 @@
+
+static unsigned int
+target(struct sk_buff **pskb,
-+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
++ unsigned int hooknum,
+ const void *targinfo,
+ void *userinfo)
+{
@@ -192,77 +295,11 @@
+
+module_init(init);
+module_exit(fini);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
+Index: linux-2.6.9/net/ipv4/netfilter/ipt_connmark.c
===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:58:18.000000000 +0200
-@@ -107,6 +107,9 @@
- len += sprintf(buffer + len, "[ASSURED] ");
- len += sprintf(buffer + len, "use=%u ",
- atomic_read(&conntrack->ct_general.use));
-+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
-+ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
-+#endif
- len += sprintf(buffer + len, "\n");
-
- return len;
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Config.in 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in 2004-06-28 12:58:18.000000000 +0200
-@@ -7,6 +7,7 @@
- tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP_NF_CONNTRACK
- if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
- dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
-+ bool ' Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
- dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
- dep_tristate ' TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
- dep_tristate ' IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
-@@ -38,6 +39,9 @@
- fi
- if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
- dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
-+ if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
-+ dep_tristate ' Connection mark match support' CONFIG_IP_NF_MATCH_CONNMARK $CONFIG_IP_NF_IPTABLES
-+ fi
- dep_tristate ' Connection tracking match support' CONFIG_IP_NF_MATCH_CONNTRACK $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
- fi
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-@@ -106,6 +110,9 @@
- dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
- fi
- dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
-+ if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
-+ dep_tristate ' CONNMARK target support' CONFIG_IP_NF_TARGET_CONNMARK $CONFIG_IP_NF_IPTABLES
-+ fi
- dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
- dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Makefile 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile 2004-06-28 12:58:18.000000000 +0200
-@@ -84,6 +84,7 @@
-
- obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
- obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
-+obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
- obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
- obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
- obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
-@@ -99,6 +100,7 @@
- obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
- obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
- obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
-+obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
- obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
- obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
- obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_connmark.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ipt_connmark.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_connmark.c 2004-06-28 12:58:18.000000000 +0200
-@@ -0,0 +1,83 @@
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.9/net/ipv4/netfilter/ipt_connmark.c 2004-11-27 00:44:47.489205504 +0100
+@@ -0,0 +1,81 @@
+/* This kernel module matches connection mark values set by the
+ * CONNMARK target
+ *
@@ -301,15 +338,13 @@
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
-+ const void *hdr,
-+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_connmark_info *info = matchinfo;
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+ if (!ct)
-+ return 0;
++ return 0;
+
+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
+}
@@ -346,55 +381,3 @@
+
+module_init(init);
+module_exit(fini);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:58:18.000000000 +0200
-@@ -735,6 +735,9 @@
- __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
- conntrack->master = expected;
- expected->sibling = conntrack;
-+#if CONFIG_IP_NF_CONNTRACK_MARK
-+ conntrack->mark = expected->expectant->mark;
-+#endif
- LIST_DELETE(&ip_conntrack_expect_list, expected);
- expected->expectant->expecting--;
- nf_conntrack_get(&master_ct(conntrack)->infos[0]);
-Index: linux-2.4.26-ct_sync/Documentation/Configure.help
-===================================================================
---- linux-2.4.26-ct_sync.orig/Documentation/Configure.help 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/Documentation/Configure.help 2004-06-28 12:58:18.000000000 +0200
-@@ -2803,6 +2803,32 @@
- If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. If unsure, say `Y'.
-
-+Per connection mark support
-+CONFIG_IP_NF_CONNTRACK_MARK
-+ This option enables support for connection marks, used by the
-+ `CONNMARK' target and `connmark' match. Similar to the mark value
-+ of packets, but this mark value is kept in the conntrack session
-+ instead of the individual packets.
-+
-+CONNMARK target support
-+CONFIG_IP_NF_TARGET_CONNMARK
-+ This option adds a `CONNMARK' target, which allows one to manipulate
-+ the connection mark value. Similar to the MARK target, but
-+ affects the connection mark value rather than the packet mark value.
-+
-+ If you want to compile it as a module, say M here and read
-+ Documentation/modules.txt. The module will be called
-+ ipt_CONNMARK.o. If unsure, say `N'.
-+
-+connmark match support
-+CONFIP_IP_NF_MATCH_CONNMARK
-+ This option adds a `connmark' match, which allows you to match the
-+ connection mark value previously set for the session by `CONNMARK'.
-+
-+ If you want to compile it as a module, say M here and read
-+ Documentation/modules.txt. The module will be called
-+ ipt_connmark.o. If unsure, say `N'.
-+
- User space queueing via NETLINK
- CONFIG_IP_NF_QUEUE
- Netfilter has the ability to queue packets to user space: the
-
Added: branches/netfilter-ha/linux-2.6/patches/conntrack_alloc.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/conntrack_alloc.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/conntrack_alloc.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -0,0 +1,176 @@
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-11 21:04:35.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-12 00:20:26.944339960 +0100
+@@ -888,6 +888,8 @@
+ EXPORT_SYMBOL(ip_conntrack_protocol_register);
+ EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
+ EXPORT_SYMBOL(invert_tuplepr);
++EXPORT_SYMBOL(ip_conntrack_alloc);
++EXPORT_SYMBOL(ip_conntrack_free);
+ EXPORT_SYMBOL(ip_conntrack_alter_reply);
+ EXPORT_SYMBOL(ip_conntrack_destroyed);
+ EXPORT_SYMBOL(need_ip_conntrack);
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-12-10 00:10:57.000000000 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack.h 2004-12-12 00:20:26.949339200 +0100
+@@ -336,10 +336,20 @@
+ ip_ct_gather_frags(struct sk_buff *skb);
+
+ /* Delete all conntracks which match. */
+-extern void
++void
+ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
+ void *data);
+
++/* Allocates and initializes a new ip_conntrack structure, increment allocated
++ * conntrack count.
++ * Returns: ERR_PTR(-ENOMEM) in case of failure, conntrack pointer otherwise */
++struct ip_conntrack *
++ip_conntrack_alloc(const struct ip_conntrack_tuple *orig,
++ const struct ip_conntrack_tuple *reply);
++
++/* Free conntrack structure and decrement number of allocated conntrack entries. */
++extern void ip_conntrack_free(struct ip_conntrack *);
++
+ /* It's confirmed if it is, or has been in the hash table. */
+ static inline int is_confirmed(struct ip_conntrack *ct)
+ {
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-12 00:20:22.049084152 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-12 00:20:26.957337984 +0100
+@@ -278,6 +278,13 @@
+ remove_expectations(ct, 1);
+ }
+
++inline void
++ip_conntrack_free(struct ip_conntrack *conntrack)
++{
++ kmem_cache_free(ip_conntrack_cachep, conntrack);
++ atomic_dec(&ip_conntrack_count);
++}
++
+ static void
+ destroy_conntrack(struct nf_conntrack *nfct)
+ {
+@@ -321,8 +328,7 @@
+ ip_conntrack_put(master);
+
+ DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
+- kmem_cache_free(ip_conntrack_cachep, ct);
+- atomic_dec(&ip_conntrack_count);
++ ip_conntrack_free(ct);
+ CONNTRACK_STAT_INC(delete);
+ }
+
+@@ -559,22 +565,19 @@
+
+ /* Allocate a new conntrack: we return -ENOMEM if classification
+ failed due to stress. Otherwise it really is unclassifiable. */
+-static struct ip_conntrack_tuple_hash *
+-init_conntrack(const struct ip_conntrack_tuple *tuple,
+- struct ip_conntrack_protocol *protocol,
+- struct sk_buff *skb)
++struct ip_conntrack *
++ip_conntrack_alloc(const struct ip_conntrack_tuple *orig,
++ const struct ip_conntrack_tuple *reply)
+ {
+ struct ip_conntrack *conntrack;
+- struct ip_conntrack_tuple repl_tuple;
+ size_t hash;
+- struct ip_conntrack_expect *expected;
+
+ if (!ip_conntrack_hash_rnd_initted) {
+ get_random_bytes(&ip_conntrack_hash_rnd, 4);
+ ip_conntrack_hash_rnd_initted = 1;
+ }
+
+- hash = hash_conntrack(tuple);
++ hash = hash_conntrack(orig);
+
+ if (ip_conntrack_max
+ && atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
+@@ -588,11 +591,6 @@
+ }
+ }
+
+- if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
+- DEBUGP("Can't invert tuple.\n");
+- return NULL;
+- }
+-
+ conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
+ if (!conntrack) {
+ DEBUGP("Can't allocate conntrack.\n");
+@@ -602,20 +600,46 @@
+ memset(conntrack, 0, sizeof(*conntrack));
+ atomic_set(&conntrack->ct_general.use, 1);
+ conntrack->ct_general.destroy = destroy_conntrack;
+- conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
++ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
+- conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
++ conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *reply;
+ conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
+- if (!protocol->new(conntrack, skb)) {
+- kmem_cache_free(ip_conntrack_cachep, conntrack);
+- return NULL;
+- }
++
+ /* Don't set timer yet: wait for confirmation */
+ init_timer(&conntrack->timeout);
+ conntrack->timeout.data = (unsigned long)conntrack;
+ conntrack->timeout.function = death_by_timeout;
+
+ INIT_LIST_HEAD(&conntrack->sibling_list);
++ atomic_inc(&ip_conntrack_count);
++
++ return conntrack;
++}
++
++static struct ip_conntrack_tuple_hash *
++init_conntrack(const struct ip_conntrack_tuple *tuple,
++ struct ip_conntrack_protocol *protocol,
++ struct sk_buff *skb)
++{
++ struct ip_conntrack *conntrack;
++ struct ip_conntrack_tuple repl_tuple;
++ struct ip_conntrack_expect *expected;
++
++ if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
++ DEBUGP("Can't invert tuple.\n");
++ return NULL;
++ }
++
++ conntrack = ip_conntrack_alloc(tuple, &repl_tuple);
++ if (!conntrack || IS_ERR(conntrack)) {
++ DEBUGP("Can't allocate conntrack.\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ if (!protocol->new(conntrack, skb)) {
++ ip_conntrack_free(conntrack);
++ return NULL;
++ }
+
+ WRITE_LOCK(&ip_conntrack_lock);
+ /* Need finding and deleting of expected ONLY if we win race */
+@@ -655,7 +679,6 @@
+ nf_conntrack_get(&master_ct(conntrack)->ct_general);
+
+ /* this is a braindead... --pablo */
+- atomic_inc(&ip_conntrack_count);
+ WRITE_UNLOCK(&ip_conntrack_lock);
+
+ if (expected->expectfn)
+@@ -670,7 +693,7 @@
+ CONNTRACK_STAT_INC(new);
+ }
+
+-end: atomic_inc(&ip_conntrack_count);
++end:
+ WRITE_UNLOCK(&ip_conntrack_lock);
+
+ ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
Added: branches/netfilter-ha/linux-2.6/patches/conntrack_hash_manip.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/conntrack_hash_manip.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/conntrack_hash_manip.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -0,0 +1,82 @@
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-15 22:00:02.732832552 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-15 22:02:17.056412264 +0100
+@@ -914,5 +914,7 @@
+ EXPORT_SYMBOL(ip_conntrack_untracked);
+ EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
+ EXPORT_SYMBOL_GPL(__ip_conntrack_find);
++EXPORT_SYMBOL_GPL(__ip_conntrack_hash_insert);
++EXPORT_SYMBOL_GPL(__ip_conntrack_hash_remove);
+ EXPORT_SYMBOL_GPL(ip_conntrack_clean_from_lists);
+ EXPORT_SYMBOL_GPL(ip_conntrack_put);
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-15 22:00:31.513457232 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-15 22:01:18.850260944 +0100
+@@ -56,6 +56,10 @@
+
+ extern void ip_conntrack_clean_from_lists(struct ip_conntrack *ct);
+
++/* Non-locked conntrack hash insert and remove function: for ct_sync. */
++void __ip_conntrack_hash_insert(struct ip_conntrack *ct);
++void __ip_conntrack_hash_remove(struct ip_conntrack *ct);
++
+ extern struct list_head *ip_conntrack_hash;
+ extern struct list_head ip_conntrack_expect_list;
+ DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-15 22:01:02.899685800 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-15 22:02:59.406974000 +0100
+@@ -269,15 +269,10 @@
+ void
+ ip_conntrack_clean_from_lists(struct ip_conntrack *ct)
+ {
+- unsigned int ho, hr;
+-
+ DEBUGP("ip_conntrack_clean_from_lists(%p)\n", ct);
+ MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+
+- ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+- hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+- LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
+- LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
++ __ip_conntrack_hash_remove(ct);
+
+ /* Destroy all un-established, pending expectations */
+ remove_expectations(ct, 1);
+@@ -391,6 +386,33 @@
+ return h;
+ }
+
++/* Insert a conntrack into the hash. Caller holds a write lock on
++ * the conntrack hash. */
++void
++__ip_conntrack_hash_insert(struct ip_conntrack *ct)
++{
++ unsigned int ho, hr;
++
++ ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++
++ list_prepend(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
++ list_prepend(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
++}
++
++/* Remove a conntrack from the hash. Caller holds a write lock on
++ * the conntrack hash. */
++void
++__ip_conntrack_hash_remove(struct ip_conntrack *ct)
++{
++ unsigned int ho, hr;
++
++ ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
++ hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
++ LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
++ LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
++}
++
+ /* Confirm a connection given skb; places it in hash table */
+ int
+ __ip_conntrack_confirm(struct sk_buff *skb)
Added: branches/netfilter-ha/linux-2.6/patches/ct_notifier_pkt.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/ct_notifier_pkt.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/ct_notifier_pkt.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -0,0 +1,486 @@
+===== include/linux/netfilter.h 1.13 vs edited =====
+Index: linux-2.6.9/include/linux/netfilter.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter.h 2004-11-27 00:25:40.442583096 +0100
++++ linux-2.6.9/include/linux/netfilter.h 2004-11-27 00:29:34.763960832 +0100
+@@ -21,7 +21,7 @@
+ #define NF_MAX_VERDICT NF_REPEAT
+
+ /* Generic cache responses from hook functions.
+- <= 0x2000 is used for protocol-flags. */
++ <= 0x2000 is reserved for conntrack event cache. */
+ #define NFC_UNKNOWN 0x4000
+ #define NFC_ALTERED 0x8000
+
+Index: linux-2.6.9/include/linux/netfilter_ipv4.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4.h 2004-08-14 07:37:39.000000000 +0200
++++ linux-2.6.9/include/linux/netfilter_ipv4.h 2004-11-27 00:29:34.765960528 +0100
+@@ -8,34 +8,6 @@
+ #include <linux/config.h>
+ #include <linux/netfilter.h>
+
+-/* IP Cache bits. */
+-/* Src IP address. */
+-#define NFC_IP_SRC 0x0001
+-/* Dest IP address. */
+-#define NFC_IP_DST 0x0002
+-/* Input device. */
+-#define NFC_IP_IF_IN 0x0004
+-/* Output device. */
+-#define NFC_IP_IF_OUT 0x0008
+-/* TOS. */
+-#define NFC_IP_TOS 0x0010
+-/* Protocol. */
+-#define NFC_IP_PROTO 0x0020
+-/* IP options. */
+-#define NFC_IP_OPTIONS 0x0040
+-/* Frag & flags. */
+-#define NFC_IP_FRAG 0x0080
+-
+-/* Per-protocol information: only matters if proto match. */
+-/* TCP flags. */
+-#define NFC_IP_TCPFLAGS 0x0100
+-/* Source port. */
+-#define NFC_IP_SRC_PT 0x0200
+-/* Dest port. */
+-#define NFC_IP_DST_PT 0x0400
+-/* Something else about the proto */
+-#define NFC_IP_PROTO_UNKNOWN 0x2000
+-
+ /* IP Hooks */
+ /* After promisc drops, checksum checks. */
+ #define NF_IP_PRE_ROUTING 0
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-11-27 00:25:40.498574584 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack.h 2004-11-27 00:29:34.768960072 +0100
+@@ -47,6 +47,58 @@
+ /* Connection is confirmed: originating packet has left box */
+ IPS_CONFIRMED_BIT = 3,
+ IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
++
++ /* Connection is destroyed (removed from lists), can not be unset. */
++ IPS_DESTROYED_BIT = 4,
++ IPS_DESTROYED = (1 << IPS_DESTROYED_BIT),
++};
++
++/* Connection tracking event bits */
++enum ip_conntrack_events
++{
++ /* New conntrack */
++ IPCT_NEW_BIT = 0,
++ IPCT_NEW = (1 << IPCT_NEW_BIT),
++
++ /* Expected connection */
++ IPCT_RELATED_BIT = 1,
++ IPCT_RELATED = (1 << IPCT_RELATED_BIT),
++
++ /* Destroyed conntrack */
++ IPCT_DESTROY_BIT = 2,
++ IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
++
++ /* Timer has been refreshed */
++ IPCT_REFRESH_BIT = 3,
++ IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
++
++ /* Status has changed */
++ IPCT_STATUS_BIT = 4,
++ IPCT_STATUS = (1 << IPCT_STATUS_BIT),
++
++ /* Update of protocol info */
++ IPCT_PROTOINFO_BIT = 5,
++ IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
++
++ /* Volatile protocol info */
++ IPCT_PROTOINFO_VOLATILE_BIT = 6,
++ IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
++
++ /* New helper for conntrack */
++ IPCT_HELPER_BIT = 7,
++ IPCT_HELPER = (1 << IPCT_HELPER_BIT),
++
++ /* Update of helper info */
++ IPCT_HELPINFO_BIT = 8,
++ IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
++
++ /* Volatile helper info */
++ IPCT_HELPINFO_VOLATILE_BIT = 9,
++ IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
++
++ /* NAT info */
++ IPCT_NATINFO_BIT = 10,
++ IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+ };
+
+ #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
+@@ -259,7 +311,7 @@
+ /* Refresh conntrack for this many jiffies */
+ extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ unsigned long extra_jiffies);
+
+ /* These are for NAT. Icky. */
+@@ -290,6 +342,11 @@
+ return test_bit(IPS_CONFIRMED_BIT, &ct->status);
+ }
+
++static inline int is_destroyed(struct ip_conntrack *ct)
++{
++ return test_bit(IPS_DESTROYED_BIT, &ct->status);
++}
++
+ extern unsigned int ip_conntrack_htable_size;
+
+ struct ip_conntrack_stat
+@@ -313,6 +370,57 @@
+
+ #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
+
++#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
++#include <linux/notifier.h>
++
++extern struct notifier_block *ip_conntrack_chain;
++
++static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
++{
++ return notifier_chain_register(&ip_conntrack_chain, nb);
++}
++
++static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
++{
++ return notifier_chain_unregister(&ip_conntrack_chain, nb);
++}
++
++static inline void ip_conntrack_event_cache_init(struct sk_buff *skb)
++{
++ /* Set to zero first 14 bits, see netfilter.h */
++ skb->nfcache &= 0xc000;
++}
++
++static inline void
++ip_conntrack_event_cache(enum ip_conntrack_events event, struct sk_buff *skb)
++{
++ skb->nfcache |= event;
++}
++
++static inline void
++ip_conntrack_deliver_cached_events(struct sk_buff *skb)
++{
++ struct ip_conntrack *ct = (struct ip_conntrack *) skb->nfct;
++
++ if (ct != NULL && is_confirmed(ct) && !is_destroyed(ct) && skb->nfcache)
++ notifier_call_chain(&ip_conntrack_chain, skb->nfcache, ct);
++}
++
++static inline void ip_conntrack_event(enum ip_conntrack_events event,
++ struct ip_conntrack *ct)
++{
++ if (is_confirmed(ct) && !is_destroyed(ct))
++ notifier_call_chain(&ip_conntrack_chain, event, ct);
++}
++#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
++static inline void ip_conntrack_event_cache_init(struct sk_buff *skb) {}
++static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
++ struct sk_buff *skb) {}
++static inline void ip_conntrack_event(enum ip_conntrack_events event,
++ struct ip_conntrack *ct) {}
++static inline void ip_conntrack_deliver_cached_events(struct sk_buff *skb) {}
++#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
++
+ /* eg. PROVIDES_CONNTRACK(ftp); */
+ #define PROVIDES_CONNTRACK(name) \
+ int needs_ip_conntrack_##name; \
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-11-27 00:25:40.500574280 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-11-27 00:29:34.770959768 +0100
+@@ -39,10 +39,14 @@
+ /* Confirm a connection: returns NF_DROP if packet must be dropped. */
+ static inline int ip_conntrack_confirm(struct sk_buff *skb)
+ {
++ int ret = NF_ACCEPT;
++
+ if (skb->nfct
+ && !is_confirmed((struct ip_conntrack *)skb->nfct))
+- return __ip_conntrack_confirm(skb);
+- return NF_ACCEPT;
++ ret = __ip_conntrack_confirm(skb);
++ ip_conntrack_deliver_cached_events(skb);
++
++ return ret;
+ }
+
+ extern struct list_head *ip_conntrack_hash;
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-11-27 00:25:40.507573216 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-11-27 00:29:34.771959616 +0100
+@@ -34,7 +34,7 @@
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ int (*packet)(struct ip_conntrack *conntrack,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo);
+
+ /* Called when a new connection for this protocol found;
+Index: linux-2.6.9/net/ipv4/netfilter/Kconfig
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/Kconfig 2004-11-27 00:25:43.824069032 +0100
++++ linux-2.6.9/net/ipv4/netfilter/Kconfig 2004-11-27 00:29:34.775959008 +0100
+@@ -677,5 +677,15 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config IP_NF_CONNTRACK_EVENTS
++ bool "Connection tracking events"
++ depends on IP_NF_CONNTRACK
++ help
++ If this option is enabled, the connection tracking code will
++ provide a notifier chain that can be used by other kernel code
++ to get notified about changes in the connection tracking state.
++
++ IF unsure, say `N'.
++
+ endmenu
+
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-11-27 00:25:43.863063104 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-11-27 00:29:34.777958704 +0100
+@@ -89,7 +89,7 @@
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ static int icmp_packet(struct ip_conntrack *ct,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo)
+ {
+ /* Try to delete connection immediately after all replies:
+@@ -102,6 +102,7 @@
+ ct->timeout.function((unsigned long)ct);
+ } else {
+ atomic_inc(&ct->proto.icmp.count);
++ ip_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
+ ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
+ }
+
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_generic.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-11-27 00:25:43.860063560 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-11-27 00:29:34.779958400 +0100
+@@ -49,7 +49,7 @@
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ static int packet(struct ip_conntrack *conntrack,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo)
+ {
+ ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-11-27 00:25:43.935052160 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-11-27 00:29:34.782957944 +0100
+@@ -310,7 +310,7 @@
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ static int sctp_packet(struct ip_conntrack *conntrack,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo)
+ {
+ enum sctp_conntrack newconntrack, oldsctpstate;
+@@ -405,6 +405,8 @@
+ }
+
+ conntrack->proto.sctp.state = newconntrack;
++ if (oldsctpstate != newconntrack)
++ ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
+ WRITE_UNLOCK(&sctp_lock);
+ }
+
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-27 00:25:43.846065688 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-27 00:30:59.285111664 +0100
+@@ -37,6 +37,7 @@
+ #include <linux/err.h>
+ #include <linux/percpu.h>
+ #include <linux/moduleparam.h>
++#include <linux/notifier.h>
+
+ /* This rwlock protects the main hash table, protocol/helper/expected
+ registrations, conntrack timers*/
+@@ -76,6 +77,10 @@
+ struct ip_conntrack ip_conntrack_untracked;
+ unsigned int ip_ct_log_invalid;
+
++#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
++struct notifier_block *ip_conntrack_chain;
++#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
++
+ DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+
+ inline void
+@@ -288,6 +293,8 @@
+ IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
+ IP_NF_ASSERT(!timer_pending(&ct->timeout));
+
++ set_bit(IPS_DESTROYED_BIT, &ct->status);
++
+ /* To make sure we don't get any weird locking issues here:
+ * destroy_conntrack() MUST NOT be called with a write lock
+ * to ip_conntrack_lock!!! -HW */
+@@ -330,6 +337,7 @@
+
+ CONNTRACK_STAT_INC(delete_list);
+
++ ip_conntrack_event(IPCT_DESTROY, ct);
+ WRITE_LOCK(&ip_conntrack_lock);
+ clean_from_lists(ct);
+ WRITE_UNLOCK(&ip_conntrack_lock);
+@@ -436,8 +444,16 @@
+ add_timer(&ct->timeout);
+ atomic_inc(&ct->ct_general.use);
+ set_bit(IPS_CONFIRMED_BIT, &ct->status);
+- WRITE_UNLOCK(&ip_conntrack_lock);
+ CONNTRACK_STAT_INC(insert);
++ WRITE_UNLOCK(&ip_conntrack_lock);
++ if (ct->helper)
++ ip_conntrack_event_cache(IPCT_HELPER, skb);
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++ if (ct->nat.info.initialized)
++ ip_conntrack_event_cache(IPCT_NATINFO, skb);
++#endif
++ ip_conntrack_event_cache(master_ct(ct) ?
++ IPCT_RELATED : IPCT_NEW, skb);
+ return NF_ACCEPT;
+ }
+
+@@ -706,6 +722,8 @@
+ /* FIXME: Do this right please. --RR */
+ (*pskb)->nfcache |= NFC_UNKNOWN;
+
++ ip_conntrack_event_cache_init(*pskb);
++
+ /* Doesn't cover locally-generated broadcast, so not worth it. */
+ #if 0
+ /* Ignore broadcast: no `connection'. */
+@@ -767,8 +785,10 @@
+ return NF_ACCEPT;
+ }
+ }
+- if (set_reply)
++ if (set_reply && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
+ set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
++ ip_conntrack_event_cache(IPCT_STATUS, *pskb);
++ }
+
+ return ret;
+ }
+@@ -1050,6 +1070,7 @@
+ if (i->ctrack->helper == me) {
+ /* Get rid of any expected. */
+ remove_expectations(i->ctrack, 0);
++ ip_conntrack_event(IPCT_HELPER, i->ctrack);
+ /* And *then* set helper to NULL */
+ i->ctrack->helper = NULL;
+ }
+@@ -1090,7 +1111,7 @@
+ /* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
+ void ip_ct_refresh_acct(struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ unsigned long extra_jiffies)
+ {
+ IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+@@ -1105,6 +1126,7 @@
+ if (del_timer(&ct->timeout)) {
+ ct->timeout.expires = jiffies + extra_jiffies;
+ add_timer(&ct->timeout);
++ ip_conntrack_event_cache(IPCT_REFRESH, skb);
+ }
+ ct_add_counters(ct, ctinfo, skb);
+ WRITE_UNLOCK(&ip_conntrack_lock);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_ftp.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-11-27 00:25:43.854064472 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-11-27 00:29:34.793956272 +0100
+@@ -300,6 +300,7 @@
+ ct_ftp_info->seq_aft_nl[dir] =
+ ntohl(th->seq) + datalen;
+ ct_ftp_info->seq_aft_nl_set[dir] = 1;
++ ip_conntrack_event_cache(IPCT_HELPINFO_VOLATILE, skb);
+ }
+ }
+
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-11-27 00:25:43.956048968 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-11-27 00:29:34.796955816 +0100
+@@ -875,6 +875,11 @@
+ {
+ }
+
++#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
++EXPORT_SYMBOL(ip_conntrack_chain);
++EXPORT_SYMBOL(ip_conntrack_register_notifier);
++EXPORT_SYMBOL(ip_conntrack_unregister_notifier);
++#endif
+ EXPORT_SYMBOL(ip_conntrack_protocol_register);
+ EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
+ EXPORT_SYMBOL(invert_tuplepr);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-11-27 00:25:43.944050792 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-11-27 00:29:34.801955056 +0100
+@@ -825,7 +825,7 @@
+
+ /* Returns verdict for packet, or -1 for invalid. */
+ static int tcp_packet(struct ip_conntrack *conntrack,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo)
+ {
+ enum tcp_conntrack new_state, old_state;
+@@ -944,6 +944,10 @@
+ ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
+ WRITE_UNLOCK(&tcp_lock);
+
++ ip_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
++ if (new_state != old_state)
++ ip_conntrack_event_cache(IPCT_PROTOINFO, skb);
++
+ if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+ /* If only reply is a RST, we can consider ourselves not to
+ have an established connection: this is a fairly common
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-11-27 00:25:43.947050336 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-11-27 00:29:34.803954752 +0100
+@@ -64,7 +64,7 @@
+
+ /* Returns verdict for packet, and may modify conntracktype */
+ static int udp_packet(struct ip_conntrack *conntrack,
+- const struct sk_buff *skb,
++ struct sk_buff *skb,
+ enum ip_conntrack_info ctinfo)
+ {
+ /* If we've seen traffic both ways, this is some kind of UDP
+@@ -73,7 +73,10 @@
+ ip_ct_refresh_acct(conntrack, ctinfo, skb,
+ ip_ct_udp_timeout_stream);
+ /* Also, more likely to be important, and not a probe */
+- set_bit(IPS_ASSURED_BIT, &conntrack->status);
++ if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)) {
++ set_bit(IPS_ASSURED_BIT, &conntrack->status);
++ ip_conntrack_event_cache(IPCT_STATUS, skb);
++ }
+ } else
+ ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
+
Modified: branches/netfilter-ha/linux-2.6/patches/ct_sync_config_and_makefile.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/ct_sync_config_and_makefile.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/ct_sync_config_and_makefile.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,47 +1,40 @@
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in
+Index: linux-2.6.9/net/ipv4/netfilter/Makefile
===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Config.in 2004-06-28 12:58:22.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in 2004-07-08 13:42:59.000000000 +0200
-@@ -14,6 +14,7 @@
- else
- dep_tristate ' Connection tracking netlink interface' CONFIG_IP_NF_NETLINK_CONNTRACK $CONFIG_IP_NF_CONNTRACK
- fi
-+ dep_tristate ' Connection tracking state synchronization' CONFIG_IP_NF_CT_SYNC $CONFIG_IP_NF_CONNTRACK_EVENTS
- dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
- bool ' Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
- dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Makefile 2004-07-08 13:42:53.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile 2004-07-08 13:42:59.000000000 +0200
-@@ -12,11 +12,12 @@
- export-objs = ip_conntrack_standalone.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o arp_tables.o
+--- linux-2.6.9.orig/net/ipv4/netfilter/Makefile 2004-12-10 00:10:57.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/Makefile 2004-12-15 22:03:22.000000000 +0100
+@@ -16,6 +16,9 @@
+ ipfwadm-objs := $(ip_nf_compat-objs) ipfwadm_core.o
+ ipchains-objs := $(ip_nf_compat-objs) ipchains_core.o
- # Multipart objects.
--list-multi := ip_conntrack.o iptable_nat.o ipfwadm.o ipchains.o
-+list-multi := ip_conntrack.o iptable_nat.o ipfwadm.o ipchains.o ct_sync.o
-
- # objects for the conntrack and NAT core (used by standalone and backw. compat)
- 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
- 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
++# conntrack state synchronization
+ct_sync-objs := ct_sync_main.o ct_sync_proto.o ct_sync_sock.o
++
+ # connection tracking
+ obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
- # objects for the standalone - connection tracking / NAT
- ip_conntrack-objs := ip_conntrack_standalone.o $(ip_nf_conntrack-objs)
-@@ -127,6 +128,9 @@
+@@ -99,3 +102,5 @@
+ obj-$(CONFIG_IP_NF_COMPAT_IPFWADM) += ipfwadm.o
obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
-
-+# connection tracking state synchronization
-+obj-$(CONFIG_IP_NF_CT_SYNC) += ct_sync.o
+
- include $(TOPDIR)/Rules.make
++obj-$(CONFIG_IP_NF_CT_SYNC) += ct_sync.o
+Index: linux-2.6.9/net/ipv4/netfilter/Kconfig
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/Kconfig 2004-12-10 00:10:57.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/Kconfig 2004-12-15 22:03:22.000000000 +0100
+@@ -718,5 +718,15 @@
+
+ IF unsure, say `N'.
- ip_conntrack.o: $(ip_conntrack-objs)
-@@ -140,3 +144,6 @@
-
- ipchains.o: $(ipchains-objs)
- $(LD) -r -o $@ $(ipchains-objs)
++config IP_NF_CT_SYNC
++ tristate "Connection tracking state synchronization"
++ depends on IP_NF_CONNTRACK_EVENTS
++ help
++ If option enables connection tracking state synchronization support
++ for the IPv4 connection tracking subsystem. Beware: this feature is
++ highly experimental.
+
-+ct_sync.o: $(ct_sync-objs)
-+ $(LD) -r -o $@ $(ct_sync-objs)
++ If unsure, say `N'.
++
+ endmenu
+
Deleted: branches/netfilter-ha/linux-2.6/patches/export_ct_id.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ct_id.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ct_id.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,43 +0,0 @@
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:58:30.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-07-06 15:36:00.000000000 +0200
-@@ -59,6 +59,10 @@
- extern struct list_head ip_conntrack_ordered_list;
- extern struct list_head ip_conntrack_expect_list;
- extern struct list_head ip_conntrack_helpers;
-+
-+extern unsigned int ip_conntrack_next_id;
-+extern unsigned int ip_conntrack_exp_next_id;
-+
- DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
- #endif /* _IP_CONNTRACK_CORE_H */
-
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:58:30.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-07-06 15:14:39.000000000 +0200
-@@ -534,6 +534,8 @@
- EXPORT_SYMBOL(ip_conntrack_lock);
- EXPORT_SYMBOL(ip_conntrack_hash);
- EXPORT_SYMBOL_GPL(hash_conntrack);
-+EXPORT_SYMBOL_GPL(ip_conntrack_next_id);
-+EXPORT_SYMBOL_GPL(ip_conntrack_exp_next_id);
- EXPORT_SYMBOL(ip_conntrack_untracked);
- EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(__ip_conntrack_find_get);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:58:30.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c 2004-07-06 15:13:50.000000000 +0200
-@@ -72,8 +72,8 @@
-
- /* for ctnetlink */
- LIST_HEAD(ip_conntrack_ordered_list);
--static unsigned int ip_conntrack_next_id = 1;
--static unsigned int ip_conntrack_exp_next_id = 1;
-+unsigned int ip_conntrack_next_id = 1;
-+unsigned int ip_conntrack_exp_next_id = 1;
- #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
- struct notifier_block *ip_conntrack_chain = NULL;
- unsigned long ip_conntrack_event_cache[NR_CPUS];
Deleted: branches/netfilter-ha/linux-2.6/patches/export_hash_conntrack.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_hash_conntrack.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_hash_conntrack.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,38 +0,0 @@
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:56:25.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:56:29.000000000 +0200
-@@ -42,6 +42,8 @@
- __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
- const struct ip_conntrack *ignored_conntrack);
-
-+u_int32_t hash_conntrack(const struct ip_conntrack_tuple *tuple);
-+
- extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
-
- /* Confirm a connection: returns NF_DROP if packet must be dropped. */
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:56:25.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:56:29.000000000 +0200
-@@ -533,6 +533,7 @@
- EXPORT_SYMBOL(ip_conntrack_ordered_list);
- EXPORT_SYMBOL(ip_conntrack_lock);
- EXPORT_SYMBOL(ip_conntrack_hash);
-+EXPORT_SYMBOL_GPL(hash_conntrack);
- EXPORT_SYMBOL(ip_conntrack_untracked);
- EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(__ip_conntrack_find_get);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:56:25.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:56:29.000000000 +0200
-@@ -123,7 +123,7 @@
- static int ip_conntrack_hash_rnd_initted;
- static unsigned int ip_conntrack_hash_rnd;
-
--static u_int32_t
-+u_int32_t
- hash_conntrack(const struct ip_conntrack_tuple *tuple)
- {
- #if 0
Added: branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_clean_from_lists.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_clean_from_lists.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_clean_from_lists.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -0,0 +1,52 @@
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-15 21:25:16.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-15 22:00:02.732832552 +0100
+@@ -914,4 +914,5 @@
+ EXPORT_SYMBOL(ip_conntrack_untracked);
+ EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
+ EXPORT_SYMBOL_GPL(__ip_conntrack_find);
++EXPORT_SYMBOL_GPL(ip_conntrack_clean_from_lists);
+ EXPORT_SYMBOL_GPL(ip_conntrack_put);
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-15 21:25:16.000000000 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-15 22:00:31.513457232 +0100
+@@ -54,6 +54,8 @@
+ return ret;
+ }
+
++extern void ip_conntrack_clean_from_lists(struct ip_conntrack *ct);
++
+ extern struct list_head *ip_conntrack_hash;
+ extern struct list_head ip_conntrack_expect_list;
+ DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-15 21:25:16.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-15 22:01:02.899685800 +0100
+@@ -266,12 +266,12 @@
+ }
+ }
+
+-static void
+-clean_from_lists(struct ip_conntrack *ct)
++void
++ip_conntrack_clean_from_lists(struct ip_conntrack *ct)
+ {
+ unsigned int ho, hr;
+
+- DEBUGP("clean_from_lists(%p)\n", ct);
++ DEBUGP("ip_conntrack_clean_from_lists(%p)\n", ct);
+ MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+
+ ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+@@ -339,7 +339,7 @@
+
+ ip_conntrack_event(IPCT_DESTROY, ct);
+ WRITE_LOCK(&ip_conntrack_lock);
+- clean_from_lists(ct);
++ ip_conntrack_clean_from_lists(ct);
+ WRITE_UNLOCK(&ip_conntrack_lock);
+ ip_conntrack_put(ct);
+ }
Modified: branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_find.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_find.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_find.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,36 +1,34 @@
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:56:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:56:25.000000000 +0200
-@@ -37,7 +37,10 @@
- struct ip_conntrack_tuple_hash *
- __ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
- const struct ip_conntrack *ignored_conntrack);
--
-+/* non-locked, non-referenced */
-+struct ip_conntrack_tuple_hash *
-+__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
-+ const struct ip_conntrack *ignored_conntrack);
-
- extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
-
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:56:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:56:25.000000000 +0200
-@@ -536,6 +536,7 @@
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-09 23:24:59.920244832 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-09 23:34:40.690954264 +0100
+@@ -913,4 +913,5 @@
+ EXPORT_SYMBOL(ip_conntrack_hash);
EXPORT_SYMBOL(ip_conntrack_untracked);
EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(__ip_conntrack_find_get);
+EXPORT_SYMBOL_GPL(__ip_conntrack_find);
EXPORT_SYMBOL_GPL(ip_conntrack_put);
- EXPORT_SYMBOL_GPL(ip_conntrack_helpers);
- #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h
===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:56:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:56:25.000000000 +0200
-@@ -414,7 +414,7 @@
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-09 23:21:07.153630736 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-12-09 23:33:26.697203024 +0100
+@@ -34,6 +34,11 @@
+ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
+ const struct ip_conntrack *ignored_conntrack);
+
++/* Non-locked, non-referenced version, for ct_sync */
++struct ip_conntrack_tuple_hash *
++__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
++ const struct ip_conntrack *ignored_conntrack);
++
+ extern int __ip_conntrack_confirm(struct sk_buff *skb);
+
+ /* Confirm a connection: returns NF_DROP if packet must be dropped. */
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-09 23:24:21.091147752 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-09 23:34:08.402862800 +0100
+@@ -354,7 +354,7 @@
&& ip_ct_tuple_equal(tuple, &i->tuple);
}
Modified: branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_helpers.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_helpers.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_conntrack_helpers.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,73 +1,50 @@
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-24 15:35:16.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:56:18.000000000 +0200
-@@ -53,6 +53,7 @@
- extern struct list_head *ip_conntrack_hash;
- extern struct list_head ip_conntrack_ordered_list;
- extern struct list_head ip_conntrack_expect_list;
-+extern struct list_head ip_conntrack_helpers;
- DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
- #endif /* _IP_CONNTRACK_CORE_H */
-
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-11-27 00:44:47.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-09 23:24:59.920244832 +0100
+@@ -898,6 +898,7 @@
+ EXPORT_SYMBOL(ip_ct_protos);
+ EXPORT_SYMBOL(ip_ct_find_proto);
+ EXPORT_SYMBOL(ip_ct_find_helper);
++EXPORT_SYMBOL_GPL(__ip_ct_find_helper_by_name);
+ EXPORT_SYMBOL(ip_conntrack_expect_alloc);
+ EXPORT_SYMBOL(ip_conntrack_expect_related);
+ EXPORT_SYMBOL(ip_conntrack_change_expect);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c
===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:56:01.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:56:18.000000000 +0200
-@@ -537,6 +537,7 @@
- EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(__ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(ip_conntrack_put);
-+EXPORT_SYMBOL_GPL(ip_conntrack_helpers);
- #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
- EXPORT_SYMBOL(ip_conntrack_chain);
- EXPORT_SYMBOL(ip_conntrack_event_cache);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:56:01.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:56:18.000000000 +0200
-@@ -62,7 +62,7 @@
- void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
- LIST_HEAD(ip_conntrack_expect_list);
- LIST_HEAD(protocol_list);
--static LIST_HEAD(helpers);
-+LIST_HEAD(ip_conntrack_helpers);
- unsigned int ip_conntrack_htable_size = 0;
- int ip_conntrack_max = 0;
- static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
-@@ -693,7 +693,7 @@
-
- struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
- {
-- return LIST_FIND(&helpers, helper_cmp,
-+ return LIST_FIND(&ip_conntrack_helpers, helper_cmp,
- struct ip_conntrack_helper *,
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-11-27 00:44:47.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-09 23:24:21.091147752 +0100
+@@ -521,6 +521,20 @@
tuple);
}
-@@ -1217,7 +1217,7 @@
- conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
- if (!conntrack->master)
-- conntrack->helper = LIST_FIND(&helpers, helper_cmp,
-+ conntrack->helper = LIST_FIND(&ip_conntrack_helpers, helper_cmp,
- struct ip_conntrack_helper *,
- newreply);
- WRITE_UNLOCK(&ip_conntrack_lock);
-@@ -1230,7 +1230,7 @@
- MOD_INC_USE_COUNT;
++static inline int
++helper_name_cmp(const struct ip_conntrack_helper *helper,
++ const char *name)
++{
++ return strcmp(helper->name, name);
++}
++
++struct ip_conntrack_helper *
++__ip_ct_find_helper_by_name(const char *name)
++{
++ return LIST_FIND(&helpers, helper_name_cmp,
++ struct ip_conntrack_helper *, name);
++}
++
+ /* Allocate a new conntrack: we return -ENOMEM if classification
+ failed due to stress. Otherwise it really is unclassifiable. */
+ static struct ip_conntrack_tuple_hash *
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_helper.h
+===================================================================
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-08-14 07:36:17.000000000 +0200
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-12-09 23:21:04.976961640 +0100
+@@ -35,6 +35,8 @@
- WRITE_LOCK(&ip_conntrack_lock);
-- list_prepend(&helpers, me);
-+ list_prepend(&ip_conntrack_helpers, me);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ extern struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple);
- return 0;
-@@ -1255,7 +1255,7 @@
++/* Lookup conntrack helper by name: for ct_sync */
++extern struct ip_conntrack_helper *__ip_ct_find_helper_by_name(const char *name);
- /* Need write lock here, to delete helper. */
- WRITE_LOCK(&ip_conntrack_lock);
-- LIST_DELETE(&helpers, me);
-+ LIST_DELETE(&ip_conntrack_helpers, me);
-
- /* Get rid of expecteds, set helpers to NULL. */
- for (i = 0; i < ip_conntrack_htable_size; i++)
+ /* Allocate space for an expectation: this is mandatory before calling
+ ip_conntrack_expect_related. */
Deleted: branches/netfilter-ha/linux-2.6/patches/export_ip_nat_hash.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_nat_hash.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_nat_hash.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,11 +0,0 @@
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_standalone.c Mon Jun 14 15:08:55 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_standalone.c Mon Jun 14 15:08:58 2004
-@@ -363,4 +363,6 @@
- EXPORT_SYMBOL(ip_nat_used_tuple);
- EXPORT_SYMBOL_GPL(ip_nat_helpers);
- EXPORT_SYMBOL_GPL(ip_nat_lock);
-+EXPORT_SYMBOL_GPL(place_in_hashes);
-+EXPORT_SYMBOL_GPL(replace_in_hashes);
- MODULE_LICENSE("GPL");
Modified: branches/netfilter-ha/linux-2.6/patches/export_ip_nat_helpers.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_nat_helpers.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_nat_helpers.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,70 +1,49 @@
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_nat_core.h
+Index: linux-2.6.9/include/linux/netfilter_ipv4/ip_nat_helper.h
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_nat_core.h Mon Dec 11 22:31:32 2000
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_nat_core.h Mon Jun 14 15:08:42 2004
-@@ -30,4 +30,5 @@
- extern struct ip_nat_protocol ip_nat_protocol_tcp;
- extern struct ip_nat_protocol ip_nat_protocol_udp;
- extern struct ip_nat_protocol ip_nat_protocol_icmp;
-+extern struct list_head ip_nat_helpers;
- #endif /* _IP_NAT_CORE_H */
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_standalone.c Wed Apr 14 15:05:41 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_standalone.c Mon Jun 14 15:08:42 2004
-@@ -361,4 +361,5 @@
- EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
- EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
- EXPORT_SYMBOL(ip_nat_used_tuple);
-+EXPORT_SYMBOL_GPL(ip_nat_helpers);
- MODULE_LICENSE("GPL");
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_core.c Mon Jun 14 14:55:19 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_core.c Mon Jun 14 15:08:42 2004
-@@ -43,7 +43,7 @@
- static struct list_head *bysource;
- static struct list_head *byipsproto;
- LIST_HEAD(protos);
--LIST_HEAD(helpers);
-+LIST_HEAD(ip_nat_helpers);
+--- linux-2.6.9.orig/include/linux/netfilter_ipv4/ip_nat_helper.h 2004-12-09 23:13:19.899664136 +0100
++++ linux-2.6.9/include/linux/netfilter_ipv4/ip_nat_helper.h 2004-12-09 23:13:41.428391272 +0100
+@@ -47,6 +47,10 @@
+ extern struct ip_nat_helper *
+ __ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
- extern struct ip_nat_protocol unknown_nat_protocol;
-
-@@ -636,7 +636,7 @@
-
- /* If there's a helper, assign it; based on new tuple. */
- if (!conntrack->master)
-- info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
-+ info->helper = LIST_FIND(&ip_nat_helpers, helper_cmp, struct ip_nat_helper *,
- &reply);
-
- /* It's done. */
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_helper.c
++/* For ct_sync: look up helper by name */
++extern struct ip_nat_helper *
++__ip_nat_find_helper_by_name(const char *name);
++
+ /* These return true or false. */
+ extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
+ struct ip_conntrack *ct,
+Index: linux-2.6.9/net/ipv4/netfilter/ip_nat_helper.c
===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_helper.c Fri Nov 28 19:26:21 2003
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_helper.c Mon Jun 14 15:08:42 2004
-@@ -508,10 +508,10 @@
- }
- }
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_nat_helper.c 2004-11-27 00:25:43.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_nat_helper.c 2004-12-09 23:11:08.798594528 +0100
+@@ -455,6 +455,19 @@
+ return ret;
+ }
+
++static inline int
++helper_name_cmp(const struct ip_nat_helper *helper,
++ const char *name)
++{
++ return strcmp(helper->name, name);
++}
++
++struct ip_nat_helper *
++__ip_nat_find_helper_by_name(const char *name)
++{
++ return LIST_FIND(&helpers, helper_name_cmp, struct ip_nat_helper *, name);
++}
++
+ void ip_nat_helper_unregister(struct ip_nat_helper *me)
+ {
WRITE_LOCK(&ip_nat_lock);
-- if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple))
-+ if (LIST_FIND(&ip_nat_helpers, helper_cmp, struct ip_nat_helper *,&me->tuple))
- ret = -EBUSY;
- else {
-- list_prepend(&helpers, me);
-+ list_prepend(&ip_nat_helpers, me);
- MOD_INC_USE_COUNT;
- }
- WRITE_UNLOCK(&ip_nat_lock);
-@@ -537,8 +537,8 @@
-
- WRITE_LOCK(&ip_nat_lock);
- /* Autoloading conntrack helper might have failed */
-- if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) {
-- LIST_DELETE(&helpers, me);
-+ if (LIST_FIND(&ip_nat_helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) {
-+ LIST_DELETE(&ip_nat_helpers, me);
- found = 1;
- }
- WRITE_UNLOCK(&ip_nat_lock);
+Index: linux-2.6.9/net/ipv4/netfilter/ip_nat_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_nat_standalone.c 2004-11-27 00:25:44.000000000 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_nat_standalone.c 2004-12-09 23:11:43.402333960 +0100
+@@ -391,4 +391,5 @@
+ EXPORT_SYMBOL(ip_nat_used_tuple);
+ EXPORT_SYMBOL(ip_nat_find_helper);
+ EXPORT_SYMBOL(__ip_nat_find_helper);
++EXPORT_SYMBOL_GPL(__ip_nat_find_helper_by_name);
+ MODULE_LICENSE("GPL");
Deleted: branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,10 +0,0 @@
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_standalone.c Mon Jun 14 15:08:42 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_standalone.c Mon Jun 14 15:08:55 2004
-@@ -362,4 +362,5 @@
- EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
- EXPORT_SYMBOL(ip_nat_used_tuple);
- EXPORT_SYMBOL_GPL(ip_nat_helpers);
-+EXPORT_SYMBOL_GPL(ip_nat_lock);
- MODULE_LICENSE("GPL");
Added: branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock_and_hash.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock_and_hash.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/export_ip_nat_lock_and_hash.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -0,0 +1,11 @@
+Index: linux-2.6.9/net/ipv4/netfilter/ip_nat_standalone.c
+===================================================================
+--- linux-2.6.9.orig/net/ipv4/netfilter/ip_nat_standalone.c 2004-12-09 23:25:14.341052536 +0100
++++ linux-2.6.9/net/ipv4/netfilter/ip_nat_standalone.c 2004-12-10 00:02:24.684988720 +0100
+@@ -392,4 +392,6 @@
+ EXPORT_SYMBOL(ip_nat_find_helper);
+ EXPORT_SYMBOL(__ip_nat_find_helper);
+ EXPORT_SYMBOL_GPL(__ip_nat_find_helper_by_name);
++EXPORT_SYMBOL_GPL(ip_nat_lock);
++EXPORT_SYMBOL_GPL(place_in_hashes);
+ MODULE_LICENSE("GPL");
Deleted: branches/netfilter-ha/linux-2.6/patches/kgdb-1.9.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/kgdb-1.9.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/kgdb-1.9.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,4698 +0,0 @@
-%patch
-Index: linux-2.4.26-ct_sync/kernel/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/kernel/Makefile 2001-09-17 06:22:40.000000000 +0200
-+++ linux-2.4.26-ct_sync/kernel/Makefile 2004-06-28 12:56:07.000000000 +0200
-@@ -19,6 +19,7 @@
- obj-$(CONFIG_UID16) += uid16.o
- obj-$(CONFIG_MODULES) += ksyms.o
- obj-$(CONFIG_PM) += pm.o
-+obj-$(CONFIG_KGDB) += kgdbstub.o
-
- ifneq ($(CONFIG_IA64),y)
- # According to Alan Modra <alan at linuxcare.com.au>, the -fno-omit-frame-pointer is
-Index: linux-2.4.26-ct_sync/kernel/module.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/kernel/module.c 2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.26-ct_sync/kernel/module.c 2004-06-28 12:56:07.000000000 +0200
-@@ -57,6 +57,8 @@
-
- #endif /* defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS) */
-
-+void module_event (void);
-+
- /* inter_module functions are always available, even when the kernel is
- * compiled without modules. Consumers of inter_module_xxx routines
- * will always work, even when both are built into the kernel, this
-@@ -560,7 +562,9 @@
- /* Initialize the module. */
- atomic_set(&mod->uc.usecount,1);
- mod->flags |= MOD_INITIALIZING;
-+ module_event();
- if (mod->init && (error = mod->init()) != 0) {
-+ module_event();
- atomic_set(&mod->uc.usecount,0);
- mod->flags &= ~MOD_INITIALIZING;
- if (error > 0) /* Buggy module */
-@@ -678,6 +682,7 @@
- error = 0;
- out:
- unlock_kernel();
-+ module_event();
- return error;
- }
-
-@@ -1248,6 +1253,13 @@
- show: s_show
- };
-
-+/* GDB can place a breakpoint in this function to probe changes in the list of
-+ * modules loaded in a kernel. */
-+void module_event (void)
-+{
-+ /* Do nothing */
-+}
-+
- #else /* CONFIG_MODULES */
-
- /* Dummy syscalls for people who don't want modules */
-Index: linux-2.4.26-ct_sync/kernel/kgdbstub.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/kernel/kgdbstub.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/kernel/kgdbstub.c 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,1074 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2, or (at your option) any
-+ * later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ */
-+
-+/*
-+ * Generic KGDB Support
-+ * Copyright (C) 2002-2003 Timesys Corporation
-+ * Implemented by Anurekh Saxena (anurekh.saxena at timesys.com)
-+ *
-+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
-+ * Contributor: Lake Stevens Instrument Division
-+ * Written by: Glenn Engel
-+ *
-+ * Modified for 386 by Jim Kingdon, Cygnus Support.
-+ * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave at gcom.com>
-+ * Integrated into 2.2.5 kernel by Tigran Aivazian <tigran at sco.com>
-+ *
-+ * thread support, support for multiple processors,support for ia-32(x86)
-+ * hardware debugging, Console support, handling nmi watchdog
-+ * - Amit S. Kale ( amitkale at emsyssoft.com )
-+ *
-+ */
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/mm.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h> /* for linux pt_regs struct */
-+#include <asm/uaccess.h>
-+#include <linux/kgdb.h>
-+#include <asm/atomic.h>
-+
-+#ifdef CONFIG_GDB_CONSOLE
-+#include <linux/console.h>
-+#endif
-+
-+#include <linux/init.h>
-+
-+
-+
-+/* DEBUGGING THE DEBUGGER */
-+#undef KGDB_DEG
-+/**************************/
-+
-+struct kgdb_arch *kgdb_ops = &arch_kgdb_ops;
-+gdb_breakpoint_t kgdb_break[MAX_BREAKPOINTS];
-+
-+int kgdb_initialized = 0;
-+static const char hexchars[] = "0123456789abcdef";
-+
-+int get_char(char *addr, unsigned char *data, int can_fault);
-+int set_char(char *addr, int data, int can_fault);
-+
-+spinlock_t slavecpulocks[KGDB_MAX_NO_CPUS];
-+volatile int procindebug[KGDB_MAX_NO_CPUS];
-+volatile unsigned kgdb_step;
-+atomic_t kgdb_lock;
-+atomic_t kgdb_setting_breakpoint;
-+atomic_t kgdb_killed_or_detached;
-+atomic_t kgdb_might_be_resumed;
-+struct task_struct *kgdb_usethread, *kgdb_contthread;
-+
-+/*
-+ * Indicate to caller of mem2hex or hex2mem that there has been an
-+ * error.
-+ */
-+volatile int kgdb_memerr = 0;
-+volatile int kgdb_memerr_expected = 0;
-+
-+/* This will point to kgdb_handle_exception by default.
-+ * The architecture code can override this in its init function
-+ */
-+gdb_debug_hook *linux_debug_hook;
-+
-+
-+static char remcomInBuffer[BUFMAX];
-+static char remcomOutBuffer[BUFMAX];
-+static short error;
-+
-+int hex(char ch)
-+{
-+ if ((ch >= 'a') && (ch <= 'f'))
-+ return (ch - 'a' + 10);
-+ if ((ch >= '0') && (ch <= '9'))
-+ return (ch - '0');
-+ if ((ch >= 'A') && (ch <= 'F'))
-+ return (ch - 'A' + 10);
-+ return (-1);
-+}
-+
-+
-+/* scan for the sequence $<data>#<checksum> */
-+
-+void getpacket(char *buffer)
-+{
-+ unsigned char checksum;
-+ unsigned char xmitcsum;
-+ int i;
-+ int count;
-+ char ch;
-+
-+ do {
-+ /* wait around for the start character, ignore all other characters */
-+ while ((ch = (getDebugChar() & 0x7f)) != '$');
-+ checksum = 0;
-+ xmitcsum = -1;
-+
-+ count = 0;
-+
-+ /* now, read until a # or end of buffer is found */
-+ while (count < BUFMAX) {
-+ ch = getDebugChar() & 0x7f;
-+ if (ch == '#')
-+ break;
-+ checksum = checksum + ch;
-+ buffer[count] = ch;
-+ count = count + 1;
-+ }
-+ buffer[count] = 0;
-+
-+ if (ch == '#') {
-+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
-+ xmitcsum += hex(getDebugChar() & 0x7f);
-+
-+ if (checksum != xmitcsum)
-+ putDebugChar('-'); /* failed checksum */
-+ else {
-+ putDebugChar('+'); /* successful transfer */
-+ /* if a sequence char is present, reply the sequence ID */
-+ if (buffer[2] == ':') {
-+ putDebugChar(buffer[0]);
-+ putDebugChar(buffer[1]);
-+ /* remove sequence chars from buffer */
-+ count = strlen(buffer);
-+ for (i = 3; i <= count; i++)
-+ buffer[i - 3] = buffer[i];
-+ }
-+ }
-+ }
-+ } while (checksum != xmitcsum);
-+
-+}
-+
-+
-+/* send the packet in buffer.*/
-+void putpacket(char *buffer)
-+{
-+ unsigned char checksum;
-+ int count;
-+ char ch;
-+
-+ /* $<packet info>#<checksum>. */
-+ do {
-+ putDebugChar('$');
-+ checksum = 0;
-+ count = 0;
-+
-+ while ((ch = buffer[count])) {
-+ putDebugChar(ch);
-+ checksum += ch;
-+ count += 1;
-+ }
-+
-+ putDebugChar('#');
-+ putDebugChar(hexchars[checksum >> 4]);
-+ putDebugChar(hexchars[checksum % 16]);
-+
-+ } while ((getDebugChar() & 0x7f) != '+');
-+
-+}
-+
-+/* convert the memory pointed to by mem into hex, placing result in buf */
-+/* return a pointer to the last char put in buf (null) */
-+/* If MAY_FAULT is non-zero, then we should set kgdb_memerr in response to
-+ a fault; if zero treat a fault like any other fault in the stub. */
-+
-+char *mem2hex(char *mem, char *buf, int count, int can_fault)
-+{
-+ int i;
-+ unsigned char ch;
-+
-+ for (i = 0; i < count; i++) {
-+
-+ if (get_char(mem++, &ch, can_fault) < 0)
-+ break;
-+
-+ *buf++ = hexchars[ch >> 4];
-+ *buf++ = hexchars[ch % 16];
-+ }
-+ *buf = 0;
-+ return (buf);
-+}
-+
-+/* convert the hex array pointed to by buf into binary to be placed in mem */
-+/* return a pointer to the character AFTER the last byte written */
-+
-+char *hex2mem(char *buf, char *mem, int count, int can_fault)
-+{
-+ int i;
-+ unsigned char ch;
-+
-+ for (i = 0; i < count; i++) {
-+ ch = hex(*buf++) << 4;
-+ ch = ch + hex(*buf++);
-+ if (set_char(mem++, ch, can_fault) < 0)
-+ break;
-+ }
-+ return (mem);
-+}
-+
-+
-+/*
-+ * WHILE WE FIND NICE HEX CHARS, BUILD AN INT
-+ * RETURN NUMBER OF CHARS PROCESSED
-+ */
-+int hexToInt(char **ptr, int *intValue)
-+{
-+ int numChars = 0;
-+ int hexValue;
-+
-+ *intValue = 0;
-+
-+ while (**ptr) {
-+ hexValue = hex(**ptr);
-+ if (hexValue >= 0) {
-+ *intValue = (*intValue << 4) | hexValue;
-+ numChars++;
-+ } else
-+ break;
-+
-+ (*ptr)++;
-+ }
-+
-+ return (numChars);
-+}
-+
-+static int stubhex(int ch)
-+{
-+ if (ch >= 'a' && ch <= 'f')
-+ return ch - 'a' + 10;
-+ if (ch >= '0' && ch <= '9')
-+ return ch - '0';
-+ if (ch >= 'A' && ch <= 'F')
-+ return ch - 'A' + 10;
-+ return -1;
-+}
-+
-+
-+static int stub_unpack_int(char *buff, int fieldlength)
-+{
-+ int nibble;
-+ int retval = 0;
-+
-+ while (fieldlength) {
-+ nibble = stubhex(*buff++);
-+ retval |= nibble;
-+ fieldlength--;
-+ if (fieldlength)
-+ retval = retval << 4;
-+ }
-+ return retval;
-+}
-+
-+static inline char *pack_hex_byte(char *pkt, int byte)
-+{
-+ *pkt++ = hexchars[(byte >> 4) & 0xf];
-+ *pkt++ = hexchars[(byte & 0xf)];
-+ return pkt;
-+}
-+
-+#define BUF_THREAD_ID_SIZE 16
-+
-+static char *pack_threadid(char *pkt, threadref *id)
-+{
-+ char *limit;
-+ unsigned char *altid;
-+
-+ altid = (unsigned char *) id;
-+ limit = pkt + BUF_THREAD_ID_SIZE;
-+ while (pkt < limit)
-+ pkt = pack_hex_byte(pkt, *altid++);
-+
-+ return pkt;
-+}
-+
-+static char *unpack_byte(char *buf, int *value)
-+{
-+ *value = stub_unpack_int(buf, 2);
-+ return buf + 2;
-+}
-+
-+static char *unpack_threadid(char *inbuf, threadref *id)
-+{
-+ char *altref;
-+ char *limit = inbuf + BUF_THREAD_ID_SIZE;
-+ int x, y;
-+
-+ altref = (char *) id;
-+
-+ while (inbuf < limit) {
-+ x = stubhex(*inbuf++);
-+ y = stubhex(*inbuf++);
-+ *altref++ = (x << 4) | y;
-+ }
-+ return inbuf;
-+}
-+
-+void int_to_threadref(threadref *id, int value)
-+{
-+ unsigned char *scan;
-+
-+ scan = (unsigned char *) id;
-+ {
-+ int i = 4;
-+ while (i--)
-+ *scan++ = 0;
-+ }
-+ *scan++ = (value >> 24) & 0xff;
-+ *scan++ = (value >> 16) & 0xff;
-+ *scan++ = (value >> 8) & 0xff;
-+ *scan++ = (value & 0xff);
-+}
-+
-+static int threadref_to_int(threadref * ref)
-+{
-+ int i, value = 0;
-+ unsigned char *scan;
-+
-+ scan = (char *) ref;
-+ scan += 4;
-+ i = 4;
-+ while (i-- > 0)
-+ value = (value << 8) | ((*scan++) & 0xff);
-+ return value;
-+}
-+
-+
-+struct task_struct *getthread(int tid)
-+{
-+#if CONFIG_SMP
-+ if (tid >= PID_MAX && tid < PID_MAX + smp_num_cpus)
-+ return init_tasks[tid - PID_MAX];
-+#else
-+ if (tid == PID_MAX)
-+ tid = 0;
-+#endif
-+ return find_task_by_pid(tid);
-+}
-+
-+#ifdef CONFIG_SMP
-+void gdb_wait(struct pt_regs *regs)
-+{
-+ unsigned flags;
-+ int processor;
-+
-+ local_irq_save(flags);
-+ processor = smp_processor_id();
-+ procindebug[processor] = 1;
-+ current->thread.kgdbregs = regs;
-+
-+ /* Wait till master processor goes completely into the debugger */
-+ while (!procindebug[atomic_read(&kgdb_lock) - 1]) {
-+ int i = 10; /* an arbitrary number */
-+
-+ while (--i)
-+ asm volatile ("nop": : : "memory");
-+ barrier();
-+ }
-+
-+ /* Wait till master processor is done with debugging */
-+ spin_lock(slavecpulocks + processor);
-+
-+ /* This has been taken from x86 kgdb implementation and
-+ * will be needed by architectures that have SMP support
-+ */
-+ if (kgdb_ops->correct_hw_break)
-+ kgdb_ops->correct_hw_break();
-+
-+ /* Signal the master processor that we are done */
-+ procindebug[processor] = 0;
-+ spin_unlock(slavecpulocks + processor);
-+ local_irq_restore(flags);
-+}
-+
-+#endif
-+
-+static void get_mem (char *addr, unsigned char *buf, int count)
-+{
-+ while (count) {
-+ if(get_char(addr++, buf, 1) < 0)
-+ return;
-+ buf++;
-+ count--;
-+ }
-+}
-+
-+static void set_mem (char *addr,unsigned char *buf, int count)
-+{
-+ while (count) {
-+ if (set_char(addr++,*buf++, 1) < 0)
-+ return;
-+ count--;
-+ }
-+}
-+
-+
-+
-+static int set_break (unsigned long addr)
-+{
-+ int i, breakno = -1;
-+
-+ for (i = 0; i < MAX_BREAKPOINTS; i++) {
-+ if ((kgdb_break[i].state == bp_enabled) &&
-+ (kgdb_break[i].bpt_addr == addr)) {
-+ breakno = -1;
-+ break;
-+ }
-+
-+ if (kgdb_break[i].state == bp_disabled) {
-+ if ((breakno == -1) || (kgdb_break[i].bpt_addr == addr))
-+ breakno = i;
-+ }
-+ }
-+ if (breakno == -1)
-+ return -1;
-+
-+ get_mem((char *)addr, kgdb_break[breakno].saved_instr, BREAK_INSTR_SIZE);
-+ if (kgdb_memerr)
-+ return -1;
-+
-+ set_mem((char *)addr, kgdb_ops->gdb_bpt_instr, BREAK_INSTR_SIZE);
-+ flush_cache_range (current->mm, addr, addr + BREAK_INSTR_SIZE);
-+ flush_icache_range (addr, addr + BREAK_INSTR_SIZE);
-+ if (kgdb_memerr)
-+ return -1;
-+
-+ kgdb_break[breakno].state = bp_enabled;
-+ kgdb_break[breakno].type = bp_breakpoint;
-+ kgdb_break[breakno].bpt_addr = addr;
-+
-+ return 0;
-+}
-+
-+static int remove_break (unsigned addr)
-+{
-+ int i;
-+
-+ for (i=0; i < MAX_BREAKPOINTS; i++) {
-+ if ((kgdb_break[i].state == bp_enabled) &&
-+ (kgdb_break[i].bpt_addr == addr)) {
-+ set_mem((char *)addr, kgdb_break[i].saved_instr,
-+ BREAK_INSTR_SIZE);
-+ flush_cache_range (current->mm, addr, addr + BREAK_INSTR_SIZE);
-+ flush_icache_range (addr, addr + BREAK_INSTR_SIZE);
-+ if (kgdb_memerr)
-+ return -1;
-+ kgdb_break[i].state = bp_disabled;
-+ return 0;
-+ }
-+ }
-+ return -1;
-+}
-+
-+int remove_all_break(void)
-+{
-+ int i;
-+ for (i=0; i < MAX_BREAKPOINTS; i++) {
-+ if(kgdb_break[i].state == bp_enabled) {
-+ unsigned long addr = kgdb_break[i].bpt_addr;
-+ set_mem((char *)addr, kgdb_break[i].saved_instr,
-+ BREAK_INSTR_SIZE);
-+ flush_cache_range (current->mm, addr, addr + BREAK_INSTR_SIZE);
-+ flush_icache_range (addr, addr + BREAK_INSTR_SIZE);
-+ }
-+ kgdb_break[i].state = bp_disabled;
-+ }
-+ return 0;
-+}
-+
-+int get_char(char *addr, unsigned char *data, int can_fault)
-+{
-+ mm_segment_t fs;
-+ int ret = 0;
-+
-+ kgdb_memerr = 0;
-+
-+ if (can_fault)
-+ kgdb_memerr_expected = 1;
-+ wmb();
-+ fs = get_fs();
-+ set_fs(KERNEL_DS);
-+
-+ if (get_user(*data, addr) != 0) {
-+ ret = -EFAULT;
-+ kgdb_memerr = 1;
-+ }
-+
-+ kgdb_memerr_expected = 0;
-+ set_fs(fs);
-+ return ret;
-+}
-+
-+int set_char(char *addr, int data, int can_fault)
-+{
-+ mm_segment_t fs;
-+ int ret = 0;
-+
-+ kgdb_memerr = 0;
-+
-+ if (can_fault)
-+ kgdb_memerr_expected = 1;
-+ wmb();
-+ fs = get_fs();
-+ set_fs(KERNEL_DS);
-+
-+ if (put_user(data, addr) != 0) {
-+ ret = -EFAULT;
-+ kgdb_memerr = 1;
-+ }
-+
-+ kgdb_memerr_expected = 0;
-+ set_fs(fs);
-+ return ret;
-+}
-+
-+/*
-+ * This function does all command procesing for interfacing to gdb.
-+ */
-+
-+int kgdb_handle_exception(int exVector, int signo, int err_code,
-+ struct pt_regs *linux_regs)
-+{
-+ int length, addr;
-+ char *ptr;
-+ unsigned long flags;
-+ int gdb_regs[NUMREGBYTES / 4];
-+ int i;
-+ int threadid;
-+#ifdef CONFIG_KGDB_THREAD
-+ threadref thref;
-+ struct task_struct *thread = NULL;
-+ int nothreads;
-+ int maxthreads;
-+#endif
-+ unsigned procid;
-+ int ret = 0;
-+ struct pt_regs *oldregs = current->thread.kgdbregs;
-+
-+ /*
-+ * Interrupts will be restored by the 'trap return' code, except when
-+ * single stepping.
-+ */
-+ local_irq_save(flags);
-+
-+ /* Hold kgdb_lock */
-+ procid = smp_processor_id();
-+ while (cmpxchg(&atomic_read(&kgdb_lock), 0, (procid + 1)) != 0) {
-+ int i = 25; /* an arbitrary number */
-+
-+ while (--i)
-+ asm volatile ("nop": : : "memory");
-+ }
-+
-+ kgdb_step = 0;
-+
-+
-+ local_irq_save(flags);
-+
-+ current->thread.kgdbregs = linux_regs;
-+
-+ if (kgdb_ops->disable_hw_debug)
-+ kgdb_ops->disable_hw_debug(linux_regs);
-+
-+
-+ for (i = 0; i < smp_num_cpus; i++) {
-+ spin_lock(&slavecpulocks[i]);
-+ }
-+
-+ /* spin_lock code is good enough as a barrier so we don't
-+ * need one here */
-+ procindebug[smp_processor_id()] = 1;
-+
-+ /* Master processor is completely in the debugger */
-+
-+ if (kgdb_ops->post_master_code)
-+ kgdb_ops->post_master_code(linux_regs, exVector, err_code);
-+
-+ if (atomic_read(&kgdb_killed_or_detached) &&
-+ atomic_read(&kgdb_might_be_resumed)) {
-+ getpacket(remcomInBuffer);
-+ if(remcomInBuffer[0] == 'H' && remcomInBuffer[1] =='c') {
-+ remove_all_break();
-+ atomic_set(&kgdb_killed_or_detached, 0);
-+ remcomOutBuffer[0] = 'O';
-+ remcomOutBuffer[1] = 'K';
-+ remcomOutBuffer[2] = 0;
-+ }
-+ else
-+ return 1;
-+ }
-+ else {
-+
-+ /* reply to host that an exception has occurred */
-+ remcomOutBuffer[0] = 'S';
-+ remcomOutBuffer[1] = hexchars[signo >> 4];
-+ remcomOutBuffer[2] = hexchars[signo % 16];
-+ remcomOutBuffer[3] = 'p';
-+
-+ int_to_threadref(&thref, current->pid ?
-+ current->pid :
-+ PID_MAX + cpu_number_map(smp_processor_id()));
-+
-+ *pack_threadid(remcomOutBuffer + 4, &thref) = 0;
-+ }
-+ putpacket(remcomOutBuffer);
-+
-+ kgdb_usethread = current;
-+
-+ while (1) {
-+ int bpt_type = 0;
-+ error = 0;
-+ remcomOutBuffer[0] = 0;
-+ remcomOutBuffer[1] = 0;
-+ getpacket(remcomInBuffer);
-+
-+#if KGDB_DEBUG
-+ bust_spinlocks(1);
-+ printk("CPU%d pid%d GDB packet: %s\n",
-+ smp_processor_id(), current->pid, remcomInBuffer);
-+ bust_spinlocks(0);
-+#endif
-+ switch (remcomInBuffer[0]) {
-+ case '?':
-+ remcomOutBuffer[0] = 'S';
-+ remcomOutBuffer[1] = hexchars[signo >> 4];
-+ remcomOutBuffer[2] = hexchars[signo % 16];
-+ remcomOutBuffer[3] = 0;
-+ break;
-+
-+ case 'g': /* return the value of the CPU registers */
-+ thread = kgdb_usethread;
-+
-+ if (!thread)
-+ thread = current;
-+
-+ /* All threads that don't have kgdbregs should be
-+ in __schedule() sleeping, since all other CPUs
-+ are in gdbwait, and thus have kgdbregs. */
-+
-+ if (thread->thread.kgdbregs)
-+ kgdb_ops->regs_to_gdb_regs(gdb_regs, thread->thread.kgdbregs);
-+ else {
-+ /* Pull stuff saved during
-+ * switch_to; nothing else is
-+ accessible (or even particularly relevant).
-+ This should be enough for a stack trace. */
-+ kgdb_ops->sleeping_thread_to_gdb_regs(gdb_regs, thread);
-+ }
-+
-+ mem2hex((char *) gdb_regs, remcomOutBuffer, NUMREGBYTES, 0);
-+ break;
-+
-+ case 'G': /* set the value of the CPU registers - return OK */
-+ hex2mem(&remcomInBuffer[1], (char *) gdb_regs,
-+ NUMREGBYTES, 0);
-+
-+ if (kgdb_usethread && kgdb_usethread != current)
-+ strcpy(remcomOutBuffer, "E00");
-+ else {
-+ kgdb_ops->gdb_regs_to_regs(gdb_regs, current->thread.kgdbregs);
-+ strcpy(remcomOutBuffer, "OK");
-+ }
-+
-+ break;
-+
-+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
-+ case 'm':
-+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
-+ ptr = &remcomInBuffer[1];
-+ if (hexToInt(&ptr, &addr) && *ptr++ == ',' &&
-+ hexToInt(&ptr, &length)) {
-+ ptr = 0;
-+ mem2hex((char *) addr, remcomOutBuffer, length, 1);
-+ if (kgdb_memerr)
-+ strcpy(remcomOutBuffer, "E03");
-+
-+ }
-+
-+ if (ptr)
-+ strcpy(remcomOutBuffer, "E01");
-+ break;
-+
-+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
-+ case 'M':
-+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
-+ ptr = &remcomInBuffer[1];
-+ if (hexToInt(&ptr, &addr) && *(ptr++) == ',' &&
-+ hexToInt(&ptr, &length) && *(ptr++) == ':') {
-+ hex2mem(ptr, (char *)addr, length, 1);
-+ if (kgdb_memerr)
-+ strcpy(remcomOutBuffer, "E03");
-+ else
-+ strcpy(remcomOutBuffer, "OK");
-+ ptr = 0;
-+ }
-+ if (ptr) {
-+ strcpy(remcomOutBuffer, "E02");
-+ }
-+ break;
-+
-+
-+ /* Continue and Single Step are Architecture specific
-+ * and will not be handled by the generic code.
-+ */
-+
-+
-+ /* kill the program. KGDB should treat this like a
-+ * continue.
-+ */
-+ case 'D':
-+ remcomOutBuffer[0] = 'O';
-+ remcomOutBuffer[1] = 'K';
-+ remcomOutBuffer[2] = '\0';
-+ remove_all_break();
-+ putpacket(remcomOutBuffer);
-+ goto default_handle;
-+
-+ case 'k':
-+ remove_all_break();
-+ goto default_handle;
-+
-+ /* query */
-+ case 'q':
-+ switch (remcomInBuffer[1]) {
-+ case 'L':
-+ /* List threads */
-+ unpack_byte(remcomInBuffer + 3,
-+ &maxthreads);
-+ unpack_threadid(remcomInBuffer + 5,
-+ &thref);
-+
-+ remcomOutBuffer[0] = 'q';
-+ remcomOutBuffer[1] = 'M';
-+ remcomOutBuffer[4] = '0';
-+ pack_threadid(remcomOutBuffer + 5, &thref);
-+
-+ threadid = threadref_to_int(&thref);
-+ for (nothreads = 0;
-+ nothreads < maxthreads
-+ && threadid < PID_MAX + smp_num_cpus; threadid++) {
-+ thread = getthread(threadid);
-+ if (thread) {
-+ int_to_threadref(&thref,
-+ threadid);
-+ pack_threadid
-+ (remcomOutBuffer + 21 +
-+ nothreads * 16,
-+ &thref);
-+ nothreads++;
-+ }
-+ }
-+
-+
-+ if (threadid == PID_MAX + smp_num_cpus) {
-+ remcomOutBuffer[4] = '1';
-+ }
-+ pack_hex_byte(remcomOutBuffer + 2,
-+ nothreads);
-+ remcomOutBuffer[21 + nothreads * 16] = '\0';
-+ break;
-+
-+ case 'C':
-+ /* Current thread id */
-+ remcomOutBuffer[0] = 'Q';
-+ remcomOutBuffer[1] = 'C';
-+ threadid = current->pid;
-+
-+ if (threadid == 0)
-+ threadid = cpu_number_map(smp_processor_id()) + PID_MAX;
-+
-+ int_to_threadref(&thref, threadid);
-+ pack_threadid(remcomOutBuffer + 2, &thref);
-+ remcomOutBuffer[18] = '\0';
-+ break;
-+
-+ case 'E':
-+ /* Print exception info */
-+ if (kgdb_ops->printexpinfo)
-+ kgdb_ops->printexpinfo(exVector,
-+ err_code,
-+ remcomOutBuffer);
-+ break;
-+ }
-+ break;
-+
-+ /* task related */
-+ case 'H':
-+ switch (remcomInBuffer[1]) {
-+ case 'g':
-+ ptr = &remcomInBuffer[2];
-+ hexToInt(&ptr, &threadid);
-+ thread = getthread(threadid);
-+ if (!thread && threadid > 0) {
-+ remcomOutBuffer[0] = 'E';
-+ remcomOutBuffer[1] = '\0';
-+ break;
-+ }
-+ kgdb_usethread = thread;
-+ remcomOutBuffer[0] = 'O';
-+ remcomOutBuffer[1] = 'K';
-+ remcomOutBuffer[2] = '\0';
-+ break;
-+
-+ case 'c':
-+ atomic_set(&kgdb_killed_or_detached, 0);
-+ ptr = &remcomInBuffer[2];
-+ hexToInt(&ptr, &threadid);
-+ thread = getthread(threadid);
-+ if (!thread && threadid > 0) {
-+ remcomOutBuffer[0] = 'E';
-+ remcomOutBuffer[1] = '\0';
-+ break;
-+ }
-+ kgdb_contthread = thread;
-+ remcomOutBuffer[0] = 'O';
-+ remcomOutBuffer[1] = 'K';
-+ remcomOutBuffer[2] = '\0';
-+ break;
-+ }
-+ break;
-+
-+ /* Query thread status */
-+ case 'T':
-+ ptr = &remcomInBuffer[1];
-+ hexToInt(&ptr, &threadid);
-+ thread = getthread(threadid);
-+ if (thread) {
-+ remcomOutBuffer[0] = 'O';
-+ remcomOutBuffer[1] = 'K';
-+ remcomOutBuffer[2] = '\0';
-+ } else {
-+ remcomOutBuffer[0] = 'E';
-+ remcomOutBuffer[1] = '\0';
-+ }
-+ break;
-+ case 'z':
-+ case 'Z':
-+ ptr = &remcomInBuffer[2];
-+ if (*(ptr++) != ',') {
-+ strcpy(remcomOutBuffer, "ERROR");
-+ break;
-+ }
-+ hexToInt(&ptr, &addr);
-+
-+ bpt_type = remcomInBuffer[1];
-+ if (bpt_type != bp_breakpoint) {
-+ if (bpt_type == bp_hardware_breakpoint &&
-+ !(kgdb_ops->flags & KGDB_HW_BREAKPOINT))
-+ break;
-+
-+ /* if set_break is not defined, then
-+ * remove_break does not matter
-+ */
-+ if(!kgdb_ops->set_break)
-+ break;
-+ }
-+
-+ if (remcomInBuffer[0] == 'Z') {
-+ if (bpt_type == bp_breakpoint)
-+ ret = set_break(addr);
-+ else
-+ ret = kgdb_ops->set_break(addr, bpt_type);
-+ }
-+ else {
-+ if (bpt_type == bp_breakpoint)
-+ ret = remove_break(addr);
-+ else
-+ ret = kgdb_ops->remove_break(addr, bpt_type);
-+ }
-+
-+ if (ret == 0)
-+ strcpy(remcomOutBuffer, "OK");
-+ else
-+ strcpy(remcomOutBuffer, "ERROR");
-+
-+ break;
-+
-+ default:
-+ default_handle:
-+ ret = 0;
-+ if (kgdb_ops->handle_buffer)
-+ ret= kgdb_ops->handle_buffer(exVector, signo,
-+ err_code,
-+ remcomInBuffer,
-+ remcomOutBuffer,
-+ linux_regs);
-+ if(ret >= 0 || remcomInBuffer[0] == 'D' ||
-+ remcomInBuffer[0] == 'k')
-+ goto kgdb_exit;
-+
-+
-+ } /* switch */
-+#if KGDB_DEBUG
-+ bust_spinlocks(1);
-+ printk("Response to GDB: %s\n", remcomOutBuffer);
-+ bust_spinlocks(0);
-+#endif
-+
-+ /* reply to the request */
-+ putpacket(remcomOutBuffer);
-+ }
-+kgdb_exit:
-+
-+ if(kgdb_ops->handler_exit)
-+ kgdb_ops->handler_exit();
-+
-+ procindebug[smp_processor_id()] = 0;
-+
-+ for (i = 0; i < smp_num_cpus; i++) {
-+ spin_unlock(&slavecpulocks[i]);
-+ }
-+ /* Wait till all the processors have quit
-+ * from the debugger
-+ */
-+ for (i = 0; i < smp_num_cpus; i++) {
-+ while (procindebug[i]) {
-+ int j = 10; /* an arbitrary number */
-+
-+ while (--j) {
-+ asm volatile ("nop" : : : "memory");
-+ }
-+ barrier();
-+ }
-+ }
-+
-+ /* Free kgdb_lock */
-+ atomic_set(&kgdb_lock, 0);
-+ current->thread.kgdbregs = oldregs;
-+ atomic_set(&kgdb_killed_or_detached, 1);
-+ local_irq_restore(flags);
-+ return ret;
-+}
-+
-+/* this function is used to set up exception handlers for tracing and
-+ breakpoints */
-+void set_debug_traps(void)
-+{
-+ int i;
-+
-+ for (i = 0; i < KGDB_MAX_NO_CPUS; i++)
-+ spin_lock_init(&slavecpulocks[i]);
-+
-+ /* Free kgdb_lock */
-+ atomic_set(&kgdb_lock, 0);
-+
-+ /* This flag is used, if gdb has detached and wants to start
-+ * another session
-+ */
-+ atomic_set(&kgdb_killed_or_detached, 0);
-+ atomic_set(&kgdb_might_be_resumed, 0);
-+
-+ for (i = 0; i < MAX_BREAKPOINTS; i++)
-+ kgdb_break[i].state = bp_disabled;
-+
-+
-+ /*
-+ * In case GDB is started before us, ack any packets (presumably
-+ * "$?#xx") sitting there. */
-+ putDebugChar('+');
-+
-+ linux_debug_hook = kgdb_handle_exception;
-+
-+ if (kgdb_ops->kgdb_init)
-+ kgdb_ops->kgdb_init();
-+
-+ kgdb_initialized = 1;
-+ atomic_set(&kgdb_setting_breakpoint, 0);
-+}
-+
-+/* This function will generate a breakpoint exception. It is used at the
-+ beginning of a program to sync up with a debugger and can be used
-+ otherwise as a quick means to stop program execution and "break" into
-+ the debugger. */
-+
-+void breakpoint(void)
-+{
-+ if (kgdb_initialized) {
-+ atomic_set(&kgdb_setting_breakpoint, 1);
-+ wmb();
-+ BREAKPOINT();
-+ wmb();
-+ atomic_set(&kgdb_setting_breakpoint, 0);
-+ }
-+}
-+
-+#ifdef CONFIG_GDB_CONSOLE
-+char gdbconbuf[BUFMAX];
-+
-+void gdb_console_write(struct console *co, const char *s, unsigned count)
-+{
-+ int i;
-+ int wcount;
-+ char *bufptr;
-+ int flags;
-+
-+ if (!gdb_initialized || atomic_read(&kgdb_killed_or_detached)) {
-+ return;
-+ }
-+ local_irq_save(flags);
-+
-+ gdbconbuf[0] = 'O';
-+ bufptr = gdbconbuf + 1;
-+ while (count > 0) {
-+ if ((count << 1) > (BUFMAX - 2)) {
-+ wcount = (BUFMAX - 2) >> 1;
-+ } else {
-+ wcount = count;
-+ }
-+ count -= wcount;
-+ for (i = 0; i < wcount; i++) {
-+ bufptr = pack_hex_byte(bufptr, s[i]);
-+ }
-+ *bufptr = '\0';
-+ s += wcount;
-+
-+ putpacket(gdbconbuf);
-+
-+ }
-+ local_irq_restore(flags);
-+}
-+#endif
-+
-+int gdb_enter;
-+int gdb_baud = 115200;
-+int gdb_ttyS;
-+int gdb_initialized;
-+
-+static int __init kgdb_opt_gdb(char *str)
-+{
-+ gdb_enter = 1;
-+ return 1;
-+}
-+static int __init kgdb_opt_gdbttyS(char *str)
-+{
-+ gdb_ttyS = simple_strtoul(str, NULL, 10);
-+ return 1;
-+}
-+static int __init kgdb_opt_gdbbaud(char *str)
-+{
-+ gdb_baud = simple_strtoul(str, NULL, 10);
-+ return 1;
-+}
-+
-+/*
-+ * Sequence of these lines has to be maintained because gdb option is a prefix
-+ * of the other two options
-+ */
-+
-+__setup("gdbttyS=", kgdb_opt_gdbttyS);
-+__setup("gdbbaud=", kgdb_opt_gdbbaud);
-+__setup("gdb", kgdb_opt_gdb);
-Index: linux-2.4.26-ct_sync/kernel/ksyms.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/kernel/ksyms.c 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.26-ct_sync/kernel/ksyms.c 2004-06-28 12:56:07.000000000 +0200
-@@ -51,6 +51,9 @@
- #include <linux/crc32.h>
- #include <linux/firmware.h>
- #include <asm/checksum.h>
-+#ifdef CONFIG_KGDB
-+#include <linux/kgdb.h>
-+#endif
-
- #if defined(CONFIG_PROC_FS)
- #include <linux/proc_fs.h>
-@@ -467,7 +470,13 @@
- EXPORT_SYMBOL(sleep_on_timeout);
- EXPORT_SYMBOL(interruptible_sleep_on);
- EXPORT_SYMBOL(interruptible_sleep_on_timeout);
--EXPORT_SYMBOL(schedule);
-+EXPORT_SYMBOL(do_schedule);
-+#ifdef CONFIG_KGDB
-+EXPORT_SYMBOL(breakpoint);
-+#ifdef CONFIG_KGDB_THREAD
-+EXPORT_SYMBOL(kern_schedule);
-+#endif
-+#endif
- EXPORT_SYMBOL(schedule_timeout);
- #if CONFIG_SMP
- EXPORT_SYMBOL(set_cpus_allowed);
-Index: linux-2.4.26-ct_sync/kernel/sched.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/kernel/sched.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/kernel/sched.c 2004-06-28 12:56:07.000000000 +0200
-@@ -544,7 +544,7 @@
- * tasks can run. It can not be killed, and it cannot sleep. The 'state'
- * information in task[0] is never used.
- */
--asmlinkage void schedule(void)
-+asmlinkage void do_schedule(void)
- {
- struct schedule_data * sched_data;
- struct task_struct *prev, *next, *p;
-@@ -702,6 +702,22 @@
- return;
- }
-
-+asmlinkage void user_schedule(void)
-+{
-+#ifdef CONFIG_KGDB_THREAD
-+ current->thread.kgdbregs = NULL;
-+#endif
-+ do_schedule();
-+}
-+
-+#ifdef CONFIG_KGDB_THREAD
-+asmlinkage void kern_do_schedule(struct pt_regs regs)
-+{
-+ current->thread.kgdbregs = ®s;
-+ do_schedule();
-+}
-+#endif
-+
- /*
- * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just wake everything
- * up. If it's an exclusive wakeup (nr_exclusive == small +ve number) then we wake all the
-Index: linux-2.4.26-ct_sync/include/asm-ppc/kgdb.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-ppc/kgdb.h 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/asm-ppc/kgdb.h 2004-06-28 12:56:07.000000000 +0200
-@@ -2,47 +2,40 @@
- * kgdb.h: Defines and declarations for serial line source level
- * remote debugging of the Linux kernel using gdb.
- *
-+ * PPC Mods (C) 2003 John Whitney (john.whitney at timesys.com)
-+ *
- * PPC Mods (C) 1998 Michael Tesch (tesch at cs.wisc.edu)
- *
- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
- */
- #ifdef __KERNEL__
--#ifndef _PPC_KGDB_H
--#define _PPC_KGDB_H
--
--#ifndef __ASSEMBLY__
--/* To initialize the serial, first thing called */
--extern void kgdb_map_scc(void);
--/* To init the kgdb engine. (called by serial hook)*/
--extern void set_debug_traps(void);
--
--/* To enter the debugger explicitly. */
--extern void breakpoint(void);
-+#ifndef _ASMPPC_KGDB_H
-+#define _ASMPPC_KGDB_H
-
--/* For taking exceptions
-- * these are defined in traps.c
-+/*
-+ * For taking exceptions these are defined in traps.c
- */
--extern void (*debugger)(struct pt_regs *regs);
--extern int (*debugger_bpt)(struct pt_regs *regs);
--extern int (*debugger_sstep)(struct pt_regs *regs);
--extern int (*debugger_iabr_match)(struct pt_regs *regs);
--extern int (*debugger_dabr_match)(struct pt_regs *regs);
--extern void (*debugger_fault_handler)(struct pt_regs *regs);
--
--/* What we bring to the party */
--int kgdb_bpt(struct pt_regs *regs);
--int kgdb_sstep(struct pt_regs *regs);
--void kgdb(struct pt_regs *regs);
--int kgdb_iabr_match(struct pt_regs *regs);
--int kgdb_dabr_match(struct pt_regs *regs);
-+extern void (*debugger) (struct pt_regs *regs);
-+extern int (*debugger_bpt) (struct pt_regs *regs);
-+extern int (*debugger_sstep) (struct pt_regs *regs);
-+extern int (*debugger_iabr_match) (struct pt_regs *regs);
-+extern int (*debugger_dabr_match) (struct pt_regs *regs);
-+extern void (*debugger_fault_handler) (struct pt_regs *regs);
-
- /*
- * external low-level support routines (ie macserial.c)
- */
--extern void kgdb_interruptible(int); /* control interrupts from serial */
--extern void putDebugChar(char); /* write a single character */
--extern char getDebugChar(void); /* read and return a single char */
-+extern void kgdb_interruptible (int); /* control interrupts from serial */
-+extern void putDebugChar (char); /* write a single character */
-+extern char getDebugChar (void); /* read and return a single char */
-+
-+#define BREAK_INSTR_SIZE 4
-+#define MAXREG (PT_FPSCR+1)
-+#define NUMREGBYTES (MAXREG * sizeof (int))
-+#define BUFMAX ((NUMREGBYTES * 2) + 512)
-+#define OUTBUFMAX ((NUMREGBYTES * 2) + 512)
-+
-+#define BREAKPOINT() asm (".long 0x7d821008");
-
--#endif /* !(__ASSEMBLY__) */
--#endif /* !(_PPC_KGDB_H) */
-+#endif /* !(_ASMPPC_KGDB_H) */
- #endif /* __KERNEL__ */
-Index: linux-2.4.26-ct_sync/include/asm-ppc/ioctls.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-ppc/ioctls.h 2003-06-13 16:51:38.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/asm-ppc/ioctls.h 2004-06-28 12:56:07.000000000 +0200
-@@ -105,4 +105,6 @@
- #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
- #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
-
-+#define TIOCGDB 0x547F /* enable GDB stub mode on this tty */
-+
- #endif /* _ASM_PPC_IOCTLS_H */
-Index: linux-2.4.26-ct_sync/include/asm-ppc/processor.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-ppc/processor.h 2004-04-14 15:05:40.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/asm-ppc/processor.h 2004-06-28 12:56:07.000000000 +0200
-@@ -843,6 +843,9 @@
- /* Saved 4xx debug registers */
- unsigned long dbcr0;
- #endif
-+#ifdef CONFIG_KGDB
-+ struct pt_regs *kgdbregs;
-+#endif
- };
-
- #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
-Index: linux-2.4.26-ct_sync/include/linux/kgdb-asserts.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/kgdb-asserts.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/kgdb-asserts.h 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,31 @@
-+#ifndef _GDB_ASSERTS_H_
-+#define _GDB_ASSERTS_H_
-+
-+/*
-+ * Copyright (C) 2001 Amit S. Kale
-+ */
-+
-+#define KGDB_ASSERT(message, condition) do { \
-+ if (!(condition)) { \
-+ printk("kgdb assertion failed: %s\n", message); \
-+ breakpoint(); \
-+ } \
-+} while (0)
-+
-+#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
-+
-+#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
-+
-+#define KA_VALID_KPTR(ptr) (!(ptr) || \
-+ ((void *)(ptr) >= (void *)PAGE_OFFSET && \
-+ (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
-+
-+#define KA_VALID_PTRORERR(errptr) (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
-+
-+#ifndef CONFIG_SMP
-+#define KA_HELD_GKL() 1
-+#else
-+#define KA_HELD_GKL() (current->lock_depth >= 0)
-+#endif
-+
-+#endif /* _GDB_ASSERTS_H_ */
-Index: linux-2.4.26-ct_sync/include/linux/kgdb.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/kgdb.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/kgdb.h 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,80 @@
-+#ifndef _GDB_H_
-+#define _GDB_H_
-+
-+/*
-+ * Copyright (C) 2001 Amit S. Kale
-+ */
-+
-+#include <linux/ptrace.h>
-+#include <asm/kgdb.h>
-+#include <linux/spinlock.h>
-+#include <linux/kgdb-defs.h>
-+
-+enum gdb_bptype
-+{
-+ bp_breakpoint = '0',
-+ bp_hardware_breakpoint,
-+ bp_write_watchpoint,
-+ bp_read_watchpoint,
-+ bp_access_watchpoint
-+};
-+
-+enum gdb_bpstate
-+{
-+ bp_disabled,
-+ bp_enabled
-+};
-+
-+#ifndef BREAK_INSTR_SIZE
-+#error BREAK_INSTR_SIZE needed by kgdb
-+#endif
-+
-+struct gdb_breakpoint
-+{
-+ unsigned int bpt_addr;
-+ unsigned char saved_instr[BREAK_INSTR_SIZE];
-+ enum gdb_bptype type;
-+ enum gdb_bpstate state;
-+};
-+
-+typedef struct gdb_breakpoint gdb_breakpoint_t;
-+
-+#ifndef MAX_BREAKPOINTS
-+#define MAX_BREAKPOINTS 16
-+#endif
-+
-+#define KGDB_HW_BREAKPOINT 1
-+
-+struct kgdb_arch {
-+ unsigned char gdb_bpt_instr[BREAK_INSTR_SIZE];
-+ unsigned long flags;
-+
-+ int (*kgdb_init) (void);
-+ void (*regs_to_gdb_regs)(int *gdb_regs, struct pt_regs *regs);
-+ void (*sleeping_thread_to_gdb_regs)(int *gdb_regs,struct task_struct *p);
-+ void (*gdb_regs_to_regs)(int *gdb_regs, struct pt_regs *regs);
-+ void (*printexpinfo)(int exceptionNo, int errorcode, char *buffer);
-+ void (*disable_hw_debug) (struct pt_regs *regs);
-+ void (*post_master_code) (struct pt_regs *regs, int eVector, int err_code);
-+ int (*handle_buffer) (int vector, int signo, int err_code,
-+ char *InBuffer, char *outBuffer,
-+ struct pt_regs *regs);
-+ int (*set_break) (unsigned long addr, int type);
-+ int (*remove_break) (unsigned long addr, int type);
-+ void (*correct_hw_break) (void);
-+ void (*handler_exit) (void);
-+};
-+
-+
-+/* Thread reference */
-+typedef unsigned char threadref[8];
-+
-+/* Routine prototypes */
-+struct console;
-+extern void gdb_console_write(struct console *co, const char *s, unsigned count);
-+
-+#ifdef CONFIG_GDB_CONSOLE
-+extern void gdb_console_init(void);
-+#endif /* CONFIG_GDB_CONSOLE */
-+
-+#endif /* _GDB_H_ */
-Index: linux-2.4.26-ct_sync/include/linux/dcache.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/dcache.h 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.26-ct_sync/include/linux/dcache.h 2004-06-28 12:56:07.000000000 +0200
-@@ -4,6 +4,7 @@
- #ifdef __KERNEL__
-
- #include <asm/atomic.h>
-+#include <linux/kgdb.h>
- #include <linux/mount.h>
- #include <linux/kernel.h>
-
-Index: linux-2.4.26-ct_sync/include/linux/kgdb-defs.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/kgdb-defs.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/kgdb-defs.h 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,58 @@
-+#ifndef _GDB_DEFS_H_
-+#define _GDB_DEFS_H_
-+
-+#include <asm/atomic.h>
-+
-+/* Wait for GDB to connect. */
-+int gdb_hook(void);
-+
-+/* To init the kgdb engine. (called by serial hook) */
-+void set_debug_traps(void);
-+
-+/* To enter the debugger explicitly. */
-+void breakpoint(void);
-+
-+/* Output a string via the GDB console. Returns non-zero on success. */
-+int kgdb_output_string(const char *s, unsigned int count);
-+
-+extern int gdb_enter; /* 1 = enter debugger on boot */
-+extern int gdb_ttyS;
-+extern int gdb_baud;
-+extern int gdb_initialized;
-+
-+void putDebugChar(char); /* write a single character */
-+char getDebugChar(void); /* read and return a single char */
-+int hexToInt(char **ptr, int *intValue);
-+int kgdb_handle_exception(int exVector, int signo, int err_code,
-+ struct pt_regs *linux_regs);
-+char *hex2mem(char *buf, char *mem, int count, int can_fault);
-+char *mem2hex(char *mem, char *buf, int count, int can_fault);
-+void putpacket(char *buffer);
-+
-+#ifdef CONFIG_KGDB
-+extern volatile int kgdb_memerr_expected;
-+#else
-+static const int kgdb_memerr_expected = 0;
-+#endif
-+
-+typedef int gdb_debug_hook(int exVector, int signo, int err_code,
-+ struct pt_regs *regs);
-+
-+#ifndef KGDB_MAX_NO_CPUS
-+#define KGDB_MAX_NO_CPUS 8
-+#endif
-+
-+extern gdb_debug_hook *linux_debug_hook;
-+extern atomic_t kgdb_lock;
-+extern spinlock_t slavecpulocks[KGDB_MAX_NO_CPUS];
-+extern volatile int procindebug[KGDB_MAX_NO_CPUS];
-+extern int kgdb_initialized;
-+extern struct kgdb_arch arch_kgdb_ops;
-+extern struct task_struct *kgdb_usethread, *kgdb_contthread;
-+extern volatile int kgdb_memerr;
-+extern atomic_t kgdb_setting_breakpoint;
-+extern atomic_t kgdb_killed_or_detached;
-+extern atomic_t kgdb_might_be_resumed;
-+extern volatile unsigned kgdb_step;
-+
-+#endif /* _GDB_DEFS_H_ */
-Index: linux-2.4.26-ct_sync/include/linux/crypto.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/crypto.h 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.26-ct_sync/include/linux/crypto.h 2004-06-28 12:56:07.000000000 +0200
-@@ -21,6 +21,7 @@
- #include <linux/types.h>
- #include <linux/list.h>
- #include <linux/string.h>
-+#include <linux/kgdb.h>
- #include <asm/page.h>
-
- /*
-Index: linux-2.4.26-ct_sync/include/linux/sched.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/sched.h 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.26-ct_sync/include/linux/sched.h 2004-06-28 12:56:07.000000000 +0200
-@@ -146,7 +146,9 @@
-
- #define MAX_SCHEDULE_TIMEOUT LONG_MAX
- extern signed long FASTCALL(schedule_timeout(signed long timeout));
--asmlinkage void schedule(void);
-+asmlinkage void do_schedule(void);
-+asmlinkage void kern_schedule(void);
-+asmlinkage void kern_do_schedule(struct pt_regs);
-
- extern int schedule_task(struct tq_struct *task);
- extern void flush_scheduled_tasks(void);
-@@ -958,5 +960,14 @@
- __cond_resched();
- }
-
-+static inline void schedule(void)
-+{
-+#ifdef CONFIG_KGDB_THREAD
-+ kern_schedule();
-+#else
-+ do_schedule();
-+#endif
-+}
-+
- #endif /* __KERNEL__ */
- #endif
-Index: linux-2.4.26-ct_sync/include/asm-i386/kgdb.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-i386/kgdb.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/asm-i386/kgdb.h 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,62 @@
-+#ifndef _ASM_KGDB_H_
-+#define _ASM_KGDB_H_
-+
-+/*
-+ * Copyright (C) 2001 Amit S. Kale
-+ */
-+
-+#include <linux/ptrace.h>
-+
-+/* gdb locks */
-+#define KGDB_MAX_NO_CPUS 8
-+
-+extern int gdb_enter; /* 1 = enter debugger on boot */
-+extern int gdb_ttyS;
-+extern int gdb_baud;
-+extern int gdb_initialized;
-+extern int gdb_irq;
-+
-+/************************************************************************/
-+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-+/* at least NUMREGBYTES*2 are needed for register packets */
-+/* Longer buffer is needed to list all threads */
-+#define BUFMAX 1024
-+
-+/* Number of bytes of registers. */
-+#define NUMREGBYTES 64
-+/*
-+ * Note that this register image is in a different order than
-+ * the register image that Linux produces at interrupt time.
-+ *
-+ * Linux's register image is defined by struct pt_regs in ptrace.h.
-+ * Just why GDB uses a different order is a historical mystery.
-+ */
-+enum regnames { _EAX, /* 0 */
-+ _ECX, /* 1 */
-+ _EDX, /* 2 */
-+ _EBX, /* 3 */
-+ _ESP, /* 4 */
-+ _EBP, /* 5 */
-+ _ESI, /* 6 */
-+ _EDI, /* 7 */
-+ _PC, /* 8 also known as eip */
-+ _PS, /* 9 also known as eflags */
-+ _CS, /* 10 */
-+ _SS, /* 11 */
-+ _DS, /* 12 */
-+ _ES, /* 13 */
-+ _FS, /* 14 */
-+ _GS /* 15 */
-+};
-+
-+#define BREAKPOINT() asm(" int $3");
-+#define BREAK_INSTR_SIZE 1
-+struct console;
-+void gdb_console_write(struct console *co, const char *s,
-+ unsigned count);
-+void gdb_console_init(void);
-+
-+void gdb_wait(struct pt_regs *regs);
-+
-+
-+#endif /* _ASM_KGDB_H_ */
-Index: linux-2.4.26-ct_sync/include/asm-i386/ioctls.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-i386/ioctls.h 2003-08-25 13:44:43.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/asm-i386/ioctls.h 2004-06-28 12:56:07.000000000 +0200
-@@ -68,6 +68,7 @@
- #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
- #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
- #define FIOQSIZE 0x5460
-+#define TIOCGDB 0x547F /* enable GDB stub mode on this tty */
-
- /* Used for packet mode */
- #define TIOCPKT_DATA 0
-Index: linux-2.4.26-ct_sync/include/asm-i386/page.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-i386/page.h 2002-08-03 02:39:45.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/asm-i386/page.h 2004-06-28 12:56:07.000000000 +0200
-@@ -95,6 +95,10 @@
- * undefined" opcode for parsing in the trap handler.
- */
-
-+#ifdef CONFIG_KGDB
-+#include <linux/kgdb-asserts.h>
-+#define BUG() KGDB_ASSERT("BUG", 0)
-+#else
- #if 1 /* Set to zero for a slightly smaller kernel */
- #define BUG() \
- __asm__ __volatile__( "ud2\n" \
-@@ -104,6 +108,7 @@
- #else
- #define BUG() __asm__ __volatile__("ud2\n")
- #endif
-+#endif
-
- #define PAGE_BUG(page) do { \
- BUG(); \
-Index: linux-2.4.26-ct_sync/include/asm-i386/processor.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/asm-i386/processor.h 2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.26-ct_sync/include/asm-i386/processor.h 2004-06-28 12:56:07.000000000 +0200
-@@ -376,6 +376,9 @@
- /* IO permissions */
- int ioperm;
- unsigned long io_bitmap[IO_BITMAP_SIZE+1];
-+#ifdef CONFIG_KGDB
-+ struct pt_regs *kgdbregs;
-+#endif
- };
-
- #define INIT_THREAD { \
-Index: linux-2.4.26-ct_sync/init/main.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/init/main.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/init/main.c 2004-06-28 12:56:07.000000000 +0200
-@@ -61,6 +61,10 @@
- #include <linux/nubus.h>
- #endif
-
-+#ifdef CONFIG_KGDB
-+#include <linux/kgdb.h>
-+#endif
-+
- #ifdef CONFIG_ISAPNP
- #include <linux/isapnp.h>
- #endif
-@@ -434,6 +438,11 @@
- * make syscalls (and thus be locked).
- */
- smp_init();
-+#ifdef CONFIG_KGDB
-+ if (gdb_enter) {
-+ gdb_hook(); /* right at boot time */
-+ }
-+#endif
- #if defined(CONFIG_SYSVIPC)
- ipc_init();
- #endif
-Index: linux-2.4.26-ct_sync/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/Makefile 2004-06-14 14:52:07.000000000 +0200
-+++ linux-2.4.26-ct_sync/Makefile 2004-06-28 12:56:07.000000000 +0200
-@@ -93,9 +93,13 @@
-
- CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
- -fno-strict-aliasing -fno-common
-+ifeq ($(CONFIG_KGDB),y)
-+CFLAGS += -g
-+else
- ifndef CONFIG_FRAME_POINTER
- CFLAGS += -fomit-frame-pointer
- endif
-+endif
- AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
-
- #
-Index: linux-2.4.26-ct_sync/drivers/char/serial.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/drivers/char/serial.c 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.26-ct_sync/drivers/char/serial.c 2004-06-28 12:56:07.000000000 +0200
-@@ -4,6 +4,7 @@
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997,
- * 1998, 1999 Theodore Ts'o
-+ * Copyright (C) 2000 VERITAS Software Corporation.
- *
- * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now
- * much more extensible to support other serial cards based on the
-@@ -34,6 +35,10 @@
- * 4/98: Added changes to support the ARM architecture proposed by
- * Russell King
- *
-+ * 3/99: Added TIOCGDB for remote debugging with gdb if compiled with
-+ * CONFIG_KGDB
-+ * Tigran Aivazian
-+ *
- * 5/99: Updated to include support for the XR16C850 and ST16C654
- * uarts. Stuart MacDonald <stuartm at connecttech.com>
- *
-@@ -210,7 +215,7 @@
- #include <asm/uaccess.h>
- #endif
- #include <linux/delay.h>
--#ifdef CONFIG_SERIAL_CONSOLE
-+#if defined(CONFIG_SERIAL_CONSOLE) || defined (CONFIG_GDB_CONSOLE)
- #include <linux/console.h>
- #endif
- #ifdef ENABLE_SERIAL_PCI
-@@ -1591,6 +1596,13 @@
- restore_flags(flags);
- }
-
-+#ifdef CONFIG_KGDB
-+void shutdown_for_gdb(struct async_struct * info)
-+{
-+ shutdown(info) ;
-+}
-+#endif
-+
- #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
- static int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300,
-@@ -2701,7 +2713,12 @@
- /* "setserial -W" is called in Debian boot */
- printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
- return 0;
--
-+#ifdef CONFIG_KGDB
-+ case TIOCGDB:
-+ gdb_ttyS = MINOR(tty->device) & 0x03F ;
-+ gdb_baud = tty_get_baud_rate(tty) ;
-+ return gdb_hook();
-+#endif
- default:
- return -ENOIOCTLCMD;
- }
-@@ -4957,12 +4974,17 @@
- *
- * Accept a maximum of eight boards
- *
-+ * 10/00: added console support for kgdb. Amit Kale <akale at veritas.com>
-+ *
- */
- static void __devinit probe_serial_pci(void)
- {
- #ifdef SERIAL_DEBUG_PCI
- printk(KERN_DEBUG "Entered probe_serial_pci()\n");
- #endif
-+#ifdef CONFIG_KGDB
-+#include <linux/kgdb.h>
-+#endif
-
- /* Register call PCI serial devices. Null out
- * the driver name upon failure, as a signal
-@@ -6031,6 +6053,129 @@
- #endif
-
- /*
-+ * ------------------------------------------------------------
-+ * Serial GDB driver (most in gdbserial.c)
-+ * ------------------------------------------------------------
-+ */
-+
-+#ifdef CONFIG_KGDB
-+#ifdef CONFIG_GDB_CONSOLE
-+static struct console gdbcons = {
-+ name: "gdb",
-+ write: gdb_console_write,
-+ flags: CON_PRINTBUFFER | CON_ENABLED,
-+ index: -1,
-+};
-+#endif
-+
-+
-+/*
-+ * Takes:
-+ * ttyS - integer specifying which serial port to use for debugging
-+ * baud - baud rate of specified serial port
-+ * Returns:
-+ * port for use by the gdb serial driver
-+ */
-+struct serial_state *
-+gdb_serial_setup(int ttyS, int baud)
-+{
-+ struct serial_state *ser;
-+ unsigned cval;
-+ int bits = 8;
-+ int parity = 'n';
-+ int cflag = CREAD | HUPCL | CLOCAL;
-+ int quot = 0;
-+
-+ /*
-+ * Now construct a cflag setting.
-+ */
-+ switch(baud) {
-+ case 1200:
-+ cflag |= B1200;
-+ break;
-+ case 2400:
-+ cflag |= B2400;
-+ break;
-+ case 4800:
-+ cflag |= B4800;
-+ break;
-+ case 19200:
-+ cflag |= B19200;
-+ break;
-+ case 38400:
-+ cflag |= B38400;
-+ break;
-+ case 57600:
-+ cflag |= B57600;
-+ break;
-+ case 115200:
-+ cflag |= B115200;
-+ break;
-+ case 9600:
-+ default:
-+ cflag |= B9600;
-+ break;
-+ }
-+ switch(bits) {
-+ case 7:
-+ cflag |= CS7;
-+ break;
-+ default:
-+ case 8:
-+ cflag |= CS8;
-+ break;
-+ }
-+ switch(parity) {
-+ case 'o': case 'O':
-+ cflag |= PARODD;
-+ break;
-+ case 'e': case 'E':
-+ cflag |= PARENB;
-+ break;
-+ }
-+
-+ /*
-+ * Divisor, bytesize and parity
-+ */
-+
-+ ser = rs_table + ttyS;
-+ ser->flags &= ~ASYNC_BOOT_AUTOCONF;
-+ quot = ser->baud_base / baud;
-+ cval = cflag & (CSIZE | CSTOPB);
-+ cval >>= 4;
-+ if (cflag & PARENB)
-+ cval |= UART_LCR_PARITY;
-+ if (!(cflag & PARODD))
-+ cval |= UART_LCR_EPAR;
-+
-+ /*
-+ * Disable UART interrupts, set DTR and RTS high
-+ * and set speed.
-+ */
-+ cval = 0x3;
-+ outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */
-+ outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */
-+ outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */
-+ outb(cval, ser->port + UART_LCR); /* reset DLAB */
-+ outb(UART_IER_RDI, ser->port + UART_IER); /* turn on interrupts*/
-+ outb(UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);
-+
-+ /*
-+ * If we read 0xff from the LSR, there is no UART here.
-+ */
-+ if (inb(ser->port + UART_LSR) == 0xff)
-+ return 0;
-+ return ser;
-+}
-+#ifdef CONFIG_GDB_CONSOLE
-+void __init gdb_console_init(void)
-+{
-+ register_console(&gdbcons);
-+}
-+#endif
-+#endif /* CONFIG_KGDB */
-+
-+/*
- Local variables:
- compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c"
- End:
-Index: linux-2.4.26-ct_sync/drivers/char/gdbserial.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/drivers/char/gdbserial.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/drivers/char/gdbserial.c 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,304 @@
-+/*
-+ * Serial interface GDB stub
-+ *
-+ * Written (hacked together) by David Grothe (dave at gcom.com)
-+ *
-+ * Modified by Scott Foehner (sfoehner at engr.sgi.com) to allow connect
-+ * on boot-up
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/serial.h>
-+#include <linux/serial_reg.h>
-+#include <linux/serialP.h>
-+#include <linux/config.h>
-+#include <linux/major.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/termios.h>
-+#include <linux/kgdb.h>
-+
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/segment.h>
-+#include <asm/bitops.h>
-+#include <asm/system.h>
-+#include <asm/irq.h>
-+#include <asm/atomic.h>
-+
-+#undef PRNT /* define for debug printing */
-+
-+#define GDB_BUF_SIZE 512 /* power of 2, please */
-+
-+static char gdb_buf[GDB_BUF_SIZE] ;
-+static int gdb_buf_in_inx ;
-+static atomic_t gdb_buf_in_cnt ;
-+static int gdb_buf_out_inx ;
-+
-+
-+static int gdb_got_dollar = -3, gdb_got_H = -3, gdb_interrupt_iteration = 0;
-+
-+extern void set_debug_traps(void) ; /* GDB routine */
-+extern struct serial_state * gdb_serial_setup(int ttyS, int baud);
-+extern void shutdown_for_gdb(struct async_struct * info) ;
-+ /* in serial.c */
-+
-+int gdb_irq;
-+int gdb_port;
-+
-+static int initialized = -1;
-+
-+/*
-+ * Get a byte from the hardware data buffer and return it
-+ */
-+static int read_data_bfr(void)
-+{
-+ if (inb(gdb_port + UART_LSR) & UART_LSR_DR)
-+ return(inb(gdb_port + UART_RX));
-+
-+ return( -1 ) ;
-+
-+} /* read_data_bfr */
-+
-+
-+/*
-+ * Get a char if available, return -1 if nothing available.
-+ * Empty the receive buffer first, then look at the interface hardware.
-+ */
-+static int read_char(void)
-+{
-+ if (atomic_read(&gdb_buf_in_cnt) != 0) /* intr routine has q'd chars */
-+ {
-+ int chr ;
-+
-+ chr = gdb_buf[gdb_buf_out_inx++] ;
-+ gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ;
-+ atomic_dec(&gdb_buf_in_cnt) ;
-+ return(chr) ;
-+ }
-+
-+ return(read_data_bfr()) ; /* read from hardware */
-+
-+} /* read_char */
-+
-+/*
-+ * Wait until the interface can accept a char, then write it.
-+ */
-+static void write_char(int chr)
-+{
-+ while ( !(inb(gdb_port + UART_LSR) & UART_LSR_THRE) ) ;
-+
-+ outb(chr, gdb_port+UART_TX);
-+
-+} /* write_char */
-+
-+/*
-+ * This is the receiver interrupt routine for the GDB stub.
-+ * It will receive a limited number of characters of input
-+ * from the gdb host machine and save them up in a buffer.
-+ *
-+ * When the gdb stub routine getDebugChar() is called it
-+ * draws characters out of the buffer until it is empty and
-+ * then reads directly from the serial port.
-+ *
-+ * We do not attempt to write chars from the interrupt routine
-+ * since the stubs do all of that via putDebugChar() which
-+ * writes one byte after waiting for the interface to become
-+ * ready.
-+ *
-+ * The debug stubs like to run with interrupts disabled since,
-+ * after all, they run as a consequence of a breakpoint in
-+ * the kernel.
-+ *
-+ * Perhaps someone who knows more about the tty driver than I
-+ * care to learn can make this work for any low level serial
-+ * driver.
-+ */
-+static void gdb_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-+{
-+ int chr ;
-+ int iir ;
-+
-+ do
-+ {
-+ chr = read_data_bfr() ;
-+ iir = inb(gdb_port + UART_IIR) ;
-+#ifdef PRNT
-+ printk("gdb_interrupt: chr=%02x '%c' after read iir=%02x\n", chr,
-+ chr > ' ' && chr < 0x7F ? chr : ' ', iir) ;
-+#endif
-+ if (chr < 0) continue ;
-+
-+ if (chr == 3) /* Ctrl-C means remote interrupt */
-+ {
-+ breakpoint();
-+ continue ;
-+ }
-+
-+ if(atomic_read(&kgdb_killed_or_detached)) {
-+ if (chr == '$')
-+ gdb_got_dollar = gdb_interrupt_iteration;
-+ else if (gdb_interrupt_iteration == gdb_got_dollar + 1 &&
-+ chr == 'H')
-+ gdb_got_H = gdb_interrupt_iteration;
-+ else if (gdb_interrupt_iteration == gdb_got_H + 1 &&
-+ chr == 'c') {
-+ gdb_buf[gdb_buf_in_inx++] = chr;
-+ atomic_inc(&gdb_buf_in_cnt);
-+ atomic_set(&kgdb_might_be_resumed, 1);
-+ wmb();
-+ breakpoint();
-+ atomic_set(&kgdb_might_be_resumed, 0);
-+ gdb_interrupt_iteration = 0;
-+ gdb_got_dollar = -3;
-+ gdb_got_H = -3;
-+ continue;
-+ }
-+ }
-+
-+ if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE)
-+ { /* buffer overflow, clear it */
-+ gdb_buf_in_inx = 0 ;
-+ atomic_set(&gdb_buf_in_cnt, 0) ;
-+ gdb_buf_out_inx = 0 ;
-+ break ;
-+ }
-+
-+ gdb_buf[gdb_buf_in_inx++] = chr ;
-+ gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ;
-+ atomic_inc(&gdb_buf_in_cnt) ;
-+ }
-+ while (iir & UART_IIR_RDI);
-+
-+ if (atomic_read(&kgdb_killed_or_detached))
-+ gdb_interrupt_iteration ++;
-+
-+
-+} /* gdb_interrupt */
-+
-+/*
-+ * Just a NULL routine for testing.
-+ */
-+void gdb_null(void)
-+{
-+} /* gdb_null */
-+
-+
-+int gdb_hook(void)
-+{
-+ int retval ;
-+ struct serial_state *ser;
-+
-+#ifdef CONFIG_SMP
-+ if (smp_num_cpus > KGDB_MAX_NO_CPUS) {
-+ printk("kgdb: too manu cpus. Cannot enable debugger with more than 8 cpus\n");
-+ return (-1);
-+ }
-+#endif
-+
-+ /*
-+ * Call first time just to get the ser ptr
-+ */
-+ if((ser = gdb_serial_setup(gdb_ttyS, gdb_baud)) == 0) {
-+ printk ("gdb_serial_setup() error");
-+ return(-1);
-+ }
-+
-+ gdb_port = ser->port;
-+ gdb_irq = ser->irq;
-+
-+ if (ser->info != NULL)
-+ {
-+ shutdown_for_gdb(ser->info) ;
-+ /*
-+ * Call second time to do the setup now that we have
-+ * shut down the previous user of the interface.
-+ */
-+ gdb_serial_setup(gdb_ttyS, gdb_baud) ;
-+ }
-+
-+ retval = request_irq(gdb_irq,
-+ gdb_interrupt,
-+ SA_INTERRUPT,
-+ "GDB-stub", NULL);
-+ if (retval == 0)
-+ initialized = 1;
-+ else
-+ {
-+ initialized = 0;
-+ printk("gdb_hook: request_irq(irq=%d) failed: %d\n", gdb_irq, retval);
-+ }
-+
-+ /*
-+ * Call GDB routine to setup the exception vectors for the debugger
-+ */
-+ set_debug_traps() ;
-+
-+ /*
-+ * Call the breakpoint() routine in GDB to start the debugging
-+ * session.
-+ */
-+ printk("Waiting for connection from remote gdb... ") ;
-+ breakpoint() ;
-+ gdb_null() ;
-+
-+ printk("Connected.\n");
-+
-+ gdb_initialized = 1;
-+ return(0) ;
-+
-+} /* gdb_hook_interrupt2 */
-+
-+/*
-+ * getDebugChar
-+ *
-+ * This is a GDB stub routine. It waits for a character from the
-+ * serial interface and then returns it. If there is no serial
-+ * interface connection then it returns a bogus value which will
-+ * almost certainly cause the system to hang.
-+ */
-+char getDebugChar(void)
-+{
-+ volatile int chr ;
-+
-+#ifdef PRNT
-+ printk("getDebugChar: ") ;
-+#endif
-+
-+ while ( (chr = read_char()) < 0 ) ;
-+
-+
-+#ifdef PRNT
-+ printk("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ') ;
-+#endif
-+ return(chr) ;
-+
-+} /* getDebugChar */
-+
-+/*
-+ * putDebugChar
-+ *
-+ * This is a GDB stub routine. It waits until the interface is ready
-+ * to transmit a char and then sends it. If there is no serial
-+ * interface connection then it simply returns to its caller, having
-+ * pretended to send the char.
-+ */
-+void putDebugChar(char chr)
-+{
-+#ifdef PRNT
-+ printk("putDebugChar: chr=%02x '%c'\n", chr,
-+ chr > ' ' && chr < 0x7F ? chr : ' ') ;
-+#endif
-+
-+ write_char(chr) ; /* this routine will wait */
-+
-+} /* putDebugChar */
-+
-Index: linux-2.4.26-ct_sync/drivers/char/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/drivers/char/Makefile 2004-02-18 14:36:31.000000000 +0100
-+++ linux-2.4.26-ct_sync/drivers/char/Makefile 2004-06-28 12:56:07.000000000 +0200
-@@ -169,6 +169,7 @@
- KEYBD = dummy_keyb.o
- endif
-
-+obj-$(CONFIG_KGDB) += gdbserial.o
- obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
- obj-$(CONFIG_SERIAL) += $(SERIAL)
- obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
-Index: linux-2.4.26-ct_sync/drivers/char/tty_io.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/drivers/char/tty_io.c 2004-04-14 15:05:29.000000000 +0200
-+++ linux-2.4.26-ct_sync/drivers/char/tty_io.c 2004-06-28 12:56:07.000000000 +0200
-@@ -90,6 +90,9 @@
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/smp_lock.h>
-+#ifdef CONFIG_GDB_CONSOLE
-+#include <linux/kgdb.h>
-+#endif
-
- #include <asm/uaccess.h>
- #include <asm/system.h>
-@@ -2248,6 +2251,9 @@
- #ifdef CONFIG_AU1X00_SERIAL_CONSOLE
- au1x00_serial_console_init();
- #endif
-+#ifdef CONFIG_GDB_CONSOLE
-+ gdb_console_init();
-+#endif
- #ifdef CONFIG_SERIAL_CONSOLE
- #if (defined(CONFIG_8xx) || defined(CONFIG_CPM2))
- console_8xx_init();
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/i386-stub.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/i386-stub.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/i386-stub.c 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,457 @@
-+/*
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2, or (at your option) any
-+ * later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ */
-+
-+/*
-+ * Copyright (C) 2000-2001 VERITAS Software Corporation.
-+ */
-+/****************************************************************************
-+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
-+ *
-+ * Module name: remcom.c $
-+ * Revision: 1.34 $
-+ * Date: 91/03/09 12:29:49 $
-+ * Contributor: Lake Stevens Instrument Division$
-+ *
-+ * Description: low level support for gdb debugger. $
-+ *
-+ * Considerations: only works on target hardware $
-+ *
-+ * Written by: Glenn Engel $
-+ * Updated by: Amit Kale<akale at veritas.com>
-+ * ModuleState: Experimental $
-+ *
-+ * NOTES: See Below $
-+ *
-+ * Modified for 386 by Jim Kingdon, Cygnus Support.
-+ * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave at gcom.com>
-+ * Integrated into 2.2.5 kernel by Tigran Aivazian <tigran at sco.com>
-+ * thread support,
-+ * support for multiple processors,
-+ * support for ia-32(x86) hardware debugging,
-+ * Console support,
-+ * handling nmi watchdog
-+ * Amit S. Kale ( amitkale at emsyssoft.com )
-+ *
-+ *
-+ * To enable debugger support, two things need to happen. One, a
-+ * call to set_debug_traps() is necessary in order to allow any breakpoints
-+ * or error conditions to be properly intercepted and reported to gdb.
-+ * Two, a breakpoint needs to be generated to begin communication. This
-+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
-+ * simulates a breakpoint by executing an int 3.
-+ *
-+ *************
-+ *
-+ * The following gdb commands are supported:
-+ *
-+ * command function Return value
-+ *
-+ * g return the value of the CPU registers hex data or ENN
-+ * G set the value of the CPU registers OK or ENN
-+ *
-+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
-+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
-+ *
-+ * c Resume at current address SNN ( signal NN)
-+ * cAA..AA Continue at address AA..AA SNN
-+ *
-+ * s Step one instruction SNN
-+ * sAA..AA Step one instruction from AA..AA SNN
-+ *
-+ * k kill
-+ *
-+ * ? What was the last sigval ? SNN (signal NN)
-+ *
-+ * All commands and responses are sent with a packet which includes a
-+ * checksum. A packet consists of
-+ *
-+ * $<packet info>#<checksum>.
-+ *
-+ * where
-+ * <packet info> :: <characters representing the command or response>
-+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
-+ *
-+ * When a packet is received, it is first acknowledged with either '+' or '-'.
-+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
-+ *
-+ * Example:
-+ *
-+ * Host: Reply:
-+ * $m0,10#2a +$00010203040506070809101112131415#42
-+ *
-+ ****************************************************************************/
-+
-+#include <linux/string.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/smp.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <asm/vm86.h>
-+#include <asm/system.h>
-+#include <asm/ptrace.h> /* for linux pt_regs struct */
-+#include <linux/kgdb.h>
-+#ifdef CONFIG_GDB_CONSOLE
-+#include <linux/console.h>
-+#endif
-+#include <linux/init.h>
-+
-+/* Put the error code here just in case the user cares. */
-+int gdb_i386errcode;
-+/* Likewise, the vector number here (since GDB only gets the signal
-+ number through the usual means, and that's not very specific). */
-+int gdb_i386vector = -1;
-+
-+#if KGDB_MAX_NO_CPUS != 8
-+#error change the definition of slavecpulocks
-+#endif
-+
-+static void i386_regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs)
-+{
-+ gdb_regs[_EAX] = regs->eax;
-+ gdb_regs[_EBX] = regs->ebx;
-+ gdb_regs[_ECX] = regs->ecx;
-+ gdb_regs[_EDX] = regs->edx;
-+ gdb_regs[_ESI] = regs->esi;
-+ gdb_regs[_EDI] = regs->edi;
-+ gdb_regs[_EBP] = regs->ebp;
-+ gdb_regs[ _DS] = regs->xds;
-+ gdb_regs[ _ES] = regs->xes;
-+ gdb_regs[ _PS] = regs->eflags;
-+ gdb_regs[ _CS] = regs->xcs;
-+ gdb_regs[ _PC] = regs->eip;
-+ gdb_regs[_ESP] = (int) (®s->esp) ;
-+ gdb_regs[ _SS] = __KERNEL_DS;
-+ gdb_regs[ _FS] = 0xFFFF;
-+ gdb_regs[ _GS] = 0xFFFF;
-+} /* regs_to_gdb_regs */
-+
-+static void i386_sleeping_thread_to_gdb_regs(int *gdb_regs, struct task_struct *p)
-+{
-+ gdb_regs[_EAX] = 0;
-+ gdb_regs[_EBX] = 0;
-+ gdb_regs[_ECX] = 0;
-+ gdb_regs[_EDX] = 0;
-+ gdb_regs[_ESI] = 0;
-+ gdb_regs[_EDI] = 0;
-+ gdb_regs[_EBP] = *(int *)p->thread.esp;
-+ gdb_regs[_DS] = __KERNEL_DS;
-+ gdb_regs[_ES] = __KERNEL_DS;
-+ gdb_regs[_PS] = 0;
-+ gdb_regs[_CS] = __KERNEL_CS;
-+ gdb_regs[_PC] = p->thread.eip;
-+ gdb_regs[_ESP] = p->thread.esp;
-+ gdb_regs[_SS] = __KERNEL_DS;
-+ gdb_regs[_FS] = 0xFFFF;
-+ gdb_regs[_GS] = 0xFFFF;
-+}
-+
-+static void i386_gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs)
-+{
-+ regs->eax = gdb_regs[_EAX] ;
-+ regs->ebx = gdb_regs[_EBX] ;
-+ regs->ecx = gdb_regs[_ECX] ;
-+ regs->edx = gdb_regs[_EDX] ;
-+ regs->esi = gdb_regs[_ESI] ;
-+ regs->edi = gdb_regs[_EDI] ;
-+ regs->ebp = gdb_regs[_EBP] ;
-+ regs->xds = gdb_regs[ _DS] ;
-+ regs->xes = gdb_regs[ _ES] ;
-+ regs->eflags= gdb_regs[ _PS] ;
-+ regs->xcs = gdb_regs[ _CS] ;
-+ regs->eip = gdb_regs[ _PC] ;
-+#if 0 /* can't change these */
-+ regs->esp = gdb_regs[_ESP] ;
-+ regs->xss = gdb_regs[ _SS] ;
-+ regs->fs = gdb_regs[ _FS] ;
-+ regs->gs = gdb_regs[ _GS] ;
-+#endif
-+
-+} /* gdb_regs_to_regs */
-+
-+struct hw_breakpoint {
-+ unsigned enabled;
-+ unsigned type;
-+ unsigned len;
-+ unsigned addr;
-+} breakinfo[4] = { {
-+enabled:0}, {
-+enabled:0}, {
-+enabled:0}, {
-+enabled:0}};
-+
-+void i386_correct_hw_break(void)
-+{
-+ int breakno;
-+ int correctit;
-+ int breakbit;
-+ unsigned dr7;
-+
-+ asm volatile ("movl %%db7, %0\n":"=r" (dr7)
-+ :);
-+ do {
-+ unsigned addr0, addr1, addr2, addr3;
-+ asm volatile ("movl %%db0, %0\n"
-+ "movl %%db1, %1\n"
-+ "movl %%db2, %2\n"
-+ "movl %%db3, %3\n":"=r" (addr0), "=r"(addr1),
-+ "=r"(addr2), "=r"(addr3):);
-+ } while (0);
-+ correctit = 0;
-+ for (breakno = 0; breakno < 3; breakno++) {
-+ breakbit = 2 << (breakno << 1);
-+ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
-+ correctit = 1;
-+ dr7 |= breakbit;
-+ dr7 &= ~(0xf0000 << (breakno << 2));
-+ dr7 |= (((breakinfo[breakno].len << 2) |
-+ breakinfo[breakno].type) << 16) <<
-+ (breakno << 2);
-+ switch (breakno) {
-+ case 0:
-+ asm volatile ("movl %0, %%dr0\n"::"r"
-+ (breakinfo[breakno].addr));
-+ break;
-+
-+ case 1:
-+ asm volatile ("movl %0, %%dr1\n"::"r"
-+ (breakinfo[breakno].addr));
-+ break;
-+
-+ case 2:
-+ asm volatile ("movl %0, %%dr2\n"::"r"
-+ (breakinfo[breakno].addr));
-+ break;
-+
-+ case 3:
-+ asm volatile ("movl %0, %%dr3\n"::"r"
-+ (breakinfo[breakno].addr));
-+ break;
-+ }
-+ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
-+ correctit = 1;
-+ dr7 &= ~breakbit;
-+ dr7 &= ~(0xf0000 << (breakno << 2));
-+ }
-+ }
-+ if (correctit) {
-+ asm volatile ("movl %0, %%db7\n"::"r" (dr7));
-+ }
-+}
-+
-+int i386_remove_hw_break(unsigned long addr, int type)
-+{
-+ int i, idx = -1;
-+ for (i = 0; i < 4; i ++) {
-+ if (breakinfo[i].addr == addr && breakinfo[i].enabled) {
-+ idx = i;
-+ break;
-+ }
-+ }
-+ if (idx == -1)
-+ return -1;
-+
-+ breakinfo[idx].enabled = 0;
-+ return 0;
-+}
-+
-+int i386_set_hw_break(unsigned long addr, int type)
-+{
-+ int i, idx = -1;
-+ for (i = 0; i < 4; i ++) {
-+ if (!breakinfo[i].enabled) {
-+ idx = i;
-+ break;
-+ }
-+ }
-+ if (idx == -1)
-+ return -1;
-+
-+ breakinfo[idx].enabled = 1;
-+ breakinfo[idx].type = type;
-+ breakinfo[idx].len = 1;
-+ breakinfo[idx].addr = addr;
-+ return 0;
-+}
-+
-+int remove_hw_break(unsigned breakno)
-+{
-+ if (!breakinfo[breakno].enabled) {
-+ return -1;
-+ }
-+ breakinfo[breakno].enabled = 0;
-+ return 0;
-+}
-+
-+int set_hw_break(unsigned breakno,
-+ unsigned type, unsigned len, unsigned addr)
-+{
-+ if (breakinfo[breakno].enabled) {
-+ return -1;
-+ }
-+ breakinfo[breakno].enabled = 1;
-+ breakinfo[breakno].type = type;
-+ breakinfo[breakno].len = len;
-+ breakinfo[breakno].addr = addr;
-+ return 0;
-+}
-+
-+static void i386_printexceptioninfo(int exceptionNo, int errorcode, char *buffer)
-+{
-+ unsigned dr6;
-+ int i;
-+ switch (exceptionNo) {
-+ case 1: /* debug exception */
-+ break;
-+ case 3: /* breakpoint */
-+ sprintf(buffer, "Software breakpoint");
-+ return;
-+ default:
-+ sprintf(buffer, "Details not available");
-+ return;
-+ }
-+ asm volatile ("movl %%db6, %0\n":"=r" (dr6)
-+ :);
-+ if (dr6 & 0x4000) {
-+ sprintf(buffer, "Single step");
-+ return;
-+ }
-+ for (i = 0; i < 4; ++i) {
-+ if (dr6 & (1 << i)) {
-+ sprintf(buffer, "Hardware breakpoint %d", i);
-+ return;
-+ }
-+ }
-+ sprintf(buffer, "Unknown trap");
-+ return;
-+}
-+
-+static void i386_disable_hw_debug(struct pt_regs *regs)
-+{
-+ /* Disable hardware debugging while we are in kgdb */
-+ asm volatile("movl %0,%%db7": /* no output */ : "r"(0));
-+}
-+
-+static void i386_post_master_code(struct pt_regs *regs, int eVector, int err_code)
-+{
-+ /* Master processor is completely in the debugger */
-+ gdb_i386vector = eVector;
-+ gdb_i386errcode = err_code;
-+}
-+static int i386_handle_exception(int exceptionVector, int signo, int err_code,
-+ char *remcomInBuffer, char *remcomOutBuffer,
-+ struct pt_regs *linux_regs)
-+{
-+ int addr, length;
-+ int breakno, breaktype;
-+ char *ptr;
-+ int newPC;
-+ int dr6;
-+
-+ switch (remcomInBuffer[0]) {
-+ case 'c':
-+ case 's':
-+ if (kgdb_contthread && kgdb_contthread != current) {
-+ strcpy(remcomOutBuffer, "E00");
-+ break;
-+ }
-+
-+ kgdb_contthread = NULL;
-+
-+ /* try to read optional parameter, pc unchanged if no parm */
-+ ptr = &remcomInBuffer[1];
-+ if (hexToInt(&ptr, &addr)) {
-+ linux_regs->eip = addr;
-+ }
-+ newPC = linux_regs->eip;
-+
-+ /* clear the trace bit */
-+ linux_regs->eflags &= 0xfffffeff;
-+
-+ /* set the trace bit if we're stepping */
-+ if (remcomInBuffer[0] == 's') {
-+ linux_regs->eflags |= 0x100;
-+ kgdb_step = 1;
-+ }
-+
-+ asm volatile ("movl %%db6, %0\n" : "=r" (dr6));
-+ if (!(dr6 & 0x4000)) {
-+ for (breakno = 0; breakno < 4; ++breakno) {
-+ if (dr6 & (1 << breakno)) {
-+ if (breakinfo[breakno].type == 0) {
-+ /* Set restore flag */
-+ linux_regs->eflags |= 0x10000;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+ i386_correct_hw_break();
-+ asm volatile ("movl %0, %%db6\n"::"r" (0));
-+
-+ return (0);
-+
-+ case 'Y':
-+ ptr = &remcomInBuffer[1];
-+ hexToInt(&ptr, &breakno);
-+ ptr++;
-+ hexToInt(&ptr, &breaktype);
-+ ptr++;
-+ hexToInt(&ptr, &length);
-+ ptr++;
-+ hexToInt(&ptr, &addr);
-+ if (set_hw_break(breakno & 0x3, breaktype & 0x3,
-+ length & 0x3, addr) == 0) {
-+ strcpy(remcomOutBuffer, "OK");
-+ } else {
-+ strcpy(remcomOutBuffer, "ERROR");
-+ }
-+ break;
-+
-+ /* Remove hardware breakpoint */
-+ case 'y':
-+ ptr = &remcomInBuffer[1];
-+ hexToInt(&ptr, &breakno);
-+ if (remove_hw_break(breakno & 0x3) == 0) {
-+ strcpy(remcomOutBuffer, "OK");
-+ } else {
-+ strcpy(remcomOutBuffer, "ERROR");
-+ }
-+ break;
-+
-+ } /* switch */
-+ return -1; /* this means that we do not want to exit from the handler */
-+}
-+
-+int i386_kgdb_init(void)
-+{
-+ return 0;
-+}
-+
-+struct kgdb_arch arch_kgdb_ops = {
-+ {0xcc},
-+ KGDB_HW_BREAKPOINT,
-+ i386_kgdb_init,
-+ i386_regs_to_gdb_regs,
-+ i386_sleeping_thread_to_gdb_regs,
-+ i386_gdb_regs_to_regs,
-+ i386_printexceptioninfo,
-+ i386_disable_hw_debug,
-+ i386_post_master_code,
-+ i386_handle_exception,
-+ i386_set_hw_break,
-+ i386_remove_hw_break,
-+ i386_correct_hw_break,
-+ NULL,
-+};
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/Makefile 2003-11-28 19:26:19.000000000 +0100
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/Makefile 2004-06-28 12:56:07.000000000 +0200
-@@ -10,7 +10,15 @@
- .S.o:
- $(CC) $(AFLAGS) -traditional -c $< -o $*.o
-
--all: kernel.o head.o init_task.o
-+ifeq ($(CONFIG_KGDB),y)
-+GDBSTART=gdbstart
-+GDBCLEAN= -rm -f gdbstart /sbin/gdbstart
-+else
-+GDBSTART=
-+GDBCLEAN=
-+endif
-+
-+all: kernel.o head.o init_task.o $(GDBSTART)
-
- O_TARGET := kernel.o
-
-@@ -32,6 +40,7 @@
-
- obj-$(CONFIG_MCA) += mca.o
- obj-$(CONFIG_MTRR) += mtrr.o
-+obj-$(CONFIG_KGDB) += i386-stub.o
- obj-$(CONFIG_X86_MSR) += msr.o
- obj-$(CONFIG_X86_CPUID) += cpuid.o
- obj-$(CONFIG_MICROCODE) += microcode.o
-@@ -44,4 +53,11 @@
- obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
- obj-$(CONFIG_EDD) += edd.o
-
-+gdbstart: gdbstart.o
-+ ${HOSTCC} -o gdbstart gdbstart.o
-+gdbstart.o: gdbstart.c
-+ ${HOSTCC} -c -o gdbstart.o gdbstart.c
-+
-+kernelclean: dummy
-+
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/gdbstart.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/gdbstart.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/gdbstart.c 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,148 @@
-+/*
-+ * This program opens a tty file and issues the GDB stub activating
-+ * ioctl on it.
-+ */
-+
-+#include <sys/types.h>
-+#include <sys/wait.h>
-+#include <asm/ioctls.h>
-+#include <stdio.h>
-+#include <string.h>
-+#include <fcntl.h>
-+#include <sys/ioctl.h>
-+#include <stdlib.h>
-+#include <termios.h>
-+#include <unistd.h>
-+
-+#define TIOCGDB 0x547F
-+
-+char *tty_name = "/dev/ttyS0" ; /* COM1 port */
-+int speed = 9600 ; /* default speed */
-+struct termios save_ts ; /* original term struct */
-+
-+void print_usage(void)
-+{
-+ printf("gdbstub [-s speed] [-t tty-dev]\n") ;
-+ printf(" defaults: /dev/ttyS0 with speed unmodified by this program\n");
-+
-+} /* print_usage */
-+
-+void tty_err(char *msg)
-+{
-+ char buf[100] ;
-+
-+ strcpy(buf, msg) ;
-+ strcat(buf, ": ") ;
-+ strcat(buf, tty_name) ;
-+ perror(buf) ;
-+ exit(1) ;
-+
-+} /* tty_err */
-+
-+
-+void setup_term(int fd)
-+{
-+ struct termios ts ;
-+ int speed_code ;
-+
-+ if (tcgetattr(fd, &ts) < 0) tty_err("tcgetattr") ;
-+
-+ save_ts = ts ;
-+ switch (speed)
-+ {
-+ case 4800:
-+ speed_code = B4800 ;
-+ break ;
-+ case 9600:
-+ speed_code = B9600 ;
-+ break ;
-+ case 19200:
-+ speed_code = B19200 ;
-+ break ;
-+ case 38400:
-+ speed_code = B38400 ;
-+ break ;
-+ case 57600:
-+ speed_code = B57600 ;
-+ break ;
-+ case 115200:
-+ speed_code = B115200 ;
-+ break ;
-+ case 230400:
-+ speed_code = B230400 ;
-+ break ;
-+ default:
-+ printf("Invalid speed: %d\n", speed) ;
-+ exit(1) ;
-+ }
-+
-+ ts.c_cflag = CS8 | CREAD | CLOCAL ;
-+ if (cfsetospeed(&ts, speed_code) < 0) tty_err("cfsetospeed") ;
-+ if (cfsetispeed(&ts, speed_code) < 0) tty_err("cfsetispeed") ;
-+
-+ if (tcsetattr(fd, TCSANOW, &ts) < 0) tty_err("tcsetattr") ;
-+
-+} /* setup_term */
-+
-+void main(int argc, char **argv)
-+{
-+ int opt ;
-+ int fil ;
-+ int rslt ;
-+
-+ while ((opt = getopt(argc, argv, "hs:t:")) > 0)
-+ {
-+ switch (opt)
-+ {
-+ case 's':
-+ speed = atol(optarg) ;
-+ break ;
-+ case 't':
-+ tty_name = optarg ;
-+ break ;
-+ case ':':
-+ printf("Invalid option\n") ;
-+ break ;
-+ case '?':
-+ case 'h':
-+ default:
-+ print_usage() ;
-+ return ;
-+ }
-+ }
-+
-+ fil = open(tty_name, O_RDWR) ;
-+ if (fil < 0)
-+ {
-+ perror(tty_name) ;
-+ return ;
-+ }
-+
-+
-+ setup_term(fil) ;
-+
-+ /*
-+ * When we issue this ioctl, control will not return until
-+ * the debugger running on the remote host machine says "go".
-+ */
-+ printf("\nAbout to activate GDB stub in the kernel on %s\n", tty_name) ;
-+ printf("Hit CR to continue, kill program to abort -- ") ;
-+ getchar() ;
-+ sync() ;
-+ rslt = ioctl(fil, TIOCGDB, 0) ;
-+ if (rslt < 0)
-+ {
-+ perror("TIOCGDB ioctl") ;
-+ return ;
-+ }
-+
-+ printf("\nGDB stub successfully activated\n") ;
-+
-+ for (;;)
-+ {
-+ pause() ;
-+ }
-+
-+ if (tcsetattr(fil, TCSANOW, &save_ts) < 0) tty_err("tcsetattr") ;
-+
-+} /* main */
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/nmi.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/nmi.c 2003-06-13 16:51:29.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/nmi.c 2004-06-28 12:56:07.000000000 +0200
-@@ -25,6 +25,20 @@
- #include <asm/mtrr.h>
- #include <asm/mpspec.h>
-
-+#ifdef CONFIG_KGDB
-+extern gdb_debug_hook * linux_debug_hook;
-+#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \
-+ { \
-+ if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) \
-+ { \
-+ (*linux_debug_hook)(trapnr, signr, error_code, regs) ; \
-+ after; \
-+ } \
-+ }
-+#else
-+#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)
-+#endif
-+
- unsigned int nmi_watchdog = NMI_NONE;
- static unsigned int nmi_hz = HZ;
- unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
-@@ -347,7 +361,20 @@
- int sum, cpu = smp_processor_id();
-
- sum = apic_timer_irqs[cpu];
-+#if defined(CONFIG_KGDB) && defined(CONFIG_SMP)
-+ if (atomic_read(&kgdb_lock)) {
-+
-+ /*
-+ * The machine is in kgdb, hold this cpu if already
-+ * not held.
-+ */
-
-+ if (!procindebug[cpu] && atomic_read(&kgdb_lock) != (cpu + 1)) {
-+ gdb_wait(regs);
-+ }
-+ alert_counter[cpu] = 0;
-+ } else
-+#endif
- if (last_irq_sums[cpu] == sum) {
- /*
- * Ayiee, looks like this CPU is stuck ...
-@@ -355,6 +382,9 @@
- */
- alert_counter[cpu]++;
- if (alert_counter[cpu] == 5*nmi_hz) {
-+
-+ CHK_REMOTE_DEBUG(2,SIGSEGV,0,regs,)
-+
- spin_lock(&nmi_print_lock);
- /*
- * We are in trouble anyway, lets at least try
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/traps.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/traps.c 2002-11-29 00:53:09.000000000 +0100
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/traps.c 2004-06-28 12:56:07.000000000 +0200
-@@ -48,8 +48,24 @@
- #endif
-
- #include <linux/irq.h>
-+#ifdef CONFIG_KGDB
-+#include <linux/kgdb.h>
-+#endif
- #include <linux/module.h>
-
-+#ifdef CONFIG_KGDB
-+#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \
-+ { \
-+ if (linux_debug_hook != (gdb_debug_hook *) NULL && !user_mode(regs)) \
-+ { \
-+ (*linux_debug_hook)(trapnr, signr, error_code, regs) ; \
-+ after; \
-+ } \
-+ }
-+#else
-+#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)
-+#endif
-+
- asmlinkage int system_call(void);
- asmlinkage void lcall7(void);
- asmlinkage void lcall27(void);
-@@ -289,6 +305,7 @@
- bust_spinlocks(1);
- handle_BUG(regs);
- printk("%s: %04lx\n", str, err & 0xffff);
-+ CHK_REMOTE_DEBUG(1,SIGTRAP,err,regs,)
- show_registers(regs);
- bust_spinlocks(0);
- spin_unlock_irq(&die_lock);
-@@ -353,6 +370,7 @@
- #define DO_ERROR(trapnr, signr, str, name) \
- asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
- { \
-+ CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\
- do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
- }
-
-@@ -370,7 +388,10 @@
- #define DO_VM86_ERROR(trapnr, signr, str, name) \
- asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
- { \
-+ CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,goto skip_trap)\
- do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
-+skip_trap: \
-+ return; \
- }
-
- #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
-@@ -422,6 +443,7 @@
- regs->eip = fixup;
- return;
- }
-+ CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,)
- die("general protection fault", regs, error_code);
- }
- }
-@@ -533,7 +555,7 @@
- __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
-
- /* If the user set TF, it's simplest to clear it right away. */
-- if ((eip >=PAGE_OFFSET) && (regs->eflags & TF_MASK))
-+ if ((eip >=PAGE_OFFSET) && (regs->eflags & TF_MASK) && !kgdb_step)
- goto clear_TF;
-
- /* Mask out spurious debug traps due to lazy DR7 setting */
-@@ -549,7 +571,7 @@
- tsk->thread.debugreg[6] = condition;
-
- /* Mask out spurious TF errors due to lazy TF clearing */
-- if (condition & DR_STEP) {
-+ if (condition & DR_STEP && !kgdb_step) {
- /*
- * The TF error should be masked out only if the current
- * process is not traced and if the TRAP flag has been set
-@@ -572,11 +594,13 @@
- info.si_errno = 0;
- info.si_code = TRAP_BRKPT;
-
-- /* If this is a kernel mode trap, save the user PC on entry to
-- * the kernel, that's what the debugger can make sense of.
-- */
-- info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip :
-- (void *)regs->eip;
-+
-+ /* If this is a kernel mode trap, we need to reset db7 to allow us
-+ * to continue sanely */
-+ if ((regs->xcs & 3) == 0)
-+ goto clear_dr7;
-+
-+ info.si_addr = (void *)regs->eip;
- force_sig_info(SIGTRAP, &info, tsk);
-
- /* Disable additional traps. They'll be re-enabled when
-@@ -586,6 +610,7 @@
- __asm__("movl %0,%%db7"
- : /* no output */
- : "r" (0));
-+ CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,)
- return;
-
- debug_vm86:
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/signal.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/signal.c 2002-08-03 02:39:42.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/signal.c 2004-06-28 12:56:07.000000000 +0200
-@@ -695,7 +695,8 @@
- * have been cleared if the watchpoint triggered
- * inside the kernel.
- */
-- __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
-+ if (current->thread.debugreg[7])
-+ __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
-
- /* Whee! Actually deliver the signal. */
- handle_signal(signr, ka, &info, oldset, regs);
-Index: linux-2.4.26-ct_sync/arch/i386/kernel/entry.S
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/kernel/entry.S 2003-06-13 16:51:29.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/i386/kernel/entry.S 2004-06-28 12:56:07.000000000 +0200
-@@ -264,7 +264,7 @@
-
- ALIGN
- reschedule:
-- call SYMBOL_NAME(schedule) # test
-+ call SYMBOL_NAME(user_schedule) # test
- jmp ret_from_sys_call
-
- ENTRY(divide_error)
-@@ -402,6 +402,31 @@
- pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
- jmp error_code
-
-+#ifdef CONFIG_KGDB_THREAD
-+ENTRY(kern_schedule)
-+ pushl %ebp
-+ movl %esp, %ebp
-+ pushl %ss
-+ pushl %ebp
-+ pushfl
-+ pushl %cs
-+ pushl 4(%ebp)
-+ pushl %eax
-+ pushl %es
-+ pushl %ds
-+ pushl %eax
-+ pushl (%ebp)
-+ pushl %edi
-+ pushl %esi
-+ pushl %edx
-+ pushl %ecx
-+ pushl %ebx
-+ call kern_do_schedule
-+ movl %ebp, %esp
-+ pop %ebp
-+ ret
-+#endif
-+
- .data
- ENTRY(sys_call_table)
- .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
-Index: linux-2.4.26-ct_sync/arch/i386/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/Makefile 2003-06-13 16:51:29.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/i386/Makefile 2004-06-28 12:56:07.000000000 +0200
-@@ -113,6 +113,11 @@
- $(MAKE) linuxsubdirs SUBDIRS=arch/i386/mm
-
- MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-+ifeq ($(CONFIG_X86_REMOTE_DEBUG),y)
-+CLEANKERNEL = $(MAKE) -C arch/$(ARCH)/kernel kernelclean
-+else
-+CLEANKERNEL =
-+endif
-
- vmlinux: arch/i386/vmlinux.lds
-
-@@ -148,6 +153,7 @@
-
- archclean:
- @$(MAKEBOOT) clean
-+ @$(CLEANKERNEL)
-
- archmrproper:
-
-Index: linux-2.4.26-ct_sync/arch/i386/mm/fault.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/mm/fault.c 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.26-ct_sync/arch/i386/mm/fault.c 2004-06-28 12:56:07.000000000 +0200
-@@ -2,6 +2,11 @@
- * linux/arch/i386/mm/fault.c
- *
- * Copyright (C) 1995 Linus Torvalds
-+ *
-+ * Change History
-+ *
-+ * Tigran Aivazian <tigran at sco.com> Remote debugging support.
-+ *
- */
-
- #include <linux/signal.h>
-@@ -19,6 +24,9 @@
- #include <linux/init.h>
- #include <linux/tty.h>
- #include <linux/vt_kern.h> /* For unblank_screen() */
-+#ifdef CONFIG_KGDB
-+#include <linux/kgdb.h>
-+#endif
-
- #include <asm/system.h>
- #include <asm/uaccess.h>
-@@ -183,6 +191,13 @@
- if (in_interrupt() || !mm)
- goto no_context;
-
-+#ifdef CONFIG_KGDB
-+ if (kgdb_memerr_expected) {
-+ /* We are in kgdb. Can't handle the fault */
-+ goto no_context;
-+ }
-+#endif
-+
- down_read(&mm->mmap_sem);
-
- vma = find_vma(mm, address);
-@@ -302,6 +317,12 @@
- return;
- }
-
-+#ifdef CONFIG_KGDB
-+ if (linux_debug_hook != (gdb_debug_hook *) NULL) {
-+ (*linux_debug_hook)(14, SIGSEGV, error_code, regs);
-+ }
-+#endif
-+
- /*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
-@@ -309,6 +330,7 @@
-
- bust_spinlocks(1);
-
-+
- if (address < PAGE_SIZE)
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- else
-Index: linux-2.4.26-ct_sync/arch/i386/config.in
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/i386/config.in 2004-02-18 14:36:30.000000000 +0100
-+++ linux-2.4.26-ct_sync/arch/i386/config.in 2004-06-28 12:56:07.000000000 +0200
-@@ -470,15 +470,21 @@
- mainmenu_option next_comment
- comment 'Kernel hacking'
-
--bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
--if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
-- bool ' Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW
-- bool ' Debug high memory support' CONFIG_DEBUG_HIGHMEM
-- bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
-- bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
-- bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
-- bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
-- bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
-+bool 'KGDB: Remote (serial) kernel debugging with gdb' CONFIG_KGDB
-+if [ "$CONFIG_KGDB" != "n" ]; then
-+ bool 'KGDB: Thread analysis' CONFIG_KGDB_THREAD
-+ bool 'KGDB: Console messages through gdb' CONFIG_GDB_CONSOLE
-+else
-+ bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
-+ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
-+ bool ' Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW
-+ bool ' Debug high memory support' CONFIG_DEBUG_HIGHMEM
-+ bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
-+ bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
-+ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
-+ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
-+ bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
-+ fi
- fi
-
- int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
-Index: linux-2.4.26-ct_sync/arch/ppc/kernel/ppc-stub.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/ppc/kernel/ppc-stub.c 2003-11-28 19:26:19.000000000 +0100
-+++ linux-2.4.26-ct_sync/arch/ppc/kernel/ppc-stub.c 2004-06-28 12:56:07.000000000 +0200
-@@ -1,742 +1,261 @@
- /*
-- * ppc-stub.c: KGDB support for the Linux kernel.
- *
-- * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
-- * some stuff borrowed from Paul Mackerras' xmon
-- * Copyright (C) 1998 Michael AK Tesch (tesch at cs.wisc.edu)
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2, or (at your option) any
-+ * later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
- *
-- * Modifications to run under Linux
-- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
-- *
-- * This file originally came from the gdb sources, and the
-- * copyright notices have been retained below.
- */
-
--/****************************************************************************
--
-- THIS SOFTWARE IS NOT COPYRIGHTED
--
-- HP offers the following for use in the public domain. HP makes no
-- warranty with regard to the software or its performance and the
-- user accepts the software "AS IS" with all faults.
--
-- HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
-- TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
--
--****************************************************************************/
--
--/****************************************************************************
-- * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
-- *
-- * Module name: remcom.c $
-- * Revision: 1.34 $
-- * Date: 91/03/09 12:29:49 $
-- * Contributor: Lake Stevens Instrument Division$
-- *
-- * Description: low level support for gdb debugger. $
-- *
-- * Considerations: only works on target hardware $
-- *
-- * Written by: Glenn Engel $
-- * ModuleState: Experimental $
-- *
-- * NOTES: See Below $
-- *
-- * Modified for SPARC by Stu Grossman, Cygnus Support.
-- *
-- * This code has been extensively tested on the Fujitsu SPARClite demo board.
-- *
-- * To enable debugger support, two things need to happen. One, a
-- * call to set_debug_traps() is necessary in order to allow any breakpoints
-- * or error conditions to be properly intercepted and reported to gdb.
-- * Two, a breakpoint needs to be generated to begin communication. This
-- * is most easily accomplished by a call to breakpoint(). Breakpoint()
-- * simulates a breakpoint by executing a trap #1.
-- *
-- *************
-- *
-- * The following gdb commands are supported:
-- *
-- * command function Return value
-- *
-- * g return the value of the CPU registers hex data or ENN
-- * G set the value of the CPU registers OK or ENN
-- * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
-- *
-- * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
-- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
-- *
-- * c Resume at current address SNN ( signal NN)
-- * cAA..AA Continue at address AA..AA SNN
-- *
-- * s Step one instruction SNN
-- * sAA..AA Step one instruction from AA..AA SNN
-- *
-- * k kill
-- *
-- * ? What was the last sigval ? SNN (signal NN)
-- *
-- * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
-- * baud rate
-- *
-- * All commands and responses are sent with a packet which includes a
-- * checksum. A packet consists of
-- *
-- * $<packet info>#<checksum>.
-- *
-- * where
-- * <packet info> :: <characters representing the command or response>
-- * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
-- *
-- * When a packet is received, it is first acknowledged with either '+' or '-'.
-- * '+' indicates a successful transfer. '-' indicates a failed transfer.
-- *
-- * Example:
-- *
-- * Host: Reply:
-- * $m0,10#2a +$00010203040506070809101112131415#42
-- *
-- ****************************************************************************/
-+/*
-+ * Copyright (C) 2003 Timesys Corporation.
-+ * KGDB for the PowerPC processor
-+ */
-
--#include <linux/config.h>
--#include <linux/kernel.h>
- #include <linux/string.h>
--#include <linux/mm.h>
--#include <linux/smp.h>
--#include <linux/smp_lock.h>
--
--#include <asm/system.h>
--#include <asm/signal.h>
--#include <asm/kgdb.h>
--#include <asm/pgtable.h>
-+#include <linux/kernel.h>
-+#include <linux/config.h>
-+#include <linux/kgdb.h>
-+#include <linux/sched.h>
-+#include <asm/current.h>
- #include <asm/ptrace.h>
--
--void breakinst(void);
-+#include <asm/processor.h>
-+#include <asm/signal.h>
-
- /*
-- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
-- * at least NUMREGBYTES*2 are needed for register packets
-+ * Forward prototypes
- */
--#define BUFMAX 2048
--static char remcomInBuffer[BUFMAX];
--static char remcomOutBuffer[BUFMAX];
--
--static int initialized;
--static int kgdb_active;
--static int kgdb_started;
--static u_int fault_jmp_buf[100];
--static int kdebug;
--
--static const char hexchars[]="0123456789abcdef";
--
--/* Place where we save old trap entries for restoration - sparc*/
--/* struct tt_entry kgdb_savettable[256]; */
--/* typedef void (*trapfunc_t)(void); */
--
--static void kgdb_fault_handler(struct pt_regs *regs);
--static int handle_exception (struct pt_regs *regs);
--
--#if 0
--/* Install an exception handler for kgdb */
--static void exceptionHandler(int tnum, unsigned int *tfunc)
--{
-- /* We are dorking with a live trap table, all irqs off */
--}
--#endif
-+static void kgdb_debugger (struct pt_regs *regs);
-+static int kgdb_breakpoint (struct pt_regs *regs);
-+static int kgdb_singlestep (struct pt_regs *regs);
-+static int kgdb_iabr_match(struct pt_regs *regs);
-+static int kgdb_dabr_match(struct pt_regs *regs);
-+static int ppc_kgdb_init (void);
-+static void ppc_regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs);
-+static void ppc_sleeping_thread_to_gdb_regs(int *gdb_regs, struct task_struct *p);
-+static void ppc_gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs);
-+void ppc_exit_handler (void);
-+int ppc_handle_exception (int vector,
-+ int signo,
-+ int err_code,
-+ char *remcomInBuffer,
-+ char *remcomOutBuffer,
-+ struct pt_regs *linux_regs);
-
--int
--kgdb_setjmp(long *buf)
--{
-- asm ("mflr 0; stw 0,0(%0);"
-- "stw 1,4(%0); stw 2,8(%0);"
-- "mfcr 0; stw 0,12(%0);"
-- "stmw 13,16(%0)"
-- : : "r" (buf));
-- /* XXX should save fp regs as well */
-- return 0;
--}
--void
--kgdb_longjmp(long *buf, int val)
--{
-- if (val == 0)
-- val = 1;
-- asm ("lmw 13,16(%0);"
-- "lwz 0,12(%0); mtcrf 0x38,0;"
-- "lwz 0,0(%0); lwz 1,4(%0); lwz 2,8(%0);"
-- "mtlr 0; mr 3,%1"
-- : : "r" (buf), "r" (val));
--}
--/* Convert ch from a hex digit to an int */
--static int
--hex(unsigned char ch)
--{
-- if (ch >= 'a' && ch <= 'f')
-- return ch-'a'+10;
-- if (ch >= '0' && ch <= '9')
-- return ch-'0';
-- if (ch >= 'A' && ch <= 'F')
-- return ch-'A'+10;
-- return -1;
--}
--
--/* Convert the memory pointed to by mem into hex, placing result in buf.
-- * Return a pointer to the last char put in buf (null), in case of mem fault,
-- * return 0.
-+/*
-+ * Global data
- */
--static unsigned char *
--mem2hex(const char *mem, char *buf, int count)
-+struct kgdb_arch arch_kgdb_ops =
- {
-- unsigned char ch;
--
-- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
-- debugger_fault_handler = kgdb_fault_handler;
-- while (count-- > 0) {
-- ch = *mem++;
-- *buf++ = hexchars[ch >> 4];
-- *buf++ = hexchars[ch & 0xf];
-- }
-- } else {
-- /* error condition */
-- }
-- debugger_fault_handler = 0;
-- *buf = 0;
-- return buf;
--}
--
--/* convert the hex array pointed to by buf into binary to be placed in mem
-- * return a pointer to the character AFTER the last byte written.
--*/
--static char *
--hex2mem(char *buf, char *mem, int count)
--{
-- int i;
-- unsigned char ch;
--
-- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
-- debugger_fault_handler = kgdb_fault_handler;
-- for (i=0; i<count; i++) {
-- ch = hex(*buf++) << 4;
-- ch |= hex(*buf++);
-- *mem++ = ch;
-- }
-- flush_icache_range((int)mem, (int)mem+count);
-- } else {
-- /* error condition */
-- }
-- debugger_fault_handler = 0;
-- return mem;
--}
-+ { 0x7d, 0x82, 0x10, 0x08 }, /* gdb_bpt_instr */
-+ 0, /* flags */
-+ ppc_kgdb_init, /* kgdb_init */
-+ ppc_regs_to_gdb_regs, /* regs_to_gdb_regs */
-+ ppc_sleeping_thread_to_gdb_regs, /* sleeping_thread_to_gdb_regs */
-+ ppc_gdb_regs_to_regs, /* gdb_regs_to_regs */
-+ NULL, /* printexpinfo */
-+ NULL, /* disable_hw_debug */
-+ NULL, /* post_master_code */
-+ ppc_handle_exception, /* handle_buffer */
-+ NULL, /* set_break */
-+ NULL, /* remove_break */
-+ NULL, /* correct_hw_break */
-+ ppc_exit_handler, /* handler_exit */
-+};
-
- /*
-- * While we find nice hex chars, build an int.
-- * Return number of chars processed.
-+ * Routines
- */
--static int
--hexToInt(char **ptr, int *intValue)
-+static void kgdb_debugger (struct pt_regs *regs)
- {
-- int numChars = 0;
-- int hexValue;
--
-- *intValue = 0;
--
-- if (kgdb_setjmp((long*)fault_jmp_buf) == 0) {
-- debugger_fault_handler = kgdb_fault_handler;
-- while (**ptr) {
-- hexValue = hex(**ptr);
-- if (hexValue < 0)
-- break;
--
-- *intValue = (*intValue << 4) | hexValue;
-- numChars ++;
--
-- (*ptr)++;
-- }
-- } else {
-- /* error condition */
-- }
-- debugger_fault_handler = 0;
--
-- return (numChars);
--}
--
--/* scan for the sequence $<data>#<checksum> */
--static void
--getpacket(char *buffer)
--{
-- unsigned char checksum;
-- unsigned char xmitcsum;
-- int i;
-- int count;
-- unsigned char ch;
--
-- do {
-- /* wait around for the start character, ignore all other
-- * characters */
-- while ((ch = (getDebugChar() & 0x7f)) != '$') ;
--
-- checksum = 0;
-- xmitcsum = -1;
--
-- count = 0;
--
-- /* now, read until a # or end of buffer is found */
-- while (count < BUFMAX) {
-- ch = getDebugChar() & 0x7f;
-- if (ch == '#')
-- break;
-- checksum = checksum + ch;
-- buffer[count] = ch;
-- count = count + 1;
-- }
--
-- if (count >= BUFMAX)
-- continue;
--
-- buffer[count] = 0;
--
-- if (ch == '#') {
-- xmitcsum = hex(getDebugChar() & 0x7f) << 4;
-- xmitcsum |= hex(getDebugChar() & 0x7f);
-- if (checksum != xmitcsum)
-- putDebugChar('-'); /* failed checksum */
-- else {
-- putDebugChar('+'); /* successful transfer */
-- /* if a sequence char is present, reply the ID */
-- if (buffer[2] == ':') {
-- putDebugChar(buffer[0]);
-- putDebugChar(buffer[1]);
-- /* remove sequence chars from buffer */
-- count = strlen(buffer);
-- for (i=3; i <= count; i++)
-- buffer[i-3] = buffer[i];
-- }
-- }
-- }
-- } while (checksum != xmitcsum);
-+ kgdb_handle_exception (0, 0, 0, regs);
-+ return;
- }
-
--/* send the packet in buffer. */
--static void putpacket(unsigned char *buffer)
-+static int kgdb_breakpoint (struct pt_regs *regs)
- {
-- unsigned char checksum;
-- int count;
-- unsigned char ch, recv;
--
-- /* $<packet info>#<checksum>. */
-- do {
-- putDebugChar('$');
-- checksum = 0;
-- count = 0;
--
-- while ((ch = buffer[count])) {
-- putDebugChar(ch);
-- checksum += ch;
-- count += 1;
-- }
--
-- putDebugChar('#');
-- putDebugChar(hexchars[checksum >> 4]);
-- putDebugChar(hexchars[checksum & 0xf]);
-- recv = getDebugChar();
-- } while ((recv & 0x7f) != '+');
--}
-+ extern atomic_t kgdb_setting_breakpoint;
-
--static void kgdb_flush_cache_all(void)
--{
-- flush_instruction_cache();
--}
-+ kgdb_handle_exception (0, SIGTRAP, 0, regs);
-
--/* Set up exception handlers for tracing and breakpoints
-- * [could be called kgdb_init()]
-- */
--void set_debug_traps(void)
--{
--#if 0
-- unsigned char c;
--
-- save_and_cli(flags);
--
-- /* In case GDB is started before us, ack any packets (presumably
-- * "$?#xx") sitting there.
-- *
-- * I've found this code causes more problems than it solves,
-- * so that's why it's commented out. GDB seems to work fine
-- * now starting either before or after the kernel -bwb
-- */
--
-- while((c = getDebugChar()) != '$');
-- while((c = getDebugChar()) != '#');
-- c = getDebugChar(); /* eat first csum byte */
-- c = getDebugChar(); /* eat second csum byte */
-- putDebugChar('+'); /* ack it */
--#endif
-- debugger = kgdb;
-- debugger_bpt = kgdb_bpt;
-- debugger_sstep = kgdb_sstep;
-- debugger_iabr_match = kgdb_iabr_match;
-- debugger_dabr_match = kgdb_dabr_match;
-+ if (atomic_read (&kgdb_setting_breakpoint))
-+ regs->nip += 4;
-
-- initialized = 1;
-+ return 1;
- }
-
--static void kgdb_fault_handler(struct pt_regs *regs)
-+static int kgdb_singlestep (struct pt_regs *regs)
- {
-- kgdb_longjmp((long*)fault_jmp_buf, 1);
-+ kgdb_handle_exception (0, SIGTRAP, 0, regs);
-+ return 1;
- }
-
--int kgdb_bpt(struct pt_regs *regs)
-+static int kgdb_iabr_match(struct pt_regs *regs)
- {
-- return handle_exception(regs);
-+ kgdb_handle_exception (0, 0, 0, regs);
-+ return 1;
- }
-
--int kgdb_sstep(struct pt_regs *regs)
-+static int kgdb_dabr_match(struct pt_regs *regs)
- {
-- return handle_exception(regs);
-+ kgdb_handle_exception (0, 0, 0, regs);
-+ return 1;
- }
-
--void kgdb(struct pt_regs *regs)
-+static int ppc_kgdb_init (void)
- {
-- handle_exception(regs);
--}
-+ debugger = kgdb_debugger;
-+ debugger_bpt = kgdb_breakpoint;
-+ debugger_sstep = kgdb_singlestep;
-+ debugger_iabr_match = kgdb_iabr_match;
-+ debugger_dabr_match = kgdb_dabr_match;
-
--int kgdb_iabr_match(struct pt_regs *regs)
--{
-- printk(KERN_ERR "kgdb doesn't support iabr, what?!?\n");
-- return handle_exception(regs);
-+ return 0;
-+
- }
-
--int kgdb_dabr_match(struct pt_regs *regs)
-+static void ppc_regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs)
- {
-- printk(KERN_ERR "kgdb doesn't support dabr, what?!?\n");
-- return handle_exception(regs);
--}
-+ int reg;
-+ int *ptr = gdb_regs;
-
--/* Convert the SPARC hardware trap type code to a unix signal number. */
--/*
-- * This table contains the mapping between PowerPC hardware trap types, and
-- * signals, which are primarily what GDB understands.
-- */
--static struct hard_trap_info
--{
-- unsigned int tt; /* Trap type code for powerpc */
-- unsigned char signo; /* Signal that we map this trap into */
--} hard_trap_info[] = {
-- { 0x200, SIGSEGV }, /* machine check */
-- { 0x300, SIGSEGV }, /* address error (store) */
-- { 0x400, SIGBUS }, /* instruction bus error */
-- { 0x500, SIGINT }, /* interrupt */
-- { 0x600, SIGBUS }, /* alingment */
-- { 0x700, SIGTRAP }, /* breakpoint trap */
-- { 0x800, SIGFPE }, /* fpu unavail */
-- { 0x900, SIGALRM }, /* decrementer */
-- { 0xa00, SIGILL }, /* reserved */
-- { 0xb00, SIGILL }, /* reserved */
-- { 0xc00, SIGCHLD }, /* syscall */
-- { 0xd00, SIGTRAP }, /* single-step/watch */
-- { 0xe00, SIGFPE }, /* fp assist */
-- { 0, 0} /* Must be last */
--};
-+ memset(gdb_regs, 0, MAXREG*4);
-
--static int computeSignal(unsigned int tt)
--{
-- struct hard_trap_info *ht;
-+ for (reg = 0; reg < 32; reg++)
-+ *(ptr++) = regs->gpr[reg];
-
-- for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
-- if (ht->tt == tt)
-- return ht->signo;
-+ for (reg = 0; reg < 64; reg++)
-+ *(ptr++) = 0;
-
-- return SIGHUP; /* default for things we don't know about */
--}
-+ *(ptr++) = regs->nip;
-+ *(ptr++) = regs->msr;
-+ *(ptr++) = regs->ccr;
-+ *(ptr++) = regs->link;
-+ *(ptr++) = regs->ctr;
-+ *(ptr++) = regs->xer;
-
--#define PC_REGNUM 64
--#define SP_REGNUM 1
-+ return;
-+} /* regs_to_gdb_regs */
-
--/*
-- * This function does all command processing for interfacing to gdb.
-- */
--static int
--handle_exception (struct pt_regs *regs)
-+static void ppc_sleeping_thread_to_gdb_regs(int *gdb_regs, struct task_struct *p)
- {
-- int sigval;
-- int addr;
-- int length;
-- char *ptr;
-- unsigned int msr;
--
-- /* We don't handle user-mode breakpoints. */
-- if (user_mode(regs))
-- return 0;
--
-- if (debugger_fault_handler) {
-- debugger_fault_handler(regs);
-- panic("kgdb longjump failed!\n");
-- }
-- if (kgdb_active) {
-- printk(KERN_ERR "interrupt while in kgdb, returning\n");
-- return 0;
-- }
--
-- kgdb_active = 1;
-- kgdb_started = 1;
--
--#ifdef KGDB_DEBUG
-- printk("kgdb: entering handle_exception; trap [0x%x]\n",
-- (unsigned int)regs->trap);
--#endif
--
-- kgdb_interruptible(0);
-- lock_kernel();
-- msr = mfmsr();
-- mtmsr(msr & ~MSR_EE); /* disable interrupts */
--
-- if (regs->nip == (unsigned long)breakinst) {
-- /* Skip over breakpoint trap insn */
-- regs->nip += 4;
-- }
--
-- /* reply to host that an exception has occurred */
-- sigval = computeSignal(regs->trap);
-- ptr = remcomOutBuffer;
--
--#if 0
-- *ptr++ = 'S';
-- *ptr++ = hexchars[sigval >> 4];
-- *ptr++ = hexchars[sigval & 0xf];
--#else
-- *ptr++ = 'T';
-- *ptr++ = hexchars[sigval >> 4];
-- *ptr++ = hexchars[sigval & 0xf];
-- *ptr++ = hexchars[PC_REGNUM >> 4];
-- *ptr++ = hexchars[PC_REGNUM & 0xf];
-- *ptr++ = ':';
-- ptr = mem2hex((char *)®s->nip, ptr, 4);
-- *ptr++ = ';';
-- *ptr++ = hexchars[SP_REGNUM >> 4];
-- *ptr++ = hexchars[SP_REGNUM & 0xf];
-- *ptr++ = ':';
-- ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4);
-- *ptr++ = ';';
--#endif
--
-- *ptr++ = 0;
-+ struct pt_regs *regs = (struct pt_regs *) (p->thread.ksp +
-+ STACK_FRAME_OVERHEAD);
-+ int reg;
-+ int *ptr = gdb_regs;
-
-- putpacket(remcomOutBuffer);
-+ memset(gdb_regs, 0, MAXREG*4);
-
-- /* XXX We may want to add some features dealing with poking the
-- * XXX page tables, ... (look at sparc-stub.c for more info)
-- * XXX also required hacking to the gdb sources directly...
-- */
--
-- while (1) {
-- remcomOutBuffer[0] = 0;
--
-- getpacket(remcomInBuffer);
-- switch (remcomInBuffer[0]) {
-- case '?': /* report most recent signal */
-- remcomOutBuffer[0] = 'S';
-- remcomOutBuffer[1] = hexchars[sigval >> 4];
-- remcomOutBuffer[2] = hexchars[sigval & 0xf];
-- remcomOutBuffer[3] = 0;
-- break;
--#if 0
-- case 'q': /* this screws up gdb for some reason...*/
-- {
-- extern long _start, sdata, __bss_start;
-+ /* Regs GPR0-2 */
-+ for (reg = 0; reg < 3; reg++)
-+ *(ptr++) = regs->gpr[reg];
-
-- ptr = &remcomInBuffer[1];
-- if (strncmp(ptr, "Offsets", 7) != 0)
-- break;
--
-- ptr = remcomOutBuffer;
-- sprintf(ptr, "Text=%8.8x;Data=%8.8x;Bss=%8.8x",
-- &_start, &sdata, &__bss_start);
-- break;
-- }
--#endif
-- case 'd':
-- /* toggle debug flag */
-- kdebug ^= 1;
-- break;
--
-- case 'g': /* return the value of the CPU registers.
-- * some of them are non-PowerPC names :(
-- * they are stored in gdb like:
-- * struct {
-- * u32 gpr[32];
-- * f64 fpr[32];
-- * u32 pc, ps, cnd, lr; (ps=msr)
-- * u32 cnt, xer, mq;
-- * }
-- */
-- {
-- int i;
-- ptr = remcomOutBuffer;
-- /* General Purpose Regs */
-- ptr = mem2hex((char *)regs, ptr, 32 * 4);
-- /* Floating Point Regs - FIXME */
-- /*ptr = mem2hex((char *), ptr, 32 * 8);*/
-- for(i=0; i<(32*8*2); i++) { /* 2chars/byte */
-- ptr[i] = '0';
-- }
-- ptr += 32*8*2;
-- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
-- ptr = mem2hex((char *)®s->nip, ptr, 4);
-- ptr = mem2hex((char *)®s->msr, ptr, 4);
-- ptr = mem2hex((char *)®s->ccr, ptr, 4);
-- ptr = mem2hex((char *)®s->link, ptr, 4);
-- ptr = mem2hex((char *)®s->ctr, ptr, 4);
-- ptr = mem2hex((char *)®s->xer, ptr, 4);
-- }
-- break;
-+ /* Regs GPR3-13 are not saved */
-+ for (reg = 3; reg < 14; reg++)
-+ *(ptr++) = 0;
-
-- case 'G': /* set the value of the CPU registers */
-- {
-- ptr = &remcomInBuffer[1];
-+ /* Regs GPR14-31 */
-+ for (reg = 14; reg < 32; reg++)
-+ *(ptr++) = regs->gpr[reg];
-
-- /*
-- * If the stack pointer has moved, you should pray.
-- * (cause only god can help you).
-- */
--
-- /* General Purpose Regs */
-- hex2mem(ptr, (char *)regs, 32 * 4);
--
-- /* Floating Point Regs - FIXME?? */
-- /*ptr = hex2mem(ptr, ??, 32 * 8);*/
-- ptr += 32*8*2;
--
-- /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
-- ptr = hex2mem(ptr, (char *)®s->nip, 4);
-- ptr = hex2mem(ptr, (char *)®s->msr, 4);
-- ptr = hex2mem(ptr, (char *)®s->ccr, 4);
-- ptr = hex2mem(ptr, (char *)®s->link, 4);
-- ptr = hex2mem(ptr, (char *)®s->ctr, 4);
-- ptr = hex2mem(ptr, (char *)®s->xer, 4);
--
-- strcpy(remcomOutBuffer,"OK");
-- }
-- break;
-- case 'H':
-- /* don't do anything, yet, just acknowledge */
-- hexToInt(&ptr, &addr);
-- strcpy(remcomOutBuffer,"OK");
-- break;
-+ for (reg = 0; reg < 64; reg++)
-+ *(ptr++) = 0;
-
-- case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
-- /* Try to read %x,%x. */
-+ *(ptr++) = regs->nip;
-+ *(ptr++) = regs->msr;
-+ *(ptr++) = regs->ccr;
-+ *(ptr++) = regs->link;
-+ *(ptr++) = regs->ctr;
-+ *(ptr++) = regs->xer;
-
-- ptr = &remcomInBuffer[1];
-+ return;
-+}
-
-- if (hexToInt(&ptr, &addr)
-- && *ptr++ == ','
-- && hexToInt(&ptr, &length)) {
-- if (mem2hex((char *)addr, remcomOutBuffer,length))
-- break;
-- strcpy (remcomOutBuffer, "E03");
-- } else {
-- strcpy(remcomOutBuffer,"E01");
-- }
-- break;
-+static void ppc_gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs)
-+{
-+ int reg;
-+ int *ptr = gdb_regs;
-
-- case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
-- /* Try to read '%x,%x:'. */
-+ for (reg = 0; reg < 32; reg++)
-+ regs->gpr[reg] = *(ptr++);
-
-- ptr = &remcomInBuffer[1];
-+ for (reg = 0; reg < 64; reg++)
-+ ptr++;
-
-- if (hexToInt(&ptr, &addr)
-- && *ptr++ == ','
-- && hexToInt(&ptr, &length)
-- && *ptr++ == ':') {
-- if (hex2mem(ptr, (char *)addr, length)) {
-- strcpy(remcomOutBuffer, "OK");
-- } else {
-- strcpy(remcomOutBuffer, "E03");
-- }
-- flush_icache_range(addr, addr+length);
-- } else {
-- strcpy(remcomOutBuffer, "E02");
-- }
-- break;
-+ regs->nip = *(ptr++);
-+ regs->msr = *(ptr++);
-+ regs->ccr = *(ptr++);
-+ regs->link = *(ptr++);
-+ regs->ctr = *(ptr++);
-+ regs->xer = *(ptr++);
-
-+ return;
-+} /* gdb_regs_to_regs */
-
-- case 'k': /* kill the program, actually just continue */
-- case 'c': /* cAA..AA Continue; address AA..AA optional */
-- /* try to read optional parameter, pc unchanged if no parm */
-
-- ptr = &remcomInBuffer[1];
-- if (hexToInt(&ptr, &addr)) {
-- regs->nip = addr;
-- }
--
--/* Need to flush the instruction cache here, as we may have deposited a
-- * breakpoint, and the icache probably has no way of knowing that a data ref to
-- * some location may have changed something that is in the instruction cache.
-+/* exit_handler:
-+ *
-+ * This is called by the generic layer when it is about to return from
-+ * the exception handler
- */
-- kgdb_flush_cache_all();
-- mtmsr(msr);
-- kgdb_interruptible(1);
-- unlock_kernel();
-- kgdb_active = 0;
-- return 1;
--
-- case 's':
-- kgdb_flush_cache_all();
-- regs->msr |= MSR_SE;
-- unlock_kernel();
-- kgdb_active = 0;
-- return 1;
--
-- case 'r': /* Reset (if user process..exit ???)*/
-- panic("kgdb reset.");
-- break;
-- } /* switch */
-- if (remcomOutBuffer[0] && kdebug) {
-- printk("remcomInBuffer: %s\n", remcomInBuffer);
-- printk("remcomOutBuffer: %s\n", remcomOutBuffer);
-- }
-- /* reply to the request */
-- putpacket(remcomOutBuffer);
-- } /* while(1) */
-+void ppc_exit_handler (void)
-+{
-+// flush_instruction_cache ();
-+ return;
- }
-
--/* This function will generate a breakpoint exception. It is used at the
-- beginning of a program to sync up with a debugger and can be used
-- otherwise as a quick means to stop program execution and "break" into
-- the debugger. */
--
--void
--breakpoint(void)
--{
-- if (!initialized) {
-- printk("breakpoint() called b4 kgdb init\n");
-- return;
-- }
--
-- asm(" .globl breakinst \n\
-- breakinst: .long 0x7d821008");
--}
-
--#ifdef CONFIG_KGDB_CONSOLE
- /*
-- * Output string in GDB O-packet format if GDB has connected. If nothing
-- * output, returns 0 (caller must then handle output)
-+ * This function does PoerPC specific procesing for interfacing to gdb.
- */
--int
--kgdb_output_string (const char* s, unsigned int count)
-+int ppc_handle_exception (int vector,
-+ int signo,
-+ int err_code,
-+ char *remcomInBuffer,
-+ char *remcomOutBuffer,
-+ struct pt_regs *linux_regs)
- {
-- char buffer[512];
-+ char *ptr;
-+ int addr;
-+
-+ switch (remcomInBuffer[0])
-+ {
-+ /*
-+ * sAA..AA Step one instruction from AA..AA
-+ * This will return an error to gdb ..
-+ */
-+ case 's':
-+ case 'c':
-+ if (kgdb_contthread && kgdb_contthread != current)
-+ {
-+ strcpy(remcomOutBuffer, "E00");
-+ break;
-+ }
-
-- if (!kgdb_started)
-- return 0;
-+ kgdb_contthread = NULL;
-
-- count = (count <= (sizeof(buffer) / 2 - 2))
-- ? count : (sizeof(buffer) / 2 - 2);
-+ /* handle the optional parameter */
-+ ptr = &remcomInBuffer[1];
-+ if (hexToInt (&ptr, &addr))
-+ linux_regs->nip = addr;
-
-- buffer[0] = 'O';
-- mem2hex (s, &buffer[1], count);
-- putpacket(buffer);
-+ /* set the trace bit if we're stepping */
-+ if (remcomInBuffer[0] == 's')
-+ {
-+#if defined (CONFIG_4xx)
-+ linux_regs->msr |= MSR_DE;
-+ current->thread.dbcr0 |= (DBCR_IDM | DBCR_IC);
-+#else
-+ linux_regs->msr |= MSR_SE;
-+#endif
-+ }
-+ return 0;
-+ }
-
-- return 1;
-+ return -1;
- }
--#endif
-Index: linux-2.4.26-ct_sync/arch/ppc/kernel/entry.S
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/ppc/kernel/entry.S 2004-04-14 15:05:27.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/ppc/kernel/entry.S 2004-06-28 12:56:07.000000000 +0200
-@@ -295,7 +295,7 @@
- lwz r3,NEED_RESCHED(r2)
- cmpi 0,r3,0 /* check need_resched flag */
- beq+ 7f
-- bl schedule
-+ bl user_schedule
- 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */
- cmpwi 0,r5,0
- beq+ do_signal_ret
-@@ -450,3 +450,53 @@
- mtspr SRR1,r9
- RFI /* return to caller */
- #endif /* CONFIG_ALL_PPC */
-+
-+#ifdef CONFIG_KGDB
-+/*
-+ * These are hooks used by KGDB because switch_to does not save registers
-+ * in pt_regs. The registers are saved on the stack on behalf of the caller
-+ * of these funtions.
-+ */
-+
-+_GLOBAL(kern_schedule)
-+ stwu r1,-INT_FRAME_SIZE(r1) /* Allocate exception frame */
-+ SAVE_8GPRS( 0, r1)
-+ SAVE_8GPRS( 8, r1)
-+ SAVE_8GPRS(16, r1)
-+ SAVE_8GPRS(24, r1)
-+ addi r3,r1,INT_FRAME_SIZE
-+ stw r3,GPR1(r1)
-+ mfcr r3
-+ stw r3,_CCR(r1)
-+ mflr r3
-+ stw r3,_NIP(r1)
-+ mfctr r3
-+ stw r3,_CTR(r1)
-+ mfxer r3
-+ stw r3,_XER(r1)
-+ mfmsr r3
-+ stw r3,_MSR(r1)
-+ lwz r3,INT_FRAME_SIZE+4(r1)
-+ stw r3,_LINK(r1)
-+
-+ bl kern_do_schedule
-+
-+ lwz r3,_CCR(r1)
-+ mtcr r3
-+ lwz r3,_XER(r1)
-+ mtxer r3
-+ lwz r3,_NIP(r1)
-+ mtlr r3
-+ lwz r3,_CTR(r1)
-+ mtctr r3
-+ lwz r3,_MSR(r1)
-+ mtmsr r3
-+ lwz r0,GPR0(r1)
-+ REST_2GPRS ( 2, r1)
-+ REST_4GPRS ( 4, r1)
-+ REST_8GPRS ( 8, r1)
-+ REST_8GPRS (16, r1)
-+ REST_8GPRS (24, r1)
-+ addi r1,r1,INT_FRAME_SIZE
-+ blr
-+#endif
-Index: linux-2.4.26-ct_sync/arch/ppc/config.in
-===================================================================
---- linux-2.4.26-ct_sync.orig/arch/ppc/config.in 2004-04-14 15:05:27.000000000 +0200
-+++ linux-2.4.26-ct_sync/arch/ppc/config.in 2004-06-28 12:56:07.000000000 +0200
-@@ -630,6 +630,8 @@
- bool ' Wait queue debugging' CONFIG_DEBUG_WAITQ
- bool ' Include kgdb kernel debugger' CONFIG_KGDB
- if [ "$CONFIG_KGDB" = "y" ]; then
-+ bool 'KGDB: Thread analysis' CONFIG_KGDB_THREAD
-+ bool 'KGDB: Console messages through gdb' CONFIG_GDB_CONSOLE
- choice ' Serial Port' \
- "ttyS0 CONFIG_KGDB_TTYS0 \
- ttyS1 CONFIG_KGDB_TTYS1 \
-Index: linux-2.4.26-ct_sync/Documentation/i386/gdb-serial.txt
-===================================================================
---- linux-2.4.26-ct_sync.orig/Documentation/i386/gdb-serial.txt 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/Documentation/i386/gdb-serial.txt 2004-06-28 12:56:07.000000000 +0200
-@@ -0,0 +1,386 @@
-+Version
-+=======
-+
-+This version of the gdbstub package was developed and tested on
-+kernel version 2.3.48. It will not install on a 2.2 kernel. It may
-+not work on earlier versions of 2.3 kernels. It is possible that
-+it will continue to work on later versions of 2.3 and then
-+versions of 2.4 (I hope).
-+
-+
-+Debugging Setup
-+===============
-+
-+Designate one machine as the "development" machine. This is the
-+machine on which you run your compiles and which has your source
-+code for the kernel. Designate a second machine as the "target"
-+machine. This is the machine that will run your experimental
-+kernel.
-+
-+The two machines will be connected together via a serial line out
-+one or the other of the COM ports of the PC. You will need a modem
-+eliminator and the appropriate cables.
-+
-+On the DEVELOPMENT machine you need to apply the patch for the gdb
-+hooks. You have probably already done that if you are reading this
-+file.
-+
-+On your DEVELOPMENT machine, go to your kernel source directory and
-+do "make menuconfig". Go down to the kernel hacking menu item and
-+open it up. Enable the kernel gdb stub code by selecting that item.
-+
-+Save and exit the menuconfig program. Then do "make clean" and
-+"make bzImage" (or whatever target you want to make). This gets
-+the kernel compiled with the "-g" option set -- necessary for
-+debugging.
-+
-+You have just built the kernel on your DEVELOPMENT machine that you
-+intend to run on our TARGET machine.
-+
-+To install this new kernel, use the following installation procedure.
-+Remember, you are on the DEVELOPMENT machine patching the kernel source
-+for the kernel that you intend to run on the TARGET machine.
-+
-+Copy this kernel to your target machine using your usual procedures.
-+I usually arrange to copy development:/usr/src/linux/arch/i386/boot/zImage
-+to /vmlinuz on the TARGET machine via a LAN based NFS access. That is,
-+I run the cp command on the target and copy from the development machine
-+via the LAN. Run Lilo on the new kernel on the target machine so that it
-+will boot! Then boot the kernel on the target machine.
-+
-+There is an utility program named "gdbstart" in the
-+development:/usr/src/linux/arch/i386/kernel directory.
-+You should copy this program over to your target machine, probably into
-+/sbin. This utility program is run on the target machine to
-+activate the kernel hooks for the debugger. It is invoked as follows:
-+
-+ gdbstart [-s speed] [-t tty-dev]
-+ defaults: /dev/ttyS0 with speed unmodified by gdbstart
-+
-+Don't run the program just yet. We'll get to that in a bit.
-+
-+Decide on which tty port you want the machines to communicate, then
-+cable them up back-to-back using the null modem. COM1 is /dev/ttyS0
-+and COM2 is /dev/ttyS1.
-+
-+On the DEVELOPMENT machine, create a file called .gdbinit in the
-+directory /usr/src/linux. An example .gdbinit file looks like this:
-+
-+define rmt
-+set remotebaud 38400
-+target remote /dev/ttyS0
-+end
-+
-+Assuming that you added my gdbinit stuff to your .gdbinit, edit .gdbinit
-+and find the section that looks like this:
-+
-+ define rmt
-+ set remotebaud 38400
-+ target remote /dev/ttyS0
-+ end
-+
-+Change the "target" definition so that it specifies the tty port that
-+you intend to use. Change the "remotebaud" definition to match the
-+data rate that you are going to use for the com line.
-+
-+On the TARGET machine I find it helpful to create shell script file
-+named "debug" in the root home directory with the following contents:
-+
-+ gdbstart -s 38400 -t /dev/ttyS0 <<EOF
-+ <blank line>
-+ EOF
-+
-+This runs the gdbstart program and gives it the carriage return that
-+it prompts for. This sets the data rate from the target machine's side.
-+
-+You are now ready to try it out.
-+
-+On your TARGET machine, freshly rebooted with your gdbstub-equipped
-+kernel, type "debug" in the root home directory. The system will appear
-+to hang with some messages on the screen from the debug stub. What
-+it is doing is waiting for contact from the development machine.
-+
-+On your DEVELOPMENT machine, cd /usr/src/linux and enter "gdb vmlinux".
-+When gdb gets the symbols loaded and prompts you, enter "rmt" (that's
-+the macro from the .gdbinit file that you just edited). If everything
-+is working correctly you should see gdb print out a few lines indicating
-+that a breakpoint has been taken. It will actually show a line of
-+code in the target kernel inside the gdbstub activation code.
-+
-+The gdb interaction should look something like this:
-+
-+ linux-dev:/usr/src/linux# gdb vmlinux
-+ GDB is free software and you are welcome to distribute copies of it
-+ under certain conditions; type "show copying" to see the conditions.
-+ There is absolutely no warranty for GDB; type "show warranty" for details.
-+ GDB 4.15.1 (i486-slackware-linux),
-+ Copyright 1995 Free Software Foundation, Inc...
-+ (gdb) rmt
-+ breakpoint () at i386-stub.c:750
-+ 750 }
-+ (gdb)
-+
-+
-+You can now use whatever gdb commands you like to set breakpoints.
-+Enter "continue" to start your target machine executing again. At this
-+point the target system will run at full speed until it encounters
-+your breakpoint or gets a segment violation in the kernel, or whatever.
-+
-+
-+Triggering gdbstub at Kernel Boot Time
-+======================================
-+
-+The gdbstub patch now has the ability for gdb to connect to the kernel during
-+bootup (as opposed to waiting for the system to come all the way up and then
-+running the gdbstart program on the target machine). This new functionality was
-+added by Scott Foehner <sfoehner at engr.sgi.com> at SGI.
-+
-+To force a kernel that has been compiled with gdbstub to pause during the boot
-+process and wait for a connection from gdb, the paramter "gdb" should be passed
-+to the kernel. This can be done by typing "gdb" after the name of the kernel
-+on the LILO command line. The patch defaults to use ttyS1 at a baud rate of
-+38400. These parameters can be changed by using "gdbttyS=<port number>" and
-+"gdbbaud=<baud rate>" on the command line.
-+
-+Example:
-+
-+LILO boot: linux gdb gdbttyS=1 gdbbaud=38400
-+
-+Note that this command is entered on the TARGET machine as it is booting
-+the kernel that was compiled on the DEVELOPMENT machine.
-+
-+An alternate approach is to place a line in the /etc/lilo.conf file on
-+your TARGET machine. Under the heading for the kernel that you intend
-+to boot, place a line that looks like this:
-+
-+ append = "gdb gdbttyS=1 gdbbaud=38400"
-+
-+This will cause the kernel to enter the gdbstub automatically at boot
-+time.
-+
-+BE SURE to run "lilo" after changing the /etc/lilo.conf file.
-+
-+
-+The "gdbstart" Program
-+=====================
-+
-+This utility program is used to set up the com port and data rate
-+for the connection from the target system to the development system.
-+Its usage has been described above.
-+
-+This version of the patch uses the same tty ioctl for kernel versions
-+2.0.30 onwards. Thus, the gdbstart utility does not need to be re-compiled
-+to install the patch in a later version of the kernel. The ioctl added
-+to the kernel for this purpose is far enough "off the end" of existing
-+ioctls (as of 2.1.120) that it should not interfere with any new kernel
-+tty ioctls for quite some time (famous last words).
-+
-+The source for the gdbstart program resides in the arch/i386/kernel directory.
-+
-+
-+Debugging hints
-+===============
-+
-+You can break into the target machine at any time from the development
-+machine by typing ^C. If the target machine has interrupts enabled
-+this will stop it in the kernel and enter the debugger.
-+
-+There is unfortunately no way of breaking into the kernel if it is
-+in a loop with interrupts disabled, so if this happens to you then
-+you need to place exploratory breakpoints or printk's into the kernel
-+to find out where it is looping.
-+
-+There is a copy of an e-mail in the kgdb distribution directory which
-+describes how to create an NMI on an ISA bus machine using a paper
-+clip. I have a sophisticated version of this made by wiring a push
-+button switch into a PC104/ISA bus adapter card. The adapter card
-+nicely furnishes wire wrap pins for all the ISA bus signals.
-+
-+When you are done debugging the kernel on the target machine it is
-+a good idea to leave it in a running state. This makes reboots
-+faster, bypassing the fsck. So do a gdb "continue" as the last gdb
-+command if this is possible. To terminate gdb itself on the development
-+machine and leave the target machine running, type ^Z to suspend gdb
-+and then kill it with "kill %1" or something similar.
-+
-+If gdbstub Does Not Work
-+========================
-+
-+If it doesn't work, you will have to troubleshoot it. Do the easy things
-+first like double checking your cabling and data rates. You might
-+try some non-kernel based programs to see if the back-to-back connection
-+works properly. Just something simple like cat /etc/hosts >/dev/ttyS0
-+on one machine and cat /dev/ttyS0 on the other will tell you if you
-+can send data from one machine to the other. There is no point in tearing
-+out your hair in the kernel if the line doesn't work.
-+
-+All of the real action takes place in the file
-+/usr/src/linux/arch/i386/kernel/gdbstub.c. That is the code on the target
-+machine that interacts with gdb on the development machine. In gdb you can
-+turn on a debug switch with the following command:
-+
-+ set remotedebug
-+
-+This will print out the protocol messages that gdb is exchanging with
-+the target machine.
-+
-+Another place to look is /usr/src/linux/drivers/char/gdbserial.c
-+That is the code that talks to the serial port on the target side.
-+There might be a problem there.
-+
-+If you are really desperate you can use printk debugging in the
-+gdbstub code in the target kernel until you get it working. In particular,
-+there is a global variable in /usr/src/linux/arch/i386/kernel/gdbstub.c
-+named "remote_debug". Compile your kernel with this set to 1, rather
-+than 0 and the debug stub will print out lots of stuff as it does
-+what it does.
-+
-+
-+Debugging Loadable Modules
-+==========================
-+
-+This technique comes courtesy of Edouard Parmelan
-+<Edouard.Parmelan at quadratec.fr>
-+
-+When you run gdb, enter the command
-+
-+source gdbinit-modules
-+
-+This will read in a file of gdb macros that was installed in your
-+kernel source directory with kgdb was installed. This file implements
-+the following commands:
-+
-+mod-list
-+ Lists the loaded modules in the form <module-address> <module-name>
-+
-+mod-print-symbols <module-address>
-+ Prints all the symbols in the indicated module.
-+
-+mod-add-symbols <module-address> <object-file-path-name>
-+ Loads the symbols from the object file and associates them
-+ with the indicated module.
-+
-+After you have loaded the module that you want to debug, use the command
-+mod-list to find the <module-address> of your module. Then use that
-+address in the mod-add-symbols command to load your module's symbols.
-+From that point onward you can debug your module as if it were a part
-+of the kernel.
-+
-+The file gdbinit-modules also contains a command named mod-add-lis as
-+an example of how to construct a command of your own to load your
-+favorite module. The idea is to "can" the pathname of the module
-+in the command so you don't have to type so much.
-+
-+Threads
-+=======
-+
-+Each process in a target machine is seen as a gdb thread. gdb thread related
-+commands (info threads, thread n) can be used.
-+
-+ia-32 hardware breakpoints
-+==========================
-+
-+gdb stub contains support for hardware breakpoints using debugging features
-+of ia-32(x86) processors. These breakpoints do not need code modification.
-+They use debugging registers. 4 hardware breakpoints are available in ia-32
-+processors.
-+
-+Each hardware breakpoint can be of one of the following three types.
-+1. Execution breakpoint - An Execution breakpoint is triggered when code at the
-+ breakpoint address is executed.
-+
-+ As limited number of hardware breakpoints are available, it is advisable
-+ to use software breakpoints ( break command ) instead of execution
-+ hardware breakpoints, unless modification of code is to be avoided.
-+
-+2. Write breakpoint - A write breakpoint is triggered when memory location at the
-+ breakpoint address is written.
-+
-+ A write or can be placed for data of variable length. Length of a write
-+ breakpoint indicates length of the datatype to be watched. Length is 1
-+ for 1 byte data , 2 for 2 byte data, 3 for 4 byte data.
-+
-+3. Access breakpoint - An access breakpoint is triggered when memory location at
-+ the breakpoint address is either read or written.
-+
-+ Access breakpoints also have lengths similar to write breakpoints.
-+
-+IO breakpoints in ia-32 are not supported.
-+
-+Since gdb stub at present does not use the protocol used by gdb for hardware
-+breakpoints, hardware breakpoints are accessed through gdb macros. gdb macros
-+for hardware breakpoints are described below.
-+
-+hwebrk - Places an execution breakpoint
-+ hwebrk breakpointno address
-+hwwbrk - Places a write breakpoint
-+ hwwbrk breakpointno length address
-+hwabrk - Places an access breakpoint
-+ hwabrk breakpointno length address
-+hwrmbrk - Removes a breakpoint
-+ hwrmbrk breakpointno
-+exinfo - Tells whether a software or hardware breakpoint has occured.
-+ Prints number of the hardware breakpoint if a hardware breakpoint has
-+ occured.
-+
-+Arguments required by these commands are as follows
-+breakpointno - 0 to 3
-+length - 1 to 3
-+address - Memory location in hex digits ( without 0x ) e.g c015e9bc
-+
-+MP support
-+==========
-+
-+When a breakpoint occurs or user issues a break ( Ctrl + C ) to gdb client,
-+all the processors are forced to enter the debugger. Current thread
-+corresponds to the thread running on the processor where breakpoint occured.
-+Threads running on other processor(s) appear similar to other non running
-+threads in the 'info threads' output.
-+
-+ia-32 hardware debugging registers on all processors are set to same values.
-+Hence any hardware breakpoints may occur on any processor.
-+
-+gdb troubleshooting
-+===================
-+
-+1. gdb hangs
-+Kill it. restart gdb. Connect to target machine.
-+
-+2. gdb cannot connect to target machine (after killing a gdb and restarting
-+another)
-+If the target machine was not inside debugger when you killed gdb, gdb cannot
-+connect because the target machine won't respond.
-+In this case echo "Ctrl+C"(ascii 3) in the serial line.
-+e.g. echo -e "\003" > /dev/ttyS1
-+This forces that target machine into debugger after which you can connect.
-+
-+3. gdb cannot connect even after echoing Ctrl+C into serial line
-+Try changing serial line settings min to 1 and time to 0
-+e.g. stty min 1 time 0 < /dev/ttyS1
-+Try echoing again
-+
-+check serial line speed and set it to correct value if required
-+e.g. stty ispeed 115200 ospeed 115200 < /dev/ttyS1
-+
-+Final Items
-+===========
-+
-+I picked up this code from Dave Grothe and enhanced it.
-+
-+If you make some really cool modification to this stuff, or if you
-+fix a bug, please let me know.
-+
-+Amit S. Kale
-+<akale at veritas.com>
-+
-+(First kgdb by David Grothe <dave at gcom.com>)
-+
-+(modified by Tigran Aivazian <tigran at sco.com>)
-+ Putting gdbstub into the kernel config menu.
-+
-+(modified by Scott Foehner <sfoehner at engr.sgi.com>)
-+ Hooks for entering gdbstub at boot time.
-+
-+(modified by Amit S. Kale <akale at veritas.com>)
-+ Threads, ia-32 hw debugging, mp support, console support,
-+ nmi watchdog handling.
-Index: linux-2.4.26-ct_sync/Documentation/Configure.help
-===================================================================
---- linux-2.4.26-ct_sync.orig/Documentation/Configure.help 2004-06-28 12:56:01.000000000 +0200
-+++ linux-2.4.26-ct_sync/Documentation/Configure.help 2004-06-28 12:56:07.000000000 +0200
-@@ -22146,6 +22146,31 @@
- If you have a Western Digital WD93 SCSI controller on
- an SGI MIPS system, say Y. Otherwise, say N.
-
-+KGDB: Remote (serial) kernel debugging with gdb
-+CONFIG_KGDB
-+ If you say Y here, it will be possible to remotely debug the
-+ kernel using gdb. This enlarges your kernel image disk size by
-+ several megabytes and requires a machine with more than 128 MB
-+ RAM to avoid excessive linking time.
-+ To use this feature you need to perform some basic setup described
-+ briefly in Documentation/i386/gdb-serial.txt.
-+ More documentation of kernel debugger available at
-+ http://kgdb.sourceforge.net
-+ This is only useful for kernel hackers. If unsure, say N.
-+
-+KGDB: Thread analysis
-+CONFIG_KGDB_THREAD
-+ With thread analysis enabled, gdb can talk to kgdb stub to list
-+ threads and to get stack trace for a thread. This option also enables
-+ some code which helps gdb get exact status of thread. Thread analysis
-+ adds some overhead to schedule and down functions. You can disable this
-+ option if you do not want to compromise on speed.
-+
-+KGDB: Console messagegs through gdb
-+CONFIG_GDB_CONSOLE
-+ If you say Y here, console messages will appear through gdb.
-+ Other consoles such as tty or ttyS will continue to work as usual.
-+
- Magic System Request Key support
- CONFIG_MAGIC_SYSRQ
- If you say Y here, you will have some control over the system even
-
Deleted: branches/netfilter-ha/linux-2.6/patches/nfnetlink-ctnetlink.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/nfnetlink-ctnetlink.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/nfnetlink-ctnetlink.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,2953 +0,0 @@
-%patch
-Index: linux-2.4.26-ct_sync/include/linux/nfnetlink_conntrack.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/nfnetlink_conntrack.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/nfnetlink_conntrack.h 2004-06-28 12:58:22.000000000 +0200
-@@ -0,0 +1,87 @@
-+#ifndef _NFNETLINK_CONNTRACK_H
-+#define _NFNETLINK_CONNTRACK_H
-+#include <linux/nfnetlink.h>
-+#include <linux/netfilter_ipv4/ip_conntrack.h>
-+
-+/* CTNETLINK for ip_conntrack */
-+
-+enum cntl_msg_types {
-+ CTNL_MSG_NEWCONNTRACK,
-+ CTNL_MSG_GETCONNTRACK,
-+ CTNL_MSG_DELCONNTRACK,
-+
-+ CTNL_MSG_NEWEXPECT,
-+ CTNL_MSG_GETEXPECT,
-+ CTNL_MSG_DELEXPECT,
-+
-+ CTNL_MSG_COUNT,
-+};
-+
-+/* ctnetlink attribute types.
-+ */
-+
-+enum ctattr_type_t
-+{
-+ CTA_UNSPEC, /* [none] I don't know (unspecified). */
-+ CTA_ORIG, /* [ip_conntrack_tuple] Original tuple. */
-+ CTA_RPLY, /* [ip_conntrack_tuple] Reply tuple. */
-+ CTA_STATUS, /* [unsigned long] Status of connection. */
-+ CTA_PROTOINFO, /* [cta_proto] Protocol specific ct information. */
-+ CTA_HELPINFO, /* [cta_help] Helper specific information. */
-+ CTA_NATINFO, /* [cta_nat] Any NAT transformations. */
-+ CTA_TIMEOUT, /* [unsigned long] timer */
-+ CTA_MARK, /* [unsigned long] mark .*/
-+
-+ CTA_EXP_TUPLE, /* [ip_conntrack_tuple] Expected tuple */
-+ CTA_EXP_MASK, /* [ip_conntrack_tuple] Mask for EXP_TUPLE */
-+ CTA_EXP_SEQNO, /* [u_int32_t] sequence number */
-+ CTA_EXP_PROTO, /* [cta_exp_proto] */
-+ CTA_EXP_HELP, /* [cta_exp_help] */
-+ CTA_EXP_TIMEOUT,/* [unsigned long] timer */
-+
-+ CTA_MAX = CTA_EXP_TIMEOUT
-+};
-+
-+/* Attribute specific data structures.
-+ */
-+
-+#include <linux/netfilter_ipv4/ip_nat.h>
-+struct cta_nat {
-+ unsigned int num_manips;
-+ struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
-+};
-+
-+struct cta_proto {
-+ unsigned char num_proto; /* Protocol number IPPROTO_X */
-+ union ip_conntrack_proto proto;
-+};
-+
-+#define CTA_HELP_MAXNAMESZ 31
-+
-+struct cta_help {
-+ char name[CTA_HELP_MAXNAMESZ]; /* name of conntrack helper */
-+ union ip_conntrack_help help;
-+};
-+
-+struct cta_exp_proto {
-+ union ip_conntrack_expect_proto proto;
-+};
-+
-+struct cta_exp_help {
-+ union ip_conntrack_expect_help help;
-+};
-+
-+/* ctnetlink multicast groups: reports any change of ctinfo,
-+ * ctstatus, or protocol state change.
-+ */
-+#define NFGRP_IPV4_CT_TCP 0x01
-+#define NFGRP_IPV4_CT_UDP 0x02
-+#define NFGRP_IPV4_CT_ICMP 0x04
-+#define NFGRP_IPV4_CT_OTHER 0x08
-+
-+#define NFGRP_IPV6_CT_TCP 0x10
-+#define NFGRP_IPV6_CT_UDP 0x20
-+#define NFGRP_IPV6_CT_ICMP 0x40
-+#define NFGRP_IPV6_CT_OTHER 0x80
-+
-+#endif /* _NFNETLINK_CONNTRACK_H */
-Index: linux-2.4.26-ct_sync/include/linux/nfnetlink.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/nfnetlink.h 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/nfnetlink.h 2004-06-28 12:58:22.000000000 +0200
-@@ -0,0 +1,158 @@
-+#ifndef _NFNETLINK_H
-+#define _NFNETLINK_H
-+#include <linux/types.h>
-+
-+/* Generic structure for encapsulation optional netfilter information.
-+ * It is reminiscent of sockaddr, but with sa_family replaced
-+ * with attribute type.
-+ * ! This should someday be put somewhere generic as now rtnetlink and
-+ * ! nfnetlink use the same attributes methods. - J. Schulist.
-+ */
-+
-+struct nfattr
-+{
-+ unsigned short nfa_len;
-+ unsigned short nfa_type;
-+};
-+
-+#define NFA_ALIGNTO 4
-+#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
-+#define NFA_OK(nfa,len) ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
-+ && (nfa)->nfa_len <= (len))
-+#define NFA_NEXT(nfa,attrlen) ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
-+ (struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
-+#define NFA_LENGTH(len) (NFA_ALIGN(sizeof(struct nfattr)) + (len))
-+#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len))
-+#define NFA_DATA(nfa) ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
-+#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
-+
-+/* General form of address family dependent message.
-+ */
-+struct nfgenmsg {
-+ unsigned char nfgen_family;
-+};
-+
-+#if 0
-+struct iptgenmsg {
-+ unsigned char iptgen_family;
-+ char iptgen_table[IPT_TABLE_MAXNAMELEN];
-+};
-+
-+struct iptmsg {
-+ unsigned char iptm_family;
-+ char iptm_table[IPT_TABLE_MAXNAMELEN];
-+ char iptm_chain[IPT_FUNCTION_MAXNAMELEN];
-+ unsigned int iptm_entry_num;
-+};
-+
-+enum iptattr_type_t
-+{
-+ IPTA_UNSPEC, /* [none] I don't know (unspecified). */
-+ IPTA_IP, /* [ipt_ip] */
-+ IPTA_NFCACHE, /* [u_int] */
-+ IPTA_COUNTERS, /* [ipt_counters] */
-+ IPTA_MATCH, /* [ipt_info] */
-+ IPTA_TARGET, /* [ipt_info] */
-+ IPTA_MAX = IPTA_TARGET
-+};
-+
-+struct ipta_info {
-+ u_int16_t size;
-+ char name[IPT_FUNCTION_MAXNAMELEN];
-+ unsigned char data[0];
-+};
-+
-+#define NFM_IPTA(n) ((struct nfattr *)(((char *)(n)) \
-+ + NLMSG_ALIGN(sizeof(struct iptmsg))))
-+
-+#endif
-+
-+#define NFM_NFA(n) ((struct nfattr *)(((char *)(n)) \
-+ + NLMSG_ALIGN(sizeof(struct nfgenmsg))))
-+#define NFM_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
-+
-+
-+#ifndef NETLINK_NETFILTER
-+#define NETLINK_NETFILTER 6
-+#endif
-+
-+/* netfilter netlink message types are split in two pieces:
-+ * 8 bit subsystem, 8bit operation.
-+ */
-+
-+#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8)
-+#define NFNL_MSG_TYPE(x) (x & 0x00ff)
-+
-+enum nfnl_subsys_id {
-+ NFNL_SUBSYS_NONE = 0,
-+ NFNL_SUBSYS_CTNETLINK,
-+ NFNL_SUBSYS_CTNETLINK_EXP,
-+ NFNL_SUBSYS_IPTNETLINK,
-+ NFNL_SUBSYS_QUEUE,
-+ NFNL_SUBSYS_ULOG,
-+ NFNL_SUBSYS_COUNT,
-+};
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/capability.h>
-+
-+struct nfnl_callback
-+{
-+ kernel_cap_t cap_required; /* capabilities required for this msg */
-+ int (*call)(struct sock *nl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp);
-+};
-+
-+struct nfnetlink_subsystem
-+{
-+ /* Internal use. */
-+ struct list_head list;
-+
-+ const char *name;
-+ __u8 subsys_id; /* nfnetlink subsystem ID */
-+ __u8 cb_count; /* number of callbacks */
-+ u_int32_t attr_count; /* number of nfattr's */
-+ struct nfnl_callback cb[0]; /* callback for individual types */
-+};
-+
-+extern void __nfa_fill(struct sk_buff *skb, int attrtype,
-+ int attrlen, const void *data);
-+#define NFA_PUT(skb, attrtype, attrlen, data) \
-+({ if (skb_tailroom(skb) < (int)NFA_SPACE(attrlen)) goto nfattr_failure; \
-+ __nfa_fill(skb, attrtype, attrlen, data); })
-+
-+extern struct semaphore nfnl_sem;
-+#define nfnl_exlock() do { } while(0)
-+#define nfnl_exunlock() do { } while(0)
-+#define nfnl_exlock_nowait() (0)
-+
-+#define nfnl_shlock() down(&nfnl_sem)
-+#define nfnl_shlock_nowait() down_trylock(&nfnl_sem)
-+
-+#ifndef CONFIG_NF_NETLINK
-+#define nfnl_shunlock() up(&nfnl_sem)
-+#else
-+#define nfnl_shunlock() do { up(&nfnl_sem); \
-+ if(nfnl && nfnl->receive_queue.qlen) \
-+ nfnl->data_ready(nfnl, 0); \
-+ } while(0)
-+#endif
-+
-+extern void nfnl_lock(void);
-+extern void nfnl_unlock(void);
-+
-+extern struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count);
-+extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n);
-+extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n);
-+
-+extern int nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
-+ struct nlmsghdr *nlh,
-+ struct nfattr *cda[]);
-+extern int nfattr_parse(struct nfattr *tb[], int maxattr,
-+ struct nfattr *nfa, int len);
-+extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
-+ int echo);
-+
-+#endif /* __KERNEL__ */
-+#endif /* _NFNETLINK_H */
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-06-28 12:58:22.000000000 +0200
-@@ -42,6 +42,17 @@
- int (*new)(struct ip_conntrack *conntrack, struct iphdr *iph,
- size_t len);
-
-+ /* check if tuples are valid for a new connection */
-+ int (*ctnl_check_tuples)(struct ip_conntrack_tuple *orig,
-+ struct ip_conntrack_tuple *reply);
-+
-+ /* check protocol data is valid */
-+ int (*ctnl_check_private)(union ip_conntrack_proto *p);
-+
-+ /* change protocol info on behalf of ctnetlink */
-+ void (*ctnl_change)(struct ip_conntrack *ct,
-+ union ip_conntrack_proto *p);
-+
- /* Called when a conntrack entry is destroyed */
- void (*destroy)(struct ip_conntrack *conntrack);
-
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-28 12:58:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-28 12:58:22.000000000 +0200
-@@ -46,6 +46,10 @@
- /* Connection is confirmed: originating packet has left box */
- IPS_CONFIRMED_BIT = 3,
- IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
-+
-+ /* Connection is destroyed (removed from lists), can not be unset. */
-+ IPS_DESTROYED_BIT = 4,
-+ IPS_DESTROYED = (1 << IPS_DESTROYED_BIT),
- };
-
- #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
-@@ -123,6 +127,9 @@
-
- /* reference count */
- atomic_t use;
-+
-+ /* unique increasing id */
-+ unsigned int id;
-
- /* expectation list for this master */
- struct list_head expected_list;
-@@ -166,6 +173,14 @@
-
- /* These are my tuples; original and reply */
- struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
-+
-+ /* ordered list member - for table dumping over netlink */
-+ struct list_head olist;
-+
-+ /* unique id (assigned when placing in hashtables) - for table dumping
-+ * over netlink */
-+ unsigned int id;
-+
-
- /* Have we seen traffic both ways yet? (bitset) */
- unsigned long status;
-@@ -241,6 +256,17 @@
-
- /* decrement reference count on an expectation */
- void ip_conntrack_expect_put(struct ip_conntrack_expect *exp);
-+
-+/* remove all unconfirmed expectations */
-+extern void ip_conntrack_remove_expectations(struct ip_conntrack *ct,
-+ int drop_refcount);
-+
-+
-+struct ip_conntrack_protocol;
-+extern int invert_tuple(struct ip_conntrack_tuple *inverse,
-+ const struct ip_conntrack_tuple *orig,
-+ const struct ip_conntrack_protocol *protocol);
-+
-
- extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
- const struct ip_conntrack_tuple *orig);
-@@ -264,13 +290,95 @@
- extern void
- ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
- void *data);
-+
-+/* returns new ip_conntrack struct or NULL */
-+extern struct ip_conntrack *
-+ip_conntrack_alloc(const struct ip_conntrack_tuple *,
-+ const struct ip_conntrack_tuple *);
-+
-+/* free conntrack structure */
-+extern void ip_conntrack_free(struct ip_conntrack *);
-+
-+/* place conntrack in hash and ordered list */
-+extern void ip_conntrack_place_in_lists(struct ip_conntrack *);
-+
-
- /* It's confirmed if it is, or has been in the hash table. */
- static inline int is_confirmed(struct ip_conntrack *ct)
- {
- return test_bit(IPS_CONFIRMED_BIT, &ct->status);
- }
-+
-+/* It is destroyed after it has been removed from hash table. */
-+static inline int is_destroyed(struct ip_conntrack *ct)
-+{
-+ return test_bit(IPS_DESTROYED_BIT, &ct->status);
-+}
-+
-
- extern unsigned int ip_conntrack_htable_size;
-+
-+enum ip_conntrack_events
-+{
-+ IPCT_NEW,
-+ IPCT_DESTROY,
-+ IPCT_STATUS,
-+ IPCT_REFRESH,
-+ IPCT_PROTOINFO,
-+ IPCT_HELPINFO,
-+ IPCT_NATINFO,
-+};
-+
-+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-+#include <linux/notifier.h>
-+
-+extern struct notifier_block *ip_conntrack_chain;
-+extern unsigned long ip_conntrack_event_cache[NR_CPUS];
-+
-+/* register notifier for conntrack events */
-+static inline int ip_conntrack_notify_register(struct notifier_block *nb)
-+{
-+ return notifier_chain_register(&ip_conntrack_chain, nb);
-+}
-+
-+static inline int ip_conntrack_notify_unregister(struct notifier_block *nb)
-+{
-+ return notifier_chain_unregister(&ip_conntrack_chain, nb);
-+}
-+
-+static inline void ip_conntrack_event(enum ip_conntrack_events event,
-+ struct ip_conntrack *ct)
-+{
-+ if (is_confirmed(ct) && !is_destroyed(ct))
-+ notifier_call_chain(&ip_conntrack_chain, 1 << event, ct);
-+}
-+
-+static inline void ip_conntrack_event_cache_init(void)
-+{
-+ ip_conntrack_event_cache[smp_processor_id()] = 0UL;
-+}
-+
-+static inline void ip_conntrack_cache_event(enum ip_conntrack_events event)
-+{
-+ ip_conntrack_event_cache[smp_processor_id()] |= 1 << event;
-+}
-+
-+static inline void ip_conntrack_do_cached_events(struct ip_conntrack *ct)
-+{
-+ unsigned long events = ip_conntrack_event_cache[smp_processor_id()];
-+
-+ if (is_confirmed(ct) && !is_destroyed(ct) && events)
-+ notifier_call_chain(&ip_conntrack_chain, events, ct);
-+}
-+#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
-+static inline int ip_conntrack_notify_register(void *nb) { return 0; }
-+static inline int ip_conntrack_notify_unregister(void *nb) { return 0; }
-+static inline void ip_conntrack_event(enum ip_conntrack_events event,
-+ struct ip_conntrack *ct) {}
-+static inline void ip_conntrack_event_cache_init(void) {}
-+static inline void ip_conntrack_cache_event(enum ip_conntrack_events event) {}
-+static inline void ip_conntrack_do_cached_events(struct ip_conntrack *ct) {}
-+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
-+
- #endif /* __KERNEL__ */
- #endif /* _IP_CONNTRACK_H */
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_helper.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2002-11-29 00:53:15.000000000 +0100
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-06-28 12:58:22.000000000 +0200
-@@ -28,6 +28,11 @@
- int (*help)(const struct iphdr *, size_t len,
- struct ip_conntrack *ct,
- enum ip_conntrack_info conntrackinfo);
-+
-+ void (*ctnl_change)(struct ip_conntrack *, union ip_conntrack_help *);
-+ void (*ctnl_new_expect)(struct ip_conntrack_expect *,
-+ union ip_conntrack_expect_proto *,
-+ union ip_conntrack_expect_help *);
- };
-
- extern int ip_conntrack_helper_register(struct ip_conntrack_helper *);
-@@ -38,8 +43,15 @@
- /* Add an expected connection: can have more than one per connection */
- extern int ip_conntrack_expect_related(struct ip_conntrack *related_to,
- struct ip_conntrack_expect *exp);
-+extern int __ip_conntrack_expect_related(struct ip_conntrack *related_to,
-+ struct ip_conntrack_expect *exp,
-+ struct ip_conntrack_expect **newp);
- extern int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
- struct ip_conntrack_tuple *newtuple);
- extern void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp);
-
-+extern struct ip_conntrack_expect *
-+__ip_ct_expect_find_tm(const struct ip_conntrack_tuple *tuple,
-+ const struct ip_conntrack_tuple *mask);
-+
- #endif /*_IP_CONNTRACK_HELPER_H*/
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-06-28 12:58:22.000000000 +0200
-@@ -33,6 +33,11 @@
- struct ip_conntrack_tuple_hash *
- ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
- const struct ip_conntrack *ignored_conntrack);
-+/* non-locked version */
-+struct ip_conntrack_tuple_hash *
-+__ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
-+ const struct ip_conntrack *ignored_conntrack);
-+
-
- extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
-
-@@ -46,6 +51,7 @@
- }
-
- extern struct list_head *ip_conntrack_hash;
-+extern struct list_head ip_conntrack_ordered_list;
- extern struct list_head ip_conntrack_expect_list;
- DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
- #endif /* _IP_CONNTRACK_CORE_H */
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-06-28 12:58:22.000000000 +0200
-@@ -186,13 +186,17 @@
- }
-
- conntrack->proto.tcp.state = newconntrack;
-+ if (newconntrack != oldtcpstate)
-+ ip_conntrack_cache_event(IPCT_PROTOINFO);
-
- /* Poor man's window tracking: record SYN/ACK for handshake check */
- if (oldtcpstate == TCP_CONNTRACK_SYN_SENT
- && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
-- && tcph->syn && tcph->ack)
-+ && tcph->syn && tcph->ack) {
- conntrack->proto.tcp.handshake_ack
- = htonl(ntohl(tcph->seq) + 1);
-+ ip_conntrack_cache_event(IPCT_PROTOINFO);
-+ }
-
- /* If only reply is a RST, we can consider ourselves not to
- have an established connection: this is a fairly common
-@@ -207,8 +211,10 @@
- if (oldtcpstate == TCP_CONNTRACK_SYN_RECV
- && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL
- && tcph->ack && !tcph->syn
-- && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)
-+ && tcph->ack_seq == conntrack->proto.tcp.handshake_ack) {
- set_bit(IPS_ASSURED_BIT, &conntrack->status);
-+ ip_conntrack_cache_event(IPCT_STATUS);
-+ }
-
- WRITE_UNLOCK(&tcp_lock);
- ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
-@@ -239,6 +245,22 @@
- return 1;
- }
-
-+static int tcp_ctnl_check_private(union ip_conntrack_proto *p)
-+{
-+ struct ip_ct_tcp *tcp = (struct ip_ct_tcp *)p;
-+ if (tcp->state >= TCP_CONNTRACK_MAX)
-+ return -EINVAL;
-+ return 0;
-+}
-+
-+static void tcp_ctnl_change(struct ip_conntrack *conntrack,
-+ union ip_conntrack_proto *p)
-+{
-+ WRITE_LOCK(&tcp_lock);
-+ memcpy(&conntrack->proto.tcp, p, sizeof(struct ip_ct_tcp));
-+ WRITE_UNLOCK(&tcp_lock);
-+}
-+
- static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp,
- struct sk_buff **pskb)
- {
-@@ -254,4 +276,5 @@
- struct ip_conntrack_protocol ip_conntrack_protocol_tcp
- = { { NULL, NULL }, IPPROTO_TCP, "tcp",
- tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
-- tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
-+ tcp_packet, tcp_new, NULL, tcp_ctnl_check_private, tcp_ctnl_change, NULL,
-+ tcp_exp_matches_pkt, NULL };
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_ftp.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_ftp.c 2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-06-28 12:58:22.000000000 +0200
-@@ -287,6 +287,7 @@
- ct_ftp_info->seq_aft_nl[dir] =
- ntohl(tcph->seq) + datalen;
- ct_ftp_info->seq_aft_nl_set[dir] = 1;
-+ ip_conntrack_cache_event(IPCT_HELPINFO);
- }
- }
- UNLOCK_BH(&ip_ftp_lock);
-@@ -382,6 +383,13 @@
- return NF_ACCEPT;
- }
-
-+static void ctnl_change(struct ip_conntrack *ct, union ip_conntrack_help *h)
-+{
-+ LOCK_BH(&ip_ftp_lock);
-+ memcpy(&ct->help, h, sizeof(ct->help));
-+ UNLOCK_BH(&ip_ftp_lock);
-+}
-+
- static struct ip_conntrack_helper ftp[MAX_PORTS];
- static char ftp_names[MAX_PORTS][10];
-
-@@ -414,6 +422,7 @@
- ftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
- ftp[i].me = ip_conntrack_ftp;
- ftp[i].help = help;
-+ ftp[i].ctnl_change = ctnl_change;
-
- tmpname = &ftp_names[i][0];
- if (ports[i] == FTP_PORT)
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:58:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-06-28 12:58:22.000000000 +0200
-@@ -503,7 +503,11 @@
-
- EXPORT_SYMBOL(ip_conntrack_protocol_register);
- EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
-+EXPORT_SYMBOL(invert_tuple);
- EXPORT_SYMBOL(invert_tuplepr);
-+EXPORT_SYMBOL(ip_conntrack_alloc);
-+EXPORT_SYMBOL(ip_conntrack_free);
-+EXPORT_SYMBOL(ip_conntrack_place_in_lists);
- EXPORT_SYMBOL(ip_conntrack_alter_reply);
- EXPORT_SYMBOL(ip_conntrack_destroyed);
- EXPORT_SYMBOL(ip_conntrack_get);
-@@ -515,16 +519,25 @@
- EXPORT_SYMBOL(__ip_ct_find_proto);
- EXPORT_SYMBOL(ip_ct_find_helper);
- EXPORT_SYMBOL(ip_conntrack_expect_related);
-+EXPORT_SYMBOL(__ip_conntrack_expect_related);
- EXPORT_SYMBOL(ip_conntrack_change_expect);
- EXPORT_SYMBOL(ip_conntrack_unexpect_related);
-+EXPORT_SYMBOL(ip_conntrack_remove_expectations);
-+EXPORT_SYMBOL(__ip_ct_expect_find_tm);
- EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
- EXPORT_SYMBOL_GPL(ip_conntrack_expect_put);
- EXPORT_SYMBOL(ip_conntrack_tuple_taken);
- EXPORT_SYMBOL(ip_ct_gather_frags);
- EXPORT_SYMBOL(ip_conntrack_htable_size);
- EXPORT_SYMBOL(ip_conntrack_expect_list);
-+EXPORT_SYMBOL(ip_conntrack_ordered_list);
- EXPORT_SYMBOL(ip_conntrack_lock);
- EXPORT_SYMBOL(ip_conntrack_hash);
- EXPORT_SYMBOL(ip_conntrack_untracked);
- EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
-+EXPORT_SYMBOL_GPL(__ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(ip_conntrack_put);
-+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-+EXPORT_SYMBOL(ip_conntrack_chain);
-+EXPORT_SYMBOL(ip_conntrack_event_cache);
-+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_irc.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_irc.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_irc.c 2004-06-28 12:58:22.000000000 +0200
-@@ -245,6 +245,24 @@
- return NF_ACCEPT;
- }
-
-+static void ctnl_change(struct ip_conntrack *ct, union ip_conntrack_help *h)
-+{
-+ LOCK_BH(&ip_irc_lock);
-+ memcpy(&ct->help, h, sizeof(ct->help));
-+ UNLOCK_BH(&ip_irc_lock);
-+}
-+
-+static void ctnl_new_expect(struct ip_conntrack_expect *exp,
-+ union ip_conntrack_expect_proto *p,
-+ union ip_conntrack_expect_help *h)
-+{
-+ if (h == NULL)
-+ return;
-+ LOCK_BH(&ip_irc_lock);
-+ memcpy(&exp->help, h, sizeof(exp->help));
-+ UNLOCK_BH(&ip_irc_lock);
-+}
-+
- static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
- static char irc_names[MAX_PORTS][10];
-
-@@ -280,6 +298,8 @@
- hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
- hlpr->me = ip_conntrack_irc;
- hlpr->help = help;
-+ hlpr->ctnl_change = ctnl_change;
-+ hlpr->ctnl_new_expect = ctnl_new_expect;
-
- tmpname = &irc_names[i][0];
- if (ports[i] == IRC_PORT)
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Config.in 2004-06-28 12:58:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in 2004-06-28 12:58:22.000000000 +0200
-@@ -4,8 +4,16 @@
- mainmenu_option next_comment
- comment ' IP: Netfilter Configuration'
-
-+tristate 'Netfilter netlink interface' CONFIG_IP_NF_NETLINK
-+
- tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP_NF_CONNTRACK
- if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
-+ bool 'Connection tracking event notifications' CONFIG_IP_NF_CONNTRACK_EVENTS
-+ if [ "$CONFIG_IP_NF_CONNTRACK" = "y" ]; then
-+ dep_tristate ' Connection tracking netlink interface' CONFIG_IP_NF_NETLINK_CONNTRACK $CONFIG_IP_NF_NETLINK
-+ else
-+ dep_tristate ' Connection tracking netlink interface' CONFIG_IP_NF_NETLINK_CONNTRACK $CONFIG_IP_NF_CONNTRACK
-+ fi
- dep_tristate ' FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
- bool ' Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
- dep_tristate ' Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Makefile 2004-06-28 12:58:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile 2004-07-08 13:42:53.000000000 +0200
-@@ -28,6 +28,15 @@
- ipfwadm-objs := $(ip_nf_compat-objs) ipfwadm_core.o
- ipchains-objs := $(ip_nf_compat-objs) ipchains_core.o
-
-+# netfilter netlink interface
-+obj-$(CONFIG_IP_NF_NETLINK) += nfnetlink.o
-+ifdef CONFIG_IP_NF_NETLINK
-+ export-objs += nfnetlink.o
-+endif
-+
-+# nfnetlink modules
-+obj-$(CONFIG_IP_NF_NETLINK_CONNTRACK) += nfnetlink_conntrack.o
-+
- # connection tracking
- obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
-
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_udp.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-06-28 12:58:22.000000000 +0200
-@@ -54,7 +54,10 @@
- if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
- ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
- /* Also, more likely to be important, and not a probe */
-- set_bit(IPS_ASSURED_BIT, &conntrack->status);
-+ if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)) {
-+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
-+ ip_conntrack_cache_event(IPCT_STATUS);
-+ }
- } else
- ip_ct_refresh(conntrack, ip_ct_udp_timeout);
-
-@@ -71,4 +74,4 @@
- struct ip_conntrack_protocol ip_conntrack_protocol_udp
- = { { NULL, NULL }, IPPROTO_UDP, "udp",
- udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
-- udp_packet, udp_new, NULL, NULL, NULL };
-+ udp_packet, udp_new, NULL, NULL, NULL, NULL, NULL, NULL };
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/nfnetlink.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/nfnetlink.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/nfnetlink.c 2004-06-28 12:58:22.000000000 +0200
-@@ -0,0 +1,354 @@
-+/* Netfilter messages via netlink socket. Allows for user space
-+ * protocol helpers and general trouble making from userspace.
-+ *
-+ * (C) 2001 by Jay Schulist <jschlst at samba.org>,
-+ * (C) 2002 by Harald Welte <laforge at gnumonks.org>
-+ *
-+ * Initial netfilter messages via netlink development funded and
-+ * generally made possible by Network Robots, Inc. (www.networkrobots.com)
-+ *
-+ * Further development of this code funded by Astaro AG (http://www.astaro.com)
-+ *
-+ * This software may be used and distributed according to the terms
-+ * of the GNU General Public License, incorporated herein by reference.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/socket.h>
-+#include <linux/kernel.h>
-+#include <linux/major.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/string.h>
-+#include <linux/sockios.h>
-+#include <linux/net.h>
-+#include <linux/fcntl.h>
-+#include <linux/skbuff.h>
-+#include <asm/uaccess.h>
-+#include <asm/system.h>
-+#include <net/sock.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <linux/list.h>
-+
-+#include <linux/netfilter.h>
-+#include <linux/netlink.h>
-+#include <linux/nfnetlink.h>
-+
-+MODULE_LICENSE("GPL");
-+
-+static char __initdata nfversion[] = "0.12";
-+
-+#if 1
-+static int nf_debug_level = 1;
-+#define nf_debug(level, format, arg...) \
-+do { \
-+ if (nf_debug_level > level) \
-+ printk(KERN_DEBUG "%s: " format, __FUNCTION__ , ## arg); \
-+} while(0)
-+#else
-+#define nf_debug(level, format, arg...)
-+#endif
-+
-+static struct sock *nfnl = NULL;
-+static LIST_HEAD(subsys_list);
-+static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
-+DECLARE_MUTEX(nfnl_sem);
-+
-+void nfnl_lock(void)
-+{
-+ nfnl_shlock();
-+ nfnl_exlock();
-+}
-+
-+void nfnl_unlock(void)
-+{
-+ nfnl_exunlock();
-+ nfnl_shunlock();
-+}
-+
-+struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count)
-+{
-+ int size;
-+ struct nfnetlink_subsystem *ss;
-+
-+ size = sizeof(struct nfnetlink_subsystem)
-+ + (cb_count * sizeof(struct nfnl_callback));
-+
-+ ss = kmalloc(size, GFP_KERNEL);
-+ if (!ss)
-+ return NULL;
-+ memset(ss, 0, size);
-+
-+ return ss;
-+}
-+
-+int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
-+{
-+ MOD_INC_USE_COUNT;
-+
-+ nf_debug(0, "registering subsystem ID %u\n", n->subsys_id);
-+
-+ nfnl_lock();
-+ list_add(&n->list, &subsys_list);
-+ subsys_table[n->subsys_id] = n;
-+ nfnl_unlock();
-+
-+ return 0;
-+}
-+
-+int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
-+{
-+ nf_debug(0, "unregistering subsystem ID %u\n", n->subsys_id);
-+
-+ nfnl_lock();
-+ subsys_table[n->subsys_id] = NULL;
-+ list_del(&n->list);
-+ nfnl_unlock();
-+
-+ MOD_DEC_USE_COUNT;
-+
-+ return 0;
-+}
-+
-+struct nfnl_callback *nfnetlink_find_client(u_int16_t nlmsg_type)
-+{
-+ struct nfnetlink_subsystem *ss;
-+ u_int8_t subsys_id = NFNL_SUBSYS_ID(nlmsg_type);
-+ u_int8_t type = NFNL_MSG_TYPE(nlmsg_type);
-+
-+ if (subsys_id >= NFNL_SUBSYS_COUNT
-+ || subsys_table[subsys_id] == NULL)
-+ return NULL;
-+
-+ ss = subsys_table[subsys_id];
-+
-+ if (type >= ss->cb_count) {
-+ nf_debug(0, "msgtype %u >= %u, returning\n", type,
-+ ss->cb_count);
-+ return NULL;
-+ }
-+
-+ return &ss->cb[type];
-+}
-+
-+void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
-+ const void *data)
-+{
-+ struct nfattr *nfa;
-+ int size = NFA_LENGTH(attrlen);
-+
-+ nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
-+ nfa->nfa_type = attrtype;
-+ nfa->nfa_len = size;
-+ memcpy(NFA_DATA(nfa), data, attrlen);
-+}
-+
-+int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
-+{
-+ memset(tb, 0, sizeof(struct nfattr *) * maxattr);
-+
-+ while (NFA_OK(nfa, len)) {
-+ unsigned flavor = nfa->nfa_type;
-+ if (flavor && flavor <= maxattr)
-+ tb[flavor-1] = nfa;
-+ nfa = NFA_NEXT(nfa, len);
-+ }
-+
-+ return 0;
-+}
-+
-+/**
-+ * nfnetlink_check_attributes - check and parse nfnetlink attributes
-+ *
-+ * subsys: nfnl subsystem for which this message is to be parsed
-+ * nlmsghdr: netlink message to be checked/parsed
-+ * cda: array of pointers, needs to be at least subsys->attr_count big
-+ *
-+ */
-+int
-+nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
-+ struct nlmsghdr *nlh, struct nfattr *cda[])
-+{
-+ int min_len;
-+
-+ memset(cda, 0, sizeof(struct nfattr *) * subsys->attr_count);
-+
-+ /* check attribute lengths. */
-+ min_len = sizeof(struct nfgenmsg);
-+ if (nlh->nlmsg_len < min_len)
-+ return -EINVAL;
-+
-+ if (nlh->nlmsg_len > min_len) {
-+ struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
-+ int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
-+
-+ while (NFA_OK(attr, attrlen)) {
-+ unsigned flavor = attr->nfa_type;
-+ if (flavor) {
-+ if (flavor > subsys->attr_count)
-+ return -EINVAL;
-+ cda[flavor - 1] = attr;
-+ }
-+ attr = NFA_NEXT(attr, attrlen);
-+ }
-+ } else
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
-+{
-+ int allocation = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
-+ int err = 0;
-+
-+ NETLINK_CB(skb).dst_groups = group;
-+ if (echo)
-+ atomic_inc(&skb->users);
-+ netlink_broadcast(nfnl, skb, pid, group, allocation);
-+ if (echo)
-+ err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
-+
-+ return err;
-+}
-+
-+/* Process one complete nfnetlink message. */
-+static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct nfnl_callback *nc;
-+ int type, err = 0;
-+
-+ nf_debug(0, "entered; subsys=%u, msgtype=%u\n",
-+ NFNL_SUBSYS_ID(nlh->nlmsg_type),
-+ NFNL_MSG_TYPE(nlh->nlmsg_type));
-+
-+ /* Only requests are handled by kernel now. */
-+ if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
-+ nf_debug(0, "received non-request message\n");
-+ return 0;
-+ }
-+
-+ /* Unknown message: reply with EINVAL */
-+ type = nlh->nlmsg_type;
-+ if (NFNL_SUBSYS_ID(type) > NFNL_SUBSYS_COUNT) {
-+ nf_debug(0, "subsys_id > subsys_count\n");
-+ goto err_inval;
-+ }
-+
-+ /* All the messages must have at least 1 byte length */
-+ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
-+ nf_debug(0, "received message was too short\n");
-+ return 0;
-+ }
-+
-+ nc = nfnetlink_find_client(type);
-+ if (!nc) {
-+ nf_debug(0, "unable to find client for type %d\n", type);
-+ goto err_inval;
-+ }
-+
-+ if (nc->cap_required &&
-+ !cap_raised(NETLINK_CB(skb).eff_cap, nc->cap_required)) {
-+ nf_debug(0, "permission denied for type %d\n", type);
-+ *errp = -EPERM;
-+ return -1;
-+ }
-+
-+ err = nc->call(nfnl, skb, nlh, errp);
-+ *errp = err;
-+ return err;
-+
-+err_inval:
-+ *errp = -EINVAL;
-+ return -1;
-+}
-+
-+/* Process one packet of messages. */
-+static inline int nfnetlink_rcv_skb(struct sk_buff *skb)
-+{
-+ int err;
-+ struct nlmsghdr *nlh;
-+
-+ while (skb->len >= NLMSG_SPACE(0)) {
-+ u32 rlen;
-+
-+ nlh = (struct nlmsghdr *)skb->data;
-+ if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
-+ || skb->len < nlh->nlmsg_len)
-+ return 0;
-+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
-+ if (rlen > skb->len)
-+ rlen = skb->len;
-+ if (nfnetlink_rcv_msg(skb, nlh, &err)) {
-+ if (!err)
-+ return -1;
-+ netlink_ack(skb, nlh, err);
-+ } else
-+ if (nlh->nlmsg_flags & NLM_F_ACK)
-+ netlink_ack(skb, nlh, 0);
-+ skb_pull(skb, rlen);
-+ }
-+
-+ return 0;
-+}
-+
-+static void nfnetlink_rcv(struct sock *sk, int len)
-+{
-+ do {
-+ struct sk_buff *skb;
-+
-+ if (nfnl_shlock_nowait())
-+ return;
-+
-+ while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
-+ if (nfnetlink_rcv_skb(skb)) {
-+ if (skb->len)
-+ skb_queue_head(&sk->receive_queue, skb);
-+ else
-+ kfree_skb(skb);
-+ break;
-+ }
-+ kfree_skb(skb);
-+ }
-+
-+ up(&nfnl_sem);
-+ } while(nfnl && nfnl->receive_queue.qlen);
-+}
-+
-+void __exit nfnetlink_exit(void)
-+{
-+ printk("Netfilter removing netlink socket.\n");
-+ sock_release(nfnl->socket);
-+ return;
-+}
-+
-+int __init nfnetlink_init(void)
-+{
-+ int i;
-+ printk("Netfilter messages via NETLINK v%s.\n", nfversion);
-+
-+ for (i = 0; i < NFNL_SUBSYS_COUNT; i++)
-+ subsys_table[i] = NULL;
-+
-+ nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv);
-+ if (!nfnl) {
-+ printk(KERN_ERR "cannot initialize nfnetlink!\n");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+module_init(nfnetlink_init);
-+module_exit(nfnetlink_exit);
-+
-+EXPORT_SYMBOL_GPL(nfnetlink_subsys_alloc);
-+EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
-+EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
-+EXPORT_SYMBOL_GPL(nfnetlink_check_attributes);
-+EXPORT_SYMBOL_GPL(nfnetlink_send);
-+EXPORT_SYMBOL_GPL(__nfa_fill);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_core.c 2004-06-14 14:52:11.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_core.c 2004-06-28 12:58:22.000000000 +0200
-@@ -632,6 +632,8 @@
- IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
- }
-
-+ ip_conntrack_event(IPCT_NATINFO, conntrack);
-+
- /* If there's a helper, assign it; based on new tuple. */
- if (!conntrack->master)
- info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:58:18.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c 2004-06-28 12:58:22.000000000 +0200
-@@ -11,6 +11,9 @@
- * 16 Jul 2002: Harald Welte <laforge at gnumonks.org>
- * - add usage/reference counts to ip_conntrack_expect
- * - export ip_conntrack[_expect]_{find_get,put} functions
-+ * 26 May 2003: Patrick McHardy <kaber at trash.net>
-+ * - event notifications
-+ * - restructured/exported some functions for ctnetlink
- * */
-
- #include <linux/version.h>
-@@ -30,6 +33,7 @@
- #include <linux/slab.h>
- #include <linux/random.h>
- #include <linux/jhash.h>
-+#include <linux/notifier.h>
- /* For ERR_PTR(). Yeah, I know... --RR */
- #include <linux/fs.h>
-
-@@ -66,6 +70,15 @@
- static kmem_cache_t *ip_conntrack_cachep;
- struct ip_conntrack ip_conntrack_untracked;
-
-+/* for ctnetlink */
-+LIST_HEAD(ip_conntrack_ordered_list);
-+static unsigned int ip_conntrack_next_id = 1;
-+static unsigned int ip_conntrack_exp_next_id = 1;
-+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-+struct notifier_block *ip_conntrack_chain = NULL;
-+unsigned long ip_conntrack_event_cache[NR_CPUS];
-+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
-+
- extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
-
- static inline int proto_cmpfn(const struct ip_conntrack_protocol *curr,
-@@ -149,7 +162,7 @@
- return ret;
- }
-
--static int
-+int
- invert_tuple(struct ip_conntrack_tuple *inverse,
- const struct ip_conntrack_tuple *orig,
- const struct ip_conntrack_protocol *protocol)
-@@ -172,6 +185,17 @@
- return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask);
- }
-
-+/* Compare expectation tuple/mask with given ones. */
-+static inline int expect_cmp_tm(const struct ip_conntrack_expect *i,
-+ const struct ip_conntrack_tuple *tuple,
-+ const struct ip_conntrack_tuple *mask)
-+{
-+// this is wrong, a write locked ip_conntrack_lock is sufficent
-+// MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock);
-+ return ip_ct_tuple_equal(&i->tuple, tuple) &&
-+ ip_ct_tuple_equal(&i->mask, mask);
-+}
-+
- static void
- destroy_expect(struct ip_conntrack_expect *exp)
- {
-@@ -202,6 +226,16 @@
- struct ip_conntrack_expect *, tuple);
- }
-
-+inline struct ip_conntrack_expect *
-+__ip_ct_expect_find_tm(const struct ip_conntrack_tuple *tuple,
-+ const struct ip_conntrack_tuple *mask)
-+{
-+ MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-+ MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock);
-+ return LIST_FIND(&ip_conntrack_expect_list, expect_cmp_tm,
-+ struct ip_conntrack_expect *, tuple, mask);
-+}
-+
- /* Find a expectation corresponding to a tuple. */
- struct ip_conntrack_expect *
- ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
-@@ -258,12 +292,13 @@
- }
-
- /* delete all unconfirmed expectations for this conntrack */
--static void remove_expectations(struct ip_conntrack *ct, int drop_refcount)
-+void
-+ip_conntrack_remove_expectations(struct ip_conntrack *ct, int drop_refcount)
- {
- struct list_head *exp_entry, *next;
- struct ip_conntrack_expect *exp;
-
-- DEBUGP("remove_expectations(%p)\n", ct);
-+ DEBUGP("ip_conntrack_remove_expectations(%p,%d)\n", ct, drop_refcount);
-
- list_for_each_safe(exp_entry, next, &ct->sibling_list) {
- exp = list_entry(exp_entry, struct ip_conntrack_expect,
-@@ -272,7 +307,7 @@
- /* we skip established expectations, as we want to delete
- * the un-established ones only */
- if (exp->sibling) {
-- DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
-+ DEBUGP("ip_conntrack_remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
- if (drop_refcount) {
- /* Indicate that this expectations parent is dead */
- ip_conntrack_put(exp->expectant);
-@@ -301,9 +336,17 @@
- hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
- LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
-+ LIST_DELETE(&ip_conntrack_ordered_list, &ct->olist);
-
- /* Destroy all un-established, pending expectations */
-- remove_expectations(ct, 1);
-+ ip_conntrack_remove_expectations(ct, 1);
-+}
-+
-+inline void
-+ip_conntrack_free(struct ip_conntrack *conntrack)
-+{
-+ kmem_cache_free(ip_conntrack_cachep, conntrack);
-+ atomic_dec(&ip_conntrack_count);
- }
-
- static void
-@@ -346,16 +389,17 @@
- ip_conntrack_put(master);
-
- DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
-- kmem_cache_free(ip_conntrack_cachep, ct);
-- atomic_dec(&ip_conntrack_count);
-+ ip_conntrack_free(ct);
- }
-
- static void death_by_timeout(unsigned long ul_conntrack)
- {
- struct ip_conntrack *ct = (void *)ul_conntrack;
-
-+ ip_conntrack_event(IPCT_DESTROY, ct);
- WRITE_LOCK(&ip_conntrack_lock);
- clean_from_lists(ct);
-+ set_bit(IPS_DESTROYED_BIT, &ct->status);
- WRITE_UNLOCK(&ip_conntrack_lock);
- ip_conntrack_put(ct);
- }
-@@ -385,6 +429,17 @@
- return h;
- }
-
-+inline struct ip_conntrack_tuple_hash *
-+__ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
-+ const struct ip_conntrack *ignored_conntrack)
-+{
-+ struct ip_conntrack_tuple_hash *h;
-+ h = __ip_conntrack_find(tuple, ignored_conntrack);
-+ if (h)
-+ atomic_inc(&h->ctrack->ct_general.use);
-+ return h;
-+}
-+
- /* Find a connection corresponding to a tuple. */
- struct ip_conntrack_tuple_hash *
- ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
-@@ -393,9 +448,7 @@
- struct ip_conntrack_tuple_hash *h;
-
- READ_LOCK(&ip_conntrack_lock);
-- h = __ip_conntrack_find(tuple, ignored_conntrack);
-- if (h)
-- atomic_inc(&h->ctrack->ct_general.use);
-+ h = __ip_conntrack_find_get(tuple, ignored_conntrack);
- READ_UNLOCK(&ip_conntrack_lock);
-
- return h;
-@@ -422,6 +475,21 @@
- return NULL;
- }
-
-+void inline
-+ip_conntrack_place_in_lists(struct ip_conntrack *conntrack)
-+{
-+ struct ip_conntrack_tuple_hash *h;
-+
-+ MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
-+
-+ conntrack->id = ip_conntrack_next_id++;
-+ list_add_tail(&conntrack->olist, &ip_conntrack_ordered_list);
-+ h = &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
-+ list_prepend(&ip_conntrack_hash[hash_conntrack(&h->tuple)], h);
-+ h = &conntrack->tuplehash[IP_CT_DIR_REPLY];
-+ list_prepend(&ip_conntrack_hash[hash_conntrack(&h->tuple)], h);
-+}
-+
- /* Confirm a connection given skb->nfct; places it in hash table */
- int
- __ip_conntrack_confirm(struct nf_ct_info *nfct)
-@@ -464,10 +532,7 @@
- conntrack_tuple_cmp,
- struct ip_conntrack_tuple_hash *,
- &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) {
-- list_prepend(&ip_conntrack_hash[hash],
-- &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
-- list_prepend(&ip_conntrack_hash[repl_hash],
-- &ct->tuplehash[IP_CT_DIR_REPLY]);
-+ ip_conntrack_place_in_lists(ct);
- /* Timer relative to confirmation time, not original
- setting time, otherwise we'd get timer wrap in
- weird delay cases. */
-@@ -476,6 +541,7 @@
- atomic_inc(&ct->ct_general.use);
- set_bit(IPS_CONFIRMED_BIT, &ct->status);
- WRITE_UNLOCK(&ip_conntrack_lock);
-+ ip_conntrack_event(IPCT_NEW, ct);
- return NF_ACCEPT;
- }
-
-@@ -632,18 +698,12 @@
- tuple);
- }
-
--/* Allocate a new conntrack: we return -ENOMEM if classification
-- failed due to stress. Otherwise it really is unclassifiable. */
--static struct ip_conntrack_tuple_hash *
--init_conntrack(const struct ip_conntrack_tuple *tuple,
-- struct ip_conntrack_protocol *protocol,
-- struct sk_buff *skb)
-+struct ip_conntrack *
-+ip_conntrack_alloc(const struct ip_conntrack_tuple *orig,
-+ const struct ip_conntrack_tuple *reply)
- {
-- struct ip_conntrack *conntrack;
-- struct ip_conntrack_tuple repl_tuple;
-- size_t hash;
-- struct ip_conntrack_expect *expected;
-- int i;
-+ struct ip_conntrack *ct;
-+ unsigned int hash, i;
- static unsigned int drop_next = 0;
-
- if (!ip_conntrack_hash_rnd_initted) {
-@@ -651,7 +711,7 @@
- ip_conntrack_hash_rnd_initted = 1;
- }
-
-- hash = hash_conntrack(tuple);
-+ hash = hash_conntrack(orig);
-
- if (ip_conntrack_max &&
- atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
-@@ -664,43 +724,61 @@
- && !early_drop(&ip_conntrack_hash[hash])) {
- if (net_ratelimit())
- printk(KERN_WARNING
-- "ip_conntrack: table full, dropping"
-- " packet.\n");
-- return ERR_PTR(-ENOMEM);
-+ "ip_conntrack: table full.\n");
-+ return NULL;
- }
- }
-
-+ ct = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
-+ if (!ct)
-+ return NULL;
-+
-+ memset(ct, 0, sizeof(*ct));
-+ atomic_set(&ct->ct_general.use, 1);
-+ ct->ct_general.destroy = destroy_conntrack;
-+ ct->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = ct;
-+ ct->tuplehash[IP_CT_DIR_REPLY].ctrack = ct;
-+ memcpy(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, reply, sizeof(*reply));
-+ memcpy(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, orig, sizeof(*orig));
-+ for (i=0; i < IP_CT_NUMBER; i++)
-+ ct->infos[i].master = &ct->ct_general;
-+
-+ /* Don't set timer yet: wait for confirmation */
-+ init_timer(&ct->timeout);
-+ ct->timeout.data = (unsigned long)ct;
-+ ct->timeout.function = death_by_timeout;
-+
-+ INIT_LIST_HEAD(&ct->sibling_list);
-+ atomic_inc(&ip_conntrack_count);
-+ return ct;
-+}
-+
-+/* Allocate a new conntrack: we return -ENOMEM if classification
-+ * failed due to stress. Otherwise it really is unclassifiable. */
-+static struct ip_conntrack_tuple_hash *
-+init_conntrack(const struct ip_conntrack_tuple *tuple,
-+ struct ip_conntrack_protocol *protocol,
-+ struct sk_buff *skb)
-+{
-+ struct ip_conntrack *conntrack;
-+ struct ip_conntrack_tuple repl_tuple;
-+ struct ip_conntrack_expect *expected;
-+
- if (!invert_tuple(&repl_tuple, tuple, protocol)) {
- DEBUGP("Can't invert tuple.\n");
- return NULL;
- }
-
-- conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
-+ conntrack = ip_conntrack_alloc(tuple, &repl_tuple);
- if (!conntrack) {
- DEBUGP("Can't allocate conntrack.\n");
- return ERR_PTR(-ENOMEM);
- }
--
-- memset(conntrack, 0, sizeof(*conntrack));
-- atomic_set(&conntrack->ct_general.use, 1);
-- conntrack->ct_general.destroy = destroy_conntrack;
-- conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
-- conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
-- conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
-- conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
-- for (i=0; i < IP_CT_NUMBER; i++)
-- conntrack->infos[i].master = &conntrack->ct_general;
--
-+
- if (!protocol->new(conntrack, skb->nh.iph, skb->len)) {
-- kmem_cache_free(ip_conntrack_cachep, conntrack);
-+ ip_conntrack_free(conntrack);
- return NULL;
- }
-- /* Don't set timer yet: wait for confirmation */
-- init_timer(&conntrack->timeout);
-- conntrack->timeout.data = (unsigned long)conntrack;
-- conntrack->timeout.function = death_by_timeout;
--
-- INIT_LIST_HEAD(&conntrack->sibling_list);
-
- WRITE_LOCK(&ip_conntrack_lock);
- /* Need finding and deleting of expected ONLY if we win race */
-@@ -742,7 +820,6 @@
- expected->expectant->expecting--;
- nf_conntrack_get(&master_ct(conntrack)->infos[0]);
- }
-- atomic_inc(&ip_conntrack_count);
- WRITE_UNLOCK(&ip_conntrack_lock);
-
- if (expected && expected->expectfn)
-@@ -827,6 +904,8 @@
- /* FIXME: Do this right please. --RR */
- (*pskb)->nfcache |= NFC_UNKNOWN;
-
-+ ip_conntrack_event_cache_init();
-+
- /* Doesn't cover locally-generated broadcast, so not worth it. */
- #if 0
- /* Ignore broadcast: no `connection'. */
-@@ -881,8 +960,12 @@
- return NF_ACCEPT;
- }
- }
-- if (set_reply)
-+ if (set_reply && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
- set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
-+ ip_conntrack_cache_event(IPCT_STATUS);
-+ }
-+
-+ ip_conntrack_do_cached_events(ct);
-
- return ret;
- }
-@@ -941,17 +1024,14 @@
- }
-
- /* Add a related connection. */
--int ip_conntrack_expect_related(struct ip_conntrack *related_to,
-- struct ip_conntrack_expect *expect)
-+inline int __ip_conntrack_expect_related(struct ip_conntrack *related_to,
-+ struct ip_conntrack_expect *expect,
-+ struct ip_conntrack_expect **newp)
- {
- struct ip_conntrack_expect *old, *new;
- int ret = 0;
-
-- WRITE_LOCK(&ip_conntrack_lock);
-- /* Because of the write lock, no reader can walk the lists,
-- * so there is no need to use the tuple lock too */
--
-- DEBUGP("ip_conntrack_expect_related %p\n", related_to);
-+ DEBUGP("__ip_conntrack_expect_related %p\n", related_to);
- DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
- DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
-
-@@ -974,16 +1054,13 @@
- }
- }
-
-- if (old) {
-- WRITE_UNLOCK(&ip_conntrack_lock);
-+ if (old)
- return -EEXIST;
-- }
- } else if (related_to->helper->max_expected &&
- related_to->expecting >= related_to->helper->max_expected) {
- /* old == NULL */
- if (!(related_to->helper->flags &
- IP_CT_HELPER_F_REUSE_EXPECT)) {
-- WRITE_UNLOCK(&ip_conntrack_lock);
- if (net_ratelimit())
- printk(KERN_WARNING
- "ip_conntrack: max number of expected "
-@@ -1023,7 +1100,6 @@
- } else if (LIST_FIND(&ip_conntrack_expect_list, expect_clash,
- struct ip_conntrack_expect *, &expect->tuple,
- &expect->mask)) {
-- WRITE_UNLOCK(&ip_conntrack_lock);
- DEBUGP("expect_related: busy!\n");
- return -EBUSY;
- }
-@@ -1031,7 +1107,6 @@
- new = (struct ip_conntrack_expect *)
- kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
- if (!new) {
-- WRITE_UNLOCK(&ip_conntrack_lock);
- DEBUGP("expect_relaed: OOM allocating expect\n");
- return -ENOMEM;
- }
-@@ -1046,17 +1121,38 @@
- list_add_tail(&new->expected_list, &related_to->sibling_list);
- /* add to global list of expectations */
- list_prepend(&ip_conntrack_expect_list, &new->list);
-- /* add and start timer if required */
-+ /* inititalize timer */
-+ init_timer(&new->timeout);
-+ new->timeout.data = (unsigned long)new;
-+ new->timeout.function = expectation_timed_out;
-+
-+ related_to->expecting++;
-+
-+ *newp = new;
-+ return ret;
-+}
-+/* Add a related connection. */
-+int ip_conntrack_expect_related(struct ip_conntrack *related_to,
-+ struct ip_conntrack_expect *expect)
-+{
-+ struct ip_conntrack_expect *new;
-+ int ret = 0;
-+
-+ /* Because of the write lock, no reader can walk the lists,
-+ * so there is no need to use the tuple lock too */
-+ WRITE_LOCK(&ip_conntrack_lock);
-+
-+ ret = __ip_conntrack_expect_related(related_to, expect, &new);
-+ if (ret < 0)
-+ goto out;
-+
- if (related_to->helper->timeout) {
-- init_timer(&new->timeout);
-- new->timeout.data = (unsigned long)new;
-- new->timeout.function = expectation_timed_out;
-- new->timeout.expires = jiffies +
-- related_to->helper->timeout * HZ;
-+ new->timeout.expires = jiffies +
-+ related_to->helper->timeout * HZ;
- add_timer(&new->timeout);
- }
-- related_to->expecting++;
-
-+out:
- WRITE_UNLOCK(&ip_conntrack_lock);
-
- return ret;
-@@ -1145,9 +1241,10 @@
- {
- if (i->ctrack->helper == me) {
- /* Get rid of any expected. */
-- remove_expectations(i->ctrack, 0);
-+ ip_conntrack_remove_expectations(i->ctrack, 0);
- /* And *then* set helper to NULL */
- i->ctrack->helper = NULL;
-+ ip_conntrack_event(IPCT_HELPINFO, i->ctrack);
- }
- return 0;
- }
-@@ -1182,11 +1279,12 @@
- /* If not in hash table, timer will not be active yet */
- if (!is_confirmed(ct))
- ct->timeout.expires = extra_jiffies;
-- else {
-+ else if (abs(jiffies + extra_jiffies - ct->timeout.expires) >= HZ) {
- /* Need del_timer for race avoidance (may already be dying). */
- if (del_timer(&ct->timeout)) {
- ct->timeout.expires = jiffies + extra_jiffies;
- add_timer(&ct->timeout);
-+ ip_conntrack_cache_event(IPCT_REFRESH);
- }
- }
- WRITE_UNLOCK(&ip_conntrack_lock);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-06-28 12:58:22.000000000 +0200
-@@ -14,6 +14,13 @@
- #define DEBUGP(format, args...)
- #endif
-
-+static u_int8_t valid_new[] = {
-+ [ICMP_ECHO] = 1,
-+ [ICMP_TIMESTAMP] = 1,
-+ [ICMP_INFO_REQUEST] = 1,
-+ [ICMP_ADDRESS] = 1
-+};
-+
- static int icmp_pkt_to_tuple(const void *datah, size_t datalen,
- struct ip_conntrack_tuple *tuple)
- {
-@@ -82,6 +89,7 @@
- ct->timeout.function((unsigned long)ct);
- } else {
- atomic_inc(&ct->proto.icmp.count);
-+ ip_conntrack_cache_event(IPCT_PROTOINFO);
- ip_ct_refresh(ct, ip_ct_icmp_timeout);
- }
-
-@@ -92,12 +100,6 @@
- static int icmp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
- {
-- static u_int8_t valid_new[]
-- = { [ICMP_ECHO] = 1,
-- [ICMP_TIMESTAMP] = 1,
-- [ICMP_INFO_REQUEST] = 1,
-- [ICMP_ADDRESS] = 1 };
--
- if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
- || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
- /* Can't create a new ICMP `conn' with this. */
-@@ -110,7 +112,25 @@
- return 1;
- }
-
-+static int icmp_ctnl_check_tuples(struct ip_conntrack_tuple *orig,
-+ struct ip_conntrack_tuple *reply)
-+{
-+ unsigned int type = orig->dst.u.icmp.type;
-+
-+ if (type >= sizeof(valid_new) || !valid_new[type])
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static void icmp_ctnl_change(struct ip_conntrack *conntrack,
-+ union ip_conntrack_proto *p)
-+{
-+ memcpy(&conntrack->proto.icmp, p, sizeof(struct ip_ct_icmp));
-+}
-+
- struct ip_conntrack_protocol ip_conntrack_protocol_icmp
- = { { NULL, NULL }, IPPROTO_ICMP, "icmp",
- icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
-- icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
-+ icmp_print_conntrack, icmp_packet, icmp_new,
-+ icmp_ctnl_check_tuples, NULL, icmp_ctnl_change, NULL, NULL, NULL };
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_generic.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2003-11-28 19:26:21.000000000 +0100
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-06-28 12:58:22.000000000 +0200
-@@ -57,5 +57,6 @@
- struct ip_conntrack_protocol ip_conntrack_generic_protocol
- = { { NULL, NULL }, 0, "unknown",
- generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
-- generic_print_conntrack, established, new, NULL, NULL, NULL };
-+ generic_print_conntrack, established, new, NULL, NULL, NULL, NULL,
-+ NULL, NULL };
-
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/nfnetlink_conntrack.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/nfnetlink_conntrack.c 2004-06-16 09:19:51.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/nfnetlink_conntrack.c 2004-06-28 12:58:22.000000000 +0200
-@@ -0,0 +1,1252 @@
-+/* Connection tracking via netlink socket. Allows for user space
-+ * protocol helpers and general trouble making from userspace.
-+ *
-+ * (C) 2001 by Jay Schulist <jschlst at samba.org>
-+ * (C) 2002 by Harald Welte <laforge at gnumonks.org>
-+ * (C) 2003 by Patrick Mchardy <kaber at trash.net>,
-+ * Harald Welte <laforge at gnumonks.org>
-+ *
-+ * Initial connection tracking via netlink development funded and
-+ * generally made possible by Network Robots, Inc. (www.networkrobots.com)
-+ *
-+ * Further development of this code funded by Astaro AG (http://www.astaro.com)
-+ *
-+ * This software may be used and distributed according to the terms
-+ * of the GNU General Public License, incorporated herein by reference.
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/socket.h>
-+#include <linux/kernel.h>
-+#include <linux/major.h>
-+#include <linux/sched.h>
-+#include <linux/timer.h>
-+#include <linux/string.h>
-+#include <linux/sockios.h>
-+#include <linux/net.h>
-+#include <linux/fcntl.h>
-+#include <linux/skbuff.h>
-+#include <asm/uaccess.h>
-+#include <asm/system.h>
-+#include <net/sock.h>
-+#include <linux/init.h>
-+#include <linux/netlink.h>
-+#include <linux/spinlock.h>
-+#include <linux/notifier.h>
-+#include <linux/rtnetlink.h>
-+
-+#include <linux/netfilter.h>
-+#include <linux/netfilter_ipv4.h>
-+#include <linux/netfilter_ipv4/ip_tables.h>
-+#include <linux/netfilter_ipv4/ip_conntrack.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
-+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-+
-+#include <linux/nfnetlink.h>
-+#include <linux/nfnetlink_conntrack.h>
-+
-+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
-+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
-+#include <linux/netfilter_ipv4/listhelp.h>
-+
-+MODULE_LICENSE("GPL");
-+
-+static char __initdata ctversion[] = "0.12";
-+
-+#if 1
-+static int ct_debug_level = 1;
-+#define ct_debug(level, format, arg...) \
-+do { \
-+ if(ct_debug_level > level) \
-+ printk(KERN_DEBUG "%s: " format, __FUNCTION__ , ## arg); \
-+} while(0)
-+/* FIXME: this define is just needed for DUMP_TUPLE */
-+#define DEBUGP(format, args...) ct_debug(0, format, ## args)
-+#else
-+#define ct_debug(level, format, arg...)
-+#define DEBUGP(format, args...)
-+#endif
-+
-+static struct nfnetlink_subsystem *ctnl_subsys;
-+
-+
-+static inline int
-+ctnetlink_dump_tuples(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+ NFA_PUT(skb, CTA_ORIG, sizeof(struct ip_conntrack_tuple),
-+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-+ NFA_PUT(skb, CTA_RPLY, sizeof(struct ip_conntrack_tuple),
-+ &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+ NFA_PUT(skb, CTA_STATUS, sizeof(ct->status), &ct->status);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_dump_timeout(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+ unsigned long timeout = (ct->timeout.expires - jiffies) / HZ;
-+
-+ NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+ struct cta_proto cp;
-+
-+ cp.num_proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
-+ memcpy(&cp.proto, &ct->proto, sizeof(cp.proto));
-+ NFA_PUT(skb, CTA_PROTOINFO, sizeof(cp), &cp);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+ struct ip_conntrack_helper *h = ct->helper;
-+ struct cta_help ch;
-+
-+ if (h == NULL)
-+ memset(&ch, 0, sizeof(struct cta_help));
-+ else {
-+ strncpy((char *)&ch.name, h->name, sizeof(ch.name));
-+ memcpy(&ch.help, &ct->help, sizeof(ch.help));
-+ }
-+ NFA_PUT(skb, CTA_HELPINFO, sizeof(ch), &ch);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_dump_natinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+#ifdef CONFIG_IP_NF_NAT_NEEDED
-+ const struct ip_nat_info *info = &ct->nat.info;
-+ struct cta_nat cn;
-+
-+ if (!info->initialized || !info->num_manips)
-+ return 0;
-+
-+ cn.num_manips = info->num_manips;
-+ memcpy(&cn.manips, &info->manips,
-+ info->num_manips * sizeof(struct ip_nat_info_manip));
-+ NFA_PUT(skb, CTA_NATINFO, sizeof(struct cta_nat), &cn);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+static inline int
-+ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
-+{
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
-+ int event, int nowait,
-+ const struct ip_conntrack *ct)
-+{
-+ struct nlmsghdr *nlh;
-+ struct nfgenmsg *nfmsg;
-+ unsigned char *b;
-+
-+ b = skb->tail;
-+
-+ event |= NFNL_SUBSYS_CTNETLINK << 8;
-+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
-+ nfmsg = NLMSG_DATA(nlh);
-+
-+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
-+ nfmsg->nfgen_family = AF_INET;
-+
-+ if (ctnetlink_dump_tuples(skb, ct) < 0 ||
-+ ctnetlink_dump_status(skb, ct) < 0 ||
-+ ctnetlink_dump_timeout(skb, ct) < 0 ||
-+ ctnetlink_dump_protoinfo(skb, ct) < 0 ||
-+ ctnetlink_dump_helpinfo(skb, ct) < 0 ||
-+ ctnetlink_dump_natinfo(skb, ct) < 0 ||
-+ ctnetlink_dump_mark(skb, ct) < 0)
-+ goto nfattr_failure;
-+
-+ nlh->nlmsg_len = skb->tail - b;
-+ return skb->len;
-+
-+nlmsg_failure:
-+nfattr_failure:
-+ skb_trim(skb, b - skb->data);
-+ return -1;
-+}
-+
-+static inline unsigned int
-+ctnetlink_get_mcgroups(struct ip_conntrack *ct)
-+{
-+ unsigned int groups;
-+ int proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
-+
-+ switch (proto) {
-+ case IPPROTO_TCP:
-+ groups = NFGRP_IPV4_CT_TCP;
-+ break;
-+ case IPPROTO_UDP:
-+ groups = NFGRP_IPV4_CT_UDP;
-+ break;
-+ case IPPROTO_ICMP:
-+ groups = NFGRP_IPV4_CT_ICMP;
-+ break;
-+ default:
-+ groups = NFGRP_IPV4_CT_OTHER;
-+ break;
-+ }
-+
-+ return groups;
-+}
-+
-+#define EVENT(m,e) ((m) & (1 << (e)))
-+
-+static int ctnetlink_conntrack_event(struct notifier_block *this,
-+ unsigned long events, void *ptr)
-+{
-+ struct nlmsghdr *nlh;
-+ struct nfgenmsg *nfmsg;
-+ struct ip_conntrack *ct = (struct ip_conntrack *)ptr;
-+ struct sk_buff *skb;
-+ unsigned int type;
-+ unsigned char *b;
-+ int flags = 0;
-+
-+ /* FIXME: much too big, costs lots of socket buffer space */
-+ skb = alloc_skb(400 /* NLMSG_GOODSIZE */, GFP_ATOMIC);
-+ if (!skb)
-+ return NOTIFY_DONE;
-+
-+ if (EVENT(events, IPCT_DESTROY))
-+ type = CTNL_MSG_DELCONNTRACK;
-+ else {
-+ type = CTNL_MSG_NEWCONNTRACK;
-+ if (EVENT(events, IPCT_NEW)) {
-+ flags = NLM_F_CREATE|NLM_F_EXCL;
-+ /* dump everything */
-+ events = ~0UL;
-+ }
-+ }
-+
-+ b = skb->tail;
-+
-+ type |= NFNL_SUBSYS_CTNETLINK << 8;
-+ nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(struct nfgenmsg));
-+ nfmsg = NLMSG_DATA(nlh);
-+
-+ nlh->nlmsg_flags = flags;
-+ nfmsg->nfgen_family = AF_INET;
-+
-+ if (ctnetlink_dump_tuples(skb, ct) < 0)
-+ goto nfattr_failure;
-+
-+ if (EVENT(events, IPCT_STATUS)
-+ && ctnetlink_dump_status(skb, ct) < 0)
-+ goto nfattr_failure;
-+ if (EVENT(events, IPCT_REFRESH)
-+ && ctnetlink_dump_timeout(skb, ct) < 0)
-+ goto nfattr_failure;
-+ if (EVENT(events, IPCT_PROTOINFO)
-+ && ctnetlink_dump_protoinfo(skb, ct) < 0)
-+ goto nfattr_failure;
-+ if (EVENT(events, IPCT_HELPINFO)
-+ && ctnetlink_dump_helpinfo(skb, ct) < 0)
-+ goto nfattr_failure;
-+ if (EVENT(events, IPCT_NATINFO)
-+ && ctnetlink_dump_natinfo(skb, ct) < 0)
-+ goto nfattr_failure;
-+
-+ nlh->nlmsg_len = skb->tail - b;
-+ nfnetlink_send(skb, 0, ctnetlink_get_mcgroups(ct), 0);
-+ return NOTIFY_DONE;
-+
-+nlmsg_failure:
-+nfattr_failure:
-+ kfree_skb(skb);
-+ return NOTIFY_DONE;
-+}
-+
-+static const int cta_min[CTA_MAX] = {
-+ [CTA_ORIG-1] = sizeof(struct ip_conntrack_tuple),
-+ [CTA_RPLY-1] = sizeof(struct ip_conntrack_tuple),
-+ [CTA_STATUS-1] = sizeof(unsigned long),
-+ [CTA_PROTOINFO-1] = sizeof(struct cta_proto),
-+ [CTA_HELPINFO-1] = sizeof(struct cta_help),
-+ [CTA_NATINFO-1] = sizeof(struct cta_nat),
-+ [CTA_TIMEOUT-1] = sizeof(unsigned long),
-+
-+ [CTA_EXP_TUPLE-1] = sizeof(struct ip_conntrack_tuple),
-+ [CTA_EXP_MASK-1] = sizeof(struct ip_conntrack_tuple),
-+ [CTA_EXP_SEQNO-1] = sizeof(u_int32_t),
-+ [CTA_EXP_PROTO-1] = sizeof(struct cta_exp_proto),
-+ [CTA_EXP_HELP-1] = sizeof(struct cta_exp_help),
-+ [CTA_EXP_TIMEOUT-1] = sizeof(unsigned long)
-+};
-+
-+static inline int ctnetlink_kill(const struct ip_conntrack *i, void *data)
-+{
-+ struct ip_conntrack *t = (struct ip_conntrack *)data;
-+
-+ if (!memcmp(&i->tuplehash[IP_CT_DIR_ORIGINAL],
-+ &t->tuplehash[IP_CT_DIR_ORIGINAL],
-+ sizeof(struct ip_conntrack_tuple_hash))) {
-+ ip_conntrack_put(t);
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct ip_conntrack_tuple_hash *h;
-+ struct ip_conntrack_tuple *tuple;
-+ struct nfattr *cda[CTA_MAX];
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1] &&
-+ NFA_PAYLOAD(cda[CTA_ORIG-1]) < cta_min[CTA_ORIG-1])
-+ return -EINVAL;
-+
-+ if (cda[CTA_RPLY-1] &&
-+ NFA_PAYLOAD(cda[CTA_RPLY-1]) < cta_min[CTA_RPLY-1])
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1])
-+ tuple = NFA_DATA(cda[CTA_ORIG-1]);
-+ else {
-+ if (cda[CTA_RPLY-1])
-+ tuple = NFA_DATA(cda[CTA_RPLY-1]);
-+ else {
-+ ct_debug(0, "no tuple found in request\n");
-+ return -EINVAL;
-+ }
-+ }
-+
-+ h = ip_conntrack_find_get(tuple, NULL);
-+ if (!h) {
-+ ct_debug(0, "tuple not found in conntrack hash:");
-+ DUMP_TUPLE(tuple);
-+ return -ENOENT;
-+ }
-+
-+ ct_debug(0, "calling selective_cleanup\n");
-+ ip_ct_selective_cleanup(ctnetlink_kill, h->ctrack);
-+
-+ return 0;
-+}
-+
-+static int ctnetlink_done(struct netlink_callback *cb)
-+{
-+ ct_debug(0, "entering\n");
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
-+{
-+ struct ip_conntrack *ct;
-+
-+ ct_debug(0, "entered, last=%lu\n", cb->args[0]);
-+
-+ /* Traverse ordered list; send originals then reply. */
-+ READ_LOCK(&ip_conntrack_lock);
-+ list_for_each_entry(ct, &ip_conntrack_ordered_list, olist) {
-+ if (ct->id <= cb->args[0])
-+ continue;
-+ if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
-+ cb->nlh->nlmsg_seq,
-+ CTNL_MSG_NEWCONNTRACK, 1, ct) < 0)
-+ break;
-+ cb->args[0] = ct->id;
-+ }
-+ READ_UNLOCK(&ip_conntrack_lock);
-+
-+ ct_debug(0, "leaving, last=%lu\n", cb->args[0]);
-+
-+ return skb->len;
-+}
-+
-+static int
-+ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct ip_conntrack_tuple_hash *h;
-+ struct ip_conntrack_tuple *tuple;
-+ struct nfattr *cda[CTA_MAX];
-+ struct ip_conntrack *ct;
-+ struct sk_buff *skb2 = NULL;
-+ int err;
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
-+ struct nfgenmsg *msg = NLMSG_DATA(nlh);
-+ u32 rlen;
-+
-+ if (msg->nfgen_family != AF_INET)
-+ return -EAFNOSUPPORT;
-+
-+ if ((*errp = netlink_dump_start(ctnl, skb, nlh,
-+ ctnetlink_dump_table,
-+ ctnetlink_done)) != 0)
-+ return -EINVAL;
-+
-+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
-+ if (rlen > skb->len)
-+ rlen = skb->len;
-+ skb_pull(skb, rlen);
-+ return 0;
-+ }
-+
-+ if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1] &&
-+ NFA_PAYLOAD(cda[CTA_ORIG-1]) < cta_min[CTA_ORIG-1])
-+ return -EINVAL;
-+
-+ if (cda[CTA_RPLY-1] &&
-+ NFA_PAYLOAD(cda[CTA_RPLY-1]) < cta_min[CTA_RPLY-1])
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1])
-+ tuple = NFA_DATA(cda[CTA_ORIG-1]);
-+ else {
-+ if (cda[CTA_RPLY-1])
-+ tuple = NFA_DATA(cda[CTA_RPLY-1]);
-+ else
-+ return -EINVAL;
-+ }
-+
-+ h = ip_conntrack_find_get(tuple, NULL);
-+ if (!h) {
-+ ct_debug(0, "tuple not found in conntrack hash:");
-+ DUMP_TUPLE(tuple);
-+ return -ENOENT;
-+ }
-+ ct = h->ctrack;
-+
-+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
-+ if (!skb2) {
-+ ip_conntrack_put(ct);
-+ return -ENOMEM;
-+ }
-+ NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
-+
-+ err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
-+ CTNL_MSG_NEWCONNTRACK, 1, ct);
-+ ip_conntrack_put(ct);
-+ if (err <= 0)
-+ goto nlmsg_failure;
-+
-+ err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
-+ if (err < 0)
-+ return err;
-+ return 0;
-+
-+nlmsg_failure:
-+ if (skb2)
-+ kfree_skb(skb2);
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_change_status(struct ip_conntrack *ct, unsigned long *status)
-+{
-+ unsigned long d = ct->status ^ *status;
-+
-+ if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DESTROYED))
-+ /* unchangeable */
-+ return -EINVAL;
-+
-+ if (d & IPS_SEEN_REPLY && !(*status & IPS_SEEN_REPLY))
-+ /* SEEN_REPLY bit can only be set */
-+ return -EINVAL;
-+
-+ if (d & IPS_ASSURED && !(*status & IPS_ASSURED))
-+ /* ASSURED bit can only be set */
-+ return -EINVAL;
-+
-+ ct->status = *status;
-+ return 0;
-+}
-+
-+static inline int
-+ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct cta_proto *cp)
-+{
-+ struct ip_conntrack_protocol *icp;
-+ int proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
-+
-+ if (cp->num_proto != proto)
-+ return -EINVAL;
-+
-+ icp = __ip_ct_find_proto(cp->num_proto);
-+ if (icp->ctnl_check_private
-+ && icp->ctnl_check_private(&cp->proto) < 0)
-+ return -EINVAL;
-+
-+ if (icp->ctnl_change)
-+ icp->ctnl_change(ct, &cp->proto);
-+
-+ return 0;
-+}
-+
-+static inline int
-+ctnetlink_change_helpinfo(struct ip_conntrack *ct, struct cta_help *h)
-+{
-+ struct ip_conntrack_helper *helper = ct->helper;
-+ struct ip_conntrack_tuple *reply;
-+
-+ if (helper == NULL) {
-+ if (*h->name == '\0')
-+ return 0;
-+ if (ct->master)
-+ return -EINVAL;
-+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-+ helper = ip_ct_find_helper(reply);
-+ if (helper == NULL)
-+ return -ENOENT;
-+ } else if (*h->name == '\0') {
-+ ip_conntrack_remove_expectations(ct, 1);
-+ ct->helper = NULL;
-+ return 0;
-+ }
-+
-+ h->name[CTA_HELP_MAXNAMESZ - 1] = '\0';
-+ if (strcmp(helper->name, h->name))
-+ return -EINVAL;
-+
-+ ct->helper = helper;
-+ if (helper->ctnl_change)
-+ helper->ctnl_change(ct, &h->help);
-+
-+ return 0;
-+}
-+
-+static inline int
-+ctnetlink_change_natinfo(struct ip_conntrack *ct, struct cta_nat *n)
-+{
-+#ifdef CONFIG_IP_NF_NAT_NEEDED
-+ struct ip_nat_info *info = &ct->nat.info;
-+ int i;
-+
-+ if (n->num_manips > IP_NAT_MAX_MANIPS)
-+ return -EINVAL;
-+
-+ if (info->initialized && n->num_manips < info->num_manips)
-+ return -EINVAL;
-+
-+ for (i = 0; i < n->num_manips; i++) {
-+ if (n->manips[i].direction > IP_CT_DIR_MAX)
-+ return -EINVAL;
-+ if (n->manips[i].hooknum > NF_IP_NUMHOOKS)
-+ return -EINVAL;
-+ if (n->manips[i].hooknum == NF_IP_FORWARD)
-+ return -EINVAL;
-+ if (n->manips[i].maniptype > IP_NAT_MANIP_DST)
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+#else
-+ return -EOPNOTSUPP;
-+#endif
-+}
-+
-+static inline int
-+ctnetlink_change_timeout(struct ip_conntrack *ct, unsigned long *timeout)
-+{
-+ if (!del_timer(&ct->timeout))
-+ return -ETIME;
-+ ct->timeout.expires = jiffies + *timeout * HZ;
-+ add_timer(&ct->timeout);
-+
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
-+{
-+ void *data;
-+ int err;
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (cda[CTA_STATUS-1]) {
-+ data = NFA_DATA(cda[CTA_STATUS-1]);
-+ if ((err = ctnetlink_change_status(ct, data)) < 0)
-+ return err;
-+ }
-+ if (cda[CTA_PROTOINFO-1]) {
-+ data = NFA_DATA(cda[CTA_PROTOINFO-1]);
-+ if ((err = ctnetlink_change_protoinfo(ct, data)) < 0)
-+ return err;
-+ }
-+ if (cda[CTA_HELPINFO-1]) {
-+ data = NFA_DATA(cda[CTA_HELPINFO-1]);
-+ if ((err = ctnetlink_change_helpinfo(ct, data)) < 0)
-+ return err;
-+ }
-+ if (cda[CTA_NATINFO-1]) {
-+ data = NFA_DATA(cda[CTA_NATINFO-1]);
-+ if ((err = ctnetlink_change_natinfo(ct, data)) < 0)
-+ return err;
-+ }
-+ if (cda[CTA_TIMEOUT-1]) {
-+ data = NFA_DATA(cda[CTA_TIMEOUT-1]);
-+ if ((err = ctnetlink_change_timeout(ct, data)) < 0)
-+ return err;
-+ }
-+
-+ ct_debug(0, "all done\n");
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_create_conntrack(struct nfattr *cda[])
-+{
-+ struct ip_conntrack *ct;
-+ struct ip_conntrack_tuple *otuple, *rtuple, t;
-+ struct ip_conntrack_protocol *icp;
-+ struct cta_proto *proto;
-+ unsigned long *status;
-+ unsigned long *timeout;
-+ int err;
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (!(cda[CTA_ORIG-1] && cda[CTA_RPLY-1] && cda[CTA_STATUS-1] &&
-+ cda[CTA_PROTOINFO-1] && cda[CTA_TIMEOUT-1])) {
-+ ct_debug(0, "required attribute(s) missing\n");
-+ return -EINVAL;
-+ }
-+
-+ otuple = NFA_DATA(cda[CTA_ORIG-1]);
-+ rtuple = NFA_DATA(cda[CTA_RPLY-1]);
-+ timeout = NFA_DATA(cda[CTA_TIMEOUT-1]);
-+
-+ status = NFA_DATA(cda[CTA_STATUS-1]);
-+ if (!(*status & IPS_CONFIRMED))
-+ return -EINVAL; /* cannot create unconfirmed connections */
-+
-+ proto = NFA_DATA(cda[CTA_PROTOINFO-1]);
-+ icp = __ip_ct_find_proto(proto->num_proto);
-+
-+ if (!invert_tuple(&t, otuple, icp) || !ip_ct_tuple_equal(&t, rtuple))
-+ ; // FIXME: nat changes reply tuples // return -EINVAL;
-+
-+ if (icp->ctnl_check_tuples
-+ && icp->ctnl_check_tuples(otuple, rtuple) < 0)
-+ return -EINVAL;
-+
-+ if (icp->ctnl_check_private
-+ && icp->ctnl_check_private(&proto->proto) < 0)
-+ return -EINVAL;
-+
-+ ct = ip_conntrack_alloc(otuple, rtuple);
-+ if (ct == NULL)
-+ return -ENOMEM;
-+
-+ ct->status = *status;
-+ ct->timeout.expires = jiffies + *timeout * HZ;
-+
-+ if (icp->ctnl_change)
-+ icp->ctnl_change(ct, &proto->proto);
-+
-+ cda[CTA_ORIG-1] = cda[CTA_RPLY-1] = cda[CTA_PROTOINFO-1] =
-+ cda[CTA_STATUS-1] = cda[CTA_TIMEOUT-1] = NULL;
-+
-+ err = ctnetlink_change_conntrack(ct, cda);
-+ if (err < 0) {
-+ ip_conntrack_free(ct);
-+ return err;
-+ }
-+
-+ ip_conntrack_place_in_lists(ct);
-+ add_timer(&ct->timeout);
-+
-+ ct_debug(0, "all done\n");
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct nfattr *cda[CTA_MAX];
-+ struct ip_conntrack_tuple *otuple = NULL, *rtuple = NULL;
-+ struct ip_conntrack_tuple_hash *h = NULL;
-+ int i, err = 0;
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
-+ return -EINVAL;
-+
-+ for (i = 0; i < CTA_MAX; i++)
-+ if (cda[i] && NFA_PAYLOAD(cda[i]) < cta_min[i])
-+ return -EINVAL;
-+
-+ ct_debug(0, "all attribute sizes ok\n");
-+
-+ if (cda[CTA_ORIG-1])
-+ otuple = NFA_DATA(cda[CTA_ORIG-1]);
-+
-+ if (cda[CTA_RPLY-1])
-+ rtuple = NFA_DATA(cda[CTA_RPLY-1]);
-+
-+ if (otuple == NULL && rtuple == NULL) {
-+ ct_debug(0, "no tuple found in request\n");
-+ return -EINVAL;
-+ }
-+
-+ WRITE_LOCK(&ip_conntrack_lock);
-+ if (otuple)
-+ h = __ip_conntrack_find_get(otuple, NULL);
-+ if (h == NULL && rtuple)
-+ h = __ip_conntrack_find_get(rtuple, NULL);
-+
-+ if (h == NULL) {
-+ ct_debug(0, "no such conntrack, create new\n");
-+ err = -ENOENT;
-+ if (!(nlh->nlmsg_flags & NLM_F_CREATE))
-+ goto out_unlock;
-+ err = ctnetlink_create_conntrack(cda);
-+ goto out_unlock;
-+ } else {
-+ ct_debug(0, "conntrack found, change\n");
-+ err = -EEXIST;
-+ if (nlh->nlmsg_flags & NLM_F_EXCL)
-+ goto out_put;
-+ err = ctnetlink_change_conntrack(h->ctrack, cda);
-+ }
-+
-+out_put:
-+ ip_conntrack_put(h->ctrack);
-+out_unlock:
-+ WRITE_UNLOCK(&ip_conntrack_lock);
-+ return err;
-+}
-+
-+/* EXPECT */
-+
-+static inline int
-+ctnetlink_exp_dump_tuples(struct sk_buff *skb,
-+ const struct ip_conntrack_expect *exp)
-+{
-+ NFA_PUT(skb, CTA_EXP_TUPLE, sizeof(struct ip_conntrack_tuple),
-+ &exp->tuple);
-+ NFA_PUT(skb, CTA_EXP_MASK, sizeof(struct ip_conntrack_tuple),
-+ &exp->mask);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_exp_dump_seqno(struct sk_buff *skb,
-+ const struct ip_conntrack_expect *exp)
-+{
-+ NFA_PUT(skb, CTA_EXP_SEQNO, sizeof(u_int32_t), &exp->seq);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static inline int
-+ctnetlink_exp_dump_proto(struct sk_buff *skb,
-+ const struct ip_conntrack_expect *exp)
-+{
-+ return 0;
-+}
-+
-+static inline int
-+ctnetlink_exp_dump_help(struct sk_buff *skb,
-+ const struct ip_conntrack_expect *exp)
-+{
-+ struct cta_exp_help ch;
-+
-+ memcpy(&ch.help, &exp->help, sizeof(ch.help));
-+ NFA_PUT(skb, CTA_EXP_HELP, sizeof(union ip_conntrack_expect_help),
-+ &exp->help);
-+ return 0;
-+
-+nfattr_failure:
-+ return -1;
-+}
-+
-+static int
-+ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
-+ int event,
-+ int nowait,
-+ const struct ip_conntrack_expect *exp)
-+{
-+ struct nlmsghdr *nlh;
-+ struct nfgenmsg *nfmsg;
-+ unsigned char *b;
-+
-+ b = skb->tail;
-+
-+ event |= NFNL_SUBSYS_CTNETLINK << 8;
-+ nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct nfgenmsg));
-+ nfmsg = NLMSG_DATA(nlh);
-+
-+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
-+ nfmsg->nfgen_family = AF_INET;
-+
-+ if (ctnetlink_exp_dump_tuples(skb, exp) < 0 ||
-+ ctnetlink_exp_dump_seqno(skb, exp) < 0 ||
-+ ctnetlink_exp_dump_proto(skb, exp) < 0 ||
-+ ctnetlink_exp_dump_help(skb, exp) < 0)
-+ goto nfattr_failure;
-+
-+ nlh->nlmsg_len = skb->tail - b;
-+ return skb->len;
-+
-+nlmsg_failure:
-+nfattr_failure:
-+ skb_trim(skb, b - skb->data);
-+ return -1;
-+}
-+
-+static inline struct sk_buff *
-+ctnetlink_exp_event_build_msg(const struct ip_conntrack_expect *exp)
-+{
-+ struct sk_buff *skb;
-+ int err;
-+
-+ skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
-+ if (!skb)
-+ return NULL;
-+
-+ err = ctnetlink_exp_fill_info(skb, 0, 0, CTNL_MSG_NEWEXPECT, 1, exp);
-+ if (err <= 0)
-+ goto nlmsg_failure;
-+ return skb;
-+
-+nlmsg_failure:
-+ if (skb)
-+ kfree_skb(skb);
-+ return NULL;
-+}
-+
-+static void
-+ctnetlink_exp_create(struct ip_conntrack_expect *exp)
-+{
-+ u16 proto = exp->tuple.dst.protonum;
-+ struct sk_buff *skb;
-+
-+ skb = ctnetlink_exp_event_build_msg(exp);
-+ if (!skb)
-+ return;
-+
-+ if (proto == IPPROTO_TCP) {
-+ nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
-+ return;
-+ } else if (proto == IPPROTO_UDP) {
-+ nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
-+ return;
-+ } else if (proto == IPPROTO_ICMP) {
-+ nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
-+ return;
-+ } else {
-+ nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
-+ return;
-+ }
-+ kfree_skb(skb);
-+ return;
-+}
-+
-+static int
-+ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct ip_conntrack_expect *exp;
-+ struct ip_conntrack_tuple *tuple;
-+ struct nfattr *cda[CTA_MAX];
-+
-+ if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1] &&
-+ NFA_PAYLOAD(cda[CTA_ORIG-1]) < cta_min[CTA_ORIG-1])
-+ return -EINVAL;
-+
-+ if (cda[CTA_RPLY-1] &&
-+ NFA_PAYLOAD(cda[CTA_RPLY-1]) < cta_min[CTA_RPLY-1])
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1])
-+ tuple = NFA_DATA(cda[CTA_ORIG-1]);
-+ else {
-+ if (cda[CTA_RPLY-1])
-+ tuple = NFA_DATA(cda[CTA_RPLY-1]);
-+ else
-+ return -EINVAL;
-+ }
-+
-+ /* bump usage count to 2 */
-+ exp = ip_conntrack_expect_find_get(tuple);
-+ if (!exp)
-+ return -ENOENT;
-+
-+ /* after list removal, usage count == 1 */
-+ ip_conntrack_unexpect_related(exp);
-+ /* we have put what we 'get' above. after this line usage count == 0 */
-+ ip_conntrack_expect_put(exp);
-+
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_exp_dump_build_msg(const struct ip_conntrack_expect *exp,
-+ struct sk_buff *skb, u32 pid, u32 seq)
-+{
-+ int err, proto;
-+
-+ proto = exp->tuple.dst.protonum;
-+ err = ctnetlink_exp_fill_info(skb, pid, seq, CTNL_MSG_NEWEXPECT, 1,
-+ exp);
-+ if (err <= 0)
-+ goto nlmsg_failure;
-+ return 0;
-+
-+nlmsg_failure:
-+ if (skb)
-+ kfree_skb(skb);
-+ return -1;
-+}
-+
-+static int
-+ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
-+{
-+ ct_debug(0, "entered\n");
-+ if (cb->args[0] == 0) {
-+ READ_LOCK(&ip_conntrack_lock);
-+ LIST_FIND(&ip_conntrack_expect_list,
-+ ctnetlink_exp_dump_build_msg,
-+ struct ip_conntrack_expect *, skb,
-+ NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq);
-+ READ_UNLOCK(&ip_conntrack_lock);
-+ cb->args[0] = 1;
-+ }
-+ ct_debug(0, "returning\n");
-+
-+ return skb->len;
-+}
-+
-+
-+static int
-+ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct ip_conntrack_expect *exp;
-+ struct ip_conntrack_tuple *tuple;
-+ struct nfattr *cda[CTA_MAX];
-+ struct sk_buff *skb2 = NULL;
-+ int err, proto;
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
-+ struct nfgenmsg *msg = NLMSG_DATA(nlh);
-+ u32 rlen;
-+
-+ if (msg->nfgen_family != AF_INET)
-+ return -EAFNOSUPPORT;
-+
-+ ct_debug(0, "starting dump\n");
-+ if ((*errp = netlink_dump_start(ctnl, skb, nlh,
-+ ctnetlink_exp_dump_table,
-+ ctnetlink_done)) != 0)
-+ return -EINVAL;
-+ rlen = NLMSG_ALIGN(nlh->nlmsg_len);
-+ if (rlen > skb->len)
-+ rlen = skb->len;
-+ skb_pull(skb, rlen);
-+ return 0;
-+ }
-+
-+ if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1]
-+ && NFA_PAYLOAD(cda[CTA_ORIG-1]) < sizeof(struct ip_conntrack_tuple))
-+ return -EINVAL;
-+
-+ if (cda[CTA_RPLY-1]
-+ && NFA_PAYLOAD(cda[CTA_RPLY-1]) < sizeof(struct ip_conntrack_tuple))
-+ return -EINVAL;
-+
-+ if (cda[CTA_ORIG-1])
-+ tuple = NFA_DATA(cda[CTA_ORIG-1]);
-+ else {
-+ if (cda[CTA_RPLY-1])
-+ tuple = NFA_DATA(cda[CTA_RPLY-1]);
-+ else
-+ return -EINVAL;
-+ }
-+
-+ exp = ip_conntrack_expect_find_get(tuple);
-+ if (!exp)
-+ return -ENOENT;
-+
-+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
-+ if (!skb2)
-+ return -ENOMEM;
-+ NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
-+ proto = exp->tuple.dst.protonum;
-+
-+ err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
-+ nlh->nlmsg_seq, CTNL_MSG_NEWEXPECT,
-+ 1, exp);
-+ if (err <= 0)
-+ goto nlmsg_failure;
-+
-+ err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
-+ if (err < 0)
-+ return err;
-+ return 0;
-+
-+nlmsg_failure:
-+ if (skb2)
-+ kfree_skb(skb2);
-+ return -1;
-+}
-+
-+static int
-+ctnetlink_change_expect(struct ip_conntrack_expect *x, struct nfattr *cda[])
-+{
-+
-+ return -EOPNOTSUPP;
-+}
-+
-+static int
-+ctnetlink_create_expect(struct nfattr *cda[])
-+{
-+ struct ip_conntrack_tuple *tuple, *mask;
-+ struct ip_conntrack_tuple *orig, *reply;
-+ struct ip_conntrack_tuple_hash *h = NULL;
-+ struct ip_conntrack_expect exp, *new;
-+ struct ip_conntrack_helper *helper;
-+ unsigned long timeout;
-+ int err;
-+
-+ ct_debug(0, "entered\n");
-+
-+ if (!(cda[CTA_ORIG-1] || cda[CTA_RPLY-1])) {
-+ ct_debug(0, "required attributes missing\n");
-+ return -EINVAL;
-+ }
-+
-+ tuple = NFA_DATA(cda[CTA_EXP_TUPLE-1]);
-+ mask = NFA_DATA(cda[CTA_EXP_MASK-1]);
-+ orig = NFA_DATA(cda[CTA_ORIG-1]);
-+ reply = NFA_DATA(cda[CTA_RPLY-1]);
-+
-+ memcpy(&exp.tuple, tuple, sizeof(struct ip_conntrack_tuple));
-+ memcpy(&exp.mask, mask, sizeof(struct ip_conntrack_tuple));
-+
-+ exp.expectfn = NULL;
-+
-+ if (cda[CTA_EXP_SEQNO-1])
-+ exp.seq = *(u_int32_t *)NFA_DATA(cda[CTA_EXP_SEQNO-1]);
-+
-+ h = __ip_conntrack_find_get(orig, NULL);
-+ if (h == NULL)
-+ h = __ip_conntrack_find_get(reply, NULL);
-+ if (h == NULL)
-+ return -ENOENT;
-+
-+ helper = h->ctrack->helper;
-+
-+ if (cda[CTA_EXP_TIMEOUT-1])
-+ timeout = *(unsigned long *)NFA_DATA(cda[CTA_EXP_TIMEOUT-1]);
-+ else if (helper && helper->timeout)
-+ timeout = helper->timeout;
-+ else
-+ return -EINVAL;
-+
-+ if (helper && helper->ctnl_new_expect) {
-+ struct cta_exp_proto *cp = NULL;
-+ struct cta_exp_help *ch = NULL;
-+
-+ if (cda[CTA_EXP_PROTO-1])
-+ cp = NFA_DATA(cda[CTA_EXP_PROTO-1]);
-+ if (cda[CTA_EXP_HELP-1])
-+ ch = NFA_DATA(cda[CTA_EXP_HELP-1]);
-+
-+ helper->ctnl_new_expect(&exp, &cp->proto, &ch->help);
-+ }
-+
-+ err = __ip_conntrack_expect_related(h->ctrack, &exp, &new);
-+ if (err < 0)
-+ return err;
-+
-+ new->timeout.expires = jiffies + timeout * HZ;
-+ add_timer(&new->timeout);
-+ return 0;
-+}
-+
-+static int
-+ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
-+ struct nlmsghdr *nlh, int *errp)
-+{
-+ struct nfattr *cda[CTA_MAX];
-+ struct ip_conntrack_tuple *tuple, *mask;
-+ struct ip_conntrack_expect *exp;
-+ int i, err = 0;
-+
-+ if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
-+ return -EINVAL;
-+
-+ for (i = 0; i < CTA_MAX; i++)
-+ if (cda[i] && NFA_PAYLOAD(cda[i]) < cta_min[i])
-+ return -EINVAL;
-+
-+ if (!cda[CTA_EXP_TUPLE-1] || !cda[CTA_EXP_MASK-1])
-+ return -EINVAL;
-+
-+ tuple = NFA_DATA(cda[CTA_EXP_TUPLE-1]);
-+ mask = NFA_DATA(cda[CTA_EXP_MASK-1]);
-+
-+ WRITE_LOCK(&ip_conntrack_lock);
-+ exp = __ip_ct_expect_find_tm(tuple, mask);
-+
-+ if (exp == NULL) {
-+ err = -ENOENT;
-+ if (!(nlh->nlmsg_flags & NLM_F_CREATE))
-+ goto out_unlock;
-+ err = ctnetlink_create_expect(cda);
-+ } else {
-+ err = -EEXIST;
-+ if (nlh->nlmsg_flags & NLM_F_EXCL)
-+ goto out_unlock;
-+ err = ctnetlink_change_expect(exp, cda);
-+ }
-+
-+out_unlock:
-+ WRITE_UNLOCK(&ip_conntrack_lock);
-+ return err;
-+}
-+
-+/* struct conntrack_expect stuff */
-+
-+static struct notifier_block ctnl_notifier = {
-+ ctnetlink_conntrack_event,
-+ NULL,
-+ 0
-+};
-+
-+static void __exit ctnetlink_exit(void)
-+{
-+ printk("ctnetlink: unregistering with nfnetlink.\n");
-+// ip_conntrack_notify_unregister(&ctnl_exp_notify);
-+ ip_conntrack_notify_unregister(&ctnl_notifier);
-+ nfnetlink_subsys_unregister(ctnl_subsys);
-+ kfree(ctnl_subsys);
-+ return;
-+}
-+
-+static int __init ctnetlink_init(void)
-+{
-+ int ret;
-+
-+ ctnl_subsys = nfnetlink_subsys_alloc(CTNL_MSG_COUNT);
-+ if (!ctnl_subsys) {
-+ ret = -ENOMEM;
-+ goto err_out;
-+ }
-+
-+ ctnl_subsys->name = "conntrack";
-+ ctnl_subsys->subsys_id = NFNL_SUBSYS_CTNETLINK;
-+ ctnl_subsys->cb_count = CTNL_MSG_COUNT;
-+ ctnl_subsys->attr_count = CTA_MAX;
-+ ctnl_subsys->cb[CTNL_MSG_NEWCONNTRACK].call = ctnetlink_new_conntrack;
-+ ctnl_subsys->cb[CTNL_MSG_NEWCONNTRACK].cap_required = CAP_NET_ADMIN;
-+ ctnl_subsys->cb[CTNL_MSG_DELCONNTRACK].call = ctnetlink_del_conntrack;
-+ ctnl_subsys->cb[CTNL_MSG_DELCONNTRACK].cap_required = CAP_NET_ADMIN;
-+ ctnl_subsys->cb[CTNL_MSG_GETCONNTRACK].call = ctnetlink_get_conntrack;
-+ ctnl_subsys->cb[CTNL_MSG_GETCONNTRACK].cap_required = 0;
-+ ctnl_subsys->cb[CTNL_MSG_NEWEXPECT].call = ctnetlink_new_expect;
-+ ctnl_subsys->cb[CTNL_MSG_NEWEXPECT].cap_required = CAP_NET_ADMIN;
-+ ctnl_subsys->cb[CTNL_MSG_DELEXPECT].call = ctnetlink_del_expect;
-+ ctnl_subsys->cb[CTNL_MSG_DELEXPECT].cap_required = CAP_NET_ADMIN;
-+ ctnl_subsys->cb[CTNL_MSG_GETEXPECT].call = ctnetlink_get_expect;
-+ ctnl_subsys->cb[CTNL_MSG_GETEXPECT].cap_required = 0;
-+
-+ printk("ctnetlink v%s: registering with nfnetlink.\n", ctversion);
-+ if ((ret = nfnetlink_subsys_register(ctnl_subsys) < 0)) {
-+ printk("ctnetlink_init: cannot register with nfnetlink.\n");
-+ goto err_free_subsys;
-+ }
-+
-+ if ((ret = ip_conntrack_notify_register(&ctnl_notifier)) < 0) {
-+ printk("ctnetlink_init: cannot register notifier.\n");
-+ goto err_unreg_subsys;
-+ }
-+
-+#if 0
-+ if ((ret = ip_conntrack_notify_register(&ctnl_exp_notify)) < 0) {
-+ printk("ctnetlink_init: cannot register exp notifier\n");
-+ goto err_unreg_notify;
-+ }
-+#endif
-+
-+
-+ return 0;
-+
-+#if 0
-+err_unreg_notify:
-+ ip_conntrack_notify_unregister(&ctnl_notify);
-+#endif
-+err_unreg_subsys:
-+ nfnetlink_subsys_unregister(ctnl_subsys);
-+err_free_subsys:
-+ kfree(ctnl_subsys);
-+err_out:
-+ return ret;
-+}
-+
-+module_init(ctnetlink_init);
-+module_exit(ctnetlink_exit);
-
-%diffstat
- include/linux/netfilter_ipv4/ip_conntrack.h | 109 +
- include/linux/netfilter_ipv4/ip_conntrack_core.h | 6
- include/linux/netfilter_ipv4/ip_conntrack_helper.h | 12
- include/linux/netfilter_ipv4/ip_conntrack_protocol.h | 11
- include/linux/nfnetlink.h | 158 ++
- include/linux/nfnetlink_conntrack.h | 87 +
- net/ipv4/netfilter/Config.in | 8
- net/ipv4/netfilter/Makefile | 9
- net/ipv4/netfilter/ip_conntrack_core.c | 242 ++-
- net/ipv4/netfilter/ip_conntrack_ftp.c | 9
- net/ipv4/netfilter/ip_conntrack_irc.c | 20
- net/ipv4/netfilter/ip_conntrack_proto_generic.c | 3
- net/ipv4/netfilter/ip_conntrack_proto_icmp.c | 34
- net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 29
- net/ipv4/netfilter/ip_conntrack_proto_udp.c | 7
- net/ipv4/netfilter/ip_conntrack_standalone.c | 13
- net/ipv4/netfilter/ip_nat_core.c | 2
- net/ipv4/netfilter/nfnetlink.c | 354 +++++
- net/ipv4/netfilter/nfnetlink_conntrack.c | 1252 +++++++++++++++++++
- 19 files changed, 2280 insertions(+), 85 deletions(-)
-
Modified: branches/netfilter-ha/linux-2.6/patches/pf_packet.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/pf_packet.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/pf_packet.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,8 +1,8 @@
%patch
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_packet.h
+Index: linux-2.6.9/include/linux/netfilter_packet.h
===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_packet.h Fri Dec 19 09:26:33 2003
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_packet.h Mon Jun 14 14:52:20 2004
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.9/include/linux/netfilter_packet.h 2004-12-15 21:06:07.525658800 +0100
@@ -0,0 +1,17 @@
+#ifndef __LINUX_NETFILTER_PACKET_H
+#define __LINUX_NETFILTER_PACKET_H
@@ -21,19 +21,19 @@
+#define NF_PACKET_OUTPUT 1
+
+#endif /* __LINUX_NETFILTER_PACKET_H */
-Index: linux-2.4.26-ct_sync/net/core/dev.c
+Index: linux-2.6.9/net/core/dev.c
===================================================================
---- linux-2.4.26-ct_sync.orig/net/core/dev.c Wed Apr 14 15:05:41 2004
-+++ linux-2.4.26-ct_sync/net/core/dev.c Mon Jun 14 14:55:01 2004
-@@ -100,6 +100,7 @@
- #include <linux/init.h>
- #include <linux/kmod.h>
- #include <linux/module.h>
-+#include <linux/netfilter_packet.h>
- #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
+--- linux-2.6.9.orig/net/core/dev.c 2004-11-27 00:25:43.000000000 +0100
++++ linux-2.6.9/net/core/dev.c 2004-12-15 21:24:52.782593744 +0100
+@@ -112,6 +112,7 @@
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#include <net/iw_handler.h>
-@@ -1032,40 +1033,11 @@
+ #endif /* CONFIG_NET_RADIO */
++#include <linux/netfilter_packet.h>
+ #include <asm/current.h>
+
+ /* This define, if set, will randomly drop a packet when congestion
+@@ -1255,37 +1256,12 @@
* to congestion or traffic shaping.
*/
@@ -41,136 +41,143 @@
+static inline int dev_queue_xmit_finish(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- struct Qdisc *q;
+ struct Qdisc *q;
+ int rc = -ENOMEM;
- if (skb_shinfo(skb)->frag_list &&
-- !(dev->features&NETIF_F_FRAGLIST) &&
-- skb_linearize(skb, GFP_ATOMIC) != 0) {
-- kfree_skb(skb);
-- return -ENOMEM;
-- }
+- !(dev->features & NETIF_F_FRAGLIST) &&
+- __skb_linearize(skb, GFP_ATOMIC))
+- goto out_kfree_skb;
-
- /* Fragmented skb is linearized if device does not support SG,
- * or if at least one of fragments is in highmem and device
- * does not support DMA from it.
- */
- if (skb_shinfo(skb)->nr_frags &&
-- (!(dev->features&NETIF_F_SG) || illegal_highdma(dev, skb)) &&
-- skb_linearize(skb, GFP_ATOMIC) != 0) {
-- kfree_skb(skb);
-- return -ENOMEM;
-- }
+- (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
+- __skb_linearize(skb, GFP_ATOMIC))
+- goto out_kfree_skb;
-
- /* If packet is not checksummed and device does not support
- * checksumming for this protocol, complete checksumming here.
- */
- if (skb->ip_summed == CHECKSUM_HW &&
-- (!(dev->features&(NETIF_F_HW_CSUM|NETIF_F_NO_CSUM)) &&
-- (!(dev->features&NETIF_F_IP_CSUM) ||
-- skb->protocol != htons(ETH_P_IP)))) {
-- if ((skb = skb_checksum_help(skb)) == NULL)
-- return -ENOMEM;
-- }
+- (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
+- (!(dev->features & NETIF_F_IP_CSUM) ||
+- skb->protocol != htons(ETH_P_IP))))
+- if (skb_checksum_help(&skb, 0))
+- goto out_kfree_skb;
-
- /* Grab device queue */
- spin_lock_bh(&dev->queue_lock);
- q = dev->qdisc;
-@@ -1125,6 +1097,43 @@
- return -ENETDOWN;
+-
+ /* Disable soft irqs for various locks below. Also
+ * stops preemption for RCU.
+ */
+@@ -1364,13 +1340,50 @@
+ }
+ out_enetdown:
+ rc = -ENETDOWN;
+-out_kfree_skb:
+ kfree_skb(skb);
+ out:
+ local_bh_enable();
+ return rc;
}
+int dev_queue_xmit(struct sk_buff *skb)
+{
-+ struct net_device *dev = skb->dev;
++ struct net_device *dev = skb->dev;
+
-+ if (skb_shinfo(skb)->frag_list &&
-+ !(dev->features&NETIF_F_FRAGLIST) &&
-+ skb_linearize(skb, GFP_ATOMIC) != 0) {
-+ kfree_skb(skb);
-+ return -ENOMEM;
-+ }
++ if (skb_shinfo(skb)->frag_list &&
++ !(dev->features & NETIF_F_FRAGLIST) &&
++ __skb_linearize(skb, GFP_ATOMIC)) {
++ kfree_skb(skb);
++ return -ENOMEM;
++ }
+
-+ /* Fragmented skb is linearized if device does not support SG,
-+ * or if at least one of fragments is in highmem and device
-+ * does not support DMA from it.
-+ */
-+ if (skb_shinfo(skb)->nr_frags &&
-+ (!(dev->features&NETIF_F_SG) || illegal_highdma(dev, skb)) &&
-+ skb_linearize(skb, GFP_ATOMIC) != 0) {
-+ kfree_skb(skb);
-+ return -ENOMEM;
-+ }
++ /* Fragmented skb is linearized if device does not support SG,
++ * or if at least one of fragments is in highmem and device
++ * does not support DMA from it.
++ */
++ if (skb_shinfo(skb)->nr_frags &&
++ (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
++ __skb_linearize(skb, GFP_ATOMIC)) {
++ kfree_skb(skb);
++ return -ENOMEM;
++ }
+
-+ /* If packet is not checksummed and device does not support
-+ * checksumming for this protocol, complete checksumming here.
-+ */
-+ if (skb->ip_summed == CHECKSUM_HW &&
-+ (!(dev->features&(NETIF_F_HW_CSUM|NETIF_F_NO_CSUM)) &&
-+ (!(dev->features&NETIF_F_IP_CSUM) ||
-+ skb->protocol != htons(ETH_P_IP)))) {
-+ if ((skb = skb_checksum_help(skb)) == NULL)
-+ return -ENOMEM;
-+ }
++ /* If packet is not checksummed and device does not support
++ * checksumming for this protocol, complete checksumming here.
++ */
++ if (skb->ip_summed == CHECKSUM_HW &&
++ (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
++ (!(dev->features & NETIF_F_IP_CSUM) ||
++ skb->protocol != htons(ETH_P_IP))))
++ if (skb_checksum_help(&skb, 0)) {
++ kfree_skb(skb);
++ return -ENOMEM;
++ }
+
-+ return NF_HOOK(PF_PACKET, NF_PACKET_OUTPUT, skb, NULL, dev,
-+ dev_queue_xmit_finish);
++ return NF_HOOK(PF_PACKET, NF_PACKET_OUTPUT, skb, NULL, dev,
++ dev_queue_xmit_finish);
+}
+
/*=======================================================================
Receiver routines
-@@ -1458,28 +1467,12 @@
+@@ -1714,29 +1727,12 @@
}
- #endif /* CONFIG_NET_DIVERT */
+ #endif
-int netif_receive_skb(struct sk_buff *skb)
-+static inline int netif_receive_skb_finish(struct sk_buff *skb)
++static int netif_receive_skb_finish(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
int ret = NET_RX_DROP;
unsigned short type;
-- if (skb->stamp.tv_sec == 0)
-- do_gettimeofday(&skb->stamp);
+-#ifdef CONFIG_NETPOLL
+- if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
+- kfree_skb(skb);
+- return NET_RX_DROP;
+- }
+-#endif
-
+- if (!skb->stamp.tv_sec)
+- net_timestamp(&skb->stamp);
+-
- skb_bond(skb);
-
-- netdev_rx_stat[smp_processor_id()].total++;
+- __get_cpu_var(netdev_rx_stat).total++;
-
--#ifdef CONFIG_NET_FASTROUTE
-- if (skb->pkt_type == PACKET_FASTROUTE) {
-- netdev_rx_stat[smp_processor_id()].fastroute_deferred_out++;
-- return dev_queue_xmit(skb);
-- }
--#endif
--
- skb->h.raw = skb->nh.raw = skb->data;
+- skb->mac_len = skb->nh.raw - skb->mac.raw;
-
pt_prev = NULL;
- for (ptype = ptype_all; ptype; ptype = ptype->next) {
- if (!ptype->dev || ptype->dev == skb->dev) {
-@@ -1540,7 +1533,29 @@
+
+ rcu_read_lock();
+@@ -1805,7 +1801,30 @@
return ret;
}
-static int process_backlog(struct net_device *backlog_dev, int *budget)
+int netif_receive_skb(struct sk_buff *skb)
+{
-+ if (skb->stamp.tv_sec == 0)
-+ do_gettimeofday(&skb->stamp);
++#ifdef CONFIG_NETPOLL
++ if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
++ kfree_skb(skb);
++ return NET_RX_DROP;
++ }
++#endif
+
++ if (!skb->stamp.tv_sec)
++ net_timestamp(&skb->stamp);
++
+ skb_bond(skb);
+
-+ netdev_rx_stat[smp_processor_id()].total++;
++ __get_cpu_var(netdev_rx_stat).total++;
+
-+#ifdef CONFIG_NET_FASTROUTE
-+ if (skb->pkt_type == PACKET_FASTROUTE) {
-+ netdev_rx_stat[smp_processor_id()].fastroute_deferred_out++;
-+ return dev_queue_xmit(skb);
-+ }
-+#endif
-+
+ skb->h.raw = skb->nh.raw = skb->data;
++ skb->mac_len = skb->nh.raw - skb->mac.raw;
+
+ return NF_HOOK(PF_PACKET, NF_PACKET_INPUT, skb, skb->dev, NULL,
+ netif_receive_skb_finish);
@@ -180,9 +187,3 @@
{
int work = 0;
int quota = min(backlog_dev->quota, *budget);
-
-%diffstat
- include/linux/netfilter_packet.h | 17 +++++
- net/core/dev.c | 111 ++++++++++++++++++++++-----------------
- 2 files changed, 80 insertions(+), 48 deletions(-)
-
Modified: branches/netfilter-ha/linux-2.6/patches/pf_packet_remove_warning.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/pf_packet_remove_warning.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/pf_packet_remove_warning.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,9 +1,9 @@
-Index: linux-2.4.26-ct_sync/net/core/netfilter.c
+Index: linux-2.6.9/net/core/netfilter.c
===================================================================
---- linux-2.4.26-ct_sync.orig/net/core/netfilter.c 2003-08-25 13:44:44.000000000 +0200
-+++ linux-2.4.26-ct_sync/net/core/netfilter.c 2004-06-24 15:35:12.000000000 +0200
-@@ -472,10 +472,12 @@
- br_read_lock_bh(BR_NETPROTO_LOCK);
+--- linux-2.6.9.orig/net/core/netfilter.c 2004-11-27 00:25:43.000000000 +0100
++++ linux-2.6.9/net/core/netfilter.c 2004-12-15 21:19:44.270494712 +0100
+@@ -508,10 +508,12 @@
+ rcu_read_lock();
#ifdef CONFIG_NETFILTER_DEBUG
+#if 0
Deleted: branches/netfilter-ha/linux-2.6/patches/proc_net_stat.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/proc_net_stat.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/proc_net_stat.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,40 +0,0 @@
-diff -Nru linux-2.4.21-24105-cts-plain/fs/proc/root.c linux-2.4.21-24105-cts-debug/fs/proc/root.c
---- linux-2.4.21-24105-cts-plain/fs/proc/root.c 2004-10-06 15:30:02.000000000 +0200
-+++ linux-2.4.21-24105-cts-debug/fs/proc/root.c 2004-10-13 12:04:56.000000000 +0200
-@@ -17,7 +17,7 @@
- #include <linux/module.h>
- #include <asm/bitops.h>
-
--struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
-+struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
-
- #ifdef CONFIG_SYSCTL
- struct proc_dir_entry *proc_sys_root;
-@@ -38,6 +38,7 @@
- }
- proc_misc_init();
- proc_net = proc_mkdir("net", 0);
-+ proc_net_stat = proc_mkdir("net/stat", 0);
- #ifdef CONFIG_SYSVIPC
- proc_mkdir("sysvipc", 0);
- #endif
-@@ -143,6 +144,7 @@
- EXPORT_SYMBOL(proc_root);
- EXPORT_SYMBOL(proc_root_fs);
- EXPORT_SYMBOL(proc_net);
-+EXPORT_SYMBOL(proc_net_stat);
- EXPORT_SYMBOL(proc_bus);
- EXPORT_SYMBOL(proc_root_driver);
- EXPORT_SYMBOL(proc_get_inode);
-diff -Nru linux-2.4.21-24105-cts-plain/include/linux/proc_fs.h linux-2.4.21-24105-cts-debug/include/linux/proc_fs.h
---- linux-2.4.21-24105-cts-plain/include/linux/proc_fs.h 2004-10-13 10:39:10.000000000 +0200
-+++ linux-2.4.21-24105-cts-debug/include/linux/proc_fs.h 2004-10-15 11:54:32.000000000 +0200
-@@ -79,6 +79,7 @@
- extern struct proc_dir_entry proc_root;
- extern struct proc_dir_entry *proc_root_fs;
- extern struct proc_dir_entry *proc_net;
-+extern struct proc_dir_entry *proc_net_stat;
- extern struct proc_dir_entry *proc_bus;
- extern struct proc_dir_entry *proc_root_driver;
- extern struct proc_dir_entry *proc_root_kcore;
-
Deleted: branches/netfilter-ha/linux-2.6/patches/raw.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/raw.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/raw.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,760 +0,0 @@
-%patch
-Index: linux-2.4.26-ct_sync/Documentation/Configure.help
-===================================================================
---- linux-2.4.26-ct_sync.orig/Documentation/Configure.help Wed Apr 14 15:05:24 2004
-+++ linux-2.4.26-ct_sync/Documentation/Configure.help Mon Jun 14 14:52:11 2004
-@@ -2978,6 +2978,34 @@
- If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. If unsure, say `N'.
-
-+raw table support (required for NOTRACK/TRACE)
-+CONFIG_IP_NF_RAW
-+ This option adds a `raw' table to iptables. This table is the very
-+ first in the netfilter framework and hooks in at the PREROUTING
-+ and OUTPUT chains.
-+
-+ If you want to compile it as a module, say M here and read
-+ <file:Documentation/modules.txt>. If unsure, say `N'.
-+
-+NOTRACK target support
-+CONFIG_IP_NF_TARGET_NOTRACK
-+ The NOTRACK target allows a select rule to specify
-+ which packets *not* to enter the conntrack/NAT
-+ subsystem with all the consequences (no ICMP error tracking,
-+ no protocol helpers for the selected packets).
-+
-+ If you want to compile it as a module, say M here and read
-+ <file:Documentation/modules.txt>. If unsure, say `N'.
-+
-+raw table support (required for TRACE)
-+CONFIG_IP6_NF_RAW
-+ This option adds a `raw' table to ip6tables. This table is the very
-+ first in the netfilter framework and hooks in at the PREROUTING
-+ and OUTPUT chains.
-+
-+ If you want to compile it as a module, say M here and read
-+ <file:Documentation/modules.txt>. If unsure, say `N'.
-+
- REJECT target support
- CONFIG_IP_NF_TARGET_REJECT
- The REJECT target allows a filtering rule to specify that an ICMP
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ip_conntrack.h Wed Apr 14 15:05:40 2004
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ip_conntrack.h Mon Jun 14 14:52:11 2004
-@@ -249,6 +249,9 @@
- /* Call me when a conntrack is destroyed. */
- extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
-
-+/* Fake conntrack entry for untracked connections */
-+extern struct ip_conntrack ip_conntrack_untracked;
-+
- /* Returns new sk_buff, or NULL */
- struct sk_buff *
- ip_ct_gather_frags(struct sk_buff *skb);
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_conntrack.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ipt_conntrack.h Fri Nov 29 00:53:15 2002
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_conntrack.h Mon Jun 14 14:52:11 2004
-@@ -10,6 +10,7 @@
-
- #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
- #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
-+#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
-
- /* flags, invflags: */
- #define IPT_CONNTRACK_STATE 0x01
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_state.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4/ipt_state.h Fri Apr 14 18:37:20 2000
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4/ipt_state.h Mon Jun 14 14:52:11 2004
-@@ -4,6 +4,8 @@
- #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
- #define IPT_STATE_INVALID (1 << 0)
-
-+#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
-+
- struct ipt_state_info
- {
- unsigned int statemask;
-Index: linux-2.4.26-ct_sync/include/linux/netfilter_ipv4.h
-===================================================================
---- linux-2.4.26-ct_sync.orig/include/linux/netfilter_ipv4.h Mon Feb 25 20:38:13 2002
-+++ linux-2.4.26-ct_sync/include/linux/netfilter_ipv4.h Mon Jun 14 14:52:11 2004
-@@ -51,6 +51,8 @@
-
- enum nf_ip_hook_priorities {
- NF_IP_PRI_FIRST = INT_MIN,
-+ NF_IP_PRI_CONNTRACK_DEFRAG = -400,
-+ NF_IP_PRI_RAW = -300,
- NF_IP_PRI_CONNTRACK = -200,
- NF_IP_PRI_MANGLE = -150,
- NF_IP_PRI_NAT_DST = -100,
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Config.in Mon Aug 25 13:44:44 2003
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Config.in Mon Jun 14 14:52:11 2004
-@@ -108,6 +108,15 @@
- dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
- dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
- dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
-+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-+ tristate ' raw table support (required for NOTRACK/TRACE)' CONFIG_IP_NF_RAW $CONFIG_IP_NF_IPTABLES
-+ fi
-+ if [ "$CONFIG_IP_NF_RAW" != "n" ]; then
-+ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
-+ dep_tristate ' NOTRACK target support' CONFIG_IP_NF_TARGET_NOTRACK $CONFIG_IP_NF_RAW
-+ fi
-+ # Marker for TRACE target
-+ fi
- fi
-
- tristate 'ARP tables support' CONFIG_IP_NF_ARPTABLES
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/Makefile Mon Aug 25 13:44:44 2003
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/Makefile Mon Jun 14 14:52:11 2004
-@@ -61,6 +61,7 @@
- obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
- obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
- obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
-+obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
-
- # matches
- obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
-@@ -100,6 +101,7 @@
- obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
- obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
- obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
-+obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
-
- # generic ARP tables
- obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_core.c Wed Feb 18 14:36:32 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_core.c Mon Jun 14 14:52:11 2004
-@@ -64,6 +64,7 @@
- static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
- struct list_head *ip_conntrack_hash;
- static kmem_cache_t *ip_conntrack_cachep;
-+struct ip_conntrack ip_conntrack_untracked;
-
- extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
-
-@@ -811,6 +812,15 @@
- int set_reply;
- int ret;
-
-+ /* Never happen */
-+ if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
-+ if (net_ratelimit()) {
-+ printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
-+ (*pskb)->nh.iph->protocol, hooknum);
-+ }
-+ return NF_DROP;
-+ }
-+
- /* FIXME: Do this right please. --RR */
- (*pskb)->nfcache |= NFC_UNKNOWN;
-
-@@ -829,18 +839,10 @@
- }
- #endif
-
-- /* Previously seen (loopback)? Ignore. Do this before
-- fragment check. */
-+ /* Previously seen (loopback or untracked)? Ignore. */
- if ((*pskb)->nfct)
- return NF_ACCEPT;
-
-- /* Gather fragments. */
-- if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-- *pskb = ip_ct_gather_frags(*pskb);
-- if (!*pskb)
-- return NF_STOLEN;
-- }
--
- proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
-
- /* It may be an icmp error... */
-@@ -1439,6 +1441,18 @@
-
- /* For use by ipt_REJECT */
- ip_ct_attach = ip_conntrack_attach;
-+
-+ /* Set up fake conntrack:
-+ - to never be deleted, not in any hashes */
-+ atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
-+ /* - and look it like as a confirmed connection */
-+ set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
-+ /* - and prepare the ctinfo field for REJECT/NAT. */
-+ ip_conntrack_untracked.infos[IP_CT_NEW].master =
-+ ip_conntrack_untracked.infos[IP_CT_RELATED].master =
-+ ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master =
-+ &ip_conntrack_untracked.ct_general;
-+
- return ret;
-
- err_free_hash:
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_conntrack_standalone.c Wed Feb 18 14:36:32 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_conntrack_standalone.c Mon Jun 14 14:52:11 2004
-@@ -189,6 +189,26 @@
- return ip_conntrack_confirm(*pskb);
- }
-
-+static unsigned int ip_conntrack_defrag(unsigned int hooknum,
-+ struct sk_buff **pskb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ int (*okfn)(struct sk_buff *))
-+{
-+ /* Previously seen (loopback)? Ignore. Do this before
-+ fragment check. */
-+ if ((*pskb)->nfct)
-+ return NF_ACCEPT;
-+
-+ /* Gather fragments. */
-+ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
-+ *pskb = ip_ct_gather_frags(*pskb);
-+ if (!*pskb)
-+ return NF_STOLEN;
-+ }
-+ return NF_ACCEPT;
-+}
-+
- static unsigned int ip_refrag(unsigned int hooknum,
- struct sk_buff **pskb,
- const struct net_device *in,
-@@ -230,9 +250,15 @@
-
- /* Connection tracking may drop packets, but never alters them, so
- make it the first hook. */
-+static struct nf_hook_ops ip_conntrack_defrag_ops
-+= { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_PRE_ROUTING,
-+ NF_IP_PRI_CONNTRACK_DEFRAG };
- static struct nf_hook_ops ip_conntrack_in_ops
- = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
- NF_IP_PRI_CONNTRACK };
-+static struct nf_hook_ops ip_conntrack_defrag_local_out_ops
-+= { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_LOCAL_OUT,
-+ NF_IP_PRI_CONNTRACK_DEFRAG };
- static struct nf_hook_ops ip_conntrack_local_out_ops
- = { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
- NF_IP_PRI_CONNTRACK };
-@@ -353,10 +379,20 @@
- if (!proc) goto cleanup_init;
- proc->owner = THIS_MODULE;
-
-+ ret = nf_register_hook(&ip_conntrack_defrag_ops);
-+ if (ret < 0) {
-+ printk("ip_conntrack: can't register pre-routing defrag hook.\n");
-+ goto cleanup_proc;
-+ }
-+ ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
-+ if (ret < 0) {
-+ printk("ip_conntrack: can't register local_out defrag hook.\n");
-+ goto cleanup_defragops;
-+ }
- ret = nf_register_hook(&ip_conntrack_in_ops);
- if (ret < 0) {
- printk("ip_conntrack: can't register pre-routing hook.\n");
-- goto cleanup_proc;
-+ goto cleanup_defraglocalops;
- }
- ret = nf_register_hook(&ip_conntrack_local_out_ops);
- if (ret < 0) {
-@@ -394,6 +430,10 @@
- nf_unregister_hook(&ip_conntrack_local_out_ops);
- cleanup_inops:
- nf_unregister_hook(&ip_conntrack_in_ops);
-+ cleanup_defraglocalops:
-+ nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
-+ cleanup_defragops:
-+ nf_unregister_hook(&ip_conntrack_defrag_ops);
- cleanup_proc:
- proc_net_remove("ip_conntrack");
- cleanup_init:
-@@ -482,5 +522,6 @@
- EXPORT_SYMBOL(ip_conntrack_expect_list);
- EXPORT_SYMBOL(ip_conntrack_lock);
- EXPORT_SYMBOL(ip_conntrack_hash);
-+EXPORT_SYMBOL(ip_conntrack_untracked);
- EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
- EXPORT_SYMBOL_GPL(ip_conntrack_put);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_core.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ip_nat_core.c Wed Feb 18 14:36:32 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ip_nat_core.c Mon Jun 14 14:52:11 2004
-@@ -991,6 +991,10 @@
- /* FIXME: Man, this is a hack. <SIGH> */
- IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
- ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
-+
-+ /* Initialize fake conntrack so that NAT will skip it */
-+ ip_conntrack_untracked.nat.info.initialized |=
-+ (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
-
- return 0;
- }
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_NOTRACK.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ipt_NOTRACK.c Fri Dec 19 09:26:33 2003
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_NOTRACK.c Mon Jun 14 14:52:11 2004
-@@ -0,0 +1,75 @@
-+/* This is a module which is used for setting up fake conntracks
-+ * on packets so that they are not seen by the conntrack/NAT code.
-+ */
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+
-+#include <linux/netfilter_ipv4/ip_tables.h>
-+#include <linux/netfilter_ipv4/ip_conntrack.h>
-+
-+static unsigned int
-+target(struct sk_buff **pskb,
-+ unsigned int hooknum,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ const void *targinfo,
-+ void *userinfo)
-+{
-+ /* Previously seen (loopback)? Ignore. */
-+ if ((*pskb)->nfct != NULL)
-+ return IPT_CONTINUE;
-+
-+ /* Attach fake conntrack entry.
-+ If there is a real ct entry correspondig to this packet,
-+ it'll hang aroun till timing out. We don't deal with it
-+ for performance reasons. JK */
-+ (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
-+ nf_conntrack_get((*pskb)->nfct);
-+
-+ return IPT_CONTINUE;
-+}
-+
-+static int
-+checkentry(const char *tablename,
-+ const struct ipt_entry *e,
-+ void *targinfo,
-+ unsigned int targinfosize,
-+ unsigned int hook_mask)
-+{
-+ if (targinfosize != 0) {
-+ printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
-+ targinfosize);
-+ return 0;
-+ }
-+
-+ if (strcmp(tablename, "raw") != 0) {
-+ printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+static struct ipt_target ipt_notrack_reg = {
-+ .name = "NOTRACK",
-+ .target = target,
-+ .checkentry = checkentry,
-+ .me = THIS_MODULE
-+};
-+
-+static int __init init(void)
-+{
-+ if (ipt_register_target(&ipt_notrack_reg))
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static void __exit fini(void)
-+{
-+ ipt_unregister_target(&ipt_notrack_reg);
-+}
-+
-+module_init(init);
-+module_exit(fini);
-+MODULE_LICENSE("GPL");
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_conntrack.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ipt_conntrack.c Wed Feb 18 14:36:32 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_conntrack.c Mon Jun 14 14:52:11 2004
-@@ -27,11 +27,13 @@
-
- #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
-
-- if (ct)
-- statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
-- else
-- statebit = IPT_CONNTRACK_STATE_INVALID;
--
-+ if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
-+ statebit = IPT_CONNTRACK_STATE_UNTRACKED;
-+ else if (ct)
-+ statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
-+ else
-+ statebit = IPT_CONNTRACK_STATE_INVALID;
-+
- if(sinfo->flags & IPT_CONNTRACK_STATE) {
- if (ct) {
- if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_state.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/ipt_state.c Wed Feb 18 14:36:32 2004
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/ipt_state.c Mon Jun 14 14:52:11 2004
-@@ -21,7 +21,9 @@
- enum ip_conntrack_info ctinfo;
- unsigned int statebit;
-
-- if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
-+ if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
-+ statebit = IPT_STATE_UNTRACKED;
-+ else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
- statebit = IPT_STATE_INVALID;
- else
- statebit = IPT_STATE_BIT(ctinfo);
-Index: linux-2.4.26-ct_sync/net/ipv4/netfilter/iptable_raw.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv4/netfilter/iptable_raw.c Fri Dec 19 09:26:33 2003
-+++ linux-2.4.26-ct_sync/net/ipv4/netfilter/iptable_raw.c Mon Jun 14 14:52:11 2004
-@@ -0,0 +1,149 @@
-+/*
-+ * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
-+ *
-+ * Copyright (C) 2003 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
-+ */
-+#include <linux/module.h>
-+#include <linux/netfilter_ipv4/ip_tables.h>
-+
-+#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
-+
-+/* Standard entry. */
-+struct ipt_standard
-+{
-+ struct ipt_entry entry;
-+ struct ipt_standard_target target;
-+};
-+
-+struct ipt_error_target
-+{
-+ struct ipt_entry_target target;
-+ char errorname[IPT_FUNCTION_MAXNAMELEN];
-+};
-+
-+struct ipt_error
-+{
-+ struct ipt_entry entry;
-+ struct ipt_error_target target;
-+};
-+
-+static struct
-+{
-+ struct ipt_replace repl;
-+ struct ipt_standard entries[2];
-+ struct ipt_error term;
-+} initial_table __initdata
-+= { { "raw", RAW_VALID_HOOKS, 3,
-+ sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
-+ { [NF_IP_PRE_ROUTING] 0,
-+ [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
-+ { [NF_IP_PRE_ROUTING] 0,
-+ [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
-+ 0, NULL, { } },
-+ {
-+ /* PRE_ROUTING */
-+ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-+ 0,
-+ sizeof(struct ipt_entry),
-+ sizeof(struct ipt_standard),
-+ 0, { 0, 0 }, { } },
-+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-+ -NF_ACCEPT - 1 } },
-+ /* LOCAL_OUT */
-+ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-+ 0,
-+ sizeof(struct ipt_entry),
-+ sizeof(struct ipt_standard),
-+ 0, { 0, 0 }, { } },
-+ { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-+ -NF_ACCEPT - 1 } }
-+ },
-+ /* ERROR */
-+ { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-+ 0,
-+ sizeof(struct ipt_entry),
-+ sizeof(struct ipt_error),
-+ 0, { 0, 0 }, { } },
-+ { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
-+ { } },
-+ "ERROR"
-+ }
-+ }
-+};
-+
-+static struct ipt_table packet_raw = {
-+ .name = "raw",
-+ .table = &initial_table.repl,
-+ .valid_hooks = RAW_VALID_HOOKS,
-+ .lock = RW_LOCK_UNLOCKED,
-+ .me = THIS_MODULE
-+};
-+
-+/* The work comes in here from netfilter.c. */
-+static unsigned int
-+ipt_hook(unsigned int hook,
-+ struct sk_buff **pskb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ int (*okfn)(struct sk_buff *))
-+{
-+ return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
-+}
-+
-+/* 'raw' is the very first table. */
-+static struct nf_hook_ops ipt_ops[] = {
-+ {
-+ .hook = ipt_hook,
-+ .pf = PF_INET,
-+ .hooknum = NF_IP_PRE_ROUTING,
-+ .priority = NF_IP_PRI_RAW
-+ },
-+ {
-+ .hook = ipt_hook,
-+ .pf = PF_INET,
-+ .hooknum = NF_IP_LOCAL_OUT,
-+ .priority = NF_IP_PRI_RAW
-+ },
-+};
-+
-+static int __init init(void)
-+{
-+ int ret;
-+
-+ /* Register table */
-+ ret = ipt_register_table(&packet_raw);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* Register hooks */
-+ ret = nf_register_hook(&ipt_ops[0]);
-+ if (ret < 0)
-+ goto cleanup_table;
-+
-+ ret = nf_register_hook(&ipt_ops[1]);
-+ if (ret < 0)
-+ goto cleanup_hook0;
-+
-+ return ret;
-+
-+ cleanup_hook0:
-+ nf_unregister_hook(&ipt_ops[0]);
-+ cleanup_table:
-+ ipt_unregister_table(&packet_raw);
-+
-+ return ret;
-+}
-+
-+static void __exit fini(void)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
-+ nf_unregister_hook(&ipt_ops[i]);
-+
-+ ipt_unregister_table(&packet_raw);
-+}
-+
-+module_init(init);
-+module_exit(fini);
-+MODULE_LICENSE("GPL");
-Index: linux-2.4.26-ct_sync/net/ipv6/netfilter/Config.in
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv6/netfilter/Config.in Fri Jun 13 16:51:39 2003
-+++ linux-2.4.26-ct_sync/net/ipv6/netfilter/Config.in Mon Jun 14 14:52:11 2004
-@@ -73,6 +73,10 @@
- dep_tristate ' MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
- fi
- #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
-+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-+ tristate ' raw table support (required for TRACE)' CONFIG_IP6_NF_RAW $CONFIG_IP6_NF_IPTABLES
-+ fi
-+ # Marker for TRACE target
- fi
-
- endmenu
-Index: linux-2.4.26-ct_sync/net/ipv6/netfilter/Makefile
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv6/netfilter/Makefile Fri Jun 13 16:51:39 2003
-+++ linux-2.4.26-ct_sync/net/ipv6/netfilter/Makefile Mon Jun 14 14:52:11 2004
-@@ -30,6 +30,7 @@
- obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
- obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
- obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
-+obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
- obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
-
- include $(TOPDIR)/Rules.make
-Index: linux-2.4.26-ct_sync/net/ipv6/netfilter/ip6table_raw.c
-===================================================================
---- linux-2.4.26-ct_sync.orig/net/ipv6/netfilter/ip6table_raw.c Fri Dec 19 09:26:33 2003
-+++ linux-2.4.26-ct_sync/net/ipv6/netfilter/ip6table_raw.c Mon Jun 14 14:52:11 2004
-@@ -0,0 +1,154 @@
-+/*
-+ * IPv6 raw table, a port of the IPv4 raw table to IPv6
-+ *
-+ * Copyright (C) 2003 Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
-+ */
-+#include <linux/module.h>
-+#include <linux/netfilter_ipv6/ip6_tables.h>
-+
-+#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
-+
-+#if 0
-+#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
-+#else
-+#define DEBUGP(x, args...)
-+#endif
-+
-+/* Standard entry. */
-+struct ip6t_standard
-+{
-+ struct ip6t_entry entry;
-+ struct ip6t_standard_target target;
-+};
-+
-+struct ip6t_error_target
-+{
-+ struct ip6t_entry_target target;
-+ char errorname[IP6T_FUNCTION_MAXNAMELEN];
-+};
-+
-+struct ip6t_error
-+{
-+ struct ip6t_entry entry;
-+ struct ip6t_error_target target;
-+};
-+
-+static struct
-+{
-+ struct ip6t_replace repl;
-+ struct ip6t_standard entries[2];
-+ struct ip6t_error term;
-+} initial_table __initdata
-+= { { "raw", RAW_VALID_HOOKS, 3,
-+ sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
-+ { [NF_IP6_PRE_ROUTING] 0,
-+ [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
-+ { [NF_IP6_PRE_ROUTING] 0,
-+ [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
-+ 0, NULL, { } },
-+ {
-+ /* PRE_ROUTING */
-+ { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-+ 0,
-+ sizeof(struct ip6t_entry),
-+ sizeof(struct ip6t_standard),
-+ 0, { 0, 0 }, { } },
-+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-+ -NF_ACCEPT - 1 } },
-+ /* LOCAL_OUT */
-+ { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-+ 0,
-+ sizeof(struct ip6t_entry),
-+ sizeof(struct ip6t_standard),
-+ 0, { 0, 0 }, { } },
-+ { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-+ -NF_ACCEPT - 1 } },
-+ },
-+ /* ERROR */
-+ { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-+ 0,
-+ sizeof(struct ip6t_entry),
-+ sizeof(struct ip6t_error),
-+ 0, { 0, 0 }, { } },
-+ { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
-+ { } },
-+ "ERROR"
-+ }
-+ }
-+};
-+
-+static struct ip6t_table packet_raw = {
-+ .name = "raw",
-+ .table = &initial_table.repl,
-+ .valid_hooks = RAW_VALID_HOOKS,
-+ .lock = RW_LOCK_UNLOCKED,
-+ .me = THIS_MODULE
-+};
-+
-+/* The work comes in here from netfilter.c. */
-+static unsigned int
-+ip6t_hook(unsigned int hook,
-+ struct sk_buff **pskb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ int (*okfn)(struct sk_buff *))
-+{
-+ return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
-+}
-+
-+static struct nf_hook_ops ip6t_ops[] = {
-+ {
-+ .hook = ip6t_hook,
-+ .pf = PF_INET6,
-+ .hooknum = NF_IP6_PRE_ROUTING,
-+ .priority = NF_IP6_PRI_FIRST
-+ },
-+ {
-+ .hook = ip6t_hook,
-+ .pf = PF_INET6,
-+ .hooknum = NF_IP6_LOCAL_OUT,
-+ .priority = NF_IP6_PRI_FIRST
-+ },
-+};
-+
-+static int __init init(void)
-+{
-+ int ret;
-+
-+ /* Register table */
-+ ret = ip6t_register_table(&packet_raw);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* Register hooks */
-+ ret = nf_register_hook(&ip6t_ops[0]);
-+ if (ret < 0)
-+ goto cleanup_table;
-+
-+ ret = nf_register_hook(&ip6t_ops[1]);
-+ if (ret < 0)
-+ goto cleanup_hook0;
-+
-+ return ret;
-+
-+ cleanup_hook0:
-+ nf_unregister_hook(&ip6t_ops[0]);
-+ cleanup_table:
-+ ip6t_unregister_table(&packet_raw);
-+
-+ return ret;
-+}
-+
-+static void __exit fini(void)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
-+ nf_unregister_hook(&ip6t_ops[i]);
-+
-+ ip6t_unregister_table(&packet_raw);
-+}
-+
-+module_init(init);
-+module_exit(fini);
-+MODULE_LICENSE("GPL");
-
Deleted: branches/netfilter-ha/linux-2.6/patches/seq_file-seq_start_token.patch
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/seq_file-seq_start_token.patch 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/seq_file-seq_start_token.patch 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,13 +0,0 @@
-diff -Nru linux-2.4.21-24105-cts-plain/include/linux/seq_file.h linux-2.4.21-24105-cts-debug/include/linux/seq_file.h
---- linux-2.4.21-24105-cts-plain/include/linux/seq_file.h 2004-10-06 15:30:06.000000000 +0200
-+++ linux-2.4.21-24105-cts-debug/include/linux/seq_file.h 2004-10-13 10:47:25.000000000 +0200
-@@ -2,6 +2,8 @@
- #define _LINUX_SEQ_FILE_H
- #ifdef __KERNEL__
-
-+#define SEQ_START_TOKEN ((void *)1)
-+
- struct seq_operations;
-
- struct seq_file {
-
Modified: branches/netfilter-ha/linux-2.6/patches/series
===================================================================
--- branches/netfilter-ha/linux-2.6/patches/series 2005-01-02 22:40:48 UTC (rev 3550)
+++ branches/netfilter-ha/linux-2.6/patches/series 2005-01-02 23:13:27 UTC (rev 3551)
@@ -1,16 +1,12 @@
-raw.patch
+ct_notifier_pkt.patch
+connmark.patch
pf_packet.patch
pf_packet_remove_warning.patch
-connmark.patch
-nfnetlink-ctnetlink.patch
-kgdb-1.9.patch
export_ip_conntrack_helpers.patch
export_ip_nat_helpers.patch
export_ip_conntrack_find.patch
-export_hash_conntrack.patch
-export_ct_id.patch
-export_ip_nat_lock.patch
-export_ip_nat_hash.patch
+export_ip_nat_lock_and_hash.patch
+export_ip_conntrack_clean_from_lists.patch
+conntrack_hash_manip.patch
+conntrack_alloc.patch
ct_sync_config_and_makefile.patch
-proc_net_stat.patch
-seq_file-seq_start_token.patch
More information about the netfilter-cvslog
mailing list