]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
selftest: af_unix: Add SO_OOBINLINE test cases in msg_oob.c
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 25 Jun 2024 01:36:41 +0000 (18:36 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 27 Jun 2024 10:05:01 +0000 (12:05 +0200)
When SO_OOBINLINE is enabled on a socket, MSG_OOB can be recv()ed
without MSG_OOB flag, and ioctl(SIOCATMARK) will behaves differently.

This patch adds some test cases for SO_OOBINLINE.

Note the new test cases found two bugs in TCP.

  1) After reading OOB data with non-inline mode, we can re-read
     the data by setting SO_OOBINLINE.

  #  RUN           msg_oob.no_peek.inline_oob_ahead_break ...
  # msg_oob.c:146:inline_oob_ahead_break:AF_UNIX :world
  # msg_oob.c:147:inline_oob_ahead_break:TCP     :oworld
  #            OK  msg_oob.no_peek.inline_oob_ahead_break
  ok 14 msg_oob.no_peek.inline_oob_ahead_break

  2) The head OOB data is dropped if SO_OOBINLINE is disabled
     if a new OOB data is queued.

  #  RUN           msg_oob.no_peek.inline_ex_oob_drop ...
  # msg_oob.c:171:inline_ex_oob_drop:AF_UNIX :x
  # msg_oob.c:172:inline_ex_oob_drop:TCP     :y
  # msg_oob.c:146:inline_ex_oob_drop:AF_UNIX :y
  # msg_oob.c:147:inline_ex_oob_drop:TCP     :Resource temporarily unavailable
  #            OK  msg_oob.no_peek.inline_ex_oob_drop
  ok 17 msg_oob.no_peek.inline_ex_oob_drop

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
tools/testing/selftests/net/af_unix/msg_oob.c

index acf4bd0afe1722424872350fb52065d6133791d4..62361b5e98c313f5c863e9ea4c770678470ba909 100644 (file)
@@ -178,6 +178,20 @@ static void __recvpair(struct __test_metadata *_metadata,
        }
 }
 
+static void __setinlinepair(struct __test_metadata *_metadata,
+                           FIXTURE_DATA(msg_oob) *self)
+{
+       int i, oob_inline = 1;
+
+       for (i = 0; i < 2; i++) {
+               int ret;
+
+               ret = setsockopt(self->fd[i * 2 + 1], SOL_SOCKET, SO_OOBINLINE,
+                                &oob_inline, sizeof(oob_inline));
+               ASSERT_EQ(ret, 0);
+       }
+}
+
 #define sendpair(buf, len, flags)                                      \
        __sendpair(_metadata, self, buf, len, flags)
 
@@ -191,6 +205,9 @@ static void __recvpair(struct __test_metadata *_metadata,
                           expected_buf, expected_len, buf_len, flags); \
        } while (0)
 
+#define setinlinepair()                                                        \
+       __setinlinepair(_metadata, self)
+
 #define tcp_incompliant                                                        \
        for (self->tcp_compliant = false;                               \
             self->tcp_compliant == false;                              \
@@ -304,4 +321,78 @@ TEST_F(msg_oob, ex_oob_ahead_break)
        recvpair("d", 1, 1, MSG_OOB);
 }
 
+TEST_F(msg_oob, inline_oob)
+{
+       setinlinepair();
+
+       sendpair("x", 1, MSG_OOB);
+
+       recvpair("", -EINVAL, 1, MSG_OOB);
+       recvpair("x", 1, 1, 0);
+}
+
+TEST_F(msg_oob, inline_oob_break)
+{
+       setinlinepair();
+
+       sendpair("hello", 5, MSG_OOB);
+
+       recvpair("", -EINVAL, 1, MSG_OOB);
+       recvpair("hell", 4, 5, 0);              /* Break at OOB but not at ex-OOB. */
+       recvpair("o", 1, 1, 0);
+}
+
+TEST_F(msg_oob, inline_oob_ahead_break)
+{
+       sendpair("hello", 5, MSG_OOB);
+       sendpair("world", 5, 0);
+
+       recvpair("o", 1, 1, MSG_OOB);
+
+       setinlinepair();
+
+       recvpair("hell", 4, 9, 0);              /* Break at OOB even with enough buffer. */
+
+       tcp_incompliant {
+               recvpair("world", 5, 6, 0);     /* TCP recv()s "oworld", ... "o" ??? */
+       }
+}
+
+TEST_F(msg_oob, inline_ex_oob_break)
+{
+       sendpair("hello", 5, MSG_OOB);
+       sendpair("wor", 3, MSG_OOB);
+       sendpair("ld", 2, 0);
+
+       setinlinepair();
+
+       recvpair("hellowo", 7, 10, 0);          /* Break at OOB but not at ex-OOB. */
+       recvpair("rld", 3, 3, 0);
+}
+
+TEST_F(msg_oob, inline_ex_oob_no_drop)
+{
+       sendpair("x", 1, MSG_OOB);
+
+       setinlinepair();
+
+       sendpair("y", 1, MSG_OOB);              /* TCP does NOT drops "x" at this moment. */
+
+       recvpair("x", 1, 1, 0);
+       recvpair("y", 1, 1, 0);
+}
+
+TEST_F(msg_oob, inline_ex_oob_drop)
+{
+       sendpair("x", 1, MSG_OOB);
+       sendpair("y", 1, MSG_OOB);              /* TCP drops "x" at this moment. */
+
+       setinlinepair();
+
+       tcp_incompliant {
+               recvpair("x", 1, 1, 0);         /* TCP recv()s "y". */
+               recvpair("y", 1, 1, 0);         /* TCP returns -EAGAIN. */
+       }
+}
+
 TEST_HARNESS_MAIN