func (c *PPPoEConn) Recv(b []byte) (n int, err error) {
	return c.file.Read(b)
}
Recv receives one or more frames over the discovery connection.
package pppoe
import (
	"fmt"
	"net"
	"os"
	"golang.org/x/sys/unix"
)
type PPPoEConn struct {
	iface *net.Interface
	fd    int
	file  *os.File
}
func newRawSocket(protocol int) (fd int, err error) {
	fd, err = unix.Socket(unix.AF_PACKET, unix.SOCK_RAW, protocol)
	if err != nil {
		return -1, fmt.Errorf("socket: %v", err)
	}
	if err = unix.SetNonblock(fd, true); err != nil {
		unix.Close(fd)
		return -1, fmt.Errorf("failed to set socket nonblocking: %v", err)
	}
	flags, err := unix.FcntlInt(uintptr(fd), unix.F_GETFD, 0)
	if err != nil {
		unix.Close(fd)
		return -1, fmt.Errorf("fcntl(F_GETFD): %v", err)
	}
	_, err = unix.FcntlInt(uintptr(fd), unix.F_SETFD, flags|unix.FD_CLOEXEC)
	if err != nil {
		unix.Close(fd)
		return -1, fmt.Errorf("fcntl(F_SETFD, FD_CLOEXEC): %v", err)
	}
	err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_BROADCAST, 1)
	if err != nil {
		unix.Close(fd)
		return -1, fmt.Errorf("setsockopt(SO_BROADCAST): %v", err)
	}
	return
}
func NewDiscoveryConnection(ifname string) (conn *PPPoEConn, err error) {
	iface, err := net.InterfaceByName(ifname)
	if err != nil {
		return nil, fmt.Errorf("failed to obtain details of interface \"%s\": %v", ifname, err)
	}
	fd, err := newRawSocket(int(ethTypeDiscoveryNetUint16()))
	if err != nil {
		return nil, fmt.Errorf("failed to create raw socket: %v", err)
	}
	sa := unix.SockaddrLinklayer{
		Protocol: ethTypeDiscoveryNetUint16(),
		Ifindex:  iface.Index,
	}
	err = unix.Bind(fd, &sa)
	if err != nil {
		unix.Close(fd)
		return nil, fmt.Errorf("failed to bind socket: %v", err)
	}
	file := os.NewFile(uintptr(fd), "pppoe")
	return &PPPoEConn{
		iface: iface,
		fd:    fd,
		file:  file,
	}, nil
}
func (c *PPPoEConn) Close() (err error) {
	if c.file != nil {
		err = c.file.Close()
		c.file = nil
	}
	return
}
func (c *PPPoEConn) Send(b []byte) (n int, err error) {
	return c.file.Write(b)
}