Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/inet/sockmods/socksdp.c
+++ new/usr/src/uts/common/inet/sockmods/socksdp.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2017 Joyent, Inc.
24 25 */
25 26
26 27 #include <sys/types.h>
27 28 #include <sys/t_lock.h>
28 29 #include <sys/param.h>
29 30 #include <sys/systm.h>
30 31 #include <sys/buf.h>
31 32 #include <sys/vfs.h>
32 33 #include <sys/vnode.h>
33 34 #include <sys/debug.h>
34 35 #include <sys/errno.h>
35 36 #include <sys/stropts.h>
36 37 #include <sys/cmn_err.h>
37 38 #include <sys/sysmacros.h>
38 39 #include <sys/policy.h>
39 40
40 41 #include <sys/filio.h>
41 42 #include <sys/sockio.h>
42 43
43 44 #include <sys/project.h>
44 45 #include <sys/tihdr.h>
45 46 #include <sys/strsubr.h>
46 47
47 48 #include <sys/socket.h>
48 49 #include <sys/socketvar.h>
49 50 #include <sys/strsun.h>
50 51
51 52 #include <sys/tsol/label.h>
52 53
53 54 #include <inet/sdp_itf.h>
54 55 #include "socksdp.h"
55 56 #include <fs/sockfs/sockcommon.h>
56 57
57 58 /*
58 59 * SDP sockfs sonode operations
59 60 */
60 61 static int sosdp_init(struct sonode *, struct sonode *, struct cred *, int);
61 62 static int sosdp_accept(struct sonode *, int, struct cred *, struct sonode **);
62 63 static int sosdp_bind(struct sonode *, struct sockaddr *, socklen_t, int,
63 64 struct cred *);
64 65 static int sosdp_listen(struct sonode *, int, struct cred *);
65 66 static int sosdp_connect(struct sonode *, struct sockaddr *, socklen_t,
66 67 int, int, struct cred *);
67 68 static int sosdp_recvmsg(struct sonode *, struct nmsghdr *, struct uio *,
68 69 struct cred *);
69 70 static int sosdp_sendmsg(struct sonode *, struct nmsghdr *, struct uio *,
70 71 struct cred *);
71 72 static int sosdp_getpeername(struct sonode *, struct sockaddr *, socklen_t *,
72 73 boolean_t, struct cred *);
73 74 static int sosdp_getsockname(struct sonode *, struct sockaddr *, socklen_t *,
74 75 struct cred *);
75 76 static int sosdp_shutdown(struct sonode *, int, struct cred *);
76 77 static int sosdp_getsockopt(struct sonode *, int, int, void *, socklen_t *,
77 78 int, struct cred *);
78 79 static int sosdp_setsockopt(struct sonode *, int, int, const void *,
79 80 socklen_t, struct cred *);
80 81 static int sosdp_ioctl(struct sonode *, int, intptr_t, int, struct cred *,
81 82 int32_t *);
82 83 static int sosdp_poll(struct sonode *, short, int, short *,
83 84 struct pollhead **);
84 85 static int sosdp_close(struct sonode *, int, struct cred *);
85 86 void sosdp_fini(struct sonode *, struct cred *);
86 87
87 88
88 89 /*
89 90 * Socket upcalls
90 91 */
91 92 static void *sdp_sock_newconn(void *parenthandle, void *connind);
92 93 static void sdp_sock_connected(void *handle);
93 94 static void sdp_sock_disconnected(void *handle, int error);
94 95 static void sdp_sock_connfail(void *handle, int error);
95 96 static int sdp_sock_recv(void *handle, mblk_t *mp, int flags);
96 97 static void sdp_sock_xmitted(void *handle, int txqueued);
97 98 static void sdp_sock_urgdata(void *handle);
98 99 static void sdp_sock_ordrel(void *handle);
99 100
100 101 sonodeops_t sosdp_sonodeops = {
101 102 sosdp_init, /* sop_init */
102 103 sosdp_accept, /* sop_accept */
103 104 sosdp_bind, /* sop_bind */
104 105 sosdp_listen, /* sop_listen */
105 106 sosdp_connect, /* sop_connect */
106 107 sosdp_recvmsg, /* sop_recvmsg */
107 108 sosdp_sendmsg, /* sop_sendmsg */
108 109 so_sendmblk_notsupp, /* sop_sendmblk */
109 110 sosdp_getpeername, /* sop_getpeername */
110 111 sosdp_getsockname, /* sop_getsockname */
111 112 sosdp_shutdown, /* sop_shutdown */
112 113 sosdp_getsockopt, /* sop_getsockopt */
113 114 sosdp_setsockopt, /* sop_setsockopt */
114 115 sosdp_ioctl, /* sop_ioctl */
115 116 sosdp_poll, /* sop_poll */
116 117 sosdp_close, /* sop_close */
117 118 };
118 119
119 120 sdp_upcalls_t sosdp_sock_upcalls = {
120 121 sdp_sock_newconn,
121 122 sdp_sock_connected,
122 123 sdp_sock_disconnected,
123 124 sdp_sock_connfail,
124 125 sdp_sock_recv,
125 126 sdp_sock_xmitted,
126 127 sdp_sock_urgdata,
127 128 sdp_sock_ordrel,
128 129 };
129 130
130 131 /* ARGSUSED */
131 132 static int
132 133 sosdp_init(struct sonode *so, struct sonode *pso, struct cred *cr, int flags)
133 134 {
134 135 int error = 0;
135 136 sdp_sockbuf_limits_t sbl;
136 137 sdp_upcalls_t *upcalls;
137 138
138 139 if (pso != NULL) {
139 140 /* passive open, just inherit settings from parent */
140 141
141 142 mutex_enter(&so->so_lock);
142 143
143 144 so->so_state |= (SS_ISBOUND | SS_ISCONNECTED |
144 145 (pso->so_state & SS_ASYNC));
145 146 sosdp_so_inherit(pso, so);
146 147 so->so_proto_props = pso->so_proto_props;
147 148
148 149 mutex_exit(&so->so_lock);
149 150
150 151 return (0);
151 152 }
152 153
153 154 if ((error = secpolicy_basic_net_access(cr)) != 0)
154 155 return (error);
155 156
156 157 upcalls = &sosdp_sock_upcalls;
157 158
158 159 so->so_proto_handle = (sock_lower_handle_t)sdp_create(so, NULL,
159 160 so->so_family, SDP_CAN_BLOCK, upcalls, &sbl, cr, &error);
160 161 if (so->so_proto_handle == NULL)
161 162 return (ENOMEM);
162 163
163 164 so->so_rcvbuf = sbl.sbl_rxbuf;
164 165 so->so_rcvlowat = sbl.sbl_rxlowat;
165 166 so->so_sndbuf = sbl.sbl_txbuf;
166 167 so->so_sndlowat = sbl.sbl_txlowat;
167 168
168 169 return (error);
169 170 }
170 171
171 172 /*
172 173 * Accept incoming connection.
173 174 */
174 175 /* ARGSUSED */
175 176 static int
176 177 sosdp_accept(struct sonode *lso, int fflag, struct cred *cr,
177 178 struct sonode **nsop)
178 179 {
179 180 int error = 0;
180 181 struct sonode *nso;
181 182
182 183 dprint(3, ("sosdp_accept: so:%p so_proto_handle:%p", (void *)lso,
183 184 (void *)lso->so_proto_handle));
184 185
185 186 if (!(lso->so_state & SS_ACCEPTCONN)) {
186 187 /*
187 188 * Not a listen socket.
188 189 */
189 190 eprintsoline(lso, EINVAL);
190 191 return (EINVAL);
191 192 }
192 193 /*
193 194 * Returns right away if socket is nonblocking.
194 195 */
195 196 error = so_acceptq_dequeue(lso, (fflag & (FNONBLOCK|FNDELAY)), &nso);
196 197 if (error != 0) {
197 198 eprintsoline(lso, error);
198 199 dprint(4, ("sosdp_accept: failed %d:lso:%p so_proto_handle:%p",
199 200 error, (void *)lso, (void *)lso->so_proto_handle));
200 201 return (error);
201 202 }
202 203
203 204 dprint(2, ("sosdp_accept: new %p\n", (void *)nso));
204 205 *nsop = nso;
205 206
206 207 return (0);
207 208 }
208 209
209 210 /*
210 211 * Bind local endpoint.
211 212 */
212 213 /* ARGSUSED */
213 214 int
214 215 sosdp_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
215 216 int flags, struct cred *cr)
216 217 {
217 218 int error = 0;
218 219
219 220 if (!(flags & _SOBIND_LOCK_HELD)) {
220 221 mutex_enter(&so->so_lock);
221 222 so_lock_single(so); /* Set SOLOCKED */
222 223 } else {
223 224 ASSERT(MUTEX_HELD(&so->so_lock));
224 225 ASSERT(so->so_flag & SOLOCKED);
225 226 }
226 227
227 228 if ((so->so_state & SS_ISBOUND) || name == NULL || namelen == 0) {
228 229 /*
229 230 * Multiple binds not allowed for any SDP socket.
230 231 * Also binding with null address is not supported.
231 232 */
232 233 error = EINVAL;
233 234 eprintsoline(so, error);
234 235 goto done;
235 236 }
236 237
237 238 /*
238 239 * X/Open requires this check
239 240 */
240 241 if (so->so_state & SS_CANTSENDMORE) {
241 242 error = EINVAL;
242 243 goto done;
243 244 }
244 245
245 246 /*
246 247 * Protocol module does address family checks
247 248 */
248 249 mutex_exit(&so->so_lock);
249 250
250 251 error = sdp_bind((struct sdp_conn_struct_t *)so->so_proto_handle,
251 252 name, namelen);
252 253
253 254 mutex_enter(&so->so_lock);
254 255
255 256 if (error == 0) {
256 257 so->so_state |= SS_ISBOUND;
257 258 } else {
258 259 eprintsoline(so, error);
259 260 }
260 261 done:
261 262 if (!(flags & _SOBIND_LOCK_HELD)) {
262 263 so_unlock_single(so, SOLOCKED);
263 264 mutex_exit(&so->so_lock);
264 265 } else {
265 266 /* If the caller held the lock don't release it here */
266 267 ASSERT(MUTEX_HELD(&so->so_lock));
267 268 ASSERT(so->so_flag & SOLOCKED);
268 269 }
269 270 return (error);
270 271 }
271 272
272 273 /*
273 274 * Turn socket into a listen socket.
274 275 */
275 276 /* ARGSUSED */
276 277 static int
277 278 sosdp_listen(struct sonode *so, int backlog, struct cred *cr)
278 279 {
279 280 int error = 0;
280 281
281 282 mutex_enter(&so->so_lock);
282 283 so_lock_single(so);
283 284
284 285 /*
285 286 * If this socket is trying to do connect, or if it has
286 287 * been connected, disallow.
287 288 */
288 289 if (so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED |
289 290 SS_ISDISCONNECTING | SS_CANTRCVMORE | SS_CANTSENDMORE)) {
290 291 error = EINVAL;
291 292 eprintsoline(so, EINVAL);
292 293 goto done;
293 294 }
294 295 /*
295 296 * If listen() is only called to change backlog, we don't
296 297 * need to notify protocol module.
297 298 */
298 299 if (so->so_state & SS_ACCEPTCONN) {
299 300 so->so_backlog = backlog;
300 301 goto done;
301 302 }
302 303
303 304 mutex_exit(&so->so_lock);
304 305
305 306 error = sdp_listen((struct sdp_conn_struct_t *)so->so_proto_handle,
306 307 backlog);
307 308
308 309 mutex_enter(&so->so_lock);
309 310 if (error == 0) {
310 311 so->so_state |= (SS_ACCEPTCONN | SS_ISBOUND);
311 312 so->so_backlog = backlog;
312 313 } else {
313 314 eprintsoline(so, error);
314 315 }
315 316 done:
316 317 so_unlock_single(so, SOLOCKED);
317 318 mutex_exit(&so->so_lock);
318 319
319 320 return (error);
320 321 }
321 322
322 323 /*
323 324 * Active open.
324 325 */
325 326 /*ARGSUSED*/
326 327 static int
327 328 sosdp_connect(struct sonode *so, struct sockaddr *name,
328 329 socklen_t namelen, int fflag, int flags, struct cred *cr)
329 330 {
330 331 int error = 0;
331 332
332 333 mutex_enter(&so->so_lock);
333 334 so_lock_single(so);
334 335
335 336 /*
336 337 * Can't connect() after listen(), or if the socket is already
337 338 * connected.
338 339 */
339 340 if (so->so_state & (SS_ACCEPTCONN|SS_ISCONNECTED|SS_ISCONNECTING)) {
340 341 if (so->so_state & SS_ISCONNECTED) {
341 342 error = EISCONN;
342 343 } else if (so->so_state & SS_ISCONNECTING) {
343 344 error = EALREADY;
344 345 } else {
345 346 error = EOPNOTSUPP;
346 347 }
347 348 eprintsoline(so, error);
348 349 goto done;
349 350 }
350 351
351 352 /*
352 353 * check for failure of an earlier call
353 354 */
354 355 if (so->so_error != 0) {
355 356 error = sogeterr(so, B_TRUE);
356 357 eprintsoline(so, error);
357 358 goto done;
358 359 }
359 360
360 361 /*
361 362 * Connection is closing, or closed, don't allow reconnect.
362 363 * TCP allows this to proceed, but the socket remains unwriteable.
363 364 * BSD returns EINVAL.
364 365 */
365 366 if (so->so_state & (SS_ISDISCONNECTING|SS_CANTRCVMORE|
366 367 SS_CANTSENDMORE)) {
367 368 error = EINVAL;
368 369 eprintsoline(so, error);
369 370 goto done;
370 371 }
371 372 if (name == NULL || namelen == 0) {
372 373 eprintsoline(so, EINVAL);
373 374 goto done;
374 375 }
375 376 soisconnecting(so);
376 377 mutex_exit(&so->so_lock);
377 378
378 379 error = sdp_connect((struct sdp_conn_struct_t *)so->so_proto_handle,
379 380 name, namelen);
380 381
381 382 mutex_enter(&so->so_lock);
382 383 if (error == 0) {
383 384 /*
384 385 * Allow other threads to access the socket
385 386 */
386 387 error = sowaitconnected(so, fflag, 0);
387 388 dprint(4,
388 389 ("sosdp_connect: wait on so:%p "
389 390 "so_proto_handle:%p failed:%d",
390 391 (void *)so, (void *)so->so_proto_handle, error));
391 392 }
392 393
393 394 switch (error) {
394 395 case 0:
395 396 case EINPROGRESS:
396 397 case EALREADY:
397 398 case EINTR:
398 399 /* Non-fatal errors */
399 400 so->so_state |= SS_ISBOUND;
400 401 break;
401 402 default:
402 403 /* clear SS_ISCONNECTING in case it was set */
403 404 so->so_state &= ~SS_ISCONNECTING;
404 405 break;
405 406 }
406 407 done:
407 408 so_unlock_single(so, SOLOCKED);
408 409 mutex_exit(&so->so_lock);
409 410 return (error);
410 411 }
411 412
412 413 /*
413 414 * Receive data.
414 415 */
415 416 /* ARGSUSED */
416 417 int
417 418 sosdp_recvmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
418 419 struct cred *cr)
419 420 {
420 421 int flags, error = 0;
421 422 int size;
422 423
423 424 flags = msg->msg_flags;
424 425 msg->msg_flags = 0;
425 426
426 427
427 428 if (!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|
428 429 SS_CANTRCVMORE))) {
429 430 return (ENOTCONN);
430 431 }
431 432
432 433 /*
433 434 * flag possibilities:
434 435 *
435 436 * MSG_PEEK Don't consume data
436 437 * MSG_WAITALL Wait for full quantity of data (ignored if MSG_PEEK)
437 438 * MSG_DONTWAIT Non-blocking (same as FNDELAY | FNONBLOCK)
438 439 *
439 440 * MSG_WAITALL can return less than the full buffer if either
440 441 *
441 442 * 1. we would block and we are non-blocking
442 443 * 2. a full message cannot be delivered
443 444 *
444 445 */
445 446
446 447 mutex_enter(&so->so_lock);
447 448
448 449 /*
449 450 * Allow just one reader at a time.
450 451 */
451 452 error = so_lock_read_intr(so,
452 453 uiop->uio_fmode | ((flags & MSG_DONTWAIT) ? FNONBLOCK : 0));
453 454 if (error != 0) {
454 455 mutex_exit(&so->so_lock);
455 456 return (error);
456 457 }
457 458 size = uiop->uio_resid;
458 459 mutex_exit(&so->so_lock);
459 460
460 461 if (!(so->so_state & SS_CANTRCVMORE)) {
461 462 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK)) {
462 463 flags |= MSG_DONTWAIT;
463 464 }
464 465 error = sdp_recv(
465 466 (struct sdp_conn_struct_t *)so->so_proto_handle, msg,
466 467 size, flags, uiop);
467 468 } else {
468 469 msg->msg_controllen = 0;
469 470 msg->msg_namelen = 0;
470 471 }
471 472 done:
472 473 mutex_enter(&so->so_lock);
473 474 so_unlock_read(so);
474 475 mutex_exit(&so->so_lock);
475 476 return (error);
476 477 }
477 478
478 479 /*
479 480 * Send message.
480 481 */
481 482 /* ARGSUSED */
482 483 static int
483 484 sosdp_sendmsg(struct sonode *so, struct nmsghdr *msg, struct uio *uiop,
484 485 struct cred *cr)
485 486 {
486 487 int flags;
487 488 ssize_t count;
488 489 int error;
489 490
490 491 ASSERT(so->so_type == SOCK_STREAM);
491 492
492 493 dprint(4, ("sosdp_sendmsg: so:%p so_proto_handle:%p",
493 494 (void *)so, (void *)so->so_proto_handle));
494 495
495 496 flags = msg->msg_flags;
496 497
497 498 if (msg->msg_controllen != 0) {
498 499 return (EOPNOTSUPP);
499 500 }
500 501
501 502 mutex_enter(&so->so_lock);
502 503 if (so->so_state & SS_CANTSENDMORE) {
503 504 mutex_exit(&so->so_lock);
504 505 return (EPIPE);
505 506 }
506 507
507 508 if (so->so_error != 0) {
508 509 error = sogeterr(so, B_TRUE);
509 510 mutex_exit(&so->so_lock);
510 511 return (error);
511 512 }
512 513
513 514 if (uiop->uio_fmode & (FNDELAY|FNONBLOCK))
514 515 flags |= MSG_DONTWAIT;
515 516
516 517 count = uiop->uio_resid;
517 518
518 519 if (!(so->so_state & (SS_ISCONNECTING | SS_ISCONNECTED))) {
519 520 dprint(4, ("sosdp_sendmsg: invalid state: <%x>",
520 521 so->so_state));
521 522 mutex_exit(&so->so_lock);
522 523 return (ENOTCONN);
523 524 }
524 525
525 526 mutex_exit(&so->so_lock);
526 527 error = sdp_send((struct sdp_conn_struct_t *)so->so_proto_handle,
527 528 msg, count, flags, uiop);
528 529
529 530 return (error);
530 531 }
531 532
532 533 /*
533 534 * Get address of remote node.
534 535 */
535 536 /* ARGSUSED */
536 537 static int
537 538 sosdp_getpeername(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
538 539 boolean_t accept, struct cred *cr)
539 540 {
540 541
541 542 if (!accept && !(so->so_state & SS_ISCONNECTED)) {
542 543 return (ENOTCONN);
543 544 } else {
544 545 return (sdp_getpeername(
545 546 (struct sdp_conn_struct_t *)so->so_proto_handle,
546 547 addr, addrlen));
547 548 }
548 549 }
549 550
550 551 /*
551 552 * Get local address.
552 553 */
553 554 /* ARGSUSED */
554 555 static int
555 556 sosdp_getsockname(struct sonode *so, struct sockaddr *addr, socklen_t *addrlen,
556 557 struct cred *cr)
557 558 {
558 559 mutex_enter(&so->so_lock);
559 560
560 561 if (!(so->so_state & SS_ISBOUND)) {
561 562 /*
562 563 * Zero address, except for address family
563 564 */
564 565 if (so->so_family == AF_INET || so->so_family == AF_INET6) {
565 566 bzero(addr, *addrlen);
566 567 *addrlen = (so->so_family == AF_INET6) ?
567 568 sizeof (struct sockaddr_in6) :
568 569 sizeof (struct sockaddr_in);
569 570 addr->sa_family = so->so_family;
570 571 }
571 572 mutex_exit(&so->so_lock);
572 573 return (0);
573 574 } else {
574 575 mutex_exit(&so->so_lock);
575 576 return (sdp_getsockname(
576 577 (struct sdp_conn_struct_t *)so->so_proto_handle,
577 578 addr, addrlen));
578 579 }
579 580 }
580 581
581 582 /*
582 583 * Called from shutdown().
583 584 */
584 585 /* ARGSUSED */
585 586 static int
586 587 sosdp_shutdown(struct sonode *so, int how, struct cred *cr)
587 588 {
588 589 uint_t state_change;
589 590 int error = 0;
590 591
591 592 mutex_enter(&so->so_lock);
592 593 so_lock_single(so);
593 594 /*
594 595 * Record the current state and then perform any state changes.
595 596 * Then use the difference between the old and new states to
596 597 * determine which needs to be done.
597 598 */
598 599 state_change = so->so_state;
599 600 if (!(state_change & SS_ISCONNECTED)) {
600 601 error = ENOTCONN;
601 602 goto done;
602 603 }
603 604
604 605 switch (how) {
605 606 case SHUT_RD:
606 607 socantrcvmore(so);
607 608 break;
608 609 case SHUT_WR:
609 610 socantsendmore(so);
610 611 break;
611 612 case SHUT_RDWR:
612 613 socantsendmore(so);
613 614 socantrcvmore(so);
614 615 break;
615 616 default:
616 617 error = EINVAL;
617 618 goto done;
618 619 }
619 620
620 621 state_change = so->so_state & ~state_change;
621 622
622 623 if (state_change & SS_CANTSENDMORE) {
623 624 so->so_state |= SS_ISDISCONNECTING;
624 625 }
625 626 so_notify_shutdown(so);
626 627
627 628 if (state_change & SS_CANTSENDMORE) {
628 629 error = sdp_shutdown(
629 630 (struct sdp_conn_struct_t *)so->so_proto_handle, how);
630 631 }
631 632
632 633 mutex_enter(&so->so_lock);
633 634 done:
634 635 so_unlock_single(so, SOLOCKED);
635 636 mutex_exit(&so->so_lock);
636 637
637 638 /*
638 639 * HACK: sdp_disconnect() may return EWOULDBLOCK. But this error is
639 640 * not documented in standard socket API. Catch it here.
640 641 */
641 642 if (error == EWOULDBLOCK)
642 643 error = 0;
643 644 return (error);
644 645 }
645 646
646 647 /*
647 648 * Get socket options.
648 649 */
649 650 /*ARGSUSED*/
650 651 static int
651 652 sosdp_getsockopt(struct sonode *so, int level, int option_name,
652 653 void *optval, socklen_t *optlenp, int flags, struct cred *cr)
653 654 {
654 655 int error = 0;
655 656 void *option = NULL;
656 657 socklen_t maxlen = *optlenp, len, optlen;
657 658 uint32_t value;
658 659 uint8_t buffer[4];
659 660 void *optbuf = &buffer;
660 661
661 662
662 663 mutex_enter(&so->so_lock);
663 664
664 665 if (level == SOL_SOCKET) {
665 666 switch (option_name) {
666 667 case SO_TYPE:
667 668 case SO_ERROR:
668 669 case SO_DEBUG:
669 670 case SO_ACCEPTCONN:
670 671 case SO_REUSEADDR:
671 672 case SO_KEEPALIVE:
672 673 case SO_DONTROUTE:
673 674 case SO_BROADCAST:
674 675 case SO_USELOOPBACK:
675 676 case SO_OOBINLINE:
676 677 case SO_SNDBUF:
677 678 case SO_RCVBUF:
678 679 case SO_SNDLOWAT:
679 680 case SO_RCVLOWAT:
680 681 case SO_DGRAM_ERRIND:
681 682 if (maxlen < (t_uscalar_t)sizeof (int32_t)) {
682 683 error = EINVAL;
683 684 eprintsoline(so, error);
684 685 goto done;
685 686 }
686 687 break;
687 688 case SO_LINGER:
688 689 if (maxlen < (t_uscalar_t)sizeof (struct linger)) {
689 690 error = EINVAL;
690 691 eprintsoline(so, error);
691 692 goto done;
692 693 }
693 694 break;
694 695 }
695 696 len = (t_uscalar_t)sizeof (uint32_t); /* Default */
696 697 option = &value;
697 698
698 699 switch (option_name) {
699 700 case SO_TYPE:
700 701 value = so->so_type;
701 702 goto copyout;
702 703
703 704 case SO_ERROR:
704 705 value = sogeterr(so, B_TRUE);
705 706 goto copyout;
706 707
707 708 case SO_ACCEPTCONN:
708 709 value = (so->so_state & SS_ACCEPTCONN) ?
709 710 SO_ACCEPTCONN : 0;
710 711 goto copyout;
711 712
712 713 case SO_DEBUG:
713 714 case SO_REUSEADDR:
714 715 case SO_KEEPALIVE:
715 716 case SO_DONTROUTE:
716 717 case SO_BROADCAST:
717 718 case SO_USELOOPBACK:
718 719 case SO_OOBINLINE:
719 720 case SO_DGRAM_ERRIND:
720 721 value = (so->so_options & option_name);
721 722 goto copyout;
722 723
723 724 /*
724 725 * The following options are only returned by sockfs
725 726 * when sdp_get_opt() fails.
726 727 */
727 728
728 729 case SO_LINGER:
729 730 option = &so->so_linger;
730 731 len = (t_uscalar_t)sizeof (struct linger);
731 732 break;
732 733 case SO_SNDBUF:
733 734 value = so->so_sndbuf;
734 735 len = (t_uscalar_t)sizeof (int);
735 736 goto copyout;
736 737
737 738 case SO_RCVBUF:
738 739 value = so->so_rcvbuf;
739 740 len = (t_uscalar_t)sizeof (int);
740 741 goto copyout;
741 742
742 743 case SO_SNDLOWAT:
743 744 value = so->so_sndlowat;
744 745 len = (t_uscalar_t)sizeof (int);
745 746 goto copyout;
746 747
747 748 case SO_RCVLOWAT:
748 749 value = so->so_rcvlowat;
749 750 len = (t_uscalar_t)sizeof (int);
750 751 goto copyout;
751 752
752 753 default:
753 754 option = NULL;
754 755 break;
755 756 }
756 757 }
757 758 if (maxlen > sizeof (buffer)) {
758 759 optbuf = kmem_alloc(maxlen, KM_SLEEP);
759 760 }
760 761 optlen = maxlen;
761 762 mutex_exit(&so->so_lock);
762 763 error = sdp_get_opt((struct sdp_conn_struct_t *)so->so_proto_handle,
763 764 level, option_name, optbuf, &optlen);
764 765 mutex_enter(&so->so_lock);
765 766 ASSERT(optlen <= maxlen);
766 767 if (error != 0) {
767 768 if (option == NULL) {
768 769 /* We have no fallback value */
769 770 eprintsoline(so, error);
770 771 goto free;
771 772 }
772 773 error = 0;
773 774 goto copyout;
774 775 }
775 776
776 777 option = optbuf;
777 778 len = optlen;
778 779
779 780 copyout:
780 781 len = MIN(len, maxlen);
781 782 bcopy(option, optval, len);
782 783 *optlenp = len;
783 784
784 785 free:
785 786 if (optbuf != &buffer) {
786 787 kmem_free(optbuf, maxlen);
787 788 }
788 789 done:
789 790 mutex_exit(&so->so_lock);
790 791 return (error);
791 792 }
792 793
793 794 /*
794 795 * Set socket options
795 796 */
796 797 /* ARGSUSED */
797 798 static int
798 799 sosdp_setsockopt(struct sonode *so, int level, int option_name,
799 800 const void *optval, t_uscalar_t optlen, struct cred *cr)
800 801 {
801 802 void *conn = NULL;
802 803 int error = 0;
803 804
804 805 if (so->so_state & SS_CANTSENDMORE) {
805 806 return (EINVAL);
806 807 }
807 808
808 809 mutex_enter(&so->so_lock);
809 810 so_lock_single(so);
810 811
811 812 if (so->so_type == SOCK_STREAM) {
812 813 conn = (void *)so->so_proto_handle;
813 814 }
814 815
815 816 dprint(2, ("sosdp_setsockopt (%d) - conn %p %d %d \n",
816 817 so->so_type, conn, level, option_name));
817 818
818 819 if (conn != NULL) {
819 820 mutex_exit(&so->so_lock);
820 821 error = sdp_set_opt((struct sdp_conn_struct_t *)conn, level,
821 822 option_name, optval, optlen);
822 823 mutex_enter(&so->so_lock);
823 824 }
824 825
825 826 /*
826 827 * Check for SOL_SOCKET options and record their values.
827 828 * If we know about a SOL_SOCKET parameter and the transport
828 829 * failed it with TBADOPT or TOUTSTATE (i.e. ENOPROTOOPT or
829 830 * EPROTO) we let the setsockopt succeed.
830 831 */
831 832 if (level == SOL_SOCKET) {
832 833 boolean_t handled = B_FALSE;
833 834
834 835 /* Check parameters */
835 836 switch (option_name) {
836 837 case SO_DEBUG:
837 838 case SO_REUSEADDR:
838 839 case SO_KEEPALIVE:
839 840 case SO_DONTROUTE:
840 841 case SO_BROADCAST:
841 842 case SO_USELOOPBACK:
842 843 case SO_OOBINLINE:
843 844 case SO_SNDBUF:
844 845 case SO_RCVBUF:
845 846 case SO_SNDLOWAT:
846 847 case SO_RCVLOWAT:
847 848 case SO_DGRAM_ERRIND:
848 849 if (optlen != (t_uscalar_t)sizeof (int32_t)) {
849 850 error = EINVAL;
850 851 eprintsoline(so, error);
851 852 goto done;
852 853 }
853 854 ASSERT(optval);
854 855 handled = B_TRUE;
855 856 break;
856 857 case SO_LINGER:
857 858 if (optlen != (t_uscalar_t)sizeof (struct linger)) {
858 859 error = EINVAL;
859 860 eprintsoline(so, error);
860 861 goto done;
861 862 }
862 863 ASSERT(optval);
863 864 handled = B_TRUE;
864 865 break;
865 866 }
866 867
867 868 #define intvalue (*(int32_t *)optval)
868 869
869 870 switch (option_name) {
870 871 case SO_TYPE:
871 872 case SO_ERROR:
872 873 case SO_ACCEPTCONN:
873 874 /* Can't be set */
874 875 error = ENOPROTOOPT;
875 876 goto done;
876 877 case SO_LINGER: {
877 878 struct linger *l = (struct linger *)optval;
878 879
879 880 so->so_linger.l_linger = l->l_linger;
880 881 if (l->l_onoff) {
881 882 so->so_linger.l_onoff = SO_LINGER;
882 883 so->so_options |= SO_LINGER;
883 884 } else {
884 885 so->so_linger.l_onoff = 0;
885 886 so->so_options &= ~SO_LINGER;
886 887 }
887 888 break;
888 889 }
889 890
890 891 case SO_DEBUG:
891 892 case SO_REUSEADDR:
892 893 case SO_KEEPALIVE:
893 894 case SO_DONTROUTE:
894 895 case SO_BROADCAST:
895 896 case SO_USELOOPBACK:
896 897 case SO_OOBINLINE:
897 898 case SO_DGRAM_ERRIND:
898 899 if (intvalue != 0) {
899 900 dprintso(so, 1,
900 901 ("sosdp_setsockopt: setting 0x%x\n",
901 902 option_name));
902 903 so->so_options |= option_name;
903 904 } else {
904 905 dprintso(so, 1,
905 906 ("sosdp_setsockopt: clearing 0x%x\n",
906 907 option_name));
907 908 so->so_options &= ~option_name;
908 909 }
909 910 break;
910 911
911 912 case SO_SNDBUF:
912 913 so->so_sndbuf = intvalue;
913 914 if (so->so_sndlowat > so->so_sndbuf) {
914 915 so->so_sndlowat = so->so_sndbuf;
915 916 }
916 917 break;
917 918 case SO_RCVBUF:
918 919 so->so_rcvbuf = intvalue;
919 920 if (so->so_rcvlowat > so->so_rcvbuf) {
920 921 so->so_rcvlowat = so->so_rcvbuf;
921 922 }
922 923 break;
923 924 case SO_SNDLOWAT:
924 925 if (so->so_sndlowat > so->so_sndbuf) {
925 926 so->so_sndlowat = so->so_sndbuf;
926 927 }
927 928 break;
928 929 case SO_RCVLOWAT:
929 930 if (so->so_rcvlowat > so->so_rcvbuf) {
930 931 so->so_rcvlowat = so->so_rcvbuf;
931 932 }
932 933 break;
933 934 }
934 935 #undef intvalue
935 936
936 937 if (error != 0) {
937 938 if ((error == ENOPROTOOPT || error == EPROTO ||
938 939 error == EINVAL) && handled) {
939 940 dprintso(so, 1,
940 941 ("sosdp_setsockopt: ignoring error %d "
941 942 "for 0x%x\n", error, option_name));
942 943 error = 0;
943 944 }
944 945 }
945 946 }
946 947
947 948 done:
948 949 so_unlock_single(so, SOLOCKED);
949 950 mutex_exit(&so->so_lock);
950 951
951 952 return (error);
952 953 }
953 954
954 955 /* ARGSUSED */
955 956 static int
956 957 sosdp_ioctl(struct sonode *so, int cmd, intptr_t arg, int mode,
957 958 struct cred *cr, int32_t *rvalp)
958 959 {
959 960 int32_t value;
960 961 int error, intval;
961 962 pid_t pid;
962 963
963 964 /* handle socket specific ioctls */
964 965 switch (cmd) {
965 966 case FIONBIO:
966 967 if (so_copyin((void *)arg, &value, sizeof (int32_t),
967 968 (mode & (int)FKIOCTL))) {
968 969 return (EFAULT);
969 970 }
970 971 mutex_enter(&so->so_lock);
971 972 if (value != 0) {
972 973 so->so_state |= SS_NDELAY;
973 974 } else {
974 975 so->so_state &= ~SS_NDELAY;
975 976 }
976 977 mutex_exit(&so->so_lock);
977 978 return (0);
978 979
979 980 case FIOASYNC:
980 981 if (so_copyin((void *)arg, &value, sizeof (int32_t),
981 982 (mode & (int)FKIOCTL))) {
982 983 return (EFAULT);
983 984 }
984 985 mutex_enter(&so->so_lock);
985 986
986 987 if (value) {
987 988 /* Turn on SIGIO */
988 989 so->so_state |= SS_ASYNC;
989 990 } else {
990 991 /* Turn off SIGIO */
991 992 so->so_state &= ~SS_ASYNC;
992 993 }
993 994 mutex_exit(&so->so_lock);
994 995 return (0);
995 996
996 997 case SIOCSPGRP:
997 998 case FIOSETOWN:
998 999 if (so_copyin((void *)arg, &pid, sizeof (pid_t),
999 1000 (mode & (int)FKIOCTL))) {
1000 1001 return (EFAULT);
1001 1002 }
1002 1003 mutex_enter(&so->so_lock);
1003 1004
1004 1005 error = (pid != so->so_pgrp) ? socket_chgpgrp(so, pid) : 0;
1005 1006 mutex_exit(&so->so_lock);
1006 1007 return (error);
1007 1008
1008 1009 case SIOCGPGRP:
1009 1010 case FIOGETOWN:
1010 1011 if (so_copyout(&so->so_pgrp, (void *)arg,
1011 1012 sizeof (pid_t), (mode & (int)FKIOCTL)))
1012 1013 return (EFAULT);
1013 1014 return (0);
1014 1015
1015 1016 case SIOCATMARK:
1016 1017 intval = 0;
1017 1018 error = sdp_ioctl(
1018 1019 (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
1019 1020 &intval, cr);
1020 1021 if (so_copyout(&intval, (void *)arg, sizeof (int),
1021 1022 (mode & (int)FKIOCTL)))
1022 1023 return (EFAULT);
1023 1024 return (0);
1024 1025
1025 1026
1026 1027 case SIOCSENABLESDP: {
1027 1028 int32_t enable;
1028 1029
1029 1030 /*
1030 1031 * System wide enable SDP
1031 1032 */
1032 1033
1033 1034 if (so_copyin((void *)arg, &enable, sizeof (int32_t),
1034 1035 mode & (int)FKIOCTL))
1035 1036 return (EFAULT);
1036 1037
1037 1038 error = sdp_ioctl(
1038 1039 (struct sdp_conn_struct_t *)so->so_proto_handle, cmd,
1039 1040 &enable, cr);
1040 1041 if (so_copyout(&enable, (void *)arg,
1041 1042 sizeof (int32_t), (mode & (int)FKIOCTL)))
1042 1043 return (EFAULT);
1043 1044 return (0);
1044 1045 }
1045 1046 /* from strioctl */
1046 1047 case FIONREAD:
1047 1048 /*
1048 1049 * Return number of bytes of data in all data messages
1049 1050 * in queue in "arg".
1050 1051 * For stream socket, amount of available data.
1051 1052 */
1052 1053 if (so->so_state & SS_ACCEPTCONN) {
1053 1054 intval = 0;
1054 1055 } else {
1055 1056 mutex_enter(&so->so_lock);
1056 1057 intval = sdp_polldata(
1057 1058 (struct sdp_conn_struct_t *)so->so_proto_handle,
1058 1059 SDP_READ);
1059 1060 mutex_exit(&so->so_lock);
1060 1061 }
1061 1062 if (so_copyout(&intval, (void *)arg, sizeof (intval),
1062 1063 (mode & (int)FKIOCTL)))
1063 1064 return (EFAULT);
1064 1065 return (0);
1065 1066 default:
1066 1067 return (EINVAL);
1067 1068 }
1068 1069 }
1069 1070
1070 1071 /*
1071 1072 * Check socktpi_poll() on why so_lock is not held in this function.
1072 1073 */
1073 1074 static int
1074 1075 sosdp_poll(struct sonode *so, short events, int anyyet, short *reventsp,
1075 1076 struct pollhead **phpp)
1076 1077 {
1077 1078 short origevents = events;
1078 1079 int so_state;
1079 1080
1080 1081 so_state = so->so_state;
1081 1082
1082 1083 ASSERT(so->so_version != SOV_STREAM);
1083 1084
1084 1085 if (!(so_state & SS_ISCONNECTED) && (so->so_type == SOCK_STREAM)) {
|
↓ open down ↓ |
1051 lines elided |
↑ open up ↑ |
1085 1086 /*
1086 1087 * Not connected yet - turn off write side events
1087 1088 */
1088 1089 events &= ~(POLLOUT|POLLWRBAND);
1089 1090 }
1090 1091
1091 1092 /*
1092 1093 * Check for errors
1093 1094 */
1094 1095 if (so->so_error != 0 &&
1095 - ((POLLIN|POLLRDNORM|POLLOUT) & origevents) != 0) {
1096 + ((POLLIN|POLLRDNORM|POLLOUT) & origevents) != 0) {
1096 1097 *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & origevents;
1097 - return (0);
1098 + goto done;
1098 1099 }
1099 1100
1100 1101 *reventsp = 0;
1102 + if (so->so_type != SOCK_STREAM) {
1103 + goto done;
1104 + }
1101 1105
1102 1106 /*
1103 - * Don't mark socket as writable until TX queued data is
1104 - * below watermark.
1107 + * Don't mark socket writable until TX queued data is below watermark.
1105 1108 */
1106 - if (so->so_type == SOCK_STREAM) {
1107 - if (sdp_polldata(
1108 - (struct sdp_conn_struct_t *)so->so_proto_handle,
1109 - SDP_XMIT)) {
1110 - *reventsp |= POLLOUT & events;
1111 - }
1112 - } else {
1113 - *reventsp = 0;
1114 - goto done;
1109 + if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1110 + SDP_XMIT)) {
1111 + *reventsp |= POLLOUT & events;
1115 1112 }
1116 1113
1117 1114 if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
1118 1115 SDP_READ)) {
1119 1116 *reventsp |= (POLLIN|POLLRDNORM) & events;
1120 1117 }
1121 1118
1122 1119 if ((so_state & SS_CANTRCVMORE) || (so->so_acceptq_len > 0)) {
1123 1120 *reventsp |= (POLLIN|POLLRDNORM) & events;
1124 1121 }
1125 1122
1126 1123 done:
1127 - if (!*reventsp && !anyyet) {
1124 + if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
1128 1125 *phpp = &so->so_poll_list;
1129 1126 }
1130 1127
1131 1128 return (0);
1132 1129 }
1133 1130
1134 1131 /* ARGSUSED */
1135 1132 static int
1136 1133 sosdp_close(struct sonode *so, int flag, struct cred *cr)
1137 1134 {
1138 1135 int error = 0;
1139 1136
1140 1137 mutex_enter(&so->so_lock);
1141 1138 so_lock_single(so);
1142 1139 /*
1143 1140 * Need to set flags as there might be ops in progress on
1144 1141 * this socket.
1145 1142 *
1146 1143 * If socket already disconnected/disconnecting,
1147 1144 * don't send signal (again).
1148 1145 */
1149 1146 soisdisconnected(so, 0);
1150 1147 mutex_exit(&so->so_lock);
1151 1148
1152 1149 /*
1153 1150 * Initiate connection shutdown.
1154 1151 */
1155 1152 error = sdp_disconnect((struct sdp_conn_struct_t *)so->so_proto_handle,
1156 1153 flag);
1157 1154
1158 1155 mutex_enter(&so->so_lock);
1159 1156 so_unlock_single(so, SOLOCKED);
1160 1157 so_notify_disconnected(so, B_FALSE, error);
1161 1158
1162 1159 return (error);
1163 1160 }
1164 1161
1165 1162 /* ARGSUSED */
1166 1163 void
1167 1164 sosdp_fini(struct sonode *so, struct cred *cr)
1168 1165 {
1169 1166 dprint(3, ("sosdp_fini: so:%p so_proto_handle:%p", (void *)so,
1170 1167 (void *)so->so_proto_handle));
1171 1168
1172 1169 ASSERT(so->so_ops == &sosdp_sonodeops);
1173 1170
1174 1171 if (so->so_proto_handle != NULL)
1175 1172 sdp_close((struct sdp_conn_struct_t *)so->so_proto_handle);
1176 1173 so->so_proto_handle = NULL;
1177 1174
1178 1175 mutex_enter(&so->so_lock);
1179 1176
1180 1177 so_acceptq_flush(so, B_TRUE);
1181 1178
1182 1179 mutex_exit(&so->so_lock);
1183 1180
1184 1181 sonode_fini(so);
1185 1182 }
1186 1183
1187 1184 /*
1188 1185 * Upcalls from SDP
1189 1186 */
1190 1187
1191 1188 /*
1192 1189 * Incoming connection on listen socket.
1193 1190 */
1194 1191 static void *
1195 1192 sdp_sock_newconn(void *parenthandle, void *connind)
1196 1193 {
1197 1194 struct sonode *lso = parenthandle;
1198 1195 struct sonode *nso;
1199 1196 int error;
1200 1197
1201 1198 ASSERT(lso->so_state & SS_ACCEPTCONN);
1202 1199 ASSERT(lso->so_proto_handle != NULL); /* closed conn */
1203 1200 ASSERT(lso->so_type == SOCK_STREAM);
1204 1201
1205 1202 dprint(3, ("sosdp_newconn A: so:%p so_proto_handle:%p", (void *)lso,
1206 1203 (void *)lso->so_proto_handle));
1207 1204
1208 1205 /*
1209 1206 * Check current # of queued conns against backlog
1210 1207 */
1211 1208 if (lso->so_rcv_queued >= lso->so_backlog) {
1212 1209 return (NULL);
1213 1210 }
1214 1211
1215 1212 nso = socket_newconn(lso, connind, NULL, SOCKET_NOSLEEP, &error);
1216 1213 if (nso == NULL) {
1217 1214 eprintsoline(lso, error);
1218 1215 return (NULL);
1219 1216 }
1220 1217
1221 1218 dprint(2, ("sdp_stream_newconn: new %p\n", (void *)nso));
1222 1219
1223 1220 (void) so_acceptq_enqueue(lso, nso);
1224 1221
1225 1222 mutex_enter(&lso->so_lock);
1226 1223 so_notify_newconn(lso);
1227 1224 return (nso);
1228 1225 }
1229 1226
1230 1227 /*
1231 1228 * For outgoing connections, the connection has been established.
1232 1229 */
1233 1230 static void
1234 1231 sdp_sock_connected(void *handle)
1235 1232 {
1236 1233 struct sonode *so = handle;
1237 1234
1238 1235 ASSERT(so->so_type == SOCK_STREAM);
1239 1236 dprint(3, ("sosdp_connected C: so:%p so_proto_handle:%p", (void *)so,
1240 1237 (void *)so->so_proto_handle));
1241 1238
1242 1239 mutex_enter(&so->so_lock);
1243 1240 ASSERT(so->so_proto_handle); /* closed conn */
1244 1241
1245 1242 ASSERT(!(so->so_state & SS_ACCEPTCONN));
1246 1243 soisconnected(so);
1247 1244
1248 1245 so_notify_connected(so);
1249 1246 }
1250 1247
1251 1248 /*
1252 1249 * Connection got disconnected. Either with an error, or through
1253 1250 * normal handshake.
1254 1251 */
1255 1252 static void
1256 1253 sdp_sock_disconnected(void *handle, int error)
1257 1254 {
1258 1255 struct sonode *so = handle;
1259 1256
1260 1257 ASSERT(so->so_type == SOCK_STREAM);
1261 1258 dprint(2, ("sosdp_disconnected C: so:%p so_proto_handle:%p error:%d",
1262 1259 (void *)so, (void *)so->so_proto_handle, error));
1263 1260
1264 1261 mutex_enter(&so->so_lock);
1265 1262 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1266 1263
1267 1264 soisdisconnected(so, error);
1268 1265 so_notify_disconnected(so, B_FALSE, error);
1269 1266 }
1270 1267
1271 1268 /*
1272 1269 * Incoming data.
1273 1270 */
1274 1271 /*ARGSUSED*/
1275 1272 static int
1276 1273 sdp_sock_recv(void *handle, mblk_t *mp, int flags)
1277 1274 {
1278 1275 struct sonode *so = handle;
1279 1276
1280 1277 ASSERT(so->so_type == SOCK_STREAM);
1281 1278
1282 1279 mutex_enter(&so->so_lock);
1283 1280 so_notify_data(so, 0);
1284 1281
1285 1282 return (so->so_rcvbuf);
1286 1283 }
1287 1284
1288 1285 /*
1289 1286 * TX queued data got acknowledged.
1290 1287 */
1291 1288 static void
1292 1289 sdp_sock_xmitted(void *handle, int writeable)
1293 1290 {
1294 1291 struct sonode *so = handle;
1295 1292
1296 1293 dprint(4, ("sosdp_sock_xmitted: so:%p so_proto_handle:%p txq:%d",
1297 1294 (void *)so, (void *)so->so_proto_handle, writeable));
1298 1295 mutex_enter(&so->so_lock);
1299 1296 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1300 1297
1301 1298
1302 1299 /*
1303 1300 * Only do pollwakeup if the amount of queued data is less than
1304 1301 * watermark.
1305 1302 */
1306 1303 if (!writeable) {
1307 1304 so_notify_writable(so);
1308 1305 } else {
1309 1306 mutex_exit(&so->so_lock);
1310 1307 }
1311 1308 }
1312 1309
1313 1310
1314 1311 /*
1315 1312 * SDP notifies socket for presence of urgent data.
1316 1313 */
1317 1314 static void
1318 1315 sdp_sock_urgdata(void *handle)
1319 1316 {
1320 1317 struct sonode *so = handle;
1321 1318
1322 1319 ASSERT(so->so_type == SOCK_STREAM);
1323 1320
1324 1321 mutex_enter(&so->so_lock);
1325 1322
1326 1323 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1327 1324 so_notify_oobsig(so);
1328 1325 }
1329 1326
1330 1327 /*
1331 1328 * SDP notifies socket about receiving of conn close request from peer side.
1332 1329 */
1333 1330 static void
1334 1331 sdp_sock_ordrel(void *handle)
1335 1332 {
1336 1333 struct sonode *so = handle;
1337 1334
1338 1335 ASSERT(so->so_type == SOCK_STREAM);
1339 1336
1340 1337 dprint(4, ("sdp_sock_ordrel : so:%p, so_proto_handle:%p",
1341 1338 (void *)so, (void *)so->so_proto_handle));
1342 1339 mutex_enter(&so->so_lock);
1343 1340 socantrcvmore(so);
1344 1341 so_notify_eof(so);
1345 1342 }
1346 1343
1347 1344 static void
1348 1345 sdp_sock_connfail(void *handle, int error)
1349 1346 {
1350 1347 struct sonode *so = handle;
1351 1348
1352 1349 dprint(3, ("sosdp_conn Failed: so:%p so_proto_handle:%p", (void *)so,
1353 1350 (void *)so->so_proto_handle));
1354 1351 mutex_enter(&so->so_lock);
1355 1352 ASSERT(so->so_proto_handle != NULL); /* closed conn */
1356 1353 so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
1357 1354 so->so_error = (ushort_t)error;
1358 1355 mutex_exit(&so->so_lock);
1359 1356 cv_broadcast(&so->so_state_cv);
1360 1357 }
|
↓ open down ↓ |
223 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX