diff --git a/link_linux.go b/link_linux.go index 56409eb..0c04d3a 100644 --- a/link_linux.go +++ b/link_linux.go @@ -58,6 +58,44 @@ func (h *Handle) ensureIndex(link *LinkAttrs) { } } +func (h *Handle) LinkSetARPOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) + msg.Change |= syscall.IFF_NOARP + msg.Flags |= syscall.IFF_NOARP + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +func LinkSetARPOff(link Link) error { + return pkgHandle.LinkSetARPOff(link) +} + +func (h *Handle) LinkSetARPOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK) + + msg := nl.NewIfInfomsg(syscall.AF_UNSPEC) + msg.Change |= syscall.IFF_NOARP + msg.Flags &= ^uint32(syscall.IFF_NOARP) + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(syscall.NETLINK_ROUTE, 0) + return err +} + +func LinkSetARPOn(link Link) error { + return pkgHandle.LinkSetARPOn(link) +} + func (h *Handle) SetPromiscOn(link Link) error { base := link.Attrs() h.ensureIndex(base) diff --git a/link_test.go b/link_test.go index cdfb959..5167e74 100644 --- a/link_test.go +++ b/link_test.go @@ -812,6 +812,49 @@ func TestLinkSet(t *testing.T) { } } +func TestLinkSetARP(t *testing.T) { + tearDown := setUpNetlinkTest(t) + defer tearDown() + + iface := &Veth{LinkAttrs: LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1500}, PeerName: "banana"} + if err := LinkAdd(iface); err != nil { + t.Fatal(err) + } + + link, err := LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + err = LinkSetARPOff(link) + if err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if link.Attrs().RawFlags&syscall.IFF_NOARP != uint32(syscall.IFF_NOARP) { + t.Fatalf("NOARP was not set!") + } + + err = LinkSetARPOn(link) + if err != nil { + t.Fatal(err) + } + + link, err = LinkByName("foo") + if err != nil { + t.Fatal(err) + } + + if link.Attrs().RawFlags&syscall.IFF_NOARP != 0 { + t.Fatalf("NOARP is still set!") + } +} + func expectLinkUpdate(ch <-chan LinkUpdate, ifaceName string, up bool) bool { for { timeout := time.After(time.Minute) diff --git a/netlink_unspecified.go b/netlink_unspecified.go index fa421e4..c0a25bc 100644 --- a/netlink_unspecified.go +++ b/netlink_unspecified.go @@ -64,6 +64,14 @@ func LinkSetXdpFd(link Link, fd int) error { return ErrNotImplemented } +func LinkSetARPOff(link Link) error { + return ErrNotImplemented +} + +func LinkSetARPOn(link Link) error { + return ErrNotImplemented +} + func LinkByName(name string) (Link, error) { return nil, ErrNotImplemented }