diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2017-09-11 20:07:40 +0200 |
---|---|---|
committer | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2017-09-11 20:07:40 +0200 |
commit | 54802b2c28265769c2dc1b126419ac673316eb64 (patch) | |
tree | ff70d73320bf90e677172ef4f1b9121bd7410144 | |
parent | 9ccbd1c6464cf62ad5531fd1a473703f4f472840 (diff) |
Report if the option is supported by a newer kernel release
Instead ot printing "Unknown argument: foo", if foo option is
supported by a newer kernel release, report that.
-rw-r--r-- | Make_global.am | 2 | ||||
-rw-r--r-- | include/libipset/types.h | 2 | ||||
-rw-r--r-- | lib/types.c | 24 | ||||
-rw-r--r-- | src/ipset.c | 33 |
4 files changed, 54 insertions, 7 deletions
diff --git a/Make_global.am b/Make_global.am index 7f4e263..f9d8dca 100644 --- a/Make_global.am +++ b/Make_global.am @@ -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 diff --git a/include/libipset/types.h b/include/libipset/types.h index 7f41afc..137d7ec 100644 --- a/include/libipset/types.h +++ b/include/libipset/types.h @@ -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); diff --git a/lib/types.c b/lib/types.c index f303ea6..0fe8a7c 100644 --- a/lib/types.c +++ b/lib/types.c @@ -416,6 +416,30 @@ ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd) } /** + * 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 * diff --git a/src/ipset.c b/src/ipset.c index 2c4fa10..79f56b8 100644 --- a/src/ipset.c +++ b/src/ipset.c @@ -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) |