1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
28 */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/stropts.h>
34 #include <sys/socketvar.h>
35 #include <sys/ksocket.h>
36 #include <io/ksocket/ksocket_impl.h>
37 #include <fs/sockfs/sockcommon.h>
38 #include <fs/sockfs/sodirect.h>
39 #include <fs/sockfs/sockfilter_impl.h>
40
41 /*
42 * There can only be a single thread waiting for data (enforced by
43 * so_lock_read()), whereas for write there might be multiple threads
44 * waiting for transmit buffers. So therefore we use cv_broadcast for
45 * write and cv_signal for read.
46 */
47 #define SO_WAKEUP_READER(so) { \
48 if ((so)->so_rcv_wakeup) { \
49 (so)->so_rcv_wakeup = B_FALSE; \
50 cv_signal(&(so)->so_rcv_cv); \
51 } \
52 }
53
54 #define SO_WAKEUP_WRITER(so) { \
55 if ((so)->so_snd_wakeup) { \
56 (so)->so_snd_wakeup = B_FALSE; \
57 cv_broadcast(&(so)->so_snd_cv); \
58 } \
59 }
60
61 static int i_so_notify_last_rx(struct sonode *, int *, int *);
62 static int i_so_notify_last_tx(struct sonode *, int *, int *);
63
64 /*
65 * The notification functions must be called with so_lock held,
66 * and they will all *drop* so_lock before returning.
67 */
68
69 /*
70 * Wake up anyone waiting for the connection to be established.
71 */
72 void
so_notify_connected(struct sonode * so)73 so_notify_connected(struct sonode *so)
74 {
75 ASSERT(MUTEX_HELD(&so->so_lock));
76
77 if (IS_KERNEL_SOCKET(so)) {
78 KSOCKET_CALLBACK(so, connected, 0);
79 mutex_exit(&so->so_lock);
80 } else {
81 socket_sendsig(so, SOCKETSIG_WRITE);
82 mutex_exit(&so->so_lock);
83 pollwakeup(&so->so_poll_list, POLLOUT);
84 }
85 sof_sonode_notify_filters(so, SOF_EV_CONNECTED, 0);
86
87 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
88 }
89
90 /*
91 * The socket is disconnecting, so no more data can be sent. Wake up
92 * anyone that is waiting to send data.
93 */
94 void
so_notify_disconnecting(struct sonode * so)95 so_notify_disconnecting(struct sonode *so)
96 {
97 int pollev = 0;
98 int sigev = 0;
99
100 ASSERT(MUTEX_HELD(&so->so_lock));
101 (void) i_so_notify_last_tx(so, &pollev, &sigev);
102
103 if (IS_KERNEL_SOCKET(so)) {
104 KSOCKET_CALLBACK(so, cantsendmore, 0);
105 mutex_exit(&so->so_lock);
106 } else {
107 if (sigev != 0)
108 socket_sendsig(so, sigev);
109 mutex_exit(&so->so_lock);
110
111 if (pollev != 0)
112 pollwakeup(&so->so_poll_list, pollev);
113 }
114 sof_sonode_notify_filters(so, SOF_EV_CANTSENDMORE, 0);
115
116 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
117 }
118
119 /*
120 * The socket is disconnected, so not more data can be sent or received.
121 * Wake up anyone that is waiting to send or receive data.
122 */
123 void
so_notify_disconnected(struct sonode * so,boolean_t connfailed,int error)124 so_notify_disconnected(struct sonode *so, boolean_t connfailed, int error)
125 {
126 int pollev = 0;
127 int sigev = 0;
128
129 ASSERT(MUTEX_HELD(&so->so_lock));
130
131 (void) i_so_notify_last_tx(so, &pollev, &sigev);
132 (void) i_so_notify_last_rx(so, &pollev, &sigev);
133
134 if (IS_KERNEL_SOCKET(so)) {
135 if (connfailed) {
136 KSOCKET_CALLBACK(so, disconnected, error);
137 } else {
138 KSOCKET_CALLBACK(so, connectfailed, error);
139 }
140 mutex_exit(&so->so_lock);
141 } else {
142 if (sigev != 0)
143 socket_sendsig(so, sigev);
144 mutex_exit(&so->so_lock);
145
146 /*
147 * If we're here because the socket has become disconnected,
148 * we explicitly set POLLHUP. At the same time, we also clear
149 * POLLOUT, as POLLOUT and POLLHUP are defined to be mutually
150 * exclusive with respect to one another.
151 */
152 if (!connfailed)
153 pollev = (pollev | POLLHUP) & ~POLLOUT;
154
155 if (pollev != 0)
156 pollwakeup(&so->so_poll_list, pollev);
157 }
158 sof_sonode_notify_filters(so, (connfailed) ? SOF_EV_CONNECTFAILED :
159 SOF_EV_DISCONNECTED, error);
160
161 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
162 }
163
164 /*
165 * The socket is writeable. Wake up anyone waiting to send data.
166 */
167 void
so_notify_writable(struct sonode * so)168 so_notify_writable(struct sonode *so)
169 {
170 ASSERT(MUTEX_HELD(&so->so_lock));
171
172 SO_WAKEUP_WRITER(so);
173
174 if (IS_KERNEL_SOCKET(so)) {
175 KSOCKET_CALLBACK(so, cansend, 0);
176 mutex_exit(&so->so_lock);
177 } else {
178 socket_sendsig(so, SOCKETSIG_WRITE);
179 mutex_exit(&so->so_lock);
180 pollwakeup(&so->so_poll_list, POLLOUT);
181 }
182
183 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
184
185 /* filters can start injecting data */
186 if (so->so_filter_active > 0)
187 sof_sonode_notify_filters(so, SOF_EV_INJECT_DATA_OUT_OK, 0);
188 }
189
190 /*
191 * Data is available, so wake up anyone waiting for data.
192 */
193 void
so_notify_data(struct sonode * so,size_t qlen)194 so_notify_data(struct sonode *so, size_t qlen)
195 {
196 ASSERT(MUTEX_HELD(&so->so_lock));
197
198 SO_WAKEUP_READER(so);
199
200 if (IS_KERNEL_SOCKET(so)) {
201 KSOCKET_CALLBACK(so, newdata, qlen);
202 mutex_exit(&so->so_lock);
203 } else {
204 socket_sendsig(so, SOCKETSIG_READ);
205 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
206 so->so_pollev &= ~SO_POLLEV_IN;
207 mutex_exit(&so->so_lock);
208 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
209 } else {
210 mutex_exit(&so->so_lock);
211 }
212 }
213
214 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
215 }
216
217 /*
218 * Transient error. Wake up anyone waiting to send or receive data.
219 */
220 void
so_notify_error(struct sonode * so)221 so_notify_error(struct sonode *so)
222 {
223 ASSERT(MUTEX_HELD(&so->so_lock));
224
225 SO_WAKEUP_WRITER(so);
226 SO_WAKEUP_READER(so);
227
228 if (IS_KERNEL_SOCKET(so)) {
229 KSOCKET_CALLBACK(so, error, 0);
230 mutex_exit(&so->so_lock);
231 } else {
232 socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ);
233 so->so_pollev &= ~SO_POLLEV_IN;
234 mutex_exit(&so->so_lock);
235 pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM);
236 }
237
238 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
239 }
240
241 /*
242 * Out-of-band data is incoming, notify any interested parties.
243 */
244 void
so_notify_oobsig(struct sonode * so)245 so_notify_oobsig(struct sonode *so)
246 {
247 socket_sendsig(so, SOCKETSIG_URG);
248 mutex_exit(&so->so_lock);
249 pollwakeup(&so->so_poll_list, POLLRDBAND);
250 }
251
252 /*
253 * Received out-of-band data. If the OOB data is delivered inline, then
254 * in addition of regular OOB notification, anyone waiting for normal
255 * data is also notified.
256 */
257 void
so_notify_oobdata(struct sonode * so,boolean_t oob_inline)258 so_notify_oobdata(struct sonode *so, boolean_t oob_inline)
259 {
260 ASSERT(MUTEX_HELD(&so->so_lock));
261 if (so->so_direct != NULL)
262 SOD_UIOAFINI(so->so_direct);
263
264 SO_WAKEUP_READER(so);
265
266 if (IS_KERNEL_SOCKET(so)) {
267 KSOCKET_CALLBACK(so, oobdata, 0);
268 mutex_exit(&so->so_lock);
269 } else {
270 if (oob_inline) {
271 socket_sendsig(so, SOCKETSIG_READ);
272 so->so_pollev &= ~SO_POLLEV_IN;
273 mutex_exit(&so->so_lock);
274 pollwakeup(&so->so_poll_list,
275 POLLRDBAND|POLLIN|POLLRDNORM);
276 } else {
277 mutex_exit(&so->so_lock);
278 pollwakeup(&so->so_poll_list, POLLRDBAND);
279 }
280 }
281
282 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
283 }
284
285 /*
286 * End-of-file has been reach, so peer will send no new data. Wake up
287 * anyone that is waiting for data.
288 */
289 void
so_notify_eof(struct sonode * so)290 so_notify_eof(struct sonode *so)
291 {
292 int pollev = 0;
293 int sigev = 0;
294
295 ASSERT(MUTEX_HELD(&so->so_lock));
296
297 (void) i_so_notify_last_rx(so, &pollev, &sigev);
298
299 if (IS_KERNEL_SOCKET(so)) {
300 KSOCKET_CALLBACK(so, cantrecvmore, 0);
301 mutex_exit(&so->so_lock);
302 } else {
303 if (sigev != 0)
304 socket_sendsig(so, sigev);
305 mutex_exit(&so->so_lock);
306 if (pollev != 0)
307 pollwakeup(&so->so_poll_list, pollev);
308
309 }
310 sof_sonode_notify_filters(so, SOF_EV_CANTRECVMORE, 0);
311
312 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
313 }
314
315 /*
316 * Wake up anyone waiting for a new connection.
317 */
318 void
so_notify_newconn(struct sonode * so)319 so_notify_newconn(struct sonode *so)
320 {
321 ASSERT(MUTEX_HELD(&so->so_lock));
322
323 if (IS_KERNEL_SOCKET(so)) {
324 KSOCKET_CALLBACK(so, newconn, 0);
325 mutex_exit(&so->so_lock);
326 } else {
327 socket_sendsig(so, SOCKETSIG_READ);
328 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
329 so->so_pollev &= ~SO_POLLEV_IN;
330 mutex_exit(&so->so_lock);
331 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
332 } else {
333 mutex_exit(&so->so_lock);
334 }
335 }
336
337 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
338 }
339
340 /*
341 * User initated shutdown/close, wake anyone that is trying to do
342 * an operation that is no longer possible.
343 */
344 void
so_notify_shutdown(struct sonode * so)345 so_notify_shutdown(struct sonode *so)
346 {
347 int pollev = 0;
348 int sigev = 0;
349
350 ASSERT(MUTEX_HELD(&so->so_lock));
351 ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE));
352
353 if (so->so_state & SS_CANTSENDMORE)
354 (void) i_so_notify_last_tx(so, &pollev, &sigev);
355 if (so->so_state & SS_CANTRCVMORE)
356 (void) i_so_notify_last_rx(so, &pollev, &sigev);
357
358 if (sigev != 0)
359 socket_sendsig(so, sigev);
360 mutex_exit(&so->so_lock);
361 if (pollev != 0)
362 pollwakeup(&so->so_poll_list, pollev);
363
364 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
365 }
366
367 /*
368 * No more data will be coming in, and this will be the last notification
369 * made.
370 */
371 static int
i_so_notify_last_rx(struct sonode * so,int * pollev,int * sigev)372 i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev)
373 {
374 if (!(so->so_state & SS_SENTLASTREADSIG)) {
375 SOCKET_TIMER_CANCEL(so);
376 SO_WAKEUP_READER(so);
377 so->so_state |= SS_SENTLASTREADSIG;
378 so->so_pollev &= ~SO_POLLEV_IN;
379
380 *pollev |= POLLIN|POLLRDNORM|POLLRDHUP;
381 *sigev |= SOCKETSIG_READ;
382
383 return (1);
384 } else {
385 return (0);
386 }
387 }
388
389 /*
390 * The socket is un-writeable. Make one last notification.
391 */
392 static int
i_so_notify_last_tx(struct sonode * so,int * pollev,int * sigev)393 i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev)
394 {
395 if (!(so->so_state & SS_SENTLASTWRITESIG)) {
396 SO_WAKEUP_WRITER(so);
397 so->so_state |= SS_SENTLASTWRITESIG;
398
399 *pollev |= POLLOUT;
400 *sigev |= SOCKETSIG_WRITE;
401
402 return (1);
403 } else {
404 return (0);
405 }
406 }
407