英文:
Is it possible to receive raw ethernet frames in Linux without specifying an interface?
问题
我正在使用mdlayhers(golang)库来处理原始以太网帧,以接收和处理网络设备上的LLDP数据包。我想监视大量接口(最多128个)的LLDP帧。
在Linux中,我认为不需要指定要捕获设备数据的接口,但我可能错了。是否可以通过在go中绑定到AF_PACKET
来接收所有接口上的原始以太网帧?即,在raw.ListenPacket
中是否有指定通配符接口的方法,或者我最好为每个接口创建一个新的goroutine?
英文:
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?
答案1
得分: 1
是的,你可以。我相信这就是你要找的代码:
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)
}
// 创建一个32KB的缓冲区
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函数将一个short(uint16)从主机字节序转换为网络字节序。
func htons(i uint16) uint16 {
return (i<<8)&0xff00 | i>>8
}
希望对你有帮助!
英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论