func TestMarshalAndParseMessageForIPv4(t *testing.T) { for _, tt := range marshalAndParseMessageForIPv4Tests { b, err := tt.Marshal(nil) if err != nil { t.Fatal(err) } m, err := icmp.ParseMessage(iana.ProtocolICMP, b) if err != nil { t.Fatal(err) } if m.Type != tt.Type || m.Code != tt.Code { t.Errorf("got %v; want %v", m, &tt) } if !reflect.DeepEqual(m.Body, tt.Body) { t.Errorf("got %v; want %v", m.Body, tt.Body) } } }
func TestMarshalAndParseMessageForIPv6(t *testing.T) { pshicmp := icmp.IPv6PseudoHeader(net.ParseIP("fe80::1"), net.ParseIP("ff02::1")) for _, tt := range marshalAndParseMessageForIPv6Tests { for _, psh := range [][]byte{pshicmp, nil} { b, err := tt.Marshal(psh) if err != nil { t.Fatal(err) } m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, b) if err != nil { t.Fatal(err) } if m.Type != tt.Type || m.Code != tt.Code { t.Errorf("got %v; want %v", m, &tt) } if !reflect.DeepEqual(m.Body, tt.Body) { t.Errorf("got %v; want %v", m.Body, tt.Body) } } } }
func TestPacketConnReadWriteMulticastICMP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if os.Getuid() != 0 { t.Skip("must be root") } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() dst, err := net.ResolveIPAddr("ip4", "224.0.0.254") // see RFC 4727 if err != nil { t.Fatalf("net.ResolveIPAddr failed: %v", err) } p := ipv4.NewPacketConn(c) defer p.Close() if err := p.JoinGroup(ifi, dst); err != nil { t.Fatalf("ipv4.PacketConn.JoinGroup on %v failed: %v", ifi, err) } if err := p.SetMulticastInterface(ifi); err != nil { t.Fatalf("ipv4.PacketConn.SetMulticastInterface failed: %v", err) } if _, err := p.MulticastInterface(); err != nil { t.Fatalf("ipv4.PacketConn.MulticastInterface failed: %v", err) } if err := p.SetMulticastLoopback(true); err != nil { t.Fatalf("ipv4.PacketConn.SetMulticastLoopback failed: %v", err) } if _, err := p.MulticastLoopback(); err != nil { t.Fatalf("ipv4.PacketConn.MulticastLoopback failed: %v", err) } cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface for i, toggle := range []bool{true, false, true} { wb, err := (&icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(nil) if err != nil { t.Fatalf("icmp.Message.Marshal failed: %v", err) } if err := p.SetControlMessage(cf, toggle); err != nil { if protocolNotSupported(err) { t.Skipf("not supported on %q", runtime.GOOS) } t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err) } if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { t.Fatalf("ipv4.PacketConn.SetDeadline failed: %v", err) } p.SetMulticastTTL(i + 1) if _, err := p.WriteTo(wb, nil, dst); err != nil { t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) } b := make([]byte, 128) if n, cm, _, err := p.ReadFrom(b); err != nil { t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) } else { t.Logf("rcvd cmsg: %v", cm) m, err := icmp.ParseMessage(iana.ProtocolICMP, b[:n]) if err != nil { t.Fatalf("icmp.ParseMessage failed: %v", err) } switch { case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 default: t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) } } } }
func TestRawConnReadWriteMulticastICMP(t *testing.T) { if testing.Short() { t.Skip("to avoid external network") } if os.Getuid() != 0 { t.Skip("must be root") } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() dst, err := net.ResolveIPAddr("ip4", "224.0.0.254") // see RFC 4727 if err != nil { t.Fatalf("ResolveIPAddr failed: %v", err) } r, err := ipv4.NewRawConn(c) if err != nil { t.Fatalf("ipv4.NewRawConn failed: %v", err) } defer r.Close() if err := r.JoinGroup(ifi, dst); err != nil { t.Fatalf("ipv4.RawConn.JoinGroup on %v failed: %v", ifi, err) } if err := r.SetMulticastInterface(ifi); err != nil { t.Fatalf("ipv4.RawConn.SetMulticastInterface failed: %v", err) } if _, err := r.MulticastInterface(); err != nil { t.Fatalf("ipv4.RawConn.MulticastInterface failed: %v", err) } if err := r.SetMulticastLoopback(true); err != nil { t.Fatalf("ipv4.RawConn.SetMulticastLoopback failed: %v", err) } if _, err := r.MulticastLoopback(); err != nil { t.Fatalf("ipv4.RawConn.MulticastLoopback failed: %v", err) } cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface for i, toggle := range []bool{true, false, true} { wb, err := (&icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(nil) if err != nil { t.Fatalf("icmp.Message.Marshal failed: %v", err) } wh := &ipv4.Header{ Version: ipv4.Version, Len: ipv4.HeaderLen, TOS: i + 1, TotalLen: ipv4.HeaderLen + len(wb), Protocol: 1, Dst: dst.IP, } if err := r.SetControlMessage(cf, toggle); err != nil { if protocolNotSupported(err) { t.Skipf("not supported on %q", runtime.GOOS) } t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err) } if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { t.Fatalf("ipv4.RawConn.SetDeadline failed: %v", err) } r.SetMulticastTTL(i + 1) if err := r.WriteTo(wh, wb, nil); err != nil { t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err) } rb := make([]byte, ipv4.HeaderLen+128) if rh, b, cm, err := r.ReadFrom(rb); err != nil { t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err) } else { t.Logf("rcvd cmsg: %v", cm) m, err := icmp.ParseMessage(iana.ProtocolICMP, b) if err != nil { t.Fatalf("icmp.ParseMessage failed: %v", err) } switch { case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 default: t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) } } } }
func TestRawConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { case "plan9", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if os.Getuid() != 0 { t.Skip("must be root") } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") if err != nil { t.Fatalf("ResolveIPAddr failed: %v", err) } r, err := ipv4.NewRawConn(c) if err != nil { t.Fatalf("ipv4.NewRawConn failed: %v", err) } defer r.Close() cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface for i, toggle := range []bool{true, false, true} { wb, err := (&icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(nil) if err != nil { t.Fatalf("icmp.Message.Marshal failed: %v", err) } wh := &ipv4.Header{ Version: ipv4.Version, Len: ipv4.HeaderLen, TOS: i + 1, TotalLen: ipv4.HeaderLen + len(wb), TTL: i + 1, Protocol: 1, Dst: dst.IP, } if err := r.SetControlMessage(cf, toggle); err != nil { t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err) } if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatalf("ipv4.RawConn.SetWriteDeadline failed: %v", err) } if err := r.WriteTo(wh, wb, nil); err != nil { t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err) } rb := make([]byte, ipv4.HeaderLen+128) loop: if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatalf("ipv4.RawConn.SetReadDeadline failed: %v", err) } if _, b, cm, err := r.ReadFrom(rb); err != nil { t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err) } else { t.Logf("rcvd cmsg: %v", cm) m, err := icmp.ParseMessage(iana.ProtocolICMP, b) if err != nil { t.Fatalf("icmp.ParseMessage failed: %v", err) } if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho { // On Linux we must handle own sent packets. goto loop } if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) } } } }