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