Source file
src/net/unixsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "errors"
12 "os"
13 "syscall"
14 )
15
16 func unixSocket(ctx context.Context, net string, laddr, raddr sockaddr, mode string, ctrlFn func(string, string, syscall.RawConn) error) (*netFD, error) {
17 var sotype int
18 switch net {
19 case "unix":
20 sotype = syscall.SOCK_STREAM
21 case "unixgram":
22 sotype = syscall.SOCK_DGRAM
23 case "unixpacket":
24 sotype = syscall.SOCK_SEQPACKET
25 default:
26 return nil, UnknownNetworkError(net)
27 }
28
29 switch mode {
30 case "dial":
31 if laddr != nil && laddr.isWildcard() {
32 laddr = nil
33 }
34 if raddr != nil && raddr.isWildcard() {
35 raddr = nil
36 }
37 if raddr == nil && (sotype != syscall.SOCK_DGRAM || laddr == nil) {
38 return nil, errMissingAddress
39 }
40 case "listen":
41 default:
42 return nil, errors.New("unknown mode: " + mode)
43 }
44
45 fd, err := socket(ctx, net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, ctrlFn)
46 if err != nil {
47 return nil, err
48 }
49 return fd, nil
50 }
51
52 func sockaddrToUnix(sa syscall.Sockaddr) Addr {
53 if s, ok := sa.(*syscall.SockaddrUnix); ok {
54 return &UnixAddr{Name: s.Name, Net: "unix"}
55 }
56 return nil
57 }
58
59 func sockaddrToUnixgram(sa syscall.Sockaddr) Addr {
60 if s, ok := sa.(*syscall.SockaddrUnix); ok {
61 return &UnixAddr{Name: s.Name, Net: "unixgram"}
62 }
63 return nil
64 }
65
66 func sockaddrToUnixpacket(sa syscall.Sockaddr) Addr {
67 if s, ok := sa.(*syscall.SockaddrUnix); ok {
68 return &UnixAddr{Name: s.Name, Net: "unixpacket"}
69 }
70 return nil
71 }
72
73 func sotypeToNet(sotype int) string {
74 switch sotype {
75 case syscall.SOCK_STREAM:
76 return "unix"
77 case syscall.SOCK_DGRAM:
78 return "unixgram"
79 case syscall.SOCK_SEQPACKET:
80 return "unixpacket"
81 default:
82 panic("sotypeToNet unknown socket type")
83 }
84 }
85
86 func (a *UnixAddr) family() int {
87 return syscall.AF_UNIX
88 }
89
90 func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
91 if a == nil {
92 return nil, nil
93 }
94 return &syscall.SockaddrUnix{Name: a.Name}, nil
95 }
96
97 func (a *UnixAddr) toLocal(net string) sockaddr {
98 return a
99 }
100
101 func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
102 var addr *UnixAddr
103 n, sa, err := c.fd.readFrom(b)
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 n, addr, err
111 }
112
113 func (c *UnixConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
114 var sa syscall.Sockaddr
115 n, oobn, flags, sa, err = c.fd.readMsg(b, oob, readMsgFlags)
116 if readMsgFlags == 0 && err == nil && oobn > 0 {
117 setReadMsgCloseOnExec(oob[:oobn])
118 }
119
120 switch sa := sa.(type) {
121 case *syscall.SockaddrUnix:
122 if sa.Name != "" {
123 addr = &UnixAddr{Name: sa.Name, Net: sotypeToNet(c.fd.sotype)}
124 }
125 }
126 return
127 }
128
129 func (c *UnixConn) writeTo(b []byte, addr *UnixAddr) (int, error) {
130 if c.fd.isConnected {
131 return 0, ErrWriteToConnected
132 }
133 if addr == nil {
134 return 0, errMissingAddress
135 }
136 if addr.Net != sotypeToNet(c.fd.sotype) {
137 return 0, syscall.EAFNOSUPPORT
138 }
139 sa := &syscall.SockaddrUnix{Name: addr.Name}
140 return c.fd.writeTo(b, sa)
141 }
142
143 func (c *UnixConn) writeMsg(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
144 if c.fd.sotype == syscall.SOCK_DGRAM && c.fd.isConnected {
145 return 0, 0, ErrWriteToConnected
146 }
147 var sa syscall.Sockaddr
148 if addr != nil {
149 if addr.Net != sotypeToNet(c.fd.sotype) {
150 return 0, 0, syscall.EAFNOSUPPORT
151 }
152 sa = &syscall.SockaddrUnix{Name: addr.Name}
153 }
154 return c.fd.writeMsg(b, oob, sa)
155 }
156
157 func (sd *sysDialer) dialUnix(ctx context.Context, laddr, raddr *UnixAddr) (*UnixConn, error) {
158 fd, err := unixSocket(ctx, sd.network, laddr, raddr, "dial", sd.Dialer.Control)
159 if err != nil {
160 return nil, err
161 }
162 return newUnixConn(fd), nil
163 }
164
165 func (ln *UnixListener) accept() (*UnixConn, error) {
166 fd, err := ln.fd.accept()
167 if err != nil {
168 return nil, err
169 }
170 return newUnixConn(fd), nil
171 }
172
173 func (ln *UnixListener) close() error {
174
175
176
177
178
179
180
181
182
183
184
185 ln.unlinkOnce.Do(func() {
186 if ln.path[0] != '@' && ln.unlink {
187 syscall.Unlink(ln.path)
188 }
189 })
190 return ln.fd.Close()
191 }
192
193 func (ln *UnixListener) file() (*os.File, error) {
194 f, err := ln.fd.dup()
195 if err != nil {
196 return nil, err
197 }
198 return f, nil
199 }
200
201
202
203
204
205
206
207
208
209 func (l *UnixListener) SetUnlinkOnClose(unlink bool) {
210 l.unlink = unlink
211 }
212
213 func (sl *sysListener) listenUnix(ctx context.Context, laddr *UnixAddr) (*UnixListener, error) {
214 fd, err := unixSocket(ctx, sl.network, laddr, nil, "listen", sl.ListenConfig.Control)
215 if err != nil {
216 return nil, err
217 }
218 return &UnixListener{fd: fd, path: fd.laddr.String(), unlink: true}, nil
219 }
220
221 func (sl *sysListener) listenUnixgram(ctx context.Context, laddr *UnixAddr) (*UnixConn, error) {
222 fd, err := unixSocket(ctx, sl.network, laddr, nil, "listen", sl.ListenConfig.Control)
223 if err != nil {
224 return nil, err
225 }
226 return newUnixConn(fd), nil
227 }
228
View as plain text