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_rq.c,v 1.29 2005/02/11 01:44:17 lindak Exp $
33 */
34
35/*
36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37 * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved.
38 * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/time.h>
44#include <sys/kmem.h>
45#include <sys/proc.h>
46#include <sys/lock.h>
47#include <sys/socket.h>
48#include <sys/mount.h>
49#include <sys/sunddi.h>
50#include <sys/cmn_err.h>
51#include <sys/sdt.h>
52
53#include <netsmb/smb_osdep.h>
54
55#include <netsmb/smb.h>
56#include <netsmb/smb2.h>
57#include <netsmb/smb_conn.h>
58#include <netsmb/smb_subr.h>
59#include <netsmb/smb_tran.h>
60#include <netsmb/smb_rq.h>
61#include <netsmb/smb2_rq.h>
62
63/*
64 * How long to wait before restarting a request (after reconnect)
65 */
66#define	SMB_RCNDELAY		2	/* seconds */
67
68/*
69 * leave this zero - we can't ssecond guess server side effects of
70 * duplicate ops, this isn't nfs!
71 */
72#define	SMBMAXRESTARTS		0
73
74
75static int  smb_rq_reply(struct smb_rq *rqp);
76static int  smb_rq_parsehdr(struct smb_rq *rqp);
77static int  smb_rq_enqueue(struct smb_rq *rqp);
78static int  smb_rq_new(struct smb_rq *rqp, uchar_t cmd);
79static int  smb_t2_reply(struct smb_t2rq *t2p);
80static int  smb_nt_reply(struct smb_ntrq *ntp);
81
82
83/*
84 * Done with a request object.  Free its contents.
85 * If it was allocated (SMBR_ALLOCED) free it too.
86 * Some of these are stack locals, not allocated.
87 *
88 * No locks here - this is the last ref.
89 */
90void
91smb_rq_done(struct smb_rq *rqp)
92{
93
94	/*
95	 * No smb_vc_rele() here - see smb_rq_init()
96	 */
97	mb_done(&rqp->sr_rq);
98	md_done(&rqp->sr_rp);
99	mutex_destroy(&rqp->sr_lock);
100	cv_destroy(&rqp->sr_cond);
101	if (rqp->sr_flags & SMBR_ALLOCED)
102		kmem_free(rqp, sizeof (*rqp));
103}
104
105int
106smb_rq_alloc(struct smb_connobj *layer, uchar_t cmd, struct smb_cred *scred,
107	struct smb_rq **rqpp)
108{
109	struct smb_rq *rqp;
110	int error;
111
112	rqp = (struct smb_rq *)kmem_alloc(sizeof (struct smb_rq), KM_SLEEP);
113	if (rqp == NULL)
114		return (ENOMEM);
115	error = smb_rq_init(rqp, layer, cmd, scred);
116	if (error) {
117		smb_rq_done(rqp);
118		return (error);
119	}
120	rqp->sr_flags |= SMBR_ALLOCED;
121	*rqpp = rqp;
122	return (0);
123}
124
125int
126smb_rq_init(struct smb_rq *rqp, struct smb_connobj *co, uchar_t cmd,
127	struct smb_cred *scred)
128{
129	int error;
130
131	bzero(rqp, sizeof (*rqp));
132	mutex_init(&rqp->sr_lock, NULL,  MUTEX_DRIVER, NULL);
133	cv_init(&rqp->sr_cond, NULL, CV_DEFAULT, NULL);
134
135	error = smb_rq_getenv(co, &rqp->sr_vc, &rqp->sr_share);
136	if (error)
137		return (error);
138
139	/*
140	 * We copied a VC pointer (vcp) into rqp->sr_vc,
141	 * but we do NOT do a smb_vc_hold here.  Instead,
142	 * the caller is responsible for the hold on the
143	 * share or the VC as needed.  For smbfs callers,
144	 * the hold is on the share, via the smbfs mount.
145	 * For nsmb ioctl callers, the hold is done when
146	 * the driver handle gets VC or share references.
147	 * This design avoids frequent hold/rele activity
148	 * when creating and completing requests.
149	 */
150
151	rqp->sr_rexmit = SMBMAXRESTARTS;
152	rqp->sr_cred = scred;	/* Note: ref hold done by caller. */
153	error = smb_rq_new(rqp, cmd);
154
155	return (error);
156}
157
158static int
159smb_rq_new(struct smb_rq *rqp, uchar_t cmd)
160{
161	struct mbchain *mbp = &rqp->sr_rq;
162	struct smb_vc *vcp = rqp->sr_vc;
163	int error;
164
165	ASSERT(rqp != NULL);
166
167	rqp->sr_sendcnt = 0;
168
169	mb_done(mbp);
170	md_done(&rqp->sr_rp);
171	error = mb_init(mbp);
172	if (error)
173		return (error);
174
175	if (vcp->vc_flags & SMBV_SMB2) {
176		/*
177		 * SMB2 request initialization
178		 */
179		rqp->sr2_command = cmd;
180		rqp->sr2_creditcharge = 1;
181		rqp->sr2_creditsrequested = 1;
182		rqp->sr_pid = 0xFEFF;	/* Made up, just like Windows */
183		rqp->sr2_rqflags = 0;
184		if ((vcp->vc_flags & SMBV_SIGNING) != 0 &&
185		    vcp->vc_mackey != NULL) {
186			rqp->sr2_rqflags |= SMB2_FLAGS_SIGNED;
187		}
188
189		/*
190		 * The SMB2 header is filled in later by
191		 * smb2_rq_fillhdr (see smb2_rq.c)
192		 * Just reserve space here.
193		 */
194		mb_put_mem(mbp, NULL, SMB2_HDRLEN, MB_MZERO);
195	} else {
196		/*
197		 * SMB1 request initialization
198		 */
199		rqp->sr_cmd = cmd;
200		rqp->sr_pid = (uint32_t)ddi_get_pid();
201		rqp->sr_rqflags  = vcp->vc_hflags;
202		rqp->sr_rqflags2 = vcp->vc_hflags2;
203
204		/*
205		 * The SMB header is filled in later by
206		 * smb_rq_fillhdr (see below)
207		 * Just reserve space here.
208		 */
209		mb_put_mem(mbp, NULL, SMB_HDRLEN, MB_MZERO);
210	}
211
212	return (0);
213}
214
215/*
216 * Given a request with it's body already composed,
217 * rewind to the start and fill in the SMB header.
218 * This is called when the request is enqueued,
219 * so we have the final MID, seq num. etc.
220 */
221void
222smb_rq_fillhdr(struct smb_rq *rqp)
223{
224	struct mbchain mbtmp, *mbp = &mbtmp;
225	mblk_t *m;
226
227	/*
228	 * Fill in the SMB header using a dup of the first mblk,
229	 * which points at the same data but has its own wptr,
230	 * so we can rewind without trashing the message.
231	 */
232	m = dupb(rqp->sr_rq.mb_top);
233	m->b_wptr = m->b_rptr;	/* rewind */
234	mb_initm(mbp, m);
235
236	mb_put_mem(mbp, SMB_SIGNATURE, 4, MB_MSYSTEM);
237	mb_put_uint8(mbp, rqp->sr_cmd);
238	mb_put_uint32le(mbp, 0);	/* status */
239	mb_put_uint8(mbp, rqp->sr_rqflags);
240	mb_put_uint16le(mbp, rqp->sr_rqflags2);
241	mb_put_uint16le(mbp, 0);	/* pid-high */
242	mb_put_mem(mbp, NULL, 8, MB_MZERO);	/* MAC sig. (later) */
243	mb_put_uint16le(mbp, 0);	/* reserved */
244	mb_put_uint16le(mbp, rqp->sr_rqtid);
245	mb_put_uint16le(mbp, (uint16_t)rqp->sr_pid);
246	mb_put_uint16le(mbp, rqp->sr_rquid);
247	mb_put_uint16le(mbp, rqp->sr_mid);
248
249	/* This will free the mblk from dupb. */
250	mb_done(mbp);
251}
252
253int
254smb_rq_simple(struct smb_rq *rqp)
255{
256	return (smb_rq_simple_timed(rqp, smb_timo_default));
257}
258
259/*
260 * Simple request-reply exchange
261 */
262int
263smb_rq_simple_timed(struct smb_rq *rqp, int timeout)
264{
265	int error = EINVAL;
266
267	for (; ; ) {
268		/*
269		 * Don't send any new requests if force unmount is underway.
270		 * This check was moved into smb_rq_enqueue.
271		 */
272		rqp->sr_flags &= ~SMBR_RESTART;
273		rqp->sr_timo = timeout;	/* in seconds */
274		rqp->sr_state = SMBRQ_NOTSENT;
275		error = smb_rq_enqueue(rqp);
276		if (error) {
277			break;
278		}
279		error = smb_rq_reply(rqp);
280		if (!error)
281			break;
282		if ((rqp->sr_flags & (SMBR_RESTART | SMBR_NORESTART)) !=
283		    SMBR_RESTART)
284			break;
285		if (rqp->sr_rexmit <= 0)
286			break;
287		SMBRQ_LOCK(rqp);
288		if (rqp->sr_share) {
289			(void) cv_reltimedwait(&rqp->sr_cond, &(rqp)->sr_lock,
290			    SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
291
292		} else {
293			delay(SEC_TO_TICK(SMB_RCNDELAY));
294		}
295		SMBRQ_UNLOCK(rqp);
296		rqp->sr_rexmit--;
297	}
298	return (error);
299}
300
301
302static int
303smb_rq_enqueue(struct smb_rq *rqp)
304{
305	struct smb_vc *vcp = rqp->sr_vc;
306	struct smb_share *ssp = rqp->sr_share;
307	int error = 0;
308
309	ASSERT((vcp->vc_flags & SMBV_SMB2) == 0);
310
311	/*
312	 * Normal requests may initiate a reconnect,
313	 * and/or wait for state changes to finish.
314	 * Some requests set the NORECONNECT flag
315	 * to avoid all that (i.e. tree discon)
316	 */
317	if (rqp->sr_flags & SMBR_NORECONNECT) {
318		if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
319			SMBSDEBUG("bad vc_state=%d\n", vcp->vc_state);
320			return (ENOTCONN);
321		}
322		if (ssp != NULL &&
323		    ((ssp->ss_flags & SMBS_CONNECTED) == 0))
324			return (ENOTCONN);
325		goto ok_out;
326	}
327
328	/*
329	 * If we're not connected, initiate a reconnect
330	 * and/or wait for an existing one to finish.
331	 */
332	if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
333		error = smb_iod_reconnect(vcp);
334		if (error != 0)
335			return (error);
336	}
337
338	/*
339	 * If this request has a "share" object
340	 * that needs a tree connect, do it now.
341	 */
342	if (ssp != NULL && (ssp->ss_flags & SMBS_CONNECTED) == 0) {
343		error = smb_share_tcon(ssp, rqp->sr_cred);
344		if (error)
345			return (error);
346	}
347
348	/*
349	 * We now know what UID + TID to use.
350	 * Store them in the request.
351	 */
352ok_out:
353	rqp->sr_rquid = vcp->vc_smbuid;
354	rqp->sr_rqtid = ssp ? ssp->ss_tid : SMB_TID_UNKNOWN;
355	error = smb1_iod_addrq(rqp);
356
357	return (error);
358}
359
360/*
361 * Used by the IOD thread during connection setup,
362 * and for smb_echo after network timeouts.  Note that
363 * unlike smb_rq_simple, callers must check sr_error.
364 */
365int
366smb_rq_internal(struct smb_rq *rqp, int timeout)
367{
368	struct smb_vc *vcp = rqp->sr_vc;
369	int error;
370
371	ASSERT((vcp->vc_flags & SMBV_SMB2) == 0);
372
373	rqp->sr_flags &= ~SMBR_RESTART;
374	rqp->sr_timo = timeout;	/* in seconds */
375	rqp->sr_state = SMBRQ_NOTSENT;
376
377	/*
378	 * In-line smb_rq_enqueue(rqp) here, as we don't want it
379	 * trying to reconnect etc. for an internal request.
380	 */
381	rqp->sr_rquid = vcp->vc_smbuid;
382	rqp->sr_rqtid = SMB_TID_UNKNOWN;
383	rqp->sr_flags |= SMBR_INTERNAL;
384	error = smb1_iod_addrq(rqp);
385	if (error != 0)
386		return (error);
387
388	/*
389	 * In-line a variant of smb_rq_reply(rqp) here as we may
390	 * need to do custom parsing for SMB1-to-SMB2 negotiate.
391	 */
392	if (rqp->sr_timo == SMBNOREPLYWAIT) {
393		smb_iod_removerq(rqp);
394		return (0);
395	}
396
397	error = smb_iod_waitrq_int(rqp);
398	if (error)
399		return (error);
400
401	/*
402	 * If the request was signed, validate the
403	 * signature on the response.
404	 */
405	if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
406		error = smb_rq_verify(rqp);
407		if (error)
408			return (error);
409	}
410
411	/*
412	 * Parse the SMB header.
413	 */
414	error = smb_rq_parsehdr(rqp);
415
416	/*
417	 * Skip the error translation smb_rq_reply does.
418	 * Callers of this expect "raw" NT status.
419	 */
420
421	return (error);
422}
423
424/*
425 * Mark location of the word count, which is filled in later by
426 * smb_rw_wend().  Also initialize the counter that it uses
427 * to figure out what value to fill in.
428 *
429 * Note that the word count happens to be 8-bit.
430 */
431void
432smb_rq_wstart(struct smb_rq *rqp)
433{
434	rqp->sr_wcount = mb_reserve(&rqp->sr_rq, sizeof (uint8_t));
435	rqp->sr_rq.mb_count = 0;
436}
437
438void
439smb_rq_wend(struct smb_rq *rqp)
440{
441	uint_t wcnt;
442
443	if (rqp->sr_wcount == NULL) {
444		SMBSDEBUG("no wcount\n");
445		return;
446	}
447	wcnt = rqp->sr_rq.mb_count;
448	if (wcnt > 0x1ff)
449		SMBSDEBUG("word count too large (%d)\n", wcnt);
450	if (wcnt & 1)
451		SMBSDEBUG("odd word count\n");
452	/* Fill in the word count (8-bits) */
453	*rqp->sr_wcount = (wcnt >> 1);
454}
455
456/*
457 * Mark location of the byte count, which is filled in later by
458 * smb_rw_bend().  Also initialize the counter that it uses
459 * to figure out what value to fill in.
460 *
461 * Note that the byte count happens to be 16-bit.
462 */
463void
464smb_rq_bstart(struct smb_rq *rqp)
465{
466	rqp->sr_bcount = mb_reserve(&rqp->sr_rq, sizeof (uint16_t));
467	rqp->sr_rq.mb_count = 0;
468}
469
470void
471smb_rq_bend(struct smb_rq *rqp)
472{
473	uint_t bcnt;
474
475	if (rqp->sr_bcount == NULL) {
476		SMBSDEBUG("no bcount\n");
477		return;
478	}
479	bcnt = rqp->sr_rq.mb_count;
480	if (bcnt > 0xffff)
481		SMBSDEBUG("byte count too large (%d)\n", bcnt);
482	/*
483	 * Fill in the byte count (16-bits)
484	 * The pointer is char * type due to
485	 * typical off-by-one alignment.
486	 */
487	rqp->sr_bcount[0] = bcnt & 0xFF;
488	rqp->sr_bcount[1] = (bcnt >> 8);
489}
490
491int
492smb_rq_getenv(struct smb_connobj *co,
493	struct smb_vc **vcpp, struct smb_share **sspp)
494{
495	struct smb_vc *vcp = NULL;
496	struct smb_share *ssp = NULL;
497	int error = EINVAL;
498
499	if (co->co_flags & SMBO_GONE) {
500		SMBSDEBUG("zombie CO\n");
501		error = EINVAL;
502		goto out;
503	}
504
505	switch (co->co_level) {
506	case SMBL_SHARE:
507		ssp = CPTOSS(co);
508		if ((co->co_flags & SMBO_GONE) ||
509		    co->co_parent == NULL) {
510			SMBSDEBUG("zombie share %s\n", ssp->ss_name);
511			break;
512		}
513		/* instead of recursion... */
514		co = co->co_parent;
515		/* FALLTHROUGH */
516	case SMBL_VC:
517		vcp = CPTOVC(co);
518		if ((co->co_flags & SMBO_GONE) ||
519		    co->co_parent == NULL) {
520			SMBSDEBUG("zombie VC %s\n", vcp->vc_srvname);
521			break;
522		}
523		error = 0;
524		break;
525
526	default:
527		SMBSDEBUG("invalid level %d passed\n", co->co_level);
528	}
529
530out:
531	if (!error) {
532		if (vcpp)
533			*vcpp = vcp;
534		if (sspp)
535			*sspp = ssp;
536	}
537
538	return (error);
539}
540
541/*
542 * Wait for a reply to this request, then parse it.
543 */
544static int
545smb_rq_reply(struct smb_rq *rqp)
546{
547	int error;
548
549	if (rqp->sr_timo == SMBNOREPLYWAIT) {
550		smb_iod_removerq(rqp);
551		return (0);
552	}
553
554	error = smb_iod_waitrq(rqp);
555	if (error)
556		return (error);
557
558	/*
559	 * If the request was signed, validate the
560	 * signature on the response.
561	 */
562	if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
563		error = smb_rq_verify(rqp);
564		if (error)
565			return (error);
566	}
567
568	/*
569	 * Parse the SMB header
570	 */
571	error = smb_rq_parsehdr(rqp);
572	if (error != 0)
573		return (error);
574
575	if (rqp->sr_error != 0) {
576		if (rqp->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) {
577			error = smb_maperr32(rqp->sr_error);
578		} else {
579			uint8_t errClass = rqp->sr_error & 0xff;
580			uint16_t errCode = rqp->sr_error >> 16;
581			/* Convert to NT status */
582			rqp->sr_error = smb_doserr2status(errClass, errCode);
583			error = smb_maperror(errClass, errCode);
584		}
585	}
586
587	if (error != 0) {
588		/*
589		 * Do a special check for STATUS_BUFFER_OVERFLOW;
590		 * it's not an error.
591		 */
592		if (rqp->sr_error == NT_STATUS_BUFFER_OVERFLOW) {
593			/*
594			 * Don't report it as an error to our caller;
595			 * they can look at rqp->sr_error if they
596			 * need to know whether we got a
597			 * STATUS_BUFFER_OVERFLOW.
598			 */
599			rqp->sr_flags |= SMBR_MOREDATA;
600			error = 0;
601		}
602	} else {
603		rqp->sr_flags &= ~SMBR_MOREDATA;
604	}
605
606	return (error);
607}
608
609/*
610 * Parse the SMB header
611 */
612static int
613smb_rq_parsehdr(struct smb_rq *rqp)
614{
615	struct mdchain mdp_save;
616	struct mdchain *mdp = &rqp->sr_rp;
617	u_int8_t tb, sig[4];
618	int error;
619
620	/*
621	 * Parse the signature.  The reader already checked that
622	 * the signature is valid.  Here we just have to check
623	 * for SMB1-to-SMB2 negotiate.  Caller handles an EPROTO
624	 * as a signal that we got an SMB2 reply.  If we return
625	 * EPROTO, rewind the mdchain back where it was.
626	 */
627	mdp_save = *mdp;
628	error = md_get_mem(mdp, sig, 4, MB_MSYSTEM);
629	if (error)
630		return (error);
631	if (sig[0] != SMB_HDR_V1) {
632		if (rqp->sr_cmd == SMB_COM_NEGOTIATE) {
633			*mdp = mdp_save;
634			return (EPROTO);
635		}
636		return (EBADRPC);
637	}
638
639	/* Check cmd */
640	error = md_get_uint8(mdp, &tb);
641	if (tb != rqp->sr_cmd)
642		return (EBADRPC);
643
644	md_get_uint32le(mdp, &rqp->sr_error);
645	md_get_uint8(mdp, &rqp->sr_rpflags);
646	md_get_uint16le(mdp, &rqp->sr_rpflags2);
647
648	/* Skip: pid-high(2), MAC sig(8), reserved(2) */
649	md_get_mem(mdp, NULL, 12, MB_MSYSTEM);
650
651	md_get_uint16le(mdp, &rqp->sr_rptid);
652	md_get_uint16le(mdp, &rqp->sr_rppid);
653	md_get_uint16le(mdp, &rqp->sr_rpuid);
654	error = md_get_uint16le(mdp, &rqp->sr_rpmid);
655
656	return (error);
657}
658
659
660#define	ALIGN4(a)	(((a) + 3) & ~3)
661
662/*
663 * TRANS2 request implementation
664 * TRANS implementation is in the "t2" routines
665 * NT_TRANSACTION implementation is the separate "nt" stuff
666 */
667int
668smb_t2_alloc(struct smb_connobj *layer, ushort_t setup, struct smb_cred *scred,
669	struct smb_t2rq **t2pp)
670{
671	struct smb_t2rq *t2p;
672	int error;
673
674	t2p = (struct smb_t2rq *)kmem_alloc(sizeof (*t2p), KM_SLEEP);
675	if (t2p == NULL)
676		return (ENOMEM);
677	error = smb_t2_init(t2p, layer, &setup, 1, scred);
678	t2p->t2_flags |= SMBT2_ALLOCED;
679	if (error) {
680		smb_t2_done(t2p);
681		return (error);
682	}
683	*t2pp = t2p;
684	return (0);
685}
686
687int
688smb_nt_alloc(struct smb_connobj *layer, ushort_t fn, struct smb_cred *scred,
689	struct smb_ntrq **ntpp)
690{
691	struct smb_ntrq *ntp;
692	int error;
693
694	ntp = (struct smb_ntrq *)kmem_alloc(sizeof (*ntp), KM_SLEEP);
695	if (ntp == NULL)
696		return (ENOMEM);
697	error = smb_nt_init(ntp, layer, fn, scred);
698	mutex_init(&ntp->nt_lock, NULL, MUTEX_DRIVER, NULL);
699	cv_init(&ntp->nt_cond, NULL, CV_DEFAULT, NULL);
700	ntp->nt_flags |= SMBT2_ALLOCED;
701	if (error) {
702		smb_nt_done(ntp);
703		return (error);
704	}
705	*ntpp = ntp;
706	return (0);
707}
708
709int
710smb_t2_init(struct smb_t2rq *t2p, struct smb_connobj *source, ushort_t *setup,
711	int setupcnt, struct smb_cred *scred)
712{
713	int i;
714	int error;
715
716	bzero(t2p, sizeof (*t2p));
717	mutex_init(&t2p->t2_lock, NULL, MUTEX_DRIVER, NULL);
718	cv_init(&t2p->t2_cond, NULL, CV_DEFAULT, NULL);
719
720	t2p->t2_source = source;
721	t2p->t2_setupcount = (u_int16_t)setupcnt;
722	t2p->t2_setupdata = t2p->t2_setup;
723	for (i = 0; i < setupcnt; i++)
724		t2p->t2_setup[i] = setup[i];
725	t2p->t2_fid = 0xffff;
726	t2p->t2_cred = scred;
727	t2p->t2_share = (source->co_level == SMBL_SHARE ?
728	    CPTOSS(source) : NULL); /* for smb up/down */
729	error = smb_rq_getenv(source, &t2p->t2_vc, NULL);
730	if (error)
731		return (error);
732	return (0);
733}
734
735int
736smb_nt_init(struct smb_ntrq *ntp, struct smb_connobj *source, ushort_t fn,
737	struct smb_cred *scred)
738{
739	int error;
740
741	bzero(ntp, sizeof (*ntp));
742	ntp->nt_source = source;
743	ntp->nt_function = fn;
744	ntp->nt_cred = scred;
745	ntp->nt_share = (source->co_level == SMBL_SHARE ?
746	    CPTOSS(source) : NULL); /* for smb up/down */
747	error = smb_rq_getenv(source, &ntp->nt_vc, NULL);
748	if (error)
749		return (error);
750	return (0);
751}
752
753void
754smb_t2_done(struct smb_t2rq *t2p)
755{
756	mb_done(&t2p->t2_tparam);
757	mb_done(&t2p->t2_tdata);
758	md_done(&t2p->t2_rparam);
759	md_done(&t2p->t2_rdata);
760	mutex_destroy(&t2p->t2_lock);
761	cv_destroy(&t2p->t2_cond);
762	if (t2p->t2_flags & SMBT2_ALLOCED)
763		kmem_free(t2p, sizeof (*t2p));
764}
765
766void
767smb_nt_done(struct smb_ntrq *ntp)
768{
769	mb_done(&ntp->nt_tsetup);
770	mb_done(&ntp->nt_tparam);
771	mb_done(&ntp->nt_tdata);
772	md_done(&ntp->nt_rparam);
773	md_done(&ntp->nt_rdata);
774	cv_destroy(&ntp->nt_cond);
775	mutex_destroy(&ntp->nt_lock);
776	if (ntp->nt_flags & SMBT2_ALLOCED)
777		kmem_free(ntp, sizeof (*ntp));
778}
779
780/*
781 * Extract data [offset,count] from mtop and add to mdp.
782 */
783static int
784smb_t2_placedata(mblk_t *mtop, u_int16_t offset, u_int16_t count,
785	struct mdchain *mdp)
786{
787	mblk_t *n;
788
789	n = m_copym(mtop, offset, count, M_WAITOK);
790	if (n == NULL)
791		return (EBADRPC);
792
793	if (mdp->md_top == NULL) {
794		md_initm(mdp, n);
795	} else
796		m_cat(mdp->md_top, n);
797
798	return (0);
799}
800
801static int
802smb_t2_reply(struct smb_t2rq *t2p)
803{
804	struct mdchain *mdp;
805	struct smb_rq *rqp = t2p->t2_rq;
806	int error, error2, totpgot, totdgot;
807	u_int16_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp;
808	u_int16_t tmp, bc, dcount;
809	u_int8_t wc;
810
811	t2p->t2_flags &= ~SMBT2_MOREDATA;
812
813	error = smb_rq_reply(rqp);
814	if (rqp->sr_flags & SMBR_MOREDATA)
815		t2p->t2_flags |= SMBT2_MOREDATA;
816	t2p->t2_sr_errclass = rqp->sr_errclass;
817	t2p->t2_sr_serror = rqp->sr_serror;
818	t2p->t2_sr_error = rqp->sr_error;
819	t2p->t2_sr_rpflags2 = rqp->sr_rpflags2;
820	if (error && !(rqp->sr_flags & SMBR_MOREDATA))
821		return (error);
822	/*
823	 * Now we have to get all subseqent responses, if any.
824	 * The CIFS specification says that they can be misordered,
825	 * which is weird.
826	 * TODO: timo
827	 */
828	totpgot = totdgot = 0;
829	totpcount = totdcount = 0xffff;
830	mdp = &rqp->sr_rp;
831	for (;;) {
832		DTRACE_PROBE2(smb_trans_reply,
833		    (smb_rq_t *), rqp, (mblk_t *), mdp->md_top);
834		m_dumpm(mdp->md_top);
835
836		if ((error2 = md_get_uint8(mdp, &wc)) != 0)
837			break;
838		if (wc < 10) {
839			error2 = ENOENT;
840			break;
841		}
842		if ((error2 = md_get_uint16le(mdp, &tmp)) != 0)
843			break;
844		if (totpcount > tmp)
845			totpcount = tmp;
846		if ((error2 = md_get_uint16le(mdp, &tmp)) != 0)
847			break;
848		if (totdcount > tmp)
849			totdcount = tmp;
850		if ((error2 = md_get_uint16le(mdp, &tmp)) != 0 || /* reserved */
851		    (error2 = md_get_uint16le(mdp, &pcount)) != 0 ||
852		    (error2 = md_get_uint16le(mdp, &poff)) != 0 ||
853		    (error2 = md_get_uint16le(mdp, &pdisp)) != 0)
854			break;
855		if (pcount != 0 && pdisp != totpgot) {
856			SMBSDEBUG("Can't handle misordered parameters %d:%d\n",
857			    pdisp, totpgot);
858			error2 = EINVAL;
859			break;
860		}
861		if ((error2 = md_get_uint16le(mdp, &dcount)) != 0 ||
862		    (error2 = md_get_uint16le(mdp, &doff)) != 0 ||
863		    (error2 = md_get_uint16le(mdp, &ddisp)) != 0)
864			break;
865		if (dcount != 0 && ddisp != totdgot) {
866			SMBSDEBUG("Can't handle misordered data: dcount %d\n",
867			    dcount);
868			error2 = EINVAL;
869			break;
870		}
871
872		/* XXX: Skip setup words?  We don't save them? */
873		md_get_uint8(mdp, &wc);  /* SetupCount */
874		md_get_uint8(mdp, NULL); /* Reserved2 */
875		tmp = wc;
876		while (tmp--)
877			md_get_uint16le(mdp, NULL);
878
879		if ((error2 = md_get_uint16le(mdp, &bc)) != 0)
880			break;
881
882		/*
883		 * There are pad bytes here, and the poff value
884		 * indicates where the next data are found.
885		 * No need to guess at the padding size.
886		 */
887		if (pcount) {
888			error2 = smb_t2_placedata(mdp->md_top, poff,
889			    pcount, &t2p->t2_rparam);
890			if (error2)
891				break;
892		}
893		totpgot += pcount;
894
895		if (dcount) {
896			error2 = smb_t2_placedata(mdp->md_top, doff,
897			    dcount, &t2p->t2_rdata);
898			if (error2)
899				break;
900		}
901		totdgot += dcount;
902
903		if (totpgot >= totpcount && totdgot >= totdcount) {
904			error2 = 0;
905			t2p->t2_flags |= SMBT2_ALLRECV;
906			break;
907		}
908		/*
909		 * We're done with this reply, look for the next one.
910		 */
911		SMBRQ_LOCK(rqp);
912		md_next_record(&rqp->sr_rp);
913		SMBRQ_UNLOCK(rqp);
914		error2 = smb_rq_reply(rqp);
915		if (rqp->sr_flags & SMBR_MOREDATA)
916			t2p->t2_flags |= SMBT2_MOREDATA;
917		if (!error2)
918			continue;
919		t2p->t2_sr_errclass = rqp->sr_errclass;
920		t2p->t2_sr_serror = rqp->sr_serror;
921		t2p->t2_sr_error = rqp->sr_error;
922		t2p->t2_sr_rpflags2 = rqp->sr_rpflags2;
923		error = error2;
924		if (!(rqp->sr_flags & SMBR_MOREDATA))
925			break;
926	}
927	return (error ? error : error2);
928}
929
930static int
931smb_nt_reply(struct smb_ntrq *ntp)
932{
933	struct mdchain *mdp;
934	struct smb_rq *rqp = ntp->nt_rq;
935	int error, error2;
936	u_int32_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp;
937	u_int32_t tmp, dcount, totpgot, totdgot;
938	u_int16_t bc;
939	u_int8_t wc;
940
941	ntp->nt_flags &= ~SMBT2_MOREDATA;
942
943	error = smb_rq_reply(rqp);
944	if (rqp->sr_flags & SMBR_MOREDATA)
945		ntp->nt_flags |= SMBT2_MOREDATA;
946	ntp->nt_sr_error = rqp->sr_error;
947	ntp->nt_sr_rpflags2 = rqp->sr_rpflags2;
948	if (error && !(rqp->sr_flags & SMBR_MOREDATA))
949		return (error);
950	/*
951	 * Now we have to get all subseqent responses. The CIFS specification
952	 * says that they can be misordered which is weird.
953	 * TODO: timo
954	 */
955	totpgot = totdgot = 0;
956	totpcount = totdcount = 0xffffffff;
957	mdp = &rqp->sr_rp;
958	for (;;) {
959		DTRACE_PROBE2(smb_trans_reply,
960		    (smb_rq_t *), rqp, (mblk_t *), mdp->md_top);
961		m_dumpm(mdp->md_top);
962
963		if ((error2 = md_get_uint8(mdp, &wc)) != 0)
964			break;
965		if (wc < 18) {
966			error2 = ENOENT;
967			break;
968		}
969		md_get_mem(mdp, NULL, 3, MB_MSYSTEM); /* reserved */
970		if ((error2 = md_get_uint32le(mdp, &tmp)) != 0)
971			break;
972		if (totpcount > tmp)
973			totpcount = tmp;
974		if ((error2 = md_get_uint32le(mdp, &tmp)) != 0)
975			break;
976		if (totdcount > tmp)
977			totdcount = tmp;
978		if ((error2 = md_get_uint32le(mdp, &pcount)) != 0 ||
979		    (error2 = md_get_uint32le(mdp, &poff)) != 0 ||
980		    (error2 = md_get_uint32le(mdp, &pdisp)) != 0)
981			break;
982		if (pcount != 0 && pdisp != totpgot) {
983			SMBSDEBUG("Can't handle misordered parameters %d:%d\n",
984			    pdisp, totpgot);
985			error2 = EINVAL;
986			break;
987		}
988		if ((error2 = md_get_uint32le(mdp, &dcount)) != 0 ||
989		    (error2 = md_get_uint32le(mdp, &doff)) != 0 ||
990		    (error2 = md_get_uint32le(mdp, &ddisp)) != 0)
991			break;
992		if (dcount != 0 && ddisp != totdgot) {
993			SMBSDEBUG("Can't handle misordered data: dcount %d\n",
994			    dcount);
995			error2 = EINVAL;
996			break;
997		}
998
999		/* XXX: Skip setup words?  We don't save them? */
1000		md_get_uint8(mdp, &wc);  /* SetupCount */
1001		tmp = wc;
1002		while (tmp--)
1003			md_get_uint16le(mdp, NULL);
1004
1005		if ((error2 = md_get_uint16le(mdp, &bc)) != 0)
1006			break;
1007
1008		/*
1009		 * There are pad bytes here, and the poff value
1010		 * indicates where the next data are found.
1011		 * No need to guess at the padding size.
1012		 */
1013		if (pcount) {
1014			error2 = smb_t2_placedata(mdp->md_top, poff, pcount,
1015			    &ntp->nt_rparam);
1016			if (error2)
1017				break;
1018		}
1019		totpgot += pcount;
1020
1021		if (dcount) {
1022			error2 = smb_t2_placedata(mdp->md_top, doff, dcount,
1023			    &ntp->nt_rdata);
1024			if (error2)
1025				break;
1026		}
1027		totdgot += dcount;
1028
1029		if (totpgot >= totpcount && totdgot >= totdcount) {
1030			error2 = 0;
1031			ntp->nt_flags |= SMBT2_ALLRECV;
1032			break;
1033		}
1034		/*
1035		 * We're done with this reply, look for the next one.
1036		 */
1037		SMBRQ_LOCK(rqp);
1038		md_next_record(&rqp->sr_rp);
1039		SMBRQ_UNLOCK(rqp);
1040		error2 = smb_rq_reply(rqp);
1041		if (rqp->sr_flags & SMBR_MOREDATA)
1042			ntp->nt_flags |= SMBT2_MOREDATA;
1043		if (!error2)
1044			continue;
1045		ntp->nt_sr_error = rqp->sr_error;
1046		ntp->nt_sr_rpflags2 = rqp->sr_rpflags2;
1047		error = error2;
1048		if (!(rqp->sr_flags & SMBR_MOREDATA))
1049			break;
1050	}
1051	return (error ? error : error2);
1052}
1053
1054/*
1055 * Perform a full round of TRANS2 request
1056 */
1057static int
1058smb_t2_request_int(struct smb_t2rq *t2p)
1059{
1060	struct smb_vc *vcp = t2p->t2_vc;
1061	struct smb_cred *scred = t2p->t2_cred;
1062	struct mbchain *mbp;
1063	struct mdchain *mdp, mbparam, mbdata;
1064	mblk_t *m;
1065	struct smb_rq *rqp;
1066	int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i;
1067	int error, doff, poff, txdcount, txpcount, nmlen, nmsize;
1068
1069	m = t2p->t2_tparam.mb_top;
1070	if (m) {
1071		md_initm(&mbparam, m);	/* do not free it! */
1072		totpcount = m_fixhdr(m);
1073		if (totpcount > 0xffff)		/* maxvalue for ushort_t */
1074			return (EINVAL);
1075	} else
1076		totpcount = 0;
1077	m = t2p->t2_tdata.mb_top;
1078	if (m) {
1079		md_initm(&mbdata, m);	/* do not free it! */
1080		totdcount = m_fixhdr(m);
1081		if (totdcount > 0xffff)
1082			return (EINVAL);
1083	} else
1084		totdcount = 0;
1085	leftdcount = totdcount;
1086	leftpcount = totpcount;
1087	txmax = vcp->vc_txmax;
1088	error = smb_rq_alloc(t2p->t2_source, t2p->t_name ?
1089	    SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp);
1090	if (error)
1091		return (error);
1092	rqp->sr_timo = smb_timo_default;
1093	rqp->sr_flags |= SMBR_MULTIPACKET;
1094	t2p->t2_rq = rqp;
1095	mbp = &rqp->sr_rq;
1096	smb_rq_wstart(rqp);
1097	mb_put_uint16le(mbp, totpcount);
1098	mb_put_uint16le(mbp, totdcount);
1099	mb_put_uint16le(mbp, t2p->t2_maxpcount);
1100	mb_put_uint16le(mbp, t2p->t2_maxdcount);
1101	mb_put_uint8(mbp, t2p->t2_maxscount);
1102	mb_put_uint8(mbp, 0);			/* reserved */
1103	mb_put_uint16le(mbp, 0);			/* flags */
1104	mb_put_uint32le(mbp, 0);			/* Timeout */
1105	mb_put_uint16le(mbp, 0);			/* reserved 2 */
1106	len = mb_fixhdr(mbp);
1107
1108	/*
1109	 * Now we know the size of the trans overhead stuff:
1110	 * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + nmsize),
1111	 * where nmsize is the OTW size of the name, including
1112	 * the unicode null terminator and any alignment.
1113	 * Use this to decide which parts (and how much)
1114	 * can go into this request: params, data
1115	 */
1116	nmlen = t2p->t_name ? t2p->t_name_len : 0;
1117	nmsize = nmlen + 1; /* null term. */
1118	if (SMB_UNICODE_STRINGS(vcp)) {
1119		nmsize *= 2;
1120		/* we know put_dmem will need to align */
1121		nmsize += 1;
1122	}
1123	len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmsize);
1124	if (len + leftpcount > txmax) {
1125		txpcount = min(leftpcount, txmax - len);
1126		poff = len;
1127		txdcount = 0;
1128		doff = 0;
1129	} else {
1130		txpcount = leftpcount;
1131		poff = txpcount ? len : 0;
1132		/*
1133		 * Other client traffic seems to "ALIGN2" here.  The extra
1134		 * 2 byte pad we use has no observed downside and may be
1135		 * required for some old servers(?)
1136		 */
1137		len = ALIGN4(len + txpcount);
1138		txdcount = min(leftdcount, txmax - len);
1139		doff = txdcount ? len : 0;
1140	}
1141	leftpcount -= txpcount;
1142	leftdcount -= txdcount;
1143	mb_put_uint16le(mbp, txpcount);
1144	mb_put_uint16le(mbp, poff);
1145	mb_put_uint16le(mbp, txdcount);
1146	mb_put_uint16le(mbp, doff);
1147	mb_put_uint8(mbp, t2p->t2_setupcount);
1148	mb_put_uint8(mbp, 0);
1149	for (i = 0; i < t2p->t2_setupcount; i++) {
1150		mb_put_uint16le(mbp, t2p->t2_setupdata[i]);
1151	}
1152	smb_rq_wend(rqp);
1153	smb_rq_bstart(rqp);
1154	if (t2p->t_name) {
1155		/* Put the string and terminating null. */
1156		error = smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1,
1157		    SMB_CS_NONE, NULL);
1158	} else {
1159		/* nmsize accounts for padding, char size. */
1160		error = mb_put_mem(mbp, NULL, nmsize, MB_MZERO);
1161	}
1162	if (error)
1163		goto freerq;
1164	len = mb_fixhdr(mbp);
1165	if (txpcount) {
1166		mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1167		error = md_get_mbuf(&mbparam, txpcount, &m);
1168		SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax);
1169		if (error)
1170			goto freerq;
1171		mb_put_mbuf(mbp, m);
1172	}
1173	len = mb_fixhdr(mbp);
1174	if (txdcount) {
1175		mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1176		error = md_get_mbuf(&mbdata, txdcount, &m);
1177		if (error)
1178			goto freerq;
1179		mb_put_mbuf(mbp, m);
1180	}
1181	smb_rq_bend(rqp);	/* incredible, but thats it... */
1182	error = smb_rq_enqueue(rqp);
1183	if (error)
1184		goto freerq;
1185	if (leftpcount || leftdcount) {
1186		error = smb_rq_reply(rqp);
1187		if (error)
1188			goto bad;
1189		/*
1190		 * this is an interim response, ignore it.
1191		 */
1192		SMBRQ_LOCK(rqp);
1193		md_next_record(&rqp->sr_rp);
1194		SMBRQ_UNLOCK(rqp);
1195	}
1196	while (leftpcount || leftdcount) {
1197		error = smb_rq_new(rqp, t2p->t_name ?
1198		    SMB_COM_TRANSACTION_SECONDARY :
1199		    SMB_COM_TRANSACTION2_SECONDARY);
1200		if (error)
1201			goto bad;
1202		mbp = &rqp->sr_rq;
1203		smb_rq_wstart(rqp);
1204		mb_put_uint16le(mbp, totpcount);
1205		mb_put_uint16le(mbp, totdcount);
1206		len = mb_fixhdr(mbp);
1207		/*
1208		 * now we have known packet size as
1209		 * ALIGN4(len + 7 * 2 + 2) for T2 request, and -2 for T one,
1210		 * and need to decide which parts should go into request
1211		 */
1212		len = ALIGN4(len + 6 * 2 + 2);
1213		if (t2p->t_name == NULL)
1214			len += 2;
1215		if (len + leftpcount > txmax) {
1216			txpcount = min(leftpcount, txmax - len);
1217			poff = len;
1218			txdcount = 0;
1219			doff = 0;
1220		} else {
1221			txpcount = leftpcount;
1222			poff = txpcount ? len : 0;
1223			len = ALIGN4(len + txpcount);
1224			txdcount = min(leftdcount, txmax - len);
1225			doff = txdcount ? len : 0;
1226		}
1227		mb_put_uint16le(mbp, txpcount);
1228		mb_put_uint16le(mbp, poff);
1229		mb_put_uint16le(mbp, totpcount - leftpcount);
1230		mb_put_uint16le(mbp, txdcount);
1231		mb_put_uint16le(mbp, doff);
1232		mb_put_uint16le(mbp, totdcount - leftdcount);
1233		leftpcount -= txpcount;
1234		leftdcount -= txdcount;
1235		if (t2p->t_name == NULL)
1236			mb_put_uint16le(mbp, t2p->t2_fid);
1237		smb_rq_wend(rqp);
1238		smb_rq_bstart(rqp);
1239		mb_put_uint8(mbp, 0);	/* name */
1240		len = mb_fixhdr(mbp);
1241		if (txpcount) {
1242			mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1243			error = md_get_mbuf(&mbparam, txpcount, &m);
1244			if (error)
1245				goto bad;
1246			mb_put_mbuf(mbp, m);
1247		}
1248		len = mb_fixhdr(mbp);
1249		if (txdcount) {
1250			mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1251			error = md_get_mbuf(&mbdata, txdcount, &m);
1252			if (error)
1253				goto bad;
1254			mb_put_mbuf(mbp, m);
1255		}
1256		smb_rq_bend(rqp);
1257		error = smb1_iod_multirq(rqp);
1258		if (error)
1259			goto bad;
1260	}	/* while left params or data */
1261	error = smb_t2_reply(t2p);
1262	if (error && !(t2p->t2_flags & SMBT2_MOREDATA))
1263		goto bad;
1264	mdp = &t2p->t2_rdata;
1265	if (mdp->md_top) {
1266		md_initm(mdp, mdp->md_top);
1267	}
1268	mdp = &t2p->t2_rparam;
1269	if (mdp->md_top) {
1270		md_initm(mdp, mdp->md_top);
1271	}
1272bad:
1273	smb_iod_removerq(rqp);
1274freerq:
1275	if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) {
1276		if (rqp->sr_flags & SMBR_RESTART)
1277			t2p->t2_flags |= SMBT2_RESTART;
1278		md_done(&t2p->t2_rparam);
1279		md_done(&t2p->t2_rdata);
1280	}
1281	smb_rq_done(rqp);
1282	return (error);
1283}
1284
1285
1286/*
1287 * Perform a full round of NT_TRANSACTION request
1288 */
1289static int
1290smb_nt_request_int(struct smb_ntrq *ntp)
1291{
1292	struct smb_vc *vcp = ntp->nt_vc;
1293	struct smb_cred *scred = ntp->nt_cred;
1294	struct mbchain *mbp;
1295	struct mdchain *mdp, mbsetup, mbparam, mbdata;
1296	mblk_t *m;
1297	struct smb_rq *rqp;
1298	int totpcount, leftpcount, totdcount, leftdcount, len, txmax;
1299	int error, doff, poff, txdcount, txpcount;
1300	int totscount;
1301
1302	m = ntp->nt_tsetup.mb_top;
1303	if (m) {
1304		md_initm(&mbsetup, m);	/* do not free it! */
1305		totscount = m_fixhdr(m);
1306		if (totscount > 2 * 0xff)
1307			return (EINVAL);
1308	} else
1309		totscount = 0;
1310	m = ntp->nt_tparam.mb_top;
1311	if (m) {
1312		md_initm(&mbparam, m);	/* do not free it! */
1313		totpcount = m_fixhdr(m);
1314		if (totpcount > 0x7fffffff)
1315			return (EINVAL);
1316	} else
1317		totpcount = 0;
1318	m = ntp->nt_tdata.mb_top;
1319	if (m) {
1320		md_initm(&mbdata, m);	/* do not free it! */
1321		totdcount =  m_fixhdr(m);
1322		if (totdcount > 0x7fffffff)
1323			return (EINVAL);
1324	} else
1325		totdcount = 0;
1326	leftdcount = totdcount;
1327	leftpcount = totpcount;
1328	txmax = vcp->vc_txmax;
1329	error = smb_rq_alloc(ntp->nt_source, SMB_COM_NT_TRANSACT, scred, &rqp);
1330	if (error)
1331		return (error);
1332	rqp->sr_timo = smb_timo_default;
1333	rqp->sr_flags |= SMBR_MULTIPACKET;
1334	ntp->nt_rq = rqp;
1335	mbp = &rqp->sr_rq;
1336	smb_rq_wstart(rqp);
1337	mb_put_uint8(mbp, ntp->nt_maxscount);
1338	mb_put_uint16le(mbp, 0);	/* reserved (flags?) */
1339	mb_put_uint32le(mbp, totpcount);
1340	mb_put_uint32le(mbp, totdcount);
1341	mb_put_uint32le(mbp, ntp->nt_maxpcount);
1342	mb_put_uint32le(mbp, ntp->nt_maxdcount);
1343	len = mb_fixhdr(mbp);
1344	/*
1345	 * now we have known packet size as
1346	 * ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2),
1347	 * and need to decide which parts should go into the first request
1348	 */
1349	len = ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2);
1350	if (len + leftpcount > txmax) {
1351		txpcount = min(leftpcount, txmax - len);
1352		poff = len;
1353		txdcount = 0;
1354		doff = 0;
1355	} else {
1356		txpcount = leftpcount;
1357		poff = txpcount ? len : 0;
1358		len = ALIGN4(len + txpcount);
1359		txdcount = min(leftdcount, txmax - len);
1360		doff = txdcount ? len : 0;
1361	}
1362	leftpcount -= txpcount;
1363	leftdcount -= txdcount;
1364	mb_put_uint32le(mbp, txpcount);
1365	mb_put_uint32le(mbp, poff);
1366	mb_put_uint32le(mbp, txdcount);
1367	mb_put_uint32le(mbp, doff);
1368	mb_put_uint8(mbp, (totscount+1)/2);
1369	mb_put_uint16le(mbp, ntp->nt_function);
1370	if (totscount) {
1371		error = md_get_mbuf(&mbsetup, totscount, &m);
1372		SMBSDEBUG("%d:%d:%d\n", error, totscount, txmax);
1373		if (error)
1374			goto freerq;
1375		mb_put_mbuf(mbp, m);
1376		if (totscount & 1)
1377			mb_put_uint8(mbp, 0); /* setup is in words */
1378	}
1379	smb_rq_wend(rqp);
1380	smb_rq_bstart(rqp);
1381	len = mb_fixhdr(mbp);
1382	if (txpcount) {
1383		mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1384		error = md_get_mbuf(&mbparam, txpcount, &m);
1385		SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax);
1386		if (error)
1387			goto freerq;
1388		mb_put_mbuf(mbp, m);
1389	}
1390	len = mb_fixhdr(mbp);
1391	if (txdcount) {
1392		mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1393		error = md_get_mbuf(&mbdata, txdcount, &m);
1394		if (error)
1395			goto freerq;
1396		mb_put_mbuf(mbp, m);
1397	}
1398	smb_rq_bend(rqp);	/* incredible, but thats it... */
1399	error = smb_rq_enqueue(rqp);
1400	if (error)
1401		goto freerq;
1402	if (leftpcount || leftdcount) {
1403		error = smb_rq_reply(rqp);
1404		if (error)
1405			goto bad;
1406		/*
1407		 * this is an interim response, ignore it.
1408		 */
1409		SMBRQ_LOCK(rqp);
1410		md_next_record(&rqp->sr_rp);
1411		SMBRQ_UNLOCK(rqp);
1412	}
1413	while (leftpcount || leftdcount) {
1414		error = smb_rq_new(rqp, SMB_COM_NT_TRANSACT_SECONDARY);
1415		if (error)
1416			goto bad;
1417		mbp = &rqp->sr_rq;
1418		smb_rq_wstart(rqp);
1419		mb_put_mem(mbp, NULL, 3, MB_MZERO);
1420		mb_put_uint32le(mbp, totpcount);
1421		mb_put_uint32le(mbp, totdcount);
1422		len = mb_fixhdr(mbp);
1423		/*
1424		 * now we have known packet size as
1425		 * ALIGN4(len + 6 * 4  + 2)
1426		 * and need to decide which parts should go into request
1427		 */
1428		len = ALIGN4(len + 6 * 4 + 2);
1429		if (len + leftpcount > txmax) {
1430			txpcount = min(leftpcount, txmax - len);
1431			poff = len;
1432			txdcount = 0;
1433			doff = 0;
1434		} else {
1435			txpcount = leftpcount;
1436			poff = txpcount ? len : 0;
1437			len = ALIGN4(len + txpcount);
1438			txdcount = min(leftdcount, txmax - len);
1439			doff = txdcount ? len : 0;
1440		}
1441		mb_put_uint32le(mbp, txpcount);
1442		mb_put_uint32le(mbp, poff);
1443		mb_put_uint32le(mbp, totpcount - leftpcount);
1444		mb_put_uint32le(mbp, txdcount);
1445		mb_put_uint32le(mbp, doff);
1446		mb_put_uint32le(mbp, totdcount - leftdcount);
1447		leftpcount -= txpcount;
1448		leftdcount -= txdcount;
1449		smb_rq_wend(rqp);
1450		smb_rq_bstart(rqp);
1451		len = mb_fixhdr(mbp);
1452		if (txpcount) {
1453			mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1454			error = md_get_mbuf(&mbparam, txpcount, &m);
1455			if (error)
1456				goto bad;
1457			mb_put_mbuf(mbp, m);
1458		}
1459		len = mb_fixhdr(mbp);
1460		if (txdcount) {
1461			mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1462			error = md_get_mbuf(&mbdata, txdcount, &m);
1463			if (error)
1464				goto bad;
1465			mb_put_mbuf(mbp, m);
1466		}
1467		smb_rq_bend(rqp);
1468		error = smb1_iod_multirq(rqp);
1469		if (error)
1470			goto bad;
1471	}	/* while left params or data */
1472	error = smb_nt_reply(ntp);
1473	if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
1474		goto bad;
1475	mdp = &ntp->nt_rdata;
1476	if (mdp->md_top) {
1477		md_initm(mdp, mdp->md_top);
1478	}
1479	mdp = &ntp->nt_rparam;
1480	if (mdp->md_top) {
1481		md_initm(mdp, mdp->md_top);
1482	}
1483bad:
1484	smb_iod_removerq(rqp);
1485freerq:
1486	if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) {
1487		if (rqp->sr_flags & SMBR_RESTART)
1488			ntp->nt_flags |= SMBT2_RESTART;
1489		md_done(&ntp->nt_rparam);
1490		md_done(&ntp->nt_rdata);
1491	}
1492	smb_rq_done(rqp);
1493	return (error);
1494}
1495
1496int
1497smb_t2_request(struct smb_t2rq *t2p)
1498{
1499	int error = EINVAL, i;
1500
1501	for (i = 0; ; ) {
1502		/*
1503		 * Don't send any new requests if force unmount is underway.
1504		 * This check was moved into smb_rq_enqueue, called by
1505		 * smb_t2_request_int()
1506		 */
1507		t2p->t2_flags &= ~SMBT2_RESTART;
1508		error = smb_t2_request_int(t2p);
1509		if (!error)
1510			break;
1511		if ((t2p->t2_flags & (SMBT2_RESTART | SMBT2_NORESTART)) !=
1512		    SMBT2_RESTART)
1513			break;
1514		if (++i > SMBMAXRESTARTS)
1515			break;
1516		mutex_enter(&(t2p)->t2_lock);
1517		if (t2p->t2_share) {
1518			(void) cv_reltimedwait(&t2p->t2_cond, &(t2p)->t2_lock,
1519			    SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
1520		} else {
1521			delay(SEC_TO_TICK(SMB_RCNDELAY));
1522		}
1523		mutex_exit(&(t2p)->t2_lock);
1524	}
1525	return (error);
1526}
1527
1528
1529int
1530smb_nt_request(struct smb_ntrq *ntp)
1531{
1532	int error = EINVAL, i;
1533
1534	for (i = 0; ; ) {
1535		/*
1536		 * Don't send any new requests if force unmount is underway.
1537		 * This check was moved into smb_rq_enqueue, called by
1538		 * smb_nt_request_int()
1539		 */
1540		ntp->nt_flags &= ~SMBT2_RESTART;
1541		error = smb_nt_request_int(ntp);
1542		if (!error)
1543			break;
1544		if ((ntp->nt_flags & (SMBT2_RESTART | SMBT2_NORESTART)) !=
1545		    SMBT2_RESTART)
1546			break;
1547		if (++i > SMBMAXRESTARTS)
1548			break;
1549		mutex_enter(&(ntp)->nt_lock);
1550		if (ntp->nt_share) {
1551			(void) cv_reltimedwait(&ntp->nt_cond, &(ntp)->nt_lock,
1552			    SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
1553
1554		} else {
1555			delay(SEC_TO_TICK(SMB_RCNDELAY));
1556		}
1557		mutex_exit(&(ntp)->nt_lock);
1558	}
1559	return (error);
1560}
1561
1562/*
1563 * Run an SMB transact named pipe.
1564 * Note: send_mb is consumed.
1565 */
1566int
1567smb_t2_xnp(struct smb_share *ssp, uint16_t fid,
1568    struct mbchain *send_mb, struct mdchain *recv_md,
1569    uint32_t *data_out_sz, /* max / returned */
1570    uint32_t *more, struct smb_cred *scrp)
1571{
1572	struct smb_t2rq *t2p = NULL;
1573	mblk_t *m;
1574	uint16_t setup[2];
1575	int err;
1576
1577	setup[0] = TRANS_TRANSACT_NAMED_PIPE;
1578	setup[1] = fid;
1579
1580	t2p = kmem_alloc(sizeof (*t2p), KM_SLEEP);
1581	err = smb_t2_init(t2p, SSTOCP(ssp), setup, 2, scrp);
1582	if (err) {
1583		*data_out_sz = 0;
1584		goto out;
1585	}
1586
1587	t2p->t2_setupcount = 2;
1588	t2p->t2_setupdata  = setup;
1589
1590	t2p->t_name = "\\PIPE\\";
1591	t2p->t_name_len = 6;
1592
1593	t2p->t2_maxscount = 0;
1594	t2p->t2_maxpcount = 0;
1595	t2p->t2_maxdcount = (uint16_t)*data_out_sz;
1596
1597	/* Transmit parameters (none) */
1598
1599	/*
1600	 * Transmit data
1601	 *
1602	 * Copy the mb, and clear the source so we
1603	 * don't end up with a double free.
1604	 */
1605	t2p->t2_tdata = *send_mb;
1606	bzero(send_mb, sizeof (*send_mb));
1607
1608	/*
1609	 * Run the request
1610	 */
1611	err = smb_t2_request(t2p);
1612
1613	/* No returned parameters. */
1614
1615	if (err == 0 && (m = t2p->t2_rdata.md_top) != NULL) {
1616		/*
1617		 * Received data
1618		 *
1619		 * Copy the mdchain, and clear the source so we
1620		 * don't end up with a double free.
1621		 */
1622		*data_out_sz = msgdsize(m);
1623		md_initm(recv_md, m);
1624		t2p->t2_rdata.md_top = NULL;
1625	} else {
1626		*data_out_sz = 0;
1627	}
1628
1629	if (t2p->t2_sr_error == NT_STATUS_BUFFER_OVERFLOW)
1630		*more = 1;
1631
1632out:
1633	if (t2p != NULL) {
1634		/* Note: t2p->t_name no longer allocated */
1635		smb_t2_done(t2p);
1636		kmem_free(t2p, sizeof (*t2p));
1637	}
1638
1639	return (err);
1640}
1641