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 | } |
100 | |