Issue
I'm using mdlayhers (golang) libraries to handle raw ethernet frames to receive and process LLDP packets on a networking device. I'd like to monitor a large number of interfaces (up to 128) for LLDP frames.
In Linux I don't believe it's required to specify an interface to capture device data, but I could be wrong. Is it possible to receive raw ethernet frames across all interfaces by, for example, binding to AF_PACKET
in go? I.e. Is there way to specify a wildcard interface in raw.ListenPacket
or am I best creating a new goroutine for each interface?
Solution
Yes you can. I believe this is what you are looking for:
package main
import (
"fmt"
"net"
"os"
"syscall"
)
func main() {
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_ALL)))
if err != nil {
fmt.Fprintf(os.Stderr, "syscall socket: %s", err.Error())
os.Exit(1)
}
// Make a 32KB buffer
buf := make([]byte, 1<<16)
for {
len, sockaddr, err := syscall.Recvfrom(fd, buf, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "syscall recvfrom: %s", err.Error())
os.Exit(1)
}
if llsa, ok := sockaddr.(*syscall.SockaddrLinklayer); ok {
inter, err := net.InterfaceByIndex(llsa.Ifindex)
if err != nil {
fmt.Fprintf(os.Stderr, "interface from ifindex: %s", err.Error())
os.Exit(1)
}
fmt.Print(inter.Name + ": ")
}
fmt.Printf("% X\n", buf[:len])
}
}
// htons converts a short (uint16) from host-to-network byte order.
func htons(i uint16) uint16 {
return (i<<8)&0xff00 | i>>8
}
Answered By - Dylan Reimerink Answer Checked By - David Goodson (WPSolving Volunteer)