diff --git a/packet.go b/packet.go index a05117c..f8b0790 100644 --- a/packet.go +++ b/packet.go @@ -132,6 +132,12 @@ func (c *Conn) SetPromiscuous(enable bool) error { return c.setPromiscuous(enable) } +// SetPromiscuous enables or disables promiscuous mode on the Conn, allowing it +// to receive traffic that is not addressed to the Conn's network interface. +func (c *Conn) SetMembership(enable bool, Type uint16, addr net.HardwareAddr) error { + return c.setMembership(enable, Type, addr) +} + // Stats contains statistics about a Conn reported by the Linux kernel. type Stats struct { // The total number of packets received. diff --git a/packet_linux.go b/packet_linux.go index 263cdd7..f658fa1 100644 --- a/packet_linux.go +++ b/packet_linux.go @@ -51,9 +51,20 @@ func (c *Conn) writeTo(b []byte, addr net.Addr) (int, error) { // setPromiscuous wraps setsockopt(2) for the unix.PACKET_MR_PROMISC option. func (c *Conn) setPromiscuous(enable bool) error { + return c.setMembership(enable, unix.PACKET_MR_PROMISC, nil) +} + +const ETH_ALEN uint16 = 6 + +// setMembership wraps setsockopt(2) for PACKET_MR_* +func (c *Conn) setMembership(enable bool, Type uint16, addr net.HardwareAddr) error { mreq := unix.PacketMreq{ Ifindex: int32(c.ifIndex), - Type: unix.PACKET_MR_PROMISC, + Type: Type, + Alen: ETH_ALEN, + } + if Type == unix.PACKET_MR_MULTICAST { + copy(mreq.Address[:], addr) } membership := unix.PACKET_DROP_MEMBERSHIP