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 
main(int argc,char * argv[])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 }
100