[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 03071) [Patch] ip6_conntrack - seq_file API
- To: usagi-users@xxxxxxxxxxxxxx
- Subject: (usagi-users 03071) [Patch] ip6_conntrack - seq_file API
- From: Michal Rokos <michal@xxxxxxxxxx>
- Date: Thu, 14 Oct 2004 19:51:22 +0200
- Reply-to: usagi-users@xxxxxxxxxxxxxx
- Resent-date: Fri, 15 Oct 2004 11:32:10 +0900
- Resent-from: sekiya@xxxxxxxxxxxxxx
- Resent-message-id: <200410151132.FMLAAB13904.usagi-users@linux-ipv6.org>
- Resent-to: usagi-users@xxxxxxxxxxxxxx (moderated)
- User-agent: KMail/1.7
Hello,
when I was in it, I ported ip6_conntrack for seq_file API too.
Michal
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/10/14 16:58:01+02:00 michal@xxxxxxxxxxxxxxxxx
# Tiny fixes for seq_file API migration.
#
# net/ipv6/netfilter/ip6_conntrack_proto_icmpv6.c
# 2004/10/14 16:57:46+02:00 michal@xxxxxxxxxxxxxxxxx +1 -0
# Missing include.
#
# net/ipv6/netfilter/ip6_conntrack_proto_generic.c
# 2004/10/14 16:57:46+02:00 michal@xxxxxxxxxxxxxxxxx +1 -1
# Fix typo.
#
# ChangeSet
# 2004/10/14 16:42:48+02:00 michal@xxxxxxxxxxxxxxxxx
# Make use seq_file API for IPv6 conntrack.
#
# net/ipv6/netfilter/ip6_conntrack_standalone.c
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +181 -105
# Make use seq_file API for IPv6 conntrack.
#
# net/ipv6/netfilter/ip6_conntrack_proto_udp.c
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +22 -11
# Make use seq_file API for IPv6 conntrack.
#
# net/ipv6/netfilter/ip6_conntrack_proto_tcp.c
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +23 -12
# Make use seq_file API for IPv6 conntrack.
#
# net/ipv6/netfilter/ip6_conntrack_proto_icmpv6.c
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +25 -14
# Make use seq_file API for IPv6 conntrack.
#
# net/ipv6/netfilter/ip6_conntrack_proto_generic.c
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +19 -9
# Make use seq_file API for IPv6 conntrack.
#
# include/linux/netfilter_ipv6/ip6_conntrack_protocol.h
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +4 -4
# Make use seq_file API for IPv6 conntrack.
#
# include/linux/netfilter_ipv6/ip6_conntrack_core.h
# 2004/10/14 16:42:30+02:00 michal@xxxxxxxxxxxxxxxxx +1 -0
# Make use seq_file API for IPv6 conntrack.
#
diff -Nru a/include/linux/netfilter_ipv6/ip6_conntrack_core.h b/include/linux/netfilter_ipv6/ip6_conntrack_core.h
--- a/include/linux/netfilter_ipv6/ip6_conntrack_core.h 2004-10-14 17:05:57 +02:00
+++ b/include/linux/netfilter_ipv6/ip6_conntrack_core.h 2004-10-14 17:05:57 +02:00
@@ -65,5 +65,6 @@
extern struct list_head *ip6_conntrack_hash;
extern struct list_head ip6_conntrack_expect_list;
DECLARE_RWLOCK_EXTERN(ip6_conntrack_lock);
+DECLARE_RWLOCK_EXTERN(ip6_conntrack_expect_tuple_lock);
#endif /* _IP6_CONNTRACK_CORE_H */
diff -Nru a/include/linux/netfilter_ipv6/ip6_conntrack_protocol.h b/include/linux/netfilter_ipv6/ip6_conntrack_protocol.h
--- a/include/linux/netfilter_ipv6/ip6_conntrack_protocol.h 2004-10-14 17:05:57 +02:00
+++ b/include/linux/netfilter_ipv6/ip6_conntrack_protocol.h 2004-10-14 17:05:57 +02:00
@@ -41,12 +41,12 @@
const struct ip6_conntrack_tuple *orig);
/* Print out the per-protocol part of the tuple. */
- unsigned int (*print_tuple)(char *buffer,
- const struct ip6_conntrack_tuple *);
+ int (*print_tuple)(struct seq_file *s,
+ const struct ip6_conntrack_tuple *tuple);
/* Print out the private part of the conntrack. */
- unsigned int (*print_conntrack)(char *buffer,
- const struct ip6_conntrack *);
+ int (*print_conntrack)(struct seq_file *s,
+ const struct ip6_conntrack *conntrack);
/* Returns verdict for packet, or -1 for invalid. */
int (*packet)(struct ip6_conntrack *conntrack,
diff -Nru a/net/ipv6/netfilter/ip6_conntrack_proto_generic.c b/net/ipv6/netfilter/ip6_conntrack_proto_generic.c
--- a/net/ipv6/netfilter/ip6_conntrack_proto_generic.c 2004-10-14 17:05:57 +02:00
+++ b/net/ipv6/netfilter/ip6_conntrack_proto_generic.c 2004-10-14 17:05:57 +02:00
@@ -43,15 +43,15 @@
}
/* Print out the per-protocol part of the tuple. */
-static unsigned int generic_print_tuple(char *buffer,
- const struct ip6_conntrack_tuple *tuple)
+static int generic_print_tuple(struct seq_file *s,
+ const struct ip6_conntrack_tuple *tuple)
{
return 0;
}
/* Print out the private part of the conntrack. */
-static unsigned int generic_print_conntrack(char *buffer,
- const struct ip6_conntrack *state)
+static int generic_print_conntrack(struct seq_file *s,
+ const struct ip6_conntrack *state)
{
return 0;
}
@@ -75,8 +75,18 @@
return 1;
}
-struct ip6_conntrack_protocol ip6_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 };
-
+struct ip6_conntrack_protocol ip6_conntrack_generic_protocol =
+{
+ .list = { NULL, NULL },
+ .proto = 0,
+ .name = "unknown",
+ .pkt_to_tuple = generic_pkt_to_tuple,
+ .invert_tuple = generic_invert_tuple,
+ .print_tuple = generic_print_tuple,
+ .print_conntrack = generic_print_conntrack,
+ .packet = established,
+ .new = new,
+ .destroy = NULL,
+ .exp_matches_pkt = NULL,
+ .me = NULL
+};
diff -Nru a/net/ipv6/netfilter/ip6_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/ip6_conntrack_proto_icmpv6.c
--- a/net/ipv6/netfilter/ip6_conntrack_proto_icmpv6.c 2004-10-14 17:05:57 +02:00
+++ b/net/ipv6/netfilter/ip6_conntrack_proto_icmpv6.c 2004-10-14 17:05:57 +02:00
@@ -18,6 +18,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/timer.h>
+#include <linux/seq_file.h>
#include <linux/netfilter.h>
#include <linux/in.h>
#include <linux/icmpv6.h>
@@ -68,21 +69,21 @@
}
/* Print out the per-protocol part of the tuple. */
-static unsigned int icmpv6_print_tuple(char *buffer,
- const struct ip6_conntrack_tuple *tuple)
+static int icmpv6_print_tuple(struct seq_file *s,
+ const struct ip6_conntrack_tuple *tuple)
{
- return sprintf(buffer, "type=%u code=%u id=%u ",
- tuple->dst.u.icmpv6.type,
- tuple->dst.u.icmpv6.code,
- ntohs(tuple->src.u.icmpv6.id));
+ return seq_printf(s, "type=%u code=%u id=%u ",
+ tuple->dst.u.icmpv6.type,
+ tuple->dst.u.icmpv6.code,
+ ntohs(tuple->src.u.icmpv6.id));
}
/* Print out the private part of the conntrack. */
-static unsigned int icmpv6_print_conntrack(char *buffer,
- const struct ip6_conntrack *conntrack)
+static int icmpv6_print_conntrack(struct seq_file *s,
+ const struct ip6_conntrack *conntrack)
{
- return sprintf(buffer, "count=%u ",
- atomic_read(&conntrack->proto.icmpv6.count));
+ return seq_printf(s, "count=%u ",
+ atomic_read(&conntrack->proto.icmpv6.count));
}
/* Returns verdict for packet, or -1 for invalid. */
@@ -129,7 +130,18 @@
return 1;
}
-struct ip6_conntrack_protocol ip6_conntrack_protocol_icmpv6
-= { { NULL, NULL }, IPPROTO_ICMPV6, "icmpv6",
- icmpv6_pkt_to_tuple, icmpv6_invert_tuple, icmpv6_print_tuple,
- icmpv6_print_conntrack, icmpv6_packet, icmpv6_new, NULL, NULL, NULL };
+struct ip6_conntrack_protocol ip6_conntrack_protocol_icmpv6 =
+{
+ .list = { NULL, NULL },
+ .proto = IPPROTO_ICMPV6,
+ .name = "icmpv6",
+ .pkt_to_tuple = icmpv6_pkt_to_tuple,
+ .invert_tuple = icmpv6_invert_tuple,
+ .print_tuple = icmpv6_print_tuple,
+ .print_conntrack = icmpv6_print_conntrack,
+ .packet = icmpv6_packet,
+ .new = icmpv6_new,
+ .destroy = NULL,
+ .exp_matches_pkt = NULL,
+ .me = NULL
+};
diff -Nru a/net/ipv6/netfilter/ip6_conntrack_proto_tcp.c b/net/ipv6/netfilter/ip6_conntrack_proto_tcp.c
--- a/net/ipv6/netfilter/ip6_conntrack_proto_tcp.c 2004-10-14 17:05:57 +02:00
+++ b/net/ipv6/netfilter/ip6_conntrack_proto_tcp.c 2004-10-14 17:05:57 +02:00
@@ -138,17 +138,17 @@
}
/* Print out the per-protocol part of the tuple. */
-static unsigned int tcp_print_tuple(char *buffer,
- const struct ip6_conntrack_tuple *tuple)
+static int tcp_print_tuple(struct seq_file *s,
+ const struct ip6_conntrack_tuple *tuple)
{
- return sprintf(buffer, "sport=%hu dport=%hu ",
- ntohs(tuple->src.u.tcp.port),
- ntohs(tuple->dst.u.tcp.port));
+ return seq_printf(s, "sport=%hu dport=%hu ",
+ ntohs(tuple->src.u.tcp.port),
+ ntohs(tuple->dst.u.tcp.port));
}
/* Print out the private part of the conntrack. */
-static unsigned int tcp_print_conntrack(char *buffer,
- const struct ip6_conntrack *conntrack)
+static int tcp_print_conntrack(struct seq_file *s,
+ const struct ip6_conntrack *conntrack)
{
enum tcp_conntrack state;
@@ -156,7 +156,7 @@
state = conntrack->proto.tcp.state;
READ_UNLOCK(&tcp_lock);
- return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
+ return seq_printf(s, "%s ", tcp_conntrack_names[state]);
}
static unsigned int get_conntrack_index(const struct tcphdr *tcph)
@@ -267,7 +267,18 @@
return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
}
-struct ip6_conntrack_protocol ip6_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 };
+struct ip6_conntrack_protocol ip6_conntrack_protocol_tcp =
+{
+ .list = { NULL, NULL },
+ .proto = IPPROTO_TCP,
+ .name = "tcp",
+ .pkt_to_tuple = tcp_pkt_to_tuple,
+ .invert_tuple = tcp_invert_tuple,
+ .print_tuple = tcp_print_tuple,
+ .print_conntrack = tcp_print_conntrack,
+ .packet = tcp_packet,
+ .new = tcp_new,
+ .destroy = NULL,
+ .exp_matches_pkt = tcp_exp_matches_pkt,
+ .me = NULL
+};
diff -Nru a/net/ipv6/netfilter/ip6_conntrack_proto_udp.c b/net/ipv6/netfilter/ip6_conntrack_proto_udp.c
--- a/net/ipv6/netfilter/ip6_conntrack_proto_udp.c 2004-10-14 17:05:57 +02:00
+++ b/net/ipv6/netfilter/ip6_conntrack_proto_udp.c 2004-10-14 17:05:57 +02:00
@@ -49,17 +49,17 @@
}
/* Print out the per-protocol part of the tuple. */
-static unsigned int udp_print_tuple(char *buffer,
- const struct ip6_conntrack_tuple *tuple)
+static int udp_print_tuple(struct seq_file *s,
+ const struct ip6_conntrack_tuple *tuple)
{
- return sprintf(buffer, "sport=%hu dport=%hu ",
- ntohs(tuple->src.u.udp.port),
- ntohs(tuple->dst.u.udp.port));
+ return seq_printf(s, "sport=%hu dport=%hu ",
+ ntohs(tuple->src.u.udp.port),
+ ntohs(tuple->dst.u.udp.port));
}
/* Print out the private part of the conntrack. */
-static unsigned int udp_print_conntrack(char *buffer,
- const struct ip6_conntrack *conntrack)
+static int udp_print_conntrack(struct seq_file *s,
+ const struct ip6_conntrack *conntrack)
{
return 0;
}
@@ -89,7 +89,18 @@
return 1;
}
-struct ip6_conntrack_protocol ip6_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 };
+struct ip6_conntrack_protocol ip6_conntrack_protocol_udp =
+{
+ .list = { NULL, NULL },
+ .proto = IPPROTO_UDP,
+ .name = "udp",
+ .pkt_to_tuple = udp_pkt_to_tuple,
+ .invert_tuple = udp_invert_tuple,
+ .print_tuple = udp_print_tuple,
+ .print_conntrack = udp_print_conntrack,
+ .packet = udp_packet,
+ .new = udp_new,
+ .destroy = NULL,
+ .exp_matches_pkt = NULL,
+ .me = NULL
+};
diff -Nru a/net/ipv6/netfilter/ip6_conntrack_standalone.c b/net/ipv6/netfilter/ip6_conntrack_standalone.c
--- a/net/ipv6/netfilter/ip6_conntrack_standalone.c 2004-10-14 17:05:57 +02:00
+++ b/net/ipv6/netfilter/ip6_conntrack_standalone.c 2004-10-14 17:05:57 +02:00
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/version.h>
#include <net/checksum.h>
@@ -58,139 +59,203 @@
*((u_int8_t *) data));
}
-static unsigned int
-print_tuple(char *buffer, const struct ip6_conntrack_tuple *tuple,
+#ifdef CONFIG_PROC_FS
+static int
+print_tuple(struct seq_file *s, const struct ip6_conntrack_tuple *tuple,
struct ip6_conntrack_protocol *proto)
{
- int len;
-
- len = sprintf(buffer, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ",
- NIP6(tuple->src.ip), NIP6(tuple->dst.ip));
-
- len += proto->print_tuple(buffer + len, tuple);
+ seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ",
+ NIP6(tuple->src.ip), NIP6(tuple->dst.ip));
- return len;
+ return proto->print_tuple(s, tuple);
}
-/* FIXME: Don't print source proto part. --RR */
-static unsigned int
-print_expect(char *buffer, const struct ip6_conntrack_expect *expect)
+static void *ct_seq_start(struct seq_file *s, loff_t *pos)
{
- unsigned int len;
-
- if (expect->expectant->helper->timeout)
- len = sprintf(buffer, "EXPECTING: %lu ",
- timer_pending(&expect->timeout)
- ? (expect->timeout.expires - jiffies)/HZ : 0);
- else
- len = sprintf(buffer, "EXPECTING: - ");
- len += sprintf(buffer + len, "use=%u proto=%u ",
- atomic_read(&expect->use), expect->tuple.dst.protonum);
- len += print_tuple(buffer + len, &expect->tuple,
- __ip6_ct_find_proto(expect->tuple.dst.protonum));
- len += sprintf(buffer + len, "\n");
- return len;
-}
-
-static unsigned int
-print_conntrack(char *buffer, struct ip6_conntrack *conntrack)
-{
- unsigned int len;
- struct ip6_conntrack_protocol *proto
- = __ip6_ct_find_proto(conntrack->tuplehash[IP6_CT_DIR_ORIGINAL]
- .tuple.dst.protonum);
-
- len = sprintf(buffer, "%-8s %u %lu ",
- proto->name,
- conntrack->tuplehash[IP6_CT_DIR_ORIGINAL]
- .tuple.dst.protonum,
- timer_pending(&conntrack->timeout)
- ? (conntrack->timeout.expires - jiffies)/HZ : 0);
-
- len += proto->print_conntrack(buffer + len, conntrack);
- len += print_tuple(buffer + len,
- &conntrack->tuplehash[IP6_CT_DIR_ORIGINAL].tuple,
- proto);
- if (!(test_bit(IP6S_SEEN_REPLY_BIT, &conntrack->status)))
- len += sprintf(buffer + len, "[UNREPLIED] ");
- len += print_tuple(buffer + len,
- &conntrack->tuplehash[IP6_CT_DIR_REPLY].tuple,
- proto);
- if (test_bit(IP6S_ASSURED_BIT, &conntrack->status))
- len += sprintf(buffer + len, "[ASSURED] ");
- len += sprintf(buffer + len, "use=%u ",
- atomic_read(&conntrack->ct_general.use));
- len += sprintf(buffer + len, "\n");
+ if (*pos >= ip6_conntrack_htable_size)
+ return NULL;
+ return &ip6_conntrack_hash[*pos];
+}
+
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
+}
- return len;
+static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ if (*pos >= ip6_conntrack_htable_size)
+ return NULL;
+ return &ip6_conntrack_hash[*pos];
}
-/* Returns true when finished. */
-static inline int
-conntrack_iterate(const struct ip6_conntrack_tuple_hash *hash,
- char *buffer, off_t offset, off_t *upto,
- unsigned int *len, unsigned int maxlen)
+/* return 0 on success, 1 in case of error */
+static int ct_seq_real_show(const struct ip6_conntrack_tuple_hash *hash,
+ struct seq_file *s)
{
- unsigned int newlen;
- IP6_NF_ASSERT(hash->ctrack);
+ struct ip6_conntrack *conntrack = hash->ctrack;
+ struct ip6_conntrack_protocol *proto;
MUST_BE_READ_LOCKED(&ip6_conntrack_lock);
+ IP6_NF_ASSERT(hash->ctrack);
+
/* Only count originals */
if (DIRECTION(hash))
return 0;
- if ((*upto)++ < offset)
- return 0;
+ proto = __ip6_ct_find_proto(conntrack->tuplehash[IP6_CT_DIR_ORIGINAL]
+ .tuple.dst.protonum);
+
+ IP6_NF_ASSERT(proto);
+
+ if (seq_printf(s, "%-8s %u %lu ",
+ proto->name,
+ conntrack->tuplehash[IP6_CT_DIR_ORIGINAL]
+ .tuple.dst.protonum,
+ timer_pending(&conntrack->timeout)
+ ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
+ return 1;
- newlen = print_conntrack(buffer + *len, hash->ctrack);
- if (*len + newlen > maxlen)
+ if (proto->print_conntrack(s, conntrack))
+ return 1;
+
+ if (print_tuple(s, &conntrack->tuplehash[IP6_CT_DIR_ORIGINAL].tuple,
+ proto))
return 1;
- else *len += newlen;
+
+ if (!(test_bit(IP6S_SEEN_REPLY_BIT, &conntrack->status)))
+ if (seq_printf(s, "[UNREPLIED] "))
+ return 1;
+ if (print_tuple(s, &conntrack->tuplehash[IP6_CT_DIR_REPLY].tuple,
+ proto))
+ return 1;
+
+ if (test_bit(IP6S_ASSURED_BIT, &conntrack->status))
+ if (seq_printf(s, "[ASSURED] "))
+ return 1;
+
+ if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
+ return 1;
+
return 0;
}
-static int
-list_conntracks(char *buffer, char **start, off_t offset, int length)
+static int ct_seq_show(struct seq_file *s, void *v)
{
- unsigned int i;
- unsigned int len = 0;
- off_t upto = 0;
- struct list_head *e;
+ struct list_head *list = v;
+ int ret = 0;
+ /* FIXME: Simply truncates if hash chain too long. */
READ_LOCK(&ip6_conntrack_lock);
- /* Traverse hash; print originals then reply. */
- for (i = 0; i < ip6_conntrack_htable_size; i++) {
- if (LIST_FIND(&ip6_conntrack_hash[i], conntrack_iterate,
- struct ip6_conntrack_tuple_hash *,
- buffer, offset, &upto, &len, length))
- goto finished;
- }
+ if (LIST_FIND(list, ct_seq_real_show,
+ struct ip6_conntrack_tuple_hash *, s))
+ ret = -ENOSPC;
+ READ_UNLOCK(&ip6_conntrack_lock);
+ return ret;
+}
- /* Now iterate through expecteds. */
- for (e = ip6_conntrack_expect_list.next;
- e != &ip6_conntrack_expect_list; e = e->next) {
- unsigned int last_len;
- struct ip6_conntrack_expect *expect
- = (struct ip6_conntrack_expect *)e;
- if (upto++ < offset) continue;
-
- last_len = len;
- len += print_expect(buffer + len, expect);
- if (len > length) {
- len = last_len;
- goto finished;
- }
+static struct seq_operations ct_seq_ops = {
+ .start = ct_seq_start,
+ .next = ct_seq_next,
+ .stop = ct_seq_stop,
+ .show = ct_seq_show
+};
+
+static int ct_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &ct_seq_ops);
+}
+
+static struct file_operations ct_file_ops = {
+ .owner = THIS_MODULE,
+ .open = ct_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/* expects */
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+ struct list_head *e = &ip6_conntrack_expect_list;
+ loff_t i;
+
+ /* strange seq_file api calls stop even if we fail,
+ * thus we need to grab lock since stop unlocks */
+ READ_LOCK(&ip6_conntrack_lock);
+ READ_LOCK(&ip6_conntrack_expect_tuple_lock);
+
+ if (list_empty(e))
+ return NULL;
+
+ for (i = 0; i <= *pos; i++) {
+ e = e->next;
+ if (e == &ip6_conntrack_expect_list)
+ return NULL;
}
+ return e;
+}
- finished:
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct list_head *e = v;
+
+ e = e->next;
+
+ if (e == &ip6_conntrack_expect_list)
+ return NULL;
+
+ return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
+ READ_UNLOCK(&ip6_conntrack_expect_tuple_lock);
READ_UNLOCK(&ip6_conntrack_lock);
+}
- /* `start' hack - see fs/proc/generic.c line ~165 */
- *start = (char *)((unsigned int)upto - offset);
- return len;
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+ struct ip6_conntrack_expect *expect = v;
+
+ if (expect->expectant->helper->timeout)
+ seq_printf(s, "%lu ",
+ timer_pending(&expect->timeout)
+ ? (expect->timeout.expires - jiffies)/HZ : 0);
+ else
+ seq_printf(s, "- ");
+
+ seq_printf(s, "use=%u proto=%u ",
+ atomic_read(&expect->use), expect->tuple.dst.protonum);
+
+ print_tuple(s, &expect->tuple,
+ __ip6_ct_find_proto(expect->tuple.dst.protonum));
+
+ return seq_putc(s, '\n');
+}
+
+static struct seq_operations exp_seq_ops = {
+ .start = exp_seq_start,
+ .next = exp_seq_next,
+ .stop = exp_seq_stop,
+ .show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &exp_seq_ops);
}
+
+static struct file_operations exp_file_ops = {
+ .owner = THIS_MODULE,
+ .open = exp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+#endif
static unsigned int ip6_confirm(unsigned int hooknum,
struct sk_buff **pskb,
@@ -360,7 +425,9 @@
static int init_or_cleanup(int init)
{
- struct proc_dir_entry *proc;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc, *proc_exp;
+#endif
int ret = 0;
if (!init) goto cleanup;
@@ -373,14 +440,19 @@
if (ret < 0)
goto cleanup_nothing;
- proc = proc_net_create("ip6_conntrack",0,list_conntracks);
+#ifdef CONFIG_PROC_FS
+ proc = proc_net_fops_create("ip6_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
- proc->owner = THIS_MODULE;
+
+ proc_exp = proc_net_fops_create("ip6_conntrack_expect", 0440,
+ &exp_file_ops);
+ if (!proc_exp) goto cleanup_proc;
+#endif
ret = nf_register_hook(&ip6_conntrack_in_ops);
if (ret < 0) {
printk("ip6_conntrack: can't register pre-routing hook.\n");
- goto cleanup_proc;
+ goto cleanup_proc_exp;
}
ret = nf_register_hook(&ip6_conntrack_local_out_ops);
if (ret < 0) {
@@ -408,9 +480,13 @@
nf_unregister_hook(&ip6_conntrack_local_out_ops);
cleanup_inops:
nf_unregister_hook(&ip6_conntrack_in_ops);
+ cleanup_proc_exp:
+#ifdef CONFIG_PROC_FS
+ proc_net_remove("ip6_conntrack_exp");
cleanup_proc:
proc_net_remove("ip6_conntrack");
cleanup_init:
+#endif
ip6_conntrack_cleanup();
cleanup_reasm:
ip6_ct_frags_cleanup();