| // Copyright 2023 The Prometheus Authors |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package procfs |
| |
| import ( |
| "bufio" |
| "bytes" |
| "fmt" |
| "io" |
| "strconv" |
| "strings" |
| |
| "github.com/prometheus/procfs/internal/util" |
| ) |
| |
| const ( |
| blackholeRepresentation string = "*" |
| blackholeIfaceName string = "blackhole" |
| routeLineColumns int = 11 |
| ) |
| |
| // A NetRouteLine represents one line from net/route. |
| type NetRouteLine struct { |
| Iface string |
| Destination uint32 |
| Gateway uint32 |
| Flags uint32 |
| RefCnt uint32 |
| Use uint32 |
| Metric uint32 |
| Mask uint32 |
| MTU uint32 |
| Window uint32 |
| IRTT uint32 |
| } |
| |
| func (fs FS) NetRoute() ([]NetRouteLine, error) { |
| return readNetRoute(fs.proc.Path("net", "route")) |
| } |
| |
| func readNetRoute(path string) ([]NetRouteLine, error) { |
| b, err := util.ReadFileNoStat(path) |
| if err != nil { |
| return nil, err |
| } |
| |
| routelines, err := parseNetRoute(bytes.NewReader(b)) |
| if err != nil { |
| return nil, fmt.Errorf("failed to read net route from %s: %w", path, err) |
| } |
| return routelines, nil |
| } |
| |
| func parseNetRoute(r io.Reader) ([]NetRouteLine, error) { |
| var routelines []NetRouteLine |
| |
| scanner := bufio.NewScanner(r) |
| scanner.Scan() |
| for scanner.Scan() { |
| fields := strings.Fields(scanner.Text()) |
| routeline, err := parseNetRouteLine(fields) |
| if err != nil { |
| return nil, err |
| } |
| routelines = append(routelines, *routeline) |
| } |
| return routelines, nil |
| } |
| |
| func parseNetRouteLine(fields []string) (*NetRouteLine, error) { |
| if len(fields) != routeLineColumns { |
| return nil, fmt.Errorf("invalid routeline, num of digits: %d", len(fields)) |
| } |
| iface := fields[0] |
| if iface == blackholeRepresentation { |
| iface = blackholeIfaceName |
| } |
| destination, err := strconv.ParseUint(fields[1], 16, 32) |
| if err != nil { |
| return nil, err |
| } |
| gateway, err := strconv.ParseUint(fields[2], 16, 32) |
| if err != nil { |
| return nil, err |
| } |
| flags, err := strconv.ParseUint(fields[3], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| refcnt, err := strconv.ParseUint(fields[4], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| use, err := strconv.ParseUint(fields[5], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| metric, err := strconv.ParseUint(fields[6], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| mask, err := strconv.ParseUint(fields[7], 16, 32) |
| if err != nil { |
| return nil, err |
| } |
| mtu, err := strconv.ParseUint(fields[8], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| window, err := strconv.ParseUint(fields[9], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| irtt, err := strconv.ParseUint(fields[10], 10, 32) |
| if err != nil { |
| return nil, err |
| } |
| routeline := &NetRouteLine{ |
| Iface: iface, |
| Destination: uint32(destination), |
| Gateway: uint32(gateway), |
| Flags: uint32(flags), |
| RefCnt: uint32(refcnt), |
| Use: uint32(use), |
| Metric: uint32(metric), |
| Mask: uint32(mask), |
| MTU: uint32(mtu), |
| Window: uint32(window), |
| IRTT: uint32(irtt), |
| } |
| return routeline, nil |
| } |