Here is the sample patch that fixes ip_tables_matches, but I still challenge the usefulness of /proc/net/ip_tables_* altogether. Those files should have been removed, or appropriately upgraded when revision support was introduced. http://picpaste.de/usefulornot_1.png I am not fond of it, at all. Doing the same for targets - code replication here we come. The LOC for it would have been better spent at the previously-posted pretty-printer (knowing that text printing meets the usual resistance). ---8<--- parent d8bf62a172295f26d960cea92aead0ce78ca524c (v2.6.29-rc2-21-gd8bf62a) commit 3f1d7c73afeeb637ef05eba0ad7ccb55305ab8f2 Author: Jan Engelhardt <jengelh@xxxxxxxxxx> Date: Tue Jan 27 23:21:16 2009 +0100 netfilter: make proc/net/ip_tables_matches print names from foreign NFPROTO The ugliness this code adds could have been better spent at a full and much more helpful dump. --- net/netfilter/x_tables.c | 115 +++++++++++++++++++++++++++++-------- 1 files changed, 90 insertions(+), 25 deletions(-) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index bfbf521..329c01c 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -827,39 +827,96 @@ static const struct file_operations xt_table_ops = { .release = seq_release_net, }; -static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) +struct match_trav { + struct list_head *head, *curr; + uint8_t class, nfproto; +}; + +enum { + MATCHTRAV_INIT, + MATCHTRAV_NFP_UNSPEC, + MATCHTRAV_NFP_SPEC, + MATCHTRAV_DONE, +}; + +static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos) { - struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; - u_int16_t af = (unsigned long)pde->data; + static const uint8_t next_class[] = { + [MATCHTRAV_NFP_UNSPEC] = MATCHTRAV_NFP_SPEC, + [MATCHTRAV_NFP_SPEC] = MATCHTRAV_DONE, + }; + struct match_trav *trav = seq->private; + + switch (trav->class) { + case MATCHTRAV_INIT: + trav->class = MATCHTRAV_NFP_UNSPEC; + mutex_lock(&xt[NFPROTO_UNSPEC].mutex); + trav->head = trav->curr = &xt[NFPROTO_UNSPEC].match; + break; + case MATCHTRAV_NFP_UNSPEC: + trav->curr = trav->curr->next; + if (trav->curr != trav->head) + break; + mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); + mutex_lock(&xt[trav->nfproto].mutex); + trav->head = trav->curr = &xt[trav->nfproto].match; + trav->class = next_class[trav->class]; + break; + case MATCHTRAV_NFP_SPEC: + trav->curr = trav->curr->next; + if (trav->curr != trav->head) + break; + /* fallthru, _stop will unlock */ + default: + return NULL; + } - mutex_lock(&xt[af].mutex); - return seq_list_start(&xt[af].match, *pos); + if (ppos != NULL) + ++*ppos; + return trav; } -static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) { - struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; - u_int16_t af = (unsigned long)pde->data; + struct match_trav *trav = seq->private; + unsigned int j; - return seq_list_next(v, &xt[af].match, pos); + trav->class = MATCHTRAV_INIT; + for (j = 0; j < *pos; ++j) + if (xt_match_seq_next(seq, NULL, NULL) == NULL) + return NULL; + return trav; } static void xt_match_seq_stop(struct seq_file *seq, void *v) { - struct proc_dir_entry *pde = seq->private; - u_int16_t af = (unsigned long)pde->data; - - mutex_unlock(&xt[af].mutex); + struct match_trav *trav = seq->private; + + switch (trav->class) { + case MATCHTRAV_NFP_UNSPEC: + mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); + break; + case MATCHTRAV_NFP_SPEC: + mutex_unlock(&xt[trav->nfproto].mutex); + break; + } } static int xt_match_seq_show(struct seq_file *seq, void *v) { - struct xt_match *match = list_entry(v, struct xt_match, list); - - if (strlen(match->name)) - return seq_printf(seq, "%s\n", match->name); - else - return 0; + const struct match_trav *trav = seq->private; + const struct xt_match *match; + + switch (trav->class) { + case MATCHTRAV_NFP_UNSPEC: + case MATCHTRAV_NFP_SPEC: + if (trav->curr == trav->head) + return 0; + match = list_entry(trav->curr, struct xt_match, list); + return (*match->name == '\0') ? 0 : + seq_printf(seq, "%s\n", match->name); + } + return 0; } static const struct seq_operations xt_match_seq_ops = { @@ -871,15 +928,23 @@ static const struct seq_operations xt_match_seq_ops = { static int xt_match_open(struct inode *inode, struct file *file) { + struct seq_file *seq; + struct match_trav *trav; int ret; - ret = seq_open(file, &xt_match_seq_ops); - if (!ret) { - struct seq_file *seq = file->private_data; + trav = kmalloc(sizeof(*trav), GFP_KERNEL); + if (trav == NULL) + return -ENOMEM; - seq->private = PDE(inode); + ret = seq_open(file, &xt_match_seq_ops); + if (ret < 0) { + kfree(trav); + return ret; } - return ret; + + seq = file->private_data; + seq->private = trav; + return 0; } static const struct file_operations xt_match_ops = { @@ -887,7 +952,7 @@ static const struct file_operations xt_match_ops = { .open = xt_match_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_private, }; static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) -- # Created with git-export-patch -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html