因為工作上需要查看主機上所收到任何的LLDP封包,故在網上搜尋了一下資料與範例程式碼,組成下列一個簡單範例。
本程式會找出所有在此本機上的Net Devices ( Interface ),並依序收集封包,一旦發現有LLDP則會列印相關資訊在console上。
package main
import (
"fmt"
"log"
"net"
"strings"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
var (
snapshot_len int32 = 1024
promiscuous bool = true
err error
timeout time.Duration = 1 * time.Second
timerclick int = 30
handle *pcap.Handle
nottododevices = []string{"virbr", "docker", "any", "lo", "usbmon"}
)
// contains checks if a string is present in a slice
func contains(s []string, str string) bool {
for _, v := range s {
if strings.Contains(str, v) {
return true
}
}
return false
}
func main() {
// Get all devices
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
// Print the device information
fmt.Println("Devices found:")
for _, device := range devices {
fmt.Println("\nName: ", device.Name)
fmt.Println("Description: ", device.Description)
fmt.Println("Devices addresses: ", device.Description)
for _, address := range device.Addresses {
fmt.Println("- IP address: ", address.IP)
fmt.Println("- Subnet mask: ", address.Netmask)
}
// Get LLDP Packets
if !contains(nottododevices, device.Name) {
fmt.Println("Get LLDP...")
ReadLLDPInfo(device.Name, snapshot_len, promiscuous, timeout)
}
}
}
func ReadLLDPInfo(device string, snapshot_len int32, promiscuous bool, timeout time.Duration) {
// Open device
handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
if err != nil {
log.Printf("[%v] Error : %s", device, err)
}
defer handle.Close()
// Use the handle as a packet source to process all packets
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
packets := packetSource.Packets()
timer := time.NewTimer(time.Duration(timerclick) * time.Second)
for {
select {
case packet := <-packets:
lldpLayerInfos := packet.Layer(layers.LayerTypeLinkLayerDiscoveryInfo)
if lldpLayerInfos == nil {
continue
}
lldpInfos := lldpLayerInfos.(*layers.LinkLayerDiscoveryInfo)
if lldpInfos.PortDescription == device {
continue
}
log.Printf("[%v] ************************************************", device)
log.Printf("[%v] PortDescription : %s", device, lldpInfos.PortDescription)
log.Printf("[%v] SysName : %s", device, lldpInfos.SysName)
log.Printf("[%v] SysDescription : %s", device, lldpInfos.SysDescription)
var mgmtAddress string
switch lldpInfos.MgmtAddress.Subtype {
case layers.IANAAddressFamilyIPV4:
mgmtAddress = net.IP(lldpInfos.MgmtAddress.Address).String()
default:
mgmtAddress = string(lldpInfos.MgmtAddress.Address)
}
log.Printf("[%v] MgmtAddress : %s", device, mgmtAddress)
case <-timer.C:
log.Printf("[%v] Time's up for %d", device, timerclick)
timer.Stop()
return
}
}
}
執行結果:
Devices found: Name: enp4s0 Description: Devices addresses: - IP address: 140.96.27.24 - Subnet mask: ffffff00 - IP address: fe80::5ded:b7e0:45dc:b29c - Subnet mask: ffffffffffffffff0000000000000000 Get LLDP... 2022/04/19 13:42:11 [enp4s0] ************************************************ 2022/04/19 13:42:11 [enp4s0] PortDescription : Gi1/0/14 2022/04/19 13:42:11 [enp4s0] SysName : n2048apm0 2022/04/19 13:42:11 [enp4s0] SysDescription : 2022/04/19 13:42:11 [enp4s0] MgmtAddress : 2022/04/19 13:42:35 [enp4s0] Time's up for 30 Name: any Description: Pseudo-device that captures on all interfaces Devices addresses: Pseudo-device that captures on all interfaces Name: lo Description: Devices addresses: - IP address: 127.0.0.1 - Subnet mask: ff000000 - IP address: ::1 - Subnet mask: ffffffffffffffffffffffffffffffff
參考資料:
Golang gopacket.NewPacketSource函數代碼示例
How to use decodeLinkLayerDiscovery in lldp.go?
for NIC in $(find /sys/class/net -type l -not -lname "*virtual*" -printf "%f\n" | sort); do
echo "NIC: ${NIC}"
echo "NIC MAC: $(ethtool -P ${NIC})"
timeout 300 tcpdump -nn -v -i ${NIC} -s 1500 -c 1 "ether[20:2] == 0x2000"
done
LLDP: Identify switch port to which the server is connected
lldpLayerInfos := packet.Layer(layers.LayerTypeLinkLayerDiscoveryInfo)
if lldpLayerInfos == nil {
continue
}
lldpInfos := lldpLayerInfos.(*layers.LinkLayerDiscoveryInfo)
log.Printf("[%v] ************************************************", iface.Name)
log.Printf("[%v] PortDescription : %s", iface.Name, lldpInfos.PortDescription)
log.Printf("[%v] SysName : %s", iface.Name, lldpInfos.SysName)
log.Printf("[%v] SysDescription : %s", iface.Name, lldpInfos.SysDescription)
var mgmtAddress string
switch lldpInfos.MgmtAddress.Subtype {
case layers.IANAAddressFamilyIPV4:
mgmtAddress = net.IP(lldpInfos.MgmtAddress.Address).String()
default:
mgmtAddress = string(lldpInfos.MgmtAddress.Address)
}
log.Printf("[%v] MgmtAddress : %s", iface.Name, mgmtAddress)
No comments:
Post a Comment