Commit eb132205ca2f7ad44d8c8c482815b6911200b6a0

Authored by Jan Engelhardt
Committed by Patrick McHardy
1 parent 5962fc6d5f

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"