unixsock_posix.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2009 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. //go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
  5. package net
  6. import (
  7. "context"
  8. "errors"
  9. "os"
  10. "syscall"
  11. )
  12. func unixSocket(ctx context.Context, net string, laddr, raddr sockaddr, mode string, ctrlFn func(string, string, syscall.RawConn) error) (*netFD, error) {
  13. var sotype int
  14. switch net {
  15. case "unix":
  16. sotype = syscall.SOCK_STREAM
  17. case "unixgram":
  18. sotype = syscall.SOCK_DGRAM
  19. case "unixpacket":
  20. sotype = syscall.SOCK_SEQPACKET
  21. default:
  22. return nil, UnknownNetworkError(net)
  23. }
  24. switch mode {
  25. case "dial":
  26. if laddr != nil && laddr.isWildcard() {
  27. laddr = nil
  28. }
  29. if raddr != nil && raddr.isWildcard() {
  30. raddr = nil
  31. }
  32. if raddr == nil && (sotype != syscall.SOCK_DGRAM || laddr == nil) {
  33. return nil, errMissingAddress
  34. }
  35. case "listen":
  36. default:
  37. return nil, errors.New("unknown mode: " + mode)
  38. }
  39. fd, err := socket(ctx, net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, ctrlFn)
  40. if err != nil {
  41. return nil, err
  42. }
  43. return fd, nil
  44. }
  45. func sockaddrToUnix(sa syscall.Sockaddr) Addr {
  46. if s, ok := sa.(*syscall.SockaddrUnix); ok {
  47. return &UnixAddr{Name: s.Name, Net: "unix"}
  48. }
  49. return nil
  50. }
  51. func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
  52. if s, ok := sa.(*syscall.SockaddrUnix); ok {
  53. return &UnixAddr{Name: s.Name, Net: "unixgram"}
  54. }
  55. return nil
  56. }
  57. func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
  58. if s, ok := sa.(*syscall.SockaddrUnix); ok {
  59. return &UnixAddr{Name: s.Name, Net: "unixpacket"}
  60. }
  61. return nil
  62. }
  63. func sotypeToNet(sotype int) string {
  64. switch sotype {
  65. case syscall.SOCK_STREAM:
  66. return "unix"
  67. case syscall.SOCK_DGRAM:
  68. return "unixgram"
  69. case syscall.SOCK_SEQPACKET:
  70. return "unixpacket"
  71. default:
  72. panic("sotypeToNet unknown socket type")
  73. }
  74. }
  75. func (a *UnixAddr) family() int {
  76. return syscall.AF_UNIX
  77. }
  78. func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
  79. if a == nil {
  80. return nil, nil
  81. }
  82. return &syscall.SockaddrUnix{Name: a.Name}, nil
  83. }
  84. func (a *UnixAddr) toLocal(net string) sockaddr {
  85. return a
  86. }
  87. func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
  88. var addr *UnixAddr
  89. n, sa, err := c.fd.readFrom(b)
  90. switch sa := sa.(type) {
  91. case *syscall.SockaddrUnix:
  92. if sa.Name != "" {
  93. addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
  94. }
  95. }
  96. return n, addr, err
  97. }
  98. func (c *UnixConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
  99. var sa syscall.Sockaddr
  100. n, oobn, flags, sa, err = c.fd.readMsg(b, oob, readMsgFlags)
  101. if readMsgFlags == 0 && err == nil && oobn > 0 {
  102. setReadMsgCloseOnExec(oob[:oobn])
  103. }
  104. switch sa := sa.(type) {
  105. case *syscall.SockaddrUnix:
  106. if sa.Name != "" {
  107. addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
  108. }
  109. }
  110. return
  111. }
  112. func (c *UnixConn) writeTo(b []byte, addr *UnixAddr) (int, error) {
  113. if c.fd.isConnected {
  114. return 0, ErrWriteToConnected
  115. }
  116. if addr == nil {
  117. return 0, errMissingAddress
  118. }
  119. if addr.Net != sotypeToNet(c.fd.sotype) {
  120. return 0, syscall.EAFNOSUPPORT
  121. }
  122. sa := &syscall.SockaddrUnix{Name: addr.Name}
  123. return c.fd.writeTo(b, sa)
  124. }
  125. func (c *UnixConn) writeMsg(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
  126. if c.fd.sotype == syscall.SOCK_DGRAM && c.fd.isConnected {
  127. return 0, 0, ErrWriteToConnected
  128. }
  129. var sa syscall.Sockaddr
  130. if addr != nil {
  131. if addr.Net != sotypeToNet(c.fd.sotype) {
  132. return 0, 0, syscall.EAFNOSUPPORT
  133. }
  134. sa = &syscall.SockaddrUnix{Name: addr.Name}
  135. }
  136. return c.fd.writeMsg(b, oob, sa)
  137. }
  138. func (sd *sysDialer) dialUnix(ctx context.Context, laddr, raddr *UnixAddr) (*UnixConn, error) {
  139. fd, err := unixSocket(ctx, sd.network, laddr, raddr, "dial", sd.Dialer.Control)
  140. if err != nil {
  141. return nil, err
  142. }
  143. return newUnixConn(fd), nil
  144. }
  145. func (ln *UnixListener) accept() (*UnixConn, error) {
  146. fd, err := ln.fd.accept()
  147. if err != nil {
  148. return nil, err
  149. }
  150. return newUnixConn(fd), nil
  151. }
  152. func (ln *UnixListener) close() error {
  153. // The operating system doesn't clean up
  154. // the file that announcing created, so
  155. // we have to clean it up ourselves.
  156. // There's a race here--we can't know for
  157. // sure whether someone else has come along
  158. // and replaced our socket name already--
  159. // but this sequence (remove then close)
  160. // is at least compatible with the auto-remove
  161. // sequence in ListenUnix. It's only non-Go
  162. // programs that can mess us up.
  163. // Even if there are racy calls to Close, we want to unlink only for the first one.
  164. ln.unlinkOnce.Do(func() {
  165. if ln.path[0] != '@' && ln.unlink {
  166. syscall.Unlink(ln.path)
  167. }
  168. })
  169. return ln.fd.Close()
  170. }
  171. func (ln *UnixListener) file() (*os.File, error) {
  172. f, err := ln.fd.dup()
  173. if err != nil {
  174. return nil, err
  175. }
  176. return f, nil
  177. }
  178. // SetUnlinkOnClose sets whether the underlying socket file should be removed
  179. // from the file system when the listener is closed.
  180. //
  181. // The default behavior is to unlink the socket file only when package net created it.
  182. // That is, when the listener and the underlying socket file were created by a call to
  183. // Listen or ListenUnix, then by default closing the listener will remove the socket file.
  184. // but if the listener was created by a call to FileListener to use an already existing
  185. // socket file, then by default closing the listener will not remove the socket file.
  186. func (l *UnixListener) SetUnlinkOnClose(unlink bool) {
  187. l.unlink = unlink
  188. }
  189. func (sl *sysListener) listenUnix(ctx context.Context, laddr *UnixAddr) (*UnixListener, error) {
  190. fd, err := unixSocket(ctx, sl.network, laddr, nil, "listen", sl.ListenConfig.Control)
  191. if err != nil {
  192. return nil, err
  193. }
  194. return &UnixListener{fd: fd, path: fd.laddr.String(), unlink: true}, nil
  195. }
  196. func (sl *sysListener) listenUnixgram(ctx context.Context, laddr *UnixAddr) (*UnixConn, error) {
  197. fd, err := unixSocket(ctx, sl.network, laddr, nil, "listen", sl.ListenConfig.Control)
  198. if err != nil {
  199. return nil, err
  200. }
  201. return newUnixConn(fd), nil
  202. }