Skip to content

Commit

Permalink
Fixed ARP table MAC address parsing, added Flags field (prometheus#414)
Browse files Browse the repository at this point in the history
* fixed arp table mac address parsing

- Added ARPEntry.Flags field related to entry flags
- Added ARPEntry.IsComplete() to check if entry is complete
- Fixed mac address parsing and error handling
- Test improved with incomplete entry information
Closes prometheus#413.

Signed-off-by: Serhii Zasenko <sergii@zasenko.name>

* Arp flag const names cleanup

Signed-off-by: Serhii Zasenko <sergii@zasenko.name>
  • Loading branch information
und3f committed Sep 20, 2021
1 parent 0154bf0 commit 477e12f
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 8 deletions.
41 changes: 36 additions & 5 deletions arp.go
Expand Up @@ -17,9 +17,26 @@ import (
"fmt"
"io/ioutil"
"net"
"strconv"
"strings"
)

// Learned from include/uapi/linux/if_arp.h
const (
// completed entry (ha valid)
ATFComplete = 0x02
// permanent entry
ATFPermanent = 0x04
// Publish entry
ATFPublish = 0x08
// Has requested trailers
ATFUseTrailers = 0x10
// Obsoleted: Want to use a netmask (only for proxy entries)
ATFNetmask = 0x20
// Don't answer this addresses
ATFDontPublish = 0x40
)

// ARPEntry contains a single row of the columnar data represented in
// /proc/net/arp.
type ARPEntry struct {
Expand All @@ -29,6 +46,8 @@ type ARPEntry struct {
HWAddr net.HardwareAddr
// Name of the device
Device string
// Flags
Flags byte
}

// GatherARPEntries retrieves all the ARP entries, parse the relevant columns,
Expand Down Expand Up @@ -72,14 +91,26 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) {
}

func parseARPEntry(columns []string) (ARPEntry, error) {
entry := ARPEntry{Device: columns[5]}
ip := net.ParseIP(columns[0])
mac := net.HardwareAddr(columns[3])
entry.IPAddr = ip

if mac, err := net.ParseMAC(columns[3]); err == nil {
entry.HWAddr = mac
} else {
return ARPEntry{}, err
}

entry := ARPEntry{
IPAddr: ip,
HWAddr: mac,
Device: columns[5],
if flags, err := strconv.ParseUint(columns[2], 0, 8); err == nil {
entry.Flags = byte(flags)
} else {
return ARPEntry{}, err
}

return entry, nil
}

// IsComplete returns true if ARP entry is marked with complete flag
func (entry *ARPEntry) IsComplete() bool {
return entry.Flags&ATFComplete != 0
}
28 changes: 26 additions & 2 deletions arp_test.go
Expand Up @@ -33,11 +33,35 @@ func TestARP(t *testing.T) {
t.Errorf("want 192.168.224.1, got %s", got)
}

if want, got := net.HardwareAddr("00:50:56:c0:00:08").String(), arpFile[0].HWAddr.String(); want != got {
t.Errorf("want 00:50:56:c0:00:08, got %s", got)
if want, got := "00:50:56:c0:00:08", arpFile[0].HWAddr.String(); want != got {
t.Errorf("want %s, got %s", want, got)
}

if want, got := "ens33", arpFile[0].Device; want != got {
t.Errorf("want ens33, got %s", got)
}

if want, got := true, arpFile[0].IsComplete(); want != got {
t.Errorf("want %t, got %t", want, got)
}

if want, got := "192.168.224.2", arpFile[1].IPAddr.String(); want != got {
t.Errorf("want 192.168.224.2, got %s", got)
}

if want, got := make(net.HardwareAddr, 6).String(), arpFile[1].HWAddr.String(); want != got {
t.Errorf("expected empty MAC, got %s", got)
}

if want, got := "ens33", arpFile[1].Device; want != got {
t.Errorf("want %s, got %s", want, got)
}

if want, got := byte(0x0), arpFile[1].Flags; want != got {
t.Errorf("want %b, got %b", want, got)
}

if want, got := false, arpFile[1].IsComplete(); want != got {
t.Errorf("want %t, got %t", want, got)
}
}
3 changes: 2 additions & 1 deletion fixtures.ttar
Expand Up @@ -2084,9 +2084,10 @@ Directory: fixtures/proc/net
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/arp
Lines: 2
Lines: 3
IP address HW type Flags HW address Mask Device
192.168.224.1 0x1 0x2 00:50:56:c0:00:08 * ens33
192.168.224.2 0x1 0x0 00:00:00:00:00:00 * ens33
Mode: 664
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/proc/net/dev
Expand Down

0 comments on commit 477e12f

Please sign in to comment.