// SPDX-License-Identifier: GPL-2.0 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> static void set_addr(struct sockaddr_storage *ss, char *ip, char *port, int *len) { if (ss->ss_family == AF_INET) { struct sockaddr_in *a = (struct sockaddr_in *)ss; a->sin_addr.s_addr = inet_addr(ip); a->sin_port = htons(atoi(port)); *len = sizeof(*a); } else { struct sockaddr_in6 *a = (struct sockaddr_in6 *)ss; a->sin6_family = AF_INET6; inet_pton(AF_INET6, ip, &a->sin6_addr); a->sin6_port = htons(atoi(port)); *len = sizeof(*a); } } static int do_client(int argc, char *argv[]) { struct sockaddr_storage ss; char buf[] = "hello"; int csk, ret, len; if (argc < 5) { printf("%s client -4|6 IP PORT [IP PORT]\n", argv[0]); return -1; } bzero((void *)&ss, sizeof(ss)); ss.ss_family = !strcmp(argv[2], "-4") ? AF_INET : AF_INET6; csk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP); if (csk < 0) { printf("failed to create socket\n"); return -1; } if (argc >= 7) { set_addr(&ss, argv[5], argv[6], &len); ret = bind(csk, (struct sockaddr *)&ss, len); if (ret < 0) { printf("failed to bind to address\n"); return -1; } } set_addr(&ss, argv[3], argv[4], &len); ret = connect(csk, (struct sockaddr *)&ss, len); if (ret < 0) { printf("failed to connect to peer\n"); return -1; } ret = send(csk, buf, strlen(buf) + 1, 0); if (ret < 0) { printf("failed to send msg %d\n", ret); return -1; } close(csk); return 0; } int main(int argc, char *argv[]) { struct sockaddr_storage ss; int lsk, csk, ret, len; char buf[20]; if (argc < 2 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { printf("%s server|client ...\n", argv[0]); return -1; } if (!strcmp(argv[1], "client")) return do_client(argc, argv); if (argc < 5) { printf("%s server -4|6 IP PORT [IFACE]\n", argv[0]); return -1; } ss.ss_family = !strcmp(argv[2], "-4") ? AF_INET : AF_INET6; lsk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP); if (lsk < 0) { printf("failed to create lsk\n"); return -1; } if (argc >= 6) { ret = setsockopt(lsk, SOL_SOCKET, SO_BINDTODEVICE, argv[5], strlen(argv[5]) + 1); if (ret < 0) { printf("failed to bind to device\n"); return -1; } } set_addr(&ss, argv[3], argv[4], &len); ret = bind(lsk, (struct sockaddr *)&ss, len); if (ret < 0) { printf("failed to bind to address\n"); return -1; } ret = listen(lsk, 5); if (ret < 0) { printf("failed to listen on port\n"); return -1; } csk = accept(lsk, (struct sockaddr *)NULL, (socklen_t *)NULL); if (csk < 0) { printf("failed to accept new client\n"); return -1; } ret = recv(csk, buf, sizeof(buf), 0); if (ret <= 0) { printf("failed to recv msg %d\n", ret); return -1; } close(csk); close(lsk); return 0; }