chunk_init_ack.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package sctp // nolint:dupl
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. /*
  7. chunkInitAck represents an SCTP Chunk of type INIT ACK
  8. See chunkInitCommon for the fixed headers
  9. Variable Parameters Status Type Value
  10. -------------------------------------------------------------
  11. State Cookie Mandatory 7
  12. IPv4 IP (Note 1) Optional 5
  13. IPv6 IP (Note 1) Optional 6
  14. Unrecognized Parameter Optional 8
  15. Reserved for ECN Capable (Note 2) Optional 32768 (0x8000)
  16. Host Name IP (Note 3) Optional 11<Paste>
  17. */
  18. type chunkInitAck struct {
  19. chunkHeader
  20. chunkInitCommon
  21. }
  22. var (
  23. errChunkTypeNotInitAck = errors.New("ChunkType is not of type INIT ACK")
  24. errChunkNotLongEnoughForParams = errors.New("chunk Value isn't long enough for mandatory parameters exp")
  25. errChunkTypeInitAckFlagZero = errors.New("ChunkType of type INIT ACK flags must be all 0")
  26. errInitAckUnmarshalFailed = errors.New("failed to unmarshal INIT body")
  27. errInitCommonDataMarshalFailed = errors.New("failed marshaling INIT common data")
  28. errChunkTypeInitAckInitateTagZero = errors.New("ChunkType of type INIT ACK InitiateTag must not be 0")
  29. errInitAckInboundStreamRequestZero = errors.New("INIT ACK inbound stream request must be > 0")
  30. errInitAckOutboundStreamRequestZero = errors.New("INIT ACK outbound stream request must be > 0")
  31. errInitAckAdvertisedReceiver1500 = errors.New("INIT ACK Advertised Receiver Window Credit (a_rwnd) must be >= 1500")
  32. )
  33. func (i *chunkInitAck) unmarshal(raw []byte) error {
  34. if err := i.chunkHeader.unmarshal(raw); err != nil {
  35. return err
  36. }
  37. if i.typ != ctInitAck {
  38. return fmt.Errorf("%w: actually is %s", errChunkTypeNotInitAck, i.typ.String())
  39. } else if len(i.raw) < initChunkMinLength {
  40. return fmt.Errorf("%w: %d actual: %d", errChunkNotLongEnoughForParams, initChunkMinLength, len(i.raw))
  41. }
  42. // The Chunk Flags field in INIT is reserved, and all bits in it should
  43. // be set to 0 by the sender and ignored by the receiver. The sequence
  44. // of parameters within an INIT can be processed in any order.
  45. if i.flags != 0 {
  46. return errChunkTypeInitAckFlagZero
  47. }
  48. if err := i.chunkInitCommon.unmarshal(i.raw); err != nil {
  49. return fmt.Errorf("%w: %v", errInitAckUnmarshalFailed, err)
  50. }
  51. return nil
  52. }
  53. func (i *chunkInitAck) marshal() ([]byte, error) {
  54. initShared, err := i.chunkInitCommon.marshal()
  55. if err != nil {
  56. return nil, fmt.Errorf("%w: %v", errInitCommonDataMarshalFailed, err)
  57. }
  58. i.chunkHeader.typ = ctInitAck
  59. i.chunkHeader.raw = initShared
  60. return i.chunkHeader.marshal()
  61. }
  62. func (i *chunkInitAck) check() (abort bool, err error) {
  63. // The receiver of the INIT ACK records the value of the Initiate Tag
  64. // parameter. This value MUST be placed into the Verification Tag
  65. // field of every SCTP packet that the INIT ACK receiver transmits
  66. // within this association.
  67. //
  68. // The Initiate Tag MUST NOT take the value 0. See Section 5.3.1 for
  69. // more on the selection of the Initiate Tag value.
  70. //
  71. // If the value of the Initiate Tag in a received INIT ACK chunk is
  72. // found to be 0, the receiver MUST destroy the association
  73. // discarding its TCB. The receiver MAY send an ABORT for debugging
  74. // purpose.
  75. if i.initiateTag == 0 {
  76. abort = true
  77. return abort, errChunkTypeInitAckInitateTagZero
  78. }
  79. // Defines the maximum number of streams the sender of this INIT ACK
  80. // chunk allows the peer end to create in this association. The
  81. // value 0 MUST NOT be used.
  82. //
  83. // Note: There is no negotiation of the actual number of streams but
  84. // instead the two endpoints will use the min(requested, offered).
  85. // See Section 5.1.1 for details.
  86. //
  87. // Note: A receiver of an INIT ACK with the MIS value set to 0 SHOULD
  88. // destroy the association discarding its TCB.
  89. if i.numInboundStreams == 0 {
  90. abort = true
  91. return abort, errInitAckInboundStreamRequestZero
  92. }
  93. // Defines the number of outbound streams the sender of this INIT ACK
  94. // chunk wishes to create in this association. The value of 0 MUST
  95. // NOT be used, and the value MUST NOT be greater than the MIS value
  96. // sent in the INIT chunk.
  97. //
  98. // Note: A receiver of an INIT ACK with the OS value set to 0 SHOULD
  99. // destroy the association discarding its TCB.
  100. if i.numOutboundStreams == 0 {
  101. abort = true
  102. return abort, errInitAckOutboundStreamRequestZero
  103. }
  104. // An SCTP receiver MUST be able to receive a minimum of 1500 bytes in
  105. // one SCTP packet. This means that an SCTP endpoint MUST NOT indicate
  106. // less than 1500 bytes in its initial a_rwnd sent in the INIT or INIT
  107. // ACK.
  108. if i.advertisedReceiverWindowCredit < 1500 {
  109. abort = true
  110. return abort, errInitAckAdvertisedReceiver1500
  111. }
  112. return false, nil
  113. }
  114. // String makes chunkInitAck printable
  115. func (i *chunkInitAck) String() string {
  116. return fmt.Sprintf("%s\n%s", i.chunkHeader, i.chunkInitCommon)
  117. }