You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

86 lines
2.2 KiB

  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. package procfs
  14. import (
  15. "fmt"
  16. "io/ioutil"
  17. "net"
  18. "strings"
  19. )
  20. // ARPEntry contains a single row of the columnar data represented in
  21. // /proc/net/arp.
  22. type ARPEntry struct {
  23. // IP address
  24. IPAddr net.IP
  25. // MAC address
  26. HWAddr net.HardwareAddr
  27. // Name of the device
  28. Device string
  29. }
  30. // GatherARPEntries retrieves all the ARP entries, parse the relevant columns,
  31. // and then return a slice of ARPEntry's.
  32. func (fs FS) GatherARPEntries() ([]ARPEntry, error) {
  33. data, err := ioutil.ReadFile(fs.proc.Path("net/arp"))
  34. if err != nil {
  35. return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err)
  36. }
  37. return parseARPEntries(data)
  38. }
  39. func parseARPEntries(data []byte) ([]ARPEntry, error) {
  40. lines := strings.Split(string(data), "\n")
  41. entries := make([]ARPEntry, 0)
  42. var err error
  43. const (
  44. expectedDataWidth = 6
  45. expectedHeaderWidth = 9
  46. )
  47. for _, line := range lines {
  48. columns := strings.Fields(line)
  49. width := len(columns)
  50. if width == expectedHeaderWidth || width == 0 {
  51. continue
  52. } else if width == expectedDataWidth {
  53. entry, err := parseARPEntry(columns)
  54. if err != nil {
  55. return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %w", err)
  56. }
  57. entries = append(entries, entry)
  58. } else {
  59. return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth)
  60. }
  61. }
  62. return entries, err
  63. }
  64. func parseARPEntry(columns []string) (ARPEntry, error) {
  65. ip := net.ParseIP(columns[0])
  66. mac := net.HardwareAddr(columns[3])
  67. entry := ARPEntry{
  68. IPAddr: ip,
  69. HWAddr: mac,
  70. Device: columns[5],
  71. }
  72. return entry, nil
  73. }