func TestRawConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris": 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", "127.0.0.1") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatalf("ipv4.NewRawConn failed: %v", err) } testUnicastSocketOptions(t, r) }
func ExampleWriteIPOSPFHello() { var ifs []*net.Interface en0, err := net.InterfaceByName("en0") if err != nil { log.Fatal(err) } ifs = append(ifs, en0) en1, err := net.InterfaceByIndex(911) if err != nil { log.Fatal(err) } ifs = append(ifs, en1) c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSPF for IPv4 if err != nil { log.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { log.Fatal(err) } for _, ifi := range ifs { err := r.JoinGroup(ifi, &net.IPAddr{IP: AllSPFRouters}) if err != nil { log.Fatal(err) } err = r.JoinGroup(ifi, &net.IPAddr{IP: AllDRouters}) if err != nil { log.Fatal(err) } } hello := make([]byte, OSPFHelloHeaderLen) ospf := make([]byte, OSPFHeaderLen) ospf[0] = OSPF_VERSION ospf[1] = OSPF_TYPE_HELLO ospf = append(ospf, hello...) iph := &ipv4.Header{} iph.Version = ipv4.Version iph.Len = ipv4.HeaderLen iph.TOS = iana.DiffServCS6 iph.TotalLen = ipv4.HeaderLen + len(ospf) iph.TTL = 1 iph.Protocol = 89 iph.Dst = AllSPFRouters for _, ifi := range ifs { err := r.SetMulticastInterface(ifi) if err != nil { return } err = r.WriteTo(iph, ospf, nil) if err != nil { return } } }
func ExampleIPOSPFListener() { var ifs []*net.Interface en0, err := net.InterfaceByName("en0") if err != nil { log.Fatal(err) } ifs = append(ifs, en0) en1, err := net.InterfaceByIndex(911) if err != nil { log.Fatal(err) } ifs = append(ifs, en1) c, err := net.ListenPacket("ip4:89", "0.0.0.0") // OSFP for IPv4 if err != nil { log.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { log.Fatal(err) } for _, ifi := range ifs { err := r.JoinGroup(ifi, &net.IPAddr{IP: AllSPFRouters}) if err != nil { log.Fatal(err) } err = r.JoinGroup(ifi, &net.IPAddr{IP: AllDRouters}) if err != nil { log.Fatal(err) } } err = r.SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true) if err != nil { log.Fatal(err) } r.SetTOS(iana.DiffServCS6) parseOSPFHeader := func(b []byte) *OSPFHeader { if len(b) < OSPFHeaderLen { return nil } return &OSPFHeader{ Version: b[0], Type: b[1], Len: uint16(b[2])<<8 | uint16(b[3]), RouterID: uint32(b[4])<<24 | uint32(b[5])<<16 | uint32(b[6])<<8 | uint32(b[7]), AreaID: uint32(b[8])<<24 | uint32(b[9])<<16 | uint32(b[10])<<8 | uint32(b[11]), Checksum: uint16(b[12])<<8 | uint16(b[13]), } } b := make([]byte, 1500) for { iph, p, _, err := r.ReadFrom(b) if err != nil { log.Fatal(err) } if iph.Version != ipv4.Version { continue } if iph.Dst.IsMulticast() { if !iph.Dst.Equal(AllSPFRouters) && !iph.Dst.Equal(AllDRouters) { continue } } ospfh := parseOSPFHeader(p) if ospfh == nil { continue } if ospfh.Version != OSPF_VERSION { continue } switch ospfh.Type { case OSPF_TYPE_HELLO: case OSPF_TYPE_DB_DESCRIPTION: case OSPF_TYPE_LS_REQUEST: case OSPF_TYPE_LS_UPDATE: case OSPF_TYPE_LS_ACK: } } }
func TestRawConnReadWriteUnicastICMP(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.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 { if protocolNotSupported(err) { t.Skipf("not supported on %q", runtime.GOOS) } 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) } } } }
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) } } } }