Commit c1e2e04388b2539960453689b8e721709f71dc9c

Authored by Jozsef Kadlecsik
Committed by Patrick McHardy
1 parent ac8cc925d3

netfilter: ipset: support listing setnames and headers too

Current listing makes possible to list sets with full content only.
The patch adds support partial listings, i.e. listing just
the existing setnames or listing set headers, without set members.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>

Showing 2 changed files with 50 additions and 27 deletions Side-by-side Diff

include/linux/netfilter/ipset/ip_set.h
... ... @@ -142,6 +142,10 @@
142 142 enum ipset_cmd_flags {
143 143 IPSET_FLAG_BIT_EXIST = 0,
144 144 IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
  145 + IPSET_FLAG_BIT_LIST_SETNAME = 1,
  146 + IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
  147 + IPSET_FLAG_BIT_LIST_HEADER = 2,
  148 + IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
145 149 };
146 150  
147 151 /* Flags at CADT attribute level */
net/netfilter/ipset/ip_set_core.c
... ... @@ -939,11 +939,14 @@
939 939  
940 940 /* List/save set data */
941 941  
942   -#define DUMP_INIT 0L
943   -#define DUMP_ALL 1L
944   -#define DUMP_ONE 2L
945   -#define DUMP_LAST 3L
  942 +#define DUMP_INIT 0
  943 +#define DUMP_ALL 1
  944 +#define DUMP_ONE 2
  945 +#define DUMP_LAST 3
946 946  
  947 +#define DUMP_TYPE(arg) (((u32)(arg)) & 0x0000FFFF)
  948 +#define DUMP_FLAGS(arg) (((u32)(arg)) >> 16)
  949 +
947 950 static int
948 951 ip_set_dump_done(struct netlink_callback *cb)
949 952 {
... ... @@ -973,6 +976,7 @@
973 976 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
974 977 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
975 978 struct nlattr *attr = (void *)nlh + min_len;
  979 + u32 dump_type;
976 980 ip_set_id_t index;
977 981  
978 982 /* Second pass, so parser can't fail */
979 983  
980 984  
... ... @@ -984,17 +988,22 @@
984 988 * [..]: type specific
985 989 */
986 990  
987   - if (!cda[IPSET_ATTR_SETNAME]) {
988   - cb->args[0] = DUMP_ALL;
989   - return 0;
990   - }
  991 + if (cda[IPSET_ATTR_SETNAME]) {
  992 + index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
  993 + if (index == IPSET_INVALID_ID)
  994 + return -ENOENT;
991 995  
992   - index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
993   - if (index == IPSET_INVALID_ID)
994   - return -ENOENT;
  996 + dump_type = DUMP_ONE;
  997 + cb->args[1] = index;
  998 + } else
  999 + dump_type = DUMP_ALL;
995 1000  
996   - cb->args[0] = DUMP_ONE;
997   - cb->args[1] = index;
  1001 + if (cda[IPSET_ATTR_FLAGS]) {
  1002 + u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
  1003 + dump_type |= (f << 16);
  1004 + }
  1005 + cb->args[0] = dump_type;
  1006 +
998 1007 return 0;
999 1008 }
1000 1009  
1001 1010  
... ... @@ -1005,9 +1014,10 @@
1005 1014 struct ip_set *set = NULL;
1006 1015 struct nlmsghdr *nlh = NULL;
1007 1016 unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
  1017 + u32 dump_type, dump_flags;
1008 1018 int ret = 0;
1009 1019  
1010   - if (cb->args[0] == DUMP_INIT) {
  1020 + if (!cb->args[0]) {
1011 1021 ret = dump_init(cb);
1012 1022 if (ret < 0) {
1013 1023 nlh = nlmsg_hdr(cb->skb);
1014 1024  
1015 1025  
... ... @@ -1022,14 +1032,17 @@
1022 1032 if (cb->args[1] >= ip_set_max)
1023 1033 goto out;
1024 1034  
1025   - max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
  1035 + dump_type = DUMP_TYPE(cb->args[0]);
  1036 + dump_flags = DUMP_FLAGS(cb->args[0]);
  1037 + max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
1026 1038 dump_last:
1027   - pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
  1039 + pr_debug("args[0]: %u %u args[1]: %ld\n",
  1040 + dump_type, dump_flags, cb->args[1]);
1028 1041 for (; cb->args[1] < max; cb->args[1]++) {
1029 1042 index = (ip_set_id_t) cb->args[1];
1030 1043 set = ip_set_list[index];
1031 1044 if (set == NULL) {
1032   - if (cb->args[0] == DUMP_ONE) {
  1045 + if (dump_type == DUMP_ONE) {
1033 1046 ret = -ENOENT;
1034 1047 goto out;
1035 1048 }
... ... @@ -1038,8 +1051,8 @@
1038 1051 /* When dumping all sets, we must dump "sorted"
1039 1052 * so that lists (unions of sets) are dumped last.
1040 1053 */
1041   - if (cb->args[0] != DUMP_ONE &&
1042   - ((cb->args[0] == DUMP_ALL) ==
  1054 + if (dump_type != DUMP_ONE &&
  1055 + ((dump_type == DUMP_ALL) ==
1043 1056 !!(set->type->features & IPSET_DUMP_LAST)))
1044 1057 continue;
1045 1058 pr_debug("List set: %s\n", set->name);
... ... @@ -1057,6 +1070,8 @@
1057 1070 }
1058 1071 NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1059 1072 NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
  1073 + if (dump_flags & IPSET_FLAG_LIST_SETNAME)
  1074 + goto next_set;
1060 1075 switch (cb->args[2]) {
1061 1076 case 0:
1062 1077 /* Core header data */
1063 1078  
1064 1079  
1065 1080  
... ... @@ -1069,24 +1084,23 @@
1069 1084 ret = set->variant->head(set, skb);
1070 1085 if (ret < 0)
1071 1086 goto release_refcount;
  1087 + if (dump_flags & IPSET_FLAG_LIST_HEADER)
  1088 + goto next_set;
1072 1089 /* Fall through and add elements */
1073 1090 default:
1074 1091 read_lock_bh(&set->lock);
1075 1092 ret = set->variant->list(set, skb, cb);
1076 1093 read_unlock_bh(&set->lock);
1077   - if (!cb->args[2]) {
  1094 + if (!cb->args[2])
1078 1095 /* Set is done, proceed with next one */
1079   - if (cb->args[0] == DUMP_ONE)
1080   - cb->args[1] = IPSET_INVALID_ID;
1081   - else
1082   - cb->args[1]++;
1083   - }
  1096 + goto next_set;
1084 1097 goto release_refcount;
1085 1098 }
1086 1099 }
1087 1100 /* If we dump all sets, continue with dumping last ones */
1088   - if (cb->args[0] == DUMP_ALL) {
1089   - cb->args[0] = DUMP_LAST;
  1101 + if (dump_type == DUMP_ALL) {
  1102 + dump_type = DUMP_LAST;
  1103 + cb->args[0] = dump_type | (dump_flags << 16);
1090 1104 cb->args[1] = 0;
1091 1105 goto dump_last;
1092 1106 }
... ... @@ -1094,6 +1108,11 @@
1094 1108  
1095 1109 nla_put_failure:
1096 1110 ret = -EFAULT;
  1111 +next_set:
  1112 + if (dump_type == DUMP_ONE)
  1113 + cb->args[1] = IPSET_INVALID_ID;
  1114 + else
  1115 + cb->args[1]++;
1097 1116 release_refcount:
1098 1117 /* If there was an error or set is done, release set */
1099 1118 if (ret || !cb->args[2]) {