// 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 }