diff --git a/link_linux.go b/link_linux.go index fd227a0..95dc601 100644 --- a/link_linux.go +++ b/link_linux.go @@ -113,6 +113,54 @@ func (h *Handle) SetPromiscOn(link Link) error { return err } +// LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast on` +func LinkSetAllmulticastOn(link Link) error { + return pkgHandle.LinkSetAllmulticastOn(link) +} + +// LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast on` +func (h *Handle) LinkSetAllmulticastOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_ALLMULTI + msg.Flags = unix.IFF_ALLMULTI + + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast off` +func LinkSetAllmulticastOff(link Link) error { + return pkgHandle.LinkSetAllmulticastOff(link) +} + +// LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device. +// Equivalent to: `ip link set $link allmulticast off` +func (h *Handle) LinkSetAllmulticastOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_ALLMULTI + msg.Flags = 0 + + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { return pkgHandle.MacvlanMACAddrAdd(link, addr) } diff --git a/link_test.go b/link_test.go index 4781ed1..980de37 100644 --- a/link_test.go +++ b/link_test.go @@ -1869,3 +1869,60 @@ func TestLinkSetBondSlave(t *testing.T) { t.Errorf("For %s expected %s to be master", slaveTwoLink.Attrs().Name, bondLink.Attrs().Name) } } + +func TestLinkSetAllmulticast(t *testing.T) { + tearDown := setUpNetlinkTest(t) + defer tearDown() + + iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo"}, PeerName: "bar"} + if err := LinkAdd(iface); err != nil { + t.Fatal(err) + } + + link, err := LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if err := LinkSetUp(link); err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + rawFlagsStart := link.Attrs().RawFlags + + if err := LinkSetAllmulticastOn(link); err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if link.Attrs().RawFlags&unix.IFF_ALLMULTI != uint32(unix.IFF_ALLMULTI) { + t.Fatal("IFF_ALLMULTI was not set!") + } + + if err := LinkSetAllmulticastOff(link); err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if link.Attrs().RawFlags&unix.IFF_ALLMULTI != 0 { + t.Fatal("IFF_ALLMULTI is still set!") + } + + rawFlagsEnd := link.Attrs().RawFlags + if rawFlagsStart != rawFlagsEnd { + t.Fatalf("RawFlags start value:%d differs from end value:%d", rawFlagsStart, rawFlagsEnd) + } +}