1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright(c) 2016 Fujitsu Ltd.
4f08c3bdfSopenharmony_ci * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*
8f08c3bdfSopenharmony_ci * Test Name: recvmsg03
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * This test needs that rds socket is supported by system.
11f08c3bdfSopenharmony_ci * If the size of address for receiving data is set larger than
12f08c3bdfSopenharmony_ci * actaul size, recvmsg() will set msg_namelen incorrectly.
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * Description:
15f08c3bdfSopenharmony_ci * This is a regression test and has been fixed by kernel commit:
16f08c3bdfSopenharmony_ci * 06b6a1cf6e776426766298d055bb3991957d90a7 (rds: set correct msg_namelen)
17f08c3bdfSopenharmony_ci */
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci#include <errno.h>
20f08c3bdfSopenharmony_ci#include <string.h>
21f08c3bdfSopenharmony_ci#include <sys/types.h>
22f08c3bdfSopenharmony_ci#include <sys/socket.h>
23f08c3bdfSopenharmony_ci#include "tst_safe_net.h"
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci#include "tst_test.h"
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#ifndef AF_RDS
28f08c3bdfSopenharmony_ci# define AF_RDS 21
29f08c3bdfSopenharmony_ci#endif
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_cistatic void setup(void)
32f08c3bdfSopenharmony_ci{
33f08c3bdfSopenharmony_ci	int res;
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci	res = socket(AF_RDS, SOCK_SEQPACKET, 0);
36f08c3bdfSopenharmony_ci	if (res == -1) {
37f08c3bdfSopenharmony_ci		if (errno == EAFNOSUPPORT)
38f08c3bdfSopenharmony_ci			tst_brk(TCONF, "rds was not supported");
39f08c3bdfSopenharmony_ci		else
40f08c3bdfSopenharmony_ci			tst_brk(TBROK | TERRNO, "socket() failed with rds");
41f08c3bdfSopenharmony_ci	}
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci	SAFE_CLOSE(res);
44f08c3bdfSopenharmony_ci}
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistatic void client(void)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	int sock_fd1;
49f08c3bdfSopenharmony_ci	char send_buf[128] = "hello world";
50f08c3bdfSopenharmony_ci	struct sockaddr_in server_addr;
51f08c3bdfSopenharmony_ci	struct sockaddr_in to_addr;
52f08c3bdfSopenharmony_ci	struct msghdr msg;
53f08c3bdfSopenharmony_ci	struct iovec iov;
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	sock_fd1 = SAFE_SOCKET(AF_RDS, SOCK_SEQPACKET, 0);
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	memset(&server_addr, 0, sizeof(server_addr));
58f08c3bdfSopenharmony_ci	server_addr.sin_family = AF_INET;
59f08c3bdfSopenharmony_ci	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
60f08c3bdfSopenharmony_ci	server_addr.sin_port = htons(4001);
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	SAFE_BIND(sock_fd1, (struct sockaddr *) &server_addr, sizeof(server_addr));
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci	memset(&to_addr, 0, sizeof(to_addr));
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	to_addr.sin_family = AF_INET;
67f08c3bdfSopenharmony_ci	to_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
68f08c3bdfSopenharmony_ci	to_addr.sin_port = htons(4000);
69f08c3bdfSopenharmony_ci	msg.msg_name = &to_addr;
70f08c3bdfSopenharmony_ci	msg.msg_namelen = sizeof(to_addr);
71f08c3bdfSopenharmony_ci	msg.msg_iov = &iov;
72f08c3bdfSopenharmony_ci	msg.msg_iovlen = 1;
73f08c3bdfSopenharmony_ci	msg.msg_iov->iov_base = send_buf;
74f08c3bdfSopenharmony_ci	msg.msg_iov->iov_len = strlen(send_buf) + 1;
75f08c3bdfSopenharmony_ci	msg.msg_control = 0;
76f08c3bdfSopenharmony_ci	msg.msg_controllen = 0;
77f08c3bdfSopenharmony_ci	msg.msg_flags = 0;
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	if (sendmsg(sock_fd1, &msg, 0) == -1) {
80f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO,
81f08c3bdfSopenharmony_ci			"sendmsg() failed to send data to server");
82f08c3bdfSopenharmony_ci	}
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(1);
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	SAFE_CLOSE(sock_fd1);
87f08c3bdfSopenharmony_ci}
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_cistatic void server(void)
90f08c3bdfSopenharmony_ci{
91f08c3bdfSopenharmony_ci	int sock_fd2;
92f08c3bdfSopenharmony_ci	static char recv_buf[128];
93f08c3bdfSopenharmony_ci	struct sockaddr_in server_addr;
94f08c3bdfSopenharmony_ci	struct sockaddr_in from_addr;
95f08c3bdfSopenharmony_ci	struct msghdr msg;
96f08c3bdfSopenharmony_ci	struct iovec iov;
97f08c3bdfSopenharmony_ci
98f08c3bdfSopenharmony_ci	sock_fd2 = SAFE_SOCKET(AF_RDS, SOCK_SEQPACKET, 0);
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ci	memset(&server_addr, 0, sizeof(server_addr));
101f08c3bdfSopenharmony_ci	server_addr.sin_family = AF_INET;
102f08c3bdfSopenharmony_ci	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
103f08c3bdfSopenharmony_ci	server_addr.sin_port = htons(4000);
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_ci	SAFE_BIND(sock_fd2, (struct sockaddr *) &server_addr, sizeof(server_addr));
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	msg.msg_name = &from_addr;
108f08c3bdfSopenharmony_ci	msg.msg_namelen = sizeof(from_addr) + 16;
109f08c3bdfSopenharmony_ci	msg.msg_iov = &iov;
110f08c3bdfSopenharmony_ci	msg.msg_iovlen = 1;
111f08c3bdfSopenharmony_ci	msg.msg_iov->iov_base = recv_buf;
112f08c3bdfSopenharmony_ci	msg.msg_iov->iov_len = 128;
113f08c3bdfSopenharmony_ci	msg.msg_control = 0;
114f08c3bdfSopenharmony_ci	msg.msg_controllen = 0;
115f08c3bdfSopenharmony_ci	msg.msg_flags = 0;
116f08c3bdfSopenharmony_ci
117f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
118f08c3bdfSopenharmony_ci
119f08c3bdfSopenharmony_ci	SAFE_RECVMSG(0, sock_fd2, &msg, 0);
120f08c3bdfSopenharmony_ci	if (msg.msg_namelen != sizeof(from_addr)) {
121f08c3bdfSopenharmony_ci		tst_res(TFAIL, "msg_namelen was set to %u incorrectly, "
122f08c3bdfSopenharmony_ci			"expected %lu", msg.msg_namelen, sizeof(from_addr));
123f08c3bdfSopenharmony_ci	} else {
124f08c3bdfSopenharmony_ci		tst_res(TPASS, "msg_namelen was set to %u correctly",
125f08c3bdfSopenharmony_ci			msg.msg_namelen);
126f08c3bdfSopenharmony_ci	}
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(1);
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ci	SAFE_CLOSE(sock_fd2);
131f08c3bdfSopenharmony_ci}
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_cistatic void verify_recvmsg(void)
134f08c3bdfSopenharmony_ci{
135f08c3bdfSopenharmony_ci	pid_t pid;
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
138f08c3bdfSopenharmony_ci	if (pid == 0) {
139f08c3bdfSopenharmony_ci		TST_CHECKPOINT_WAIT(0);
140f08c3bdfSopenharmony_ci		client();
141f08c3bdfSopenharmony_ci	} else {
142f08c3bdfSopenharmony_ci		server();
143f08c3bdfSopenharmony_ci		tst_reap_children();
144f08c3bdfSopenharmony_ci	}
145f08c3bdfSopenharmony_ci}
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_cistatic struct tst_test test = {
148f08c3bdfSopenharmony_ci	.forks_child = 1,
149f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
150f08c3bdfSopenharmony_ci	.setup = setup,
151f08c3bdfSopenharmony_ci	.test_all = verify_recvmsg,
152f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
153f08c3bdfSopenharmony_ci		{"linux-git", "06b6a1cf6e77"},
154f08c3bdfSopenharmony_ci		{}
155f08c3bdfSopenharmony_ci	}
156f08c3bdfSopenharmony_ci};
157