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