aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikio Hara <mikioh.mikioh@gmail.com>2012-02-23 06:26:31 +0900
committerMikio Hara <mikioh.mikioh@gmail.com>2012-02-23 06:26:31 +0900
commit9765325d4980b15c46b57663bdfd501a75b1f4e6 (patch)
tree9008c9952a08f7410a7b8afced8d6d2edfc134f0
parent880cda557a8cc638667916eac28e185e686e5878 (diff)
downloadgo-9765325d4980b15c46b57663bdfd501a75b1f4e6.tar.gz
go-9765325d4980b15c46b57663bdfd501a75b1f4e6.zip
net: make parseProcNetIGMP more robust
Suggested by Paul Borman. Fixes #2826. R=rsc, borman CC=golang-dev https://golang.org/cl/5689048
-rw-r--r--src/pkg/net/interface_linux.go30
-rw-r--r--src/pkg/net/interface_linux_test.go54
-rw-r--r--src/pkg/net/interface_test.go8
-rw-r--r--src/pkg/net/parse.go2
-rw-r--r--src/pkg/net/testdata/igmp24
-rw-r--r--src/pkg/net/testdata/igmp618
6 files changed, 119 insertions, 17 deletions
diff --git a/src/pkg/net/interface_linux.go b/src/pkg/net/interface_linux.go
index 21038c629b..15c2f3781b 100644
--- a/src/pkg/net/interface_linux.go
+++ b/src/pkg/net/interface_linux.go
@@ -166,13 +166,13 @@ func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
return nil, err
}
}
- ifmat4 := parseProcNetIGMP(ifi)
- ifmat6 := parseProcNetIGMP6(ifi)
+ ifmat4 := parseProcNetIGMP("/proc/net/igmp", ifi)
+ ifmat6 := parseProcNetIGMP6("/proc/net/igmp6", ifi)
return append(ifmat4, ifmat6...), nil
}
-func parseProcNetIGMP(ifi *Interface) []Addr {
- fd, err := open("/proc/net/igmp")
+func parseProcNetIGMP(path string, ifi *Interface) []Addr {
+ fd, err := open(path)
if err != nil {
return nil
}
@@ -185,23 +185,26 @@ func parseProcNetIGMP(ifi *Interface) []Addr {
fd.readLine() // skip first line
b := make([]byte, IPv4len)
for l, ok := fd.readLine(); ok; l, ok = fd.readLine() {
- f := getFields(l)
- switch len(f) {
- case 4:
+ f := splitAtBytes(l, " :\r\t\n")
+ if len(f) < 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 {
fmt.Sscanf(f[0], "%08x", &b)
ifma := IPAddr{IP: IPv4(b[3], b[2], b[1], b[0])}
ifmat = append(ifmat, ifma.toAddr())
}
- case 5:
- name = f[1]
}
}
return ifmat
}
-func parseProcNetIGMP6(ifi *Interface) []Addr {
- fd, err := open("/proc/net/igmp6")
+func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
+ fd, err := open(path)
if err != nil {
return nil
}
@@ -210,7 +213,10 @@ func parseProcNetIGMP6(ifi *Interface) []Addr {
var ifmat []Addr
b := make([]byte, IPv6len)
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 {
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]}}
diff --git a/src/pkg/net/interface_linux_test.go b/src/pkg/net/interface_linux_test.go
new file mode 100644
index 0000000000..f14d1fe06e
--- /dev/null
+++ b/src/pkg/net/interface_linux_test.go
@@ -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)
+ }
+}
diff --git a/src/pkg/net/interface_test.go b/src/pkg/net/interface_test.go
index 4ce01dc906..769414e0ee 100644
--- a/src/pkg/net/interface_test.go
+++ b/src/pkg/net/interface_test.go
@@ -31,17 +31,17 @@ func TestInterfaces(t *testing.T) {
for _, ifi := range ift {
ifxi, err := InterfaceByIndex(ifi.Index)
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) {
- 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)
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) {
- 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("\thardware address %q", ifi.HardwareAddr.String())
diff --git a/src/pkg/net/parse.go b/src/pkg/net/parse.go
index 4c4200a49b..7c87b42f6d 100644
--- a/src/pkg/net/parse.go
+++ b/src/pkg/net/parse.go
@@ -67,7 +67,7 @@ func open(name string) (*file, error) {
if err != nil {
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 {
diff --git a/src/pkg/net/testdata/igmp b/src/pkg/net/testdata/igmp
new file mode 100644
index 0000000000..5f380a2c7d
--- /dev/null
+++ b/src/pkg/net/testdata/igmp
@@ -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
diff --git a/src/pkg/net/testdata/igmp6 b/src/pkg/net/testdata/igmp6
new file mode 100644
index 0000000000..6cd5a2d4d9
--- /dev/null
+++ b/src/pkg/net/testdata/igmp6
@@ -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