aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@kernel.org>2023-11-22 19:34:01 +0000
committerDavid Ahern <dsahern@kernel.org>2023-11-22 19:34:01 +0000
commit27fa7cc40030e246803518d073d63705cda29af6 (patch)
treed3e23ecaf64fd268f616345d80289956fe53c7bf
parente4956e7f1fd9bb8d8bf74947c32ac381e19b96ec (diff)
parentbd5226437a4c73404a0e50e419f1cd055b032a74 (diff)
downloadiproute2-27fa7cc40030e246803518d073d63705cda29af6.tar.gz
Merge branch 'parsing-cleanup' into next
Petr Machata says: ==================== Library functions parse_one_of() and parse_on_off() were added about three years ago to unify all the disparate reimplementations of the same basic idea. It used the matches() function to determine whether a string under consideration corresponds to one of the keywords. This reflected many, though not all cases of on/off parsing at the time. This decision has some odd consequences. In particular, "o" can be used as a shorthand for "off", which is not obvious, because "o" is the prefix of both. By sheer luck, the end result actually makes some sense: "on" means on, anything else either means off or errors out. Similar issues are in principle also possible for parse_one_of() uses, though currently this does not come up. Ideally parse_on_off() would accept the strings "on" and "off" and no others. Patch #1 is a cleanup. Patch #2 is shaping the code for the next patches. Patch #3 converts parse_on_off() to strcmp(). See the commit message for the rationale of why the change should be considered acceptable. We'd ideally do parse_one_of() likewise. But the strings this function parses tend to be longer, which means more opportunities for typos and more of a reason to abbreviate things. So instead, patch #4 adds a function parse_one_of_deprecated() for ip macsec to use in one place, where these typos are to be expected, and converts that site to the new function. Then patch #5 changes the behavior of parse_one_of() to accept prefixes like it has so far, but to warn that they are deprecated: # dcb ets set dev swp1 tc-tsa 0:s WARNING: 's' matches 'strict' by prefix. Matching by prefix is deprecated in this context, please use the full string. The idea is that several releases down the line, we might consider switching over to strcmp(), as presumably enough advance warning will have been given. ==================== Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r--include/utils.h5
-rw-r--r--ip/ipmacsec.c6
-rw-r--r--lib/utils.c49
3 files changed, 49 insertions, 11 deletions
diff --git a/include/utils.h b/include/utils.h
index f26ed822f..9ba129b8f 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -198,7 +198,7 @@ int check_ifname(const char *);
int check_altifname(const char *name);
int get_ifname(char *, const char *);
const char *get_ifname_rta(int ifindex, const struct rtattr *rta);
-bool matches(const char *prefix, const char *string);
+int matches(const char *prefix, const char *string);
int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
int inet_addr_match_rta(const inet_prefix *m, const struct rtattr *rta);
@@ -342,6 +342,9 @@ int do_batch(const char *name, bool force,
int parse_one_of(const char *msg, const char *realval, const char * const *list,
size_t len, int *p_err);
+int parse_one_of_deprecated(const char *msg, const char *realval,
+ const char * const *list,
+ size_t len, int *p_err);
bool parse_on_off(const char *msg, const char *realval, int *p_err);
int parse_mapping_num_all(__u32 *keyp, const char *key);
diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c
index 476a6d1d2..fc4c86314 100644
--- a/ip/ipmacsec.c
+++ b/ip/ipmacsec.c
@@ -1457,8 +1457,10 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv,
invarg("expected replay window size", *argv);
} else if (strcmp(*argv, "validate") == 0) {
NEXT_ARG();
- validate = parse_one_of("validate", *argv, validate_str,
- ARRAY_SIZE(validate_str), &ret);
+ validate = parse_one_of_deprecated("validate", *argv,
+ validate_str,
+ ARRAY_SIZE(validate_str),
+ &ret);
if (ret != 0)
return ret;
addattr8(n, MACSEC_BUFLEN,
diff --git a/lib/utils.c b/lib/utils.c
index 99ba7a233..599e859ea 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -873,18 +873,35 @@ const char *get_ifname_rta(int ifindex, const struct rtattr *rta)
return name;
}
-/* Returns false if 'prefix' is a not empty prefix of 'string'.
+/* Returns 0 if 'prefix' is a not empty prefix of 'string', != 0 otherwise.
*/
-bool matches(const char *prefix, const char *string)
+int matches(const char *prefix, const char *string)
{
if (!*prefix)
- return true;
+ return 1;
while (*string && *prefix == *string) {
prefix++;
string++;
}
- return !!*prefix;
+ return *prefix;
+}
+
+static int matches_warn(const char *prefix, const char *string)
+{
+ int rc;
+
+ rc = matches(prefix, string);
+ if (rc)
+ return rc;
+
+ if (strlen(prefix) != strlen(string))
+ fprintf(stderr,
+ "WARNING: '%s' matches '%s' by prefix.\n"
+ "Matching by prefix is deprecated in this context, please use the full string.\n",
+ prefix, string);
+
+ return 0;
}
int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
@@ -1729,13 +1746,15 @@ int do_batch(const char *name, bool force,
return ret;
}
-int parse_one_of(const char *msg, const char *realval, const char * const *list,
- size_t len, int *p_err)
+static int
+__parse_one_of(const char *msg, const char *realval,
+ const char * const *list, size_t len, int *p_err,
+ int (*matcher)(const char *, const char *))
{
int i;
for (i = 0; i < len; i++) {
- if (list[i] && matches(realval, list[i]) == 0) {
+ if (list[i] && matcher(realval, list[i]) == 0) {
*p_err = 0;
return i;
}
@@ -1750,11 +1769,25 @@ int parse_one_of(const char *msg, const char *realval, const char * const *list,
return 0;
}
+int parse_one_of(const char *msg, const char *realval, const char * const *list,
+ size_t len, int *p_err)
+{
+ return __parse_one_of(msg, realval, list, len, p_err, matches_warn);
+}
+
+int parse_one_of_deprecated(const char *msg, const char *realval,
+ const char * const *list,
+ size_t len, int *p_err)
+{
+ return __parse_one_of(msg, realval, list, len, p_err, matches);
+}
+
bool parse_on_off(const char *msg, const char *realval, int *p_err)
{
static const char * const values_on_off[] = { "off", "on" };
- return parse_one_of(msg, realval, values_on_off, ARRAY_SIZE(values_on_off), p_err);
+ return __parse_one_of(msg, realval, values_on_off,
+ ARRAY_SIZE(values_on_off), p_err, strcmp);
}
int parse_mapping_gen(int *argcp, char ***argvp,