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_DISCON_REQ, 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 if ((nbp->nbp_flags & NBF_CONNECTED) == 0) 680 return (ENOTCONN); 681 682 if (tiptr == NULL) 683 return (EBADF); 684 if (mpp) { 685 if (*mpp) { 686 NBDEBUG("*mpp not 0 - leak?"); 687 } 688 *mpp = NULL; 689 } 690 m0 = NULL; 691 692 /* 693 * Get the NetBIOS header (not consumed yet) 694 */ 695 error = nbssn_peekhdr(nbp, &len, &rpcode); 696 if (error) { 697 if (error != ETIME) 698 NBDEBUG("peekhdr, error=%d\n", error); 699 return (error); 700 } 701 NBDEBUG("Have pkt, type=0x%x len=0x%x\n", 702 (int)rpcode, (int)len); 703 704 /* 705 * Block here waiting for the whole packet to arrive. 706 * If we get a timeout, return without side effects. 707 * The data length we wait for here includes both the 708 * NetBIOS header and the payload. 709 */ 710 error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, len + 4); 711 if (error) { 712 NBDEBUG("getmsg(body), error=%d\n", error); 713 return (error); 714 } 715 716 /* 717 * We now have an entire NetBIOS message. 718 * Trim off the NetBIOS header and consume it. 719 * Note: _peekhdr has done pullupmsg for us, 720 * so we know it's safe to advance b_rptr. 721 */ 722 m0 = nbp->nbp_frag; 723 m0->b_rptr += 4; 724 725 /* 726 * There may be more data after the message 727 * we're about to return, in which case we 728 * split it and leave the remainder. 729 */ 730 rlen = msgdsize(m0); 731 ASSERT(rlen >= len); 732 nbp->nbp_frag = NULL; 733 if (rlen > len) 734 nbp->nbp_frag = m_split(m0, len, 1); 735 736 if (nbp->nbp_state != NBST_SESSION) { 737 /* 738 * No session is established. 739 * Return whatever packet we got. 740 */ 741 goto out; 742 } 743 744 /* 745 * A session is established; the only packets 746 * we should see are session message and 747 * keep-alive packets. Drop anything else. 748 */ 749 switch (rpcode) { 750 751 case NB_SSN_KEEPALIVE: 752 /* 753 * It's a keepalive. Discard any data in it 754 * (there's not supposed to be any, but that 755 * doesn't mean some server won't send some) 756 */ 757 if (len) 758 NBDEBUG("Keepalive with data %d\n", (int)len); 759 error = EAGAIN; 760 break; 761 762 case NB_SSN_MESSAGE: 763 /* 764 * Session message. Does it have any data? 765 */ 766 if (len == 0) { 767 /* 768 * No data - treat as keepalive (drop). 769 */ 770 error = EAGAIN; 771 break; 772 } 773 /* 774 * Yes, has data. Return it. 775 */ 776 error = 0; 777 break; 778 779 default: 780 /* 781 * Drop anything else. 782 */ 783 NBDEBUG("non-session packet %x\n", rpcode); 784 error = EAGAIN; 785 break; 786 } 787 788 out: 789 if (error) { 790 if (m0) 791 m_freem(m0); 792 return (error); 793 } 794 if (mpp) 795 *mpp = m0; 796 else 797 m_freem(m0); 798 *lenp = (int)len; 799 *rpcodep = rpcode; 800 return (0); 801 } 802 803 /* 804 * SMB transport interface 805 */ 806 static int 807 smb_nbst_create(struct smb_vc *vcp, struct proc *p) 808 { 809 struct nbpcb *nbp; 810 int error; 811 812 nbp = kmem_zalloc(sizeof (struct nbpcb), KM_SLEEP); 813 814 /* 815 * We don't keep reference counts or otherwise 816 * prevent nbp->nbp_tiptr from going away, so 817 * do the TLI open here and keep it until the 818 * last ref calls smb_nbst_done. 819 * This does t_kopen (open endpoint) 820 */ 821 error = nb_tcpopen(nbp, p); 822 if (error) { 823 kmem_free(nbp, sizeof (*nbp)); 824 return (error); 825 } 826 827 nbp->nbp_timo.tv_sec = SMB_NBTIMO; 828 nbp->nbp_state = NBST_CLOSED; /* really IDLE */ 829 nbp->nbp_vc = vcp; 830 nbp->nbp_sndbuf = smb_tcpsndbuf; 831 nbp->nbp_rcvbuf = smb_tcprcvbuf; 832 mutex_init(&nbp->nbp_lock, NULL, MUTEX_DRIVER, NULL); 833 vcp->vc_tdata = nbp; 834 835 nb_setopts(nbp); 836 837 return (0); 838 } 839 840 /*ARGSUSED*/ 841 static int 842 smb_nbst_done(struct smb_vc *vcp, struct proc *p) 843 { 844 struct nbpcb *nbp = vcp->vc_tdata; 845 846 if (nbp == NULL) 847 return (ENOTCONN); 848 vcp->vc_tdata = NULL; 849 850 /* 851 * Don't really need to disconnect here, 852 * because the close following will do it. 853 * But it's harmless. 854 */ 855 if (nbp->nbp_flags & NBF_CONNECTED) 856 nb_disconnect(nbp); 857 if (nbp->nbp_tiptr) 858 t_kclose(nbp->nbp_tiptr, 1); 859 if (nbp->nbp_laddr) 860 smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr); 861 if (nbp->nbp_paddr) 862 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr); 863 mutex_destroy(&nbp->nbp_lock); 864 kmem_free(nbp, sizeof (*nbp)); 865 return (0); 866 } 867 868 /*ARGSUSED*/ 869 static int 870 smb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap, struct proc *p) 871 { 872 struct nbpcb *nbp = vcp->vc_tdata; 873 struct sockaddr_nb *snb; 874 int error; 875 876 NBDEBUG("\n"); 877 error = EINVAL; 878 879 /* 880 * Allow repeated bind calls on one endpoint. 881 * This happens with reconnect. 882 */ 883 884 /* 885 * Null name is an "anonymous" (NULL) bind request. 886 * (Let the transport pick a local name.) 887 * This transport does not support NULL bind. 888 */ 889 if (sap == NULL) 890 goto out; 891 892 /*LINTED*/ 893 snb = (struct sockaddr_nb *)smb_dup_sockaddr(sap); 894 if (snb == NULL) { 895 error = ENOMEM; 896 goto out; 897 } 898 mutex_enter(&nbp->nbp_lock); 899 if (nbp->nbp_laddr) 900 smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr); 901 nbp->nbp_laddr = snb; 902 nbp->nbp_flags |= NBF_LOCADDR; 903 mutex_exit(&nbp->nbp_lock); 904 error = 0; 905 906 out: 907 return (error); 908 } 909 910 static int 911 smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap, struct proc *p) 912 { 913 struct nbpcb *nbp = vcp->vc_tdata; 914 struct sockaddr_in sin; 915 struct sockaddr_nb *snb; 916 struct timespec ts1, ts2; 917 int error; 918 919 NBDEBUG("\n"); 920 if (nbp->nbp_tiptr == NULL) 921 return (EBADF); 922 if (nbp->nbp_laddr == NULL) 923 return (EINVAL); 924 925 /* 926 * Note: nbssn_rq_request() will call nbssn_recv(), 927 * so set the RECVLOCK flag here. Otherwise we'll 928 * hit an ASSERT for this flag in nbssn_recv(). 929 */ 930 mutex_enter(&nbp->nbp_lock); 931 if (nbp->nbp_flags & NBF_RECVLOCK) { 932 NBDEBUG("attempt to reenter session layer!\n"); 933 mutex_exit(&nbp->nbp_lock); 934 return (EWOULDBLOCK); 935 } 936 nbp->nbp_flags |= NBF_RECVLOCK; 937 mutex_exit(&nbp->nbp_lock); 938 939 /*LINTED*/ 940 snb = (struct sockaddr_nb *)smb_dup_sockaddr(sap); 941 if (snb == NULL) { 942 error = ENOMEM; 943 goto out; 944 } 945 if (nbp->nbp_paddr) 946 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr); 947 nbp->nbp_paddr = snb; 948 949 /* Setup the remote IP address. */ 950 bzero(&sin, sizeof (sin)); 951 sin.sin_family = AF_INET; 952 sin.sin_port = htons(SMB_TCP_PORT); 953 sin.sin_addr.s_addr = snb->snb_ipaddr; 954 955 /* 956 * For our general timeout we use the greater of 957 * the default (15 sec) and 4 times the time it 958 * took for the first round trip. We used to use 959 * just the latter, but sometimes if the first 960 * round trip is very fast the subsequent 4 sec 961 * timeouts are simply too short. 962 */ 963 gethrestime(&ts1); 964 error = nb_connect_in(nbp, &sin, p); 965 if (error) 966 goto out; 967 gethrestime(&ts2); 968 timespecsub(&ts2, &ts1); 969 timespecadd(&ts2, &ts2); 970 timespecadd(&ts2, &ts2); /* * 4 */ 971 /*CSTYLED*/ 972 if (timespeccmp(&ts2, (&(nbp->nbp_timo)), >)) 973 nbp->nbp_timo = ts2; 974 error = nbssn_rq_request(nbp, p); 975 if (error) 976 nb_disconnect(nbp); 977 out: 978 mutex_enter(&nbp->nbp_lock); 979 nbp->nbp_flags &= ~NBF_RECVLOCK; 980 mutex_exit(&nbp->nbp_lock); 981 982 return (error); 983 } 984 985 /*ARGSUSED*/ 986 static int 987 smb_nbst_disconnect(struct smb_vc *vcp, struct proc *p) 988 { 989 struct nbpcb *nbp = vcp->vc_tdata; 990 991 if (nbp == NULL) 992 return (ENOTCONN); 993 994 return (nb_disconnect(nbp)); 995 } 996 997 static int 998 nb_disconnect(struct nbpcb *nbp) 999 { 1000 TIUSER *tiptr; 1001 int save_flags; 1002 1003 tiptr = nbp->nbp_tiptr; 1004 if (tiptr == NULL) 1005 return (EBADF); 1006 1007 mutex_enter(&nbp->nbp_lock); 1008 save_flags = nbp->nbp_flags; 1009 nbp->nbp_flags &= ~NBF_CONNECTED; 1010 if (nbp->nbp_frag) { 1011 freemsg(nbp->nbp_frag); 1012 nbp->nbp_frag = NULL; 1013 } 1014 mutex_exit(&nbp->nbp_lock); 1015 1016 if (save_flags & NBF_CONNECTED) { 1017 nb_snddis(tiptr); 1018 (void) t_kunbind(tiptr); 1019 } 1020 1021 if (nbp->nbp_state != NBST_RETARGET) { 1022 nbp->nbp_state = NBST_CLOSED; /* really IDLE */ 1023 } 1024 return (0); 1025 } 1026 1027 /* 1028 * Always consume the message. 1029 * (On error too!) 1030 */ 1031 /*ARGSUSED*/ 1032 static int 1033 smb_nbst_send(struct smb_vc *vcp, mblk_t *m, struct proc *p) 1034 { 1035 struct nbpcb *nbp = vcp->vc_tdata; 1036 ptrdiff_t diff; 1037 uint32_t mlen; 1038 int error; 1039 1040 if (nbp == NULL || nbp->nbp_tiptr == NULL) { 1041 error = EBADF; 1042 goto errout; 1043 } 1044 1045 /* 1046 * Get the message length, which 1047 * does NOT include the NetBIOS header 1048 */ 1049 mlen = msgdsize(m); 1050 1051 /* 1052 * Normally, mb_init() will have left space 1053 * for us to prepend the NetBIOS header in 1054 * the data block of the first mblk. 1055 * However, we have to check in case other 1056 * code did not leave this space, or if the 1057 * message is from dupmsg (db_ref > 1) 1058 * 1059 * If don't find room in the first data block, 1060 * we have to allocb a new message and link it 1061 * on the front of the chain. We try not to 1062 * do this becuase it's less efficient. Also, 1063 * some network drivers will apparently send 1064 * each mblk in the chain as separate frames. 1065 * (That's arguably a driver bug.) 1066 */ 1067 1068 diff = MBLKHEAD(m); 1069 if (diff == 4 && DB_REF(m) == 1) { 1070 /* We can use the first dblk. */ 1071 m->b_rptr -= 4; 1072 } else { 1073 /* Link a new mblk on the head. */ 1074 mblk_t *m0; 1075 1076 /* M_PREPEND */ 1077 m0 = allocb_wait(4, BPRI_LO, STR_NOSIG, &error); 1078 if (!m0) 1079 goto errout; 1080 1081 m0->b_wptr += 4; 1082 m0->b_cont = m; 1083 m = m0; 1084 } 1085 1086 nb_sethdr(m, NB_SSN_MESSAGE, mlen); 1087 error = tli_send(nbp->nbp_tiptr, m, 0); 1088 return (error); 1089 1090 errout: 1091 if (m) 1092 m_freem(m); 1093 return (error); 1094 } 1095 1096 1097 static int 1098 smb_nbst_recv(struct smb_vc *vcp, mblk_t **mpp, struct proc *p) 1099 { 1100 struct nbpcb *nbp = vcp->vc_tdata; 1101 uint8_t rpcode; 1102 int error, rplen; 1103 1104 mutex_enter(&nbp->nbp_lock); 1105 if (nbp->nbp_flags & NBF_RECVLOCK) { 1106 NBDEBUG("attempt to reenter session layer!\n"); 1107 mutex_exit(&nbp->nbp_lock); 1108 return (EWOULDBLOCK); 1109 } 1110 nbp->nbp_flags |= NBF_RECVLOCK; 1111 mutex_exit(&nbp->nbp_lock); 1112 error = nbssn_recv(nbp, mpp, &rplen, &rpcode, p); 1113 mutex_enter(&nbp->nbp_lock); 1114 nbp->nbp_flags &= ~NBF_RECVLOCK; 1115 mutex_exit(&nbp->nbp_lock); 1116 return (error); 1117 } 1118 1119 /* 1120 * Wait for up to "ticks" clock ticks for input on vcp. 1121 * Returns zero if input is available, otherwise ETIME 1122 * indicating time expired, or other error codes. 1123 */ 1124 /*ARGSUSED*/ 1125 static int 1126 smb_nbst_poll(struct smb_vc *vcp, int ticks, struct proc *p) 1127 { 1128 int error; 1129 int events = 0; 1130 int waitflg = READWAIT; 1131 struct nbpcb *nbp = vcp->vc_tdata; 1132 1133 error = t_kspoll(nbp->nbp_tiptr, ticks, waitflg, &events); 1134 if (!error && !events) 1135 error = ETIME; 1136 1137 return (error); 1138 } 1139 1140 static int 1141 smb_nbst_getparam(struct smb_vc *vcp, int param, void *data) 1142 { 1143 struct nbpcb *nbp = vcp->vc_tdata; 1144 1145 switch (param) { 1146 case SMBTP_SNDSZ: 1147 *(int *)data = nbp->nbp_sndbuf; 1148 break; 1149 case SMBTP_RCVSZ: 1150 *(int *)data = nbp->nbp_rcvbuf; 1151 break; 1152 case SMBTP_TIMEOUT: 1153 *(struct timespec *)data = nbp->nbp_timo; 1154 break; 1155 #ifdef SMBTP_SELECTID 1156 case SMBTP_SELECTID: 1157 *(void **)data = nbp->nbp_selectid; 1158 break; 1159 #endif 1160 #ifdef SMBTP_UPCALL 1161 case SMBTP_UPCALL: 1162 *(void **)data = nbp->nbp_upcall; 1163 break; 1164 #endif 1165 default: 1166 return (EINVAL); 1167 } 1168 return (0); 1169 } 1170 1171 /*ARGSUSED*/ 1172 static int 1173 smb_nbst_setparam(struct smb_vc *vcp, int param, void *data) 1174 { 1175 return (EINVAL); 1176 } 1177 1178 /* 1179 * Check for fatal errors 1180 */ 1181 /*ARGSUSED*/ 1182 static int 1183 smb_nbst_fatal(struct smb_vc *vcp, int error) 1184 { 1185 switch (error) { 1186 case ENOTCONN: 1187 case ENETRESET: 1188 case ECONNABORTED: 1189 case EPIPE: 1190 return (1); 1191 } 1192 return (0); 1193 } 1194 1195 1196 struct smb_tran_desc smb_tran_nbtcp_desc = { 1197 SMBT_NBTCP, 1198 smb_nbst_create, 1199 smb_nbst_done, 1200 smb_nbst_bind, 1201 smb_nbst_connect, 1202 smb_nbst_disconnect, 1203 smb_nbst_send, 1204 smb_nbst_recv, 1205 smb_nbst_poll, 1206 smb_nbst_getparam, 1207 smb_nbst_setparam, 1208 smb_nbst_fatal, 1209 {NULL, NULL} 1210 }; 1211