golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/ipv6/example_test.go (about) 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 14 "golang.org/x/net/icmp" 15 "golang.org/x/net/ipv6" 16 ) 17 18 func ExampleConn_markingTCP() { 19 ln, err := net.Listen("tcp", "[::]:1024") 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() 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 } 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 107 c, err := net.ListenPacket("ip6:58", "::") // ICMP for IPv6 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) 126 f.Accept(ipv6.ICMPTypeTimeExceeded) 127 f.Accept(ipv6.ICMPTypeEchoReply) 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 } 160 rm, err := icmp.ParseMessage(58, rb[:n]) 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() { 182 c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6 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{ 209 TrafficClass: 0xc0, // DSCP CS6 210 HopLimit: 1, 211 IfIndex: en0.Index, 212 } 213 if _, err := p.WriteTo(ospf, &cm, &allSPFRouters); err != nil { 214 log.Fatal(err) 215 } 216 }