194 lines
5.1 KiB
Go
194 lines
5.1 KiB
Go
|
// Copyright 2012 Google, Inc. 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"
|
||
|
"errors"
|
||
|
|
||
|
"github.com/google/gopacket"
|
||
|
)
|
||
|
|
||
|
// LLC is the layer used for 802.2 Logical Link Control headers.
|
||
|
// See http://standards.ieee.org/getieee802/download/802.2-1998.pdf
|
||
|
type LLC struct {
|
||
|
BaseLayer
|
||
|
DSAP uint8
|
||
|
IG bool // true means group, false means individual
|
||
|
SSAP uint8
|
||
|
CR bool // true means response, false means command
|
||
|
Control uint16
|
||
|
}
|
||
|
|
||
|
// LayerType returns gopacket.LayerTypeLLC.
|
||
|
func (l *LLC) LayerType() gopacket.LayerType { return LayerTypeLLC }
|
||
|
|
||
|
// DecodeFromBytes decodes the given bytes into this layer.
|
||
|
func (l *LLC) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||
|
if len(data) < 3 {
|
||
|
return errors.New("LLC header too small")
|
||
|
}
|
||
|
l.DSAP = data[0] & 0xFE
|
||
|
l.IG = data[0]&0x1 != 0
|
||
|
l.SSAP = data[1] & 0xFE
|
||
|
l.CR = data[1]&0x1 != 0
|
||
|
l.Control = uint16(data[2])
|
||
|
|
||
|
if l.Control&0x1 == 0 || l.Control&0x3 == 0x1 {
|
||
|
if len(data) < 4 {
|
||
|
return errors.New("LLC header too small")
|
||
|
}
|
||
|
l.Control = l.Control<<8 | uint16(data[3])
|
||
|
l.Contents = data[:4]
|
||
|
l.Payload = data[4:]
|
||
|
} else {
|
||
|
l.Contents = data[:3]
|
||
|
l.Payload = data[3:]
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||
|
func (l *LLC) CanDecode() gopacket.LayerClass {
|
||
|
return LayerTypeLLC
|
||
|
}
|
||
|
|
||
|
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||
|
func (l *LLC) NextLayerType() gopacket.LayerType {
|
||
|
switch {
|
||
|
case l.DSAP == 0xAA && l.SSAP == 0xAA:
|
||
|
return LayerTypeSNAP
|
||
|
case l.DSAP == 0x42 && l.SSAP == 0x42:
|
||
|
return LayerTypeSTP
|
||
|
}
|
||
|
return gopacket.LayerTypeZero // Not implemented
|
||
|
}
|
||
|
|
||
|
// SNAP is used inside LLC. See
|
||
|
// http://standards.ieee.org/getieee802/download/802-2001.pdf.
|
||
|
// From http://en.wikipedia.org/wiki/Subnetwork_Access_Protocol:
|
||
|
// "[T]he Subnetwork Access Protocol (SNAP) is a mechanism for multiplexing,
|
||
|
// on networks using IEEE 802.2 LLC, more protocols than can be distinguished
|
||
|
// by the 8-bit 802.2 Service Access Point (SAP) fields."
|
||
|
type SNAP struct {
|
||
|
BaseLayer
|
||
|
OrganizationalCode []byte
|
||
|
Type EthernetType
|
||
|
}
|
||
|
|
||
|
// LayerType returns gopacket.LayerTypeSNAP.
|
||
|
func (s *SNAP) LayerType() gopacket.LayerType { return LayerTypeSNAP }
|
||
|
|
||
|
// DecodeFromBytes decodes the given bytes into this layer.
|
||
|
func (s *SNAP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||
|
if len(data) < 5 {
|
||
|
return errors.New("SNAP header too small")
|
||
|
}
|
||
|
s.OrganizationalCode = data[:3]
|
||
|
s.Type = EthernetType(binary.BigEndian.Uint16(data[3:5]))
|
||
|
s.BaseLayer = BaseLayer{data[:5], data[5:]}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||
|
func (s *SNAP) CanDecode() gopacket.LayerClass {
|
||
|
return LayerTypeSNAP
|
||
|
}
|
||
|
|
||
|
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||
|
func (s *SNAP) NextLayerType() gopacket.LayerType {
|
||
|
// See BUG(gconnel) in decodeSNAP
|
||
|
return s.Type.LayerType()
|
||
|
}
|
||
|
|
||
|
func decodeLLC(data []byte, p gopacket.PacketBuilder) error {
|
||
|
l := &LLC{}
|
||
|
err := l.DecodeFromBytes(data, p)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
p.AddLayer(l)
|
||
|
return p.NextDecoder(l.NextLayerType())
|
||
|
}
|
||
|
|
||
|
func decodeSNAP(data []byte, p gopacket.PacketBuilder) error {
|
||
|
s := &SNAP{}
|
||
|
err := s.DecodeFromBytes(data, p)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
p.AddLayer(s)
|
||
|
// BUG(gconnell): When decoding SNAP, we treat the SNAP type as an Ethernet
|
||
|
// type. This may not actually be an ethernet type in all cases,
|
||
|
// depending on the organizational code. Right now, we don't check.
|
||
|
return p.NextDecoder(s.Type)
|
||
|
}
|
||
|
|
||
|
// SerializeTo writes the serialized form of this layer into the
|
||
|
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||
|
// See the docs for gopacket.SerializableLayer for more info.
|
||
|
func (l *LLC) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||
|
var igFlag, crFlag byte
|
||
|
var length int
|
||
|
|
||
|
if l.Control&0xFF00 != 0 {
|
||
|
length = 4
|
||
|
} else {
|
||
|
length = 3
|
||
|
}
|
||
|
|
||
|
if l.DSAP&0x1 != 0 {
|
||
|
return errors.New("DSAP value invalid, should not include IG flag bit")
|
||
|
}
|
||
|
|
||
|
if l.SSAP&0x1 != 0 {
|
||
|
return errors.New("SSAP value invalid, should not include CR flag bit")
|
||
|
}
|
||
|
|
||
|
if buf, err := b.PrependBytes(length); err != nil {
|
||
|
return err
|
||
|
} else {
|
||
|
igFlag = 0
|
||
|
if l.IG {
|
||
|
igFlag = 0x1
|
||
|
}
|
||
|
|
||
|
crFlag = 0
|
||
|
if l.CR {
|
||
|
crFlag = 0x1
|
||
|
}
|
||
|
|
||
|
buf[0] = l.DSAP + igFlag
|
||
|
buf[1] = l.SSAP + crFlag
|
||
|
|
||
|
if length == 4 {
|
||
|
buf[2] = uint8(l.Control >> 8)
|
||
|
buf[3] = uint8(l.Control)
|
||
|
} else {
|
||
|
buf[2] = uint8(l.Control)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// SerializeTo writes the serialized form of this layer into the
|
||
|
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||
|
// See the docs for gopacket.SerializableLayer for more info.
|
||
|
func (s *SNAP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||
|
if buf, err := b.PrependBytes(5); err != nil {
|
||
|
return err
|
||
|
} else {
|
||
|
buf[0] = s.OrganizationalCode[0]
|
||
|
buf[1] = s.OrganizationalCode[1]
|
||
|
buf[2] = s.OrganizationalCode[2]
|
||
|
binary.BigEndian.PutUint16(buf[3:5], uint16(s.Type))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|