From 42614f5e5bce108beecffc3816b88455dd3cec02 Mon Sep 17 00:00:00 2001 From: Nicolas Bouliane Date: Sun, 20 Mar 2022 13:26:10 -0400 Subject: [PATCH] arp: set and check arp state --- arp.go | 12 +++++++----- network.go | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/arp.go b/arp.go index 2e0c4b6..dd97321 100644 --- a/arp.go +++ b/arp.go @@ -54,12 +54,12 @@ const ( ) // Add either adds a new entry or updates an ArpEntry in the ArpTable syncmap. -func (t *ArpTable) Add(IP string, mac net.HardwareAddr, timeNow time.Time) error { +func (t *ArpTable) Add(IP string, mac net.HardwareAddr, timeNow time.Time, status ArpStatus) error { if IP == "" { return errors.New("valid IP address must be provided") } ip := net.ParseIP(IP) - t.ArpMap.Store(IP, &ArpEntry{IP: ip, Mac: mac, Status: StatusReady, Timestamp: timeNow}) + t.ArpMap.Store(IP, &ArpEntry{IP: ip, Mac: mac, Status: status, Timestamp: timeNow}) return nil } @@ -78,8 +78,10 @@ func (t *ArpTable) Get(IP string) (*ArpEntry, bool, error) { return nil, false, errors.New("invalid ARP entry type") } - if arpEntry.Mac == nil { - return nil, false, errors.New("invalid ARP entry") + // Update the status from waiting to stale to express that the waiting time (2seconds) has expired + // This will allow us to send again an ARP request + if arpEntry.Status == StatusWaiting && arpEntry.Timestamp.Add(time.Second*2).Before(time.Now()) { + arpEntry.Status = StatusStale } return arpEntry, found, nil @@ -138,7 +140,7 @@ func GenerateARPRequest(arpTable *ArpTable, srcMAC []byte, dstIP string, srcIP s // FIXME this function should be .Upsert() (Add or Update the entry) if arpTable != nil { - err := arpTable.Add(dstIP, net.HardwareAddr{}, time.Now()) + err := arpTable.Add(dstIP, net.HardwareAddr{}, time.Now(), StatusWaiting) if err != nil { return nil, fmt.Errorf("unable to add waiting ARP entry: %v", err) } diff --git a/network.go b/network.go index c3ad6f8..06ceb98 100644 --- a/network.go +++ b/network.go @@ -148,7 +148,7 @@ func ReadUTUN() { Lerror.Printf("unable to retrieve ARP entry for %v: %v", dstIP.String(), err) } - if found { + if found && entry.Status == StatusReady { // We found the destination MAC in the ARP table, continue to craft // the ethernet header of the IP packet. @@ -163,7 +163,7 @@ func ReadUTUN() { } Ldebug.Printf("wrote %d bytes to vswitch\n", b) - } else { + } else if !found || found && entry.Status == StatusStale { // TODO: Queue ethernet frame while ARP is being resolving the dst MAC address @@ -394,7 +394,7 @@ func connSwitch(ctx context.Context, cancel context.CancelFunc, config *tls.Conf if oper == OperationReply { Ldebug.Printf("Received ARP response\n") // We received an ARP response - err := arpTable.Add(spa.String(), sha, time.Now()) + err := arpTable.Add(spa.String(), sha, time.Now(), StatusReady) if err != nil { Lerror.Printf("unable to update ARP entry: %v", err) } @@ -405,7 +405,7 @@ func connSwitch(ctx context.Context, cancel context.CancelFunc, config *tls.Conf // ETH src MAC match the arp SHA AND arp SPA match TPA if bytes.Equal(frameBuf[10:16], frameBuf[26:32]) && bytes.Equal(frameBuf[32:36], frameBuf[42:46]) { Ldebug.Printf("we received an GARP") - arpTable.Add(spa.String(), sha, time.Now()) + arpTable.Add(spa.String(), sha, time.Now(), StatusReady) } else { // We received an ARP request, send a response sendBuf := GenerateARPReply(gMAC[0:6], sha, tpa, spa)