Compare commits

..

13 Commits

Author SHA1 Message Date
Yu Watanabe f4dad55b8b
Merge pull request #13899 from poettering/in-gid-tweak
user-util: tweak to in_gid()
2019-11-03 22:54:32 +09:00
Yu Watanabe 5e467d74ad
Merge pull request #13909 from poettering/env-copy-pid
Fixes for the "saved_env" copy logic
2019-11-03 22:46:42 +09:00
Justin Trudell 0ccdaa79ca nspawn: respect quiet on capabilities warning 2019-11-03 22:05:48 +09:00
Lennart Poettering fe573a798d fs-util: let's avoid unnecessary strerror()
strerror() is not thread safe. Let's avoid it where it is easy hence.

(Ideally we'd not use it at all anymore, but that's sometimes a bit
nasty, not in this case though, where it is very easy to avoid)

Follow-up for: 27c3112dcb
2019-11-03 22:04:39 +09:00
Yu Watanabe 8574039520
Merge pull request #13916 from ddstreet/test-network
test-network: minor changes to work better on Debian/Ubuntu autopkgtest
2019-11-03 21:42:15 +09:00
Lennart Poettering 43c3fb4680 nspawn: mangle slice name
It's user-facing, parsed from the command line and we typically mangle
in these cases, let's do so here too. (In particular as the identical
switch for systemd-run already does it.)
2019-11-03 21:32:56 +09:00
Dan Streetman 426654d728 test-network: Remove/replace non-capturing group regex
The systemd-networkd-tests.py has some regex that uses non-capturing
groups, but there is no need to use that with assertRegex; the
groups aren't referenced so it doesn't matter if it's capturing or
non-capturing.  However, there are a few places where optional groups
should have been used instead, so this changes that.

Specifically, groups like this:
(?:whatever |)
should actually be:
(whatever )?

Additionally, this is specifically needed for these tests to run on
Debian systems, because this assertRegex:
'Link File: (?:/usr)/lib/systemd/network/99-default.link'
needs to be:
'Link File: (/usr)?/lib/systemd/network/99-default.link'
2019-11-01 12:32:49 -04:00
Dan Streetman 7471bcb06e test: check /usr/lib and /lib for systemd binaries
Fedora uses /usr/lib while Debian uses /lib; find the right location
2019-11-01 12:00:57 -04:00
Dan Streetman 856423f14d test/test-network/systemd-networkd-tests.py: suppress stderr for functionality checks 2019-11-01 12:00:53 -04:00
Lennart Poettering dfaf16ebed static-destruct: add missing closing '(' in comment 2019-11-01 11:31:20 +01:00
Lennart Poettering 0e06a03165 pid1: rework environment block copy logic
This reworks the logic introduced in
a5cede8c24 (#13693).

First of all, let's move this out of util.c, since only PID 1 really
needs this, and there's no real need to have it in util.c.

Then, fix freeing of the variable. It previously relied on
STATIC_DESTRUCTOR_REGISTER() which however relies on static_destruct()
to be called explicitly. Currently only the main-func.h macros do that,
and PID 1 does not. (It might be worth investigating whether to do that,
but it's not trivial.) Hence the freeing wasn't applied.

Finally, an OOM check was missing, add it in.
2019-11-01 11:30:59 +01:00
Lennart Poettering eb2cfa81b0 test: add really basic in_gid() test 2019-10-31 21:00:00 +01:00
Lennart Poettering 6e0a388854 user-util: tweak to in_gid()
Let's make this robust towards parallel updates to group lists. This is
not going to happen IRL, but it makes me sleep better at night: let's
iterate a couple of times in case the list is updated while we are at
it.

Follow-up for: f5e0b942af
2019-10-31 20:59:27 +01:00
9 changed files with 129 additions and 84 deletions

View File

@ -662,15 +662,12 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
} }
int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) {
if (inotify_add_watch(fd, pathname, mask) < 0) { if (inotify_add_watch(fd, pathname, mask) < 0) {
const char *reason;
if (errno == ENOSPC) if (errno == ENOSPC)
reason = "inotify watch limit reached"; return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname);
else
reason = strerror_safe(errno);
return log_error_errno(errno, "Failed to add a watch for %s: %s", pathname, reason); return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname);
} }
return 0; return 0;

