diff options
| author | Jan Engelhardt <jengelh@medozas.de> | 2009-02-18 10:42:19 -0500 |
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2009-02-18 10:42:19 -0500 |
| commit | eb132205ca2f7ad44d8c8c482815b6911200b6a0 (patch) | |
| tree | e9ffa29e92c8e22631c3127c4598b88df5ee22a9 | |
| parent | 5962fc6d5fff09c8e6fb8cadcb18327a0f4277f7 (diff) | |
netfilter: make proc/net/ip* print names from foreign NFPROTO
When extensions were moved to the NFPROTO_UNSPEC wildcard in
ab4f21e6fb1c09b13c4c3cb8357babe8223471bd, they disappeared from the
procfs files.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
| -rw-r--r-- | net/netfilter/x_tables.c | 199 |
1 files changed, 142 insertions, 57 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index bfbf521f6ea5..5baccfa5a0de 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
| @@ -827,59 +827,143 @@ static const struct file_operations xt_table_ops = { | |||
| 827 | .release = seq_release_net, | 827 | .release = seq_release_net, |
| 828 | }; | 828 | }; |
| 829 | 829 | ||
| 830 | static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) | 830 | /* |
| 831 | * Traverse state for ip{,6}_{tables,matches} for helping crossing | ||
| 832 | * the multi-AF mutexes. | ||
| 833 | */ | ||
| 834 | struct nf_mttg_trav { | ||
| 835 | struct list_head *head, *curr; | ||
| 836 | uint8_t class, nfproto; | ||
| 837 | }; | ||
| 838 | |||
| 839 | enum { | ||
| 840 | MTTG_TRAV_INIT, | ||
| 841 | MTTG_TRAV_NFP_UNSPEC, | ||
| 842 | MTTG_TRAV_NFP_SPEC, | ||
| 843 | MTTG_TRAV_DONE, | ||
| 844 | }; | ||
| 845 | |||
| 846 | static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, | ||
| 847 | bool is_target) | ||
| 831 | { | 848 | { |
| 832 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 849 | static const uint8_t next_class[] = { |
| 833 | u_int16_t af = (unsigned long)pde->data; | 850 | [MTTG_TRAV_NFP_UNSPEC] = MTTG_TRAV_NFP_SPEC, |
| 851 | [MTTG_TRAV_NFP_SPEC] = MTTG_TRAV_DONE, | ||
| 852 | }; | ||
| 853 | struct nf_mttg_trav *trav = seq->private; | ||
| 854 | |||
| 855 | switch (trav->class) { | ||
| 856 | case MTTG_TRAV_INIT: | ||
| 857 | trav->class = MTTG_TRAV_NFP_UNSPEC; | ||
| 858 | mutex_lock(&xt[NFPROTO_UNSPEC].mutex); | ||
| 859 | trav->head = trav->curr = is_target ? | ||
| 860 | &xt[NFPROTO_UNSPEC].target : &xt[NFPROTO_UNSPEC].match; | ||
| 861 | break; | ||
| 862 | case MTTG_TRAV_NFP_UNSPEC: | ||
| 863 | trav->curr = trav->curr->next; | ||
| 864 | if (trav->curr != trav->head) | ||
| 865 | break; | ||
| 866 | mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); | ||
| 867 | mutex_lock(&xt[trav->nfproto].mutex); | ||
| 868 | trav->head = trav->curr = is_target ? | ||
| 869 | &xt[trav->nfproto].target : &xt[trav->nfproto].match; | ||
| 870 | trav->class = next_class[trav->class]; | ||
| 871 | break; | ||
| 872 | case MTTG_TRAV_NFP_SPEC: | ||
| 873 | trav->curr = trav->curr->next; | ||
| 874 | if (trav->curr != trav->head) | ||
| 875 | break; | ||
| 876 | /* fallthru, _stop will unlock */ | ||
| 877 | default: | ||
| 878 | return NULL; | ||
| 879 | } | ||
| 834 | 880 | ||
| 835 | mutex_lock(&xt[af].mutex); | 881 | if (ppos != NULL) |
| 836 | return seq_list_start(&xt[af].match, *pos); | 882 | ++*ppos; |
| 883 | return trav; | ||
| 837 | } | 884 | } |
| 838 | 885 | ||
| 839 | static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 886 | static void *xt_mttg_seq_start(struct seq_file *seq, loff_t *pos, |
| 887 | bool is_target) | ||
| 840 | { | 888 | { |
| 841 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 889 | struct nf_mttg_trav *trav = seq->private; |
| 842 | u_int16_t af = (unsigned long)pde->data; | 890 | unsigned int j; |
| 843 | 891 | ||
| 844 | return seq_list_next(v, &xt[af].match, pos); | 892 | trav->class = MTTG_TRAV_INIT; |
| 893 | for (j = 0; j < *pos; ++j) | ||
| 894 | if (xt_mttg_seq_next(seq, NULL, NULL, is_target) == NULL) | ||
| 895 | return NULL; | ||
| 896 | return trav; | ||
| 845 | } | 897 | } |
| 846 | 898 | ||
| 847 | static void xt_match_seq_stop(struct seq_file *seq, void *v) | 899 | static void xt_mttg_seq_stop(struct seq_file *seq, void *v) |
| 848 | { | 900 | { |
| 849 | struct proc_dir_entry *pde = seq->private; | 901 | struct nf_mttg_trav *trav = seq->private; |
| 850 | u_int16_t af = (unsigned long)pde->data; | 902 | |
| 903 | switch (trav->class) { | ||
| 904 | case MTTG_TRAV_NFP_UNSPEC: | ||
| 905 | mutex_unlock(&xt[NFPROTO_UNSPEC].mutex); | ||
| 906 | break; | ||
| 907 | case MTTG_TRAV_NFP_SPEC: | ||
| 908 | mutex_unlock(&xt[trav->nfproto].mutex); | ||
| 909 | break; | ||
| 910 | } | ||
| 911 | } | ||
| 851 | 912 | ||
| 852 | mutex_unlock(&xt[af].mutex); | 913 | static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) |
| 914 | { | ||
| 915 | return xt_mttg_seq_start(seq, pos, false); | ||
| 853 | } | 916 | } |
| 854 | 917 | ||
| 855 | static int xt_match_seq_show(struct seq_file *seq, void *v) | 918 | static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos) |
| 856 | { | 919 | { |
| 857 | struct xt_match *match = list_entry(v, struct xt_match, list); | 920 | return xt_mttg_seq_next(seq, v, ppos, false); |
| 921 | } | ||
| 858 | 922 | ||
| 859 | if (strlen(match->name)) | 923 | static int xt_match_seq_show(struct seq_file *seq, void *v) |
| 860 | return seq_printf(seq, "%s\n", match->name); | 924 | { |
| 861 | else | 925 | const struct nf_mttg_trav *trav = seq->private; |
| 862 | return 0; | 926 | const struct xt_match *match; |
| 927 | |||
| 928 | switch (trav->class) { | ||
| 929 | case MTTG_TRAV_NFP_UNSPEC: | ||
| 930 | case MTTG_TRAV_NFP_SPEC: | ||
| 931 | if (trav->curr == trav->head) | ||
| 932 | return 0; | ||
| 933 | match = list_entry(trav->curr, struct xt_match, list); | ||
| 934 | return (*match->name == '\0') ? 0 : | ||
| 935 | seq_printf(seq, "%s\n", match->name); | ||
| 936 | } | ||
| 937 | return 0; | ||
| 863 | } | 938 | } |
| 864 | 939 | ||
| 865 | static const struct seq_operations xt_match_seq_ops = { | 940 | static const struct seq_operations xt_match_seq_ops = { |
| 866 | .start = xt_match_seq_start, | 941 | .start = xt_match_seq_start, |
| 867 | .next = xt_match_seq_next, | 942 | .next = xt_match_seq_next, |
| 868 | .stop = xt_match_seq_stop, | 943 | .stop = xt_mttg_seq_stop, |
| 869 | .show = xt_match_seq_show, | 944 | .show = xt_match_seq_show, |
| 870 | }; | 945 | }; |
| 871 | 946 | ||
| 872 | static int xt_match_open(struct inode *inode, struct file *file) | 947 | static int xt_match_open(struct inode *inode, struct file *file) |
| 873 | { | 948 | { |
| 949 | struct seq_file *seq; | ||
| 950 | struct nf_mttg_trav *trav; | ||
| 874 | int ret; | 951 | int ret; |
| 875 | 952 | ||
| 876 | ret = seq_open(file, &xt_match_seq_ops); | 953 | trav = kmalloc(sizeof(*trav), GFP_KERNEL); |
| 877 | if (!ret) { | 954 | if (trav == NULL) |
| 878 | struct seq_file *seq = file->private_data; | 955 | return -ENOMEM; |
| 879 | 956 | ||
| 880 | seq->private = PDE(inode); | 957 | ret = seq_open(file, &xt_match_seq_ops); |
| 958 | if (ret < 0) { | ||
| 959 | kfree(trav); | ||
| 960 | return ret; | ||
| 881 | } | 961 | } |
| 882 | return ret; | 962 | |
| 963 | seq = file->private_data; | ||
| 964 | seq->private = trav; | ||
| 965 | trav->nfproto = (unsigned long)PDE(inode)->data; | ||
| 966 | return 0; | ||
| 883 | } | 967 | } |
| 884 | 968 | ||
| 885 | static const struct file_operations xt_match_ops = { | 969 | static const struct file_operations xt_match_ops = { |
| @@ -887,62 +971,63 @@ static const struct file_operations xt_match_ops = { | |||
| 887 | .open = xt_match_open, | 971 | .open = xt_match_open, |
| 888 | .read = seq_read, | 972 | .read = seq_read, |
| 889 | .llseek = seq_lseek, | 973 | .llseek = seq_lseek, |
| 890 | .release = seq_release, | 974 | .release = seq_release_private, |
| 891 | }; | 975 | }; |
| 892 | 976 | ||
| 893 | static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) | 977 | static void *xt_target_seq_start(struct seq_file *seq, loff_t *pos) |
| 894 | { | 978 | { |
| 895 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 979 | return xt_mttg_seq_start(seq, pos, true); |
| 896 | u_int16_t af = (unsigned long)pde->data; | ||
| 897 | |||
| 898 | mutex_lock(&xt[af].mutex); | ||
| 899 | return seq_list_start(&xt[af].target, *pos); | ||
| 900 | } | 980 | } |
| 901 | 981 | ||
| 902 | static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 982 | static void *xt_target_seq_next(struct seq_file *seq, void *v, loff_t *ppos) |
| 903 | { | 983 | { |
| 904 | struct proc_dir_entry *pde = (struct proc_dir_entry *)seq->private; | 984 | return xt_mttg_seq_next(seq, v, ppos, true); |
| 905 | u_int16_t af = (unsigned long)pde->data; | ||
| 906 | |||
| 907 | return seq_list_next(v, &xt[af].target, pos); | ||
| 908 | } | ||
| 909 | |||
| 910 | static void xt_target_seq_stop(struct seq_file *seq, void *v) | ||
| 911 | { | ||
| 912 | struct proc_dir_entry *pde = seq->private; | ||
| 913 | u_int16_t af = (unsigned long)pde->data; | ||
| 914 | |||
| 915 | mutex_unlock(&xt[af].mutex); | ||
| 916 | } | 985 | } |
| 917 | 986 | ||
| 918 | static int xt_target_seq_show(struct seq_file *seq, void *v) | 987 | static int xt_target_seq_show(struct seq_file *seq, void *v) |
| 919 | { | 988 | { |
| 920 | struct xt_target *target = list_entry(v, struct xt_target, list); | 989 | const struct nf_mttg_trav *trav = seq->private; |
| 921 | 990 | const struct xt_target *target; | |
| 922 | if (strlen(target->name)) | 991 | |
| 923 | return seq_printf(seq, "%s\n", target->name); | 992 | switch (trav->class) { |
| 924 | else | 993 | case MTTG_TRAV_NFP_UNSPEC: |
| 925 | return 0; | 994 | case MTTG_TRAV_NFP_SPEC: |
| 995 | if (trav->curr == trav->head) | ||
| 996 | return 0; | ||
| 997 | target = list_entry(trav->curr, struct xt_target, list); | ||
| 998 | return (*target->name == '\0') ? 0 : | ||
| 999 | seq_printf(seq, "%s\n", target->name); | ||
| 1000 | } | ||
| 1001 | return 0; | ||
| 926 | } | 1002 | } |
| 927 | 1003 | ||
| 928 | static const struct seq_operations xt_target_seq_ops = { | 1004 | static const struct seq_operations xt_target_seq_ops = { |
| 929 | .start = xt_target_seq_start, | 1005 | .start = xt_target_seq_start, |
| 930 | .next = xt_target_seq_next, | 1006 | .next = xt_target_seq_next, |
| 931 | .stop = xt_target_seq_stop, | 1007 | .stop = xt_mttg_seq_stop, |
| 932 | .show = xt_target_seq_show, | 1008 | .show = xt_target_seq_show, |
| 933 | }; | 1009 | }; |
| 934 | 1010 | ||
| 935 | static int xt_target_open(struct inode *inode, struct file *file) | 1011 | static int xt_target_open(struct inode *inode, struct file *file) |
| 936 | { | 1012 | { |
| 1013 | struct seq_file *seq; | ||
| 1014 | struct nf_mttg_trav *trav; | ||
| 937 | int ret; | 1015 | int ret; |
| 938 | 1016 | ||
| 939 | ret = seq_open(file, &xt_target_seq_ops); | 1017 | trav = kmalloc(sizeof(*trav), GFP_KERNEL); |
| 940 | if (!ret) { | 1018 | if (trav == NULL) |
| 941 | struct seq_file *seq = file->private_data; | 1019 | return -ENOMEM; |
| 942 | 1020 | ||
| 943 | seq->private = PDE(inode); | 1021 | ret = seq_open(file, &xt_target_seq_ops); |
| 1022 | if (ret < 0) { | ||
| 1023 | kfree(trav); | ||
| 1024 | return ret; | ||
| 944 | } | 1025 | } |
| 945 | return ret; | 1026 | |
| 1027 | seq = file->private_data; | ||
| 1028 | seq->private = trav; | ||
| 1029 | trav->nfproto = (unsigned long)PDE(inode)->data; | ||
| 1030 | return 0; | ||
| 946 | } | 1031 | } |
| 947 | 1032 | ||
| 948 | static const struct file_operations xt_target_ops = { | 1033 | static const struct file_operations xt_target_ops = { |
| @@ -950,7 +1035,7 @@ static const struct file_operations xt_target_ops = { | |||
| 950 | .open = xt_target_open, | 1035 | .open = xt_target_open, |
| 951 | .read = seq_read, | 1036 | .read = seq_read, |
| 952 | .llseek = seq_lseek, | 1037 | .llseek = seq_lseek, |
| 953 | .release = seq_release, | 1038 | .release = seq_release_private, |
| 954 | }; | 1039 | }; |
| 955 | 1040 | ||
| 956 | #define FORMAT_TABLES "_tables_names" | 1041 | #define FORMAT_TABLES "_tables_names" |
