Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2025 Google LLC */
3
4#include <linux/sockios.h>
5#include <sys/ioctl.h>
6#include <sys/socket.h>
7#include <sys/types.h>
8
9#include "kselftest_harness.h"
10
11#define NR_CHUNKS 100
12#define MSG_LEN 256
13
14FIXTURE(scm_inq)
15{
16 int fd[2];
17};
18
19FIXTURE_VARIANT(scm_inq)
20{
21 int type;
22};
23
24FIXTURE_VARIANT_ADD(scm_inq, stream)
25{
26 .type = SOCK_STREAM,
27};
28
29FIXTURE_VARIANT_ADD(scm_inq, dgram)
30{
31 .type = SOCK_DGRAM,
32};
33
34FIXTURE_VARIANT_ADD(scm_inq, seqpacket)
35{
36 .type = SOCK_SEQPACKET,
37};
38
39FIXTURE_SETUP(scm_inq)
40{
41 int err;
42
43 err = socketpair(AF_UNIX, variant->type | SOCK_NONBLOCK, 0, self->fd);
44 ASSERT_EQ(0, err);
45}
46
47FIXTURE_TEARDOWN(scm_inq)
48{
49 close(self->fd[0]);
50 close(self->fd[1]);
51}
52
53static void send_chunks(struct __test_metadata *_metadata,
54 FIXTURE_DATA(scm_inq) *self)
55{
56 char buf[MSG_LEN] = {};
57 int i, ret;
58
59 for (i = 0; i < NR_CHUNKS; i++) {
60 ret = send(self->fd[0], buf, sizeof(buf), 0);
61 ASSERT_EQ(sizeof(buf), ret);
62 }
63}
64
65static void recv_chunks(struct __test_metadata *_metadata,
66 FIXTURE_DATA(scm_inq) *self)
67{
68 char cmsg_buf[CMSG_SPACE(sizeof(int))];
69 struct msghdr msg = {};
70 struct iovec iov = {};
71 struct cmsghdr *cmsg;
72 char buf[MSG_LEN];
73 int i, ret;
74 int inq;
75
76 msg.msg_iov = &iov;
77 msg.msg_iovlen = 1;
78 msg.msg_control = cmsg_buf;
79 msg.msg_controllen = sizeof(cmsg_buf);
80
81 iov.iov_base = buf;
82 iov.iov_len = sizeof(buf);
83
84 for (i = 0; i < NR_CHUNKS; i++) {
85 memset(buf, 0, sizeof(buf));
86 memset(cmsg_buf, 0, sizeof(cmsg_buf));
87
88 ret = recvmsg(self->fd[1], &msg, 0);
89 ASSERT_EQ(MSG_LEN, ret);
90
91 cmsg = CMSG_FIRSTHDR(&msg);
92 ASSERT_NE(NULL, cmsg);
93 ASSERT_EQ(CMSG_LEN(sizeof(int)), cmsg->cmsg_len);
94 ASSERT_EQ(SOL_SOCKET, cmsg->cmsg_level);
95 ASSERT_EQ(SCM_INQ, cmsg->cmsg_type);
96
97 ret = ioctl(self->fd[1], SIOCINQ, &inq);
98 ASSERT_EQ(0, ret);
99 ASSERT_EQ(*(int *)CMSG_DATA(cmsg), inq);
100 }
101}
102
103TEST_F(scm_inq, basic)
104{
105 int err, inq;
106
107 err = setsockopt(self->fd[1], SOL_SOCKET, SO_INQ, &(int){1}, sizeof(int));
108 if (variant->type != SOCK_STREAM) {
109 ASSERT_EQ(-ENOPROTOOPT, -errno);
110 return;
111 }
112
113 ASSERT_EQ(0, err);
114
115 err = ioctl(self->fd[1], SIOCINQ, &inq);
116 ASSERT_EQ(0, err);
117 ASSERT_EQ(0, inq);
118
119 send_chunks(_metadata, self);
120 recv_chunks(_metadata, self);
121}
122
123TEST_HARNESS_MAIN