source: code/trunk/vendor/github.com/prometheus/procfs/arp.go@ 822

Last change on this file since 822 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 2.9 KB
RevLine 
[822]1// 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 "net"
19 "os"
20 "strconv"
21 "strings"
22)
23
24// Learned from include/uapi/linux/if_arp.h.
25const (
26 // completed entry (ha valid).
27 ATFComplete = 0x02
28 // permanent entry.
29 ATFPermanent = 0x04
30 // Publish entry.
31 ATFPublish = 0x08
32 // Has requested trailers.
33 ATFUseTrailers = 0x10
34 // Obsoleted: Want to use a netmask (only for proxy entries).
35 ATFNetmask = 0x20
36 // Don't answer this addresses.
37 ATFDontPublish = 0x40
38)
39
40// ARPEntry contains a single row of the columnar data represented in
41// /proc/net/arp.
42type ARPEntry struct {
43 // IP address
44 IPAddr net.IP
45 // MAC address
46 HWAddr net.HardwareAddr
47 // Name of the device
48 Device string
49 // Flags
50 Flags byte
51}
52
53// GatherARPEntries retrieves all the ARP entries, parse the relevant columns,
54// and then return a slice of ARPEntry's.
55func (fs FS) GatherARPEntries() ([]ARPEntry, error) {
56 data, err := os.ReadFile(fs.proc.Path("net/arp"))
57 if err != nil {
58 return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err)
59 }
60
61 return parseARPEntries(data)
62}
63
64func parseARPEntries(data []byte) ([]ARPEntry, error) {
65 lines := strings.Split(string(data), "\n")
66 entries := make([]ARPEntry, 0)
67 var err error
68 const (
69 expectedDataWidth = 6
70 expectedHeaderWidth = 9
71 )
72 for _, line := range lines {
73 columns := strings.Fields(line)
74 width := len(columns)
75
76 if width == expectedHeaderWidth || width == 0 {
77 continue
78 } else if width == expectedDataWidth {
79 entry, err := parseARPEntry(columns)
80 if err != nil {
81 return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %w", err)
82 }
83 entries = append(entries, entry)
84 } else {
85 return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth)
86 }
87
88 }
89
90 return entries, err
91}
92
93func parseARPEntry(columns []string) (ARPEntry, error) {
94 entry := ARPEntry{Device: columns[5]}
95 ip := net.ParseIP(columns[0])
96 entry.IPAddr = ip
97
98 if mac, err := net.ParseMAC(columns[3]); err == nil {
99 entry.HWAddr = mac
100 } else {
101 return ARPEntry{}, err
102 }
103
104 if flags, err := strconv.ParseUint(columns[2], 0, 8); err == nil {
105 entry.Flags = byte(flags)
106 } else {
107 return ARPEntry{}, err
108 }
109
110 return entry, nil
111}
112
113// IsComplete returns true if ARP entry is marked with complete flag.
114func (entry *ARPEntry) IsComplete() bool {
115 return entry.Flags&ATFComplete != 0
116}
Note: See TracBrowser for help on using the repository browser.