-
Notifications
You must be signed in to change notification settings - Fork 0
/
link_layer_handler_arp.go
73 lines (61 loc) · 1.57 KB
/
link_layer_handler_arp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package edurouter
import (
"context"
"github.com/mdlayher/ethernet"
"github.com/rs/zerolog/log"
)
type ARPv4LinkLayerHandler struct {
supplierCh chan FrameIn
publishCh chan<- *ethernet.Frame
}
func (llh *ARPv4LinkLayerHandler) SupplierC() chan<- FrameIn {
return llh.supplierCh
}
func NewARPv4LinkLayerHandler(publishCh chan<- *ethernet.Frame) *ARPv4LinkLayerHandler {
return &ARPv4LinkLayerHandler{
supplierCh: make(chan FrameIn, 128),
publishCh: publishCh,
}
}
func (llh *ARPv4LinkLayerHandler) RunHandler(ctx context.Context) {
go llh.runHandler(ctx)
}
func (llh *ARPv4LinkLayerHandler) runHandler(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case f := <-llh.supplierCh:
var packet ARPv4Pdu
// ARP logic
err := (&packet).UnmarshalBinary(f.Frame.Payload)
if err != nil {
log.Error().Msgf("error during arp unmarshall: %v", err)
continue
}
if !packet.IsEthernetAndIPv4() {
continue
}
if packet.IsArpResponse() {
err = f.Interface.ArpTable.Store(packet.SrcProtoAddr, packet.SrcHardwareAddr)
if err != nil {
log.Error().Msgf("error during arp arp table store: %v", err)
}
continue
}
if packet.IsArpRequestForConfig(f.Interface) {
arpResponse := packet.BuildARPResponseWithConfig(f.Interface)
arpBinary, err := arpResponse.MarshalBinary()
if err != nil {
continue
}
llh.publishCh <- ðernet.Frame{
Destination: f.Frame.Source,
Source: *f.Interface.HardwareAddr,
EtherType: ethernet.EtherTypeARP,
Payload: arpBinary,
}
}
}
}
}