diff --git a/go.mod b/go.mod index f6621d239..c9c91ef8a 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( github.com/d2g/dhcp4client v1.0.0 github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5 github.com/godbus/dbus/v5 v5.0.4 - github.com/j-keck/arping v1.0.2 github.com/mattn/go-shellwords v1.0.12 github.com/networkplumbing/go-nft v0.2.0 github.com/onsi/ginkgo v1.16.4 diff --git a/go.sum b/go.sum index 395483e76..6a816fe82 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,6 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v1.0.0 h1:9VJe1a5uKtdeJIHC/UvbTweracOh6GafT0nfbEGVcQ0= -github.com/containernetworking/cni v1.0.0/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= github.com/containernetworking/cni v1.0.1 h1:9OIL/sZmMYDBe+G8svzILAlulUpaDTUjeAbtH/JNLBo= github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= @@ -375,8 +373,6 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/j-keck/arping v1.0.2 h1:hlLhuXgQkzIJTZuhMigvG/CuSkaspeaD9hRDk2zuiMI= -github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= diff --git a/pkg/ip/link_linux.go b/pkg/ip/link_linux.go index 9e6f17c69..91f931b57 100644 --- a/pkg/ip/link_linux.go +++ b/pkg/ip/link_linux.go @@ -36,9 +36,8 @@ var ( func makeVethPair(name, peer string, mtu int, mac string, hostNS ns.NetNS) (netlink.Link, error) { veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{ - Name: name, - Flags: net.FlagUp, - MTU: mtu, + Name: name, + MTU: mtu, }, PeerName: peer, PeerNamespace: netlink.NsFd(int(hostNS.Fd())), @@ -146,10 +145,6 @@ func SetupVethWithName(contVethName, hostVethName string, mtu int, contVethMac s return net.Interface{}, net.Interface{}, err } - if err = netlink.LinkSetUp(contVeth); err != nil { - return net.Interface{}, net.Interface{}, fmt.Errorf("failed to set %q up: %v", contVethName, err) - } - var hostVeth netlink.Link err = hostNS.Do(func(_ ns.NetNS) error { hostVeth, err = netlink.LinkByName(hostVethName) diff --git a/pkg/ipam/ipam_linux.go b/pkg/ipam/ipam_linux.go index 8c8b8e0b0..60694cc92 100644 --- a/pkg/ipam/ipam_linux.go +++ b/pkg/ipam/ipam_linux.go @@ -43,10 +43,6 @@ func ConfigureIface(ifName string, res *current.Result) error { return fmt.Errorf("failed to lookup %q: %v", ifName, err) } - if err := netlink.LinkSetUp(link); err != nil { - return fmt.Errorf("failed to set %q UP: %v", ifName, err) - } - var v4gw, v6gw net.IP var has_enabled_ipv6 bool = false for _, ipc := range res.IPs { @@ -99,6 +95,10 @@ func ConfigureIface(ifName string, res *current.Result) error { } } + if err := netlink.LinkSetUp(link); err != nil { + return fmt.Errorf("failed to set %q UP: %v", ifName, err) + } + if v6gw != nil { ip.SettleAddresses(ifName, 10) } diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index dbce42441..b6ff02c9b 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -25,7 +25,6 @@ import ( "syscall" "time" - "github.com/j-keck/arping" "github.com/vishvananda/netlink" "github.com/containernetworking/cni/pkg/skel" @@ -324,6 +323,11 @@ func ensureVlanInterface(br *netlink.Bridge, vlanId int) (netlink.Link, error) { if err != nil { return nil, fmt.Errorf("failed to lookup %q: %v", brGatewayIface.Name, err) } + + err = netlink.LinkSetUp(brGatewayVeth) + if err != nil { + return nil, fmt.Errorf("failed to up %q: %v", brGatewayIface.Name, err) + } } return brGatewayVeth, nil @@ -524,6 +528,8 @@ func cmdAdd(args *skel.CmdArgs) error { } } + _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1") + // Add the IP to the interface if err := ipam.ConfigureIface(args.IfName, result); err != nil { return err @@ -551,23 +557,6 @@ func cmdAdd(args *skel.CmdArgs) error { } } - // Send a gratuitous arp - if err := netns.Do(func(_ ns.NetNS) error { - contVeth, err := net.InterfaceByName(args.IfName) - if err != nil { - return err - } - - for _, ipc := range result.IPs { - if ipc.Address.IP.To4() != nil { - _ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth) - } - } - return nil - }); err != nil { - return err - } - if n.IsGW { var firstV4Addr net.IP var vlanInterface *current.Interface @@ -618,6 +607,20 @@ func cmdAdd(args *skel.CmdArgs) error { } } } + } else { + if err := netns.Do(func(_ ns.NetNS) error { + link, err := netlink.LinkByName(args.IfName) + if err != nil { + return fmt.Errorf("failed to retrieve link: %v", err) + } + // If layer 2 we still need to set the container veth to up + if err = netlink.LinkSetUp(link); err != nil { + return fmt.Errorf("failed to set %q up: %v", args.IfName, err) + } + return nil + }); err != nil { + return err + } } // Refetch the bridge since its MAC address may change when the first diff --git a/plugins/main/bridge/bridge_test.go b/plugins/main/bridge/bridge_test.go index 5d1e0dcb1..118074ed6 100644 --- a/plugins/main/bridge/bridge_test.go +++ b/plugins/main/bridge/bridge_test.go @@ -28,8 +28,8 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/types/040" - "github.com/containernetworking/cni/pkg/types/100" + types040 "github.com/containernetworking/cni/pkg/types/040" + types100 "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/plugins/pkg/ip" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" diff --git a/plugins/main/ipvlan/ipvlan.go b/plugins/main/ipvlan/ipvlan.go index 06b5117d4..42c51b65c 100644 --- a/plugins/main/ipvlan/ipvlan.go +++ b/plugins/main/ipvlan/ipvlan.go @@ -18,10 +18,8 @@ import ( "encoding/json" "errors" "fmt" - "net" "runtime" - "github.com/j-keck/arping" "github.com/vishvananda/netlink" "github.com/containernetworking/cni/pkg/skel" @@ -33,6 +31,7 @@ import ( "github.com/containernetworking/plugins/pkg/ipam" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" + "github.com/containernetworking/plugins/pkg/utils/sysctl" ) type NetConf struct { @@ -256,20 +255,11 @@ func cmdAdd(args *skel.CmdArgs) error { result.Interfaces = []*current.Interface{ipvlanInterface} err = netns.Do(func(_ ns.NetNS) error { + _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1") + if err := ipam.ConfigureIface(args.IfName, result); err != nil { return err } - - contVeth, err := net.InterfaceByName(args.IfName) - if err != nil { - return fmt.Errorf("failed to look up %q: %v", args.IfName, err) - } - - for _, ipc := range result.IPs { - if ipc.Address.IP.To4() != nil { - _ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth) - } - } return nil }) if err != nil { diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index 99044a333..fccb0822a 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -21,7 +21,6 @@ import ( "net" "runtime" - "github.com/j-keck/arping" "github.com/vishvananda/netlink" "github.com/containernetworking/cni/pkg/skel" @@ -33,6 +32,7 @@ import ( "github.com/containernetworking/plugins/pkg/ipam" "github.com/containernetworking/plugins/pkg/ns" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" + "github.com/containernetworking/plugins/pkg/utils/sysctl" ) type NetConf struct { @@ -294,20 +294,11 @@ func cmdAdd(args *skel.CmdArgs) error { } err = netns.Do(func(_ ns.NetNS) error { + _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", args.IfName), "1") + if err := ipam.ConfigureIface(args.IfName, result); err != nil { return err } - - contVeth, err := net.InterfaceByName(args.IfName) - if err != nil { - return fmt.Errorf("failed to look up %q: %v", args.IfName, err) - } - - for _, ipc := range result.IPs { - if ipc.Address.IP.To4() != nil { - _ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth) - } - } return nil }) if err != nil { diff --git a/plugins/main/ptp/ptp.go b/plugins/main/ptp/ptp.go index 6eb121e13..bd15e8c6b 100644 --- a/plugins/main/ptp/ptp.go +++ b/plugins/main/ptp/ptp.go @@ -22,7 +22,6 @@ import ( "os" "runtime" - "github.com/j-keck/arping" "github.com/vishvananda/netlink" "github.com/containernetworking/cni/pkg/skel" @@ -35,6 +34,7 @@ import ( "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/utils" bv "github.com/containernetworking/plugins/pkg/utils/buildversion" + "github.com/containernetworking/plugins/pkg/utils/sysctl" ) func init() { @@ -83,15 +83,17 @@ func setupContainerVeth(netns ns.NetNS, ifName string, mtu int, pr *current.Resu pr.Interfaces = []*current.Interface{hostInterface, containerInterface} - if err = ipam.ConfigureIface(ifName, pr); err != nil { - return err - } - contVeth, err := net.InterfaceByName(ifName) if err != nil { return fmt.Errorf("failed to look up %q: %v", ifName, err) } + _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv4/conf/%s/arp_notify", ifName), "1") + + if err = ipam.ConfigureIface(ifName, pr); err != nil { + return err + } + for _, ipc := range pr.IPs { // Delete the route that was automatically added route := netlink.Route{ @@ -139,13 +141,6 @@ func setupContainerVeth(netns ns.NetNS, ifName string, mtu int, pr *current.Resu } } - // Send a gratuitous arp for all v4 addresses - for _, ipc := range pr.IPs { - if ipc.Address.IP.To4() != nil { - _ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth) - } - } - return nil }) if err != nil { diff --git a/plugins/meta/tuning/tuning.go b/plugins/meta/tuning/tuning.go index f8cb46b74..0d3e546c7 100644 --- a/plugins/meta/tuning/tuning.go +++ b/plugins/meta/tuning/tuning.go @@ -27,7 +27,6 @@ import ( "path/filepath" "strings" - "github.com/j-keck/arping" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" @@ -315,11 +314,6 @@ func cmdAdd(args *skel.CmdArgs) error { return err } - result, err := current.NewResultFromResult(tuningConf.PrevResult) - if err != nil { - return err - } - // The directory /proc/sys/net is per network namespace. Enter in the // network namespace before writing on it. @@ -355,12 +349,6 @@ func cmdAdd(args *skel.CmdArgs) error { return err } - for _, ipc := range result.IPs { - if ipc.Address.IP.To4() != nil { - _ = arping.GratuitousArpOverIfaceByName(ipc.Address.IP, args.IfName) - } - } - updateResultsMacAddr(tuningConf, args.IfName, tuningConf.Mac) } diff --git a/vendor/github.com/j-keck/arping/.gitignore b/vendor/github.com/j-keck/arping/.gitignore deleted file mode 100644 index 670656214..000000000 --- a/vendor/github.com/j-keck/arping/.gitignore +++ /dev/null @@ -1 +0,0 @@ -arping diff --git a/vendor/github.com/j-keck/arping/LICENSE b/vendor/github.com/j-keck/arping/LICENSE deleted file mode 100644 index 887a32ed4..000000000 --- a/vendor/github.com/j-keck/arping/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - - Copyright (c) 2014-2016 j-keck [jhyphenkeck@gmail.com] - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - diff --git a/vendor/github.com/j-keck/arping/README.md b/vendor/github.com/j-keck/arping/README.md deleted file mode 100644 index 086ade5b7..000000000 --- a/vendor/github.com/j-keck/arping/README.md +++ /dev/null @@ -1,31 +0,0 @@ -[![pkg.go.dev](https://godoc.org/github.com/j-keck/arping?status.svg)](https://pkg.go.dev/github.com/j-keck/arping) - -# arping - -arping is a native go library to ping a host per arp datagram, or query a host mac address - -The currently supported platforms are: Linux and BSD. - - -## Usage -### arping library - -* import this library per `import "github.com/j-keck/arping"` -* export GOPATH if not already (`export GOPATH=$PWD`) -* download the library `go get` -* run it `sudo -E go run ` -* or build it `go build` - - -The library requires raw socket access. So it must run as root, or with appropriate capabilities under linux: `sudo setcap cap_net_raw+ep `. - -For api doc and examples see: [godoc](http://godoc.org/github.com/j-keck/arping) or check the standalone under 'cmd/arping/main.go'. - - - -### arping executable - -To get a runnable pinger use `go get -u github.com/j-keck/arping/cmd/arping`. This will build the binary in $GOPATH/bin. - -arping requires raw socket access. So it must run as root, or with appropriate capabilities under Linux: `sudo setcap cap_net_raw+ep `. - diff --git a/vendor/github.com/j-keck/arping/arp_datagram.go b/vendor/github.com/j-keck/arping/arp_datagram.go deleted file mode 100644 index 1443bc210..000000000 --- a/vendor/github.com/j-keck/arping/arp_datagram.go +++ /dev/null @@ -1,98 +0,0 @@ -package arping - -import ( - "bytes" - "encoding/binary" - "net" -) - -const ( - requestOper = 1 - responseOper = 2 -) - -type arpDatagram struct { - htype uint16 // Hardware Type - ptype uint16 // Protocol Type - hlen uint8 // Hardware address Length - plen uint8 // Protocol address length - oper uint16 // Operation 1->request, 2->response - sha []byte // Sender hardware address, length from Hlen - spa []byte // Sender protocol address, length from Plen - tha []byte // Target hardware address, length from Hlen - tpa []byte // Target protocol address, length from Plen -} - -func newArpRequest( - srcMac net.HardwareAddr, - srcIP net.IP, - dstMac net.HardwareAddr, - dstIP net.IP) arpDatagram { - return arpDatagram{ - htype: uint16(1), - ptype: uint16(0x0800), - hlen: uint8(6), - plen: uint8(4), - oper: uint16(requestOper), - sha: srcMac, - spa: srcIP.To4(), - tha: dstMac, - tpa: dstIP.To4()} -} - -func (datagram arpDatagram) Marshal() []byte { - buf := new(bytes.Buffer) - binary.Write(buf, binary.BigEndian, datagram.htype) - binary.Write(buf, binary.BigEndian, datagram.ptype) - binary.Write(buf, binary.BigEndian, datagram.hlen) - binary.Write(buf, binary.BigEndian, datagram.plen) - binary.Write(buf, binary.BigEndian, datagram.oper) - buf.Write(datagram.sha) - buf.Write(datagram.spa) - buf.Write(datagram.tha) - buf.Write(datagram.tpa) - - return buf.Bytes() -} - -func (datagram arpDatagram) MarshalWithEthernetHeader() []byte { - // ethernet frame header - var ethernetHeader []byte - ethernetHeader = append(ethernetHeader, datagram.tha...) - ethernetHeader = append(ethernetHeader, datagram.sha...) - ethernetHeader = append(ethernetHeader, []byte{0x08, 0x06}...) // arp - - return append(ethernetHeader, datagram.Marshal()...) -} - -func (datagram arpDatagram) SenderIP() net.IP { - return net.IP(datagram.spa) -} -func (datagram arpDatagram) SenderMac() net.HardwareAddr { - return net.HardwareAddr(datagram.sha) -} - -func (datagram arpDatagram) IsResponseOf(request arpDatagram) bool { - return datagram.oper == responseOper && bytes.Equal(request.spa, datagram.tpa) && - bytes.Equal(request.tpa, datagram.spa) -} - -func parseArpDatagram(buffer []byte) arpDatagram { - var datagram arpDatagram - - b := bytes.NewBuffer(buffer) - binary.Read(b, binary.BigEndian, &datagram.htype) - binary.Read(b, binary.BigEndian, &datagram.ptype) - binary.Read(b, binary.BigEndian, &datagram.hlen) - binary.Read(b, binary.BigEndian, &datagram.plen) - binary.Read(b, binary.BigEndian, &datagram.oper) - - haLen := int(datagram.hlen) - paLen := int(datagram.plen) - datagram.sha = b.Next(haLen) - datagram.spa = b.Next(paLen) - datagram.tha = b.Next(haLen) - datagram.tpa = b.Next(paLen) - - return datagram -} diff --git a/vendor/github.com/j-keck/arping/arping.go b/vendor/github.com/j-keck/arping/arping.go deleted file mode 100644 index b305731db..000000000 --- a/vendor/github.com/j-keck/arping/arping.go +++ /dev/null @@ -1,233 +0,0 @@ -// Package arping is a native go library to ping a host per arp datagram, or query a host mac address -// -// The currently supported platforms are: Linux and BSD. -// -// -// The library requires raw socket access. So it must run as root, or with appropriate capabilities under linux: -// `sudo setcap cap_net_raw+ep `. -// -// -// Examples: -// -// ping a host: -// ------------ -// package main -// import ("fmt"; "github.com/j-keck/arping"; "net") -// -// func main(){ -// dstIP := net.ParseIP("192.168.1.1") -// if hwAddr, duration, err := arping.Ping(dstIP); err != nil { -// fmt.Println(err) -// } else { -// fmt.Printf("%s (%s) %d usec\n", dstIP, hwAddr, duration/1000) -// } -// } -// -// -// resolve mac address: -// -------------------- -// package main -// import ("fmt"; "github.com/j-keck/arping"; "net") -// -// func main(){ -// dstIP := net.ParseIP("192.168.1.1") -// if hwAddr, _, err := arping.Ping(dstIP); err != nil { -// fmt.Println(err) -// } else { -// fmt.Printf("%s is at %s\n", dstIP, hwAddr) -// } -// } -// -// -// check if host is online: -// ------------------------ -// package main -// import ("fmt"; "github.com/j-keck/arping"; "net") -// -// func main(){ -// dstIP := net.ParseIP("192.168.1.1") -// _, _, err := arping.Ping(dstIP) -// if err == arping.ErrTimeout { -// fmt.Println("offline") -// }else if err != nil { -// fmt.Println(err.Error()) -// }else{ -// fmt.Println("online") -// } -// } -// -package arping - -import ( - "errors" - "fmt" - "io/ioutil" - "log" - "net" - "os" - "time" -) - -var ( - // ErrTimeout error - ErrTimeout = errors.New("timeout") - - verboseLog = log.New(ioutil.Discard, "", 0) - timeout = time.Duration(500 * time.Millisecond) -) - -// Ping sends an arp ping to 'dstIP' -func Ping(dstIP net.IP) (net.HardwareAddr, time.Duration, error) { - if err := validateIP(dstIP); err != nil { - return nil, 0, err - } - - iface, err := findUsableInterfaceForNetwork(dstIP) - if err != nil { - return nil, 0, err - } - return PingOverIface(dstIP, *iface) -} - -// PingOverIfaceByName sends an arp ping over interface name 'ifaceName' to 'dstIP' -func PingOverIfaceByName(dstIP net.IP, ifaceName string) (net.HardwareAddr, time.Duration, error) { - if err := validateIP(dstIP); err != nil { - return nil, 0, err - } - - iface, err := net.InterfaceByName(ifaceName) - if err != nil { - return nil, 0, err - } - return PingOverIface(dstIP, *iface) -} - -// PingOverIface sends an arp ping over interface 'iface' to 'dstIP' -func PingOverIface(dstIP net.IP, iface net.Interface) (net.HardwareAddr, time.Duration, error) { - if err := validateIP(dstIP); err != nil { - return nil, 0, err - } - - srcMac := iface.HardwareAddr - srcIP, err := findIPInNetworkFromIface(dstIP, iface) - if err != nil { - return nil, 0, err - } - - broadcastMac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - request := newArpRequest(srcMac, srcIP, broadcastMac, dstIP) - - sock, err := initialize(iface) - if err != nil { - return nil, 0, err - } - defer sock.deinitialize() - - type PingResult struct { - mac net.HardwareAddr - duration time.Duration - err error - } - pingResultChan := make(chan PingResult, 1) - - go func() { - // send arp request - verboseLog.Printf("arping '%s' over interface: '%s' with address: '%s'\n", dstIP, iface.Name, srcIP) - if sendTime, err := sock.send(request); err != nil { - pingResultChan <- PingResult{nil, 0, err} - } else { - for { - // receive arp response - response, receiveTime, err := sock.receive() - - if err != nil { - pingResultChan <- PingResult{nil, 0, err} - return - } - - if response.IsResponseOf(request) { - duration := receiveTime.Sub(sendTime) - verboseLog.Printf("process received arp: srcIP: '%s', srcMac: '%s'\n", - response.SenderIP(), response.SenderMac()) - pingResultChan <- PingResult{response.SenderMac(), duration, err} - return - } - - verboseLog.Printf("ignore received arp: srcIP: '%s', srcMac: '%s'\n", - response.SenderIP(), response.SenderMac()) - } - } - }() - - select { - case pingResult := <-pingResultChan: - return pingResult.mac, pingResult.duration, pingResult.err - case <-time.After(timeout): - sock.deinitialize() - return nil, 0, ErrTimeout - } -} - -// GratuitousArp sends an gratuitous arp from 'srcIP' -func GratuitousArp(srcIP net.IP) error { - if err := validateIP(srcIP); err != nil { - return err - } - - iface, err := findUsableInterfaceForNetwork(srcIP) - if err != nil { - return err - } - return GratuitousArpOverIface(srcIP, *iface) -} - -// GratuitousArpOverIfaceByName sends an gratuitous arp over interface name 'ifaceName' from 'srcIP' -func GratuitousArpOverIfaceByName(srcIP net.IP, ifaceName string) error { - if err := validateIP(srcIP); err != nil { - return err - } - - iface, err := net.InterfaceByName(ifaceName) - if err != nil { - return err - } - return GratuitousArpOverIface(srcIP, *iface) -} - -// GratuitousArpOverIface sends an gratuitous arp over interface 'iface' from 'srcIP' -func GratuitousArpOverIface(srcIP net.IP, iface net.Interface) error { - if err := validateIP(srcIP); err != nil { - return err - } - - srcMac := iface.HardwareAddr - broadcastMac := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - request := newArpRequest(srcMac, srcIP, broadcastMac, srcIP) - - sock, err := initialize(iface) - if err != nil { - return err - } - defer sock.deinitialize() - verboseLog.Printf("gratuitous arp over interface: '%s' with address: '%s'\n", iface.Name, srcIP) - _, err = sock.send(request) - return err -} - -// EnableVerboseLog enables verbose logging on stdout -func EnableVerboseLog() { - verboseLog = log.New(os.Stdout, "", 0) -} - -// SetTimeout sets ping timeout -func SetTimeout(t time.Duration) { - timeout = t -} - -func validateIP(ip net.IP) error { - // ip must be a valid V4 address - if len(ip.To4()) != net.IPv4len { - return fmt.Errorf("not a valid v4 Address: %s", ip) - } - return nil -} diff --git a/vendor/github.com/j-keck/arping/arping_bsd.go b/vendor/github.com/j-keck/arping/arping_bsd.go deleted file mode 100644 index 5176fc65b..000000000 --- a/vendor/github.com/j-keck/arping/arping_bsd.go +++ /dev/null @@ -1,104 +0,0 @@ -// +build darwin freebsd openbsd - -package arping - -import ( - "errors" - "fmt" - "net" - "os" - "runtime" - "syscall" - "time" -) - -type BsdSocket struct { - bpf *os.File - bpfFd int - buflen int -} - -var bpfArpFilter = []syscall.BpfInsn{ - // make sure this is an arp packet - *syscall.BpfStmt(syscall.BPF_LD+syscall.BPF_H+syscall.BPF_ABS, 12), - *syscall.BpfJump(syscall.BPF_JMP+syscall.BPF_JEQ+syscall.BPF_K, 0x0806, 0, 1), - // if we passed all the tests, ask for the whole packet. - *syscall.BpfStmt(syscall.BPF_RET+syscall.BPF_K, -1), - // otherwise, drop it. - *syscall.BpfStmt(syscall.BPF_RET+syscall.BPF_K, 0), -} - -func initialize(iface net.Interface) (s *BsdSocket, err error) { - s = &BsdSocket{} - verboseLog.Println("search available /dev/bpfX") - for i := 0; i <= 10; i++ { - bpfPath := fmt.Sprintf("/dev/bpf%d", i) - s.bpf, err = os.OpenFile(bpfPath, os.O_RDWR, 0666) - if err != nil { - verboseLog.Printf(" open failed: %s - %s\n", bpfPath, err.Error()) - } else { - verboseLog.Printf(" open success: %s\n", bpfPath) - break - } - } - s.bpfFd = int(s.bpf.Fd()) - if s.bpfFd == -1 { - return s, errors.New("unable to open /dev/bpfX") - } - - if err := syscall.SetBpfInterface(s.bpfFd, iface.Name); err != nil { - return s, err - } - - if err := syscall.SetBpfImmediate(s.bpfFd, 1); err != nil { - return s, err - } - - s.buflen, err = syscall.BpfBuflen(s.bpfFd) - if err != nil { - return s, err - } - - if err := syscall.SetBpf(s.bpfFd, bpfArpFilter); err != nil { - return s, err - } - - if err := syscall.FlushBpf(s.bpfFd); err != nil { - return s, err - } - - return s, nil -} - -func (s *BsdSocket) send(request arpDatagram) (time.Time, error) { - _, err := syscall.Write(s.bpfFd, request.MarshalWithEthernetHeader()) - return time.Now(), err -} - -func (s *BsdSocket) receive() (arpDatagram, time.Time, error) { - buffer := make([]byte, s.buflen) - n, err := syscall.Read(s.bpfFd, buffer) - if err != nil { - return arpDatagram{}, time.Now(), err - } - - // - // FreeBSD uses a different bpf header (bh_tstamp differ in it's size) - // https://www.freebsd.org/cgi/man.cgi?bpf(4)#BPF_HEADER - // - var bpfHdrLength int - if runtime.GOOS == "freebsd" { - bpfHdrLength = 26 - } else { - bpfHdrLength = 18 - } - - // skip bpf header + 14 bytes ethernet header - var hdrLength = bpfHdrLength + 14 - - return parseArpDatagram(buffer[hdrLength:n]), time.Now(), nil -} - -func (s *BsdSocket) deinitialize() error { - return s.bpf.Close() -} diff --git a/vendor/github.com/j-keck/arping/arping_linux.go b/vendor/github.com/j-keck/arping/arping_linux.go deleted file mode 100644 index b03df6c96..000000000 --- a/vendor/github.com/j-keck/arping/arping_linux.go +++ /dev/null @@ -1,43 +0,0 @@ -package arping - -import ( - "net" - "syscall" - "time" -) - -type LinuxSocket struct { - sock int - toSockaddr syscall.SockaddrLinklayer -} - -func initialize(iface net.Interface) (s *LinuxSocket, err error) { - s = &LinuxSocket{} - s.toSockaddr = syscall.SockaddrLinklayer{Ifindex: iface.Index} - - // 1544 = htons(ETH_P_ARP) - const proto = 1544 - s.sock, err = syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, proto) - return s, err -} - -func (s *LinuxSocket) send(request arpDatagram) (time.Time, error) { - return time.Now(), syscall.Sendto(s.sock, request.MarshalWithEthernetHeader(), 0, &s.toSockaddr) -} - -func (s *LinuxSocket) receive() (arpDatagram, time.Time, error) { - buffer := make([]byte, 128) - socketTimeout := timeout.Nanoseconds() * 2 - t := syscall.NsecToTimeval(socketTimeout) - syscall.SetsockoptTimeval(s.sock, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &t) - n, _, err := syscall.Recvfrom(s.sock, buffer, 0) - if err != nil { - return arpDatagram{}, time.Now(), err - } - // skip 14 bytes ethernet header - return parseArpDatagram(buffer[14:n]), time.Now(), nil -} - -func (s *LinuxSocket) deinitialize() error { - return syscall.Close(s.sock) -} diff --git a/vendor/github.com/j-keck/arping/arping_windows.go b/vendor/github.com/j-keck/arping/arping_windows.go deleted file mode 100644 index abe302d91..000000000 --- a/vendor/github.com/j-keck/arping/arping_windows.go +++ /dev/null @@ -1,28 +0,0 @@ -// windows currently not supported. -// dummy implementation to prevent compilation errors under windows - -package arping - -import ( - "errors" - "net" - "time" -) - -var errWindowsNotSupported = errors.New("arping under windows not supported") - -func initialize(iface net.Interface) error { - return errWindowsNotSupported -} - -func send(request arpDatagram) (time.Time, error) { - return time.Now(), errWindowsNotSupported -} - -func receive() (arpDatagram, time.Time, error) { - return arpDatagram{}, time.Now(), errWindowsNotSupported -} - -func deinitialize() error { - return errWindowsNotSupported -} diff --git a/vendor/github.com/j-keck/arping/go.mod b/vendor/github.com/j-keck/arping/go.mod deleted file mode 100644 index 04c772bee..000000000 --- a/vendor/github.com/j-keck/arping/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/j-keck/arping - -go 1.12 diff --git a/vendor/github.com/j-keck/arping/netutils.go b/vendor/github.com/j-keck/arping/netutils.go deleted file mode 100644 index 2b707d3c0..000000000 --- a/vendor/github.com/j-keck/arping/netutils.go +++ /dev/null @@ -1,64 +0,0 @@ -package arping - -import ( - "errors" - "fmt" - "net" -) - -func findIPInNetworkFromIface(dstIP net.IP, iface net.Interface) (net.IP, error) { - addrs, err := iface.Addrs() - - if err != nil { - return nil, err - } - - for _, a := range addrs { - if ipnet, ok := a.(*net.IPNet); ok { - if ipnet.Contains(dstIP) { - return ipnet.IP, nil - } - } - } - return nil, fmt.Errorf("iface: '%s' can't reach ip: '%s'", iface.Name, dstIP) -} - -func findUsableInterfaceForNetwork(dstIP net.IP) (*net.Interface, error) { - ifaces, err := net.Interfaces() - - if err != nil { - return nil, err - } - - isDown := func(iface net.Interface) bool { - return iface.Flags&1 == 0 - } - - hasAddressInNetwork := func(iface net.Interface) bool { - if _, err := findIPInNetworkFromIface(dstIP, iface); err != nil { - return false - } - return true - } - - verboseLog.Println("search usable interface") - logIfaceResult := func(msg string, iface net.Interface) { - verboseLog.Printf("%10s: %6s %18s %s", msg, iface.Name, iface.HardwareAddr, iface.Flags) - } - - for _, iface := range ifaces { - if isDown(iface) { - logIfaceResult("DOWN", iface) - continue - } - - if !hasAddressInNetwork(iface) { - logIfaceResult("OTHER NET", iface) - continue - } - - logIfaceResult("USABLE", iface) - return &iface, nil - } - return nil, errors.New("no usable interface found") -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 222f8e753..f3e581297 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -78,9 +78,6 @@ github.com/gogo/protobuf/proto github.com/gogo/protobuf/protoc-gen-gogo/descriptor # github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e github.com/golang/groupcache/lru -# github.com/j-keck/arping v1.0.2 -## explicit -github.com/j-keck/arping # github.com/mattn/go-shellwords v1.0.12 ## explicit github.com/mattn/go-shellwords