From: Pablo Neira <pablo@eurodev.net>
To: Patrick McHardy <kaber@trash.net>
Cc: Harald Welte <laforge@netfilter.org>,
Netfilter Development Mailinglist
<netfilter-devel@lists.netfilter.org>
Subject: Re: [PATCH 2.6] connection tracking events
Date: Sat, 16 Oct 2004 20:21:28 +0200 [thread overview]
Message-ID: <417166A8.3050809@eurodev.net> (raw)
In-Reply-To: <41713F11.9020301@eurodev.net>
[-- Attachment #1: Type: text/plain, Size: 531 bytes --]
Pablo Neira wrote:
> Attached the lastest version, I'm having a look at Harald's now to see
> I think that I can take something.
Based on Harald's patch, I've:
- renamed PROTOINFO/PROTOINFO_SOFT for PROTOINFO_VOLATILE/PROTOINFO, I
like it.
- added SCTP events
- added some comments to the source code
Harald's patch is similar to mine but I've also added a new event for
confirmed expectations (IPCT_RELATED) and the pickup bit which is useful
for tcp connections to make them pick up missing information.
regards,
Pablo
[-- Attachment #2: notifier.patch --]
[-- Type: text/x-patch, Size: 12691 bytes --]
===== include/linux/netfilter_ipv4/ip_conntrack.h 1.27 vs edited =====
--- 1.27/include/linux/netfilter_ipv4/ip_conntrack.h Sun Oct 10 21:44:23 2004
+++ edited/include/linux/netfilter_ipv4/ip_conntrack.h Sat Oct 16 18:42:42 2004
@@ -47,6 +47,14 @@
/* 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),
+
+ /* Some protocol information is missing, pick it up. */
+ IPS_PICKUP_BIT = 5,
+ IPS_PICKUP = (1 << IPS_PICKUP_BIT),
};
#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
@@ -290,6 +298,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 +326,68 @@
#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
+enum ip_conntrack_events
+{
+ IPCT_NEW,
+ IPCT_RELATED,
+ IPCT_DESTROY,
+ IPCT_STATUS,
+ IPCT_REFRESH,
+ IPCT_PROTOINFO,
+ IPCT_PROTOINFO_VOLATILE,
+ IPCT_HELPINFO,
+ IPCT_NATINFO,
+};
+
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+#include <linux/notifier.h>
+
+extern struct notifier_block *ip_conntrack_chain;
+DECLARE_PER_CPU(unsigned long, ip_conntrack_event_cache);
+
+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(void)
+{
+ __get_cpu_var(ip_conntrack_event_cache) = 0UL;
+}
+
+static inline void ip_conntrack_cache_event(enum ip_conntrack_events event)
+{
+ __get_cpu_var(ip_conntrack_event_cache) |= 1 << event;
+}
+
+static inline void ip_conntrack_deliver_cached_events(struct ip_conntrack *ct)
+{
+ unsigned long events = __get_cpu_var(ip_conntrack_event_cache);
+
+ if (is_confirmed(ct) && !is_destroyed(ct) && events)
+ notifier_call_chain(&ip_conntrack_chain, events, 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, 1 << event, ct);
+}
+#else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+static inline int ip_conntrack_register_notifier(void *nb) { return 0; }
+static inline int ip_conntrack_unregister_notifier(void *nb) { return 0; }
+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_deliver_cached_events(struct ip_conntrack *ct) {}
+static inline void ip_conntrack_event(enum ip_conntrack_events event,
+ struct ip_conntrack *ct) {}
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
/* eg. PROVIDES_CONNTRACK(ftp); */
#define PROVIDES_CONNTRACK(name) \
int needs_ip_conntrack_##name; \
===== net/ipv4/netfilter/Kconfig 1.32 vs edited =====
--- 1.32/net/ipv4/netfilter/Kconfig Sat Oct 16 17:53:47 2004
+++ edited/net/ipv4/netfilter/Kconfig Sat Oct 16 18:56:12 2004
@@ -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
===== net/ipv4/netfilter/ip_conntrack_proto_icmp.c 1.16 vs edited =====
--- 1.16/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Sun Oct 10 21:44:20 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_icmp.c Sat Oct 16 18:43:07 2004
@@ -102,6 +102,7 @@
ct->timeout.function((unsigned long)ct);
} else {
atomic_inc(&ct->proto.icmp.count);
+ ip_conntrack_cache_event(IPCT_PROTOINFO_VOLATILE);
ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
}
===== net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1.8 vs edited =====
--- 1.8/net/ipv4/netfilter/ip_conntrack_proto_sctp.c Sun Sep 26 23:17:15 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_sctp.c Sat Oct 16 18:55:30 2004
@@ -405,6 +405,8 @@
}
conntrack->proto.sctp.state = newconntrack;
+ if (oldsctpstate != newconntrack)
+ ip_conntrack_cache_event(IPCT_PROTOINFO);
WRITE_UNLOCK(&sctp_lock);
}
===== net/ipv4/netfilter/ip_conntrack_core.c 1.72 vs edited =====
--- 1.72/net/ipv4/netfilter/ip_conntrack_core.c Sun Oct 10 21:44:21 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_core.c Sat Oct 16 18:41:37 2004
@@ -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,11 @@
struct ip_conntrack ip_conntrack_untracked;
unsigned int ip_ct_log_invalid;
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+struct notifier_block *ip_conntrack_chain;
+DEFINE_PER_CPU(unsigned long, ip_conntrack_event_cache);
+#endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
+
DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
inline void
@@ -330,6 +336,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);
@@ -437,6 +444,7 @@
atomic_inc(&ct->ct_general.use);
set_bit(IPS_CONFIRMED_BIT, &ct->status);
WRITE_UNLOCK(&ip_conntrack_lock);
+ ip_conntrack_event(master_ct(ct)? IPCT_RELATED : IPCT_NEW, ct);
CONNTRACK_STAT_INC(insert);
return NF_ACCEPT;
}
@@ -706,6 +714,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'. */
@@ -767,8 +777,11 @@
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_deliver_cached_events(ct);
return ret;
}
@@ -1052,6 +1065,7 @@
remove_expectations(i->ctrack, 0);
/* And *then* set helper to NULL */
i->ctrack->helper = NULL;
+ ip_conntrack_event(IPCT_HELPINFO, i->ctrack);
}
return 0;
}
@@ -1105,6 +1119,7 @@
if (del_timer(&ct->timeout)) {
ct->timeout.expires = jiffies + extra_jiffies;
add_timer(&ct->timeout);
+ ip_conntrack_cache_event(IPCT_REFRESH);
}
ct_add_counters(ct, ctinfo, skb);
WRITE_UNLOCK(&ip_conntrack_lock);
===== net/ipv4/netfilter/ip_conntrack_ftp.c 1.27 vs edited =====
--- 1.27/net/ipv4/netfilter/ip_conntrack_ftp.c Sun Oct 10 21:44:22 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_ftp.c Sat Oct 16 18:41:37 2004
@@ -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_cache_event(IPCT_HELPINFO);
}
}
===== net/ipv4/netfilter/ip_conntrack_standalone.c 1.51 vs edited =====
--- 1.51/net/ipv4/netfilter/ip_conntrack_standalone.c Thu Oct 7 00:11:17 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_standalone.c Sat Oct 16 18:41:37 2004
@@ -47,6 +47,9 @@
extern atomic_t ip_conntrack_count;
DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+DECLARE_PER_CPU(unsigned long, ip_conntrack_event_cache);
+#endif
static int kill_proto(const struct ip_conntrack *i, void *data)
{
@@ -875,6 +878,10 @@
{
}
+#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
+EXPORT_PER_CPU_SYMBOL(ip_conntrack_event_cache);
+EXPORT_SYMBOL(ip_conntrack_chain);
+#endif
EXPORT_SYMBOL(ip_conntrack_protocol_register);
EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
EXPORT_SYMBOL(invert_tuplepr);
===== net/ipv4/netfilter/ip_conntrack_proto_tcp.c 1.23 vs edited =====
--- 1.23/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Mon Sep 13 02:00:29 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Sat Oct 16 18:42:58 2004
@@ -823,6 +823,32 @@
return NF_ACCEPT;
}
+static inline void
+pickup_connection(struct ip_conntrack *conntrack, struct iphdr *iph,
+ struct tcphdr *th, const struct sk_buff *skb)
+{
+ /*
+ * We are in the middle of a connection,
+ * its history is lost for us.
+ * Let's try to use the data from the packet.
+ */
+ conntrack->proto.tcp.seen[0].td_end =
+ segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
+ conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
+ if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
+ conntrack->proto.tcp.seen[0].td_maxwin = 1;
+ conntrack->proto.tcp.seen[0].td_maxend =
+ conntrack->proto.tcp.seen[0].td_end +
+ conntrack->proto.tcp.seen[0].td_maxwin;
+ conntrack->proto.tcp.seen[0].td_scale = 0;
+
+ /* We assume SACK. Should we assume window scaling too? */
+ conntrack->proto.tcp.seen[0].flags =
+ conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
+ conntrack->proto.tcp.seen[0].loose =
+ conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
+}
+
/* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct ip_conntrack *conntrack,
const struct sk_buff *skb,
@@ -838,6 +864,11 @@
th = skb_header_pointer(skb, iph->ihl * 4,
sizeof(_tcph), &_tcph);
BUG_ON(th == NULL);
+
+ if (test_bit(IPS_PICKUP_BIT, &conntrack->status)) {
+ pickup_connection(conntrack, iph, th, skb);
+ __clear_bit(IPS_PICKUP_BIT, &conntrack->status);
+ }
WRITE_LOCK(&tcp_lock);
old_state = conntrack->proto.tcp.state;
@@ -944,6 +975,10 @@
? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
WRITE_UNLOCK(&tcp_lock);
+ ip_conntrack_cache_event(IPCT_PROTOINFO_VOLATILE);
+ if (new_state != old_state)
+ ip_conntrack_cache_event(IPCT_PROTOINFO);
+
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
@@ -1014,29 +1049,8 @@
} else if (ip_ct_tcp_loose == 0) {
/* Don't try to pick up connections. */
return 0;
- } else {
- /*
- * We are in the middle of a connection,
- * its history is lost for us.
- * Let's try to use the data from the packet.
- */
- conntrack->proto.tcp.seen[0].td_end =
- segment_seq_plus_len(ntohl(th->seq), skb->len,
- iph, th);
- conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
- if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
- conntrack->proto.tcp.seen[0].td_maxwin = 1;
- conntrack->proto.tcp.seen[0].td_maxend =
- conntrack->proto.tcp.seen[0].td_end +
- conntrack->proto.tcp.seen[0].td_maxwin;
- conntrack->proto.tcp.seen[0].td_scale = 0;
-
- /* We assume SACK. Should we assume window scaling too? */
- conntrack->proto.tcp.seen[0].flags =
- conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
- conntrack->proto.tcp.seen[0].loose =
- conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
- }
+ } else
+ pickup_connection(conntrack, iph, th, skb);
conntrack->proto.tcp.seen[1].td_end = 0;
conntrack->proto.tcp.seen[1].td_maxend = 0;
===== net/ipv4/netfilter/ip_conntrack_proto_udp.c 1.18 vs edited =====
--- 1.18/net/ipv4/netfilter/ip_conntrack_proto_udp.c Sun Oct 10 21:44:22 2004
+++ edited/net/ipv4/netfilter/ip_conntrack_proto_udp.c Sat Oct 16 18:41:37 2004
@@ -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_cache_event(IPCT_STATUS);
+ }
} else
ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
===== net/ipv4/netfilter/ip_nat_core.c 1.48 vs edited =====
--- 1.48/net/ipv4/netfilter/ip_nat_core.c Sun Oct 10 21:44:22 2004
+++ edited/net/ipv4/netfilter/ip_nat_core.c Sat Oct 16 18:41:37 2004
@@ -607,6 +607,7 @@
IP_NAT_MANIP_SRC, inv_tuple.src });
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)
prev parent reply other threads:[~2004-10-16 18:21 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-10-15 17:54 [PATCH 2.6] connection tracking events Harald Welte
2004-10-16 13:21 ` Patrick McHardy
2004-10-16 15:07 ` Harald Welte
2004-10-16 15:20 ` Patrick McHardy
2004-10-16 15:32 ` Pablo Neira
2004-10-16 18:21 ` Pablo Neira [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=417166A8.3050809@eurodev.net \
--to=pablo@eurodev.net \
--cc=kaber@trash.net \
--cc=laforge@netfilter.org \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.