Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layers / sctp.go
1 // 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
7 package layers
8
9 import (
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.
19 type 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
28 func (s *SCTP) LayerType() gopacket.LayerType { return LayerTypeSCTP }
29
30 func 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
41 var sctpChunkTypePrefixDecoder = gopacket.DecodeFunc(decodeWithSCTPChunkTypePrefix)
42
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)
46 }
47
48 func 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.
54 func (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
71 func (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
86 func (t *SCTP) CanDecode() gopacket.LayerClass {
87         return LayerTypeSCTP
88 }
89
90 func (t *SCTP) NextLayerType() gopacket.LayerType {
91         return gopacket.LayerTypePayload
92 }
93
94 // SCTPChunk contains the common fields in all SCTP chunks.
95 type 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
108 func roundUpToNearest4(i int) int {
109         if i%4 == 0 {
110                 return i
111         }
112         return i + 4 - (i % 4)
113 }
114
115 func 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.
140 type SCTPParameter struct {
141         Type         uint16
142         Length       uint16
143         ActualLength int
144         Value        []byte
145 }
146
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]),
151                 Length:       length,
152                 Value:        data[4:length],
153                 ActualLength: roundUpToNearest4(int(length)),
154         }
155 }
156
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)
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.
170 type SCTPUnknownChunkType struct {
171         SCTPChunk
172         bytes []byte
173 }
174
175 func 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.
188 func (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.
198 func (s *SCTPUnknownChunkType) LayerType() gopacket.LayerType { return LayerTypeSCTPUnknownChunkType }
199
200 // Payload returns all bytes in this header, including the decoded Type, Length,
201 // and Flags.
202 func (s *SCTPUnknownChunkType) Payload() []byte { return s.bytes }
203
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)
207 }
208
209 // SCTPData is the SCTP Data chunk layer.
210 type 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.
220 func (s *SCTPData) LayerType() gopacket.LayerType { return LayerTypeSCTPData }
221
222 // SCTPPayloadProtocol represents a payload protocol
223 type SCTPPayloadProtocol uint32
224
225 // SCTPPayloadProtocol constonts from http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml
226 const (
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
248 func (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
292 func 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.
313 func (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.
345 type SCTPInitParameter SCTPParameter
346
347 // SCTPInit is used as the return value for both SCTPInit and SCTPInitAck
348 // messages.
349 type 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.
359 func (sc *SCTPInit) LayerType() gopacket.LayerType {
360         if sc.Type == SCTPChunkTypeInitAck {
361                 return LayerTypeSCTPInitAck
362         }
363         // sc.Type == SCTPChunkTypeInit
364         return LayerTypeSCTPInit
365 }
366
367 func 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.
391 func (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.
414 type 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
424 func (sc *SCTPSack) LayerType() gopacket.LayerType {
425         return LayerTypeSCTPSack
426 }
427
428 func 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.
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))
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.
495 type SCTPHeartbeatParameter SCTPParameter
496
497 // SCTPHeartbeat is the SCTP heartbeat layer, also used for heatbeat ack.
498 type SCTPHeartbeat struct {
499         SCTPChunk
500         Parameters []SCTPHeartbeatParameter
501 }
502
503 // LayerType returns gopacket.LayerTypeSCTPHeartbeat.
504 func (sc *SCTPHeartbeat) LayerType() gopacket.LayerType {
505         if sc.Type == SCTPChunkTypeHeartbeatAck {
506                 return LayerTypeSCTPHeartbeatAck
507         }
508         // sc.Type == SCTPChunkTypeHeartbeat
509         return LayerTypeSCTPHeartbeat
510 }
511
512 func 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.
531 func (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.
550 type SCTPErrorParameter SCTPParameter
551
552 // SCTPError is the SCTP error layer, also used for SCTP aborts.
553 type SCTPError struct {
554         SCTPChunk
555         Parameters []SCTPErrorParameter
556 }
557
558 // LayerType returns LayerTypeSCTPAbort or LayerTypeSCTPError.
559 func (sc *SCTPError) LayerType() gopacket.LayerType {
560         if sc.Type == SCTPChunkTypeAbort {
561                 return LayerTypeSCTPAbort
562         }
563         // sc.Type == SCTPChunkTypeError
564         return LayerTypeSCTPError
565 }
566
567 func 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.
587 func (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.
606 type SCTPShutdown struct {
607         SCTPChunk
608         CumulativeTSNAck uint32
609 }
610
611 // LayerType returns gopacket.LayerTypeSCTPShutdown.
612 func (sc *SCTPShutdown) LayerType() gopacket.LayerType { return LayerTypeSCTPShutdown }
613
614 func 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.
628 func (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.
641 type SCTPShutdownAck struct {
642         SCTPChunk
643 }
644
645 // LayerType returns gopacket.LayerTypeSCTPShutdownAck.
646 func (sc *SCTPShutdownAck) LayerType() gopacket.LayerType { return LayerTypeSCTPShutdownAck }
647
648 func 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.
661 func (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.
673 type SCTPCookieEcho struct {
674         SCTPChunk
675         Cookie []byte
676 }
677
678 // LayerType returns gopacket.LayerTypeSCTPCookieEcho.
679 func (sc *SCTPCookieEcho) LayerType() gopacket.LayerType { return LayerTypeSCTPCookieEcho }
680
681 func 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.
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))
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).
710 type SCTPEmptyLayer struct {
711         SCTPChunk
712 }
713
714 // LayerType returns either gopacket.LayerTypeSCTPShutdownComplete or
715 // LayerTypeSCTPCookieAck.
716 func (sc *SCTPEmptyLayer) LayerType() gopacket.LayerType {
717         if sc.Type == SCTPChunkTypeShutdownComplete {
718                 return LayerTypeSCTPShutdownComplete
719         }
720         // sc.Type == SCTPChunkTypeCookieAck
721         return LayerTypeSCTPCookieAck
722 }
723
724 func 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.
737 func (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 }