extension.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package icmp
  5. // An Extension represents an ICMP extension.
  6. type Extension interface {
  7. // Len returns the length of ICMP extension.
  8. // Proto must be either the ICMPv4 or ICMPv6 protocol number.
  9. Len(proto int) int
  10. // Marshal returns the binary encoding of ICMP extension.
  11. // Proto must be either the ICMPv4 or ICMPv6 protocol number.
  12. Marshal(proto int) ([]byte, error)
  13. }
  14. const extensionVersion = 2
  15. func validExtensionHeader(b []byte) bool {
  16. v := int(b[0]&0xf0) >> 4
  17. s := uint16(b[2])<<8 | uint16(b[3])
  18. if s != 0 {
  19. s = checksum(b)
  20. }
  21. if v != extensionVersion || s != 0 {
  22. return false
  23. }
  24. return true
  25. }
  26. // parseExtensions parses b as a list of ICMP extensions.
  27. // The length attribute l must be the length attribute field in
  28. // received icmp messages.
  29. //
  30. // It will return a list of ICMP extensions and an adjusted length
  31. // attribute that represents the length of the padded original
  32. // datagram field. Otherwise, it returns an error.
  33. func parseExtensions(b []byte, l int) ([]Extension, int, error) {
  34. // Still a lot of non-RFC 4884 compliant implementations are
  35. // out there. Set the length attribute l to 128 when it looks
  36. // inappropriate for backwards compatibility.
  37. //
  38. // A minimal extension at least requires 8 octets; 4 octets
  39. // for an extension header, and 4 octets for a single object
  40. // header.
  41. //
  42. // See RFC 4884 for further information.
  43. if 128 > l || l+8 > len(b) {
  44. l = 128
  45. }
  46. if l+8 > len(b) {
  47. return nil, -1, errNoExtension
  48. }
  49. if !validExtensionHeader(b[l:]) {
  50. if l == 128 {
  51. return nil, -1, errNoExtension
  52. }
  53. l = 128
  54. if !validExtensionHeader(b[l:]) {
  55. return nil, -1, errNoExtension
  56. }
  57. }
  58. var exts []Extension
  59. for b = b[l+4:]; len(b) >= 4; {
  60. ol := int(b[0])<<8 | int(b[1])
  61. if 4 > ol || ol > len(b) {
  62. break
  63. }
  64. switch b[2] {
  65. case classMPLSLabelStack:
  66. ext, err := parseMPLSLabelStack(b[:ol])
  67. if err != nil {
  68. return nil, -1, err
  69. }
  70. exts = append(exts, ext)
  71. case classInterfaceInfo:
  72. ext, err := parseInterfaceInfo(b[:ol])
  73. if err != nil {
  74. return nil, -1, err
  75. }
  76. exts = append(exts, ext)
  77. }
  78. b = b[ol:]
  79. }
  80. return exts, l, nil
  81. }