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