github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/ipv4/multicast_test.go (about)

     1  // Copyright 2012 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  package ipv4_test
     6  
     7  import (
     8  	"bytes"
     9  	"net"
    10  	"os"
    11  	"runtime"
    12  	"testing"
    13  	"time"
    14  
    15  	"golang.org/x/net/icmp"
    16  	"golang.org/x/net/internal/iana"
    17  	"golang.org/x/net/internal/nettest"
    18  	"golang.org/x/net/ipv4"
    19  )
    20  
    21  var packetConnReadWriteMulticastUDPTests = []struct {
    22  	addr     string
    23  	grp, src *net.UDPAddr
    24  }{
    25  	{"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
    26  
    27  	{"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
    28  }
    29  
    30  func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
    31  	switch runtime.GOOS {
    32  	case "nacl", "plan9", "solaris", "windows":
    33  		t.Skipf("not supported on %s", runtime.GOOS)
    34  	}
    35  	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
    36  	if ifi == nil {
    37  		t.Skipf("not available on %s", runtime.GOOS)
    38  	}
    39  
    40  	for _, tt := range packetConnReadWriteMulticastUDPTests {
    41  		c, err := net.ListenPacket("udp4", tt.addr)
    42  		if err != nil {
    43  			t.Fatal(err)
    44  		}
    45  		defer c.Close()
    46  
    47  		grp := *tt.grp
    48  		grp.Port = c.LocalAddr().(*net.UDPAddr).Port
    49  		p := ipv4.NewPacketConn(c)
    50  		defer p.Close()
    51  		if tt.src == nil {
    52  			if err := p.JoinGroup(ifi, &grp); err != nil {
    53  				t.Fatal(err)
    54  			}
    55  			defer p.LeaveGroup(ifi, &grp)
    56  		} else {
    57  			if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
    58  				switch runtime.GOOS {
    59  				case "freebsd", "linux":
    60  				default: // platforms that don't support IGMPv2/3 fail here
    61  					t.Logf("not supported on %s", runtime.GOOS)
    62  					continue
    63  				}
    64  				t.Fatal(err)
    65  			}
    66  			defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
    67  		}
    68  		if err := p.SetMulticastInterface(ifi); err != nil {
    69  			t.Fatal(err)
    70  		}
    71  		if _, err := p.MulticastInterface(); err != nil {
    72  			t.Fatal(err)
    73  		}
    74  		if err := p.SetMulticastLoopback(true); err != nil {
    75  			t.Fatal(err)
    76  		}
    77  		if _, err := p.MulticastLoopback(); err != nil {
    78  			t.Fatal(err)
    79  		}
    80  		cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
    81  		wb := []byte("HELLO-R-U-THERE")
    82  
    83  		for i, toggle := range []bool{true, false, true} {
    84  			if err := p.SetControlMessage(cf, toggle); err != nil {
    85  				if nettest.ProtocolNotSupported(err) {
    86  					t.Logf("not supported on %s", runtime.GOOS)
    87  					continue
    88  				}
    89  				t.Fatal(err)
    90  			}
    91  			if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
    92  				t.Fatal(err)
    93  			}
    94  			p.SetMulticastTTL(i + 1)
    95  			if n, err := p.WriteTo(wb, nil, &grp); err != nil {
    96  				t.Fatal(err)
    97  			} else if n != len(wb) {
    98  				t.Fatalf("got %v; want %v", n, len(wb))
    99  			}
   100  			rb := make([]byte, 128)
   101  			if n, _, _, err := p.ReadFrom(rb); err != nil {
   102  				t.Fatal(err)
   103  			} else if !bytes.Equal(rb[:n], wb) {
   104  				t.Fatalf("got %v; want %v", rb[:n], wb)
   105  			}
   106  		}
   107  	}
   108  }
   109  
   110  var packetConnReadWriteMulticastICMPTests = []struct {
   111  	grp, src *net.IPAddr
   112  }{
   113  	{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
   114  
   115  	{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
   116  }
   117  
   118  func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
   119  	switch runtime.GOOS {
   120  	case "nacl", "plan9", "solaris", "windows":
   121  		t.Skipf("not supported on %s", runtime.GOOS)
   122  	}
   123  	if m, ok := nettest.SupportsRawIPSocket(); !ok {
   124  		t.Skip(m)
   125  	}
   126  	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
   127  	if ifi == nil {
   128  		t.Skipf("not available on %s", runtime.GOOS)
   129  	}
   130  
   131  	for _, tt := range packetConnReadWriteMulticastICMPTests {
   132  		c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
   133  		if err != nil {
   134  			t.Fatal(err)
   135  		}
   136  		defer c.Close()
   137  
   138  		p := ipv4.NewPacketConn(c)
   139  		defer p.Close()
   140  		if tt.src == nil {
   141  			if err := p.JoinGroup(ifi, tt.grp); err != nil {
   142  				t.Fatal(err)
   143  			}
   144  			defer p.LeaveGroup(ifi, tt.grp)
   145  		} else {
   146  			if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
   147  				switch runtime.GOOS {
   148  				case "freebsd", "linux":
   149  				default: // platforms that don't support IGMPv2/3 fail here
   150  					t.Logf("not supported on %s", runtime.GOOS)
   151  					continue
   152  				}
   153  				t.Fatal(err)
   154  			}
   155  			defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
   156  		}
   157  		if err := p.SetMulticastInterface(ifi); err != nil {
   158  			t.Fatal(err)
   159  		}
   160  		if _, err := p.MulticastInterface(); err != nil {
   161  			t.Fatal(err)
   162  		}
   163  		if err := p.SetMulticastLoopback(true); err != nil {
   164  			t.Fatal(err)
   165  		}
   166  		if _, err := p.MulticastLoopback(); err != nil {
   167  			t.Fatal(err)
   168  		}
   169  		cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
   170  
   171  		for i, toggle := range []bool{true, false, true} {
   172  			wb, err := (&icmp.Message{
   173  				Type: ipv4.ICMPTypeEcho, Code: 0,
   174  				Body: &icmp.Echo{
   175  					ID: os.Getpid() & 0xffff, Seq: i + 1,
   176  					Data: []byte("HELLO-R-U-THERE"),
   177  				},
   178  			}).Marshal(nil)
   179  			if err != nil {
   180  				t.Fatal(err)
   181  			}
   182  			if err := p.SetControlMessage(cf, toggle); err != nil {
   183  				if nettest.ProtocolNotSupported(err) {
   184  					t.Logf("not supported on %s", runtime.GOOS)
   185  					continue
   186  				}
   187  				t.Fatal(err)
   188  			}
   189  			if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
   190  				t.Fatal(err)
   191  			}
   192  			p.SetMulticastTTL(i + 1)
   193  			if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
   194  				t.Fatal(err)
   195  			} else if n != len(wb) {
   196  				t.Fatalf("got %v; want %v", n, len(wb))
   197  			}
   198  			rb := make([]byte, 128)
   199  			if n, _, _, err := p.ReadFrom(rb); err != nil {
   200  				t.Fatal(err)
   201  			} else {
   202  				m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
   203  				if err != nil {
   204  					t.Fatal(err)
   205  				}
   206  				switch {
   207  				case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
   208  				case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
   209  				default:
   210  					t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
   211  				}
   212  			}
   213  		}
   214  	}
   215  }
   216  
   217  var rawConnReadWriteMulticastICMPTests = []struct {
   218  	grp, src *net.IPAddr
   219  }{
   220  	{&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
   221  
   222  	{&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
   223  }
   224  
   225  func TestRawConnReadWriteMulticastICMP(t *testing.T) {
   226  	if testing.Short() {
   227  		t.Skip("to avoid external network")
   228  	}
   229  	if m, ok := nettest.SupportsRawIPSocket(); !ok {
   230  		t.Skip(m)
   231  	}
   232  	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
   233  	if ifi == nil {
   234  		t.Skipf("not available on %s", runtime.GOOS)
   235  	}
   236  
   237  	for _, tt := range rawConnReadWriteMulticastICMPTests {
   238  		c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
   239  		if err != nil {
   240  			t.Fatal(err)
   241  		}
   242  		defer c.Close()
   243  
   244  		r, err := ipv4.NewRawConn(c)
   245  		if err != nil {
   246  			t.Fatal(err)
   247  		}
   248  		defer r.Close()
   249  		if tt.src == nil {
   250  			if err := r.JoinGroup(ifi, tt.grp); err != nil {
   251  				t.Fatal(err)
   252  			}
   253  			defer r.LeaveGroup(ifi, tt.grp)
   254  		} else {
   255  			if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
   256  				switch runtime.GOOS {
   257  				case "freebsd", "linux":
   258  				default: // platforms that don't support IGMPv2/3 fail here
   259  					t.Logf("not supported on %s", runtime.GOOS)
   260  					continue
   261  				}
   262  				t.Fatal(err)
   263  			}
   264  			defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
   265  		}
   266  		if err := r.SetMulticastInterface(ifi); err != nil {
   267  			t.Fatal(err)
   268  		}
   269  		if _, err := r.MulticastInterface(); err != nil {
   270  			t.Fatal(err)
   271  		}
   272  		if err := r.SetMulticastLoopback(true); err != nil {
   273  			t.Fatal(err)
   274  		}
   275  		if _, err := r.MulticastLoopback(); err != nil {
   276  			t.Fatal(err)
   277  		}
   278  		cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
   279  
   280  		for i, toggle := range []bool{true, false, true} {
   281  			wb, err := (&icmp.Message{
   282  				Type: ipv4.ICMPTypeEcho, Code: 0,
   283  				Body: &icmp.Echo{
   284  					ID: os.Getpid() & 0xffff, Seq: i + 1,
   285  					Data: []byte("HELLO-R-U-THERE"),
   286  				},
   287  			}).Marshal(nil)
   288  			if err != nil {
   289  				t.Fatal(err)
   290  			}
   291  			wh := &ipv4.Header{
   292  				Version:  ipv4.Version,
   293  				Len:      ipv4.HeaderLen,
   294  				TOS:      i + 1,
   295  				TotalLen: ipv4.HeaderLen + len(wb),
   296  				Protocol: 1,
   297  				Dst:      tt.grp.IP,
   298  			}
   299  			if err := r.SetControlMessage(cf, toggle); err != nil {
   300  				if nettest.ProtocolNotSupported(err) {
   301  					t.Logf("not supported on %s", runtime.GOOS)
   302  					continue
   303  				}
   304  				t.Fatal(err)
   305  			}
   306  			if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
   307  				t.Fatal(err)
   308  			}
   309  			r.SetMulticastTTL(i + 1)
   310  			if err := r.WriteTo(wh, wb, nil); err != nil {
   311  				t.Fatal(err)
   312  			}
   313  			rb := make([]byte, ipv4.HeaderLen+128)
   314  			if rh, b, _, err := r.ReadFrom(rb); err != nil {
   315  				t.Fatal(err)
   316  			} else {
   317  				m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
   318  				if err != nil {
   319  					t.Fatal(err)
   320  				}
   321  				switch {
   322  				case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
   323  				case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
   324  				default:
   325  					t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
   326  				}
   327  			}
   328  		}
   329  	}
   330  }