github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/route/message_test.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build darwin dragonfly freebsd netbsd openbsd
     6  
     7  package route
     8  
     9  import (
    10  	"os"
    11  	"syscall"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  func TestFetchAndParseRIB(t *testing.T) {
    17  	for _, typ := range []RIBType{sysNET_RT_DUMP, sysNET_RT_IFLIST} {
    18  		var lastErr error
    19  		var ms []Message
    20  		for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
    21  			rs, err := fetchAndParseRIB(af, typ)
    22  			if err != nil {
    23  				lastErr = err
    24  				continue
    25  			}
    26  			ms = append(ms, rs...)
    27  		}
    28  		if len(ms) == 0 && lastErr != nil {
    29  			t.Error(typ, lastErr)
    30  			continue
    31  		}
    32  		ss, err := msgs(ms).validate()
    33  		if err != nil {
    34  			t.Error(typ, err)
    35  			continue
    36  		}
    37  		for _, s := range ss {
    38  			t.Log(typ, s)
    39  		}
    40  	}
    41  }
    42  
    43  var (
    44  	rtmonSock int
    45  	rtmonErr  error
    46  )
    47  
    48  func init() {
    49  	// We need to keep rtmonSock alive to avoid treading on
    50  	// recycled socket descriptors.
    51  	rtmonSock, rtmonErr = syscall.Socket(sysAF_ROUTE, sysSOCK_RAW, sysAF_UNSPEC)
    52  }
    53  
    54  // TestMonitorAndParseRIB leaks a worker goroutine and a socket
    55  // descriptor but that's intentional.
    56  func TestMonitorAndParseRIB(t *testing.T) {
    57  	if testing.Short() || os.Getuid() != 0 {
    58  		t.Skip("must be root")
    59  	}
    60  
    61  	if rtmonErr != nil {
    62  		t.Fatal(rtmonErr)
    63  	}
    64  
    65  	// We suppose that using an IPv4 link-local address and the
    66  	// dot1Q ID for Token Ring and FDDI doesn't harm anyone.
    67  	pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
    68  	if err := pv.configure(1002); err != nil {
    69  		t.Skip(err)
    70  	}
    71  	if err := pv.setup(); err != nil {
    72  		t.Skip(err)
    73  	}
    74  	pv.teardown()
    75  
    76  	go func() {
    77  		b := make([]byte, os.Getpagesize())
    78  		for {
    79  			// There's no easy way to unblock this read
    80  			// call because the routing message exchange
    81  			// over routing socket is a connectionless
    82  			// message-oriented protocol, no control plane
    83  			// for signaling connectivity, and we cannot
    84  			// use the net package of standard library due
    85  			// to the lack of support for routing socket
    86  			// and circular dependency.
    87  			n, err := syscall.Read(rtmonSock, b)
    88  			if err != nil {
    89  				return
    90  			}
    91  			ms, err := ParseRIB(0, b[:n])
    92  			if err != nil {
    93  				t.Error(err)
    94  				return
    95  			}
    96  			ss, err := msgs(ms).validate()
    97  			if err != nil {
    98  				t.Error(err)
    99  				return
   100  			}
   101  			for _, s := range ss {
   102  				t.Log(s)
   103  			}
   104  		}
   105  	}()
   106  
   107  	for _, vid := range []int{1002, 1003, 1004, 1005} {
   108  		pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
   109  		if err := pv.configure(vid); err != nil {
   110  			t.Fatal(err)
   111  		}
   112  		if err := pv.setup(); err != nil {
   113  			t.Fatal(err)
   114  		}
   115  		time.Sleep(200 * time.Millisecond)
   116  		if err := pv.teardown(); err != nil {
   117  			t.Fatal(err)
   118  		}
   119  		time.Sleep(200 * time.Millisecond)
   120  	}
   121  }
   122  
   123  func TestParseRIBWithFuzz(t *testing.T) {
   124  	for _, fuzz := range []string{
   125  		"0\x00\x05\x050000000000000000" +
   126  			"00000000000000000000" +
   127  			"00000000000000000000" +
   128  			"00000000000000000000" +
   129  			"0000000000000\x02000000" +
   130  			"00000000",
   131  		"\x02\x00\x05\f0000000000000000" +
   132  			"0\x0200000000000000",
   133  		"\x02\x00\x05\x100000000000000\x1200" +
   134  			"0\x00\xff\x00",
   135  		"\x02\x00\x05\f0000000000000000" +
   136  			"0\x12000\x00\x02\x0000",
   137  		"\x00\x00\x00\x01\x00",
   138  		"00000",
   139  	} {
   140  		for typ := RIBType(0); typ < 256; typ++ {
   141  			ParseRIB(typ, []byte(fuzz))
   142  		}
   143  	}
   144  }
   145  
   146  func TestRouteMessage(t *testing.T) {
   147  	s, err := syscall.Socket(sysAF_ROUTE, sysSOCK_RAW, sysAF_UNSPEC)
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	defer syscall.Close(s)
   152  
   153  	var ms []RouteMessage
   154  	for _, af := range []int{sysAF_INET, sysAF_INET6} {
   155  		if _, err := fetchAndParseRIB(af, sysNET_RT_DUMP); err != nil {
   156  			t.Log(err)
   157  			continue
   158  		}
   159  		switch af {
   160  		case sysAF_INET:
   161  			ms = append(ms, []RouteMessage{
   162  				{
   163  					Type: sysRTM_GET,
   164  					Addrs: []Addr{
   165  						sysRTAX_DST:     &Inet4Addr{IP: [4]byte{127, 0, 0, 1}},
   166  						sysRTAX_GATEWAY: nil,
   167  						sysRTAX_NETMASK: nil,
   168  						sysRTAX_GENMASK: nil,
   169  						sysRTAX_IFP:     &LinkAddr{},
   170  						sysRTAX_IFA:     &Inet4Addr{},
   171  						sysRTAX_AUTHOR:  nil,
   172  						sysRTAX_BRD:     &Inet4Addr{},
   173  					},
   174  				},
   175  				{
   176  					Type: sysRTM_GET,
   177  					Addrs: []Addr{
   178  						sysRTAX_DST: &Inet4Addr{IP: [4]byte{127, 0, 0, 1}},
   179  					},
   180  				},
   181  			}...)
   182  		case sysAF_INET6:
   183  			ms = append(ms, []RouteMessage{
   184  				{
   185  					Type: sysRTM_GET,
   186  					Addrs: []Addr{
   187  						sysRTAX_DST:     &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
   188  						sysRTAX_GATEWAY: nil,
   189  						sysRTAX_NETMASK: nil,
   190  						sysRTAX_GENMASK: nil,
   191  						sysRTAX_IFP:     &LinkAddr{},
   192  						sysRTAX_IFA:     &Inet6Addr{},
   193  						sysRTAX_AUTHOR:  nil,
   194  						sysRTAX_BRD:     &Inet6Addr{},
   195  					},
   196  				},
   197  				{
   198  					Type: sysRTM_GET,
   199  					Addrs: []Addr{
   200  						sysRTAX_DST: &Inet6Addr{IP: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}},
   201  					},
   202  				},
   203  			}...)
   204  		}
   205  	}
   206  	for i, m := range ms {
   207  		m.ID = uintptr(os.Getpid())
   208  		m.Seq = i + 1
   209  		wb, err := m.Marshal()
   210  		if err != nil {
   211  			t.Fatalf("%v: %v", m, err)
   212  		}
   213  		if _, err := syscall.Write(s, wb); err != nil {
   214  			t.Fatalf("%v: %v", m, err)
   215  		}
   216  		rb := make([]byte, os.Getpagesize())
   217  		n, err := syscall.Read(s, rb)
   218  		if err != nil {
   219  			t.Fatalf("%v: %v", m, err)
   220  		}
   221  		rms, err := ParseRIB(0, rb[:n])
   222  		if err != nil {
   223  			t.Fatalf("%v: %v", m, err)
   224  		}
   225  		for _, rm := range rms {
   226  			if rm, ok := rm.(*RouteMessage); ok && rm.Err != nil {
   227  				t.Errorf("%v: %v", m, rm.Err)
   228  			}
   229  		}
   230  		ss, err := msgs(rms).validate()
   231  		if err != nil {
   232  			t.Fatalf("%v: %v", m, err)
   233  		}
   234  		for _, s := range ss {
   235  			t.Log(s)
   236  		}
   237  	}
   238  }