Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 1 | // Copyright 2014 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 ipv6_test |
| 6 | |
| 7 | import ( |
| 8 | "fmt" |
| 9 | "log" |
| 10 | "net" |
| 11 | "os" |
| 12 | "time" |
| 13 | |
Mikio Hara | 597bbe1 | 2014-12-03 12:33:31 +0900 | [diff] [blame] | 14 | "golang.org/x/net/icmp" |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 15 | "golang.org/x/net/ipv6" |
| 16 | ) |
| 17 | |
| 18 | func ExampleConn_markingTCP() { |
Mikio Hara | 0d2c2e1 | 2015-12-15 09:19:55 +0900 | [diff] [blame] | 19 | ln, err := net.Listen("tcp", "[::]:1024") |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 20 | if err != nil { |
| 21 | log.Fatal(err) |
| 22 | } |
| 23 | defer ln.Close() |
| 24 | |
| 25 | for { |
| 26 | c, err := ln.Accept() |
| 27 | if err != nil { |
| 28 | log.Fatal(err) |
| 29 | } |
| 30 | go func(c net.Conn) { |
| 31 | defer c.Close() |
Mikio Hara | 0d2c2e1 | 2015-12-15 09:19:55 +0900 | [diff] [blame] | 32 | if c.RemoteAddr().(*net.TCPAddr).IP.To16() != nil && c.RemoteAddr().(*net.TCPAddr).IP.To4() == nil { |
| 33 | p := ipv6.NewConn(c) |
| 34 | if err := p.SetTrafficClass(0x28); err != nil { // DSCP AF11 |
| 35 | log.Fatal(err) |
| 36 | } |
| 37 | if err := p.SetHopLimit(128); err != nil { |
| 38 | log.Fatal(err) |
| 39 | } |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 40 | } |
| 41 | if _, err := c.Write([]byte("HELLO-R-U-THERE-ACK")); err != nil { |
| 42 | log.Fatal(err) |
| 43 | } |
| 44 | }(c) |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | func ExamplePacketConn_servingOneShotMulticastDNS() { |
| 49 | c, err := net.ListenPacket("udp6", "[::]:5353") // mDNS over UDP |
| 50 | if err != nil { |
| 51 | log.Fatal(err) |
| 52 | } |
| 53 | defer c.Close() |
| 54 | p := ipv6.NewPacketConn(c) |
| 55 | |
| 56 | en0, err := net.InterfaceByName("en0") |
| 57 | if err != nil { |
| 58 | log.Fatal(err) |
| 59 | } |
| 60 | mDNSLinkLocal := net.UDPAddr{IP: net.ParseIP("ff02::fb")} |
| 61 | if err := p.JoinGroup(en0, &mDNSLinkLocal); err != nil { |
| 62 | log.Fatal(err) |
| 63 | } |
| 64 | defer p.LeaveGroup(en0, &mDNSLinkLocal) |
| 65 | if err := p.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { |
| 66 | log.Fatal(err) |
| 67 | } |
| 68 | |
| 69 | var wcm ipv6.ControlMessage |
| 70 | b := make([]byte, 1500) |
| 71 | for { |
| 72 | _, rcm, peer, err := p.ReadFrom(b) |
| 73 | if err != nil { |
| 74 | log.Fatal(err) |
| 75 | } |
| 76 | if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(mDNSLinkLocal.IP) { |
| 77 | continue |
| 78 | } |
| 79 | wcm.IfIndex = rcm.IfIndex |
| 80 | answers := []byte("FAKE-MDNS-ANSWERS") // fake mDNS answers, you need to implement this |
| 81 | if _, err := p.WriteTo(answers, &wcm, peer); err != nil { |
| 82 | log.Fatal(err) |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | func ExamplePacketConn_tracingIPPacketRoute() { |
| 88 | // Tracing an IP packet route to www.google.com. |
| 89 | |
| 90 | const host = "www.google.com" |
| 91 | ips, err := net.LookupIP(host) |
| 92 | if err != nil { |
| 93 | log.Fatal(err) |
| 94 | } |
| 95 | var dst net.IPAddr |
| 96 | for _, ip := range ips { |
| 97 | if ip.To16() != nil && ip.To4() == nil { |
| 98 | dst.IP = ip |
| 99 | fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host) |
| 100 | break |
| 101 | } |
| 102 | } |
| 103 | if dst.IP == nil { |
| 104 | log.Fatal("no AAAA record found") |
| 105 | } |
| 106 | |
Mikio Hara | 66f0418 | 2015-08-17 12:15:29 +0900 | [diff] [blame] | 107 | c, err := net.ListenPacket("ip6:58", "::") // ICMP for IPv6 |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 108 | if err != nil { |
| 109 | log.Fatal(err) |
| 110 | } |
| 111 | defer c.Close() |
| 112 | p := ipv6.NewPacketConn(c) |
| 113 | |
| 114 | if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil { |
| 115 | log.Fatal(err) |
| 116 | } |
| 117 | wm := icmp.Message{ |
| 118 | Type: ipv6.ICMPTypeEchoRequest, Code: 0, |
| 119 | Body: &icmp.Echo{ |
| 120 | ID: os.Getpid() & 0xffff, |
| 121 | Data: []byte("HELLO-R-U-THERE"), |
| 122 | }, |
| 123 | } |
| 124 | var f ipv6.ICMPFilter |
| 125 | f.SetAll(true) |
Mikio Hara | 668aea8 | 2014-12-04 17:32:07 +0900 | [diff] [blame] | 126 | f.Accept(ipv6.ICMPTypeTimeExceeded) |
| 127 | f.Accept(ipv6.ICMPTypeEchoReply) |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 128 | if err := p.SetICMPFilter(&f); err != nil { |
| 129 | log.Fatal(err) |
| 130 | } |
| 131 | |
| 132 | var wcm ipv6.ControlMessage |
| 133 | rb := make([]byte, 1500) |
| 134 | for i := 1; i <= 64; i++ { // up to 64 hops |
| 135 | wm.Body.(*icmp.Echo).Seq = i |
| 136 | wb, err := wm.Marshal(nil) |
| 137 | if err != nil { |
| 138 | log.Fatal(err) |
| 139 | } |
| 140 | |
| 141 | // In the real world usually there are several |
| 142 | // multiple traffic-engineered paths for each hop. |
| 143 | // You may need to probe a few times to each hop. |
| 144 | begin := time.Now() |
| 145 | wcm.HopLimit = i |
| 146 | if _, err := p.WriteTo(wb, &wcm, &dst); err != nil { |
| 147 | log.Fatal(err) |
| 148 | } |
| 149 | if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil { |
| 150 | log.Fatal(err) |
| 151 | } |
| 152 | n, rcm, peer, err := p.ReadFrom(rb) |
| 153 | if err != nil { |
| 154 | if err, ok := err.(net.Error); ok && err.Timeout() { |
| 155 | fmt.Printf("%v\t*\n", i) |
| 156 | continue |
| 157 | } |
| 158 | log.Fatal(err) |
| 159 | } |
Mikio Hara | 66f0418 | 2015-08-17 12:15:29 +0900 | [diff] [blame] | 160 | rm, err := icmp.ParseMessage(58, rb[:n]) |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 161 | if err != nil { |
| 162 | log.Fatal(err) |
| 163 | } |
| 164 | rtt := time.Since(begin) |
| 165 | |
| 166 | // In the real world you need to determine whether the |
| 167 | // received message is yours using ControlMessage.Src, |
| 168 | // ControlMesage.Dst, icmp.Echo.ID and icmp.Echo.Seq. |
| 169 | switch rm.Type { |
| 170 | case ipv6.ICMPTypeTimeExceeded: |
| 171 | names, _ := net.LookupAddr(peer.String()) |
| 172 | fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm) |
| 173 | case ipv6.ICMPTypeEchoReply: |
| 174 | names, _ := net.LookupAddr(peer.String()) |
| 175 | fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, rcm) |
| 176 | return |
| 177 | } |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | func ExamplePacketConn_advertisingOSPFHello() { |
Mikio Hara | 66f0418 | 2015-08-17 12:15:29 +0900 | [diff] [blame] | 182 | c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6 |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 183 | if err != nil { |
| 184 | log.Fatal(err) |
| 185 | } |
| 186 | defer c.Close() |
| 187 | p := ipv6.NewPacketConn(c) |
| 188 | |
| 189 | en0, err := net.InterfaceByName("en0") |
| 190 | if err != nil { |
| 191 | log.Fatal(err) |
| 192 | } |
| 193 | allSPFRouters := net.IPAddr{IP: net.ParseIP("ff02::5")} |
| 194 | if err := p.JoinGroup(en0, &allSPFRouters); err != nil { |
| 195 | log.Fatal(err) |
| 196 | } |
| 197 | defer p.LeaveGroup(en0, &allSPFRouters) |
| 198 | |
| 199 | hello := make([]byte, 24) // fake hello data, you need to implement this |
| 200 | ospf := make([]byte, 16) // fake ospf header, you need to implement this |
| 201 | ospf[0] = 3 // version 3 |
| 202 | ospf[1] = 1 // hello packet |
| 203 | ospf = append(ospf, hello...) |
| 204 | if err := p.SetChecksum(true, 12); err != nil { |
| 205 | log.Fatal(err) |
| 206 | } |
| 207 | |
| 208 | cm := ipv6.ControlMessage{ |
Mikio Hara | 66f0418 | 2015-08-17 12:15:29 +0900 | [diff] [blame] | 209 | TrafficClass: 0xc0, // DSCP CS6 |
Mikio Hara | 7ad508c | 2014-11-19 06:09:29 +0900 | [diff] [blame] | 210 | HopLimit: 1, |
| 211 | IfIndex: en0.Index, |
| 212 | } |
| 213 | if _, err := p.WriteTo(ospf, &cm, &allSPFRouters); err != nil { |
| 214 | log.Fatal(err) |
| 215 | } |
| 216 | } |