func TestSetICMPFilter(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } if os.Getuid() != 0 { t.Skip("must be root") } c, err := net.ListenPacket("ip6:ipv6-icmp", "::1") if err != nil { t.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeEchoRequest) f.Accept(ipv6.ICMPTypeEchoReply) if err := p.SetICMPFilter(&f); err != nil { t.Fatal(err) } kf, err := p.ICMPFilter() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(kf, &f) { t.Fatalf("got %#v; want %#v", kf, f) } }
func TestICMPFilter(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } var f ipv6.ICMPFilter for _, toggle := range []bool{false, true} { f.SetAll(toggle) for _, typ := range []ipv6.ICMPType{ ipv6.ICMPTypeDestinationUnreachable, ipv6.ICMPTypeEchoReply, ipv6.ICMPTypeNeighborSolicitation, ipv6.ICMPTypeDuplicateAddressConfirmation, } { f.Accept(typ) if f.WillBlock(typ) { t.Errorf("ipv6.ICMPFilter.Set(%v, false) failed", typ) } f.Block(typ) if !f.WillBlock(typ) { t.Errorf("ipv6.ICMPFilter.Set(%v, true) failed", typ) } } } }
func TestPacketConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": t.Skipf("not supported on %q", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } if os.Getuid() != 0 { t.Skip("must be root") } c, err := net.ListenPacket("ip6:ipv6-icmp", "::1") if err != nil { t.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) defer p.Close() dst, err := net.ResolveIPAddr("ip6", "::1") if err != nil { t.Fatal(err) } pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP) cm := ipv6.ControlMessage{ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, Src: net.IPv6loopback, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) if ifi != nil { cm.IfIndex = ifi.Index } var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeEchoReply) if err := p.SetICMPFilter(&f); err != nil { t.Fatal(err) } var psh []byte for i, toggle := range []bool{true, false, true} { if toggle { psh = nil if err := p.SetChecksum(true, 2); err != nil { t.Fatal(err) } } else { psh = pshicmp // Some platforms never allow to disable the // kernel checksum processing. p.SetChecksum(false, -1) } wb, err := (&icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(psh) if err != nil { t.Fatal(err) } if err := p.SetControlMessage(cf, toggle); err != nil { if nettest.ProtocolNotSupported(err) { t.Skipf("not supported on %q", runtime.GOOS) } t.Fatal(err) } cm.HopLimit = i + 1 if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, err := p.WriteTo(wb, &cm, dst); err != nil { t.Fatal(err) } else if n != len(wb) { t.Fatalf("got %v; want %v", n, len(wb)) } rb := make([]byte, 128) if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if n, cm, _, err := p.ReadFrom(rb); err != nil { switch runtime.GOOS { case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket t.Logf("not supported on %q", runtime.GOOS) continue } t.Fatal(err) } else { t.Logf("rcvd cmsg: %v", cm) if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { t.Fatal(err) } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) } } } }
func TestPacketConnReadWriteMulticastICMP(t *testing.T) { switch runtime.GOOS { case "freebsd": // due to a bug on loopback marking // See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065. t.Skipf("not supported on %s", runtime.GOOS) case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !supportsIPv6 { t.Skip("ipv6 is not supported") } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } for _, tt := range packetConnReadWriteMulticastICMPTests { c, err := net.ListenPacket("ip6:ipv6-icmp", "::") if err != nil { t.Fatal(err) } defer c.Close() pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP) p := ipv6.NewPacketConn(c) defer p.Close() if tt.src == nil { if err := p.JoinGroup(ifi, tt.grp); err != nil { t.Fatal(err) } defer p.LeaveGroup(ifi, tt.grp) } else { if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { switch runtime.GOOS { case "freebsd", "linux": default: // platforms that don't support MLDv2 fail here t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) } if err := p.SetMulticastInterface(ifi); err != nil { t.Fatal(err) } if _, err := p.MulticastInterface(); err != nil { t.Fatal(err) } if err := p.SetMulticastLoopback(true); err != nil { t.Fatal(err) } if _, err := p.MulticastLoopback(); err != nil { t.Fatal(err) } cm := ipv6.ControlMessage{ TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, Src: net.IPv6loopback, IfIndex: ifi.Index, } cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeEchoReply) if err := p.SetICMPFilter(&f); err != nil { t.Fatal(err) } var psh []byte for i, toggle := range []bool{true, false, true} { if toggle { psh = nil if err := p.SetChecksum(true, 2); err != nil { // Solaris never allows to // modify ICMP properties. if runtime.GOOS != "solaris" { t.Fatal(err) } } } else { psh = pshicmp // Some platforms never allow to // disable the kernel checksum // processing. p.SetChecksum(false, -1) } wb, err := (&icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(psh) if err != nil { t.Fatal(err) } if err := p.SetControlMessage(cf, toggle); err != nil { if nettest.ProtocolNotSupported(err) { t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { t.Fatal(err) } cm.HopLimit = i + 1 if n, err := p.WriteTo(wb, &cm, tt.grp); err != nil { t.Fatal(err) } else if n != len(wb) { t.Fatalf("got %v; want %v", n, len(wb)) } rb := make([]byte, 128) if n, _, _, err := p.ReadFrom(rb); err != nil { switch runtime.GOOS { case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } else { if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { t.Fatal(err) } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) } } } } }
func doPing(tt pingTest, seq int) error { c, err := icmp.ListenPacket(tt.network, tt.address) if err != nil { return err } defer c.Close() dst, err := googleAddr(c, tt.protocol) if err != nil { return err } if tt.protocol == iana.ProtocolIPv6ICMP { var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeDestinationUnreachable) f.Accept(ipv6.ICMPTypePacketTooBig) f.Accept(ipv6.ICMPTypeTimeExceeded) f.Accept(ipv6.ICMPTypeParameterProblem) f.Accept(ipv6.ICMPTypeEchoReply) if err := c.IPv6PacketConn().SetICMPFilter(&f); err != nil { return err } } wm := icmp.Message{ Type: tt.mtype, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: 1 << uint(seq), Data: []byte("HELLO-R-U-THERE"), }, } wb, err := wm.Marshal(nil) if err != nil { return err } if n, err := c.WriteTo(wb, dst); err != nil { return err } else if n != len(wb) { return fmt.Errorf("got %v; want %v", n, len(wb)) } rb := make([]byte, 1500) if err := c.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { return err } n, peer, err := c.ReadFrom(rb) if err != nil { return err } rm, err := icmp.ParseMessage(tt.protocol, rb[:n]) if err != nil { return err } switch rm.Type { case ipv4.ICMPTypeEchoReply, ipv6.ICMPTypeEchoReply: return nil default: return fmt.Errorf("got %+v from %v; want echo reply", rm, peer) } }
func ExamplePacketConn_tracingIPPacketRoute() { // Tracing an IP packet route to www.google.com. const host = "www.google.com" ips, err := net.LookupIP(host) if err != nil { log.Fatal(err) } var dst net.IPAddr for _, ip := range ips { if ip.To16() != nil && ip.To4() == nil { dst.IP = ip fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host) break } } if dst.IP == nil { log.Fatal("no AAAA record found") } c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolIPv6ICMP), "::") // ICMP for IPv6 if err != nil { log.Fatal(err) } defer c.Close() p := ipv6.NewPacketConn(c) if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { log.Fatal(err) } wm := icmp.Message{ Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Data: []byte("HELLO-R-U-THERE"), }, } var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeTimeExceeded) f.Accept(ipv6.ICMPTypeEchoReply) if err := p.SetICMPFilter(&f); err != nil { log.Fatal(err) } var wcm ipv6.ControlMessage rb := make([]byte, 1500) for i := 1; i <= 64; i++ { // up to 64 hops wm.Body.(*icmp.Echo).Seq = i wb, err := wm.Marshal(nil) if err != nil { log.Fatal(err) } // In the real world usually there are several // multiple traffic-engineered paths for each hop. // You may need to probe a few times to each hop. begin := time.Now() wcm.HopLimit = i if _, err := p.WriteTo(wb, &wcm, &dst); err != nil { log.Fatal(err) } if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { log.Fatal(err) } n, rcm, peer, err := p.ReadFrom(rb) if err != nil { if err, ok := err.(net.Error); ok && err.Timeout() { fmt.Printf("%v\t*\n", i) continue } log.Fatal(err) } rm, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]) if err != nil { log.Fatal(err) } rtt := time.Since(begin) // In the real world you need to determine whether the // received message is yours using ControlMessage.Src, // ControlMesage.Dst, icmp.Echo.ID and icmp.Echo.Seq. switch rm.Type { case ipv6.ICMPTypeTimeExceeded: names, _ := net.LookupAddr(peer.String()) fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm) case ipv6.ICMPTypeEchoReply: names, _ := net.LookupAddr(peer.String()) fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm) return } } }
func main() { var err error // create redis connection pool if db, err = pool.New("tcp", "localhost:6379", 10); err != nil { panic(err) } defer db.Empty() dbc, err := db.Get() if err != nil { fmt.Println(err) } for k, v := range defaultConfig { dbc.PipeAppend("HSETNX", "fahrrad/config", k, v) } for k, _ := range defaultConfig { dbc.PipeAppend("HGET", "fahrrad/config", k) } for _, _ = range defaultConfig { dbc.PipeResp() } var v int v, err = dbc.PipeResp().Int() if err == nil { AssignedPrefixLength = uint8(v) } v, err = dbc.PipeResp().Int() if err == nil { OnLinkPrefixLength = uint8(v) } v, err = dbc.PipeResp().Int() if err == nil { DefaultValidLifetime = uint32(v) } v, err = dbc.PipeResp().Int() if err == nil { DefaultPreferredLifetime = uint32(v) } v, err = dbc.PipeResp().Int() if err == nil { TickerDelay = time.Duration(v) * time.Second } defer db.Put(dbc) // open listening connection conn, err := net.ListenIP("ip6:ipv6-icmp", &net.IPAddr{net.IPv6unspecified, ""}) if err != nil { panic(err) } defer conn.Close() pc = ipv6.NewPacketConn(conn) // RFC4861 requires the hop limit set to 255, but the default value in golang is 64 pc.SetHopLimit(255) // only accept neighbor discovery messages filter := new(ipv6.ICMPFilter) filter.SetAll(true) filter.Accept(ipv6.ICMPTypeRouterSolicitation) filter.Accept(ipv6.ICMPTypeRouterAdvertisement) filter.Accept(ipv6.ICMPTypeNeighborSolicitation) filter.Accept(ipv6.ICMPTypeNeighborAdvertisement) if err = pc.SetICMPFilter(filter); err != nil { panic(err) } rschan = make(chan routerSolicitation) go hostManager() // read from socket buf := make([]byte, 512) for { n, _, srcAddr, err := pc.ReadFrom(buf) if err != nil { panic(err) } go handleND(srcAddr, buf[:n]) } }