From: Masatake YAMATO Date: Wed, 18 Sep 2024 19:04:40 +0000 (+0900) Subject: tests: (test_mkfds::foreign-sockets) new factory X-Git-Tag: v2.42-start~184^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=02d9903ed68919bf2a511d7ed795ddbf1390a41f;p=thirdparty%2Futil-linux.git tests: (test_mkfds::foreign-sockets) new factory The way to make a socket in another net namespace is suggested by Dmitry Safonov. Signed-off-by: Masatake YAMATO --- diff --git a/tests/helpers/test_mkfds.c b/tests/helpers/test_mkfds.c index 0f20435df..309fa6e29 100644 --- a/tests/helpers/test_mkfds.c +++ b/tests/helpers/test_mkfds.c @@ -3091,6 +3091,68 @@ static void *make_sockdiag(const struct factory *factory, struct fdesc fdescs[], return NULL; } +static void *make_foreign_sockets(const struct factory *factory _U_, struct fdesc fdescs[], + int argc _U_, char ** argv _U_) +{ + int foreign_sd[2]; /* These two */ + int original_ns; + int foreign_ns; + struct stat foreign_ns_sb; + + original_ns = open("/proc/self/ns/net", O_RDONLY); + if (original_ns < 0) + err(EXIT_FAILURE, "failed in open(/proc/self/ns/net) before unshare"); + + if (unshare(CLONE_NEWNET) < 0) + err((errno == EPERM? EXIT_EPERM: EXIT_FAILURE), + "failed in unshare()"); + + foreign_ns = open("/proc/self/ns/net", O_RDONLY); + if (foreign_ns < 0) + err(EXIT_FAILURE, "failed in open(/proc/self/ns/net) after unshare"); + if (fstat(foreign_ns, &foreign_ns_sb) < 0) + err(EXIT_FAILURE, "failed in fstat(NETNS)"); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, foreign_sd) < 0) + err(EXIT_FAILURE, "failed in socketpair(SOCK_STREAM)"); + + if (setns(original_ns, CLONE_NEWNET) < 0) + err(EXIT_FAILURE, "failed in setns()"); + + close(foreign_ns); /* Make the namespace unreadable. */ + close(original_ns); + + for (int i = 0; i < 2; i++) { + if (foreign_sd[i] != fdescs[i].fd) { + if (dup2(foreign_sd[i], fdescs[i].fd) < 0) + err(EXIT_FAILURE, "failed to dup %d -> %d", + foreign_sd[i], fdescs[i].fd); + close(foreign_sd[i]); + } + fdescs[i] = (struct fdesc){ + .fd = fdescs[i].fd, + .close = close_fdesc, + .data = NULL + }; + } + + return xmemdup(&foreign_ns_sb.st_ino, sizeof(foreign_ns_sb.st_ino)); +} + +static void report_foreign_sockets(const struct factory *factory _U_, + int nth, void *data, FILE *fp) +{ + if (nth == 0) { + long *netns_id = (long *)data; + fprintf(fp, "%ld", *netns_id); + } +} + +static void free_foreign_sockets(const struct factory * factory _U_, void *data) +{ + free (data); +} + #define PARAM_END { .name = NULL, } static const struct factory factories[] = { { @@ -3982,6 +4044,20 @@ static const struct factory factories[] = { PARAM_END } }, + { + .name = "foreign-sockets", + .desc = "import sockets made in a foreign network namespaec", + .priv = true, + .N = 2, + .EX_N = 0, + .EX_O = 1, + .make = make_foreign_sockets, + .report = report_foreign_sockets, + .free = free_foreign_sockets, + .params = (struct parameter []) { + PARAM_END + } + }, }; static int count_parameters(const struct factory *factory)