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