1 /* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smb_trantcp.c,v 1.39 2005/03/02 01:27:44 lindak Exp $ 33 */ 34 /* 35 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 36 * Use is subject to license terms. 37 */ 38 39 #pragma ident "%Z%%M% %I% %E% SMI" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/autoconf.h> 44 #include <sys/sysmacros.h> 45 #include <sys/sunddi.h> 46 #include <sys/kmem.h> 47 #include <sys/proc.h> 48 #include <sys/protosw.h> 49 #include <sys/socket.h> 50 #include <sys/poll.h> 51 #include <sys/stream.h> 52 #include <sys/strsubr.h> 53 #include <sys/strsun.h> 54 #include <sys/stropts.h> 55 #include <sys/cmn_err.h> 56 #include <sys/tihdr.h> 57 #include <sys/tiuser.h> 58 #include <sys/t_kuser.h> 59 #include <sys/priv.h> 60 61 #include <net/if.h> 62 #include <net/route.h> 63 64 #include <netinet/in.h> 65 #include <netinet/tcp.h> 66 67 #ifdef APPLE 68 #include <sys/smb_apple.h> 69 #else 70 #include <netsmb/smb_osdep.h> 71 #endif 72 73 #include <netsmb/mchain.h> 74 #include <netsmb/netbios.h> 75 76 #include <netsmb/smb.h> 77 #include <netsmb/smb_conn.h> 78 #include <netsmb/smb_subr.h> 79 #include <netsmb/smb_tran.h> 80 #include <netsmb/smb_trantcp.h> 81 82 /* 83 * SMB messages are up to 64K. 84 * Let's leave room for two. 85 */ 86 static int smb_tcpsndbuf = 0x20000; 87 static int smb_tcprcvbuf = 0x20000; 88 89 static dev_t smb_tcp_dev; 90 91 static int nbssn_recv(struct nbpcb *nbp, mblk_t **mpp, int *lenp, 92 uint8_t *rpcodep, struct proc *p); 93 static int nb_disconnect(struct nbpcb *nbp); 94 95 static int 96 nb_wait_ack(TIUSER *tiptr, t_scalar_t ack_prim, int fmode) 97 { 98 int msgsz; 99 union T_primitives *pptr; 100 mblk_t *bp; 101 ptrdiff_t diff; 102 int error; 103 104 /* 105 * wait for ack 106 */ 107 bp = NULL; 108 if ((error = tli_recv(tiptr, &bp, fmode)) != 0) 109 return (error); 110 111 diff = MBLKL(bp); 112 ASSERT(diff == (ptrdiff_t)((int)diff)); 113 msgsz = (int)diff; 114 115 if (msgsz < sizeof (int)) { 116 freemsg(bp); 117 return (EPROTO); 118 } 119 120 /*LINTED*/ 121 pptr = (union T_primitives *)bp->b_rptr; 122 if (pptr->type == ack_prim) 123 error = 0; /* Success */ 124 else if (pptr->type == T_ERROR_ACK) { 125 if (pptr->error_ack.TLI_error == TSYSERR) 126 error = pptr->error_ack.UNIX_error; 127 else 128 error = t_tlitosyserr(pptr->error_ack.TLI_error); 129 } else 130 error = EPROTO; 131 132 freemsg(bp); 133 return (error); 134 } 135 136 /* 137 * Internal set sockopt for int-sized options. 138 * Is there a common Solaris function for this? 139 * Code from uts/common/rpc/clnt_cots.c 140 */ 141 static int 142 nb_setsockopt_int(TIUSER *tiptr, int level, int name, int val) 143 { 144 int fmode; 145 mblk_t *mp; 146 struct opthdr *opt; 147 struct T_optmgmt_req *tor; 148 int *valp; 149 int error, mlen; 150 151 mlen = (sizeof (struct T_optmgmt_req) + 152 sizeof (struct opthdr) + sizeof (int)); 153 if (!(mp = allocb_wait(mlen, BPRI_LO, STR_NOSIG, &error))) 154 return (error); 155 156 mp->b_datap->db_type = M_PROTO; 157 /*LINTED*/ 158 tor = (struct T_optmgmt_req *)mp->b_wptr; 159 tor->PRIM_type = T_SVR4_OPTMGMT_REQ; 160 tor->MGMT_flags = T_NEGOTIATE; 161 tor->OPT_length = sizeof (struct opthdr) + sizeof (int); 162 tor->OPT_offset = sizeof (struct T_optmgmt_req); 163 mp->b_wptr += sizeof (struct T_optmgmt_req); 164 165 /*LINTED*/ 166 opt = (struct opthdr *)mp->b_wptr; 167 opt->level = level; 168 opt->name = name; 169 opt->len = sizeof (int); 170 mp->b_wptr += sizeof (struct opthdr); 171 172 /* LINTED */ 173 valp = (int *)mp->b_wptr; 174 *valp = val; 175 mp->b_wptr += sizeof (int); 176 177 fmode = tiptr->fp->f_flag; 178 if ((error = tli_send(tiptr, mp, fmode)) != 0) 179 return (error); 180 181 fmode = 0; /* need to block */ 182 error = nb_wait_ack(tiptr, T_OPTMGMT_ACK, fmode); 183 return (error); 184 } 185 186 /* 187 * Get mblks into *mpp until the data length is at least mlen. 188 * Note that *mpp may already contain a fragment. 189 * 190 * If we ever have to wait more than 15 sec. to read a message, 191 * return ETIME. (Caller will declare the VD dead.) 192 */ 193 static int 194 nb_getmsg_mlen(struct nbpcb *nbp, mblk_t **mpp, size_t mlen) 195 { 196 mblk_t *im, *tm; 197 union T_primitives *pptr; 198 size_t dlen; 199 int events, fmode, timo, waitflg; 200 int error = 0; 201 202 /* 203 * Get the first message (fragment) if 204 * we don't already have a left-over. 205 */ 206 dlen = msgdsize(*mpp); /* *mpp==null is OK */ 207 while (dlen < mlen) { 208 209 /* 210 * I think we still want this to return ETIME 211 * if nothing arrives for SMB_NBTIMO (15) sec. 212 * so we can report "server not responding". 213 * We _could_ just block here now that our 214 * IOD is just a reader. 215 */ 216 #if 1 217 /* Wait with timeout... */ 218 events = 0; 219 waitflg = READWAIT; 220 timo = SEC_TO_TICK(SMB_NBTIMO); 221 error = t_kspoll(nbp->nbp_tiptr, timo, waitflg, &events); 222 if (!error && !events) 223 error = ETIME; 224 if (error) 225 break; 226 /* file mode for recv is: */ 227 fmode = FNDELAY; /* non-blocking */ 228 #else 229 fmode = 0; /* normal (blocking) */ 230 #endif 231 232 /* Get some more... */ 233 tm = NULL; 234 error = tli_recv(nbp->nbp_tiptr, &tm, fmode); 235 if (error == EAGAIN) 236 continue; 237 if (error) 238 break; 239 240 /* 241 * Normally get M_DATA messages here, 242 * but have to check for other types. 243 */ 244 switch (tm->b_datap->db_type) { 245 case M_DATA: 246 break; 247 case M_PROTO: 248 case M_PCPROTO: 249 /*LINTED*/ 250 pptr = (union T_primitives *)tm->b_rptr; 251 switch (pptr->type) { 252 case T_DATA_IND: 253 /* remove 1st mblk, keep the rest. */ 254 im = tm->b_cont; 255 tm->b_cont = NULL; 256 freeb(tm); 257 tm = im; 258 break; 259 case T_DISCON_IND: 260 /* Peer disconnected. */ 261 NBDEBUG("T_DISCON_IND: reason=%d", 262 pptr->discon_ind.DISCON_reason); 263 goto discon; 264 case T_ORDREL_IND: 265 /* Peer disconnecting. */ 266 NBDEBUG("T_ORDREL_IND"); 267 goto discon; 268 case T_OK_ACK: 269 switch (pptr->ok_ack.CORRECT_prim) { 270 case T_DISCON_REQ: 271 NBDEBUG("T_OK_ACK/T_DISCON_REQ"); 272 goto discon; 273 default: 274 NBDEBUG("T_OK_ACK/prim=%d", 275 pptr->ok_ack.CORRECT_prim); 276 goto discon; 277 } 278 default: 279 NBDEBUG("M_PROTO/type=%d", pptr->type); 280 goto discon; 281 } 282 break; /* M_PROTO, M_PCPROTO */ 283 284 default: 285 NBDEBUG("unexpected msg type=%d", 286 tm->b_datap->db_type); 287 /*FALLTHROUGH*/ 288 discon: 289 /* 290 * The connection is no longer usable. 291 * Drop this message and disconnect. 292 * 293 * Note: nb_disconnect only does t_snddis 294 * on the first call, but does important 295 * cleanup and state change on any call. 296 */ 297 freemsg(tm); 298 nb_disconnect(nbp); 299 return (ENOTCONN); 300 } 301 302 /* 303 * If we have a data message, append it to 304 * the previous chunk(s) and update dlen 305 */ 306 if (!tm) 307 continue; 308 if (*mpp == NULL) { 309 *mpp = tm; 310 } else { 311 /* Append */ 312 for (im = *mpp; im->b_cont; im = im->b_cont) 313 ; 314 im->b_cont = tm; 315 } 316 dlen += msgdsize(tm); 317 } 318 319 return (error); 320 } 321 322 /* 323 * Send a T_DISCON_REQ (disconnect) 324 */ 325 static int 326 nb_snddis(TIUSER *tiptr) 327 { 328 mblk_t *mp; 329 struct T_discon_req *dreq; 330 int error, fmode, mlen; 331 332 mlen = sizeof (struct T_discon_req); 333 if (!(mp = allocb_wait(mlen, BPRI_LO, STR_NOSIG, &error))) 334 return (error); 335 336 mp->b_datap->db_type = M_PROTO; 337 /*LINTED*/ 338 dreq = (struct T_discon_req *)mp->b_wptr; 339 dreq->PRIM_type = T_DISCON_REQ; 340 dreq->SEQ_number = -1; 341 mp->b_wptr += sizeof (struct T_discon_req); 342 343 fmode = tiptr->fp->f_flag; 344 if ((error = tli_send(tiptr, mp, fmode)) != 0) 345 return (error); 346 347 #if 0 /* Now letting the IOD recv this. */ 348 fmode = 0; /* need to block */ 349 error = nb_wait_ack(tiptr, T_OK_ACK, fmode); 350 #endif 351 return (error); 352 } 353 354 #ifdef APPLE 355 static int 356 nb_intr(struct nbpcb *nbp, struct proc *p) 357 { 358 return (0); 359 } 360 #endif 361 362 /* 363 * Stuff the NetBIOS header into space already prepended. 364 */ 365 static int 366 nb_sethdr(mblk_t *m, uint8_t type, uint32_t len) 367 { 368 uint32_t *p; 369 370 len &= 0x1FFFF; 371 len |= (type << 24); 372 373 /*LINTED*/ 374 p = (uint32_t *)m->b_rptr; 375 *p = htonl(len); 376 return (0); 377 } 378 379 /* 380 * Note: Moved name encoding into here. 381 */ 382 static int 383 nb_put_name(struct mbchain *mbp, struct sockaddr_nb *snb) 384 { 385 int i, len; 386 uchar_t ch, *p; 387 388 /* 389 * Do the NetBIOS "first-level encoding" here. 390 * (RFC1002 explains this wierdness...) 391 * See similar code in smbfs library: 392 * lib/libsmbfs/smb/nb_name.c 393 * 394 * Here is what we marshall: 395 * uint8_t NAME_LENGTH (always 32) 396 * uint8_t ENCODED_NAME[32] 397 * uint8_t SCOPE_LENGTH 398 * XXX Scope should follow here, then another null, 399 * if and when we support NetBIOS scopes. 400 */ 401 len = 1 + (2 * NB_NAMELEN) + 1; 402 403 p = mb_reserve(mbp, len); 404 if (!p) 405 return (ENOSR); 406 407 /* NAME_LENGTH */ 408 *p++ = (2 * NB_NAMELEN); 409 410 /* ENCODED_NAME */ 411 for (i = 0; i < NB_NAMELEN; i++) { 412 ch = (uchar_t)snb->snb_name[i]; 413 *p++ = 'A' + ((ch >> 4) & 0xF); 414 *p++ = 'A' + ((ch) & 0xF); 415 } 416 417 /* SCOPE_LENGTH */ 418 *p++ = 0; 419 420 return (0); 421 } 422 423 static int 424 nb_tcpopen(struct nbpcb *nbp, struct proc *p) 425 { 426 TIUSER *tiptr; 427 int err, oflags = FREAD|FWRITE; 428 cred_t *cr = p->p_cred; 429 430 if (!smb_tcp_dev) { 431 smb_tcp_dev = makedevice( 432 clone_major, ddi_name_to_major("tcp")); 433 } 434 435 /* 436 * This magic arranges for our network endpoint 437 * to have the right "label" for operation in a 438 * "trusted extensions" environment. 439 */ 440 if (is_system_labeled()) { 441 cr = crdup(cr); 442 (void) setpflags(NET_MAC_AWARE, 1, cr); 443 } else { 444 crhold(cr); 445 } 446 err = t_kopen(NULL, smb_tcp_dev, oflags, &tiptr, cr); 447 crfree(cr); 448 if (err) 449 return (err); 450 451 /* Note: I_PUSH "timod" is done by t_kopen */ 452 453 /* Save the TPI handle we use everywhere. */ 454 nbp->nbp_tiptr = tiptr; 455 456 /* 457 * Internal ktli calls need the "fmode" flags 458 * from the t_kopen call. XXX: Not sure if the 459 * flags have the right bits set, or if we 460 * always want the same block/non-block flags. 461 * XXX: Look into this... 462 */ 463 nbp->nbp_fmode = tiptr->fp->f_flag; 464 return (0); 465 } 466 467 /*ARGSUSED*/ 468 static int 469 nb_connect_in(struct nbpcb *nbp, struct sockaddr_in *to, struct proc *p) 470 { 471 int error; 472 TIUSER *tiptr = NULL; 473 struct t_call call; 474 475 tiptr = nbp->nbp_tiptr; 476 if (tiptr == NULL) 477 return (EBADF); 478 if (nbp->nbp_flags & NBF_CONNECTED) 479 return (EISCONN); 480 481 /* 482 * Set various socket/TCP options. 483 * Failures here are not fatal - 484 * just log a complaint. 485 * 486 * We don't need these two: 487 * SO_RCVTIMEO, SO_SNDTIMEO 488 */ 489 490 error = nb_setsockopt_int(tiptr, SOL_SOCKET, SO_SNDBUF, 491 nbp->nbp_sndbuf); 492 if (error) 493 NBDEBUG("nb_connect_in: set SO_SNDBUF"); 494 495 error = nb_setsockopt_int(tiptr, SOL_SOCKET, SO_RCVBUF, 496 nbp->nbp_rcvbuf); 497 if (error) 498 NBDEBUG("nb_connect_in: set SO_RCVBUF"); 499 500 error = nb_setsockopt_int(tiptr, SOL_SOCKET, SO_KEEPALIVE, 1); 501 if (error) 502 NBDEBUG("nb_connect_in: set SO_KEEPALIVE"); 503 504 error = nb_setsockopt_int(tiptr, IPPROTO_TCP, TCP_NODELAY, 1); 505 if (error) 506 NBDEBUG("nb_connect_in: set TCP_NODELAY"); 507 508 /* Do local bind (any address) */ 509 if ((error = t_kbind(tiptr, NULL, NULL)) != 0) { 510 NBDEBUG("nb_connect_in: bind local"); 511 return (error); 512 } 513 514 /* 515 * Setup (snd)call address (connect to). 516 * Just pass NULL for the (rcv)call. 517 */ 518 bzero(&call, sizeof (call)); 519 call.addr.len = sizeof (*to); 520 call.addr.buf = (char *)to; 521 /* call.opt - none */ 522 /* call.udata -- XXX: Should put NB session req here! */ 523 524 /* Send the connect, wait... */ 525 error = t_kconnect(tiptr, &call, NULL); 526 if (error) { 527 NBDEBUG("nb_connect_in: connect %d error", error); 528 /* 529 * XXX: t_kconnect returning EPROTO here instead of ETIMEDOUT 530 * here. Temporarily return ETIMEDOUT error if we get EPROTO. 531 */ 532 if (error == EPROTO) 533 error = ETIMEDOUT; 534 } else { 535 mutex_enter(&nbp->nbp_lock); 536 nbp->nbp_flags |= NBF_CONNECTED; 537 mutex_exit(&nbp->nbp_lock); 538 } 539 540 return (error); 541 } 542 543 static int 544 nbssn_rq_request(struct nbpcb *nbp, struct proc *p) 545 { 546 struct mbchain mb, *mbp = &mb; 547 struct mdchain md, *mdp = &md; 548 mblk_t *m0; 549 struct sockaddr_in sin; 550 ushort_t port; 551 uint8_t rpcode; 552 int error, rplen; 553 554 error = mb_init(mbp); 555 if (error) 556 return (error); 557 558 /* 559 * Put a zero for the 4-byte NetBIOS header, 560 * then let nb_sethdr() overwrite it. 561 */ 562 mb_put_uint32le(mbp, 0); 563 nb_put_name(mbp, nbp->nbp_paddr); 564 nb_put_name(mbp, nbp->nbp_laddr); 565 nb_sethdr(mbp->mb_top, NB_SSN_REQUEST, mb_fixhdr(mbp) - 4); 566 567 m0 = mb_detach(mbp); 568 error = tli_send(nbp->nbp_tiptr, m0, nbp->nbp_fmode); 569 m0 = NULL; /* Note: _always_ consumed by tli_send */ 570 mb_done(mbp); 571 if (error) 572 return (error); 573 574 nbp->nbp_state = NBST_RQSENT; 575 error = nbssn_recv(nbp, &m0, &rplen, &rpcode, p); 576 if (error == EWOULDBLOCK) { /* Timeout */ 577 NBDEBUG("initial request timeout\n"); 578 return (ETIMEDOUT); 579 } 580 if (error) { 581 NBDEBUG("recv() error %d\n", error); 582 return (error); 583 } 584 /* 585 * Process NETBIOS reply 586 */ 587 if (m0) 588 md_initm(mdp, m0); 589 590 error = 0; 591 if (rpcode == NB_SSN_POSRESP) { 592 mutex_enter(&nbp->nbp_lock); 593 nbp->nbp_state = NBST_SESSION; 594 mutex_exit(&nbp->nbp_lock); 595 goto out; 596 } 597 if (rpcode != NB_SSN_RTGRESP) { 598 error = ECONNABORTED; 599 goto out; 600 } 601 if (rplen != 6) { 602 error = ECONNABORTED; 603 goto out; 604 } 605 md_get_mem(mdp, (caddr_t)&sin.sin_addr, 4, MB_MSYSTEM); 606 md_get_uint16(mdp, &port); 607 sin.sin_port = port; 608 nbp->nbp_state = NBST_RETARGET; 609 nb_disconnect(nbp); 610 error = nb_connect_in(nbp, &sin, p); 611 if (!error) 612 error = nbssn_rq_request(nbp, p); 613 if (error) { 614 nb_disconnect(nbp); 615 } 616 617 out: 618 if (m0) 619 md_done(mdp); 620 return (error); 621 } 622 623 /* 624 * Wait for up to 15 sec. for the next packet. 625 * Often return ETIME and do nothing else. 626 * When a packet header is available, check 627 * the header and get the length, but don't 628 * consume it. No side effects here except 629 * for the pullupmsg call. 630 */ 631 static int 632 nbssn_peekhdr(struct nbpcb *nbp, size_t *lenp, uint8_t *rpcodep) 633 { 634 uint32_t len, *hdr; 635 int error; 636 637 /* 638 * Get the first message (fragment) if 639 * we don't already have a left-over. 640 */ 641 error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, sizeof (len)); 642 if (error) 643 return (error); 644 645 if (!pullupmsg(nbp->nbp_frag, sizeof (len))) 646 return (ENOSR); 647 648 /* 649 * Check the NetBIOS header. 650 * (NOT consumed here) 651 */ 652 /*LINTED*/ 653 hdr = (uint32_t *)nbp->nbp_frag->b_rptr; 654 655 len = ntohl(*hdr); 656 if ((len >> 16) & 0xFE) { 657 NBDEBUG("bad nb header received 0x%x (MBZ flag set)\n", len); 658 return (EPIPE); 659 } 660 *rpcodep = (len >> 24) & 0xFF; 661 switch (*rpcodep) { 662 case NB_SSN_MESSAGE: 663 case NB_SSN_REQUEST: 664 case NB_SSN_POSRESP: 665 case NB_SSN_NEGRESP: 666 case NB_SSN_RTGRESP: 667 case NB_SSN_KEEPALIVE: 668 break; 669 default: 670 NBDEBUG("bad nb header received 0x%x (bogus type)\n", len); 671 return (EPIPE); 672 } 673 len &= 0x1ffff; 674 if (len > SMB_MAXPKTLEN) { 675 NBDEBUG("packet too long (%d)\n", len); 676 return (EFBIG); 677 } 678 *lenp = len; 679 return (0); 680 } 681 682 /* 683 * Receive a NetBIOS message. This may block to wait for the entire 684 * message to arrive. The caller knows there is (or should be) a 685 * message to be read. When we receive and drop a keepalive or 686 * zero-length message, return EAGAIN so the caller knows that 687 * something was received. This avoids false triggering of the 688 * "server not responding" state machine. 689 */ 690 /*ARGSUSED*/ 691 static int 692 nbssn_recv(struct nbpcb *nbp, mblk_t **mpp, int *lenp, 693 uint8_t *rpcodep, struct proc *p) 694 { 695 TIUSER *tiptr = nbp->nbp_tiptr; 696 mblk_t *m0; 697 uint8_t rpcode; 698 int error; 699 size_t rlen, len; 700 701 /* We should be the only reader. */ 702 ASSERT(nbp->nbp_flags & NBF_RECVLOCK); 703 704 if (tiptr == NULL) 705 return (EBADF); 706 if (mpp) { 707 if (*mpp) { 708 NBDEBUG("*mpp not 0 - leak?"); 709 } 710 *mpp = NULL; 711 } 712 m0 = NULL; 713 714 /* 715 * Get the NetBIOS header (not consumed yet) 716 */ 717 error = nbssn_peekhdr(nbp, &len, &rpcode); 718 if (error) { 719 if (error != ETIME) 720 NBDEBUG("peekhdr, error=%d\n", error); 721 return (error); 722 } 723 NBDEBUG("Have pkt, type=0x%x len=0x%x\n", 724 (int)rpcode, (int)len); 725 726 /* 727 * Block here waiting for the whole packet to arrive. 728 * If we get a timeout, return without side effects. 729 * The data length we wait for here includes both the 730 * NetBIOS header and the payload. 731 */ 732 error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, len + 4); 733 if (error) { 734 NBDEBUG("getmsg(body), error=%d\n", error); 735 return (error); 736 } 737 738 /* 739 * We now have an entire NetBIOS message. 740 * Trim off the NetBIOS header and consume it. 741 * Note: _peekhdr has done pullupmsg for us, 742 * so we know it's safe to advance b_rptr. 743 */ 744 m0 = nbp->nbp_frag; 745 m0->b_rptr += 4; 746 747 /* 748 * There may be more data after the message 749 * we're about to return, in which case we 750 * split it and leave the remainder. 751 */ 752 rlen = msgdsize(m0); 753 ASSERT(rlen >= len); 754 nbp->nbp_frag = NULL; 755 if (rlen > len) 756 nbp->nbp_frag = m_split(m0, len, 1); 757 758 if (nbp->nbp_state != NBST_SESSION) { 759 /* 760 * No session is established. 761 * Return whatever packet we got. 762 */ 763 goto out; 764 } 765 766 /* 767 * A session is established; the only packets 768 * we should see are session message and 769 * keep-alive packets. Drop anything else. 770 */ 771 switch (rpcode) { 772 773 case NB_SSN_KEEPALIVE: 774 /* 775 * It's a keepalive. Discard any data in it 776 * (there's not supposed to be any, but that 777 * doesn't mean some server won't send some) 778 */ 779 if (len) 780 NBDEBUG("Keepalive with data %d\n", (int)len); 781 error = EAGAIN; 782 break; 783 784 case NB_SSN_MESSAGE: 785 /* 786 * Session message. Does it have any data? 787 */ 788 if (len == 0) { 789 /* 790 * No data - treat as keepalive (drop). 791 */ 792 error = EAGAIN; 793 break; 794 } 795 /* 796 * Yes, has data. Return it. 797 */ 798 error = 0; 799 break; 800 801 default: 802 /* 803 * Drop anything else. 804 */ 805 NBDEBUG("non-session packet %x\n", rpcode); 806 error = EAGAIN; 807 break; 808 } 809 810 out: 811 if (error) { 812 if (m0) 813 m_freem(m0); 814 return (error); 815 } 816 if (mpp) 817 *mpp = m0; 818 else 819 m_freem(m0); 820 *lenp = (int)len; 821 *rpcodep = rpcode; 822 return (0); 823 } 824 825 /* 826 * SMB transport interface 827 */ 828 static int 829 smb_nbst_create(struct smb_vc *vcp, struct proc *p) 830 { 831 struct nbpcb *nbp; 832 int error; 833 834 nbp = kmem_zalloc(sizeof (struct nbpcb), KM_SLEEP); 835 836 /* 837 * We don't keep reference counts or otherwise 838 * prevent nbp->nbp_tiptr from going away, so 839 * do the TLI open here and keep it until the 840 * last ref calls smb_nbst_done. 841 * This does t_kopen (open endpoint) 842 */ 843 error = nb_tcpopen(nbp, p); 844 if (error) { 845 kmem_free(nbp, sizeof (*nbp)); 846 return (error); 847 } 848 849 nbp->nbp_timo.tv_sec = SMB_NBTIMO; 850 nbp->nbp_state = NBST_CLOSED; /* really IDLE */ 851 nbp->nbp_vc = vcp; 852 nbp->nbp_sndbuf = smb_tcpsndbuf; 853 nbp->nbp_rcvbuf = smb_tcprcvbuf; 854 mutex_init(&nbp->nbp_lock, NULL, MUTEX_DRIVER, NULL); 855 vcp->vc_tdata = nbp; 856 return (0); 857 } 858 859 /*ARGSUSED*/ 860 static int 861 smb_nbst_done(struct smb_vc *vcp, struct proc *p) 862 { 863 struct nbpcb *nbp = vcp->vc_tdata; 864 865 if (nbp == NULL) 866 return (ENOTCONN); 867 vcp->vc_tdata = NULL; 868 869 /* 870 * Don't really need to disconnect here, 871 * because the close following will do it. 872 * But it's harmless. 873 */ 874 if (nbp->nbp_flags & NBF_CONNECTED) 875 nb_disconnect(nbp); 876 if (nbp->nbp_tiptr) 877 t_kclose(nbp->nbp_tiptr, 1); 878 if (nbp->nbp_laddr) 879 smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr); 880 if (nbp->nbp_paddr) 881 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr); 882 mutex_destroy(&nbp->nbp_lock); 883 kmem_free(nbp, sizeof (*nbp)); 884 return (0); 885 } 886 887 /*ARGSUSED*/ 888 static int 889 smb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap, struct proc *p) 890 { 891 struct nbpcb *nbp = vcp->vc_tdata; 892 struct sockaddr_nb *snb; 893 int error; 894 895 NBDEBUG("\n"); 896 error = EINVAL; 897 898 if (nbp->nbp_flags & NBF_LOCADDR) 899 goto out; 900 901 /* 902 * Null name is an "anonymous" (NULL) bind request. 903 * (Let the transport pick a local name.) 904 * This transport does not support NULL bind. 905 */ 906 if (sap == NULL) 907 goto out; 908 909 /*LINTED*/ 910 snb = (struct sockaddr_nb *)smb_dup_sockaddr(sap); 911 if (snb == NULL) { 912 error = ENOMEM; 913 goto out; 914 } 915 mutex_enter(&nbp->nbp_lock); 916 nbp->nbp_laddr = snb; 917 nbp->nbp_flags |= NBF_LOCADDR; 918 mutex_exit(&nbp->nbp_lock); 919 error = 0; 920 921 out: 922 return (error); 923 } 924 925 static int 926 smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap, struct proc *p) 927 { 928 struct nbpcb *nbp = vcp->vc_tdata; 929 struct sockaddr_in sin; 930 struct sockaddr_nb *snb; 931 struct timespec ts1, ts2; 932 int error; 933 934 NBDEBUG("\n"); 935 if (nbp->nbp_tiptr == NULL) 936 return (EBADF); 937 if (nbp->nbp_laddr == NULL) 938 return (EINVAL); 939 940 /* 941 * Note: nbssn_rq_request() will call nbssn_recv(), 942 * so set the RECVLOCK flag here. Otherwise we'll 943 * hit an ASSERT for this flag in nbssn_recv(). 944 */ 945 mutex_enter(&nbp->nbp_lock); 946 if (nbp->nbp_flags & NBF_RECVLOCK) { 947 NBDEBUG("attempt to reenter session layer!\n"); 948 mutex_exit(&nbp->nbp_lock); 949 return (EWOULDBLOCK); 950 } 951 nbp->nbp_flags |= NBF_RECVLOCK; 952 mutex_exit(&nbp->nbp_lock); 953 954 /*LINTED*/ 955 snb = (struct sockaddr_nb *)smb_dup_sockaddr(sap); 956 if (snb == NULL) { 957 error = ENOMEM; 958 goto out; 959 } 960 if (nbp->nbp_paddr) 961 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr); 962 nbp->nbp_paddr = snb; 963 964 /* Setup the remote IP address. */ 965 bzero(&sin, sizeof (sin)); 966 sin.sin_family = AF_INET; 967 sin.sin_port = htons(SMB_TCP_PORT); 968 sin.sin_addr.s_addr = snb->snb_ipaddr; 969 970 /* 971 * For our general timeout we use the greater of 972 * the default (15 sec) and 4 times the time it 973 * took for the first round trip. We used to use 974 * just the latter, but sometimes if the first 975 * round trip is very fast the subsequent 4 sec 976 * timeouts are simply too short. 977 */ 978 gethrestime(&ts1); 979 error = nb_connect_in(nbp, &sin, p); 980 if (error) 981 goto out; 982 gethrestime(&ts2); 983 timespecsub(&ts2, &ts1); 984 timespecadd(&ts2, &ts2); 985 timespecadd(&ts2, &ts2); /* * 4 */ 986 /*CSTYLED*/ 987 if (timespeccmp(&ts2, (&(nbp->nbp_timo)), >)) 988 nbp->nbp_timo = ts2; 989 error = nbssn_rq_request(nbp, p); 990 if (error) 991 nb_disconnect(nbp); 992 out: 993 mutex_enter(&nbp->nbp_lock); 994 nbp->nbp_flags &= ~NBF_RECVLOCK; 995 mutex_exit(&nbp->nbp_lock); 996 997 return (error); 998 } 999 1000 /*ARGSUSED*/ 1001 static int 1002 smb_nbst_disconnect(struct smb_vc *vcp, struct proc *p) 1003 { 1004 struct nbpcb *nbp = vcp->vc_tdata; 1005 1006 if (nbp == NULL) 1007 return (ENOTCONN); 1008 1009 return (nb_disconnect(nbp)); 1010 } 1011 1012 static int 1013 nb_disconnect(struct nbpcb *nbp) 1014 { 1015 TIUSER *tiptr; 1016 int save_flags; 1017 1018 tiptr = nbp->nbp_tiptr; 1019 if (tiptr == NULL) 1020 return (EBADF); 1021 1022 mutex_enter(&nbp->nbp_lock); 1023 save_flags = nbp->nbp_flags; 1024 nbp->nbp_flags &= ~NBF_CONNECTED; 1025 if (nbp->nbp_frag) { 1026 freemsg(nbp->nbp_frag); 1027 nbp->nbp_frag = NULL; 1028 } 1029 mutex_exit(&nbp->nbp_lock); 1030 1031 if (save_flags & NBF_CONNECTED) 1032 nb_snddis(tiptr); 1033 1034 if (nbp->nbp_state != NBST_RETARGET) { 1035 nbp->nbp_state = NBST_CLOSED; /* really IDLE */ 1036 } 1037 return (0); 1038 } 1039 1040 /* 1041 * Always consume the message. 1042 * (On error too!) 1043 */ 1044 /*ARGSUSED*/ 1045 static int 1046 smb_nbst_send(struct smb_vc *vcp, mblk_t *m, struct proc *p) 1047 { 1048 struct nbpcb *nbp = vcp->vc_tdata; 1049 ptrdiff_t diff; 1050 uint32_t mlen; 1051 int error; 1052 1053 if (nbp == NULL || nbp->nbp_tiptr == NULL) { 1054 error = EBADF; 1055 goto errout; 1056 } 1057 1058 /* 1059 * Get the message length, which 1060 * does NOT include the NetBIOS header 1061 */ 1062 mlen = msgdsize(m); 1063 1064 /* 1065 * Normally, mb_init() will have left space 1066 * for us to prepend the NetBIOS header in 1067 * the data block of the first mblk. 1068 * However, we have to check in case other 1069 * code did not leave this space, or if the 1070 * message is from dupmsg (db_ref > 1) 1071 * 1072 * If don't find room in the first data block, 1073 * we have to allocb a new message and link it 1074 * on the front of the chain. We try not to 1075 * do this becuase it's less efficient. Also, 1076 * some network drivers will apparently send 1077 * each mblk in the chain as separate frames. 1078 * (That's arguably a driver bug.) 1079 */ 1080 1081 diff = MBLKHEAD(m); 1082 if (diff == 4 && DB_REF(m) == 1) { 1083 /* We can use the first dblk. */ 1084 m->b_rptr -= 4; 1085 } else { 1086 /* Link a new mblk on the head. */ 1087 mblk_t *m0; 1088 1089 /* M_PREPEND */ 1090 m0 = allocb_wait(4, BPRI_LO, STR_NOSIG, &error); 1091 if (!m0) 1092 goto errout; 1093 1094 m0->b_wptr += 4; 1095 m0->b_cont = m; 1096 m = m0; 1097 } 1098 1099 nb_sethdr(m, NB_SSN_MESSAGE, mlen); 1100 error = tli_send(nbp->nbp_tiptr, m, 0); 1101 return (error); 1102 1103 errout: 1104 if (m) 1105 m_freem(m); 1106 return (error); 1107 } 1108 1109 1110 static int 1111 smb_nbst_recv(struct smb_vc *vcp, mblk_t **mpp, struct proc *p) 1112 { 1113 struct nbpcb *nbp = vcp->vc_tdata; 1114 uint8_t rpcode; 1115 int error, rplen; 1116 1117 mutex_enter(&nbp->nbp_lock); 1118 if (nbp->nbp_flags & NBF_RECVLOCK) { 1119 NBDEBUG("attempt to reenter session layer!\n"); 1120 mutex_exit(&nbp->nbp_lock); 1121 return (EWOULDBLOCK); 1122 } 1123 nbp->nbp_flags |= NBF_RECVLOCK; 1124 mutex_exit(&nbp->nbp_lock); 1125 error = nbssn_recv(nbp, mpp, &rplen, &rpcode, p); 1126 mutex_enter(&nbp->nbp_lock); 1127 nbp->nbp_flags &= ~NBF_RECVLOCK; 1128 mutex_exit(&nbp->nbp_lock); 1129 return (error); 1130 } 1131 1132 /* 1133 * Wait for up to "ticks" clock ticks for input on vcp. 1134 * Returns zero if input is available, otherwise ETIME 1135 * indicating time expired, or other error codes. 1136 */ 1137 /*ARGSUSED*/ 1138 static int 1139 smb_nbst_poll(struct smb_vc *vcp, int ticks, struct proc *p) 1140 { 1141 int error; 1142 int events = 0; 1143 int waitflg = READWAIT; 1144 struct nbpcb *nbp = vcp->vc_tdata; 1145 1146 error = t_kspoll(nbp->nbp_tiptr, ticks, waitflg, &events); 1147 if (!error && !events) 1148 error = ETIME; 1149 1150 return (error); 1151 } 1152 1153 static int 1154 smb_nbst_getparam(struct smb_vc *vcp, int param, void *data) 1155 { 1156 struct nbpcb *nbp = vcp->vc_tdata; 1157 1158 switch (param) { 1159 case SMBTP_SNDSZ: 1160 *(int *)data = nbp->nbp_sndbuf; 1161 break; 1162 case SMBTP_RCVSZ: 1163 *(int *)data = nbp->nbp_rcvbuf; 1164 break; 1165 case SMBTP_TIMEOUT: 1166 *(struct timespec *)data = nbp->nbp_timo; 1167 break; 1168 #ifdef SMBTP_SELECTID 1169 case SMBTP_SELECTID: 1170 *(void **)data = nbp->nbp_selectid; 1171 break; 1172 #endif 1173 #ifdef SMBTP_UPCALL 1174 case SMBTP_UPCALL: 1175 *(void **)data = nbp->nbp_upcall; 1176 break; 1177 #endif 1178 default: 1179 return (EINVAL); 1180 } 1181 return (0); 1182 } 1183 1184 /*ARGSUSED*/ 1185 static int 1186 smb_nbst_setparam(struct smb_vc *vcp, int param, void *data) 1187 { 1188 return (EINVAL); 1189 } 1190 1191 /* 1192 * Check for fatal errors 1193 */ 1194 /*ARGSUSED*/ 1195 static int 1196 smb_nbst_fatal(struct smb_vc *vcp, int error) 1197 { 1198 switch (error) { 1199 case ENOTCONN: 1200 case ENETRESET: 1201 case ECONNABORTED: 1202 case EPIPE: 1203 return (1); 1204 } 1205 return (0); 1206 } 1207 1208 1209 struct smb_tran_desc smb_tran_nbtcp_desc = { 1210 SMBT_NBTCP, 1211 smb_nbst_create, 1212 smb_nbst_done, 1213 smb_nbst_bind, 1214 smb_nbst_connect, 1215 smb_nbst_disconnect, 1216 smb_nbst_send, 1217 smb_nbst_recv, 1218 smb_nbst_poll, 1219 smb_nbst_getparam, 1220 smb_nbst_setparam, 1221 smb_nbst_fatal, 1222 {NULL, NULL} 1223 }; 1224