github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/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  	"github.com/hxx258456/ccgo/net/icmp"
    16  	"github.com/hxx258456/ccgo/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  }