View File

@ -40,8 +40,8 @@ typedef struct StaticDestructor {
extern const struct StaticDestructor _weak_ __start_SYSTEMD_STATIC_DESTRUCT[]; extern const struct StaticDestructor _weak_ __start_SYSTEMD_STATIC_DESTRUCT[];
extern const struct StaticDestructor _weak_ __stop_SYSTEMD_STATIC_DESTRUCT[]; extern const struct StaticDestructor _weak_ __stop_SYSTEMD_STATIC_DESTRUCT[];
/* The function to destroy everything. (Note that this must be static inline, as it's key that it remains in the same /* The function to destroy everything. (Note that this must be static inline, as it's key that it remains in
* linking unit as the variables we want to destroy. */ * the same linking unit as the variables we want to destroy.) */
static inline void static_destruct(void) { static inline void static_destruct(void) {
const StaticDestructor *d; const StaticDestructor *d;

View File

@ -409,8 +409,10 @@ char* gid_to_name(gid_t gid) {
} }
int in_gid(gid_t gid) { int in_gid(gid_t gid) {
gid_t *gids; _cleanup_free_ gid_t *allocated = NULL;
int ngroups, r, i; gid_t local[16], *p = local;
int ngroups = ELEMENTSOF(local);
unsigned attempt = 0;
if (getgid() == gid) if (getgid() == gid)
return 1; return 1;
@ -421,23 +423,39 @@ int in_gid(gid_t gid) {
if (!gid_is_valid(gid)) if (!gid_is_valid(gid))
return -EINVAL; return -EINVAL;
for (;;) {
ngroups = getgroups(ngroups, p);
if (ngroups >= 0)
break;
if (errno != EINVAL)
return -errno;
/* Give up eventually */
if (attempt++ > 10)
return -EINVAL;
/* Get actual size needed, and size the array explicitly. Note that this is potentially racy
* to use (in multi-threaded programs), hence let's call this in a loop. */
ngroups = getgroups(0, NULL); ngroups = getgroups(0, NULL);
if (ngroups < 0) if (ngroups < 0)
return -errno; return -errno;
if (ngroups == 0) if (ngroups == 0)
return 0; return false;
gids = newa(gid_t, ngroups); free(allocated);
r = getgroups(ngroups, gids); allocated = new(gid_t, ngroups);
if (r < 0) if (!allocated)
return -errno; return -ENOMEM;
for (i = 0; i < r; i++) p = allocated;
if (gids[i] == gid) }
return 1;
return 0; for (int i = 0; i < ngroups; i++)
if (p[i] == gid)
return true;
return false;
} }
int in_group(const char *name) { int in_group(const char *name) {

View File

@ -38,7 +38,6 @@
#include "set.h" #include "set.h"
#include "signal-util.h" #include "signal-util.h"
#include "stat-util.h" #include "stat-util.h"
#include "static-destruct.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "time-util.h" #include "time-util.h"
@ -49,11 +48,8 @@
int saved_argc = 0; int saved_argc = 0;
char **saved_argv = NULL; char **saved_argv = NULL;
char **saved_env = NULL;
static int saved_in_initrd = -1; static int saved_in_initrd = -1;
STATIC_DESTRUCTOR_REGISTER(saved_env, strv_freep);
bool kexec_loaded(void) { bool kexec_loaded(void) {
_cleanup_free_ char *s = NULL; _cleanup_free_ char *s = NULL;
@ -301,7 +297,3 @@ void disable_coredumps(void) {
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m"); log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
} }
void save_env(void) {
saved_env = strv_copy(environ);
}

View File

@ -13,9 +13,6 @@ static inline void save_argc_argv(int argc, char **argv) {
saved_argv = argv; saved_argv = argv;
} }
extern char **saved_env;
void save_env(void);
bool kexec_loaded(void); bool kexec_loaded(void);
int prot_from_flags(int flags) _const_; int prot_from_flags(int flags) _const_;

View File

@ -146,6 +146,9 @@ static OOMPolicy arg_default_oom_policy;
static CPUSet arg_cpu_affinity; static CPUSet arg_cpu_affinity;
static NUMAPolicy arg_numa_policy; static NUMAPolicy arg_numa_policy;
/* A copy of the original environment block */
static char **saved_env = NULL;
static int parse_configuration(const struct rlimit *saved_rlimit_nofile, static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
const struct rlimit *saved_rlimit_memlock); const struct rlimit *saved_rlimit_memlock);
@ -2353,6 +2356,17 @@ static bool early_skip_setup_check(int argc, char *argv[]) {
return found_deserialize; /* When we are deserializing, then we are reexecuting, hence avoid the extensive setup */ return found_deserialize; /* When we are deserializing, then we are reexecuting, hence avoid the extensive setup */
} }
static int save_env(void) {
char **l;
l = strv_copy(environ);
if (!l)
return -ENOMEM;
strv_free_and_replace(saved_env, l);
return 0;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL, userspace_timestamp = DUAL_TIMESTAMP_NULL, kernel_timestamp = DUAL_TIMESTAMP_NULL, dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL, userspace_timestamp = DUAL_TIMESTAMP_NULL, kernel_timestamp = DUAL_TIMESTAMP_NULL,
@ -2391,9 +2405,13 @@ int main(int argc, char *argv[]) {
/* Save the original command line */ /* Save the original command line */
save_argc_argv(argc, argv); save_argc_argv(argc, argv);
/* Save the original environment as we might need to restore it if we're requested to /* Save the original environment as we might need to restore it if we're requested to execute another
* execute another system manager later. */ * system manager later. */
save_env(); r = save_env();
if (r < 0) {
error_message = "Failed to copy environment block";
goto finish;
}
/* Make sure that if the user says "syslog" we actually log to the journal. */ /* Make sure that if the user says "syslog" we actually log to the journal. */
log_set_upgrade_syslog_to_journal(true); log_set_upgrade_syslog_to_journal(true);
@ -2681,6 +2699,8 @@ finish:
arg_serialization = safe_fclose(arg_serialization); arg_serialization = safe_fclose(arg_serialization);
fds = fdset_free(fds); fds = fdset_free(fds);
saved_env = strv_free(saved_env);
#if HAVE_VALGRIND_VALGRIND_H #if HAVE_VALGRIND_VALGRIND_H
/* If we are PID 1 and running under valgrind, then let's exit /* If we are PID 1 and running under valgrind, then let's exit
* here explicitly. valgrind will only generate nice output on * here explicitly. valgrind will only generate nice output on

View File

@ -103,6 +103,7 @@
#include "terminal-util.h" #include "terminal-util.h"
#include "tmpfile-util.h" #include "tmpfile-util.h"
#include "umask-util.h" #include "umask-util.h"
#include "unit-name.h"
#include "user-util.h" #include "user-util.h"
#include "util.h" #include "util.h"
@ -891,13 +892,17 @@ static int parse_argv(int argc, char *argv[]) {
arg_settings_mask |= SETTING_MACHINE_ID; arg_settings_mask |= SETTING_MACHINE_ID;
break; break;
case 'S': case 'S': {
r = free_and_strdup(&arg_slice, optarg); _cleanup_free_ char *mangled = NULL;
r = unit_name_mangle_with_suffix(optarg, NULL, UNIT_NAME_MANGLE_WARN, ".slice", &mangled);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
free_and_replace(arg_slice, mangled);
arg_settings_mask |= SETTING_SLICE; arg_settings_mask |= SETTING_SLICE;
break; break;
}
case 'M': case 'M':
if (isempty(optarg)) if (isempty(optarg))
@ -2385,7 +2390,8 @@ static int drop_capabilities(uid_t uid) {
/* If we're not using OCI, proceed with mangled capabilities (so we don't error out) /* If we're not using OCI, proceed with mangled capabilities (so we don't error out)
* in order to maintain the same behavior as systemd < 242. */ * in order to maintain the same behavior as systemd < 242. */
if (capability_quintet_mangle(&q)) if (capability_quintet_mangle(&q))
log_warning("Some capabilities will not be set because they are not in the current bounding set."); log_full(arg_quiet ? LOG_DEBUG : LOG_WARNING,
"Some capabilities will not be set because they are not in the current bounding set.");
} }

View File

@ -286,6 +286,15 @@ static void test_make_salt(void) {
assert(!streq(s, t)); assert(!streq(s, t));
} }
static void test_in_gid(void) {
assert(in_gid(getgid()) >= 0);
assert(in_gid(getegid()) >= 0);
assert(in_gid(GID_INVALID) < 0);
assert(in_gid(TTY_GID) == 0); /* The TTY gid is for owning ttys, it would be really really weird if we were in it. */
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_uid_to_name_one(0, "root"); test_uid_to_name_one(0, "root");
test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME); test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
@ -320,5 +329,7 @@ int main(int argc, char *argv[]) {
test_make_salt(); test_make_salt();
test_in_gid();
return 0; return 0;
} }

