1--- ../kernel/linux-2.4.20-pre4/net/ipv4/netfilter/ip_tables.c	2002-08-29 01:56:13.000000000 +0200
2+++ linux-2.4.20-pre4/net/ipv4/netfilter/ip_tables.c	2002-08-29 20:30:37.000000000 +0200
3@@ -1699,14 +1699,15 @@
4 = { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL };
5 
6 #ifdef CONFIG_PROC_FS
7-static inline int print_name(const struct ipt_table *t,
8+static inline int print_name(const char *i,
9 			     off_t start_offset, char *buffer, int length,
10 			     off_t *pos, unsigned int *count)
11 {
12 	if ((*count)++ >= start_offset) {
13 		unsigned int namelen;
14 
15-		namelen = sprintf(buffer + *pos, "%s\n", t->name);
16+		namelen = sprintf(buffer + *pos, "%s\n",
17+				  i + sizeof(struct list_head));
18 		if (*pos + namelen > length) {
19 			/* Stop iterating */
20 			return 1;
21@@ -1724,7 +1725,7 @@
22 	if (down_interruptible(&ipt_mutex) != 0)
23 		return 0;
24 
25-	LIST_FIND(&ipt_tables, print_name, struct ipt_table *,
26+	LIST_FIND(&ipt_tables, print_name, void *,
27 		  offset, buffer, length, &pos, &count);
28 
29 	up(&ipt_mutex);
30@@ -1733,6 +1734,46 @@
31 	*start=(char *)((unsigned long)count-offset);
32 	return pos;
33 }
34+
35+static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
36+{
37+	off_t pos = 0;
38+	unsigned int count = 0;
39+
40+	if (down_interruptible(&ipt_mutex) != 0)
41+		return 0;
42+
43+	LIST_FIND(&ipt_target, print_name, void *,
44+		  offset, buffer, length, &pos, &count);
45+	
46+	up(&ipt_mutex);
47+
48+	*start = (char *)((unsigned long)count - offset);
49+	return pos;
50+}
51+
52+static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
53+{
54+	off_t pos = 0;
55+	unsigned int count = 0;
56+
57+	if (down_interruptible(&ipt_mutex) != 0)
58+		return 0;
59+	
60+	LIST_FIND(&ipt_match, print_name, void *,
61+		  offset, buffer, length, &pos, &count);
62+
63+	up(&ipt_mutex);
64+
65+	*start = (char *)((unsigned long)count - offset);
66+	return pos;
67+}
68+
69+static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] =
70+{ { "ip_tables_names", ipt_get_tables },
71+  { "ip_tables_targets", ipt_get_targets },
72+  { "ip_tables_matches", ipt_get_matches },
73+  { NULL, NULL} };
74 #endif /*CONFIG_PROC_FS*/
75 
76 static int __init init(void)
77@@ -1758,13 +1799,19 @@
78 #ifdef CONFIG_PROC_FS
79 	{
80 	struct proc_dir_entry *proc;
81+	int i;
82 
83-	proc = proc_net_create("ip_tables_names", 0, ipt_get_tables);
84-	if (!proc) {
85-		nf_unregister_sockopt(&ipt_sockopts);
86-		return -ENOMEM;
87+	for (i = 0; ipt_proc_entry[i].name; i++) {
88+		proc = proc_net_create(ipt_proc_entry[i].name, 0,
89+				       ipt_proc_entry[i].get_info);
90+		if (!proc) {
91+			while (--i >= 0)
92+				proc_net_remove(ipt_proc_entry[i].name);
93+			nf_unregister_sockopt(&ipt_sockopts);
94+			return -ENOMEM;
95+		}
96+		proc->owner = THIS_MODULE;
97 	}
98-	proc->owner = THIS_MODULE;
99 	}
100 #endif
101 
102@@ -1776,7 +1823,11 @@
103 {
104 	nf_unregister_sockopt(&ipt_sockopts);
105 #ifdef CONFIG_PROC_FS
106-	proc_net_remove("ip_tables_names");
107+	{
108+	int i;
109+	for (i = 0; ipt_proc_entry[i].name; i++)
110+		proc_net_remove(ipt_proc_entry[i].name);
111+	}
112 #endif
113 }
114 
115