icmp6.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // Copyright 2012 Google, Inc. All rights reserved.
  2. // Copyright 2009-2011 Andreas Krennmair. All rights reserved.
  3. //
  4. // Use of this source code is governed by a BSD-style license
  5. // that can be found in the LICENSE file in the root of the source
  6. // tree.
  7. package layers
  8. import (
  9. "encoding/binary"
  10. "errors"
  11. "fmt"
  12. "reflect"
  13. "github.com/google/gopacket"
  14. )
  15. const (
  16. // The following are from RFC 4443
  17. ICMPv6TypeDestinationUnreachable = 1
  18. ICMPv6TypePacketTooBig = 2
  19. ICMPv6TypeTimeExceeded = 3
  20. ICMPv6TypeParameterProblem = 4
  21. ICMPv6TypeEchoRequest = 128
  22. ICMPv6TypeEchoReply = 129
  23. // The following are from RFC 4861
  24. ICMPv6TypeRouterSolicitation = 133
  25. ICMPv6TypeRouterAdvertisement = 134
  26. ICMPv6TypeNeighborSolicitation = 135
  27. ICMPv6TypeNeighborAdvertisement = 136
  28. ICMPv6TypeRedirect = 137
  29. )
  30. const (
  31. // DestinationUnreachable
  32. ICMPv6CodeNoRouteToDst = 0
  33. ICMPv6CodeAdminProhibited = 1
  34. ICMPv6CodeBeyondScopeOfSrc = 2
  35. ICMPv6CodeAddressUnreachable = 3
  36. ICMPv6CodePortUnreachable = 4
  37. ICMPv6CodeSrcAddressFailedPolicy = 5
  38. ICMPv6CodeRejectRouteToDst = 6
  39. // TimeExceeded
  40. ICMPv6CodeHopLimitExceeded = 0
  41. ICMPv6CodeFragmentReassemblyTimeExceeded = 1
  42. // ParameterProblem
  43. ICMPv6CodeErroneousHeaderField = 0
  44. ICMPv6CodeUnrecognizedNextHeader = 1
  45. ICMPv6CodeUnrecognizedIPv6Option = 2
  46. )
  47. type icmpv6TypeCodeInfoStruct struct {
  48. typeStr string
  49. codeStr *map[uint8]string
  50. }
  51. var (
  52. icmpv6TypeCodeInfo = map[uint8]icmpv6TypeCodeInfoStruct{
  53. ICMPv6TypeDestinationUnreachable: icmpv6TypeCodeInfoStruct{
  54. "DestinationUnreachable", &map[uint8]string{
  55. ICMPv6CodeNoRouteToDst: "NoRouteToDst",
  56. ICMPv6CodeAdminProhibited: "AdminProhibited",
  57. ICMPv6CodeBeyondScopeOfSrc: "BeyondScopeOfSrc",
  58. ICMPv6CodeAddressUnreachable: "AddressUnreachable",
  59. ICMPv6CodePortUnreachable: "PortUnreachable",
  60. ICMPv6CodeSrcAddressFailedPolicy: "SrcAddressFailedPolicy",
  61. ICMPv6CodeRejectRouteToDst: "RejectRouteToDst",
  62. },
  63. },
  64. ICMPv6TypePacketTooBig: icmpv6TypeCodeInfoStruct{
  65. "PacketTooBig", nil,
  66. },
  67. ICMPv6TypeTimeExceeded: icmpv6TypeCodeInfoStruct{
  68. "TimeExceeded", &map[uint8]string{
  69. ICMPv6CodeHopLimitExceeded: "HopLimitExceeded",
  70. ICMPv6CodeFragmentReassemblyTimeExceeded: "FragmentReassemblyTimeExceeded",
  71. },
  72. },
  73. ICMPv6TypeParameterProblem: icmpv6TypeCodeInfoStruct{
  74. "ParameterProblem", &map[uint8]string{
  75. ICMPv6CodeErroneousHeaderField: "ErroneousHeaderField",
  76. ICMPv6CodeUnrecognizedNextHeader: "UnrecognizedNextHeader",
  77. ICMPv6CodeUnrecognizedIPv6Option: "UnrecognizedIPv6Option",
  78. },
  79. },
  80. ICMPv6TypeEchoRequest: icmpv6TypeCodeInfoStruct{
  81. "EchoRequest", nil,
  82. },
  83. ICMPv6TypeEchoReply: icmpv6TypeCodeInfoStruct{
  84. "EchoReply", nil,
  85. },
  86. ICMPv6TypeRouterSolicitation: icmpv6TypeCodeInfoStruct{
  87. "RouterSolicitation", nil,
  88. },
  89. ICMPv6TypeRouterAdvertisement: icmpv6TypeCodeInfoStruct{
  90. "RouterAdvertisement", nil,
  91. },
  92. ICMPv6TypeNeighborSolicitation: icmpv6TypeCodeInfoStruct{
  93. "NeighborSolicitation", nil,
  94. },
  95. ICMPv6TypeNeighborAdvertisement: icmpv6TypeCodeInfoStruct{
  96. "NeighborAdvertisement", nil,
  97. },
  98. ICMPv6TypeRedirect: icmpv6TypeCodeInfoStruct{
  99. "Redirect", nil,
  100. },
  101. }
  102. )
  103. type ICMPv6TypeCode uint16
  104. // Type returns the ICMPv6 type field.
  105. func (a ICMPv6TypeCode) Type() uint8 {
  106. return uint8(a >> 8)
  107. }
  108. // Code returns the ICMPv6 code field.
  109. func (a ICMPv6TypeCode) Code() uint8 {
  110. return uint8(a)
  111. }
  112. func (a ICMPv6TypeCode) String() string {
  113. t, c := a.Type(), a.Code()
  114. strInfo, ok := icmpv6TypeCodeInfo[t]
  115. if !ok {
  116. // Unknown ICMPv6 type field
  117. return fmt.Sprintf("%d(%d)", t, c)
  118. }
  119. typeStr := strInfo.typeStr
  120. if strInfo.codeStr == nil && c == 0 {
  121. // The ICMPv6 type does not make use of the code field
  122. return fmt.Sprintf("%s", strInfo.typeStr)
  123. }
  124. if strInfo.codeStr == nil && c != 0 {
  125. // The ICMPv6 type does not make use of the code field, but it is present anyway
  126. return fmt.Sprintf("%s(Code: %d)", typeStr, c)
  127. }
  128. codeStr, ok := (*strInfo.codeStr)[c]
  129. if !ok {
  130. // We don't know this ICMPv6 code; print the numerical value
  131. return fmt.Sprintf("%s(Code: %d)", typeStr, c)
  132. }
  133. return fmt.Sprintf("%s(%s)", typeStr, codeStr)
  134. }
  135. func (a ICMPv6TypeCode) GoString() string {
  136. t := reflect.TypeOf(a)
  137. return fmt.Sprintf("%s(%d, %d)", t.String(), a.Type(), a.Code())
  138. }
  139. // SerializeTo writes the ICMPv6TypeCode value to the 'bytes' buffer.
  140. func (a ICMPv6TypeCode) SerializeTo(bytes []byte) {
  141. binary.BigEndian.PutUint16(bytes, uint16(a))
  142. }
  143. // CreateICMPv6TypeCode is a convenience function to create an ICMPv6TypeCode
  144. // gopacket type from the ICMPv6 type and code values.
  145. func CreateICMPv6TypeCode(typ uint8, code uint8) ICMPv6TypeCode {
  146. return ICMPv6TypeCode(binary.BigEndian.Uint16([]byte{typ, code}))
  147. }
  148. // ICMPv6 is the layer for IPv6 ICMP packet data
  149. type ICMPv6 struct {
  150. BaseLayer
  151. TypeCode ICMPv6TypeCode
  152. Checksum uint16
  153. // TypeBytes is deprecated and always nil. See the different ICMPv6 message types
  154. // instead (e.g. ICMPv6TypeRouterSolicitation).
  155. TypeBytes []byte
  156. tcpipchecksum
  157. }
  158. // LayerType returns LayerTypeICMPv6.
  159. func (i *ICMPv6) LayerType() gopacket.LayerType { return LayerTypeICMPv6 }
  160. // DecodeFromBytes decodes the given bytes into this layer.
  161. func (i *ICMPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
  162. if len(data) < 4 {
  163. df.SetTruncated()
  164. return errors.New("ICMP layer less then 4 bytes for ICMPv6 packet")
  165. }
  166. i.TypeCode = CreateICMPv6TypeCode(data[0], data[1])
  167. i.Checksum = binary.BigEndian.Uint16(data[2:4])
  168. i.BaseLayer = BaseLayer{data[:4], data[4:]}
  169. return nil
  170. }
  171. // SerializeTo writes the serialized form of this layer into the
  172. // SerializationBuffer, implementing gopacket.SerializableLayer.
  173. // See the docs for gopacket.SerializableLayer for more info.
  174. func (i *ICMPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
  175. bytes, err := b.PrependBytes(4)
  176. if err != nil {
  177. return err
  178. }
  179. i.TypeCode.SerializeTo(bytes)
  180. if opts.ComputeChecksums {
  181. bytes[2] = 0
  182. bytes[3] = 0
  183. csum, err := i.computeChecksum(b.Bytes(), IPProtocolICMPv6)
  184. if err != nil {
  185. return err
  186. }
  187. i.Checksum = csum
  188. }
  189. binary.BigEndian.PutUint16(bytes[2:], i.Checksum)
  190. return nil
  191. }
  192. // CanDecode returns the set of layer types that this DecodingLayer can decode.
  193. func (i *ICMPv6) CanDecode() gopacket.LayerClass {
  194. return LayerTypeICMPv6
  195. }
  196. // NextLayerType returns the layer type contained by this DecodingLayer.
  197. func (i *ICMPv6) NextLayerType() gopacket.LayerType {
  198. switch i.TypeCode.Type() {
  199. case ICMPv6TypeRouterSolicitation:
  200. return LayerTypeICMPv6RouterSolicitation
  201. case ICMPv6TypeRouterAdvertisement:
  202. return LayerTypeICMPv6RouterAdvertisement
  203. case ICMPv6TypeNeighborSolicitation:
  204. return LayerTypeICMPv6NeighborSolicitation
  205. case ICMPv6TypeNeighborAdvertisement:
  206. return LayerTypeICMPv6NeighborAdvertisement
  207. case ICMPv6TypeRedirect:
  208. return LayerTypeICMPv6Redirect
  209. }
  210. return gopacket.LayerTypePayload
  211. }
  212. func decodeICMPv6(data []byte, p gopacket.PacketBuilder) error {
  213. i := &ICMPv6{}
  214. return decodingLayerDecoder(i, data, p)
  215. }