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  }