Skip to content

Commit

Permalink
fix: fix Linux default network interface parsing (#331)
Browse files Browse the repository at this point in the history
Fixes #317

This fix resolves a problem where the header line of
/proc/net/route is skipped twice when running on Linux.
Additionally, this change also adds error checking to the Scanner
performing the parsing operation.
  • Loading branch information
dekobon authored Jun 8, 2023
1 parent a0d027a commit d291ed7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 49 deletions.
48 changes: 26 additions & 22 deletions src/core/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,20 +292,21 @@ func parseToLinuxRouteStruct(output []byte) (routeStruct, error) {
const (
destinationField = 1 // field containing hex destination address
)
lineNumber := 0
scanner := bufio.NewScanner(bytes.NewReader(output))

// Skip header line
if !scanner.Scan() {
return routeStruct{}, errors.New("Invalid linux route file")
if scanner.Err() == nil {
return routeStruct{}, errors.New("invalid linux route file: no header line")
} else {
return routeStruct{}, fmt.Errorf("invalid linux route file: %w", scanner.Err())
}
}

lineNumber := 0

for scanner.Scan() {
lineNumber++
if lineNumber == 1 {
// Skip header line.
continue
}
row := scanner.Text()
tokens := strings.Fields(strings.TrimSpace(row))
if len(tokens) < 11 {
Expand All @@ -325,25 +326,28 @@ func parseToLinuxRouteStruct(output []byte) (routeStruct, error) {
}

// The default interface is the one that's 0
if destination != 0 {
continue
if destination == 0 {
return routeStruct{
Iface: tokens[0],
Destination: tokens[1],
Gateway: tokens[2],
Flags: tokens[3],
RefCnt: tokens[4],
Use: tokens[5],
Metric: tokens[6],
Mask: tokens[7],
MTU: tokens[8],
Window: tokens[9],
IRTT: tokens[10],
}, nil
}
}

return routeStruct{
Iface: tokens[0],
Destination: tokens[1],
Gateway: tokens[2],
Flags: tokens[3],
RefCnt: tokens[4],
Use: tokens[5],
Metric: tokens[6],
Mask: tokens[7],
MTU: tokens[8],
Window: tokens[9],
IRTT: tokens[10],
}, nil
if scanner.Err() == nil {
return routeStruct{}, errors.New("interface with default destination not found")
} else {
return routeStruct{}, fmt.Errorf("invalid linux route file: %w", scanner.Err())
}
return routeStruct{}, errors.New("interface with default destination not found")
}

func ipv6ToStr(ip []byte) string {
Expand Down
8 changes: 3 additions & 5 deletions src/core/network/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ func TestParseToLinuxRouteStruct(t *testing.T) {
err error
}{
{
input: []byte(`
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
input: []byte(`Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
enp0s3 0002000A 00000000 0001 0 0 0 00FFFFFF 0 0 0
enp0s3 0202000A 00000000 0005 0 0 100 FFFFFFFF 0 0 0
enp0s3 00000000 0202000A 0003 0 0 100 00000000 0 0 0
Expand All @@ -44,15 +43,14 @@ func TestParseToLinuxRouteStruct(t *testing.T) {
err: nil,
},
{
input: []byte(`
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT`),
input: []byte(`Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT`),
expected: routeStruct{},
err: errors.New("interface with default destination not found"),
},
{
input: []byte(``),
expected: routeStruct{},
err: errors.New("Invalid linux route file"),
err: errors.New("invalid linux route file: no header line"),
},
}
for _, test := range tests {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d291ed7

Please sign in to comment.