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