DecodeFromBytes analyses a byte slice and attempts to decode it as a BFD control packet. Upon succeeds, it loads the BFD object with information about the packet and returns nil. Upon failure, it returns an error (non nil).
(data []byte, df gopacket.DecodeFeedback)
| 327 | // and returns nil. |
| 328 | // Upon failure, it returns an error (non nil). |
| 329 | func (d *BFD) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { |
| 330 | |
| 331 | // If the data block is too short to be a BFD record, then return an error. |
| 332 | if len(data) < bfdMinimumRecordSizeInBytes { |
| 333 | df.SetTruncated() |
| 334 | return errors.New("BFD packet too short") |
| 335 | } |
| 336 | |
| 337 | pLen := uint8(data[3]) |
| 338 | if len(data) != int(pLen) { |
| 339 | return errors.New("BFD packet length does not match") |
| 340 | } |
| 341 | |
| 342 | // BFD type embeds type BaseLayer which contains two fields: |
| 343 | // Contents is supposed to contain the bytes of the data at this level. |
| 344 | // Payload is supposed to contain the payload of this level. |
| 345 | // Here we set the baselayer to be the bytes of the BFD record. |
| 346 | d.BaseLayer = BaseLayer{Contents: data[:len(data)]} |
| 347 | |
| 348 | // Extract the fields from the block of bytes. |
| 349 | // To make sense of this, refer to the packet diagram |
| 350 | // above and the section on endian conventions. |
| 351 | |
| 352 | // The first few fields are all packed into the first 32 bits. Unpack them. |
| 353 | d.Version = BFDVersion(((data[0] & 0xE0) >> 5)) |
| 354 | d.Diagnostic = BFDDiagnostic(data[0] & 0x1F) |
| 355 | data = data[1:] |
| 356 | |
| 357 | d.State = BFDState((data[0] & 0xC0) >> 6) |
| 358 | d.Poll = data[0]&0x20 != 0 |
| 359 | d.Final = data[0]&0x10 != 0 |
| 360 | d.ControlPlaneIndependent = data[0]&0x08 != 0 |
| 361 | d.AuthPresent = data[0]&0x04 != 0 |
| 362 | d.Demand = data[0]&0x02 != 0 |
| 363 | d.Multipoint = data[0]&0x01 != 0 |
| 364 | data = data[1:] |
| 365 | |
| 366 | data, d.DetectMultiplier = data[1:], BFDDetectMultiplier(data[0]) |
| 367 | data, _ = data[1:], uint8(data[0]) // Consume length |
| 368 | |
| 369 | // The remaining fields can just be copied in big endian order. |
| 370 | data, d.MyDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4])) |
| 371 | data, d.YourDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4])) |
| 372 | data, d.DesiredMinTxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4])) |
| 373 | data, d.RequiredMinRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4])) |
| 374 | data, d.RequiredMinEchoRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4])) |
| 375 | |
| 376 | if d.AuthPresent && (len(data) > 2) { |
| 377 | d.AuthHeader = &BFDAuthHeader{} |
| 378 | data, d.AuthHeader.AuthType = data[1:], BFDAuthType(data[0]) |
| 379 | data, _ = data[1:], uint8(data[0]) // Consume length |
| 380 | data, d.AuthHeader.KeyID = data[1:], BFDAuthKeyID(data[0]) |
| 381 | |
| 382 | switch d.AuthHeader.AuthType { |
| 383 | case BFDAuthTypePassword: |
| 384 | d.AuthHeader.Data = BFDAuthData(data) |
| 385 | case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5: |
| 386 | // Skipped reserved byte |
no test coverage detected