nspawn: correctly parse a list of interfaces

Interface=/MACVLAN=/IPVLAN= nspawn options take a _list_ of interface
names - this was recently enhanced by 2f091b1b49 to support interface
pairs. Unfortunately, this also introduced a regression where we don't
parse the list as a list, but just as a single value. For example,
having `Interface=sd-shared1 sd-shared2` in an nspawn config file would
throw:

systemd-nspawn[898]: Network interface, interface name not valid: sd-shared1 sd-shared2
systemd-nspawn[898]: /run/systemd/nspawn/testsuite-13.nspawn-settings.1po.nspawn:41: Failed to parse file: Invalid argument

Follow-up to 2f091b1b49.
This commit is contained in:
Frantisek Sumsal 2023-05-18 12:54:15 +02:00
parent 28ed232639
commit 8f4d843afc

View file

@ -752,38 +752,48 @@ int remove_veth_links(const char *primary, char **pairs) {
}
static int network_iface_pair_parse(const char* iftype, char ***l, const char *p, const char* ifprefix) {
_cleanup_free_ char *a = NULL, *b = NULL;
int r;
r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_error_errno(r, "Failed to extract first word in %s parameter: %m", iftype);
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Short read while reading %s parameter: %m", iftype);
if (!ifname_valid(a))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, a);
for (;;) {
_cleanup_free_ char *word = NULL, *a = NULL, *b = NULL;
const char *interface;
if (isempty(p)) {
if (ifprefix)
b = strjoin(ifprefix, a);
else
b = strdup(a);
} else
b = strdup(p);
if (!b)
return log_oom();
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse interface name: %m");
if (r == 0)
break;
if (!ifname_valid(b))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, b);
interface = word;
r = extract_first_word(&interface, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
if (r < 0)
return log_error_errno(r, "Failed to extract first word in %s parameter: %m", iftype);
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Short read while reading %s parameter: %m", iftype);
if (!ifname_valid(a))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, a);
r = strv_push_pair(l, a, b);
if (r < 0)
return log_oom();
if (isempty(interface)) {
if (ifprefix)
b = strjoin(ifprefix, a);
else
b = strdup(a);
} else
b = strdup(interface);
if (!b)
return log_oom();
if (!ifname_valid(b))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s, interface name not valid: %s", iftype, b);
r = strv_consume_pair(l, TAKE_PTR(a), TAKE_PTR(b));
if (r < 0)
return log_oom();
}
a = b = NULL;
return 0;
}