blob: 85a4f8bdd0ab08f8006d5ace4ee38a03e385ab2e [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// 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
7package layers
8
9import (
10 "encoding/binary"
11 "errors"
12 "fmt"
13 "net"
14
15 "github.com/google/gopacket"
16)
17
18type LinuxSLLPacketType uint16
19
20const (
21 LinuxSLLPacketTypeHost LinuxSLLPacketType = 0 // To us
22 LinuxSLLPacketTypeBroadcast LinuxSLLPacketType = 1 // To all
23 LinuxSLLPacketTypeMulticast LinuxSLLPacketType = 2 // To group
24 LinuxSLLPacketTypeOtherhost LinuxSLLPacketType = 3 // To someone else
25 LinuxSLLPacketTypeOutgoing LinuxSLLPacketType = 4 // Outgoing of any type
26 // These ones are invisible by user level
27 LinuxSLLPacketTypeLoopback LinuxSLLPacketType = 5 // MC/BRD frame looped back
28 LinuxSLLPacketTypeFastroute LinuxSLLPacketType = 6 // Fastrouted frame
29)
30
31func (l LinuxSLLPacketType) String() string {
32 switch l {
33 case LinuxSLLPacketTypeHost:
34 return "host"
35 case LinuxSLLPacketTypeBroadcast:
36 return "broadcast"
37 case LinuxSLLPacketTypeMulticast:
38 return "multicast"
39 case LinuxSLLPacketTypeOtherhost:
40 return "otherhost"
41 case LinuxSLLPacketTypeOutgoing:
42 return "outgoing"
43 case LinuxSLLPacketTypeLoopback:
44 return "loopback"
45 case LinuxSLLPacketTypeFastroute:
46 return "fastroute"
47 }
48 return fmt.Sprintf("Unknown(%d)", int(l))
49}
50
51type LinuxSLL struct {
52 BaseLayer
53 PacketType LinuxSLLPacketType
54 AddrLen uint16
55 Addr net.HardwareAddr
56 EthernetType EthernetType
57 AddrType uint16
58}
59
60// LayerType returns LayerTypeLinuxSLL.
61func (sll *LinuxSLL) LayerType() gopacket.LayerType { return LayerTypeLinuxSLL }
62
63func (sll *LinuxSLL) CanDecode() gopacket.LayerClass {
64 return LayerTypeLinuxSLL
65}
66
67func (sll *LinuxSLL) LinkFlow() gopacket.Flow {
68 return gopacket.NewFlow(EndpointMAC, sll.Addr, nil)
69}
70
71func (sll *LinuxSLL) NextLayerType() gopacket.LayerType {
72 return sll.EthernetType.LayerType()
73}
74
75func (sll *LinuxSLL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
76 if len(data) < 16 {
77 return errors.New("Linux SLL packet too small")
78 }
79 sll.PacketType = LinuxSLLPacketType(binary.BigEndian.Uint16(data[0:2]))
80 sll.AddrType = binary.BigEndian.Uint16(data[2:4])
81 sll.AddrLen = binary.BigEndian.Uint16(data[4:6])
82
83 sll.Addr = net.HardwareAddr(data[6 : sll.AddrLen+6])
84 sll.EthernetType = EthernetType(binary.BigEndian.Uint16(data[14:16]))
85 sll.BaseLayer = BaseLayer{data[:16], data[16:]}
86
87 return nil
88}
89
90func decodeLinuxSLL(data []byte, p gopacket.PacketBuilder) error {
91 sll := &LinuxSLL{}
92 if err := sll.DecodeFromBytes(data, p); err != nil {
93 return err
94 }
95 p.AddLayer(sll)
96 p.SetLinkLayer(sll)
97 return p.NextDecoder(sll.EthernetType)
98}