blob: 8dcad6f37a95242abf44dca39646893f773a97a9 [file] [log] [blame]
James Kuszmaul4cb043c2021-01-17 11:25:51 -08001/*
2 * Copyright (C) 2011-2013 Michael Tuexen
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32 * Usage: client remote_addr remote_port [local_port] [local_encaps_port] [remote_encaps_port]
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <stdarg.h>
39#ifndef _WIN32
40#include <unistd.h>
41#endif
42#include <sys/types.h>
43#ifndef _WIN32
44#include <sys/socket.h>
45#include <netinet/in.h>
46#include <arpa/inet.h>
47#else
48#include <io.h>
49#endif
50#include <usrsctp.h>
51
52int done = 0;
53
54#ifdef _WIN32
55typedef char* caddr_t;
56#endif
57
58static int
59receive_cb(struct socket *sock, union sctp_sockstore addr, void *data,
60 size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info)
61{
62 if (data == NULL) {
63 done = 1;
64 usrsctp_close(sock);
65 } else {
66#ifdef _WIN32
67 _write(_fileno(stdout), data, (unsigned int)datalen);
68#else
69 if (write(fileno(stdout), data, datalen) < 0) {
70 perror("write");
71 }
72#endif
73 free(data);
74 }
75 return (1);
76}
77
78void
79debug_printf(const char *format, ...)
80{
81 va_list ap;
82
83 va_start(ap, format);
84 vprintf(format, ap);
85 va_end(ap);
86}
87
88int
89main(int argc, char *argv[])
90{
91 struct socket *sock;
92 struct sockaddr *addr, *addrs;
93 struct sockaddr_in addr4;
94 struct sockaddr_in6 addr6;
95 struct sctp_udpencaps encaps;
96 struct sctpstat stat;
97 char buffer[80];
98 int i, n;
99
100 if (argc < 3) {
101 printf("%s", "Usage: client remote_addr remote_port local_port local_encaps_port remote_encaps_port\n");
102 return (-1);
103 }
104 if (argc > 4) {
105 usrsctp_init(atoi(argv[4]), NULL, debug_printf);
106 } else {
107 usrsctp_init(9899, NULL, debug_printf);
108 }
109#ifdef SCTP_DEBUG
110 usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
111#endif
112 usrsctp_sysctl_set_sctp_blackhole(2);
113 if ((sock = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) == NULL) {
114 perror("usrsctp_socket");
115 }
116 if (argc > 3) {
117 memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
118#ifdef HAVE_SIN6_LEN
119 addr6.sin6_len = sizeof(struct sockaddr_in6);
120#endif
121 addr6.sin6_family = AF_INET6;
122 addr6.sin6_port = htons(atoi(argv[3]));
123 addr6.sin6_addr = in6addr_any;
124 if (usrsctp_bind(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
125 perror("bind");
126 }
127 }
128 if (argc > 5) {
129 memset(&encaps, 0, sizeof(struct sctp_udpencaps));
130 encaps.sue_address.ss_family = AF_INET6;
131 encaps.sue_port = htons(atoi(argv[5]));
132 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
133 perror("setsockopt");
134 }
135 }
136 memset((void *)&addr4, 0, sizeof(struct sockaddr_in));
137 memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
138#ifdef HAVE_SIN_LEN
139 addr4.sin_len = sizeof(struct sockaddr_in);
140#endif
141#ifdef HAVE_SIN6_LEN
142 addr6.sin6_len = sizeof(struct sockaddr_in6);
143#endif
144 addr4.sin_family = AF_INET;
145 addr6.sin6_family = AF_INET6;
146 addr4.sin_port = htons(atoi(argv[2]));
147 addr6.sin6_port = htons(atoi(argv[2]));
148 if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) {
149 if (usrsctp_connect(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
150 perror("usrsctp_connect");
151 }
152 } else if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) {
153 if (usrsctp_connect(sock, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) < 0) {
154 perror("usrsctp_connect");
155 }
156 } else {
157 printf("Illegal destination address.\n");
158 }
159 if ((n = usrsctp_getladdrs(sock, 0, &addrs)) < 0) {
160 perror("usrsctp_getladdrs");
161 } else {
162 addr = addrs;
163 printf("Local addresses: ");
164 for (i = 0; i < n; i++) {
165 if (i > 0) {
166 printf("%s", ", ");
167 }
168 switch (addr->sa_family) {
169 case AF_INET:
170 {
171 struct sockaddr_in *sin;
172 char buf[INET_ADDRSTRLEN];
173 const char *name;
174
175 sin = (struct sockaddr_in *)addr;
176 name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
177 printf("%s", name);
178#ifndef HAVE_SA_LEN
179 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
180#endif
181 break;
182 }
183 case AF_INET6:
184 {
185 struct sockaddr_in6 *sin6;
186 char buf[INET6_ADDRSTRLEN];
187 const char *name;
188
189 sin6 = (struct sockaddr_in6 *)addr;
190 name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
191 printf("%s", name);
192#ifndef HAVE_SA_LEN
193 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
194#endif
195 break;
196 }
197 default:
198 break;
199 }
200#ifdef HAVE_SA_LEN
201 addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
202#endif
203 }
204 printf(".\n");
205 usrsctp_freeladdrs(addrs);
206 }
207 if ((n = usrsctp_getpaddrs(sock, 0, &addrs)) < 0) {
208 perror("usrsctp_getpaddrs");
209 } else {
210 addr = addrs;
211 printf("Peer addresses: ");
212 for (i = 0; i < n; i++) {
213 if (i > 0) {
214 printf("%s", ", ");
215 }
216 switch (addr->sa_family) {
217 case AF_INET:
218 {
219 struct sockaddr_in *sin;
220 char buf[INET_ADDRSTRLEN];
221 const char *name;
222
223 sin = (struct sockaddr_in *)addr;
224 name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
225 printf("%s", name);
226#ifndef HAVE_SA_LEN
227 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
228#endif
229 break;
230 }
231 case AF_INET6:
232 {
233 struct sockaddr_in6 *sin6;
234 char buf[INET6_ADDRSTRLEN];
235 const char *name;
236
237 sin6 = (struct sockaddr_in6 *)addr;
238 name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
239 printf("%s", name);
240#ifndef HAVE_SA_LEN
241 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
242#endif
243 break;
244 }
245 default:
246 break;
247 }
248#ifdef HAVE_SA_LEN
249 addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
250#endif
251 }
252 printf(".\n");
253 usrsctp_freepaddrs(addrs);
254 }
255 while ((fgets(buffer, sizeof(buffer), stdin) != NULL) && !done) {
256 usrsctp_sendv(sock, buffer, strlen(buffer), NULL, 0, NULL, 0, SCTP_SENDV_NOINFO, 0);
257 }
258 if (!done) {
259 if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
260 perror("usrsctp_shutdown");
261 }
262 }
263 while (!done) {
264#ifdef _WIN32
265 Sleep(1*1000);
266#else
267 sleep(1);
268#endif
269 }
270 usrsctp_get_stat(&stat);
271 printf("Number of packets (sent/received): (%u/%u).\n",
272 stat.sctps_outpackets, stat.sctps_inpackets);
273 while (usrsctp_finish() != 0) {
274#ifdef _WIN32
275 Sleep(1000);
276#else
277 sleep(1);
278#endif
279 }
280 return(0);
281}