Home > OS >  Is it possible to receive raw ethernet frames in Linux without specifying an interface?
Is it possible to receive raw ethernet frames in Linux without specifying an interface?

Time:01-13

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?

CodePudding user response:

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
}
  •  Tags:  
  • Related