ip-address: Fix filtering by negated address flags

When disabling a flag, one needs to AND with the inverse not the flag
itself. Otherwise specifying for instance 'home -nodad' will effectively
clear the flags variable.

While being at it, simplify the code a bit by merging common parts of
negated and non-negated case branches. Also allow for the "special
cases" to be inverted, too.

Fixes: f73ac674d0 ("ip: change flag names to an array")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
This commit is contained in:
Phil Sutter 2018-11-15 14:28:59 +01:00 committed by Stephen Hemminger
parent 87e3ec0e2f
commit 133db49b49
2 changed files with 52 additions and 34 deletions

View File

@ -1211,38 +1211,35 @@ static void print_ifa_flags(FILE *fp, const struct ifaddrmsg *ifa,
static int get_filter(const char *arg) static int get_filter(const char *arg)
{ {
bool inv = false;
unsigned int i; unsigned int i;
if (arg[0] == '-') {
inv = true;
arg++;
}
/* Special cases */ /* Special cases */
if (strcmp(arg, "dynamic") == 0) { if (strcmp(arg, "dynamic") == 0) {
filter.flags &= ~IFA_F_PERMANENT; inv = !inv;
filter.flagmask |= IFA_F_PERMANENT; arg = "permanent";
} else if (strcmp(arg, "primary") == 0) { } else if (strcmp(arg, "primary") == 0) {
filter.flags &= ~IFA_F_SECONDARY; inv = !inv;
filter.flagmask |= IFA_F_SECONDARY; arg = "secondary";
} else if (*arg == '-') {
for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
if (strcmp(arg + 1, ifa_flag_names[i].name))
continue;
filter.flags &= ifa_flag_names[i].value;
filter.flagmask |= ifa_flag_names[i].value;
return 0;
}
return -1;
} else {
for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
if (strcmp(arg, ifa_flag_names[i].name))
continue;
filter.flags |= ifa_flag_names[i].value;
filter.flagmask |= ifa_flag_names[i].value;
return 0;
}
return -1;
} }
return 0; for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) {
if (strcmp(arg, ifa_flag_names[i].name))
continue;
if (inv)
filter.flags &= ~ifa_flag_names[i].value;
else
filter.flags |= ifa_flag_names[i].value;
filter.flagmask |= ifa_flag_names[i].value;
return 0;
}
return -1;
} }
static int ifa_label_match_rta(int ifindex, const struct rtattr *rta) static int ifa_label_match_rta(int ifindex, const struct rtattr *rta)

View File

@ -76,10 +76,15 @@ ip-address \- protocol address management
.IR FLAG-LIST " := [ " FLAG-LIST " ] " FLAG .IR FLAG-LIST " := [ " FLAG-LIST " ] " FLAG
.ti -8 .ti -8
.IR FLAG " := " .IR FLAG " := ["
.RB "[ " permanent " | " dynamic " | " secondary " | " primary " |" .RB [ - ] permanent " |"
.RB [ - ] tentative " | [" - ] deprecated " | [" - ] dadfailed " |" .RB [ - ] dynamic " |"
.BR temporary " |" .RB [ - ] secondary " |"
.RB [ - ] primary " |"
.RB [ - ] tentative " |"
.RB [ - ] deprecated " |"
.RB [ - ] dadfailed " |"
.RB [ - ] temporary " |"
.IR CONFFLAG-LIST " ]" .IR CONFFLAG-LIST " ]"
.ti -8 .ti -8
@ -334,7 +339,9 @@ only list running interfaces.
.BR dynamic " and " permanent .BR dynamic " and " permanent
(IPv6 only) only list addresses installed due to stateless (IPv6 only) only list addresses installed due to stateless
address configuration or only list permanent (not dynamic) address configuration or only list permanent (not dynamic)
addresses. addresses. These two flags are inverses of each other, so
.BR -dynamic " is equal to " permanent " and "
.BR -permanent " is equal to " dynamic .
.TP .TP
.B tentative .B tentative
@ -365,12 +372,26 @@ address detection.
address detection. address detection.
.TP .TP
.B temporary .BR temporary " or " secondary
(IPv6 only) only list temporary addresses. List temporary IPv6 or secondary IPv4 addresses only. The Linux kernel shares a
single bit for those, so they are actually aliases for each other although the
meaning differs depending on address family.
.TP .TP
.BR primary " and " secondary .BR -temporary " or " -secondary
only list primary (or secondary) addresses. These flags are aliases for
.BR primary .
.TP
.B primary
List only primary addresses, in IPv6 exclude temporary ones. This flag is the
inverse of
.BR temporary " and " secondary .
.TP
.B -primary
This is an alias for
.BR temporary " or " secondary .
.SS ip address flush - flush protocol addresses .SS ip address flush - flush protocol addresses
This command flushes the protocol addresses selected by some criteria. This command flushes the protocol addresses selected by some criteria.