aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--doc/platform-requirements/.gitignore1
-rw-r--r--doc/platform-requirements/Makefile4
-rw-r--r--doc/platform-requirements/udp-close-dup.c105
3 files changed, 108 insertions, 2 deletions
diff --git a/doc/platform-requirements/.gitignore b/doc/platform-requirements/.gitignore
index 555031d..3b5a10a 100644
--- a/doc/platform-requirements/.gitignore
+++ b/doc/platform-requirements/.gitignore
@@ -1,2 +1,3 @@
/reuseaddr-priority
/recv-zero
+/udp-close-dup
diff --git a/doc/platform-requirements/Makefile b/doc/platform-requirements/Makefile
index 82aaac2..6a7d374 100644
--- a/doc/platform-requirements/Makefile
+++ b/doc/platform-requirements/Makefile
@@ -3,8 +3,8 @@
# Copyright Red Hat
# Author: David Gibson <david@gibson.dropbear.id.au>
-TARGETS = reuseaddr-priority recv-zero
-SRCS = reuseaddr-priority.c recv-zero.c
+TARGETS = reuseaddr-priority recv-zero udp-close-dup
+SRCS = reuseaddr-priority.c recv-zero.c udp-close-dup.c
CFLAGS = -Wall
all: cppcheck clang-tidy $(TARGETS:%=check-%)
diff --git a/doc/platform-requirements/udp-close-dup.c b/doc/platform-requirements/udp-close-dup.c
new file mode 100644
index 0000000..99060fc
--- /dev/null
+++ b/doc/platform-requirements/udp-close-dup.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/* udp-close-dup.c
+ *
+ * Verify that closing one dup() of a UDP socket won't stop other dups from
+ * receiving packets.
+ *
+ * Copyright Red Hat
+ * Author: David Gibson <david@gibson.dropbear.id.au>
+ */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+
+#define DSTPORT 13257U
+
+/* 127.0.0.1:DSTPORT */
+static const struct sockaddr_in lo_dst = SOCKADDR_INIT(INADDR_LOOPBACK, DSTPORT);
+
+enum dup_method {
+ DUP_DUP,
+ DUP_FCNTL,
+ NUM_METHODS,
+};
+
+static void test_close_dup(enum dup_method method)
+{
+ long token;
+ int s1, s2, send_s;
+ ssize_t rc;
+
+ s1 = sock_reuseaddr();
+ if (bind(s1, (struct sockaddr *)&lo_dst, sizeof(lo_dst)) < 0)
+ die("bind(): %s\n", strerror(errno));
+
+ send_s = sock_reuseaddr();
+ if (connect(send_s, (struct sockaddr *)&lo_dst, sizeof(lo_dst)) < 0)
+ die("connect(): %s\n", strerror(errno));
+
+ /* Receive before duplicating */
+ token = random();
+ send_token(send_s, token);
+ recv_token(s1, token);
+
+ switch (method) {
+ case DUP_DUP:
+ /* NOLINTNEXTLINE(android-cloexec-dup) */
+ s2 = dup(s1);
+ if (s2 < 0)
+ die("dup(): %s\n", strerror(errno));
+ break;
+ case DUP_FCNTL:
+ s2 = fcntl(s1, F_DUPFD_CLOEXEC, 0);
+ if (s2 < 0)
+ die("F_DUPFD_CLOEXEC: %s\n", strerror(errno));
+ break;
+ default:
+ die("Bad method\n");
+ }
+
+ /* Receive via original handle */
+ token = random();
+ send_token(send_s, token);
+ recv_token(s1, token);
+
+ /* Receive via duplicated handle */
+ token = random();
+ send_token(send_s, token);
+ recv_token(s2, token);
+
+ /* Close duplicate */
+ rc = close(s2);
+ if (rc < 0)
+ die("close() dup: %s\n", strerror(errno));
+
+ /* Receive after closing duplicate */
+ token = random();
+ send_token(send_s, token);
+ recv_token(s1, token);
+}
+
+int main(int argc, char *argv[])
+{
+ enum dup_method method;
+
+ (void)argc;
+ (void)argv;
+
+ for (method = 0; method < NUM_METHODS; method++)
+ test_close_dup(method);
+
+ printf("Closing dup()ed UDP sockets seems to work as expected\n");
+
+ exit(0);
+}