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
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}
747