From: Frantisek Sumsal Date: Thu, 18 May 2023 10:54:15 +0000 (+0200) Subject: nspawn: correctly parse a list of interfaces X-Git-Tag: v254-rc1~447^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f4d843afc450573b4fa8cf4b122d43915698d76;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c index d898f0d4c91..b1c4f1cad8e 100644 --- a/src/nspawn/nspawn-network.c +++ b/src/nspawn/nspawn-network.c @@ -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); - - if (isempty(p)) { - if (ifprefix) - b = strjoin(ifprefix, a); - else - b = strdup(a); - } else - b = strdup(p); - if (!b) - return log_oom(); + for (;;) { + _cleanup_free_ char *word = NULL, *a = NULL, *b = NULL; + const char *interface; - if (!ifname_valid(b)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "%s, interface name not valid: %s", iftype, b); + 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; - r = strv_push_pair(l, a, b); - if (r < 0) - return log_oom(); + 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); + + 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; }