extension.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. import (
  6. "encoding/binary"
  7. "golang.org/x/net/ipv4"
  8. "golang.org/x/net/ipv6"
  9. )
  10. // An Extension represents an ICMP extension.
  11. type Extension interface {
  12. // Len returns the length of ICMP extension.
  13. // The provided proto must be either the ICMPv4 or ICMPv6
  14. // protocol number.
  15. Len(proto int) int
  16. // Marshal returns the binary encoding of ICMP extension.
  17. // The provided proto must be either the ICMPv4 or ICMPv6
  18. // protocol number.
  19. Marshal(proto int) ([]byte, error)
  20. }
  21. const extensionVersion = 2
  22. func validExtensionHeader(b []byte) bool {
  23. v := int(b[0]&0xf0) >> 4
  24. s := binary.BigEndian.Uint16(b[2:4])
  25. if s != 0 {
  26. s = checksum(b)
  27. }
  28. if v != extensionVersion || s != 0 {
  29. return false
  30. }
  31. return true
  32. }
  33. // parseExtensions parses b as a list of ICMP extensions.
  34. // The length attribute l must be the length attribute field in
  35. // received icmp messages.
  36. //
  37. // It will return a list of ICMP extensions and an adjusted length
  38. // attribute that represents the length of the padded original
  39. // datagram field. Otherwise, it returns an error.
  40. func parseExtensions(typ Type, b []byte, l int) ([]Extension, int, error) {
  41. // Still a lot of non-RFC 4884 compliant implementations are
  42. // out there. Set the length attribute l to 128 when it looks
  43. // inappropriate for backwards compatibility.
  44. //
  45. // A minimal extension at least requires 8 octets; 4 octets
  46. // for an extension header, and 4 octets for a single object
  47. // header.
  48. //
  49. // See RFC 4884 for further information.
  50. switch typ {
  51. case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
  52. if len(b) < 8 || !validExtensionHeader(b) {
  53. return nil, -1, errNoExtension
  54. }
  55. l = 0
  56. default:
  57. if 128 > l || l+8 > len(b) {
  58. l = 128
  59. }
  60. if l+8 > len(b) {
  61. return nil, -1, errNoExtension
  62. }
  63. if !validExtensionHeader(b[l:]) {
  64. if l == 128 {
  65. return nil, -1, errNoExtension
  66. }
  67. l = 128
  68. if !validExtensionHeader(b[l:]) {
  69. return nil, -1, errNoExtension
  70. }
  71. }
  72. }
  73. var exts []Extension
  74. for b = b[l+4:]; len(b) >= 4; {
  75. ol := int(binary.BigEndian.Uint16(b[:2]))
  76. if 4 > ol || ol > len(b) {
  77. break
  78. }
  79. switch b[2] {
  80. case classMPLSLabelStack:
  81. ext, err := parseMPLSLabelStack(b[:ol])
  82. if err != nil {
  83. return nil, -1, err
  84. }
  85. exts = append(exts, ext)
  86. case classInterfaceInfo:
  87. ext, err := parseInterfaceInfo(b[:ol])
  88. if err != nil {
  89. return nil, -1, err
  90. }
  91. exts = append(exts, ext)
  92. case classInterfaceIdent:
  93. ext, err := parseInterfaceIdent(b[:ol])
  94. if err != nil {
  95. return nil, -1, err
  96. }
  97. exts = append(exts, ext)
  98. default:
  99. ext := &RawExtension{Data: make([]byte, ol)}
  100. copy(ext.Data, b[:ol])
  101. exts = append(exts, ext)
  102. }
  103. b = b[ol:]
  104. }
  105. return exts, l, nil
  106. }
  107. func validExtensions(typ Type, exts []Extension) bool {
  108. switch typ {
  109. case ipv4.ICMPTypeDestinationUnreachable, ipv4.ICMPTypeTimeExceeded, ipv4.ICMPTypeParameterProblem,
  110. ipv6.ICMPTypeDestinationUnreachable, ipv6.ICMPTypeTimeExceeded:
  111. for i := range exts {
  112. switch exts[i].(type) {
  113. case *MPLSLabelStack, *InterfaceInfo, *RawExtension:
  114. default:
  115. return false
  116. }
  117. }
  118. return true
  119. case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
  120. var n int
  121. for i := range exts {
  122. switch exts[i].(type) {
  123. case *InterfaceIdent:
  124. n++
  125. case *RawExtension:
  126. default:
  127. return false
  128. }
  129. }
  130. // Not a single InterfaceIdent object or a combo of
  131. // RawExtension and InterfaceIdent objects is not
  132. // allowed.
  133. if n == 1 && len(exts) > 1 {
  134. return false
  135. }
  136. return true
  137. default:
  138. return false
  139. }
  140. }
  141. // A RawExtension represents a raw extension.
  142. //
  143. // A raw extension is excluded from message processing and can be used
  144. // to construct applications such as protocol conformance testing.
  145. type RawExtension struct {
  146. Data []byte // data
  147. }
  148. // Len implements the Len method of Extension interface.
  149. func (p *RawExtension) Len(proto int) int {
  150. if p == nil {
  151. return 0
  152. }
  153. return len(p.Data)
  154. }
  155. // Marshal implements the Marshal method of Extension interface.
  156. func (p *RawExtension) Marshal(proto int) ([]byte, error) {
  157. return p.Data, nil
  158. }