blob: 4e47e6172096a3aa12a694404f173dbbd3cdc2db [file] [log] [blame]
khenaidoo26721882021-08-11 17:42:52 -04001// Copyright 2019 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package procfs
15
16import (
17 "fmt"
18 "io/ioutil"
19 "net"
20 "strings"
21)
22
23// ARPEntry contains a single row of the columnar data represented in
24// /proc/net/arp.
25type ARPEntry struct {
26 // IP address
27 IPAddr net.IP
28 // MAC address
29 HWAddr net.HardwareAddr
30 // Name of the device
31 Device string
32}
33
34// GatherARPEntries retrieves all the ARP entries, parse the relevant columns,
35// and then return a slice of ARPEntry's.
36func (fs FS) GatherARPEntries() ([]ARPEntry, error) {
37 data, err := ioutil.ReadFile(fs.proc.Path("net/arp"))
38 if err != nil {
39 return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err)
40 }
41
42 return parseARPEntries(data)
43}
44
45func parseARPEntries(data []byte) ([]ARPEntry, error) {
46 lines := strings.Split(string(data), "\n")
47 entries := make([]ARPEntry, 0)
48 var err error
49 const (
50 expectedDataWidth = 6
51 expectedHeaderWidth = 9
52 )
53 for _, line := range lines {
54 columns := strings.Fields(line)
55 width := len(columns)
56
57 if width == expectedHeaderWidth || width == 0 {
58 continue
59 } else if width == expectedDataWidth {
60 entry, err := parseARPEntry(columns)
61 if err != nil {
62 return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %w", err)
63 }
64 entries = append(entries, entry)
65 } else {
66 return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth)
67 }
68
69 }
70
71 return entries, err
72}
73
74func parseARPEntry(columns []string) (ARPEntry, error) {
75 ip := net.ParseIP(columns[0])
76 mac := net.HardwareAddr(columns[3])
77
78 entry := ARPEntry{
79 IPAddr: ip,
80 HWAddr: mac,
81 Device: columns[5],
82 }
83
84 return entry, nil
85}