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 }