1 // Copyright 2012 Google, Inc. All rights reserved.
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
15 "github.com/google/gopacket"
18 // SCTP contains information on the top level of an SCTP packet.
21 SrcPort, DstPort SCTPPort
22 VerificationTag uint32
27 // LayerType returns gopacket.LayerTypeSCTP
28 func (s *SCTP) LayerType() gopacket.LayerType { return LayerTypeSCTP }
30 func decodeSCTP(data []byte, p gopacket.PacketBuilder) error {
32 err := sctp.DecodeFromBytes(data, p)
34 p.SetTransportLayer(sctp)
38 return p.NextDecoder(sctpChunkTypePrefixDecoder)
41 var sctpChunkTypePrefixDecoder = gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix)
43 // TransportFlow returns a flow based on the source and destination SCTP port.
44 func (s *SCTP) TransportFlow() gopacket.Flow {
45 return gopacket.NewFlow(EndpointSCTPPort, s.sPort, s.dPort)
48 func decodeWithSCTPChunkTypePrefix(data []byte, p gopacket.PacketBuilder) error {
49 chunkType := SCTPChunkType(data[0])
50 return chunkType.Decode(data, p)
53 // SerializeTo is for gopacket.SerializableLayer.
54 func (s SCTP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
55 bytes, err := b.PrependBytes(12)
59 binary.BigEndian.PutUint16(bytes[0:2], uint16(s.SrcPort))
60 binary.BigEndian.PutUint16(bytes[2:4], uint16(s.DstPort))
61 binary.BigEndian.PutUint32(bytes[4:8], s.VerificationTag)
62 if opts.ComputeChecksums {
63 // Note: MakeTable(Castagnoli) actually only creates the table once, then
64 // passes back a singleton on every other call, so this shouldn't cause
65 // excessive memory allocation.
66 binary.LittleEndian.PutUint32(bytes[8:12], crc32.Checksum(b.Bytes(), crc32.MakeTable(crc32.Castagnoli)))
71 func (sctp *SCTP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
73 return errors.New("Invalid SCTP common header length")
75 sctp.SrcPort = SCTPPort(binary.BigEndian.Uint16(data[:2]))
77 sctp.DstPort = SCTPPort(binary.BigEndian.Uint16(data[2:4]))
78 sctp.dPort = data[2:4]
79 sctp.VerificationTag = binary.BigEndian.Uint32(data[4:8])
80 sctp.Checksum = binary.BigEndian.Uint32(data[8:12])
81 sctp.BaseLayer = BaseLayer{data[:12], data[12:]}
86 func (t *SCTP) CanDecode() gopacket.LayerClass {
90 func (t *SCTP) NextLayerType() gopacket.LayerType {
91 return gopacket.LayerTypePayload
94 // SCTPChunk contains the common fields in all SCTP chunks.
95 type SCTPChunk struct {
100 // ActualLength is the total length of an SCTP chunk, including padding.
101 // SCTP chunks start and end on 4-byte boundaries. So if a chunk has a length
102 // of 18, it means that it has data up to and including byte 18, then padding
103 // up to the next 4-byte boundary, 20. In this case, Length would be 18, and
104 // ActualLength would be 20.
108 func roundUpToNearest4(i int) int {
112 return i + 4 - (i % 4)
115 func decodeSCTPChunk(data []byte) (SCTPChunk, error) {
116 length := binary.BigEndian.Uint16(data[2:4])
118 return SCTPChunk{}, errors.New("invalid SCTP chunk length")
120 actual := roundUpToNearest4(int(length))
121 ct := SCTPChunkType(data[0])
123 // For SCTP Data, use a separate layer for the payload
125 if ct == SCTPChunkTypeData {
126 delta = int(actual) - int(length)
134 ActualLength: actual,
135 BaseLayer: BaseLayer{data[:actual], data[actual : len(data)-delta]},
139 // SCTPParameter is a TLV parameter inside a SCTPChunk.
140 type SCTPParameter struct {
147 func decodeSCTPParameter(data []byte) SCTPParameter {
148 length := binary.BigEndian.Uint16(data[2:4])
149 return SCTPParameter{
150 Type: binary.BigEndian.Uint16(data[0:2]),
152 Value: data[4:length],
153 ActualLength: roundUpToNearest4(int(length)),
157 func (p SCTPParameter) Bytes() []byte {
158 length := 4 + len(p.Value)
159 data := make([]byte, roundUpToNearest4(length))
160 binary.BigEndian.PutUint16(data[0:2], p.Type)
161 binary.BigEndian.PutUint16(data[2:4], uint16(length))
162 copy(data[4:], p.Value)
166 // SCTPUnknownChunkType is the layer type returned when we don't recognize the
167 // chunk type. Since there's a length in a known location, we can skip over
168 // it even if we don't know what it is, and continue parsing the rest of the
169 // chunks. This chunk is stored as an ErrorLayer in the packet.
170 type SCTPUnknownChunkType struct {
175 func decodeSCTPChunkTypeUnknown(data []byte, p gopacket.PacketBuilder) error {
176 chunk, err := decodeSCTPChunk(data)
180 sc := &SCTPUnknownChunkType{SCTPChunk: chunk}
181 sc.bytes = data[:sc.ActualLength]
184 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
187 // SerializeTo is for gopacket.SerializableLayer.
188 func (s SCTPUnknownChunkType) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
189 bytes, err := b.PrependBytes(s.ActualLength)
197 // LayerType returns gopacket.LayerTypeSCTPUnknownChunkType.
198 func (s *SCTPUnknownChunkType) LayerType() gopacket.LayerType { return LayerTypeSCTPUnknownChunkType }
200 // Payload returns all bytes in this header, including the decoded Type, Length,
202 func (s *SCTPUnknownChunkType) Payload() []byte { return s.bytes }
204 // Error implements ErrorLayer.
205 func (s *SCTPUnknownChunkType) Error() error {
206 return fmt.Errorf("No decode method available for SCTP chunk type %s", s.Type)
209 // SCTPData is the SCTP Data chunk layer.
210 type SCTPData struct {
212 Unordered, BeginFragment, EndFragment bool
215 StreamSequence uint16
216 PayloadProtocol SCTPPayloadProtocol
219 // LayerType returns gopacket.LayerTypeSCTPData.
220 func (s *SCTPData) LayerType() gopacket.LayerType { return LayerTypeSCTPData }
222 // SCTPPayloadProtocol represents a payload protocol
223 type SCTPPayloadProtocol uint32
225 // SCTPPayloadProtocol constonts from http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml
227 SCTPProtocolReserved SCTPPayloadProtocol = 0
242 SCTPPayloadSIMCO = 15
243 SCTPPayloadDDPSegment = 16
244 SCTPPayloadDDPStream = 17
248 func (p SCTPPayloadProtocol) String() string {
250 case SCTPProtocolReserved:
254 case SCTPPayloadM2UA:
256 case SCTPPayloadM3UA:
260 case SCTPPayloadM2PA:
262 case SCTPPayloadV5UA:
264 case SCTPPayloadH248:
266 case SCTPPayloadBICC:
268 case SCTPPayloadTALI:
272 case SCTPPayloadASAP:
274 case SCTPPayloadENRP:
276 case SCTPPayloadH323:
278 case SCTPPayloadQIPC:
280 case SCTPPayloadSIMCO:
282 case SCTPPayloadDDPSegment:
284 case SCTPPayloadDDPStream:
286 case SCTPPayloadS1AP:
289 return fmt.Sprintf("Unknown(%d)", p)
292 func decodeSCTPData(data []byte, p gopacket.PacketBuilder) error {
293 chunk, err := decodeSCTPChunk(data)
299 Unordered: data[1]&0x4 != 0,
300 BeginFragment: data[1]&0x2 != 0,
301 EndFragment: data[1]&0x1 != 0,
302 TSN: binary.BigEndian.Uint32(data[4:8]),
303 StreamId: binary.BigEndian.Uint16(data[8:10]),
304 StreamSequence: binary.BigEndian.Uint16(data[10:12]),
305 PayloadProtocol: SCTPPayloadProtocol(binary.BigEndian.Uint32(data[12:16])),
307 // Length is the length in bytes of the data, INCLUDING the 16-byte header.
309 return p.NextDecoder(gopacket.LayerTypePayload)
312 // SerializeTo is for gopacket.SerializableLayer.
313 func (sc SCTPData) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
315 // Pad the payload to a 32 bit boundary
316 if rem := len(payload) % 4; rem != 0 {
317 b.AppendBytes(4 - rem)
320 bytes, err := b.PrependBytes(length)
324 bytes[0] = uint8(sc.Type)
329 if sc.BeginFragment {
336 binary.BigEndian.PutUint16(bytes[2:4], uint16(length+len(payload)))
337 binary.BigEndian.PutUint32(bytes[4:8], sc.TSN)
338 binary.BigEndian.PutUint16(bytes[8:10], sc.StreamId)
339 binary.BigEndian.PutUint16(bytes[10:12], sc.StreamSequence)
340 binary.BigEndian.PutUint32(bytes[12:16], uint32(sc.PayloadProtocol))
344 // SCTPInitParameter is a parameter for an SCTP Init or InitAck packet.
345 type SCTPInitParameter SCTPParameter
347 // SCTPInit is used as the return value for both SCTPInit and SCTPInitAck
349 type SCTPInit struct {
352 AdvertisedReceiverWindowCredit uint32
353 OutboundStreams, InboundStreams uint16
355 Parameters []SCTPInitParameter
358 // LayerType returns either gopacket.LayerTypeSCTPInit or gopacket.LayerTypeSCTPInitAck.
359 func (sc *SCTPInit) LayerType() gopacket.LayerType {
360 if sc.Type == SCTPChunkTypeInitAck {
361 return LayerTypeSCTPInitAck
363 // sc.Type == SCTPChunkTypeInit
364 return LayerTypeSCTPInit
367 func decodeSCTPInit(data []byte, p gopacket.PacketBuilder) error {
368 chunk, err := decodeSCTPChunk(data)
374 InitiateTag: binary.BigEndian.Uint32(data[4:8]),
375 AdvertisedReceiverWindowCredit: binary.BigEndian.Uint32(data[8:12]),
376 OutboundStreams: binary.BigEndian.Uint16(data[12:14]),
377 InboundStreams: binary.BigEndian.Uint16(data[14:16]),
378 InitialTSN: binary.BigEndian.Uint32(data[16:20]),
380 paramData := data[20:sc.ActualLength]
381 for len(paramData) > 0 {
382 p := SCTPInitParameter(decodeSCTPParameter(paramData))
383 paramData = paramData[p.ActualLength:]
384 sc.Parameters = append(sc.Parameters, p)
387 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
390 // SerializeTo is for gopacket.SerializableLayer.
391 func (sc SCTPInit) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
393 for _, param := range sc.Parameters {
394 payload = append(payload, SCTPParameter(param).Bytes()...)
396 length := 20 + len(payload)
397 bytes, err := b.PrependBytes(roundUpToNearest4(length))
401 bytes[0] = uint8(sc.Type)
403 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
404 binary.BigEndian.PutUint32(bytes[4:8], sc.InitiateTag)
405 binary.BigEndian.PutUint32(bytes[8:12], sc.AdvertisedReceiverWindowCredit)
406 binary.BigEndian.PutUint16(bytes[12:14], sc.OutboundStreams)
407 binary.BigEndian.PutUint16(bytes[14:16], sc.InboundStreams)
408 binary.BigEndian.PutUint32(bytes[16:20], sc.InitialTSN)
409 copy(bytes[20:], payload)
413 // SCTPSack is the SCTP Selective ACK chunk layer.
414 type SCTPSack struct {
416 CumulativeTSNAck uint32
417 AdvertisedReceiverWindowCredit uint32
418 NumGapACKs, NumDuplicateTSNs uint16
420 DuplicateTSNs []uint32
423 // LayerType return LayerTypeSCTPSack
424 func (sc *SCTPSack) LayerType() gopacket.LayerType {
425 return LayerTypeSCTPSack
428 func decodeSCTPSack(data []byte, p gopacket.PacketBuilder) error {
429 chunk, err := decodeSCTPChunk(data)
435 CumulativeTSNAck: binary.BigEndian.Uint32(data[4:8]),
436 AdvertisedReceiverWindowCredit: binary.BigEndian.Uint32(data[8:12]),
437 NumGapACKs: binary.BigEndian.Uint16(data[12:14]),
438 NumDuplicateTSNs: binary.BigEndian.Uint16(data[14:16]),
440 // We maximize gapAcks and dupTSNs here so we're not allocating tons
441 // of memory based on a user-controlable field. Our maximums are not exact,
442 // but should give us sane defaults... we'll still hit slice boundaries and
443 // fail if the user-supplied values are too high (in the for loops below), but
444 // the amount of memory we'll have allocated because of that should be small
445 // (< sc.ActualLength)
446 gapAcks := sc.SCTPChunk.ActualLength / 2
447 dupTSNs := (sc.SCTPChunk.ActualLength - gapAcks*2) / 4
448 if gapAcks > int(sc.NumGapACKs) {
449 gapAcks = int(sc.NumGapACKs)
451 if dupTSNs > int(sc.NumDuplicateTSNs) {
452 dupTSNs = int(sc.NumDuplicateTSNs)
454 sc.GapACKs = make([]uint16, 0, gapAcks)
455 sc.DuplicateTSNs = make([]uint32, 0, dupTSNs)
456 bytesRemaining := data[16:]
457 for i := 0; i < int(sc.NumGapACKs); i++ {
458 sc.GapACKs = append(sc.GapACKs, binary.BigEndian.Uint16(bytesRemaining[:2]))
459 bytesRemaining = bytesRemaining[2:]
461 for i := 0; i < int(sc.NumDuplicateTSNs); i++ {
462 sc.DuplicateTSNs = append(sc.DuplicateTSNs, binary.BigEndian.Uint32(bytesRemaining[:4]))
463 bytesRemaining = bytesRemaining[4:]
466 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
469 // SerializeTo is for gopacket.SerializableLayer.
470 func (sc SCTPSack) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
471 length := 16 + 2*len(sc.GapACKs) + 4*len(sc.DuplicateTSNs)
472 bytes, err := b.PrependBytes(roundUpToNearest4(length))
476 bytes[0] = uint8(sc.Type)
478 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
479 binary.BigEndian.PutUint32(bytes[4:8], sc.CumulativeTSNAck)
480 binary.BigEndian.PutUint32(bytes[8:12], sc.AdvertisedReceiverWindowCredit)
481 binary.BigEndian.PutUint16(bytes[12:14], uint16(len(sc.GapACKs)))
482 binary.BigEndian.PutUint16(bytes[14:16], uint16(len(sc.DuplicateTSNs)))
483 for i, v := range sc.GapACKs {
484 binary.BigEndian.PutUint16(bytes[16+i*2:], v)
486 offset := 16 + 2*len(sc.GapACKs)
487 for i, v := range sc.DuplicateTSNs {
488 binary.BigEndian.PutUint32(bytes[offset+i*4:], v)
493 // SCTPHeartbeatParameter is the parameter type used by SCTP heartbeat and
494 // heartbeat ack layers.
495 type SCTPHeartbeatParameter SCTPParameter
497 // SCTPHeartbeat is the SCTP heartbeat layer, also used for heatbeat ack.
498 type SCTPHeartbeat struct {
500 Parameters []SCTPHeartbeatParameter
503 // LayerType returns gopacket.LayerTypeSCTPHeartbeat.
504 func (sc *SCTPHeartbeat) LayerType() gopacket.LayerType {
505 if sc.Type == SCTPChunkTypeHeartbeatAck {
506 return LayerTypeSCTPHeartbeatAck
508 // sc.Type == SCTPChunkTypeHeartbeat
509 return LayerTypeSCTPHeartbeat
512 func decodeSCTPHeartbeat(data []byte, p gopacket.PacketBuilder) error {
513 chunk, err := decodeSCTPChunk(data)
517 sc := &SCTPHeartbeat{
520 paramData := data[4:sc.Length]
521 for len(paramData) > 0 {
522 p := SCTPHeartbeatParameter(decodeSCTPParameter(paramData))
523 paramData = paramData[p.ActualLength:]
524 sc.Parameters = append(sc.Parameters, p)
527 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
530 // SerializeTo is for gopacket.SerializableLayer.
531 func (sc SCTPHeartbeat) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
533 for _, param := range sc.Parameters {
534 payload = append(payload, SCTPParameter(param).Bytes()...)
536 length := 4 + len(payload)
538 bytes, err := b.PrependBytes(roundUpToNearest4(length))
542 bytes[0] = uint8(sc.Type)
544 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
545 copy(bytes[4:], payload)
549 // SCTPErrorParameter is the parameter type used by SCTP Abort and Error layers.
550 type SCTPErrorParameter SCTPParameter
552 // SCTPError is the SCTP error layer, also used for SCTP aborts.
553 type SCTPError struct {
555 Parameters []SCTPErrorParameter
558 // LayerType returns LayerTypeSCTPAbort or LayerTypeSCTPError.
559 func (sc *SCTPError) LayerType() gopacket.LayerType {
560 if sc.Type == SCTPChunkTypeAbort {
561 return LayerTypeSCTPAbort
563 // sc.Type == SCTPChunkTypeError
564 return LayerTypeSCTPError
567 func decodeSCTPError(data []byte, p gopacket.PacketBuilder) error {
568 // remarkably similar to decodeSCTPHeartbeat ;)
569 chunk, err := decodeSCTPChunk(data)
576 paramData := data[4:sc.Length]
577 for len(paramData) > 0 {
578 p := SCTPErrorParameter(decodeSCTPParameter(paramData))
579 paramData = paramData[p.ActualLength:]
580 sc.Parameters = append(sc.Parameters, p)
583 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
586 // SerializeTo is for gopacket.SerializableLayer.
587 func (sc SCTPError) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
589 for _, param := range sc.Parameters {
590 payload = append(payload, SCTPParameter(param).Bytes()...)
592 length := 4 + len(payload)
594 bytes, err := b.PrependBytes(roundUpToNearest4(length))
598 bytes[0] = uint8(sc.Type)
600 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
601 copy(bytes[4:], payload)
605 // SCTPShutdown is the SCTP shutdown layer.
606 type SCTPShutdown struct {
608 CumulativeTSNAck uint32
611 // LayerType returns gopacket.LayerTypeSCTPShutdown.
612 func (sc *SCTPShutdown) LayerType() gopacket.LayerType { return LayerTypeSCTPShutdown }
614 func decodeSCTPShutdown(data []byte, p gopacket.PacketBuilder) error {
615 chunk, err := decodeSCTPChunk(data)
621 CumulativeTSNAck: binary.BigEndian.Uint32(data[4:8]),
624 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
627 // SerializeTo is for gopacket.SerializableLayer.
628 func (sc SCTPShutdown) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
629 bytes, err := b.PrependBytes(8)
633 bytes[0] = uint8(sc.Type)
635 binary.BigEndian.PutUint16(bytes[2:4], 8)
636 binary.BigEndian.PutUint32(bytes[4:8], sc.CumulativeTSNAck)
640 // SCTPShutdownAck is the SCTP shutdown layer.
641 type SCTPShutdownAck struct {
645 // LayerType returns gopacket.LayerTypeSCTPShutdownAck.
646 func (sc *SCTPShutdownAck) LayerType() gopacket.LayerType { return LayerTypeSCTPShutdownAck }
648 func decodeSCTPShutdownAck(data []byte, p gopacket.PacketBuilder) error {
649 chunk, err := decodeSCTPChunk(data)
653 sc := &SCTPShutdownAck{
657 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
660 // SerializeTo is for gopacket.SerializableLayer.
661 func (sc SCTPShutdownAck) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
662 bytes, err := b.PrependBytes(4)
666 bytes[0] = uint8(sc.Type)
668 binary.BigEndian.PutUint16(bytes[2:4], 4)
672 // SCTPCookieEcho is the SCTP Cookie Echo layer.
673 type SCTPCookieEcho struct {
678 // LayerType returns gopacket.LayerTypeSCTPCookieEcho.
679 func (sc *SCTPCookieEcho) LayerType() gopacket.LayerType { return LayerTypeSCTPCookieEcho }
681 func decodeSCTPCookieEcho(data []byte, p gopacket.PacketBuilder) error {
682 chunk, err := decodeSCTPChunk(data)
686 sc := &SCTPCookieEcho{
689 sc.Cookie = data[4:sc.Length]
691 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
694 // SerializeTo is for gopacket.SerializableLayer.
695 func (sc SCTPCookieEcho) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
696 length := 4 + len(sc.Cookie)
697 bytes, err := b.PrependBytes(roundUpToNearest4(length))
701 bytes[0] = uint8(sc.Type)
703 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
704 copy(bytes[4:], sc.Cookie)
708 // This struct is used by all empty SCTP chunks (currently CookieAck and
709 // ShutdownComplete).
710 type SCTPEmptyLayer struct {
714 // LayerType returns either gopacket.LayerTypeSCTPShutdownComplete or
715 // LayerTypeSCTPCookieAck.
716 func (sc *SCTPEmptyLayer) LayerType() gopacket.LayerType {
717 if sc.Type == SCTPChunkTypeShutdownComplete {
718 return LayerTypeSCTPShutdownComplete
720 // sc.Type == SCTPChunkTypeCookieAck
721 return LayerTypeSCTPCookieAck
724 func decodeSCTPEmptyLayer(data []byte, p gopacket.PacketBuilder) error {
725 chunk, err := decodeSCTPChunk(data)
729 sc := &SCTPEmptyLayer{
733 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
736 // SerializeTo is for gopacket.SerializableLayer.
737 func (sc SCTPEmptyLayer) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
738 bytes, err := b.PrependBytes(4)
742 bytes[0] = uint8(sc.Type)
744 binary.BigEndian.PutUint16(bytes[2:4], 4)