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
smb_rq_done(struct smb_rq * rqp)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
smb_rq_alloc(struct smb_connobj * layer,uchar_t cmd,struct smb_cred * scred,struct smb_rq ** rqpp)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
smb_rq_init(struct smb_rq * rqp,struct smb_connobj * co,uchar_t cmd,struct smb_cred * scred)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
smb_rq_new(struct smb_rq * rqp,uchar_t cmd)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
smb_rq_fillhdr(struct smb_rq * rqp)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
smb_rq_simple(struct smb_rq * rqp)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
smb_rq_simple_timed(struct smb_rq * rqp,int timeout)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
smb_rq_enqueue(struct smb_rq * rqp)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
smb_rq_wstart(struct smb_rq * rqp)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
smb_rq_wend(struct smb_rq * rqp)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
smb_rq_bstart(struct smb_rq * rqp)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
smb_rq_bend(struct smb_rq * rqp)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
smb_rq_intr(struct smb_rq * rqp)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
smb_rq_getenv(struct smb_connobj * co,struct smb_vc ** vcpp,struct smb_share ** sspp)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
smb_rq_reply(struct smb_rq * rqp)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
smb_t2_alloc(struct smb_connobj * layer,ushort_t setup,struct smb_cred * scred,struct smb_t2rq ** t2pp)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
smb_nt_alloc(struct smb_connobj * layer,ushort_t fn,struct smb_cred * scred,struct smb_ntrq ** ntpp)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
smb_t2_init(struct smb_t2rq * t2p,struct smb_connobj * source,ushort_t * setup,int setupcnt,struct smb_cred * scred)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
smb_nt_init(struct smb_ntrq * ntp,struct smb_connobj * source,ushort_t fn,struct smb_cred * scred)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
smb_t2_done(struct smb_t2rq * t2p)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
smb_nt_done(struct smb_ntrq * ntp)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
smb_t2_placedata(mblk_t * mtop,u_int16_t offset,u_int16_t count,struct mdchain * mdp)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
smb_t2_reply(struct smb_t2rq * t2p)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
smb_nt_reply(struct smb_ntrq * ntp)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
smb_t2_request_int(struct smb_t2rq * t2p)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
smb_nt_request_int(struct smb_ntrq * ntp)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
smb_t2_request(struct smb_t2rq * t2p)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
smb_nt_request(struct smb_ntrq * ntp)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