]> granicus.if.org Git - ipset/commitdiff
Support listing setnames and headers too
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Mon, 18 Apr 2011 15:32:25 +0000 (17:32 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Mon, 18 Apr 2011 15:32:25 +0000 (17:32 +0200)
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.

include/libipset/linux_ip_set.h
include/libipset/session.h
kernel/include/linux/netfilter/ipset/ip_set.h
kernel/net/netfilter/ipset/ip_set_core.c
lib/session.c
src/ipset.8
src/ui.c

index d81a811cd0b5e53f3601305a163bc0601e74d5bc..00cf0c60c0dc06909034def17676a4708df633f3 100644 (file)
@@ -142,6 +142,10 @@ enum ipset_errno {
 enum ipset_cmd_flags {
        IPSET_FLAG_BIT_EXIST    = 0,
        IPSET_FLAG_EXIST        = (1 << IPSET_FLAG_BIT_EXIST),
+       IPSET_FLAG_BIT_LIST_SETNAME = 1,
+       IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
+       IPSET_FLAG_BIT_LIST_HEADER = 2,
+       IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
 };
 
 /* Flags at CADT attribute level */
index a06c79f20fbda1eeb20e567bfb4de2f3019c1ffc..5ccdd6c6cba09a81fb0ca62284c258e2b24be872 100644 (file)
@@ -65,6 +65,10 @@ enum ipset_envopt {
        IPSET_ENV_RESOLVE       = (1 << IPSET_ENV_BIT_RESOLVE),
        IPSET_ENV_BIT_EXIST     = 3,
        IPSET_ENV_EXIST         = (1 << IPSET_ENV_BIT_EXIST),
+       IPSET_ENV_BIT_LIST_SETNAME = 4,
+       IPSET_ENV_LIST_SETNAME  = (1 << IPSET_ENV_BIT_LIST_SETNAME),
+       IPSET_ENV_BIT_LIST_HEADER = 5,
+       IPSET_ENV_LIST_HEADER   = (1 << IPSET_ENV_BIT_LIST_HEADER),
 };
 
 extern int ipset_envopt_parse(struct ipset_session *session,
index 68b21f5d6a844bc06d9b279f463a1cabb543b951..e677c4d8f00e8f60fe4fdb18d1ff103d3fe927d1 100644 (file)
@@ -142,6 +142,10 @@ enum ipset_errno {
 enum ipset_cmd_flags {
        IPSET_FLAG_BIT_EXIST    = 0,
        IPSET_FLAG_EXIST        = (1 << IPSET_FLAG_BIT_EXIST),
+       IPSET_FLAG_BIT_LIST_SETNAME = 1,
+       IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
+       IPSET_FLAG_BIT_LIST_HEADER = 2,
+       IPSET_FLAG_LIST_HEADER  = (1 << IPSET_FLAG_BIT_LIST_HEADER),
 };
 
 /* Flags at CADT attribute level */
index 126d5550bd0471e4d0f8098546790e1d7c8b4905..ea1f56151a96656202a8d3deae6e5d3b1df931dc 100644 (file)
@@ -944,10 +944,13 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
 
 /* List/save set data */
 
-#define DUMP_INIT      0L
-#define DUMP_ALL       1L
-#define DUMP_ONE       2L
-#define DUMP_LAST      3L
+#define DUMP_INIT      0
+#define DUMP_ALL       1
+#define DUMP_ONE       2
+#define DUMP_LAST      3
+
+#define DUMP_TYPE(arg)         (((u32)(arg)) & 0x0000FFFF)
+#define DUMP_FLAGS(arg)                (((u32)(arg)) >> 16)
 
 static int
 ip_set_dump_done(struct netlink_callback *cb)
@@ -978,6 +981,7 @@ dump_init(struct netlink_callback *cb)
        int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
        struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
        struct nlattr *attr = (void *)nlh + min_len;
+       u32 dump_type;
        ip_set_id_t index;
 
        /* Second pass, so parser can't fail */
@@ -989,17 +993,22 @@ dump_init(struct netlink_callback *cb)
         *         [..]: type specific
         */
 
-       if (!cda[IPSET_ATTR_SETNAME]) {
-               cb->args[0] = DUMP_ALL;
-               return 0;
-       }
+       if (cda[IPSET_ATTR_SETNAME]) {
+               index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
+               if (index == IPSET_INVALID_ID)
+                       return -ENOENT;
 
-       index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
-       if (index == IPSET_INVALID_ID)
-               return -ENOENT;
+               dump_type = DUMP_ONE;
+               cb->args[1] = index;
+       } else
+               dump_type = DUMP_ALL;
+
+       if (cda[IPSET_ATTR_FLAGS]) {
+               u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
+               dump_type |= (f << 16);
+       }
+       cb->args[0] = dump_type;
 
-       cb->args[0] = DUMP_ONE;
-       cb->args[1] = index;
        return 0;
 }
 
@@ -1010,9 +1019,10 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
        struct ip_set *set = NULL;
        struct nlmsghdr *nlh = NULL;
        unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
+       u32 dump_type, dump_flags;
        int ret = 0;
 
-       if (cb->args[0] == DUMP_INIT) {
+       if (!cb->args[0]) {
                ret = dump_init(cb);
                if (ret < 0) {
                        nlh = nlmsg_hdr(cb->skb);
@@ -1027,14 +1037,17 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
        if (cb->args[1] >= ip_set_max)
                goto out;
 
-       max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
+       dump_type = DUMP_TYPE(cb->args[0]);
+       dump_flags = DUMP_FLAGS(cb->args[0]);
+       max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
 dump_last:
-       pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
+       pr_debug("args[0]: %u %u args[1]: %ld\n",
+                dump_type, dump_flags, cb->args[1]);
        for (; cb->args[1] < max; cb->args[1]++) {
                index = (ip_set_id_t) cb->args[1];
                set = ip_set_list[index];
                if (set == NULL) {
-                       if (cb->args[0] == DUMP_ONE) {
+                       if (dump_type == DUMP_ONE) {
                                ret = -ENOENT;
                                goto out;
                        }
@@ -1043,8 +1056,8 @@ dump_last:
                /* When dumping all sets, we must dump "sorted"
                 * so that lists (unions of sets) are dumped last.
                 */
-               if (cb->args[0] != DUMP_ONE &&
-                   ((cb->args[0] == DUMP_ALL) ==
+               if (dump_type != DUMP_ONE &&
+                   ((dump_type == DUMP_ALL) ==
                     !!(set->type->features & IPSET_DUMP_LAST)))
                        continue;
                pr_debug("List set: %s\n", set->name);
@@ -1062,6 +1075,8 @@ dump_last:
                }
                NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
                NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
+               if (dump_flags & IPSET_FLAG_LIST_SETNAME)
+                       goto next_set;
                switch (cb->args[2]) {
                case 0:
                        /* Core header data */
@@ -1074,24 +1089,23 @@ dump_last:
                        ret = set->variant->head(set, skb);
                        if (ret < 0)
                                goto release_refcount;
+                       if (dump_flags & IPSET_FLAG_LIST_HEADER)
+                               goto next_set;
                        /* Fall through and add elements */
                default:
                        read_lock_bh(&set->lock);
                        ret = set->variant->list(set, skb, cb);
                        read_unlock_bh(&set->lock);
-                       if (!cb->args[2]) {
+                       if (!cb->args[2])
                                /* Set is done, proceed with next one */
-                               if (cb->args[0] == DUMP_ONE)
-                                       cb->args[1] = IPSET_INVALID_ID;
-                               else
-                                       cb->args[1]++;
-                       }
+                               goto next_set;
                        goto release_refcount;
                }
        }
        /* If we dump all sets, continue with dumping last ones */
-       if (cb->args[0] == DUMP_ALL) {
-               cb->args[0] = DUMP_LAST;
+       if (dump_type == DUMP_ALL) {
+               dump_type = DUMP_LAST;
+               cb->args[0] = dump_type | (dump_flags << 16);
                cb->args[1] = 0;
                goto dump_last;
        }
@@ -1099,6 +1113,11 @@ dump_last:
 
 nla_put_failure:
        ret = -EFAULT;
+next_set:
+       if (dump_type == DUMP_ONE)
+               cb->args[1] = IPSET_INVALID_ID;
+       else
+               cb->args[1]++;
 release_refcount:
        /* If there was an error or set is done, release set */
        if (ret || !cb->args[2]) {
index a1931431b19d8f55addbfe52a5cd440c3f170039..9a7f45b683b762781250f75740ac3d52e321c687 100644 (file)
@@ -136,6 +136,8 @@ ipset_envopt_parse(struct ipset_session *session, int opt,
        case IPSET_ENV_QUIET:
        case IPSET_ENV_RESOLVE:
        case IPSET_ENV_EXIST:
+       case IPSET_ENV_LIST_SETNAME:
+       case IPSET_ENV_LIST_HEADER:
                session->envopts |= opt;
                return 0;
        default:
@@ -885,7 +887,9 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
                safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
                safe_snprintf(session, "\nReferences: ");
                safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
-               safe_snprintf(session, "\nMembers:\n");
+               safe_snprintf(session,
+                       session->envopts & IPSET_ENV_LIST_HEADER ?
+                       "\n" : "\nMembers:\n");
                break;
        case IPSET_LIST_XML:
                safe_snprintf(session, "</elements>\n    <memsize>");
@@ -938,6 +942,16 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
 
        ATTR2DATA(session, nla, IPSET_ATTR_SETNAME, cmd_attrs);
        D("setname %s", ipset_data_setname(data));
+       if (session->envopts & IPSET_ENV_LIST_SETNAME) {
+               if (session->mode == IPSET_LIST_XML)
+                       safe_snprintf(session, "<ipset name=\"%s\"/>\n",
+                                     ipset_data_setname(data));
+               else
+                       safe_snprintf(session, "%s\n",
+                                     ipset_data_setname(data));
+               return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
+       }
+
        if (STREQ(ipset_data_setname(data), session->saved_setname)) {
                /* Header part already seen */
                if (ipset_data_test(data, IPSET_OPT_TYPE)
@@ -1602,11 +1616,26 @@ build_msg(struct ipset_session *session, bool aggregate)
        }
        case IPSET_CMD_DESTROY:
        case IPSET_CMD_FLUSH:
-       case IPSET_CMD_LIST:
        case IPSET_CMD_SAVE:
                if (ipset_data_test(data, IPSET_SETNAME))
                        ADDATTR_SETNAME(session, nlh, data);
                break;
+       case IPSET_CMD_LIST: {
+               uint32_t flags = 0;
+               
+               if (session->envopts & IPSET_ENV_LIST_SETNAME)
+                       flags |= IPSET_FLAG_LIST_SETNAME;
+               if (session->envopts & IPSET_ENV_LIST_HEADER)
+                       flags |= IPSET_FLAG_LIST_HEADER;
+               if (ipset_data_test(data, IPSET_SETNAME))
+                       ADDATTR_SETNAME(session, nlh, data);
+               if (flags) {
+                       ipset_data_set(data, IPSET_OPT_FLAGS, &flags);
+                       ADDATTR(session, nlh, data, IPSET_ATTR_FLAGS, AF_INET,
+                               cmd_attrs);
+               }
+               break;
+       }
        case IPSET_CMD_RENAME:
        case IPSET_CMD_SWAP:
                if (!ipset_data_test(data, IPSET_SETNAME))
index d9e5ff8e902f8e4e2b722456101a2f71e2456e17..21750fab0558c555e542229be99535e3c8217f5c 100644 (file)
@@ -21,7 +21,7 @@ ipset \(em administration tool for IP sets
 .PP 
 COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR }
 .PP 
-\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR }
+\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR }
 .PP 
 \fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ]
 .PP 
@@ -109,7 +109,7 @@ Destroy the specified set or all the sets if none is given.
 
 If the set has got reference(s), nothing is done and no set destroyed.
 .TP 
-\fBlist\fP [ \fISETNAME\fP ]
+\fBlist\fP [ \fISETNAME\fP ] [ \fIOPTIONS\fP ]
 List the header data and the entries for the specified set, or for
 all sets if none is given. The
 \fB\-resolve\fP
@@ -120,8 +120,13 @@ type supports the operation). The option
 \fB\-output\fR
 can be used to control the format of the listing:
 \fBplain\fR, \fBsave\fR or \fBxml\fR.
-The default is
-\fBplain\fR. 
+(The default is
+\fBplain\fR.)
+If the option
+\fB\-name\fR
+is specified, just the names of the existing sets are listed. If the option
+\fB\-terse\fR
+is specified, just the set names and headers are listed. 
 .TP 
 \fBsave\fP [ \fISETNAME\fP ]
 Save the given set, or all sets if none is given
@@ -190,6 +195,13 @@ DNS lookups.
 .TP 
 \fB\-s\fP, \fB\-sorted\fP
 Sorted output. When listing sets entries are listed sorted. Not supported yet.
+.TP 
+\fB\-n\fP, \fB\-name\fP
+List just the names of the existing sets, i.e. suppress listing of set headers and members.
+.TP 
+\fB\-t\fP, \fB\-terse\fP
+List the set names and headers, i.e. suppress listing of set members.
+
 .SH "SET TYPES"
 A set type comprises of the storage method by which the data is stored and
 the data type(s) which are stored in the set. Therefore the
index 3601c65b2285175ad986c8b454d86da67ea4eff1..020a1fe880655de7f2b6b01fbd3dedefae05bb6f 100644 (file)
--- a/src/ui.c
+++ b/src/ui.c
@@ -188,6 +188,19 @@ const struct ipset_envopts ipset_envopts[] = {
                  "        when adding already existing elements\n"
                  "        or when deleting non-existing elements.",
        },
+       { .name = { "-n", "-name" },
+         .parse = ipset_envopt_parse,
+         .has_arg = IPSET_NO_ARG,      .flag = IPSET_ENV_LIST_SETNAME,
+         .help = "\n"
+                 "        When listing, list just setnames from kernel.\n",
+       },
+       { .name = { "-t", "-terse" },
+         .parse = ipset_envopt_parse,
+         .has_arg = IPSET_NO_ARG,      .flag = IPSET_ENV_LIST_HEADER,
+         .help = "\n"
+                 "        When listing, list setnames and set headers\n"
+                 "        from kernel only.",
+       },
        { },
 };