Source file src/pkg/net/sockopt.go
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 freebsd linux netbsd openbsd windows 6 7 // Socket options 8 9 package net 10 11 import ( 12 "os" 13 "syscall" 14 "time" 15 ) 16 17 // Boolean to int. 18 func boolint(b bool) int { 19 if b { 20 return 1 21 } 22 return 0 23 } 24 25 func ipv4AddrToInterface(ip IP) (*Interface, error) { 26 ift, err := Interfaces() 27 if err != nil { 28 return nil, err 29 } 30 for _, ifi := range ift { 31 ifat, err := ifi.Addrs() 32 if err != nil { 33 return nil, err 34 } 35 for _, ifa := range ifat { 36 switch v := ifa.(type) { 37 case *IPAddr: 38 if ip.Equal(v.IP) { 39 return &ifi, nil 40 } 41 case *IPNet: 42 if ip.Equal(v.IP) { 43 return &ifi, nil 44 } 45 } 46 } 47 } 48 if ip.Equal(IPv4zero) { 49 return nil, nil 50 } 51 return nil, errNoSuchInterface 52 } 53 54 func interfaceToIPv4Addr(ifi *Interface) (IP, error) { 55 if ifi == nil { 56 return IPv4zero, nil 57 } 58 ifat, err := ifi.Addrs() 59 if err != nil { 60 return nil, err 61 } 62 for _, ifa := range ifat { 63 switch v := ifa.(type) { 64 case *IPAddr: 65 if v.IP.To4() != nil { 66 return v.IP, nil 67 } 68 case *IPNet: 69 if v.IP.To4() != nil { 70 return v.IP, nil 71 } 72 } 73 } 74 return nil, errNoSuchInterface 75 } 76 77 func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error { 78 if ifi == nil { 79 return nil 80 } 81 ifat, err := ifi.Addrs() 82 if err != nil { 83 return err 84 } 85 for _, ifa := range ifat { 86 switch v := ifa.(type) { 87 case *IPAddr: 88 if a := v.IP.To4(); a != nil { 89 copy(mreq.Interface[:], a) 90 goto done 91 } 92 case *IPNet: 93 if a := v.IP.To4(); a != nil { 94 copy(mreq.Interface[:], a) 95 goto done 96 } 97 } 98 } 99 done: 100 if bytesEqual(mreq.Multiaddr[:], IPv4zero.To4()) { 101 return errNoSuchMulticastInterface 102 } 103 return nil 104 } 105 106 func setReadBuffer(fd *netFD, bytes int) error { 107 if err := fd.incref(false); err != nil { 108 return err 109 } 110 defer fd.decref() 111 return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)) 112 } 113 114 func setWriteBuffer(fd *netFD, bytes int) error { 115 if err := fd.incref(false); err != nil { 116 return err 117 } 118 defer fd.decref() 119 return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)) 120 } 121 122 func setReadDeadline(fd *netFD, t time.Time) error { 123 if t.IsZero() { 124 fd.rdeadline = 0 125 } else { 126 fd.rdeadline = t.UnixNano() 127 } 128 return nil 129 } 130 131 func setWriteDeadline(fd *netFD, t time.Time) error { 132 if t.IsZero() { 133 fd.wdeadline = 0 134 } else { 135 fd.wdeadline = t.UnixNano() 136 } 137 return nil 138 } 139 140 func setDeadline(fd *netFD, t time.Time) error { 141 if err := setReadDeadline(fd, t); err != nil { 142 return err 143 } 144 return setWriteDeadline(fd, t) 145 } 146 147 func setReuseAddr(fd *netFD, reuse bool) error { 148 if err := fd.incref(false); err != nil { 149 return err 150 } 151 defer fd.decref() 152 return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))) 153 } 154 155 func setDontRoute(fd *netFD, dontroute bool) error { 156 if err := fd.incref(false); err != nil { 157 return err 158 } 159 defer fd.decref() 160 return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))) 161 } 162 163 func setKeepAlive(fd *netFD, keepalive bool) error { 164 if err := fd.incref(false); err != nil { 165 return err 166 } 167 defer fd.decref() 168 return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))) 169 } 170 171 func setNoDelay(fd *netFD, noDelay bool) error { 172 if err := fd.incref(false); err != nil { 173 return err 174 } 175 defer fd.decref() 176 return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))) 177 } 178 179 func setLinger(fd *netFD, sec int) error { 180 var l syscall.Linger 181 if sec >= 0 { 182 l.Onoff = 1 183 l.Linger = int32(sec) 184 } else { 185 l.Onoff = 0 186 l.Linger = 0 187 } 188 if err := fd.incref(false); err != nil { 189 return err 190 } 191 defer fd.decref() 192 return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l)) 193 }