...

Source file src/net/rawconn_unix_test.go

Documentation: net

		 1  // Copyright 2017 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  //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
		 6  // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
		 7  
		 8  package net
		 9  
		10  import (
		11  	"errors"
		12  	"syscall"
		13  )
		14  
		15  func readRawConn(c syscall.RawConn, b []byte) (int, error) {
		16  	var operr error
		17  	var n int
		18  	err := c.Read(func(s uintptr) bool {
		19  		n, operr = syscall.Read(int(s), b)
		20  		if operr == syscall.EAGAIN {
		21  			return false
		22  		}
		23  		return true
		24  	})
		25  	if err != nil {
		26  		return n, err
		27  	}
		28  	return n, operr
		29  }
		30  
		31  func writeRawConn(c syscall.RawConn, b []byte) error {
		32  	var operr error
		33  	err := c.Write(func(s uintptr) bool {
		34  		_, operr = syscall.Write(int(s), b)
		35  		if operr == syscall.EAGAIN {
		36  			return false
		37  		}
		38  		return true
		39  	})
		40  	if err != nil {
		41  		return err
		42  	}
		43  	return operr
		44  }
		45  
		46  func controlRawConn(c syscall.RawConn, addr Addr) error {
		47  	var operr error
		48  	fn := func(s uintptr) {
		49  		_, operr = syscall.GetsockoptInt(int(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR)
		50  		if operr != nil {
		51  			return
		52  		}
		53  		switch addr := addr.(type) {
		54  		case *TCPAddr:
		55  			// There's no guarantee that IP-level socket
		56  			// options work well with dual stack sockets.
		57  			// A simple solution would be to take a look
		58  			// at the bound address to the raw connection
		59  			// and to classify the address family of the
		60  			// underlying socket by the bound address:
		61  			//
		62  			// - When IP.To16() != nil and IP.To4() == nil,
		63  			//	 we can assume that the raw connection
		64  			//	 consists of an IPv6 socket using only
		65  			//	 IPv6 addresses.
		66  			//
		67  			// - When IP.To16() == nil and IP.To4() != nil,
		68  			//	 the raw connection consists of an IPv4
		69  			//	 socket using only IPv4 addresses.
		70  			//
		71  			// - Otherwise, the raw connection is a dual
		72  			//	 stack socket, an IPv6 socket using IPv6
		73  			//	 addresses including IPv4-mapped or
		74  			//	 IPv4-embedded IPv6 addresses.
		75  			if addr.IP.To16() != nil && addr.IP.To4() == nil {
		76  				operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
		77  			} else if addr.IP.To16() == nil && addr.IP.To4() != nil {
		78  				operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
		79  			}
		80  		}
		81  	}
		82  	if err := c.Control(fn); err != nil {
		83  		return err
		84  	}
		85  	return operr
		86  }
		87  
		88  func controlOnConnSetup(network string, address string, c syscall.RawConn) error {
		89  	var operr error
		90  	var fn func(uintptr)
		91  	switch network {
		92  	case "tcp", "udp", "ip":
		93  		return errors.New("ambiguous network: " + network)
		94  	case "unix", "unixpacket", "unixgram":
		95  		fn = func(s uintptr) {
		96  			_, operr = syscall.GetsockoptInt(int(s), syscall.SOL_SOCKET, syscall.SO_ERROR)
		97  		}
		98  	default:
		99  		switch network[len(network)-1] {
	 100  		case '4':
	 101  			fn = func(s uintptr) {
	 102  				operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
	 103  			}
	 104  		case '6':
	 105  			fn = func(s uintptr) {
	 106  				operr = syscall.SetsockoptInt(int(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
	 107  			}
	 108  		default:
	 109  			return errors.New("unknown network: " + network)
	 110  		}
	 111  	}
	 112  	if err := c.Control(fn); err != nil {
	 113  		return err
	 114  	}
	 115  	return operr
	 116  }
	 117  

View as plain text