1 /* SCTP kernel Implementation
2 * (C) Copyright IBM Corp. 2003
3 * Copyright (c) 2003 Cisco
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)
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.
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.
24 * Copyright (c) 2003 Cisco
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions are met:
29 * a) Redistributions of source code must retain the above copyright notice,
30 * this list of conditions and the following disclaimer.
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.
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.
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.
52 * Please send any bug reports or fixes you make to the
54 * lksctp developers <lksctp-developers@lists.sourceforge.net>
56 * Or submit a bug report through the following website:
57 * http://www.sf.net/projects/lksctp
59 * Any bugs reported to us we will try to fix... any fixes shared will
60 * be incorporated into the next SCTP release.
62 * Written or modified by:
63 * Randall Stewart <rrs@cisco.com>
64 * Sridhar Samudrala <sri@us.ibm.com>
72 #include <sys/types.h>
73 #include <sys/ioctl.h>
75 #include <sys/socket.h>
77 #include <netinet/in.h>
82 #include <arpa/inet.h>
90 #include <netinet/sctp.h>
92 #include <sys/inttypes.h>
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. */
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. */
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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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;
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,
192 update_crc32(u_int32_t crc32,
193 unsigned char *buffer,
197 for (i = 0; i < length; i++) {
198 SCTP_CRC32C(crc32, buffer[i]);
204 sctp_csum_finalize(u_int32_t crc32)
207 #if BYTE_ORDER == BIG_ENDIAN
208 u_int8_t byte0, byte1, byte2, byte3;
210 /* Complement the result */
212 #if BYTE_ORDER == BIG_ENDIAN
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...
218 byte0 = result & 0x000000ff;
219 byte1 = (result >> 8) & 0x000000ff;
220 byte2 = (result >> 16) & 0x000000ff;
221 byte3 = (result >> 24) & 0x000000ff;
222 result = ((byte0 << 24) |
226 crc32 = htonl(result);
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.
241 /* Prepare buffers */
242 u_int32_t temp,*csum;
245 temp = update_crc32(temp,buffer1,(sizeof(buffer1)-4));
246 temp = sctp_csum_finalize(temp);
247 csum = (u_int32_t *)(buffer1+(sizeof(buffer1)-4));
249 printf("Buffer1: Found csum:%x calculated:%x\n",
254 temp = update_crc32(temp,buffer2,(sizeof(buffer2)-4));
255 temp = sctp_csum_finalize(temp);
256 csum = (u_int32_t *)(buffer2+(sizeof(buffer2)-4));
258 printf("Buffer2: Found csum:%x calculated:%x\n",
264 temp = update_crc32(temp,buffer3,(sizeof(buffer3)-4));
265 temp = sctp_csum_finalize(temp);
266 csum = (u_int32_t *)(buffer3+(sizeof(buffer3)-4));
268 printf("Buffer3: Found csum:%x calculated:%x\n",
274 temp = update_crc32(temp,buffer4,(sizeof(buffer4)-4));
275 temp = sctp_csum_finalize(temp);
276 csum = (u_int32_t *)(buffer4+(sizeof(buffer4)-4));
278 printf("Buffer4: Found csum:%x calculated:%x\n",
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;
296 struct sockaddr_in *sin;
297 struct sockaddr_in6 *sin6;
299 snp = (union sctp_notification *)notify_buf;
301 switch(snp->sn_header.sn_type) {
302 case SCTP_ASSOC_CHANGE:
303 sac = &snp->sn_assoc_change;
304 switch(sac->sac_state) {
307 str = "COMMUNICATION UP";
311 str = "COMMUNICATION LOST";
317 case SCTP_SHUTDOWN_COMP:
318 str = "SHUTDOWN COMPLETE";
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);
328 } /* end switch(sac->sac_state) */
329 printf("SCTP_ASSOC_CHANGE: %s, assoc=%xh\n", str,
330 (uint32_t)sac->sac_assoc_id);
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";
338 case SCTP_ADDR_UNREACHABLE:
339 str = "ADDRESS UNAVAILABLE";
341 case SCTP_ADDR_REMOVED:
342 str = "ADDRESS REMOVED";
344 case SCTP_ADDR_ADDED:
345 str = "ADDRESS ADDED";
347 case SCTP_ADDR_MADE_PRIM:
348 str = "ADDRESS MADE PRIMARY";
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));
357 sin = (struct sockaddr_in *)&spc->spc_aaddr;
358 inet_ntop(AF_INET, (char*)&sin->sin_addr, buf, sizeof(buf));
360 printf("SCTP_PEER_ADDR_CHANGE: %s, addr=%s, assoc=%xh\n", str,
361 buf, (uint32_t)spc->spc_assoc_id);
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);
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);
373 case SCTP_ADAPTATION_INDICATION:
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);
381 case SCTP_PARTIAL_DELIVERY_EVENT:
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");
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);
399 printf("Unknown notification event type=%xh\n",
400 snp->sn_header.sn_type);
401 } /* end switch(snp->sn_type) */
406 static char readBuffer[65535];
408 static char controlVector[65535];
409 static struct msghdr msg;
411 my_sctpReadInput(int fd,int maxread)
413 /* receive some number of datagrams and
416 struct sctp_sndrcvinfo *s_info;
420 unsigned char from[200];
423 memset(&msg,0,sizeof(msg));
424 memset(controlVector,0,sizeof(controlVector));
425 memset(readBuffer,0,sizeof(readBuffer));
427 iov[0].iov_base = readBuffer;
428 iov[0].iov_len = maxread;
429 iov[1].iov_base = NULL;
431 msg.msg_name = (caddr_t)from;
432 msg.msg_namelen = sizeof(from);
435 msg.msg_control = (caddr_t)controlVector;
436 msg.msg_controllen = sizeof(controlVector);
438 sz = recvmsg(fd,&msg,0);
439 printf("Read fd:%d returns %d errno:%d control len is %d msgflg:%x\n",
445 if (msg.msg_flags & MSG_NOTIFICATION) {
446 printf("Got a notification\n");
447 return(my_handle_notification(fd,readBuffer));
449 printf("Got data\n");
460 fd_set readfds,writefds,exceptfds;
462 memset(&tv,0,sizeof(tv));
471 select(max,&readfds,&writefds,&exceptfds,NULL);
473 if(FD_ISSET(fd,&readfds)){
474 printf("Read please\n");
475 cameup += my_sctpReadInput(fd,4100);
483 struct sctp_sndrcvinfo *s_info;
484 struct cmsghdr *cmsg;
486 if(msg.msg_controllen){
487 /* parse through and see if we find
488 * the sctp_sndrcvinfo
490 cmsg = (struct cmsghdr *)controlVector;
492 if(cmsg->cmsg_level == IPPROTO_SCTP){
493 if(cmsg->cmsg_type == SCTP_SNDRCV){
495 s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
499 cmsg = CMSG_NXTHDR(&msg,cmsg);
502 printf("No CMSG?\n");
506 printf("No sinfo?\n");
509 return(s_info->sinfo_assoc_id);
514 process(int fd,int magic)
516 int fd1,num_asoc,ret,i;
525 printf("pass %d\n",i);
533 printf("Got data? %d\n",sz);
536 printf("asoc count is %d\n",num_asoc);
539 printf("Reading for %d bytes from fd:%d\n",
541 my_sctpReadInput(fd,i);
543 memcpy(buffer1,readBuffer,i);
545 printf("Huh I am messed up read %d wanted %d\n",
549 if(msg.msg_flags & MSG_EOR){
550 printf("Huh got EOR on paritial read?\n");
553 asoc = dig_out_asocid();
556 fd1 = sctp_peeloff(fd,asoc);
558 printf("peeloff failed %d/err:%d\n",
562 my_sctpReadInput(fd1,(4100-i));
564 memcpy(&buffer1[i],readBuffer,sz);
565 printf("Copied %d bytes\n",sz);
567 printf("Huh only read %d\n",sz);
570 printf("magic engaged\n");
571 my_sctpReadInput(fd,i);
573 my_sctpReadInput(fd,4100);
576 memcpy(buffer2,readBuffer,sz);
577 printf("copied %d bytes\n",sz);
579 printf("Huh only read %d\n",sz);
581 my_sctpReadInput(fd1,4100);
583 memcpy(buffer3,readBuffer,sz);
584 printf("copied %d bytes\n",sz);
586 printf("Huh only read %d\n",sz);
588 my_sctpReadInput(fd,4100);
590 memcpy(buffer4,readBuffer,sz);
591 printf("copied %d bytes\n",sz);
593 printf("Huh only read %d\n",sz);
605 main(int argc, char **argv)
610 struct sctp_event_subscribe event;
611 while((i= getopt(argc,argv,"m:M:")) != EOF){
614 myport = (uint16_t)strtol(optarg,NULL,0);
617 magic = strtol(optarg,NULL,0);
621 /**********************socket 1 *******************/
622 fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
624 printf("can't open socket:%d\n",errno);
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);
638 if(getsockname(fd,(struct sockaddr *)&got,&len) < 0){
639 printf("get sockname failed err:%d\n",errno);
643 printf("fd uses port %d\n",ntohs(got.sin_port));
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,
656 sizeof(event)) != 0) {
657 printf("Gak, can't set events errno:%d\n",errno);
660 printf("to process\n");