func SendGratuitousARPReply(ip string, iface string) error { // Set up ARP client with socket ifi, err := net.InterfaceByName(iface) if err != nil { return err } c, err := arp.NewClient(ifi) if err != nil { return err } // Set request deadline from flag if err := c.SetDeadline(time.Now().Add(1 * time.Second)); err != nil { return err } srcIp := net.ParseIP(ip).To4() packet, err := arp.NewPacket(arp.OperationReply, ifi.HardwareAddr, srcIp, ethernetBroadcast, net.IPv4bcast) if err != nil { return err } if err := c.WriteTo(packet, ethernetBroadcast); err != nil { return err } // Clean up ARP client socket _ = c.Close() return nil }
func main() { flag.Parse() // Ensure valid interface and IPv4 address ifi, err := net.InterfaceByName(*ifaceFlag) if err != nil { log.Fatal(err) } ip := net.ParseIP(*ipFlag).To4() if ip == nil { log.Fatalf("invalid IPv4 address: %q", *ipFlag) } // Handle ARP requests bound for designated IPv4 address, using proxy ARP // to indicate that the address belongs to this machine arp.HandleFunc(arp.OperationRequest, func(w arp.ResponseSender, r *arp.Request) { // Ignore ARP requests which are not broadcast or bound directly for // this machine if !bytes.Equal(r.TargetHardwareAddr, ethernet.Broadcast) && !bytes.Equal(r.TargetHardwareAddr, ifi.HardwareAddr) { return } log.Printf("request: who-has %s? tell %s (%s)", r.TargetIP, r.SenderIP, r.SenderHardwareAddr) // Ignore ARP requests which do not indicate the target IP if !bytes.Equal(r.TargetIP, ip) { return } // Send reply indicating that this machine has the requested // IP address p, err := arp.NewPacket( arp.OperationReply, ifi.HardwareAddr, ip, r.SenderHardwareAddr, r.SenderIP, ) if err != nil { log.Fatal(err) } log.Printf(" reply: %s is-at %s", ip, ifi.HardwareAddr) if _, err := w.Send(p); err != nil { log.Fatal(err) } }) if err := arp.ListenAndServe(*ifaceFlag, nil); err != nil { log.Fatal(err) } }