i386: Fix cstorebf4 fp comparison operand [PR117495]
[official-gcc.git] / libgo / go / syscall / socket.go
blob54a4a9940c64c4850017cdf4857c8dea3acba28e
1 // socket.go -- Socket handling.
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.
7 // Low-level socket interface.
8 // Only for implementing net package.
9 // DO NOT USE DIRECTLY.
11 package syscall
13 import "unsafe"
15 // These functions are called from the internal/syscall/unix package.
16 // Use go:linkname to export them.
18 //go:linkname recvfromInet4
19 //go:linkname recvfromInet6
20 //go:linkname sendtoInet4
21 //go:linkname sendtoInet6
22 //go:linkname sendmsgNInet4
23 //go:linkname sendmsgNInet6
24 //go:linkname recvmsgInet4
25 //go:linkname recvmsgInet6
27 // For testing: clients can set this flag to force
28 // creation of IPv6 sockets to return EAFNOSUPPORT.
29 var SocketDisableIPv6 bool
31 type Sockaddr interface {
32 sockaddr() (ptr *RawSockaddrAny, len Socklen_t, err error) // lowercase; only we can define Sockaddrs
35 type RawSockaddrAny struct {
36 Addr RawSockaddr
37 Pad [96]int8
40 const SizeofSockaddrAny = 0x6c
42 type SockaddrInet4 struct {
43 Port int
44 Addr [4]byte
45 raw RawSockaddrInet4
48 func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
49 if sa.Port < 0 || sa.Port > 0xFFFF {
50 return nil, 0, EINVAL
52 sa.raw.Family = AF_INET
53 n := sa.raw.setLen()
54 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
55 p[0] = byte(sa.Port >> 8)
56 p[1] = byte(sa.Port)
57 for i := 0; i < len(sa.Addr); i++ {
58 sa.raw.Addr[i] = sa.Addr[i]
60 return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil
63 type SockaddrInet6 struct {
64 Port int
65 ZoneId uint32
66 Addr [16]byte
67 raw RawSockaddrInet6
70 func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
71 if sa.Port < 0 || sa.Port > 0xFFFF {
72 return nil, 0, EINVAL
74 sa.raw.Family = AF_INET6
75 n := sa.raw.setLen()
76 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
77 p[0] = byte(sa.Port >> 8)
78 p[1] = byte(sa.Port)
79 sa.raw.Scope_id = sa.ZoneId
80 for i := 0; i < len(sa.Addr); i++ {
81 sa.raw.Addr[i] = sa.Addr[i]
83 return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, nil
86 type SockaddrUnix struct {
87 Name string
88 raw RawSockaddrUnix
91 func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, error) {
92 name := sa.Name
93 n := len(name)
94 if n > len(sa.raw.Path) {
95 return nil, 0, EINVAL
97 sa.raw.Family = AF_UNIX
98 sa.raw.setLen(n)
99 for i := 0; i < n; i++ {
100 sa.raw.Path[i] = int8(name[i])
102 // length is family (uint16), name, NUL.
103 sl := Socklen_t(2)
104 if n > 0 {
105 sl += Socklen_t(n) + 1
107 sl = sa.raw.adjustAbstract(sl)
108 // Check again after adjustAbstract adjusts the length.
109 // This is testing whether the +1 for NUL puts us out of range.
110 if sl-2 > Socklen_t(len(sa.raw.Path)) {
111 return nil, 0, EINVAL
114 // length is family (uint16), name, NUL.
115 return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), sl, nil
118 func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
119 switch rsa.Addr.Family {
120 case AF_UNIX:
121 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
122 sa := new(SockaddrUnix)
123 n, err := pp.getLen()
124 if err != nil {
125 return nil, err
127 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))
128 sa.Name = string(bytes[0:n])
129 return sa, nil
131 case AF_INET:
132 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
133 sa := new(SockaddrInet4)
134 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
135 sa.Port = int(p[0])<<8 + int(p[1])
136 for i := 0; i < len(sa.Addr); i++ {
137 sa.Addr[i] = pp.Addr[i]
139 return sa, nil
141 case AF_INET6:
142 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
143 sa := new(SockaddrInet6)
144 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
145 sa.Port = int(p[0])<<8 + int(p[1])
146 for i := 0; i < len(sa.Addr); i++ {
147 sa.Addr[i] = pp.Addr[i]
149 return sa, nil
151 return anyToSockaddrOS(rsa)
154 //sys accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, err error)
155 //accept(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
157 func Accept(fd int) (nfd int, sa Sockaddr, err error) {
158 var rsa RawSockaddrAny
159 var len Socklen_t = SizeofSockaddrAny
160 nfd, err = accept(fd, &rsa, &len)
161 if err != nil {
162 return
164 sa, err = anyToSockaddr(&rsa)
165 if err != nil {
166 Close(nfd)
167 nfd = 0
169 return
172 //sysnb getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
173 //getsockname(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
175 func Getsockname(fd int) (sa Sockaddr, err error) {
176 var rsa RawSockaddrAny
177 var len Socklen_t = SizeofSockaddrAny
178 if err = getsockname(fd, &rsa, &len); err != nil {
179 return
181 return anyToSockaddr(&rsa)
184 //sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (err error)
185 //getpeername(fd _C_int, sa *RawSockaddrAny, len *Socklen_t) _C_int
187 func Getpeername(fd int) (sa Sockaddr, err error) {
188 var rsa RawSockaddrAny
189 var len Socklen_t = SizeofSockaddrAny
190 if err = getpeername(fd, &rsa, &len); err != nil {
191 return
193 return anyToSockaddr(&rsa)
196 func Bind(fd int, sa Sockaddr) (err error) {
197 ptr, n, err := sa.sockaddr()
198 if err != nil {
199 return err
201 return bind(fd, ptr, n)
204 func Connect(fd int, sa Sockaddr) (err error) {
205 ptr, n, err := sa.sockaddr()
206 if err != nil {
207 return err
209 return connect(fd, ptr, n)
212 func Socket(domain, typ, proto int) (fd int, err error) {
213 if domain == AF_INET6 && SocketDisableIPv6 {
214 return -1, EAFNOSUPPORT
216 fd, err = socket(domain, typ, proto)
217 return
220 func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
221 var fdx [2]_C_int
222 err = socketpair(domain, typ, proto, &fdx)
223 if err == nil {
224 fd[0] = int(fdx[0])
225 fd[1] = int(fdx[1])
227 return
230 func GetsockoptByte(fd, level, opt int) (value byte, err error) {
231 var n byte
232 vallen := Socklen_t(1)
233 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
234 return n, err
237 func GetsockoptInt(fd, level, opt int) (value int, err error) {
238 var n int32
239 vallen := Socklen_t(4)
240 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
241 return int(n), err
244 func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
245 vallen := Socklen_t(4)
246 err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
247 return value, err
250 func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
251 var value IPMreq
252 vallen := Socklen_t(SizeofIPMreq)
253 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
254 return &value, err
257 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
258 var value IPMreqn
259 vallen := Socklen_t(SizeofIPMreqn)
260 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
261 return &value, err
264 func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
265 var value IPv6Mreq
266 vallen := Socklen_t(SizeofIPv6Mreq)
267 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
268 return &value, err
271 func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
272 var value ICMPv6Filter
273 vallen := Socklen_t(SizeofICMPv6Filter)
274 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
275 return &value, err
278 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen Socklen_t) (err error)
279 //setsockopt(s _C_int, level _C_int, optname _C_int, val *byte, vallen Socklen_t) _C_int
281 func SetsockoptByte(fd, level, opt int, value byte) (err error) {
282 var n = byte(value)
283 return setsockopt(fd, level, opt, unsafe.Pointer(&n), 1)
286 func SetsockoptInt(fd, level, opt int, value int) (err error) {
287 var n = int32(value)
288 return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
291 func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
292 return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
295 func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
296 return setsockopt(fd, level, opt, unsafe.Pointer(tv), Socklen_t(unsafe.Sizeof(*tv)))
299 func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
300 return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
303 type Linger struct {
304 Onoff int32
305 Linger int32
308 func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
309 return setsockopt(fd, level, opt, unsafe.Pointer(l), Socklen_t(unsafe.Sizeof(*l)))
312 func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
313 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
316 func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
317 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
320 func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
321 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), Socklen_t(unsafe.Sizeof(*mreq)))
324 func SetsockoptString(fd, level, opt int, s string) (err error) {
325 var p unsafe.Pointer
326 if len(s) > 0 {
327 p = unsafe.Pointer(&[]byte(s)[0])
329 return setsockopt(fd, level, opt, p, Socklen_t(len(s)))
332 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, err error)
333 //recvfrom(fd _C_int, buf *byte, len Size_t, flags _C_int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
335 func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
336 var rsa RawSockaddrAny
337 var len Socklen_t = SizeofSockaddrAny
338 if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
339 return
341 if rsa.Addr.Family != AF_UNSPEC {
342 from, err = anyToSockaddr(&rsa)
344 return
347 func recvfromInet4(fd int, p []byte, flags int, from *SockaddrInet4) (n int, err error) {
348 var rsa RawSockaddrAny
349 var socklen Socklen_t = SizeofSockaddrAny
350 if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
351 return
353 pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa))
354 port := (*[2]byte)(unsafe.Pointer(&pp.Port))
355 from.Port = int(port[0])<<8 + int(port[1])
356 from.Addr = pp.Addr
357 return
360 func recvfromInet6(fd int, p []byte, flags int, from *SockaddrInet6) (n int, err error) {
361 var rsa RawSockaddrAny
362 var socklen Socklen_t = SizeofSockaddrAny
363 if n, err = recvfrom(fd, p, flags, &rsa, &socklen); err != nil {
364 return
366 pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa))
367 port := (*[2]byte)(unsafe.Pointer(&pp.Port))
368 from.Port = int(port[0])<<8 + int(port[1])
369 from.ZoneId = pp.Scope_id
370 from.Addr = pp.Addr
371 return
374 func recvmsgInet4(fd int, p, oob []byte, flags int, from *SockaddrInet4) (n, oobn int, recvflags int, err error) {
375 var rsa RawSockaddrAny
376 n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
377 if err != nil {
378 return
380 pp := (*RawSockaddrInet4)(unsafe.Pointer(&rsa))
381 port := (*[2]byte)(unsafe.Pointer(&pp.Port))
382 from.Port = int(port[0])<<8 + int(port[1])
383 from.Addr = pp.Addr
384 return
387 func recvmsgInet6(fd int, p, oob []byte, flags int, from *SockaddrInet6) (n, oobn int, recvflags int, err error) {
388 var rsa RawSockaddrAny
389 n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
390 if err != nil {
391 return
393 pp := (*RawSockaddrInet6)(unsafe.Pointer(&rsa))
394 port := (*[2]byte)(unsafe.Pointer(&pp.Port))
395 from.Port = int(port[0])<<8 + int(port[1])
396 from.ZoneId = pp.Scope_id
397 from.Addr = pp.Addr
398 return
401 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
402 var rsa RawSockaddrAny
403 n, oobn, recvflags, err = recvmsgRaw(fd, p, oob, flags, &rsa)
404 // source address is only specified if the socket is unconnected
405 if rsa.Addr.Family != AF_UNSPEC {
406 from, err = anyToSockaddr(&rsa)
408 return
411 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
412 _, err = SendmsgN(fd, p, oob, to, flags)
413 return
416 func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
417 var ptr *RawSockaddrAny
418 var salen Socklen_t
419 if to != nil {
420 ptr, salen, err = to.sockaddr()
421 if err != nil {
422 return 0, err
425 return sendmsgN(fd, p, oob, ptr, salen, flags)
428 func sendmsgNInet4(fd int, p, oob []byte, to *SockaddrInet4, flags int) (n int, err error) {
429 ptr, salen, err := to.sockaddr()
430 if err != nil {
431 return 0, err
433 return sendmsgN(fd, p, oob, ptr, salen, flags)
436 func sendmsgNInet6(fd int, p, oob []byte, to *SockaddrInet6, flags int) (n int, err error) {
437 ptr, salen, err := to.sockaddr()
438 if err != nil {
439 return 0, err
441 return sendmsgN(fd, p, oob, ptr, salen, flags)
444 func sendtoInet4(fd int, p []byte, flags int, to *SockaddrInet4) (err error) {
445 ptr, n, err := to.sockaddr()
446 if err != nil {
447 return err
449 return sendto(fd, p, flags, ptr, n)
452 func sendtoInet6(fd int, p []byte, flags int, to *SockaddrInet6) (err error) {
453 ptr, n, err := to.sockaddr()
454 if err != nil {
455 return err
457 return sendto(fd, p, flags, ptr, n)
460 func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
461 ptr, n, err := to.sockaddr()
462 if err != nil {
463 return err
465 return sendto(fd, p, flags, ptr, n)
468 func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
469 var msg Msghdr
470 msg.Name = (*byte)(unsafe.Pointer(&rsa))
471 msg.Namelen = uint32(SizeofSockaddrAny)
472 var iov Iovec
473 if len(p) > 0 {
474 iov.Base = (*byte)(unsafe.Pointer(&p[0]))
475 iov.SetLen(len(p))
477 var dummy byte
478 if len(oob) > 0 {
479 var sockType int
480 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
481 if err != nil {
482 return
484 // receive at least one normal byte
485 if sockType != SOCK_DGRAM && len(p) == 0 {
486 iov.Base = &dummy
487 iov.SetLen(1)
489 msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
490 msg.SetControllen(len(oob))
492 msg.Iov = &iov
493 msg.Iovlen = 1
494 if n, err = recvmsg(fd, &msg, flags); err != nil {
495 return
497 oobn = int(msg.Controllen)
498 recvflags = int(msg.Flags)
499 return
502 func sendmsgN(fd int, p, oob []byte, to *RawSockaddrAny, salen Socklen_t, flags int) (n int, err error) {
503 var msg Msghdr
504 msg.Name = (*byte)(unsafe.Pointer(to))
505 msg.Namelen = uint32(salen)
506 var iov Iovec
507 if len(p) > 0 {
508 iov.Base = (*byte)(unsafe.Pointer(&p[0]))
509 iov.SetLen(len(p))
511 var dummy byte
512 if len(oob) > 0 {
513 var sockType int
514 sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE)
515 if err != nil {
516 return 0, err
518 // send at least one normal byte
519 if sockType != SOCK_DGRAM && len(p) == 0 {
520 iov.Base = &dummy
521 iov.SetLen(1)
523 msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
524 msg.SetControllen(len(oob))
526 msg.Iov = &iov
527 msg.Iovlen = 1
528 if n, err = sendmsg(fd, &msg, flags); err != nil {
529 return 0, err
531 if len(oob) > 0 && len(p) == 0 {
532 n = 0
534 return n, nil
537 //sys Listen(fd int, n int) (err error)
538 //listen(fd _C_int, n _C_int) _C_int
540 //sys Shutdown(fd int, how int) (err error)
541 //shutdown(fd _C_int, how _C_int) _C_int
543 func (iov *Iovec) SetLen(length int) {
544 iov.Len = Iovec_len_t(length)
547 func (msghdr *Msghdr) SetControllen(length int) {
548 msghdr.Controllen = Msghdr_controllen_t(length)
551 func (cmsg *Cmsghdr) SetLen(length int) {
552 cmsg.Len = Cmsghdr_len_t(length)