github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/net/sockopt_posix.go (about)

     1  // Copyright 2009 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  // +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
     6  
     7  package net
     8  
     9  import (
    10  	"runtime"
    11  	"syscall"
    12  )
    13  
    14  // Boolean to int.
    15  func boolint(b bool) int {
    16  	if b {
    17  		return 1
    18  	}
    19  	return 0
    20  }
    21  
    22  func ipv4AddrToInterface(ip IP) (*Interface, error) {
    23  	ift, err := Interfaces()
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	for _, ifi := range ift {
    28  		ifat, err := ifi.Addrs()
    29  		if err != nil {
    30  			return nil, err
    31  		}
    32  		for _, ifa := range ifat {
    33  			switch v := ifa.(type) {
    34  			case *IPAddr:
    35  				if ip.Equal(v.IP) {
    36  					return &ifi, nil
    37  				}
    38  			case *IPNet:
    39  				if ip.Equal(v.IP) {
    40  					return &ifi, nil
    41  				}
    42  			}
    43  		}
    44  	}
    45  	if ip.Equal(IPv4zero) {
    46  		return nil, nil
    47  	}
    48  	return nil, errNoSuchInterface
    49  }
    50  
    51  func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
    52  	if ifi == nil {
    53  		return IPv4zero, nil
    54  	}
    55  	ifat, err := ifi.Addrs()
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	for _, ifa := range ifat {
    60  		switch v := ifa.(type) {
    61  		case *IPAddr:
    62  			if v.IP.To4() != nil {
    63  				return v.IP, nil
    64  			}
    65  		case *IPNet:
    66  			if v.IP.To4() != nil {
    67  				return v.IP, nil
    68  			}
    69  		}
    70  	}
    71  	return nil, errNoSuchInterface
    72  }
    73  
    74  func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
    75  	if ifi == nil {
    76  		return nil
    77  	}
    78  	ifat, err := ifi.Addrs()
    79  	if err != nil {
    80  		return err
    81  	}
    82  	for _, ifa := range ifat {
    83  		switch v := ifa.(type) {
    84  		case *IPAddr:
    85  			if a := v.IP.To4(); a != nil {
    86  				copy(mreq.Interface[:], a)
    87  				goto done
    88  			}
    89  		case *IPNet:
    90  			if a := v.IP.To4(); a != nil {
    91  				copy(mreq.Interface[:], a)
    92  				goto done
    93  			}
    94  		}
    95  	}
    96  done:
    97  	if bytesEqual(mreq.Multiaddr[:], IPv4zero.To4()) {
    98  		return errNoSuchMulticastInterface
    99  	}
   100  	return nil
   101  }
   102  
   103  func setReadBuffer(fd *netFD, bytes int) error {
   104  	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
   105  	runtime.KeepAlive(fd)
   106  	return wrapSyscallError("setsockopt", err)
   107  }
   108  
   109  func setWriteBuffer(fd *netFD, bytes int) error {
   110  	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
   111  	runtime.KeepAlive(fd)
   112  	return wrapSyscallError("setsockopt", err)
   113  }
   114  
   115  func setKeepAlive(fd *netFD, keepalive bool) error {
   116  	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
   117  	runtime.KeepAlive(fd)
   118  	return wrapSyscallError("setsockopt", err)
   119  }
   120  
   121  func setLinger(fd *netFD, sec int) error {
   122  	var l syscall.Linger
   123  	if sec >= 0 {
   124  		l.Onoff = 1
   125  		l.Linger = int32(sec)
   126  	} else {
   127  		l.Onoff = 0
   128  		l.Linger = 0
   129  	}
   130  	err := fd.pfd.SetsockoptLinger(syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
   131  	runtime.KeepAlive(fd)
   132  	return wrapSyscallError("setsockopt", err)
   133  }