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.
7package socket // import "golang.org/x/net/internal/socket"
8
9import (
10	"errors"
11	"net"
12	"runtime"
13	"unsafe"
14)
15
16var errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
17
18// An Option represents a sticky socket option.
19type 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.
27func (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.
40func (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.
65func (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.
78func (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.
94func 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.
105type ControlMessage []byte
106
107// Data returns the data field of the control message at the head on
108// m.
109func (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.
120func (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.
130func (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.
141func (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.
152func (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.
168func (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.
210func 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.
219type 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.
246func (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.
254func (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.
266func (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.
278func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
279	return c.sendMsgs(ms, flags)
280}
281