blob: 511176e560fd107cbc3be90a94589f862da54979 [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +00001// Copyright 2012 Google, Inc. All rights reserved.
2//
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
5// tree.
6
7package layers
8
9import (
10 "encoding/binary"
11 "errors"
12 "fmt"
13 "hash/crc32"
14
15 "github.com/google/gopacket"
16)
17
18// SCTP contains information on the top level of an SCTP packet.
19type SCTP struct {
20 BaseLayer
21 SrcPort, DstPort SCTPPort
22 VerificationTag uint32
23 Checksum uint32
24 sPort, dPort []byte
25}
26
27// LayerType returns gopacket.LayerTypeSCTP
28func (s *SCTP) LayerType() gopacket.LayerType { return LayerTypeSCTP }
29
30func decodeSCTP(data []byte, p gopacket.PacketBuilder) error {
31 sctp := &SCTP{}
32 err := sctp.DecodeFromBytes(data, p)
33 p.AddLayer(sctp)
34 p.SetTransportLayer(sctp)
35 if err != nil {
36 return err
37 }
38 return p.NextDecoder(sctpChunkTypePrefixDecoder)
39}
40
41var sctpChunkTypePrefixDecoder = gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix)
42
43// TransportFlow returns a flow based on the source and destination SCTP port.
44func (s *SCTP) TransportFlow() gopacket.Flow {
45 return gopacket.NewFlow(EndpointSCTPPort, s.sPort, s.dPort)
46}
47
48func decodeWithSCTPChunkTypePrefix(data []byte, p gopacket.PacketBuilder) error {
49 chunkType := SCTPChunkType(data[0])
50 return chunkType.Decode(data, p)
51}
52
53// SerializeTo is for gopacket.SerializableLayer.
54func (s SCTP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
55 bytes, err := b.PrependBytes(12)
56 if err != nil {
57 return err
58 }
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)))
67 }
68 return nil
69}
70
71func (sctp *SCTP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
72 if len(data) < 12 {
73 return errors.New("Invalid SCTP common header length")
74 }
75 sctp.SrcPort = SCTPPort(binary.BigEndian.Uint16(data[:2]))
76 sctp.sPort = 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:]}
82
83 return nil
84}
85
86func (t *SCTP) CanDecode() gopacket.LayerClass {
87 return LayerTypeSCTP
88}
89
90func (t *SCTP) NextLayerType() gopacket.LayerType {
91 return gopacket.LayerTypePayload
92}
93
94// SCTPChunk contains the common fields in all SCTP chunks.
95type SCTPChunk struct {
96 BaseLayer
97 Type SCTPChunkType
98 Flags uint8
99 Length uint16
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.
105 ActualLength int
106}
107
108func roundUpToNearest4(i int) int {
109 if i%4 == 0 {
110 return i
111 }
112 return i + 4 - (i % 4)
113}
114
115func decodeSCTPChunk(data []byte) (SCTPChunk, error) {
116 length := binary.BigEndian.Uint16(data[2:4])
117 if length < 4 {
118 return SCTPChunk{}, errors.New("invalid SCTP chunk length")
119 }
120 actual := roundUpToNearest4(int(length))
121 ct := SCTPChunkType(data[0])
122
123 // For SCTP Data, use a separate layer for the payload
124 delta := 0
125 if ct == SCTPChunkTypeData {
126 delta = int(actual) - int(length)
127 actual = 16
128 }
129
130 return SCTPChunk{
131 Type: ct,
132 Flags: data[1],
133 Length: length,
134 ActualLength: actual,
135 BaseLayer: BaseLayer{data[:actual], data[actual : len(data)-delta]},
136 }, nil
137}
138
139// SCTPParameter is a TLV parameter inside a SCTPChunk.
140type SCTPParameter struct {
141 Type uint16
142 Length uint16
143 ActualLength int
144 Value []byte
145}
146
147func decodeSCTPParameter(data []byte) SCTPParameter {
148 length := binary.BigEndian.Uint16(data[2:4])
149 return SCTPParameter{
150 Type: binary.BigEndian.Uint16(data[0:2]),
151 Length: length,
152 Value: data[4:length],
153 ActualLength: roundUpToNearest4(int(length)),
154 }
155}
156
157func (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)
163 return data
164}
165
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.
170type SCTPUnknownChunkType struct {
171 SCTPChunk
172 bytes []byte
173}
174
175func decodeSCTPChunkTypeUnknown(data []byte, p gopacket.PacketBuilder) error {
176 chunk, err := decodeSCTPChunk(data)
177 if err != nil {
178 return err
179 }
180 sc := &SCTPUnknownChunkType{SCTPChunk: chunk}
181 sc.bytes = data[:sc.ActualLength]
182 p.AddLayer(sc)
183 p.SetErrorLayer(sc)
184 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
185}
186
187// SerializeTo is for gopacket.SerializableLayer.
188func (s SCTPUnknownChunkType) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
189 bytes, err := b.PrependBytes(s.ActualLength)
190 if err != nil {
191 return err
192 }
193 copy(bytes, s.bytes)
194 return nil
195}
196
197// LayerType returns gopacket.LayerTypeSCTPUnknownChunkType.
198func (s *SCTPUnknownChunkType) LayerType() gopacket.LayerType { return LayerTypeSCTPUnknownChunkType }
199
200// Payload returns all bytes in this header, including the decoded Type, Length,
201// and Flags.
202func (s *SCTPUnknownChunkType) Payload() []byte { return s.bytes }
203
204// Error implements ErrorLayer.
205func (s *SCTPUnknownChunkType) Error() error {
206 return fmt.Errorf("No decode method available for SCTP chunk type %s", s.Type)
207}
208
209// SCTPData is the SCTP Data chunk layer.
210type SCTPData struct {
211 SCTPChunk
212 Unordered, BeginFragment, EndFragment bool
213 TSN uint32
214 StreamId uint16
215 StreamSequence uint16
216 PayloadProtocol SCTPPayloadProtocol
217}
218
219// LayerType returns gopacket.LayerTypeSCTPData.
220func (s *SCTPData) LayerType() gopacket.LayerType { return LayerTypeSCTPData }
221
222// SCTPPayloadProtocol represents a payload protocol
223type SCTPPayloadProtocol uint32
224
225// SCTPPayloadProtocol constonts from http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml
226const (
227 SCTPProtocolReserved SCTPPayloadProtocol = 0
228 SCTPPayloadUIA = 1
229 SCTPPayloadM2UA = 2
230 SCTPPayloadM3UA = 3
231 SCTPPayloadSUA = 4
232 SCTPPayloadM2PA = 5
233 SCTPPayloadV5UA = 6
234 SCTPPayloadH248 = 7
235 SCTPPayloadBICC = 8
236 SCTPPayloadTALI = 9
237 SCTPPayloadDUA = 10
238 SCTPPayloadASAP = 11
239 SCTPPayloadENRP = 12
240 SCTPPayloadH323 = 13
241 SCTPPayloadQIPC = 14
242 SCTPPayloadSIMCO = 15
243 SCTPPayloadDDPSegment = 16
244 SCTPPayloadDDPStream = 17
245 SCTPPayloadS1AP = 18
246)
247
248func (p SCTPPayloadProtocol) String() string {
249 switch p {
250 case SCTPProtocolReserved:
251 return "Reserved"
252 case SCTPPayloadUIA:
253 return "UIA"
254 case SCTPPayloadM2UA:
255 return "M2UA"
256 case SCTPPayloadM3UA:
257 return "M3UA"
258 case SCTPPayloadSUA:
259 return "SUA"
260 case SCTPPayloadM2PA:
261 return "M2PA"
262 case SCTPPayloadV5UA:
263 return "V5UA"
264 case SCTPPayloadH248:
265 return "H.248"
266 case SCTPPayloadBICC:
267 return "BICC"
268 case SCTPPayloadTALI:
269 return "TALI"
270 case SCTPPayloadDUA:
271 return "DUA"
272 case SCTPPayloadASAP:
273 return "ASAP"
274 case SCTPPayloadENRP:
275 return "ENRP"
276 case SCTPPayloadH323:
277 return "H.323"
278 case SCTPPayloadQIPC:
279 return "QIPC"
280 case SCTPPayloadSIMCO:
281 return "SIMCO"
282 case SCTPPayloadDDPSegment:
283 return "DDPSegment"
284 case SCTPPayloadDDPStream:
285 return "DDPStream"
286 case SCTPPayloadS1AP:
287 return "S1AP"
288 }
289 return fmt.Sprintf("Unknown(%d)", p)
290}
291
292func decodeSCTPData(data []byte, p gopacket.PacketBuilder) error {
293 chunk, err := decodeSCTPChunk(data)
294 if err != nil {
295 return err
296 }
297 sc := &SCTPData{
298 SCTPChunk: chunk,
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])),
306 }
307 // Length is the length in bytes of the data, INCLUDING the 16-byte header.
308 p.AddLayer(sc)
309 return p.NextDecoder(gopacket.LayerTypePayload)
310}
311
312// SerializeTo is for gopacket.SerializableLayer.
313func (sc SCTPData) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
314 payload := b.Bytes()
315 // Pad the payload to a 32 bit boundary
316 if rem := len(payload) % 4; rem != 0 {
317 b.AppendBytes(4 - rem)
318 }
319 length := 16
320 bytes, err := b.PrependBytes(length)
321 if err != nil {
322 return err
323 }
324 bytes[0] = uint8(sc.Type)
325 flags := uint8(0)
326 if sc.Unordered {
327 flags |= 0x4
328 }
329 if sc.BeginFragment {
330 flags |= 0x2
331 }
332 if sc.EndFragment {
333 flags |= 0x1
334 }
335 bytes[1] = flags
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))
341 return nil
342}
343
344// SCTPInitParameter is a parameter for an SCTP Init or InitAck packet.
345type SCTPInitParameter SCTPParameter
346
347// SCTPInit is used as the return value for both SCTPInit and SCTPInitAck
348// messages.
349type SCTPInit struct {
350 SCTPChunk
351 InitiateTag uint32
352 AdvertisedReceiverWindowCredit uint32
353 OutboundStreams, InboundStreams uint16
354 InitialTSN uint32
355 Parameters []SCTPInitParameter
356}
357
358// LayerType returns either gopacket.LayerTypeSCTPInit or gopacket.LayerTypeSCTPInitAck.
359func (sc *SCTPInit) LayerType() gopacket.LayerType {
360 if sc.Type == SCTPChunkTypeInitAck {
361 return LayerTypeSCTPInitAck
362 }
363 // sc.Type == SCTPChunkTypeInit
364 return LayerTypeSCTPInit
365}
366
367func decodeSCTPInit(data []byte, p gopacket.PacketBuilder) error {
368 chunk, err := decodeSCTPChunk(data)
369 if err != nil {
370 return err
371 }
372 sc := &SCTPInit{
373 SCTPChunk: chunk,
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]),
379 }
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)
385 }
386 p.AddLayer(sc)
387 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
388}
389
390// SerializeTo is for gopacket.SerializableLayer.
391func (sc SCTPInit) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
392 var payload []byte
393 for _, param := range sc.Parameters {
394 payload = append(payload, SCTPParameter(param).Bytes()...)
395 }
396 length := 20 + len(payload)
397 bytes, err := b.PrependBytes(roundUpToNearest4(length))
398 if err != nil {
399 return err
400 }
401 bytes[0] = uint8(sc.Type)
402 bytes[1] = sc.Flags
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)
410 return nil
411}
412
413// SCTPSack is the SCTP Selective ACK chunk layer.
414type SCTPSack struct {
415 SCTPChunk
416 CumulativeTSNAck uint32
417 AdvertisedReceiverWindowCredit uint32
418 NumGapACKs, NumDuplicateTSNs uint16
419 GapACKs []uint16
420 DuplicateTSNs []uint32
421}
422
423// LayerType return LayerTypeSCTPSack
424func (sc *SCTPSack) LayerType() gopacket.LayerType {
425 return LayerTypeSCTPSack
426}
427
428func decodeSCTPSack(data []byte, p gopacket.PacketBuilder) error {
429 chunk, err := decodeSCTPChunk(data)
430 if err != nil {
431 return err
432 }
433 sc := &SCTPSack{
434 SCTPChunk: chunk,
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]),
439 }
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)
450 }
451 if dupTSNs > int(sc.NumDuplicateTSNs) {
452 dupTSNs = int(sc.NumDuplicateTSNs)
453 }
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:]
460 }
461 for i := 0; i < int(sc.NumDuplicateTSNs); i++ {
462 sc.DuplicateTSNs = append(sc.DuplicateTSNs, binary.BigEndian.Uint32(bytesRemaining[:4]))
463 bytesRemaining = bytesRemaining[4:]
464 }
465 p.AddLayer(sc)
466 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
467}
468
469// SerializeTo is for gopacket.SerializableLayer.
470func (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))
473 if err != nil {
474 return err
475 }
476 bytes[0] = uint8(sc.Type)
477 bytes[1] = sc.Flags
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)
485 }
486 offset := 16 + 2*len(sc.GapACKs)
487 for i, v := range sc.DuplicateTSNs {
488 binary.BigEndian.PutUint32(bytes[offset+i*4:], v)
489 }
490 return nil
491}
492
493// SCTPHeartbeatParameter is the parameter type used by SCTP heartbeat and
494// heartbeat ack layers.
495type SCTPHeartbeatParameter SCTPParameter
496
497// SCTPHeartbeat is the SCTP heartbeat layer, also used for heatbeat ack.
498type SCTPHeartbeat struct {
499 SCTPChunk
500 Parameters []SCTPHeartbeatParameter
501}
502
503// LayerType returns gopacket.LayerTypeSCTPHeartbeat.
504func (sc *SCTPHeartbeat) LayerType() gopacket.LayerType {
505 if sc.Type == SCTPChunkTypeHeartbeatAck {
506 return LayerTypeSCTPHeartbeatAck
507 }
508 // sc.Type == SCTPChunkTypeHeartbeat
509 return LayerTypeSCTPHeartbeat
510}
511
512func decodeSCTPHeartbeat(data []byte, p gopacket.PacketBuilder) error {
513 chunk, err := decodeSCTPChunk(data)
514 if err != nil {
515 return err
516 }
517 sc := &SCTPHeartbeat{
518 SCTPChunk: chunk,
519 }
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)
525 }
526 p.AddLayer(sc)
527 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
528}
529
530// SerializeTo is for gopacket.SerializableLayer.
531func (sc SCTPHeartbeat) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
532 var payload []byte
533 for _, param := range sc.Parameters {
534 payload = append(payload, SCTPParameter(param).Bytes()...)
535 }
536 length := 4 + len(payload)
537
538 bytes, err := b.PrependBytes(roundUpToNearest4(length))
539 if err != nil {
540 return err
541 }
542 bytes[0] = uint8(sc.Type)
543 bytes[1] = sc.Flags
544 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
545 copy(bytes[4:], payload)
546 return nil
547}
548
549// SCTPErrorParameter is the parameter type used by SCTP Abort and Error layers.
550type SCTPErrorParameter SCTPParameter
551
552// SCTPError is the SCTP error layer, also used for SCTP aborts.
553type SCTPError struct {
554 SCTPChunk
555 Parameters []SCTPErrorParameter
556}
557
558// LayerType returns LayerTypeSCTPAbort or LayerTypeSCTPError.
559func (sc *SCTPError) LayerType() gopacket.LayerType {
560 if sc.Type == SCTPChunkTypeAbort {
561 return LayerTypeSCTPAbort
562 }
563 // sc.Type == SCTPChunkTypeError
564 return LayerTypeSCTPError
565}
566
567func decodeSCTPError(data []byte, p gopacket.PacketBuilder) error {
568 // remarkably similar to decodeSCTPHeartbeat ;)
569 chunk, err := decodeSCTPChunk(data)
570 if err != nil {
571 return err
572 }
573 sc := &SCTPError{
574 SCTPChunk: chunk,
575 }
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)
581 }
582 p.AddLayer(sc)
583 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
584}
585
586// SerializeTo is for gopacket.SerializableLayer.
587func (sc SCTPError) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
588 var payload []byte
589 for _, param := range sc.Parameters {
590 payload = append(payload, SCTPParameter(param).Bytes()...)
591 }
592 length := 4 + len(payload)
593
594 bytes, err := b.PrependBytes(roundUpToNearest4(length))
595 if err != nil {
596 return err
597 }
598 bytes[0] = uint8(sc.Type)
599 bytes[1] = sc.Flags
600 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
601 copy(bytes[4:], payload)
602 return nil
603}
604
605// SCTPShutdown is the SCTP shutdown layer.
606type SCTPShutdown struct {
607 SCTPChunk
608 CumulativeTSNAck uint32
609}
610
611// LayerType returns gopacket.LayerTypeSCTPShutdown.
612func (sc *SCTPShutdown) LayerType() gopacket.LayerType { return LayerTypeSCTPShutdown }
613
614func decodeSCTPShutdown(data []byte, p gopacket.PacketBuilder) error {
615 chunk, err := decodeSCTPChunk(data)
616 if err != nil {
617 return err
618 }
619 sc := &SCTPShutdown{
620 SCTPChunk: chunk,
621 CumulativeTSNAck: binary.BigEndian.Uint32(data[4:8]),
622 }
623 p.AddLayer(sc)
624 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
625}
626
627// SerializeTo is for gopacket.SerializableLayer.
628func (sc SCTPShutdown) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
629 bytes, err := b.PrependBytes(8)
630 if err != nil {
631 return err
632 }
633 bytes[0] = uint8(sc.Type)
634 bytes[1] = sc.Flags
635 binary.BigEndian.PutUint16(bytes[2:4], 8)
636 binary.BigEndian.PutUint32(bytes[4:8], sc.CumulativeTSNAck)
637 return nil
638}
639
640// SCTPShutdownAck is the SCTP shutdown layer.
641type SCTPShutdownAck struct {
642 SCTPChunk
643}
644
645// LayerType returns gopacket.LayerTypeSCTPShutdownAck.
646func (sc *SCTPShutdownAck) LayerType() gopacket.LayerType { return LayerTypeSCTPShutdownAck }
647
648func decodeSCTPShutdownAck(data []byte, p gopacket.PacketBuilder) error {
649 chunk, err := decodeSCTPChunk(data)
650 if err != nil {
651 return err
652 }
653 sc := &SCTPShutdownAck{
654 SCTPChunk: chunk,
655 }
656 p.AddLayer(sc)
657 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
658}
659
660// SerializeTo is for gopacket.SerializableLayer.
661func (sc SCTPShutdownAck) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
662 bytes, err := b.PrependBytes(4)
663 if err != nil {
664 return err
665 }
666 bytes[0] = uint8(sc.Type)
667 bytes[1] = sc.Flags
668 binary.BigEndian.PutUint16(bytes[2:4], 4)
669 return nil
670}
671
672// SCTPCookieEcho is the SCTP Cookie Echo layer.
673type SCTPCookieEcho struct {
674 SCTPChunk
675 Cookie []byte
676}
677
678// LayerType returns gopacket.LayerTypeSCTPCookieEcho.
679func (sc *SCTPCookieEcho) LayerType() gopacket.LayerType { return LayerTypeSCTPCookieEcho }
680
681func decodeSCTPCookieEcho(data []byte, p gopacket.PacketBuilder) error {
682 chunk, err := decodeSCTPChunk(data)
683 if err != nil {
684 return err
685 }
686 sc := &SCTPCookieEcho{
687 SCTPChunk: chunk,
688 }
689 sc.Cookie = data[4:sc.Length]
690 p.AddLayer(sc)
691 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
692}
693
694// SerializeTo is for gopacket.SerializableLayer.
695func (sc SCTPCookieEcho) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
696 length := 4 + len(sc.Cookie)
697 bytes, err := b.PrependBytes(roundUpToNearest4(length))
698 if err != nil {
699 return err
700 }
701 bytes[0] = uint8(sc.Type)
702 bytes[1] = sc.Flags
703 binary.BigEndian.PutUint16(bytes[2:4], uint16(length))
704 copy(bytes[4:], sc.Cookie)
705 return nil
706}
707
708// This struct is used by all empty SCTP chunks (currently CookieAck and
709// ShutdownComplete).
710type SCTPEmptyLayer struct {
711 SCTPChunk
712}
713
714// LayerType returns either gopacket.LayerTypeSCTPShutdownComplete or
715// LayerTypeSCTPCookieAck.
716func (sc *SCTPEmptyLayer) LayerType() gopacket.LayerType {
717 if sc.Type == SCTPChunkTypeShutdownComplete {
718 return LayerTypeSCTPShutdownComplete
719 }
720 // sc.Type == SCTPChunkTypeCookieAck
721 return LayerTypeSCTPCookieAck
722}
723
724func decodeSCTPEmptyLayer(data []byte, p gopacket.PacketBuilder) error {
725 chunk, err := decodeSCTPChunk(data)
726 if err != nil {
727 return err
728 }
729 sc := &SCTPEmptyLayer{
730 SCTPChunk: chunk,
731 }
732 p.AddLayer(sc)
733 return p.NextDecoder(gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix))
734}
735
736// SerializeTo is for gopacket.SerializableLayer.
737func (sc SCTPEmptyLayer) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
738 bytes, err := b.PrependBytes(4)
739 if err != nil {
740 return err
741 }
742 bytes[0] = uint8(sc.Type)
743 bytes[1] = sc.Flags
744 binary.BigEndian.PutUint16(bytes[2:4], 4)
745 return nil
746}