1 // Copyright 2017 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 // Package socket provides a portable interface for socket system
6 // calls.
7 package socket // import "golang.org/x/net/internal/socket"
8 9 import (
10 "errors"
11 "net"
12 "runtime"
13 "unsafe"
14 )
15 16 var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
17 18 // An Option represents a sticky socket option.
19 type Option struct {
20 Level int // level
21 Name int // name; must be equal or greater than 1
22 Len int // length of value in bytes; must be equal or greater than 1
23 }
24 25 // Get reads a value for the option from the kernel.
26 // It returns the number of bytes written into b.
27 func (o *Option) Get(c *Conn, b []byte) (int, error) {
28 if o.Name < 1 || o.Len < 1 {
29 return 0, errors.New("invalid option")
30 }
31 if len(b) < o.Len {
32 return 0, errors.New("short buffer")
33 }
34 return o.get(c, b)
35 }
36 37 // GetInt returns an integer value for the option.
38 //
39 // The Len field of Option must be either 1 or 4.
40 func (o *Option) GetInt(c *Conn) (int, error) {
41 if o.Len != 1 && o.Len != 4 {
42 return 0, errors.New("invalid option")
43 }
44 var b []byte
45 var bb [4]byte
46 if o.Len == 1 {
47 b = bb[:1]
48 } else {
49 b = bb[:4]
50 }
51 n, err := o.get(c, b)
52 if err != nil {
53 return 0, err
54 }
55 if n != o.Len {
56 return 0, errors.New("invalid option length")
57 }
58 if o.Len == 1 {
59 return int(b[0]), nil
60 }
61 return int(NativeEndian.Uint32(b[:4])), nil
62 }
63 64 // Set writes the option and value to the kernel.
65 func (o *Option) Set(c *Conn, b []byte) error {
66 if o.Name < 1 || o.Len < 1 {
67 return errors.New("invalid option")
68 }
69 if len(b) < o.Len {
70 return errors.New("short buffer")
71 }
72 return o.set(c, b)
73 }
74 75 // SetInt writes the option and value to the kernel.
76 //
77 // The Len field of Option must be either 1 or 4.
78 func (o *Option) SetInt(c *Conn, v int) error {
79 if o.Len != 1 && o.Len != 4 {
80 return errors.New("invalid option")
81 }
82 var b []byte
83 if o.Len == 1 {
84 b = []byte{byte(v)}
85 } else {
86 var bb [4]byte
87 NativeEndian.PutUint32(bb[:o.Len], uint32(v))
88 b = bb[:4]
89 }
90 return o.set(c, b)
91 }
92 93 // ControlMessageSpace returns the whole length of control message.
94 func ControlMessageSpace(dataLen int) int {
95 return controlMessageSpace(dataLen)
96 }
97 98 // A ControlMessage represents the head message in a stream of control
99 // messages.
100 //
101 // A control message comprises of a header, data and a few padding
102 // fields to conform to the interface to the kernel.
103 //
104 // See RFC 3542 for further information.
105 type ControlMessage []byte
106 107 // Data returns the data field of the control message at the head on
108 // m.
109 func (m ControlMessage) Data(dataLen int) []byte {
110 l := controlHeaderLen()
111 if len(m) < l || len(m) < l+dataLen {
112 return nil
113 }
114 return m[l : l+dataLen]
115 }
116 117 // Next returns the control message at the next on m.
118 //
119 // Next works only for standard control messages.
120 func (m ControlMessage) Next(dataLen int) ControlMessage {
121 l := ControlMessageSpace(dataLen)
122 if len(m) < l {
123 return nil
124 }
125 return m[l:]
126 }
127 128 // MarshalHeader marshals the header fields of the control message at
129 // the head on m.
130 func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
131 if len(m) < controlHeaderLen() {
132 return errors.New("short message")
133 }
134 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
135 h.set(controlMessageLen(dataLen), lvl, typ)
136 return nil
137 }
138 139 // ParseHeader parses and returns the header fields of the control
140 // message at the head on m.
141 func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err error) {
142 l := controlHeaderLen()
143 if len(m) < l {
144 return 0, 0, 0, errors.New("short message")
145 }
146 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
147 return h.lvl(), h.typ(), int(uint64(h.len()) - uint64(l)), nil
148 }
149 150 // Marshal marshals the control message at the head on m, and returns
151 // the next control message.
152 func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMessage, error) {
153 l := len(data)
154 if len(m) < ControlMessageSpace(l) {
155 return nil, errors.New("short message")
156 }
157 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
158 h.set(controlMessageLen(l), lvl, typ)
159 if l > 0 {
160 copy(m.Data(l), data)
161 }
162 return m.Next(l), nil
163 }
164 165 // Parse parses m as a single or multiple control messages.
166 //
167 // Parse works for both standard and compatible messages.
168 func (m ControlMessage) Parse() ([]ControlMessage, error) {
169 var ms []ControlMessage
170 for len(m) >= controlHeaderLen() {
171 h := (*cmsghdr)(unsafe.Pointer(&m[0]))
172 l := h.len()
173 if l <= 0 {
174 return nil, errors.New("invalid header length")
175 }
176 if uint64(l) < uint64(controlHeaderLen()) {
177 return nil, errors.New("invalid message length")
178 }
179 if uint64(l) > uint64(len(m)) {
180 return nil, errors.New("short buffer")
181 }
182 // On message reception:
183 //
184 // |<- ControlMessageSpace --------------->|
185 // |<- controlMessageLen ---------->| |
186 // |<- controlHeaderLen ->| | |
187 // +---------------+------+---------+------+
188 // | Header | PadH | Data | PadD |
189 // +---------------+------+---------+------+
190 //
191 // On compatible message reception:
192 //
193 // | ... |<- controlMessageLen ----------->|
194 // | ... |<- controlHeaderLen ->| |
195 // +-----+---------------+------+----------+
196 // | ... | Header | PadH | Data |
197 // +-----+---------------+------+----------+
198 ms = append(ms, ControlMessage(m[:l]))
199 ll := l - controlHeaderLen()
200 if len(m) >= ControlMessageSpace(ll) {
201 m = m[ControlMessageSpace(ll):]
202 } else {
203 m = m[controlMessageLen(ll):]
204 }
205 }
206 return ms, nil
207 }
208 209 // NewControlMessage returns a new stream of control messages.
210 func NewControlMessage(dataLen []int) ControlMessage {
211 var l int
212 for i := range dataLen {
213 l += ControlMessageSpace(dataLen[i])
214 }
215 return make([]byte, l)
216 }
217 218 // A Message represents an IO message.
219 type Message struct {
220 // When writing, the Buffers field must contain at least one
221 // byte to write.
222 // When reading, the Buffers field will always contain a byte
223 // to read.
224 Buffers [][]byte
225 226 // OOB contains protocol-specific control or miscellaneous
227 // ancillary data known as out-of-band data.
228 OOB []byte
229 230 // Addr specifies a destination address when writing.
231 // It can be nil when the underlying protocol of the raw
232 // connection uses connection-oriented communication.
233 // After a successful read, it may contain the source address
234 // on the received packet.
235 Addr net.Addr
236 237 N int // # of bytes read or written from/to Buffers
238 NN int // # of bytes read or written from/to OOB
239 Flags int // protocol-specific information on the received message
240 }
241 242 // RecvMsg wraps recvmsg system call.
243 //
244 // The provided flags is a set of platform-dependent flags, such as
245 // syscall.MSG_PEEK.
246 func (c *Conn) RecvMsg(m *Message, flags int) error {
247 return c.recvMsg(m, flags)
248 }
249 250 // SendMsg wraps sendmsg system call.
251 //
252 // The provided flags is a set of platform-dependent flags, such as
253 // syscall.MSG_DONTROUTE.
254 func (c *Conn) SendMsg(m *Message, flags int) error {
255 return c.sendMsg(m, flags)
256 }
257 258 // RecvMsgs wraps recvmmsg system call.
259 //
260 // It returns the number of processed messages.
261 //
262 // The provided flags is a set of platform-dependent flags, such as
263 // syscall.MSG_PEEK.
264 //
265 // Only Linux supports this.
266 func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
267 return c.recvMsgs(ms, flags)
268 }
269 270 // SendMsgs wraps sendmmsg system call.
271 //
272 // It returns the number of processed messages.
273 //
274 // The provided flags is a set of platform-dependent flags, such as
275 // syscall.MSG_DONTROUTE.
276 //
277 // Only Linux supports this.
278 func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
279 return c.sendMsgs(ms, flags)
280 }
281