Commit eb132205ca2f7ad44d8c8c482815b6911200b6a0
Committed by
Patrick McHardy
1 parent
5962fc6d5f
Exists in
master
and in
39 other branches
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>
Showing 1 changed file with 142 additions and 57 deletions Side-by-side Diff
net/netfilter/x_tables.c
... | ... | @@ -827,59 +827,143 @@ |
827 | 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; | |
833 | - u_int16_t af = (unsigned long)pde->data; | |
849 | + static const uint8_t next_class[] = { | |
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; | |
834 | 854 | |
835 | - mutex_lock(&xt[af].mutex); | |
836 | - return seq_list_start(&xt[af].match, *pos); | |
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 | + } | |
880 | + | |
881 | + if (ppos != NULL) | |
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; | |
842 | - u_int16_t af = (unsigned long)pde->data; | |
889 | + struct nf_mttg_trav *trav = seq->private; | |
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; | |
850 | - u_int16_t af = (unsigned long)pde->data; | |
901 | + struct nf_mttg_trav *trav = seq->private; | |
851 | 902 | |
852 | - mutex_unlock(&xt[af].mutex); | |
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 | + } | |
853 | 911 | } |
854 | 912 | |
913 | +static void *xt_match_seq_start(struct seq_file *seq, loff_t *pos) | |
914 | +{ | |
915 | + return xt_mttg_seq_start(seq, pos, false); | |
916 | +} | |
917 | + | |
918 | +static void *xt_match_seq_next(struct seq_file *seq, void *v, loff_t *ppos) | |
919 | +{ | |
920 | + return xt_mttg_seq_next(seq, v, ppos, false); | |
921 | +} | |
922 | + | |
855 | 923 | static int xt_match_seq_show(struct seq_file *seq, void *v) |
856 | 924 | { |
857 | - struct xt_match *match = list_entry(v, struct xt_match, list); | |
925 | + const struct nf_mttg_trav *trav = seq->private; | |
926 | + const struct xt_match *match; | |
858 | 927 | |
859 | - if (strlen(match->name)) | |
860 | - return seq_printf(seq, "%s\n", match->name); | |
861 | - else | |
862 | - return 0; | |
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 | 940 | static const struct seq_operations xt_match_seq_ops = { |
866 | 941 | .start = xt_match_seq_start, |
867 | 942 | .next = xt_match_seq_next, |
868 | - .stop = xt_match_seq_stop, | |
943 | + .stop = xt_mttg_seq_stop, | |
869 | 944 | .show = xt_match_seq_show, |
870 | 945 | }; |
871 | 946 | |
872 | 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 | 951 | int ret; |
875 | 952 | |
876 | - ret = seq_open(file, &xt_match_seq_ops); | |
877 | - if (!ret) { | |
878 | - struct seq_file *seq = file->private_data; | |
953 | + trav = kmalloc(sizeof(*trav), GFP_KERNEL); | |
954 | + if (trav == NULL) | |
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 | 969 | static const struct file_operations xt_match_ops = { |
886 | 970 | |
887 | 971 | |
888 | 972 | |
889 | 973 | |
890 | 974 | |
891 | 975 | |
892 | 976 | |
893 | 977 | |
894 | 978 | |
895 | 979 | |
896 | 980 | |
... | ... | @@ -887,62 +971,63 @@ |
887 | 971 | .open = xt_match_open, |
888 | 972 | .read = seq_read, |
889 | 973 | .llseek = seq_lseek, |
890 | - .release = seq_release, | |
974 | + .release = seq_release_private, | |
891 | 975 | }; |
892 | 976 | |
893 | 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; | |
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); | |
979 | + return xt_mttg_seq_start(seq, pos, true); | |
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; | |
905 | - u_int16_t af = (unsigned long)pde->data; | |
906 | - | |
907 | - return seq_list_next(v, &xt[af].target, pos); | |
984 | + return xt_mttg_seq_next(seq, v, ppos, true); | |
908 | 985 | } |
909 | 986 | |
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 | -} | |
917 | - | |
918 | 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; | |
990 | + const struct xt_target *target; | |
921 | 991 | |
922 | - if (strlen(target->name)) | |
923 | - return seq_printf(seq, "%s\n", target->name); | |
924 | - else | |
925 | - return 0; | |
992 | + switch (trav->class) { | |
993 | + case MTTG_TRAV_NFP_UNSPEC: | |
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 | 1004 | static const struct seq_operations xt_target_seq_ops = { |
929 | 1005 | .start = xt_target_seq_start, |
930 | 1006 | .next = xt_target_seq_next, |
931 | - .stop = xt_target_seq_stop, | |
1007 | + .stop = xt_mttg_seq_stop, | |
932 | 1008 | .show = xt_target_seq_show, |
933 | 1009 | }; |
934 | 1010 | |
935 | 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 | 1015 | int ret; |
938 | 1016 | |
939 | - ret = seq_open(file, &xt_target_seq_ops); | |
940 | - if (!ret) { | |
941 | - struct seq_file *seq = file->private_data; | |
1017 | + trav = kmalloc(sizeof(*trav), GFP_KERNEL); | |
1018 | + if (trav == NULL) | |
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 | 1033 | static const struct file_operations xt_target_ops = { |
... | ... | @@ -950,7 +1035,7 @@ |
950 | 1035 | .open = xt_target_open, |
951 | 1036 | .read = seq_read, |
952 | 1037 | .llseek = seq_lseek, |
953 | - .release = seq_release, | |
1038 | + .release = seq_release_private, | |
954 | 1039 | }; |
955 | 1040 | |
956 | 1041 | #define FORMAT_TABLES "_tables_names" |