github.com/gopacket/gopacket@v1.1.0/layers/icmp6msg.go (about)

     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  
     8  package layers
     9  
    10  import (
    11  	"encoding/binary"
    12  	"encoding/hex"
    13  	"errors"
    14  	"fmt"
    15  	"net"
    16  	"time"
    17  
    18  	"github.com/gopacket/gopacket"
    19  )
    20  
    21  // Based on RFC 4861
    22  
    23  // ICMPv6Opt indicate how to decode the data associated with each ICMPv6Option.
    24  type ICMPv6Opt uint8
    25  
    26  const (
    27  	_ ICMPv6Opt = iota
    28  
    29  	// ICMPv6OptSourceAddress contains the link-layer address of the sender of
    30  	// the packet. It is used in the Neighbor Solicitation, Router
    31  	// Solicitation, and Router Advertisement packets. Must be ignored for other
    32  	// Neighbor discovery messages.
    33  	ICMPv6OptSourceAddress
    34  
    35  	// ICMPv6OptTargetAddress contains the link-layer address of the target. It
    36  	// is used in Neighbor Advertisement and Redirect packets. Must be ignored
    37  	// for other Neighbor discovery messages.
    38  	ICMPv6OptTargetAddress
    39  
    40  	// ICMPv6OptPrefixInfo provides hosts with on-link prefixes and prefixes
    41  	// for Address Autoconfiguration. The Prefix Information option appears in
    42  	// Router Advertisement packets and MUST be silently ignored for other
    43  	// messages.
    44  	ICMPv6OptPrefixInfo
    45  
    46  	// ICMPv6OptRedirectedHeader is used in Redirect messages and contains all
    47  	// or part of the packet that is being redirected.
    48  	ICMPv6OptRedirectedHeader
    49  
    50  	// ICMPv6OptMTU is used in Router Advertisement messages to ensure that all
    51  	// nodes on a link use the same MTU value in those cases where the link MTU
    52  	// is not well known. This option MUST be silently ignored for other
    53  	// Neighbor Discovery messages.
    54  	ICMPv6OptMTU
    55  )
    56  
    57  // ICMPv6Echo represents the structure of a ping.
    58  type ICMPv6Echo struct {
    59  	BaseLayer
    60  	Identifier uint16
    61  	SeqNumber  uint16
    62  }
    63  
    64  // ICMPv6RouterSolicitation is sent by hosts to find routers.
    65  type ICMPv6RouterSolicitation struct {
    66  	BaseLayer
    67  	Options ICMPv6Options
    68  }
    69  
    70  // ICMPv6RouterAdvertisement is sent by routers in response to Solicitation.
    71  type ICMPv6RouterAdvertisement struct {
    72  	BaseLayer
    73  	HopLimit       uint8
    74  	Flags          uint8
    75  	RouterLifetime uint16
    76  	ReachableTime  uint32
    77  	RetransTimer   uint32
    78  	Options        ICMPv6Options
    79  }
    80  
    81  // ICMPv6NeighborSolicitation is sent to request the link-layer address of a
    82  // target node.
    83  type ICMPv6NeighborSolicitation struct {
    84  	BaseLayer
    85  	TargetAddress net.IP
    86  	Options       ICMPv6Options
    87  }
    88  
    89  // ICMPv6NeighborAdvertisement is sent by nodes in response to Solicitation.
    90  type ICMPv6NeighborAdvertisement struct {
    91  	BaseLayer
    92  	Flags         uint8
    93  	TargetAddress net.IP
    94  	Options       ICMPv6Options
    95  }
    96  
    97  // ICMPv6Redirect is sent by routers to inform hosts of a better first-hop node
    98  // on the path to a destination.
    99  type ICMPv6Redirect struct {
   100  	BaseLayer
   101  	TargetAddress      net.IP
   102  	DestinationAddress net.IP
   103  	Options            ICMPv6Options
   104  }
   105  
   106  // ICMPv6Option contains the type and data for a single option.
   107  type ICMPv6Option struct {
   108  	Type ICMPv6Opt
   109  	Data []byte
   110  }
   111  
   112  // ICMPv6Options is a slice of ICMPv6Option.
   113  type ICMPv6Options []ICMPv6Option
   114  
   115  func (i ICMPv6Opt) String() string {
   116  	switch i {
   117  	case ICMPv6OptSourceAddress:
   118  		return "SourceAddress"
   119  	case ICMPv6OptTargetAddress:
   120  		return "TargetAddress"
   121  	case ICMPv6OptPrefixInfo:
   122  		return "PrefixInfo"
   123  	case ICMPv6OptRedirectedHeader:
   124  		return "RedirectedHeader"
   125  	case ICMPv6OptMTU:
   126  		return "MTU"
   127  	default:
   128  		return fmt.Sprintf("Unknown(%d)", i)
   129  	}
   130  }
   131  
   132  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   133  func (i *ICMPv6Echo) CanDecode() gopacket.LayerClass {
   134  	return LayerTypeICMPv6Echo
   135  }
   136  
   137  // LayerType returns LayerTypeICMPv6Echo.
   138  func (i *ICMPv6Echo) LayerType() gopacket.LayerType {
   139  	return LayerTypeICMPv6Echo
   140  }
   141  
   142  // NextLayerType returns the layer type contained by this DecodingLayer.
   143  func (i *ICMPv6Echo) NextLayerType() gopacket.LayerType {
   144  	return gopacket.LayerTypePayload
   145  }
   146  
   147  // DecodeFromBytes decodes the given bytes into this layer.
   148  func (i *ICMPv6Echo) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   149  	if len(data) < 4 {
   150  		df.SetTruncated()
   151  		return errors.New("ICMP layer less then 4 bytes for ICMPv6 Echo")
   152  	}
   153  	i.Identifier = binary.BigEndian.Uint16(data[0:2])
   154  	i.SeqNumber = binary.BigEndian.Uint16(data[2:4])
   155  
   156  	return nil
   157  }
   158  
   159  // SerializeTo writes the serialized form of this layer into the
   160  // SerializationBuffer, implementing gopacket.SerializableLayer.
   161  // See the docs for gopacket.SerializableLayer for more info.
   162  func (i *ICMPv6Echo) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   163  	buf, err := b.PrependBytes(4)
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	binary.BigEndian.PutUint16(buf, i.Identifier)
   169  	binary.BigEndian.PutUint16(buf[2:], i.SeqNumber)
   170  	return nil
   171  }
   172  
   173  // LayerType returns LayerTypeICMPv6.
   174  func (i *ICMPv6RouterSolicitation) LayerType() gopacket.LayerType {
   175  	return LayerTypeICMPv6RouterSolicitation
   176  }
   177  
   178  // NextLayerType returns the layer type contained by this DecodingLayer.
   179  func (i *ICMPv6RouterSolicitation) NextLayerType() gopacket.LayerType {
   180  	return gopacket.LayerTypePayload
   181  }
   182  
   183  // DecodeFromBytes decodes the given bytes into this layer.
   184  func (i *ICMPv6RouterSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   185  	// first 4 bytes are reserved followed by options
   186  	if len(data) < 4 {
   187  		df.SetTruncated()
   188  		return errors.New("ICMP layer less then 4 bytes for ICMPv6 router solicitation")
   189  	}
   190  
   191  	// truncate old options
   192  	i.Options = i.Options[:0]
   193  
   194  	return i.Options.DecodeFromBytes(data[4:], df)
   195  }
   196  
   197  // SerializeTo writes the serialized form of this layer into the
   198  // SerializationBuffer, implementing gopacket.SerializableLayer.
   199  // See the docs for gopacket.SerializableLayer for more info.
   200  func (i *ICMPv6RouterSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   201  	if err := i.Options.SerializeTo(b, opts); err != nil {
   202  		return err
   203  	}
   204  
   205  	buf, err := b.PrependBytes(4)
   206  	if err != nil {
   207  		return err
   208  	}
   209  
   210  	copy(buf, lotsOfZeros[:4])
   211  	return nil
   212  }
   213  
   214  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   215  func (i *ICMPv6RouterSolicitation) CanDecode() gopacket.LayerClass {
   216  	return LayerTypeICMPv6RouterSolicitation
   217  }
   218  
   219  // LayerType returns LayerTypeICMPv6RouterAdvertisement.
   220  func (i *ICMPv6RouterAdvertisement) LayerType() gopacket.LayerType {
   221  	return LayerTypeICMPv6RouterAdvertisement
   222  }
   223  
   224  // NextLayerType returns the layer type contained by this DecodingLayer.
   225  func (i *ICMPv6RouterAdvertisement) NextLayerType() gopacket.LayerType {
   226  	return gopacket.LayerTypePayload
   227  }
   228  
   229  // DecodeFromBytes decodes the given bytes into this layer.
   230  func (i *ICMPv6RouterAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   231  	if len(data) < 12 {
   232  		df.SetTruncated()
   233  		return errors.New("ICMP layer less then 12 bytes for ICMPv6 router advertisement")
   234  	}
   235  
   236  	i.HopLimit = uint8(data[0])
   237  	// M, O bit followed by 6 reserved bits
   238  	i.Flags = uint8(data[1])
   239  	i.RouterLifetime = binary.BigEndian.Uint16(data[2:4])
   240  	i.ReachableTime = binary.BigEndian.Uint32(data[4:8])
   241  	i.RetransTimer = binary.BigEndian.Uint32(data[8:12])
   242  	i.BaseLayer = BaseLayer{data, nil} // assume no payload
   243  
   244  	// truncate old options
   245  	i.Options = i.Options[:0]
   246  
   247  	return i.Options.DecodeFromBytes(data[12:], df)
   248  }
   249  
   250  // SerializeTo writes the serialized form of this layer into the
   251  // SerializationBuffer, implementing gopacket.SerializableLayer.
   252  // See the docs for gopacket.SerializableLayer for more info.
   253  func (i *ICMPv6RouterAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   254  	if err := i.Options.SerializeTo(b, opts); err != nil {
   255  		return err
   256  	}
   257  
   258  	buf, err := b.PrependBytes(12)
   259  	if err != nil {
   260  		return err
   261  	}
   262  
   263  	buf[0] = byte(i.HopLimit)
   264  	buf[1] = byte(i.Flags)
   265  	binary.BigEndian.PutUint16(buf[2:], i.RouterLifetime)
   266  	binary.BigEndian.PutUint32(buf[4:], i.ReachableTime)
   267  	binary.BigEndian.PutUint32(buf[8:], i.RetransTimer)
   268  	return nil
   269  }
   270  
   271  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   272  func (i *ICMPv6RouterAdvertisement) CanDecode() gopacket.LayerClass {
   273  	return LayerTypeICMPv6RouterAdvertisement
   274  }
   275  
   276  // ManagedAddressConfig is true when addresses are available via DHCPv6. If
   277  // set, the OtherConfig flag is redundant.
   278  func (i *ICMPv6RouterAdvertisement) ManagedAddressConfig() bool {
   279  	return i.Flags&0x80 != 0
   280  }
   281  
   282  // OtherConfig is true when there is other configuration information available
   283  // via DHCPv6. For example, DNS-related information.
   284  func (i *ICMPv6RouterAdvertisement) OtherConfig() bool {
   285  	return i.Flags&0x40 != 0
   286  }
   287  
   288  // LayerType returns LayerTypeICMPv6NeighborSolicitation.
   289  func (i *ICMPv6NeighborSolicitation) LayerType() gopacket.LayerType {
   290  	return LayerTypeICMPv6NeighborSolicitation
   291  }
   292  
   293  // NextLayerType returns the layer type contained by this DecodingLayer.
   294  func (i *ICMPv6NeighborSolicitation) NextLayerType() gopacket.LayerType {
   295  	return gopacket.LayerTypePayload
   296  }
   297  
   298  // DecodeFromBytes decodes the given bytes into this layer.
   299  func (i *ICMPv6NeighborSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   300  	if len(data) < 20 {
   301  		df.SetTruncated()
   302  		return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor solicitation")
   303  	}
   304  
   305  	i.TargetAddress = net.IP(data[4:20])
   306  	i.BaseLayer = BaseLayer{data, nil} // assume no payload
   307  
   308  	// truncate old options
   309  	i.Options = i.Options[:0]
   310  
   311  	return i.Options.DecodeFromBytes(data[20:], df)
   312  }
   313  
   314  // SerializeTo writes the serialized form of this layer into the
   315  // SerializationBuffer, implementing gopacket.SerializableLayer.
   316  // See the docs for gopacket.SerializableLayer for more info.
   317  func (i *ICMPv6NeighborSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   318  	if err := i.Options.SerializeTo(b, opts); err != nil {
   319  		return err
   320  	}
   321  
   322  	buf, err := b.PrependBytes(20)
   323  	if err != nil {
   324  		return err
   325  	}
   326  
   327  	copy(buf, lotsOfZeros[:4])
   328  	copy(buf[4:], i.TargetAddress)
   329  	return nil
   330  }
   331  
   332  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   333  func (i *ICMPv6NeighborSolicitation) CanDecode() gopacket.LayerClass {
   334  	return LayerTypeICMPv6NeighborSolicitation
   335  }
   336  
   337  // LayerType returns LayerTypeICMPv6NeighborAdvertisement.
   338  func (i *ICMPv6NeighborAdvertisement) LayerType() gopacket.LayerType {
   339  	return LayerTypeICMPv6NeighborAdvertisement
   340  }
   341  
   342  // NextLayerType returns the layer type contained by this DecodingLayer.
   343  func (i *ICMPv6NeighborAdvertisement) NextLayerType() gopacket.LayerType {
   344  	return gopacket.LayerTypePayload
   345  }
   346  
   347  // DecodeFromBytes decodes the given bytes into this layer.
   348  func (i *ICMPv6NeighborAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   349  	if len(data) < 20 {
   350  		df.SetTruncated()
   351  		return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor advertisement")
   352  	}
   353  
   354  	i.Flags = uint8(data[0])
   355  	i.TargetAddress = net.IP(data[4:20])
   356  	i.BaseLayer = BaseLayer{data, nil} // assume no payload
   357  
   358  	// truncate old options
   359  	i.Options = i.Options[:0]
   360  
   361  	return i.Options.DecodeFromBytes(data[20:], df)
   362  }
   363  
   364  // SerializeTo writes the serialized form of this layer into the
   365  // SerializationBuffer, implementing gopacket.SerializableLayer.
   366  // See the docs for gopacket.SerializableLayer for more info.
   367  func (i *ICMPv6NeighborAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   368  	if err := i.Options.SerializeTo(b, opts); err != nil {
   369  		return err
   370  	}
   371  
   372  	buf, err := b.PrependBytes(20)
   373  	if err != nil {
   374  		return err
   375  	}
   376  
   377  	buf[0] = byte(i.Flags)
   378  	copy(buf[1:], lotsOfZeros[:3])
   379  	copy(buf[4:], i.TargetAddress)
   380  	return nil
   381  }
   382  
   383  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   384  func (i *ICMPv6NeighborAdvertisement) CanDecode() gopacket.LayerClass {
   385  	return LayerTypeICMPv6NeighborAdvertisement
   386  }
   387  
   388  // Router indicates whether the sender is a router or not.
   389  func (i *ICMPv6NeighborAdvertisement) Router() bool {
   390  	return i.Flags&0x80 != 0
   391  }
   392  
   393  // Solicited indicates whether the advertisement was solicited or not.
   394  func (i *ICMPv6NeighborAdvertisement) Solicited() bool {
   395  	return i.Flags&0x40 != 0
   396  }
   397  
   398  // Override indicates whether the advertisement should Override an existing
   399  // cache entry.
   400  func (i *ICMPv6NeighborAdvertisement) Override() bool {
   401  	return i.Flags&0x20 != 0
   402  }
   403  
   404  // LayerType returns LayerTypeICMPv6Redirect.
   405  func (i *ICMPv6Redirect) LayerType() gopacket.LayerType {
   406  	return LayerTypeICMPv6Redirect
   407  }
   408  
   409  // NextLayerType returns the layer type contained by this DecodingLayer.
   410  func (i *ICMPv6Redirect) NextLayerType() gopacket.LayerType {
   411  	return gopacket.LayerTypePayload
   412  }
   413  
   414  // DecodeFromBytes decodes the given bytes into this layer.
   415  func (i *ICMPv6Redirect) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   416  	if len(data) < 36 {
   417  		df.SetTruncated()
   418  		return errors.New("ICMP layer less then 36 bytes for ICMPv6 redirect")
   419  	}
   420  
   421  	i.TargetAddress = net.IP(data[4:20])
   422  	i.DestinationAddress = net.IP(data[20:36])
   423  	i.BaseLayer = BaseLayer{data, nil} // assume no payload
   424  
   425  	// truncate old options
   426  	i.Options = i.Options[:0]
   427  
   428  	return i.Options.DecodeFromBytes(data[36:], df)
   429  }
   430  
   431  // SerializeTo writes the serialized form of this layer into the
   432  // SerializationBuffer, implementing gopacket.SerializableLayer.
   433  // See the docs for gopacket.SerializableLayer for more info.
   434  func (i *ICMPv6Redirect) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   435  	if err := i.Options.SerializeTo(b, opts); err != nil {
   436  		return err
   437  	}
   438  
   439  	buf, err := b.PrependBytes(36)
   440  	if err != nil {
   441  		return err
   442  	}
   443  
   444  	copy(buf, lotsOfZeros[:4])
   445  	copy(buf[4:], i.TargetAddress)
   446  	copy(buf[20:], i.DestinationAddress)
   447  	return nil
   448  }
   449  
   450  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   451  func (i *ICMPv6Redirect) CanDecode() gopacket.LayerClass {
   452  	return LayerTypeICMPv6Redirect
   453  }
   454  
   455  func (i ICMPv6Option) String() string {
   456  	hd := hex.EncodeToString(i.Data)
   457  	if len(hd) > 0 {
   458  		hd = " 0x" + hd
   459  	}
   460  
   461  	switch i.Type {
   462  	case ICMPv6OptSourceAddress, ICMPv6OptTargetAddress:
   463  		return fmt.Sprintf("ICMPv6Option(%s:%v)",
   464  			i.Type,
   465  			net.HardwareAddr(i.Data))
   466  	case ICMPv6OptPrefixInfo:
   467  		if len(i.Data) == 30 {
   468  			prefixLen := uint8(i.Data[0])
   469  			onLink := (i.Data[1]&0x80 != 0)
   470  			autonomous := (i.Data[1]&0x40 != 0)
   471  			validLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[2:6])) * time.Second
   472  			preferredLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[6:10])) * time.Second
   473  
   474  			prefix := net.IP(i.Data[14:])
   475  
   476  			return fmt.Sprintf("ICMPv6Option(%s:%v/%v:%t:%t:%v:%v)",
   477  				i.Type,
   478  				prefix, prefixLen,
   479  				onLink, autonomous,
   480  				validLifetime, preferredLifetime)
   481  		}
   482  	case ICMPv6OptRedirectedHeader:
   483  		// could invoke IP decoder on data... probably best not to
   484  		break
   485  	case ICMPv6OptMTU:
   486  		if len(i.Data) == 6 {
   487  			return fmt.Sprintf("ICMPv6Option(%s:%v)",
   488  				i.Type,
   489  				binary.BigEndian.Uint32(i.Data[2:]))
   490  		}
   491  
   492  	}
   493  	return fmt.Sprintf("ICMPv6Option(%s:%s)", i.Type, hd)
   494  }
   495  
   496  // DecodeFromBytes decodes the given bytes into this layer.
   497  func (i *ICMPv6Options) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
   498  	for len(data) > 0 {
   499  		if len(data) < 2 {
   500  			df.SetTruncated()
   501  			return errors.New("ICMP layer less then 2 bytes for ICMPv6 message option")
   502  		}
   503  
   504  		// unit is 8 octets, convert to bytes
   505  		length := int(data[1]) * 8
   506  
   507  		if length == 0 {
   508  			df.SetTruncated()
   509  			return errors.New("ICMPv6 message option with length 0")
   510  		}
   511  
   512  		if len(data) < length {
   513  			df.SetTruncated()
   514  			return fmt.Errorf("ICMP layer only %v bytes for ICMPv6 message option with length %v", len(data), length)
   515  		}
   516  
   517  		o := ICMPv6Option{
   518  			Type: ICMPv6Opt(data[0]),
   519  			Data: data[2:length],
   520  		}
   521  
   522  		// chop off option we just consumed
   523  		data = data[length:]
   524  
   525  		*i = append(*i, o)
   526  	}
   527  
   528  	return nil
   529  }
   530  
   531  // SerializeTo writes the serialized form of this layer into the
   532  // SerializationBuffer, implementing gopacket.SerializableLayer.
   533  // See the docs for gopacket.SerializableLayer for more info.
   534  func (i *ICMPv6Options) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
   535  	for _, opt := range []ICMPv6Option(*i) {
   536  		length := len(opt.Data) + 2
   537  		buf, err := b.PrependBytes(length)
   538  		if err != nil {
   539  			return err
   540  		}
   541  
   542  		buf[0] = byte(opt.Type)
   543  		buf[1] = byte(length / 8)
   544  		copy(buf[2:], opt.Data)
   545  	}
   546  
   547  	return nil
   548  }
   549  
   550  func decodeICMPv6Echo(data []byte, p gopacket.PacketBuilder) error {
   551  	i := &ICMPv6Echo{}
   552  	return decodingLayerDecoder(i, data, p)
   553  }
   554  
   555  func decodeICMPv6RouterSolicitation(data []byte, p gopacket.PacketBuilder) error {
   556  	i := &ICMPv6RouterSolicitation{}
   557  	return decodingLayerDecoder(i, data, p)
   558  }
   559  
   560  func decodeICMPv6RouterAdvertisement(data []byte, p gopacket.PacketBuilder) error {
   561  	i := &ICMPv6RouterAdvertisement{}
   562  	return decodingLayerDecoder(i, data, p)
   563  }
   564  
   565  func decodeICMPv6NeighborSolicitation(data []byte, p gopacket.PacketBuilder) error {
   566  	i := &ICMPv6NeighborSolicitation{}
   567  	return decodingLayerDecoder(i, data, p)
   568  }
   569  
   570  func decodeICMPv6NeighborAdvertisement(data []byte, p gopacket.PacketBuilder) error {
   571  	i := &ICMPv6NeighborAdvertisement{}
   572  	return decodingLayerDecoder(i, data, p)
   573  }
   574  
   575  func decodeICMPv6Redirect(data []byte, p gopacket.PacketBuilder) error {
   576  	i := &ICMPv6Redirect{}
   577  	return decodingLayerDecoder(i, data, p)
   578  }