|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005 Christian Dankbar, Irene Ruengeler, Michael Tuexen, Andras Varga 00003 // Copyright (C) 2010 Thomas Dreibholz 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 #include <platdep/sockets.h> 00020 #include "headers/defs.h" 00021 namespace INETFw // load headers into a namespace, to avoid conflicts with platform definitions of the same stuff 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 //#include "platdep/intxtypes.h" 00033 00034 #if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(_WIN64) 00035 #include <netinet/in.h> // htonl, ntohl, ... 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 // fill SCTP common header structure 00060 ch->source_port = htons(msg->getSrcPort()); 00061 ch->destination_port = htons(msg->getDestPort()); 00062 ch->verification_tag = htonl(msg->getTag()); 00063 00064 00065 // SCTP chunks: 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Data sent \n"; 00076 SCTPDataChunk *dataChunk = check_and_cast<SCTPDataChunk *>(chunk); 00077 struct data_chunk *dc = (struct data_chunk*) (buf + writtenbytes); // append data to buffer 00078 unsigned char flags = 0; 00079 00080 // fill buffer with data from SCTP data chunk structure 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->getEncapsulatedPacket()); 00097 // T.D. 09.02.2010: Only copy data when there is something to copy! 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 //sctpEV3<<"serialize INIT sizeKeyVector="<<sizeKeyVector<<"\n"; 00110 // source data from internal struct: 00111 SCTPInitChunk *initChunk = check_and_cast<SCTPInitChunk *>(chunk); 00112 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Init sent \n"; 00113 // destination is send buffer: 00114 struct init_chunk *ic = (struct init_chunk*) (buf + writtenbytes); // append data to buffer 00115 //buflen += (initChunk->getBitLength() / 8); 00116 00117 // fill buffer with data from SCTP init chunk structure 00118 ic->type = initChunk->getChunkType(); 00119 ic->flags = 0; // no flags available in this type of SCTPChunk 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 // Var.-Len. Parameters 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 //sctpEV3<<"serialize INIT_ACK sizeKeyVector="<<sizeKeyVector<<"\n"; 00148 SCTPInitAckChunk *initAckChunk = check_and_cast<SCTPInitAckChunk *>(chunk); 00149 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: InitAck sent \n"; 00150 // destination is send buffer: 00151 struct init_ack_chunk *iac = (struct init_ack_chunk*) (buf + writtenbytes); // append data to buffer 00152 // fill buffer with data from SCTP init ack chunk structure 00153 iac->type = initAckChunk->getChunkType(); 00154 // iac->flags = initAckChunk->getFlags(); // no flags available in this type of SCTPChunk 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 // Var.-Len. Parameters 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 //sctpEV3<<"uLen="<<uLen<<"\n"; 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 //sctpEV3<<"unknown->length="<<pLen<<"\n"; 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 /*if(cookielen == 0) 00200 { 00201 cookielen = 4; 00202 initAckChunk->setCookieArraySize(cookielen); 00203 initAckChunk->setCookie(0, '1'); 00204 initAckChunk->setCookie(1, '3'); 00205 initAckChunk->setCookie(2, '3'); 00206 initAckChunk->setCookie(3, '7'); 00207 iac->length = htons(ntohs(iac->length) + 8); 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 // destination is send buffer: 00244 struct sack_chunk *sac = (struct sack_chunk*) (buf + writtenbytes); // append data to buffer 00245 writtenbytes += (sackChunk->getBitLength() / 8); 00246 00247 // fill buffer with data from SCTP init ack chunk structure 00248 sac->type = sackChunk->getChunkType(); 00249 // sac->flags = sackChunk->getFlags(); // no flags available in this type of SCTPChunk 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 // GAPs and Dup. TSNs: 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Heartbeat sent \n"; 00276 SCTPHeartbeatChunk *heartbeatChunk = check_and_cast<SCTPHeartbeatChunk *>(chunk); 00277 00278 // destination is send buffer: 00279 struct heartbeat_chunk *hbc = (struct heartbeat_chunk*) (buf + writtenbytes); // append data to buffer 00280 writtenbytes += (heartbeatChunk->getBitLength() / 8); 00281 00282 // fill buffer with data from SCTP init ack chunk structure 00283 hbc->type = heartbeatChunk->getChunkType(); 00284 // hbc->flags = heartbeatChunk->getFlags(); // no flags available in this type of SCTPChunk 00285 hbc->length = htons(heartbeatChunk->getBitLength() / 8); 00286 00287 // deliver info: 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); // mandatory 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: HeartbeatAck sent \n"; 00301 SCTPHeartbeatAckChunk *heartbeatAckChunk = check_and_cast<SCTPHeartbeatAckChunk *>(chunk); 00302 00303 // destination is send buffer: 00304 struct heartbeat_ack_chunk *hbac = (struct heartbeat_ack_chunk*) (buf + writtenbytes); // append data to buffer 00305 writtenbytes += (heartbeatAckChunk->getBitLength() / 8); 00306 00307 // fill buffer with data from SCTP init ack chunk structure 00308 hbac->type = heartbeatAckChunk->getChunkType(); 00309 // hbac->flags = heartbeatAckChunk->getFlags(); // no flags available in this type of SCTPChunk 00310 hbac->length = htons(heartbeatAckChunk->getBitLength() / 8); 00311 00312 // deliver info: 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); //mandatory 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); // mandatory 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: Abort sent \n"; 00340 SCTPAbortChunk *abortChunk = check_and_cast<SCTPAbortChunk *>(chunk); 00341 00342 // destination is send buffer: 00343 struct abort_chunk *ac = (struct abort_chunk*) (buf + writtenbytes); // append data to buffer 00344 writtenbytes += (abortChunk->getBitLength() / 8); 00345 00346 // fill buffer with data from SCTP init ack chunk structure 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: CookieEcho sent \n"; 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 //sctpEV3<<"buflen cookie_echo="<<buflen<<"\n"; 00386 uint32 uLen = cookieChunk->getUnrecognizedParametersArraySize(); 00387 if (uLen>0) 00388 { 00389 //sctpEV3<<"uLen="<<uLen<<"\n"; 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 //sctpEV3<<"plength="<<pLen<<" ecLen="<<ecLen<<"\n"; 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 //sctpEV3<<"ecParPtr="<<ecParPtr<<"\n"; 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: CookieAck sent \n"; 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: ShutdownAck sent \n"; 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: ShutdownAck sent \n"; 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 //sctpEV3<<simulation.simTime()<<" SCTPAssociation:: ShutdownAck sent \n"; 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 // break; 00492 00493 } 00494 00495 /*drop(chunk); 00496 delete chunk;*/ 00497 00498 } 00499 // finally, set the CRC32 checksum field in the SCTP common header 00500 00501 /*sctpEV3<<"srcport="<<msg->getSrcPort() <<"destport="<<msg->getDestPort() <<"writtenbytes vor checksum="<<writtenbytes<<"\n";*/ 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 // chunks 00556 uint32 chunkPtr = 0; 00557 00558 // catch ALL chunks - when a chunk is taken, the chunkPtr is set to the next chunk 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); // (recvBuffer + size_ip + size_common_header); 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 //sctpEV3<<"INIT arrived from wire\n"; 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 // we supppose an ipv4 address parameter 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 //chunkPtr += cLen; 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 //sctpEV3<<"cLen="<<cLen<<"\n"; 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 //sctpEV3<<"ParamType = "<<paramType<<" parameterLength="<<ntohs(parameter->length)<<"\n"; 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 // put cookie data into chunk (char array cookie) 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 //sctpEV3<<"parptr="<<parptr<<"\n"; 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 //sctpEV3<<"SCTPMessage: Heartbeat received\n"; 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 // we supppose type 1 here 00849 //sctpEV3<<"HB-chunk+parptr="<<size_heartbeat_chunk+parptr<<"\n"; 00850 const struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbc) + size_heartbeat_chunk + parptr); 00851 if(ntohs(hbi->type) == 1) // sender specific hb info 00852 { 00853 //sctpEV3<<"HBInfo\n"; 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)); // set pointer forwards with count of bytes in length field of TLV 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 // we supppose type 1 here, the same provided in heartbeat chunks 00886 const struct heartbeat_info *hbi = (struct heartbeat_info*) (((unsigned char*)hbac) + size_heartbeat_ack_chunk + parptr); 00887 if(ntohs(hbi->type) == 1) // sender specific hb info 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); // set pointer forwards with count of bytes in length field of TLV 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 // TODO: handle attached error causes 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 //printf("TODO: Implement chunk type %d, found in chunk array on %d!\n", chunkType, ct); 01006 sctpEV3 << "Parser: Unknown SCTP chunk type " << chunkType; 01007 01008 /*throw new cRuntimeError("TODO: unknown chunktype in incoming packet from external interface! Implement it!");*/ 01009 01010 break; 01011 } // end of switch(chunkType) 01012 chunkPtr += cLen; 01013 } // end of while() 01014 } 01015 01016 01017