mirror of
https://github.com/golang/go
synced 2024-11-22 05:34:39 -07:00
net: make parseProcNetIGMP more robust
Suggested by Paul Borman. Fixes #2826. R=rsc, borman CC=golang-dev https://golang.org/cl/5689048
This commit is contained in:
parent
880cda557a
commit
9765325d49
@ -166,13 +166,13 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ifmat4 := parseProcNetIGMP(ifi)
|
ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi)
|
||||||
ifmat6 := parseProcNetIGMP6(ifi)
|
ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi)
|
||||||
return append(ifmat4, ifmat6...), nil
|
return append(ifmat4, ifmat6...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProcNetIGMP(ifi *Interface) []Addr {
|
func parseProcNetIGMP(path string, ifi *Interface) []Addr {
|
||||||
fd, err := open("/proc/net/igmp")
|
fd, err := open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -185,23 +185,26 @@ func parseProcNetIGMP(ifi *Interface) []Addr {
|
|||||||
fd.readLine() // skip first line
|
fd.readLine() // skip first line
|
||||||
b := make([]byte, IPv4len)
|
b := make([]byte, IPv4len)
|
||||||
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
|
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
|
||||||
f := getFields(l)
|
f := splitAtBytes(l, " :\r\t\n")
|
||||||
switch len(f) {
|
if len(f) < 4 {
|
||||||
case 4:
|
continue
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case l[0] != ' ' && l[0] != '\t': // new interface line
|
||||||
|
name = f[1]
|
||||||
|
case len(f[0]) == 8:
|
||||||
if ifi == nil || name == ifi.Name {
|
if ifi == nil || name == ifi.Name {
|
||||||
fmt.Sscanf(f[0], "%08x", &b)
|
fmt.Sscanf(f[0], "%08x", &b)
|
||||||
ifma := IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])}
|
ifma := IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])}
|
||||||
ifmat = append(ifmat, ifma.toAddr())
|
ifmat = append(ifmat, ifma.toAddr())
|
||||||
}
|
}
|
||||||
case 5:
|
|
||||||
name = f[1]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ifmat
|
return ifmat
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProcNetIGMP6(ifi *Interface) []Addr {
|
func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
|
||||||
fd, err := open("/proc/net/igmp6")
|
fd, err := open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -210,7 +213,10 @@ func parseProcNetIGMP6(ifi *Interface) []Addr {
|
|||||||
var ifmat []Addr
|
var ifmat []Addr
|
||||||
b := make([]byte, IPv6len)
|
b := make([]byte, IPv6len)
|
||||||
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
|
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
|
||||||
f := getFields(l)
|
f := splitAtBytes(l, " \r\t\n")
|
||||||
|
if len(f) < 6 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if ifi == nil || f[1] == ifi.Name {
|
if ifi == nil || f[1] == ifi.Name {
|
||||||
fmt.Sscanf(f[2], "%32x", &b)
|
fmt.Sscanf(f[2], "%32x", &b)
|
||||||
ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
|
ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
|
||||||
|
54
src/pkg/net/interface_linux_test.go
Normal file
54
src/pkg/net/interface_linux_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
const (
|
||||||
|
numOfTestIPv4MCAddrs = 14
|
||||||
|
numOfTestIPv6MCAddrs = 18
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
igmpInterfaceTable = []Interface{
|
||||||
|
{Name: "lo"},
|
||||||
|
{Name: "eth0"}, {Name: "eth1"}, {Name: "eth2"},
|
||||||
|
{Name: "eth0.100"}, {Name: "eth0.101"}, {Name: "eth0.102"}, {Name: "eth0.103"},
|
||||||
|
{Name: "device1tap2"},
|
||||||
|
}
|
||||||
|
igmp6InterfaceTable = []Interface{
|
||||||
|
{Name: "lo"},
|
||||||
|
{Name: "eth0"}, {Name: "eth1"}, {Name: "eth2"},
|
||||||
|
{Name: "eth0.100"}, {Name: "eth0.101"}, {Name: "eth0.102"}, {Name: "eth0.103"},
|
||||||
|
{Name: "device1tap2"},
|
||||||
|
{Name: "pan0"},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseProcNet(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if p := recover(); p != nil {
|
||||||
|
t.Fatalf("panicked")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var ifmat4 []Addr
|
||||||
|
for _, ifi := range igmpInterfaceTable {
|
||||||
|
ifmat := parseProcNetIGMP("testdata/igmp", &ifi)
|
||||||
|
ifmat4 = append(ifmat4, ifmat...)
|
||||||
|
}
|
||||||
|
if len(ifmat4) != numOfTestIPv4MCAddrs {
|
||||||
|
t.Fatalf("parseProcNetIGMP returns %v addresses, expected %v", len(ifmat4), numOfTestIPv4MCAddrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ifmat6 []Addr
|
||||||
|
for _, ifi := range igmp6InterfaceTable {
|
||||||
|
ifmat := parseProcNetIGMP6("testdata/igmp6", &ifi)
|
||||||
|
ifmat6 = append(ifmat6, ifmat...)
|
||||||
|
}
|
||||||
|
if len(ifmat6) != numOfTestIPv6MCAddrs {
|
||||||
|
t.Fatalf("parseProcNetIGMP6 returns %v addresses, expected %v", len(ifmat6), numOfTestIPv6MCAddrs)
|
||||||
|
}
|
||||||
|
}
|
@ -31,17 +31,17 @@ func TestInterfaces(t *testing.T) {
|
|||||||
for _, ifi := range ift {
|
for _, ifi := range ift {
|
||||||
ifxi, err := InterfaceByIndex(ifi.Index)
|
ifxi, err := InterfaceByIndex(ifi.Index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("InterfaceByIndex(%#q) failed: %v", ifi.Index, err)
|
t.Fatalf("InterfaceByIndex(%q) failed: %v", ifi.Index, err)
|
||||||
}
|
}
|
||||||
if !sameInterface(ifxi, &ifi) {
|
if !sameInterface(ifxi, &ifi) {
|
||||||
t.Fatalf("InterfaceByIndex(%#q) = %v, want %v", ifi.Index, *ifxi, ifi)
|
t.Fatalf("InterfaceByIndex(%q) = %v, want %v", ifi.Index, *ifxi, ifi)
|
||||||
}
|
}
|
||||||
ifxn, err := InterfaceByName(ifi.Name)
|
ifxn, err := InterfaceByName(ifi.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("InterfaceByName(%#q) failed: %v", ifi.Name, err)
|
t.Fatalf("InterfaceByName(%q) failed: %v", ifi.Name, err)
|
||||||
}
|
}
|
||||||
if !sameInterface(ifxn, &ifi) {
|
if !sameInterface(ifxn, &ifi) {
|
||||||
t.Fatalf("InterfaceByName(%#q) = %v, want %v", ifi.Name, *ifxn, ifi)
|
t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, *ifxn, ifi)
|
||||||
}
|
}
|
||||||
t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
|
t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
|
||||||
t.Logf("\thardware address %q", ifi.HardwareAddr.String())
|
t.Logf("\thardware address %q", ifi.HardwareAddr.String())
|
||||||
|
@ -67,7 +67,7 @@ func open(name string) (*file, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &file{fd, make([]byte, 1024)[0:0], false}, nil
|
return &file{fd, make([]byte, os.Getpagesize())[0:0], false}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func byteIndex(s string, c byte) int {
|
func byteIndex(s string, c byte) int {
|
||||||
|
24
src/pkg/net/testdata/igmp
vendored
Normal file
24
src/pkg/net/testdata/igmp
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Idx Device : Count Querier Group Users Timer Reporter
|
||||||
|
1 lo : 1 V3
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
2 eth0 : 2 V2
|
||||||
|
FB0000E0 1 0:00000000 1
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
3 eth1 : 1 V3
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
4 eth2 : 1 V3
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
5 eth0.100 : 2 V3
|
||||||
|
FB0000E0 1 0:00000000 0
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
6 eth0.101 : 2 V3
|
||||||
|
FB0000E0 1 0:00000000 0
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
7 eth0.102 : 2 V3
|
||||||
|
FB0000E0 1 0:00000000 0
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
8 eth0.103 : 2 V3
|
||||||
|
FB0000E0 1 0:00000000 0
|
||||||
|
010000E0 1 0:00000000 0
|
||||||
|
9 device1tap2: 1 V3
|
||||||
|
010000E0 1 0:00000000 0
|
18
src/pkg/net/testdata/igmp6
vendored
Normal file
18
src/pkg/net/testdata/igmp6
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
1 lo ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
2 eth0 ff0200000000000000000001ffac891e 1 00000006 0
|
||||||
|
2 eth0 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
3 eth1 ff0200000000000000000001ffac8928 2 00000006 0
|
||||||
|
3 eth1 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
4 eth2 ff0200000000000000000001ffac8932 2 00000006 0
|
||||||
|
4 eth2 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
5 eth0.100 ff0200000000000000000001ffac891e 1 00000004 0
|
||||||
|
5 eth0.100 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
6 pan0 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
7 eth0.101 ff0200000000000000000001ffac891e 1 00000004 0
|
||||||
|
7 eth0.101 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
8 eth0.102 ff0200000000000000000001ffac891e 1 00000004 0
|
||||||
|
8 eth0.102 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
9 eth0.103 ff0200000000000000000001ffac891e 1 00000004 0
|
||||||
|
9 eth0.103 ff020000000000000000000000000001 1 0000000C 0
|
||||||
|
10 device1tap2 ff0200000000000000000001ff4cc3a3 1 00000004 0
|
||||||
|
10 device1tap2 ff020000000000000000000000000001 1 0000000C 0
|
Loading…
Reference in New Issue
Block a user