diff options
-rw-r--r-- | src/devices/nm-device-tun.c | 3 | ||||
-rw-r--r-- | src/devices/tests/test-lldp.c | 52 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 23 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 17 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 6 | ||||
-rw-r--r-- | src/platform/tests/test-common.c | 7 | ||||
-rw-r--r-- | src/platform/tests/test-common.h | 3 | ||||
-rw-r--r-- | src/platform/tests/test-link.c | 12 |
8 files changed, 88 insertions, 35 deletions
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index 123455f16d..c3ce4b7357 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -264,7 +264,8 @@ create_and_realize (NMDevice *device, plerr = nm_platform_link_tun_add (nm_device_get_platform (device), iface, &props, - out_plink); + out_plink, + NULL); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create TUN/TAP interface '%s' for '%s': %s", diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 655f26ecad..5d0625f80a 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -347,8 +347,7 @@ static void _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { const NMPlatformLink *link; - struct ifreq ifr = { }; - int fd, s; + nm_auto_close int fd = -1; fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); if (fd == -1) { @@ -357,20 +356,45 @@ _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) return; } - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); - g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); - - /* Bring the interface up */ - s = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - g_assert (s >= 0); - ifr.ifr_flags |= IFF_UP; - g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); - nm_close (s); + if (nmtst_get_rand_bool ()) { + const NMPlatformLnkTun lnk = { + .type = IFF_TAP, + .pi = FALSE, + .vnet_hdr = FALSE, + .multi_queue = FALSE, + .persist = FALSE, + }; + + nm_close (nm_steal_fd (&fd)); + + link = nmtstp_link_tun_add (NM_PLATFORM_GET, + FALSE, + TEST_IFNAME, + &lnk, + &fd); + g_assert (link); + nmtstp_link_set_updown (NM_PLATFORM_GET, -1, link->ifindex, TRUE); + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 0); + } else { + int s; + struct ifreq ifr = { }; + + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); + g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); + + /* Bring the interface up */ + s = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + g_assert (s >= 0); + ifr.ifr_flags |= IFF_UP; + g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); + nm_close (s); + + link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 100); + } - link = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 100); fixture->ifindex = link->ifindex; - fixture->fd = fd; + fixture->fd = nm_steal_fd (&fd); memcpy (fixture->mac, link->addr.data, ETH_ALEN); } diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 8923708657..0ed8fa06fb 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -5596,15 +5596,15 @@ static gboolean link_tun_add (NMPlatform *platform, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link) + const NMPlatformLink **out_link, + int *out_fd) { const NMPObject *obj; struct ifreq ifr = { }; nm_auto_close int fd = -1; - if ( !NM_IN_SET (props->type, IFF_TAP, IFF_TUN) - || !props->persist) - g_return_val_if_reached (FALSE); + nm_assert (NM_IN_SET (props->type, IFF_TAP, IFF_TUN)); + nm_assert (props->persist || out_fd); fd = open ("/dev/net/tun", O_RDWR | O_CLOEXEC); if (fd < 0) @@ -5629,18 +5629,23 @@ link_tun_add (NMPlatform *platform, return FALSE; } - if (ioctl (fd, TUNSETPERSIST, (int) !!props->persist)) - return FALSE; + if (props->persist) { + if (ioctl (fd, TUNSETPERSIST, 1)) + return FALSE; + } do_request_link (platform, 0, name); obj = nmp_cache_lookup_link_full (nm_platform_get_cache (platform), 0, name, FALSE, NM_LINK_TYPE_TUN, NULL, NULL); - if (out_link) - *out_link = obj ? &obj->link : NULL; - return !!obj; + if (!obj) + return FALSE; + + NM_SET_OUT (out_link, &obj->link); + NM_SET_OUT (out_fd, nm_steal_fd (&fd)); + return TRUE; } static gboolean diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index e264324aa0..976039def4 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -2046,6 +2046,11 @@ nm_platform_link_vxlan_add (NMPlatform *self, * @vnet_hdr: whether to set the IFF_VNET_HDR flag * @multi_queue: whether to set the IFF_MULTI_QUEUE flag * @out_link: on success, the link object + * @out_fd: (allow-none): if give, return the file descriptor for the + * created device. Note that when creating a non-persistent device, + * this argument is mandatory, otherwise it makes no sense + * to create such an interface. + * The caller is responsible for closing this file descriptor. * * Create a TUN or TAP interface. */ @@ -2053,7 +2058,8 @@ NMPlatformError nm_platform_link_tun_add (NMPlatform *self, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link) + const NMPlatformLink **out_link, + int *out_fd) { char b[255]; NMPlatformError plerr; @@ -2062,6 +2068,13 @@ nm_platform_link_tun_add (NMPlatform *self, g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (NM_IN_SET (props->type, IFF_TUN, IFF_TAP), NM_PLATFORM_ERROR_BUG); + + /* creating a non-persistant device requires that the caller handles + * the file descriptor. */ + g_return_val_if_fail (props->persist || out_fd, NM_PLATFORM_ERROR_BUG); + + NM_SET_OUT (out_fd, -1); plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_TUN, out_link); if (plerr != NM_PLATFORM_ERROR_SUCCESS) @@ -2069,7 +2082,7 @@ nm_platform_link_tun_add (NMPlatform *self, _LOGD ("link: adding tun '%s' %s", name, nm_platform_lnk_tun_to_string (props, b, sizeof (b))); - if (!klass->link_tun_add (self, name, props, out_link)) + if (!klass->link_tun_add (self, name, props, out_link, out_fd)) return NM_PLATFORM_ERROR_UNSPECIFIED; return NM_PLATFORM_ERROR_SUCCESS; } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 824735083a..e6cef63bae 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -853,7 +853,8 @@ typedef struct { gboolean (*link_tun_add) (NMPlatform *platform, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link); + const NMPlatformLink **out_link, + int *out_fd); gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, const NMPlatformLink **out_link); gboolean (*infiniband_partition_delete) (NMPlatform *, int parent, int p_key); @@ -1286,7 +1287,8 @@ NMPlatformError nm_platform_link_sit_add (NMPlatform *self, NMPlatformError nm_platform_link_tun_add (NMPlatform *self, const char *name, const NMPlatformLnkTun *props, - const NMPlatformLink **out_link); + const NMPlatformLink **out_link, + int *out_fd); const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index f54c0dd4c1..8724fedc86 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1472,7 +1472,8 @@ const NMPlatformLink * nmtstp_link_tun_add (NMPlatform *platform, gboolean external_command, const char *name, - const NMPlatformLnkTun *lnk) + const NMPlatformLnkTun *lnk, + int *out_fd) { const NMPlatformLink *pllink = NULL; NMPlatformError plerr; @@ -1481,6 +1482,7 @@ nmtstp_link_tun_add (NMPlatform *platform, g_assert (nm_utils_is_valid_iface_name (name, NULL)); g_assert (lnk); g_assert (NM_IN_SET (lnk->type, IFF_TUN, IFF_TAP)); + g_assert (!out_fd || *out_fd == -1); if (!lnk->persist) { /* ip tuntap does not support non-persistent devices. @@ -1522,7 +1524,8 @@ nmtstp_link_tun_add (NMPlatform *platform, else g_error ("failure to add tun/tap device via ip-route"); } else { - plerr = nm_platform_link_tun_add (platform, name, lnk, &pllink); + g_assert (lnk->persist || out_fd); + plerr = nm_platform_link_tun_add (platform, name, lnk, &pllink, out_fd); g_assert_cmpint (plerr, ==, NM_PLATFORM_ERROR_SUCCESS); } diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index e7e8b127b5..bd02b0d7d3 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -313,7 +313,8 @@ const NMPlatformLink *nmtstp_link_sit_add (NMPlatform *platform, const NMPlatformLink *nmtstp_link_tun_add (NMPlatform *platform, gboolean external_command, const char *name, - const NMPlatformLnkTun *lnk); + const NMPlatformLnkTun *lnk, + int *out_fd); const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform, gboolean external_command, const char *name, diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index a44936e5dc..dcd600ee64 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -699,6 +699,7 @@ test_software_detect (gconstpointer user_data) guint i_step; const gboolean ext = test_data->external_command; NMPlatformLnkTun lnk_tun; + nm_auto_close int tun_fd = -1; nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); ifindex_parent = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; @@ -910,9 +911,9 @@ test_software_detect (gconstpointer user_data) .vnet_hdr = nmtst_get_rand_bool (), .multi_queue = nmtst_get_rand_bool (), - /* arguably, adding non-persistant devices from within NetworkManager makes - * no sense. */ - .persist = TRUE, + /* if we add the device via iproute2 (external), we can only + * create persistent devices. */ + .persist = (ext == 1) ? TRUE : nmtst_get_rand_bool (), }; break; default: @@ -920,7 +921,10 @@ test_software_detect (gconstpointer user_data) break; } - g_assert (nmtstp_link_tun_add (NULL, ext, DEVICE_NAME, &lnk_tun)); + g_assert (nmtstp_link_tun_add (NULL, ext, DEVICE_NAME, &lnk_tun, + (!lnk_tun.persist || nmtst_get_rand_bool ()) + ? &tun_fd + : NULL)); break; } default: |