ksocket.c revision 8348:4137e18bfaf0
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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#include <sys/file.h> 28#include <sys/stropts.h> 29#include <sys/socket.h> 30#include <sys/socketvar.h> 31#include <sys/sysmacros.h> 32#include <sys/filio.h> /* FIO* ioctls */ 33#include <sys/sockio.h> /* SIOC* ioctls */ 34#include <sys/cmn_err.h> 35#include <sys/ksocket.h> 36#include <io/ksocket/ksocket_impl.h> 37#include <fs/sockfs/sockcommon.h> 38 39#define SOCKETMOD_TCP "tcp" 40#define SOCKETMOD_UDP "udp" 41/* 42 * Kernel Sockets 43 * 44 * Mostly a wrapper around the private socket_* functions. 45 */ 46int 47ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags, 48 struct cred *cr) 49{ 50 static const int version = SOV_DEFAULT; 51 int error = 0; 52 struct sonode *so; 53 *ksp = NULL; 54 55 if (domain == AF_NCA || domain == AF_UNIX) 56 return (EAFNOSUPPORT); 57 58 ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP); 59 so = socket_create(domain, type, protocol, NULL, NULL, version, flags, 60 cr, &error); 61 if (so == NULL) { 62 if (error == EAFNOSUPPORT) { 63 char *mod = NULL; 64 65 /* 66 * Could be that root file sytem is not loaded or 67 * soconfig has not run yet. 68 */ 69 if (type == SOCK_STREAM && (domain == AF_INET || 70 domain == AF_INET6) && (protocol == 0 || 71 protocol == IPPROTO_TCP)) { 72 mod = SOCKETMOD_TCP; 73 } else if (type == SOCK_DGRAM && (domain == AF_INET || 74 domain == AF_INET6) && (protocol == 0 || 75 protocol == IPPROTO_UDP)) { 76 mod = SOCKETMOD_UDP; 77 } else { 78 return (EAFNOSUPPORT); 79 } 80 81 so = socket_create(domain, type, protocol, NULL, 82 mod, version, flags, cr, &error); 83 if (so == NULL) 84 return (error); 85 } else { 86 return (error); 87 } 88 } 89 90 so->so_mode |= SM_KERNEL; 91 92 *ksp = SOTOKS(so); 93 94 return (0); 95} 96int 97ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen, 98 struct cred *cr) 99{ 100 int error; 101 102 if (!KSOCKET_VALID(ks)) 103 return (ENOTSOCK); 104 105 error = socket_bind(KSTOSO(ks), addr, addrlen, _SOBIND_SOCKBSD, cr); 106 107 return (error); 108} 109 110int 111ksocket_listen(ksocket_t ks, int backlog, struct cred *cr) 112{ 113 if (!KSOCKET_VALID(ks)) 114 return (ENOTSOCK); 115 116 return (socket_listen(KSTOSO(ks), backlog, cr)); 117} 118 119int 120ksocket_accept(ksocket_t ks, struct sockaddr *addr, 121 socklen_t *addrlenp, ksocket_t *nks, struct cred *cr) 122{ 123 int error; 124 struct sonode *nso = NULL; 125 126 *nks = NULL; 127 128 if (!KSOCKET_VALID(ks)) 129 return (ENOTSOCK); 130 131 if (addr != NULL && addrlenp == NULL) 132 return (EFAULT); 133 134 error = socket_accept(KSTOSO(ks), KSOCKET_FMODE(ks), cr, &nso); 135 if (error != 0) 136 return (error); 137 138 ASSERT(nso != NULL); 139 140 nso->so_mode |= SM_KERNEL; 141 142 if (addr != NULL && addrlenp != NULL) { 143 error = socket_getpeername(nso, addr, addrlenp, B_TRUE, cr); 144 if (error != 0) { 145 (void) socket_close(nso, 0, cr); 146 socket_destroy(nso); 147 return ((error == ENOTCONN) ? ECONNABORTED : error); 148 } 149 } 150 151 *nks = SOTOKS(nso); 152 153 return (error); 154} 155 156int 157ksocket_connect(ksocket_t ks, const struct sockaddr *addr, socklen_t addrlen, 158 struct cred *cr) 159{ 160 if (!KSOCKET_VALID(ks)) 161 return (ENOTSOCK); 162 163 return (socket_connect(KSTOSO(ks), addr, addrlen, 164 KSOCKET_FMODE(ks), 0, cr)); 165} 166 167int 168ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags, 169 size_t *sent, struct cred *cr) 170{ 171 int error; 172 struct nmsghdr msghdr; 173 struct uio auio; 174 struct iovec iov; 175 176 if (!KSOCKET_VALID(ks)) { 177 if (sent != NULL) 178 *sent = 0; 179 return (ENOTSOCK); 180 } 181 182 iov.iov_base = msg; 183 iov.iov_len = msglen; 184 185 bzero(&auio, sizeof (struct uio)); 186 auio.uio_loffset = 0; 187 auio.uio_iov = &iov; 188 auio.uio_iovcnt = 1; 189 auio.uio_resid = msglen; 190 if (flags & MSG_USERSPACE) 191 auio.uio_segflg = UIO_USERSPACE; 192 else 193 auio.uio_segflg = UIO_SYSSPACE; 194 auio.uio_extflg = UIO_COPY_DEFAULT; 195 auio.uio_limit = 0; 196 auio.uio_fmode = KSOCKET_FMODE(ks); 197 198 msghdr.msg_name = NULL; 199 msghdr.msg_namelen = 0; 200 msghdr.msg_control = NULL; 201 msghdr.msg_controllen = 0; 202 msghdr.msg_flags = flags | MSG_EOR; 203 204 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 205 if (error != 0) { 206 if (sent != NULL) 207 *sent = 0; 208 return (error); 209 } 210 211 if (sent != NULL) 212 *sent = msglen - auio.uio_resid; 213 return (0); 214} 215 216int 217ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, 218 struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) 219{ 220 int error; 221 struct nmsghdr msghdr; 222 struct uio auio; 223 struct iovec iov; 224 225 if (!KSOCKET_VALID(ks)) { 226 if (sent != NULL) 227 *sent = 0; 228 return (ENOTSOCK); 229 } 230 231 iov.iov_base = msg; 232 iov.iov_len = msglen; 233 234 bzero(&auio, sizeof (struct uio)); 235 auio.uio_loffset = 0; 236 auio.uio_iov = &iov; 237 auio.uio_iovcnt = 1; 238 auio.uio_resid = msglen; 239 if (flags & MSG_USERSPACE) 240 auio.uio_segflg = UIO_USERSPACE; 241 else 242 auio.uio_segflg = UIO_SYSSPACE; 243 auio.uio_extflg = UIO_COPY_DEFAULT; 244 auio.uio_limit = 0; 245 auio.uio_fmode = KSOCKET_FMODE(ks); 246 247 msghdr.msg_iov = &iov; 248 msghdr.msg_iovlen = 1; 249 msghdr.msg_name = (char *)name; 250 msghdr.msg_namelen = namelen; 251 msghdr.msg_control = NULL; 252 msghdr.msg_controllen = 0; 253 msghdr.msg_flags = flags | MSG_EOR; 254 255 error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); 256 if (error != 0) { 257 if (sent != NULL) 258 *sent = 0; 259 return (error); 260 } 261 if (sent != NULL) 262 *sent = msglen - auio.uio_resid; 263 return (0); 264} 265 266int 267ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, 268 size_t *sent, struct cred *cr) 269{ 270 int error; 271 ssize_t len; 272 int i; 273 struct uio auio; 274 275 if (!KSOCKET_VALID(ks)) { 276 if (sent != NULL) 277 *sent = 0; 278 return (ENOTSOCK); 279 } 280 281 bzero(&auio, sizeof (struct uio)); 282 auio.uio_loffset = 0; 283 auio.uio_iov = msg->msg_iov; 284 auio.uio_iovcnt = msg->msg_iovlen; 285 if (flags & MSG_USERSPACE) 286 auio.uio_segflg = UIO_USERSPACE; 287 else 288 auio.uio_segflg = UIO_SYSSPACE; 289 auio.uio_extflg = UIO_COPY_DEFAULT; 290 auio.uio_limit = 0; 291 auio.uio_fmode = KSOCKET_FMODE(ks); 292 len = 0; 293 for (i = 0; i < msg->msg_iovlen; i++) { 294 ssize_t iovlen; 295 iovlen = (msg->msg_iov)[i].iov_len; 296 len += iovlen; 297 if (len < 0 || iovlen < 0) 298 return (EINVAL); 299 } 300 auio.uio_resid = len; 301 302 msg->msg_flags = flags | MSG_EOR; 303 304 error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr); 305 if (error != 0) { 306 if (sent != NULL) 307 *sent = 0; 308 return (error); 309 } 310 311 if (sent != NULL) 312 *sent = len - auio.uio_resid; 313 return (0); 314} 315 316 317int 318ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags, 319 size_t *recv, struct cred *cr) 320{ 321 int error; 322 struct nmsghdr msghdr; 323 struct uio auio; 324 struct iovec iov; 325 326 if (!KSOCKET_VALID(ks)) { 327 if (recv != NULL) 328 *recv = 0; 329 return (ENOTSOCK); 330 } 331 332 iov.iov_base = msg; 333 iov.iov_len = msglen; 334 335 bzero(&auio, sizeof (struct uio)); 336 auio.uio_loffset = 0; 337 auio.uio_iov = &iov; 338 auio.uio_iovcnt = 1; 339 auio.uio_resid = msglen; 340 if (flags & MSG_USERSPACE) 341 auio.uio_segflg = UIO_USERSPACE; 342 else 343 auio.uio_segflg = UIO_SYSSPACE; 344 auio.uio_extflg = UIO_COPY_DEFAULT; 345 auio.uio_limit = 0; 346 auio.uio_fmode = KSOCKET_FMODE(ks); 347 348 msghdr.msg_name = NULL; 349 msghdr.msg_namelen = 0; 350 msghdr.msg_control = NULL; 351 msghdr.msg_controllen = 0; 352 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 353 MSG_DONTWAIT | MSG_USERSPACE); 354 355 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 356 if (error != 0) { 357 if (recv != NULL) 358 *recv = 0; 359 return (error); 360 } 361 362 if (recv != NULL) 363 *recv = msglen - auio.uio_resid; 364 return (0); 365} 366 367int 368ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags, 369 struct sockaddr *name, socklen_t *namelen, size_t *recv, struct cred *cr) 370{ 371 int error; 372 struct nmsghdr msghdr; 373 struct uio auio; 374 struct iovec iov; 375 376 if (!KSOCKET_VALID(ks)) { 377 if (recv != NULL) 378 *recv = 0; 379 return (ENOTSOCK); 380 } 381 382 iov.iov_base = msg; 383 iov.iov_len = msglen; 384 385 bzero(&auio, sizeof (struct uio)); 386 auio.uio_loffset = 0; 387 auio.uio_iov = &iov; 388 auio.uio_iovcnt = 1; 389 auio.uio_resid = msglen; 390 if (flags & MSG_USERSPACE) 391 auio.uio_segflg = UIO_USERSPACE; 392 else 393 auio.uio_segflg = UIO_SYSSPACE; 394 auio.uio_extflg = UIO_COPY_DEFAULT; 395 auio.uio_limit = 0; 396 auio.uio_fmode = KSOCKET_FMODE(ks); 397 398 msghdr.msg_name = (char *)name; 399 msghdr.msg_namelen = *namelen; 400 msghdr.msg_control = NULL; 401 msghdr.msg_controllen = 0; 402 msghdr.msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 403 MSG_DONTWAIT | MSG_USERSPACE); 404 405 error = socket_recvmsg(KSTOSO(ks), &msghdr, &auio, cr); 406 if (error != 0) { 407 if (recv != NULL) 408 *recv = 0; 409 return (error); 410 } 411 if (recv != NULL) 412 *recv = msglen - auio.uio_resid; 413 414 bcopy(msghdr.msg_name, name, msghdr.msg_namelen); 415 bcopy(&msghdr.msg_namelen, namelen, sizeof (msghdr.msg_namelen)); 416 return (0); 417} 418 419int 420ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recv, 421 struct cred *cr) 422{ 423 int error; 424 ssize_t len; 425 int i; 426 struct uio auio; 427 428 if (!KSOCKET_VALID(ks)) { 429 if (recv != NULL) 430 *recv = 0; 431 return (ENOTSOCK); 432 } 433 434 bzero(&auio, sizeof (struct uio)); 435 auio.uio_loffset = 0; 436 auio.uio_iov = msg->msg_iov; 437 auio.uio_iovcnt = msg->msg_iovlen; 438 if (msg->msg_flags & MSG_USERSPACE) 439 auio.uio_segflg = UIO_USERSPACE; 440 else 441 auio.uio_segflg = UIO_SYSSPACE; 442 auio.uio_extflg = UIO_COPY_DEFAULT; 443 auio.uio_limit = 0; 444 auio.uio_fmode = KSOCKET_FMODE(ks); 445 len = 0; 446 447 for (i = 0; i < msg->msg_iovlen; i++) { 448 ssize_t iovlen; 449 iovlen = (msg->msg_iov)[i].iov_len; 450 len += iovlen; 451 if (len < 0 || iovlen < 0) 452 return (EINVAL); 453 } 454 auio.uio_resid = len; 455 456 msg->msg_flags = flags & (MSG_OOB | MSG_PEEK | MSG_WAITALL | 457 MSG_DONTWAIT | MSG_USERSPACE); 458 459 error = socket_recvmsg(KSTOSO(ks), msg, &auio, cr); 460 if (error != 0) { 461 if (recv != NULL) 462 *recv = 0; 463 return (error); 464 } 465 if (recv != NULL) 466 *recv = len - auio.uio_resid; 467 return (0); 468 469} 470 471int 472ksocket_shutdown(ksocket_t ks, int how, struct cred *cr) 473{ 474 struct sonode *so; 475 476 if (!KSOCKET_VALID(ks)) 477 return (ENOTSOCK); 478 479 so = KSTOSO(ks); 480 481 return (socket_shutdown(so, how, cr)); 482} 483 484int 485ksocket_close(ksocket_t ks, struct cred *cr) 486{ 487 struct sonode *so; 488 so = KSTOSO(ks); 489 490 mutex_enter(&so->so_lock); 491 492 if (!KSOCKET_VALID(ks)) { 493 mutex_exit(&so->so_lock); 494 return (ENOTSOCK); 495 } 496 497 so->so_state |= SS_CLOSING; 498 499 if (so->so_count > 1) { 500 mutex_enter(&so->so_acceptq_lock); 501 cv_broadcast(&so->so_acceptq_cv); 502 mutex_exit(&so->so_acceptq_lock); 503 cv_broadcast(&so->so_rcv_cv); 504 cv_broadcast(&so->so_state_cv); 505 cv_broadcast(&so->so_want_cv); 506 cv_broadcast(&so->so_snd_cv); 507 cv_broadcast(&so->so_copy_cv); 508 } 509 while (so->so_count > 1) 510 cv_wait(&so->so_closing_cv, &so->so_lock); 511 512 mutex_exit(&so->so_lock); 513 /* Remove callbacks, if any */ 514 (void) ksocket_setcallbacks(ks, NULL, NULL, cr); 515 516 (void) socket_close(so, 0, cr); 517 socket_destroy(so); 518 519 return (0); 520} 521 522int 523ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 524 struct cred *cr) 525{ 526 struct sonode *so; 527 528 if (!KSOCKET_VALID(ks)) 529 return (ENOTSOCK); 530 531 so = KSTOSO(ks); 532 533 if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 534 return (EFAULT); 535 536 return (socket_getsockname(so, addr, addrlen, cr)); 537} 538 539int 540ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen, 541 struct cred *cr) 542{ 543 struct sonode *so; 544 545 if (!KSOCKET_VALID(ks)) 546 return (ENOTSOCK); 547 548 so = KSTOSO(ks); 549 550 if (addrlen == NULL || (addr == NULL && *addrlen != 0)) 551 return (EFAULT); 552 553 return (socket_getpeername(so, addr, addrlen, B_FALSE, cr)); 554} 555 556int 557ksocket_getsockopt(ksocket_t ks, int level, int optname, void *optval, 558 int *optlen, struct cred *cr) 559{ 560 struct sonode *so; 561 562 if (!KSOCKET_VALID(ks)) 563 return (ENOTSOCK); 564 565 so = KSTOSO(ks); 566 567 if (optlen == NULL) 568 return (EFAULT); 569 if (*optlen > SO_MAXARGSIZE) 570 return (EINVAL); 571 572 return (socket_getsockopt(so, level, optname, optval, 573 (socklen_t *)optlen, 0, cr)); 574} 575 576int 577ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval, 578 int optlen, struct cred *cr) 579{ 580 struct sonode *so; 581 582 if (!KSOCKET_VALID(ks)) 583 return (ENOTSOCK); 584 585 so = KSTOSO(ks); 586 587 if (optval == NULL) 588 optlen = 0; 589 590 return (socket_setsockopt(so, level, optname, optval, 591 (t_uscalar_t)optlen, cr)); 592} 593 594/* ARGSUSED */ 595int 596ksocket_setcallbacks(ksocket_t ks, ksocket_callbacks_t *cb, void *arg, 597 struct cred *cr) 598{ 599 struct sonode *so; 600 601 if (!KSOCKET_VALID(ks)) 602 return (ENOTSOCK); 603 604 so = KSTOSO(ks); 605 606 if (cb == NULL && arg != NULL) 607 return (EFAULT); 608 if (cb == NULL) { 609 mutex_enter(&so->so_lock); 610 bzero(&(so->so_ksock_callbacks), sizeof (ksocket_callbacks_t)); 611 so->so_ksock_cb_arg = NULL; 612 mutex_exit(&so->so_lock); 613 } else { 614 mutex_enter(&so->so_lock); 615 SETCALLBACK(so, cb, connected, KSOCKET_CB_CONNECTED) 616 SETCALLBACK(so, cb, connectfailed, KSOCKET_CB_CONNECTFAILED) 617 SETCALLBACK(so, cb, disconnected, KSOCKET_CB_DISCONNECTED) 618 SETCALLBACK(so, cb, newdata, KSOCKET_CB_NEWDATA) 619 SETCALLBACK(so, cb, newconn, KSOCKET_CB_NEWCONN) 620 SETCALLBACK(so, cb, cansend, KSOCKET_CB_CANSEND) 621 SETCALLBACK(so, cb, oobdata, KSOCKET_CB_OOBDATA) 622 SETCALLBACK(so, cb, cantsendmore, KSOCKET_CB_CANTSENDMORE) 623 SETCALLBACK(so, cb, cantrecvmore, KSOCKET_CB_CANTRECVMORE) 624 so->so_ksock_cb_arg = arg; 625 mutex_exit(&so->so_lock); 626 } 627 return (0); 628} 629 630int 631ksocket_ioctl(ksocket_t ks, int cmd, intptr_t arg, int *rvalp, struct cred *cr) 632{ 633 struct sonode *so; 634 int rval; 635 636 if (!KSOCKET_VALID(ks)) 637 return (ENOTSOCK); 638 639 so = KSTOSO(ks); 640 641 switch (cmd) { 642 default: 643 /* STREAM iotcls are not supported */ 644 if ((cmd & 0xffffff00U) == STR) { 645 rval = EOPNOTSUPP; 646 } else { 647 rval = socket_ioctl(so, cmd, arg, 648 KSOCKET_FMODE(ks) | FKIOCTL, cr, rvalp); 649 } 650 break; 651 case FIOASYNC: 652 case SIOCSPGRP: 653 case FIOSETOWN: 654 case SIOCGPGRP: 655 case FIOGETOWN: 656 rval = EOPNOTSUPP; 657 break; 658 } 659 660 return (rval); 661} 662 663int 664ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags, 665 mblk_t **mpp, cred_t *cr) 666{ 667 struct sonode *so; 668 int i_val; 669 socklen_t val_len; 670 mblk_t *mp = *mpp; 671 int error; 672 673 if (!KSOCKET_VALID(ks)) 674 return (ENOTSOCK); 675 676 so = KSTOSO(ks); 677 678 if (flags & MSG_MBLK_QUICKRELE) { 679 error = socket_getsockopt(so, SOL_SOCKET, SO_SND_COPYAVOID, 680 &i_val, &val_len, 0, CRED()); 681 if (error != 0) 682 return (error); 683 684 /* Zero copy is not enable */ 685 if (i_val == 0) 686 return (ECANCELED); 687 688 for (; mp != NULL; mp = mp->b_cont) 689 mp->b_datap->db_struioflag |= STRUIO_ZC; 690 } 691 692 error = socket_sendmblk(so, msg, flags, cr, mpp); 693 694 return (error); 695} 696 697 698void 699ksocket_hold(ksocket_t ks) 700{ 701 struct sonode *so; 702 so = KSTOSO(ks); 703 704 if (!mutex_owned(&so->so_lock)) { 705 mutex_enter(&so->so_lock); 706 so->so_count++; 707 mutex_exit(&so->so_lock); 708 } else 709 so->so_count++; 710} 711 712void 713ksocket_rele(ksocket_t ks) 714{ 715 struct sonode *so; 716 717 so = KSTOSO(ks); 718 /* 719 * When so_count equals 1 means no thread working on this ksocket 720 */ 721 if (so->so_count < 2) 722 cmn_err(CE_PANIC, "ksocket_rele: sonode ref count 0 or 1"); 723 724 if (!mutex_owned(&so->so_lock)) { 725 mutex_enter(&so->so_lock); 726 if (--so->so_count == 1) 727 cv_signal(&so->so_closing_cv); 728 mutex_exit(&so->so_lock); 729 } else { 730 if (--so->so_count == 1) 731 cv_signal(&so->so_closing_cv); 732 } 733} 734