-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathutil.go
110 lines (97 loc) · 2.86 KB
/
util.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package egressguy
import (
"errors"
"fmt"
"net"
"time"
"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
"github.com/gopacket/gopacket/pcap"
"github.com/gopacket/gopacket/routing"
)
var GOPACKETS_OPTS = gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
const ETHER_OFFSET = 14
func GetHwAddr(handle *pcap.Handle, iface *net.Interface, src net.IP, gw net.IP) (net.HardwareAddr, error) {
start := time.Now()
// Prepare the layers to send for an ARP request.
eth := layers.Ethernet{
SrcMAC: iface.HardwareAddr,
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
EthernetType: layers.EthernetTypeARP,
}
arp := layers.ARP{
AddrType: layers.LinkTypeEthernet,
Protocol: layers.EthernetTypeIPv4,
HwAddressSize: 6,
ProtAddressSize: 4,
Operation: layers.ARPRequest,
SourceHwAddress: []byte(iface.HardwareAddr),
SourceProtAddress: []byte(src),
DstHwAddress: []byte{0, 0, 0, 0, 0, 0},
DstProtAddress: []byte(gw),
}
buf := gopacket.NewSerializeBuffer()
if err := gopacket.SerializeLayers(buf, GOPACKETS_OPTS, ð, &arp); err != nil {
return nil, err
}
if err := handle.WritePacketData(buf.Bytes()); err != nil {
return nil, err
}
// Wait 3 seconds for an ARP reply.
for {
if time.Since(start) > time.Second*3 {
return nil, errors.New("timeout getting ARP reply")
}
data, _, err := handle.ZeroCopyReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
continue
} else if err != nil {
return nil, err
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil {
arp := arpLayer.(*layers.ARP)
if net.IP(arp.SourceProtAddress).Equal(net.IP(gw)) {
return net.HardwareAddr(arp.SourceHwAddress), nil
}
}
}
}
func HumanizeBytes(bytes uint64) string {
if bytes > 1<<40 {
return fmt.Sprintf("%.2f TiB", float64(bytes)/(1<<40))
} else if bytes > 1<<30 {
return fmt.Sprintf("%.2f GiB", float64(bytes)/(1<<30))
} else if bytes > 1<<20 {
return fmt.Sprintf("%.2f MiB", float64(bytes)/(1<<20))
} else if bytes > 1<<10 {
return fmt.Sprintf("%.2f KiB", float64(bytes)/(1<<10))
} else {
return fmt.Sprintf("%d B", bytes)
}
}
func GetRoutingInfo(ifaceName string, dst net.IP) (*net.Interface, net.IP, net.IP, error) {
router, err := routing.New()
if err != nil {
return nil, nil, nil, err
}
if ifaceName == "" {
return router.Route(dst)
} else {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return nil, nil, nil, err
}
iface, gw, src, err := router.RouteWithSrc(iface.HardwareAddr, nil, dst)
if err != nil {
return nil, nil, nil, err
}
if iface.Name != ifaceName {
return nil, nil, nil, errors.New("failed to route through the specified interface")
}
return iface, gw, src, nil
}
}