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