Skip to content

Commit

Permalink
Add (*afpacket.TPacket).SetPromiscuous
Browse files Browse the repository at this point in the history
Closes #564.

Signed-off-by: Maxime Soulé <[email protected]>
  • Loading branch information
maxatome committed Apr 26, 2024
1 parent 32ee382 commit 35c1a1f
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 12 deletions.
45 changes: 33 additions & 12 deletions afpacket/afpacket.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,20 @@ type TPacket struct {

var _ gopacket.ZeroCopyPacketDataSource = &TPacket{}

// bindToInterface binds the TPacket socket to a particular named interface.
func (h *TPacket) bindToInterface(ifaceName string) error {
ifIndex := 0
// bindToInterface binds the TPacket socket to the configured interface.
func (h *TPacket) bindToInterface() error {
h.opts.ifaceIdx = 0
// An empty string here means to listen to all interfaces
if ifaceName != "" {
iface, err := net.InterfaceByName(ifaceName)
if h.opts.iface != "" {
iface, err := net.InterfaceByName(h.opts.iface)
if err != nil {
return fmt.Errorf("InterfaceByName: %v", err)
}
ifIndex = iface.Index
h.opts.ifaceIdx = iface.Index
}
s := &unix.SockaddrLinklayer{
Protocol: htons(uint16(unix.ETH_P_ALL)),
Ifindex: ifIndex,
Ifindex: h.opts.ifaceIdx,
}
return unix.Bind(h.fd, s)
}
Expand Down Expand Up @@ -242,7 +242,7 @@ func NewTPacket(opts ...interface{}) (h *TPacket, err error) {
return nil, err
}
h.fd = fd
if err = h.bindToInterface(h.opts.iface); err != nil {
if err = h.bindToInterface(); err != nil {
goto errlbl
}
if err = h.setRequestedTPacketVersion(); err != nil {
Expand Down Expand Up @@ -279,6 +279,26 @@ func (h *TPacket) SetEBPF(progFd int32) error {
return setsockopt(h.fd, unix.SOL_SOCKET, unix.SO_ATTACH_BPF, unsafe.Pointer(&progFd), 4)
}

// SetPromiscuous sets promiscous mode to the required value. If it is
// enabled, traffic not destined for the interface will also be
// captured.
//
// Non empty OptInterface options is required, otherwise an error is returned.
func (h *TPacket) SetPromiscuous(on bool) error {
if h.opts.ifaceIdx == 0 {
return errors.New("SetPromiscuous needs non empty OptInterface option")
}
mreq := unix.PacketMreq{
Ifindex: int32(h.opts.ifaceIdx),
Type: unix.PACKET_MR_PROMISC,
}
opt := unix.PACKET_DROP_MEMBERSHIP
if on {
opt = unix.PACKET_ADD_MEMBERSHIP
}
return unix.SetsockoptPacketMreq(h.fd, unix.SOL_PACKET, opt, &mreq)
}

func (h *TPacket) releaseCurrentPacket() error {
h.current.clearStatus()
h.offset++
Expand All @@ -293,10 +313,11 @@ func (h *TPacket) releaseCurrentPacket() error {
// to old bytes when using ZeroCopyReadPacketData... if you need to keep data past
// the next time you call ZeroCopyReadPacketData, use ReadPacketData, which copies
// the bytes into a new buffer for you.
// tp, _ := NewTPacket(...)
// data1, _, _ := tp.ZeroCopyReadPacketData()
// // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around.
// data2, _, _ := tp.ZeroCopyReadPacketData() // invalidates bytes in data1
//
// tp, _ := NewTPacket(...)
// data1, _, _ := tp.ZeroCopyReadPacketData()
// // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around.
// data2, _, _ := tp.ZeroCopyReadPacketData() // invalidates bytes in data1
func (h *TPacket) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
h.mu.Lock()
retry:
Expand Down
2 changes: 2 additions & 0 deletions afpacket/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// that can be found in the LICENSE file in the root of the source
// tree.

//go:build linux
// +build linux

package afpacket
Expand Down Expand Up @@ -126,6 +127,7 @@ type options struct {
version OptTPacketVersion
socktype OptSocketType
iface string
ifaceIdx int
}

var defaultOpts = options{
Expand Down

0 comments on commit 35c1a1f

Please sign in to comment.