]> Cypherpunks repositories - gostls13.git/commitdiff
net: make parseProcNetIGMP more robust
authorMikio Hara <mikioh.mikioh@gmail.com>
Wed, 22 Feb 2012 21:26:31 +0000 (06:26 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Wed, 22 Feb 2012 21:26:31 +0000 (06:26 +0900)
Suggested by Paul Borman.

Fixes #2826.

R=rsc, borman
CC=golang-dev
https://golang.org/cl/5689048

src/pkg/net/interface_linux.go
src/pkg/net/interface_linux_test.go [new file with mode: 0644]
src/pkg/net/interface_test.go
src/pkg/net/parse.go
src/pkg/net/testdata/igmp [new file with mode: 0644]
src/pkg/net/testdata/igmp6 [new file with mode: 0644]

index 21038c629b13e42e1e1e52bbdf87e78eee1f89ec..15c2f3781b1d8ef1a9dbadd4c3ef4873b6fc6fca 100644 (file)
@@ -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 (file)
index 0000000..f14d1fe
--- /dev/null
@@ -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)
+       }
+}
index 4ce01dc906189598ac0be0052760d3f707c568bb..769414e0eef8c78ff0be6ee9ced7095d138240a8 100644 (file)
@@ -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())
index 4c4200a49b7277f9b90aa73b851c6b422e8e58a3..7c87b42f6d9edbc3ddef05a105d282e7f724a9e1 100644 (file)
@@ -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 (file)
index 0000000..5f380a2
--- /dev/null
@@ -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 (file)
index 0000000..6cd5a2d
--- /dev/null
@@ -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