1// socket.go -- Socket handling.
2
3// Copyright 2009 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Low-level socket interface.
8// Only for implementing net package.
9// DO NOT USE DIRECTLY.
10
11package syscall
12
13import "unsafe"
14
15// For testing: clients can set this flag to force
16// creation of IPv6 sockets to return EAFNOSUPPORT.
17var SocketDisableIPv6 bool
18
19type Sockaddr interface {
20	sockaddr() (ptr *RawSockaddrAny, len Socklen_t, err error) // lowercase; only we can define Sockaddrs
21}
22
23type RawSockaddrAny struct {
24	Addr RawSockaddr
25	Pad  [96]int8
26}
27
28const SizeofSockaddrAny = 0x6c
29
30type SockaddrInet4 struct {
31	Port int
32	Addr [4]byte
33	raw  RawSockaddrInet4
34}
35
36func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
37	if sa.Port < 0 || sa.Port > 0xFFFF {
38		return nil, 0, EINVAL
39	}
40	sa.raw.Family = AF_INET
41	n := sa.raw.setLen()
42	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
43	p[0] = byte(sa.Port >> 8)
44	p[1] = byte(sa.Port)
45	for i := 0; i < len(sa.Addr); i++ {
46		sa.raw.Addr[i] = sa.Addr[i]
47	}
48	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil
49}
50
51type SockaddrInet6 struct {
52	Port   int
53	ZoneId uint32
54	Addr   [16]byte
55	raw    RawSockaddrInet6
56}
57
58func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
59	if sa.Port < 0 || sa.Port > 0xFFFF {
60		return nil, 0, EINVAL
61	}
62	sa.raw.Family = AF_INET6
63	n := sa.raw.setLen()
64	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
65	p[0] = byte(sa.Port >> 8)
66	p[1] = byte(sa.Port)
67	sa.raw.Scope_id = sa.ZoneId
68	for i := 0; i < len(sa.Addr); i++ {
69		sa.raw.Addr[i] = sa.Addr[i]
70	}
71	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil
72}
73
74type SockaddrUnix struct {
75	Name string
76	raw  RawSockaddrUnix
77}
78
79func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
80	name := sa.Name
81	n := len(name)
82	if n > len(sa.raw.Path) {
83		return nil, 0, EINVAL
84	}
85	sa.raw.Family = AF_UNIX
86	sa.raw.setLen(n)
87	for i := 0; i < n; i++ {
88		sa.raw.Path[i] = int8(name[i])
89	}
90	// length is family (uint16), name, NUL.
91	sl := Socklen_t(2)
92	if n > 0 {
93		sl += Socklen_t(n) + 1
94	}
95	sl = sa.raw.adjustAbstract(sl)
96	// Check again after adjustAbstract adjusts the length.
97	// This is testing whether the +1 for NUL puts us out of range.
98	if sl-2 > Socklen_t(len(sa.raw.Path)) {
99		return nil, 0, EINVAL
100	}
101
102	// length is family (uint16), name, NUL.
103	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), sl, nil
104}
105
106func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
107	switch rsa.Addr.Family {
108	case AF_UNIX:
109		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
110		sa := new(SockaddrUnix)
111		n, err := pp.getLen()
112		if err != nil {
113			return nil, err
114		}
115		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
116		sa.Name = string(bytes[0:n])
117		return sa, nil
118
119	case AF_INET:
120		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
121		sa := new(SockaddrInet4)
122		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
123		sa.Port = int(p[0])<<8 + int(p[1])
124		for i := 0; i < len(sa.Addr); i++ {
125			sa.Addr[i] = pp.Addr[i]
126		}
127		return sa, nil
128
129	case AF_INET6:
130		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
131		sa := new(SockaddrInet6)
132		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
133		sa.Port = int(p[0])<<8 + int(p[1])
134		for i := 0; i < len(sa.Addr); i++ {
135			sa.Addr[i] = pp.Addr[i]
136		}
137		return sa, nil
138	}
139	return anyToSockaddrOS(rsa)
140}
141
142//sys	accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, err error)
143//accept(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
144
145func Accept(fd int) (nfd int, sa Sockaddr, err error) {
146	var rsa RawSockaddrAny
147	var len Socklen_t = SizeofSockaddrAny
148	nfd, err = accept(fd, &rsa, &len)
149	if err != nil {
150		return
151	}
152	sa, err = anyToSockaddr(&rsa)
153	if err != nil {
154		Close(nfd)
155		nfd = 0
156	}
157	return
158}
159
160//sysnb	getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
161//getsockname(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
162
163func Getsockname(fd int) (sa Sockaddr, err error) {
164	var rsa RawSockaddrAny
165	var len Socklen_t = SizeofSockaddrAny
166	if err = getsockname(fd, &rsa, &len); err != nil {
167		return
168	}
169	return anyToSockaddr(&rsa)
170}
171
172//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
173//getpeername(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
174
175func Getpeername(fd int) (sa Sockaddr, err error) {
176	var rsa RawSockaddrAny
177	var len Socklen_t = SizeofSockaddrAny
178	if err = getpeername(fd, &rsa, &len); err != nil {
179		return
180	}
181	return anyToSockaddr(&rsa)
182}
183
184func Bind(fd int, sa Sockaddr) (err error) {
185	ptr, n, err := sa.sockaddr()
186	if err != nil {
187		return err
188	}
189	return bind(fd, ptr, n)
190}
191
192func Connect(fd int, sa Sockaddr) (err error) {
193	ptr, n, err := sa.sockaddr()
194	if err != nil {
195		return err
196	}
197	return connect(fd, ptr, n)
198}
199
200func Socket(domain, typ, proto int) (fd int, err error) {
201	if domain == AF_INET6 && SocketDisableIPv6 {
202		return -1, EAFNOSUPPORT
203	}
204	fd, err = socket(domain, typ, proto)
205	return
206}
207
208func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
209	var fdx [2]_C_int
210	err = socketpair(domain, typ, proto, &fdx)
211	if err == nil {
212		fd[0] = int(fdx[0])
213		fd[1] = int(fdx[1])
214	}
215	return
216}
217
218func GetsockoptByte(fd, level, opt int) (value byte, err error) {
219	var n byte
220	vallen := Socklen_t(1)
221	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
222	return n, err
223}
224
225func GetsockoptInt(fd, level, opt int) (value int, err error) {
226	var n int32
227	vallen := Socklen_t(4)
228	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
229	return int(n), err
230}
231
232func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
233	vallen := Socklen_t(4)
234	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
235	return value, err
236}
237
238func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
239	var value IPMreq
240	vallen := Socklen_t(SizeofIPMreq)
241	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
242	return &value, err
243}
244
245func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
246	var value IPMreqn
247	vallen := Socklen_t(SizeofIPMreqn)
248	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
249	return &value, err
250}
251
252func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
253	var value IPv6Mreq
254	vallen := Socklen_t(SizeofIPv6Mreq)
255	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
256	return &value, err
257}
258
259func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
260	var value ICMPv6Filter
261	vallen := Socklen_t(SizeofICMPv6Filter)
262	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
263	return &value, err
264}
265
266//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen Socklen_t) (err error)
267//setsockopt(s _C_int, level _C_int, optname _C_int, val *byte, vallen Socklen_t) _C_int
268
269func SetsockoptByte(fd, level, opt int, value byte) (err error) {
270	var n = byte(value)
271	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 1)
272}
273
274func SetsockoptInt(fd, level, opt int, value int) (err error) {
275	var n = int32(value)
276	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
277}
278
279func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
280	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
281}
282
283func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
284	return setsockopt(fd, level, opt, unsafe.Pointer(tv), Socklen_t(unsafe.Sizeof(*tv)))
285}
286
287func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
288	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
289}
290
291type Linger struct {
292	Onoff  int32
293	Linger int32
294}
295
296func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
297	return setsockopt(fd, level, opt, unsafe.Pointer(l), Socklen_t(unsafe.Sizeof(*l)))
298}
299
300func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
301	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
302}
303
304func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
305	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
306}
307
308func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
309	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
310}
311
312func SetsockoptString(fd, level, opt int, s string) (err error) {
313	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), Socklen_t(len(s)))
314}
315
316//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, err error)
317//recvfrom(fd _C_int, buf *byte, len Size_t, flags _C_int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
318
319func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
320	var rsa RawSockaddrAny
321	var len Socklen_t = SizeofSockaddrAny
322	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
323		return
324	}
325	if rsa.Addr.Family != AF_UNSPEC {
326		from, err = anyToSockaddr(&rsa)
327	}
328	return
329}
330
331func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
332	ptr, n, err := to.sockaddr()
333	if err != nil {
334		return err
335	}
336	return sendto(fd, p, flags, ptr, n)
337}
338
339func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
340	var msg Msghdr
341	var rsa RawSockaddrAny
342	msg.Name = (*byte)(unsafe.Pointer(&rsa))
343	msg.Namelen = uint32(SizeofSockaddrAny)
344	var iov Iovec
345	if len(p) > 0 {
346		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
347		iov.SetLen(len(p))
348	}
349	var dummy byte
350	if len(oob) > 0 {
351		var sockType int
352		sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
353		if err != nil {
354			return
355		}
356		// receive at least one normal byte
357		if sockType != SOCK_DGRAM && len(p) == 0 {
358			iov.Base = &dummy
359			iov.SetLen(1)
360		}
361		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
362		msg.SetControllen(len(oob))
363	}
364	msg.Iov = &iov
365	msg.Iovlen = 1
366	if n, err = recvmsg(fd, &msg, flags); err != nil {
367		return
368	}
369	oobn = int(msg.Controllen)
370	recvflags = int(msg.Flags)
371	// source address is only specified if the socket is unconnected
372	if rsa.Addr.Family != AF_UNSPEC {
373		from, err = anyToSockaddr(&rsa)
374	}
375	return
376}
377
378func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
379	_, err = SendmsgN(fd, p, oob, to, flags)
380	return
381}
382
383func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
384	var ptr *RawSockaddrAny
385	var salen Socklen_t
386	if to != nil {
387		var err error
388		ptr, salen, err = to.sockaddr()
389		if err != nil {
390			return 0, err
391		}
392	}
393	var msg Msghdr
394	msg.Name = (*byte)(unsafe.Pointer(ptr))
395	msg.Namelen = uint32(salen)
396	var iov Iovec
397	if len(p) > 0 {
398		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
399		iov.SetLen(len(p))
400	}
401	var dummy byte
402	if len(oob) > 0 {
403		var sockType int
404		sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
405		if err != nil {
406			return 0, err
407		}
408		// send at least one normal byte
409		if sockType != SOCK_DGRAM && len(p) == 0 {
410			iov.Base = &dummy
411			iov.SetLen(1)
412		}
413		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
414		msg.SetControllen(len(oob))
415	}
416	msg.Iov = &iov
417	msg.Iovlen = 1
418	if n, err = sendmsg(fd, &msg, flags); err != nil {
419		return 0, err
420	}
421	if len(oob) > 0 && len(p) == 0 {
422		n = 0
423	}
424	return n, nil
425}
426
427//sys	Listen(fd int, n int) (err error)
428//listen(fd _C_int, n _C_int) _C_int
429
430//sys	Shutdown(fd int, how int) (err error)
431//shutdown(fd _C_int, how _C_int) _C_int
432
433func (iov *Iovec) SetLen(length int) {
434	iov.Len = Iovec_len_t(length)
435}
436
437func (msghdr *Msghdr) SetControllen(length int) {
438	msghdr.Controllen = Msghdr_controllen_t(length)
439}
440
441func (cmsg *Cmsghdr) SetLen(length int) {
442	cmsg.Len = Cmsghdr_len_t(length)
443}
444