xref: /illumos-gate/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c (revision adee678425979226b2b55d1a0b39ce4c989382e9)
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 
75 static int  smb_rq_reply(struct smb_rq *rqp);
76 static int  smb_rq_parsehdr(struct smb_rq *rqp);
77 static int  smb_rq_enqueue(struct smb_rq *rqp);
78 static int  smb_rq_new(struct smb_rq *rqp, uchar_t cmd);
79 static int  smb_t2_reply(struct smb_t2rq *t2p);
80 static 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  */
90 void
smb_rq_done(struct smb_rq * rqp)91 smb_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 
105 int
smb_rq_alloc(struct smb_connobj * layer,uchar_t cmd,struct smb_cred * scred,struct smb_rq ** rqpp)106 smb_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 
125 int
smb_rq_init(struct smb_rq * rqp,struct smb_connobj * co,uchar_t cmd,struct smb_cred * scred)126 smb_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 
158 static int
smb_rq_new(struct smb_rq * rqp,uchar_t cmd)159 smb_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  */
221 void
smb_rq_fillhdr(struct smb_rq * rqp)222 smb_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 
253 int
smb_rq_simple(struct smb_rq * rqp)254 smb_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  */
262 int
smb_rq_simple_timed(struct smb_rq * rqp,int timeout)263 smb_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 
302 static int
smb_rq_enqueue(struct smb_rq * rqp)303 smb_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 	 */
352 ok_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  */
365 int
smb_rq_internal(struct smb_rq * rqp,int timeout)366 smb_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  */
431 void
smb_rq_wstart(struct smb_rq * rqp)432 smb_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 
438 void
smb_rq_wend(struct smb_rq * rqp)439 smb_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  */
463 void
smb_rq_bstart(struct smb_rq * rqp)464 smb_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 
470 void
smb_rq_bend(struct smb_rq * rqp)471 smb_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 
491 int
smb_rq_getenv(struct smb_connobj * co,struct smb_vc ** vcpp,struct smb_share ** sspp)492 smb_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 
530 out:
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  */
544 static int
smb_rq_reply(struct smb_rq * rqp)545 smb_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  */
612 static int
smb_rq_parsehdr(struct smb_rq * rqp)613 smb_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  */
667 int
smb_t2_alloc(struct smb_connobj * layer,ushort_t setup,struct smb_cred * scred,struct smb_t2rq ** t2pp)668 smb_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 
687 int
smb_nt_alloc(struct smb_connobj * layer,ushort_t fn,struct smb_cred * scred,struct smb_ntrq ** ntpp)688 smb_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 
709 int
smb_t2_init(struct smb_t2rq * t2p,struct smb_connobj * source,ushort_t * setup,int setupcnt,struct smb_cred * scred)710 smb_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 
735 int
smb_nt_init(struct smb_ntrq * ntp,struct smb_connobj * source,ushort_t fn,struct smb_cred * scred)736 smb_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 
753 void
smb_t2_done(struct smb_t2rq * t2p)754 smb_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 
766 void
smb_nt_done(struct smb_ntrq * ntp)767 smb_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  */
783 static int
smb_t2_placedata(mblk_t * mtop,u_int16_t offset,u_int16_t count,struct mdchain * mdp)784 smb_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 
801 static int
smb_t2_reply(struct smb_t2rq * t2p)802 smb_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 
930 static int
smb_nt_reply(struct smb_ntrq * ntp)931 smb_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  */
1057 static int
smb_t2_request_int(struct smb_t2rq * t2p)1058 smb_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 	}
1272 bad:
1273 	smb_iod_removerq(rqp);
1274 freerq:
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  */
1289 static int
smb_nt_request_int(struct smb_ntrq * ntp)1290 smb_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 	}
1483 bad:
1484 	smb_iod_removerq(rqp);
1485 freerq:
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 
1496 int
smb_t2_request(struct smb_t2rq * t2p)1497 smb_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 
1529 int
smb_nt_request(struct smb_ntrq * ntp)1530 smb_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  */
1566 int
smb_t2_xnp(struct smb_share * ssp,uint16_t fid,struct mbchain * send_mb,struct mdchain * recv_md,uint32_t * data_out_sz,uint32_t * more,struct smb_cred * scrp)1567 smb_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 
1632 out:
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