[PATCH] Introducing the Change API
Pablo Neira
pablo at eurodev.net
Sat Dec 4 23:15:18 CET 2004
Hi,
I've finished the change API patch which goes on top of the conntrack
event API[1]. This patch provides a way to modify some parts of a
conntrack such as protocol and helper private info.
I've defined three generic functions:
a) helper handlings
generic_change_help
generic_change_new_expect
b) proto handlings
generic_change_proto
Since there are mostly the same thing, if there's any weird protocol, we
can still defined our own function. I've also added a new field in
ip_conntrack_protocol and ip_conntrack_helper, to make their locks, if
any, accessible. So it's flexible enough.
Comments and review welcome.
Next step, work on the ctnetlink-nfnetlink stuff. Is there any plan to
push forward both patches?
Refs:
[1]
https://lists.netfilter.org/pipermail/netfilter-devel/2004-November/017453.html
--
Pablo
-------------- next part --------------
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_amanda.c change/net/ipv4/netfilter/ip_conntrack_amanda.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-12-04 19:35:16.000000000 +0100
@@ -136,6 +136,8 @@
.mask = { .src = { .u = { 0xFFFF } },
.dst = { .protonum = 0xFFFF },
},
+ .change_help = generic_change_help,
+ .change_new_expect = generic_change_new_expect,
};
static void __exit fini(void)
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_core.c change/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_core.c 2004-12-04 20:14:15.000000000 +0100
@@ -1244,6 +1244,51 @@
}
}
+void generic_change_proto(struct ip_conntrack *ct,
+ union ip_conntrack_proto *p)
+{
+ struct ip_conntrack_tuple *t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+ struct ip_conntrack_protocol *proto;
+
+ proto = ip_ct_find_proto(t->dst.protonum);
+ if (proto->lock != NULL) {
+ WRITE_LOCK(proto->lock);
+ memcpy(&ct->proto, p, sizeof(union ip_conntrack_proto));
+ WRITE_UNLOCK(proto->lock);
+ } else
+ memcpy(&ct->proto, p, sizeof(union ip_conntrack_proto));
+}
+
+void generic_change_help(struct ip_conntrack *ct, union ip_conntrack_help *h)
+{
+ struct ip_conntrack_helper *helper= ct->helper;
+
+ if (helper->lock != NULL) {
+ LOCK_BH(helper->lock);
+ memcpy(&ct->help, h, sizeof(ct->help));
+ UNLOCK_BH(helper->lock);
+ } else
+ memcpy(&ct->help, h, sizeof(ct->help));
+}
+
+int generic_change_new_expect(struct ip_conntrack_expect *exp,
+ union ip_conntrack_expect_proto *p,
+ union ip_conntrack_expect_help *h)
+{
+ struct ip_conntrack_helper *helper = exp->expectant->helper;
+
+ if (h == NULL)
+ return -1;
+ if (helper->lock != NULL) {
+ LOCK_BH(helper->lock);
+ memcpy(&exp->help, h, sizeof(exp->help));
+ UNLOCK_BH(helper->lock);
+ } else
+ memcpy(&exp->help, h, sizeof(exp->help));
+
+ return 0;
+}
+
/* Fast function for those who don't want to parse /proc (and I don't
blame them). */
/* Reversing the socket's dst/src point of view gives us the reply
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_ftp.c change/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_ftp.c 2004-12-04 19:35:11.000000000 +0100
@@ -440,6 +440,9 @@
ftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
ftp[i].me = ip_conntrack_ftp;
ftp[i].help = help;
+ ftp[i].lock = &ip_ftp_lock;
+ ftp[i].change_help = generic_change_help;
+ ftp[i].change_new_expect = generic_change_new_expect;
tmpname = &ftp_names[i][0];
if (ports[i] == FTP_PORT)
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_irc.c change/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_irc.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_irc.c 2004-12-04 19:34:57.000000000 +0100
@@ -271,6 +271,9 @@
hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
hlpr->me = ip_conntrack_irc;
hlpr->help = help;
+ hlpr->lock = &irc_buffer_lock;
+ hlpr->change_help = generic_change_help;
+ hlpr->change_new_expect = generic_change_new_expect;
tmpname = &irc_names[i][0];
if (ports[i] == IRC_PORT)
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c change/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-12-04 19:09:42.000000000 +0100
@@ -109,16 +109,17 @@
return NF_ACCEPT;
}
+static u_int8_t valid_new[] = {
+ [ICMP_ECHO] = 1,
+ [ICMP_TIMESTAMP] = 1,
+ [ICMP_INFO_REQUEST] = 1,
+ [ICMP_ADDRESS] = 1
+};
+
/* Called when a new connection for this protocol found. */
static int icmp_new(struct ip_conntrack *conntrack,
const struct sk_buff *skb)
{
- 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. */
@@ -266,6 +267,17 @@
return icmp_error_message(skb, ctinfo, hooknum);
}
+static int icmp_change_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;
+}
+
struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
{
.proto = IPPROTO_ICMP,
@@ -277,4 +289,6 @@
.packet = icmp_packet,
.new = icmp_new,
.error = icmp_error,
+ .change_check_tuples = icmp_change_check_tuples,
+ .change_proto = generic_change_proto,
};
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_sctp.c change/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-12-04 19:17:53.000000000 +0100
@@ -506,6 +506,7 @@
struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
.proto = IPPROTO_SCTP,
.name = "sctp",
+ .lock = &sctp_lock,
.pkt_to_tuple = sctp_pkt_to_tuple,
.invert_tuple = sctp_invert_tuple,
.print_tuple = sctp_print_tuple,
@@ -514,6 +515,7 @@
.new = sctp_new,
.destroy = NULL,
.exp_matches_pkt = sctp_exp_matches_pkt,
+ .change_proto = generic_change_proto,
.me = THIS_MODULE
};
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c change/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-12-04 19:09:06.000000000 +0100
@@ -1079,6 +1079,7 @@
{
.proto = IPPROTO_TCP,
.name = "tcp",
+ .lock = &tcp_lock,
.pkt_to_tuple = tcp_pkt_to_tuple,
.invert_tuple = tcp_invert_tuple,
.print_tuple = tcp_print_tuple,
@@ -1087,4 +1088,5 @@
.new = tcp_new,
.exp_matches_pkt = tcp_exp_matches_pkt,
.error = tcp_error,
+ .change_proto = generic_change_proto,
};
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_udp.c change/net/ipv4/netfilter/ip_conntrack_proto_udp.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-12-04 19:09:13.000000000 +0100
@@ -146,4 +146,5 @@
.packet = udp_packet,
.new = udp_new,
.error = udp_error,
+ .change_proto = generic_change_proto,
};
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_standalone.c change/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-12-04 14:58:09.000000000 +0100
@@ -880,6 +880,9 @@
{
}
+EXPORT_SYMBOL(generic_change_proto);
+EXPORT_SYMBOL(generic_change_help);
+EXPORT_SYMBOL(generic_change_new_expect);
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
EXPORT_SYMBOL(ip_conntrack_chain);
EXPORT_SYMBOL(ip_conntrack_register_notifier);
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/net/ipv4/netfilter/ip_conntrack_tftp.c change/net/ipv4/netfilter/ip_conntrack_tftp.c
--- linux-2.5/net/ipv4/netfilter/ip_conntrack_tftp.c 2004-12-04 20:13:32.000000000 +0100
+++ change/net/ipv4/netfilter/ip_conntrack_tftp.c 2004-12-04 19:34:43.000000000 +0100
@@ -123,6 +123,8 @@
tftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
tftp[i].me = THIS_MODULE;
tftp[i].help = tftp_help;
+ tftp[i].change_help = generic_change_help;
+ tftp[i].change_new_expect = generic_change_new_expect;
tmpname = &tftp_names[i][0];
if (ports[i] == TFTP_PORT)
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/include/linux/netfilter_ipv4/ip_conntrack_helper.h change/include/linux/netfilter_ipv4/ip_conntrack_helper.h
--- linux-2.5/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-12-04 20:13:32.000000000 +0100
+++ change/include/linux/netfilter_ipv4/ip_conntrack_helper.h 2004-12-04 20:02:28.000000000 +0100
@@ -18,6 +18,7 @@
unsigned int max_expected; /* Maximum number of concurrent
* expected connections */
unsigned int timeout; /* timeout for expecteds */
+ spinlock_t *lock; /* protect private info and buffer */
/* Mask of things we will help (compared against server response) */
struct ip_conntrack_tuple tuple;
@@ -28,6 +29,11 @@
int (*help)(struct sk_buff *skb,
struct ip_conntrack *ct,
enum ip_conntrack_info conntrackinfo);
+
+ void (*change_help)(struct ip_conntrack *, union ip_conntrack_help *);
+ int (*change_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 *);
@@ -45,5 +51,10 @@
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 void generic_change_help(struct ip_conntrack *ct,
+ union ip_conntrack_help *h);
+extern int generic_change_new_expect(struct ip_conntrack_expect *exp,
+ union ip_conntrack_expect_proto *p,
+ union ip_conntrack_expect_help *h);
#endif /*_IP_CONNTRACK_HELPER_H*/
Los ficheros binarios linux-2.5/include/linux/netfilter_ipv4/.ip_conntrack.h.swp y change/include/linux/netfilter_ipv4/.ip_conntrack.h.swp son distintos
diff -Nru --exclude='*cmd.c' --exclude='*.ko' --exclude='*.cmd' --exclude='*.o' --exclude=Makefile --exclude=SCCS --exclude='*.rej' --exclude='*.d' --exclude='*.mod.c' linux-2.5/include/linux/netfilter_ipv4/ip_conntrack_protocol.h change/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
--- linux-2.5/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-12-04 20:13:32.000000000 +0100
+++ change/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-12-04 19:37:57.000000000 +0100
@@ -13,6 +13,9 @@
/* Protocol name */
const char *name;
+ /* Lock which protects private proto stuff */
+ rwlock_t *lock;
+
/* Try to fill in the third arg: dataoff is offset past IP
hdr. Return true if possible. */
int (*pkt_to_tuple)(const struct sk_buff *skb,
@@ -51,6 +54,17 @@
int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
unsigned int hooknum);
+ /* check if tuples are valid for a new connection */
+ int (*change_check_tuples)(struct ip_conntrack_tuple *orig,
+ struct ip_conntrack_tuple *reply);
+
+ /* check protocol data is valid */
+ int (*change_check_proto)(union ip_conntrack_proto *p);
+
+ /* change protocol info on behalf of ctnetlink */
+ void (*change_proto)(struct ip_conntrack *ct,
+ union ip_conntrack_proto *p);
+
/* Module (if any) which this is connected to. */
struct module *me;
};
@@ -67,6 +81,10 @@
return ip_ct_protos[protocol];
}
+/* Change API */
+extern void generic_change_proto(struct ip_conntrack *conntrack,
+ union ip_conntrack_proto *p);
+
/* Existing built-in protocols */
extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
More information about the netfilter-devel
mailing list