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

     1  // Copyright 2012 Google, Inc. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  package layers
     8  
     9  import (
    10  	"encoding/binary"
    11  
    12  	"github.com/gopacket/gopacket"
    13  )
    14  
    15  // GRE is a Generic Routing Encapsulation header.
    16  type GRE struct {
    17  	BaseLayer
    18  	ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute, AckPresent bool
    19  	RecursionControl, Flags, Version                                                       uint8
    20  	Protocol                                                                               EthernetType
    21  	Checksum, Offset                                                                       uint16
    22  	Key, Seq, Ack                                                                          uint32
    23  	*GRERouting
    24  }
    25  
    26  // GRERouting is GRE routing information, present if the RoutingPresent flag is
    27  // set.
    28  type GRERouting struct {
    29  	AddressFamily        uint16
    30  	SREOffset, SRELength uint8
    31  	RoutingInformation   []byte
    32  	Next                 *GRERouting
    33  }
    34  
    35  // LayerType returns gopacket.LayerTypeGRE.
    36  func (g *GRE) LayerType() gopacket.LayerType { return LayerTypeGRE }
    37  
    38  // DecodeFromBytes decodes the given bytes into this layer.
    39  func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
    40  	g.ChecksumPresent = data[0]&0x80 != 0
    41  	g.RoutingPresent = data[0]&0x40 != 0
    42  	g.KeyPresent = data[0]&0x20 != 0
    43  	g.SeqPresent = data[0]&0x10 != 0
    44  	g.StrictSourceRoute = data[0]&0x08 != 0
    45  	g.AckPresent = data[1]&0x80 != 0
    46  	g.RecursionControl = data[0] & 0x7
    47  	g.Flags = data[1] >> 3
    48  	g.Version = data[1] & 0x7
    49  	g.Protocol = EthernetType(binary.BigEndian.Uint16(data[2:4]))
    50  	offset := 4
    51  	if g.ChecksumPresent || g.RoutingPresent {
    52  		g.Checksum = binary.BigEndian.Uint16(data[offset : offset+2])
    53  		g.Offset = binary.BigEndian.Uint16(data[offset+2 : offset+4])
    54  		offset += 4
    55  	}
    56  	if g.KeyPresent {
    57  		g.Key = binary.BigEndian.Uint32(data[offset : offset+4])
    58  		offset += 4
    59  	}
    60  	if g.SeqPresent {
    61  		g.Seq = binary.BigEndian.Uint32(data[offset : offset+4])
    62  		offset += 4
    63  	}
    64  	if g.RoutingPresent {
    65  		tail := &g.GRERouting
    66  		for {
    67  			sre := &GRERouting{
    68  				AddressFamily: binary.BigEndian.Uint16(data[offset : offset+2]),
    69  				SREOffset:     data[offset+2],
    70  				SRELength:     data[offset+3],
    71  			}
    72  			sre.RoutingInformation = data[offset+4 : offset+4+int(sre.SRELength)]
    73  			offset += 4 + int(sre.SRELength)
    74  			if sre.AddressFamily == 0 && sre.SRELength == 0 {
    75  				break
    76  			}
    77  			(*tail) = sre
    78  			tail = &sre.Next
    79  		}
    80  	}
    81  	if g.AckPresent {
    82  		g.Ack = binary.BigEndian.Uint32(data[offset : offset+4])
    83  		offset += 4
    84  	}
    85  	g.BaseLayer = BaseLayer{data[:offset], data[offset:]}
    86  	return nil
    87  }
    88  
    89  // SerializeTo writes the serialized form of this layer into the SerializationBuffer,
    90  // implementing gopacket.SerializableLayer. See the docs for gopacket.SerializableLayer for more info.
    91  func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
    92  	size := 4
    93  	if g.ChecksumPresent || g.RoutingPresent {
    94  		size += 4
    95  	}
    96  	if g.KeyPresent {
    97  		size += 4
    98  	}
    99  	if g.SeqPresent {
   100  		size += 4
   101  	}
   102  	if g.RoutingPresent {
   103  		r := g.GRERouting
   104  		for r != nil {
   105  			size += 4 + int(r.SRELength)
   106  			r = r.Next
   107  		}
   108  		size += 4
   109  	}
   110  	if g.AckPresent {
   111  		size += 4
   112  	}
   113  	buf, err := b.PrependBytes(size)
   114  	if err != nil {
   115  		return err
   116  	}
   117  	// Reset any potentially dirty memory in the first 2 bytes, as these use OR to set flags.
   118  	buf[0] = 0
   119  	buf[1] = 0
   120  	if g.ChecksumPresent {
   121  		buf[0] |= 0x80
   122  	}
   123  	if g.RoutingPresent {
   124  		buf[0] |= 0x40
   125  	}
   126  	if g.KeyPresent {
   127  		buf[0] |= 0x20
   128  	}
   129  	if g.SeqPresent {
   130  		buf[0] |= 0x10
   131  	}
   132  	if g.StrictSourceRoute {
   133  		buf[0] |= 0x08
   134  	}
   135  	if g.AckPresent {
   136  		buf[1] |= 0x80
   137  	}
   138  	buf[0] |= g.RecursionControl
   139  	buf[1] |= g.Flags << 3
   140  	buf[1] |= g.Version
   141  	binary.BigEndian.PutUint16(buf[2:4], uint16(g.Protocol))
   142  	offset := 4
   143  	if g.ChecksumPresent || g.RoutingPresent {
   144  		// Don't write the checksum value yet, as we may need to compute it,
   145  		// which requires the entire header be complete.
   146  		// Instead we zeroize the memory in case it is dirty.
   147  		buf[offset] = 0
   148  		buf[offset+1] = 0
   149  		binary.BigEndian.PutUint16(buf[offset+2:offset+4], g.Offset)
   150  		offset += 4
   151  	}
   152  	if g.KeyPresent {
   153  		binary.BigEndian.PutUint32(buf[offset:offset+4], g.Key)
   154  		offset += 4
   155  	}
   156  	if g.SeqPresent {
   157  		binary.BigEndian.PutUint32(buf[offset:offset+4], g.Seq)
   158  		offset += 4
   159  	}
   160  	if g.RoutingPresent {
   161  		sre := g.GRERouting
   162  		for sre != nil {
   163  			binary.BigEndian.PutUint16(buf[offset:offset+2], sre.AddressFamily)
   164  			buf[offset+2] = sre.SREOffset
   165  			buf[offset+3] = sre.SRELength
   166  			copy(buf[offset+4:offset+4+int(sre.SRELength)], sre.RoutingInformation)
   167  			offset += 4 + int(sre.SRELength)
   168  			sre = sre.Next
   169  		}
   170  		// Terminate routing field with a "NULL" SRE.
   171  		binary.BigEndian.PutUint32(buf[offset:offset+4], 0)
   172  	}
   173  	if g.AckPresent {
   174  		binary.BigEndian.PutUint32(buf[offset:offset+4], g.Ack)
   175  		offset += 4
   176  	}
   177  	if g.ChecksumPresent {
   178  		if opts.ComputeChecksums {
   179  			g.Checksum = tcpipChecksum(b.Bytes(), 0)
   180  		}
   181  
   182  		binary.BigEndian.PutUint16(buf[4:6], g.Checksum)
   183  	}
   184  	return nil
   185  }
   186  
   187  // CanDecode returns the set of layer types that this DecodingLayer can decode.
   188  func (g *GRE) CanDecode() gopacket.LayerClass {
   189  	return LayerTypeGRE
   190  }
   191  
   192  // NextLayerType returns the layer type contained by this DecodingLayer.
   193  func (g *GRE) NextLayerType() gopacket.LayerType {
   194  	return g.Protocol.LayerType()
   195  }
   196  
   197  func decodeGRE(data []byte, p gopacket.PacketBuilder) error {
   198  	g := &GRE{}
   199  	return decodingLayerDecoder(g, data, p)
   200  }