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 | char buf[] = "hello" ; |
33 | int csk, ret, len; |
34 | |
35 | if (argc < 5) { |
36 | printf("%s client -4|6 IP PORT [IP PORT]\n" , argv[0]); |
37 | return -1; |
38 | } |
39 | |
40 | bzero((void *)&ss, sizeof(ss)); |
41 | ss.ss_family = !strcmp(argv[2], "-4" ) ? AF_INET : AF_INET6; |
42 | csk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP); |
43 | if (csk < 0) { |
44 | printf("failed to create socket\n" ); |
45 | return -1; |
46 | } |
47 | |
48 | if (argc >= 7) { |
49 | set_addr(ss: &ss, ip: argv[5], port: argv[6], len: &len); |
50 | ret = bind(csk, (struct sockaddr *)&ss, len); |
51 | if (ret < 0) { |
52 | printf("failed to bind to address\n" ); |
53 | return -1; |
54 | } |
55 | } |
56 | |
57 | set_addr(ss: &ss, ip: argv[3], port: argv[4], len: &len); |
58 | ret = connect(csk, (struct sockaddr *)&ss, len); |
59 | if (ret < 0) { |
60 | printf("failed to connect to peer\n" ); |
61 | return -1; |
62 | } |
63 | |
64 | ret = send(csk, buf, strlen(buf) + 1, 0); |
65 | if (ret < 0) { |
66 | printf("failed to send msg %d\n" , ret); |
67 | return -1; |
68 | } |
69 | close(csk); |
70 | |
71 | return 0; |
72 | } |
73 | |
74 | int main(int argc, char *argv[]) |
75 | { |
76 | struct sockaddr_storage ss; |
77 | int lsk, csk, ret, len; |
78 | char buf[20]; |
79 | |
80 | if (argc < 2 || (strcmp(argv[1], "server" ) && strcmp(argv[1], "client" ))) { |
81 | printf("%s server|client ...\n" , argv[0]); |
82 | return -1; |
83 | } |
84 | |
85 | if (!strcmp(argv[1], "client" )) |
86 | return do_client(argc, argv); |
87 | |
88 | if (argc < 5) { |
89 | printf("%s server -4|6 IP PORT [IFACE]\n" , argv[0]); |
90 | return -1; |
91 | } |
92 | |
93 | ss.ss_family = !strcmp(argv[2], "-4" ) ? AF_INET : AF_INET6; |
94 | lsk = socket(ss.ss_family, SOCK_STREAM, IPPROTO_SCTP); |
95 | if (lsk < 0) { |
96 | printf("failed to create lsk\n" ); |
97 | return -1; |
98 | } |
99 | |
100 | if (argc >= 6) { |
101 | ret = setsockopt(lsk, SOL_SOCKET, SO_BINDTODEVICE, |
102 | argv[5], strlen(argv[5]) + 1); |
103 | if (ret < 0) { |
104 | printf("failed to bind to device\n" ); |
105 | return -1; |
106 | } |
107 | } |
108 | |
109 | set_addr(ss: &ss, ip: argv[3], port: argv[4], len: &len); |
110 | ret = bind(lsk, (struct sockaddr *)&ss, len); |
111 | if (ret < 0) { |
112 | printf("failed to bind to address\n" ); |
113 | return -1; |
114 | } |
115 | |
116 | ret = listen(lsk, 5); |
117 | if (ret < 0) { |
118 | printf("failed to listen on port\n" ); |
119 | return -1; |
120 | } |
121 | |
122 | csk = accept(lsk, (struct sockaddr *)NULL, (socklen_t *)NULL); |
123 | if (csk < 0) { |
124 | printf("failed to accept new client\n" ); |
125 | return -1; |
126 | } |
127 | |
128 | ret = recv(csk, buf, sizeof(buf), 0); |
129 | if (ret <= 0) { |
130 | printf("failed to recv msg %d\n" , ret); |
131 | return -1; |
132 | } |
133 | close(csk); |
134 | close(lsk); |
135 | |
136 | return 0; |
137 | } |
138 | |