]> granicus.if.org Git - ipset/commitdiff
Report if the option is supported by a newer kernel release
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Mon, 11 Sep 2017 18:07:40 +0000 (20:07 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Mon, 11 Sep 2017 18:07:40 +0000 (20:07 +0200)
Instead ot printing "Unknown argument: foo", if foo option is
supported by a newer kernel release, report that.

Make_global.am
include/libipset/types.h
lib/types.c
src/ipset.c

index 7f4e26321592db623fd23460737eb670a015f552..f9d8dcaf67942a33edbf33025774d245ca341055 100644 (file)
@@ -69,7 +69,7 @@
 # interface. 
 
 #            curr:rev:age
-LIBVERSION = 9:0:6
+LIBVERSION = 10:0:7
 
 AM_CPPFLAGS = $(kinclude_CFLAGS) $(all_includes) -I$(top_srcdir)/include
 
index 7f41afca77263e3667c86f5572da2e4bc139937b..137d7ec1764a1f44a6df0c4460a9d241190a63cd 100644 (file)
@@ -103,6 +103,8 @@ extern const struct ipset_type *
        ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd);
 extern const struct ipset_type *
        ipset_type_check(struct ipset_session *session);
+extern const struct ipset_type *
+       ipset_type_higher_rev(const struct ipset_type *type);
 
 extern int ipset_type_add(struct ipset_type *type);
 extern const struct ipset_type *ipset_types(void);
index f303ea6080ec1c8ca6b9d9e571974d1c797bf372..0fe8a7c4820ea042e82ec1bae281c24f7323388f 100644 (file)
@@ -415,6 +415,30 @@ ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd)
        return NULL;
 }
 
+/**
+ * ipset_type_higher_rev - find the next higher userspace revision
+ * @type: set type
+ *
+ * Find the next higher revision of the set type for the input
+ * set type. Higher revision numbers come first on typelist.
+ *
+ * Returns the found or original set type, cannot fail.
+ */
+const struct ipset_type *
+ipset_type_higher_rev(const struct ipset_type *type)
+{
+       const struct ipset_type *t;
+
+       /* Check all registered types in userspace */
+       for (t = typelist; t != NULL; t = t->next) {
+               if (STREQ(type->name, t->name)
+                   && type->family == t->family
+                   && type == t->next)
+                       return t;
+       }
+       return type;
+}
+
 /**
  * ipset_type_check - check the set type received from kernel
  * @session: session structure
index 2c4fa100d09f790fced1610acc26f821fe09f2d2..79f56b869ea70277b01a197d0dbdf4fbae87b4ea 100644 (file)
@@ -275,15 +275,21 @@ static bool do_parse(const struct ipset_arg *arg, bool family)
 }
 
 static int
-call_parser(int *argc, char *argv[], const struct ipset_arg *args, bool family)
+call_parser(int *argc, char *argv[], const struct ipset_type *type,
+           enum ipset_adt cmd, bool family)
 {
-       int ret = 0, i = 1;
+       const struct ipset_arg *args = type->args[cmd];
        const struct ipset_arg *arg;
        const char *optstr;
+       const struct ipset_type *t = type;
+       u_int8_t revision = type->revision;
+       int ret = 0, i = 1;
 
        /* Currently CREATE and ADT may have got additional arguments */
        if (!args && *argc > 1)
-               goto err_unknown;
+               return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'",
+                                 argv[i]);
+
        while (*argc > i) {
                ret = -1;
                for (arg = args; arg->opt; arg++) {
@@ -336,6 +342,21 @@ call_parser(int *argc, char *argv[], const struct ipset_arg *args, bool family)
        return ret;
 
 err_unknown:
+       while ((type = ipset_type_higher_rev(t)) != t) {
+               args = type->args[cmd];
+               for (arg = args; arg->opt; arg++) {
+                       D("argc: %u, %s vs %s", i, argv[i], arg->name[0]);
+                       if (ipset_match_option(argv[i], arg->name))
+                               return exit_error(PARAMETER_PROBLEM,
+                                       "Argument `%s' is supported in the kernel module "
+                                       "of the set type %s starting from the revision %u "
+                                       "and you have installed revision %u only. "
+                                       "Your kernel is behind your ipset utility.",
+                                       argv[i], type->name,
+                                       type->revision, revision);
+               }
+               t = type;
+       }
        return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", argv[i]);
 }
 
@@ -717,14 +738,14 @@ parse_commandline(int argc, char *argv[])
                        return handle_error();
 
                /* Parse create options: first check INET family */
-               ret = call_parser(&argc, argv, type->args[IPSET_CREATE], true);
+               ret = call_parser(&argc, argv, type, IPSET_CREATE, true);
                if (ret < 0)
                        return handle_error();
                else if (ret)
                        return ret;
 
                /* Parse create options: then check all options */
-               ret = call_parser(&argc, argv, type->args[IPSET_CREATE], false);
+               ret = call_parser(&argc, argv, type, IPSET_CREATE, false);
                if (ret < 0)
                        return handle_error();
                else if (ret)
@@ -792,7 +813,7 @@ parse_commandline(int argc, char *argv[])
                        return handle_error();
 
                /* Parse additional ADT options */
-               ret = call_parser(&argc, argv, type->args[cmd2cmd(cmd)], false);
+               ret = call_parser(&argc, argv, type, cmd2cmd(cmd), false);
                if (ret < 0)
                        return handle_error();
                else if (ret)