blob: 5c195d3bfdb72c27b478d31e63abd5586ccce3df [file] [log] [blame]
Austin Schuh8d0a2852019-12-28 22:54:28 -08001/* SCTP kernel Implementation
2 * (C) Copyright IBM Corp. 2003
3 *
4 * The SCTP implementation is free software;
5 * you can redistribute it and/or modify it under the terms of
6 * the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * The SCTP implementation is distributed in the hope that it
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * ************************
13 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU CC; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 * In addition:
22 *
23 * Copyright (c) 2003 Cisco
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions are met:
27 *
28 * a) Redistributions of source code must retain the above copyright notice,
29 * this list of conditions and the following disclaimer.
30 *
31 * b) Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in
33 * the documentation and/or other materials provided with the distribution.
34 *
35 * c) Neither the name of Cisco Systems, Inc. nor the names of its
36 * contributors may be used to endorse or promote products derived
37 * from this software without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
41 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
43 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
45 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
46 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
47 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
48 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
49 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 *
51 * Please send any bug reports or fixes you make to the
52 * email address(es):
53 * lksctp developers <lksctp-developers@lists.sourceforge.net>
54 *
55 * Or submit a bug report through the following website:
56 * http://www.sf.net/projects/lksctp
57 *
58 * Any bugs reported to us we will try to fix... any fixes shared will
59 * be incorporated into the next SCTP release.
60 *
61 * Written or modified by:
62 * Randall Stewart <rrs@cisco.com>
63 * Sridhar Samudrala <sri@us.ibm.com>
64 */
65
66#include <ctype.h>
67
68#include <stdio.h>
69#include <stdlib.h>
70#include <unistd.h>
71#include <sys/types.h>
72#include <sys/ioctl.h>
73#include <sys/stat.h>
74#include <sys/socket.h>
75#include <net/if.h>
76#include <netinet/in.h>
77
78#include <stdarg.h>
79#include <signal.h>
80#include <fcntl.h>
81#include <arpa/inet.h>
82#include <time.h>
83#include <string.h>
84#include <errno.h>
85#include <poll.h>
86#include <sys/uio.h>
87#include <netdb.h>
88
89#include <netinet/sctp.h>
90#ifdef __NetBSD__
91#include <sys/inttypes.h>
92#endif
93
94#define SCTP_CRC32C_POLY 0x1EDC6F41
95#define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF])
96/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
97/* Copyright 2001, D. Otis. Use this program, code or tables */
98/* extracted from it, as desired without restriction. */
99/* */
100/* 32 Bit Reflected CRC table generation for SCTP. */
101/* To accommodate serial byte data being shifted out least */
102/* significant bit first, the table's 32 bit words are reflected */
103/* which flips both byte and bit MS and LS positions. The CRC */
104/* is calculated MS bits first from the perspective of the serial*/
105/* stream. The x^32 term is implied and the x^0 term may also */
106/* be shown as +1. The polynomial code used is 0x1EDC6F41. */
107/* Castagnoli93 */
108/* x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+ */
109/* x^11+x^10+x^9+x^8+x^6+x^0 */
110/* Guy Castagnoli Stefan Braeuer and Martin Herrman */
111/* "Optimization of Cyclic Redundancy-Check Codes */
112/* with 24 and 32 Parity Bits", */
113/* IEEE Transactions on Communications, Vol.41, No.6, June 1993 */
114/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
115
116static unsigned char buffer1[4100];
117static unsigned char buffer2[4100];
118static unsigned char buffer3[4100];
119static unsigned char buffer4[4100];
120static struct sockaddr_in bindto,got,to;
121static socklen_t len;
122
123unsigned long sctp_crc_c[256] = {
124 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
125 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
126 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
127 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
128 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
129 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
130 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
131 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
132 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
133 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
134 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
135 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
136 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
137 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
138 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
139 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
140 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
141 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
142 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
143 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
144 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
145 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
146 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
147 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
148 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
149 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
150 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
151 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
152 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
153 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
154 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
155 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
156 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
157 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
158 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
159 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
160 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
161 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
162 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
163 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
164 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
165 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
166 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
167 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
168 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
169 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
170 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
171 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
172 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
173 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
174 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
175 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
176 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
177 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
178 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
179 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
180 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
181 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
182 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
183 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
184 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
185 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
186 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
187 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
188};
189
190u_int32_t
191update_crc32(u_int32_t crc32,
192 unsigned char *buffer,
193 unsigned int length)
194{
195 int i;
196 for (i = 0; i < length; i++) {
197 SCTP_CRC32C(crc32, buffer[i]);
198 }
199 return (crc32);
200}
201
202u_int32_t
203sctp_csum_finalize(u_int32_t crc32)
204{
205 u_int32_t result;
206#if BYTE_ORDER == BIG_ENDIAN
207 u_int8_t byte0, byte1, byte2, byte3;
208#endif
209 /* Complement the result */
210 result = ~crc32;
211#if BYTE_ORDER == BIG_ENDIAN
212 /*
213 * For BIG-ENDIAN.. aka Motorola byte order the result is in
214 * little-endian form. So we must manually swap the bytes. Then
215 * we can call htonl() which does nothing...
216 */
217 byte0 = result & 0x000000ff;
218 byte1 = (result >> 8) & 0x000000ff;
219 byte2 = (result >> 16) & 0x000000ff;
220 byte3 = (result >> 24) & 0x000000ff;
221 result = ((byte0 << 24) |
222 (byte1 << 16) |
223 (byte2 << 8) |
224 byte3);
225 crc32 = htonl(result);
226#else
227 /*
228 * For INTEL platforms the result comes out in network order.
229 * No htonl is required or the swap above. So we optimize out
230 * both the htonl and the manual swap above.
231 */
232 crc32 = result;
233#endif
234 return (crc32);
235}
236
237static u_int32_t at = 468700;
238
239void
240prepare_buffers(void)
241{
242 /* Prepare buffers */
243 u_int32_t temp,*p;
244 int i;
245
246 p = (u_int32_t *)buffer1;
247 for(i=0;i<(sizeof(buffer1)/4);i++){
248 *p = at;
249 at++;
250 p++;
251 }
252 /* backup over the last int */
253 p--;
254 *p = 0;
255 temp = 0xffffffff;
256 temp = update_crc32(temp,buffer1,(sizeof(buffer1)-4));
257 *p = sctp_csum_finalize(temp);
258
259 p = (u_int32_t *)buffer2;
260 for(i=0;i<(sizeof(buffer2)/4);i++){
261 *p = at;
262 at++;
263 p++;
264 }
265 p--;
266 *p = 0;
267 temp = 0xffffffff;
268 temp = update_crc32(temp,buffer2,(sizeof(buffer2)-4));
269 *p = sctp_csum_finalize(temp);
270
271 p = (u_int32_t *)buffer3;
272 for(i=0;i<(sizeof(buffer3)/4);i++){
273 *p = at;
274 at++;
275 p++;
276 }
277 p--;
278 *p = 0;
279 temp = 0xffffffff;
280 temp = update_crc32(temp,buffer3,(sizeof(buffer3)-4));
281 *p = sctp_csum_finalize(temp);
282
283 p = (u_int32_t *)buffer4;
284 for(i=0;i<(sizeof(buffer4)/4);i++){
285 *p = at;
286 at++;
287 p++;
288 }
289 p--;
290 *p = 0;
291 temp = 0xffffffff;
292 temp = update_crc32(temp,buffer4,(sizeof(buffer4)-4));
293 *p = sctp_csum_finalize(temp);
294}
295
296static int
297my_handle_notification(int fd,char *notify_buf) {
298 union sctp_notification *snp;
299 struct sctp_assoc_change *sac;
300 struct sctp_paddr_change *spc;
301 struct sctp_remote_error *sre;
302 struct sctp_send_failed *ssf;
303 struct sctp_shutdown_event *sse;
304 int asocDown;
305 char *str;
306 char buf[256];
307 struct sockaddr_in *sin;
308 struct sockaddr_in6 *sin6;
309
310 asocDown = 0;
311 snp = (union sctp_notification *)notify_buf;
312 switch(snp->sn_header.sn_type) {
313 case SCTP_ASSOC_CHANGE:
314 sac = &snp->sn_assoc_change;
315 switch(sac->sac_state) {
316
317 case SCTP_COMM_UP:
318 str = "COMMUNICATION UP";
319 break;
320 case SCTP_COMM_LOST:
321 str = "COMMUNICATION LOST";
322 asocDown = 1;
323 break;
324 case SCTP_RESTART:
325 str = "RESTART";
326 break;
327 case SCTP_SHUTDOWN_COMP:
328 str = "SHUTDOWN COMPLETE";
329 asocDown = 1;
330 break;
331 case SCTP_CANT_STR_ASSOC:
332 str = "CANT START ASSOC";
333 printf("EXIT:SCTP_ASSOC_CHANGE: %s, assoc=%xh\n", str,
334 (uint32_t)sac->sac_assoc_id);
335 exit(0);
336 break;
337 default:
338 str = "UNKNOWN";
339 } /* end switch(sac->sac_state) */
340 printf("SCTP_ASSOC_CHANGE: %s, assoc=%xh\n", str,
341 (uint32_t)sac->sac_assoc_id);
342 break;
343 case SCTP_PEER_ADDR_CHANGE:
344 spc = &snp->sn_paddr_change;
345 switch(spc->spc_state) {
346 case SCTP_ADDR_AVAILABLE:
347 str = "ADDRESS AVAILABLE";
348 break;
349 case SCTP_ADDR_UNREACHABLE:
350 str = "ADDRESS UNAVAILABLE";
351 break;
352 case SCTP_ADDR_REMOVED:
353 str = "ADDRESS REMOVED";
354 break;
355 case SCTP_ADDR_ADDED:
356 str = "ADDRESS ADDED";
357 break;
358 case SCTP_ADDR_MADE_PRIM:
359 str = "ADDRESS MADE PRIMARY";
360 break;
361 default:
362 str = "UNKNOWN";
363 } /* end switch */
364 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
365 if (sin6->sin6_family == AF_INET6) {
366 inet_ntop(AF_INET6, (char*)&sin6->sin6_addr, buf, sizeof(buf));
367 } else {
368 sin = (struct sockaddr_in *)&spc->spc_aaddr;
369 inet_ntop(AF_INET, (char*)&sin->sin_addr, buf, sizeof(buf));
370 }
371 printf("SCTP_PEER_ADDR_CHANGE: %s, addr=%s, assoc=%xh\n", str,
372 buf, (uint32_t)spc->spc_assoc_id);
373 break;
374 case SCTP_REMOTE_ERROR:
375 sre = &snp->sn_remote_error;
376 printf("SCTP_REMOTE_ERROR: assoc=%xh\n",
377 (uint32_t)sre->sre_assoc_id);
378 break;
379 case SCTP_SEND_FAILED:
380 ssf = &snp->sn_send_failed;
381 printf("SCTP_SEND_FAILED: assoc=%xh\n",
382 (uint32_t)ssf->ssf_assoc_id);
383 break;
384 case SCTP_ADAPTATION_INDICATION:
385 {
386 struct sctp_adaptation_event *ae;
387 ae = &snp->sn_adaptation_event;
388 printf("\nSCTP_adaptation_indication bits:0x%x\n",
389 (u_int)ae->sai_adaptation_ind);
390 }
391 break;
392 case SCTP_PARTIAL_DELIVERY_EVENT:
393 {
394 struct sctp_pdapi_event *pdapi;
395 pdapi = &snp->sn_pdapi_event;
396 printf("SCTP_PD-API event:%u\n",
397 pdapi->pdapi_indication);
398 if(pdapi->pdapi_indication == 0){
399 printf("PDI- Aborted\n");
400 }
401 }
402 break;
403
404 case SCTP_SHUTDOWN_EVENT:
405 sse = &snp->sn_shutdown_event;
406 printf("SCTP_SHUTDOWN_EVENT: assoc=%xh\n",
407 (uint32_t)sse->sse_assoc_id);
408 break;
409 default:
410 printf("Unknown notification event type=%xh\n",
411 snp->sn_header.sn_type);
412 } /* end switch(snp->sn_type) */
413 if(asocDown){
414 printf("Bring association back up\n");
415 len = sizeof(to);
416 if(connect(fd,(struct sockaddr *)&to,len) == -1){
417 printf("Sorry connect fails %d\n",errno);
418 }
419 return(1);
420 }
421 return(0);
422}
423
424
425
426int
427my_sctpReadInput(int fd)
428{
429 /* receive some number of datagrams and
430 * act on them.
431 */
432 int sz;
433 struct msghdr msg;
434 struct iovec iov[2];
435 unsigned char from[200];
436 char readBuffer[65535];
437 char controlVector[65535];
438
439 iov[0].iov_base = readBuffer;
440 iov[0].iov_len = sizeof(readBuffer);
441 iov[1].iov_base = NULL;
442 iov[1].iov_len = 0;
443 msg.msg_name = (caddr_t)from;
444 msg.msg_namelen = sizeof(from);
445 msg.msg_iov = iov;
446 msg.msg_iovlen = 1;
447 msg.msg_control = (caddr_t)controlVector;
448 msg.msg_controllen = sizeof(controlVector);
449 msg.msg_flags = 0;
450 errno = 0;
451 sz = recvmsg(fd,&msg,0);
452 if(sz <= 0){
453 printf("Read returns %d errno:%d control len is %zu msgflg:%x\n",
454 sz,errno,
455 msg.msg_controllen,msg.msg_flags);
456 }
457 if (msg.msg_flags & MSG_NOTIFICATION) {
458 return(my_handle_notification(fd,readBuffer));
459 }else{
460 printf("Huh, I got data?.. ignored (%d bytes)\n",sz);
461 return(0);
462 }
463}
464
465
466int
467clear_fds(int fd,int fd1)
468{
469 int felldown;
470 int max,notdone;
471 fd_set readfds,writefds,exceptfds;
472 struct timeval tv;
473 memset(&tv,0,sizeof(tv));
474 FD_ZERO(&readfds);
475 FD_ZERO(&writefds);
476 FD_ZERO(&exceptfds);
477 felldown = 0;
478 FD_SET(fd,&readfds);
479 FD_SET(fd1,&readfds);
480 if(fd > fd1){
481 max = fd + 1;
482 }else{
483 max = fd1 + 1;
484 }
485 notdone = 1;
486 while(notdone){
487 if (select(max, &readfds, &writefds, &exceptfds, &tv) == -1)
488 break;
489 notdone = 0;
490 if(FD_ISSET(fd,&readfds)){
491 notdone++;
492 printf("clearing fd:%d\n",fd);
493 felldown += my_sctpReadInput(fd);
494 notdone = 1;
495 }
496 if(FD_ISSET(fd1,&readfds)){
497 notdone++;
498 printf("clearing fd1:%d\n",fd1);
499 felldown += my_sctpReadInput(fd1);
500 }
501 }
502 return(felldown);
503}
504
505void
506process_out_data(int fd,int fd1)
507{
508 int notdone,x,ret;
509 while(1){
510 /* Prepare the buffers */
511 prepare_buffers();
512 /* send out the 4 buffers */
513 ret = sendto(fd,buffer1,sizeof(buffer1),0,
514 (struct sockaddr *)&to,sizeof(to));
515 if(ret < sizeof(buffer1)){
516 printf("Gak1, error:%d ret:%d\n",errno,ret);
517 }
518
519 ret = sendto(fd1,buffer2,sizeof(buffer1),0,
520 (struct sockaddr *)&to,sizeof(to));
521 if(ret < sizeof(buffer2)){
522 printf("Gak2, error:%d ret:%d\n",errno,ret);
523 }
524
525
526 ret = sendto(fd,buffer3,sizeof(buffer1),0,
527 (struct sockaddr *)&to,sizeof(to));
528 if(ret < sizeof(buffer3)){
529 printf("Gak3, error:%d ret:%d\n",errno,ret);
530 }
531
532
533 ret = sendto(fd1,buffer4,sizeof(buffer1),0,
534 (struct sockaddr *)&to,sizeof(to));
535 if(ret < sizeof(buffer4)){
536 printf("Gak4, error:%d ret:%d\n",errno,ret);
537 }
538
539 /* now wait until we get a assoc failing */
540 notdone = 1;
541 while(notdone){
542 x = clear_fds(fd,fd1);
543 if(x){
544 notdone = 0;
545 }
546 sleep(1);
547 }
548 }
549}
550
551int
552main(int argc, char **argv)
553{
554 int i,fd,fd1;
555 char *addr=NULL;
556 uint16_t port=0;
557 int protocol_touse = IPPROTO_SCTP;
558 struct sctp_event_subscribe event = {0};
559
560 while((i= getopt(argc,argv,"p:h:")) != EOF){
561 switch(i){
562 case 'h':
563 addr = optarg;
564 break;
565 case 'p':
566 port = (uint16_t)strtol(optarg,NULL,0);
567 break;
568 };
569 }
570 memset(&to,0,sizeof(to));
571 if((addr == NULL) || (port == 0)){
572 printf("Usage: %s -h addr -p port\n", argv[0]);
573 return(-1);
574 }
575 if(inet_pton(AF_INET, addr, (void *) &to.sin_addr)){
576 //to.sin_len = sizeof(to);
577 to.sin_family = AF_INET;
578 printf("port selected is %d\n",port);
579 printf("addr %x\n",(u_int)ntohl(to.sin_addr.s_addr));
580 to.sin_port = htons(port);
581 }else{
582 printf("Can't translate the address\n");
583 return(-1);
584 }
585 /**********************socket 1 *******************/
586 fd = socket(AF_INET, SOCK_SEQPACKET, protocol_touse);
587 if(fd == -1){
588 printf("can't open socket:%d\n",errno);
589 return(-1);
590 }
591 memset(&bindto,0,sizeof(bindto));
592 //len = bindto.sin_len = sizeof(bindto);
593 len = sizeof(bindto);
594 bindto.sin_family = AF_INET;
595 bindto.sin_port = 0;
596 if(bind(fd,(struct sockaddr *)&bindto, len) < 0){
597 printf("can't bind a socket:%d\n",errno);
598 close(fd);
599 return(-1);
600 }
601 if(getsockname(fd,(struct sockaddr *)&got,&len) < 0){
602 printf("get sockname failed err:%d\n",errno);
603 close(fd);
604 return(-1);
605 }
606 printf("fd uses port %d\n",ntohs(got.sin_port));
607
608 /**********************socket 2 *******************/
609 fd1 = socket(AF_INET, SOCK_SEQPACKET, protocol_touse);
610 if(fd1 == -1){
611 printf("can't open socket:%d\n",errno);
612 close(fd);
613 return(-1);
614 }
615 memset(&bindto,0,sizeof(bindto));
616 //len = bindto.sin_len = sizeof(bindto);
617 len = sizeof(bindto);
618 bindto.sin_family = AF_INET;
619 bindto.sin_port = 0;
620 if(bind(fd1,(struct sockaddr *)&bindto, len) < 0){
621 printf("can't bind a socket:%d\n",errno);
622 close(fd);
623 close(fd1);
624 return(-1);
625 }
626 if(getsockname(fd1,(struct sockaddr *)&got,&len) < 0){
627 printf("get sockname failed err:%d\n",errno);
628 close(fd);
629 close(fd1);
630 return(-1);
631 }
632 printf("fd1 uses port %d\n",ntohs(got.sin_port));
633
634 /* enable all event notifications */
635 event.sctp_data_io_event = 1;
636 event.sctp_association_event = 1;
637 event.sctp_address_event = 1;
638 event.sctp_send_failure_event = 1;
639 event.sctp_peer_error_event = 1;
640 event.sctp_shutdown_event = 1;
641 event.sctp_partial_delivery_event = 1;
642 event.sctp_adaptation_layer_event = 1;
643 if (setsockopt(fd, IPPROTO_SCTP,
644 SCTP_EVENTS, &event,
645 sizeof(event)) != 0) {
646 printf("Gak, can't set events errno:%d\n",errno);
647 exit(0);
648 }
649 if (setsockopt(fd1, IPPROTO_SCTP,
650 SCTP_EVENTS, &event,
651 sizeof(event)) != 0) {
652 printf("Gak, can't set events errno:%d\n",errno);
653 exit(0);
654 }
655
656 if(connect(fd,(struct sockaddr *)&to,len) == -1){
657 printf("Sorry connect fails %d\n",errno);
658 close(fd);
659 return(-1);
660 }
661 if(connect(fd1,(struct sockaddr *)&to,len) == -1){
662 printf("Sorry connect fails %d\n",errno);
663 close(fd);
664 return(-1);
665 }
666 printf("Connected\n");
667 clear_fds(fd,fd1);
668 process_out_data(fd,fd1);
669
670 return(0);
671}
672