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