...

Source file src/github.com/mdlayher/arp/cmd/proxyarpd/main.go

Documentation: github.com/mdlayher/arp/cmd/proxyarpd

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"flag"
     6  	"io"
     7  	"log"
     8  	"net"
     9  	"net/netip"
    10  
    11  	"github.com/mdlayher/arp"
    12  	"github.com/mdlayher/ethernet"
    13  )
    14  
    15  var (
    16  	// ifaceFlag is used to set a network interface for ARP traffic
    17  	ifaceFlag = flag.String("i", "eth0", "network interface to use for ARP traffic")
    18  
    19  	// ipFlag is used to set an IPv4 address to proxy ARP on behalf of
    20  	ipFlag = flag.String("ip", "", "IP address for device to proxy ARP on behalf of")
    21  )
    22  
    23  func main() {
    24  	flag.Parse()
    25  
    26  	// Ensure valid interface and IPv4 address
    27  	ifi, err := net.InterfaceByName(*ifaceFlag)
    28  	if err != nil {
    29  		log.Fatal(err)
    30  	}
    31  	ip, err := netip.ParseAddr(*ipFlag)
    32  	if err != nil || !ip.Is4() {
    33  		log.Fatalf("invalid IPv4 address: %q", *ipFlag)
    34  	}
    35  
    36  	client, err := arp.Dial(ifi)
    37  	if err != nil {
    38  		log.Fatalf("couldn't create ARP client: %s", err)
    39  	}
    40  
    41  	// Handle ARP requests bound for designated IPv4 address, using proxy ARP
    42  	// to indicate that the address belongs to this machine
    43  	for {
    44  		pkt, eth, err := client.Read()
    45  		if err != nil {
    46  			if err == io.EOF {
    47  				log.Println("EOF")
    48  				break
    49  			}
    50  			log.Fatalf("error processing ARP requests: %s", err)
    51  		}
    52  
    53  		// Ignore ARP replies
    54  		if pkt.Operation != arp.OperationRequest {
    55  			continue
    56  		}
    57  
    58  		// Ignore ARP requests which are not broadcast or bound directly for
    59  		// this machine
    60  		if !bytes.Equal(eth.Destination, ethernet.Broadcast) && !bytes.Equal(eth.Destination, ifi.HardwareAddr) {
    61  			continue
    62  		}
    63  
    64  		log.Printf("request: who-has %s?  tell %s (%s)", pkt.TargetIP, pkt.SenderIP, pkt.SenderHardwareAddr)
    65  
    66  		// Ignore ARP requests which do not indicate the target IP
    67  		if pkt.TargetIP != ip {
    68  			continue
    69  		}
    70  
    71  		log.Printf("  reply: %s is-at %s", ip, ifi.HardwareAddr)
    72  		if err := client.Reply(pkt, ifi.HardwareAddr, ip); err != nil {
    73  			log.Fatal(err)
    74  		}
    75  	}
    76  }
    77  

View as plain text