1 /*
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 #ifdef _WIN32
36 #define _CRT_SECURE_NO_WARNINGS
37 #endif
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdarg.h>
42 #ifndef _WIN32
43 #include <unistd.h>
44 #endif
45 #include <sys/types.h>
46 #ifndef _WIN32
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #else
51 #include <io.h>
52 #endif
53 #include <usrsctp.h>
54 #include "programs_helper.h"
55
56 int done = 0;
57
58 #ifdef _WIN32
59 typedef char* caddr_t;
60 #endif
61
62
63
64 static int
receive_cb(struct socket * sock,union sctp_sockstore addr,void * data,size_t datalen,struct sctp_rcvinfo rcv,int flags,void * ulp_info)65 receive_cb(struct socket *sock, union sctp_sockstore addr, void *data,
66 size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info)
67 {
68 if (data == NULL) {
69 done = 1;
70 usrsctp_close(sock);
71 } else {
72 if (flags & MSG_NOTIFICATION) {
73 handle_notification((union sctp_notification *)data, datalen);
74 } else {
75 #ifdef _WIN32
76 _write(_fileno(stdout), data, (unsigned int)datalen);
77 #else
78 if (write(fileno(stdout), data, datalen) < 0) {
79 perror("write");
80 }
81 #endif
82 }
83 free(data);
84 }
85 return (1);
86 }
87
88 int
main(int argc,char * argv[])89 main(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 struct sctp_event event;
98 uint16_t event_types[] = {SCTP_ASSOC_CHANGE,
99 SCTP_PEER_ADDR_CHANGE,
100 SCTP_SEND_FAILED_EVENT};
101 char buffer[80];
102 unsigned int i;
103 int n;
104
105 if (argc < 3) {
106 printf("%s", "Usage: client remote_addr remote_port local_port local_encaps_port remote_encaps_port\n");
107 return (-1);
108 }
109 if (argc > 4) {
110 usrsctp_init(atoi(argv[4]), NULL, debug_printf_stack);
111 } else {
112 usrsctp_init(9899, NULL, debug_printf_stack);
113 }
114 #ifdef SCTP_DEBUG
115 usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE);
116 #endif
117 usrsctp_sysctl_set_sctp_blackhole(2);
118 usrsctp_sysctl_set_sctp_no_csum_on_loopback(0);
119
120 if ((sock = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) == NULL) {
121 perror("usrsctp_socket");
122 }
123 memset(&event, 0, sizeof(event));
124 event.se_assoc_id = SCTP_ALL_ASSOC;
125 event.se_on = 1;
126 for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) {
127 event.se_type = event_types[i];
128 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) {
129 perror("setsockopt SCTP_EVENT");
130 }
131 }
132 if (argc > 3) {
133 memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
134 #ifdef HAVE_SIN6_LEN
135 addr6.sin6_len = sizeof(struct sockaddr_in6);
136 #endif
137 addr6.sin6_family = AF_INET6;
138 addr6.sin6_port = htons(atoi(argv[3]));
139 addr6.sin6_addr = in6addr_any;
140 if (usrsctp_bind(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
141 perror("bind");
142 }
143 }
144 if (argc > 5) {
145 memset(&encaps, 0, sizeof(struct sctp_udpencaps));
146 encaps.sue_address.ss_family = AF_INET6;
147 encaps.sue_port = htons(atoi(argv[5]));
148 if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) {
149 perror("setsockopt");
150 }
151 }
152 memset((void *)&addr4, 0, sizeof(struct sockaddr_in));
153 memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
154 #ifdef HAVE_SIN_LEN
155 addr4.sin_len = sizeof(struct sockaddr_in);
156 #endif
157 #ifdef HAVE_SIN6_LEN
158 addr6.sin6_len = sizeof(struct sockaddr_in6);
159 #endif
160 addr4.sin_family = AF_INET;
161 addr6.sin6_family = AF_INET6;
162 addr4.sin_port = htons(atoi(argv[2]));
163 addr6.sin6_port = htons(atoi(argv[2]));
164 if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) {
165 if (usrsctp_connect(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) {
166 perror("usrsctp_connect");
167 }
168 } else if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) {
169 if (usrsctp_connect(sock, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) < 0) {
170 perror("usrsctp_connect");
171 }
172 } else {
173 printf("Illegal destination address.\n");
174 }
175 if ((n = usrsctp_getladdrs(sock, 0, &addrs)) < 0) {
176 perror("usrsctp_getladdrs");
177 } else {
178 addr = addrs;
179 printf("Local addresses: ");
180 for (i = 0; i < (unsigned int)n; i++) {
181 if (i > 0) {
182 printf("%s", ", ");
183 }
184 switch (addr->sa_family) {
185 case AF_INET:
186 {
187 struct sockaddr_in *sin;
188 char buf[INET_ADDRSTRLEN];
189 const char *name;
190
191 sin = (struct sockaddr_in *)addr;
192 name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
193 printf("%s", name);
194 #ifndef HAVE_SA_LEN
195 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
196 #endif
197 break;
198 }
199 case AF_INET6:
200 {
201 struct sockaddr_in6 *sin6;
202 char buf[INET6_ADDRSTRLEN];
203 const char *name;
204
205 sin6 = (struct sockaddr_in6 *)addr;
206 name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
207 printf("%s", name);
208 #ifndef HAVE_SA_LEN
209 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
210 #endif
211 break;
212 }
213 default:
214 break;
215 }
216 #ifdef HAVE_SA_LEN
217 addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
218 #endif
219 }
220 printf(".\n");
221 usrsctp_freeladdrs(addrs);
222 }
223 if ((n = usrsctp_getpaddrs(sock, 0, &addrs)) < 0) {
224 perror("usrsctp_getpaddrs");
225 } else {
226 addr = addrs;
227 printf("Peer addresses: ");
228 for (i = 0; i < (unsigned int)n; i++) {
229 if (i > 0) {
230 printf("%s", ", ");
231 }
232 switch (addr->sa_family) {
233 case AF_INET:
234 {
235 struct sockaddr_in *sin;
236 char buf[INET_ADDRSTRLEN];
237 const char *name;
238
239 sin = (struct sockaddr_in *)addr;
240 name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN);
241 printf("%s", name);
242 #ifndef HAVE_SA_LEN
243 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
244 #endif
245 break;
246 }
247 case AF_INET6:
248 {
249 struct sockaddr_in6 *sin6;
250 char buf[INET6_ADDRSTRLEN];
251 const char *name;
252
253 sin6 = (struct sockaddr_in6 *)addr;
254 name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
255 printf("%s", name);
256 #ifndef HAVE_SA_LEN
257 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
258 #endif
259 break;
260 }
261 default:
262 break;
263 }
264 #ifdef HAVE_SA_LEN
265 addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len);
266 #endif
267 }
268 printf(".\n");
269 usrsctp_freepaddrs(addrs);
270 }
271 while ((fgets(buffer, sizeof(buffer), stdin) != NULL) && !done) {
272 usrsctp_sendv(sock, buffer, strlen(buffer), NULL, 0, NULL, 0, SCTP_SENDV_NOINFO, 0);
273 }
274 if (!done) {
275 if (usrsctp_shutdown(sock, SHUT_WR) < 0) {
276 perror("usrsctp_shutdown");
277 }
278 }
279 while (!done) {
280 #ifdef _WIN32
281 Sleep(1 * 1000);
282 #else
283 sleep(1);
284 #endif
285 }
286 usrsctp_get_stat(&stat);
287 printf("Number of packets (sent/received): (%u/%u).\n",
288 stat.sctps_outpackets, stat.sctps_inpackets);
289 while (usrsctp_finish() != 0) {
290 #ifdef _WIN32
291 Sleep(1 * 1000);
292 #else
293 sleep(1);
294 #endif
295 }
296 return(0);
297 }
298