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