1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1548 rshoaib * Common Development and Distribution License (the "License"). 6 1548 rshoaib * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1548 rshoaib 22 0 stevel /* 23 8778 Erik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #include <sys/types.h> 28 0 stevel #include <sys/inttypes.h> 29 0 stevel #include <sys/t_lock.h> 30 0 stevel #include <sys/param.h> 31 0 stevel #include <sys/systm.h> 32 0 stevel #include <sys/buf.h> 33 0 stevel #include <sys/conf.h> 34 0 stevel #include <sys/cred.h> 35 0 stevel #include <sys/kmem.h> 36 0 stevel #include <sys/sysmacros.h> 37 0 stevel #include <sys/vfs.h> 38 0 stevel #include <sys/vnode.h> 39 0 stevel #include <sys/debug.h> 40 0 stevel #include <sys/errno.h> 41 0 stevel #include <sys/time.h> 42 0 stevel #include <sys/file.h> 43 0 stevel #include <sys/user.h> 44 0 stevel #include <sys/stream.h> 45 0 stevel #include <sys/strsubr.h> 46 0 stevel #include <sys/esunddi.h> 47 0 stevel #include <sys/flock.h> 48 0 stevel #include <sys/modctl.h> 49 0 stevel #include <sys/vtrace.h> 50 0 stevel #include <sys/strsun.h> 51 0 stevel #include <sys/cmn_err.h> 52 0 stevel #include <sys/proc.h> 53 0 stevel #include <sys/ddi.h> 54 0 stevel 55 0 stevel #include <sys/suntpi.h> 56 0 stevel #include <sys/socket.h> 57 0 stevel #include <sys/sockio.h> 58 0 stevel #include <sys/socketvar.h> 59 0 stevel #include <netinet/in.h> 60 8348 Eric #include <inet/common.h> 61 8348 Eric #include <inet/proto_set.h> 62 0 stevel 63 0 stevel #include <sys/tiuser.h> 64 0 stevel #define _SUN_TPI_VERSION 2 65 0 stevel #include <sys/tihdr.h> 66 898 kais 67 898 kais #include <inet/kssl/ksslapi.h> 68 0 stevel 69 0 stevel #include <c2/audit.h> 70 6707 brutus 71 8348 Eric #include <fs/sockfs/socktpi.h> 72 8348 Eric #include <fs/sockfs/socktpi_impl.h> 73 0 stevel 74 0 stevel int so_default_version = SOV_SOCKSTREAM; 75 0 stevel 76 0 stevel #ifdef DEBUG 77 0 stevel /* Set sockdebug to print debug messages when SO_DEBUG is set */ 78 0 stevel int sockdebug = 0; 79 0 stevel 80 0 stevel /* Set sockprinterr to print error messages when SO_DEBUG is set */ 81 0 stevel int sockprinterr = 0; 82 0 stevel 83 0 stevel /* 84 0 stevel * Set so_default_options to SO_DEBUG is all sockets should be created 85 0 stevel * with SO_DEBUG set. This is needed to get debug printouts from the 86 0 stevel * socket() call itself. 87 0 stevel */ 88 0 stevel int so_default_options = 0; 89 0 stevel #endif /* DEBUG */ 90 0 stevel 91 0 stevel #ifdef SOCK_TEST 92 0 stevel /* 93 0 stevel * Set to number of ticks to limit cv_waits for code coverage testing. 94 0 stevel * Set to 1000 when SO_DEBUG is set to 2. 95 0 stevel */ 96 0 stevel clock_t sock_test_timelimit = 0; 97 0 stevel #endif /* SOCK_TEST */ 98 0 stevel 99 0 stevel /* 100 0 stevel * For concurrency testing of e.g. opening /dev/ip which does not 101 0 stevel * handle T_INFO_REQ messages. 102 0 stevel */ 103 0 stevel int so_no_tinfo = 0; 104 0 stevel 105 0 stevel /* 106 0 stevel * Timeout for getting a T_CAPABILITY_ACK - it is possible for a provider 107 0 stevel * to simply ignore the T_CAPABILITY_REQ. 108 0 stevel */ 109 0 stevel clock_t sock_capability_timeout = 2; /* seconds */ 110 0 stevel 111 0 stevel static int do_tcapability(struct sonode *so, t_uscalar_t cap_bits1); 112 0 stevel static void so_removehooks(struct sonode *so); 113 0 stevel 114 0 stevel static mblk_t *strsock_proto(vnode_t *vp, mblk_t *mp, 115 0 stevel strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 116 0 stevel strsigset_t *allmsgsigs, strpollset_t *pollwakeups); 117 0 stevel static mblk_t *strsock_misc(vnode_t *vp, mblk_t *mp, 118 0 stevel strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 119 0 stevel strsigset_t *allmsgsigs, strpollset_t *pollwakeups); 120 0 stevel 121 0 stevel /* 122 0 stevel * Convert a socket to a stream. Invoked when the illusory sockmod 123 0 stevel * is popped from the stream. 124 0 stevel * Change the stream head back to default operation without losing 125 0 stevel * any messages (T_conn_ind's are moved to the stream head queue). 126 0 stevel */ 127 0 stevel int 128 0 stevel so_sock2stream(struct sonode *so) 129 0 stevel { 130 0 stevel struct vnode *vp = SOTOV(so); 131 0 stevel queue_t *rq; 132 0 stevel mblk_t *mp; 133 0 stevel int error = 0; 134 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 135 0 stevel 136 8348 Eric ASSERT(MUTEX_HELD(&sti->sti_plumb_lock)); 137 0 stevel 138 0 stevel mutex_enter(&so->so_lock); 139 0 stevel so_lock_single(so); 140 0 stevel 141 0 stevel ASSERT(so->so_version != SOV_STREAM); 142 0 stevel 143 8348 Eric if (sti->sti_direct) { 144 741 masputra mblk_t **mpp; 145 741 masputra int rval; 146 0 stevel 147 741 masputra /* 148 741 masputra * Tell the transport below that sockmod is being popped 149 741 masputra */ 150 0 stevel mutex_exit(&so->so_lock); 151 741 masputra error = strioctl(vp, _SIOCSOCKFALLBACK, 0, 0, K_TO_K, CRED(), 152 0 stevel &rval); 153 0 stevel mutex_enter(&so->so_lock); 154 0 stevel if (error != 0) { 155 741 masputra dprintso(so, 0, ("so_sock2stream(%p): " 156 7240 rh87107 "_SIOCSOCKFALLBACK failed\n", (void *)so)); 157 0 stevel goto exit; 158 0 stevel } 159 8348 Eric sti->sti_direct = 0; 160 0 stevel 161 8348 Eric for (mpp = &sti->sti_conn_ind_head; (mp = *mpp) != NULL; 162 0 stevel mpp = &mp->b_next) { 163 0 stevel struct T_conn_ind *conn_ind; 164 0 stevel 165 0 stevel /* 166 0 stevel * strsock_proto() has already verified the length of 167 0 stevel * this message block. 168 0 stevel */ 169 0 stevel ASSERT(MBLKL(mp) >= sizeof (struct T_conn_ind)); 170 0 stevel 171 0 stevel conn_ind = (struct T_conn_ind *)mp->b_rptr; 172 0 stevel if (conn_ind->OPT_length == 0 && 173 0 stevel conn_ind->OPT_offset == 0) 174 0 stevel continue; 175 0 stevel 176 0 stevel if (DB_REF(mp) > 1) { 177 0 stevel mblk_t *newmp; 178 0 stevel size_t length; 179 0 stevel cred_t *cr; 180 8778 Erik pid_t cpid; 181 8778 Erik int error; /* Dummy - error not returned */ 182 0 stevel 183 0 stevel /* 184 0 stevel * Copy the message block because it is used 185 0 stevel * elsewhere, too. 186 8778 Erik * Can't use copyb since we want to wait 187 8778 Erik * yet allow for EINTR. 188 0 stevel */ 189 8778 Erik /* Round up size for reuse */ 190 8778 Erik length = MAX(MBLKL(mp), 64); 191 8778 Erik cr = msg_getcred(mp, &cpid); 192 8778 Erik if (cr != NULL) { 193 8778 Erik newmp = allocb_cred_wait(length, 0, 194 8778 Erik &error, cr, cpid); 195 8778 Erik } else { 196 8778 Erik newmp = allocb_wait(length, 0, 0, 197 8778 Erik &error); 198 8778 Erik } 199 0 stevel if (newmp == NULL) { 200 0 stevel error = EINTR; 201 0 stevel goto exit; 202 0 stevel } 203 0 stevel bcopy(mp->b_rptr, newmp->b_wptr, length); 204 0 stevel newmp->b_wptr += length; 205 0 stevel newmp->b_next = mp->b_next; 206 0 stevel 207 0 stevel /* 208 0 stevel * Link the new message block into the queue 209 0 stevel * and free the old one. 210 0 stevel */ 211 0 stevel *mpp = newmp; 212 0 stevel mp->b_next = NULL; 213 0 stevel freemsg(mp); 214 0 stevel 215 0 stevel mp = newmp; 216 0 stevel conn_ind = (struct T_conn_ind *)mp->b_rptr; 217 0 stevel } 218 0 stevel 219 0 stevel /* 220 0 stevel * Remove options added by TCP for accept fast-path. 221 0 stevel */ 222 0 stevel conn_ind->OPT_length = 0; 223 0 stevel conn_ind->OPT_offset = 0; 224 0 stevel } 225 0 stevel } 226 0 stevel 227 0 stevel so->so_version = SOV_STREAM; 228 8348 Eric so->so_proto_handle = NULL; 229 0 stevel 230 0 stevel /* 231 0 stevel * Remove the hooks in the stream head to avoid queuing more 232 0 stevel * packets in sockfs. 233 0 stevel */ 234 0 stevel mutex_exit(&so->so_lock); 235 0 stevel so_removehooks(so); 236 0 stevel mutex_enter(&so->so_lock); 237 0 stevel 238 0 stevel /* 239 0 stevel * Clear any state related to urgent data. Leave any T_EXDATA_IND 240 0 stevel * on the queue - the behavior of urgent data after a switch is 241 0 stevel * left undefined. 242 0 stevel */ 243 8348 Eric so->so_error = sti->sti_delayed_error = 0; 244 0 stevel freemsg(so->so_oobmsg); 245 0 stevel so->so_oobmsg = NULL; 246 8348 Eric sti->sti_oobsigcnt = sti->sti_oobcnt = 0; 247 0 stevel 248 0 stevel so->so_state &= ~(SS_RCVATMARK|SS_OOBPEND|SS_HAVEOOBDATA|SS_HADOOBDATA| 249 8348 Eric SS_SAVEDEOR); 250 0 stevel ASSERT(so_verify_oobstate(so)); 251 0 stevel 252 8348 Eric freemsg(sti->sti_ack_mp); 253 8348 Eric sti->sti_ack_mp = NULL; 254 0 stevel 255 0 stevel /* 256 8348 Eric * Flush the T_DISCON_IND on sti_discon_ind_mp. 257 0 stevel */ 258 0 stevel so_flush_discon_ind(so); 259 0 stevel 260 0 stevel /* 261 0 stevel * Move any queued T_CONN_IND messages to stream head queue. 262 0 stevel */ 263 0 stevel rq = RD(strvp2wq(vp)); 264 8348 Eric while ((mp = sti->sti_conn_ind_head) != NULL) { 265 8348 Eric sti->sti_conn_ind_head = mp->b_next; 266 0 stevel mp->b_next = NULL; 267 8348 Eric if (sti->sti_conn_ind_head == NULL) { 268 8348 Eric ASSERT(sti->sti_conn_ind_tail == mp); 269 8348 Eric sti->sti_conn_ind_tail = NULL; 270 0 stevel } 271 0 stevel dprintso(so, 0, 272 8348 Eric ("so_sock2stream(%p): moving T_CONN_IND\n", (void *)so)); 273 0 stevel 274 0 stevel /* Drop lock across put() */ 275 0 stevel mutex_exit(&so->so_lock); 276 0 stevel put(rq, mp); 277 0 stevel mutex_enter(&so->so_lock); 278 0 stevel } 279 0 stevel 280 0 stevel exit: 281 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 282 0 stevel so_unlock_single(so, SOLOCKED); 283 0 stevel mutex_exit(&so->so_lock); 284 0 stevel return (error); 285 0 stevel } 286 0 stevel 287 0 stevel /* 288 0 stevel * Covert a stream back to a socket. This is invoked when the illusory 289 0 stevel * sockmod is pushed on a stream (where the stream was "created" by 290 0 stevel * popping the illusory sockmod). 291 0 stevel * This routine can not recreate the socket state (certain aspects of 292 0 stevel * it like urgent data state and the bound/connected addresses for AF_UNIX 293 0 stevel * sockets can not be recreated by asking the transport for information). 294 0 stevel * Thus this routine implicitly assumes that the socket is in an initial 295 0 stevel * state (as if it was just created). It flushes any messages queued on the 296 0 stevel * read queue to avoid dealing with e.g. TPI acks or T_exdata_ind messages. 297 0 stevel */ 298 0 stevel void 299 0 stevel so_stream2sock(struct sonode *so) 300 0 stevel { 301 0 stevel struct vnode *vp = SOTOV(so); 302 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 303 0 stevel 304 8348 Eric ASSERT(MUTEX_HELD(&sti->sti_plumb_lock)); 305 0 stevel 306 0 stevel mutex_enter(&so->so_lock); 307 0 stevel so_lock_single(so); 308 0 stevel ASSERT(so->so_version == SOV_STREAM); 309 0 stevel so->so_version = SOV_SOCKSTREAM; 310 8348 Eric sti->sti_pushcnt = 0; 311 0 stevel mutex_exit(&so->so_lock); 312 0 stevel 313 0 stevel /* 314 0 stevel * Set a permenent error to force any thread in sorecvmsg to 315 0 stevel * return (and drop SOREADLOCKED). Clear the error once 316 0 stevel * we have SOREADLOCKED. 317 0 stevel * This makes a read sleeping during the I_PUSH of sockmod return 318 0 stevel * EIO. 319 0 stevel */ 320 0 stevel strsetrerror(SOTOV(so), EIO, 1, NULL); 321 0 stevel 322 0 stevel /* 323 0 stevel * Get the read lock before flushing data to avoid 324 0 stevel * problems with the T_EXDATA_IND MSG_PEEK code in sorecvmsg. 325 0 stevel */ 326 0 stevel mutex_enter(&so->so_lock); 327 0 stevel (void) so_lock_read(so, 0); /* Set SOREADLOCKED */ 328 0 stevel mutex_exit(&so->so_lock); 329 0 stevel 330 0 stevel strsetrerror(SOTOV(so), 0, 0, NULL); 331 0 stevel so_installhooks(so); 332 0 stevel 333 0 stevel /* 334 0 stevel * Flush everything on the read queue. 335 0 stevel * This ensures that no T_CONN_IND remain and that no T_EXDATA_IND 336 0 stevel * remain; those types of messages would confuse sockfs. 337 0 stevel */ 338 0 stevel strflushrq(vp, FLUSHALL); 339 0 stevel mutex_enter(&so->so_lock); 340 0 stevel 341 0 stevel /* 342 8348 Eric * Flush the T_DISCON_IND on sti_discon_ind_mp. 343 0 stevel */ 344 0 stevel so_flush_discon_ind(so); 345 0 stevel so_unlock_read(so); /* Clear SOREADLOCKED */ 346 0 stevel 347 0 stevel so_unlock_single(so, SOLOCKED); 348 0 stevel mutex_exit(&so->so_lock); 349 0 stevel } 350 0 stevel 351 0 stevel /* 352 0 stevel * Install the hooks in the stream head. 353 0 stevel */ 354 0 stevel void 355 0 stevel so_installhooks(struct sonode *so) 356 0 stevel { 357 0 stevel struct vnode *vp = SOTOV(so); 358 0 stevel 359 0 stevel strsetrputhooks(vp, SH_SIGALLDATA | SH_IGN_ZEROLEN | SH_CONSOL_DATA, 360 0 stevel strsock_proto, strsock_misc); 361 0 stevel strsetwputhooks(vp, SH_SIGPIPE | SH_RECHECK_ERR, 0); 362 0 stevel } 363 0 stevel 364 0 stevel /* 365 0 stevel * Remove the hooks in the stream head. 366 0 stevel */ 367 0 stevel static void 368 0 stevel so_removehooks(struct sonode *so) 369 0 stevel { 370 0 stevel struct vnode *vp = SOTOV(so); 371 0 stevel 372 0 stevel strsetrputhooks(vp, 0, NULL, NULL); 373 0 stevel strsetwputhooks(vp, 0, STRTIMOUT); 374 0 stevel /* 375 0 stevel * Leave read behavior as it would have been for a normal 376 0 stevel * stream i.e. a read of an M_PROTO will fail. 377 0 stevel */ 378 0 stevel } 379 0 stevel 380 8348 Eric void 381 8348 Eric so_basic_strinit(struct sonode *so) 382 0 stevel { 383 0 stevel struct vnode *vp = SOTOV(so); 384 0 stevel struct stdata *stp; 385 0 stevel mblk_t *mp; 386 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 387 0 stevel 388 0 stevel /* Preallocate an unbind_req message */ 389 8778 Erik mp = soallocproto(sizeof (struct T_unbind_req), _ALLOC_SLEEP, CRED()); 390 0 stevel mutex_enter(&so->so_lock); 391 8348 Eric sti->sti_unbind_mp = mp; 392 0 stevel #ifdef DEBUG 393 0 stevel so->so_options = so_default_options; 394 0 stevel #endif /* DEBUG */ 395 0 stevel mutex_exit(&so->so_lock); 396 0 stevel 397 0 stevel so_installhooks(so); 398 0 stevel 399 0 stevel stp = vp->v_stream; 400 0 stevel /* 401 0 stevel * Have to keep minpsz at zero in order to allow write/send of zero 402 0 stevel * bytes. 403 0 stevel */ 404 0 stevel mutex_enter(&stp->sd_lock); 405 0 stevel if (stp->sd_qn_minpsz == 1) 406 0 stevel stp->sd_qn_minpsz = 0; 407 0 stevel mutex_exit(&stp->sd_lock); 408 8348 Eric } 409 6707 brutus 410 8348 Eric /* 411 8348 Eric * Initialize the streams side of a socket including 412 8348 Eric * T_info_req/ack processing. If tso is not NULL its values are used thereby 413 8348 Eric * avoiding the T_INFO_REQ. 414 8348 Eric */ 415 8348 Eric int 416 8348 Eric so_strinit(struct sonode *so, struct sonode *tso) 417 8348 Eric { 418 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 419 8348 Eric sotpi_info_t *tsti; 420 8348 Eric int error; 421 6707 brutus 422 8348 Eric so_basic_strinit(so); 423 8348 Eric 424 8348 Eric /* 425 8348 Eric * The T_CAPABILITY_REQ should be the first message sent down because 426 8348 Eric * at least TCP has a fast-path for this which avoids timeouts while 427 8348 Eric * waiting for the T_CAPABILITY_ACK under high system load. 428 8348 Eric */ 429 8348 Eric if (tso == NULL) { 430 8348 Eric error = do_tcapability(so, TC1_ACCEPTOR_ID | TC1_INFO); 431 8348 Eric if (error) 432 8348 Eric return (error); 433 8348 Eric } else { 434 8348 Eric tsti = SOTOTPI(tso); 435 8348 Eric 436 8348 Eric mutex_enter(&so->so_lock); 437 8348 Eric sti->sti_tsdu_size = tsti->sti_tsdu_size; 438 8348 Eric sti->sti_etsdu_size = tsti->sti_etsdu_size; 439 8348 Eric sti->sti_addr_size = tsti->sti_addr_size; 440 8348 Eric sti->sti_opt_size = tsti->sti_opt_size; 441 8348 Eric sti->sti_tidu_size = tsti->sti_tidu_size; 442 8348 Eric sti->sti_serv_type = tsti->sti_serv_type; 443 8348 Eric so->so_mode = tso->so_mode & ~SM_ACCEPTOR_ID; 444 8348 Eric mutex_exit(&so->so_lock); 445 8348 Eric 446 8348 Eric /* the following do_tcapability may update so->so_mode */ 447 8348 Eric if ((tsti->sti_serv_type != T_CLTS) && 448 8348 Eric (sti->sti_direct == 0)) { 449 8348 Eric error = do_tcapability(so, TC1_ACCEPTOR_ID); 450 8348 Eric if (error) 451 8348 Eric return (error); 452 8348 Eric } 453 6707 brutus } 454 8348 Eric /* 455 8348 Eric * If the addr_size is 0 we treat it as already bound 456 8348 Eric * and connected. This is used by the routing socket. 457 8348 Eric * We set the addr_size to something to allocate a the address 458 8348 Eric * structures. 459 8348 Eric */ 460 8348 Eric if (sti->sti_addr_size == 0) { 461 8348 Eric so->so_state |= SS_ISBOUND | SS_ISCONNECTED; 462 8348 Eric /* Address size can vary with address families. */ 463 8348 Eric if (so->so_family == AF_INET6) 464 8348 Eric sti->sti_addr_size = 465 8348 Eric (t_scalar_t)sizeof (struct sockaddr_in6); 466 8348 Eric else 467 8348 Eric sti->sti_addr_size = 468 8348 Eric (t_scalar_t)sizeof (struct sockaddr_in); 469 8348 Eric ASSERT(sti->sti_unbind_mp); 470 8348 Eric } 471 8348 Eric 472 8348 Eric so_alloc_addr(so, sti->sti_addr_size); 473 0 stevel 474 0 stevel return (0); 475 0 stevel } 476 0 stevel 477 0 stevel static void 478 0 stevel copy_tinfo(struct sonode *so, struct T_info_ack *tia) 479 0 stevel { 480 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 481 8348 Eric 482 8348 Eric sti->sti_tsdu_size = tia->TSDU_size; 483 8348 Eric sti->sti_etsdu_size = tia->ETSDU_size; 484 8348 Eric sti->sti_addr_size = tia->ADDR_size; 485 8348 Eric sti->sti_opt_size = tia->OPT_size; 486 8348 Eric sti->sti_tidu_size = tia->TIDU_size; 487 8348 Eric sti->sti_serv_type = tia->SERV_type; 488 0 stevel switch (tia->CURRENT_state) { 489 0 stevel case TS_UNBND: 490 0 stevel break; 491 0 stevel case TS_IDLE: 492 0 stevel so->so_state |= SS_ISBOUND; 493 8348 Eric sti->sti_laddr_len = 0; 494 8348 Eric sti->sti_laddr_valid = 0; 495 0 stevel break; 496 0 stevel case TS_DATA_XFER: 497 0 stevel so->so_state |= SS_ISBOUND|SS_ISCONNECTED; 498 8348 Eric sti->sti_laddr_len = 0; 499 8348 Eric sti->sti_faddr_len = 0; 500 8348 Eric sti->sti_laddr_valid = 0; 501 8348 Eric sti->sti_faddr_valid = 0; 502 0 stevel break; 503 0 stevel } 504 0 stevel 505 0 stevel /* 506 0 stevel * Heuristics for determining the socket mode flags 507 0 stevel * (SM_ATOMIC, SM_CONNREQUIRED, SM_ADDR, SM_FDPASSING, 508 0 stevel * and SM_EXDATA, SM_OPTDATA, and SM_BYTESTREAM) 509 0 stevel * from the info ack. 510 0 stevel */ 511 8348 Eric if (sti->sti_serv_type == T_CLTS) { 512 0 stevel so->so_mode |= SM_ATOMIC | SM_ADDR; 513 0 stevel } else { 514 0 stevel so->so_mode |= SM_CONNREQUIRED; 515 8348 Eric if (sti->sti_etsdu_size != 0 && sti->sti_etsdu_size != -2) 516 0 stevel so->so_mode |= SM_EXDATA; 517 0 stevel } 518 0 stevel if (so->so_type == SOCK_SEQPACKET || so->so_type == SOCK_RAW) { 519 0 stevel /* Semantics are to discard tail end of messages */ 520 0 stevel so->so_mode |= SM_ATOMIC; 521 0 stevel } 522 0 stevel if (so->so_family == AF_UNIX) { 523 0 stevel so->so_mode |= SM_FDPASSING | SM_OPTDATA; 524 8348 Eric if (sti->sti_addr_size == -1) { 525 0 stevel /* MAXPATHLEN + soun_family + nul termination */ 526 8348 Eric sti->sti_addr_size = (t_scalar_t)(MAXPATHLEN + 527 5753 gww sizeof (short) + 1); 528 0 stevel } 529 0 stevel if (so->so_type == SOCK_STREAM) { 530 0 stevel /* 531 0 stevel * Make it into a byte-stream transport. 532 0 stevel * SOCK_SEQPACKET sockets are unchanged. 533 0 stevel */ 534 8348 Eric sti->sti_tsdu_size = 0; 535 0 stevel } 536 8348 Eric } else if (sti->sti_addr_size == -1) { 537 0 stevel /* 538 0 stevel * Logic extracted from sockmod - have to pick some max address 539 0 stevel * length in order to preallocate the addresses. 540 0 stevel */ 541 8348 Eric sti->sti_addr_size = SOA_DEFSIZE; 542 0 stevel } 543 8348 Eric if (sti->sti_tsdu_size == 0) 544 0 stevel so->so_mode |= SM_BYTESTREAM; 545 0 stevel } 546 0 stevel 547 0 stevel static int 548 0 stevel check_tinfo(struct sonode *so) 549 0 stevel { 550 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 551 8348 Eric 552 0 stevel /* Consistency checks */ 553 8348 Eric if (so->so_type == SOCK_DGRAM && sti->sti_serv_type != T_CLTS) { 554 0 stevel eprintso(so, ("service type and socket type mismatch\n")); 555 0 stevel eprintsoline(so, EPROTO); 556 0 stevel return (EPROTO); 557 0 stevel } 558 8348 Eric if (so->so_type == SOCK_STREAM && sti->sti_serv_type == T_CLTS) { 559 0 stevel eprintso(so, ("service type and socket type mismatch\n")); 560 0 stevel eprintsoline(so, EPROTO); 561 0 stevel return (EPROTO); 562 0 stevel } 563 8348 Eric if (so->so_type == SOCK_SEQPACKET && sti->sti_serv_type == T_CLTS) { 564 0 stevel eprintso(so, ("service type and socket type mismatch\n")); 565 0 stevel eprintsoline(so, EPROTO); 566 0 stevel return (EPROTO); 567 0 stevel } 568 0 stevel if (so->so_family == AF_INET && 569 8348 Eric sti->sti_addr_size != (t_scalar_t)sizeof (struct sockaddr_in)) { 570 0 stevel eprintso(so, 571 0 stevel ("AF_INET must have sockaddr_in address length. Got %d\n", 572 8348 Eric sti->sti_addr_size)); 573 0 stevel eprintsoline(so, EMSGSIZE); 574 0 stevel return (EMSGSIZE); 575 0 stevel } 576 0 stevel if (so->so_family == AF_INET6 && 577 8348 Eric sti->sti_addr_size != (t_scalar_t)sizeof (struct sockaddr_in6)) { 578 0 stevel eprintso(so, 579 0 stevel ("AF_INET6 must have sockaddr_in6 address length. Got %d\n", 580 8348 Eric sti->sti_addr_size)); 581 0 stevel eprintsoline(so, EMSGSIZE); 582 0 stevel return (EMSGSIZE); 583 0 stevel } 584 0 stevel 585 0 stevel dprintso(so, 1, ( 586 0 stevel "tinfo: serv %d tsdu %d, etsdu %d, addr %d, opt %d, tidu %d\n", 587 8348 Eric sti->sti_serv_type, sti->sti_tsdu_size, sti->sti_etsdu_size, 588 8348 Eric sti->sti_addr_size, sti->sti_opt_size, 589 8348 Eric sti->sti_tidu_size)); 590 0 stevel dprintso(so, 1, ("tinfo: so_state %s\n", 591 5753 gww pr_state(so->so_state, so->so_mode))); 592 0 stevel return (0); 593 0 stevel } 594 0 stevel 595 0 stevel /* 596 0 stevel * Send down T_info_req and wait for the ack. 597 0 stevel * Record interesting T_info_ack values in the sonode. 598 0 stevel */ 599 0 stevel static int 600 0 stevel do_tinfo(struct sonode *so) 601 0 stevel { 602 0 stevel struct T_info_req tir; 603 0 stevel mblk_t *mp; 604 0 stevel int error; 605 0 stevel 606 0 stevel ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 607 0 stevel 608 0 stevel if (so_no_tinfo) { 609 8348 Eric SOTOTPI(so)->sti_addr_size = 0; 610 0 stevel return (0); 611 0 stevel } 612 0 stevel 613 7240 rh87107 dprintso(so, 1, ("do_tinfo(%p)\n", (void *)so)); 614 0 stevel 615 0 stevel /* Send T_INFO_REQ */ 616 0 stevel tir.PRIM_type = T_INFO_REQ; 617 0 stevel mp = soallocproto1(&tir, sizeof (tir), 618 0 stevel sizeof (struct T_info_req) + sizeof (struct T_info_ack), 619 8778 Erik _ALLOC_INTR, CRED()); 620 0 stevel if (mp == NULL) { 621 0 stevel eprintsoline(so, ENOBUFS); 622 0 stevel return (ENOBUFS); 623 0 stevel } 624 0 stevel /* T_INFO_REQ has to be M_PCPROTO */ 625 0 stevel DB_TYPE(mp) = M_PCPROTO; 626 0 stevel 627 0 stevel error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, 628 5753 gww MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0); 629 0 stevel if (error) { 630 0 stevel eprintsoline(so, error); 631 0 stevel return (error); 632 0 stevel } 633 0 stevel mutex_enter(&so->so_lock); 634 0 stevel /* Wait for T_INFO_ACK */ 635 0 stevel if ((error = sowaitprim(so, T_INFO_REQ, T_INFO_ACK, 636 0 stevel (t_uscalar_t)sizeof (struct T_info_ack), &mp, 0))) { 637 0 stevel mutex_exit(&so->so_lock); 638 0 stevel eprintsoline(so, error); 639 0 stevel return (error); 640 0 stevel } 641 0 stevel 642 0 stevel ASSERT(mp); 643 0 stevel copy_tinfo(so, (struct T_info_ack *)mp->b_rptr); 644 0 stevel mutex_exit(&so->so_lock); 645 0 stevel freemsg(mp); 646 0 stevel return (check_tinfo(so)); 647 0 stevel } 648 0 stevel 649 0 stevel /* 650 0 stevel * Send down T_capability_req and wait for the ack. 651 0 stevel * Record interesting T_capability_ack values in the sonode. 652 0 stevel */ 653 0 stevel static int 654 0 stevel do_tcapability(struct sonode *so, t_uscalar_t cap_bits1) 655 0 stevel { 656 0 stevel struct T_capability_req tcr; 657 0 stevel struct T_capability_ack *tca; 658 0 stevel mblk_t *mp; 659 0 stevel int error; 660 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 661 0 stevel 662 0 stevel ASSERT(cap_bits1 != 0); 663 0 stevel ASSERT((cap_bits1 & ~(TC1_ACCEPTOR_ID | TC1_INFO)) == 0); 664 0 stevel ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 665 0 stevel 666 8348 Eric if (sti->sti_provinfo->tpi_capability == PI_NO) 667 0 stevel return (do_tinfo(so)); 668 0 stevel 669 0 stevel if (so_no_tinfo) { 670 8348 Eric sti->sti_addr_size = 0; 671 0 stevel if ((cap_bits1 &= ~TC1_INFO) == 0) 672 0 stevel return (0); 673 0 stevel } 674 0 stevel 675 7240 rh87107 dprintso(so, 1, ("do_tcapability(%p)\n", (void *)so)); 676 0 stevel 677 0 stevel /* Send T_CAPABILITY_REQ */ 678 0 stevel tcr.PRIM_type = T_CAPABILITY_REQ; 679 0 stevel tcr.CAP_bits1 = cap_bits1; 680 0 stevel mp = soallocproto1(&tcr, sizeof (tcr), 681 0 stevel sizeof (struct T_capability_req) + sizeof (struct T_capability_ack), 682 8778 Erik _ALLOC_INTR, CRED()); 683 0 stevel if (mp == NULL) { 684 0 stevel eprintsoline(so, ENOBUFS); 685 0 stevel return (ENOBUFS); 686 0 stevel } 687 0 stevel /* T_CAPABILITY_REQ should be M_PCPROTO here */ 688 0 stevel DB_TYPE(mp) = M_PCPROTO; 689 0 stevel 690 0 stevel error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, 691 0 stevel MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0); 692 0 stevel if (error) { 693 0 stevel eprintsoline(so, error); 694 0 stevel return (error); 695 0 stevel } 696 0 stevel mutex_enter(&so->so_lock); 697 0 stevel /* Wait for T_CAPABILITY_ACK */ 698 0 stevel if ((error = sowaitprim(so, T_CAPABILITY_REQ, T_CAPABILITY_ACK, 699 0 stevel (t_uscalar_t)sizeof (*tca), &mp, sock_capability_timeout * hz))) { 700 0 stevel mutex_exit(&so->so_lock); 701 8348 Eric PI_PROVLOCK(sti->sti_provinfo); 702 8348 Eric if (sti->sti_provinfo->tpi_capability == PI_DONTKNOW) 703 8348 Eric sti->sti_provinfo->tpi_capability = PI_NO; 704 8348 Eric PI_PROVUNLOCK(sti->sti_provinfo); 705 0 stevel ASSERT((so->so_mode & SM_ACCEPTOR_ID) == 0); 706 0 stevel if (cap_bits1 & TC1_INFO) { 707 0 stevel /* 708 0 stevel * If the T_CAPABILITY_REQ timed out and then a 709 0 stevel * T_INFO_REQ gets a protocol error, most likely 710 0 stevel * the capability was slow (vs. unsupported). Return 711 0 stevel * ENOSR for this case as a best guess. 712 0 stevel */ 713 0 stevel if (error == ETIME) { 714 0 stevel return ((error = do_tinfo(so)) == EPROTO ? 715 0 stevel ENOSR : error); 716 0 stevel } 717 0 stevel return (do_tinfo(so)); 718 0 stevel } 719 0 stevel return (0); 720 0 stevel } 721 0 stevel 722 0 stevel ASSERT(mp); 723 0 stevel tca = (struct T_capability_ack *)mp->b_rptr; 724 0 stevel 725 0 stevel ASSERT((cap_bits1 & TC1_INFO) == (tca->CAP_bits1 & TC1_INFO)); 726 8348 Eric so_proc_tcapability_ack(so, tca); 727 0 stevel 728 0 stevel cap_bits1 = tca->CAP_bits1; 729 0 stevel 730 0 stevel mutex_exit(&so->so_lock); 731 0 stevel freemsg(mp); 732 0 stevel 733 0 stevel if (cap_bits1 & TC1_INFO) 734 0 stevel return (check_tinfo(so)); 735 0 stevel 736 0 stevel return (0); 737 0 stevel } 738 0 stevel 739 0 stevel /* 740 8348 Eric * Process a T_CAPABILITY_ACK 741 8348 Eric */ 742 8348 Eric void 743 8348 Eric so_proc_tcapability_ack(struct sonode *so, struct T_capability_ack *tca) 744 8348 Eric { 745 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 746 8348 Eric 747 8348 Eric if (sti->sti_provinfo->tpi_capability == PI_DONTKNOW) { 748 8348 Eric PI_PROVLOCK(sti->sti_provinfo); 749 8348 Eric sti->sti_provinfo->tpi_capability = PI_YES; 750 8348 Eric PI_PROVUNLOCK(sti->sti_provinfo); 751 8348 Eric } 752 8348 Eric 753 8348 Eric if (tca->CAP_bits1 & TC1_ACCEPTOR_ID) { 754 8348 Eric sti->sti_acceptor_id = tca->ACCEPTOR_id; 755 8348 Eric so->so_mode |= SM_ACCEPTOR_ID; 756 8348 Eric } 757 8348 Eric 758 8348 Eric if (tca->CAP_bits1 & TC1_INFO) 759 8348 Eric copy_tinfo(so, &tca->INFO_ack); 760 8348 Eric } 761 8348 Eric 762 8348 Eric /* 763 8348 Eric * Retrieve socket error, clear error if not peek. 764 0 stevel */ 765 0 stevel int 766 8348 Eric sogeterr(struct sonode *so, boolean_t clear_err) 767 0 stevel { 768 0 stevel int error; 769 0 stevel 770 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 771 0 stevel 772 0 stevel error = so->so_error; 773 8348 Eric if (clear_err) 774 8348 Eric so->so_error = 0; 775 0 stevel 776 0 stevel return (error); 777 0 stevel } 778 0 stevel 779 0 stevel /* 780 0 stevel * This routine is registered with the stream head to retrieve read 781 0 stevel * side errors. 782 0 stevel * It does not clear the socket error for a peeking read side operation. 783 0 stevel * It the error is to be cleared it sets *clearerr. 784 0 stevel */ 785 0 stevel int 786 0 stevel sogetrderr(vnode_t *vp, int ispeek, int *clearerr) 787 0 stevel { 788 0 stevel struct sonode *so = VTOSO(vp); 789 0 stevel int error; 790 0 stevel 791 0 stevel mutex_enter(&so->so_lock); 792 0 stevel if (ispeek) { 793 0 stevel error = so->so_error; 794 0 stevel *clearerr = 0; 795 0 stevel } else { 796 0 stevel error = so->so_error; 797 0 stevel so->so_error = 0; 798 0 stevel *clearerr = 1; 799 0 stevel } 800 0 stevel mutex_exit(&so->so_lock); 801 0 stevel return (error); 802 0 stevel } 803 0 stevel 804 0 stevel /* 805 0 stevel * This routine is registered with the stream head to retrieve write 806 0 stevel * side errors. 807 0 stevel * It does not clear the socket error for a peeking read side operation. 808 0 stevel * It the error is to be cleared it sets *clearerr. 809 0 stevel */ 810 0 stevel int 811 0 stevel sogetwrerr(vnode_t *vp, int ispeek, int *clearerr) 812 0 stevel { 813 0 stevel struct sonode *so = VTOSO(vp); 814 0 stevel int error; 815 0 stevel 816 0 stevel mutex_enter(&so->so_lock); 817 0 stevel if (so->so_state & SS_CANTSENDMORE) { 818 0 stevel error = EPIPE; 819 0 stevel *clearerr = 0; 820 0 stevel } else { 821 0 stevel error = so->so_error; 822 0 stevel if (ispeek) { 823 0 stevel *clearerr = 0; 824 0 stevel } else { 825 0 stevel so->so_error = 0; 826 0 stevel *clearerr = 1; 827 0 stevel } 828 0 stevel } 829 0 stevel mutex_exit(&so->so_lock); 830 0 stevel return (error); 831 0 stevel } 832 0 stevel 833 0 stevel /* 834 0 stevel * Set a nonpersistent read and write error on the socket. 835 0 stevel * Used when there is a T_uderror_ind for a connected socket. 836 0 stevel * The caller also needs to call strsetrerror and strsetwerror 837 0 stevel * after dropping the lock. 838 0 stevel */ 839 0 stevel void 840 0 stevel soseterror(struct sonode *so, int error) 841 0 stevel { 842 0 stevel ASSERT(error != 0); 843 0 stevel 844 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 845 0 stevel so->so_error = (ushort_t)error; 846 0 stevel } 847 0 stevel 848 0 stevel void 849 0 stevel soisconnecting(struct sonode *so) 850 0 stevel { 851 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 852 0 stevel so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); 853 0 stevel so->so_state |= SS_ISCONNECTING; 854 0 stevel cv_broadcast(&so->so_state_cv); 855 0 stevel } 856 0 stevel 857 0 stevel void 858 0 stevel soisconnected(struct sonode *so) 859 0 stevel { 860 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 861 0 stevel so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); 862 0 stevel so->so_state |= SS_ISCONNECTED; 863 0 stevel cv_broadcast(&so->so_state_cv); 864 0 stevel } 865 0 stevel 866 0 stevel /* 867 0 stevel * The caller also needs to call strsetrerror, strsetwerror and strseteof. 868 0 stevel */ 869 0 stevel void 870 0 stevel soisdisconnected(struct sonode *so, int error) 871 0 stevel { 872 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 873 8348 Eric so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 874 0 stevel so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE); 875 0 stevel so->so_error = (ushort_t)error; 876 0 stevel if (so->so_peercred != NULL) { 877 0 stevel crfree(so->so_peercred); 878 0 stevel so->so_peercred = NULL; 879 0 stevel } 880 0 stevel cv_broadcast(&so->so_state_cv); 881 0 stevel } 882 0 stevel 883 0 stevel /* 884 0 stevel * For connected AF_UNIX SOCK_DGRAM sockets when the peer closes. 885 0 stevel * Does not affect write side. 886 0 stevel * The caller also has to call strsetrerror. 887 0 stevel */ 888 0 stevel static void 889 0 stevel sobreakconn(struct sonode *so, int error) 890 0 stevel { 891 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 892 0 stevel so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); 893 0 stevel so->so_error = (ushort_t)error; 894 0 stevel cv_broadcast(&so->so_state_cv); 895 0 stevel } 896 0 stevel 897 0 stevel /* 898 0 stevel * Can no longer send. 899 0 stevel * Caller must also call strsetwerror. 900 0 stevel * 901 0 stevel * We mark the peer address as no longer valid for getpeername, but 902 0 stevel * leave it around for so_unix_close to notify the peer (that 903 0 stevel * transport has no addressing held at that layer). 904 0 stevel */ 905 0 stevel void 906 0 stevel socantsendmore(struct sonode *so) 907 0 stevel { 908 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 909 8348 Eric so->so_state |= SS_CANTSENDMORE; 910 0 stevel cv_broadcast(&so->so_state_cv); 911 0 stevel } 912 0 stevel 913 0 stevel /* 914 0 stevel * The caller must call strseteof(,1) as well as this routine 915 0 stevel * to change the socket state. 916 0 stevel */ 917 0 stevel void 918 0 stevel socantrcvmore(struct sonode *so) 919 0 stevel { 920 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 921 0 stevel so->so_state |= SS_CANTRCVMORE; 922 0 stevel cv_broadcast(&so->so_state_cv); 923 0 stevel } 924 0 stevel 925 0 stevel /* 926 0 stevel * The caller has sent down a "request_prim" primitive and wants to wait for 927 0 stevel * an ack ("ack_prim") or an T_ERROR_ACK for it. 928 0 stevel * The specified "ack_prim" can be a T_OK_ACK. 929 0 stevel * 930 0 stevel * Assumes that all the TPI acks are M_PCPROTO messages. 931 0 stevel * 932 0 stevel * Note that the socket is single-threaded (using so_lock_single) 933 0 stevel * for all operations that generate TPI ack messages. Since 934 0 stevel * only TPI ack messages are M_PCPROTO we should never receive 935 0 stevel * anything except either the ack we are expecting or a T_ERROR_ACK 936 0 stevel * for the same primitive. 937 0 stevel */ 938 0 stevel int 939 0 stevel sowaitprim(struct sonode *so, t_scalar_t request_prim, t_scalar_t ack_prim, 940 0 stevel t_uscalar_t min_size, mblk_t **mpp, clock_t wait) 941 0 stevel { 942 0 stevel mblk_t *mp; 943 0 stevel union T_primitives *tpr; 944 0 stevel int error; 945 0 stevel 946 0 stevel dprintso(so, 1, ("sowaitprim(%p, %d, %d, %d, %p, %lu)\n", 947 7240 rh87107 (void *)so, request_prim, ack_prim, min_size, (void *)mpp, wait)); 948 0 stevel 949 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 950 0 stevel 951 0 stevel error = sowaitack(so, &mp, wait); 952 0 stevel if (error) 953 0 stevel return (error); 954 0 stevel 955 7240 rh87107 dprintso(so, 1, ("got msg %p\n", (void *)mp)); 956 0 stevel if (DB_TYPE(mp) != M_PCPROTO || 957 0 stevel MBLKL(mp) < sizeof (tpr->type)) { 958 0 stevel freemsg(mp); 959 0 stevel eprintsoline(so, EPROTO); 960 0 stevel return (EPROTO); 961 0 stevel } 962 0 stevel tpr = (union T_primitives *)mp->b_rptr; 963 0 stevel /* 964 0 stevel * Did we get the primitive that we were asking for? 965 0 stevel * For T_OK_ACK we also check that it matches the request primitive. 966 0 stevel */ 967 0 stevel if (tpr->type == ack_prim && 968 0 stevel (ack_prim != T_OK_ACK || 969 0 stevel tpr->ok_ack.CORRECT_prim == request_prim)) { 970 0 stevel if (MBLKL(mp) >= (ssize_t)min_size) { 971 0 stevel /* Found what we are looking for */ 972 0 stevel *mpp = mp; 973 0 stevel return (0); 974 0 stevel } 975 0 stevel /* Too short */ 976 0 stevel freemsg(mp); 977 0 stevel eprintsoline(so, EPROTO); 978 0 stevel return (EPROTO); 979 0 stevel } 980 0 stevel 981 0 stevel if (tpr->type == T_ERROR_ACK && 982 0 stevel tpr->error_ack.ERROR_prim == request_prim) { 983 0 stevel /* Error to the primitive we were looking for */ 984 0 stevel if (tpr->error_ack.TLI_error == TSYSERR) { 985 0 stevel error = tpr->error_ack.UNIX_error; 986 0 stevel } else { 987 8348 Eric error = proto_tlitosyserr(tpr->error_ack.TLI_error); 988 0 stevel } 989 0 stevel dprintso(so, 0, ("error_ack for %d: %d/%d ->%d\n", 990 8348 Eric tpr->error_ack.ERROR_prim, tpr->error_ack.TLI_error, 991 8348 Eric tpr->error_ack.UNIX_error, error)); 992 0 stevel freemsg(mp); 993 0 stevel return (error); 994 0 stevel } 995 0 stevel /* 996 0 stevel * Wrong primitive or T_ERROR_ACK for the wrong primitive 997 0 stevel */ 998 0 stevel #ifdef DEBUG 999 0 stevel if (tpr->type == T_ERROR_ACK) { 1000 0 stevel dprintso(so, 0, ("error_ack for %d: %d/%d\n", 1001 8348 Eric tpr->error_ack.ERROR_prim, tpr->error_ack.TLI_error, 1002 5753 gww tpr->error_ack.UNIX_error)); 1003 0 stevel } else if (tpr->type == T_OK_ACK) { 1004 0 stevel dprintso(so, 0, ("ok_ack for %d, expected %d for %d\n", 1005 8348 Eric tpr->ok_ack.CORRECT_prim, ack_prim, request_prim)); 1006 0 stevel } else { 1007 0 stevel dprintso(so, 0, 1008 5753 gww ("unexpected primitive %d, expected %d for %d\n", 1009 5753 gww tpr->type, ack_prim, request_prim)); 1010 0 stevel } 1011 0 stevel #endif /* DEBUG */ 1012 0 stevel 1013 0 stevel freemsg(mp); 1014 0 stevel eprintsoline(so, EPROTO); 1015 0 stevel return (EPROTO); 1016 0 stevel } 1017 0 stevel 1018 0 stevel /* 1019 0 stevel * Wait for a T_OK_ACK for the specified primitive. 1020 0 stevel */ 1021 0 stevel int 1022 0 stevel sowaitokack(struct sonode *so, t_scalar_t request_prim) 1023 0 stevel { 1024 0 stevel mblk_t *mp; 1025 0 stevel int error; 1026 0 stevel 1027 0 stevel error = sowaitprim(so, request_prim, T_OK_ACK, 1028 0 stevel (t_uscalar_t)sizeof (struct T_ok_ack), &mp, 0); 1029 0 stevel if (error) 1030 0 stevel return (error); 1031 0 stevel freemsg(mp); 1032 0 stevel return (0); 1033 0 stevel } 1034 0 stevel 1035 0 stevel /* 1036 8348 Eric * Queue a received TPI ack message on sti_ack_mp. 1037 0 stevel */ 1038 0 stevel void 1039 0 stevel soqueueack(struct sonode *so, mblk_t *mp) 1040 0 stevel { 1041 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1042 8348 Eric 1043 0 stevel if (DB_TYPE(mp) != M_PCPROTO) { 1044 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1045 0 stevel "sockfs: received unexpected M_PROTO TPI ack. Prim %d\n", 1046 0 stevel *(t_scalar_t *)mp->b_rptr); 1047 0 stevel freemsg(mp); 1048 0 stevel return; 1049 0 stevel } 1050 0 stevel 1051 0 stevel mutex_enter(&so->so_lock); 1052 8348 Eric if (sti->sti_ack_mp != NULL) { 1053 8348 Eric dprintso(so, 1, ("sti_ack_mp already set\n")); 1054 8348 Eric freemsg(sti->sti_ack_mp); 1055 8348 Eric sti->sti_ack_mp = NULL; 1056 0 stevel } 1057 8348 Eric sti->sti_ack_mp = mp; 1058 8348 Eric cv_broadcast(&sti->sti_ack_cv); 1059 0 stevel mutex_exit(&so->so_lock); 1060 0 stevel } 1061 0 stevel 1062 0 stevel /* 1063 0 stevel * Wait for a TPI ack ignoring signals and errors. 1064 0 stevel */ 1065 0 stevel int 1066 0 stevel sowaitack(struct sonode *so, mblk_t **mpp, clock_t wait) 1067 0 stevel { 1068 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1069 8348 Eric 1070 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1071 0 stevel 1072 8348 Eric while (sti->sti_ack_mp == NULL) { 1073 0 stevel #ifdef SOCK_TEST 1074 0 stevel if (wait == 0 && sock_test_timelimit != 0) 1075 0 stevel wait = sock_test_timelimit; 1076 0 stevel #endif 1077 0 stevel if (wait != 0) { 1078 0 stevel /* 1079 0 stevel * Only wait for the time limit. 1080 0 stevel */ 1081 11066 rafael if (cv_reltimedwait(&sti->sti_ack_cv, &so->so_lock, 1082 11066 rafael wait, TR_CLOCK_TICK) == -1) { 1083 0 stevel eprintsoline(so, ETIME); 1084 0 stevel return (ETIME); 1085 0 stevel } 1086 0 stevel } 1087 0 stevel else 1088 8348 Eric cv_wait(&sti->sti_ack_cv, &so->so_lock); 1089 0 stevel } 1090 8348 Eric *mpp = sti->sti_ack_mp; 1091 0 stevel #ifdef DEBUG 1092 0 stevel { 1093 0 stevel union T_primitives *tpr; 1094 0 stevel mblk_t *mp = *mpp; 1095 0 stevel 1096 0 stevel tpr = (union T_primitives *)mp->b_rptr; 1097 0 stevel ASSERT(DB_TYPE(mp) == M_PCPROTO); 1098 0 stevel ASSERT(tpr->type == T_OK_ACK || 1099 5753 gww tpr->type == T_ERROR_ACK || 1100 5753 gww tpr->type == T_BIND_ACK || 1101 5753 gww tpr->type == T_CAPABILITY_ACK || 1102 5753 gww tpr->type == T_INFO_ACK || 1103 5753 gww tpr->type == T_OPTMGMT_ACK); 1104 0 stevel } 1105 0 stevel #endif /* DEBUG */ 1106 8348 Eric sti->sti_ack_mp = NULL; 1107 0 stevel return (0); 1108 0 stevel } 1109 0 stevel 1110 0 stevel /* 1111 8348 Eric * Queue a received T_CONN_IND message on sti_conn_ind_head/tail. 1112 0 stevel */ 1113 0 stevel void 1114 0 stevel soqueueconnind(struct sonode *so, mblk_t *mp) 1115 0 stevel { 1116 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1117 8348 Eric 1118 0 stevel if (DB_TYPE(mp) != M_PROTO) { 1119 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1120 0 stevel "sockfs: received unexpected M_PCPROTO T_CONN_IND\n"); 1121 0 stevel freemsg(mp); 1122 0 stevel return; 1123 0 stevel } 1124 0 stevel 1125 0 stevel mutex_enter(&so->so_lock); 1126 0 stevel ASSERT(mp->b_next == NULL); 1127 8348 Eric if (sti->sti_conn_ind_head == NULL) { 1128 8348 Eric sti->sti_conn_ind_head = mp; 1129 0 stevel } else { 1130 8348 Eric ASSERT(sti->sti_conn_ind_tail->b_next == NULL); 1131 8348 Eric sti->sti_conn_ind_tail->b_next = mp; 1132 0 stevel } 1133 8348 Eric sti->sti_conn_ind_tail = mp; 1134 0 stevel /* Wakeup a single consumer of the T_CONN_IND */ 1135 8348 Eric cv_signal(&so->so_acceptq_cv); 1136 0 stevel mutex_exit(&so->so_lock); 1137 0 stevel } 1138 0 stevel 1139 0 stevel /* 1140 0 stevel * Wait for a T_CONN_IND. 1141 0 stevel * Don't wait if nonblocking. 1142 0 stevel * Accept signals and socket errors. 1143 0 stevel */ 1144 0 stevel int 1145 0 stevel sowaitconnind(struct sonode *so, int fmode, mblk_t **mpp) 1146 0 stevel { 1147 0 stevel mblk_t *mp; 1148 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1149 0 stevel int error = 0; 1150 0 stevel 1151 0 stevel ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1152 0 stevel mutex_enter(&so->so_lock); 1153 0 stevel check_error: 1154 0 stevel if (so->so_error) { 1155 8348 Eric error = sogeterr(so, B_TRUE); 1156 0 stevel if (error) { 1157 0 stevel mutex_exit(&so->so_lock); 1158 0 stevel return (error); 1159 0 stevel } 1160 0 stevel } 1161 0 stevel 1162 8348 Eric if (sti->sti_conn_ind_head == NULL) { 1163 0 stevel if (fmode & (FNDELAY|FNONBLOCK)) { 1164 0 stevel error = EWOULDBLOCK; 1165 0 stevel goto done; 1166 0 stevel } 1167 8348 Eric 1168 8348 Eric if (so->so_state & SS_CLOSING) { 1169 8348 Eric error = EINTR; 1170 8348 Eric goto done; 1171 8348 Eric } 1172 8348 Eric 1173 8348 Eric if (!cv_wait_sig_swap(&so->so_acceptq_cv, &so->so_lock)) { 1174 0 stevel error = EINTR; 1175 0 stevel goto done; 1176 0 stevel } 1177 0 stevel goto check_error; 1178 0 stevel } 1179 8348 Eric mp = sti->sti_conn_ind_head; 1180 8348 Eric sti->sti_conn_ind_head = mp->b_next; 1181 0 stevel mp->b_next = NULL; 1182 8348 Eric if (sti->sti_conn_ind_head == NULL) { 1183 8348 Eric ASSERT(sti->sti_conn_ind_tail == mp); 1184 8348 Eric sti->sti_conn_ind_tail = NULL; 1185 0 stevel } 1186 0 stevel *mpp = mp; 1187 0 stevel done: 1188 0 stevel mutex_exit(&so->so_lock); 1189 0 stevel return (error); 1190 0 stevel } 1191 0 stevel 1192 0 stevel /* 1193 0 stevel * Flush a T_CONN_IND matching the sequence number from the list. 1194 0 stevel * Return zero if found; non-zero otherwise. 1195 0 stevel * This is called very infrequently thus it is ok to do a linear search. 1196 0 stevel */ 1197 0 stevel int 1198 0 stevel soflushconnind(struct sonode *so, t_scalar_t seqno) 1199 0 stevel { 1200 0 stevel mblk_t *prevmp, *mp; 1201 0 stevel struct T_conn_ind *tci; 1202 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1203 0 stevel 1204 0 stevel mutex_enter(&so->so_lock); 1205 8348 Eric for (prevmp = NULL, mp = sti->sti_conn_ind_head; mp != NULL; 1206 0 stevel prevmp = mp, mp = mp->b_next) { 1207 0 stevel tci = (struct T_conn_ind *)mp->b_rptr; 1208 0 stevel if (tci->SEQ_number == seqno) { 1209 0 stevel dprintso(so, 1, 1210 5753 gww ("t_discon_ind: found T_CONN_IND %d\n", seqno)); 1211 0 stevel /* Deleting last? */ 1212 8348 Eric if (sti->sti_conn_ind_tail == mp) { 1213 8348 Eric sti->sti_conn_ind_tail = prevmp; 1214 0 stevel } 1215 0 stevel if (prevmp == NULL) { 1216 0 stevel /* Deleting first */ 1217 8348 Eric sti->sti_conn_ind_head = mp->b_next; 1218 0 stevel } else { 1219 0 stevel prevmp->b_next = mp->b_next; 1220 0 stevel } 1221 0 stevel mp->b_next = NULL; 1222 8348 Eric 1223 8348 Eric ASSERT((sti->sti_conn_ind_head == NULL && 1224 8348 Eric sti->sti_conn_ind_tail == NULL) || 1225 8348 Eric (sti->sti_conn_ind_head != NULL && 1226 8348 Eric sti->sti_conn_ind_tail != NULL)); 1227 8348 Eric 1228 0 stevel so->so_error = ECONNABORTED; 1229 0 stevel mutex_exit(&so->so_lock); 1230 898 kais 1231 898 kais /* 1232 898 kais * T_KSSL_PROXY_CONN_IND may carry a handle for 1233 898 kais * an SSL context, and needs to be released. 1234 898 kais */ 1235 898 kais if ((tci->PRIM_type == T_SSL_PROXY_CONN_IND) && 1236 898 kais (mp->b_cont != NULL)) { 1237 898 kais kssl_ctx_t kssl_ctx; 1238 898 kais 1239 898 kais ASSERT(MBLKL(mp->b_cont) == 1240 898 kais sizeof (kssl_ctx_t)); 1241 898 kais kssl_ctx = *((kssl_ctx_t *)mp->b_cont->b_rptr); 1242 898 kais kssl_release_ctx(kssl_ctx); 1243 898 kais } 1244 0 stevel freemsg(mp); 1245 0 stevel return (0); 1246 0 stevel } 1247 0 stevel } 1248 0 stevel mutex_exit(&so->so_lock); 1249 0 stevel dprintso(so, 1, ("t_discon_ind: NOT found T_CONN_IND %d\n", seqno)); 1250 0 stevel return (-1); 1251 0 stevel } 1252 0 stevel 1253 0 stevel /* 1254 0 stevel * Wait until the socket is connected or there is an error. 1255 0 stevel * fmode should contain any nonblocking flags. nosig should be 1256 0 stevel * set if the caller does not want the wait to be interrupted by a signal. 1257 0 stevel */ 1258 0 stevel int 1259 0 stevel sowaitconnected(struct sonode *so, int fmode, int nosig) 1260 0 stevel { 1261 0 stevel int error; 1262 0 stevel 1263 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1264 0 stevel 1265 0 stevel while ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 1266 5753 gww SS_ISCONNECTING && so->so_error == 0) { 1267 0 stevel 1268 7240 rh87107 dprintso(so, 1, ("waiting for SS_ISCONNECTED on %p\n", 1269 7240 rh87107 (void *)so)); 1270 0 stevel if (fmode & (FNDELAY|FNONBLOCK)) 1271 0 stevel return (EINPROGRESS); 1272 0 stevel 1273 8348 Eric if (so->so_state & SS_CLOSING) 1274 8348 Eric return (EINTR); 1275 8348 Eric 1276 0 stevel if (nosig) 1277 0 stevel cv_wait(&so->so_state_cv, &so->so_lock); 1278 0 stevel else if (!cv_wait_sig_swap(&so->so_state_cv, &so->so_lock)) { 1279 0 stevel /* 1280 0 stevel * Return EINTR and let the application use 1281 0 stevel * nonblocking techniques for detecting when 1282 0 stevel * the connection has been established. 1283 0 stevel */ 1284 0 stevel return (EINTR); 1285 0 stevel } 1286 7240 rh87107 dprintso(so, 1, ("awoken on %p\n", (void *)so)); 1287 0 stevel } 1288 0 stevel 1289 0 stevel if (so->so_error != 0) { 1290 8348 Eric error = sogeterr(so, B_TRUE); 1291 0 stevel ASSERT(error != 0); 1292 0 stevel dprintso(so, 1, ("sowaitconnected: error %d\n", error)); 1293 0 stevel return (error); 1294 0 stevel } 1295 0 stevel if (!(so->so_state & SS_ISCONNECTED)) { 1296 0 stevel /* 1297 0 stevel * Could have received a T_ORDREL_IND or a T_DISCON_IND with 1298 0 stevel * zero errno. Or another thread could have consumed so_error 1299 0 stevel * e.g. by calling read. 1300 0 stevel */ 1301 0 stevel error = ECONNREFUSED; 1302 0 stevel dprintso(so, 1, ("sowaitconnected: error %d\n", error)); 1303 0 stevel return (error); 1304 0 stevel } 1305 0 stevel return (0); 1306 0 stevel } 1307 0 stevel 1308 0 stevel 1309 0 stevel /* 1310 0 stevel * Handle the signal generation aspect of urgent data. 1311 0 stevel */ 1312 0 stevel static void 1313 0 stevel so_oob_sig(struct sonode *so, int extrasig, 1314 0 stevel strsigset_t *signals, strpollset_t *pollwakeups) 1315 0 stevel { 1316 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1317 8348 Eric 1318 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1319 0 stevel 1320 0 stevel ASSERT(so_verify_oobstate(so)); 1321 8348 Eric ASSERT(sti->sti_oobsigcnt >= sti->sti_oobcnt); 1322 8348 Eric if (sti->sti_oobsigcnt > sti->sti_oobcnt) { 1323 0 stevel /* 1324 0 stevel * Signal has already been generated once for this 1325 0 stevel * urgent "event". However, since TCP can receive updated 1326 0 stevel * urgent pointers we still generate a signal. 1327 0 stevel */ 1328 0 stevel ASSERT(so->so_state & SS_OOBPEND); 1329 0 stevel if (extrasig) { 1330 0 stevel *signals |= S_RDBAND; 1331 0 stevel *pollwakeups |= POLLRDBAND; 1332 0 stevel } 1333 0 stevel return; 1334 0 stevel } 1335 0 stevel 1336 8348 Eric sti->sti_oobsigcnt++; 1337 8348 Eric ASSERT(sti->sti_oobsigcnt > 0); /* Wraparound */ 1338 8348 Eric ASSERT(sti->sti_oobsigcnt > sti->sti_oobcnt); 1339 0 stevel 1340 0 stevel /* 1341 0 stevel * Record (for select/poll) that urgent data is pending. 1342 0 stevel */ 1343 0 stevel so->so_state |= SS_OOBPEND; 1344 0 stevel /* 1345 0 stevel * New urgent data on the way so forget about any old 1346 0 stevel * urgent data. 1347 0 stevel */ 1348 0 stevel so->so_state &= ~(SS_HAVEOOBDATA|SS_HADOOBDATA); 1349 0 stevel if (so->so_oobmsg != NULL) { 1350 0 stevel dprintso(so, 1, ("sock: discarding old oob\n")); 1351 0 stevel freemsg(so->so_oobmsg); 1352 0 stevel so->so_oobmsg = NULL; 1353 0 stevel } 1354 0 stevel *signals |= S_RDBAND; 1355 0 stevel *pollwakeups |= POLLRDBAND; 1356 0 stevel ASSERT(so_verify_oobstate(so)); 1357 0 stevel } 1358 0 stevel 1359 0 stevel /* 1360 0 stevel * Handle the processing of the T_EXDATA_IND with urgent data. 1361 0 stevel * Returns the T_EXDATA_IND if it should be queued on the read queue. 1362 0 stevel */ 1363 0 stevel /* ARGSUSED2 */ 1364 0 stevel static mblk_t * 1365 0 stevel so_oob_exdata(struct sonode *so, mblk_t *mp, 1366 0 stevel strsigset_t *signals, strpollset_t *pollwakeups) 1367 0 stevel { 1368 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1369 8348 Eric 1370 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1371 0 stevel 1372 0 stevel ASSERT(so_verify_oobstate(so)); 1373 0 stevel 1374 8348 Eric ASSERT(sti->sti_oobsigcnt > sti->sti_oobcnt); 1375 0 stevel 1376 8348 Eric sti->sti_oobcnt++; 1377 8348 Eric ASSERT(sti->sti_oobcnt > 0); /* wraparound? */ 1378 8348 Eric ASSERT(sti->sti_oobsigcnt >= sti->sti_oobcnt); 1379 0 stevel 1380 0 stevel /* 1381 0 stevel * Set MSGMARK for SIOCATMARK. 1382 0 stevel */ 1383 0 stevel mp->b_flag |= MSGMARK; 1384 0 stevel 1385 0 stevel ASSERT(so_verify_oobstate(so)); 1386 0 stevel return (mp); 1387 0 stevel } 1388 0 stevel 1389 0 stevel /* 1390 0 stevel * Handle the processing of the actual urgent data. 1391 0 stevel * Returns the data mblk if it should be queued on the read queue. 1392 0 stevel */ 1393 0 stevel static mblk_t * 1394 0 stevel so_oob_data(struct sonode *so, mblk_t *mp, 1395 0 stevel strsigset_t *signals, strpollset_t *pollwakeups) 1396 0 stevel { 1397 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1398 8348 Eric 1399 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1400 0 stevel 1401 0 stevel ASSERT(so_verify_oobstate(so)); 1402 0 stevel 1403 8348 Eric ASSERT(sti->sti_oobsigcnt >= sti->sti_oobcnt); 1404 0 stevel ASSERT(mp != NULL); 1405 0 stevel /* 1406 0 stevel * For OOBINLINE we keep the data in the T_EXDATA_IND. 1407 0 stevel * Otherwise we store it in so_oobmsg. 1408 0 stevel */ 1409 0 stevel ASSERT(so->so_oobmsg == NULL); 1410 0 stevel if (so->so_options & SO_OOBINLINE) { 1411 0 stevel *pollwakeups |= POLLIN | POLLRDNORM | POLLRDBAND; 1412 0 stevel *signals |= S_INPUT | S_RDNORM; 1413 0 stevel } else { 1414 0 stevel *pollwakeups |= POLLRDBAND; 1415 0 stevel so->so_state |= SS_HAVEOOBDATA; 1416 0 stevel so->so_oobmsg = mp; 1417 0 stevel mp = NULL; 1418 0 stevel } 1419 0 stevel ASSERT(so_verify_oobstate(so)); 1420 0 stevel return (mp); 1421 0 stevel } 1422 0 stevel 1423 0 stevel /* 1424 0 stevel * Caller must hold the mutex. 1425 0 stevel * For delayed processing, save the T_DISCON_IND received 1426 8348 Eric * from below on sti_discon_ind_mp. 1427 0 stevel * When the message is processed the framework will call: 1428 0 stevel * (*func)(so, mp); 1429 0 stevel */ 1430 0 stevel static void 1431 0 stevel so_save_discon_ind(struct sonode *so, 1432 0 stevel mblk_t *mp, 1433 0 stevel void (*func)(struct sonode *so, mblk_t *)) 1434 0 stevel { 1435 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1436 8348 Eric 1437 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1438 0 stevel 1439 0 stevel /* 1440 0 stevel * Discard new T_DISCON_IND if we have already received another. 1441 8348 Eric * Currently the earlier message can either be on sti_discon_ind_mp 1442 0 stevel * or being processed. 1443 0 stevel */ 1444 8348 Eric if (sti->sti_discon_ind_mp != NULL || (so->so_flag & SOASYNC_UNBIND)) { 1445 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1446 0 stevel "sockfs: received unexpected additional T_DISCON_IND\n"); 1447 0 stevel freemsg(mp); 1448 0 stevel return; 1449 0 stevel } 1450 0 stevel mp->b_prev = (mblk_t *)func; 1451 0 stevel mp->b_next = NULL; 1452 8348 Eric sti->sti_discon_ind_mp = mp; 1453 0 stevel } 1454 0 stevel 1455 0 stevel /* 1456 0 stevel * Caller must hold the mutex and make sure that either SOLOCKED 1457 0 stevel * or SOASYNC_UNBIND is set. Called from so_unlock_single(). 1458 8348 Eric * Perform delayed processing of T_DISCON_IND message on sti_discon_ind_mp. 1459 0 stevel * Need to ensure that strsock_proto() will not end up sleeping for 1460 0 stevel * SOASYNC_UNBIND, while executing this function. 1461 0 stevel */ 1462 0 stevel void 1463 0 stevel so_drain_discon_ind(struct sonode *so) 1464 0 stevel { 1465 0 stevel mblk_t *bp; 1466 0 stevel void (*func)(struct sonode *so, mblk_t *); 1467 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1468 0 stevel 1469 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1470 0 stevel ASSERT(so->so_flag & (SOLOCKED|SOASYNC_UNBIND)); 1471 0 stevel 1472 8348 Eric /* Process T_DISCON_IND on sti_discon_ind_mp */ 1473 8348 Eric if ((bp = sti->sti_discon_ind_mp) != NULL) { 1474 8348 Eric sti->sti_discon_ind_mp = NULL; 1475 0 stevel func = (void (*)())bp->b_prev; 1476 0 stevel bp->b_prev = NULL; 1477 0 stevel 1478 0 stevel /* 1479 0 stevel * This (*func) is supposed to generate a message downstream 1480 0 stevel * and we need to have a flag set until the corresponding 1481 0 stevel * upstream message reaches stream head. 1482 0 stevel * When processing T_DISCON_IND in strsock_discon_ind 1483 0 stevel * we hold SOASYN_UNBIND when sending T_UNBIND_REQ down and 1484 0 stevel * drop the flag after we get the ACK in strsock_proto. 1485 0 stevel */ 1486 0 stevel (void) (*func)(so, bp); 1487 0 stevel } 1488 0 stevel } 1489 0 stevel 1490 0 stevel /* 1491 0 stevel * Caller must hold the mutex. 1492 8348 Eric * Remove the T_DISCON_IND on sti_discon_ind_mp. 1493 0 stevel */ 1494 0 stevel void 1495 0 stevel so_flush_discon_ind(struct sonode *so) 1496 0 stevel { 1497 0 stevel mblk_t *bp; 1498 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1499 0 stevel 1500 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1501 0 stevel 1502 0 stevel /* 1503 8348 Eric * Remove T_DISCON_IND mblk at sti_discon_ind_mp. 1504 0 stevel */ 1505 8348 Eric if ((bp = sti->sti_discon_ind_mp) != NULL) { 1506 8348 Eric sti->sti_discon_ind_mp = NULL; 1507 0 stevel bp->b_prev = NULL; 1508 0 stevel freemsg(bp); 1509 0 stevel } 1510 0 stevel } 1511 0 stevel 1512 0 stevel /* 1513 0 stevel * Caller must hold the mutex. 1514 0 stevel * 1515 0 stevel * This function is used to process the T_DISCON_IND message. It does 1516 0 stevel * immediate processing when called from strsock_proto and delayed 1517 8348 Eric * processing of discon_ind saved on sti_discon_ind_mp when called from 1518 0 stevel * so_drain_discon_ind. When a T_DISCON_IND message is saved in 1519 8348 Eric * sti_discon_ind_mp for delayed processing, this function is registered 1520 0 stevel * as the callback function to process the message. 1521 0 stevel * 1522 0 stevel * SOASYNC_UNBIND should be held in this function, during the non-blocking 1523 0 stevel * unbind operation, and should be released only after we receive the ACK 1524 0 stevel * in strsock_proto, for the T_UNBIND_REQ sent here. Since SOLOCKED is not set, 1525 0 stevel * no TPI messages would be sent down at this time. This is to prevent M_FLUSH 1526 0 stevel * sent from either this function or tcp_unbind(), flushing away any TPI 1527 0 stevel * message that is being sent down and stays in a lower module's queue. 1528 0 stevel * 1529 0 stevel * This function drops so_lock and grabs it again. 1530 0 stevel */ 1531 0 stevel static void 1532 0 stevel strsock_discon_ind(struct sonode *so, mblk_t *discon_mp) 1533 0 stevel { 1534 0 stevel struct vnode *vp; 1535 0 stevel struct stdata *stp; 1536 0 stevel union T_primitives *tpr; 1537 0 stevel struct T_unbind_req *ubr; 1538 0 stevel mblk_t *mp; 1539 0 stevel int error; 1540 8348 Eric sotpi_info_t *sti = SOTOTPI(so); 1541 0 stevel 1542 0 stevel ASSERT(MUTEX_HELD(&so->so_lock)); 1543 0 stevel ASSERT(discon_mp); 1544 0 stevel ASSERT(discon_mp->b_rptr); 1545 0 stevel 1546 0 stevel tpr = (union T_primitives *)discon_mp->b_rptr; 1547 0 stevel ASSERT(tpr->type == T_DISCON_IND); 1548 0 stevel 1549 0 stevel vp = SOTOV(so); 1550 0 stevel stp = vp->v_stream; 1551 0 stevel ASSERT(stp); 1552 0 stevel 1553 0 stevel /* 1554 0 stevel * Not a listener 1555 0 stevel */ 1556 0 stevel ASSERT((so->so_state & SS_ACCEPTCONN) == 0); 1557 0 stevel 1558 0 stevel /* 1559 0 stevel * This assumes that the name space for DISCON_reason 1560 0 stevel * is the errno name space. 1561 0 stevel */ 1562 0 stevel soisdisconnected(so, tpr->discon_ind.DISCON_reason); 1563 8348 Eric sti->sti_laddr_valid = 0; 1564 8348 Eric sti->sti_faddr_valid = 0; 1565 0 stevel 1566 0 stevel /* 1567 0 stevel * Unbind with the transport without blocking. 1568 0 stevel * If we've already received a T_DISCON_IND do not unbind. 1569 0 stevel * 1570 0 stevel * If there is no preallocated unbind message, we have already 1571 0 stevel * unbound with the transport 1572 0 stevel * 1573 0 stevel * If the socket is not bound, no need to unbind. 1574 0 stevel */ 1575 8348 Eric mp = sti->sti_unbind_mp; 1576 0 stevel if (mp == NULL) { 1577 0 stevel ASSERT(!(so->so_state & SS_ISBOUND)); 1578 0 stevel mutex_exit(&so->so_lock); 1579 0 stevel } else if (!(so->so_state & SS_ISBOUND)) { 1580 0 stevel mutex_exit(&so->so_lock); 1581 0 stevel } else { 1582 8348 Eric sti->sti_unbind_mp = NULL; 1583 0 stevel 1584 0 stevel /* 1585 0 stevel * Is another T_DISCON_IND being processed. 1586 0 stevel */ 1587 0 stevel ASSERT((so->so_flag & SOASYNC_UNBIND) == 0); 1588 0 stevel 1589 0 stevel /* 1590 0 stevel * Make strsock_proto ignore T_OK_ACK and T_ERROR_ACK for 1591 0 stevel * this unbind. Set SOASYNC_UNBIND. This should be cleared 1592 0 stevel * only after we receive the ACK in strsock_proto. 1593 0 stevel */ 1594 0 stevel so->so_flag |= SOASYNC_UNBIND; 1595 0 stevel ASSERT(!(so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING))); 1596 8348 Eric so->so_state &= ~(SS_ISBOUND|SS_ACCEPTCONN); 1597 8348 Eric sti->sti_laddr_valid = 0; 1598 0 stevel mutex_exit(&so->so_lock); 1599 0 stevel 1600 0 stevel /* 1601 0 stevel * Send down T_UNBIND_REQ ignoring flow control. 1602 0 stevel * XXX Assumes that MSG_IGNFLOW implies that this thread 1603 0 stevel * does not run service procedures. 1604 0 stevel */ 1605 0 stevel ASSERT(DB_TYPE(mp) == M_PROTO); 1606 0 stevel ubr = (struct T_unbind_req *)mp->b_rptr; 1607 0 stevel mp->b_wptr += sizeof (*ubr); 1608 0 stevel ubr->PRIM_type = T_UNBIND_REQ; 1609 0 stevel 1610 0 stevel /* 1611 0 stevel * Flush the read and write side (except stream head read queue) 1612 0 stevel * and send down T_UNBIND_REQ. 1613 0 stevel */ 1614 0 stevel (void) putnextctl1(strvp2wq(SOTOV(so)), M_FLUSH, FLUSHRW); 1615 0 stevel error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0, 1616 5753 gww MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR|MSG_IGNFLOW, 0); 1617 0 stevel /* LINTED - warning: statement has no consequent: if */ 1618 0 stevel if (error) { 1619 0 stevel eprintsoline(so, error); 1620 0 stevel } 1621 0 stevel } 1622 0 stevel 1623 0 stevel if (tpr->discon_ind.DISCON_reason != 0) 1624 0 stevel strsetrerror(SOTOV(so), 0, 0, sogetrderr); 1625 0 stevel strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 1626 0 stevel strseteof(SOTOV(so), 1); 1627 0 stevel /* 1628 0 stevel * strseteof takes care of read side wakeups, 1629 0 stevel * pollwakeups, and signals. 1630 0 stevel */ 1631 0 stevel dprintso(so, 1, ("T_DISCON_IND: error %d\n", so->so_error)); 1632 0 stevel freemsg(discon_mp); 1633 0 stevel 1634 0 stevel 1635 0 stevel pollwakeup(&stp->sd_pollist, POLLOUT); 1636 0 stevel mutex_enter(&stp->sd_lock); 1637 0 stevel 1638 0 stevel /* 1639 0 stevel * Wake sleeping write 1640 0 stevel */ 1641 0 stevel if (stp->sd_flag & WSLEEP) { 1642 0 stevel stp->sd_flag &= ~WSLEEP; 1643 0 stevel cv_broadcast(&stp->sd_wrq->q_wait); 1644 0 stevel } 1645 0 stevel 1646 0 stevel /* 1647 0 stevel * strsendsig can handle multiple signals with a 1648 0 stevel * single call. Send SIGPOLL for S_OUTPUT event. 1649 0 stevel */ 1650 0 stevel if (stp->sd_sigflags & S_OUTPUT) 1651 0 stevel strsendsig(stp->sd_siglist, S_OUTPUT, 0, 0); 1652 0 stevel 1653 0 stevel mutex_exit(&stp->sd_lock); 1654 0 stevel mutex_enter(&so->so_lock); 1655 0 stevel } 1656 0 stevel 1657 0 stevel /* 1658 0 stevel * This routine is registered with the stream head to receive M_PROTO 1659 0 stevel * and M_PCPROTO messages. 1660 0 stevel * 1661 0 stevel * Returns NULL if the message was consumed. 1662 0 stevel * Returns an mblk to make that mblk be processed (and queued) by the stream 1663 0 stevel * head. 1664 0 stevel * 1665 0 stevel * Sets the return parameters (*wakeups, *firstmsgsigs, *allmsgsigs, and 1666 0 stevel * *pollwakeups) for the stream head to take action on. Note that since 1667 0 stevel * sockets always deliver SIGIO for every new piece of data this routine 1668 0 stevel * never sets *firstmsgsigs; any signals are returned in *allmsgsigs. 1669 0 stevel * 1670 0 stevel * This routine handles all data related TPI messages independent of 1671 0 stevel * the type of the socket i.e. it doesn't care if T_UNITDATA_IND message 1672 0 stevel * arrive on a SOCK_STREAM. 1673 0 stevel */ 1674 0 stevel static mblk_t * 1675 0 stevel strsock_proto(vnode_t *vp, mblk_t *mp, 1676 0 stevel strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 1677 0 stevel strsigset_t *allmsgsigs, strpollset_t *pollwakeups) 1678 0 stevel { 1679 0 stevel union T_primitives *tpr; 1680 0 stevel struct sonode *so; 1681 8348 Eric sotpi_info_t *sti; 1682 0 stevel 1683 0 stevel so = VTOSO(vp); 1684 8348 Eric sti = SOTOTPI(so); 1685 0 stevel 1686 7240 rh87107 dprintso(so, 1, ("strsock_proto(%p, %p)\n", (void *)vp, (void *)mp)); 1687 0 stevel 1688 0 stevel /* Set default return values */ 1689 0 stevel *firstmsgsigs = *wakeups = *allmsgsigs = *pollwakeups = 0; 1690 0 stevel 1691 0 stevel ASSERT(DB_TYPE(mp) == M_PROTO || 1692 0 stevel DB_TYPE(mp) == M_PCPROTO); 1693 0 stevel 1694 0 stevel if (MBLKL(mp) < sizeof (tpr->type)) { 1695 0 stevel /* The message is too short to even contain the primitive */ 1696 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1697 0 stevel "sockfs: Too short TPI message received. Len = %ld\n", 1698 0 stevel (ptrdiff_t)(MBLKL(mp))); 1699 0 stevel freemsg(mp); 1700 0 stevel return (NULL); 1701 0 stevel } 1702 0 stevel if (!__TPI_PRIM_ISALIGNED(mp->b_rptr)) { 1703 0 stevel /* The read pointer is not aligned correctly for TPI */ 1704 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1705 0 stevel "sockfs: Unaligned TPI message received. rptr = %p\n", 1706 0 stevel (void *)mp->b_rptr); 1707 0 stevel freemsg(mp); 1708 0 stevel return (NULL); 1709 0 stevel } 1710 0 stevel tpr = (union T_primitives *)mp->b_rptr; 1711 0 stevel dprintso(so, 1, ("strsock_proto: primitive %d\n", tpr->type)); 1712 0 stevel 1713 0 stevel switch (tpr->type) { 1714 0 stevel 1715 0 stevel case T_DATA_IND: 1716 0 stevel if (MBLKL(mp) < sizeof (struct T_data_ind)) { 1717 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1718 0 stevel "sockfs: Too short T_DATA_IND. Len = %ld\n", 1719 0 stevel (ptrdiff_t)(MBLKL(mp))); 1720 0 stevel freemsg(mp); 1721 0 stevel return (NULL); 1722 0 stevel } 1723 0 stevel /* 1724 0 stevel * Ignore zero-length T_DATA_IND messages. These might be 1725 0 stevel * generated by some transports. 1726 0 stevel * This is needed to prevent read (which skips the M_PROTO 1727 0 stevel * part) to unexpectedly return 0 (or return EWOULDBLOCK 1728 0 stevel * on a non-blocking socket after select/poll has indicated 1729 0 stevel * that data is available). 1730 0 stevel */ 1731 0 stevel if (msgdsize(mp->b_cont) == 0) { 1732 0 stevel dprintso(so, 0, 1733 0 stevel ("strsock_proto: zero length T_DATA_IND\n")); 1734 0 stevel freemsg(mp); 1735 0 stevel return (NULL); 1736 0 stevel } 1737 0 stevel *allmsgsigs = S_INPUT | S_RDNORM; 1738 0 stevel *pollwakeups = POLLIN | POLLRDNORM; 1739 0 stevel *wakeups = RSLEEP; 1740 0 stevel return (mp); 1741 0 stevel 1742 0 stevel case T_UNITDATA_IND: { 1743 0 stevel struct T_unitdata_ind *tudi = &tpr->unitdata_ind; 1744 0 stevel void *addr; 1745 0 stevel t_uscalar_t addrlen; 1746 0 stevel 1747 0 stevel if (MBLKL(mp) < sizeof (struct T_unitdata_ind)) { 1748 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1749 0 stevel "sockfs: Too short T_UNITDATA_IND. Len = %ld\n", 1750 0 stevel (ptrdiff_t)(MBLKL(mp))); 1751 0 stevel freemsg(mp); 1752 0 stevel return (NULL); 1753 0 stevel } 1754 0 stevel 1755 0 stevel /* Is this is not a connected datagram socket? */ 1756 0 stevel if ((so->so_mode & SM_CONNREQUIRED) || 1757 0 stevel !(so->so_state & SS_ISCONNECTED)) { 1758 0 stevel /* 1759 0 stevel * Not a connected datagram socket. Look for 1760 0 stevel * the SO_UNIX_CLOSE option. If such an option is found 1761 0 stevel * discard the message (since it has no meaning 1762 0 stevel * unless connected). 1763 0 stevel */ 1764 0 stevel if (so->so_family == AF_UNIX && msgdsize(mp) == 0 && 1765 0 stevel tudi->OPT_length != 0) { 1766 0 stevel void *opt; 1767 0 stevel t_uscalar_t optlen = tudi->OPT_length; 1768 0 stevel 1769 0 stevel opt = sogetoff(mp, tudi->OPT_offset, 1770 5753 gww optlen, __TPI_ALIGN_SIZE); 1771 0 stevel if (opt == NULL) { 1772 0 stevel /* The len/off falls outside mp */ 1773 0 stevel freemsg(mp); 1774 0 stevel mutex_enter(&so->so_lock); 1775 0 stevel soseterror(so, EPROTO); 1776 0 stevel mutex_exit(&so->so_lock); 1777 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1778 0 stevel "sockfs: T_unidata_ind with " 1779 0 stevel "invalid optlen/offset %u/%d\n", 1780 0 stevel optlen, tudi->OPT_offset); 1781 0 stevel return (NULL); 1782 0 stevel } 1783 0 stevel if (so_getopt_unix_close(opt, optlen)) { 1784 0 stevel freemsg(mp); 1785 0 stevel return (NULL); 1786 0 stevel } 1787 0 stevel } 1788 0 stevel *allmsgsigs = S_INPUT | S_RDNORM; 1789 0 stevel *pollwakeups = POLLIN | POLLRDNORM; 1790 0 stevel *wakeups = RSLEEP; 1791 0 stevel if (audit_active) 1792 0 stevel audit_sock(T_UNITDATA_IND, strvp2wq(vp), 1793 5753 gww mp, 0); 1794 0 stevel return (mp); 1795 0 stevel } 1796 0 stevel 1797 0 stevel /* 1798 0 stevel * A connect datagram socket. For AF_INET{,6} we verify that 1799 0 stevel * the source address matches the "connected to" address. 1800 0 stevel * The semantics of AF_UNIX sockets is to not verify 1801 0 stevel * the source address. 1802 0 stevel * Note that this source address verification is transport 1803 0 stevel * specific. Thus the real fix would be to extent TPI 1804 0 stevel * to allow T_CONN_REQ messages to be send to connectionless 1805 0 stevel * transport providers and always let the transport provider 1806 0 stevel * do whatever filtering is needed. 1807 0 stevel * 1808 0 stevel * The verification/filtering semantics for transports 1809 0 stevel * other than AF_INET and AF_UNIX are unknown. The choice 1810 0 stevel * would be to either filter using bcmp or let all messages 1811 0 stevel * get through. This code does not filter other address 1812 0 stevel * families since this at least allows the application to 1813 0 stevel * work around any missing filtering. 1814 0 stevel * 1815 0 stevel * XXX Should we move filtering to UDP/ICMP??? 1816 0 stevel * That would require passing e.g. a T_DISCON_REQ to UDP 1817 0 stevel * when the socket becomes unconnected. 1818 0 stevel */ 1819 0 stevel addrlen = tudi->SRC_length; 1820 0 stevel /* 1821 0 stevel * The alignment restriction is really to strict but 1822 0 stevel * we want enough alignment to inspect the fields of 1823 0 stevel * a sockaddr_in. 1824 0 stevel */ 1825 0 stevel addr = sogetoff(mp, tudi->SRC_offset, addrlen, 1826 5753 gww __TPI_ALIGN_SIZE); 1827 0 stevel if (addr == NULL) { 1828 0 stevel freemsg(mp); 1829 0 stevel mutex_enter(&so->so_lock); 1830 0 stevel soseterror(so, EPROTO); 1831 0 stevel mutex_exit(&so->so_lock); 1832 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1833 0 stevel "sockfs: T_unidata_ind with invalid " 1834 0 stevel "addrlen/offset %u/%d\n", 1835 0 stevel addrlen, tudi->SRC_offset); 1836 0 stevel return (NULL); 1837 0 stevel } 1838 0 stevel 1839 0 stevel if (so->so_family == AF_INET) { 1840 0 stevel /* 1841 0 stevel * For AF_INET we allow wildcarding both sin_addr 1842 0 stevel * and sin_port. 1843 0 stevel */ 1844 0 stevel struct sockaddr_in *faddr, *sin; 1845 0 stevel 1846 8348 Eric /* Prevent sti_faddr_sa from changing while accessed */ 1847 0 stevel mutex_enter(&so->so_lock); 1848 8348 Eric ASSERT(sti->sti_faddr_len == 1849 5753 gww (socklen_t)sizeof (struct sockaddr_in)); 1850 8348 Eric faddr = (struct sockaddr_in *)sti->sti_faddr_sa; 1851 0 stevel sin = (struct sockaddr_in *)addr; 1852 0 stevel if (addrlen != 1853 5753 gww (t_uscalar_t)sizeof (struct sockaddr_in) || 1854 0 stevel (sin->sin_addr.s_addr != faddr->sin_addr.s_addr && 1855 0 stevel faddr->sin_addr.s_addr != INADDR_ANY) || 1856 0 stevel (so->so_type != SOCK_RAW && 1857 0 stevel sin->sin_port != faddr->sin_port && 1858 0 stevel faddr->sin_port != 0)) { 1859 0 stevel #ifdef DEBUG 1860 0 stevel dprintso(so, 0, 1861 5753 gww ("sockfs: T_UNITDATA_IND mismatch: %s", 1862 5753 gww pr_addr(so->so_family, 1863 8348 Eric (struct sockaddr *)addr, addrlen))); 1864 0 stevel dprintso(so, 0, (" - %s\n", 1865 8348 Eric pr_addr(so->so_family, sti->sti_faddr_sa, 1866 8348 Eric (t_uscalar_t)sti->sti_faddr_len))); 1867 0 stevel #endif /* DEBUG */ 1868 0 stevel mutex_exit(&so->so_lock); 1869 0 stevel freemsg(mp); 1870 0 stevel return (NULL); 1871 0 stevel } 1872 0 stevel mutex_exit(&so->so_lock); 1873 0 stevel } else if (so->so_family == AF_INET6) { 1874 0 stevel /* 1875 0 stevel * For AF_INET6 we allow wildcarding both sin6_addr 1876 0 stevel * and sin6_port. 1877 0 stevel */ 1878 0 stevel struct sockaddr_in6 *faddr6, *sin6; 1879 0 stevel static struct in6_addr zeroes; /* inits to all zeros */ 1880 0 stevel 1881 8348 Eric /* Prevent sti_faddr_sa from changing while accessed */ 1882 0 stevel mutex_enter(&so->so_lock); 1883 8348 Eric ASSERT(sti->sti_faddr_len == 1884 0 stevel (socklen_t)sizeof (struct sockaddr_in6)); 1885 8348 Eric faddr6 = (struct sockaddr_in6 *)sti->sti_faddr_sa; 1886 0 stevel sin6 = (struct sockaddr_in6 *)addr; 1887 0 stevel /* XXX could we get a mapped address ::ffff:0.0.0.0 ? */ 1888 0 stevel if (addrlen != 1889 0 stevel (t_uscalar_t)sizeof (struct sockaddr_in6) || 1890 0 stevel (!IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 1891 5753 gww &faddr6->sin6_addr) && 1892 0 stevel !IN6_ARE_ADDR_EQUAL(&faddr6->sin6_addr, &zeroes)) || 1893 0 stevel (so->so_type != SOCK_RAW && 1894 0 stevel sin6->sin6_port != faddr6->sin6_port && 1895 0 stevel faddr6->sin6_port != 0)) { 1896 0 stevel #ifdef DEBUG 1897 0 stevel dprintso(so, 0, 1898 0 stevel ("sockfs: T_UNITDATA_IND mismatch: %s", 1899 5753 gww pr_addr(so->so_family, 1900 8348 Eric (struct sockaddr *)addr, addrlen))); 1901 0 stevel dprintso(so, 0, (" - %s\n", 1902 8348 Eric pr_addr(so->so_family, sti->sti_faddr_sa, 1903 8348 Eric (t_uscalar_t)sti->sti_faddr_len))); 1904 0 stevel #endif /* DEBUG */ 1905 0 stevel mutex_exit(&so->so_lock); 1906 0 stevel freemsg(mp); 1907 0 stevel return (NULL); 1908 0 stevel } 1909 0 stevel mutex_exit(&so->so_lock); 1910 0 stevel } else if (so->so_family == AF_UNIX && 1911 0 stevel msgdsize(mp->b_cont) == 0 && 1912 0 stevel tudi->OPT_length != 0) { 1913 0 stevel /* 1914 0 stevel * Attempt to extract AF_UNIX 1915 0 stevel * SO_UNIX_CLOSE indication from options. 1916 0 stevel */ 1917 0 stevel void *opt; 1918 0 stevel t_uscalar_t optlen = tudi->OPT_length; 1919 0 stevel 1920 0 stevel opt = sogetoff(mp, tudi->OPT_offset, 1921 5753 gww optlen, __TPI_ALIGN_SIZE); 1922 0 stevel if (opt == NULL) { 1923 0 stevel /* The len/off falls outside mp */ 1924 0 stevel freemsg(mp); 1925 0 stevel mutex_enter(&so->so_lock); 1926 0 stevel soseterror(so, EPROTO); 1927 0 stevel mutex_exit(&so->so_lock); 1928 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1929 0 stevel "sockfs: T_unidata_ind with invalid " 1930 0 stevel "optlen/offset %u/%d\n", 1931 0 stevel optlen, tudi->OPT_offset); 1932 0 stevel return (NULL); 1933 0 stevel } 1934 0 stevel /* 1935 0 stevel * If we received a unix close indication mark the 1936 0 stevel * socket and discard this message. 1937 0 stevel */ 1938 0 stevel if (so_getopt_unix_close(opt, optlen)) { 1939 0 stevel mutex_enter(&so->so_lock); 1940 0 stevel sobreakconn(so, ECONNRESET); 1941 0 stevel mutex_exit(&so->so_lock); 1942 0 stevel strsetrerror(SOTOV(so), 0, 0, sogetrderr); 1943 0 stevel freemsg(mp); 1944 0 stevel *pollwakeups = POLLIN | POLLRDNORM; 1945 0 stevel *allmsgsigs = S_INPUT | S_RDNORM; 1946 0 stevel *wakeups = RSLEEP; 1947 0 stevel return (NULL); 1948 0 stevel } 1949 0 stevel } 1950 0 stevel *allmsgsigs = S_INPUT | S_RDNORM; 1951 0 stevel *pollwakeups = POLLIN | POLLRDNORM; 1952 0 stevel *wakeups = RSLEEP; 1953 0 stevel return (mp); 1954 0 stevel } 1955 0 stevel 1956 0 stevel case T_OPTDATA_IND: { 1957 0 stevel struct T_optdata_ind *tdi = &tpr->optdata_ind; 1958 0 stevel 1959 0 stevel if (MBLKL(mp) < sizeof (struct T_optdata_ind)) { 1960 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1961 0 stevel "sockfs: Too short T_OPTDATA_IND. Len = %ld\n", 1962 0 stevel (ptrdiff_t)(MBLKL(mp))); 1963 0 stevel freemsg(mp); 1964 0 stevel return (NULL); 1965 0 stevel } 1966 0 stevel /* 1967 0 stevel * Allow zero-length messages carrying options. 1968 0 stevel * This is used when carrying the SO_UNIX_CLOSE option. 1969 0 stevel */ 1970 0 stevel if (so->so_family == AF_UNIX && msgdsize(mp->b_cont) == 0 && 1971 0 stevel tdi->OPT_length != 0) { 1972 0 stevel /* 1973 0 stevel * Attempt to extract AF_UNIX close indication 1974 0 stevel * from the options. Ignore any other options - 1975 0 stevel * those are handled once the message is removed 1976 0 stevel * from the queue. 1977 0 stevel * The close indication message should not carry data. 1978 0 stevel */ 1979 0 stevel void *opt; 1980 0 stevel t_uscalar_t optlen = tdi->OPT_length; 1981 0 stevel 1982 0 stevel opt = sogetoff(mp, tdi->OPT_offset, 1983 5753 gww optlen, __TPI_ALIGN_SIZE); 1984 0 stevel if (opt == NULL) { 1985 0 stevel /* The len/off falls outside mp */ 1986 0 stevel freemsg(mp); 1987 0 stevel mutex_enter(&so->so_lock); 1988 0 stevel soseterror(so, EPROTO); 1989 0 stevel mutex_exit(&so->so_lock); 1990 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 1991 0 stevel "sockfs: T_optdata_ind with invalid " 1992 0 stevel "optlen/offset %u/%d\n", 1993 0 stevel optlen, tdi->OPT_offset); 1994 0 stevel return (NULL); 1995 0 stevel } 1996 0 stevel /* 1997 0 stevel * If we received a close indication mark the 1998 0 stevel * socket and discard this message. 1999 0 stevel */ 2000 0 stevel if (so_getopt_unix_close(opt, optlen)) { 2001 0 stevel mutex_enter(&so->so_lock); 2002 0 stevel socantsendmore(so); 2003 8348 Eric sti->sti_faddr_valid = 0; 2004 0 stevel mutex_exit(&so->so_lock); 2005 0 stevel strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2006 0 stevel freemsg(mp); 2007 0 stevel return (NULL); 2008 0 stevel } 2009 0 stevel } 2010 0 stevel *allmsgsigs = S_INPUT | S_RDNORM; 2011 0 stevel *pollwakeups = POLLIN | POLLRDNORM; 2012 0 stevel *wakeups = RSLEEP; 2013 0 stevel return (mp); 2014 0 stevel } 2015 0 stevel 2016 0 stevel case T_EXDATA_IND: { 2017 0 stevel mblk_t *mctl, *mdata; 2018 2933 ss146032 mblk_t *lbp; 2019 2933 ss146032 union T_primitives *tprp; 2020 2933 ss146032 struct stdata *stp; 2021 2933 ss146032 queue_t *qp; 2022 0 stevel 2023 0 stevel if (MBLKL(mp) < sizeof (struct T_exdata_ind)) { 2024 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2025 0 stevel "sockfs: Too short T_EXDATA_IND. Len = %ld\n", 2026 0 stevel (ptrdiff_t)(MBLKL(mp))); 2027 0 stevel freemsg(mp); 2028 0 stevel return (NULL); 2029 0 stevel } 2030 0 stevel /* 2031 0 stevel * Ignore zero-length T_EXDATA_IND messages. These might be 2032 0 stevel * generated by some transports. 2033 0 stevel * 2034 0 stevel * This is needed to prevent read (which skips the M_PROTO 2035 0 stevel * part) to unexpectedly return 0 (or return EWOULDBLOCK 2036 0 stevel * on a non-blocking socket after select/poll has indicated 2037 0 stevel * that data is available). 2038 0 stevel */ 2039 0 stevel dprintso(so, 1, 2040 5753 gww ("T_EXDATA_IND(%p): counts %d/%d state %s\n", 2041 8348 Eric (void *)vp, sti->sti_oobsigcnt, sti->sti_oobcnt, 2042 5753 gww pr_state(so->so_state, so->so_mode))); 2043 0 stevel 2044 0 stevel if (msgdsize(mp->b_cont) == 0) { 2045 0 stevel dprintso(so, 0, 2046 5753 gww ("strsock_proto: zero length T_EXDATA_IND\n")); 2047 0 stevel freemsg(mp); 2048 0 stevel return (NULL); 2049 0 stevel } 2050 0 stevel 2051 0 stevel /* 2052 0 stevel * Split into the T_EXDATA_IND and the M_DATA part. 2053 0 stevel * We process these three pieces separately: 2054 0 stevel * signal generation 2055 0 stevel * handling T_EXDATA_IND 2056 0 stevel * handling M_DATA component 2057 0 stevel */ 2058 0 stevel mctl = mp; 2059 0 stevel mdata = mctl->b_cont; 2060 0 stevel mctl->b_cont = NULL; 2061 0 stevel mutex_enter(&so->so_lock); 2062 0 stevel so_oob_sig(so, 0, allmsgsigs, pollwakeups); 2063 0 stevel mctl = so_oob_exdata(so, mctl, allmsgsigs, pollwakeups); 2064 0 stevel mdata = so_oob_data(so, mdata, allmsgsigs, pollwakeups); 2065 2933 ss146032 2066 2933 ss146032 stp = vp->v_stream; 2067 2933 ss146032 ASSERT(stp != NULL); 2068 2933 ss146032 qp = _RD(stp->sd_wrq); 2069 2933 ss146032 2070 2933 ss146032 mutex_enter(QLOCK(qp)); 2071 2933 ss146032 lbp = qp->q_last; 2072 2933 ss146032 2073 2933 ss146032 /* 2074 2933 ss146032 * We want to avoid queueing up a string of T_EXDATA_IND 2075 2933 ss146032 * messages with no intervening data messages at the stream 2076 2933 ss146032 * head. These messages contribute to the total message 2077 2933 ss146032 * count. Eventually this can lead to STREAMS flow contol 2078 2933 ss146032 * and also cause TCP to advertise a zero window condition 2079 2933 ss146032 * to the peer. This can happen in the degenerate case where 2080 2933 ss146032 * the sender and receiver exchange only OOB data. The sender 2081 2933 ss146032 * only sends messages with MSG_OOB flag and the receiver 2082 2933 ss146032 * receives only MSG_OOB messages and does not use SO_OOBINLINE. 2083 2933 ss146032 * An example of this scenario has been reported in applications 2084 2933 ss146032 * that use OOB data to exchange heart beats. Flow control 2085 2933 ss146032 * relief will never happen if the application only reads OOB 2086 2933 ss146032 * data which is done directly by sorecvoob() and the 2087 2933 ss146032 * T_EXDATA_IND messages at the streamhead won't be consumed. 2088 2933 ss146032 * Note that there is no correctness issue in compressing the 2089 2933 ss146032 * string of T_EXDATA_IND messages into a single T_EXDATA_IND 2090 2933 ss146032 * message. A single read that does not specify MSG_OOB will 2091 2933 ss146032 * read across all the marks in a loop in sotpi_recvmsg(). 2092 2933 ss146032 * Each mark is individually distinguishable only if the 2093 2933 ss146032 * T_EXDATA_IND messages are separated by data messages. 2094 2933 ss146032 */ 2095 2933 ss146032 if ((qp->q_first != NULL) && (DB_TYPE(lbp) == M_PROTO)) { 2096 2933 ss146032 tprp = (union T_primitives *)lbp->b_rptr; 2097 2933 ss146032 if ((tprp->type == T_EXDATA_IND) && 2098 2933 ss146032 !(so->so_options & SO_OOBINLINE)) { 2099 2933 ss146032 2100 2933 ss146032 /* 2101 2933 ss146032 * free the new M_PROTO message 2102 2933 ss146032 */ 2103 2933 ss146032 freemsg(mctl); 2104 2933 ss146032 2105 2933 ss146032 /* 2106 2933 ss146032 * adjust the OOB count and OOB signal count 2107 2933 ss146032 * just incremented for the new OOB data. 2108 2933 ss146032 */ 2109 8348 Eric sti->sti_oobcnt--; 2110 8348 Eric sti->sti_oobsigcnt--; 2111 2933 ss146032 mutex_exit(QLOCK(qp)); 2112 2933 ss146032 mutex_exit(&so->so_lock); 2113 2933 ss146032 return (NULL); 2114 2933 ss146032 } 2115 2933 ss146032 } 2116 2933 ss146032 mutex_exit(QLOCK(qp)); 2117 0 stevel 2118 0 stevel /* 2119 0 stevel * Pass the T_EXDATA_IND and the M_DATA back separately 2120 0 stevel * by using b_next linkage. (The stream head will queue any 2121 0 stevel * b_next linked messages separately.) This is needed 2122 0 stevel * since MSGMARK applies to the last by of the message 2123 0 stevel * hence we can not have any M_DATA component attached 2124 0 stevel * to the marked T_EXDATA_IND. Note that the stream head 2125 0 stevel * will not consolidate M_DATA messages onto an MSGMARK'ed 2126 0 stevel * message in order to preserve the constraint that 2127 0 stevel * the T_EXDATA_IND always is a separate message. 2128 0 stevel */ 2129 0 stevel ASSERT(mctl != NULL); 2130 0 stevel mctl->b_next = mdata; 2131 0 stevel mp = mctl; 2132 0 stevel #ifdef DEBUG 2133 0 stevel if (mdata == NULL) { 2134 0 stevel dprintso(so, 1, 2135 5753 gww ("after outofline T_EXDATA_IND(%p): " 2136 5753 gww "counts %d/%d poll 0x%x sig 0x%x state %s\n", 2137 8348 Eric (void *)vp, sti->sti_oobsigcnt, 2138 8348 Eric sti->sti_oobcnt, *pollwakeups, *allmsgsigs, 2139 5753 gww pr_state(so->so_state, so->so_mode))); 2140 0 stevel } else { 2141 0 stevel dprintso(so, 1, 2142 5753 gww ("after inline T_EXDATA_IND(%p): " 2143 5753 gww "counts %d/%d poll 0x%x sig 0x%x state %s\n", 2144 8348 Eric (void *)vp, sti->sti_oobsigcnt, 2145 8348 Eric sti->sti_oobcnt, *pollwakeups, *allmsgsigs, 2146 5753 gww pr_state(so->so_state, so->so_mode))); 2147 0 stevel } 2148 0 stevel #endif /* DEBUG */ 2149 0 stevel mutex_exit(&so->so_lock); 2150 0 stevel *wakeups = RSLEEP; 2151 0 stevel return (mp); 2152 0 stevel } 2153 0 stevel 2154 0 stevel case T_CONN_CON: { 2155 0 stevel struct T_conn_con *conn_con; 2156 0 stevel void *addr; 2157 0 stevel t_uscalar_t addrlen; 2158 0 stevel 2159 0 stevel /* 2160 0 stevel * Verify the state, update the state to ISCONNECTED, 2161 0 stevel * record the potentially new address in the message, 2162 0 stevel * and drop the message. 2163 0 stevel */ 2164 0 stevel if (MBLKL(mp) < sizeof (struct T_conn_con)) { 2165 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2166 0 stevel "sockfs: Too short T_CONN_CON. Len = %ld\n", 2167 0 stevel (ptrdiff_t)(MBLKL(mp))); 2168 0 stevel freemsg(mp); 2169 0 stevel return (NULL); 2170 0 stevel } 2171 0 stevel 2172 0 stevel mutex_enter(&so->so_lock); 2173 0 stevel if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) != 2174 0 stevel SS_ISCONNECTING) { 2175 0 stevel mutex_exit(&so->so_lock); 2176 0 stevel dprintso(so, 1, 2177 5753 gww ("T_CONN_CON: state %x\n", so->so_state)); 2178 0 stevel freemsg(mp); 2179 0 stevel return (NULL); 2180 0 stevel } 2181 0 stevel 2182 0 stevel conn_con = &tpr->conn_con; 2183 0 stevel addrlen = conn_con->RES_length; 2184 0 stevel /* 2185 0 stevel * Allow the address to be of different size than sent down 2186 0 stevel * in the T_CONN_REQ as long as it doesn't exceed the maxlen. 2187 0 stevel * For AF_UNIX require the identical length. 2188 0 stevel */ 2189 0 stevel if (so->so_family == AF_UNIX ? 2190 8348 Eric addrlen != (t_uscalar_t)sizeof (sti->sti_ux_laddr) : 2191 8348 Eric addrlen > (t_uscalar_t)sti->sti_faddr_maxlen) { 2192 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2193 0 stevel "sockfs: T_conn_con with different " 2194 0 stevel "length %u/%d\n", 2195 0 stevel addrlen, conn_con->RES_length); 2196 0 stevel soisdisconnected(so, EPROTO); 2197 8348 Eric sti->sti_laddr_valid = 0; 2198 8348 Eric sti->sti_faddr_valid = 0; 2199 0 stevel mutex_exit(&so->so_lock); 2200 0 stevel strsetrerror(SOTOV(so), 0, 0, sogetrderr); 2201 0 stevel strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2202 0 stevel strseteof(SOTOV(so), 1); 2203 0 stevel freemsg(mp); 2204 0 stevel /* 2205 0 stevel * strseteof takes care of read side wakeups, 2206 0 stevel * pollwakeups, and signals. 2207 0 stevel */ 2208 0 stevel *wakeups = WSLEEP; 2209 0 stevel *allmsgsigs = S_OUTPUT; 2210 0 stevel *pollwakeups = POLLOUT; 2211 0 stevel return (NULL); 2212 0 stevel } 2213 0 stevel addr = sogetoff(mp, conn_con->RES_offset, addrlen, 1); 2214 0 stevel if (addr == NULL) { 2215 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2216 0 stevel "sockfs: T_conn_con with invalid " 2217 0 stevel "addrlen/offset %u/%d\n", 2218 0 stevel addrlen, conn_con->RES_offset); 2219 0 stevel mutex_exit(&so->so_lock); 2220 0 stevel strsetrerror(SOTOV(so), 0, 0, sogetrderr); 2221 0 stevel strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2222 0 stevel strseteof(SOTOV(so), 1); 2223 0 stevel freemsg(mp); 2224 0 stevel /* 2225 0 stevel * strseteof takes care of read side wakeups, 2226 0 stevel * pollwakeups, and signals. 2227 0 stevel */ 2228 0 stevel *wakeups = WSLEEP; 2229 0 stevel *allmsgsigs = S_OUTPUT; 2230 0 stevel *pollwakeups = POLLOUT; 2231 0 stevel return (NULL); 2232 0 stevel } 2233 0 stevel 2234 0 stevel /* 2235 0 stevel * Save for getpeername. 2236 0 stevel */ 2237 0 stevel if (so->so_family != AF_UNIX) { 2238 8348 Eric sti->sti_faddr_len = (socklen_t)addrlen; 2239 8348 Eric ASSERT(sti->sti_faddr_len <= sti->sti_faddr_maxlen); 2240 8348 Eric bcopy(addr, sti->sti_faddr_sa, addrlen); 2241 8348 Eric sti->sti_faddr_valid = 1; 2242 0 stevel } 2243 0 stevel 2244 0 stevel if (so->so_peercred != NULL) 2245 0 stevel crfree(so->so_peercred); 2246 8778 Erik so->so_peercred = msg_getcred(mp, &so->so_cpid); 2247 0 stevel if (so->so_peercred != NULL) 2248 0 stevel crhold(so->so_peercred); 2249 0 stevel 2250 0 stevel /* Wakeup anybody sleeping in sowaitconnected */ 2251 0 stevel soisconnected(so); 2252 0 stevel mutex_exit(&so->so_lock); 2253 0 stevel 2254 0 stevel /* 2255 0 stevel * The socket is now available for sending data. 2256 0 stevel */ 2257 0 stevel *wakeups = WSLEEP; 2258 0 stevel *allmsgsigs = S_OUTPUT; 2259 0 stevel *pollwakeups = POLLOUT; 2260 0 stevel freemsg(mp); 2261 0 stevel return (NULL); 2262 0 stevel } 2263 0 stevel 2264 898 kais /* 2265 898 kais * Extra processing in case of an SSL proxy, before queuing or 2266 898 kais * forwarding to the fallback endpoint 2267 898 kais */ 2268 898 kais case T_SSL_PROXY_CONN_IND: 2269 0 stevel case T_CONN_IND: 2270 0 stevel /* 2271 0 stevel * Verify the min size and queue the message on 2272 8348 Eric * the sti_conn_ind_head/tail list. 2273 0 stevel */ 2274 0 stevel if (MBLKL(mp) < sizeof (struct T_conn_ind)) { 2275 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2276 0 stevel "sockfs: Too short T_CONN_IND. Len = %ld\n", 2277 0 stevel (ptrdiff_t)(MBLKL(mp))); 2278 0 stevel freemsg(mp); 2279 0 stevel return (NULL); 2280 0 stevel } 2281 0 stevel 2282 0 stevel if (audit_active) 2283 0 stevel audit_sock(T_CONN_IND, strvp2wq(vp), mp, 0); 2284 0 stevel if (!(so->so_state & SS_ACCEPTCONN)) { 2285 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2286 0 stevel "sockfs: T_conn_ind on non-listening socket\n"); 2287 0 stevel freemsg(mp); 2288 898 kais return (NULL); 2289 898 kais } 2290 898 kais 2291 898 kais if (tpr->type == T_SSL_PROXY_CONN_IND && mp->b_cont == NULL) { 2292 898 kais /* No context: need to fall back */ 2293 898 kais struct sonode *fbso; 2294 898 kais stdata_t *fbstp; 2295 898 kais 2296 898 kais tpr->type = T_CONN_IND; 2297 898 kais 2298 8348 Eric fbso = kssl_find_fallback(sti->sti_kssl_ent); 2299 898 kais 2300 898 kais /* 2301 898 kais * No fallback: the remote will timeout and 2302 898 kais * disconnect. 2303 898 kais */ 2304 898 kais if (fbso == NULL) { 2305 898 kais freemsg(mp); 2306 898 kais return (NULL); 2307 898 kais } 2308 898 kais fbstp = SOTOV(fbso)->v_stream; 2309 898 kais qreply(fbstp->sd_wrq->q_next, mp); 2310 0 stevel return (NULL); 2311 0 stevel } 2312 0 stevel soqueueconnind(so, mp); 2313 0 stevel *allmsgsigs = S_INPUT | S_RDNORM; 2314 0 stevel *pollwakeups = POLLIN | POLLRDNORM; 2315 0 stevel *wakeups = RSLEEP; 2316 0 stevel return (NULL); 2317 0 stevel 2318 0 stevel case T_ORDREL_IND: 2319 0 stevel if (MBLKL(mp) < sizeof (struct T_ordrel_ind)) { 2320 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2321 0 stevel "sockfs: Too short T_ORDREL_IND. Len = %ld\n", 2322 0 stevel (ptrdiff_t)(MBLKL(mp))); 2323 0 stevel freemsg(mp); 2324 0 stevel return (NULL); 2325 0 stevel } 2326 0 stevel 2327 0 stevel /* 2328 0 stevel * Some providers send this when not fully connected. 2329 0 stevel * SunLink X.25 needs to retrieve disconnect reason after 2330 0 stevel * disconnect for compatibility. It uses T_ORDREL_IND 2331 0 stevel * instead of T_DISCON_IND so that it may use the 2332 0 stevel * endpoint after a connect failure to retrieve the 2333 0 stevel * reason using an ioctl. Thus we explicitly clear 2334 0 stevel * SS_ISCONNECTING here for SunLink X.25. 2335 0 stevel * This is a needed TPI violation. 2336 0 stevel */ 2337 0 stevel mutex_enter(&so->so_lock); 2338 0 stevel so->so_state &= ~SS_ISCONNECTING; 2339 0 stevel socantrcvmore(so); 2340 0 stevel mutex_exit(&so->so_lock); 2341 0 stevel strseteof(SOTOV(so), 1); 2342 0 stevel /* 2343 0 stevel * strseteof takes care of read side wakeups, 2344 0 stevel * pollwakeups, and signals. 2345 0 stevel */ 2346 0 stevel freemsg(mp); 2347 0 stevel return (NULL); 2348 0 stevel 2349 0 stevel case T_DISCON_IND: 2350 0 stevel if (MBLKL(mp) < sizeof (struct T_discon_ind)) { 2351 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2352 0 stevel "sockfs: Too short T_DISCON_IND. Len = %ld\n", 2353 0 stevel (ptrdiff_t)(MBLKL(mp))); 2354 0 stevel freemsg(mp); 2355 0 stevel return (NULL); 2356 0 stevel } 2357 0 stevel if (so->so_state & SS_ACCEPTCONN) { 2358 0 stevel /* 2359 0 stevel * This is a listener. Look for a queued T_CONN_IND 2360 0 stevel * with a matching sequence number and remove it 2361 0 stevel * from the list. 2362 0 stevel * It is normal to not find the sequence number since 2363 0 stevel * the soaccept might have already dequeued it 2364 0 stevel * (in which case the T_CONN_RES will fail with 2365 0 stevel * TBADSEQ). 2366 0 stevel */ 2367 0 stevel (void) soflushconnind(so, tpr->discon_ind.SEQ_number); 2368 0 stevel freemsg(mp); 2369 0 stevel return (0); 2370 0 stevel } 2371 0 stevel 2372 0 stevel /* 2373 0 stevel * Not a listener 2374 0 stevel * 2375 0 stevel * If SS_CANTRCVMORE for AF_UNIX ignore the discon_reason. 2376 0 stevel * Such a discon_ind appears when the peer has first done 2377 0 stevel * a shutdown() followed by a close() in which case we just 2378 0 stevel * want to record socantsendmore. 2379 0 stevel * In this case sockfs first receives a T_ORDREL_IND followed 2380 0 stevel * by a T_DISCON_IND. 2381 0 stevel * Note that for other transports (e.g. TCP) we need to handle 2382 0 stevel * the discon_ind in this case since it signals an error. 2383 0 stevel */ 2384 0 stevel mutex_enter(&so->so_lock); 2385 0 stevel if ((so->so_state & SS_CANTRCVMORE) && 2386 0 stevel (so->so_family == AF_UNIX)) { 2387 0 stevel socantsendmore(so); 2388 8348 Eric sti->sti_faddr_valid = 0; 2389 0 stevel mutex_exit(&so->so_lock); 2390 0 stevel strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2391 0 stevel dprintso(so, 1, 2392 5753 gww ("T_DISCON_IND: error %d\n", so->so_error)); 2393 0 stevel freemsg(mp); 2394 0 stevel /* 2395 0 stevel * Set these variables for caller to process them. 2396 0 stevel * For the else part where T_DISCON_IND is processed, 2397 0 stevel * this will be done in the function being called 2398 0 stevel * (strsock_discon_ind()) 2399 0 stevel */ 2400 0 stevel *wakeups = WSLEEP; 2401 0 stevel *allmsgsigs = S_OUTPUT; 2402 0 stevel *pollwakeups = POLLOUT; 2403 0 stevel } else if (so->so_flag & (SOASYNC_UNBIND | SOLOCKED)) { 2404 0 stevel /* 2405 0 stevel * Deferred processing of T_DISCON_IND 2406 0 stevel */ 2407 0 stevel so_save_discon_ind(so, mp, strsock_discon_ind); 2408 0 stevel mutex_exit(&so->so_lock); 2409 0 stevel } else { 2410 0 stevel /* 2411 0 stevel * Process T_DISCON_IND now 2412 0 stevel */ 2413 0 stevel (void) strsock_discon_ind(so, mp); 2414 0 stevel mutex_exit(&so->so_lock); 2415 0 stevel } 2416 0 stevel return (NULL); 2417 0 stevel 2418 0 stevel case T_UDERROR_IND: { 2419 0 stevel struct T_uderror_ind *tudi = &tpr->uderror_ind; 2420 0 stevel void *addr; 2421 0 stevel t_uscalar_t addrlen; 2422 0 stevel int error; 2423 0 stevel 2424 0 stevel dprintso(so, 0, 2425 5753 gww ("T_UDERROR_IND: error %d\n", tudi->ERROR_type)); 2426 0 stevel 2427 0 stevel if (MBLKL(mp) < sizeof (struct T_uderror_ind)) { 2428 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2429 0 stevel "sockfs: Too short T_UDERROR_IND. Len = %ld\n", 2430 0 stevel (ptrdiff_t)(MBLKL(mp))); 2431 0 stevel freemsg(mp); 2432 0 stevel return (NULL); 2433 0 stevel } 2434 0 stevel /* Ignore on connection-oriented transports */ 2435 0 stevel if (so->so_mode & SM_CONNREQUIRED) { 2436 0 stevel freemsg(mp); 2437 0 stevel eprintsoline(so, 0); 2438 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2439 0 stevel "sockfs: T_uderror_ind on connection-oriented " 2440 0 stevel "transport\n"); 2441 0 stevel return (NULL); 2442 0 stevel } 2443 0 stevel addrlen = tudi->DEST_length; 2444 0 stevel addr = sogetoff(mp, tudi->DEST_offset, addrlen, 1); 2445 0 stevel if (addr == NULL) { 2446 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2447 0 stevel "sockfs: T_uderror_ind with invalid " 2448 0 stevel "addrlen/offset %u/%d\n", 2449 0 stevel addrlen, tudi->DEST_offset); 2450 0 stevel freemsg(mp); 2451 0 stevel return (NULL); 2452 0 stevel } 2453 0 stevel 2454 0 stevel /* Verify source address for connected socket. */ 2455 0 stevel mutex_enter(&so->so_lock); 2456 0 stevel if (so->so_state & SS_ISCONNECTED) { 2457 0 stevel void *faddr; 2458 0 stevel t_uscalar_t faddr_len; 2459 0 stevel boolean_t match = B_FALSE; 2460 0 stevel 2461 0 stevel switch (so->so_family) { 2462 0 stevel case AF_INET: { 2463 0 stevel /* Compare just IP address and port */ 2464 0 stevel struct sockaddr_in *sin1, *sin2; 2465 0 stevel 2466 8348 Eric sin1 = (struct sockaddr_in *)sti->sti_faddr_sa; 2467 0 stevel sin2 = (struct sockaddr_in *)addr; 2468 0 stevel if (addrlen == sizeof (struct sockaddr_in) && 2469 0 stevel sin1->sin_port == sin2->sin_port && 2470 0 stevel sin1->sin_addr.s_addr == 2471 0 stevel sin2->sin_addr.s_addr) 2472 0 stevel match = B_TRUE; 2473 0 stevel break; 2474 0 stevel } 2475 0 stevel case AF_INET6: { 2476 0 stevel /* Compare just IP address and port. Not flow */ 2477 0 stevel struct sockaddr_in6 *sin1, *sin2; 2478 0 stevel 2479 8348 Eric sin1 = (struct sockaddr_in6 *)sti->sti_faddr_sa; 2480 0 stevel sin2 = (struct sockaddr_in6 *)addr; 2481 0 stevel if (addrlen == sizeof (struct sockaddr_in6) && 2482 0 stevel sin1->sin6_port == sin2->sin6_port && 2483 0 stevel IN6_ARE_ADDR_EQUAL(&sin1->sin6_addr, 2484 5753 gww &sin2->sin6_addr)) 2485 0 stevel match = B_TRUE; 2486 0 stevel break; 2487 0 stevel } 2488 0 stevel case AF_UNIX: 2489 8348 Eric faddr = &sti->sti_ux_faddr; 2490 0 stevel faddr_len = 2491 8348 Eric (t_uscalar_t)sizeof (sti->sti_ux_faddr); 2492 0 stevel if (faddr_len == addrlen && 2493 0 stevel bcmp(addr, faddr, addrlen) == 0) 2494 0 stevel match = B_TRUE; 2495 0 stevel break; 2496 0 stevel default: 2497 8348 Eric faddr = sti->sti_faddr_sa; 2498 8348 Eric faddr_len = (t_uscalar_t)sti->sti_faddr_len; 2499 0 stevel if (faddr_len == addrlen && 2500 0 stevel bcmp(addr, faddr, addrlen) == 0) 2501 0 stevel match = B_TRUE; 2502 0 stevel break; 2503 0 stevel } 2504 0 stevel 2505 0 stevel if (!match) { 2506 0 stevel #ifdef DEBUG 2507 0 stevel dprintso(so, 0, 2508 5753 gww ("sockfs: T_UDERR_IND mismatch: %s - ", 2509 5753 gww pr_addr(so->so_family, 2510 8348 Eric (struct sockaddr *)addr, addrlen))); 2511 0 stevel dprintso(so, 0, ("%s\n", 2512 8348 Eric pr_addr(so->so_family, sti->sti_faddr_sa, 2513 8348 Eric sti->sti_faddr_len))); 2514 0 stevel #endif /* DEBUG */ 2515 0 stevel mutex_exit(&so->so_lock); 2516 0 stevel freemsg(mp); 2517 0 stevel return (NULL); 2518 0 stevel } 2519 0 stevel /* 2520 0 stevel * Make the write error nonpersistent. If the error 2521 0 stevel * is zero we use ECONNRESET. 2522 0 stevel * This assumes that the name space for ERROR_type 2523 0 stevel * is the errno name space. 2524 0 stevel */ 2525 0 stevel if (tudi->ERROR_type != 0) 2526 0 stevel error = tudi->ERROR_type; 2527 0 stevel else 2528 0 stevel error = ECONNRESET; 2529 0 stevel 2530 0 stevel soseterror(so, error); 2531 0 stevel mutex_exit(&so->so_lock); 2532 0 stevel strsetrerror(SOTOV(so), 0, 0, sogetrderr); 2533 0 stevel strsetwerror(SOTOV(so), 0, 0, sogetwrerr); 2534 0 stevel *wakeups = RSLEEP | WSLEEP; 2535 0 stevel *allmsgsigs = S_INPUT | S_RDNORM | S_OUTPUT; 2536 0 stevel *pollwakeups = POLLIN | POLLRDNORM | POLLOUT; 2537 0 stevel freemsg(mp); 2538 0 stevel return (NULL); 2539 0 stevel } 2540 0 stevel /* 2541 0 stevel * If the application asked for delayed errors 2542 8348 Eric * record the T_UDERROR_IND sti_eaddr_mp and the reason in 2543 8348 Eric * sti_delayed_error for delayed error posting. If the reason 2544 0 stevel * is zero use ECONNRESET. 2545 0 stevel * Note that delayed error indications do not make sense for 2546 0 stevel * AF_UNIX sockets since sendto checks that the destination 2547 0 stevel * address is valid at the time of the sendto. 2548 0 stevel */ 2549 0 stevel if (!(so->so_options & SO_DGRAM_ERRIND)) { 2550 0 stevel mutex_exit(&so->so_lock); 2551 0 stevel freemsg(mp); 2552 0 stevel return (NULL); 2553 0 stevel } 2554 8348 Eric if (sti->sti_eaddr_mp != NULL) 2555 8348 Eric freemsg(sti->sti_eaddr_mp); 2556 0 stevel 2557 8348 Eric sti->sti_eaddr_mp = mp; 2558 0 stevel if (tudi->ERROR_type != 0) 2559 0 stevel error = tudi->ERROR_type; 2560 0 stevel else 2561 0 stevel error = ECONNRESET; 2562 8348 Eric sti->sti_delayed_error = (ushort_t)error; 2563 0 stevel mutex_exit(&so->so_lock); 2564 0 stevel return (NULL); 2565 0 stevel } 2566 0 stevel 2567 0 stevel case T_ERROR_ACK: 2568 0 stevel dprintso(so, 0, 2569 5753 gww ("strsock_proto: T_ERROR_ACK for %d, error %d/%d\n", 2570 5753 gww tpr->error_ack.ERROR_prim, 2571 5753 gww tpr->error_ack.TLI_error, 2572 5753 gww tpr->error_ack.UNIX_error)); 2573 0 stevel 2574 0 stevel if (MBLKL(mp) < sizeof (struct T_error_ack)) { 2575 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2576 0 stevel "sockfs: Too short T_ERROR_ACK. Len = %ld\n", 2577 0 stevel (ptrdiff_t)(MBLKL(mp))); 2578 0 stevel freemsg(mp); 2579 0 stevel return (NULL); 2580 0 stevel } 2581 0 stevel /* 2582 0 stevel * Check if we were waiting for the async message 2583 0 stevel */ 2584 0 stevel mutex_enter(&so->so_lock); 2585 0 stevel if ((so->so_flag & SOASYNC_UNBIND) && 2586 0 stevel tpr->error_ack.ERROR_prim == T_UNBIND_REQ) { 2587 0 stevel so_unlock_single(so, SOASYNC_UNBIND); 2588 0 stevel mutex_exit(&so->so_lock); 2589 0 stevel freemsg(mp); 2590 0 stevel return (NULL); 2591 0 stevel } 2592 0 stevel mutex_exit(&so->so_lock); 2593 0 stevel soqueueack(so, mp); 2594 0 stevel return (NULL); 2595 0 stevel 2596 0 stevel case T_OK_ACK: 2597 0 stevel if (MBLKL(mp) < sizeof (struct T_ok_ack)) { 2598 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2599 0 stevel "sockfs: Too short T_OK_ACK. Len = %ld\n", 2600 0 stevel (ptrdiff_t)(MBLKL(mp))); 2601 0 stevel freemsg(mp); 2602 0 stevel return (NULL); 2603 0 stevel } 2604 0 stevel /* 2605 0 stevel * Check if we were waiting for the async message 2606 0 stevel */ 2607 0 stevel mutex_enter(&so->so_lock); 2608 0 stevel if ((so->so_flag & SOASYNC_UNBIND) && 2609 0 stevel tpr->ok_ack.CORRECT_prim == T_UNBIND_REQ) { 2610 0 stevel dprintso(so, 1, 2611 5753 gww ("strsock_proto: T_OK_ACK async unbind\n")); 2612 0 stevel so_unlock_single(so, SOASYNC_UNBIND); 2613 0 stevel mutex_exit(&so->so_lock); 2614 0 stevel freemsg(mp); 2615 0 stevel return (NULL); 2616 0 stevel } 2617 0 stevel mutex_exit(&so->so_lock); 2618 0 stevel soqueueack(so, mp); 2619 0 stevel return (NULL); 2620 0 stevel 2621 0 stevel case T_INFO_ACK: 2622 0 stevel if (MBLKL(mp) < sizeof (struct T_info_ack)) { 2623 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2624 0 stevel "sockfs: Too short T_INFO_ACK. Len = %ld\n", 2625 0 stevel (ptrdiff_t)(MBLKL(mp))); 2626 0 stevel freemsg(mp); 2627 0 stevel return (NULL); 2628 0 stevel } 2629 0 stevel soqueueack(so, mp); 2630 0 stevel return (NULL); 2631 0 stevel 2632 0 stevel case T_CAPABILITY_ACK: 2633 0 stevel /* 2634 0 stevel * A T_capability_ack need only be large enough to hold 2635 0 stevel * the PRIM_type and CAP_bits1 fields; checking for anything 2636 0 stevel * larger might reject a correct response from an older 2637 0 stevel * provider. 2638 0 stevel */ 2639 0 stevel if (MBLKL(mp) < 2 * sizeof (t_uscalar_t)) { 2640 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2641 0 stevel "sockfs: Too short T_CAPABILITY_ACK. Len = %ld\n", 2642 0 stevel (ptrdiff_t)(MBLKL(mp))); 2643 0 stevel freemsg(mp); 2644 0 stevel return (NULL); 2645 0 stevel } 2646 0 stevel soqueueack(so, mp); 2647 0 stevel return (NULL); 2648 0 stevel 2649 0 stevel case T_BIND_ACK: 2650 0 stevel if (MBLKL(mp) < sizeof (struct T_bind_ack)) { 2651 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2652 0 stevel "sockfs: Too short T_BIND_ACK. Len = %ld\n", 2653 0 stevel (ptrdiff_t)(MBLKL(mp))); 2654 0 stevel freemsg(mp); 2655 0 stevel return (NULL); 2656 0 stevel } 2657 0 stevel soqueueack(so, mp); 2658 0 stevel return (NULL); 2659 0 stevel 2660 0 stevel case T_OPTMGMT_ACK: 2661 0 stevel if (MBLKL(mp) < sizeof (struct T_optmgmt_ack)) { 2662 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2663 0 stevel "sockfs: Too short T_OPTMGMT_ACK. Len = %ld\n", 2664 0 stevel (ptrdiff_t)(MBLKL(mp))); 2665 0 stevel freemsg(mp); 2666 0 stevel return (NULL); 2667 0 stevel } 2668 0 stevel soqueueack(so, mp); 2669 0 stevel return (NULL); 2670 0 stevel default: 2671 0 stevel #ifdef DEBUG 2672 1548 rshoaib zcmn_err(getzoneid(), CE_WARN, 2673 5753 gww "sockfs: unknown TPI primitive %d received\n", 2674 5753 gww tpr->type); 2675 0 stevel #endif /* DEBUG */ 2676 0 stevel freemsg(mp); 2677 0 stevel return (NULL); 2678 0 stevel } 2679 0 stevel } 2680 0 stevel 2681 0 stevel /* 2682 0 stevel * This routine is registered with the stream head to receive other 2683 0 stevel * (non-data, and non-proto) messages. 2684 0 stevel * 2685 0 stevel * Returns NULL if the message was consumed. 2686 0 stevel * Returns an mblk to make that mblk be processed by the stream head. 2687 0 stevel * 2688 0 stevel * Sets the return parameters (*wakeups, *firstmsgsigs, *allmsgsigs, and 2689 0 stevel * *pollwakeups) for the stream head to take action on. 2690 0 stevel */ 2691 0 stevel static mblk_t * 2692 0 stevel strsock_misc(vnode_t *vp, mblk_t *mp, 2693 0 stevel strwakeup_t *wakeups, strsigset_t *firstmsgsigs, 2694 0 stevel strsigset_t *allmsgsigs, strpollset_t *pollwakeups) 2695 0 stevel { 2696 0 stevel struct sonode *so; 2697 8348 Eric sotpi_info_t *sti; 2698 0 stevel 2699 0 stevel so = VTOSO(vp); 2700 8348 Eric sti = SOTOTPI(so); 2701 0 stevel 2702 0 stevel dprintso(so, 1, ("strsock_misc(%p, %p, 0x%x)\n", 2703 7240 rh87107 (void *)vp, (void *)mp, DB_TYPE(mp))); 2704 0 stevel 2705 0 stevel /* Set default return values */ 2706 0 stevel *wakeups = *allmsgsigs = *firstmsgsigs = *pollwakeups = 0; 2707 0 stevel 2708 0 stevel switch (DB_TYPE(mp)) { 2709 0 stevel case M_PCSIG: 2710 0 stevel /* 2711 0 stevel * This assumes that an M_PCSIG for the urgent data arrives 2712 0 stevel * before the corresponding T_EXDATA_IND. 2713 0 stevel * 2714 0 stevel * Note: Just like in SunOS 4.X and 4.4BSD a poll will be 2715 0 stevel * awoken before the urgent data shows up. 2716 0 stevel * For OOBINLINE this can result in select returning 2717 0 stevel * only exceptions as opposed to except|read. 2718 0 stevel */ 2719 0 stevel if (*mp->b_rptr == SIGURG) { 2720 0 stevel mutex_enter(&so->so_lock); 2721 0 stevel dprintso(so, 1, 2722 5753 gww ("SIGURG(%p): counts %d/%d state %s\n", 2723 8348 Eric (void *)vp, sti->sti_oobsigcnt, sti->sti_oobcnt, 2724 5753 gww pr_state(so->so_state, so->so_mode))); 2725 0 stevel so_oob_sig(so, 1, allmsgsigs, pollwakeups); 2726 0 stevel dprintso(so, 1, 2727 5753 gww ("after SIGURG(%p): counts %d/%d " 2728 5753 gww " poll 0x%x sig 0x%x state %s\n", 2729 8348 Eric (void *)vp, sti->sti_oobsigcnt, sti->sti_oobcnt, 2730 8348 Eric *pollwakeups, *allmsgsigs, 2731 5753 gww pr_state(so->so_state, so->so_mode))); 2732 0 stevel mutex_exit(&so->so_lock); 2733 0 stevel } 2734 0 stevel freemsg(mp); 2735 0 stevel return (NULL); 2736 0 stevel 2737 0 stevel case M_SIG: 2738 0 stevel case M_HANGUP: 2739 0 stevel case M_UNHANGUP: 2740 0 stevel case M_ERROR: 2741 0 stevel /* M_ERRORs etc are ignored */ 2742 0 stevel freemsg(mp); 2743 0 stevel return (NULL); 2744 0 stevel 2745 0 stevel case M_FLUSH: 2746 0 stevel /* 2747 0 stevel * Do not flush read queue. If the M_FLUSH 2748 0 stevel * arrives because of an impending T_discon_ind 2749 0 stevel * we still have to keep any queued data - this is part of 2750 0 stevel * socket semantics. 2751 0 stevel */ 2752 0 stevel if (*mp->b_rptr & FLUSHW) { 2753 0 stevel *mp->b_rptr &= ~FLUSHR; 2754 0 stevel return (mp); 2755 0 stevel } 2756 0 stevel freemsg(mp); 2757 0 stevel return (NULL); 2758 0 stevel 2759 0 stevel default: 2760 0 stevel return (mp); 2761 0 stevel } 2762 0 stevel } 2763 0 stevel 2764 0 stevel 2765 0 stevel /* Register to receive signals for certain events */ 2766 0 stevel int 2767 0 stevel so_set_asyncsigs(vnode_t *vp, pid_t pgrp, int events, int mode, cred_t *cr) 2768 0 stevel { 2769 0 stevel struct strsigset ss; 2770 0 stevel int32_t rval; 2771 0 stevel 2772 0 stevel /* 2773 0 stevel * Note that SOLOCKED will be set except for the call from soaccept(). 2774 0 stevel */ 2775 0 stevel ASSERT(!mutex_owned(&VTOSO(vp)->so_lock)); 2776 0 stevel ss.ss_pid = pgrp; 2777 0 stevel ss.ss_events = events; 2778 0 stevel return (strioctl(vp, I_ESETSIG, (intptr_t)&ss, mode, K_TO_K, cr, 2779 0 stevel &rval)); 2780 0 stevel } 2781 0 stevel 2782 0 stevel 2783 0 stevel /* Register for events matching the SS_ASYNC flag */ 2784 0 stevel int 2785 0 stevel so_set_events(struct sonode *so, vnode_t *vp, cred_t *cr) 2786 0 stevel { 2787 0 stevel int events = so->so_state & SS_ASYNC ? 2788 0 stevel S_RDBAND | S_BANDURG | S_RDNORM | S_OUTPUT : 2789 0 stevel S_RDBAND | S_BANDURG; 2790 0 stevel 2791 0 stevel return (so_set_asyncsigs(vp, so->so_pgrp, events, 0, cr)); 2792 0 stevel } 2793 0 stevel 2794 0 stevel 2795 0 stevel /* Change the SS_ASYNC flag, and update signal delivery if needed */ 2796 0 stevel int 2797 0 stevel so_flip_async(struct sonode *so, vnode_t *vp, int mode, cred_t *cr) 2798 0 stevel { 2799 0 stevel ASSERT(mutex_owned(&so->so_lock)); 2800 0 stevel if (so->so_pgrp != 0) { 2801 0 stevel int error; 2802 0 stevel int events = so->so_state & SS_ASYNC ? /* Old flag */ 2803 0 stevel S_RDBAND | S_BANDURG : /* New sigs */ 2804 0 stevel S_RDBAND | S_BANDURG | S_RDNORM | S_OUTPUT; 2805 0 stevel 2806 0 stevel so_lock_single(so); 2807 0 stevel mutex_exit(&so->so_lock); 2808 0 stevel 2809 0 stevel error = so_set_asyncsigs(vp, so->so_pgrp, events, mode, cr); 2810 0 stevel 2811 0 stevel mutex_enter(&so->so_lock); 2812 0 stevel so_unlock_single(so, SOLOCKED); 2813 0 stevel if (error) 2814 0 stevel return (error); 2815 0 stevel } 2816 0 stevel so->so_state ^= SS_ASYNC; 2817 0 stevel return (0); 2818 0 stevel } 2819 0 stevel 2820 0 stevel /* 2821 0 stevel * Set new pid/pgrp for SIGPOLL (or SIGIO for FIOASYNC mode), replacing 2822 0 stevel * any existing one. If passed zero, just clear the existing one. 2823 0 stevel */ 2824 0 stevel int 2825 0 stevel so_set_siggrp(struct sonode *so, vnode_t *vp, pid_t pgrp, int mode, cred_t *cr) 2826 0 stevel { 2827 0 stevel int events = so->so_state & SS_ASYNC ? 2828 0 stevel S_RDBAND | S_BANDURG | S_RDNORM | S_OUTPUT : 2829 0 stevel S_RDBAND | S_BANDURG; 2830 0 stevel int error; 2831 0 stevel 2832 0 stevel ASSERT(mutex_owned(&so->so_lock)); 2833 0 stevel 2834 0 stevel /* 2835 0 stevel * Change socket process (group). 2836 0 stevel * 2837 0 stevel * strioctl (via so_set_asyncsigs) will perform permission check and 2838 0 stevel * also keep a PID_HOLD to prevent the pid from being reused. 2839 0 stevel */ 2840 0 stevel so_lock_single(so); 2841 0 stevel mutex_exit(&so->so_lock); 2842 0 stevel 2843 0 stevel if (pgrp != 0) { 2844 0 stevel dprintso(so, 1, ("setown: adding pgrp %d ev 0x%x\n", 2845 0 stevel pgrp, events)); 2846 0 stevel error = so_set_asyncsigs(vp, pgrp, events, mode, cr); 2847 0 stevel if (error != 0) { 2848 0 stevel eprintsoline(so, error); 2849 0 stevel goto bad; 2850 0 stevel } 2851 0 stevel } 2852 0 stevel /* Remove the previously registered process/group */ 2853 0 stevel if (so->so_pgrp != 0) { 2854 0 stevel dprintso(so, 1, ("setown: removing pgrp %d\n", so->so_pgrp)); 2855 0 stevel error = so_set_asyncsigs(vp, so->so_pgrp, 0, mode, cr); 2856 0 stevel if (error != 0) { 2857 0 stevel eprintsoline(so, error); 2858 0 stevel error = 0; 2859 0 stevel } 2860 0 stevel } 2861 0 stevel mutex_enter(&so->so_lock); 2862 0 stevel so_unlock_single(so, SOLOCKED); 2863 0 stevel so->so_pgrp = pgrp; 2864 0 stevel return (0); 2865 0 stevel bad: 2866 0 stevel mutex_enter(&so->so_lock); 2867 0 stevel so_unlock_single(so, SOLOCKED); 2868 0 stevel return (error); 2869 0 stevel } 2870 0 stevel 2871 8348 Eric /* 2872 8348 Eric * Wrapper for getmsg. If the socket has been converted to a stream 2873 8348 Eric * pass the request to the stream head. 2874 8348 Eric */ 2875 8348 Eric int 2876 8348 Eric sock_getmsg( 2877 8348 Eric struct vnode *vp, 2878 8348 Eric struct strbuf *mctl, 2879 8348 Eric struct strbuf *mdata, 2880 8348 Eric uchar_t *prip, 2881 8348 Eric int *flagsp, 2882 8348 Eric int fmode, 2883 8348 Eric rval_t *rvp 2884 8348 Eric ) 2885 8348 Eric { 2886 8348 Eric struct sonode *so; 2887 0 stevel 2888 8348 Eric ASSERT(vp->v_type == VSOCK); 2889 8348 Eric /* 2890 8348 Eric * Use the stream head to find the real socket vnode. 2891 8348 Eric * This is needed when namefs sits above sockfs. Some 2892 8348 Eric * sockets (like SCTP) are not streams. 2893 8348 Eric */ 2894 8348 Eric if (!vp->v_stream) { 2895 8348 Eric return (ENOSTR); 2896 8348 Eric } 2897 8348 Eric ASSERT(vp->v_stream->sd_vnode); 2898 8348 Eric vp = vp->v_stream->sd_vnode; 2899 8348 Eric ASSERT(vn_matchops(vp, socket_vnodeops)); 2900 8348 Eric so = VTOSO(vp); 2901 8348 Eric 2902 8348 Eric dprintso(so, 1, ("sock_getmsg(%p) %s\n", 2903 8348 Eric (void *)so, pr_state(so->so_state, so->so_mode))); 2904 8348 Eric 2905 8348 Eric if (so->so_version == SOV_STREAM) { 2906 8348 Eric /* The imaginary "sockmod" has been popped - act as a stream */ 2907 8348 Eric return (strgetmsg(vp, mctl, mdata, prip, flagsp, fmode, rvp)); 2908 8348 Eric } 2909 8348 Eric eprintsoline(so, ENOSTR); 2910 8348 Eric return (ENOSTR); 2911 8348 Eric } 2912 0 stevel 2913 0 stevel /* 2914 8348 Eric * Wrapper for putmsg. If the socket has been converted to a stream 2915 8348 Eric * pass the request to the stream head. 2916 8348 Eric * 2917 8348 Eric * Note that a while a regular socket (SOV_SOCKSTREAM) does support the 2918 8348 Eric * streams ioctl set it does not support putmsg and getmsg. 2919 8348 Eric * Allowing putmsg would prevent sockfs from tracking the state of 2920 8348 Eric * the socket/transport and would also invalidate the locking in sockfs. 2921 0 stevel */ 2922 8348 Eric int 2923 8348 Eric sock_putmsg( 2924 8348 Eric struct vnode *vp, 2925 8348 Eric struct strbuf *mctl, 2926 8348 Eric struct strbuf *mdata, 2927 8348 Eric uchar_t pri, 2928 8348 Eric int flag, 2929 8348 Eric int fmode 2930 8348 Eric ) 2931 8348 Eric { 2932 8348 Eric struct sonode *so; 2933 0 stevel 2934 8348 Eric ASSERT(vp->v_type == VSOCK); 2935 8348 Eric /* 2936 8348 Eric * Use the stream head to find the real socket vnode. 2937 8348 Eric * This is needed when namefs sits above sockfs. 2938 8348 Eric */ 2939 8348 Eric if (!vp->v_stream) { 2940 8348 Eric return (ENOSTR); 2941 8348 Eric } 2942 8348 Eric ASSERT(vp->v_stream->sd_vnode); 2943 8348 Eric vp = vp->v_stream->sd_vnode; 2944 8348 Eric ASSERT(vn_matchops(vp, socket_vnodeops)); 2945 8348 Eric so = VTOSO(vp); 2946 8348 Eric 2947 8348 Eric dprintso(so, 1, ("sock_putmsg(%p) %s\n", 2948 8348 Eric (void *)so, pr_state(so->so_state, so->so_mode))); 2949 8348 Eric 2950 8348 Eric if (so->so_version == SOV_STREAM) { 2951 8348 Eric /* The imaginary "sockmod" has been popped - act as a stream */ 2952 8348 Eric return (strputmsg(vp, mctl, mdata, pri, flag, fmode)); 2953 8348 Eric } 2954 8348 Eric eprintsoline(so, ENOSTR); 2955 8348 Eric return (ENOSTR); 2956 8348 Eric } 2957 8348 Eric 2958 8348 Eric /* 2959 8348 Eric * Special function called only from f_getfl(). 2960 8348 Eric * Returns FASYNC if the SS_ASYNC flag is set on a socket, else 0. 2961 8348 Eric * No locks are acquired here, so it is safe to use while uf_lock is held. 2962 8348 Eric * This exists solely for BSD fcntl() FASYNC compatibility. 2963 8348 Eric */ 2964 8348 Eric int 2965 8348 Eric sock_getfasync(vnode_t *vp) 2966 0 stevel { 2967 8348 Eric struct sonode *so; 2968 8348 Eric 2969 8348 Eric ASSERT(vp->v_type == VSOCK); 2970 8348 Eric /* 2971 8348 Eric * For stream model, v_stream is used; For non-stream, v_stream always 2972 8348 Eric * equals NULL 2973 8348 Eric */ 2974 8348 Eric if (vp->v_stream != NULL) 2975 8348 Eric so = VTOSO(vp->v_stream->sd_vnode); 2976 0 stevel else 2977 8348 Eric so = VTOSO(vp); 2978 8348 Eric 2979 8348 Eric if (so->so_version == SOV_STREAM || !(so->so_state & SS_ASYNC)) 2980 8348 Eric return (0); 2981 8348 Eric 2982 8348 Eric return (FASYNC); 2983 0 stevel } 2984