Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <platdep/sockets.h>
00020 #include "headers/defs.h"
00021 namespace INETFw
00022 {
00023 #include "headers/bsdint.h"
00024 #include "headers/in.h"
00025 #include "headers/in_systm.h"
00026 #include "headers/ip.h"
00027 #include "headers/sctp.h"
00028 };
00029
00030 #include "SCTPSerializer.h"
00031 #include "SCTPAssociation.h"
00032
00033
00034 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64)
00035 #include <netinet/in.h>
00036 #include <arpa/inet.h>
00037 #include <sys/socket.h>
00038 #endif
00039
00040 #include <sys/types.h>
00041
00042
00043 using namespace INETFw;
00044
00045
00046
00047 int32 SCTPSerializer::serialize(const SCTPMessage *msg, unsigned char *buf, uint32 bufsize)
00048 {
00049 int32 size_init_chunk = sizeof(struct init_chunk);
00050 int32 size_sack_chunk = sizeof(struct sack_chunk);
00051 int32 size_heartbeat_chunk = sizeof(struct heartbeat_chunk);
00052 int32 size_heartbeat_ack_chunk = sizeof(struct heartbeat_ack_chunk);
00053 int32 size_chunk = sizeof(struct chunk);
00054
00055
00056 struct common_header *ch = (struct common_header*) (buf);
00057 uint32 writtenbytes = sizeof(struct common_header);
00058
00059
00060 ch->source_port = htons(msg->getSrcPort());
00061 ch->destination_port = htons(msg->getDestPort());
00062 ch->verification_tag = htonl(msg->getTag());
00063
00064
00065
00066 int32 noChunks = msg->getChunksArraySize();
00067 for(int32 cc = 0; cc < noChunks; cc++)
00068 {
00069 const SCTPChunk *chunk = check_and_cast<SCTPChunk *>(((SCTPMessage *)msg)->getChunks(cc));
00070 unsigned char chunkType = chunk->getChunkType();
00071 switch(chunkType)
00072 {
00073 case DATA:
00074 {
00075
00076 SCTPDataChunk *dataChunk = check_and_cast<SCTPDataChunk *>(chunk);
00077 struct data_chunk *dc = (struct data_chunk*) (buf + writtenbytes);
00078 unsigned char flags = 0;
00079
00080
00081 dc->type = dataChunk->getChunkType();
00082 if (dataChunk->getUBit())
00083 flags |= UNORDERED_BIT;
00084 if (dataChunk->getBBit())
00085 flags |= BEGIN_BIT;
00086 if (dataChunk->getEBit())
00087 flags |= END_BIT;
00088 dc->flags = flags;
00089 dc->length = htons(dataChunk->getByteLength());
00090 dc->tsn = htonl(dataChunk->getTsn());
00091 dc->sid = htons(dataChunk->getSid());
00092 dc->ssn = htons(dataChunk->getSsn());
00093 dc->ppi = htonl(dataChunk->getPpid());
00094 writtenbytes += SCTP_DATA_CHUNK_LENGTH;
00095
00096 SCTPSimpleMessage *smsg = check_and_cast<SCTPSimpleMessage *>(dataChunk->getEncapsulatedMsg());
00097
00098 const uint32 datalen = smsg->getDataLen();
00099 if( smsg->getDataArraySize() >= datalen) {
00100 for (uint32 i = 0; i < datalen; i++) {
00101 dc->user_data[i] = smsg->getData(i);
00102 }
00103 }
00104 writtenbytes += ADD_PADDING(datalen);
00105 break;
00106 }
00107 case INIT:
00108 {
00109
00110
00111 SCTPInitChunk *initChunk = check_and_cast<SCTPInitChunk *>(chunk);
00112
00113
00114 struct init_chunk *ic = (struct init_chunk*) (buf + writtenbytes);
00115
00116
00117
00118 ic->type = initChunk->getChunkType();
00119 ic->flags = 0;
00120 ic->initiate_tag = htonl(initChunk->getInitTag());
00121 ic->a_rwnd = htonl(initChunk->getA_rwnd());
00122 ic->mos = htons(initChunk->getNoOutStreams());
00123 ic->mis = htons(initChunk->getNoInStreams());
00124 ic->initial_tsn = htonl(initChunk->getInitTSN());
00125 int32 parPtr = 0;
00126
00127 struct supported_address_types_parameter* sup_addr = (struct supported_address_types_parameter*) (((unsigned char *)ic) + size_init_chunk + parPtr);
00128 sup_addr->type = htons(INIT_SUPPORTED_ADDRESS);
00129 sup_addr->length = htons(6);
00130 sup_addr->address_type = htons(INIT_PARAM_IPV4);
00131 parPtr += 8;
00132 int32 numaddr = initChunk->getAddressesArraySize();
00133 for(int32 i=0; i<numaddr; i++)
00134 {
00135 struct init_ipv4_address_parameter *ipv4addr = (struct init_ipv4_address_parameter*) (((unsigned char *)ic) + size_init_chunk + parPtr);
00136 ipv4addr->type = htons(INIT_PARAM_IPV4);
00137 ipv4addr->length = htons(8);
00138 ipv4addr->address = htonl(initChunk->getAddresses(i).get4().getInt());
00139 parPtr += sizeof(struct init_ipv4_address_parameter);
00140 }
00141 ic->length = htons(SCTP_INIT_CHUNK_LENGTH+parPtr);
00142 writtenbytes += SCTP_INIT_CHUNK_LENGTH+parPtr;
00143 break;
00144 }
00145 case INIT_ACK:
00146 {
00147
00148 SCTPInitAckChunk *initAckChunk = check_and_cast<SCTPInitAckChunk *>(chunk);
00149
00150
00151 struct init_ack_chunk *iac = (struct init_ack_chunk*) (buf + writtenbytes);
00152
00153 iac->type = initAckChunk->getChunkType();
00154
00155 iac->initiate_tag = htonl(initAckChunk->getInitTag());
00156 iac->a_rwnd = htonl(initAckChunk->getA_rwnd());
00157 iac->mos = htons(initAckChunk->getNoOutStreams());
00158 iac->mis = htons(initAckChunk->getNoInStreams());
00159 iac->initial_tsn = htonl(initAckChunk->getInitTSN());
00160
00161 int32 parPtr=0;
00162
00163 struct supported_address_types_parameter* sup_addr = (struct supported_address_types_parameter*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00164 sup_addr->type = htons(INIT_SUPPORTED_ADDRESS);
00165 sup_addr->length = htons(6);
00166 sup_addr->address_type = htons(INIT_PARAM_IPV4);
00167 parPtr += 8;
00168
00169
00170 int32 numaddr = initAckChunk->getAddressesArraySize();
00171 for(int32 i=0; i<numaddr; i++)
00172 {
00173 struct init_ipv4_address_parameter *ipv4addr = (struct init_ipv4_address_parameter*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00174 ipv4addr->type = htons(INIT_PARAM_IPV4);
00175 ipv4addr->length = htons(8);
00176 ipv4addr->address = htonl(initAckChunk->getAddresses(i).get4().getInt());
00177 parPtr += 8;
00178 }
00179 uint32 uLen = initAckChunk->getUnrecognizedParametersArraySize();
00180 if (uLen>0)
00181 {
00182
00183 int32 k=0;
00184 uint32 pLen=0;
00185 while (uLen>0)
00186 {
00187 struct tlv* unknown = (struct tlv*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00188 unknown->type = htons(UNRECOGNIZED_PARAMETER);
00189 pLen = initAckChunk->getUnrecognizedParameters(k+2)*16+initAckChunk->getUnrecognizedParameters(k+3);
00190 unknown->length = htons(pLen+4);
00191
00192 for (uint32 i=0; i<ADD_PADDING(pLen); i++,k++)
00193 unknown->value[i] = initAckChunk->getUnrecognizedParameters(k);
00194 parPtr += ADD_PADDING(pLen+4);
00195 uLen-=ADD_PADDING(pLen);
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 int32 cookielen = initAckChunk->getCookieArraySize();
00210 if (cookielen == 0)
00211 {
00212 SCTPCookie* stateCookie = check_and_cast<SCTPCookie*>(initAckChunk->getStateCookie());
00213 struct init_cookie_parameter *cookie = (struct init_cookie_parameter*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00214 cookie->type = htons(INIT_PARAM_COOKIE);
00215 cookie->length = htons(SCTP_COOKIE_LENGTH + 4);
00216 cookie->creationTime = htonl((uint32)stateCookie->getCreationTime().dbl());
00217 cookie->localTag = htonl(stateCookie->getLocalTag());
00218 cookie->peerTag = htonl(stateCookie->getPeerTag());
00219 for(int32 i=0; i<32; i++)
00220 {
00221 cookie->localTieTag[i] = stateCookie->getLocalTieTag(i);
00222 cookie->peerTieTag[i] = stateCookie->getPeerTieTag(i);
00223 }
00224 parPtr += (SCTP_COOKIE_LENGTH + 4);
00225 }
00226 else
00227 {
00228 struct tlv *cookie = (struct tlv*) (((unsigned char *)iac) + size_init_chunk + parPtr);
00229 cookie->type = htons(INIT_PARAM_COOKIE);
00230 cookie->length = htons(cookielen+4);
00231 for(int32 i=0; i<cookielen; i++)
00232 cookie->value[i] = initAckChunk->getCookie(i);
00233 parPtr += cookielen + 4;
00234 }
00235 iac->length = htons(SCTP_INIT_CHUNK_LENGTH+parPtr);
00236 writtenbytes += SCTP_INIT_CHUNK_LENGTH+parPtr;
00237 break;
00238 }
00239 case SACK:
00240 {
00241 SCTPSackChunk *sackChunk = check_and_cast<SCTPSackChunk *>(chunk);
00242
00243
00244 struct sack_chunk *sac = (struct sack_chunk*) (buf + writtenbytes);
00245 writtenbytes += (sackChunk->getBitLength() / 8);
00246
00247
00248 sac->type = sackChunk->getChunkType();
00249
00250 sac->length = htons(sackChunk->getBitLength() / 8);
00251 uint32 cumtsnack = sackChunk->getCumTsnAck();
00252 sac->cum_tsn_ack = htonl(cumtsnack);
00253 sac->a_rwnd = htonl(sackChunk->getA_rwnd());
00254 sac->nr_of_gaps = htons(sackChunk->getNumGaps());
00255 sac->nr_of_dups = htons(sackChunk->getNumDupTsns());
00256
00257
00258 int32 numgaps = sackChunk->getNumGaps();
00259 int32 numdups = sackChunk->getNumDupTsns();
00260 for(int32 i=0; i<numgaps; i++)
00261 {
00262 struct sack_gap *gap = (struct sack_gap*) (((unsigned char *)sac) + size_sack_chunk + i*sizeof(struct sack_gap));
00263 gap->start = htons(sackChunk->getGapStart(i) - cumtsnack);
00264 gap->stop = htons(sackChunk->getGapStop(i) - cumtsnack);
00265 }
00266 for(int32 i=0; i<numdups; i++)
00267 {
00268 struct sack_duptsn *dup = (struct sack_duptsn*) (((unsigned char *)sac) + size_sack_chunk + numgaps*sizeof(struct sack_gap) + i*sizeof(sack_duptsn));
00269 dup->tsn = htonl(sackChunk->getDupTsns(i));
00270 }
00271 break;
00272 }
00273 case HEARTBEAT:
00274 {
00275
00276 SCTPHeartbeatChunk *heartbeatChunk = check_and_cast<SCTPHeartbeatChunk *>(chunk);
00277
00278
00279 struct heartbeat_chunk *hbc = (struct heartbeat_chunk*) (buf + writtenbytes);
00280 writtenbytes += (heartbeatChunk->getBitLength() / 8);
00281
00282
00283 hbc->type = heartbeatChunk->getChunkType();
00284
00285 hbc->length = htons(heartbeatChunk->getBitLength() / 8);
00286
00287
00288 struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbc) + size_heartbeat_chunk);
00289 IPvXAddress addr = heartbeatChunk->getRemoteAddr();
00290 simtime_t time = heartbeatChunk->getTimeField();
00291 int32 infolen = sizeof(addr.get4().getInt()) + sizeof(uint32);
00292 hbi->type = htons(1);
00293 hbi->length = htons(infolen+4);
00294 HBI_ADDR(hbi) = htonl(addr.get4().getInt());
00295 HBI_TIME(hbi) = htonl((uint32)time.dbl());
00296 break;
00297 }
00298 case HEARTBEAT_ACK:
00299 {
00300
00301 SCTPHeartbeatAckChunk *heartbeatAckChunk = check_and_cast<SCTPHeartbeatAckChunk *>(chunk);
00302
00303
00304 struct heartbeat_ack_chunk *hbac = (struct heartbeat_ack_chunk*) (buf + writtenbytes);
00305 writtenbytes += (heartbeatAckChunk->getBitLength() / 8);
00306
00307
00308 hbac->type = heartbeatAckChunk->getChunkType();
00309
00310 hbac->length = htons(heartbeatAckChunk->getBitLength() / 8);
00311
00312
00313 struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbac) + size_heartbeat_ack_chunk);
00314 int32 infolen = heartbeatAckChunk->getInfoArraySize();
00315 hbi->type = htons(1);
00316 if (infolen > 0)
00317 {
00318 hbi->length = htons(infolen+4);
00319 for(int32 i=0; i<infolen; i++)
00320 {
00321 HBI_INFO(hbi)[i] = heartbeatAckChunk->getInfo(i);
00322 }
00323 }
00324 else
00325 {
00326 IPvXAddress addr = heartbeatAckChunk->getRemoteAddr();
00327 infolen = sizeof(addr.get4().getInt()) + sizeof(uint32);
00328 hbi->type = htons(1);
00329 hbi->length = htons(infolen+4);
00330
00331 simtime_t time = heartbeatAckChunk->getTimeField();
00332 HBI_ADDR(hbi) = htonl(addr.get4().getInt());
00333 HBI_TIME(hbi) = htonl((uint32)time.dbl());
00334 }
00335 break;
00336 }
00337 case ABORT:
00338 {
00339
00340 SCTPAbortChunk *abortChunk = check_and_cast<SCTPAbortChunk *>(chunk);
00341
00342
00343 struct abort_chunk *ac = (struct abort_chunk*) (buf + writtenbytes);
00344 writtenbytes += (abortChunk->getBitLength() / 8);
00345
00346
00347 ac->type = abortChunk->getChunkType();
00348 unsigned char flags = 0;
00349 if(abortChunk->getT_Bit())
00350 flags |= T_BIT;
00351 ac->flags = flags;
00352 ac->length = htons(abortChunk->getBitLength() / 8);
00353 break;
00354 }
00355 case COOKIE_ECHO:
00356 {
00357
00358 SCTPCookieEchoChunk *cookieChunk = check_and_cast<SCTPCookieEchoChunk *>(chunk);
00359
00360 struct cookie_echo_chunk *cec = (struct cookie_echo_chunk*) (buf + writtenbytes);
00361
00362
00363 cec->type = cookieChunk->getChunkType();
00364 cec->length = htons(cookieChunk->getBitLength() / 8);
00365 int32 cookielen = cookieChunk->getCookieArraySize();
00366 if (cookielen>0)
00367 {
00368 for(int32 i=0; i<cookielen; i++)
00369 cec->state_cookie[i] = cookieChunk->getCookie(i);
00370 }
00371 else
00372 {
00373 SCTPCookie* stateCookie = check_and_cast<SCTPCookie*>(cookieChunk->getStateCookie());
00374 struct cookie_parameter *cookie = (struct cookie_parameter*) (buf + writtenbytes+4);
00375 cookie->creationTime = htonl((uint32)stateCookie->getCreationTime().dbl());
00376 cookie->localTag = htonl(stateCookie->getLocalTag());
00377 cookie->peerTag = htonl(stateCookie->getPeerTag());
00378 for(int32 i=0; i<32; i++)
00379 {
00380 cookie->localTieTag[i] = stateCookie->getLocalTieTag(i);
00381 cookie->peerTieTag[i] = stateCookie->getPeerTieTag(i);
00382 }
00383 }
00384 writtenbytes += (ADD_PADDING(cookieChunk->getBitLength() / 8));
00385
00386 uint32 uLen = cookieChunk->getUnrecognizedParametersArraySize();
00387 if (uLen>0)
00388 {
00389
00390 struct error_chunk* error = (struct error_chunk*)(buf + writtenbytes);
00391 error->type = ERRORTYPE;
00392 error->flags = 0;
00393 int32 k=0;
00394 uint32 pLen=0;
00395 uint32 ecLen = SCTP_ERROR_CHUNK_LENGTH;
00396 uint32 ecParPtr = 0;
00397 while (uLen>0)
00398 {
00399 struct tlv* unknown = (struct tlv*) (((unsigned char *)error) + sizeof(struct error_chunk) + ecParPtr);
00400 unknown->type = htons(UNRECOGNIZED_PARAMETER);
00401 pLen = cookieChunk->getUnrecognizedParameters(k+2)*16+cookieChunk->getUnrecognizedParameters(k+3);
00402 unknown->length = htons(pLen+4);
00403 ecLen += pLen+4;
00404
00405 for (uint32 i=0; i<ADD_PADDING(pLen); i++,k++)
00406 unknown->value[i] = cookieChunk->getUnrecognizedParameters(k);
00407 ecParPtr += ADD_PADDING(pLen+4);
00408
00409 uLen-=ADD_PADDING(pLen);
00410 }
00411 error->length = htons(ecLen);
00412 writtenbytes += SCTP_ERROR_CHUNK_LENGTH+ecParPtr;
00413 }
00414
00415 break;
00416 }
00417 case COOKIE_ACK:
00418 {
00419
00420 SCTPCookieAckChunk *cookieAckChunk = check_and_cast<SCTPCookieAckChunk *>(chunk);
00421
00422 struct cookie_ack_chunk *cac = (struct cookie_ack_chunk*) (buf + writtenbytes);
00423 writtenbytes += (cookieAckChunk->getBitLength() / 8);
00424
00425 cac->type = cookieAckChunk->getChunkType();
00426 cac->length = htons(cookieAckChunk->getBitLength() / 8);
00427
00428 break;
00429 }
00430 case SHUTDOWN:
00431 {
00432
00433 SCTPShutdownChunk *shutdownChunk = check_and_cast<SCTPShutdownChunk *>(chunk);
00434
00435 struct shutdown_chunk *sac = (struct shutdown_chunk*) (buf + writtenbytes);
00436 writtenbytes += (shutdownChunk->getBitLength() / 8);
00437
00438 sac->type = shutdownChunk->getChunkType();
00439 sac->cumulative_tsn_ack = htonl(shutdownChunk->getCumTsnAck());
00440 sac->length = htons(shutdownChunk->getBitLength() / 8);
00441
00442 break;
00443 }
00444 case SHUTDOWN_ACK:
00445 {
00446
00447 SCTPShutdownAckChunk *shutdownAckChunk = check_and_cast<SCTPShutdownAckChunk *>(chunk);
00448
00449 struct shutdown_ack_chunk *sac = (struct shutdown_ack_chunk*) (buf + writtenbytes);
00450 writtenbytes += (shutdownAckChunk->getBitLength() / 8);
00451
00452 sac->type = shutdownAckChunk->getChunkType();
00453 sac->length = htons(shutdownAckChunk->getBitLength() / 8);
00454
00455 break;
00456 }
00457 case SHUTDOWN_COMPLETE:
00458 {
00459
00460 SCTPShutdownCompleteChunk *shutdownCompleteChunk = check_and_cast<SCTPShutdownCompleteChunk *>(chunk);
00461
00462 struct shutdown_complete_chunk *sac = (struct shutdown_complete_chunk*) (buf + writtenbytes);
00463 writtenbytes += (shutdownCompleteChunk->getBitLength() / 8);
00464
00465 sac->type = shutdownCompleteChunk->getChunkType();
00466 sac->length = htons(shutdownCompleteChunk->getBitLength() / 8);
00467 unsigned char flags = 0;
00468 if(shutdownCompleteChunk->getTBit())
00469 flags |= T_BIT;
00470 sac->flags = flags;
00471 break;
00472 }
00473 case ERRORTYPE:
00474 {
00475 SCTPErrorChunk* errorchunk = check_and_cast<SCTPErrorChunk*>(chunk);
00476 struct error_chunk* error = (struct error_chunk*)(buf + writtenbytes);
00477 error->type = errorchunk->getChunkType();
00478 error->flags = 0;
00479
00480 if (errorchunk->getParametersArraySize()>0)
00481 {
00482 writtenbytes += size_chunk;
00483 }
00484 else
00485 writtenbytes += ADD_PADDING(error->length);
00486 break;
00487 }
00488 default:
00489 printf("Serialize TODO: Implement for outgoing chunk type %d!\n", chunkType);
00490 throw new cRuntimeError("TODO: unknown chunktype in outgoing packet on external interface! Implement it!");
00491
00492
00493 }
00494
00495
00496
00497
00498 }
00499
00500
00501
00502
00503 ch->checksum = checksum((unsigned char*)ch, writtenbytes);
00504 return writtenbytes;
00505 }
00506
00507 uint32 SCTPSerializer::checksum(const uint8_t *buf, register uint32 len)
00508 {
00509 uint32 h;
00510 unsigned char byte0, byte1, byte2, byte3;
00511 uint32 crc32c;
00512 register uint32 i;
00513 register uint32 res = (~0L);
00514 for (i = 0; i < len; i++)
00515 CRC32C(res, buf[i]);
00516 h = ~res;
00517 byte0 = h & 0xff;
00518 byte1 = (h>>8) & 0xff;
00519 byte2 = (h>>16) & 0xff;
00520 byte3 = (h>>24) & 0xff;
00521 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
00522 return htonl(crc32c);
00523 }
00524
00525 void SCTPSerializer::parse(const uint8_t *buf, uint32 bufsize, SCTPMessage *dest)
00526 {
00527 int32 size_common_header = sizeof(struct common_header);
00528 int32 size_init_chunk = sizeof(struct init_chunk);
00529 int32 size_init_ack_chunk = sizeof(struct init_ack_chunk);
00530 int32 size_data_chunk = sizeof(struct data_chunk);
00531 int32 size_sack_chunk = sizeof(struct sack_chunk);
00532 int32 size_heartbeat_chunk = sizeof(struct heartbeat_chunk);
00533 int32 size_heartbeat_ack_chunk = sizeof(struct heartbeat_ack_chunk);
00534 int32 size_abort_chunk = sizeof(struct abort_chunk);
00535 int32 size_cookie_echo_chunk = sizeof(struct cookie_echo_chunk);
00536 uint16 paramType;
00537 int32 parptr, chunklen, cLen, woPadding;
00538 struct common_header *common_header = (struct common_header*) (buf);
00539 int32 tempChecksum = common_header->checksum;
00540 common_header->checksum = 0;
00541 int32 chksum = checksum((unsigned char*)common_header, bufsize);
00542 common_header->checksum = tempChecksum;
00543
00544 const unsigned char *chunks = (unsigned char*) (buf + size_common_header);
00545 sctpEV3<<"SCTPSerializer::parse SCTPMessage\n";
00546 if (tempChecksum == chksum)
00547 dest->setChecksumOk(true);
00548 else
00549 dest->setChecksumOk(false);
00550 sctpEV3<<"checksumOK="<<dest->getChecksumOk()<<"\n";
00551 dest->setSrcPort(ntohs(common_header->source_port));
00552 dest->setDestPort(ntohs(common_header->destination_port));
00553 dest->setTag(ntohl(common_header->verification_tag));
00554 dest->setBitLength(SCTP_COMMON_HEADER*8);
00555
00556 uint32 chunkPtr = 0;
00557
00558
00559 while(chunkPtr < (bufsize - size_common_header))
00560 {
00561 const struct chunk * chunk = (struct chunk*)(chunks + chunkPtr);
00562 int32 chunkType = chunk->type;
00563 sctpEV3<<"chunkType="<<chunkType<<"\n";
00564 woPadding = ntohs(chunk->length);
00565 sctpEV3<<"chunk->length="<<ntohs(chunk->length)<<"\n";
00566 cLen = ADD_PADDING(woPadding);
00567 switch(chunkType)
00568 {
00569 case DATA:
00570 {
00571 ev<<"Data received\n";
00572 const struct data_chunk *dc = (struct data_chunk*) (chunks + chunkPtr);
00573 sctpEV3<<"cLen="<<cLen<<"\n";
00574 if(cLen == 0)
00575 throw new cRuntimeError("Incoming SCTP packet contains data chunk with length==0");
00576 SCTPDataChunk *chunk = new SCTPDataChunk("DATA");
00577 chunk->setChunkType(chunkType);
00578 chunk->setUBit(dc->flags & UNORDERED_BIT);
00579 chunk->setBBit(dc->flags & BEGIN_BIT);
00580 chunk->setEBit(dc->flags & END_BIT);
00581 chunk->setTsn(ntohl(dc->tsn));
00582 chunk->setSid(ntohs(dc->sid));
00583 chunk->setSsn(ntohs(dc->ssn));
00584 chunk->setPpid(ntohl(dc->ppi));
00585 chunk->setBitLength(SCTP_DATA_CHUNK_LENGTH*8);
00586 sctpEV3<<"parse data: woPadding="<<woPadding<<" size_data_chunk="<<size_data_chunk<<"\n";
00587 if(woPadding > size_data_chunk)
00588 {
00589 SCTPSimpleMessage* msg=new SCTPSimpleMessage("data");
00590 int32 datalen = (woPadding - size_data_chunk);
00591 msg->setBitLength(datalen*8);
00592 msg->setDataLen(datalen);
00593 msg->setDataArraySize(datalen);
00594 for(int32 i=0; i<datalen; i++)
00595 msg->setData(i, dc->user_data[i]);
00596
00597 chunk->encapsulate(msg);
00598 }
00599 sctpEV3<<"datachunkLength="<<chunk->getBitLength()<<"\n";
00600 dest->addChunk(chunk);
00601 break;
00602 }
00603 case INIT:
00604 {
00605 ev<<"parse INIT\n";
00606 const struct init_chunk *init_chunk = (struct init_chunk*) (chunks + chunkPtr);
00607 chunklen = SCTP_INIT_CHUNK_LENGTH;
00608 SCTPInitChunk *chunk = new SCTPInitChunk("INIT");
00609 chunk->setChunkType(chunkType);
00610 chunk->setName("INIT");
00611 chunk->setInitTag(ntohl(init_chunk->initiate_tag));
00612 chunk->setA_rwnd(ntohl(init_chunk->a_rwnd));
00613 chunk->setNoOutStreams(ntohs(init_chunk->mos));
00614 chunk->setNoInStreams(ntohs(init_chunk->mis));
00615 chunk->setInitTSN(ntohl(init_chunk->initial_tsn));
00616 chunk->setAddressesArraySize(0);
00617 chunk->setUnrecognizedParametersArraySize(0);
00618
00619 if(cLen > size_init_chunk)
00620 {
00621 int32 parcounter = 0, addrcounter = 0;
00622 parptr = 0;
00623 bool stopProcessing = false;
00624 while(cLen > size_init_chunk+parptr && !stopProcessing)
00625 {
00626 sctpEV3<<"Process INIT parameters\n";
00627 const struct tlv *parameter = (struct tlv*)(((unsigned char*)init_chunk) + size_init_chunk + parptr);
00628 paramType = ntohs(parameter->type);
00629 sctpEV3<<"search for param "<<paramType<<"\n";
00630 switch (paramType)
00631 {
00632 case SUPPORTED_ADDRESS_TYPES:
00633 {
00634 break;
00635 }
00636 case INIT_PARAM_IPV4:
00637 {
00638
00639 sctpEV3<<"IPv4\n";
00640 const struct init_ipv4_address_parameter *v4addr;
00641 v4addr = (struct init_ipv4_address_parameter*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00642 chunk->setAddressesArraySize(++addrcounter);
00643 IPvXAddress *localv4Addr;
00644 localv4Addr = new IPvXAddress("0.0.0.0");
00645 localv4Addr->set(ntohl(v4addr->address));
00646 chunk->setAddresses(addrcounter-1, *localv4Addr);
00647 chunklen += 8;
00648 break;
00649 }
00650 case INIT_PARAM_IPV6:
00651 {
00652 sctpEV3<<"IPv6\n";
00653 const struct init_ipv6_address_parameter *ipv6addr;
00654 ipv6addr = (struct init_ipv6_address_parameter*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00655 IPv6Address ipv6Addr = IPv6Address(ipv6addr->address[0], ipv6addr->address[1],
00656 ipv6addr->address[2], ipv6addr->address[3]);
00657 IPvXAddress *localv6Addr;
00658 localv6Addr = new IPvXAddress("0:0:0:0:0:0:0:0");
00659 sctpEV3<<"address"<<ipv6Addr<<"\n";
00660 localv6Addr->set(ipv6Addr);
00661 chunk->setAddressesArraySize(++addrcounter);
00662 chunk->setAddresses(addrcounter-1, *localv6Addr);
00663 chunklen += 20;
00664 break;
00665 }
00666 default:
00667 {
00668 sctpEV3 << "ExtInterface: Unknown SCTP INIT parameter type " << paramType<<"\n";
00669 uint16 skip = (paramType & 0x8000) >> 15;
00670 if (skip == 0)
00671 stopProcessing = true;
00672 uint16 report = (paramType & 0x4000) >> 14;
00673 if (report != 0)
00674 {
00675 const struct tlv *unknown;
00676 unknown = (struct tlv*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00677 uint32 unknownLen=chunk->getUnrecognizedParametersArraySize();
00678 chunk->setUnrecognizedParametersArraySize(unknownLen+ADD_PADDING(ntohs(unknown->length)));
00679 struct data_vector* dv = (struct data_vector*) (((unsigned char*)init_chunk) + size_init_chunk + parptr);
00680
00681 for (uint32 i=unknownLen; i<unknownLen+ADD_PADDING(ntohs(unknown->length)); i++)
00682 chunk->setUnrecognizedParameters(i,dv->data[i-unknownLen]);
00683 }
00684 sctpEV3<<"stopProcessing="<<stopProcessing<<" report="<<report<<"\n";
00685 break;
00686 }
00687 }
00688 parptr += ADD_PADDING(ntohs(parameter->length));
00689 parcounter++;
00690 }
00691
00692
00693 }
00694 chunk->setBitLength(chunklen*8);
00695 dest->addChunk(chunk);
00696
00697 break;
00698 }
00699 case INIT_ACK:
00700 {
00701 const struct init_ack_chunk *iac = (struct init_ack_chunk*) (chunks + chunkPtr);
00702 chunklen = SCTP_INIT_CHUNK_LENGTH;
00703 SCTPInitAckChunk *chunk = new SCTPInitAckChunk("INIT_ACK");
00704 chunk->setChunkType(chunkType);
00705 chunk->setInitTag(ntohl(iac->initiate_tag));
00706 chunk->setA_rwnd(ntohl(iac->a_rwnd));
00707 chunk->setNoOutStreams(ntohs(iac->mos));
00708 chunk->setNoInStreams(ntohs(iac->mis));
00709 chunk->setInitTSN(ntohl(iac->initial_tsn));
00710 chunk->setUnrecognizedParametersArraySize(0);
00711 if(cLen > size_init_ack_chunk)
00712 {
00713 int32 parcounter = 0, addrcounter = 0;
00714 parptr = 0;
00715 bool stopProcessing = false;
00716
00717 while(cLen > size_init_ack_chunk+parptr && !stopProcessing)
00718 {
00719 const struct tlv *parameter = (struct tlv*)(((unsigned char*)iac) + size_init_ack_chunk + parptr);
00720 paramType = ntohs(parameter->type);
00721
00722 switch (paramType)
00723 {
00724 case SUPPORTED_ADDRESS_TYPES:
00725 {
00726 break;
00727 }
00728 case INIT_PARAM_IPV4:
00729 {
00730 sctpEV3<<"parse IPv4\n";
00731 const struct init_ipv4_address_parameter *v4addr;
00732 v4addr = (struct init_ipv4_address_parameter*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00733 chunk->setAddressesArraySize(++addrcounter);
00734 IPvXAddress *localv4Addr;
00735 localv4Addr = new IPvXAddress("0.0.0.0");
00736 localv4Addr->set(ntohl(v4addr->address));
00737 chunk->setAddresses(addrcounter-1, *localv4Addr);
00738 chunklen += 8;
00739 break;
00740 }
00741 case INIT_PARAM_IPV6:
00742 {
00743 sctpEV3<<"IPv6\n";
00744 const struct init_ipv6_address_parameter *ipv6addr;
00745 ipv6addr = (struct init_ipv6_address_parameter*) (((unsigned char*)iac) + size_init_chunk + parptr);
00746 IPv6Address ipv6Addr = IPv6Address(ipv6addr->address[0], ipv6addr->address[1],
00747 ipv6addr->address[2], ipv6addr->address[3]);
00748 IPvXAddress *localv6Addr;
00749 localv6Addr = new IPvXAddress("0:0:0:0:0:0:0:0");
00750 sctpEV3<<"address"<<ipv6Addr<<"\n";
00751 localv6Addr->set(ipv6Addr);
00752
00753 chunk->setAddressesArraySize(++addrcounter);
00754 chunk->setAddresses(addrcounter-1, *localv6Addr);
00755 chunklen += 20;
00756 break;
00757 }
00758 case INIT_PARAM_COOKIE:
00759 {
00760 const struct tlv *cookie = (struct tlv*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00761 int32 cookieLen = ntohs(cookie->length) - 4;
00762
00763 chunk->setCookieArraySize(cookieLen);
00764 for(int32 i=0; i<cookieLen; i++)
00765 chunk->setCookie(i, cookie->value[i]);
00766 chunklen+=cookieLen+4;
00767 break;
00768 }
00769 default:
00770 {
00771 sctpEV3 << "ExtInterface: Unknown SCTP INIT-ACK parameter type " << paramType<<"\n";
00772 uint16 skip = (paramType & 0x8000) >> 15;
00773 if (skip == 0)
00774 stopProcessing = true;
00775 uint16 report = (paramType & 0x4000) >> 14;
00776 if (report != 0)
00777 {
00778 const struct tlv *unknown;
00779 unknown = (struct tlv*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00780 uint32 unknownLen=chunk->getUnrecognizedParametersArraySize();
00781 chunk->setUnrecognizedParametersArraySize(unknownLen+ADD_PADDING(ntohs(unknown->length)));
00782 struct data_vector* dv = (struct data_vector*) (((unsigned char*)iac) + size_init_ack_chunk + parptr);
00783
00784 for (uint32 i=unknownLen; i<unknownLen+ADD_PADDING(ntohs(unknown->length)); i++)
00785 chunk->setUnrecognizedParameters(i,dv->data[i-unknownLen]);
00786 }
00787 sctpEV3<<"stopProcessing="<<stopProcessing<<" report="<<report<<"\n";
00788
00789 break;
00790 }
00791 }
00792 parptr += ADD_PADDING(ntohs(parameter->length));
00793
00794 parcounter++;
00795 }
00796 }
00797 chunk->setBitLength(chunklen*8);
00798 dest->addChunk(chunk);
00799 break;
00800 }
00801 case SACK:
00802 {
00803 ev<<"SCTPMessage: SACK received\n";
00804 const struct sack_chunk *sac = (struct sack_chunk*) (chunks + chunkPtr);
00805 SCTPSackChunk *chunk = new SCTPSackChunk("SACK");
00806 chunk->setChunkType(chunkType);
00807 uint32 cumtsnack = ntohl(sac->cum_tsn_ack);
00808 chunk->setCumTsnAck(cumtsnack);
00809 chunk->setA_rwnd(ntohl(sac->a_rwnd));
00810
00811 int32 ngaps = ntohs(sac->nr_of_gaps);
00812 int32 ndups = ntohs(sac->nr_of_dups);
00813 chunk->setNumGaps(ngaps);
00814 chunk->setNumDupTsns(ndups);
00815
00816 chunk->setGapStartArraySize(ngaps);
00817 chunk->setGapStopArraySize(ngaps);
00818 chunk->setDupTsnsArraySize(ndups);
00819
00820 for(int32 i=0; i<ngaps; i++)
00821 {
00822 const struct sack_gap *gap = (struct sack_gap*) (((unsigned char*)sac) + size_sack_chunk + i*sizeof(sack_gap));
00823 chunk->setGapStart(i, ntohs(gap->start) + cumtsnack);
00824 chunk->setGapStop(i, ntohs(gap->stop) + cumtsnack);
00825 }
00826 for(int32 i=0; i<ndups; i++)
00827 {
00828 const struct sack_duptsn *dup = (struct sack_duptsn*) (((unsigned char*)sac) + size_sack_chunk + ngaps*sizeof(sack_gap) + i*sizeof(sack_duptsn));
00829 chunk->setDupTsns(i, ntohl(dup->tsn));
00830 }
00831
00832 chunk->setBitLength(cLen*8);
00833 dest->addChunk(chunk);
00834 break;
00835 }
00836 case HEARTBEAT:
00837 {
00838
00839 const struct heartbeat_chunk *hbc = (struct heartbeat_chunk*) (chunks + chunkPtr);
00840 SCTPHeartbeatChunk *chunk = new SCTPHeartbeatChunk("HEARTBEAT");
00841 chunk->setChunkType(chunkType);
00842 if(cLen > size_heartbeat_chunk)
00843 {
00844 int32 parcounter = 0;
00845 parptr = 0;
00846 while(cLen > size_heartbeat_chunk+parptr)
00847 {
00848
00849
00850 const struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbc) + size_heartbeat_chunk + parptr);
00851 if(ntohs(hbi->type) == 1)
00852 {
00853
00854 int32 infoLen = ntohs(hbi->length) - 4;
00855 parptr += ADD_PADDING(infoLen) + 4;
00856 parcounter++;
00857 chunk->setInfoArraySize(infoLen);
00858 for(int32 i=0; i<infoLen; i++)
00859 chunk->setInfo(i, HBI_INFO(hbi)[i]);
00860 }
00861 else
00862 {
00863 parptr += ADD_PADDING(ntohs(hbi->length));
00864 parcounter++;
00865 continue;
00866 }
00867 }
00868 }
00869 chunk->setBitLength(cLen*8);
00870 dest->addChunk(chunk);
00871 break;
00872 }
00873 case HEARTBEAT_ACK:
00874 {
00875 ev<<"SCTPMessage: Heartbeat_Ack received\n";
00876 const struct heartbeat_ack_chunk *hbac = (struct heartbeat_ack_chunk*) (chunks + chunkPtr);
00877 SCTPHeartbeatAckChunk *chunk = new SCTPHeartbeatAckChunk("HEARTBEAT_ACK");
00878 chunk->setChunkType(chunkType);
00879 if(cLen>size_heartbeat_ack_chunk)
00880 {
00881 int32 parcounter = 0;
00882 parptr = 0;
00883 while(cLen > size_heartbeat_ack_chunk+parptr)
00884 {
00885
00886 const struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbac) + size_heartbeat_ack_chunk + parptr);
00887 if(ntohs(hbi->type) == 1)
00888 {
00889 parptr += sizeof(struct heartbeat_info);
00890 parcounter++;
00891 chunk->setRemoteAddr(IPvXAddress(ntohl(HBI_ADDR(hbi))));
00892 chunk->setTimeField(ntohl((uint32)HBI_TIME(hbi)));
00893 }
00894 else
00895 {
00896 parptr += ntohs(hbi->length);
00897 parcounter++;
00898 continue;
00899 }
00900
00901 }
00902 }
00903 chunk->setBitLength(cLen*8);
00904 dest->addChunk(chunk);
00905 break;
00906 }
00907 case ABORT:
00908 {
00909 ev<<"SCTPMessage: Abort received\n";
00910 const struct abort_chunk *ac = (struct abort_chunk*) (chunks + chunkPtr);
00911 cLen = ntohs(ac->length);
00912 SCTPAbortChunk *chunk = new SCTPAbortChunk("ABORT");
00913 chunk->setChunkType(chunkType);
00914 chunk->setT_Bit(ac->flags & T_BIT);
00915 if(cLen>size_abort_chunk)
00916 {
00917
00918 }
00919 chunk->setBitLength(cLen*8);
00920 dest->addChunk(chunk);
00921 break;
00922 }
00923 case COOKIE_ECHO:
00924 {
00925 SCTPCookieEchoChunk *chunk = new SCTPCookieEchoChunk("COOKIE_ECHO");
00926 chunk->setChunkType(chunkType);
00927 sctpEV3<<"Parse Cookie-Echo\n";
00928 if(cLen>size_cookie_echo_chunk)
00929 {
00930 int32 cookieSize = woPadding-size_cookie_echo_chunk;
00931 sctpEV3<<"cookieSize="<<cookieSize<<"\n";
00932 const struct cookie_parameter *cookie = (struct cookie_parameter*)(chunks+chunkPtr+4);
00933 SCTPCookie* stateCookie = new SCTPCookie();
00934 stateCookie->setCreationTime(ntohl(cookie->creationTime));
00935 stateCookie->setLocalTag(ntohl(cookie->localTag));
00936 stateCookie->setPeerTag(ntohl(cookie->peerTag));
00937 stateCookie->setLocalTieTagArraySize(32);
00938 stateCookie->setPeerTieTagArraySize(32);
00939 for(int32 i=0; i<32; i++)
00940 {
00941 stateCookie->setLocalTieTag(i, cookie->localTieTag[i]);
00942 stateCookie->setPeerTieTag(i, cookie->peerTieTag[i]);
00943 }
00944 stateCookie->setBitLength(SCTP_COOKIE_LENGTH*8);
00945 chunk->setStateCookie(stateCookie);
00946 }
00947 chunk->setBitLength(woPadding*8);
00948 dest->addChunk(chunk);
00949 break;
00950 }
00951 case COOKIE_ACK:
00952 {
00953 ev<<"SCTPMessage: Cookie_Ack received\n";
00954 SCTPCookieAckChunk *chunk = new SCTPCookieAckChunk("COOKIE_ACK");
00955 chunk->setChunkType(chunkType);
00956 chunk->setBitLength(cLen*8);
00957 dest->addChunk(chunk);
00958 break;
00959 }
00960 case SHUTDOWN:
00961 {
00962 ev<<"SCTPMessage: Shutdown received\n";
00963 const struct shutdown_chunk *sc = (struct shutdown_chunk*) (chunks + chunkPtr);
00964 SCTPShutdownChunk *chunk = new SCTPShutdownChunk("SHUTDOWN");
00965 chunk->setChunkType(chunkType);
00966 uint32 cumtsnack = ntohl(sc->cumulative_tsn_ack);
00967 chunk->setCumTsnAck(cumtsnack);
00968 chunk->setBitLength(cLen*8);
00969 dest->addChunk(chunk);
00970 break;
00971 }
00972 case SHUTDOWN_ACK:
00973 {
00974 ev<<"SCTPMessage: ShutdownAck received\n";
00975 SCTPShutdownAckChunk *chunk = new SCTPShutdownAckChunk("SHUTDOWN_ACK");
00976 chunk->setChunkType(chunkType);
00977 chunk->setBitLength(cLen*8);
00978 dest->addChunk(chunk);
00979 break;
00980 }
00981 case SHUTDOWN_COMPLETE:
00982 {
00983 ev<<"SCTPMessage: ShutdownComplete received\n";
00984 const struct shutdown_complete_chunk *scc = (struct shutdown_complete_chunk*) (chunks + chunkPtr);
00985 SCTPShutdownCompleteChunk *chunk = new SCTPShutdownCompleteChunk("SHUTDOWN_COMPLETE");
00986 chunk->setChunkType(chunkType);
00987 chunk->setTBit(scc->flags & T_BIT);
00988 chunk->setBitLength(cLen*8);
00989 dest->addChunk(chunk);
00990 break;
00991 }
00992 case ERRORTYPE:
00993 {
00994 const struct error_chunk *error;
00995 error = (struct error_chunk*) (chunks + chunkPtr);
00996 SCTPErrorChunk *errorchunk;
00997 errorchunk = new SCTPErrorChunk("ERROR");
00998 errorchunk->setChunkType(chunkType);
00999 errorchunk->setBitLength(SCTP_ERROR_CHUNK_LENGTH*8);
01000 parptr = 0;
01001 dest->addChunk(errorchunk);
01002 break;
01003 }
01004 default:
01005
01006 sctpEV3 << "Parser: Unknown SCTP chunk type " << chunkType;
01007
01008
01009
01010 break;
01011 }
01012 chunkPtr += cLen;
01013 }
01014 }
01015
01016
01017