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 <sys/types.h> 8 #include <netinet/in.h> 9 #include <arpa/inet.h> 10 11 static void set_addr(struct sockaddr_storage *ss, char *ip, char *port, int *len) 12 { 13 if (ss->ss_family == AF_INET) { 14 struct sockaddr_in *a = (struct sockaddr_in *)ss; 15 16 a->sin_addr.s_addr = inet_addr(ip); 17 a->sin_port = htons(atoi(port)); 18 *len = sizeof(*a); 19 } else { 20 struct sockaddr_in6 *a = (struct sockaddr_in6 *)ss; 21 22 a->sin6_family = AF_INET6; 23 inet_pton(AF_INET6, ip, &a->sin6_addr); 24 a->sin6_port = htons(atoi(port)); 25 *len = sizeof(*a); 26 } 27 } 28 29 static int do_client(int argc, char *argv[]) 30 { 31 struct sockaddr_storage ss; 32 int csk, ret, len; 33 34 if (argc < 5) { 35 printf("%s client -4|6 IP PORT [IP PORT]\n", argv[0]); 36 return -1; 37 } 38 39 bzero((void *)&ss, sizeof(ss)); 40 ss.ss_family = !strcmp(argv[2], "-4") ? AF_INET : AF_INET6; 41 csk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP); 42 if (csk < 0) { 43 printf("failed to create socket\n"); 44 return -1; 45 } 46 47 if (argc >= 7) { 48 set_addr(&ss, argv[5], argv[6], &len); 49 ret = bind(csk, (struct sockaddr *)&ss, len); 50 if (ret < 0) { 51 printf("failed to bind to address\n"); 52 return -1; 53 } 54 } 55 56 set_addr(&ss, argv[3], argv[4], &len); 57 ret = connect(csk, (struct sockaddr *)&ss, len); 58 if (ret < 0) 59 return -1; 60 61 recv(csk, NULL, 0, 0); 62 close(csk); 63 64 return 0; 65 } 66 67 int main(int argc, char *argv[]) 68 { 69 struct sockaddr_storage ss; 70 int lsk, csk, ret, len; 71 72 if (argc < 2 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { 73 printf("%s server|client ...\n", argv[0]); 74 return -1; 75 } 76 77 if (!strcmp(argv[1], "client")) 78 return do_client(argc, argv); 79 80 if (argc < 5) { 81 printf("%s server -4|6 IP PORT [IFACE]\n", argv[0]); 82 return -1; 83 } 84 85 ss.ss_family = !strcmp(argv[2], "-4") ? AF_INET : AF_INET6; 86 lsk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP); 87 if (lsk < 0) { 88 printf("failed to create lsk\n"); 89 return -1; 90 } 91 92 if (argc >= 6) { 93 ret = setsockopt(lsk, SOL_SOCKET, SO_BINDTODEVICE, 94 argv[5], strlen(argv[5]) + 1); 95 if (ret < 0) { 96 printf("failed to bind to device\n"); 97 return -1; 98 } 99 } 100 101 set_addr(&ss, argv[3], argv[4], &len); 102 ret = bind(lsk, (struct sockaddr *)&ss, len); 103 if (ret < 0) { 104 printf("failed to bind to address\n"); 105 return -1; 106 } 107 108 ret = listen(lsk, 5); 109 if (ret < 0) { 110 printf("failed to listen on port\n"); 111 return -1; 112 } 113 114 csk = accept(lsk, (struct sockaddr *)NULL, (socklen_t *)NULL); 115 if (csk < 0) { 116 printf("failed to accept new client\n"); 117 return -1; 118 } 119 120 close(csk); 121 close(lsk); 122 123 return 0; 124 } 125