Merge tag '6.6-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd
[platform/kernel/linux-starfive.git] / tools / testing / selftests / netfilter / sctp_collision.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <arpa/inet.h>
8
9 int main(int argc, char *argv[])
10 {
11         struct sockaddr_in saddr = {}, daddr = {};
12         int sd, ret, len = sizeof(daddr);
13         struct timeval tv = {25, 0};
14         char buf[] = "hello";
15
16         if (argc != 6 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) {
17                 printf("%s <server|client> <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>\n",
18                        argv[0]);
19                 return -1;
20         }
21
22         sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
23         if (sd < 0) {
24                 printf("Failed to create sd\n");
25                 return -1;
26         }
27
28         saddr.sin_family = AF_INET;
29         saddr.sin_addr.s_addr = inet_addr(argv[2]);
30         saddr.sin_port = htons(atoi(argv[3]));
31
32         ret = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr));
33         if (ret < 0) {
34                 printf("Failed to bind to address\n");
35                 goto out;
36         }
37
38         ret = listen(sd, 5);
39         if (ret < 0) {
40                 printf("Failed to listen on port\n");
41                 goto out;
42         }
43
44         daddr.sin_family = AF_INET;
45         daddr.sin_addr.s_addr = inet_addr(argv[4]);
46         daddr.sin_port = htons(atoi(argv[5]));
47
48         /* make test shorter than 25s */
49         ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
50         if (ret < 0) {
51                 printf("Failed to setsockopt SO_RCVTIMEO\n");
52                 goto out;
53         }
54
55         if (!strcmp(argv[1], "server")) {
56                 sleep(1); /* wait a bit for client's INIT */
57                 ret = connect(sd, (struct sockaddr *)&daddr, len);
58                 if (ret < 0) {
59                         printf("Failed to connect to peer\n");
60                         goto out;
61                 }
62                 ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len);
63                 if (ret < 0) {
64                         printf("Failed to recv msg %d\n", ret);
65                         goto out;
66                 }
67                 ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len);
68                 if (ret < 0) {
69                         printf("Failed to send msg %d\n", ret);
70                         goto out;
71                 }
72                 printf("Server: sent! %d\n", ret);
73         }
74
75         if (!strcmp(argv[1], "client")) {
76                 usleep(300000); /* wait a bit for server's listening */
77                 ret = connect(sd, (struct sockaddr *)&daddr, len);
78                 if (ret < 0) {
79                         printf("Failed to connect to peer\n");
80                         goto out;
81                 }
82                 sleep(1); /* wait a bit for server's delayed INIT_ACK to reproduce the issue */
83                 ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len);
84                 if (ret < 0) {
85                         printf("Failed to send msg %d\n", ret);
86                         goto out;
87                 }
88                 ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len);
89                 if (ret < 0) {
90                         printf("Failed to recv msg %d\n", ret);
91                         goto out;
92                 }
93                 printf("Client: rcvd! %d\n", ret);
94         }
95         ret = 0;
96 out:
97         close(sd);
98         return ret;
99 }