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