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
97	// length is family (uint16), name, NUL.
98	return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), sl, nil
99}
100
101func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
102	switch rsa.Addr.Family {
103	case AF_UNIX:
104		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
105		sa := new(SockaddrUnix)
106		n, err := pp.getLen()
107		if err != nil {
108			return nil, err
109		}
110		bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
111		sa.Name = string(bytes[0:n])
112		return sa, nil
113
114	case AF_INET:
115		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
116		sa := new(SockaddrInet4)
117		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
118		sa.Port = int(p[0])<<8 + int(p[1])
119		for i := 0; i < len(sa.Addr); i++ {
120			sa.Addr[i] = pp.Addr[i]
121		}
122		return sa, nil
123
124	case AF_INET6:
125		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
126		sa := new(SockaddrInet6)
127		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
128		sa.Port = int(p[0])<<8 + int(p[1])
129		for i := 0; i < len(sa.Addr); i++ {
130			sa.Addr[i] = pp.Addr[i]
131		}
132		return sa, nil
133	}
134	return anyToSockaddrOS(rsa)
135}
136
137//sys	accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, err error)
138//accept(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
139
140func Accept(fd int) (nfd int, sa Sockaddr, err error) {
141	var rsa RawSockaddrAny
142	var len Socklen_t = SizeofSockaddrAny
143	nfd, err = accept(fd, &rsa, &len)
144	if err != nil {
145		return
146	}
147	sa, err = anyToSockaddr(&rsa)
148	if err != nil {
149		Close(nfd)
150		nfd = 0
151	}
152	return
153}
154
155//sysnb	getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
156//getsockname(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
157
158func Getsockname(fd int) (sa Sockaddr, err error) {
159	var rsa RawSockaddrAny
160	var len Socklen_t = SizeofSockaddrAny
161	if err = getsockname(fd, &rsa, &len); err != nil {
162		return
163	}
164	return anyToSockaddr(&rsa)
165}
166
167//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
168//getpeername(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
169
170func Getpeername(fd int) (sa Sockaddr, err error) {
171	var rsa RawSockaddrAny
172	var len Socklen_t = SizeofSockaddrAny
173	if err = getpeername(fd, &rsa, &len); err != nil {
174		return
175	}
176	return anyToSockaddr(&rsa)
177}
178
179func Bind(fd int, sa Sockaddr) (err error) {
180	ptr, n, err := sa.sockaddr()
181	if err != nil {
182		return err
183	}
184	return bind(fd, ptr, n)
185}
186
187func Connect(fd int, sa Sockaddr) (err error) {
188	ptr, n, err := sa.sockaddr()
189	if err != nil {
190		return err
191	}
192	return connect(fd, ptr, n)
193}
194
195func Socket(domain, typ, proto int) (fd int, err error) {
196	if domain == AF_INET6 && SocketDisableIPv6 {
197		return -1, EAFNOSUPPORT
198	}
199	fd, err = socket(domain, typ, proto)
200	return
201}
202
203func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
204	var fdx [2]_C_int
205	err = socketpair(domain, typ, proto, &fdx)
206	if err == nil {
207		fd[0] = int(fdx[0])
208		fd[1] = int(fdx[1])
209	}
210	return
211}
212
213func GetsockoptByte(fd, level, opt int) (value byte, err error) {
214	var n byte
215	vallen := Socklen_t(1)
216	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
217	return n, err
218}
219
220func GetsockoptInt(fd, level, opt int) (value int, err error) {
221	var n int32
222	vallen := Socklen_t(4)
223	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
224	return int(n), err
225}
226
227func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
228	vallen := Socklen_t(4)
229	err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
230	return value, err
231}
232
233func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
234	var value IPMreq
235	vallen := Socklen_t(SizeofIPMreq)
236	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
237	return &value, err
238}
239
240func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
241	var value IPMreqn
242	vallen := Socklen_t(SizeofIPMreqn)
243	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
244	return &value, err
245}
246
247func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
248	var value IPv6Mreq
249	vallen := Socklen_t(SizeofIPv6Mreq)
250	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
251	return &value, err
252}
253
254func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
255	var value ICMPv6Filter
256	vallen := Socklen_t(SizeofICMPv6Filter)
257	err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
258	return &value, err
259}
260
261//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen Socklen_t) (err error)
262//setsockopt(s _C_int, level _C_int, optname _C_int, val *byte, vallen Socklen_t) _C_int
263
264func SetsockoptByte(fd, level, opt int, value byte) (err error) {
265	var n = byte(value)
266	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 1)
267}
268
269func SetsockoptInt(fd, level, opt int, value int) (err error) {
270	var n = int32(value)
271	return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
272}
273
274func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
275	return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
276}
277
278func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
279	return setsockopt(fd, level, opt, unsafe.Pointer(tv), Socklen_t(unsafe.Sizeof(*tv)))
280}
281
282func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
283	return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
284}
285
286type Linger struct {
287	Onoff  int32
288	Linger int32
289}
290
291func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
292	return setsockopt(fd, level, opt, unsafe.Pointer(l), Socklen_t(unsafe.Sizeof(*l)))
293}
294
295func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
296	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
297}
298
299func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
300	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
301}
302
303func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
304	return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
305}
306
307func SetsockoptString(fd, level, opt int, s string) (err error) {
308	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), Socklen_t(len(s)))
309}
310
311//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, err error)
312//recvfrom(fd _C_int, buf *byte, len Size_t, flags _C_int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
313
314func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
315	var rsa RawSockaddrAny
316	var len Socklen_t = SizeofSockaddrAny
317	if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
318		return
319	}
320	if rsa.Addr.Family != AF_UNSPEC {
321		from, err = anyToSockaddr(&rsa)
322	}
323	return
324}
325
326func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
327	ptr, n, err := to.sockaddr()
328	if err != nil {
329		return err
330	}
331	return sendto(fd, p, flags, ptr, n)
332}
333
334func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
335	var msg Msghdr
336	var rsa RawSockaddrAny
337	msg.Name = (*byte)(unsafe.Pointer(&rsa))
338	msg.Namelen = uint32(SizeofSockaddrAny)
339	var iov Iovec
340	if len(p) > 0 {
341		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
342		iov.SetLen(len(p))
343	}
344	var dummy byte
345	if len(oob) > 0 {
346		// receive at least one normal byte
347		if len(p) == 0 {
348			iov.Base = &dummy
349			iov.SetLen(1)
350		}
351		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
352		msg.SetControllen(len(oob))
353	}
354	msg.Iov = &iov
355	msg.Iovlen = 1
356	if n, err = recvmsg(fd, &msg, flags); err != nil {
357		return
358	}
359	oobn = int(msg.Controllen)
360	recvflags = int(msg.Flags)
361	// source address is only specified if the socket is unconnected
362	if rsa.Addr.Family != AF_UNSPEC {
363		from, err = anyToSockaddr(&rsa)
364	}
365	return
366}
367
368func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
369	_, err = SendmsgN(fd, p, oob, to, flags)
370	return
371}
372
373func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
374	var ptr *RawSockaddrAny
375	var salen Socklen_t
376	if to != nil {
377		var err error
378		ptr, salen, err = to.sockaddr()
379		if err != nil {
380			return 0, err
381		}
382	}
383	var msg Msghdr
384	msg.Name = (*byte)(unsafe.Pointer(ptr))
385	msg.Namelen = uint32(salen)
386	var iov Iovec
387	if len(p) > 0 {
388		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
389		iov.SetLen(len(p))
390	}
391	var dummy byte
392	if len(oob) > 0 {
393		// send at least one normal byte
394		if len(p) == 0 {
395			iov.Base = &dummy
396			iov.SetLen(1)
397		}
398		msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
399		msg.SetControllen(len(oob))
400	}
401	msg.Iov = &iov
402	msg.Iovlen = 1
403	if n, err = sendmsg(fd, &msg, flags); err != nil {
404		return 0, err
405	}
406	if len(oob) > 0 && len(p) == 0 {
407		n = 0
408	}
409	return n, nil
410}
411
412//sys	Listen(fd int, n int) (err error)
413//listen(fd _C_int, n _C_int) _C_int
414
415//sys	Shutdown(fd int, how int) (err error)
416//shutdown(fd _C_int, how _C_int) _C_int
417
418func (iov *Iovec) SetLen(length int) {
419	iov.Len = Iovec_len_t(length)
420}
421
422func (msghdr *Msghdr) SetControllen(length int) {
423	msghdr.Controllen = Msghdr_controllen_t(length)
424}
425
426func (cmsg *Cmsghdr) SetLen(length int) {
427	cmsg.Len = Cmsghdr_len_t(length)
428}
429