/** * <code> * 2) Authenticate the State Cookie as one that it previously generated * by comparing the computed MAC against the one carried in the * State Cookie. If this comparison fails, the SCTP packet, * including the COOKIE ECHO and any DATA chunks, should be silently * discarded, * * 3) Compare the port numbers and the Verification Tag contained * within the COOKIE ECHO chunk to the actual port numbers and the * Verification Tag within the SCTP common header of the received * packet. If these values do not match, the packet MUST be * silently discarded. * * 4) Compare the creation timestamp in the State Cookie to the current * local time. If the elapsed time is longer than the lifespan * carried in the State Cookie, then the packet, including the * COOKIE ECHO and any attached DATA chunks, SHOULD be discarded, * and the endpoint MUST transmit an ERROR chunk with a "Stale * Cookie" error cause to the peer endpoint. * * 5) If the State Cookie is valid, create an association to the sender * of the COOKIE ECHO chunk with the information in the TCB data * carried in the COOKIE ECHO and enter the ESTABLISHED state. * * 6) Send a COOKIE ACK chunk to the peer acknowledging receipt of the * COOKIE ECHO. The COOKIE ACK MAY be bundled with an outbound DATA * chunk or SACK chunk; however, the COOKIE ACK MUST be the first * chunk in the SCTP packet. * * 7) Immediately acknowledge any DATA chunk bundled with the COOKIE * ECHO with a SACK (subsequent DATA chunk acknowledgement should * follow the rules defined in Section 6.2). As mentioned in step * 6, if the SACK is bundled with the COOKIE ACK, the COOKIE ACK * MUST appear first in the SCTP packet. * </code> */ private Chunk[] cookieEchoDeal(CookieEchoChunk echo) { Chunk[] reply = new Chunk[0]; if (_state == State.CLOSED || _state == State.COOKIEWAIT || _state == State.COOKIEECHOED) { // Authenticate the State Cookie CookieHolder cookie; if (null != (cookie = checkCookieEcho(echo.getCookieData()))) { // Compare the creation timestamp in the State Cookie to the current local time. uint howStale = howStaleIsMyCookie(cookie); if (howStale == 0) { //enter the ESTABLISHED state _state = State.ESTABLISHED; /* * Send a COOKIE ACK chunk to the peer acknowledging receipt of the * COOKIE ECHO. The COOKIE ACK MAY be bundled with an outbound DATA * chunk or SACK chunk; however, the COOKIE ACK MUST be the first * chunk in the SCTP packet. */ reply = new Chunk[1]; reply[0] = new CookieAckChunk(); } else { reply = new Chunk[1]; /* If the elapsed time is longer than the lifespan * carried in the State Cookie, then the packet, including the * COOKIE ECHO and any attached DATA chunks, SHOULD be discarded, * and the endpoint MUST transmit an ERROR chunk with a "Stale * Cookie" error cause to the peer endpoint.*/ StaleCookieError sce = new StaleCookieError(); sce.setMeasure(howStale * 1000); ErrorChunk ec = new ErrorChunk(sce); reply[0] = ec; } } else { Logger.Error("Got a COOKIE_ECHO that doesn't match any we sent. ?!?"); } } else { Logger.Debug("Got an COOKIE_ECHO when not closed - ignoring it"); } return(reply); }
protected VariableParam readErrorParam() { int type = _body.GetUShort(); int len = _body.GetUShort(); int blen = len - 4; byte[] data; KnownError var = null; switch (type) { case 1: var = new KnownError(1, "InvalidStreamIdentifier"); break; //[RFC4960] case 2: var = new KnownError(2, "MissingMandatoryParameter"); break; //[RFC4960] case 3: var = new StaleCookieError(); break; //[RFC4960] case 4: var = new KnownError(4, "OutofResource"); break; //[RFC4960] case 5: var = new KnownError(5, "UnresolvableAddress"); break; //[RFC4960] case 6: var = new KnownError(6, "UnrecognizedChunkType"); break; //[RFC4960] case 7: var = new KnownError(7, "InvalidMandatoryParameter"); break; //[RFC4960] case 8: var = new KnownError(8, "UnrecognizedParameters"); break; //[RFC4960] case 9: var = new KnownError(9, "NoUserData"); break; //[RFC4960] case 10: var = new KnownError(10, "CookieReceivedWhileShuttingDown"); break; //[RFC4960] case 11: var = new KnownError(11, "RestartofanAssociationwithNewAddresses"); break; //[RFC4960] case 12: var = new KnownError(12, "UserInitiatedAbort"); break; //[RFC4460] case 13: var = new ProtocolViolationError(13, "ProtocolViolation"); break; //[RFC4460] // 14-159,Unassigned, case 160: var = new KnownError(160, "RequesttoDeleteLastRemainingIPAddress"); break; //[RFC5061] case 161: var = new KnownError(161, "OperationRefusedDuetoResourceShortage"); break; //[RFC5061] case 162: var = new KnownError(162, "RequesttoDeleteSourceIPAddress"); break; //[RFC5061] case 163: var = new KnownError(163, "AssociationAbortedduetoillegalASCONF-ACK"); break; //[RFC5061] case 164: var = new KnownError(164, "Requestrefused-noauthorization"); break; //[RFC5061] // 165-260,Unassigned, case 261: var = new KnownError(261, "UnsupportedHMACIdentifier"); break; //[RFC4895] // 262-65535,Unassigned, } try { var.readBody(_body, blen); Logger.Trace("variable type " + var.getType() + " name " + var.getName()); Logger.Trace("additional info " + var.ToString()); } catch (SctpPacketFormatException ex) { Logger.Error(ex.ToString()); } if (_body.hasRemaining()) { int mod = blen % 4; if (mod != 0) { for (int pad = mod; pad < 4; pad++) { _body.GetByte(); } } } return(var); }