Home | History | Annotate | Download | only in net
      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 }
    134