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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2012 David Hoeppner. All rights reserved. 29 */ 30 31 /* 32 * This file contains all DCCP kernel socket related functions. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/strlog.h> 37 #include <sys/policy.h> 38 #include <sys/sockio.h> 39 #include <sys/strsubr.h> 40 #include <sys/strsun.h> 41 #define _SUN_TPI_VERSION 2 42 #include <sys/tihdr.h> 43 #include <sys/timod.h> 44 #include <sys/squeue_impl.h> 45 #include <sys/squeue.h> 46 #include <sys/socketvar.h> 47 48 #include <inet/common.h> 49 #include <inet/dccp_impl.h> 50 #include <inet/dccp_stack.h> 51 #include <inet/proto_set.h> 52 #include <inet/ip.h> 53 54 #include <sys/cmn_err.h> 55 56 static void dccp_activate(sock_lower_handle_t, sock_upper_handle_t, 57 sock_upcalls_t *, int, cred_t *); 58 static int dccp_accept(sock_lower_handle_t, sock_lower_handle_t, 59 sock_upper_handle_t, cred_t *); 60 static int dccp_bind(sock_lower_handle_t, struct sockaddr *, 61 socklen_t, cred_t *); 62 static int dccp_listen(sock_lower_handle_t, int, cred_t *); 63 static int dccp_connect(sock_lower_handle_t, const struct sockaddr *, 64 socklen_t, sock_connid_t *, cred_t *); 65 static int dccp_getpeername(sock_lower_handle_t, struct sockaddr *, 66 socklen_t *, cred_t *); 67 static int dccp_getsockname(sock_lower_handle_t, struct sockaddr *, 68 socklen_t *, cred_t *); 69 static int dccp_getsockopt(sock_lower_handle_t, int, int, void *, 70 socklen_t *, cred_t *); 71 static int dccp_setsockopt(sock_lower_handle_t, int, int, const void *, 72 socklen_t, cred_t *); 73 static int dccp_send(sock_lower_handle_t, mblk_t *, struct nmsghdr *, 74 cred_t *); 75 static int dccp_shutdown(sock_lower_handle_t, int, cred_t *); 76 static void dccp_clr_flowctrl(sock_lower_handle_t); 77 static int dccp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *, 78 cred_t *); 79 static int dccp_close(sock_lower_handle_t, int, cred_t *); 80 81 sock_downcalls_t sock_dccp_downcalls = { 82 dccp_activate, /* sd_activate */ 83 dccp_accept, /* sd_accept */ 84 dccp_bind, /* sd_bind */ 85 dccp_listen, /* sd_listen */ 86 dccp_connect, /* sd_connect */ 87 dccp_getpeername, /* sd_getpeername */ 88 dccp_getsockname, /* sd_getsockname */ 89 dccp_getsockopt, /* sd_getsockopt */ 90 dccp_setsockopt, /* sd_setsockopt */ 91 dccp_send, /* sd_send */ 92 NULL, /* sd_send_uio */ 93 NULL, /* sd_recv_uio */ 94 NULL, /* sd_poll */ 95 dccp_shutdown, /* sd_shutdown */ 96 dccp_clr_flowctrl, /* sd_setflowctrl */ 97 dccp_ioctl, /* sd_ioctl */ 98 dccp_close, /* sd_close */ 99 }; 100 101 /* ARGSUSED */ 102 static void 103 dccp_activate(sock_lower_handle_t proto_handle, sock_upper_handle_t sock_handle, 104 sock_upcalls_t *sock_upcalls, int flags, cred_t *cr) 105 { 106 conn_t *connp = (conn_t *)proto_handle; 107 struct sock_proto_props sopp; 108 extern struct module_info dccp_rinfo; 109 110 cmn_err(CE_NOTE, "dccp_socket.c: dccp_activate"); 111 112 ASSERT(connp->conn_upper_handle == NULL); 113 114 /* All Solaris components should pass a cred for this operation */ 115 ASSERT(cr != NULL); 116 117 sopp.sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT | 118 SOCKOPT_MAXPSZ | SOCKOPT_MAXBLK | SOCKOPT_RCVTIMER | 119 SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ; 120 121 sopp.sopp_rxhiwat = SOCKET_RECVHIWATER; 122 sopp.sopp_rxlowat = SOCKET_RECVLOWATER; 123 sopp.sopp_maxpsz = INFPSZ; 124 sopp.sopp_maxblk = INFPSZ; 125 sopp.sopp_rcvtimer = SOCKET_TIMER_INTERVAL; 126 sopp.sopp_rcvthresh = SOCKET_RECVHIWATER >> 3; 127 sopp.sopp_maxaddrlen = sizeof (sin6_t); 128 sopp.sopp_minpsz = (dccp_rinfo.mi_minpsz == 1) ? 0 : 129 dccp_rinfo.mi_minpsz; 130 131 connp->conn_upcalls = sock_upcalls; 132 connp->conn_upper_handle = sock_handle; 133 134 /* XXX conn_rcvbuf */ 135 (*connp->conn_upcalls->su_set_proto_props)(connp->conn_upper_handle, 136 &sopp); 137 } 138 139 /*ARGSUSED*/ 140 static int 141 dccp_accept(sock_lower_handle_t lproto_handle, 142 sock_lower_handle_t eproto_handle, sock_upper_handle_t sock_handle, 143 cred_t *cr) 144 { 145 conn_t *lconnp, *econnp; 146 dccp_t *listener, *eager; 147 148 cmn_err(CE_NOTE, "dccp_socket.c: dccp_accept"); 149 150 econnp = (conn_t *)eproto_handle; 151 eager = econnp->conn_dccp; 152 ASSERT(IPCL_IS_NONSTR(econnp)); 153 ASSERT(eager->dccp_listener != NULL); 154 listener = eager->dccp_listener; 155 lconnp = (conn_t *)listener->dccp_connp; 156 ASSERT(listener->dccp_state == DCCPS_LISTEN); 157 ASSERT(lconnp->conn_upper_handle != NULL); 158 159 ASSERT(econnp->conn_upper_handle == NULL || 160 econnp->conn_upper_handle == sock_handle); 161 ASSERT(econnp->conn_upcalls == NULL || 162 econnp->conn_upcalls == lconnp->conn_upcalls); 163 econnp->conn_upper_handle = sock_handle; 164 econnp->conn_upcalls = lconnp->conn_upcalls; 165 166 ASSERT(econnp->conn_netstack == 167 listener->dccp_connp->conn_netstack); 168 ASSERT(eager->dccp_dccps == listener->dccp_dccps); 169 170 ASSERT(econnp->conn_ref >= 2); 171 eager->dccp_listener = NULL; /* XXX */ 172 CONN_DEC_REF(listener->dccp_connp); 173 174 return ((eager->dccp_state < DCCPS_OPEN) ? ECONNABORTED : 0); 175 } 176 177 static int 178 dccp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa, 179 socklen_t len, cred_t *cr) 180 { 181 conn_t *connp = (conn_t *)proto_handle; 182 int error; 183 184 cmn_err(CE_NOTE, "dccp_socket.c: dccp_bind"); 185 186 ASSERT(connp->conn_upper_handle != NULL); 187 188 /* All Solaris components should pass a cred for this operation */ 189 ASSERT(cr != NULL); 190 191 error = squeue_synch_enter(connp, NULL); 192 if (error != 0) { 193 /* Failed to enter */ 194 return (ENOSR); 195 } 196 197 /* Binding to NULL address means unbind */ 198 if (sa == NULL) { 199 if (connp->conn_dccp->dccp_state < DCCPS_LISTEN) { 200 error = dccp_do_unbind(connp); 201 } else { 202 error = EINVAL; 203 } 204 } else { 205 error = dccp_do_bind(connp, sa, len, cr, B_TRUE); 206 } 207 208 squeue_synch_exit(connp); 209 210 if (error < 0) { 211 if (error == -TOUTSTATE) { 212 error = EINVAL; 213 } else { 214 error = proto_tlitosyserr(-error); 215 } 216 } 217 218 return (error); 219 } 220 221 /* ARGSUSED */ 222 static int 223 dccp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr) 224 { 225 conn_t *connp = (conn_t *)proto_handle; 226 dccp_t *dccp = connp->conn_dccp; 227 int error; 228 229 cmn_err(CE_NOTE, "dccp_socket.c: dccp_listen"); 230 231 ASSERT(connp->conn_upper_handle != NULL); 232 233 /* All Solaris components should pass a cred for this operation */ 234 ASSERT(cr != NULL); 235 236 error = squeue_synch_enter(connp, NULL); 237 if (error != 0) { 238 /* Failed to enter */ 239 return (ENOBUFS); 240 } 241 242 error = dccp_do_listen(connp, NULL, 0, backlog, cr, B_FALSE); 243 if (error == 0) { 244 /* XXX dccps->dccps_conn_req_max_q0 */ 245 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle, 246 SOCK_OPCTL_ENAB_ACCEPT, 247 (uintptr_t)(dccp->dccp_conn_req_max)); 248 } else if (error < 0) { 249 if (error == -TOUTSTATE) { 250 error = EINVAL; 251 } else { 252 error = proto_tlitosyserr(-error); 253 } 254 } 255 256 squeue_synch_exit(connp); 257 258 return (error); 259 } 260 261 /* 262 * Socket connect. 263 */ 264 static int 265 dccp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa, 266 socklen_t len, sock_connid_t *id, cred_t *cr) 267 { 268 conn_t *connp = (conn_t *)proto_handle; 269 int error; 270 271 cmn_err(CE_NOTE, "dccp_socket.c: dccp_connect"); 272 273 ASSERT(connp->conn_upper_handle != NULL); 274 275 /* All Solaris components should pass a cred for this operation */ 276 ASSERT(cr != NULL); 277 278 error = proto_verify_ip_addr(connp->conn_family, sa, len); 279 if (error != 0) { 280 return (error); 281 } 282 283 error = squeue_synch_enter(connp, NULL); 284 if (error != 0) { 285 /* Failed to enter */ 286 return (ENOSR); 287 } 288 289 /* 290 * DCCP supports quick connect, so no need to do an implicit bind. 291 */ 292 error = dccp_do_connect(connp, sa, len, cr, curproc->p_pid); 293 if (error == 0) { 294 *id = connp->conn_dccp->dccp_connid; 295 } else if (error < 0) { 296 if (error == -TOUTSTATE) { 297 switch (connp->conn_dccp->dccp_state) { 298 case DCCPS_REQUEST: 299 error = EALREADY; 300 break; 301 case DCCPS_PARTOPEN: 302 error = EISCONN; 303 break; 304 case DCCPS_LISTEN: 305 error = EOPNOTSUPP; 306 break; 307 default: 308 error = EINVAL; 309 break; 310 } 311 } else { 312 error = proto_tlitosyserr(-error); 313 } 314 } 315 316 /* XXX loopback */ 317 318 squeue_synch_exit(connp); 319 320 return ((error == 0) ? EINPROGRESS : error); 321 } 322 323 /* ARGSUSED3 */ 324 static int 325 dccp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr, 326 socklen_t *addrlenp, cred_t *cr) 327 { 328 conn_t *connp = (conn_t *)proto_handle; 329 dccp_t *dccp = connp->conn_dccp; 330 331 cmn_err(CE_NOTE, "dccp_socket.c: dccp_getpeername"); 332 333 /* All Solaris components should pass a cred for this operation */ 334 ASSERT(cr != NULL); 335 336 ASSERT(dccp != NULL); 337 if (dccp->dccp_state < DCCPS_OPEN) { 338 return (ENOTCONN); 339 } 340 341 return (conn_getpeername(connp, addr, addrlenp)); 342 } 343 344 /* ARGSUSED3 */ 345 static int 346 dccp_getsockname(sock_lower_handle_t proto_handle, struct sockaddr *addr, 347 socklen_t *addrlenp, cred_t *cr) 348 { 349 conn_t *connp = (conn_t *)proto_handle; 350 int error; 351 352 cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockname"); 353 354 /* All Solaris components should pass a cred for this operation */ 355 ASSERT(cr != NULL); 356 357 /* XXX UDP has locks here, TCP not */ 358 mutex_enter(&connp->conn_lock); 359 error = conn_getsockname(connp, addr, addrlenp); 360 mutex_exit(&connp->conn_lock); 361 362 return (error); 363 } 364 365 static int 366 dccp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name, 367 void *optvalp, socklen_t *optlen, cred_t *cr) 368 { 369 conn_t *connp = (conn_t *)proto_handle; 370 void *optvalp_buf; 371 t_uscalar_t max_optbuf_len; 372 int len; 373 int error; 374 375 cmn_err(CE_NOTE, "dccp_socket.c: dccp_getsockopt"); 376 377 ASSERT(connp->conn_upper_handle != NULL); 378 379 /* All Solaris components should pass a cred for this operation */ 380 ASSERT(cr != NULL); 381 382 error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len, 383 dccp_opt_obj.odb_opt_des_arr, 384 dccp_opt_obj.odb_opt_arr_cnt, 385 B_FALSE, B_TRUE, cr); 386 if (error != 0) { 387 if (error < 0) { 388 error = proto_tlitosyserr(-error); 389 } 390 return (error); 391 } 392 393 optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP); 394 if (optvalp_buf == NULL) { 395 return (ENOMEM); 396 } 397 398 error = squeue_synch_enter(connp, NULL); 399 if (error == ENOMEM) { 400 kmem_free(optvalp_buf, max_optbuf_len); 401 return (ENOMEM); 402 } 403 404 len = dccp_opt_get(connp, level, option_name, optvalp_buf); 405 squeue_synch_exit(connp); 406 407 if (len == -1) { 408 kmem_free(optvalp_buf, max_optbuf_len); 409 return (EINVAL); 410 } 411 412 /* 413 * Update optlen and copy option value. 414 */ 415 t_uscalar_t size = MIN(len, *optlen); 416 417 bcopy(optvalp_buf, optvalp, size); 418 bcopy(&size, optlen, sizeof (size)); 419 420 kmem_free(optvalp_buf, max_optbuf_len); 421 422 return (0); 423 } 424 425 static int 426 dccp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name, 427 const void *optvalp, socklen_t optlen, cred_t *cr) 428 { 429 conn_t *connp = (conn_t *)proto_handle; 430 int error; 431 432 cmn_err(CE_NOTE, "dccp_socket.c: dccp_setsockopt"); 433 434 ASSERT(connp->conn_upper_handle != NULL); 435 436 /* All Solaris components should pass a cred for this operation */ 437 ASSERT(cr != NULL); 438 439 error = squeue_synch_enter(connp, NULL); 440 if (error == ENOMEM) { 441 return (ENOMEM); 442 } 443 444 error = proto_opt_check(level, option_name, optlen, NULL, 445 dccp_opt_obj.odb_opt_des_arr, 446 dccp_opt_obj.odb_opt_arr_cnt, 447 B_TRUE, B_FALSE, cr); 448 449 if (error != 0) { 450 if (error < 0) { 451 error = proto_tlitosyserr(-error); 452 } 453 squeue_synch_exit(connp); 454 return (error); 455 } 456 457 error = dccp_opt_set(connp, SETFN_OPTCOM_NEGOTIATE, level, option_name, 458 optlen, (uchar_t *)optvalp, (uint_t *)&optlen, (uchar_t *)optvalp, 459 NULL, cr); 460 squeue_synch_exit(connp); 461 462 ASSERT(error >= 0); 463 464 return (error); 465 } 466 467 /* ARGSUSED */ 468 static int 469 dccp_send(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg, 470 cred_t *cr) 471 { 472 conn_t *connp = (conn_t *)proto_handle; 473 dccp_t *dccp; 474 uint32_t msize; 475 int32_t dccpstate; 476 477 cmn_err(CE_NOTE, "dccp_socket.c: dccp_send"); 478 479 /* All Solaris components should pass a cred for this operation */ 480 ASSERT(cr != NULL); 481 482 ASSERT(connp->conn_ref >= 2); 483 ASSERT(connp->conn_upper_handle != NULL); 484 485 if (msg->msg_controllen != 0) { 486 freemsg(mp); 487 return (EOPNOTSUPP); 488 } 489 490 switch (DB_TYPE(mp)) { 491 case M_DATA: 492 dccp = connp->conn_dccp; 493 ASSERT(dccp != NULL); 494 495 dccpstate = dccp->dccp_state; 496 if (dccpstate < DCCPS_OPEN) { 497 freemsg(mp); 498 499 /* 500 * We return ENOTCONN if the endpoint is trying to 501 * connect or has never been connected, and EPIPE if it 502 * has been disconnected. The connection id helps us 503 * distinguish between the last two cases. 504 */ 505 return ((dccpstate == DCCPS_REQUEST) ? ENOTCONN : 506 ((dccp->dccp_connid > 0) ? EPIPE : ENOTCONN)); 507 } else if (dccpstate > DCCPS_CLOSING) { 508 freemsg(mp); 509 return (EPIPE); 510 } 511 512 /* XXX */ 513 514 msize = msgdsize(mp); 515 516 CONN_INC_REF(connp); 517 518 if (msg->msg_flags & MSG_OOB) { 519 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output_urgent, 520 connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT); 521 } else { 522 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_output, 523 connp, NULL, dccp_squeue_flag, SQTAG_DCCP_OUTPUT); 524 } 525 526 return (0); 527 528 default: 529 ASSERT(0); 530 } 531 532 freemsg(mp); 533 534 return (0); 535 } 536 537 /* ARGSUSED */ 538 static int 539 dccp_shutdown(sock_lower_handle_t proto_handle, int how, cred_t *cr) 540 { 541 conn_t *connp = (conn_t *)proto_handle; 542 dccp_t *dccp = connp->conn_dccp; 543 544 cmn_err(CE_NOTE, "dccp_socket.c: dccp_shutdown"); 545 546 /* All Solaris components should pass a cred for this operation. */ 547 ASSERT(cr != NULL); 548 549 ASSERT(connp->conn_upper_handle != NULL); 550 551 /* 552 * X/Open requires that we check the connected state. 553 */ 554 if (dccp->dccp_state < DCCPS_REQUEST) 555 return (ENOTCONN); 556 557 /* Shutdown the send side */ 558 if (how != SHUT_RD) { 559 mblk_t *bp; 560 561 bp = allocb_wait(0, BPRI_HI, STR_NOSIG, NULL); 562 CONN_INC_REF(connp); 563 SQUEUE_ENTER_ONE(connp->conn_sqp, bp, dccp_shutdown_output, 564 connp, NULL, SQ_NODRAIN, SQTAG_DCCP_SHUTDOWN_OUTPUT); 565 566 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle, 567 SOCK_OPCTL_SHUT_SEND, 0); 568 } 569 570 /* Shutdown the recv side */ 571 if (how != SHUT_WR) { 572 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle, 573 SOCK_OPCTL_SHUT_RECV, 0); 574 } 575 576 return (0); 577 } 578 579 static void 580 dccp_clr_flowctrl(sock_lower_handle_t proto_handle) 581 { 582 conn_t *connp = (conn_t *)proto_handle; 583 dccp_t *dccp = connp->conn_dccp; 584 mblk_t *mp; 585 int error; 586 587 ASSERT(connp->conn_upper_handle != NULL); 588 589 cmn_err(CE_NOTE, "dccp_socket.c: dccp_clr_flowctrl"); 590 591 error = squeue_synch_enter(connp, mp); 592 ASSERT(error == 0); 593 594 squeue_synch_exit(connp); 595 } 596 597 /* ARGSUSED */ 598 static int 599 dccp_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg, 600 int mode, int32_t *rvalp, cred_t *cr) 601 { 602 conn_t *connp = (conn_t *)proto_handle; 603 int error; 604 605 cmn_err(CE_NOTE, "dccp_socket.c: dccp_ioctl"); 606 607 ASSERT(connp->conn_upper_handle != NULL); 608 609 /* All Solaris components should pass a cred for this operation. */ 610 ASSERT(cr != NULL); 611 612 /* 613 * If we don't have a helper stream then create one. 614 * ip_create_helper_stream takes care of locking the conn_t, 615 * so this check for NULL is just a performance optimization. 616 */ 617 if (connp->conn_helper_info == NULL) { 618 dccp_stack_t *dccps = connp->conn_dccp->dccp_dccps; 619 620 /* 621 * Create a helper stream for non-STREAMS socket. 622 */ 623 error = ip_create_helper_stream(connp, dccps->dccps_ldi_ident); 624 if (error != 0) { 625 ip0dbg(("dccp_ioctl: create of IP helper stream " 626 "failed %d\n", error)); 627 return (error); 628 } 629 } 630 631 switch (cmd) { 632 case ND_SET: 633 case ND_GET: 634 case _SIOCSOCKFALLBACK: 635 /* XXX case DCCP_IOC_ABORT_CONN: */ 636 case TI_GETPEERNAME: 637 case TI_GETMYNAME: 638 ip1dbg(("dccp_ioctl: cmd 0x%x on non streams socket", cmd)); 639 error = EINVAL; 640 break; 641 default: 642 /* 643 * If the conn is not closing, pass on to IP using 644 * helper stream. Bump the ioctlref to prevent dccp_close 645 * from closing the rq/wq out from underneath the ioctl 646 * if it ends up queued or aborted/interrupted. 647 */ 648 mutex_enter(&connp->conn_lock); 649 if (connp->conn_state_flags & (CONN_CLOSING)) { 650 mutex_exit(&connp->conn_lock); 651 error = EINVAL; 652 break; 653 } 654 CONN_INC_IOCTLREF_LOCKED(connp); 655 error = ldi_ioctl(connp->conn_helper_info->iphs_handle, 656 cmd, arg, mode, cr, rvalp); 657 CONN_DEC_IOCTLREF(connp); 658 break; 659 } 660 661 return (error); 662 } 663 664 /* ARGSUSED */ 665 static int 666 dccp_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr) 667 { 668 conn_t *connp = (conn_t *)proto_handle; 669 670 cmn_err(CE_NOTE, "dccp_socket.c: dccp_close\n"); 671 672 ASSERT(connp->conn_upper_handle != NULL); 673 674 /* All Solaris components should pass a cred for this operation */ 675 ASSERT(cr != NULL); 676 677 dccp_close_common(connp, flags); 678 679 ip_free_helper_stream(connp); 680 681 CONN_DEC_REF(connp); 682 683 /* 684 * EINPROGRESS tells sockfs to wait for a 'closed' upcall before 685 * freeing the socket. 686 */ 687 return (EINPROGRESS); 688 } 689 690 691 /* 692 * Socket create function. 693 */ 694 sock_lower_handle_t 695 dccp_create(int family, int type, int proto, sock_downcalls_t **sockdowncalls, 696 uint_t *smodep, int *errorp, int flags, cred_t *credp) 697 { 698 conn_t *connp; 699 boolean_t isv6; 700 701 /* XXX (type != SOCK_STREAM */ 702 if ((family != AF_INET && family != AF_INET6) || 703 (proto != 0 && proto != IPPROTO_DCCP)) { 704 *errorp = EPROTONOSUPPORT; 705 return (NULL); 706 } 707 708 cmn_err(CE_NOTE, "dccp_socket: dccp_create\n"); 709 710 isv6 = family == AF_INET6 ? B_TRUE: B_FALSE; 711 connp = dccp_create_common(credp, isv6, B_TRUE, errorp); 712 if (connp == NULL) { 713 return (NULL); 714 } 715 716 /* 717 * Increment ref for DCCP connection. 718 */ 719 mutex_enter(&connp->conn_lock); 720 CONN_INC_REF_LOCKED(connp); 721 ASSERT(connp->conn_ref == 2); 722 connp->conn_state_flags &= ~CONN_INCIPIENT; 723 connp->conn_flags |= IPCL_NONSTR; 724 mutex_exit(&connp->conn_lock); 725 726 ASSERT(errorp != NULL); 727 *errorp = 0; 728 *sockdowncalls = &sock_dccp_downcalls; 729 *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP | 730 SM_SENDFILESUPP; 731 732 return ((sock_lower_handle_t)connp); 733 } 734 735 int 736 dccp_fallback(sock_lower_handle_t proto_handle, queue_t *q, 737 boolean_t issocket, so_proto_quiesced_cb_t quiesced_cb, 738 sock_quiesce_arg_t *arg) 739 { 740 cmn_err(CE_NOTE, "dccp_socket: dccp_fallback\n"); 741 742 return (0); 743 } 744 745 /* 746 * Notifies a non-STREAMS based listener about a new connection. This 747 * function is executed on the *eager*'s squeue once the 3 way handshake 748 * has completed. Note that the behavior differs from STREAMS, where the 749 * T_CONN_IND is sent up by tcp_send_conn_ind() while on the *listener*'s 750 * squeue. 751 * 752 * Returns B_TRUE if the notification succeeded and an upper handle was 753 * obtained. `tcp' should be closed on failure. 754 */ 755 boolean_t 756 dccp_newconn_notify(dccp_t *dccp, ip_recv_attr_t *ira) 757 { 758 dccp_t *listener = dccp->dccp_listener; 759 dccp_t *tail; 760 conn_t *lconnp = listener->dccp_connp; 761 conn_t *econnp = dccp->dccp_connp; 762 ipaddr_t *addr_cache; 763 sock_upper_handle_t upper; 764 struct sock_proto_props sopp; 765 766 cmn_err(CE_NOTE, "dccp_socket.c: dccp_newconn_notify"); 767 768 /* 769 mutex_enter(&listener->dccp_eager_lock); 770 addr_cache = (ipaddr_t *)(listener->dccp_ip_addr_cache); 771 if (addr_cache != NULL) { 772 addr_cache[IP_ADDR_CACHE_HASH(dccp->dccp_connp->conn_faddr_v4)] = 773 dccp->dccp_connp->conn_faddr_v4; 774 } 775 mutex_exit(&listener->dccp_eager_lock); 776 */ 777 778 /* 779 * Notify the ULP about the new connection. 780 */ 781 if ((upper = (*lconnp->conn_upcalls->su_newconn) 782 (lconnp->conn_upper_handle, (sock_lower_handle_t)econnp, 783 &sock_dccp_downcalls, ira->ira_cred, ira->ira_cpid, 784 &econnp->conn_upcalls)) == NULL) { 785 return (B_FALSE); 786 } 787 econnp->conn_upper_handle = upper; 788 789 dccp->dccp_detached = B_FALSE; 790 dccp->dccp_hard_binding = B_FALSE; 791 dccp->dccp_tconnind_started = B_TRUE; 792 793 if (econnp->conn_keepalive) { 794 dccp->dccp_ka_last_intrvl = 0; 795 dccp->dccp_ka_tid = DCCP_TIMER(dccp, dccp_keepalive_timer, 796 dccp->dccp_ka_interval); 797 } 798 799 /* Update the necessary parameters */ 800 dccp_get_proto_props(dccp, &sopp); 801 802 (*econnp->conn_upcalls->su_set_proto_props) 803 (econnp->conn_upper_handle, &sopp); 804 805 return (B_TRUE); 806 }