xref: /illumos-gate/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c (revision 0e233487902b546a8949e2147ff8af45b1afc77c)
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