mirror of
https://github.com/systemd/systemd.git
synced 2024-12-14 04:33:37 +08:00
Merge pull request #14547 from keszybz/networkctl-matching
networkctl: return error or warning when interfaces are not matched
This commit is contained in:
commit
222a6aace7
@ -1160,9 +1160,9 @@ static int graph_one_property(
|
|||||||
assert(prop);
|
assert(prop);
|
||||||
assert(color);
|
assert(color);
|
||||||
|
|
||||||
match_patterns = strv_fnmatch(patterns, u->id, 0);
|
match_patterns = strv_fnmatch(patterns, u->id);
|
||||||
|
|
||||||
if (!strv_isempty(from_patterns) && !match_patterns && !strv_fnmatch(from_patterns, u->id, 0))
|
if (!strv_isempty(from_patterns) && !match_patterns && !strv_fnmatch(from_patterns, u->id))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units);
|
r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units);
|
||||||
@ -1172,9 +1172,9 @@ static int graph_one_property(
|
|||||||
STRV_FOREACH(unit, units) {
|
STRV_FOREACH(unit, units) {
|
||||||
bool match_patterns2;
|
bool match_patterns2;
|
||||||
|
|
||||||
match_patterns2 = strv_fnmatch(patterns, *unit, 0);
|
match_patterns2 = strv_fnmatch(patterns, *unit);
|
||||||
|
|
||||||
if (!strv_isempty(to_patterns) && !match_patterns2 && !strv_fnmatch(to_patterns, *unit, 0))
|
if (!strv_isempty(to_patterns) && !match_patterns2 && !strv_fnmatch(to_patterns, *unit))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!strv_isempty(patterns) && !match_patterns && !match_patterns2)
|
if (!strv_isempty(patterns) && !match_patterns && !match_patterns2)
|
||||||
|
@ -800,12 +800,13 @@ char **strv_shell_escape(char **l, const char *bad) {
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
|
bool strv_fnmatch_full(char* const* patterns, const char *s, int flags, size_t *matched_pos) {
|
||||||
char* const* p;
|
for (size_t i = 0; patterns && patterns[i]; i++)
|
||||||
|
if (fnmatch(patterns[i], s, flags) == 0) {
|
||||||
STRV_FOREACH(p, patterns)
|
if (matched_pos)
|
||||||
if (fnmatch(*p, s, flags) == 0)
|
*matched_pos = i;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -177,12 +177,15 @@ void strv_print(char * const *l);
|
|||||||
char **strv_reverse(char **l);
|
char **strv_reverse(char **l);
|
||||||
char **strv_shell_escape(char **l, const char *bad);
|
char **strv_shell_escape(char **l, const char *bad);
|
||||||
|
|
||||||
bool strv_fnmatch(char* const* patterns, const char *s, int flags);
|
bool strv_fnmatch_full(char* const* patterns, const char *s, int flags, size_t *matched_pos);
|
||||||
|
static inline bool strv_fnmatch(char* const* patterns, const char *s) {
|
||||||
|
return strv_fnmatch_full(patterns, s, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, int flags) {
|
static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, int flags) {
|
||||||
assert(s);
|
assert(s);
|
||||||
return strv_isempty(patterns) ||
|
return strv_isempty(patterns) ||
|
||||||
strv_fnmatch(patterns, s, flags);
|
strv_fnmatch_full(patterns, s, flags, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
char ***strv_free_free(char ***l);
|
char ***strv_free_free(char ***l);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "format-table.h"
|
#include "format-table.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
|
#include "glob-util.h"
|
||||||
#include "hwdb-util.h"
|
#include "hwdb-util.h"
|
||||||
#include "local-addresses.h"
|
#include "local-addresses.h"
|
||||||
#include "locale-util.h"
|
#include "locale-util.h"
|
||||||
@ -267,7 +268,7 @@ static int decode_netdev(sd_netlink_message *m, LinkInfo *info) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) {
|
static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns, bool matched_patterns[]) {
|
||||||
_cleanup_strv_free_ char **altnames = NULL;
|
_cleanup_strv_free_ char **altnames = NULL;
|
||||||
const char *name;
|
const char *name;
|
||||||
int ifindex, r;
|
int ifindex, r;
|
||||||
@ -297,20 +298,26 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) {
|
|||||||
|
|
||||||
if (patterns) {
|
if (patterns) {
|
||||||
char str[DECIMAL_STR_MAX(int)];
|
char str[DECIMAL_STR_MAX(int)];
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
assert(matched_patterns);
|
||||||
|
|
||||||
xsprintf(str, "%i", ifindex);
|
xsprintf(str, "%i", ifindex);
|
||||||
if (!strv_fnmatch(patterns, str, 0) && !strv_fnmatch(patterns, name, 0)) {
|
if (!strv_fnmatch_full(patterns, str, 0, &pos) &&
|
||||||
|
!strv_fnmatch_full(patterns, name, 0, &pos)) {
|
||||||
bool match = false;
|
bool match = false;
|
||||||
char **p;
|
char **p;
|
||||||
|
|
||||||
STRV_FOREACH(p, altnames)
|
STRV_FOREACH(p, altnames)
|
||||||
if (strv_fnmatch(patterns, *p, 0)) {
|
if (strv_fnmatch_full(patterns, *p, 0, &pos)) {
|
||||||
match = true;
|
match = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!match)
|
if (!match)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matched_patterns[pos] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_rtnl_message_link_get_type(m, &info->iftype);
|
r = sd_rtnl_message_link_get_type(m, &info->iftype);
|
||||||
@ -465,11 +472,18 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to enumerate links: %m");
|
return log_error_errno(r, "Failed to enumerate links: %m");
|
||||||
|
|
||||||
|
_cleanup_free_ bool *matched_patterns = NULL;
|
||||||
|
if (patterns) {
|
||||||
|
matched_patterns = new0(bool, strv_length(patterns));
|
||||||
|
if (!matched_patterns)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
for (i = reply; i; i = sd_netlink_message_next(i)) {
|
for (i = reply; i; i = sd_netlink_message_next(i)) {
|
||||||
if (!GREEDY_REALLOC0(links, allocated, c + 2)) /* We keep one trailing one as marker */
|
if (!GREEDY_REALLOC0(links, allocated, c + 2)) /* We keep one trailing one as marker */
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
r = decode_link(i, links + c, patterns);
|
r = decode_link(i, links + c, patterns, matched_patterns);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
@ -487,6 +501,20 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
|
|||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look if we matched all our arguments that are not globs. It
|
||||||
|
* is OK for a glob to match nothing, but not for an exact argument. */
|
||||||
|
for (size_t pos = 0; pos < strv_length(patterns); pos++) {
|
||||||
|
if (matched_patterns[pos])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (string_is_glob(patterns[pos]))
|
||||||
|
log_debug("Pattern \"%s\" doesn't match any interface, ignoring.",
|
||||||
|
patterns[pos]);
|
||||||
|
else
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(ENODEV),
|
||||||
|
"Interface \"%s\" not found.", patterns[pos]);
|
||||||
|
}
|
||||||
|
|
||||||
typesafe_qsort(links, c, link_info_compare);
|
typesafe_qsort(links, c, link_info_compare);
|
||||||
|
|
||||||
if (bus)
|
if (bus)
|
||||||
@ -495,6 +523,9 @@ static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, Lin
|
|||||||
|
|
||||||
*ret = TAKE_PTR(links);
|
*ret = TAKE_PTR(links);
|
||||||
|
|
||||||
|
if (patterns && c == 0)
|
||||||
|
log_warning("No interfaces matched.");
|
||||||
|
|
||||||
return (int) c;
|
return (int) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1875,7 +1875,7 @@ static int link_new_bound_by_list(Link *link) {
|
|||||||
if (strv_isempty(carrier->network->bind_carrier))
|
if (strv_isempty(carrier->network->bind_carrier))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
|
if (strv_fnmatch(carrier->network->bind_carrier, link->ifname)) {
|
||||||
r = link_put_carrier(link, carrier, &link->bound_by_links);
|
r = link_put_carrier(link, carrier, &link->bound_by_links);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1917,7 +1917,7 @@ static int link_new_bound_to_list(Link *link) {
|
|||||||
m = link->manager;
|
m = link->manager;
|
||||||
|
|
||||||
HASHMAP_FOREACH (carrier, m->links, i) {
|
HASHMAP_FOREACH (carrier, m->links, i) {
|
||||||
if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
|
if (strv_fnmatch(link->network->bind_carrier, carrier->ifname)) {
|
||||||
r = link_put_carrier(link, carrier, &link->bound_to_links);
|
r = link_put_carrier(link, carrier, &link->bound_to_links);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -29,7 +29,7 @@ static bool manager_ignore_link(Manager *m, Link *link) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* ignore interfaces we explicitly are asked to ignore */
|
/* ignore interfaces we explicitly are asked to ignore */
|
||||||
return strv_fnmatch(m->ignore, link->ifname, 0);
|
return strv_fnmatch(m->ignore, link->ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) {
|
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) {
|
||||||
|
@ -924,14 +924,16 @@ static void test_foreach_string(void) {
|
|||||||
|
|
||||||
static void test_strv_fnmatch(void) {
|
static void test_strv_fnmatch(void) {
|
||||||
_cleanup_strv_free_ char **v = NULL;
|
_cleanup_strv_free_ char **v = NULL;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0));
|
assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a"));
|
||||||
|
|
||||||
v = strv_new("*\\*");
|
v = strv_new("xxx", "*\\*", "yyy");
|
||||||
assert_se(!strv_fnmatch(v, "\\", 0));
|
assert_se(!strv_fnmatch_full(v, "\\", 0, NULL));
|
||||||
assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE));
|
assert_se(strv_fnmatch_full(v, "\\", FNM_NOESCAPE, &pos));
|
||||||
|
assert(pos == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user