google / gopacket

Provides packet processing capabilities for Go
BSD 3-Clause "New" or "Revised" License
6.23k stars 1.12k forks source link

Set afpacket socket in promiscuous mode #564

Open dawei73 opened 5 years ago

dawei73 commented 5 years ago

It would be nice to be able to set the socket in promiscuous mode.

perhaps something like this:

func (h *TPacket) SetPromiscMode(ifaceName string) error {
    ifIndex := 0
    // An empty string here means to listen to all interfaces
    if ifaceName != "" {
        iface, err := net.InterfaceByName(ifaceName)
        if err != nil {
            return fmt.Errorf("InterfaceByName: %v", err)
        }
        ifIndex = iface.Index
    }
    var sp C.struct_packet_mreq
    sp.mr_ifindex = C.int(ifIndex)
    sp.mr_type = unix.PACKET_MR_PROMISC
    sp.mr_alen = 0
    sp.mr_address = [8]C.uchar{0,0,0,0,0,0,0,0}
    if err := setsockopt(h.fd, unix.SOL_PACKET, unix.PACKET_ADD_MEMBERSHIP, unsafe.Pointer(&sp), unsafe.Sizeof(sp)); err != nil {
        return fmt.Errorf("setsockopt promisc mode: %v", err)
  }
    return nil
}
norg commented 4 years ago

This would be very helpful as it could help in some scenarios where we don't see any packets unless it's set to promiscuous mode. Is there any plan to include this?

Current workaround is ip link set $INTERFACE promisc on.

maxatome commented 3 months ago

Using reflect, so very dirty :)

func setPromiscuous(tp *afpacket.TPacket, ifidx int, on bool) error {
    mreq := unix.PacketMreq{
        Ifindex: int32(ifidx),
        Type:    unix.PACKET_MR_PROMISC,
    }
    opt := unix.PACKET_DROP_MEMBERSHIP
    if on {
        opt = unix.PACKET_ADD_MEMBERSHIP
    }
    fd := int(reflect.ValueOf(tp).Elem().FieldByName("fd").Int())
    return unix.SetsockoptPacketMreq(fd, unix.SOL_PACKET, opt, &mreq)
}

ifidx is the interface index.