// Copyright 2012 Google, Inc. All rights reserved. // Copyright 2009-2011 Andreas Krennmair. All rights reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file in the root of the source // tree. package layers import ( "encoding/binary" "fmt" "github.com/google/gopacket" ) // Dot1Q is the packet layer for 802.1Q VLAN headers. type Dot1Q struct { BaseLayer Priority uint8 DropEligible bool VLANIdentifier uint16 Type EthernetType } // LayerType returns gopacket.LayerTypeDot1Q func (d *Dot1Q) LayerType() gopacket.LayerType { return LayerTypeDot1Q } // DecodeFromBytes decodes the given bytes into this layer. func (d *Dot1Q) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { d.Priority = (data[0] & 0xE0) >> 5 d.DropEligible = data[0]&0x10 != 0 d.VLANIdentifier = binary.BigEndian.Uint16(data[:2]) & 0x0FFF d.Type = EthernetType(binary.BigEndian.Uint16(data[2:4])) d.BaseLayer = BaseLayer{Contents: data[:4], Payload: data[4:]} return nil } // CanDecode returns the set of layer types that this DecodingLayer can decode. func (d *Dot1Q) CanDecode() gopacket.LayerClass { return LayerTypeDot1Q } // NextLayerType returns the layer type contained by this DecodingLayer. func (d *Dot1Q) NextLayerType() gopacket.LayerType { return d.Type.LayerType() } func decodeDot1Q(data []byte, p gopacket.PacketBuilder) error { d := &Dot1Q{} return decodingLayerDecoder(d, data, p) } // SerializeTo writes the serialized form of this layer into the // SerializationBuffer, implementing gopacket.SerializableLayer. // See the docs for gopacket.SerializableLayer for more info. func (d *Dot1Q) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { bytes, err := b.PrependBytes(4) if err != nil { return err } if d.VLANIdentifier > 0xFFF { return fmt.Errorf("vlan identifier %v is too high", d.VLANIdentifier) } firstBytes := uint16(d.Priority)<<13 | d.VLANIdentifier if d.DropEligible { firstBytes |= 0x1000 } binary.BigEndian.PutUint16(bytes, firstBytes) binary.BigEndian.PutUint16(bytes[2:], uint16(d.Type)) return nil }