View File

@ -22,12 +22,16 @@ network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid' dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file' dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
networkd_bin='/usr/lib/systemd/systemd-networkd' systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
resolved_bin='/usr/lib/systemd/systemd-resolved' which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
networkctl_bin='/usr/bin/networkctl' networkd_bin=shutil.which('systemd-networkd', path=which_paths)
resolvectl_bin='/usr/bin/resolvectl' resolved_bin=shutil.which('systemd-resolved', path=which_paths)
timedatectl_bin='/usr/bin/timedatectl' wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
networkctl_bin=shutil.which('networkctl', path=which_paths)
resolvectl_bin=shutil.which('resolvectl', path=which_paths)
timedatectl_bin=shutil.which('timedatectl', path=which_paths)
use_valgrind=False use_valgrind=False
enable_debug=True enable_debug=True
env = {} env = {}
@ -53,7 +57,7 @@ def run(*command, **kwargs):
def is_module_available(module_name): def is_module_available(module_name):
lsmod_output = check_output('lsmod') lsmod_output = check_output('lsmod')
module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE) module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
return module_re.search(lsmod_output) or not call('modprobe', module_name) return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL)
def expectedFailureIfModuleIsNotAvailable(module_name): def expectedFailureIfModuleIsNotAvailable(module_name):
def f(func): def f(func):
@ -65,7 +69,7 @@ def expectedFailureIfModuleIsNotAvailable(module_name):
def expectedFailureIfERSPANModuleIsNotAvailable(): def expectedFailureIfERSPANModuleIsNotAvailable():
def f(func): def f(func):
rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123') rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr=subprocess.DEVNULL)
if rc == 0: if rc == 0:
call('ip link del erspan99') call('ip link del erspan99')
return func return func
@ -76,7 +80,7 @@ def expectedFailureIfERSPANModuleIsNotAvailable():
def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable(): def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
def f(func): def f(func):
rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7') rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL)
if rc == 0: if rc == 0:
call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7') call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
return func return func
@ -87,7 +91,7 @@ def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable(): def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
def f(func): def f(func):
rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7') rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL)
if rc == 0: if rc == 0:
call('ip rule del not from 192.168.100.19 ipproto tcp table 7') call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
return func return func
@ -99,7 +103,7 @@ def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
def expectedFailureIfLinkFileFieldIsNotSet(): def expectedFailureIfLinkFileFieldIsNotSet():
def f(func): def f(func):
support = False support = False
rc = call('ip link add name dummy99 type dummy') rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL)
if rc == 0: if rc == 0:
ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT) ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip(): if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
@ -115,7 +119,7 @@ def expectedFailureIfLinkFileFieldIsNotSet():
def expectedFailureIfNexthopIsNotAvailable(): def expectedFailureIfNexthopIsNotAvailable():
def f(func): def f(func):
rc = call('ip nexthop list') rc = call('ip nexthop list', stderr=subprocess.DEVNULL)
if rc == 0: if rc == 0:
return func return func
else: else:
@ -510,12 +514,12 @@ class NetworkctlTests(unittest.TestCase, Utilities):
output = check_output(*networkctl_cmd, 'status', 'test1') output = check_output(*networkctl_cmd, 'status', 'test1')
print(output) print(output)
self.assertRegex(output, r'Link File: (?:/usr)/lib/systemd/network/99-default.link') self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network') self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
output = check_output(*networkctl_cmd, 'status', 'lo') output = check_output(*networkctl_cmd, 'status', 'lo')
print(output) print(output)
self.assertRegex(output, r'Link File: (?:/usr)/lib/systemd/network/99-default.link') self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
self.assertRegex(output, r'Network File: n/a') self.assertRegex(output, r'Network File: n/a')
def test_delete_links(self): def test_delete_links(self):
@ -748,7 +752,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online(['bridge99', 'test1:degraded'], bool_any=True) self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring') self.check_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
self.check_operstate('test1', 'degraded') self.check_operstate('test1', 'degraded')
def test_bridge(self): def test_bridge(self):
@ -921,7 +925,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
output = check_output('ip -d link show tun99') output = check_output('ip -d link show tun99')
print(output) print(output)
# Old ip command does not support IFF_ flags # Old ip command does not support IFF_ flags
self.assertRegex(output, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ') self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
def test_tap(self): def test_tap(self):
copy_unit_to_networkd_unit_path('25-tap.netdev') copy_unit_to_networkd_unit_path('25-tap.netdev')
@ -932,7 +936,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
output = check_output('ip -d link show tap99') output = check_output('ip -d link show tap99')
print(output) print(output)
# Old ip command does not support IFF_ flags # Old ip command does not support IFF_ flags
self.assertRegex(output, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ') self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
@expectedFailureIfModuleIsNotAvailable('vrf') @expectedFailureIfModuleIsNotAvailable('vrf')
def test_vrf(self): def test_vrf(self):
@ -1010,16 +1014,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
output = check_output('ip -d link show ipiptun99') output = check_output('ip -d link show ipiptun99')
print(output) print(output)
self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98') self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
output = check_output('ip -d link show ipiptun98') output = check_output('ip -d link show ipiptun98')
print(output) print(output)
self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98') self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
output = check_output('ip -d link show ipiptun97') output = check_output('ip -d link show ipiptun97')
print(output) print(output)
self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98') self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
output = check_output('ip -d link show ipiptun96') output = check_output('ip -d link show ipiptun96')
print(output) print(output)
self.assertRegex(output, 'ipip (?:ipip |)remote any local any dev dummy98') self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
def test_gre_tunnel(self): def test_gre_tunnel(self):
copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network', copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
@ -1159,10 +1163,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
output = check_output('ip -d link show vti6tun98') output = check_output('ip -d link show vti6tun98')
print(output) print(output)
self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98') self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
output = check_output('ip -d link show vti6tun97') output = check_output('ip -d link show vti6tun97')
print(output) print(output)
self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
def test_ip6tnl_tunnel(self): def test_ip6tnl_tunnel(self):
copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network', copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
@ -1177,10 +1181,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
output = check_output('ip -d link show ip6tnl98') output = check_output('ip -d link show ip6tnl98')
print(output) print(output)
self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98') self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
output = check_output('ip -d link show ip6tnl97') output = check_output('ip -d link show ip6tnl97')
print(output) print(output)
self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
def test_sit_tunnel(self): def test_sit_tunnel(self):
copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network', copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
@ -1193,16 +1197,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
output = check_output('ip -d link show sittun99') output = check_output('ip -d link show sittun99')
print(output) print(output)
self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98") self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
output = check_output('ip -d link show sittun98') output = check_output('ip -d link show sittun98')
print(output) print(output)
self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98") self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
output = check_output('ip -d link show sittun97') output = check_output('ip -d link show sittun97')
print(output) print(output)
self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98") self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
output = check_output('ip -d link show sittun96') output = check_output('ip -d link show sittun96')
print(output) print(output)
self.assertRegex(output, "sit (?:ip6ip |)remote any local any dev dummy98") self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
def test_isatap_tunnel(self): def test_isatap_tunnel(self):
copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network', copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
@ -1596,7 +1600,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
print(output) print(output)
self.assertRegex(output, '111:') self.assertRegex(output, '111:')
self.assertRegex(output, 'from 192.168.100.18') self.assertRegex(output, 'from 192.168.100.18')
self.assertRegex(output, r'tos (?:0x08|throughput)\s') self.assertRegex(output, r'tos (0x08|throughput)\s')
self.assertRegex(output, 'iif test1') self.assertRegex(output, 'iif test1')
self.assertRegex(output, 'oif test1') self.assertRegex(output, 'oif test1')
self.assertRegex(output, 'lookup 7') self.assertRegex(output, 'lookup 7')
@ -1634,11 +1638,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
output = check_output('ip rule list table 7') output = check_output('ip rule list table 7')
print(output) print(output)
self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7') self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
output = check_output('ip rule list table 8') output = check_output('ip rule list table 8')
print(output) print(output)
self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8') self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
stop_networkd(remove_state_files=False) stop_networkd(remove_state_files=False)
@ -2109,7 +2113,7 @@ class NetworkdStateFileTests(unittest.TestCase, Utilities):
self.assertRegex(data, r'LLMNR=no') self.assertRegex(data, r'LLMNR=no')
self.assertRegex(data, r'MDNS=yes') self.assertRegex(data, r'MDNS=yes')
self.assertRegex(data, r'DNSSEC=no') self.assertRegex(data, r'DNSSEC=no')
self.assertRegex(data, r'ADDRESSES=192.168.(?:10.10|12.12)/24 192.168.(?:12.12|10.10)/24') self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env) check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env) check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
@ -2379,7 +2383,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
print('### ip -6 route list table all dev bridge99') print('### ip -6 route list table all dev bridge99')
output = check_output('ip -6 route list table all dev bridge99') output = check_output('ip -6 route list table all dev bridge99')
print(output) print(output)
self.assertRegex(output, 'ff00::/8 table local metric 256 (?:linkdown |)pref medium') self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
def test_bridge_ignore_carrier_loss(self): def test_bridge_ignore_carrier_loss(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
@ -2645,7 +2649,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
print(output) print(output)
@ -2824,7 +2828,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
output = check_output('ip address show dev veth99 scope global') output = check_output('ip address show dev veth99 scope global')
print(output) print(output)
self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (?:noprefixroute dynamic|dynamic noprefixroute)') self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
output = check_output('ip -6 route show dev veth99') output = check_output('ip -6 route show dev veth99')
print(output) print(output)
@ -2933,7 +2937,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
output = check_output('ip address show dev veth99 scope global') output = check_output('ip address show dev veth99 scope global')
print(output) print(output)
@ -2976,7 +2980,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
print('## ip -d link show dev vrf99') print('## ip -d link show dev vrf99')
output = check_output('ip -d link show dev vrf99') output = check_output('ip -d link show dev vrf99')
@ -2988,7 +2992,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
print(output) print(output)
self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99') self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
self.assertRegex(output, 'inet6 .* scope link') self.assertRegex(output, 'inet6 .* scope link')
print('## ip address show dev veth99') print('## ip address show dev veth99')
@ -2996,7 +3000,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
print(output) print(output)
self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99') self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)') self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
self.assertRegex(output, 'inet6 .* scope link') self.assertRegex(output, 'inet6 .* scope link')
print('## ip route show vrf vrf99') print('## ip route show vrf vrf99')
@ -3145,7 +3149,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
time.sleep(3) time.sleep(3)
output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
@ -3163,7 +3167,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
time.sleep(3) time.sleep(3)
output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
@ -3181,7 +3185,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
time.sleep(3) time.sleep(3)
output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
@ -3199,7 +3203,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
# link become 'routable' when at least one protocol provide an valid address. # link become 'routable' when at least one protocol provide an valid address.
self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
time.sleep(3) time.sleep(3)
output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)