在Linux中,是否可以在不指定接口的情况下接收原始以太网帧?

huangapple go评论70阅读模式
英文:

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 (
	&quot;fmt&quot;
	&quot;net&quot;
	&quot;os&quot;
	&quot;syscall&quot;
)

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, &quot;syscall socket: %s&quot;, err.Error())
		os.Exit(1)
	}

	// Make a 32KB buffer
	buf := make([]byte, 1&lt;&lt;16)
	for {
		len, sockaddr, err := syscall.Recvfrom(fd, buf, 0)
		if err != nil {
			fmt.Fprintf(os.Stderr, &quot;syscall recvfrom: %s&quot;, 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, &quot;interface from ifindex: %s&quot;, err.Error())
				os.Exit(1)
			}
			fmt.Print(inter.Name + &quot;: &quot;)
		}

		fmt.Printf(&quot;% X\n&quot;, buf[:len])
	}
}

// htons converts a short (uint16) from host-to-network byte order.
func htons(i uint16) uint16 {
	return (i&lt;&lt;8)&amp;0xff00 | i&gt;&gt;8
}

huangapple
  • 本文由 发表于 2022年1月11日 11:15:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/70661217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定