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