// SPDX-License-Identifier: GPL-2.0 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct sockaddr_in saddr = {}, daddr = {}; int sd, ret, len = sizeof(daddr); struct timeval tv = {25, 0}; char buf[] = "hello"; if (argc != 6 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { printf("%s <server|client> <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>\n", argv[0]); return -1; } sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sd < 0) { printf("Failed to create sd\n"); return -1; } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = inet_addr(argv[2]); saddr.sin_port = htons(atoi(argv[3])); ret = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { printf("Failed to bind to address\n"); goto out; } ret = listen(sd, 5); if (ret < 0) { printf("Failed to listen on port\n"); goto out; } daddr.sin_family = AF_INET; daddr.sin_addr.s_addr = inet_addr(argv[4]); daddr.sin_port = htons(atoi(argv[5])); /* make test shorter than 25s */ ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); if (ret < 0) { printf("Failed to setsockopt SO_RCVTIMEO\n"); goto out; } if (!strcmp(argv[1], "server")) { sleep(1); /* wait a bit for client's INIT */ ret = connect(sd, (struct sockaddr *)&daddr, len); if (ret < 0) { printf("Failed to connect to peer\n"); goto out; } ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); if (ret < 0) { printf("Failed to recv msg %d\n", ret); goto out; } ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); if (ret < 0) { printf("Failed to send msg %d\n", ret); goto out; } printf("Server: sent! %d\n", ret); } if (!strcmp(argv[1], "client")) { usleep(300000); /* wait a bit for server's listening */ ret = connect(sd, (struct sockaddr *)&daddr, len); if (ret < 0) { printf("Failed to connect to peer\n"); goto out; } sleep(1); /* wait a bit for server's delayed INIT_ACK to reproduce the issue */ ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); if (ret < 0) { printf("Failed to send msg %d\n", ret); goto out; } ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); if (ret < 0) { printf("Failed to recv msg %d\n", ret); goto out; } printf("Client: rcvd! %d\n", ret); } ret = 0; out: close(sd); return ret; }